Tooltip: 'Import PMD file for MikuMikuDance.'
"""
__author__= ["ousttrue"]
-__version__= "0.8"
+__version__= "1.0"
__url__=()
__bpydoc__="""
0.1: 20091126
0.6: 20100416 fix fornt face. texture load fail safe. add progress.
0.7: 20100506 C extension.
0.8: 20100521 add shape_key group.
+1.0: 20100530 add invisilbe bone tail(armature layer 2).
"""
import Blender
from Blender import Mathutils
MMD_SHAPE_GROUP_NAME='_MMD_SHAPE'
+###############################################################################
+# ProgressBar
+###############################################################################
class ProgressBar(object):
def __init__(self, base):
print "#### %s ####" % base
print message
message="%s: %s" % (self.base, message)
if message.__class__ is unicode:
- message=message.encode(INTERNAL_ENCODING)
+ message=message.encode(FS_ENCODING)
Blender.Window.DrawProgressBar(self.progress, message)
def finish(self):
progressBar.set(message, progress)
+###############################################################################
+# functions
+###############################################################################
def convert_coord(pos):
"""
Left handed y-up to Right handed z-up
material=createMaterial()
material.setRGBCol([m.diffuse.r, m.diffuse.g, m.diffuse.b])
material.setAlpha(m.diffuse.a)
- print(m.shinness)
- material.setHardness(int(m.shinness))
+ material.setSpec(m.shinness*0.1)
material.setSpecCol([m.specular.r, m.specular.g, m.specular.b])
material.setMirCol([m.ambient.r, m.ambient.g, m.ambient.b])
+ material.enableSSS=True if m.flag==1 else False
# set texture
if m.getTexture()!='':
tex_file=re.compile('\*.*.spa$').sub('', m.getTexture())
mesh_face_indices=[]
mesh_face_materials=[]
used_vertices=set()
+
+ def degenerate(i0, i1, i2):
+ return i0==i1 or i1==i2 or i2==i0
+
for material_index in material_order:
face_offset=face_map[material_index]
m=l.materials[material_index]
i0=material_faces[j]
i1=material_faces[j+1]
i2=material_faces[j+2]
- mesh_face_indices.append([i0, i1, i2])
+ triangle=[i0, i1, i2]
+ if degenerate(*triangle):
+ continue
+ mesh_face_indices.append(triangle)
mesh_face_materials.append(material_index)
used_vertices.add(i0)
used_vertices.add(i1)
used_vertices.add(i2)
+
mesh.faces.extend(mesh_face_indices, ignoreDups=True)
- assert(len(mesh.faces)==len(mesh_face_indices))
# face params
used_map={}
return vertex_map
-def build_bone(armature, b, parent=None):
- if b.tail_index==0:
- return
+class Builder(object):
+ def __init__(self):
+ self.boneMap={}
+
+ def build(self, armature, bones):
+ for b in bones:
+ if not b.parent:
+ self.__build(armature, b, None, None)
+ armature.update()
+
+ def __build(self, armature, b, p, parent):
+ name=englishmap.getEnglishBoneName(b.getName())
+ if not name:
+ name=b.getName().encode(INTERNAL_ENCODING)
+ self.boneMap[name]=b
+
+ bone=Blender.Armature.Editbone()
+ bone.name=name
+ armature.bones[name]=bone
+
+ if b.tail_index==0:
+ # 先端
+ assert(b.type==6 or b.type==7)
+ bone.head = Mathutils.Vector(*convert_coord(b.pos))
+ bone.tail=bone.head+Mathutils.Vector(0, 1, 0)
+ assert(parent)
+ bone.parent=parent
+ if bone.name=="center_t":
+ # センターボーンは(0, 1, 0)の方向を向いていないと具合が悪い
+ parent.tail=parent.head+Mathutils.Vector(0, 1, 0)
+ bone.head=parent.tail
+ bone.tail=bone.head+Mathutils.Vector(0, 1, 0)
+ else:
+ assert(parent.tail==bone.head)
+ bone.options=[Blender.Armature.CONNECTED]
+ # armature layer 2
+ bone.layerMask = (1<<1)
+ else:
+ bone.head = Mathutils.Vector(*convert_coord(b.pos))
+ bone.tail = Mathutils.Vector(*convert_coord(b.tail))
+ if parent:
+ bone.parent=parent
+ if parent.tail==bone.head:
+ bone.options=[Blender.Armature.CONNECTED]
- bone = Blender.Armature.Editbone()
- name=englishmap.getEnglishBoneName(b.getName())
- bone.name = name if name else b.getName().encode(
- INTERNAL_ENCODING)
- armature.bones[bone.name] = bone
- if parent:
- bone.head = Mathutils.Vector(*convert_coord(b.pos))
- bone.parent=parent
- options=[]
- if parent.tail==bone.head:
- options.append(Blender.Armature.CONNECTED)
- bone.options=options
- bone.tail = Mathutils.Vector(*convert_coord(b.tail))
if bone.head==bone.tail:
- bone.tail=bone.head-Mathutils.Vector(0, 1, 0)
- elif b.__class__ is pmd.BONE_IK:
- bone.head = Mathutils.Vector(*convert_coord(b.pos))
- bone.tail = Mathutils.Vector(*convert_coord(b.tail))
- else:
- # center
- tail=Mathutils.Vector(*convert_coord(b.pos))
- bone.tail = tail
- bone.head = tail-Mathutils.Vector(0, 1, 0)
+ bone.tail=bone.head+Mathutils.Vector(0, 1, 0)
- for child in b.children:
- build_bone(armature, child, bone)
+ for c in b.children:
+ self.__build(armature, c, b, bone)
def importArmature(scene, l):
armature_object.drawMode | Blender.Object.DrawModes.XRAY)
# armature settings
armature.drawType = Blender.Armature.OCTAHEDRON
+ armature.drawNames=True
armature.envelopes = False
armature.vertexGroups = True
armature.mirrorEdit = True
# create armature
armature.makeEditable()
- for b in l.bones:
- if not b.parent:
- build_bone(armature, b)
- armature.update()
+
+ ############################################################
+ # build bone
+ ############################################################
+ builder=Builder()
+ builder.build(armature, l.bones)
############################################################
# IK
for ik in l.ik_list:
# IKtarget->parent(=IK).name
target=l.bones[ik.target]
- parent=l.bones[target.parent_index]
- name = englishmap.getEnglishBoneName(parent.getName())
+ name = englishmap.getEnglishBoneName(target.getName())
p_bone = pose.bones[name]
if not p_bone:
print 'not found', name
print 'over MAX_CHAINLEN', ik, len(ik.children)
continue
# IK solver
- ik_const = p_bone.constraints.append(Blender.Constraint.Type.IKSOLVER)
- ik_const[cSetting.CHAINLEN] = len(ik.children)
- ik_const[cSetting.TARGET] = armature_object
- ik_const[cSetting.BONE] = englishmap.getEnglishBoneName(
+ ik_solver = p_bone.constraints.append(Blender.Constraint.Type.IKSOLVER)
+ ik_solver[cSetting.CHAINLEN]=len(ik.children)
+ ik_solver[cSetting.TARGET]=armature_object
+ ik_solver[cSetting.USETIP]=False
+
+ effector_name=englishmap.getEnglishBoneName(
l.bones[ik.index].getName())
- # Limit ROT
- lrot_const = p_bone.constraints.append(Blender.Constraint.Type.LIMITROT)
- lrot_const.influence = ik.weight
- lrot_const[cSetting.OWNERSPACE] = cSetting.SPACE_LOCAL
- lrot_const[cSetting.LIMIT] = (cSetting.LIMIT_XROT | cSetting.LIMIT_ZROT)
- lrot_const[cSetting.XMIN] = ik.iterations
- lrot_const[cSetting.XMAX] = 180
- lrot_const[cSetting.ZMIN] = 180 - ik.iterations
- lrot_const[cSetting.ZMAX] = 0
+ if not effector_name:
+ effector_name=l.bones[ik.index].getName()
+
+ ik_solver[cSetting.BONE]=effector_name
+ #ik_solver.influence=ik.weight
+ # not used. place folder when export.
+ ik_solver[cSetting.ROTWEIGHT]=ik.weight
+ ik_solver[cSetting.ITERATIONS]=ik.iterations * 10
armature.makeEditable()
armature.update()
# load pmd
progress_set('load %s' % filename, 0.0)
- import locale
- locale.setlocale(locale.LC_ALL, '')
-
l=pmd.IO()
if not l.read(filename):
print "fail to load %s" % filename
# import objects container
root=scene.objects.new("Empty")
root.setName(
- l.english_model_name if len(l.english_model_name)>0 else l.getName().encode(INTERNAL_ENCODING))
+ l.english_name if len(l.english_name)>0 else l.getName().encode(INTERNAL_ENCODING))
# import mesh
mesh_objects=importMesh(scene, l, tex_dir)
armature_object=importArmature(scene, l)
if armature_object:
armature = armature_object.getData()
- armature.drawNames=True
root.makeParent([armature_object])
# add armature modifier
mod=o.modifiers.append(Blender.Modifier.Types.ARMATURE)
mod[Blender.Modifier.Settings.OBJECT] = armature_object
mod[Blender.Modifier.Settings.ENVELOPES] = False
- o.makeDisplayList()
-
+ #o.makeDisplayList()
+
+ ############################################################
+ # Limitation
+ ############################################################
+ for n, b in armature_object.getPose().bones.items():
+ if n.endswith("_t"):
+ continue
+
+ if n.startswith("knee_"):
+ b.lockYRot=True
+ b.lockZRot=True
+ b.limitX=True
+ b.limitMin=[0, 0, 0]
+ b.limitMax=[180, 0, 0]
+ elif n.startswith("ankle_"):
+ b.lockYRot=True
+
# redraw
scene.update(0)