Interpolation using boost:timer and slerp, quaternions
Im aware this code just looks like a massive block of mess so iv'e done my best to comment what i can... If anyone regularly does skeletal animation im hoping youl see whats going on here.
The problem im having is that float interp = (next-current)/(next-start);
is not returning whats expected, e.g. values greater than 1 and minus values... Im guessing this is the whole reason the animations arent being shown and theres no other underlying mistakes.. If there is anything obvious sticking out please let me know.
m_animations
stores all the keyframe information for a joint.
void Animation::getRotation(Joint& J) {
int i=0,j=0; //i for bone to animation j for which keyframe in animation
float start, next, current = m_time.elapsed(); //storing time elapsed to keep it the same thoughout method to avoid errors
for (i=0; i<m_animations.size(); i++) {
if(m_animations[i].m_bname == J.name) //finds which bone is being animated
break;
} //retrieve the correct 'anim' for Joint
if (current > m_animations[i].rx_time[m_animations[i].rx_time.size()-1]) { //checks to see if end of animation
m_time.restart();
current = m_time.elapsed(); //resets the animation at its end
}
for (j=0; j<m_animations[i].rx_time.size()-1; j++) {
if(m_animations[i].rx_time[j] >= next && next < m_animations[i].rx_time[j+1]) { //finds the keyframe
start = m_animations[i].rx_time[j]; //start time of current frame
next = m_animations[i].rx_time[j+1]; //end time of current frame
break;
}
}
cout << start <<" "<< current <<" "<< m_time.elapsed() <<" "<< next << endl;
//Get start and end quaternions for slerp
Rotation3 Rj(m_animations[i].rx_angle[j], m_animations[i].ry_angle[j], m_animations[i].rz_angle[j], J.translation);
J.quat = Rj.GetQuat(); //rotating to
Rotation3 R = Rotation3(m_animations[i].rx_angle[j+1], m_animations[i].ry_angle[j+1], m_animations[i].rz_angle[j+1], J.translation);
Quat4 q = R.GetQuat(); //rotating开发者_如何学运维 from
float interp = (next-current)/(next-start); //find interpolation point
Quat4 slerp = Slerp(J.quat, q, interp); //sphereical linear interpolation
R = Rotation3(slerp,J.translation);
J.rotation.PasteRotation(R.GetRotationMatrix());
}
Also if it helps heres the update skeleton function that calls getRotation
void Animation::update_skeleton(Joint& J) {
getRotation(J);
J.world.PasteTranslation(J.translation); //world becomes translation matrix
J.world *= J.rotation;
if(J.pName != "") {
J.world = Mat4(J.parent->world) *= J.world; //as not to overwrite the parents world matrix
}
J.translation = J.world.ExtractTranslation();
for(int i=0; i<J.children.size(); i++) {
update_skeleton(*J.children[i]);
}
}
Also when i run my program, it seems to be as if there is only one joint... So im guessing something might be going wrong with the J.translation
value during getRotation, but im hoping that fixing my interpolation problem might solve this...
Any help will be VERY appreciated.
You seem to be resetting current before using the original values of start and next, if I've read the code properly that will be causing current to be greater than next, leading to yor negative interpolations.
Turns out there were quite a few mistakes... But the main error was to do with pointers, I fixed it by giving the bones ids for parents, children and itself. Then I changed the functions to take bone id instead of reference to a joint. Problem = fixed :D
精彩评论