From 8eb2defbed5f40813112744f8ec0ab8791f7d280 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Sun, 16 May 2010 06:31:31 +0900 Subject: [PATCH] add import_anim_vmd.py. --- swig/blender25/import_anim_vmd.py | 256 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 swig/blender25/import_anim_vmd.py diff --git a/swig/blender25/import_anim_vmd.py b/swig/blender25/import_anim_vmd.py new file mode 100644 index 0000000..eb43ee5 --- /dev/null +++ b/swig/blender25/import_anim_vmd.py @@ -0,0 +1,256 @@ +# 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() + -- 2.11.0