+# coding: utf-8
+
+__author__= ['ousttrue']
+__url__ = ("")
+__version__= '20100515 0.1:'
+__bpydoc__= '''\
+vmd Importer
+
+This script imports a vmd into Blender for editing.
+'''
+
+import bpy
+from bpy.props import *
+import mathutils
+import sys
+import os
+import math
+from meshio import vmd, englishmap
+
+
+EPSILON=1e-5
+THRESHOLD=-0.85
+
+
+def ToDegree(x):
+ return x/math.pi * 180.0
+
+
+def clampDegree(d):
+ return d % 360
+
+
+def multQuat(l, r):
+ q=mathutils.Quaternion((0, 0, 0), l.w*r.w-(l.x*r.x+l.y*r.y+l.z*r.z))
+ q.x=l.w*r.x+r.w*l.x+l.y*r.z-l.z*r.y
+ q.y=l.w*r.y+r.w*l.y+l.z*r.x-l.x*r.z
+ q.z=l.w*r.z+r.w*l.z+l.x*r.y-l.y*r.x
+ return q
+
+
+def import_motion_key(l, o):
+ print('import_motion_key: %s' % o.name)
+
+ armature = o.data
+ pose = o.pose
+ not_in_map={}
+ not_found={}
+ counter=0
+ last_frame=0
+ for n in l.boneKeys:
+ keyFrames=l.getBoneKeyFrameList(n)
+ boneName=englishmap.getEnglishBoneName(n)
+ try:
+ poseBone=pose.bones[boneName]
+ bone=armature.bones[boneName]
+ # rot
+ armRotate=bone.matrix_local.rotation_part()
+ # quat
+ armRotateQuaternion=armRotate.to_quat()
+ if armRotateQuaternion.w<0:
+ armRotateQuaternion.w=-armRotateQuaternion.w
+ armRotateQuaternion.x=-armRotateQuaternion.x
+ armRotateQuaternion.y=-armRotateQuaternion.y
+ armRotateQuaternion.z=-armRotateQuaternion.z
+
+ # inv
+ armRotateInv=mathutils.Matrix(armRotate).transpose()
+ # quat
+ armRotateInvQuaternion=armRotateInv.to_quat()
+ if armRotateInvQuaternion.w<0:
+ armRotateInvQuaternion.w=-armRotateInvQuaternion.w
+ armRotateInvQuaternion.x=-armRotateInvQuaternion.x
+ armRotateInvQuaternion.y=-armRotateInvQuaternion.y
+ armRotateInvQuaternion.z=-armRotateInvQuaternion.z
+
+ reverseFlag=False
+ lastQ=None
+
+ for i in range(len(keyFrames.list)):
+ key=keyFrames.getKey(i)
+ ####################
+ # rotation
+ ####################
+ if lastQ and lastQ.dot(key.q)<0:
+ reverseFlag=not reverseFlag
+ lastQ=key.q
+
+ # convert left-handed y-up to right-handed z-up
+ if reverseFlag:
+ # reverse quaternion for slerp
+ q=mathutils.Quaternion((0, 0, 0), -key.q.w)
+ q.x=key.q.x
+ q.y=key.q.z
+ q.z=key.q.y
+ else:
+ q=mathutils.Quaternion((0, 0, 0), key.q.w)
+ q.x=-key.q.x
+ q.y=-key.q.z
+ q.z=-key.q.y
+
+ poseBone.rotation_quaternion=multQuat(
+ armRotateInvQuaternion,
+ multQuat(q, armRotateQuaternion))
+
+ ####################
+ # location
+ ####################
+ poseBone.location = mathutils.Vector(
+ (float(key.pos.x), float(key.pos.z), float(key.pos.y)))
+
+ # insert
+ poseBone.keyframe_insert('rotation_quaternion', -1, keyFrames.getFrame(i))
+ poseBone.keyframe_insert('location', -1, keyFrames.getFrame(i))
+ last_frame=max(last_frame, keyFrames.getFrame(i))
+
+ counter+=1
+
+ except KeyError as msg:
+ not_found[boneName]=True
+ continue
+
+ print("bone not exists")
+ for name in not_found.keys():
+ print(name)
+
+ return last_frame
+
+
+def IPO_CURVE_get_or_create(ipo, name):
+ for c in ipo:
+ if c.name == name:
+ return c
+ return ipo.addCurve(name)
+
+
+def import_shape_key(l, mesh):
+ print('import_shape_key: %s' % mesh.name)
+ return 0
+ # ToDo
+ key = mesh.getData().key
+ if key is None:
+ Draw.PupMenu('selecting mesh not has a Key')
+ return
+ # get or create IPO
+ ipo = key.getIpo()
+ if ipo == None:
+ ipo = Blender.Ipo.New("Key", "ShapeKey")
+ key.ipo = ipo
+
+ # insert shape keys
+ counter=0
+ last_frame=0
+ for n in l.morphKeys:
+ keyFrames=l.getMorphKeyFrameList(n)
+ if n=='base':
+ continue
+ name=englishmap.getEnglishSkinName(n)
+ try:
+ curve=IPO_CURVE_get_or_create(ipo, name)
+ except NameError as msg:
+ print(NameError, msg)
+ print(n, name)
+ continue
+ curve.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
+ for i in xrange(len(keyFrames.list)):
+ key=keyFrames.getKey(i)
+ frame=keyFrames.getFrame(i)
+ curve[frame]=key.weight
+ last_frame=max(last_frame, frame)
+
+ counter+=1
+
+ return last_frame
+
+
+def load(filename, context):
+ """
+ load vmd file to context.
+ """
+ io=vmd.IO()
+ if not io.read(filename):
+ print("fail to read", filename)
+ return
+
+ scene=context.scene
+
+ # import
+ last_frame=0
+ for o in scene.objects:
+ if o.selected:
+ if o.data.__class__ is bpy.types.Armature:
+ last_frame=max(
+ last_frame, import_motion_key(io, o))
+ elif o.data.__class__ is bpy.types.Mesh:
+ last_frame=max(
+ last_frame, import_shape_key(io, o))
+
+ # set end frame
+ scene.frame_end = last_frame
+ print("last frame: %d" % last_frame)
+
+ # redraw
+ scene.update()
+
+ print("finised")
+
+
+###############################################################################
+# import operator
+###############################################################################
+class IMPORT_OT_vmd(bpy.types.Operator):
+ bl_idname = "import_anim.vmd"
+ bl_label = 'Import VMD'
+
+ # List of operator properties, the attributes will be assigned
+ # to the class instance from the operator settings before calling.
+ path = StringProperty(
+ name="File Path",
+ description="File path used for importing the VMD file",
+ maxlen= 1024, default= "")
+ filename = StringProperty(
+ name="File Name",
+ description="Name of the file.")
+ directory = StringProperty(
+ name="Directory",
+ description="Directory of the file.")
+
+ def execute(self, context):
+ load(self.properties.path, context)
+ return {'FINISHED'}
+
+ def invoke(self, context, event):
+ wm = context.manager
+ wm.add_fileselect(self)
+ return {'RUNNING_MODAL'}
+
+
+###############################################################################
+# register menu
+###############################################################################
+def menu_func(self, context):
+ self.layout.operator(IMPORT_OT_vmd.bl_idname,
+ text="MikuMikuDance motion (.vmd)")
+
+def register():
+ bpy.types.register(IMPORT_OT_vmd)
+ bpy.types.INFO_MT_file_import.append(menu_func)
+
+def unregister():
+ bpy.types.unregister(IMPORT_OT_vmd)
+ bpy.types.INFO_MT_file_import.remove(menu_func)
+
+
+if __name__=="__main__":
+ register()
+