Jump to content
  • Advertisement
Sign in to follow this  
Ratslayer

Storing info about the mesh animation

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

Hello. I've finally decided to take on 3D animation and here is my understanding of this aspect:

Animation is achieved through movement of a skeleton, whom the mesh's vertices are tied to. Every vertex has a weight variable for each bone that defines how much that vertex is affected by the bone's movement. The movement of the bone is defined in a translation vector and a rotation quaternion.

Now, unless my understanding is wrong, the question is the following: how do I store this information? I have the following format for the mesh data:


struct meshFormat
{
int nVertices;
int nFaces;
Vertex[nVertices] vertices;
int[nFaces*3] faces; //This can vary depending on the triangle drawing method, but lets say it's always a triangle list
}
struct Vertex
{
float[3] pos;
float[3] normal;
float[2] texCoords;
}



So my idea is to use the following format:

struct meshFormat
{
int nVertices;
int nFaces;
int nBones;
Vertex[nVertices] vertices;
int[nFaces*3] faces;
float[nBones*nVertices] weights;
}



But then, the problem is obvious: The size of the file grows immensely. For every bone I get nVertices additional floats, and many of them are just wasted. So my question is: how should I go around that? Am I missing something in the whole skinning/animation picture? Does that post even make sense?

Share this post


Link to post
Share on other sites
Advertisement
What I would do is make something like this...


int nNumBoneWeights[nVertices];
float *pBoneWeights[nVertices];
float fAllVertexBoneWeights[nTotalVertexBoneWeights];





Let's say you were looking at vertex [5].

nNumBoneWeights[5] would tell you how many bones affected that vertex.

pBoneWeights[5] would be a pointer to the first weight of that vertex, which is really just a pointer into fAllVertexBoneWeights where the [5]th vertex's bone weights begin.

fAllVertexBoneWeights is the nonzero weights of all bones for each vertex - ie each bone only has the number of weights it needs but all the weights are in this array and each vertexes weights are next to eachother in the array (ie they are contiguous)

If you are reading this from a binary file, there are ways to make this loadable straight from disk without much manipulation needed. It helps loading time and cachemisses too but not sure if you care about that or not just yet (:

Share this post


Link to post
Share on other sites
I can't understand how I would know what bone precisely affects the vertex by knowing the total number of bone weights. If I understand correctly, if I have like 10 total bones and only bone 2, 5 and 8 affecting the vertex 5 with weights 1.0f, 0.2f, 0.4f, then I would get an array of 3 weight variables [0]=>1.0f, [1]=>0.2f, [2]=>0.4f that I can not associate with the bone spacial transformations, as the indexes 2, 5 and 8 are not retrievable.

Also, what ways are you talking about? I do load from binary files and I guess I do care about loading times (although I won't do much to improve them just yet. But it's always handy to know that such techniques/approaches exist).

Share this post


Link to post
Share on other sites
Sorry you are right, you'd need something like these 2 guys too...


int *pBoneIndex[nVertices];
int nAllVertexBoneIndices[nTotalVertexBoneWeights];



pBoneIndex[5] and would be a pointer to the first bone index and would just be a pointer into nAllVertexBoneIndices.

basically check this out...

nNumBoneWeights[5] would tell you how many bones affected the [5]th vertex.
pBoneWeight[5] would be a pointer to the first bone's weight for the [5]th vertex
pBoneIndex[5] would be a pointer to the first bone's index for the [5]th vertex

Ignore the thing i said about loading times and cache misses because you aren't looking to improve those things right now (wasn't sure when you first asked)

Share this post


Link to post
Share on other sites
You might try a skinned vertex format something like

struct SkinVertex
{
float pos[3];
float normal[3];
float tangent[3];
// ...other stuff here...
ushort jointIndex[4]; // bone
float weights[4]; // or make this [3] and [4] = 1.0 - ([0] + [1] + [2])
};

You would then determine the local transform of each joint (bone) by interpolating the animation data for the joint.
Calculate the skeleton joints world transform by working your way through the skeleton.
Then calculate the skin matrix = jointWorld * jointInvBindMatrix, then make an array of these joint skin matrices, index it using jointIndex[j] and apply it to the vertex using weights[j].

Share this post


Link to post
Share on other sites
Yeah, those ideas make sense. But now that NumberXaero mentioned it, I realized I have no idea how I am actually going to apply my bone info to the vertices themselves. Embedding bone info into the vertex data seems not right: it allows a limited amount of bones to affect the vertex, and it wastes memory if the vertices are part of a static mesh, like environment geometry. The only thing I can think about is passing this bone info as a separate buffer to the video card and then applying it to the mesh prior to any other shading techniques. However, can I do that without having to copy-paste the animation application technique into every effect that uses it (I'm using DirectX)? DX11 allows sharing techniques between effects, if I'm not mistaken, but I'm using DX10, and I'm not sure how to proceed from here. What would be the way to deal with that problem?

Share this post


Link to post
Share on other sites
Why not have a different vertex format for static geometry? The renderer could set the appropriate shader dynamically, based on the vertex type.

Share this post


Link to post
Share on other sites
Yeah, that could work, but the problem with a limited number of bones affecting it is still not solved. Or is it a problem at all?

Share this post


Link to post
Share on other sites
"it allows a limited amount of bones to affect the vertex, and it wastes memory if the vertices are part of a static mesh, like environment geometry"

Just so you know, what i posted allows 0 to N bone weights per each vertex.

one vertex could have 0 bone weights and another could have 50 :P

Share this post


Link to post
Share on other sites
Quote:
Original post by Ratslayer
Yeah, that could work, but the problem with a limited number of bones affecting it is still not solved. Or is it a problem at all?
Many games and mesh formats place an exlicit limit on the number of bones that may affect a single vertex - a common number from a few years back was 4 weights/vertex. My impression is that the weights from any additional bones are likely so small that their influence will not be missed, but an animator would be better qualified to answer that.

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!