Trouble with Quaternions... about to lose all my hair.. please dont let me go bald

Started by
4 comments, last by Boltimus 12 years, 5 months ago
[size=2]Hello everyone, I'm using jogl and am simply trying to rotate a sphere in all three axes: x, y, and z.

Here is the code that draws the ball, I'll post two other snippets after it...



private void drawBall( GL2 gl )
{

/* now add the texture */
rdsTexture.enable( gl );
rdsTexture.bind( gl );

/* rotate for inclination and toolface */
Quat4f result = this.rotate(roll, pitch, yaw);
result.normalize();
float[ ] modelView = this.quatToMatrix( result );

/* the default view is straight and level */
gl.glMultMatrixf( modelView , 0 );

/* draw a sphere */
GLUquadric quadric = glu.gluNewQuadric( );
glu.gluQuadricTexture( quadric , true );
glu.gluSphere( quadric , 6.0f , 64 , 64 );
}



okay, now here is the code for the this.rotate ...


public Quat4f rotate( double roll , double pitch , double yaw )
{

// Assuming the angles are in radians.
float cY = ( float ) Math.cos( Math.toRadians( yaw ) / 2.0f );
float sY = ( float ) Math.sin( Math.toRadians( yaw ) / 2.0f );
float cX = ( float ) Math.cos( Math.toRadians( pitch ) / 2.0f );
float sX = ( float ) Math.sin( Math.toRadians( pitch ) / 2.0f );
float cZ = ( float ) Math.cos( Math.toRadians( roll ) / 2.0f );
float sZ = ( float ) Math.sin( Math.toRadians( roll ) / 2.0f );

Quat4f q = new Quat4f( );
q.w = cZ * cY * cX + sZ * sY * sX;
q.x = cZ * cY * sX - sZ * sY * cX;
q.y = cZ * sY * cX + sZ * cY * sX;
q.z = sZ * cY * cX - cZ * sY * sX;

q.normalize( );
return q;
}



and finally, the code for this.quatToMatrix ...


private float[ ] quatToMatrix( Quat4f q )
{

float[] matrix = new float[16];

// First Column
matrix[0] = 1 - 2 * (q.y * q.y + q.z * q.z);
matrix[1] = 2 * (q.x * q.y + q.z * q.w);
matrix[2] = 2 * (q.x * q.z - q.y * q.w);
matrix[3] = 0;

// Second Column
matrix[4] = 2 * (q.x * q.y - q.z * q.w);
matrix[5] = 1 - 2 * (q.x * q.x + q.z * q.z);
matrix[6] = 2 * (q.z * q.y + q.x * q.w);
matrix[7] = 0;

// Third Column
matrix[8] = 2 * (q.x * q.z + q.y * q.w);
matrix[9] = 2 * (q.y * q.z - q.x * q.w);
matrix[10] = 1 - 2 * (q.x * q.x + q.y * q.y);
matrix[11] = 0;

// Fourth Column
matrix[12] = 0;
matrix[13] = 0;
matrix[14] = 0;
matrix[15] = 1;

return matrix;
}



[font="Arial"]Here is what is happening ... I can pitch (rotate around x-axis) fine, but if I roll to the right or left by 90 degrees and then pitch, the ball appears to yaw. Does something look amiss here?[/font]
~Bolt"All men dream: but not equally. Those who dream by night in the dusty recesses of their minds wake in the day to find that it was vanity: but the dreamers of the day are dangerous men, for they may act their dreams with open eyes, to make it possible." This I did...
Advertisement

[font="Arial"]Here is what is happening ... I can pitch (rotate around x-axis) fine, but if I roll to the right or left by 90 degrees and then pitch, the ball appears to yaw. Does something look amiss here?[/font]


There's probably nothing wrong with your code, but your understanding of 3D rotations needs improvement. The composition of roll and pitch produces yaw, and as long as you try to represent your rotations as roll-pitch-yaw combinations, you'll get the behavior you observe.

What you probably want to do is store the current orientation as a quaternion, and not store roll, pitch and yaw anywhere. You can then multiply the quaternion that represents your current orientation by quaternions that represent small rotations around the axes, according to the user's input. Remember to renormalize the quaternion every now and then (or every frame, since it's cheap).

What you probably want to do is store the current orientation as a quaternion, and not store roll, pitch and yaw anywhere.
[/quote]

Ok, let me make sure I got this then.... when I first start up and init, I would just setup a quat that is constructed from basically the identity matrix. then .. (see below)


You can then multiply the quaternion that represents your current orientation by quaternions that represent small rotations around the axes, according to the user's input.
[/quote]


as changes are made in each axis multiply, that current orientation quat by the rotation quat. For example when the user presses the up-arrow key ...I would create a rotation quat around the x-axis for 1 degree of rotation and then multiply it against my master orientation quat and store the value as my new orientation, and then convert it to matrix form where I would multiply it against the ModelViewMatrix?
~Bolt"All men dream: but not equally. Those who dream by night in the dusty recesses of their minds wake in the day to find that it was vanity: but the dreamers of the day are dangerous men, for they may act their dreams with open eyes, to make it possible." This I did...


What you probably want to do is store the current orientation as a quaternion, and not store roll, pitch and yaw anywhere.


Ok, let me make sure I got this then.... when I first start up and init, I would just setup a quat that is constructed from basically the identity matrix. then .. (see below)[/quote]

So far, so good. The quaternion constructed from basically the identity matrix is more commonly referred to as "one". :)


You can then multiply the quaternion that represents your current orientation by quaternions that represent small rotations around the axes, according to the user's input.
[/quote]


as changes are made in each axis multiply, that current orientation quat by the rotation quat. For example when the user presses the up-arrow key ...I would create a rotation quat around the x-axis for 1 degree of rotation and then multiply it against my master orientation quat and store the value as my new orientation, and then convert it to matrix form where I would multiply it against the ModelViewMatrix?
[/quote]

Yup, I think you got it. But, as I said earlier, you should probably renormalize the quaternion after you modify it. This is as simple as scaling it by a factor of 1/sqrt(w^2+x^2+y^2+z^2). Otherwise little precision errors will accumulate and eventually it will become apparent that the quaternion no longer represents a rotation, since it doesn't have unit length.
Awesome!! I'll give a try and report back. Thanks for the paradigm shift!! :) <BOW>
~Bolt"All men dream: but not equally. Those who dream by night in the dusty recesses of their minds wake in the day to find that it was vanity: but the dreamers of the day are dangerous men, for they may act their dreams with open eyes, to make it possible." This I did...
Alvaro!!! thanks so much!!!! that was it.. I could not believe how easy it was to do. It was right under my eyes, I just wasn't looking at it the right way. Once again, I and my scalp thank you! :)
~Bolt"All men dream: but not equally. Those who dream by night in the dusty recesses of their minds wake in the day to find that it was vanity: but the dreamers of the day are dangerous men, for they may act their dreams with open eyes, to make it possible." This I did...

This topic is closed to new replies.

Advertisement