OSDN Git Service

implement bone motion import(import_anim_vmd).
[meshio/meshio.git] / swig / blender25 / import_anim_vmd.py
1 # coding: utf-8
2
3 __author__= ['ousttrue']
4 __url__ = ("")
5 __version__= '20100515 0.2:'
6 __bpydoc__= '''\
7 vmd Importer
8
9 This script imports a vmd into Blender for editing.
10 0.1 2010/05/15 first implement.
11 0.2 2010/05/16 implement bone motion.
12 '''
13
14 import bpy
15 from bpy.props import *
16 import mathutils
17 import sys
18 import os
19 import math
20 from meshio import vmd, englishmap
21
22
23 EPSILON=1e-5
24 THRESHOLD=-0.85
25
26
27 def ToDegree(x):
28     return x/math.pi * 180.0
29
30
31 def clampDegree(d):
32     return d % 360
33
34
35 def multQuat(l, r):
36     q=mathutils.Quaternion()
37     q.w=l.w*r.w-(l.x*r.x+l.y*r.y+l.z*r.z)
38     q.x=l.w*r.x+r.w*l.x+l.y*r.z-l.z*r.y
39     q.y=l.w*r.y+r.w*l.y+l.z*r.x-l.x*r.z
40     q.z=l.w*r.z+r.w*l.z+l.x*r.y-l.y*r.x
41     return q
42
43
44 def import_motion_key(l, o):
45     print('import_motion_key: %s' % o.name)
46
47    
48     armature = o.data
49     pose = o.pose
50     not_in_map={}
51     not_found={}
52     counter=0
53     last_frame=0
54     for n in l.boneKeys:
55         keyFrames=l.getBoneKeyFrameList(n)
56         boneName=englishmap.getEnglishBoneName(n)
57         try:
58             bone=armature.bones[boneName]
59             # rot
60             armRotate=bone.matrix_local.rotation_part()
61             # quat
62             armRotateQuaternion=armRotate.to_quat()
63             #if armRotateQuaternion.w<0:
64             #    armRotateQuaternion.w=-armRotateQuaternion.w
65             #    armRotateQuaternion.x=-armRotateQuaternion.x
66             #    armRotateQuaternion.y=-armRotateQuaternion.y
67             #    armRotateQuaternion.z=-armRotateQuaternion.z
68
69             # inv
70             armRotateInv=mathutils.Matrix(armRotate).transpose()
71             # quat
72             armRotateInvQuaternion=armRotateInv.to_quat()
73             #if armRotateInvQuaternion.w<0:
74             #    armRotateInvQuaternion.w=-armRotateInvQuaternion.w
75             #    armRotateInvQuaternion.x=-armRotateInvQuaternion.x
76             #    armRotateInvQuaternion.y=-armRotateInvQuaternion.y
77             #    armRotateInvQuaternion.z=-armRotateInvQuaternion.z
78
79             reverseFlag=False
80             lastQ=None
81
82             poseBone=pose.bones[boneName]
83             for i in range(len(keyFrames.list)):
84                 key=keyFrames.getKey(i)
85                 ####################
86                 # rotation
87                 ####################
88                 if lastQ and lastQ.dot(key.q)<0:
89                     reverseFlag=not reverseFlag
90                 lastQ=key.q
91
92                 # convert left-handed y-up to right-handed z-up
93                 if reverseFlag:
94                     # reverse quaternion for slerp
95                     q=mathutils.Quaternion()
96                     q.w=-key.q.w
97                     q.x=key.q.x
98                     q.y=key.q.z
99                     q.z=key.q.y
100                 else:
101                     q=mathutils.Quaternion()
102                     q.w=key.q.w
103                     q.x=-key.q.x
104                     q.y=-key.q.z
105                     q.z=-key.q.y
106
107                 poseBone.rotation_quaternion=multQuat(
108                         armRotateInvQuaternion, 
109                         multQuat(q, armRotateQuaternion))
110
111                 ####################
112                 # location
113                 ####################
114                 poseBone.location = mathutils.Vector(
115                         (float(key.pos.x), float(key.pos.z), float(key.pos.y)))
116
117                 # insert
118                 poseBone.keyframe_insert(
119                         'location', -1, keyFrames.getFrame(i))
120                 poseBone.keyframe_insert(
121                         'rotation_quaternion', -1, keyFrames.getFrame(i))
122
123                 last_frame=max(last_frame, keyFrames.getFrame(i))
124                 counter+=1
125
126         except KeyError as msg:
127             not_found[boneName]=True
128             continue
129             
130     print("bone not exists")
131     for name in not_found.keys():
132         print(name)
133
134     return last_frame
135
136
137 def IPO_CURVE_get_or_create(ipo, name):
138     for c in ipo:
139         if c.name == name:
140             return c
141     return ipo.addCurve(name)
142
143
144 def import_shape_key(l, mesh):
145     print('import_shape_key: %s' % mesh.name)
146     return 0
147     # ToDo
148     key = mesh.getData().key
149     if key is None:
150         Draw.PupMenu('selecting mesh not has a Key')
151         return
152     # get or create IPO  
153     ipo = key.getIpo()
154     if ipo == None:
155         ipo = Blender.Ipo.New("Key", "ShapeKey")
156         key.ipo = ipo
157
158     # insert shape keys
159     counter=0
160     last_frame=0
161     for n in l.morphKeys:
162         keyFrames=l.getMorphKeyFrameList(n)
163         if n=='base':
164             continue
165         name=englishmap.getEnglishSkinName(n)
166         try:
167             curve=IPO_CURVE_get_or_create(ipo, name)
168         except NameError as msg:
169             print(NameError, msg)
170             print(n, name)
171             continue
172         curve.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
173         for i in xrange(len(keyFrames.list)):
174             key=keyFrames.getKey(i)
175             frame=keyFrames.getFrame(i)
176             curve[frame]=key.weight
177             last_frame=max(last_frame, frame)
178
179             counter+=1
180
181     return last_frame
182
183
184 def load(filename, context):
185     """
186     load vmd file to context.
187     """
188     io=vmd.IO()
189     if not io.read(filename):
190         print("fail to read", filename)
191         return
192
193     scene=context.scene
194
195     # import
196     last_frame=0
197     for o in scene.objects:
198         if o.selected:
199             if o.data.__class__ is bpy.types.Armature:
200                 last_frame=max(
201                         last_frame, import_motion_key(io, o))
202             elif o.data.__class__ is bpy.types.Mesh:
203                 last_frame=max(
204                         last_frame, import_shape_key(io, o))
205
206     # set end frame
207     scene.frame_end = last_frame
208     print("last frame: %d" % last_frame)
209
210     # redraw
211     scene.update()
212
213     print("finised")
214
215
216 ###############################################################################
217 # import operator
218 ###############################################################################
219 class IMPORT_OT_vmd(bpy.types.Operator):
220     bl_idname = "import_anim.vmd"
221     bl_label = 'Import VMD'
222
223     # List of operator properties, the attributes will be assigned
224     # to the class instance from the operator settings before calling.
225     path = StringProperty(
226             name="File Path", 
227             description="File path used for importing the VMD file", 
228             maxlen= 1024, default= "")
229     filename = StringProperty(
230             name="File Name", 
231             description="Name of the file.")
232     directory = StringProperty(
233             name="Directory", 
234             description="Directory of the file.")
235
236     def execute(self, context):
237         load(self.properties.path, context)
238         return {'FINISHED'}
239
240     def invoke(self, context, event):
241         wm = context.manager
242         wm.add_fileselect(self)
243         return {'RUNNING_MODAL'}
244
245
246 ###############################################################################
247 # register menu
248 ###############################################################################
249 def menu_func(self, context):
250     self.layout.operator(IMPORT_OT_vmd.bl_idname, 
251             text="MikuMikuDance motion (.vmd)")
252
253 def register():
254     bpy.types.register(IMPORT_OT_vmd)
255     bpy.types.INFO_MT_file_import.append(menu_func)
256
257 def unregister():
258     bpy.types.unregister(IMPORT_OT_vmd)
259     bpy.types.INFO_MT_file_import.remove(menu_func)
260
261
262 if __name__=="__main__":
263     register()
264