# Damn dirty quaternions

This topic is 4906 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi all, Yes i've had a look through previous posts. The problem is most of them seem to be dealing with quaternion cameras. OK now thats out the way let me explain the problem Basically I have a global axis XYZ which is tied in to the camera rotation, so for the moment lets pretend that it never changes and Y is always up, X off to the right I want to rotate objects around this axis. I have some numeric spinners to set the rotation value, so to rotate 90 degrees around the y axis just pop 90 into the y box. So far all is good. BUT, if you rotate 90 degress around the X axis, then try and rotate around the Z axis, it turns on the Y axis instead. Now I realize that this probably has something to do with an axis shifting with the model, That would be fine if all the axis did that. The y rotation spinner however will always spin around the correct axis. This means that if you rotate an object 90 degrees on the X axis, the Z rotation is now exactly the same as the Y rotation. I hope i've explained whats happening ok. Basically each object has a rotation vector. To rotate around the Y axis just add 1 to the Y value etc. The rendering part is as follows.
Dim qRot As Microsoft.DirectX.Quaternion

RadianRot.X = System.Math.PI * Me.ObjectDetailsList(Me.WhichObj).Rotation.x / 180
RadianRot.Y = System.Math.PI * Me.ObjectDetailsList(Me.WhichObj).Rotation.Y / 180
RadianRot.Z = System.Math.PI * Me.ObjectDetailsList(Me.WhichObj).Rotation.Z / 180

Dim RotMatrix As Microsoft.DirectX.Matrix = Matrix.Identity
'might use this later for object positional
Dim Cent As Microsoft.DirectX.Vector3
Cent = New Microsoft.DirectX.Vector3(0, 0, 0)
RotMatrix.AffineTransformation(1, Cent, qRot, New Microsoft.DirectX.Vector3(0, 0, 0))

// tried this and it is exactly the same //'RotMatrix.Multiply(Matrix.RotationX(Geometry.DegreeToRadian(Me.ObjectDetailsList(Me.WhichObj).Rotation.X)))
Me.device.Transform.World = Matrix.Multiply(RotMatrix, Me.device.Transform.World)
Me.device.RenderState.Lighting = True
device.SetStreamSource(0, Me.ModelVertexBuffer, 0)
device.VertexFormat = CustomVertex.PositionNormal.Format
device.DrawPrimitives(PrimitiveType.TriangleList, 0, Me.FacetCount)


If anyone can help or point me in the right direction I would be very grateful. Cheers DRB2K2

##### Share on other sites
im not sure if it makes a difference, but try constructing the quaternions seperatly from the rotationvalues, then combine them by multiplication into one.

##### Share on other sites
oh wait i think i got it.

you should accumulate the rotation in the quaternion. it seems like right now youre accumulating in euler angles, then convert those to quats. that way you might aswell not use a quat.

##### Share on other sites
hmmmmmmmm not too sure I see what you're getting at there. The vector3 structure is only used as a holding place for the rotation angle.

Do you mean to simply change this into a quaternion structure instead?
If thats the case then I don't think there'll be a difference.

Thanks for the suggestion though, keep em coming.

Cheers
DRB2k2

##### Share on other sites
Ok have cracked it
The rendering part was fine, what was wrong was the bit where I was calculating the rotation.
Before if I wanted a 90 rotation on the Z axis I would just put
Rot.Z = 90

Now though I've done this.
            Dim temp As Microsoft.DirectX.Vector3 = New Microsoft.DirectX.Vector3(Me.NumericUpDown_RotX.Value, Me.NumericUpDown_RotY.Value, Me.NumericUpDown_RotZ.Value)            Dim test As Microsoft.DirectX.Vector3 = New Microsoft.DirectX.Vector3(0, 0, 1)            test.TransformCoordinate(Me.GlobalMatrix)            Dim mat As Matrix = Matrix.Identity            mat.RotationAxis(test, Me.NumericUpDown_RotZ.Value)            temp.TransformCoordinate(mat)            Me.ObjectDetailsList(Me.WhichObj).Rotation = temp

Basically we know that we want to rotate on the axis 0,0,1 for a z rotation.
This is dependent on the world transform so me.GlobalMatrix is simply device.transform.world

we then rotate around the transformed Z axis by the amount held in the rotation spinners e.g. 90 degrees
Then transform the entire rotation amount by these
et voila it all works
for the moment

Cheers
DRB2k2

##### Share on other sites
damn,
well it nearly works, just now the X axis always changes with the model
            RadianRot.X = System.Math.PI * Me.ObjectDetailsList(Me.WhichObj).Rotation.x / 180            RadianRot.Y = System.Math.PI * Me.ObjectDetailsList(Me.WhichObj).Rotation.Y / 180            RadianRot.Z = System.Math.PI * Me.ObjectDetailsList(Me.WhichObj).Rotation.Z / 180            'qRot = Microsoft.DirectX.Quaternion.RotationYawPitchRoll(RadianRot.Y, RadianRot.X, RadianRot.Z)            Dim qX, qY, qZ As Quaternion            qX = Quaternion.RotationAxis(New Microsoft.DirectX.Vector3(1, 0, 0), RadianRot.X)            qY = Quaternion.RotationAxis(New Microsoft.DirectX.Vector3(0, 1, 0), RadianRot.Y)            qZ = Quaternion.RotationAxis(New Microsoft.DirectX.Vector3(0, 0, 1), RadianRot.Z)            'multiplication not communative causing rotation problems here            qRot = Quaternion.Multiply(qX, qY)            qRot.Multiply(qZ)

If I change around the multiplication order whichever one is done first changes its axis and ends up being the same axis as the last.

hmmmmmmmm is there a better way to generate a rotation matrix I wonder.

Cheers
DRB2k2

##### Share on other sites
Quote:
 Original post by drb2k2If I change around the multiplication order whichever one is done first changes its axis and ends up being the same axis as the last.

i think the difference might be in post-or premulitplication.

try both of these, and see if there is a difference:
            qRot = Quaternion.Multiply(qX, qY)            qRot = Quaternion.Multiply(qRot, qZ)//or             qRot = Quaternion.Multiply(qX, qY)            qRot = Quaternion.Multiply(qZ, qRot)

if i recall correctly the difference between post and premultiplication is that either you do rotation a in coordinate system b, or rotation b along coordinate system a. then again im not sure. i should brush up on these things myself a bit...

##### Share on other sites
as about pre-multiply and post multiply.
if to transform points you use
Q*Point*~Q - based formula, then
A*B will do rotation same as if you rotate first by B then by A.
That is, if i want to rotate camera around camera's x axis, i should rotate after i get point into camera space.
That is, i should use
QuaternionThatRotatesAroundXAxis*CameraQuaternion;
(then, result is supposed to be used for transform like Q*Point*~Q)

If i want to rotate around world's x axis i must use
CameraQuaternion*QuaternionThatRotatesAroundXAxis;
- i first rotate around world, then rotate by camera.

Some people store inverse of camera's quaternion instead of camera's quaternion itself. I myself do that, i have unified coordinate system class (instead of camera class) with method GetTransformTo and GetTransformFrom (returning 4x4 matrix ready for OGL). I use GetTransformTo for camera and GetTransformFrom for skeletons/etc. Very handy, in fact.

##### Share on other sites
ahha,
I see what you mean
Have decided to settle for
            RadianRot.X = System.Math.PI * Me.ObjectDetailsList(Me.WhichObj).Rotation.x / 180            RadianRot.Y = System.Math.PI * Me.ObjectDetailsList(Me.WhichObj).Rotation.Y / 180            RadianRot.Z = System.Math.PI * Me.ObjectDetailsList(Me.WhichObj).Rotation.Z / 180            Dim matX, matY, matZ As Matrix            matX = Matrix.RotationX(RadianRot.X)            matY = Matrix.RotationY(RadianRot.Y)            matZ = Matrix.RotationZ(RadianRot.Z)            RotMatrix = Matrix.Multiply(matX, matY)            RotMatrix = Matrix.Multiply(RotMatrix, matZ)            RotMatrix = Matrix.Multiply(RotMatrix, Me.device.Transform.World)

Still not 100% on it though, thanks guys for your help especially Eelco
Much obliged

Cheers
DRB2k2

##### Share on other sites
Could it be that the product of tow quaternion is different than the product of two matrices.

q0 * q1 != r0 * r1

I believe this can be and was proof on another thread

1. 1
2. 2
Rutin
23
3. 3
JoeJ
20
4. 4
5. 5

• 22
• 40
• 23
• 13
• 13
• ### Forum Statistics

• Total Topics
631732
• Total Posts
3001926
×