<p>I’m currently working on a project involving animation programming using OpenGL and BVH (Biovision Hierarchy) data for animation, and I am trying to get my head around it. I’ve run into some issues and could use some insight.</p>
<p>The problem I’m facing is that when I render my animation, it doesn’t come out as expected. I find the format of BVH quite confusing but this seems correct and it should work but the animation looks quite odd.</p>
<p>I am unsure if, for each rotation you need to multiply it by the parentMatrix? doing this seemed to prevent the legs going up to the up and flicking back down so I assumed it was correct?
BVH file: <a href="https://pastebin.com/4w2Qv5TD" rel="nofollow noreferrer">mixamo.bvh</a></p>
<pre><code>void Skeleton::drawJoint(Mat4&amp; viewMatrix, Mat4 parentMatrix, Joint* joint, uint32_t currFrame)
{ 
    
    vec3 offset_from_parent = vec3(
        joint-&gt;jointOffsetX,
        joint-&gt;jointOffsetY,
        joint-&gt;jointOffsetZ
    );
        
        vec3 anotherRot = vec3(
        frames[currFrame][BVH_CHANNEL[joint-&gt;joint_channel[0]]],
        frames[currFrame][BVH_CHANNEL[joint-&gt;joint_channel[1]]],
        frames[currFrame][BVH_CHANNEL[joint-&gt;joint_channel[2]]]
    );
    
    auto jointPos = parentMatrix * (offset_from_parent);
        // get rotation for current joint for current frame
    auto boneRot =  parentMatrix * bone_rotations[currFrame][joint-&gt;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&amp; child : joint-&gt;Children)
    {
        vec3 end = local * vec3(child.joint_offset[0], child.joint_offset[1], child.joint_offset[2]);
        drawCylinder(viewMatrix, jointPos, end);
    
        drawJoint(viewMatrix, localMatrix, &amp;child, scale, frame);
    }
}
</code></pre>
<p><a href="https://i.sstatic.net/1UGte.gif" rel="nofollow noreferrer"><img src="https://i.sstatic.net/1UGte.gif" alt="enter image description here" /></a></p>

CC BY-SA 4.0
2023-12-02T16:52:51.327Z
I don't know the bvh format, but a rotation matrix can also be seen as a orientation matrix same with euler angles. Which would be better, because then the orientation is given as euler angles and you are free to use e. G. quaternions instead. So try to not simply multiply the current orientation with the next key frame euler angles, but try to interpolate the orientation from current to next key frame.
Thomas
CC BY-SA 4.0
2023-12-02T19:18:25.057Z
@Thomas Thanks for the suggestion. Adding interp right now would complicate things. I need to get it running without interp, without my rotations being weird before I start implementing interp
blov
CC BY-SA 4.0
2023-12-10T09:56:48.493Z
Can I suggest you modify the title? BVH seems a very unfortunate abbreviation as today it’s surely going to be read as “Bounding Volume Hierarchy”. (I’ve been in graphics for decades and not heard of Biovision Hierarchy before)
Simon F
<opengl><transformations><animation>
Animation issue using BVH data in OpenGL
blov
# Animation issue using BVH data in OpenGL

(Asked by: username_0 on 2023-12-02)

I’m currently working on a project involving animation programming using OpenGL and BVH (Biovision Hierarchy) data for animation, and I am trying to get my head around it. I’ve run into some issues and could use some insight.

The problem I’m facing is that when I render my animation, it doesn’t come out as expected. I find the format of BVH quite confusing but this seems correct and it should work but the animation looks quite odd.

I am unsure if, for each rotation you need to multiply it by the parentMatrix? doing this seemed to prevent the legs going up to the up and flicking back down so I assumed it was correct?
BVH file: [mixamo.bvh](https://pastebin.com/4w2Qv5TD)

```
void Skeleton::drawJoint(Mat4& viewMatrix, Mat4 parentMatrix, Joint* joint, uint32_t currFrame)
{ 
    
    vec3 offset_from_parent = vec3(
        joint->jointOffsetX,
        joint->jointOffsetY,
        joint->jointOffsetZ
    );
        
        vec3 anotherRot = 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);
    }
}

```

[![enter image description here](https://i.sstatic.net/1UGte.gif)](https://i.sstatic.net/1UGte.gif)

**Tags:** opengl, transformations, animation

> **Comments:**
> **username_1**: I don't know the bvh format, but a rotation matrix can also be seen as a orientation matrix same with euler angles. Which would be better, because then the orientation is given as euler angles and you are free to use e. G. quaternions instead. So try to not simply multiply the current orientation with the next key frame euler angles, but try to interpolate the orientation from current to next key frame.  
> **username_0**: @username_1 Thanks for the suggestion. Adding interp right now would complicate things. I need to get it running without interp, without my rotations being weird before I start implementing interp  
> **username_2**: Can I suggest you modify the title? BVH seems a very unfortunate abbreviation as today it’s surely going to be read as “Bounding Volume Hierarchy”. (I’ve been in graphics for decades and not heard of Biovision Hierarchy before)  

---

## 0 answers

