Exporting Bone Data *Solved*

Scripting in Blender with Python, and working on the API

Moderators: jesterKing, stiv

Post Reply
jebus
Posts: 0
Joined: Thu Feb 23, 2006 12:56 pm

Exporting Bone Data *Solved*

Post by jebus » Sun Feb 26, 2006 2:49 pm

Hi all,

I have recently been attempting at writing python script to export 3d models to my own file format, but i've run into problems with successfully exporting matrix data belonging to the armature/bones of my model.

First of all, i am using Direct3D and a left-hard coordinate system. Secondly there are two objects that i wish to export: a single mesh and an armature with underlying bones that control this mesh. For every key frame i would like to write the bone matrices to my file so that i could transform each vertex from within D3D in this manner:

V' = M1 * V * w1 + M2 * v * w2;

Where V' is the new vertex pos, V is the old vertex pos and where M1 + M2 and w1 + w2 are the matrices and vertex weights corrosponding to the two most influential bones for each vertex.

I know that the vertices are weighted properly because arms, legs and feet are visible when i try to render this in D3D, but they are all over the place with respect to each other.

So, a few questions:
Should i be converting the vertex coordinates of the mesh(to the D3D format) as i write them to the file, or should i incorporate this into all the bone matrices? (I havent had any luck with either so far...)

Do i need to change the blender matrices before writing them to the file? D3D seems to store their matrices differently to everything else...

What combination of bone.localMatrix / .poseMatrix etc etc do i have to use to get the final bone matrix that i could use in the above equation?

I have been trying to solve this for so long but i have got absolutely nowhere. Any help, however sarcastic towards my oversights, is greatly appreciated! :D

Thanks in advance,
Jebus
Last edited by jebus on Thu Apr 27, 2006 6:33 am, edited 1 time in total.

jebus
Posts: 0
Joined: Thu Feb 23, 2006 12:56 pm

Post by jebus » Sun Mar 19, 2006 10:03 am

Isnt anyone able to help?
Does anoyone have any info they would like to share regarding any bone/armature matrices?
Anything would help as i just dont "get" the way blender organises armatures that are attached to meshes.

Lost and confused,
Jebus

kakapo
Posts: 0
Joined: Sat Sep 04, 2004 2:32 pm

Post by kakapo » Sun Mar 19, 2006 12:47 pm

i managed to export bone animations to my model format but i am no expert on this either. i usually do a lot of trial and error coding. :)

what i would do:

don't care about the different coordinate systems. at the beginning it doesn't matter if your character is oriented correctly or not. the important first step is to get the animations working. after that you can try to correct the coordinate system.

i don't know your model format but in memory opengl (column major) and direct3d (row major) matrices are aligned exactly the same. it just is important that the translation part is the 13th, 14th, 15th, 16th value of the 16 value array. so probably you won't have to change anything but if it doesn't work try to transpose the matrix.

again, i don't know your model format or engine but the final bone matrix often gets computed like that:

final_matrix = inverse_armature_space_matrix * local_pose_matrix * armature_space_matrix

first the vertex has to be transformed to bone space, then the animation gets applied, then the result has to be transformed back to object space again.



i think posebone.localmatrix only is a 3x3 matrix so i calculate the 4x4 localmatrix myself. if i remember correctly like that:

local_pose_matrix = (posebone.posematrix * poseboneparent.posematrix.inverse) * (bone.matrix["armaturespace"] * boneparent.matrix["armaturespace"].inverse).inverse



i hope this helps?

der_ton
Posts: 0
Joined: Mon Oct 20, 2003 1:02 am

Post by der_ton » Tue Mar 21, 2006 10:21 am

I've been struggling with this a bit, too, maybe you've seen this thread:
http://www.blender.org/forum/viewtopic.php?t=8144

Looking at the code of existing exporters might give you some hints, atleast that's how I learned most of the details of Blender's matrices, and the documentation and, as kakapo said, trial and error.

jebus
Posts: 0
Joined: Thu Feb 23, 2006 12:56 pm

Post by jebus » Fri Apr 14, 2006 9:36 am

Thanks for the replies!

kakapo, i tried implementing what you have given me, but i am still running into familiar problems whenever i try to change the model's pose.

1) Whenever i try to rotate a bone, the final product in my program does not match up with the original in blender. The rest of the model is fine, but the transformed section is not rotated correctly. It looks as if the axes are switched.

2) The rotated area doesnt seem to end up in the same position as it was, ie: the bone's "root" doesnt return to where it should be.

Any ideas?

EDIT: Does anyone have an export script involving armatures that they would like to send me? :D

jebus
Posts: 0
Joined: Thu Feb 23, 2006 12:56 pm

Post by jebus » Thu Apr 27, 2006 6:31 am

Problem Solved. :wink:

Here is the code for anyone with the same problem:

Code: Select all

finalMatrix = Matrix(armObject.matrix).invert() * Matrix(armBone.matrix['ARMATURESPACE']).invert() * poseBone.poseMatrix * armObject.matrix * flipMatrix
Where:
-armObject is the armature linked with the mesh
-armBone = armature.bones[boneName]
-poseBone = pose.bones[boneName]
-flipMatrix = Matrix([1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1])
(to convert from Blender to DirectX coords)

Thanks for the help.

pbergeron
Posts: 0
Joined: Mon May 15, 2006 8:02 pm

Post by pbergeron » Wed May 17, 2006 6:33 am

jebus wrote:Problem Solved. :wink:

Here is the code for anyone with the same problem:

Code: Select all

finalMatrix = Matrix(armObject.matrix).invert() * Matrix(armBone.matrix['ARMATURESPACE']).invert() * poseBone.poseMatrix * armObject.matrix * flipMatrix
Where:
-armObject is the armature linked with the mesh
-armBone = armature.bones[boneName]
-poseBone = pose.bones[boneName]
-flipMatrix = Matrix([1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1])
(to convert from Blender to DirectX coords)

Thanks for the help.
Isn't the following:

armBone.matrix['ARMATURESPACE']).invert() * poseBone.poseMatrix

equivalent to:

poseBone.localMatrix
?

pbergeron
Posts: 0
Joined: Mon May 15, 2006 8:02 pm

Post by pbergeron » Wed May 17, 2006 8:17 pm

Ok guys,
I have take this about as far as I can go with it, but cannot get it to work. I am trying to export a skinned mesh (frame hierarchy) from Blender to DirectX. I understand there are already exporters, but the ones I found are bloated (storing 3 times the amount of data necessary).

Here are the directions (DirectX SDK) for translating from right handed to left-handed coordinate system:

Direct3D uses a left-handed coordinate system. If you are porting an application that is based on a right-handed coordinate system, you must make two changes to the data passed to Direct3D.

Step 1:
Flip the order of triangle vertices so that the system traverses them clockwise from the front. In other words, if the vertices are v0, v1, v2, pass them to Direct3D as v0, v2, v1.

Step 2:
Use the view matrix to scale world space by -1 in the z-direction. To do this, flip the sign of the _31, _32, _33, and _34 member of the D3DMATRIX structure that you use for your view matrix.

Step 3:
If you are porting a left-handed modeling application where the z-axis points up, you must do a rotation on all the vertex data in addition to the previous steps.


Here is an example of how I use the data from Blender in the .X file:
NOTE: these are not the actual values, but rather the Blender matrices being used to output the matrices

Code: Select all

Frame Scene_Root {
   FrameTransformMatrix {
      // performs steps 2 and 3
      RotationMatrix(-90, 4, 'x') * Matrix([1,0,0,0],[0,1,0,0],[0,0,-1,0],[0,0,0,1])
	}
   Frame Armature_Root {
      FrameTransformMatrix {
            // this would be the armature OBJECT's matrix and 
            objArm.matrix
      }
      Frame RootBone {
			FrameTransformMatrix {
				// this bone is not relative to any parent
				poseBone.poseMatrix
			}
			Frame ChildBone1 {
				FrameTransformMatrix {
					poseBone.poseMatrix * parent.bone.matrix['ARMATURESPACE'].invert()
				}
				Frame GrandChildBone1 {
					FrameTransformMatrix {
						poseBone.poseMatrix * parent.bone.matrix['ARMATURESPACE'].invert()
					}
				}
			}
			Frame SiblingBone1 {
				FrameTransformMatrix {
					poseBone.poseMatrix * parent.bone.matrix['ARMATURESPACE'].invert()
				}
			}
		} // end of Root Bone
	} // end of Armature_Root
   Frame MyMesh {
		FrameTransformMatrix {
				identity
		}
		Mesh {
			// standard mesh stuff, but with faces defined as v0, v2, v1

			// 1 of these for each bone
			SkinnedWeights {
				// standard stuff
				
				// last item is the offset matrix.  the bind pose matrix
				bone.matrix['ARMATURESPACE'].invert()
			}
		} // end of Mesh
	} // end Frame MyMesh
} // end of scene root
I have tried lots of variations on the matrices and even the vertices, but nothing has worked 100%. I think I may be off by a sign somewhere (due to a rotation that I am not taking into account) or something. Any help would be wonderful.

jebus
Posts: 0
Joined: Thu Feb 23, 2006 12:56 pm

Post by jebus » Fri May 19, 2006 2:01 pm

Hey pbergeron,

In answer to your question:
pbergeron wrote: Isn't the following:

armBone.matrix['ARMATURESPACE']).invert() * poseBone.poseMatrix

equivalent to:

poseBone.localMatrix
?
Yes, that seems to be the case.

As for your exporter, just take a look at the dx8 one that comes with blender. It seems to support skinning, and it also converts from blender to dx coordinates.

Jebus

Post Reply