Тестирование 3D-хитов в WPF - PullRequest
1 голос
/ 25 июля 2011

Я пишу приложение WPF, которое отображает ландшафт в 3D.

Когда я выполняю тестирование удара, возвращается неправильная 3D-точка (а не точка, на которую я нажал).

Я попытался выделить треугольник, в который был нанесен удар (создав новую сетку, взяв координаты из объекта RayMeshGeometry3DHitTestResult). Я вижу, что получен удар по неправильному треугольнику (треугольник выделен, но он не находится под курсором).

Я использую перспективную камеру с полем зрения 60, а ближняя и дальняя плоскости имеют 3 и 35000 соответственно.

Есть идеи, почему это может произойти и что я могу сделать, чтобы решить эту проблему?

Дайте мне знать, если вам нужны дополнительные данные.

Редактировать: это код, который я использую для проверки попадания:

private void m_viewport3d_MouseDown(object sender, MouseButtonEventArgs e)
{
    Point mousePos = e.GetPosition(m_viewport3d);
    PointHitTestParameters hitParams = new PointHitTestParameters(mousePos);
    HitTestResult result = VisualTreeHelper.HitTest(m_viewport3d, mousePos);
    RayMeshGeometry3DHitTestResult rayMeshResult = result as RayMeshGeometry3DHitTestResult;
    if (rayMeshResult != null)
    {
        MeshGeometry3D mesh = new MeshGeometry3D();
        mesh.Positions.Add(rayMeshResult.MeshHit.Positions[rayMeshResult.VertexIndex1]);
        mesh.Positions.Add(rayMeshResult.MeshHit.Positions[rayMeshResult.VertexIndex2]);
        mesh.Positions.Add(rayMeshResult.MeshHit.Positions[rayMeshResult.VertexIndex3]);
        mesh.TriangleIndices.Add(0);
        mesh.TriangleIndices.Add(1);
        mesh.TriangleIndices.Add(2);
        GeometryModel3D marker = new GeometryModel3D(mesh, new DiffuseMaterial(Brushes.Blue));
        //...add marker to the scene...
    }
}

Ответы [ 3 ]

2 голосов
/ 31 марта 2012

Что меня привлекло, так это то, что точки были в координатах модели.Мне пришлось трансформироваться в мировые координаты.Вот мой код, который выполняет тест на попадание (он возвращает все попадания под курсором, а не только первый):

//  This will cast a ray from the point (on _viewport) along the direction that the camera is looking, and returns hits
private List<RayMeshGeometry3DHitTestResult> CastRay(Point clickPoint, IEnumerable<Visual3D> ignoreVisuals)
{
    List<RayMeshGeometry3DHitTestResult> retVal = new List<RayMeshGeometry3DHitTestResult>();

    //  This gets called every time there is a hit
    HitTestResultCallback resultCallback = delegate(HitTestResult result)
    {
        if (result is RayMeshGeometry3DHitTestResult)       //  It could also be a RayHitTestResult, which isn't as exact as RayMeshGeometry3DHitTestResult
        {
            RayMeshGeometry3DHitTestResult resultCast = (RayMeshGeometry3DHitTestResult)result;
            if (ignoreVisuals == null || !ignoreVisuals.Any(o => o == resultCast.VisualHit))
            {
                retVal.Add(resultCast);
            }
        }

        return HitTestResultBehavior.Continue;
    };

    //  Get hits against existing models
    VisualTreeHelper.HitTest(grdViewPort, null, resultCallback, new PointHitTestParameters(clickPoint));

    //  Exit Function
    return retVal;
}

И некоторая логика, которая потребляет попадание:

if (hit.VisualHit.Transform != null)
{
    return hit.VisualHit.Transform.Transform(hit.PointHit);
}
else
{
    return hit.PointHit;
}
1 голос
/ 26 июля 2011

Выясняет, что это была Normalize проблема. Я не должен был нормализовать внешний вид камеры и векторы вверх. В масштабах, которые я использую, искажение слишком велико, чтобы тест на попадание работал правильно.

1 голос
/ 25 июля 2011

Вам нужно предоставить луч для проверки удара, чтобы он работал в 3d.Используйте правильную перегрузку VisualTreeHelper.HitTest, которая принимает Visual3D и RayHitTestParameters: http://msdn.microsoft.com/en-us/library/ms608751.aspx

...