Jump to content
  • Advertisement
Sign in to follow this  
slang

OpenGL Skeletal Animation Using Half-Life 2 MDL (SMD)

This topic is 4647 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Over the past few weeks, I have attempted to implement Skeletal Animation using the Half-Life 2 MDL (converted to SMD) file format, but I am suffering from some buggy behaviors. As you can see in the screenshots above, at this point right now, I can correctly render SMD reference models (and construct bone hierarchies, also). However, what I am suffering is this: http://www.quake4.jp/slang/files/videos/flx_hl2_mdl_01.m1v The model in the video is CPU-skinned and I am also implementing GPU skinning simultaneously, but the buggy behaviors are the same in both cases (I am using OpenGL and GLSL, by the way). Hence I suspect that the bone transformations are the problem, maybe relating to DirectX's left-handed coordinate system and OpenGL's right-handed coordinate system, but I am at a loss what I should do. Any ideas?

Share this post


Link to post
Share on other sites
Advertisement
Handedness could be the problem, in which case you want to invert all the Z components of the positions and normals. Rotations should be fine since all you're doing is reconciling the difference in axial handedness.

If that doesn't work, then you might try checking out the HL2 SDK (c_baseanimating.h/cpp in particular) or the Source WiKi. Unfortunately I can't tell you more because I've never worked that closely with any generation of the MDL format.

Share this post


Link to post
Share on other sites
Zipster:

Thanks for your reply.

Well, I had already tried inverting all the Z components of the reference model before, but it didn't work. As you said, I'm gonna check the Half-Life 2 SDK for the source code.

---

Let v denote the vertex position in the reference model space, and let M denote the bone-to-world transformation matrix, then the skinned vertex position v' is given by:



As previously noted, I can correctly calculate the v' in case of reference postures at this point. However, the problem occurs when it comes to animations. So, I am narrowing down the cause of the problem into the bone-to-world transformation matrix M of the animation keyframes.

And I have figured out that the bones used for animations are rotated 90 degrees around Y axis of the reference model space. It's really strange and I think the problem may be related to that.

[Edited by - slang on January 29, 2006 6:14:47 AM]

Share this post


Link to post
Share on other sites
All I've had to work from is this somewhat incomplete reference on the file format. I found a few files in the studiomdl project with the SDK (studiomdl.cpp, bone_setup.cpp) but they were a mess. How are you calculating the vertex position in reference space, or in other words how do you build Mref? In the triangle data I see that each vertex has a world position plus a series of bone weights, which indicates to me that if you can determine the position of a vertex as a function of the weighted bone transformations then you can animate everything properly. However I don't have any working code to play with, so I can't be certain.

Share this post


Link to post
Share on other sites
> How are you calculating the vertex position in reference space,
> or in other words how do you build Mref?

There are mainly two types of the Half-Life 2 SMD file format; one is Reference SMD, and the other is Animation SMD.

In the Reference SMD, as you already noticed, each vertex has its own position in world space (I used "reference space" for this) and there also exists reference bone data (positions and rotations).

Since all the bone data defined in the Reference SMD is given by in their parents' local spaces, first I transform all of the bones' local transformation matrices into the bone-to-world transformation matrices (these will be Mref in the equation, I think). Then I calculate the inverse of Mref in order to transform the vertex from the reference space into the parent's local space, because the bone transformation matrix Mi of the animation is also bone-to-world.

The strange thing is, like I said, the bone data defined in the Animation SMD is 90-degree-rotated around Y axis of the reference space. I almost believe this causes the problem but, more strangely, I have found that not all of the bones are rotated. Some are, but some aren't...

> if you can determine the position of a vertex as a function of the
> weighted bone transformations then you can animate everything properly.

What exactly do you mean "as a function"?

Thanks again.

Share this post


Link to post
Share on other sites
I think I am one step closer to the success of the implementation, but still I have the buggy behaviors...



I updated the video (7.32 MB).
http://www.quake4.jp/slang/files/videos/flx_hl2_mdl_01.m1v

And here goes part of the source code.

void FLXbone::CalculateLocalTransformation(void)
{
glPushMatrix();
{
glMatrixMode(GL_MODELVIEW_MATRIX);
glLoadIdentity();

// bone's local translation and Euler rotations
glTranslatef(m_Position.x, m_Position.y, m_Position.z);
glRotatef(RADTODEG(m_Rotation.z), 0, 0, 1);
glRotatef(RADTODEG(m_Rotation.y), 0, 1, 0);
glRotatef(RADTODEG(m_Rotation.x), 1, 0, 0);

glGetFloatv(GL_MODELVIEW_MATRIX, m_Transformation.m);
}
glPopMatrix();
}


// transform all of the bone transformation matrices into world space
for (i=0; i<m_NumBones; i++)
{
int parent_id = m_Bones.m_ParentID;
mat4 transformation = m_Bones.m_Transformation;

while (parent_id != -1)
{
transformation = m_Bones[parent_id].m_Transformation * transformation;
parent_id = m_Bones[parent_id].m_ParentID;
}

m_TempBones.m_Transformation = transformation;
}

// calculate the inverse of the bone's transformation matrix
for (i=0; i<m_NumBones; i++)
{
m_Bones.m_Transformation = m_TempBones.m_Transformation;
m_Bones.m_Inverse = m_Bones.m_Transformation;

// use quarternion inverse
quat inverse_tm(m_Bones.m_Inverse.m);
inverse_tm.Invert();
inverse_tm.GetMatrix(m_Bones.m_Inverse.m);
}


Any help, comment or indication would be appreciated!!!

Thanks.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!