X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=blender25-meshio%2Fexport_pmd.py;h=c61a91558cd049a5121ee8e9bf8d99951e367e02;hb=2d68b0ab21b557470659a933fcc8c2d069cb5232;hp=8fb08a5070cc0c2123fb3e70e64ecefe1bf6a4cf;hpb=d6a98c93a2201c3b1d9a8481da91274398c1dc84;p=meshio%2Fpymeshio.git diff --git a/blender25-meshio/export_pmd.py b/blender25-meshio/export_pmd.py index 8fb08a5..c61a915 100644 --- a/blender25-meshio/export_pmd.py +++ b/blender25-meshio/export_pmd.py @@ -7,7 +7,7 @@ Tooltip: 'Export PMD file for MikuMikuDance.' """ __author__= ["ousttrue"] -__version__= "2.4" +__version__= "2.5" __url__=() __bpydoc__=""" pmd Importer @@ -29,6 +29,7 @@ This script exports a pmd model. 2.2 20101005: update for Blender2.54. 2.3 20101228: update for Blender2.55. 2.4 20110429: update for Blender2.57b. +2.5 20110522: implement RigidBody and Constraint. """ bl_addon_info = { @@ -44,34 +45,6 @@ bl_addon_info = { 'tracker_url': 'http://sourceforge.jp/ticket/newticket.php?group_id=5081', } -MMD_SHAPE_GROUP_NAME='_MMD_SHAPE' -MMD_MB_NAME='mb_name' -MMD_MB_COMMENT='mb_comment' -MMD_COMMENT='comment' -BASE_SHAPE_NAME='Basis' -RIGID_NAME='rigid_name' -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_NAME='constraint_name' -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' -TOON_TEXTURE_OBJECT='ToonTextures' - ############################################################################### # import @@ -85,8 +58,8 @@ try: print('use meshio C module') except ImportError: # full python - from .pymeshio import englishmap - from .pymeshio import pmd + from pymeshio import englishmap + from pymeshio import pmd # for 2.5 @@ -94,7 +67,7 @@ import bpy import mathutils # wrapper -from . import bl25 as bl +import bl25 as bl xrange=range @@ -116,7 +89,7 @@ def setMaterialParams(material, m): # flag material.flag=1 if m.subsurface_scattering.use else 0 # toon - material.toon_index=7 + material.toon_index=0 def toCP932(s): return s.encode('cp932') @@ -303,6 +276,29 @@ class IKSolver(object): self.weight=weight +class SSS(object): + def __init__(self): + self.use=1 + + +class DefaultMatrial(object): + def __init__(self): + self.name='default' + # diffuse + self.diffuse_color=[1, 1, 1] + self.alpha=1 + # specular + self.specular_toon_size=0 + self.specular_hardness=5 + self.specular_color=[1, 1, 1] + # ambient + self.mirror_color=[1, 1, 1] + # flag + self.subsurface_scattering=SSS() + # texture + self.texture_slots=[] + + class OneSkinMesh(object): __slots__=['vertexArray', 'morphList', 'rigidbodies', 'constraints', ] def __init__(self): @@ -357,7 +353,11 @@ class OneSkinMesh(object): for g in v.groups: setWeight(i, obj.vertex_groups[g.group].name, g.weight) else: - setWeight(i, obj.vertex_groups[0].name, 1) + try: + setWeight(i, obj.vertex_groups[0].name, 1) + except: + # no vertex_groups + pass # 合計値が1になるようにする for i in xrange(len(mesh.vertices)): @@ -374,10 +374,14 @@ class OneSkinMesh(object): return weightMap, secondWeightMap def __processFaces(self, obj_name, mesh, weightMap, secondWeightMap): + default_material=DefaultMatrial() # 各面の処理 for i, face in enumerate(mesh.faces): faceVertexCount=bl.face.getVertexCount(face) - material=mesh.materials[bl.face.getMaterialIndex(face)] + try: + material=mesh.materials[bl.face.getMaterialIndex(face)] + except IndexError as e: + material=default_material v=[mesh.vertices[index] for index in bl.face.getVertices(face)] uv=bl.mesh.getFaceUV( mesh, i, face, bl.face.getVertexCount(face)) @@ -460,26 +464,37 @@ class OneSkinMesh(object): ) def __mesh(self, obj): - if RIGID_SHAPE_TYPE in obj: + if bl.RIGID_SHAPE_TYPE in obj: return - if CONSTRAINT_A in obj: + if bl.CONSTRAINT_A in obj: return - #if not bl.modifier.hasType(obj, 'ARMATURE'): - # return - bl.message("export: %s" % obj.name) # メッシュのコピーを生成してオブジェクトの行列を適用する copyMesh, copyObj=bl.object.duplicate(obj) if len(copyMesh.vertices)>0: # apply transform - copyObj.scale=obj.scale - bpy.ops.object.transform_apply(scale=True) - copyObj.rotation_euler=obj.rotation_euler - bpy.ops.object.transform_apply(rotation=True) - copyObj.location=obj.location - bpy.ops.object.transform_apply(location=True) + """ + try: + # svn 36722 + copyObj.scale=obj.scale + bpy.ops.object.transform_apply(scale=True) + copyObj.rotation_euler=obj.rotation_euler + bpy.ops.object.transform_apply(rotation=True) + copyObj.location=obj.location + bpy.ops.object.transform_apply(location=True) + except AttributeError as e: + # 2.57b + copyObj.scale=obj.scale + bpy.ops.object.scale_apply() + copyObj.rotation_euler=obj.rotation_euler + bpy.ops.object.rotation_apply() + copyObj.location=obj.location + bpy.ops.object.location_apply() + """ + copyMesh.transform(obj.matrix_world) + # apply modifier for m in [m for m in copyObj.modifiers]: if m.type=='SOLIDFY': @@ -507,12 +522,12 @@ class OneSkinMesh(object): baseMorph=None # shape keys - vg=bl.object.getVertexGroup(obj, MMD_SHAPE_GROUP_NAME) + vg=bl.object.getVertexGroup(obj, bl.MMD_SHAPE_GROUP_NAME) # base used=set() for b in bl.object.getShapeKeys(obj): - if b.name==BASE_SHAPE_NAME: + if b.name==bl.BASE_SHAPE_NAME: baseMorph=self.__getOrCreateMorph('base', 0) basis=b @@ -533,17 +548,17 @@ class OneSkinMesh(object): break assert(basis) - print(basis.name, len(baseMorph.offsets)) + #print(basis.name, len(baseMorph.offsets)) if len(baseMorph.offsets)==0: return # shape keys for b in bl.object.getShapeKeys(obj): - if b.name==BASE_SHAPE_NAME: + if b.name==bl.BASE_SHAPE_NAME: continue - print(b.name) + #print(b.name) morph=self.__getOrCreateMorph(b.name, 4) used=set() for index, src, dst in zip( @@ -568,17 +583,17 @@ class OneSkinMesh(object): for i, v in enumerate(englishmap.skinMap): if v[0]==morph.name: return i - print(morph) + #print(morph) return len(englishmap.skinMap) self.morphList.sort(key=getIndex) def __rigidbody(self, obj): - if not RIGID_SHAPE_TYPE in obj: + if not bl.RIGID_SHAPE_TYPE in obj: return self.rigidbodies.append(obj) def __constraint(self, obj): - if not CONSTRAINT_A in obj: + if not bl.CONSTRAINT_A in obj: return self.constraints.append(obj) @@ -785,11 +800,14 @@ class BoneBuilder(object): if name=='': return 0 else: - return self.getIndex(self.__boneByName(name)) + try: + return self.getIndex(self.__boneByName(name)) + except: + return 0 def __boneByName(self, name): return self.boneMap[name] - + def __getBone(self, parent, b): if len(b.children)==0: parent.type=7 @@ -841,9 +859,9 @@ class PmdExporter(object): root=object_node_map[bl.object.getActive()] o=root.o self.englishName=o.name - self.englishComment=o[MMD_COMMENT] if MMD_COMMENT in o else 'blender export\n' - self.name=o[MMD_MB_NAME] if MMD_MB_NAME in o else 'Blenderエクスポート' - self.comment=o[MMD_MB_COMMENT] if MMD_MB_COMMENT in o else 'Blnderエクスポート\n' + self.englishComment=o[bl.MMD_COMMENT] if bl.MMD_COMMENT in o else 'blender export\n' + self.name=o[bl.MMD_MB_NAME] if bl.MMD_MB_NAME in o else 'Blenderエクスポート' + self.comment=o[bl.MMD_MB_COMMENT] if bl.MMD_MB_COMMENT in o else 'Blnderエクスポート\n' # ワンスキンメッシュを作る self.oneSkinMesh=OneSkinMesh() @@ -889,9 +907,10 @@ class PmdExporter(object): v.pos.x=pos[0] v.pos.y=pos[2] v.pos.z=pos[1] + # convert right-handed z-up to left-handed y-up v.normal.x=attribute.nx - v.normal.y=attribute.ny - v.normal.z=attribute.nz + v.normal.y=attribute.nz + v.normal.z=attribute.ny v.uv.x=attribute.u v.uv.y=1.0-attribute.v # reverse vertical v.bone0=self.skeleton.indexByName(b0) @@ -903,15 +922,24 @@ class PmdExporter(object): vertexCount=self.oneSkinMesh.getVertexCount() for material_name, indices in self.oneSkinMesh.vertexArray.each(): #print('material:', material_name) - m=bl.material.get(material_name) + try: + m=bl.material.get(material_name) + except KeyError as e: + m=DefaultMatrial() # マテリアル material=io.addMaterial() setMaterialParams(material, m) material.vertex_count=len(indices) - material.toon_index=0 - textures=[os.path.basename(path) + def get_texture_name(texture): + pos=texture.replace("\\", "/").rfind("/") + if pos==-1: + return texture + else: + return texture[pos+1:] + textures=[get_texture_name(path) for path in bl.material.eachEnalbeTexturePath(m)] + print(textures) if len(textures)>0: material.texture='*'.join(textures) else: @@ -940,7 +968,9 @@ class PmdExporter(object): # english name bone_english_name=toCP932(b.name) - assert(len(bone_english_name)<20) + if len(bone_english_name)>=20: + print(bone_english_name) + #assert(len(bone_english_name)<20) bone.english_name=bone_english_name if len(v)>=3: @@ -1036,7 +1066,7 @@ class PmdExporter(object): toonMeshObject=None for o in bl.object.each(): try: - if o.name.startswith(TOON_TEXTURE_OBJECT): + if o.name.startswith(bl.TOON_TEXTURE_OBJECT): toonMeshObject=o except: p(o.name) @@ -1047,55 +1077,52 @@ class PmdExporter(object): for i in range(10): t=bl.material.getTexture(toonMaterial, i) if t: - io.toon_textures[i]=pmd.encode_string(t.name) + io.toon_textures[i]="%s" % t.name else: - io.toon_textures[i]=pmd.encode_string("toon%02d.bmp\n" % i) + io.toon_textures[i]="toon%02d.bmp" % (i+1) else: for i in range(10): - io.toon_textures[i]=pmd.encode_string("toon%02d.bmp\n" % i) + io.toon_textures[i]="toon%02d.bmp" % (i+1) # rigid body rigidNameMap={} for i, obj in enumerate(self.oneSkinMesh.rigidbodies): - name=obj[RIGID_NAME] if RIGID_NAME in obj else obj.name - #print(name) + name=obj[bl.RIGID_NAME] if bl.RIGID_NAME in obj else obj.name + print(name) rigidBody=pmd.RigidBody(name) rigidNameMap[name]=i - boneIndex=boneNameMap[obj[RIGID_BONE_NAME]] + boneIndex=boneNameMap[obj[bl.RIGID_BONE_NAME]] if boneIndex==0: boneIndex=0xFFFF bone=self.skeleton.bones[0] else: bone=self.skeleton.bones[boneIndex] rigidBody.boneIndex=boneIndex - #rigidBody.position.x=obj[RIGID_LOCATION][0] - #rigidBody.position.y=obj[RIGID_LOCATION][1] - #rigidBody.position.z=obj[RIGID_LOCATION][2] rigidBody.position.x=obj.location.x-bone.pos[0] rigidBody.position.y=obj.location.z-bone.pos[2] rigidBody.position.z=obj.location.y-bone.pos[1] rigidBody.rotation.x=-obj.rotation_euler[0] rigidBody.rotation.y=-obj.rotation_euler[2] rigidBody.rotation.z=-obj.rotation_euler[1] - rigidBody.processType=obj[RIGID_PROCESS_TYPE] - rigidBody.group=obj[RIGID_GROUP] - rigidBody.target=obj[RIGID_INTERSECTION_GROUP] - rigidBody.weight=obj[RIGID_WEIGHT] - rigidBody.linearDamping=obj[RIGID_LINEAR_DAMPING] - rigidBody.angularDamping=obj[RIGID_ANGULAR_DAMPING] - rigidBody.restitution=obj[RIGID_RESTITUTION] - rigidBody.friction=obj[RIGID_FRICTION] - if obj[RIGID_SHAPE_TYPE]==0: + rigidBody.processType=obj[bl.RIGID_PROCESS_TYPE] + rigidBody.group=obj[bl.RIGID_GROUP] + rigidBody.target=obj[bl.RIGID_INTERSECTION_GROUP] + rigidBody.weight=obj[bl.RIGID_WEIGHT] + rigidBody.linearDamping=obj[bl.RIGID_LINEAR_DAMPING] + rigidBody.angularDamping=obj[bl.RIGID_ANGULAR_DAMPING] + rigidBody.restitution=obj[bl.RIGID_RESTITUTION] + rigidBody.friction=obj[bl.RIGID_FRICTION] + if obj[bl.RIGID_SHAPE_TYPE]==0: rigidBody.shapeType=pmd.SHAPE_SPHERE rigidBody.w=obj.scale[0] rigidBody.d=0 rigidBody.h=0 - elif obj[RIGID_SHAPE_TYPE]==1: + elif obj[bl.RIGID_SHAPE_TYPE]==1: rigidBody.shapeType=pmd.SHAPE_BOX rigidBody.w=obj.scale[0] rigidBody.d=obj.scale[1] rigidBody.h=obj.scale[2] - elif obj[RIGID_SHAPE_TYPE]==2: + elif obj[bl.RIGID_SHAPE_TYPE]==2: rigidBody.shapeType=pmd.SHAPE_CAPSULE rigidBody.w=obj.scale[0] rigidBody.h=obj.scale[2] @@ -1104,33 +1131,34 @@ class PmdExporter(object): # constraint for obj in self.oneSkinMesh.constraints: - constraint=pmd.Constraint(obj[CONSTRAINT_NAME]) - constraint.rigidA=rigidNameMap[obj[CONSTRAINT_A]] - constraint.rigidB=rigidNameMap[obj[CONSTRAINT_B]] + print(obj) + constraint=pmd.Constraint(obj[bl.CONSTRAINT_NAME]) + constraint.rigidA=rigidNameMap[obj[bl.CONSTRAINT_A]] + constraint.rigidB=rigidNameMap[obj[bl.CONSTRAINT_B]] constraint.pos.x=obj.location[0] constraint.pos.y=obj.location[2] constraint.pos.z=obj.location[1] constraint.rot.x=-obj.rotation_euler[0] constraint.rot.y=-obj.rotation_euler[2] constraint.rot.z=-obj.rotation_euler[1] - constraint.constraintPosMin.x=obj[CONSTRAINT_POS_MIN][0] - constraint.constraintPosMin.y=obj[CONSTRAINT_POS_MIN][1] - constraint.constraintPosMin.z=obj[CONSTRAINT_POS_MIN][2] - constraint.constraintPosMax.x=obj[CONSTRAINT_POS_MAX][0] - constraint.constraintPosMax.y=obj[CONSTRAINT_POS_MAX][1] - constraint.constraintPosMax.z=obj[CONSTRAINT_POS_MAX][2] - constraint.constraintRotMin.x=obj[CONSTRAINT_ROT_MIN][0] - constraint.constraintRotMin.y=obj[CONSTRAINT_ROT_MIN][1] - constraint.constraintRotMin.z=obj[CONSTRAINT_ROT_MIN][2] - constraint.constraintRotMax.x=obj[CONSTRAINT_ROT_MAX][0] - constraint.constraintRotMax.y=obj[CONSTRAINT_ROT_MAX][1] - constraint.constraintRotMax.z=obj[CONSTRAINT_ROT_MAX][2] - constraint.springPos.x=obj[CONSTRAINT_SPRING_POS][0] - constraint.springPos.y=obj[CONSTRAINT_SPRING_POS][1] - constraint.springPos.z=obj[CONSTRAINT_SPRING_POS][2] - constraint.springRot.x=obj[CONSTRAINT_SPRING_ROT][0] - constraint.springRot.y=obj[CONSTRAINT_SPRING_ROT][1] - constraint.springRot.z=obj[CONSTRAINT_SPRING_ROT][2] + constraint.constraintPosMin.x=obj[bl.CONSTRAINT_POS_MIN][0] + constraint.constraintPosMin.y=obj[bl.CONSTRAINT_POS_MIN][1] + constraint.constraintPosMin.z=obj[bl.CONSTRAINT_POS_MIN][2] + constraint.constraintPosMax.x=obj[bl.CONSTRAINT_POS_MAX][0] + constraint.constraintPosMax.y=obj[bl.CONSTRAINT_POS_MAX][1] + constraint.constraintPosMax.z=obj[bl.CONSTRAINT_POS_MAX][2] + constraint.constraintRotMin.x=obj[bl.CONSTRAINT_ROT_MIN][0] + constraint.constraintRotMin.y=obj[bl.CONSTRAINT_ROT_MIN][1] + constraint.constraintRotMin.z=obj[bl.CONSTRAINT_ROT_MIN][2] + constraint.constraintRotMax.x=obj[bl.CONSTRAINT_ROT_MAX][0] + constraint.constraintRotMax.y=obj[bl.CONSTRAINT_ROT_MAX][1] + constraint.constraintRotMax.z=obj[bl.CONSTRAINT_ROT_MAX][2] + constraint.springPos.x=obj[bl.CONSTRAINT_SPRING_POS][0] + constraint.springPos.y=obj[bl.CONSTRAINT_SPRING_POS][1] + constraint.springPos.z=obj[bl.CONSTRAINT_SPRING_POS][2] + constraint.springRot.x=obj[bl.CONSTRAINT_SPRING_ROT][0] + constraint.springRot.y=obj[bl.CONSTRAINT_SPRING_ROT][1] + constraint.springRot.z=obj[bl.CONSTRAINT_SPRING_ROT][2] io.constraints.append(constraint) # 書き込み