WPF中的3D命中测试

时间:2011-07-25 13:47:14

标签: wpf 3d hittest

我正在编写一个以3D形式显示地形的WPF应用程序。

当我执行命中测试时,返回错误的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 个答案:

答案 0 :(得分:2)

引起我注意的是模特坐标中的要点。我不得不转变为世界的坐标。这是我的代码执行命中测试(这将返回光标下的所有命中,而不仅仅是第一个):

//  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 :(得分:1)

您需要提供射线以进行测试,以便在3d中工作。使用VisualTreeHelper.HitTest的正确重载,该重载采用Visual3D和RayHitTestParameters:http://msdn.microsoft.com/en-us/library/ms608751.aspx

答案 2 :(得分:1)

弄清楚这是一个Normalize问题。我不应该对相机的外观和向上矢量进行标准化。在我正在使用的音阶中,失真太大,无法使命中测试正常工作。