LWJGL - Problems with implementing "roll" in 6DOF cameras using quaternions and translation matrix

I spent a couple of weeks on this problem and cannot find the right solution and I need some advice.

I am working on creating a Camera class using LWJGL / Java, and I use Quaternions to handle bearing rotation (rotation), rotation, and rotation. I would like this camera to handle all 6 degrees of movement in 3D space and roll. Bearings, Pitch and Roll are all quaternions. I multiply them by the quaternion “change” and create a translation matrix from it. I put this in a floating point buffer and multiplied the view matrix by my buffer containing the rotation matrix.

I can make the rotation of the bearing and the pitch work correctly, but when I do the throw, I have problems. Basically, rotating around the Z axis (rolling) does not seem to work. When I ever “roll” a camera, it seems to wrap around the global Z axis instead of the direction axis of the local camera. Usually I can get 2 out of 3 to work depending on the order of multiplication of the quaternions, but I can not get them to work together.

Since they all work independently, I assume that something is wrong with my orientation method, where I combine them and create a rotation matrix. I'm having trouble inserting the whole class, so here are the methods and declarations related 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, and Matrix4f are all LWJGL classes, not custom ones.

, , 3 , Bearing, Pitch and Roll, ModelView, ?

EDIT: , . . Gist RiverC. , , . , .

+5
2

.

q1 q2, q2 q1 ( ), q2 * q1.

, FPS, - , , . :

roll * pitch * yaw

java, Quaternions ,

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

, Quaternion , reset /.

, Wiki Quaternions, .

+3

, , . , :

- "" , , , Z, .

, (0,0,1), Z.

, : ( , ) , (x, y, z) w- ( w = cos (/2)).

, , , , :

 roll.setFromAxisAngle(new Vector4f(direction.x, direction.y, direction.z, rollAngle * DEGTORAD));

, LWJGL , setFromAxisAngle.

+3

All Articles