Advertisement

Applying per frame translation in animation BVH

Started by December 03, 2023 12:15 AM
1 comment, last by Alberth 11 months, 3 weeks ago

I’m currently working on a project involving animation using BVH (Biovision Hierarchy) data for animation. Slightly confused on how per frame translation would be applied to the animation. I have the new frame translation as newpos but im not sure how to apply it to animation correctly. BVH file's have offset which are described in the parent's coordinate system. Each new positions per frame should be relative to the parent in BVH files, if I remember correctly. I'm not sure how to apply it. Do I need to remove jointPos and replace with the new position or do I need to keep and use both?

void Skeleton::drawJoint(Mat4& viewMatrix, Mat4 parentMatrix, Joint* joint, uint32_t currFrame)
{ 
    
    vec3 offset_from_parent = vec3(
    	joint->jointOffsetX,
    	joint->jointOffsetY,
    	joint->jointOffsetZ
    );
    
    // new position I need to apply to translate     
    vec3 newpos = vec3(
    	frames[currFrame][BVH_CHANNEL[joint->joint_channel[0]]],
    	frames[currFrame][BVH_CHANNEL[joint->joint_channel[1]]],
    	frames[currFrame][BVH_CHANNEL[joint->joint_channel[2]]]
    );
    
    auto jointPos = parentMatrix * (offset_from_parent);
    // get rotation for current joint for current frame
    auto boneRot =  parentMatrix * bone_rotations[currFrame][joint->id];
    
    // BVH stores rotation as Z,Y,X so, boneRot.x would be rotation for z
    auto z = boneRot.x;
    auto y = boneRot.y;
    auto x = boneRot.z;
    
    //z,y,x multiply like: x,y,z
    auto local = Mat4::Translate(jointPos) * (Mat4::RotateX(x) * Mat4::RotateY(y) * Mat4::RotateZ(z));
    
    for(auto& child : joint->Children)
    {
        vec3 end = local * vec3(child.joint_offset[0], child.joint_offset[1], child.joint_offset[2]);
    	drawCylinder(viewMatrix, jointPos, end);
    
        drawJoint(viewMatrix, localMatrix, &child, scale, frame);
    }
    
}

Simply trying it may give a faster answer than waiting for someone to answer the question.

Try to figure out what you see as the most likely correct solution, and build it in a small scale. If it works, you're done. If it fails you learned your idea was wrong, try to figure out what is wrong, correct it, and try again.

Even if you do get an answer before you're done, such experiments are useful to get experience. Not only in setting up and doing them, but also in building knowledge in these systems, so the next time you remember what didn't work before (and why), so you can avoid that.

By waiting for the correct answer instead of trying it yourself, you won't ever see the wrong approaches, so you're not going to be aware of them the next time.

This topic is closed to new replies.

Advertisement