Skip to content
Snippets Groups Projects
Commit 2afc158e authored by Chris Foster's avatar Chris Foster
Browse files

Begun work on Full Animation. Having trouble with axis flipping.

parent 306c82dd
Branches
Tags
No related merge requests found
...@@ -15,6 +15,15 @@ ...@@ -15,6 +15,15 @@
# All rights reserved. # All rights reserved.
# ***** GPL LICENSE BLOCK ***** # ***** GPL LICENSE BLOCK *****
#NOTE: ========================================================
#I've begun work on a Full Animation feature to more accurately export
#FCurve data. It's going pretty well, but I'm having some trouble with
#axis flipping. To "enable" the feature, uncomment line #988
#The problem is in the WriteFullAnimationSet function at line #948
# - Chris (2010-7-11)
#One line description for early versions of Blender 2.52. #One line description for early versions of Blender 2.52.
"Export: DirectX Model Format (.x)" "Export: DirectX Model Format (.x)"
...@@ -30,6 +39,7 @@ bl_addon_info = { ...@@ -30,6 +39,7 @@ bl_addon_info = {
'tracker_url': 'https://projects.blender.org/tracker/index.php?'\ 'tracker_url': 'https://projects.blender.org/tracker/index.php?'\
'func=detail&aid=22795&group_id=153&atid=469', 'func=detail&aid=22795&group_id=153&atid=469',
'category': 'Import/Export'} 'category': 'Import/Export'}
""" """
Name: 'DirectX Exporter' Name: 'DirectX Exporter'
Blender: 252 Blender: 252
...@@ -38,7 +48,8 @@ Tooltip: 'Exports to the DirectX model file format (.x)' ...@@ -38,7 +48,8 @@ Tooltip: 'Exports to the DirectX model file format (.x)'
""" """
__author__ = "Chris Foster (Kira Vakaan)" __author__ = "Chris Foster (Kira Vakaan)"
__url__ = "www.tobedecided.com" __url__ = "http://wiki.blender.org/index.php/Extensions:2.5/Py/" \
"Scripts/File_I-O/DirectX_Exporter"
__version__ = "1.1" __version__ = "1.1"
__bpydoc__ = """\ __bpydoc__ = """\
""" """
...@@ -165,7 +176,10 @@ def ExportDirectX(Config): ...@@ -165,7 +176,10 @@ def ExportDirectX(Config):
print("Done") print("Done")
if Config.Verbose: if Config.Verbose:
print("Writing Animation...") print("Writing Animation...")
WriteAnimationSet(Config) if Config.ExportAnimation==1:
WriteKeyedAnimationSet(Config)
else:
WriteFullAnimationSet(Config)
bpy.context.scene.frame_current = CurrentFrame bpy.context.scene.frame_current = CurrentFrame
if Config.Verbose: if Config.Verbose:
print("Done") print("Done")
...@@ -178,17 +192,19 @@ def GetObjectChildren(Parent): ...@@ -178,17 +192,19 @@ def GetObjectChildren(Parent):
return [Object for Object in Parent.children return [Object for Object in Parent.children
if Object.type in ("ARMATURE", "EMPTY", "MESH")] if Object.type in ("ARMATURE", "EMPTY", "MESH")]
#Returns the vertex count of Mesh, counting each vertex for every face.
def GetMeshVertexCount(Mesh): def GetMeshVertexCount(Mesh):
VertexCount = 0 VertexCount = 0
for Face in Mesh.faces: for Face in Mesh.faces:
VertexCount += len(Face.verts) VertexCount += len(Face.verts)
return VertexCount return VertexCount
#Returns the file path of first image texture from Material.
def GetMaterialTexture(Material): def GetMaterialTexture(Material):
if Material: if Material:
#Create a list of Textures that have type "IMAGE"
ImageTextures = [Material.texture_slots[TextureSlot].texture for TextureSlot in Material.texture_slots.keys() if Material.texture_slots[TextureSlot].texture.type == "IMAGE"] ImageTextures = [Material.texture_slots[TextureSlot].texture for TextureSlot in Material.texture_slots.keys() if Material.texture_slots[TextureSlot].texture.type == "IMAGE"]
#Refine a new list with only image textures that have a file source
ImageFiles = [os.path.basename(Texture.image.filename) for Texture in ImageTextures if Texture.image.source == "FILE"] ImageFiles = [os.path.basename(Texture.image.filename) for Texture in ImageTextures if Texture.image.source == "FILE"]
if ImageFiles: if ImageFiles:
return ImageFiles[0] return ImageFiles[0]
...@@ -529,9 +545,11 @@ def WriteMeshSkinWeights(Config, Object, Mesh): ...@@ -529,9 +545,11 @@ def WriteMeshSkinWeights(Config, Object, Mesh):
MaxInfluences = 0 MaxInfluences = 0
UsedBones = set() UsedBones = set()
#Maps bones to a list of vertices they affect
VertexGroups = {} VertexGroups = {}
for Vertex in Mesh.verts: for Vertex in Mesh.verts:
#BoneInfluences contains the bones of the armature that affect the current vertex
BoneInfluences = [PoseBones[Object.vertex_groups[Group.group].name] for Group in Vertex.groups if Object.vertex_groups[Group.group].name in PoseBones] BoneInfluences = [PoseBones[Object.vertex_groups[Group.group].name] for Group in Vertex.groups if Object.vertex_groups[Group.group].name in PoseBones]
if len(BoneInfluences) > MaxInfluences: if len(BoneInfluences) > MaxInfluences:
MaxInfluences = len(BoneInfluences) MaxInfluences = len(BoneInfluences)
...@@ -617,7 +635,7 @@ def WriteMeshSkinWeights(Config, Object, Mesh): ...@@ -617,7 +635,7 @@ def WriteMeshSkinWeights(Config, Object, Mesh):
Config.File.write("{}}} //End of {} Skin Weights\n".format(" " * Config.Whitespace, LegalName(ArmatureObject.name) + "_" + LegalName(Bone.name))) Config.File.write("{}}} //End of {} Skin Weights\n".format(" " * Config.Whitespace, LegalName(ArmatureObject.name) + "_" + LegalName(Bone.name)))
def WriteAnimationSet(Config): def WriteKeyedAnimationSet(Config):
Config.File.write("{}AnimationSet {{\n".format(" " * Config.Whitespace)) Config.File.write("{}AnimationSet {{\n".format(" " * Config.Whitespace))
Config.Whitespace += 1 Config.Whitespace += 1
for Object in [Object for Object in Config.ObjectList if Object.animation_data]: for Object in [Object for Object in Config.ObjectList if Object.animation_data]:
...@@ -896,6 +914,61 @@ def WriteAnimationSet(Config): ...@@ -896,6 +914,61 @@ def WriteAnimationSet(Config):
Config.Whitespace -= 1 Config.Whitespace -= 1
Config.File.write("{}}} //End of AnimationSet\n".format(" " * Config.Whitespace)) Config.File.write("{}}} //End of AnimationSet\n".format(" " * Config.Whitespace))
def WriteFullAnimationSet(Config):
Config.File.write("{}AnimationSet {{\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
KeyframeCount = bpy.context.scene.frame_end - bpy.context.scene.frame_start + 1
for Object in Config.ObjectList:
Config.File.write("{}Animation {{\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{}{{{}}}\n".format(" " * Config.Whitespace, LegalName(Object.name)))
#Position
Config.File.write("{}AnimationKey {{ //Position\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{}2;\n{}{};\n".format(" " * Config.Whitespace," " * Config.Whitespace,KeyframeCount))
for Frame in range(0, KeyframeCount):
bpy.context.scene.set_frame(Frame)
Position = Config.SystemMatrix * Object.location
Config.File.write("{}{}{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, (str(Frame) + ";3;").ljust(8), Position[0], Position[1], Position[2]))
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
#Rotation
Config.File.write("{}AnimationKey {{ //Rotation\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{}0;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, KeyframeCount))
for Frame in range(0, KeyframeCount):
bpy.context.scene.set_frame(Frame)
#Works pretty well, but causes a slightly noticeable axis flip at 180*
Rotation = (Config.SystemMatrix * (Object.rotation_euler.to_matrix().to_4x4()) * Config.InverseSystemMatrix).to_quat()
Config.File.write("{}{}{:9f},{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace,(str(Frame) + ";4;").ljust(8), -Rotation[0], Rotation[1], Rotation[2], Rotation[3]))
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
#Scale
Config.File.write("{}AnimationKey {{ //Scale\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{}1;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, KeyframeCount))
for Frame in range(0, KeyframeCount):
bpy.context.scene.set_frame(Frame)
Scale = Config.SystemMatrix * Object.scale
Config.File.write("{}{}{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace,(str(Frame) + ";3;").ljust(8), Scale[0], Scale[1], Scale[2]))
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
if Config.ExportArmatures and Object.type == "ARMATURE":
pass
Config.Whitespace -= 1
Config.File.write("{}}} //End of AnimationSet\n".format(" " * Config.Whitespace))
def CloseFile(Config): def CloseFile(Config):
...@@ -993,4 +1066,4 @@ def unregister(): ...@@ -993,4 +1066,4 @@ def unregister():
if __name__ == "__main__": if __name__ == "__main__":
register() register()
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment