Explorar o código

Revising blender exporters

Panagiotis Christopoulos Charitos %!s(int64=15) %!d(string=hai) anos
pai
achega
c2bd65bdba

+ 16 - 14
blenderscripts/main.py

@@ -3,9 +3,6 @@ print( "\n\n\n\n\n\n\n---- STARTING EXPORTER ----" )
 import sys
 import sys
 import Blender
 import Blender
 
 
-"""from common import *
-reload( sys.modules["common"] )"""
-
 import mesh
 import mesh
 reload(sys.modules["mesh"])
 reload(sys.modules["mesh"])
 
 
@@ -15,9 +12,8 @@ reload(sys.modules["skeleton"])
 from material import *
 from material import *
 reload(sys.modules["material"])
 reload(sys.modules["material"])
 
 
-
-def foo(m):
-	print(m.blMesh)
+import skelanim
+reload(sys.modules["skelanim"])
 
 
 
 
 objs = Blender.Object.GetSelected()
 objs = Blender.Object.GetSelected()
@@ -27,19 +23,25 @@ if len(objs) < 1:
 
 
 for obj in objs:
 for obj in objs:
 	mi = mesh.Initializer()
 	mi = mesh.Initializer()
-	
 	mi.blMesh = mesh.getBlMeshFromBlObj(obj)
 	mi.blMesh = mesh.getBlMeshFromBlObj(obj)
-	#mi.blSkeleton = skeleton.GetSkeleton(obj)
-	mi.saveDir = "/home/godlike/src/anki/maps/sponza/"
+	mi.blSkeleton = skeleton.getBlSkeletonFromBlObj(obj)
+	mi.saveDir = "/home/godlike/src/anki/models/imp/"
 	#mtl = GetMaterial( mi.mesh )
 	#mtl = GetMaterial( mi.mesh )
-	mi.mtlName = "maps/sponza/sponza.mtl"
+	mi.mtlName = "models/imp/imp.mtl"
 	mi.flipYZ = 1
 	mi.flipYZ = 1
+	mesh.export(mi)
 	
 	
+	si = skeleton.Initializer()
+	si.skeleton = skeleton.getBlSkeletonFromBlObj(obj)
+	si.saveDir = "/home/godlike/src/anki/models/imp/"
+	si.flipYZ = 1
+	skeleton.export(si)
 	
 	
-	mesh.export(mi)
-	#ExportSkeleton( path, skel, cmnts )
-	#ExportVWeights( path, mesh, skel, cmnts )
-	#ExportMaterial( path, epath, mtl, cmnts )
+	"""ai = skelanim.Initializer()
+	ai.obj = obj
+	ai.saveDir = "/home/godlike/src/anki/models/imp/"
+	ai.flipYZ = 1
+	skelanim.export(ai)"""
 
 
 
 
 print("---- ENDING EXPORTER ----")
 print("---- ENDING EXPORTER ----")

+ 4 - 14
blenderscripts/mesh.py

@@ -6,7 +6,7 @@ from Blender.Mathutils import *
 
 
 
 
 #=======================================================================================================================
 #=======================================================================================================================
-# Initializer                                                                                                      =
+# Initializer                                                                                                          =
 #=======================================================================================================================
 #=======================================================================================================================
 class Initializer:
 class Initializer:
 	def __init__(self):
 	def __init__(self):
@@ -14,7 +14,7 @@ class Initializer:
 		self.blSkeleton = None # Blender Armature
 		self.blSkeleton = None # Blender Armature
 		self.mtlName = "" # Material name
 		self.mtlName = "" # Material name
 		self.saveDir = "" # the name of the saved file
 		self.saveDir = "" # the name of the saved file
-		self.flipYZ = 0
+		self.flipYZ = 0 #convert from bl to right handed coord system
 	
 	
 
 
 #=======================================================================================================================
 #=======================================================================================================================
@@ -32,17 +32,6 @@ class Vert:
 		self.weights = [-1.0, -1.0, -1.0, -1.0]
 		self.weights = [-1.0, -1.0, -1.0, -1.0]
 		self.nextId = -1 # shows the next vertId. Is != -1 if the vert is problematic
 		self.nextId = -1 # shows the next vertId. Is != -1 if the vert is problematic
 
 
-	"""def __init__(self, v):
-		self.x = v.x
-		self.y = v.y
-		self.z = v.z
-		self.s = v.s
-		self.t = v.t
-		self.bonesNum = v.bonesNum
-		self.boneIds = [v.boneIds[0], v.boneIds[1], v.boneIds[2], v.boneIds[3]]
-		self.weights = [v.weights[0], v.weights[1], v.weights[2], v.weights[3]]
-		self.nextId = v.nextId # shows the next vertId. Is != -1 if the vert is problematic"""
-
 
 
 #=======================================================================================================================
 #=======================================================================================================================
 # Tri                                                                                                                  =
 # Tri                                                                                                                  =
@@ -305,4 +294,5 @@ def export(meshInit):
 	filename = os.path.abspath(meshInit.saveDir + mesh.name + ".mesh")
 	filename = os.path.abspath(meshInit.saveDir + mesh.name + ".mesh")
 	file = open(filename, "w")
 	file = open(filename, "w")
 	file.write(getAnkiMeshScript(mesh, skeleton, meshInit.mtlName, meshInit.flipYZ))
 	file.write(getAnkiMeshScript(mesh, skeleton, meshInit.mtlName, meshInit.flipYZ))
-	print("Mesh exported!! \"" + filename + "\"")	
+	print("Mesh exported!! \"" + filename + "\"")	
+	

+ 217 - 0
blenderscripts/skelanim.py

@@ -0,0 +1,217 @@
+import sys
+import os
+from copy import deepcopy
+from Blender import Mathutils
+from Blender.Mathutils import *
+import Blender
+
+
+#=======================================================================================================================
+# Initializer                                                                                                          =
+#=======================================================================================================================
+class Initializer:
+	def __init__(self):
+		self.obj = None
+		self.saveDir = "" # the name of the saved file
+		self.flipYZ = 0 #convert from bl to right handed coord system
+
+
+# MulMatrix
+def MulMatrix(m, b):
+	c = Matrix()
+	c[0][0] = m[0][0]*b[0][0] + m[0][1]*b[1][0] + m[0][2]*b[2][0] + m[0][3]*b[3][0]
+	c[0][1] = m[0][0]*b[0][1] + m[0][1]*b[1][1] + m[0][2]*b[2][1] + m[0][3]*b[3][1]
+	c[0][2] = m[0][0]*b[0][2] + m[0][1]*b[1][2] + m[0][2]*b[2][2] + m[0][3]*b[3][2]
+	c[0][3] = m[0][0]*b[0][3] + m[0][1]*b[1][3] + m[0][2]*b[2][3] + m[0][3]*b[3][3]
+	c[1][0] = m[1][0]*b[0][0] + m[1][1]*b[1][0] + m[1][2]*b[2][0] + m[1][3]*b[3][0]
+	c[1][1] = m[1][0]*b[0][1] + m[1][1]*b[1][1] + m[1][2]*b[2][1] + m[1][3]*b[3][1]
+	c[1][2] = m[1][0]*b[0][2] + m[1][1]*b[1][2] + m[1][2]*b[2][2] + m[1][3]*b[3][2]
+	c[1][3] = m[1][0]*b[0][3] + m[1][1]*b[1][3] + m[1][2]*b[2][3] + m[1][3]*b[3][3]
+	c[2][0] = m[2][0]*b[0][0] + m[2][1]*b[1][0] + m[2][2]*b[2][0] + m[2][3]*b[3][0]
+	c[2][1] = m[2][0]*b[0][1] + m[2][1]*b[1][1] + m[2][2]*b[2][1] + m[2][3]*b[3][1]
+	c[2][2] = m[2][0]*b[0][2] + m[2][1]*b[1][2] + m[2][2]*b[2][2] + m[2][3]*b[3][2]
+	c[2][3] = m[2][0]*b[0][3] + m[2][1]*b[1][3] + m[2][2]*b[2][3] + m[2][3]*b[3][3]
+	c[3][0] = m[3][0]*b[0][0] + m[3][1]*b[1][0] + m[3][2]*b[2][0] + m[3][3]*b[3][0]
+	c[3][1] = m[3][0]*b[0][1] + m[3][1]*b[1][1] + m[3][2]*b[2][1] + m[3][3]*b[3][1]
+	c[3][2] = m[3][0]*b[0][2] + m[3][1]*b[1][2] + m[3][2]*b[2][2] + m[3][3]*b[3][2]
+	c[3][3] = m[3][0]*b[0][3] + m[3][1]*b[1][3] + m[3][2]*b[2][3] + m[3][3]*b[3][3]
+	return c
+
+
+
+class BonePose:
+	def __init__(self):
+		self.rotation = Quaternion(1.0, 0.0, 0.0, 0.0)
+		self.translation = Vector(0.0, 0.0, 0.0)
+
+
+class BoneAnim:
+	def __init__(self):
+		self.keyframes = [] # before the "write to file" phase this array is ether empty
+		                    # if the bone doesnt have animation or an array of poses
+	
+	
+class SkelAnim:
+	def __init__(self):
+		self.bones = []
+		self.keyframes = []
+
+
+#=======================================================================================================================
+# getAnkiScript                                                                                                        =
+#=======================================================================================================================
+def getAnkiScript(obj, flipYZ, action):
+	skeleton = obj.getData(0, 0) 	
+	
+	b_cmnts = 1
+	
+	# init and populate the instances
+	skelAnim = SkelAnim()
+	skelAnim.keyframes = action.getFrameNumbers()
+	
+	boneNames = deepcopy(skeleton.bones.keys())
+	boneNames.sort()
+	
+	#skelAnim.bones = [BoneAnim() for anim in range(len(boneNames))]
+	
+	for i in range(0, len(boneNames)):
+		skelAnim.bones.append(BoneAnim())
+		for j in range(0, len(skelAnim.keyframes)):
+			skelAnim.bones[i].keyframes.append(BonePose())
+	
+	
+	# now populate with the correct data
+	# for all the kframes
+	for i in range(0, len(skelAnim.keyframes)):
+		kframe = skelAnim.keyframes[i]
+		Blender.Set("curframe", kframe)
+		Blender.Redraw()
+		pose = obj.getPose()
+		
+		# for all bones
+		for j in range(0, len(boneNames)):
+			boneName = boneNames[j]
+			poseBone = pose.bones[boneName]
+			bone = skeleton.bones[boneName]
+			
+			# rotation
+			rot = poseBone.quat.toMatrix()
+			rot.resize4x4()
+			# translation
+			tra = Matrix()
+			tra.identity()
+			for m in range(0, 3):
+				tra[m][3] = poseBone.loc[m]
+			# bone matris at armature space aka MA
+			MA = Matrix(bone.matrix["ARMATURESPACE"])
+			MAi = Matrix(MA)
+			MAi.invert()
+			
+			# calc the m4 = MA * tra * rot * MAi
+			rot.transpose()
+			tra.transpose()
+			MA.transpose()
+			MAi.transpose()
+			
+			m4 = MulMatrix(rot, MAi)
+			m4 = MulMatrix(tra, m4)
+			m4 = MulMatrix(MA, m4)
+			
+			m4.transpose()
+			
+			# get the final quat and loc
+			quat = m4.rotationPart()
+			quat = quat.toQuat()
+			loc  = m4.translationPart()
+			
+			quat = poseBone.quat
+			loc = poseBone.loc
+			
+			for k in range(0, 4):
+				skelAnim.bones[j].keyframes[i].rotation[k] = quat[k]
+			
+			for k in range(0, 3):
+				skelAnim.bones[j].keyframes[i].translation[k] = loc[k]
+	
+	Blender.Set("curframe", 1)
+	Blender.Redraw()	
+	
+	
+	# now do the apropriate for the bones without translation or rotation
+	zeroVec = Vector(0.0, 0.0, 0.0)
+	identQuat = Quaternion(1.0, 0.0, 0.0, 0.0)
+	# for all the bones
+	for i in range(0, len(boneNames)):
+		noAnimNum = 0   # how many times we found that the bone has no anim
+		bone = skelAnim.bones[i]
+		# for all the keyframes
+		for j in range(0, len(skelAnim.keyframes)):
+			
+			if bone.keyframes[j].rotation == identQuat and bone.keyframes[j].translation == zeroVec:
+				noAnimNum = noAnimNum + 1
+			
+		if noAnimNum == len(skelAnim.keyframes):
+			print("Bone \"%s\" has no animation" % boneNames[i])
+			bone.keyframes = []
+	
+		
+	# write to ftxt
+	ftxt = ""
+	
+	# the keyframes
+	ftxt += str(len(skelAnim.keyframes)) + "\n"
+	
+	for kf in skelAnim.keyframes:
+		ftxt += str(kf - 1) + " "
+	ftxt += "\n"
+	
+	# the bones num
+	ftxt += str(len(boneNames)) + "\n"
+	
+	# for all bones
+	for i in range(0, len(boneNames)):
+		bone = skelAnim.bones[i]
+		
+		if len(bone.keyframes):
+			ftxt += "1\n"
+
+			# for all keyframes			
+			for j in range(0, len(skelAnim.keyframes)):				
+				# write rotation			
+				for k in range(0, 4):
+					ftxt += str(bone.keyframes[j].rotation[k]) + " "
+				ftxt += "\n"
+				
+				# write translation
+				for k in range(0, 3):
+					ftxt += str(bone.keyframes[j].translation[k]) + " "
+				ftxt += "\n"
+			
+		else:
+			ftxt += "0\n"
+	
+	return ftxt
+
+
+
+#=======================================================================================================================
+# export                                                                                                               =
+#=======================================================================================================================
+def export(init):
+	obj = init.obj
+	
+	if obj.getType() != "Armature":
+		raise RuntimeError("Select a skeleton and not a(n) " + obj.getType())
+
+	print("Trying to export skeleton animation")
+	
+	action = obj.getAction()
+	if action == 0:
+		raise RuntimeError("Empty action for obj " + obj.getName())
+	
+	filename = init.saveDir + action.name + "." + obj.getName() + ".anim"	
+	file = open(filename, "w")
+	file.write(getAnkiScript(obj, init.flipYZ, action))
+	
+	print("Skeleton animation exported!! \"" + filename + "\"")	
+	

+ 109 - 61
blenderscripts/skeleton.py

@@ -1,119 +1,167 @@
-from common import *
 import sys
 import sys
-reload( sys.modules["common"] )
+import os
+from copy import deepcopy
+from Blender import Mathutils
+from Blender.Mathutils import *
+import Blender
 
 
 
 
+#=======================================================================================================================
+# multMatrix                                                                                                           =
+#=======================================================================================================================
+def multMatrix(m, b):
+	c = Matrix()
+	c[0][0] = m[0][0]*b[0][0] + m[0][1]*b[1][0] + m[0][2]*b[2][0] + m[0][3]*b[3][0]
+	c[0][1] = m[0][0]*b[0][1] + m[0][1]*b[1][1] + m[0][2]*b[2][1] + m[0][3]*b[3][1]
+	c[0][2] = m[0][0]*b[0][2] + m[0][1]*b[1][2] + m[0][2]*b[2][2] + m[0][3]*b[3][2]
+	c[0][3] = m[0][0]*b[0][3] + m[0][1]*b[1][3] + m[0][2]*b[2][3] + m[0][3]*b[3][3]
+	c[1][0] = m[1][0]*b[0][0] + m[1][1]*b[1][0] + m[1][2]*b[2][0] + m[1][3]*b[3][0]
+	c[1][1] = m[1][0]*b[0][1] + m[1][1]*b[1][1] + m[1][2]*b[2][1] + m[1][3]*b[3][1]
+	c[1][2] = m[1][0]*b[0][2] + m[1][1]*b[1][2] + m[1][2]*b[2][2] + m[1][3]*b[3][2]
+	c[1][3] = m[1][0]*b[0][3] + m[1][1]*b[1][3] + m[1][2]*b[2][3] + m[1][3]*b[3][3]
+	c[2][0] = m[2][0]*b[0][0] + m[2][1]*b[1][0] + m[2][2]*b[2][0] + m[2][3]*b[3][0]
+	c[2][1] = m[2][0]*b[0][1] + m[2][1]*b[1][1] + m[2][2]*b[2][1] + m[2][3]*b[3][1]
+	c[2][2] = m[2][0]*b[0][2] + m[2][1]*b[1][2] + m[2][2]*b[2][2] + m[2][3]*b[3][2]
+	c[2][3] = m[2][0]*b[0][3] + m[2][1]*b[1][3] + m[2][2]*b[2][3] + m[2][3]*b[3][3]
+	c[3][0] = m[3][0]*b[0][0] + m[3][1]*b[1][0] + m[3][2]*b[2][0] + m[3][3]*b[3][0]
+	c[3][1] = m[3][0]*b[0][1] + m[3][1]*b[1][1] + m[3][2]*b[2][1] + m[3][3]*b[3][1]
+	c[3][2] = m[3][0]*b[0][2] + m[3][1]*b[1][2] + m[3][2]*b[2][2] + m[3][3]*b[3][2]
+	c[3][3] = m[3][0]*b[0][3] + m[3][1]*b[1][3] + m[3][2]*b[2][3] + m[3][3]*b[3][3]
+	return c
 
 
 
 
-#===================================================================================================
-# GetSkeleton                                                                                      =
-#===================================================================================================
-def GetSkeleton( obj ):	
+#=======================================================================================================================
+# rotateMatrix                                                                                                         =
+#=======================================================================================================================
+rotMat = Matrix()
+rotMat[0][0] = 1.0
+rotMat[0][1] = 0.0
+rotMat[0][2] = 0.0
+rotMat[0][3] = 0.0
+rotMat[1][0] = 0.0
+rotMat[1][1] = 0.0
+rotMat[1][2] = 1.0
+rotMat[1][3] = 0.0
+rotMat[2][0] = 0.0
+rotMat[2][1] = -1.0
+rotMat[2][2] = 0.0
+rotMat[2][3] = 0.0
+rotMat[3][0] = 0.0
+rotMat[3][1] = 0.0
+rotMat[3][2] = 0.0
+rotMat[3][3] = 1.0
+
+
+#=======================================================================================================================
+# Initializer                                                                                                          =
+#=======================================================================================================================
+class Initializer:
+	def __init__(self):
+		self.blSkeleton = None # Blender Armature
+		self.saveDir = "" # the name of the saved file
+		self.flipYZ = 0 #convert from bl to right handed coord system
+	
+
+
+#======================================================================================================================
+# getBlSkeletonFromBlObj                                                                                               =
+#=======================================================================================================================
+def getBlSkeletonFromBlObj(obj):	
 	# check if obj is correct class
 	# check if obj is correct class
-	if( obj.__class__.__name__ != "Blender Object" ):
-		ERROR( "The given func param is not a \"Blender Object\" class but a \"" + obj.__class__.__name__ + "\"" )
-		return 0
+	if(obj.__class__.__name__ != "Blender Object"):
+		raise RuntimeError("The given func param is not a \"Blender Object\" class but a \"" + obj.__class__.__name__ + "\"")
 	
 	
 	# check modifiers
 	# check modifiers
 	if len(obj.modifiers) < 1:
 	if len(obj.modifiers) < 1:
-		ERROR( "Obj \"" + obj.getName() + "\" doesnt have modifiers so no armature found" )
-		return 0
+		raise RuntimeError("Obj \"" + obj.getName() + "\" doesnt have modifiers so no armature found")
 	
 	
 	# search for modifier of skeleton type
 	# search for modifier of skeleton type
 	for mod in obj.modifiers:
 	for mod in obj.modifiers:
 		if mod.type == Blender.Modifier.Types.ARMATURE:
 		if mod.type == Blender.Modifier.Types.ARMATURE:
 			aobj = mod[Blender.Modifier.Settings.OBJECT]
 			aobj = mod[Blender.Modifier.Settings.OBJECT]
-			skeleton = Blender.Object.Get( aobj.name ).getData( 0, 1 ) # set skeleton
+			skeleton = Blender.Object.Get(aobj.name).getData(0, 1) # set skeleton
 			return skeleton
 			return skeleton
 	
 	
-	ERROR( "Obj \"" + obj.getName() + "\" has no modifier of type armature" )
-	return 0
+	raise RuntimeError("Obj \"" + obj.getName() + "\" has no modifier of type armature")
 		
 		
 
 
 
 
-#===================================================================================================
-# ScriptSkeleton                                                                                   =
-#===================================================================================================
-def ScriptSkeleton( skeleton, b_cmnts ):
-	# check if skeleton is correct class
-	if( skeleton.__class__.__name__ != "Armature" ):
-		ERROR( "The given func param is not a \"Armature\" class but a \"" + skeleton.__class__.__name__ + "\"" )
-		return "error"
-	
+#=======================================================================================================================
+# getAnkiSkeletonScript                                                                                                =
+#=======================================================================================================================
+def getAnkiSkeletonScript(skeleton, flipYZ):	
 	ftxt = "" # file text
 	ftxt = "" # file text
 	
 	
 	# write the file
 	# write the file
-	bone_names = skeleton.bones.keys()
-	bone_names.sort() # the bones are written in alpabetical order
+	boneNames = skeleton.bones.keys()
+	boneNames.sort() # the bones are written in alpabetical order
 
 
-	if( b_cmnts ): ftxt += "/*BONES*/ "
-	ftxt += str( len(bone_names) ) + "\n"
+	ftxt += str(len(boneNames)) + "\n"
 
 
-	for bone_nam in bone_names:	
-		bone = skeleton.bones[ bone_nam ]
-		if( b_cmnts ): ftxt += "\t/*\"" + bone.name + "\" BONE_ID " + str(bone_names.index(bone_nam)) + "*/\n"
+	for boneName in boneNames:	
+		bone = skeleton.bones[boneName]
 		
 		
 		# name
 		# name
-		if( b_cmnts ): ftxt += "\t\t/*BONE_NAME*/ "	
 		ftxt += "\"" + bone.name + "\"\n"
 		ftxt += "\"" + bone.name + "\"\n"
 		
 		
 		# head
 		# head
 		co = bone.head["ARMATURESPACE"]
 		co = bone.head["ARMATURESPACE"]
-		if( b_cmnts ): ftxt +=  "\t\t/*HEAD_ARMATURE_SPACE*/ "
-		ftxt += str(co.x) + " " + str(co.y) + " " + str(co.z) + "\n"
+		if flipYZ:
+			ftxt += str(co.x) + " " + str(co.z) + " " + str(-co.y) + "\n"
+		else:
+			ftxt += str(co.x) + " " + str(co.y) + " " + str(co.z) + "\n"
 		
 		
 		# tail
 		# tail
-		co = bone.tail["ARMATURESPACE"]				
-		if( b_cmnts ): ftxt +=  "\t\t/*TAIL_ARMATURE_SPACE*/ "
+		co = bone.tail["ARMATURESPACE"]
+		if flipYZ:
+			ftxt += str(co.x) + " " + str(co.z) + " " + str(-co.y) + "\n"
+		else:
+			ftxt += str(co.x) + " " + str(co.y) + " " + str(co.z) + "\n"
 		
 		
-		ftxt += str(co.x) + " " + str(co.y) + " " + str(co.z) + "\n"
+		# matrix
+		m4 = bone.matrix["ARMATURESPACE"].copy()
+		
+		if flipYZ:
+			m4 = multMatrix(rotMat, m4)
 		
 		
-		# matrix		
-		if( b_cmnts ): ftxt += "\t\t/*MATRIX_ARMATURE_SPACE*/ "
-				
 		for i_ in range(0, 4):
 		for i_ in range(0, 4):
 			for j_ in range(0, 4):
 			for j_ in range(0, 4):
-				ftxt += str( bone.matrix["ARMATURESPACE"][j_][i_] ) + " "
+				ftxt += str(m4[j_][i_]) + " "
 		ftxt += "\n"
 		ftxt += "\n"
 		
 		
 		# write the parent
 		# write the parent
-		if( b_cmnts ): ftxt += "\t\t/*PARENT_ID*/ "
 				
 				
 		if not bone.parent:
 		if not bone.parent:
 			ftxt += "NULL\n"
 			ftxt += "NULL\n"
 		else:
 		else:
-			ftxt += str( bone_names.index( bone.parent.name ) )
-			if( b_cmnts ): ftxt += " // " + bone.parent.name
-			ftxt += "\n"
-					
+			ftxt += str(boneNames.index(bone.parent.name)) + "\n"					
 
 
 			
 			
 		# write the childs
 		# write the childs
-		if( b_cmnts ): ftxt += "\t\t/*CHILD_IDS_NUM*/ "
-		ftxt += str( len(bone.children) ) + " "
-		if( b_cmnts ): ftxt += "/*CHILD_IDS*/ "
+		ftxt += str(len(bone.children)) + "\n"
 		
 		
 		for child in bone.children:
 		for child in bone.children:
-			ftxt += str( bone_names.index( child.name ) ) + " "
-			if( b_cmnts ): ftxt += "/*" + child.name + "*/ "
+			ftxt += str(boneNames.index(child.name)) + " "
 		
 		
 		ftxt += "\n"	
 		ftxt += "\n"	
 		
 		
 	return ftxt
 	return ftxt
 	
 	
 	
 	
-#===================================================================================================
-# ExportSkeleton                                                                                   =
-#===================================================================================================
-def ExportSkeleton( path, skeleton, b_cmnts ):
+#=======================================================================================================================
+# export                                                                                                               =
+#=======================================================================================================================
+def export(skeletonInit):
+	skeleton = skeletonInit.skeleton
 	#check if mesh is the correct class
 	#check if mesh is the correct class
-	if( skeleton.__class__.__name__ != "Armature" ):
-		ERROR( "The given func param is not a \"Armature\" class but a \"" + skeleton.__class__.__name__ + "\"" )
-		return false
+	if(skeleton.__class__.__name__ != "Armature"):
+		raise RuntimeError("The given func param is not a \"Armature\" class but a \"" + skeleton.__class__.__name__ + "\"")
 	
 	
-	INFO( "Trying to export skeleton \"" + skeleton.name + "\"" )
+	print("Trying to export skeleton \"" + skeleton.name + "\"")
 	
 	
-	filename = path + skeleton.name + ".skel"
-	WriteFile( filename, ScriptSkeleton( skeleton, b_cmnts ) )
+	filename = skeletonInit.saveDir + skeleton.name + ".skel"
+	file = open(filename, "w")
+	file.write(getAnkiSkeletonScript(skeleton, skeletonInit.flipYZ))
 	
 	
-	INFO( "Skeleton exported!! \"" + filename + "\"" )	
+	print("Skeleton exported!! \"" + filename + "\"")	
+	

+ 0 - 224
blenderscripts/skeleton_anim.py

@@ -1,224 +0,0 @@
-import sys
-from common import *
-reload( sys.modules["common"] )
-from Blender.Mathutils import *
-
-
-# MulMatrix
-def MulMatrix( m, b ):
-	c = Matrix()
-	c[0][0] = m[0][0]*b[0][0] + m[0][1]*b[1][0] + m[0][2]*b[2][0] + m[0][3]*b[3][0]
-	c[0][1] = m[0][0]*b[0][1] + m[0][1]*b[1][1] + m[0][2]*b[2][1] + m[0][3]*b[3][1]
-	c[0][2] = m[0][0]*b[0][2] + m[0][1]*b[1][2] + m[0][2]*b[2][2] + m[0][3]*b[3][2]
-	c[0][3] = m[0][0]*b[0][3] + m[0][1]*b[1][3] + m[0][2]*b[2][3] + m[0][3]*b[3][3]
-	c[1][0] = m[1][0]*b[0][0] + m[1][1]*b[1][0] + m[1][2]*b[2][0] + m[1][3]*b[3][0]
-	c[1][1] = m[1][0]*b[0][1] + m[1][1]*b[1][1] + m[1][2]*b[2][1] + m[1][3]*b[3][1]
-	c[1][2] = m[1][0]*b[0][2] + m[1][1]*b[1][2] + m[1][2]*b[2][2] + m[1][3]*b[3][2]
-	c[1][3] = m[1][0]*b[0][3] + m[1][1]*b[1][3] + m[1][2]*b[2][3] + m[1][3]*b[3][3]
-	c[2][0] = m[2][0]*b[0][0] + m[2][1]*b[1][0] + m[2][2]*b[2][0] + m[2][3]*b[3][0]
-	c[2][1] = m[2][0]*b[0][1] + m[2][1]*b[1][1] + m[2][2]*b[2][1] + m[2][3]*b[3][1]
-	c[2][2] = m[2][0]*b[0][2] + m[2][1]*b[1][2] + m[2][2]*b[2][2] + m[2][3]*b[3][2]
-	c[2][3] = m[2][0]*b[0][3] + m[2][1]*b[1][3] + m[2][2]*b[2][3] + m[2][3]*b[3][3]
-	c[3][0] = m[3][0]*b[0][0] + m[3][1]*b[1][0] + m[3][2]*b[2][0] + m[3][3]*b[3][0]
-	c[3][1] = m[3][0]*b[0][1] + m[3][1]*b[1][1] + m[3][2]*b[2][1] + m[3][3]*b[3][1]
-	c[3][2] = m[3][0]*b[0][2] + m[3][1]*b[1][2] + m[3][2]*b[2][2] + m[3][3]*b[3][2]
-	c[3][3] = m[3][0]*b[0][3] + m[3][1]*b[1][3] + m[3][2]*b[2][3] + m[3][3]*b[3][3]
-	return c
-
-
-
-class bone_pose_t:
-	def __init__(self):
-		self.rotation = Quaternion( 1.0, 0.0, 0.0, 0.0 )
-		self.translation = Vector( 0.0, 0.0, 0.0 )
-
-
-class bone_anim_t:
-	def __init__(self):
-		self.keyframes = [] # before the "write to file" phase this array is ether empty
-		                    # if the bone doesnt have animation or an array of poses
-	
-	
-class skeleton_anim_t:
-	def __init__(self):
-		self.bones = []
-		self.keyframes = []
-
-
-#===================================================================================================
-# ScriptAnim                                                                                       =
-#===================================================================================================
-def ScriptAnim( obj, b_cmnts ):
-	
-	if obj.getType() != "Armature":
-		ERROR( "Select a skeleton and not a(n) " + obj.getType() )
-		return 0
-	
-	skeleton = obj.getData( 0, 0 ) 
-	
-	
-	# init and populate the instances
-	skeleton_anim = skeleton_anim_t()
-	skeleton_anim.keyframes = action.getFrameNumbers()
-	
-	bone_names = skeleton.bones.keys()
-	bone_names.sort()
-	
-	for i in range( 0, len(bone_names) ):
-		skeleton_anim.bones.append( bone_anim_t() )
-		for j in range( 0, len(skeleton_anim.keyframes) ):
-			skeleton_anim.bones[i].keyframes.append( bone_pose_t() )
-	
-	
-	# now populate with the correct data
-	# for all the kframes
-	for i in range( 0, len(skeleton_anim.keyframes) ):
-		kframe = skeleton_anim.keyframes[i]
-		Blender.Set( "curframe", kframe )
-		Blender.Redraw()
-		pose = obj.getPose()
-		
-		# for all bones
-		for j in range( 0, len(bone_names) ):
-			bone_name = bone_names[j]
-			pose_bone = pose.bones[bone_name]
-			bone = skeleton.bones[bone_name]
-			
-			# rotation
-			rot = pose_bone.quat.toMatrix()
-			rot.resize4x4()
-			# translation
-			tra = Matrix()
-			tra.identity()
-			for m in range(0, 3):
-				tra[m][3] = pose_bone.loc[m]
-			# bone matris at armature space aka MA
-			MA = Matrix( bone.matrix["ARMATURESPACE"] )
-			MAi = Matrix( MA )
-			MAi.invert()
-			
-			# calc the m4 = MA * tra * rot * MAi
-			rot.transpose()
-			tra.transpose()
-			MA.transpose()
-			MAi.transpose()
-			
-			m4 = MulMatrix( rot, MAi )
-			m4 = MulMatrix( tra, m4 )
-			m4 = MulMatrix( MA, m4 )
-			
-			m4.transpose()
-			
-			# get the final quat and loc
-			quat = m4.rotationPart()
-			quat = quat.toQuat()
-			loc  = m4.translationPart()
-			
-			quat = pose_bone.quat
-			loc = pose_bone.loc
-			
-			for k in range(0, 4):
-				skeleton_anim.bones[j].keyframes[i].rotation[k] = quat[k]
-			
-			for k in range(0, 3):
-				skeleton_anim.bones[j].keyframes[i].translation[k] = loc[k]
-	
-	Blender.Set( "curframe", 1 )
-	Blender.Redraw()	
-	
-	
-	# now do the apropriate for the bones without translation or rotation
-	zero_vec = Vector( 0.0, 0.0, 0.0 )
-	ident_quat = Quaternion( 1.0, 0.0, 0.0, 0.0 )
-	# for all the bones
-	for i in range( 0, len(bone_names) ):
-		no_anim_num = 0   # how many times we found that the bone has no anim
-		bone = skeleton_anim.bones[i]
-		# for all the keyframes
-		for j in range( 0, len(skeleton_anim.keyframes) ):
-			
-			if bone.keyframes[j].rotation == ident_quat and bone.keyframes[j].translation == zero_vec:
-				no_anim_num = no_anim_num + 1
-			
-		if no_anim_num == len( skeleton_anim.keyframes ):
-			print "Bone \"%s\" has no animation" % bone_names[ i ]
-			bone.keyframes = []
-	
-		
-	# write to ftxt
-	ftxt = ""
-	
-	# the keyframes
-	if b_cmnts:
-		ftxt += "/*KEYFRAMES_NUM*/ "
-	ftxt += len(skeleton_anim.keyframes) + "\n"
-	
-	if b_cmnts:
-		ftxt += "/*KEYFRAMES*/ "
-	for kf in skeleton_anim.keyframes:
-		ftxt += str(kf - 1)
-	ftxt += "\n"
-	
-	# the bones num
-	if b_cmnts:
-		ftxt += "/*BONES_NUM*/ " 
-	ftxt += str( len(bone_names) )
-	
-	for i in range( 0, len(bone_names) ):
-		bone = skeleton_anim.bones[i]
-		if b_cmnts:
-			ftxt += "\t/*BONE_NAME " + bone_names[i] + "*/\n"
-		
-		if len( bone.keyframes ):
-			if b_cmnts:
-				ftxt += "\t\t/*HAS_ANIM*/ "
-			ftxt += "1\n"
-			
-			for j in range( 0, len( skeleton_anim.keyframes ) ):
-				file.write( "\t\tKEYFRAME %d\n" % (skeleton_anim.keyframes[j] - 1) ) # -1 cause my keyframes start from 0
-				if b_cmnts:
-					ftxt += "\t\t/*KEYFRAME" + str(skeleton_anim.keyframes[j] - 1) + "*/\n"
-				
-				# write rotation			
-				if b_cmnts:
-					ftxt += "\t\t\t/*ROTATION*/ "
-				for k in range( 0, 4 ):
-					ftxt += str( bone.keyframes[j].rotation[k] ) + " "
-				ftxt += "\n"
-				
-				# write translation
-				if b_cmnts:
-					ftxt += "\t\t\t/*TRANSLATION*/ "
-				for k in range( 0, 3 ):
-					ftxt += str( bone.keyframes[j].translation[k] ) + " "
-				ftxt += "\n"
-			
-		else:
-			if b_cmnts:
-				ftxt += "\t\t/*HAS_ANIM*/ "
-			ftxt += "0\n"
-	
-	return ftxt
-
-
-
-#===================================================================================================
-# ExportAnim                                                                                       =
-#===================================================================================================
-def ExportAnim( path, obj, b_cmnts ):
-	print obj.__class__.__name__
-	
-
-	
-	
-	action = obj.getAction()
-	if action == 0:
-		ERROR( "Empty action for obj " + obj.getName() )
-		return false
-	
-	INFO( "Trying to export skeleton animation \"" + skeleton.name + "\"" )
-	
-	filename = path + action.name + "." + obj.getName() + ".anim"
-	WriteFile( filename, ScriptAnim( obj, b_cmnts ) )
-	
-	INFO( "Skeleton animation exported!! \"" + filename + "\"" )	

+ 4 - 0
src/Main.cpp

@@ -346,6 +346,10 @@ int main(int argc, char* argv[])
 {
 {
 	new App(argc, argv);
 	new App(argc, argv);
 
 
+/*	Mat3 m(Axisang(-PI/2, Vec3(1,0,0)));
+	PRINT(fixed << m);
+	return 0;*/
+
 	init();
 	init();
 
 
 	mainLoop();
 	mainLoop();

+ 2 - 2
src/Resources/Material.cpp

@@ -184,7 +184,7 @@ bool Material::load(const char* filename)
 
 
 					// check if acceptable value
 					// check if acceptable value
 					MsSwitch* mss = msSwitches;
 					MsSwitch* mss = msSwitches;
-					while(mss->prefix != NULL)
+					while(mss->switchName != NULL)
 					{
 					{
 						if(!strcmp(mss->switchName, token->getString()))
 						if(!strcmp(mss->switchName, token->getString()))
 							break;
 							break;
@@ -192,7 +192,7 @@ bool Material::load(const char* filename)
 						++mss;
 						++mss;
 					}
 					}
 
 
-					if(mss->prefix == NULL)
+					if(mss->switchName == NULL)
 					{
 					{
 						PARSE_ERR("Incorrect switch " << token->getString());
 						PARSE_ERR("Incorrect switch " << token->getString());
 						return false;
 						return false;

+ 8 - 5
src/Resources/SkelAnim.cpp

@@ -9,11 +9,11 @@
 bool SkelAnim::load(const char* filename)
 bool SkelAnim::load(const char* filename)
 {
 {
 	Scanner scanner;
 	Scanner scanner;
-	if(!scanner.loadFile(filename)) return false;
+	if(!scanner.loadFile(filename))
+		return false;
 
 
 	const Scanner::Token* token;
 	const Scanner::Token* token;
 
 
-
 	// keyframes
 	// keyframes
 	token = &scanner.getNextToken();
 	token = &scanner.getNextToken();
 	if(token->getCode() != Scanner::TC_NUMBER || token->getDataType() != Scanner::DT_INT)
 	if(token->getCode() != Scanner::TC_NUMBER || token->getDataType() != Scanner::DT_INT)
@@ -23,7 +23,8 @@ bool SkelAnim::load(const char* filename)
 	}
 	}
 	keyframes.resize(token->getValue().getInt());
 	keyframes.resize(token->getValue().getInt());
 
 
-	if(!Parser::parseArrOfNumbers(scanner, false, false, keyframes.size(), &keyframes[0])) return false;
+	if(!Parser::parseArrOfNumbers(scanner, false, false, keyframes.size(), &keyframes[0]))
+		return false;
 
 
 	// bones num
 	// bones num
 	token = &scanner.getNextToken();
 	token = &scanner.getNextToken();
@@ -54,11 +55,13 @@ bool SkelAnim::load(const char* filename)
 			{
 			{
 				// parse the quat
 				// parse the quat
 				float tmp[4];
 				float tmp[4];
-				if(!Parser::parseArrOfNumbers(scanner, false, true, 4, &tmp[0])) return false;
+				if(!Parser::parseArrOfNumbers(scanner, false, true, 4, &tmp[0]))
+					return false;
 				bones[i].keyframes[j].rotation = Quat(tmp[1], tmp[2], tmp[3], tmp[0]);
 				bones[i].keyframes[j].rotation = Quat(tmp[1], tmp[2], tmp[3], tmp[0]);
 
 
 				// parse the vec3
 				// parse the vec3
-				if(!Parser::parseArrOfNumbers(scanner, false, true, 3, &bones[i].keyframes[j].translation[0])) return false;
+				if(!Parser::parseArrOfNumbers(scanner, false, true, 3, &bones[i].keyframes[j].translation[0]))
+					return false;
 			}
 			}
 		}
 		}
 	} // end for all bones
 	} // end for all bones

+ 11 - 9
src/Resources/SkelAnim.h

@@ -1,16 +1,18 @@
-#ifndef _SKEL_ANIM_H_
-#define _SKEL_ANIM_H_
+#ifndef SKELANIM_H
+#define SKELANIM_H
 
 
 #include "Common.h"
 #include "Common.h"
 #include "Resource.h"
 #include "Resource.h"
 #include "Math.h"
 #include "Math.h"
 
 
 
 
-/// Skeleton animation
+/// Skeleton animation resource
 class SkelAnim: public Resource
 class SkelAnim: public Resource
 {
 {
 	public:
 	public:
-		/// BonePose
+		/**
+		 * Bone pose
+		 */
 		class BonePose
 		class BonePose
 		{
 		{
 			public:
 			public:
@@ -18,26 +20,26 @@ class SkelAnim: public Resource
 				Vec3 translation;
 				Vec3 translation;
 		};
 		};
 
 
-
-		/// BoneAnim
+		/**
+		 * Bone animation
+		 */
 		class BoneAnim
 		class BoneAnim
 		{
 		{
 			public:
 			public:
 				Vec<BonePose> keyframes; ///< The poses for every keyframe. Its empty if the bone doesnt have any animation
 				Vec<BonePose> keyframes; ///< The poses for every keyframe. Its empty if the bone doesnt have any animation
 
 
 				BoneAnim() {}
 				BoneAnim() {}
-				~BoneAnim() { if(keyframes.size()) keyframes.clear();}
+				~BoneAnim() {}
 		};
 		};
 		
 		
 		Vec<uint> keyframes;
 		Vec<uint> keyframes;
 		uint framesNum;
 		uint framesNum;
-
 		Vec<BoneAnim> bones;
 		Vec<BoneAnim> bones;
 
 
 		SkelAnim();
 		SkelAnim();
 		~SkelAnim() {}
 		~SkelAnim() {}
 		bool load(const char* filename);
 		bool load(const char* filename);
-		void unload() { keyframes.clear(); bones.clear(); framesNum=0; }
+		void unload() {}
 };
 };
 
 
 
 

+ 16 - 4
src/Resources/Skeleton.cpp

@@ -29,6 +29,9 @@ bool Skeleton::load(const char* filename)
 		Bone& bone = bones[i];
 		Bone& bone = bones[i];
 		bone.id = i;
 		bone.id = i;
 
 
+		Mat3 m3_(Axisang(-PI/2, Vec3(1,0,0)));
+		Mat4 m4_(Vec3(0), m3_, 1.0);
+
 		// NAME
 		// NAME
 		token = &scanner.getNextToken();
 		token = &scanner.getNextToken();
 		if(token->getCode() != Scanner::TC_STRING)
 		if(token->getCode() != Scanner::TC_STRING)
@@ -39,14 +42,23 @@ bool Skeleton::load(const char* filename)
 		bone.name = token->getValue().getString();
 		bone.name = token->getValue().getString();
 
 
 		// head
 		// head
-		if(!Parser::parseArrOfNumbers<float>(scanner, false, true, 3, &bone.head[0])) return false;
+		if(!Parser::parseArrOfNumbers<float>(scanner, false, true, 3, &bone.head[0]))
+			return false;
+
+		//bone.head = m3_ * bone.head;
 
 
 		// tail
 		// tail
-		if(!Parser::parseArrOfNumbers<float>(scanner, false, true, 3, &bone.tail[0])) return false;
+		if(!Parser::parseArrOfNumbers<float>(scanner, false, true, 3, &bone.tail[0]))
+			return false;
+
+		//bone.tail = m3_ * bone.tail;
 
 
 		// matrix
 		// matrix
 		Mat4 m4;
 		Mat4 m4;
-		if(!Parser::parseArrOfNumbers<float>(scanner, false, true, 16, &m4[0])) return false;
+		if(!Parser::parseArrOfNumbers<float>(scanner, false, true, 16, &m4[0]))
+			return false;
+
+		//m4 = m4_ * m4;
 
 
 		// matrix for real
 		// matrix for real
 		bone.rotSkelSpace = m4.getRotationPart();
 		bone.rotSkelSpace = m4.getRotationPart();
@@ -58,7 +70,7 @@ bool Skeleton::load(const char* filename)
 		// parent
 		// parent
 		token = &scanner.getNextToken();
 		token = &scanner.getNextToken();
 		if((token->getCode() != Scanner::TC_NUMBER || token->getDataType() != Scanner::DT_INT) &&
 		if((token->getCode() != Scanner::TC_NUMBER || token->getDataType() != Scanner::DT_INT) &&
-		   (token->getCode() != Scanner::TC_IDENTIFIER || strcmp(token->getValue().getString(), "NULL")!=0))
+		   (token->getCode() != Scanner::TC_IDENTIFIER || strcmp(token->getValue().getString(), "NULL") != 0))
 		{
 		{
 			PARSE_ERR_EXPECTED("integer or NULL");
 			PARSE_ERR_EXPECTED("integer or NULL");
 			return false;
 			return false;