开发者

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜