Tooltip: 'Import PMD file for MikuMikuDance.'
"""
__author__= ["ousttrue"]
-__version__= "1.1"
+__version__= "1.2"
__url__=()
__bpydoc__="""
pmd Importer
0.8: 20100521: add shape_key group.
1.0: 20100530: add invisilbe bone tail(armature layer 2).
1.1: 20100608: integrate 2.4 and 2.5.
+1.2: 20100616: implement rigid body.
"""
MMD_SHAPE_GROUP_NAME='_MMD_SHAPE'
BASE_SHAPE_NAME='Basis'
+RIGID_SHAPE_TYPE='rigid_shape_type'
+RIGID_PROCESS_TYPE='rigid_process_type'
+RIGID_BONE_NAME='rigid_bone_name'
+#RIGID_LOCATION='rigid_loation'
+RIGID_GROUP='ribid_group'
+RIGID_INTERSECTION_GROUP='rigid_intersection_group'
+RIGID_WEIGHT='rigid_weight'
+RIGID_LINEAR_DAMPING='rigid_linear_damping'
+RIGID_ANGULAR_DAMPING='rigid_angular_damping'
+RIGID_RESTITUTION='rigid_restitution'
+RIGID_FRICTION='rigid_friction'
+CONSTRAINT_A='const_a'
+CONSTRAINT_B='const_b'
+CONSTRAINT_POS_MIN='const_pos_min'
+CONSTRAINT_POS_MAX='const_pos_max'
+CONSTRAINT_ROT_MIN='const_rot_min'
+CONSTRAINT_ROT_MAX='const_rot_max'
+CONSTRAINT_SPRING_POS='const_spring_pos'
+CONSTRAINT_SPRING_ROT='const_spring_rot'
###############################################################################
###############################################################################
import os
import sys
-import re
import math
# C extension
xrange=range
###############################################################################
-# progress bar
-###############################################################################
-def progress_start(base):
- global progressBar
- progressBar=bl.ProgressBar(base)
-
-def progress_finish():
- global progressBar
- progressBar.finish()
-
-def progress_print(message, progress=0.05):
- global progressBar
- progressBar.advance(message, progress)
-
-def progress_set(message, progress):
- global progressBar
- progressBar.set(message, progress)
-
-
-###############################################################################
def convert_coord(pos):
"""
Left handed y-up to Right handed z-up
for index, offset in zip(s.indices, s.pos_list):
try:
- vertex_index=base.indices[index]
+ vertex_index=vertex_map[base.indices[index]]
bl.shapeKeyAssign(new_shape_key, vertex_index,
mesh.verts[vertex_index].co+
bl.createVector(*convert_coord(offset)))
def __build(armature, b, p, parent):
name=englishmap.getEnglishBoneName(b.getName())
if not name:
- name=b.getName().encode(bl.INTERNAL_ENCODING)
+ name=b.getName()
bone=bl.createArmatureBone(armature, name)
if b.tail_index==0:
- # 先端
- assert(b.type==6 or b.type==7)
+ # 先端ボーン
+ assert(b.type==6 or b.type==7 or b.type==9)
bone.head = bl.createVector(*convert_coord(b.pos))
bone.tail=bone.head+bl.createVector(0, 1, 0)
assert(parent)
# armature layer 2
bl.boneLayerMask(bone, [0, 1])
else:
+ # 通常ボーン
bone.head = bl.createVector(*convert_coord(b.pos))
bone.tail = bl.createVector(*convert_coord(b.tail))
if parent:
for ik in l.ik_list:
target=l.bones[ik.target]
name = englishmap.getEnglishBoneName(target.getName())
+ if not name:
+ name=target.getName()
p_bone = pose.bones[name]
if not p_bone:
print('not found', name)
############################################################
# material
############################################################
- progress_print('create materials')
+ bl.progress_print('create materials')
mesh_material_map={}
textureMap={}
imageMap={}
material=bl.createPmdMaterial(m)
texture_name=m.getTexture()
- #tex_file=re.compile('\*.*.spa$').sub('', m.getTexture())
- #tex_path = os.path.join(tex_dir, tex_file).encode(
- # bl.INTERNAL_ENCODING)
if texture_name!='':
if texture_name in textureMap:
texture=textureMap[texture_name]
############################################################
# vertex
############################################################
- progress_print('create vertices')
+ bl.progress_print('create vertices')
# create vertices
vertices=[]
if isBlender24():
############################################################
# face
############################################################
- progress_print('create faces')
+ bl.progress_print('create faces')
# create faces
mesh_face_indices=[]
mesh_face_materials=[]
############################################################
# clean up not used vertices
############################################################
- progress_print('clean up vertices not used')
+ bl.progress_print('clean up vertices not used')
remove_vertices=[]
vertex_map={}
for i, v in enumerate(l.each_vertex()):
bl.meshVertsDelete(mesh, remove_vertices)
- progress_print('%s created' % mesh.name)
+ bl.progress_print('%s created' % mesh.name)
return vertex_map
face_map, tex_dir)
# enter Edit Mode
- bl.enterEditMode()
+ #bl.enterEditMode()
# crete shape key
__importShape(meshObject, io, vertex_map)
# exit Edit Mode
- bl.exitEditMode()
+ #bl.exitEditMode()
mesh.update()
material_offset+=16
return mesh_objects
+def __importConstraints(scene, io):
+ if isBlender24():
+ return
+ print("create constrains")
+ container=bl.createEmptyObject(scene, 'Constraints')
+ layer=[
+ True, False, False, False, False, False, False, False,
+ False, False, False, False, False, False, False, False,
+ False, False, False, False, False, False, False, False,
+ False, False, False, False, False, False, False, False,
+ ]
+ material=bl.createMaterial('constraint')
+ material.diffuse_color=(1, 0, 0)
+ constraintMeshes=[]
+ for c in io.constraints:
+ bpy.ops.mesh.primitive_uv_sphere_add(
+ segments=8,
+ rings=4,
+ size=0.1,
+ location=(c.pos.x, c.pos.z, c.pos.y),
+ layer=layer
+ )
+ meshObject=scene.objects.active
+ constraintMeshes.append(meshObject)
+ mesh=bl.objectGetData(meshObject)
+ bl.meshAddMaterial(mesh, material)
+ meshObject.name='c'+c.getName()
+ #meshObject.draw_transparent=True
+ #meshObject.draw_wire=True
+ meshObject.max_draw_type='SOLID'
+ rot=c.rot
+ meshObject.rotation_euler=(-rot.x, -rot.z, -rot.y)
+
+ meshObject[CONSTRAINT_A]=io.rigidbodies[c.rigidA].getName()
+ meshObject[CONSTRAINT_B]=io.rigidbodies[c.rigidB].getName()
+ meshObject[CONSTRAINT_POS_MIN]=bl.VtoV(c.constraintPosMin)
+ meshObject[CONSTRAINT_POS_MAX]=bl.VtoV(c.constraintPosMax)
+ meshObject[CONSTRAINT_ROT_MIN]=bl.VtoV(c.constraintRotMin)
+ meshObject[CONSTRAINT_ROT_MAX]=bl.VtoV(c.constraintRotMax)
+ meshObject[CONSTRAINT_SPRING_POS]=bl.VtoV(c.springPos)
+ meshObject[CONSTRAINT_SPRING_ROT]=bl.VtoV(c.springRot)
+
+ for meshObject in reversed(constraintMeshes):
+ bl.objectMakeParent(container, meshObject)
+
+ return container
+
+
+def __importRigidBodies(scene, io):
+ if isBlender24():
+ return
+ print("create rigid bodies")
+
+ container=bl.createEmptyObject(scene, 'RigidBodies')
+ layer=[
+ True, False, False, False, False, False, False, False,
+ False, False, False, False, False, False, False, False,
+ False, False, False, False, False, False, False, False,
+ False, False, False, False, False, False, False, False,
+ ]
+ material=bl.createMaterial('rigidBody')
+ rigidMeshes=[]
+ for rigid in io.rigidbodies:
+ if rigid.boneIndex==0xFFFF:
+ # no reference bone
+ bone=io.bones[0]
+ else:
+ bone=io.bones[rigid.boneIndex]
+ pos=bone.pos+rigid.position
+
+ if rigid.shapeType==pmd.SHAPE_SPHERE:
+ bpy.ops.mesh.primitive_ico_sphere_add(
+ location=(pos.x, pos.z, pos.y),
+ layer=layer
+ )
+ bpy.ops.transform.resize(
+ value=(rigid.w, rigid.w, rigid.w))
+ elif rigid.shapeType==pmd.SHAPE_BOX:
+ bpy.ops.mesh.primitive_cube_add(
+ location=(pos.x, pos.z, pos.y),
+ layer=layer
+ )
+ bpy.ops.transform.resize(
+ value=(rigid.w, rigid.d, rigid.h))
+ elif rigid.shapeType==pmd.SHAPE_CAPSULE:
+ bpy.ops.mesh.primitive_tube_add(
+ location=(pos.x, pos.z, pos.y),
+ layer=layer
+ )
+ bpy.ops.transform.resize(
+ value=(rigid.w, rigid.w, rigid.h))
+ else:
+ assert(False)
+
+ meshObject=scene.objects.active
+ mesh=bl.objectGetData(meshObject)
+ rigidMeshes.append(meshObject)
+ bl.meshAddMaterial(mesh, material)
+ meshObject.name=rigid.getName()
+ #meshObject.draw_transparent=True
+ #meshObject.draw_wire=True
+ meshObject.max_draw_type='WIRE'
+ rot=rigid.rotation
+ meshObject.rotation_euler=(-rot.x, -rot.z, -rot.y)
+
+ # custom properties
+ meshObject[RIGID_SHAPE_TYPE]=rigid.shapeType
+ meshObject[RIGID_PROCESS_TYPE]=rigid.processType
+
+ bone_name = englishmap.getEnglishBoneName(bone.getName())
+ if not bone_name:
+ bone_name=bone.getName()
+ meshObject[RIGID_BONE_NAME]=bone_name
+
+ #meshObject[RIGID_LOCATION]=bl.VtoV(rigid.location)
+ meshObject[RIGID_GROUP]=rigid.group
+ meshObject[RIGID_INTERSECTION_GROUP]=rigid.target
+ meshObject[RIGID_WEIGHT]=rigid.weight
+ meshObject[RIGID_LINEAR_DAMPING]=rigid.linearDamping
+ meshObject[RIGID_ANGULAR_DAMPING]=rigid.angularDamping
+ meshObject[RIGID_RESTITUTION]=rigid.restitution
+ meshObject[RIGID_FRICTION]=rigid.friction
+
+ for meshObject in reversed(rigidMeshes):
+ bl.objectMakeParent(container, meshObject)
+
+ return container
+
+
def __execute(filename, scene):
"""
load pmd file to context.
"""
+ bl.progress_start('pmd_import')
+
# load pmd
- progress_set('load %s' % filename, 0.0)
+ bl.progress_set('load %s' % filename, 0.0)
io=pmd.IO()
if not io.read(filename):
print("fail to load %s" % filename)
return
- progress_set('loaded %s' % filename, 0.1)
+ bl.progress_set('loaded %s' % filename, 0.1)
# create root object
- root=bl.createEmptyObject(scene,
- io.english_name if len(io.english_name)>0 else io.getName().encode(bl.INTERNAL_ENCODING))
+ model_name=io.getEnglishName()
+ if len(model_name)==0:
+ model_name=io.getName()
+ root=bl.createEmptyObject(scene, model_name)
# import mesh
mesh_objects=__importMesh(scene, io, os.path.dirname(filename))
for n, b in bl.objectGetPose(armature_object).bones.items():
bl.poseBoneLimit(n, b)
- # select objects
- bl.objectSelect(root)
- for o in mesh_objects:
- bl.objectSelect(o)
- bl.objectSelect(armature_object)
-
+ # import rigid bodies
+ rigidBodies=__importRigidBodies(scene, io)
+ if rigidBodies:
+ bl.objectMakeParent(root, rigidBodies)
+
+ # import constraints
+ constraints=__importConstraints(scene, io)
+ if constraints:
+ bl.objectMakeParent(root, constraints)
+
+ bl.objectActivate(scene, root)
+ bl.progress_finish()
if isBlender24():
# for 2.4
if mode_edit:
Blender.Window.EditMode(0)
- progress_start('pmd_import')
scene = bpy.data.scenes.active
__execute(filename, scene)
scene.update(0)
- progress_finish()
# restore edit mode
if mode_edit:
else:
# for 2.5
def execute_25(*args):
- progress_start('pmd_import')
__execute(*args)
- progress_finish()
# import operator
class IMPORT_OT_pmd(bpy.types.Operator):