Quaternion problem (with exe)

Started by
13 comments, last by Nathaniel Hammen 19 years, 6 months ago
I have a feeling the bone for your model's left arm is falling into the 'invert cosine' special case. It's probably the only bone that's going through that case too, based on the angles that the bones are rotating through. The if statement for LERP/SLERP is there just to protect the acos(x) function ... so odds are the LERP portion is never being used. Personally, I'm not sure falling back to a LERP is necessary -- I've never needed it myself.

The important part is that if you invert the cosine, you need to normalize the slerped quaternion.
temp.x = first.x * scale0 + second.x * scale1;temp.y = first.y * scale0 + second.y * scale1;temp.z = first.z * scale0 + second.z * scale1;temp.w = first.w * scale0 + second.w * scale1;if (cosineWasInverted) { result = temp.Normalize(); }else { result = temp; }


There are two other interesting things to note, instead of inverting the cosine, you should also be able to invert the scale0 factor. When you invert the cosine, what you're saying is, instead of slerping clockwise, slerp counter clockwise, because the shorter arc is in that direction. Inverting scale0 lets you precalculate scale0 and scale1 and then do an if{} block for the scale / normalize. I'm also inverting sine omega, because we want to minimize our slow floating-point divides for the CPU. I'd also recommend you implement inlined quaternion operators for *scale and +quaterion (that's definitely just me though).

   double omega, sinom;   // standard case (slerp)   omega = acos(cosine);   inv_sinom = 1/sin(omega);   scale0 = static_cast<float>(sin((1.0 - time) * omega) * inv_sinom);   scale1 = static_cast<float>(sin(time * omega) * inv_sinom);   if (cosine < 0.0f) {      // invert the scale and normalize      scale0 = -scale0;      // Would be nice to see some Quaternion operators here      // e.g. result = first*scale0 + second*scale1 !!!      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;      // Now normalize the final quaternion      result.Normalize();   }   else {      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;   }


Check the code with breakpoints first. If the cosine inversion is ONLY happening with the left-arm bone, then you know there's a solid chance that this is your problem. Then try to apply the minimal fix from the first code snippet. If that works you can consider some other options for improving the slerp.
Advertisement
Just FYI,

your exe does not shutdown properly. I downloaded it to look at it and closed out of it... three hours later I noticed my system was running really slow and went into taskmanager and it was still there taking up 98% of the CPU
Quote:Original post by Anonymous Poster
your exe does not shutdown properly. I downloaded it to look at it and closed out of it... three hours later I noticed my system was running really slow and went into taskmanager and it was still there taking up 98% of the CPU


Does the same thing on my system too.
Sorry about the shutdown thing, it will shutdown properly if you use Esc key, i don't know how to shut it down properly from the X button in GLFW.
Quote:Original post by GamerSg
Sorry about the shutdown thing, it will shutdown properly if you use Esc key, i don't know how to shut it down properly from the X button in GLFW.


if(!glfwGetWindowParam(GLFW_OPENED)) tell it to quit.

Of course, you could always look in the reference to find this kind of thing out.

[Edited by - Nathaniel Hammen on September 25, 2004 10:22:17 PM]
I am the master of ideas.....If only I could write them down...

This topic is closed to new replies.

Advertisement