Jump to content
  • Advertisement
Sign in to follow this  
GamerSg

Quaternion problem (with exe)

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

I recently finished doing skeletal animation, but every once in awhile, there will be bones which dont seem to animate the way they should. In other words, they dont take the path they should and rotate weirdly. Example Here Click on the Skeletal.zip link. [Edited by - GamerSg on September 23, 2004 1:55:44 AM]

Share this post


Link to post
Share on other sites
Advertisement
There is totally no scaling/translation in my code, so im only doing rotation via quaternions. As you can see, it works normally for all the other bones, but screws up for the right hand.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Maybe your animation matrices do not match with the amount of reference matrices.

In other words:
if your reference mesh has 25 BONES and your animation does not,
every time you transform the inverted world vertices wia tha animation world matrix, you have to check if it is the same, for example:

for ( i=every bone in reference mesh )
for ( j=every bone in animation mesh )
if ( ref_bone.name == anim_bone.name )
do transform
else
keep reference bone.

Share this post


Link to post
Share on other sites
I was thinking the problem lies more with my Quaternion Interpolation, if you observe the animation closely, the figure is doing a jumping jack (couldnt think of any other animation) which goes something like this (in keyframes)

1)
o
| |
||

2)

__ o __
| |
/ \
3)
o
| |
||

4)

\ o /
| |
/


If you notice, the right hand does reach the keyframes. The problem lies with the path it takes to reach the next keyframe. For some reason, the left hand seems to work well.

Share this post


Link to post
Share on other sites
Perhaps you need to normalize some quaternions somewhere... like after transforming a child bone's rotation by a parent bone's? (Your download link didnt work when I tried so couldn't get a better look)

I've had some pretty interesting looking animations before when I forgot to normalize.

Share this post


Link to post
Share on other sites
Sorry about the link.

Is it a must to normalize?
When should i normalise?
Obviously normalizing every quaternion is going to result in quite a hit in performance?

Share this post


Link to post
Share on other sites
You certainly need to normalise before you build a rotation matrix from your quaternion (unless your quat to matrix routine auto-normalises), otherwise you'll get shearing or scaling problems.
You don't need to normalise every time you multiply quaternions together.

Share this post


Link to post
Share on other sites
Hmm i just looked through my code and realised that i am not doing the rotation multiplication with quaternions, instead im converting a bone's quaternion to a matrix first, before multiplying the matrix with the parents matrix.

Also, all my quaternions are normalised before they are exported.

Share this post


Link to post
Share on other sites
Still stuck with no clues.

Link should be fixed now.
Here is my quaternion interpolation code which i had obtained from the quaternion article on gamasutra.

void Math::InterpolateQuat(Quat& first,Quat& second,Quat& result,float time)
{
//Interpolates between 2 quaternions based on time factor ranging from 0-1
//Variables
double cosine;
Quat temp; //temp quaternion
float scale0,scale1;

//dot product between the 2 quats
cosine = first.x * second.x + first.y * second.y + first.z * second.z + first.w * second.w;


if(cosine<0.0)
{
//if it is negative, make it positive
cosine = -cosine;
temp.x = -second.x;
temp.y = -second.y;
temp.z = -second.z;
temp.w = -second.w;
}
else
{
temp.x = second.x;
temp.y = second.y;
temp.z = second.z;
temp.w = second.w;
}

if ( (1.0 - cosine) > 0.0001 ) {
double omega, sinom;
// standard case (slerp)
omega = acos(cosine);
sinom = sin(omega);
scale0 = static_cast<float>(sin((1.0 - time) * omega) / sinom);
scale1 = static_cast<float>(sin(time * omega) / sinom);
}
else {//else do LERP
scale0 = 1.0f - time;
scale1 = time;
}


result.x = first.x * scale0 + second.x * scale1;
result.y = first.y * scale0 + second.y * scale1;
result.z = first.z * scale0 + second.z * scale1;
result.w = first.w * scale0 + second.w * scale1;
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!