Why My Quaternion Slerp always rotate in same directon?

Started by
4 comments, last by Pet123 17 years, 10 months ago
Hi there i need to rotate character's head in game, everytime rotate the head, current rotation and final destination rotation are known, this should be simple by using quaternion. to my surprise, the quaternion Slerp method always give interpolated results in same direction, even if its obvious to rotate in another direction will be much nearer. i have spent serveral hours to try to get this solved, but no luck. here is the pseudo-code i used to rotate the head, please someone points out where it is going wrong, thank you.


// rot_matrix_current and rot_matrix_dest are known
const float angle = angle_between_current_rotation_and_dest_rotation(rot_matrix_current, rot_matrix_dest);

const quaternion q_current = make_quaternion_from_matrix(rot_matrix_current);
const quaternion q_dest    = make_quaternion_from_matrix(rot_matrix_dest);

// speed is rotation speed, its known value
float t = time_elapsed_since_last_update * speed / angle;
t = clamp(t, 0, 1);

const quaternion q = slerp(t, q_current, q_dest);

rot_matrix_current = make_matrix_from_quaternion(q);

set_head_rotation(rot_matrix_current);


Advertisement
Can you post the slerp() function? Maybe you've left out the dot product check.
hi jyk

sorry for the title maybe its misleading : the slerp() function comes along with the engine we are using.

anyway, by your reply, i guess the method im using here is correct?

ummm i'd better write some code to test the slerp() ... but i doubt its the reason.
Quote:Original post by Pet123
hi jyk

sorry for the title maybe its misleading : the slerp() function comes along with the engine we are using.

anyway, by your reply, i guess the method im using here is correct?

ummm i'd better write some code to test the slerp() ... but i doubt its the reason.
What about angle_between_current_rotation_and_dest_rotation()? Are you sure it's always returning the smallest angle between the two orientations, and that it's always positive?
I do this at the quadratic interpolation stage, given four quats:

quat_previous, quat_a, quat_b, quat_next

// try to make sure that the shortest paths across the 4D hypersphere are followed...
if ( quat_a.dot(quat_b) < 0) quat_b = -quat_b;
if ( quat_a.dot(quat_previous) < 0) quat_previous = -quat_previous;
if ( quat_b.dot(quat_next) < 0) quat_next = -quat_next;

For a simple slerp you probably only need the first line. Hope that helps.
Geocyte Has Committed Suicide.
Quote:What about angle_between_current_rotation_and_dest_rotation()? Are you sure it's always returning the smallest angle between the two orientations, and that it's always positive?


the angle is calculated using dot product of two forward vectors extracted from the two rotation matrices, and actually only its absoulate value used here. i can confirm you that it is the shortest yesterday but now i'd think again and write code to test it. :P

Quote:
I do this at the quadratic interpolation stage, given four quats:

quat_previous, quat_a, quat_b, quat_next

// try to make sure that the shortest paths across the 4D hypersphere are followed...
if ( quat_a.dot(quat_b) < 0) quat_b = -quat_b;
if ( quat_a.dot(quat_previous) < 0) quat_previous = -quat_previous;
if ( quat_b.dot(quat_next) < 0) quat_next = -quat_next;

For a simple slerp you probably only need the first line. Hope that helps.

yeah, it does help and just like what you said only the first line needed in my case.




it works now, i just added this (like what Geocyte said in his reply)
if (q_current.dot(q_dest) < 0)    q_dest = -qdest;


thanks jyk and Geocyte.


This topic is closed to new replies.

Advertisement