WPF3D如何操作与摄像机平行的平面中的对象

时间:2011-11-30 08:45:16

标签: c# .net wpf 3d

我正在WPF中创建一个应用程序。我使用了很多3DTools。我有一个四面体,里面有一个立方体。我想在3D方向上移动立方体。

我的四面体,以(0,0,0)为中心,使用轨迹球旋转(以编程方式,我在视口上有透明边框来捕捉事件)。

应用程序的用户认为更自然地在其中移动立方体的方法是将其始终移动到2D平面(与屏幕平行)。因此,如果我想在屏幕中更深地移动它,我只需旋转四面体并在Y轴上移动它,例如。我认为这可能是一个很好的解决方案。

我有问题,我想帮助解决问题:首先,当我移动四面体(在轨迹球内)时,轨迹球看起来像移动所有系统坐标。我说这是因为我为了调试目的画了轴,那些轴也在旋转。但事实并非如此 - 它们只是因为轨迹球内的物体而移动(对吗?)。 编辑实际上,我认为轨迹球内部的坐标系正在发生变化。当我在Y-X轴上移动立方体时,我表现不错。但是,如果我稍微转一下,并尝试在Z轴上移动,我会看到它越来越大(离相机越来越近)越来越小(远离相机)。 =(

所以我的问题是如何定义一个不会被轨迹球旋转的平面?对我来说,答案看起来像“好吧,只是在轨道球之外定义”但是,正如我所说(和3DTools文档说)我的视口有边框......所以我不知道如何处理这个。

我的四面体在一组ScreenSpaceLines3D中。我必须把立方体放在里面。我的第二个问题是如何跟踪旋转的四面体顶点的位置?当Position属性给我原始位置而没有别的时候,我真的很失望。我应该保留矩阵变换,然后在我需要的时候应用到我的观点吗?

很抱歉很长的文字,但我真的陷入了这个不那么多的编程问题。我在WPF中知道,我仍然缺乏一些概念。

提前致谢,

佩德罗

2 个答案:

答案 0 :(得分:5)

然后我要做的就是尝试制作自己的操纵器(创建从3DTools取代TrackBall Manipulator的新类)来完成这些操作。例如,在过去我做过缩放/平移,围绕目标旋转,自由旋转,自由移动,旋转对象,翻译对象等......所有这些都是通过简单的矩阵/矢量操作完成的。

对于您的示例,您需要做的是计算与Camera-> Target和world up向量之间的平面正交的法线。如果您正在查看屏幕,这将为您提供一个“平行”在摄像机顶部的矢量,就像本地X轴一样。使用此向量,您可以限制立方体在此方向上的运动。

为此,计算从摄像机到目标的矢量V.这是通过从摄像机位置减去对象位置来实现的。然后,计算一个向量平移的向量,如下所示:

  

给定相机的矢量目标,v = xi,yj,zk
  归一化向量,v'= xi,yj,zk / sqrt(xi ^ 2 + yj ^ 2 + zk ^ 2)
  设U =全局世界向上矢量u = 0,0,1

然后我们可以计算R =与摄像机视图方向平行的水平矢量

R = v' ^ U, where ^ is the cross product, given by   
 a ^ b = (a2b3 - a3b2)i + (a3b1 - a1b3)j + (a1b2 - a2b1)k 

这会给你一个看起来像这样的矢量。

Cross Product to find vector parallel to camera direction

现在您知道了这个向量R,当您向左/向右移动鼠标时,您可以使用它来翻译对象。例如,在伪代码中:

// Pseudocode
onMouseMove()
{
    // Using calculation for R vector above
    Vector r = calulateVector();

    // Assuming passed in the number of points to translate 
    // (or some derivative of mousemove)
    let int pts = mousePointsMovedLeftOrRight;

    // Perform a translate in direction of R
    Vector targetPosition = TargetObject.PositionVector;
    targetPosition.X += r.X * pts;
    targetPosition.Y += r.Y * pts;
    targetPosition.Z += r.Z * pts;
}

我家里的笔记本电脑上有代码可以做到这一点(它是OpenGL但原理相同 - 在3D空间中提供对象和摄像机的各种操作)。如果您想了解更多信息,请随时与我联系/评论。

致以最诚挚的问候,

答案 1 :(得分:1)

我在没有轨迹球的情况下做了类似的事情。我只是使用MouseMove事件来移动和定向相机,但它同样适用于移动对象。如果你需要,我仍然有代码。