Sign in to follow this  

Skinned meshes/Skeletal animation (Without D3DX)

This topic is 4105 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

Hey guys, I'm looking into finally getting skeletal animation into my engine, but I've hit a few roadblocks. First off, I don't want to use D3DX to do it (I'll explain why at the end, as it's quite ancillary to the problem). Secondly, I'm intending to support methods for skinning in software, the fixed-function pipeline and using vertex shaders, so any information on any of these methods would be appreciated. Anyways, I understand the basic concepts and implementation of skinning for an object with <= ~4 bones: just set up the matrix table (Or the VS registers, which I'll consider as parallel to as the matrix table for clarity) with the respective bone matricies, set the appropriate weights for the verticies and all should be peachy. However, most objects that use bones in a game have a tendency to use far more than 4 bones, with an average of between 24-32 bones being fairly standard for a humanoid character. Most literature I've read on skinning seems to either forget or avoid this rather serious problem. So what happens in these situations? I can't load new bones into the matrix table whilst the vertex buffer is in mid-process, so it would appear that I'd have to break the object into several VBs so that I can modify the table between sections. But yet again, this causes a problem. What happens in situations where a triangles verticies use differing matricies? Say a triangle uses verticies A, B and C, where A and B use 2 differing bones each (For a total of 4 bones) and vertex C uses a different matrix altogether (Bringing the grand total to 5, above the assumed limit), it's not possible to change the vertex buffer at a certain point in a triangles rendering. So, a possible solution would be to limit each triangle to use a maximum of 4 bones, and discard the ones with the lowest influence while duplicating the verticies on the triangles edge so that neighbouring triangles can still use the most appropriate bones. However this creates an addition problem where cracks will start to appear in the mesh at the triangle seams during animation. Obviously, this is only a really major problem with using the fixed-function pipeline. In software I can store additional information in the verticies and grab matricies as I need them (Even though it would be more efficient to only keep a select number in use at any one time to avoid thrashing the cache). In shaders, however, the problem still seems to apply, as there's only a certain number of registers you can use at any one time (Roughly 8 matricies, if I'm not mistaken), but I can't be too sure of this am I'm still a shader virgin. So, the question is, how do you guys deal with processing meshes to deal with skinning? How do you get around these problems? Also, as an additional question, how do you guys go about selecting which verticies will go into which vertex buffer? I'm thinking that walking through the mesh and collecting information about how many bones have been used (While trying to minimise the amount of unique bones referenced) would probably work, but it could produce situations where some vertex buffers only contain several verticies which could mean that a mesh, under dire circumstances, could have up to or above 60 VBs, which I'd like to avoid if possible. Note: The reasons I've chosen not to use D3DX are various. The primary reason is that I want to implement this from the ground up so that I can get a better understanding of the problems of and solutions to skeletal animation. The secondary reason is compatability, so that if I choose to make a Linux, MacOS, PSP or other port in the future, I won't have to return to the issues currently at hand. The third reason is that I want to use my own file format, as I'm a bit of a control freak and I like to be able to keep my file formats as my own where sensibly applicable. :)

Share this post


Link to post
Share on other sites
Quote:
how do you guys deal with processing meshes to deal with skinning? How do you get around these problems?


I'm not sure what you mean by the 4-bone limit. What is limiting you to only 4 bones? If implemented properly, you should be able to have an infinite number of bones (only to be limited by memory availability).

The way I understand it, a skeleton is a hierarchical tree of bones (nodes). As a node, each bone has a parent and a list of children. As a spatial entity, each bone would have its own individual transformation matrix (4x4).

For skinning, each bone has a list of 'attached' vertices (by index) and weight-values for each attached vertex.

From your post, it seems that you are linking individual triangles to each bone, which would indeed cause problems with the skinning.

You traverse the skeleton from top-down, transforming each child bone by its parent bone (using the local transform matrices). After transforming a bone, you transform the vertices attached to the bone (again, using the new local transform matrix, and also the bones weight-value for each vertex). Finally, when the entire skeleton has been traversed, you render the entire deformed mesh as a whole. Only one VB is needed. This process is destructive to the original mesh, so you'd probably operate on a copy of the mesh.

Here is how I learned:
http://darwin3d.com/gdm1999.htm
http://darwin3d.com/gamedev/articles/col1099.pdf

http://darwin3d.com/gdm1998.htm
http://darwin3d.com/gamedev/articles/col0598.pdf

Hope this helps.

[Edited by - swordfish on September 17, 2006 6:52:49 AM]

Share this post


Link to post
Share on other sites
That's the software method of skinning, which is fairly easy for me to understand due to the fact that it doesn't suffer from imposed limitations (Although the idea of having the bone maintain a list of verticies instead of vice-versa is a good idea, thanks for that. :))

The problem comes around with using hardware skinning, be it fixed-function or vertex-shader. In fixed-function (As to my understanding), each vertex can have up to 8 weights (Although hardware support varies from 4 to 8 out of what I've seen), but there's no way to store a list of bone indices. It works by having a seperate table of 8 matricies (Pre-calculated from the hierachial skeleton), and the weights on the vertex directly map the entries in that table. This is where the 4-bone limit comes from (I chose 4 rather than 8 because I prefer to work from the worst case up).

Share this post


Link to post
Share on other sites
Okay, I see your predicament now.

http://www.gamasutra.com/features/20030325/fernando_05.shtml

That might help, but I don't see anything that implies that any more than 4 bones would be available. I've never attempted hardware skinning, so this is a bit of a grey area for me. From the looks of it, you'll have to figure out a clever and creative way to do so. I'm surprised there isn't more info on this topic.

Quote:
Although this example is rather limited, you could generalize it to handle more bone matrices, general bone matrices (for example, allowing scaling), and matrices influencing each vertex-and to compute a better lighting model.

Share this post


Link to post
Share on other sites
For GPU skinning, it is common for each vertex to be weighted to at most 4 joints (perhaps this is what you meant?). This kind of limitation is not really present when doing it in software and you don't need to be concerned with the limitations of vertex shaders (although the 4 weight maximum is just good practice as you can just use a float4 for the weights and a float4 for the joint indices).

Even when skinning on the GPU, you don't need to have you artists limit themselves to 26ish joints. You can split a model up into batches so you only need to send the transform matrices for your maximum amount of bones to the GPU. This doesn't mean multiple VBs, just multiple draw calls. This can be quite a headache to get right though, as you need to map your actual skeleton to smaller batches and have your change your vertices joint indices to reflect those maps.

The best example I can think of that would introduce you to all the potential problems of skinning (and one that I've tackled myself) would be to skin Doom 3's md5mesh format on the GPU [smile]

Here are a couple of resources that would make for interesting reading ...

Md5Mesh and Md5Anim file formats and skinning in software
PfhorSlayer's Journal entry on GPU skinning an md5mesh

All the best,
ViLiO

Share this post


Link to post
Share on other sites
Quote:
Original post by ViLiO
You can split a model up into batches so you only need to send the transform matrices for your maximum amount of bones to the GPU. This doesn't mean multiple VBs, just multiple draw calls.


Ack, you're completly right here. Don't know where I got the idea for using multiple vertex buffers.

Thanks!

Share this post


Link to post
Share on other sites

This topic is 4105 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this