让对象朝正确的方向看?

时间:2017-02-04 09:06:40

标签: java opengl matrix graphics 3d

短背景

我正在使用SceneManager,它允许创建SceneNode个对象。每个SceneNode包含有关位置,缩放和旋转的信息。要使对象显示在场景中,它只会附加到SceneNode,并且SceneNode中包含的变换将应用于它。例如,要让相机查看场景中的球体,我们可以写:

Camera cam           = sceneManager.createCamera("MainCamera", Camera.ProjectionType.PERSPECTIVE);
Entity sphere        = sceneManager.createEntity("Sphere", "sphere_mesh.obj");

SceneNode camNode    = sceneManager.createSceneNode(cam.getname() + "Node");
SceneNode sphereNode = sceneManager.createSceneNode(sphere.getname() + "Node");

// turns camera node towards the sphere node as expected
camNode.lookAt(sphereNode);

上面的简化示例应该给出一般的想法,并且会产生预期的结果,即我没有问题让事情出现在屏幕上并让相机看着它们。

问题

我想让SceneNode包含Entity点,而另一个SceneNode包含另一个Entity,而不是Camera,但它最终会指向相反的方向我打算看一下。

例如,如果我们的目标节点位于[0, 0, -5]位置,而另一个观察者节点位于[0, 0, 5]位置,我们希望对象观察者节点的前向矢量为[0, 0, -1],而是它最终为[0, 0, 1],从目标中看

我最近在将Light附加到SceneNode并告诉lookAt多维数据集SceneNode照亮它之后发现了这个错误,但它没有亮起来。

此图显示了问题,中心立方体应该点亮,但不是。

Forward looks back

白色球体标记了聚光灯的位置,它应该看着中心立方体,但它没有被点亮,因为它实际上是在相反的方向上看。换句话说,我尝试过:lightNode.lookAt(cubeNode);

在调试时,我可以看到生成的旋转矩阵如下所示:

 s  u  f  = side, up, forward; column-major matrix
[1  0  0]
[0  1  0]
[0  0  1] <-- wrong: looking down the +Z axis, towards viewer

相反,它应该是这样的:

 s  u  f
[1  0  0]
[0  1  0]
[0  0 -1] <-- good: looking down the -Z axis, into screen

(是的,底层渲染系统是基于OpenGL的,这意味着“前面”实际上是在-Z轴下方。)

如果我修改上面的代码来查看实际位置的否定,即lightNode.lookAt(cubeNode.getRelativePosition().mult(-1));,那么它会查看多维数据集并点亮它,如下所示。

Back looks forward

所以,为了让它看向“前面”,我不得不告诉它看起来“回来”。在过去的几天里,我一直在寻找这个错误,甚至仔细检查 look-at 矩阵是否正确构建。根据我的参考资料,它似乎是正确的,但无论如何我都把它包括在内,因为它有可能在某一点上被怀疑。

public static Matrix4 createLookAtMatrix(Vector4 eyePosition, Vector4 targetPosition, Vector4 upDirection) {
    Vector4 f = targetPosition.sub(eyePosition).normalize();
    Vector4 s = f.cross(upDirection).normalize();
    Vector4 u = s.cross(f).normalize();

    float[][] values = new float[][] {
        { s.x(),  s.y(),  s.z(), -s.dot(eyePosition) },
        { u.x(),  u.y(),  u.z(), -u.dot(eyePosition) },
        {-f.x(), -f.y(), -f.z(), -f.dot(eyePosition) },
        { 0f   ,  0f   ,  0f   ,  1f                 }
    };

    return createFrom(values);
}

我目前缺乏想法,并希望获得导致捕获和执行此错误的任何帮助。

我真的不知道它是否与我几个月前发布过的older question有关,但仍然没有解决,但是这里包括它以防它被证明是相关的。

1 个答案:

答案 0 :(得分:0)

我假设您创建了look_at函数以使用相机。这就是为什么它不能与其他对象一起工作的原因。相机z轴始终指向远离您所看到的位置,这就是为什么您将减号添加到我假设的矩阵的第三行。

解决它的一种方法是拥有createLookAtMatrix和createCameraLookAtMatrix。梯子就像你现在拥有的那个,另一个没有第三排的减号。

另一种方法是始终将相机置于相机控制下#34;场景图中的节点。您可以让相机局部变换始终在y轴上旋转180度,然后将矩阵的外观设置为父节点。

在任何情况下,这都适用于相机以外的物体:

public static Matrix4 createLookAtMatrixForObjects(Vector4 eyePosition, Vector4 targetPosition, Vector4 upDirection) {
    Vector4 f = targetPosition.sub(eyePosition).normalize();
    Vector4 s = f.cross(upDirection).normalize();
    Vector4 u = s.cross(f).normalize();

    float[][] values = new float[][] {
        { s.x(),  s.y(),  s.z(), -s.dot(eyePosition) },
        { u.x(),  u.y(),  u.z(), -u.dot(eyePosition) },
        { f.x(),  f.y(),  f.z(), -f.dot(eyePosition) },
        { 0f   ,  0f   ,  0f   ,  1f                 }
    };

    return createFrom(values);
}