 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
Vincent_M
Joined: 03 Apr 2007 Posts: 73
|
Posted: Fri Apr 04, 2008 12:32 pm Post subject: Quaternions |
|
|
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: |
if(NumAnimations > 0) {
ScePspFMatrix4 mat;
for(int i=0;i<Animations[0].NumFrames;i++) {
Animations[0].Frames[i].Keys = new ScePspFMatrix4[Animations[0].Frames[i].NumKeys];
for(int e=0;e<Animations[0].Frames[i].NumKeys;e++) {
gumLoadIdentity(&mat);
gumLoadIdentity(&Animations[0].Frames[i].Keys[e]);
// manually plug the quaternion into the matrix
mat.x.x =
(Animations[0].Frames[i].quaternion[e].w * Animations[0].Frames[i].quaternion[e].w) +
(Animations[0].Frames[i].quaternion[e].x * Animations[0].Frames[i].quaternion[e].x) -
(Animations[0].Frames[i].quaternion[e].y * Animations[0].Frames[i].quaternion[e].y) -
(Animations[0].Frames[i].quaternion[e].z * Animations[0].Frames[i].quaternion[e].z);
mat.x.y =
(2.0f * Animations[0].Frames[i].quaternion[e].x * Animations[0].Frames[i].quaternion[e].y) -
(2.0f * Animations[0].Frames[i].quaternion[e].w * Animations[0].Frames[i].quaternion[e].z);
mat.x.z =
(2.0f * Animations[0].Frames[i].quaternion[e].x * Animations[0].Frames[i].quaternion[e].z) +
(2.0f * Animations[0].Frames[i].quaternion[e].w * Animations[0].Frames[i].quaternion[e].y);
mat.y.x =
(2.0f * Animations[0].Frames[i].quaternion[e].x * Animations[0].Frames[i].quaternion[e].y) +
(2.0f * Animations[0].Frames[i].quaternion[e].w * Animations[0].Frames[i].quaternion[e].z);
mat.y.y =
(Animations[0].Frames[i].quaternion[e].w * Animations[0].Frames[i].quaternion[e].w) +
(Animations[0].Frames[i].quaternion[e].x * Animations[0].Frames[i].quaternion[e].x) -
(Animations[0].Frames[i].quaternion[e].y * Animations[0].Frames[i].quaternion[e].y) -
(Animations[0].Frames[i].quaternion[e].z * Animations[0].Frames[i].quaternion[e].z);
mat.y.z =
(2.0f * Animations[0].Frames[i].quaternion[e].y * Animations[0].Frames[i].quaternion[e].z) -
(2.0f * Animations[0].Frames[i].quaternion[e].w * Animations[0].Frames[i].quaternion[e].x);
mat.z.x =
(2.0f * Animations[0].Frames[i].quaternion[e].x * Animations[0].Frames[i].quaternion[e].z) -
(2.0f * Animations[0].Frames[i].quaternion[e].w * Animations[0].Frames[i].quaternion[e].y);
mat.z.y =
(2.0f * Animations[0].Frames[i].quaternion[e].y * Animations[0].Frames[i].quaternion[e].z) +
(2.0f * Animations[0].Frames[i].quaternion[e].w * Animations[0].Frames[i].quaternion[e].x);
mat.z.z =
(Animations[0].Frames[i].quaternion[e].w * Animations[0].Frames[i].quaternion[e].w) +
(Animations[0].Frames[i].quaternion[e].x * Animations[0].Frames[i].quaternion[e].x) -
(Animations[0].Frames[i].quaternion[e].y * Animations[0].Frames[i].quaternion[e].y) -
(Animations[0].Frames[i].quaternion[e].z * Animations[0].Frames[i].quaternion[e].z);
gumMultMatrix(&Animations[0].Frames[i].Keys[e], &mat, &Animations[0].Frames[i].Keys[e]);
gumTranslate(&Animations[0].Frames[i].Keys[e], Animations[0].Frames[i].translate);
//gumScale(&Animations[0].Frames[i].Keys[e], Animations[0].Frames[i].scale);
}
}
}
|
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! |
|
| Back to top |
|
 |
Vincent_M
Joined: 03 Apr 2007 Posts: 73
|
Posted: Fri Apr 04, 2008 12:45 pm Post subject: |
|
|
Sorry for posting twice, but this is kinda huge. I think I solved the problem. Here's my code:
| Code: |
if(NumAnimations > 0) {
ScePspFMatrix4 mat;
printf("number of frames: %i\n", Animations[0].NumFrames);
for(int i=0;i<Animations[0].NumFrames;i++) {
Animations[0].Frames[i].Keys = new ScePspFMatrix4[Animations[0].Frames[i].NumKeys];
for(int e=0;e<Animations[0].Frames[i].NumKeys;e++) {
gumLoadIdentity(&mat);
gumLoadIdentity(&Animations[0].Frames[i].Keys[e]);
// manually plug the quaternion into the matrix
mat.x.x =
(Animations[0].Frames[i].quaternion[e].w * Animations[0].Frames[i].quaternion[e].w) +
(Animations[0].Frames[i].quaternion[e].x * Animations[0].Frames[i].quaternion[e].x) -
(Animations[0].Frames[i].quaternion[e].y * Animations[0].Frames[i].quaternion[e].y) -
(Animations[0].Frames[i].quaternion[e].z * Animations[0].Frames[i].quaternion[e].z);
mat.x.y =
(2.0f * Animations[0].Frames[i].quaternion[e].x * Animations[0].Frames[i].quaternion[e].y) -
(2.0f * Animations[0].Frames[i].quaternion[e].w * Animations[0].Frames[i].quaternion[e].z);
mat.x.z =
(2.0f * Animations[0].Frames[i].quaternion[e].x * Animations[0].Frames[i].quaternion[e].z) +
(2.0f * Animations[0].Frames[i].quaternion[e].w * Animations[0].Frames[i].quaternion[e].y);
mat.x.w = 0.0f;
mat.y.x =
(2.0f * Animations[0].Frames[i].quaternion[e].x * Animations[0].Frames[i].quaternion[e].y) +
(2.0f * Animations[0].Frames[i].quaternion[e].w * Animations[0].Frames[i].quaternion[e].z);
mat.y.y =
(Animations[0].Frames[i].quaternion[e].w * Animations[0].Frames[i].quaternion[e].w) -
(Animations[0].Frames[i].quaternion[e].x * Animations[0].Frames[i].quaternion[e].x) +
(Animations[0].Frames[i].quaternion[e].y * Animations[0].Frames[i].quaternion[e].y) -
(Animations[0].Frames[i].quaternion[e].z * Animations[0].Frames[i].quaternion[e].z);
mat.y.z =
(2.0f * Animations[0].Frames[i].quaternion[e].y * Animations[0].Frames[i].quaternion[e].z) -
(2.0f * Animations[0].Frames[i].quaternion[e].w * Animations[0].Frames[i].quaternion[e].x);
mat.y.w = 0.0f;
mat.z.x =
(2.0f * Animations[0].Frames[i].quaternion[e].x * Animations[0].Frames[i].quaternion[e].z) -
(2.0f * Animations[0].Frames[i].quaternion[e].w * Animations[0].Frames[i].quaternion[e].y);
mat.z.y =
(2.0f * Animations[0].Frames[i].quaternion[e].y * Animations[0].Frames[i].quaternion[e].z) +
(2.0f * Animations[0].Frames[i].quaternion[e].w * Animations[0].Frames[i].quaternion[e].x);
mat.z.z =
(Animations[0].Frames[i].quaternion[e].w * Animations[0].Frames[i].quaternion[e].w) -
(Animations[0].Frames[i].quaternion[e].x * Animations[0].Frames[i].quaternion[e].x) -
(Animations[0].Frames[i].quaternion[e].y * Animations[0].Frames[i].quaternion[e].y) +
(Animations[0].Frames[i].quaternion[e].z * Animations[0].Frames[i].quaternion[e].z);
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(&Animations[0].Frames[i].Keys[e], Animations[0].Frames[i].translate);
gumMultMatrix(&Animations[0].Frames[i].Keys[e], &Animations[0].Frames[i].Keys[e], &mat);
gumScale(&Animations[0].Frames[i].Keys[e], Animations[0].Frames[i].scale);
}
}
}
|
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. ;) |
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Sat Apr 05, 2008 8:44 am Post subject: |
|
|
| huh, mrmr[ice]'s libvfpumath deals quaternions with vfpu. You should have a look into it. |
|
| Back to top |
|
 |
Vincent_M
Joined: 03 Apr 2007 Posts: 73
|
Posted: Tue Apr 08, 2008 12:14 pm Post subject: |
|
|
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: |
// set the start and end elements
startQuat = model->FrameArray[e]->AnimationFrame->quaternionKey[currentKey].quaternion;
endQuat = model->FrameArray[e]->AnimationFrame->quaternionKey[currentKey+1].quaternion;
startScale = model->FrameArray[e]->AnimationFrame->scaleKey[currentKey].scale;
endScale = model->FrameArray[e]->AnimationFrame->scaleKey[currentKey+1].scale;
startTrans = model->FrameArray[e]->AnimationFrame->translationKey[currentKey].translate;
endTrans = model->FrameArray[e]->AnimationFrame->translationKey[currentKey+1].translate;
t = (float)(frameNum - interStart) / (float)(interEnd - interStart);
// setup the interpolated quaternion
quaternion.x = startQuat.x + ((endQuat.x - startQuat.x) * t);
quaternion.y = startQuat.y + ((endQuat.y - startQuat.y) * t);
quaternion.z = startQuat.z + ((endQuat.z - startQuat.z) * t);
quaternion.w = startQuat.w + ((endQuat.w - startQuat.w) * t);
// setup the interpolated translation
interTrans.x = startTrans.x + ((endTrans.x - startTrans.x) * t);
interTrans.y = startTrans.y + ((endTrans.y - startTrans.y) * t);
interTrans.z = startTrans.z + ((endTrans.z - startTrans.z) * t);
// setup the interpolated scale
interScale.x = startScale.x + ((endScale.x - startScale.x) * t);
interScale.y = startScale.y + ((endScale.y - startScale.y) * t);
interScale.z = startScale.z + ((endScale.z - startScale.z) * t);
|
The code above is the actual interpolation happening. I apply the interpolated keys to the matrix just as I did above. |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|