OSDN Git Service

export toon textures.
[meshio/meshio.git] / swig / blender / pmd_import.py
1 #!BPY
2 # coding:utf-8
3 """
4  Name: 'MikuMikuDance model (.pmd)...'
5  Blender: 248
6  Group: 'Import'
7  Tooltip: 'Import PMD file for MikuMikuDance.'
8 """
9 __author__= ["ousttrue"]
10 __version__= "1.8"
11 __url__=()
12 __bpydoc__="""
13 pmd Importer
14
15 This script imports a pmd into Blender for editing.
16
17 0.1 20091126: first implement.
18 0.2 20091209: implement IK.
19 0.3 20091210: implement morph target.
20 0.4 20100305: use english name.
21 0.5 20100408: cleanup not used vertices.
22 0.6 20100416: fix fornt face. texture load fail safe. add progress.
23 0.7 20100506: C extension.
24 0.8 20100521: add shape_key group.
25 1.0 20100530: add invisilbe bone tail(armature layer 2).
26 1.1 20100608: integrate 2.4 and 2.5.
27 1.2 20100616: implement rigid body.
28 1.3 20100619: fix for various models.
29 1.4 20100623: fix constraint name.
30 1.5 20100626: refactoring.
31 1.6 20100629: sphere map.
32 1.7 20100703: implement bone group.
33 1.8 20100710: implement toon texture.
34 """
35
36 MMD_SHAPE_GROUP_NAME='_MMD_SHAPE'
37 BASE_SHAPE_NAME='Basis'
38 RIGID_SHAPE_TYPE='rigid_shape_type'
39 RIGID_PROCESS_TYPE='rigid_process_type'
40 RIGID_BONE_NAME='rigid_bone_name'
41 #RIGID_LOCATION='rigid_loation'
42 RIGID_GROUP='ribid_group'
43 RIGID_INTERSECTION_GROUP='rigid_intersection_group'
44 RIGID_WEIGHT='rigid_weight'
45 RIGID_LINEAR_DAMPING='rigid_linear_damping'
46 RIGID_ANGULAR_DAMPING='rigid_angular_damping'
47 RIGID_RESTITUTION='rigid_restitution'
48 RIGID_FRICTION='rigid_friction'
49 CONSTRAINT_NAME='constraint_name'
50 CONSTRAINT_A='const_a'
51 CONSTRAINT_B='const_b'
52 CONSTRAINT_POS_MIN='const_pos_min'
53 CONSTRAINT_POS_MAX='const_pos_max'
54 CONSTRAINT_ROT_MIN='const_rot_min'
55 CONSTRAINT_ROT_MAX='const_rot_max'
56 CONSTRAINT_SPRING_POS='const_spring_pos'
57 CONSTRAINT_SPRING_ROT='const_spring_rot'
58 TOON_TEXTURE_OBJECT='ToonTextures'
59
60
61 ###############################################################################
62 # import
63 ###############################################################################
64 import os
65 import sys
66 import math
67
68 # C extension
69 from meshio import pmd, englishmap
70
71 def isBlender24():
72     return sys.version_info[0]<3
73
74 if isBlender24():
75     # for 2.4
76     import Blender
77     from Blender import Mathutils
78     import bpy
79
80     # wrapper
81     import bl24 as bl
82
83     def createPmdMaterial(m, index):
84         material=Blender.Material.New()
85         # fresnelが無いw
86         material.setDiffuseShader(Blender.Material.Shaders.DIFFUSE_TOON)
87         material.setRGBCol([m.diffuse.r, m.diffuse.g, m.diffuse.b])
88         material.setAlpha(m.diffuse.a)
89         # specular
90         material.setSpecShader(Blender.Material.Shaders.SPEC_TOON)
91         material.setSpec(m.shinness*0.1)
92         material.setSpecCol([m.specular.r, m.specular.g, m.specular.b])
93         # ambient
94         material.setMirCol([m.ambient.r, m.ambient.g, m.ambient.b])
95         # flag
96         material.enableSSS=True if m.flag==1 else False
97         # name
98         material.name="m_%02d" % index
99         return material
100
101     def poseBoneLimit(n, b):
102         if n.endswith("_t"):
103             return
104         if n.startswith("knee_"):
105             b.lockYRot=True
106             b.lockZRot=True
107             b.limitX=True
108             b.limitMin=[0, 0, 0]
109             b.limitMax=[180, 0, 0]
110         elif n.startswith("ankle_"):
111             b.lockYRot=True
112
113     def setSphereMap(material, index, blend_type='MULTIPLY'):
114         slot=material.textures[index]
115         slot.mapto=Blender.Texture.MapTo.NOR
116         slot.mapping=Blender.Texture.Mappings.SPHERE
117         if blend_type=='MULTIPLY':
118             slot.blendmode=Blender.Texture.BlendModes.MULTIPLY
119         elif blend_type=='ADD':
120             slot.blendmode=Blender.Texture.BlendModes.ADD
121
122 else:
123     # for 2.5
124     import bpy
125     from bpy.props import *
126     import mathutils
127
128     # wrapper
129     import bl25 as bl
130
131     xrange=range
132
133     def createPmdMaterial(m, index):
134         material = bpy.data.materials.new("Material")
135         # diffuse
136         material.diffuse_shader='FRESNEL'
137         material.diffuse_color=([m.diffuse.r, m.diffuse.g, m.diffuse.b])
138         material.alpha=m.diffuse.a
139         # specular
140         material.specular_shader='TOON'
141         material.specular_color=([m.specular.r, m.specular.g, m.specular.b])
142         material.specular_toon_size=int(m.shinness)
143         # ambient
144         material.mirror_color=([m.ambient.r, m.ambient.g, m.ambient.b])
145         # flag
146         material.subsurface_scattering.enabled=True if m.flag==1 else False
147         # other
148         material.name="m_%02d" % index
149         material.preview_render_type='FLAT'
150         material.transparency=True
151         return material
152
153     def poseBoneLimit(n, b):
154         if n.endswith("_t"):
155             return
156         if n.startswith("knee_"):
157             b.ik_dof_y=False
158             b.ik_dof_z=False
159             b.ik_dof_x=True
160             b.ik_limit_x=True
161             b.ik_min_x=0
162             b.ik_max_x=180
163         elif n.startswith("ankle_"):
164             #b.ik_dof_y=False
165             pass
166
167     def setSphereMap(material, index, blend_type='MULTIPLY'):
168         slot=material.texture_slots[index]
169         slot.texture_coordinates='NORMAL'
170         slot.mapping='SPHERE'
171         slot.blend_type=blend_type
172
173
174 ###############################################################################
175 def VtoV(v):
176     return bl.createVector(v.x, v.y, v.z)
177
178
179 def convert_coord(pos):
180     """
181     Left handed y-up to Right handed z-up
182     """
183     return (pos.x, pos.z, pos.y)
184
185
186 def to_radian(degree):
187     return math.pi * degree / 180
188
189
190 def get_bone_name(l, index):
191     if index==0xFFFF:
192         return l.bones[0].getName()
193
194     if index < len(l.bones):
195         name=englishmap.getEnglishBoneName(l.bones[index].getName())
196         if name:
197             return name
198         return l.bones[index].getName()
199     print('invalid bone index', index)
200     return l.bones[0].getName()
201
202
203 def get_group_name(g):
204     group_name=englishmap.getEnglishBoneGroupName(g.getName().strip())
205     if not group_name:
206         group_name=g.getName().strip()
207     return group_name
208
209
210 def __importToonTextures(io, tex_dir):
211     mesh, meshObject=bl.mesh.create(TOON_TEXTURE_OBJECT)
212     material=bl.material.create(TOON_TEXTURE_OBJECT)
213     bl.mesh.addMaterial(mesh, material)
214     for i in range(10):
215         t=io.getToonTexture(i)
216         path=os.path.join(tex_dir, t.getName())
217         texture, image=bl.texture.create(path)
218         bl.material.addTexture(material, texture, False)
219     return meshObject, material
220
221
222 def __importShape(obj, l, vertex_map):
223     if len(l.morph_list)==0:
224         return
225
226     # set shape_key pin
227     bl.object.pinShape(obj, True)
228
229     # find base 
230     base=None
231     for s in l.morph_list:
232         if s.type==0:
233             base=s
234
235             # create vertex group
236             bl.object.addVertexGroup(obj, MMD_SHAPE_GROUP_NAME)
237             hasShape=False
238             for i in s.indices:
239                 if i in vertex_map:
240                     hasShape=True
241                     bl.object.assignVertexGroup(
242                             obj, MMD_SHAPE_GROUP_NAME, vertex_map[i], 0)
243             if not hasShape:
244                 return
245     assert(base)
246
247     # create base key
248     baseShapeBlock=bl.object.addShapeKey(obj, BASE_SHAPE_NAME)
249     # mesh
250     mesh=bl.object.getData(obj)
251     mesh.update()
252
253     # each skin
254     for s in l.morph_list:
255         if s.type==0:
256             continue
257
258         # name
259         name=englishmap.getEnglishSkinName(s.getName())
260         if not name:
261             name=s.getName()
262
263         if isBlender24():
264             # 24
265             for index, offset in zip(s.indices, s.pos_list):
266                 try:
267                     vertex_index=vertex_map[base.indices[index]]
268                     v=mesh.verts[vertex_index].co
269                     offset=convert_coord(offset)
270                     v[0]+=offset[0]
271                     v[1]+=offset[1]
272                     v[2]+=offset[2]
273                 except IndexError as msg:
274                     print(msg)
275                     print(index, len(base.indices), len(vertex_map))
276                     print(len(mesh.verts))
277                     print(base.indices[index])
278                     print(vertex_index)
279                     break
280                 except KeyError:
281                     #print 'this mesh not has shape vertices'
282                     break
283
284             # create shapekey block
285             new_shape_key=bl.object.addShapeKey(obj, name)
286
287             # copy vertex to shape key
288             mesh.update()
289             
290             # restore
291             for mv, v in zip(mesh.verts, baseShapeBlock.getData()):
292                 mv.co[0] = v[0]
293                 mv.co[1] = v[1]
294                 mv.co[2] = v[2]
295             mesh.update()
296
297         else:
298             # 25
299             new_shape_key=bl.object.addShapeKey(obj, name)
300
301             for index, offset in zip(s.indices, s.pos_list):
302                 try:
303                     vertex_index=vertex_map[base.indices[index]]
304                     bl.shapekey.assign(new_shape_key, vertex_index,
305                             mesh.verts[vertex_index].co+
306                             bl.createVector(*convert_coord(offset)))
307                 except IndexError as msg:
308                     print(msg)
309                     print(index, len(base.indices), len(vertex_map))
310                     print(len(mesh.verts))
311                     print(base.indices[index])
312                     print(vertex_index)
313                     break
314                 except KeyError:
315                     #print 'this mesh not has shape vertices'
316                     break
317
318     # select base shape
319     bl.object.setActivateShapeKey(obj, 0)
320
321
322 def __build(armature, b, p, parent):
323     name=englishmap.getEnglishBoneName(b.getName())
324     if not name:
325         name=b.getName()
326
327     bone=bl.armature.createBone(armature, name)
328
329     if parent and (b.tail_index==0 or b.type==6 or b.type==7 or b.type==9):
330         bone.head = bl.createVector(*convert_coord(b.pos))
331         bone.tail=bone.head+bl.createVector(0, 1, 0)
332         bone.parent=parent
333         if bone.name=="center_t":
334             # センターボーンは(0, 1, 0)の方向を向いていないと具合が悪い
335             parent.tail=parent.head+bl.createVector(0, 1, 0)
336             bone.head=parent.tail
337             bone.tail=bone.head+bl.createVector(0, 1, 0)
338         else:
339             if parent.tail==bone.head:
340                 pass
341             else:
342                 print('diffurence with parent.tail and head', name)
343
344         if b.type!=9:
345             bl.bone.setConnected(bone)
346         # armature layer 2
347         bl.bone.setLayerMask(bone, [0, 1])
348     else:
349         # 通常ボーン
350         bone.head = bl.createVector(*convert_coord(b.pos))
351         bone.tail = bl.createVector(*convert_coord(b.tail))
352         if parent:
353             bone.parent=parent
354             if parent.tail==bone.head:
355                 bl.bone.setConnected(bone)
356
357     if bone.head==bone.tail:
358         bone.tail=bone.head+bl.createVector(0, 1, 0)
359
360     for c in b.children:
361         __build(armature, c, b, bone)
362
363
364 def __importArmature(l):
365     armature, armature_object=bl.armature.create()
366
367     # build bone
368     bl.armature.makeEditable(armature_object)
369     for b in l.bones:
370         if not b.parent:
371             __build(armature, b, None, None)
372     bl.armature.update(armature)
373     bl.enterObjectMode()
374
375     # IK constraint
376     pose = bl.object.getPose(armature_object)
377     for ik in l.ik_list:
378         target=l.bones[ik.target]
379         name = englishmap.getEnglishBoneName(target.getName())
380         if not name:
381             name=target.getName()
382         p_bone = pose.bones[name]
383         if not p_bone:
384             print('not found', name)
385             continue
386         if len(ik.children) >= 16:
387             print('over MAX_CHAINLEN', ik, len(ik.children))
388             continue
389         effector_name=englishmap.getEnglishBoneName(
390                 l.bones[ik.index].getName())
391         if not effector_name:
392             effector_name=l.bones[ik.index].getName()
393
394         constraint=bl.armature.createIkConstraint(armature_object, 
395                 p_bone, effector_name, ik)
396
397     bl.armature.makeEditable(armature_object)
398     bl.armature.update(armature)
399     bl.enterObjectMode()
400
401     if isBlender24():
402         pass
403     else:
404         # create bone group
405         for i, g in enumerate(l.bone_group_list):
406             name=get_group_name(g)
407             bl.object.createBoneGroup(armature_object, name, "THEME%02d" % (i+1))
408
409         # assign bone to group
410         for b_index, g_index in l.bone_display_list:
411             # bone
412             b=l.bones[b_index]
413             bone_name=englishmap.getEnglishBoneName(b.getName())
414             if not bone_name:
415                 bone_name=b.getName()
416             # group
417             g=l.bone_group_list[g_index-1]
418             group_name=get_group_name(g)
419
420             # assign
421             pose.bones[bone_name].bone_group=pose.bone_groups[group_name]
422
423         bl.enterObjectMode()
424
425     return armature_object
426         
427
428 def __import16MaerialAndMesh(meshObject, l, 
429         material_order, face_map, tex_dir, toon_material):
430
431     mesh=bl.object.getData(meshObject)
432     ############################################################
433     # material
434     ############################################################
435     bl.progress_print('create materials')
436     mesh_material_map={}
437     textureMap={}
438     imageMap={}
439     index=0
440
441     for material_index in material_order:
442         try:
443             m=l.materials[material_index]
444             mesh_material_map[material_index]=index
445         except KeyError:
446             break
447
448         material=createPmdMaterial(m, material_index)
449         toon_index=bl.material.addTexture(
450                 material, 
451                 bl.material.getTexture(
452                     toon_material, 
453                     0 if m.toon_index==0xFF else m.toon_index
454                     ),
455                 False)
456
457         texture_name=m.getTexture()
458         if texture_name!='':
459             for i, t in enumerate(texture_name.split('*')):
460                 if t in textureMap:
461                     texture=textureMap[t]
462                 else:
463                     path=os.path.join(tex_dir, t)
464                     texture, image=bl.texture.create(path)
465                     textureMap[texture_name]=texture
466                     imageMap[material_index]=image
467                 texture_index=bl.material.addTexture(material, texture)
468                 if t.endswith('sph'):
469                     # sphere map
470                     setSphereMap(material, texture_index)
471                 elif t.endswith('spa'):
472                     # sphere map
473                     setSphereMap(material, texture_index, 'ADD')
474
475         bl.mesh.addMaterial(mesh, material)
476         index+=1
477
478     ############################################################
479     # vertex
480     ############################################################
481     bl.progress_print('create vertices')
482     # create vertices
483     vertices=[]
484     for v in l.each_vertex():
485         vertices.append(convert_coord(v.pos))
486
487     ############################################################
488     # face
489     ############################################################
490     bl.progress_print('create faces')
491     # create faces
492     mesh_face_indices=[]
493     mesh_face_materials=[]
494     used_vertices=set()
495
496     for material_index in material_order:
497         face_offset=face_map[material_index]
498         m=l.materials[material_index]
499         material_faces=l.indices[face_offset:face_offset+m.vertex_count]
500
501         def degenerate(i0, i1, i2):
502             """
503             縮退しているか?
504             """
505             return i0==i1 or i1==i2 or i2==i0
506
507         for j in xrange(0, len(material_faces), 3):
508             i0=material_faces[j]
509             i1=material_faces[j+1]
510             i2=material_faces[j+2]
511             # flip
512             triangle=[i2, i1, i0]
513             if degenerate(*triangle):
514                 continue
515             mesh_face_indices.append(triangle[0:3])
516             mesh_face_materials.append(material_index)
517             used_vertices.add(i0)
518             used_vertices.add(i1)
519             used_vertices.add(i2)
520
521     ############################################################
522     # create vertices & faces
523     ############################################################
524     bl.mesh.addGeometry(mesh, vertices, mesh_face_indices)
525
526     ############################################################
527     # vertex bone weight
528     ############################################################
529     # create vertex group
530     vertex_groups={}
531     for v in l.each_vertex():
532         vertex_groups[v.bone0]=True
533         vertex_groups[v.bone1]=True
534     for i in vertex_groups.keys():
535         bl.object.addVertexGroup(meshObject, get_bone_name(l, i))
536
537     # vertex params
538     bl.mesh.useVertexUV(mesh)
539     for i, v, mvert in zip(xrange(len(l.vertices)), 
540         l.each_vertex(), mesh.verts):
541         # normal, uv
542         bl.vertex.setNormal(mvert, convert_coord(v.normal))
543         # bone weight
544         w1=float(v.weight0)/100.0
545         w2=1.0-w1
546         bl.object.assignVertexGroup(meshObject, get_bone_name(l, v.bone0),
547             i,  w1)
548         bl.object.assignVertexGroup(meshObject, get_bone_name(l, v.bone1),
549             i,  w2)
550
551     ############################################################
552     # face params
553     ############################################################
554     used_map={}
555     bl.mesh.addUV(mesh)
556     for i, (face, material_index) in enumerate(
557             zip(mesh.faces, mesh_face_materials)):
558         try:
559             index=mesh_material_map[material_index]
560         except KeyError as message:
561             print(message, mesh_material_map, m)
562             assert(False)
563         bl.face.setMaterial(face, index)
564         material=mesh.materials[index]
565         used_map[index]=True
566         if bl.material.hasTexture(material):
567             uv_array=[l.getUV(i) for i in bl.face.getIndices(face)]
568             bl.mesh.setFaceUV(mesh, i, face, 
569                     # fix uv
570                     [(uv.x, 1.0-uv.y) for uv in uv_array], 
571                     imageMap.get(index, None))
572
573         # set smooth
574         face.smooth = 1
575
576     mesh.update()
577
578     ############################################################
579     # clean up not used vertices
580     ############################################################
581     bl.progress_print('clean up vertices not used')
582     remove_vertices=[]
583     vertex_map={}
584     for i, v in enumerate(l.each_vertex()):
585         if i in used_vertices:
586             vertex_map[i]=len(vertex_map)
587         else:
588             remove_vertices.append(i)
589
590     bl.mesh.vertsDelete(mesh, remove_vertices)
591
592     bl.progress_print('%s created' % mesh.name)
593     return vertex_map
594
595
596 def __importMaterialAndMesh(io, tex_dir, toon_material):
597     """
598     @param l[in] mmd.PMDLoader
599     @param filename[in]
600     """
601     ############################################################
602     # shpaeキーで使われるマテリアル優先的に前に並べる
603     ############################################################
604     # shapeキーで使われる頂点インデックスを集める
605     shape_key_used_vertices=set()
606     if len(io.morph_list)>0:
607         # base 
608         base=None
609         for s in io.morph_list:
610             if s.type!=0:
611                 continue
612             base=s
613             break
614         assert(base)
615
616         for index in base.indices:
617             shape_key_used_vertices.add(index)
618
619     # マテリアルに含まれる頂点がshape_keyに含まれるか否か?
620     def isMaterialUsedInShape(offset, m):
621         for i in xrange(offset, offset+m.vertex_count): 
622             if io.indices[i] in shape_key_used_vertices:
623                 return True
624
625     material_with_shape=set()
626
627     # 各マテリアルの開始頂点インデックスを記録する
628     face_map={}
629     face_count=0
630     for i, m in enumerate(io.materials):
631         face_map[i]=face_count
632         if isMaterialUsedInShape(face_count, m):
633             material_with_shape.add(i)
634         face_count+=m.vertex_count
635
636     # shapeキーで使われる頂点のあるマテリアル
637     material_with_shape=list(material_with_shape)
638     material_with_shape.sort()
639
640     # shapeキーに使われていないマテリアル
641     material_without_shape=[]
642     for i in range(len(io.materials)):
643         if not i in material_with_shape:
644             material_without_shape.append(i)
645
646     # メッシュの生成
647     def __splitList(l, length):
648         for i in range(0, len(l), length):
649             yield l[i:i+length]
650
651     def __importMeshAndShape(material16, name):
652         mesh, meshObject=bl.mesh.create(name)
653
654         # activate object
655         bl.object.deselectAll()
656         bl.object.activate(meshObject)
657
658         # shapeキーで使われる順に並べなおしたマテリアル16個分の
659         # メッシュを作成する
660         vertex_map=__import16MaerialAndMesh(
661                 meshObject, io, material16, face_map, tex_dir, toon_material)
662
663         # crete shape key
664         __importShape(meshObject, io, vertex_map)
665
666         mesh.update()
667         return meshObject
668
669     mesh_objects=[__importMeshAndShape(material16, 'with_shape')
670         for material16 in __splitList(material_with_shape, 16)]
671     
672     mesh_objects+=[__importMeshAndShape(material16, 'mesh')
673         for material16 in __splitList(material_without_shape, 16)]
674  
675     return mesh_objects
676
677
678 def __importConstraints(io):
679     if isBlender24():
680         return
681     print("create constraint")
682     container=bl.object.createEmpty('Constraints')
683     layer=[
684             True, False, False, False, False, False, False, False,
685             False, False, False, False, False, False, False, False,
686             False, False, False, False, False, False, False, False,
687             False, False, False, False, False, False, False, False,
688             ]
689     material=bl.material.create('constraint')
690     material.diffuse_color=(1, 0, 0)
691     constraintMeshes=[]
692     for i, c in enumerate(io.constraints):
693         bpy.ops.mesh.primitive_uv_sphere_add(
694                 segments=8,
695                 rings=4,
696                 size=0.1,
697                 location=(c.pos.x, c.pos.z, c.pos.y),
698                 layer=layer
699                 )
700         meshObject=bl.object.getActive()
701         constraintMeshes.append(meshObject)
702         mesh=bl.object.getData(meshObject)
703         bl.mesh.addMaterial(mesh, material)
704         meshObject.name='c_%d' % i
705         #meshObject.draw_transparent=True
706         #meshObject.draw_wire=True
707         meshObject.max_draw_type='SOLID'
708         rot=c.rot
709         meshObject.rotation_euler=(-rot.x, -rot.z, -rot.y)
710
711         meshObject[CONSTRAINT_NAME]=c.getName()
712         meshObject[CONSTRAINT_A]=io.rigidbodies[c.rigidA].getName()
713         meshObject[CONSTRAINT_B]=io.rigidbodies[c.rigidB].getName()
714         meshObject[CONSTRAINT_POS_MIN]=VtoV(c.constraintPosMin)
715         meshObject[CONSTRAINT_POS_MAX]=VtoV(c.constraintPosMax)
716         meshObject[CONSTRAINT_ROT_MIN]=VtoV(c.constraintRotMin)
717         meshObject[CONSTRAINT_ROT_MAX]=VtoV(c.constraintRotMax)
718         meshObject[CONSTRAINT_SPRING_POS]=VtoV(c.springPos)
719         meshObject[CONSTRAINT_SPRING_ROT]=VtoV(c.springRot)
720
721     for meshObject in reversed(constraintMeshes):
722         bl.object.makeParent(container, meshObject)
723
724     return container
725
726
727 def __importRigidBodies(io):
728     if isBlender24():
729         return
730     print("create rigid bodies")
731
732     container=bl.object.createEmpty('RigidBodies')
733     layer=[
734             True, False, False, False, False, False, False, False,
735             False, False, False, False, False, False, False, False,
736             False, False, False, False, False, False, False, False,
737             False, False, False, False, False, False, False, False,
738             ]
739     material=bl.material.create('rigidBody')
740     rigidMeshes=[]
741     for rigid in io.rigidbodies:
742         if rigid.boneIndex==0xFFFF:
743             # no reference bone
744             bone=io.bones[0]
745         else:
746             bone=io.bones[rigid.boneIndex]
747         pos=bone.pos+rigid.position
748
749         if rigid.shapeType==pmd.SHAPE_SPHERE:
750             bpy.ops.mesh.primitive_ico_sphere_add(
751                     location=(pos.x, pos.z, pos.y),
752                     layer=layer
753                     )
754             bpy.ops.transform.resize(
755                     value=(rigid.w, rigid.w, rigid.w))
756         elif rigid.shapeType==pmd.SHAPE_BOX:
757             bpy.ops.mesh.primitive_cube_add(
758                     location=(pos.x, pos.z, pos.y),
759                     layer=layer
760                     )
761             bpy.ops.transform.resize(
762                     value=(rigid.w, rigid.d, rigid.h))
763         elif rigid.shapeType==pmd.SHAPE_CAPSULE:
764             bpy.ops.mesh.primitive_tube_add(
765                     location=(pos.x, pos.z, pos.y),
766                     layer=layer
767                     )
768             bpy.ops.transform.resize(
769                     value=(rigid.w, rigid.w, rigid.h))
770         else:
771             assert(False)
772
773         meshObject=bl.object.getActive()
774         mesh=bl.object.getData(meshObject)
775         rigidMeshes.append(meshObject)
776         bl.mesh.addMaterial(mesh, material)
777         meshObject.name=rigid.getName()
778         #meshObject.draw_transparent=True
779         #meshObject.draw_wire=True
780         meshObject.max_draw_type='WIRE'
781         rot=rigid.rotation
782         meshObject.rotation_euler=(-rot.x, -rot.z, -rot.y)
783
784         # custom properties
785         meshObject[RIGID_SHAPE_TYPE]=rigid.shapeType
786         meshObject[RIGID_PROCESS_TYPE]=rigid.processType
787
788         bone_name = englishmap.getEnglishBoneName(bone.getName())
789         if not bone_name:
790             bone_name=bone.getName()
791         meshObject[RIGID_BONE_NAME]=bone_name
792
793         meshObject[RIGID_GROUP]=rigid.group
794         meshObject[RIGID_INTERSECTION_GROUP]=rigid.target
795         meshObject[RIGID_WEIGHT]=rigid.weight
796         meshObject[RIGID_LINEAR_DAMPING]=rigid.linearDamping
797         meshObject[RIGID_ANGULAR_DAMPING]=rigid.angularDamping
798         meshObject[RIGID_RESTITUTION]=rigid.restitution
799         meshObject[RIGID_FRICTION]=rigid.friction
800
801     for meshObject in reversed(rigidMeshes):
802         bl.object.makeParent(container, meshObject)
803
804     return container
805
806
807 def _execute(filename):
808     """
809     load pmd file to context.
810     """
811            
812     # load pmd
813     bl.progress_set('load %s' % filename, 0.0)
814
815     io=pmd.IO()
816     if not io.read(filename):
817         bl.message("fail to load %s" % filename)
818         return
819     bl.progress_set('loaded %s' % filename, 0.1)
820
821     # create root object
822     model_name=io.getEnglishName()
823     if len(model_name)==0:
824         model_name=io.getName()
825     root=bl.object.createEmpty(model_name)
826
827     # toon textures
828     tex_dir=os.path.dirname(filename)
829     toonTextures, toonMaterial=__importToonTextures(io, tex_dir)
830     bl.object.makeParent(root, toonTextures)
831
832     # import mesh
833     mesh_objects=__importMaterialAndMesh(io, tex_dir, toonMaterial)
834     for o in mesh_objects:
835         bl.object.makeParent(root, o)
836
837     # import armature
838     armature_object=__importArmature(io)
839     if armature_object:
840         bl.object.makeParent(root, armature_object)
841         armature = bl.object.getData(armature_object) 
842
843         # add armature modifier
844         for o in mesh_objects:
845             bl.modifier.addArmature(o, armature_object)
846
847         # Limitation
848         for n, b in bl.object.getPose(armature_object).bones.items():
849             poseBoneLimit(n, b)
850
851     # import rigid bodies
852     rigidBodies=__importRigidBodies(io)
853     if rigidBodies:
854         bl.object.makeParent(root, rigidBodies)
855
856     # import constraints
857     constraints=__importConstraints(io)
858     if constraints:
859         bl.object.makeParent(root, constraints)
860
861     bl.object.activate(root)
862
863
864 if isBlender24():
865     # for 2.4
866     def execute_24(filename):
867         bl.initialize('pmd_import', bpy.data.scenes.active)
868         _execute(filename.decode(bl.INTERNAL_ENCODING))
869         bl.finalize()
870
871     Blender.Window.FileSelector(
872             execute_24, 
873             'Import PMD file', 
874             Blender.sys.makename(ext='.pmd'))
875
876 else:
877     # import operator
878     class IMPORT_OT_pmd(bpy.types.Operator):
879         bl_idname = "import_scene.pmd"
880         bl_label = 'Import PMD'
881
882         # List of operator properties, the attributes will be assigned
883         # to the class instance from the operator settings before calling.
884
885         path = StringProperty(
886                 name="File Path", 
887                 description="File path used for importing the PMD file", 
888                 maxlen= 1024, default= "")
889         filename = StringProperty(
890                 name="File Name", 
891                 description="Name of the file.")
892         directory = StringProperty(
893                 name="Directory", 
894                 description="Directory of the file.")
895
896         def execute(self, context):
897             bl.initialize('pmd_import', context.scene)
898             _execute(self.properties.path)
899             bl.finalize()
900             return 'FINISHED'
901
902         def invoke(self, context, event):
903             wm = context.manager
904             wm.add_fileselect(self)
905             return 'RUNNING_MODAL'
906
907     # register menu
908     def menu_func(self, context): 
909         self.layout.operator(IMPORT_OT_pmd.bl_idname, 
910                 text="MikuMikuDance model (.pmd)")
911
912     def register():
913         bpy.types.register(IMPORT_OT_pmd)
914         bpy.types.INFO_MT_file_import.append(menu_func)
915
916     def unregister():
917         bpy.types.unregister(IMPORT_OT_pmd)
918         bpy.types.INFO_MT_file_import.remove(menu_func)
919
920     if __name__=="__main__":
921         register()
922