OSDN Git Service

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