Java – from Import 3D skeleton animation from SMD model

I'm writing one SMD importer, I'm trapped in the bone animation part The problem is that I don't know exactly how it works I'm using this to write the exporter, but it doesn't show how to use the information stored in the file

I think all vertices with the same bone ID should be grouped, translated and rotated, because you can't rotate each vertex But I don't know if I'm right. Even if I am, I still don't know how to do this through script

So the question is: how do I use the skeleton animation information stored in the file?

Solution

I'm not particularly familiar with the SMD format, but here

Note: this answer assumes that you know how to construct composite transforms for objects / nodes This is a matrix that combines its translation, rotation and scaling (although it seems that scale is not used in SMD) In addition, matrix multiplication, matrix inversion and matrix * vector multiplication are used

Bones and animation

The nodes of the model form a tree; Except for the root bone (node part), every bone has a parent bone Each node has its own local transformation (position and rotation)

Local node Transformation: the local transformation of a node is constructed from its position and rotation 4 × 4 matrix, which transforms the point from its local space to the space of its parent node: if the vector representing the position in the node space is multiplied by the matrix to obtain the vector in the parent space For details on how to do this, see this link Google a bit more

In SMD, bone transformations are defined only in keyframes (skeleton parts) in animation The "reference" SMD file has a single frame animation; The position and rotation of each bone node in the model reference position

The animation SMD file has an animation sequence containing multiple frames, each frame specifying a different transformation of (some) bones When playing an animation, you can interpolate between frames according to the time of the frame and the current scene / game time, and transform (rotate the position) for each bone

Get static bone transformation

In preprocessing (when the mesh is loaded), you need to calculate the so-called "rest" bone transformation These are the model to bone space transformations for each bone at the reference position The reasons are as follows:

All vertex positions are defined in model space, but ultimately, vertex transformations must start in bone space because you want vertices to move with a single bone Therefore, you must first convert the vertex position into bone space This is the source of static bone turnover

Therefore, the static transformation we are looking for converts vertices from model space to bone space Place all bones in reference positions Traverse the tree from the root node and connect the transformation matrix So, for example, for an upper arm node, you get the transform:

transform = root * spine * shoulderR * upperArmR

However, this is a transformation from upper arm space to model space Therefore, the static bone transformation can be obtained by reversing the matrix Do this for each bone and store these matrices

Note that the rest transformation does not change over time; They are repaired according to the reference position of the model

Vertex / bone Association

Each vertex is associated with one or more bone nodes For each such association, vertices have corresponding weights Typically, the sum of all weights is 1 In SMD, these associations are defined in triangular segments According to the page you linked, the format is:

triangles
my_material
bone_id    x y z    nx ny nz    u v    bone_links

This defines a vertex at (x, y, z) and eventually connects it to the bone_ ID (assuming a weight of 1) bone_ The links section can (sort) override it and specify multiple associations, as follows:

bone_links = num_links bone_id[0] weight[0] bone_id[1] weight[1] ... etc.

If the weight is not equal to 1, the remaining weight is converted to the original bone_ ID Association

Therefore, the example vertices associated with bones 0, 1, and 2 will be:

0    x y z   nx ny nz   u v    3   0 0.15  1 0.35  2 0.5

Vertex Transformation

This is where we finally determine the vertex position according to the current bone transformation As mentioned earlier; Based on the current time and animation, you can determine (insert) the current bone transformation For each bone, the transformation of the bone to the world is calculated Example (we've seen it before):

boneToWorld = root * spine * shoulderR * upperArmR

Now, for vertices associated with a single bone, its animation / skin position is given below:

vertexPosAnimated = boneToWorld * boneAtRest * vertexPosModel

This first converts the vertex position from model space (vertexposmodel) to its associated bone space (this transformation does not change over time) Then, using the current position of the bone, the vertices are converted from bone to model space again This allows it to move with the bone as the transformation changes

It is observed that when the bone is currently in the rest position, boneatrest is the inversion of bonetoworld, so bonetoworld * boneatrest is the identity matrix, so the vertex position remains unchanged, which is correct!

Finally, since vertices can be associated with multiple bones instead of the above, we calculate the above weighted sum of each related bone For example, for vertices associated with 3 bones:

vertexPosAnimated =
    boneToWorld[0] * boneAtRest[0] * vertexPosModel * weight[0] +
    boneToWorld[1] * boneAtRest[1] * vertexPosModel * weight[1] +
    boneToWorld[2] * boneAtRest[2] * vertexPosModel * weight[2];

Last thought

These are some broad strokes. I didn't even discuss shader implementation (if that's what you want to do), but I think I've covered all the principles, and it's a long answer

One thing I found helpful in 3D engine development was M3G documentation (old Java mobile 3D API) The entries on SkinnedMesh basically describe what I post here

In addition, try to understand the concept of converting vertices from model to bone space using static bone transformation, and return again using its current transformation This is the key to the whole thing

Good luck!

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>