Skip to content
Browse files

Implemented the export of bone animations.

  • Loading branch information...
1 parent 9cbbc66 commit c93e36a8db6f91c74dcf1644334684619274483f @flo committed Apr 10, 2012
Showing with 157 additions and 54 deletions.
  1. +156 −53 m3export.py
  2. +1 −1 structures.xml
View
209 m3export.py
@@ -40,6 +40,7 @@
import os.path
actionTypeScene = "SCENE"
+actionTypeArmature = "OBJECT"
class Exporter:
def exportParticleSystems(self, scene, m3FileName):
@@ -130,6 +131,104 @@ def initMesh(self, model):
bone.location.initValue = self.createVector3FromBlenderVector(location)
bone.location.nullValue = self.createVector3FromBlenderVector(location)
+ boneName = blenderBone.name
+
+ locationAnimId = bone.location.header.animId
+ rotationAnimId = bone.rotation.header.animId
+ scaleAnimId = bone.scale.header.animId
+
+ locationAnimPath = 'pose.bones["%s"].location' % boneName
+ rotationAnimPath = 'pose.bones["%s"].rotation_quaternion' % boneName
+ scaleAnimPath = 'pose.bones["%s"].scale' % boneName
+
+ animationActionTuples = self.determineAnimationActionTuplesFor(armatureObject.name, actionTypeArmature)
+ for animation, action in animationActionTuples:
+ frames = self.getAllFramesOf(animation)
+ timeValuesInMS = self.allFramesToMSValues(frames)
+ xLocValues = self.getNoneOrValuesFor(action, locationAnimPath, 0, frames)
+ yLocValues = self.getNoneOrValuesFor(action, locationAnimPath, 1, frames)
+ zLocValues = self.getNoneOrValuesFor(action, locationAnimPath, 2, frames)
+ wRotValues = self.getNoneOrValuesFor(action, rotationAnimPath, 0, frames)
+ xRotValues = self.getNoneOrValuesFor(action, rotationAnimPath, 1, frames)
+ yRotValues = self.getNoneOrValuesFor(action, rotationAnimPath, 2, frames)
+ zRotValues = self.getNoneOrValuesFor(action, rotationAnimPath, 3, frames)
+ xScaValues = self.getNoneOrValuesFor(action, scaleAnimPath, 0, frames)
+ yScaValues = self.getNoneOrValuesFor(action, scaleAnimPath, 1, frames)
+ zScaValues = self.getNoneOrValuesFor(action, scaleAnimPath, 2, frames)
+
+ locAnimated = (xLocValues != None) or (yLocValues != None) or (zLocValues != None)
+ rotAnimated = (wRotValues != None) or (xRotValues != None) or (yRotValues != None) or (zRotValues != None)
+ scaAnimated = (xScaValues != None) or (yScaValues != None) or (zScaValues != None)
+ if locAnimated or rotAnimated or scaAnimated:
+ if xLocValues == None:
+ xLocValues = len(timeValuesInMS) * [location.x]
+ if yLocValues == None:
+ yLocValues = len(timeValuesInMS) * [location.y]
+ if zLocValues == None:
+ zLocValues = len(timeValuesInMS) * [location.z]
+
+ if wRotValues == None:
+ wRotValues = len(timeValuesInMS) * [rotation.w]
+ if xRotValues == None:
+ xRotValues = len(timeValuesInMS) * [rotation.x]
+ if yRotValues == None:
+ yRotValues = len(timeValuesInMS) * [rotation.y]
+ if zRotValues == None:
+ zRotValues = len(timeValuesInMS) * [rotation.z]
+
+ if xScaValues == None:
+ xScaValues = len(timeValuesInMS) * [scale.x]
+ if yScaValues == None:
+ yScaValues = len(timeValuesInMS) * [scale.y]
+ if zScaValues == None:
+ zScaValues = len(timeValuesInMS) * [scale.z]
+ m3Locs = []
+ m3Rots = []
+ m3Scas = []
+ for xLoc, yLoc, zLoc, wRot, xRot, yRot, zRot, xSca, ySca, zSca in zip(xLocValues, yLocValues, zLocValues, wRotValues, xRotValues, yRotValues, zRotValues, xScaValues, yScaValues, zScaValues):
+ loc = mathutils.Vector((xLoc, yLoc, zLoc))
+ rot = mathutils.Quaternion((wRot, xRot, yRot, zRot))
+ sca = mathutils.Vector((xSca, ySca, zSca))
+ poseMatrix = shared.locRotScaleMatrix(loc, rot, sca)
+ m3PoseMatrix = leftCorrectionMatrix * poseMatrix * rightCorrectionMatrix
+ sca, rot = shared.scaleAndRotationOf(m3PoseMatrix)
+ loc = m3PoseMatrix.translation
+ m3Locs.append(self.createVector3FromBlenderVector(loc))
+ m3Rots.append(self.createQuaternionFromBlenderQuaternion(rot))
+ m3Scas.append(self.createVector3FromBlenderVector(sca))
+
+ animIdToAnimDataMap = self.nameToAnimIdToAnimDataMap[animation.name]
+
+ m3AnimBlock = m3.SD3VV0()
+ m3AnimBlock.frames = timeValuesInMS
+ m3AnimBlock.flags = 0
+ m3AnimBlock.fend = self.frameToMS(animation.endFrame)
+ m3AnimBlock.keys = m3Locs
+ animIdToAnimDataMap[locationAnimId] = m3AnimBlock
+
+ m3AnimBlock = m3.SD4QV0()
+ m3AnimBlock.frames = timeValuesInMS
+ m3AnimBlock.flags = 0
+ m3AnimBlock.fend = self.frameToMS(animation.endFrame)
+ m3AnimBlock.keys = m3Rots
+ animIdToAnimDataMap[rotationAnimId] = m3AnimBlock
+
+ m3AnimBlock = m3.SD3VV0()
+ m3AnimBlock.frames = timeValuesInMS
+ m3AnimBlock.flags = 0
+ m3AnimBlock.fend = self.frameToMS(animation.endFrame)
+ m3AnimBlock.keys = m3Scas
+ animIdToAnimDataMap[scaleAnimId] = m3AnimBlock
+
+ bone.location.header.flags = 1
+ bone.location.header.animFlags = shared.animFlagsForAnimatedProperty
+ bone.rotation.header.flags = 1
+ bone.rotation.header.animFlags = shared.animFlagsForAnimatedProperty
+ bone.scale.header.flags = 1
+ bone.scale.header.animFlags = shared.animFlagsForAnimatedProperty
+ bone.setNamedBit("flags", "animated", True)
+
+
absRestPosMatrixFixed = absRestPosMatrix * shared.rotFixMatrixInverted
absoluteInverseRestPoseMatrixFixed = absRestPosMatrixFixed.inverted()
@@ -752,6 +851,47 @@ def createIdentityMatrix(self):
matrix.w = self.createVector4(0.0, 0.0, 0.0, 1.0)
return matrix
+ def determineAnimationActionTuplesFor(self, actionOwnerName, actionOwnerType):
+ animationActionTuples = []
+ scene = self.scene
+ for animation in scene.m3_animations:
+ for assignedAction in animation.assignedActions:
+ if actionOwnerName == assignedAction.targetName:
+ actionName = assignedAction.actionName
+ action = bpy.data.actions.get(actionName)
+ if action == None:
+ print("Warning: The action %s was referenced by name but does no longer exist" % assignedAction.actionName)
+ else:
+ if action.id_root == actionOwnerType:
+ animationActionTuples.append((animation, action))
+ return animationActionTuples
+
+
+ def getAllFramesOf(self, animation):
+ #TODO Does the end frame need to be included?
+ return range(animation.startFrame, animation.endFrame)
+
+ def allFramesToMSValues(self, frames):
+ timeValues = []
+ for frame in frames:
+ timeInMS = self.frameToMS(frame)
+ timeValues.append(timeInMS)
+ return timeValues
+
+ def getNoneOrValuesFor(self, action, animPath, curveArrayIndex, frames):
+ values = []
+ curve = self.findFCurveWithPathAndIndex(action, animPath, curveArrayIndex)
+ if curve == None:
+ return None
+ for frame in frames:
+ values.append(curve.evaluate(frame))
+ return values
+
+ def findFCurveWithPathAndIndex(self, action, animPath, curveArrayIndex):
+ for curve in action.fcurves:
+ if (curve.data_path == animPath) and (curve.array_index == curveArrayIndex):
+ return curve
+ return None
class BlenderToM3DataTransferer:
@@ -763,19 +903,7 @@ def __init__(self, exporter, m3Object, blenderObject, animPathPrefix, actionOwn
self.actionOwnerName = actionOwnerName
self.actionOwnerType = actionOwnerType
- self.animationActionTuples = []
-
- scene = self.exporter.scene
- for animation in scene.m3_animations:
- for assignedAction in animation.assignedActions:
- if actionOwnerName == assignedAction.targetName:
- actionName = assignedAction.actionName
- action = bpy.data.actions.get(actionName)
- if action == None:
- print("Warning: The action %s was referenced by name but does no longer exist" % assignedAction.actionName)
- else:
- if action.id_root == actionOwnerType:
- self.animationActionTuples.append((animation, action))
+ self.animationActionTuples = self.exporter.determineAnimationActionTuplesFor(actionOwnerName, actionOwnerType)
def transferAnimatableColor(self, fieldName):
animRef = m3.ColorAnimationReference()
@@ -789,12 +917,12 @@ def transferAnimatableColor(self, fieldName):
animPath = self.animPathPrefix + fieldName
for animation, action in self.animationActionTuples:
- frames = self.getAllFramesOf(animation)
- timeValuesInMS = self.allFramesToMSValues(frames)
- redValues = self.getNoneOrValuesFor(action, animPath, 0, frames)
- greenValues = self.getNoneOrValuesFor(action, animPath, 1, frames)
- blueValues = self.getNoneOrValuesFor(action, animPath, 2, frames)
- alphaValues = self.getNoneOrValuesFor(action, animPath, 2, frames)
+ frames = self.exporter.getAllFramesOf(animation)
+ timeValuesInMS = self.exporter.allFramesToMSValues(frames)
+ redValues = self.exporter.getNoneOrValuesFor(action, animPath, 0, frames)
+ greenValues = self.exporter.getNoneOrValuesFor(action, animPath, 1, frames)
+ blueValues = self.exporter.getNoneOrValuesFor(action, animPath, 2, frames)
+ alphaValues = self.exporter.getNoneOrValuesFor(action, animPath, 2, frames)
if (redValues != None) or (greenValues != None) or (blueValues != None) or (alphaValues != None):
if redValues == None:
redValues = len(timeValuesInMS) * [m3CurrentColor.red]
@@ -832,9 +960,9 @@ def transferAnimatableSingleFloatOrInt(self, fieldName, animRefClass, animRefFla
animPath = self.animPathPrefix + fieldName
for animation, action in self.animationActionTuples:
- frames = self.getAllFramesOf(animation)
- timeValuesInMS = self.allFramesToMSValues(frames)
- values = self.getNoneOrValuesFor(action, animPath, 0, frames)
+ frames = self.exporter.getAllFramesOf(animation)
+ timeValuesInMS = self.exporter.allFramesToMSValues(frames)
+ values = self.exporter.getNoneOrValuesFor(action, animPath, 0, frames)
if values != None:
convertedValues = []
for value in values:
@@ -883,11 +1011,11 @@ def transferAnimatableVector3(self, fieldName):
animPath = self.animPathPrefix + fieldName
for animation, action in self.animationActionTuples:
- frames = self.getAllFramesOf(animation)
- timeValuesInMS = self.allFramesToMSValues(frames)
- xValues = self.getNoneOrValuesFor(action, animPath, 0, frames)
- yValues = self.getNoneOrValuesFor(action, animPath, 1, frames)
- zValues = self.getNoneOrValuesFor(action, animPath, 2, frames)
+ frames = self.exporter.getAllFramesOf(animation)
+ timeValuesInMS = self.exporter.allFramesToMSValues(frames)
+ xValues = self.exporter.getNoneOrValuesFor(action, animPath, 0, frames)
+ yValues = self.exporter.getNoneOrValuesFor(action, animPath, 1, frames)
+ zValues = self.exporter.getNoneOrValuesFor(action, animPath, 2, frames)
if (xValues != None) or (yValues != None) or (zValues != None):
if xValues == None:
xValues = len(timeValuesInMS) * [currentBVector.x]
@@ -931,32 +1059,7 @@ def transferFloat(self, fieldName):
def transferEnum(self, fieldName):
value = getattr(self.blenderObject, fieldName)
setattr(self.m3Object, fieldName , int(value))
-
- def getAllFramesOf(self, animation):
- #TODO Does the end frame need to be included?
- return range(animation.startFrame, animation.endFrame)
-
- def allFramesToMSValues(self, frames):
- timeValues = []
- for frame in frames:
- timeInMS = self.exporter.frameToMS(frame)
- timeValues.append(timeInMS)
- return timeValues
-
- def getNoneOrValuesFor(self, action, animPath, curveArrayIndex, frames):
- values = []
- curve = self.findFCurveWithPathAndIndex(action, animPath, curveArrayIndex)
- if curve == None:
- return None
- for frame in frames:
- values.append(curve.evaluate(frame))
- return values
-
- def findFCurveWithPathAndIndex(self, action, animPath, curveArrayIndex):
- for curve in action.fcurves:
- if (curve.data_path == animPath) and (curve.array_index == curveArrayIndex):
- return curve
- return None
+
def exportParticleSystems(scene, filename):
exporter = Exporter()
View
2 structures.xml
@@ -324,7 +324,7 @@
<bit mask="0x10" name="billboard1" />
<bit mask="0x40" name="billboard2" />
<bit mask="0x100" name="twoDProjection" />
- <bit mask="0x200" name="animated " />
+ <bit mask="0x200" name="animated" />
<bit mask="0x400" name="inverseKinematics " />
<bit mask="0x800 " name="skinned" />
<bit mask="0x2000" name="real" />

0 comments on commit c93e36a

Please sign in to comment.
Something went wrong with that request. Please try again.