Jump to content
  • Advertisement
Sign in to follow this  

Confusion Of Assimp Sdk, Animation System Design Need Advice

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

Hellow !

I 'm going to make an animation system for game......

I will export models to custom format model using the assimp sdk.  I will only export joint nodes and mesh nodes, and animation data.  

The  output scene file format will look like these:


  <JointNode>  lcltransform  .....

     <meshNode>  lcltransform....  <\meshNode>


  ......many joints to omit.



The JointNode holds inverse bind pose matrix .

As for the MeshNode, I know , I know, the static mesh is not completely static, the "static" means it can not be deformed,

it can also have motions, so mesh will be implemented as MeshNode. It will inherit transform from  ancestors, so it will move!!  

As for the ModelNode, why it inherit from SceneNode is that  it act as the root node of all joint nodes and model nodes,   somewhat look like  assimp root node.

All these node will hold local transform.



The question is, assimp scene nodes are not just joint nodes and mesh nodes, and "pure node", which is used to pass transform, the root is the most apparent one.

I 'm confusing that  whether it will go wrong, if I don't export these nodes, because I'm afraid that some "pure nodes" would have a non-identity transform !!


In the animation export part , I will use these code:

std::map<std::string, int> name2Joint;

struct animation 

  void export() 
     export(duration, tickPersecond);
     for(node in influenced nodes) 
        jointID = name2Joint[node.name];
        export(jointID, frame.pos, frame.rot, frame.scale);
My animation system is the one of the most naivest animation system in the world , it can only import, and display .
I have not begin to code, and I don't know if it will work, so
I will show my code,  and if someone find any mistake or have a better implementation, please tell. 
Here's are my data structure regarding animation in the engine side:
struct Frame 
   _pos, _rot, _scale; // all are  reference to parent
struct JointFrame 
  _jointID;                                        // will be used to find joint node at update time
  vector<Frame> _frames;
struct Animation 
  vector<JointFrame> _jointFrames;
  void update();
And here's the data structure of Model in engine side:
struct SceneNode 
  SceneNode  *_parent;
    pos, rot, scale;             // all are  reference to parent
  virtual  void update();
  virtual   void postUpdate()=0;
struct Joint : public SceneNode 
  Matrix4f _invBindMat;  // inverse bind matrix
struct Model  : public SceneNode  
//why it inherit from SceneNode is that 
// it act as the root node of all joint nodes and model nodes,   somewhat look like  assimp root node
   vector<Mesh> _meshes;  
   vector<Joint*> _joints;
   vector<Matrix4f> _JointFinalMats
   void PostUpdate();       // use to update _JointFinalMats after all Joints' GlobalTransform have updated, will be called by Scene
struct Scene
  vector<SceneNode*> _nodes;
  void update();


The flowchart of big big updates :



   animation.update();  //  update joint's local transform by keyframes

    foreach(node in _nodes) node.update();    // update joint's global transform

    foreach(node in _nodes) node.postUpdate();  // update jointFinalMat array




void Animation ::update() 
   for(jointFrame in   _jointFrames) 


      frame = jointFrame.findFrame(gametime);

      joint =   this->parentModel.findJoint(jointFrame._jointID);


      // all are reference to parent







void SceneNode::update() 
   _globalTransform = localTransform(_pos, _rot, _scale)  *    _parent->_globalTransform ;



void Model::postUpdate() 

    foreach(joint in _joints) 


       _JointFinalMats[joint.ID] =  joint._invBindMat * joint._globalTransform;




After I have attached joints to scene graph,  and Scene::update will call joint::update, where  jointFinalMat = inverseBindposeMat *  jointGlobalTransform

will take place. Since the jointGlobalTransform has contain  ToRootMat,  I will pass a identity matrix to shader as a world matrix.

The code will look like :


    worldMat = Identity;

  worldMat =  mesh.globalTransfom


the shader code:

cbuffer cbPerObject : register(b0)
row_major float4x4 worldMat;
row_major float4x4 worldInvTransposeMat;
row_major float4x4 worldviewprojMat;
cbuffer cbSkinned : register(b1)
row_major float4x4 boneMat[96];


struct SkinnedVertexIn
float3 PosL       : POSITION;
float3 NormalL    : NORMAL;
float3 TangentL   : TANGENT;
float2 Tex        : TEXCOORD;
uint4 BoneIndices : BONEINDICES;
float4 Weights    : WEIGHTS;


VertexOut vsmain(SkinnedVertexIn vin)
VertexOut vout;
float weights[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
weights[0] = vin.Weights.x;
weights[1] = vin.Weights.y;
weights[2] = vin.Weights.z;
weights[3] = 1.0f - weights[0] - weights[1] - weights[2];
float3 posL = float3(0.0f, 0.0f, 0.0f);
float3 normalL = float3(0.0f, 0.0f, 0.0f);
float3 tangentL = float3(0.0f, 0.0f, 0.0f);
for (int i = 0; i < 4; ++i)
posL += weights * mul(float4(vin.PosL, 1.0f), boneMat[vin.BoneIndices]).xyz;
normalL += weights * mul(vin.NormalL, (float3x3)boneMat[vin.BoneIndices]);
tangentL += weights * mul(vin.TangentL.xyz, (float3x3)boneMat[vin.BoneIndices]);
vout.PosW = mul(float4(posL, 1.0f), worldMat).xyz;
vout.NormalW = mul(normalL, (float3x3) worldInvTransposeMat);
vout.TangentW = mul(tangentL, (float3x3)worldMat);
vout.PosH = mul(float4(posL, 1.0f), worldviewprojMat);
vout.Tex = vin.Tex;
return vout;

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!