Community
FBX Forum
Welcome to Autodesk’s FBX Forums. Share your knowledge, ask questions, and explore popular FBX topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Porting a max plugin exporter to a fbx importer

3 REPLIES 3
SOLVED
Reply
Message 1 of 4
obt
Participant
1415 Views, 3 Replies

Porting a max plugin exporter to a fbx importer

I have a working 3dsmax exporter, which can export a skin modifier model in max to a model format for my game engine. The model in my game engine is animated and posed correctly.

 

Upon export from max I call GetNodeTM a alot. I noticed in fbx one have to use

EvaluateGlobalTransform/EvaluateLocalTransform, but these apparently does not do what GetNodeTM does.

 

How do I in my fbx import code obtain the GetNodeTM matrix from an FBXNode?

 

Thanks,

obt

 

3 REPLIES 3
Message 2 of 4
obt
Participant
in reply to: obt

I have done some traces from my 3dsMax plugin:

 

Matrix3 matOffset = node->GetNodeTM(pInterface->GetTime());

AffineParts ap;

decomp_affine(matOffset, &ap);

TRACE("Name= %16s, pos= %6.2f,%6.2f,%6.2f, rot= %6.2f,%6.2f,%6.2f,%6.2f\n",

node->GetName(), ap.t.x, ap.t.y, ap.t.z, ap.q.x, ap.q.y, ap.q.z, ap.q.w);

 

Name= Bip01, pos= 0.98, -1.95, 38.57, rot= -0.71, -0.00, 0.00, 0.71
Name= Bip01_Pelvis, pos= 0.98, -1.95, 38.57, rot= -0.71, -0.00, -0.00, 0.71
Name= Bip01_L_Thigh, pos= 4.87, -1.95, 38.57, rot= -0.02, -0.68, -0.02, 0.73
Name= Bip01_L_Calf, pos= 6.13, -1.03, 20.74, rot= -0.03, -0.68, -0.03, 0.73

Name= Bip01_L_Foot, pos= 7.30, 0.39, 4.28, rot= 0.34, -0.62, 0.22, 0.67
Name= Bip01_L_Toe0, pos= 8.02, -3.59, 0.48, rot= 0.53, -0.40, 0.45, 0.60
Name= LToeeff, pos= 9.14, -7.35, 0.48, rot= 0.53, -0.40, 0.45, 0.60
Name= Bip01_R_Thigh, pos= -2.91, -1.95, 38.57, rot= -0.02, -0.73, -0.02, 0.68
Name= Bip01_R_Calf, pos= -4.01, -1.03, 20.75, rot= -0.03, -0.73, -0.03, 0.68
Name= Bip01_R_Foot, pos= -5.02, 0.39, 4.28, rot= 0.19, -0.68, 0.38, 0.60

 

And here are the similar traces from my FBX importer:

 

FbxAMatrix matOffset = pNode->EvaluateGlobalTransform();

FbxVector4 t = matOffset.GetT();

FbxQuaternion q = matOffset.GetQ();

 

TRACE("Name= %16s, pos= %6.2f,%6.2f,%6.2f, rot= %6.2f,%6.2f,%6.2f,%6.2f\n",

pNode->GetName(), t[0], t[1], t[2], q[0], q[1], q[2], q[3]);

 

Name= Bip01, pos= -0.00, 38.57, 0.53, rot= -0.00, -0.00, 0.00, 1.00
Name= Bip01_Pelvis, pos= 0.00, 38.57, 0.53, rot= -0.00, 0.00, -0.00, 1.00
Name= Bip01_L_Thigh, pos= 3.89, 38.57, 0.53, rot= -0.50, 0.50, -0.47, 0.53
Name= Bip01_L_Calf, pos= 5.16, 20.74, -0.39, rot= -0.50, 0.50, -0.46, 0.54
Name= Bip01_L_Foot, pos= 6.33, 4.28, -1.81, rot= 0.71, -0.28, 0.60, -0.24
Name= Bip01_L_Toe0, pos= 7.04, 0.48, 2.17, rot= 0.80, 0.04, 0.60, -0.05
Name= LToeeff, pos= 8.16, 0.48, 5.93, rot= 0.80, 0.04, 0.60, -0.05
Name= Bip01_R_Thigh, pos= -3.89, 38.57, 0.53, rot= -0.47, 0.53, -0.50, 0.50
Name= Bip01_R_Calf, pos= -4.99, 20.75, -0.39, rot= -0.46, 0.54, -0.49, 0.51
Name= Bip01_R_Foot, pos= -6.00, 4.28, -1.81, rot= 0.56, -0.22, 0.75, -0.29

 

From the plugin, y and z are reverted, and z negated. Beside this, it is interesting that the y values are identical between the runs.

In the FBX importer, the quarternions are all different than the plugin, could that be the problem? The model after FBX import looks exploded in all directions.

 

 

 

 

Message 3 of 4
obt
Participant
in reply to: obt

I finally got my FBX importer to work in my DirectX 11 game engine. The models I import come in correctly posed, and they are correctly animated as well. These are skinned multi mesh models. The trick? Do the steps I did in my max plugin:

 

1.  Swap y and z when reading the control points

2.  Read tu as it is, and modify tv to 1.0-tv

3.  For polygon sizes > 3, create a fan of triangles

4.  Reverse triangles (0->2, 1->1, 2->0). Save vertices, texvertices, and indices into own arrays.

5.  When looping over the clusters, just retrieve the bonelink name, the vertex indices, and weights.

     Save these 3 params in own skin array per bone. Don't get any matrices whatsoever!

6.  Upon Enumerating the bones, calculate the skin matrix (bindpose) as this:

         

  FbxMatrix matOffset = pNode->EvaluateGlobalTransform();
  FbxMatrix matSkinning = matOffset.Inverse();

      Save matSkinning in own bone array

7.  After this, still in the Enumeration loop, load the animations. First calculate a pose matrix:

 

FbxMatrix matTM = pNode->EvaluateGlobalTransform();

if (pNode->GetParent())
{
  FbxMatrix matParentTM = pNode->GetParent()->EvaluateGlobalTransform();

  matTM = matParentTM.Inverse() * matTM;
}

FbxMatrix matPose = matTM;

   Save matPose in own bone array. This pose matrix can be used for calculating min/max of the model, and also for posing the model in a world editor. It is not used when animating. Following this is the animation loop:

   

for (int i=0; i<numAnimFrames; i++)
{
  FbxTime t;
  t.SetFrame(i);
			
  FbxMatrix matTM = pNode->EvaluateGlobalTransform(t);
  if (pNode->GetParent())
  {
    FbxMatrix matParentTM = pNode->GetParent()->EvaluateGlobalTransform(t);

    matTM = matParentTM.Inverse() * matTM;
  }

  FbxMatrix matAnim = matTM;
}

     Save matAnim in own key frame array. These matAnim's replaces the pose matrix upon animating.

8.  Calculate numAnimFrames as this:

  

int GetNumberAnimationFrames(FbxScene* pScene, FbxTimeSpan& interval)
{
    FbxNode* pRootNode = pScene->GetRootNode();

	if (pRootNode->GetAnimationInterval(interval))
	{
		FbxTime start = interval.GetStart();
		FbxTime end = interval.GetStop();

		FbxLongLong longstart = start.GetFrameCount();
		FbxLongLong longend = end.GetFrameCount();

		return int(longend - longstart);
	}

	return 0;
}

9. Process own vertices, texvertices, and indices array to add new vertices having different texture coordinates

 

10. For the bones with geometry meshes, process the collected bone skin arrays inorder to produce final skin vertices with weights and indices. Create skinning arrays containg bone indices so that matSkin can be found upon rendering. The rendering loop setup the matrices required by the vertex shader.

 

11. Rotate the final model 180 degrees around z and 90 degrees around x

 

12. Use the following funtion when saving a FbxMatrix to a D3DXMatrix:

D3DXMATRIX ConvertMatrix(const FbxMatrix& fbxmat)
{
  D3DXMATRIX mat;

  mat._11 = float(fbxmat[0][0]); mat._12 = float(fbxmat[0][2]); mat._13 = float(fbxmat[0][1]); mat._14 = float(fbxmat[0][3]); 
  mat._21 = float(fbxmat[2][0]); mat._22 = float(fbxmat[2][2]); mat._23 = float(fbxmat[2][1]); mat._24 = float(fbxmat[2][3]); 
  mat._31 = float(fbxmat[1][0]); mat._32 = float(fbxmat[1][2]); mat._33 = float(fbxmat[1][1]); mat._34 = float(fbxmat[1][3]); 
  mat._41 = float(fbxmat[3][0]); mat._42 = float(fbxmat[3][2]); mat._43 = float(fbxmat[3][1]); mat._44 = float(fbxmat[3][3]); 

  return mat;
}

  

Comments:

 

I my plugin, I call "Quat q(mat3)" to create a quaternion from a matrix. In my FBX importer I tried to call "

fbxmat.GetElements(t, quat, sh, s, sign)", but this return a different quaternion.

 

Also, I tried to call:

FbxAxisSystem maxDX(FbxAxisSystem::eDirectX);
maxDX.ConvertScene(pScene);

but this does not seem to have any affect whatsoever. All matrices from

EvaluateGlobalTransform stays the same.

 

Conclusion:

 

With very few steps and matrices from Fbx, one can fairly simple create a muti mesh skinning Fbx importer, creating proprietary skin vertices having vertex weights and indices, and creating sufficient more vertices to ensure proper texturing. There is no need to get any matrices in the geometry loop over the clusters. Performance of Fbx? I ran some test using Intel VTune Amplifier XE 2013, and the top 50 list of the worst performers were all FBX routines. The number 1 worst performer: A routine called "FbxConnectionPoint::SubConnectFind".

 

   

    

 

 

 

Message 4 of 4
obt
Participant
in reply to: obt

The model I tested this with was s multi mesh model with 3 meshes, all having the skin modifier. The routine GetObjectTM in my max plugin all returned the same offset for these 3 meshes.

 

Now I am testing another model with 5 meshes, and these meshes returns for GetObjectTM in my max plugin different offsets. The result is, that these 5 meshes in my Fbx imported are not connected correctly. Individually they come in fine, though. 4 of these meshes have the skin modifier and one does not.

 

Since this model exports correctly, including pose and animation, using my max plugin, I should be able to figure this out.

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report