[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [11881] trunk/blender/release/scripts/ export_fbx.py: Objects can now be animated (camera paths, lamps etc)

Campbell Barton cbarton at metavr.com
Wed Aug 29 11:50:09 CEST 2007


Revision: 11881
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=11881
Author:   campbellbarton
Date:     2007-08-29 11:50:08 +0200 (Wed, 29 Aug 2007)

Log Message:
-----------
Objects can now be animated (camera paths, lamps etc)
However meshes that use an armature cant use object animation.

faster exporting for non modifier applied, armature meshes (transform all verts using wrapped C func)

Modified Paths:
--------------
    trunk/blender/release/scripts/export_fbx.py

Modified: trunk/blender/release/scripts/export_fbx.py
===================================================================
--- trunk/blender/release/scripts/export_fbx.py	2007-08-29 05:42:39 UTC (rev 11880)
+++ trunk/blender/release/scripts/export_fbx.py	2007-08-29 09:50:08 UTC (rev 11881)
@@ -118,6 +118,8 @@
 	
 	print '\tCopied %d images' % copyCount
 
+mtx4_identity = Matrix()
+
 mtx_z90 = RotationMatrix(90, 3, 'z')
 mtx_x90 = RotationMatrix(90, 3, 'x')
 
@@ -439,6 +441,10 @@
 			else:
 				return (mtx4_z90 * ((self.getPoseMatrix(frame) * arm_mat)))  *  (mtx4_z90 * (self.parent.getPoseMatrix(frame) * arm_mat)).invert()
 		
+		# we need thes because cameras and lights modified rotations
+		def getAnimMatrixRot(self, frame):
+			return self.getAnimMatrix(frame)
+		
 		def flushAnimData(self):
 			self.__anim_poselist.clear()
 
@@ -449,15 +455,33 @@
 			self.fbxName = sane_obname(ob)
 			self.blenObject = ob
 			self.matrixWorld = ob.matrixWorld * GLOBAL_MATRIX
+			self.__anim_poselist = {}
+		
+		def setPoseFrame(self, f):
+			self.__anim_poselist[f] =  self.blenObject.matrixWorld.copy()
+		
+		def getAnimMatrix(self, frame):
+			return self.__anim_poselist[frame] * GLOBAL_MATRIX
+		
+		def getAnimMatrixRot(self, frame):
+			type = self.blenObject.type
+			matrix_rot = (self.__anim_poselist[frame] * GLOBAL_MATRIX).rotationPart()
+			
+			# Lamps need to be rotated
+			if type =='Lamp':
+				matrix_rot = mtx_x90 * matrix_rot
+			elif ob and type =='Camera':
+				y = Vector(0,1,0) * matrix_rot
+				matrix_rot = matrix_rot * RotationMatrix(90, 3, 'r', y)
+			
+			return matrix_rot
+			
 	# ----------------------------------------------
 	
 	
 	
 	
 	
-	
-	
-	
 	print '\nFBX export starting...', filename
 	start_time = Blender.sys.time()
 	file = open(filename, 'w')
@@ -531,7 +555,7 @@
 				matrix_rot = matrix.rotationPart()
 				# Lamps need to be rotated
 				if ob and ob.type =='Lamp':
-					matrix_rot = mtx_x90 * matrix.rotationPart()
+					matrix_rot = mtx_x90 * matrix_rot
 					rot = tuple(matrix_rot.toEuler())
 				elif ob and ob.type =='Camera':
 					y = Vector(0,1,0) * matrix_rot
@@ -1275,9 +1299,10 @@
 		file.write('\n\t\tTransformLink: %s' % matstr)
 		file.write('\n\t}')
 	
-	#def write_mesh(obname, ob, mtx, me, mats, arm, armname):
 	def write_mesh(my_mesh):
 		
+		me = my_mesh.blenData
+		
 		# if there are non NULL materials on this mesh
 		if [mat for mat in my_mesh.blenMaterials if mat]: 	do_materials = True
 		else:												do_materials = False
@@ -1289,33 +1314,57 @@
 		file.write('\n\tModel: "Model::%s", "Mesh" {' % my_mesh.fbxName)
 		file.write('\n\t\tVersion: 232') # newline is added in write_object_props
 		
-		# Apply the mesh matrix because bones arnt applied correctly if we use object transformation
-		# Other then that, object matricies work well on meshes.
-		# if this can be fixd, be sure to remove matrix multiplication on the verts.
-		#write_object_props(ob, None, mtx)
-		write_object_props(my_mesh.blenObject, None, Matrix()) 
+		if my_mesh.fbxArm:
+			if my_mesh.origData:
+				do_tx_write = True
+			else:
+				do_tx_write = False
+				me.transform(my_mesh.matrixWorld)
+			
+		else:
+			do_tx_write = False
 		
+		
+		# When we have an armature...
+		if my_mesh.fbxArm:
+			# Apply the mesh matrix because bones arnt applied correctly if we use object transformation
+			# Other then that, object matricies work well on meshes.
+			# if this can be fixd, be sure to remove matrix multiplication on the verts.
+			
+			write_object_props(my_mesh.blenObject, None, mtx4_identity)
+		else:
+			write_object_props(my_mesh.blenObject, None, my_mesh.matrixWorld)
+		
 		file.write('\n\t\t}')
 		file.write('\n\t\tMultiLayer: 0')
 		file.write('\n\t\tMultiTake: 1')
 		file.write('\n\t\tShading: Y')
 		file.write('\n\t\tCulling: "CullingOff"')
 		
-		me = my_mesh.blenData
 		
 		# Write the Real Mesh data here
 		file.write('\n\t\tVertices: ')
 		i=-1
-		for v in me.verts:
-			if i==-1:
-				file.write('%.6f,%.6f,%.6f' % tuple(v.co * my_mesh.matrixWorld))
-				i=0
-			else:
-				if i==7:
-					file.write('\n\t\t')
-					i=0
-				file.write(',%.6f,%.6f,%.6f'% tuple(v.co * my_mesh.matrixWorld))
-			i+=1
+		
+		if do_tx_write :# transform verts on write?
+			for v in me.verts:
+				if i==-1:
+					file.write('%.6f,%.6f,%.6f' % tuple(v.co * my_mesh.matrixWorld));	i=0
+				else:
+					if i==7:
+						file.write('\n\t\t');	i=0
+					file.write(',%.6f,%.6f,%.6f'% tuple(v.co * my_mesh.matrixWorld))
+				i+=1
+		else:	# same as above but has alredy been transformed
+			for v in me.verts:
+				if i==-1:
+					file.write('%.6f,%.6f,%.6f' % tuple(v.co));	i=0
+				else:
+					if i==7:
+						file.write('\n\t\t');	i=0
+					file.write(',%.6f,%.6f,%.6f'% tuple(v.co))
+				i+=1
+				
 		file.write('\n\t\tPolygonVertexIndex: ')
 		i=-1
 		for f in me.faces:
@@ -1367,19 +1416,33 @@
 		mtx_rot = my_mesh.matrixWorld.rotationPart()
 		
 		i=-1
-		for v in me.verts:
-			if i==-1:
-				file.write('%.15f,%.15f,%.15f' % tuple(v.no * mtx_rot))
-				i=0
-			else:
-				if i==2:
-					file.write('\n			 ')
-					i=0
-				file.write(',%.15f,%.15f,%.15f' % tuple(v.no * mtx_rot))
-			i+=1
-		file.write('\n\t\t}')
 		
 		
+		if do_tx_write: # transform normals on write?
+			for v in me.verts:
+				if i==-1:
+					file.write('%.15f,%.15f,%.15f' % tuple(v.no * mtx_rot));	i=0
+				else:
+					if i==2:
+						file.write('\n			 ');	i=0
+					file.write(',%.15f,%.15f,%.15f' % tuple(v.no * mtx_rot))
+				i+=1
+			file.write('\n\t\t}')
+			
+		
+		else:	# same as above but has alredy been transformed
+			for v in me.verts:
+				if i==-1:
+					file.write('%.15f,%.15f,%.15f' % tuple(v.no));	i=0
+				else:
+					if i==2:
+						file.write('\n			 ');	i=0
+					file.write(',%.15f,%.15f,%.15f' % tuple(v.no))
+				i+=1
+			file.write('\n\t\t}')
+		
+		
+		
 		# Write VertexColor Layers
 		collayers = []
 		if me.vertexColors:
@@ -1721,6 +1784,7 @@
 				if EXP_EMPTY:
 					ob_null.append(my_object_generic(ob))
 			elif EXP_MESH:
+				origData = True
 				if tmp_ob_type != 'Mesh':
 					me = bpy.data.meshes.new()
 					try:	me.getFromObject(ob)
@@ -1728,6 +1792,7 @@
 					if me:
 						meshes_to_clear.append( me )
 						mats = me.materials
+						origData = False
 				else:
 					# Mesh Type!
 					if EXP_MESH_APPLY_MOD:
@@ -1747,6 +1812,7 @@
 						
 						# print ob, me, me.getVertGroupNames()
 						meshes_to_clear.append( me )
+						origData = False
 						mats = me.materials
 					else:
 						me = ob.getData(mesh=1)
@@ -1806,10 +1872,9 @@
 					else:
 						blenParentBoneName = armob = None
 					
-					#ob_meshes.append( (obname, ob, mtx, me, mats, armob, armname) )
-					
 					my_mesh = my_object_generic(ob)
 					my_mesh.blenData =		me
+					my_mesh.origData = 		origData
 					my_mesh.blenMaterials =	mats
 					my_mesh.blenTextures =	texture_mapping_local.values()
 					
@@ -2068,7 +2133,7 @@
 		file.write('\n\t\tPoseNode:  {')
 		file.write('\n\t\t\tNode: "Model::%s"' % fbxName )
 		if matrix:		file.write('\n\t\t\tMatrix: %s' % mat4x4str(matrix))
-		else:			file.write('\n\t\t\tMatrix: %s' % mat4x4str(Matrix()))
+		else:			file.write('\n\t\t\tMatrix: %s' % mat4x4str(mtx4_identity))
 		file.write('\n\t\t}')
 	
 	file.write('\n\t}')
@@ -2367,88 +2432,103 @@
 			i = act_start
 			while i <= act_end:
 				Blender.Set('curframe', i)
-				#Blender.Window.RedrawAll()
-				for my_bone in ob_bones:
-					my_bone.setPoseFrame(i)
+				for ob_generic in (ob_bones, ob_meshes, ob_null, ob_cameras, ob_lights):
+					for my_ob in ob_generic:
+						#Blender.Window.RedrawAll()
+						if ob_generic == ob_meshes and my_ob.fbxArm:
+							# We cant animate armature meshes!
+							pass
+						else:
+							my_ob.setPoseFrame(i)
+						
 				i+=1
 			
 			
 			#for bonename, bone, obname, me, armob in ob_bones:
-			for my_bone in ob_bones:
-				
-				file.write('\n\t\tModel: "Model::%s" {' % my_bone.fbxName) # ??? - not sure why this is needed
-				file.write('\n\t\t\tVersion: 1.1')
-				file.write('\n\t\t\tChannel: "Transform" {')
-				
-				context_bone_anim_mats = [ my_bone.getAnimMatrix(frame) for frame in xrange(act_start, act_end+1) ]
-				
-				# ----------------
-				for TX_LAYER, TX_CHAN in enumerate('TRS'): # transform, rotate, scale
+			for ob_generic in (ob_bones, ob_meshes, ob_null, ob_cameras, ob_lights):
 					
-					if		TX_CHAN=='T':	context_bone_anim_vecs = [mtx.translationPart()	for mtx in context_bone_anim_mats]
-					elif 	TX_CHAN=='R':	context_bone_anim_vecs = [mtx.toEuler()			for mtx in context_bone_anim_mats]
-					else:					context_bone_anim_vecs = [mtx.scalePart()		for mtx in context_bone_anim_mats]
+				for my_ob in ob_generic:
 					
-					file.write('\n\t\t\t\tChannel: "%s" {' % TX_CHAN) # translation
 					
-					for i in xrange(3):
-						# Loop on each axis of the bone
-						file.write('\n\t\t\t\t\tChannel: "%s" {'% ('XYZ'[i])) # translation
-						file.write('\n\t\t\t\t\t\tDefault: %.15f' % context_bone_anim_vecs[0][i] )
-						file.write('\n\t\t\t\t\t\tKeyVer: 4005')
+					if ob_generic == ob_meshes and my_ob.fbxArm:
+						# do nothing,
+						pass
+					else:
+							
+						file.write('\n\t\tModel: "Model::%s" {' % my_ob.fbxName) # ??? - not sure why this is needed
+						file.write('\n\t\t\tVersion: 1.1')
+						file.write('\n\t\t\tChannel: "Transform" {')
 						
-						if not ANIM_OPTIMIZE:
-							# Just write all frames, simple but in-eficient
-							file.write('\n\t\t\t\t\t\tKeyCount: %i' % (1 + act_end - act_start))
-							file.write('\n\t\t\t\t\t\tKey: ')
-							frame = act_start
-							while frame <= act_end:
-								if frame!=act_start:
-									file.write(',')
-								
-								# Curve types are 
-								# C,n is for bezier? - linear is best for now so we can do simple keyframe removal
-								file.write('\n\t\t\t\t\t\t\t%i,%.15f,C,n'  % (fbx_time(frame-1), context_bone_anim_vecs[frame-act_start][i] ))
-								#file.write('\n\t\t\t\t\t\t\t%i,%.15f,L'  % (fbx_time(frame-1), context_bone_anim_vecs[frame-act_start][i] ))
-								frame+=1
-						else:
-							# remove unneeded keys, j is the frame, needed when some frames are removed.
-							context_bone_anim_keys = [ (vec[i], j) for j, vec in enumerate(context_bone_anim_vecs) ]
+						context_bone_anim_mats = [ (my_ob.getAnimMatrix(frame), my_ob.getAnimMatrixRot(frame)) for frame in xrange(act_start, act_end+1) ]
+						
+						# ----------------
+						# ----------------
+						for TX_LAYER, TX_CHAN in enumerate('TRS'): # transform, rotate, scale
 							

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list