Quaternions

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
Vincent_M
Posts: 73
Joined: Tue Apr 03, 2007 4:16 am

Quaternions

Post by Vincent_M »

Alright, quaternion support has been added to the .x loader! I tried applying quaternions loaded from an .x file to my transformation matrices. Eventually, I'll be working with interpolated animation that will drastically cut down on key-frames needed, but so far, no go.. I'm pretty close though.

Here's my code for applying a quaternion to a matrix that I multiply with a translation and scale matrix:

Code: Select all

if(NumAnimations > 0) {
		ScePspFMatrix4 mat;
		for&#40;int i=0;i<Animations&#91;0&#93;.NumFrames;i++&#41; &#123;
			Animations&#91;0&#93;.Frames&#91;i&#93;.Keys = new ScePspFMatrix4&#91;Animations&#91;0&#93;.Frames&#91;i&#93;.NumKeys&#93;;
			
			for&#40;int e=0;e<Animations&#91;0&#93;.Frames&#91;i&#93;.NumKeys;e++&#41; &#123;
				gumLoadIdentity&#40;&mat&#41;;
				gumLoadIdentity&#40;&Animations&#91;0&#93;.Frames&#91;i&#93;.Keys&#91;e&#93;&#41;;


				// manually plug the quaternion into the matrix
				mat.x.x =
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w&#41; +
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x&#41; -
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y&#41; -
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z&#41;;
				mat.x.y =
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y&#41; -
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z&#41;;
				mat.x.z =
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z&#41; +
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y&#41;;


				mat.y.x =
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y&#41; +
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z&#41;;
				mat.y.y =
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w&#41; +
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x&#41; -
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y&#41; -
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z&#41;;
				mat.y.z =
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z&#41; -
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x&#41;;


				mat.z.x =
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z&#41; -
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y&#41;;
				mat.z.y =
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z&#41; +
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x&#41;;
				mat.z.z =
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w&#41; +
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x&#41; -
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y&#41; -
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z&#41;;
				
				gumMultMatrix&#40;&Animations&#91;0&#93;.Frames&#91;i&#93;.Keys&#91;e&#93;, &mat, &Animations&#91;0&#93;.Frames&#91;i&#93;.Keys&#91;e&#93;&#41;;
				gumTranslate&#40;&Animations&#91;0&#93;.Frames&#91;i&#93;.Keys&#91;e&#93;, Animations&#91;0&#93;.Frames&#91;i&#93;.translate&#41;;
				//gumScale&#40;&Animations&#91;0&#93;.Frames&#91;i&#93;.Keys&#91;e&#93;, Animations&#91;0&#93;.Frames&#91;i&#93;.scale&#41;;
			&#125;
		&#125;
	&#125;
This is a pretty crude application, but it is just to see if it works. There's no concern for performance or memory savings here. As soon as this works, I'll get quaternion interpolation to work, and move on from there. I was looking at how Raphael converted his quaternions to matrices with the triEngine, but it is all done in VFPU, and I don't understand that yet. I need to learn that already...

Anyway, the motion appears to be correct from what it looks like. For some reason, all the boxes attached to my biped model are squashed, but they do appear to move, and from what it looks like, rotate the right way. If anyone has any suggestions, I'm more than happy to hear them! =)

EDIT: Never mind about what I said earlier about the motion. It is wrong!
Vincent_M
Posts: 73
Joined: Tue Apr 03, 2007 4:16 am

Post by Vincent_M »

Sorry for posting twice, but this is kinda huge. I think I solved the problem. Here's my code:

Code: Select all

	if&#40;NumAnimations > 0&#41; &#123;
		ScePspFMatrix4 mat;
		printf&#40;"number of frames&#58; %i\n", Animations&#91;0&#93;.NumFrames&#41;;
		for&#40;int i=0;i<Animations&#91;0&#93;.NumFrames;i++&#41; &#123;
			Animations&#91;0&#93;.Frames&#91;i&#93;.Keys = new ScePspFMatrix4&#91;Animations&#91;0&#93;.Frames&#91;i&#93;.NumKeys&#93;;
			
			for&#40;int e=0;e<Animations&#91;0&#93;.Frames&#91;i&#93;.NumKeys;e++&#41; &#123;
				gumLoadIdentity&#40;&mat&#41;;
				gumLoadIdentity&#40;&Animations&#91;0&#93;.Frames&#91;i&#93;.Keys&#91;e&#93;&#41;;


				// manually plug the quaternion into the matrix
				mat.x.x =
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w&#41; +
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x&#41; -
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y&#41; -
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z&#41;;
				mat.x.y =
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y&#41; -
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z&#41;;
				mat.x.z =
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z&#41; +
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y&#41;;
				mat.x.w = 0.0f;


				mat.y.x =
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y&#41; +
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z&#41;;
				mat.y.y =
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w&#41; -
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x&#41; +
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y&#41; -
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z&#41;;
				mat.y.z =
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z&#41; -
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x&#41;;
				mat.y.w = 0.0f;


				mat.z.x =
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z&#41; -
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y&#41;;
				mat.z.y =
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z&#41; +
						&#40;2.0f * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x&#41;;
				mat.z.z =
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.w&#41; -
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.x&#41; -
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.y&#41; +
						&#40;Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z * Animations&#91;0&#93;.Frames&#91;i&#93;.quaternion&#91;e&#93;.z&#41;;
				mat.z.w = 0.0f;
				
				mat.w.x = 0.0f;
				mat.w.y = 0.0f;
				mat.w.z = 0.0f;
				mat.w.w = 1.0f;

				gumTranslate&#40;&Animations&#91;0&#93;.Frames&#91;i&#93;.Keys&#91;e&#93;, Animations&#91;0&#93;.Frames&#91;i&#93;.translate&#41;;
				gumMultMatrix&#40;&Animations&#91;0&#93;.Frames&#91;i&#93;.Keys&#91;e&#93;, &Animations&#91;0&#93;.Frames&#91;i&#93;.Keys&#91;e&#93;, &mat&#41;;
				gumScale&#40;&Animations&#91;0&#93;.Frames&#91;i&#93;.Keys&#91;e&#93;, Animations&#91;0&#93;.Frames&#91;i&#93;.scale&#41;;
			&#125;
		&#125;
	&#125;
I'm posting this just in case anyone has any suggestions on applying quaternions to matrices and combining that new rotation matrix with a translation and scale matrix. That, and it could help others in the future once I know for sure that this is right. ;)
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

huh, mrmr[ice]'s libvfpumath deals quaternions with vfpu. You should have a look into it.
Vincent_M
Posts: 73
Joined: Tue Apr 03, 2007 4:16 am

Post by Vincent_M »

Hmm... I'm going to check it out. I have interpolated implemented through my own way, but I think there is a small error. All orientations are perfect except that some of the objects scale down to 0.0f and then back up to 1,0f even though all scale keys are set to 1.0f. The scaling is implemented correctly, so it has nothing to do with that. This glitch happens the same way even when I don't even apply scaling. This did not happen when I was using pure key frames and not scaling at all.

Here's my code:

Code: Select all

// set the start and end elements
startQuat = model->FrameArray&#91;e&#93;->AnimationFrame->quaternionKey&#91;currentKey&#93;.quaternion;
endQuat   = model->FrameArray&#91;e&#93;->AnimationFrame->quaternionKey&#91;currentKey+1&#93;.quaternion;
								
startScale = model->FrameArray&#91;e&#93;->AnimationFrame->scaleKey&#91;currentKey&#93;.scale;
endScale   = model->FrameArray&#91;e&#93;->AnimationFrame->scaleKey&#91;currentKey+1&#93;.scale;
								
startTrans = model->FrameArray&#91;e&#93;->AnimationFrame->translationKey&#91;currentKey&#93;.translate;
endTrans   = model->FrameArray&#91;e&#93;->AnimationFrame->translationKey&#91;currentKey+1&#93;.translate;

t = &#40;float&#41;&#40;frameNum - interStart&#41; / &#40;float&#41;&#40;interEnd - interStart&#41;;

// setup the interpolated quaternion
quaternion.x = startQuat.x + &#40;&#40;endQuat.x - startQuat.x&#41; * t&#41;;
quaternion.y = startQuat.y + &#40;&#40;endQuat.y - startQuat.y&#41; * t&#41;;
quaternion.z = startQuat.z + &#40;&#40;endQuat.z - startQuat.z&#41; * t&#41;;
quaternion.w = startQuat.w + &#40;&#40;endQuat.w - startQuat.w&#41; * t&#41;;
								
// setup the interpolated translation
interTrans.x = startTrans.x + &#40;&#40;endTrans.x - startTrans.x&#41; * t&#41;;
interTrans.y = startTrans.y + &#40;&#40;endTrans.y - startTrans.y&#41; * t&#41;;
interTrans.z = startTrans.z + &#40;&#40;endTrans.z - startTrans.z&#41; * t&#41;;
								
// setup the interpolated scale
interScale.x = startScale.x + &#40;&#40;endScale.x - startScale.x&#41; * t&#41;;
interScale.y = startScale.y + &#40;&#40;endScale.y - startScale.y&#41; * t&#41;;
interScale.z = startScale.z + &#40;&#40;endScale.z - startScale.z&#41; * t&#41;;
The code above is the actual interpolation happening. I apply the interpolated keys to the matrix just as I did above.
Post Reply