LWJGL-使用四元数和转换矩阵在6DOF相机中实现“滚动"的问题 [英] LWJGL - Problems implementing 'roll' in a 6DOF Camera using quaternions and a translation matrix

查看:103
本文介绍了LWJGL-使用四元数和转换矩阵在6DOF相机中实现“滚动"的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这个问题上花了几周时间,似乎找不到合适的解决方案,需要一些建议.

I've spent a couple weeks on this issue and can't seem to find a proper solution and need some advice.

我正在使用LWJGL/Java创建Camera类,并正在使用四元数来处理轴承(偏航),俯仰和横滚旋转.我希望这款相机能够处理3D空间中所有6度的运动并滚动.方位角,俯仰角和横滚都是四元数.我将它们乘以一个变化"四元数,然后从中创建一个翻译矩阵.我将其放入浮动缓冲区,然后将Modelview矩阵乘以包含旋转矩阵的缓冲区.

I'm working on creating a Camera class using LWJGL/Java, and am using Quaternions to handle bearing (yaw), pitch and roll rotations. I'd like this camera to handle all 6 degrees of movement in 3D space, and roll. Bearing, Pitch and Roll are all quaternions. I multiply them into a 'change' quaternion, and create a translation matrix from that. I put that in a float buffer, and multiply the modelview matrix by my buffer containing the rotation matrix.

我可以使方位角和俯仰角旋转正常工作,但是当我实施侧滚时,我遇到了问题.主要是,绕Z轴旋转(滚动)似乎不起作用.每当我滚动"相机时,它似乎绕全局Z轴而不是本地相机方向轴滚动.通常,我可以根据四元数的乘积顺序得到3个中的2个,但是我不能让它们一起工作.

I can get the bearing and pitch rotations to work properly, but when I implement roll, I'm running into issues. Mainly, rotating around the Z-axis (rolling) doesn't seem to work. When ever I "roll" the camera, it seems to roll around the global Z axis instead of the local camera direction axis. I can usually get 2 of the 3 to work depending on the order I multiply the quaternions, but I can't get them working together.

由于它们都是独立工作的,因此我假设定向方法存在问题,我将它们组合起来并构建了旋转矩阵.我在粘贴整个类时遇到问题,所以这里是与轮换有关的方法和声明:

Since they all work independently, I'm assuming there's something wrong with my orientation method where I combine them and build a rotation matrix. I'm having problems pasting the whole class in, so here are the methods and declarations relating to rotation:

private final static float DEGTORAD = (float)(Math.PI/180);    

//Eye - position of the camera in the 3D world.
private Vector3f eye;

//Camera axis vectors, calculated each time reorient() is called.
//Initialized to global x, y, and z axis initially.
private Vector3f up;
private Vector3f right;
private Vector3f direction;

//Angles of rotation (in degrees)    
private float pitchAngle;
private float bearingAngle;
private float rollAngle;

private Quaternion pitch;
private Quaternion bearing;
private Quaternion roll;

private FloatBuffer viewMatrixBuffer = BufferUtils.createFloatBuffer(16);
private Quaternion currentOrientation;

...

/**
 * Change the bearing (yaw)
 * @param bearing delta in degrees
 */
public void bearing(float bearingDelta){
    bearingAngle += bearingDelta;
    if(bearingAngle > 360){
        bearingAngle -= 360;
    }else if(bearingAngle < 0){
        bearingAngle += 360;
    }
    bearing.setFromAxisAngle(new Vector4f(0f, 1f, 0f, bearingAngle * DEGTORAD));
    bearing.normalise();
}

/**
 * Change the pitch
 * @param pitch delta in degrees
 */
public void pitch(float pitchDelta){
    pitchAngle += pitchDelta;
    if(pitchAngle > 360){
        pitchAngle -= 360;
    }else if(pitchAngle < 0){
        pitchAngle += 360;
    }
    pitch.setFromAxisAngle(new Vector4f(1f, 0f, 0f, pitchAngle * DEGTORAD));
    pitch.normalise();
}

/**
 * @param initialRoll
 */
public void roll(float initialRoll) {
    rollAngle += initialRoll;
    if(rollAngle > 360){
        rollAngle -= 360;
    }else if(rollAngle < 0){
        rollAngle += 360;
    }
    roll.setFromAxisAngle(new Vector4f(0, 0, 1, rollAngle * DEGTORAD));
    roll.normalise();
}

/**
 * Change direction to focus on a certain point in the world
 * @param eye
 */
public void lookThrough(){
    reorient();
    GL11.glMultMatrix(viewMatrixBuffer);
}    

public void reorient(){
    //Multiply in order: bearing, pitch, roll.  Non-commutative!
    Quaternion change = new Quaternion();
    Quaternion.mul(bearing, pitch, change);
    Quaternion.mul(roll, change, change);
    // orient the camera...
    Matrix4f rotationMatrix = getRotationMatrix(change);

    //Get the looking direction
    direction.x = rotationMatrix.m20;
    direction.y = rotationMatrix.m21;
    direction.z = rotationMatrix.m22;

    //Set the position
    rotationMatrix.m30 = eye.x;
    rotationMatrix.m31 = eye.y;
    rotationMatrix.m32 = eye.z;
    rotationMatrix.m33 = 1;

    rotationMatrix.invert();
    rotationMatrix.store(viewMatrixBuffer);

    viewMatrixBuffer.rewind();

    Vector3f.cross(new Vector3f(0,1,0), direction, null).normalise(right);
    Vector3f.cross(right, direction, null).normalise(up);               
}

Vector3f,Quaternion和Matrix4f都是LWJGL类,不是定制的.

Vector3f, Quaternion, and Matrix4f are all LWJGL classes, not custom made.

所以我的问题是,给定3个代表轴承,俯仰和横滚的四元数,如何修改ModelView矩阵以准确表示这些旋转?

So my question is, given 3 Quaternions representing Bearing, Pitch and Roll, how do I modify the ModelView matrix to accurately represent these rotations?

我觉得这非常接近.请参阅RiverC注释中的Gist链接.旋转了许多度之后,视图会跳很多圈,然后在滚动时恢复正常.它的要旨在那里,但仍然略有偏离.

I feel that this is very close. See the Gist link in RiverC's comment. After rotating so many degrees, the view jumps around a lot before coming back to normal when rolling. The gist of it is there, but it's still slightly off.

推荐答案

您正在以错误的顺序进行乘法.

You're doing the multiplications in the wrong order.

对于两次旋转q1和q2,如果q2跟在q1之后(因为旋转通常是非相交的),则将q2 * q1乘以

For two rotations q1 and q2, if q2 is to follow q1 (since rotations are generally non-communitive) you multiply q2*q1.

在万向节式系统(例如FPS控件)中,优先级顺序始终为偏航,俯仰,横滚.这将建议以下数学:

In a gimbal style system such as controls for a FPS, the priority order is always yaw, pitch, roll. This would suggest the following math:

roll * pitch * yaw

从Java角度讲,我建议不要为每次更新都创建新的四元数

As a java point, I would suggest not creating new Quaternions for every update but anyway

change = Quaternion.mul(Quaternion.mul(roll, pitch, change), yaw, change);

如果您查看代码,则第四个四元数将被结果覆盖,因此无需在每帧/每次更新时都对其进行重置或重新创建.

If you look at the code, the third Quaternion will just be overwritten with the result, so no need to reset it or recreate it each frame / update.

这种轮换顺序的事情令人困惑,但是如果您查看有关四元数的Wiki页面,这是一般规则.

This rotational order thing is confusing, but if you look at the Wiki page on Quaternions, it's the general rule.

这篇关于LWJGL-使用四元数和转换矩阵在6DOF相机中实现“滚动"的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆