如何避免相机翻转四元数旋转?

我有一台相机,它使用四元数围绕固定点进行轨道运动。 问题是,当相机围绕x轴旋转并通过杆时,相机将翻转并产生镜像图像。 这是有道理的,因为相机朝向相反的方向,但相机的向上矢量没有改变。 显然,一个新的矢量需要从外观矢量和正确的矢量来计算,但是我似乎无法使它工作。 注意:这使用http://commons.apache.org/math/api-2.2/org/apache/commons/math/geometry/Rotation.html来表示四元数。

无论如何,我正在使用以下基本步骤旋转相机。

旋转四元数初始化为标识[1,0,0,0]:

private Rotation total = Rotation.IDENTITY;

摄像机的向上向量被初始化为:

private Vector3D up = new Vector3D(0, 1, 0);

通过将相机的当前旋转存储为四元数,然后对该四元数应用任何后续旋转来完成旋转,然后使用组合的四元数(总数)来旋转相机的位置。 以下代码描述了此过程:

/**
 * Rotates the camera by combining the current rotation (total) with any new axis/angle representation of a new rotation (newAxis, rotation).
 */
public void rotateCamera() {
    if (rotation != 0) {
        //Construct quaternion from the new rotation:
        Rotation local = new Rotation(Math.cos(rotation/2), Math.sin(rotation/2) * newAxis.getX(), Math.sin(rotation/2) * newAxis.getY(), Math.sin(rotation/2) * newAxis.getZ(), true);

        //Generate new camera rotation quaternion from current rotation quaternion and new rotation quaternion:
        total = total.applyTo(local);

        //Rotate the position of the camera using the camera rotation quaternion:
        cam = rotateVector(local, cam);

        //rotation is complete so set the next rotation to 0
        rotation = 0;
    }
}

/**
 * Rotate a vector around a quaternion rotation.
 * 
 * @param rotation The quaternion rotation.
 * @param vector A vector to be rotated.
 * @return The rotated vector.
 */
public Vector3D rotateVector(Rotation rotation, Vector3D vector) {
    //set world centre to origin, i.e. (width/2, height/2, 0) to (0, 0, 0)
    vector = new Vector3D(vector.getX() - width/2, vector.getY() - height/2, vector.getZ());

    //rotate vector
    vector = rotation.applyTo(vector);

    //set vector in world coordinates, i.e. (0, 0, 0) to (width/2, height/2, 0) 
    return new Vector3D(vector.getX() + width/2, vector.getY() + height/2, vector.getZ());
}

存储任何新旋转的轴/角度的字段newAxis和旋转通过按键生成,如下所示:

@Override
public void keyPressed(KeyEvent e) {
    if (e.getKeyCode() == KeyEvent.VK_W) {
        camera.setAxis(new Vector3D(1, 0, 0));
        camera.setRotation(0.1);
    }
    if (e.getKeyCode() == KeyEvent.VK_A) {
        camera.setAxis(new Vector3D(0, 1, 0));
        camera.setRotation(0.1);
    }
    if (e.getKeyCode() == KeyEvent.VK_S) {
        camera.setAxis(new Vector3D(1, 0, 0));
        camera.setRotation(-0.1);
    }
    if (e.getKeyCode() == KeyEvent.VK_D) {
        camera.setAxis(new Vector3D(0, 1, 0));
        camera.setRotation(-0.1);
    }
}

在每个渲染循环中,rotateCamera()方法被调用,然后下面的代码设置摄像机:

glu.gluLookAt(camera.getCam().getX(), camera.getCam().getY(), camera.getCam().getZ(), camera.getView().getX(), camera.getView().getY(), camera.getView().getZ(), 0, 1, 0);

你做的事很奇怪。 单位四元数表示整个方向。 你通常不会使用'up'向量。 但是......看起来你只需要使用一个常量“向上”向量[0,1,0]而不是从四元数中得到它就可以得到你想要的效果。

这听起来好像你不需要四元数。 你想要的是一个恒定的[向上]向量[0,1,0]。 然后你需要一个'at'点,这永远是你的轨道。 然后,您需要一个可以围绕y轴旋转的“眼睛”点(围绕您的轨道点)或围绕由“向上”向量和轨道点与轨道点之间的向量之间的叉积定义的轴'眼睛'点。

链接地址: http://www.djcxy.com/p/81755.html

上一篇: How to avoid camera flipping on quaternion rotation?

下一篇: How to restrict vertical angle? FPS glm::lookAt camera?