def create_pmx(ex, enable_bdef4=True): """ PMX 出力 """ model = pmx.Model() o = ex.root.o model.name = o.get(bl.MMD_MB_NAME, 'Blenderエクスポート') model.english_name = o.get(bl.MMD_ENGLISH_NAME, 'blender export model') model.comment = o.get(bl.MMD_MB_COMMENT, 'Blnderエクスポート\n') model.english_comment = o.get(bl.MMD_ENGLISH_COMMENT, 'blender export commen\n') class DeformBuilder: def __init__(self, skeleton): self.skeleton = skeleton self.bone_names = {b.name for b in skeleton.bones} self.count_bdef1 = 0 self.count_bdef2 = 0 self.count_bdef4 = 0 self.count_error = 0 def __filter(self, name, weight): return name in self.bone_names def __call__(self, ext_weight): weights=[ (self.skeleton.indexByName(w[0]), w[1]) \ for w in ext_weight.get_normalized(4, self.__filter) ] if len(weights) == 0: self.count_error += 1 return pmx.Bdef1(0) # Recovery elif len(weights) == 1: self.count_bdef1 += 1 return pmx.Bdef1(weights[0][0]) elif len(weights) == 2: self.count_bdef2 += 1 return pmx.Bdef2(weights[0][0], weights[1][0], weights[0][1]) else: if len(weights) == 3: weights.append((0, 0.0)) # Dummy Data self.count_bdef4 += 1 return pmx.Bdef4(weights[0][0], weights[1][0], weights[2][0], weights[3][0], weights[0][1], weights[1][1], weights[2][1], weights[3][1]) def show(self): print("BDEF Statistics >>>") print("\tBDEF1: %d BDEF2: %d BDEF4: %d ERROR: %d" % \ (self.count_bdef1, self.count_bdef2, self.count_bdef4, self.count_error)) deform_builder = DeformBuilder(ex.skeleton) def get_deform(b0, b1, weight): if b0 == -1: return pmx.Bdef1(b1, weight) elif b1 == -1: return pmx.Bdef1(b0, weight) else: return pmx.Bdef2(b0, b1, weight) model.vertices=[pmx.Vertex( # convert right-handed z-up to left-handed y-up common.Vector3(pos[0], pos[2], pos[1]), # convert right-handed z-up to left-handed y-up common.Vector3(attribute.nx, attribute.nz, attribute.ny), # reverse vertical common.Vector2(attribute.u, 1.0-attribute.v), deform_builder(ext_weight) if enable_bdef4 else \ get_deform(ex.skeleton.indexByName(b0), ex.skeleton.indexByName(b1), weight), # edge flag, 0: enable edge, 1: not edge 1.0 ) for pos, attribute, b0, b1, weight, ext_weight in ex.oneSkinMesh.vertexArray.zip2()] if enable_bdef4: deform_builder.show() boneMap = dict([(b.name, i) for i, b in enumerate(ex.skeleton.bones)]) def getFixedAxis(b): if b.isFixedAxis(): return common.Vector3(b.tail[0], b.tail[2], b.tail[1]).normalize() else: return common.Vector3(0, 0, 0) def create_bone(b): bone = pmx.Bone( name=b.name, english_name=b.english_name, # convert right-handed z-up to left-handed y-up position=common.Vector3(b.pos[0] if not near(b.pos[0], 0) else 0, b.pos[2] if not near(b.pos[2], 0) else 0, b.pos[1] if not near(b.pos[1], 0) else 0), parent_index=b.parent_index, layer=0, flag=0, tail_position=None, tail_index=b.tail_index, effect_index=-1, effect_factor=0.0, fixed_axis=getFixedAxis(b), local_x_vector=None, local_z_vector=None, external_key=-1, ik=None) if b.constraint == exporter.bonebuilder.CONSTRAINT_COPY_ROTATION: bone.layer = 2 bone.effect_index = boneMap[b.constraintTarget] bone.effect_factor = b.constraintInfluence bone.setFlag(pmx.BONEFLAG_IS_EXTERNAL_ROTATION, True) if b.constraint == exporter.bonebuilder.CONSTRAINT_LIMIT_ROTATION: bone.setFlag(pmx.BONEFLAG_HAS_FIXED_AXIS, True) bone.setFlag(pmx.BONEFLAG_TAILPOS_IS_BONE, b.hasTail) bone.setFlag(pmx.BONEFLAG_CAN_ROTATE, True) bone.setFlag(pmx.BONEFLAG_CAN_TRANSLATE, b.canTranslate) bone.setFlag(pmx.BONEFLAG_IS_VISIBLE, b.isVisible) bone.setFlag(pmx.BONEFLAG_CAN_MANIPULATE, b.canManipulate()) if b.ikSolver: bone.setFlag(pmx.BONEFLAG_IS_IK, True) bone.ik_target_index = b.ikSolver.effector_index bone.ik = pmx.Ik(b.ikSolver.effector_index, b.ikSolver.iterations, b.ikSolver.weight, [ pmx.IkLink(c.index, c.limitAngle, common.Vector3(*c.limitMin), common.Vector3(*c.limitMax)) for c in b.ikSolver.chain ]) return bone model.bones = [create_bone(b) for b in ex.skeleton.bones] # textures textures = set() def get_texture_name(texture): pos = texture.replace("\\", "/").rfind("/") if pos == -1: return texture else: return texture[pos + 1:] try: for m in ex.oneSkinMesh.vertexArray.indexArrays.keys(): for path in bl.material.eachEnalbeTexturePath(bl.material.get(m)): textures.add(get_texture_name(path)) except KeyError as e: # no material pass model.textures = list(textures) # texture pathからtexture indexを逆引き texturePathMap = {} for i, texture_path in enumerate(model.textures): texturePathMap[texture_path] = i def get_flag(m): """ return material flag """ return (m.get(bl.MATERIALFLAG_BOTHFACE, 0) + (m.get(bl.MATERIALFLAG_GROUNDSHADOW, 0) << 1) + (m.get(bl.MATERIALFLAG_SELFSHADOWMAP, 0) << 2) + (m.get(bl.MATERIALFLAG_SELFSHADOW, 0) << 3) + (m.get(bl.MATERIALFLAG_EDGE, 0) << 4)) def get_toon_shareing_flag(m): """ return shared: 1 not shared: 0 """ for t in bl.material.eachEnalbeTexturePath(m): if re.match("""toon\d\d.bmp"""): return 1 return 0 def get_texture_params(m, texturePathMap): texture_index = -1 toon_texture_index = -1 toon_sharing_flag = 0 sphere_texture_index = -1 sphere_mode = pmx.MATERIALSPHERE_NONE for t in bl.material.eachEnalbeTexture(m): texture_type = t.get(bl.TEXTURE_TYPE, 'NORMAL') texture_path = get_texture_name(bl.texture.getPath(t)) if texture_type == 'NORMAL': texture_index = texturePathMap[texture_path] elif texture_type == 'TOON': toon_texture_index = texturePathMap[texture_path] toon_sharing_flag = 0 elif texture_type == 'SPH': sphere_texture_index = texturePathMap[texture_path] sphere_mode = pmx.MATERIALSPHERE_SPH elif texture_type == 'SPA': sphere_texture_index = texturePathMap[texture_path] sphere_mode = pmx.MATERIALSPHERE_SPA if bl.MATERIAL_SHAREDTOON in m: toon_texture_index = m[bl.MATERIAL_SHAREDTOON] toon_sharing_flag = 1 return (texture_index, toon_texture_index, toon_sharing_flag, sphere_texture_index, sphere_mode) # 面とマテリアル vertexCount = ex.oneSkinMesh.getVertexCount() model.materials = [] for material_name, indices in ex.oneSkinMesh.vertexArray.each(): #print('material:', material_name) try: m = bl.material.get(material_name) except KeyError as e: m = exporter.oneskinmesh.DefaultMaterial() ( texture_index, toon_texture_index, toon_sharing_flag, sphere_texture_index, sphere_mode, ) = get_texture_params(m, texturePathMap) # マテリアル model.materials.append( pmx.Material(name=m.name, english_name='', diffuse_color=common.RGB(m.diffuse_color[0], m.diffuse_color[1], m.diffuse_color[2]), alpha=m.use_transparency and m.alpha or 1.0, specular_factor=(0 if m.specular_toon_size < 1e-5 else m.specular_toon_size * 10), specular_color=common.RGB(m.specular_color[0], m.specular_color[1], m.specular_color[2]), ambient_color=common.RGB(m.mirror_color[0], m.mirror_color[1], m.mirror_color[2]), flag=get_flag(m), edge_color=common.RGBA(0, 0, 0, 1), edge_size=1.0, texture_index=texture_index, sphere_texture_index=sphere_texture_index, sphere_mode=sphere_mode, toon_sharing_flag=toon_sharing_flag, toon_texture_index=toon_texture_index, comment='', vertex_count=len(indices))) # 面 for i in indices: assert (i < vertexCount) for i in range(0, len(indices), 3): # reverse triangle model.indices.append(indices[i + 2]) model.indices.append(indices[i + 1]) model.indices.append(indices[i]) def get_vertex_index(rel_index): return ex.oneSkinMesh.morphList[0].offsets[rel_index][0] # 表情 from pymeshio import englishmap for i, m in enumerate(ex.oneSkinMesh.morphList[1:]): # name english_name = "morph: %d" % i panel = 4 for en, n, p in englishmap.skinMap: if n == m.name: english_name = en panel = p break morph = pmx.Morph( name=m.name, english_name=english_name, panel=panel, morph_type=1, ) morph.offsets = [ pmx.VertexMorphOffset( get_vertex_index(index), common.Vector3(offset[0], offset[2], offset[1])) for index, offset in m.offsets ] model.morphs.append(morph) # ボーングループ model.display_slots = [] for name, members in ex.skeleton.bone_groups: if name == "表情": slot = pmx.DisplaySlot( name=name, english_name=englishmap.getEnglishBoneGroupName(name), special_flag=1) slot.references = [(1, i) for i in range(len(model.morphs))] model.display_slots.append(slot) else: slot = pmx.DisplaySlot( name=name, english_name=englishmap.getEnglishBoneGroupName(name), special_flag=1 if name == "Root" else 0) slot.references = [(0, ex.skeleton.boneByName(m).index) for m in members] model.display_slots.append(slot) # rigid body boneNameMap = {} for i, b in enumerate(ex.skeleton.bones): boneNameMap[b.name] = i rigidNameMap = {} for i, obj in enumerate(ex.oneSkinMesh.rigidbodies): name = obj[bl.RIGID_NAME] if bl.RIGID_NAME in obj else obj.name #print(name) rigidNameMap[name] = i boneIndex = boneNameMap[obj[bl.RIGID_BONE_NAME]] if boneIndex == 0: boneIndex = -1 if obj[bl.RIGID_SHAPE_TYPE] == 0: shape_type = 0 shape_size = common.Vector3(obj.scale[0], 0, 0) elif obj[bl.RIGID_SHAPE_TYPE] == 1: shape_type = 1 shape_size = common.Vector3(obj.scale[0], obj.scale[2], obj.scale[1]) elif obj[bl.RIGID_SHAPE_TYPE] == 2: shape_type = 2 shape_size = common.Vector3(obj.scale[0], obj.scale[2], 0) rigidBody = pmx.RigidBody( name=name, english_name='', collision_group=obj[bl.RIGID_GROUP], no_collision_group=obj[bl.RIGID_INTERSECTION_GROUP], bone_index=boneIndex, shape_position=common.Vector3(obj.location.x, obj.location.z, obj.location.y), shape_rotation=common.Vector3(-obj.rotation_euler[0], -obj.rotation_euler[2], -obj.rotation_euler[1]), shape_type=shape_type, shape_size=shape_size, mass=obj[bl.RIGID_WEIGHT], linear_damping=obj[bl.RIGID_LINEAR_DAMPING], angular_damping=obj[bl.RIGID_ANGULAR_DAMPING], restitution=obj[bl.RIGID_RESTITUTION], friction=obj[bl.RIGID_FRICTION], mode=obj[bl.RIGID_PROCESS_TYPE]) model.rigidbodies.append(rigidBody) # joint model.joints = [ pmx.Joint( name=obj[bl.CONSTRAINT_NAME], english_name='', joint_type=0, rigidbody_index_a=rigidNameMap[obj[bl.CONSTRAINT_A]], rigidbody_index_b=rigidNameMap[obj[bl.CONSTRAINT_B]], position=common.Vector3(obj.location[0], obj.location[2], obj.location[1]), rotation=common.Vector3(-obj.rotation_euler[0], -obj.rotation_euler[2], -obj.rotation_euler[1]), translation_limit_min=common.Vector3( obj[bl.CONSTRAINT_POS_MIN][0], obj[bl.CONSTRAINT_POS_MIN][1], obj[bl.CONSTRAINT_POS_MIN][2]), translation_limit_max=common.Vector3( obj[bl.CONSTRAINT_POS_MAX][0], obj[bl.CONSTRAINT_POS_MAX][1], obj[bl.CONSTRAINT_POS_MAX][2]), rotation_limit_min=common.Vector3(obj[bl.CONSTRAINT_ROT_MIN][0], obj[bl.CONSTRAINT_ROT_MIN][1], obj[bl.CONSTRAINT_ROT_MIN][2]), rotation_limit_max=common.Vector3(obj[bl.CONSTRAINT_ROT_MAX][0], obj[bl.CONSTRAINT_ROT_MAX][1], obj[bl.CONSTRAINT_ROT_MAX][2]), spring_constant_translation=common.Vector3( obj[bl.CONSTRAINT_SPRING_POS][0], obj[bl.CONSTRAINT_SPRING_POS][1], obj[bl.CONSTRAINT_SPRING_POS][2]), spring_constant_rotation=common.Vector3( obj[bl.CONSTRAINT_SPRING_ROT][0], obj[bl.CONSTRAINT_SPRING_ROT][1], obj[bl.CONSTRAINT_SPRING_ROT][2])) for obj in ex.oneSkinMesh.constraints ] return model
def savepmx(model, filename): pmx_model = pmx.Model() pmx_model.english_name = u'Empty model' pmx_model.comment = u'NeoX Model Converterで生成' pmx_model.english_comment = u'Created by NeoX Model Converter.' parent_child_dict = {} old2new = {} index_pool = [-1] bone_pool = [] for i in range(len(model['bone_parent'])): p = model['bone_parent'][i] if p not in parent_child_dict: parent_child_dict[p] = [] parent_child_dict[p].append(i) def build_joint(index, parent_index): matrix = model['bone_original_matrix'][index] x, y, z = tf.translation_from_matrix(matrix.T) bone_pool.append( pmx.Bone(name=model['bone_name'][index], english_name=model['bone_name'][index], position=common.Vector3(-x, y, -z), parent_index=parent_index, layer=0, flag=0)) bone_pool[-1].setFlag(pmx.BONEFLAG_CAN_ROTATE, True) bone_pool[-1].setFlag(pmx.BONEFLAG_IS_VISIBLE, True) bone_pool[-1].setFlag(pmx.BONEFLAG_CAN_MANIPULATE, True) def deep_first_search(index, index_pool, parent_index): index_pool[0] += 1 current_node_index = index_pool[0] old2new[index] = current_node_index build_joint(index, parent_index) if index in parent_child_dict: for child in parent_child_dict[index]: deep_first_search(child, index_pool, current_node_index) deep_first_search(model['bone_parent'].index(-1), index_pool, -1) pmx_model.bones = bone_pool for i in range(len(model['position'])): x, y, z = model['position'][i] nx, ny, nz = model['normal'][i] u, v = model['uv'][i] if 65535 in model['vertex_joint'][i]: vertex_joint_index = list( map(lambda x: old2new[x] if x != 65535 else 0, model['vertex_joint'][i])) else: vertex_joint_index = list( map(lambda x: old2new[x] if x != 255 else 0, model['vertex_joint'][i])) vertex = pmx.Vertex( common.Vector3(-x, y, -z), common.Vector3(-nx, ny, -nz), common.Vector2(u, v), pmx.Bdef4(*vertex_joint_index, *(model['vertex_joint_weight'][i])), 0.0) pmx_model.vertices.append(vertex) for i in range(len(model['face'])): pmx_model.indices += list(model['face'][i]) pmx_model.materials[0].vertex_count = len(model['face']) * 3 ########### pmx_model.materials = [] for i in range(len(model['mesh'])): _, mesh_face_count, _, _ = model['mesh'][i] pmx_model.materials.append( pmx.Material(u'Mat{}'.format(i), u'material{}'.format(i), common.RGB(0.5, 0.5, 1), 1.0, 1, common.RGB(1, 1, 1), common.RGB(0, 0, 0), 0, common.RGBA(0, 0, 0, 1), 0, -1, -1, pmx.MATERIALSPHERE_NONE, 1, 0, u"comment", mesh_face_count * 3)) filename = filename.replace('.mesh', '') pymeshio.pmx.writer.write_to_file(pmx_model, filename + '.pmx') for bone in pmx_model.bones: if bone.english_name in paj_middle_bone_name: bone.position.x = 0.0 if 'bip001_l_finger13' in [bone.english_name for bone in pmx_model.bones]: paj_bone_name.update(paj_hand1_name) else: paj_bone_name.update(paj_hand0_name) for bone in pmx_model.bones: if bone.english_name in paj_bone_name: bone.name = paj_bone_name[bone.english_name][0] bone.english_name = paj_bone_name[bone.english_name][1] def add_bone(pmxm, bone, index): assert index <= len(pmxm.bones) pmxm.bones.insert(index, bone) for bone in pmxm.bones: if bone.parent_index >= index: bone.parent_index += 1 for vertex in pmxm.vertices: if vertex.deform.index0 >= index: vertex.deform.index0 += 1 if vertex.deform.index1 >= index: vertex.deform.index1 += 1 if vertex.deform.index2 >= index: vertex.deform.index2 += 1 if vertex.deform.index3 >= index: vertex.deform.index3 += 1 return index def find_bone_index_by_name(pmxm, bone_english_name): ret = None for i in range(len(pmxm.bones)): if pmxm.bones[i].english_name == bone_english_name: ret = i break return ret ####################### parent_node_index = find_bone_index_by_name(pmx_model, 'ParentNode') center_bone = pmx.Bone(name='センター', english_name='Center', position=common.Vector3(0, 8.0, 0), parent_index=parent_node_index, layer=0, flag=0) center_bone.setFlag(pmx.BONEFLAG_CAN_ROTATE, True) center_bone.setFlag(pmx.BONEFLAG_IS_VISIBLE, True) center_bone.setFlag(pmx.BONEFLAG_CAN_MANIPULATE, True) waist_index = find_bone_index_by_name(pmx_model, 'Waist') center_index = add_bone(pmx_model, center_bone, waist_index) groove_bone = pmx.Bone(name='グルーブ', english_name='Groove', position=common.Vector3(0, 8.2, 0), parent_index=center_index, layer=0, flag=0) groove_bone.setFlag(pmx.BONEFLAG_CAN_ROTATE, True) groove_bone.setFlag(pmx.BONEFLAG_IS_VISIBLE, True) groove_bone.setFlag(pmx.BONEFLAG_CAN_MANIPULATE, True) waist_index = find_bone_index_by_name(pmx_model, 'Waist') groove_index = add_bone(pmx_model, groove_bone, waist_index) waist_index = find_bone_index_by_name(pmx_model, 'Waist') pmx_model.bones[waist_index].parent_index = groove_index waist_index = find_bone_index_by_name(pmx_model, 'Waist') upper_body_index = find_bone_index_by_name(pmx_model, 'UpperBody') pmx_model.bones[upper_body_index].parent_index = waist_index ########################## for LR in ['Left', 'Right']: ankle_index = find_bone_index_by_name(pmx_model, '{}Ankle'.format(LR)) ankle_x, ankle_y, ankle_z = pmx_model.bones[ ankle_index].position.to_tuple() toe_index = find_bone_index_by_name(pmx_model, '{}Toe'.format(LR)) toe_vec = pmx_model.bones[toe_index].position toe_vec.y = ankle_y - 1.0 toe_vec.z = -1.65 leg_ik_parent_bone = pmx.Bone( name='左足IK親' if LR == 'Left' else '右足IK親', english_name='{}LegIkParent'.format(LR), position=common.Vector3(ankle_x, 0, ankle_z), parent_index=parent_node_index, layer=0, flag=0) leg_ik_parent_bone.setFlag(pmx.BONEFLAG_CAN_ROTATE, True) leg_ik_parent_bone.setFlag(pmx.BONEFLAG_CAN_TRANSLATE, True) leg_ik_parent_bone.setFlag(pmx.BONEFLAG_IS_VISIBLE, True) leg_ik_parent_bone.setFlag(pmx.BONEFLAG_CAN_MANIPULATE, True) leg_ik_parent_index = add_bone(pmx_model, leg_ik_parent_bone, len(pmx_model.bones)) leg_ik_bone = pmx.Bone(name='左足IK' if LR == 'Left' else '右足IK', english_name='{}LegIk'.format(LR), position=common.Vector3(ankle_x, ankle_y, ankle_z), parent_index=leg_ik_parent_index, layer=0, flag=0) leg_ik_bone.setFlag(pmx.BONEFLAG_CAN_ROTATE, True) leg_ik_bone.setFlag(pmx.BONEFLAG_CAN_TRANSLATE, True) leg_ik_bone.setFlag(pmx.BONEFLAG_IS_IK, True) leg_ik_bone.setFlag(pmx.BONEFLAG_IS_VISIBLE, True) leg_ik_bone.setFlag(pmx.BONEFLAG_CAN_MANIPULATE, True) knee_index = find_bone_index_by_name(pmx_model, '{}Knee'.format(LR)) leg_index = find_bone_index_by_name(pmx_model, '{}Leg'.format(LR)) leg_ik_link = [ pmx.IkLink(knee_index, 1, common.Vector3(-180.0 / 57.325, 0, 0), common.Vector3(-0.5 / 57.325, 0, 0)), pmx.IkLink(leg_index, 0) ] leg_ik_bone.ik = pmx.Ik(ankle_index, 40, 2, leg_ik_link) leg_ik_index = add_bone(pmx_model, leg_ik_bone, len(pmx_model.bones)) toe_ik_bone = pmx.Bone(name='左つま先IK' if LR == 'Left' else '右つま先IK', english_name='{}LegIk'.format(LR), position=common.Vector3(toe_vec.x, toe_vec.y, toe_vec.z), parent_index=leg_ik_index, layer=0, flag=0) toe_ik_bone.setFlag(pmx.BONEFLAG_CAN_ROTATE, True) toe_ik_bone.setFlag(pmx.BONEFLAG_CAN_TRANSLATE, True) toe_ik_bone.setFlag(pmx.BONEFLAG_IS_IK, True) toe_ik_bone.setFlag(pmx.BONEFLAG_IS_VISIBLE, True) toe_ik_bone.setFlag(pmx.BONEFLAG_CAN_MANIPULATE, True) toe_ik_bone.ik = pmx.Ik(toe_index, 3, 4, [pmx.IkLink(ankle_index, 0)]) add_bone(pmx_model, toe_ik_bone, len(pmx_model.bones)) ''' # build local axis and get rotation left_arm_index = find_bone_index_by_name(pmx_model, 'LeftArm') left_elbow_index = find_bone_index_by_name(pmx_model, 'LeftElbow') left_wrist_index = find_bone_index_by_name(pmx_model, 'LeftWrist') larm_pos = np.array(list(pmx_model.bones[left_arm_index].position.to_tuple())) lelbow_pos = np.array(list(pmx_model.bones[left_elbow_index].position.to_tuple())) lwrist_pos = np.array(list(pmx_model.bones[left_wrist_index].position.to_tuple())) vec_ew = lwrist_pos - lelbow_pos vec_ea = larm_pos - lelbow_pos vec_ew = vec_ew / np.linalg.norm(vec_ew) vec_ea = vec_ea / np.linalg.norm(vec_ea) cos_ew_ea = np.dot(vec_ea, vec_ew) if -1 * math.cos(3/180 * 3.14) < cos_ew_ea and cos_ew_ea < 0: y_axis = np.cross(vec_ew, vec_ea) y_axis = y_axis / np.linalg.norm(y_axis) z_axis = np.cross(vec_ea, y_axis) z_axis = z_axis / np.linalg.norm(z_axis) x_axis = np.cross(z_axis, y_axis) x_axis = x_axis / np.linalg.norm(x_axis) # pmx_model.bones[left_elbow_index].setFlag(pmx.BONEFLAG_HAS_LOCAL_COORDINATE, True) pmx_model.bones[left_elbow_index].local_x_vector = common.Vector3(*x_axis.tolist()) pmx_model.bones[left_elbow_index].local_z_vector = common.Vector3(*z_axis.tolist()) ''' head_index = find_bone_index_by_name(pmx_model, 'Head') eyes_bone = pmx.Bone(name='両目', english_name='Eyes', position=common.Vector3(0, 25, 0), parent_index=head_index, layer=0, flag=0) eyes_bone.setFlag(pmx.BONEFLAG_CAN_ROTATE, True) eyes_bone.setFlag(pmx.BONEFLAG_IS_VISIBLE, True) eyes_bone.setFlag(pmx.BONEFLAG_CAN_MANIPULATE, True) pmx_model.bones.append(eyes_bone) eyes_index = find_bone_index_by_name(pmx_model, 'Eyes') for LR in 'lr': eyeball_index = find_bone_index_by_name(pmx_model, 'bone_eyeball_{}'.format(LR)) pmx_model.bones[eyeball_index].effect_index = eyes_index pmx_model.bones[eyeball_index].effect_factor = 2.2 pmx_model.bones[eyeball_index].setFlag( pmx.BONEFLAG_IS_EXTERNAL_ROTATION, True) ''' morph_ref_model = pymeshio.pmx.reader.read_from_file('morph_ref') pmx_model.morphs = morph_ref_model.morphs for morph in pmx_model.morphs: for offset in morph.offsets: bone_english_name = morph_ref_model.bones[offset.bone_index].english_name offset.bone_index = find_bone_index_by_name(pmx_model, bone_english_name) ''' pymeshio.pmx.writer.write_to_file(pmx_model, filename + '_modified.pmx')
def khiankhuen(chue_tem_file='',khanat_ok=0.125,chai_kraduk=1,chai_bs=1,chai_watsadu=1,lok_tex=1,mod_sph=1,tex_sph=''): t0 = time.time() chue_path_file = os.path.dirname(chue_tem_file) shoki = os.path.join(os.path.dirname(__file__),u'shoki.pmx') model = pmxread(shoki) # สร้างโมเดล pmx ตั้งต้น # เพื่อความรวดเร็ว ดึง append มาเก็บไว้ก่อน model_vert_ap = model.vertices.append model_ind_ap = model.indices.append model_bon_ap = model.bones.append model_mat_ap = model.materials.append model_mor_ap = model.morphs.append model_slot_ap1 = model.display_slots[1].references.append model_slot_ap2 = model.display_slots[2].references.append # โหนดโพลิกอนทั้งหมดที่เลือกอยู่ list_chue_nod_poly = mc.filterExpand(mc.ls(tr=1,sl=1),sm=12) list_chue_nod_shep = [] list_chue_nod_skin = [] list_matrix_mun = [0] if(list_chue_nod_poly==None): # กรณีที่ไม่ได้เลือกโพลิกอนไว้เลย print(u'ポリゴンは選択せれていません') return for chue_nod_poly in list_chue_nod_poly: # โหนดรูปร่างของโพลิกอนนั้นๆ chue_nod_shep = mc.listRelatives(chue_nod_poly,s=1)[0] list_chue_nod_shep.append(chue_nod_shep) # หาโหนด skin ที่ใช้กับโพลิกอนนั้นๆ if(chai_kraduk): for chue_nod_skin in mc.ls(typ='skinCluster'): if(chue_nod_shep in mc.skinCluster(chue_nod_skin,q=1,g=1)): list_chue_nod_skin.append(chue_nod_skin) break # ถ้าหาไม่เจอก็คือไม่มี else: list_chue_nod_skin.append(0) if(chai_kraduk): dic_chue_nod_kho = {u'全ての親':0} i_kho = 1 for k in mc.ls(typ='joint',l=1): # ถ้ามีอยู่แล้วก็ข้ามไปได้เลย if(k in dic_chue_nod_kho): continue # หาว่าตรึงอยู่กับสกินที่ใช้หรือเปล่า for chue_nod_skin in list_chue_nod_skin: if(chue_nod_skin and k in (pm.PyNode(x).fullPath() for x in mc.skinCluster(chue_nod_skin,q=1,inf=1))): break # ถ้าไม่มีเลยก็ข้ามไป else: continue # หาตัวรากฐาน parent = mc.listRelatives(k,p=1,f=1) if(parent): pp = [''] for p in parent[0].split('|')[1:]: pp.append(p) pj = '|'.join(pp) if(mc.nodeType(pj)=='joint'): parent = pj break else: parent = k else: parent = k # ถ้าไม่มีก็คือตัวมันเองเป็น # ถ้าตัวรากฐานมีอยู่แล้วก็ข้ามไปได้เลย if(parent in dic_chue_nod_kho): continue # ถ้ายังไม่มีก็ใส่ข้อมูลเข้าไปทั้งตัวรากฐานและลูกทั้งหมด list_child = mc.listRelatives(parent,ad=1,f=1) list_cp = [parent] if(list_child): list_cp += list(reversed(list_child)) for j,chue_nod_kho in enumerate(list_cp): dic_chue_nod_kho[chue_nod_kho] = i_kho+j for chue_nod_kho in list_cp: if(mc.objExists(chue_nod_kho+'.namae')): namae = mc.getAttr(chue_nod_kho+'.namae') else: namae = u'骨%d'%i_kho kw = {'name':namae,'english_name':chue_nod_kho,'layer':0,'flag':2074} kho = pm.PyNode(chue_nod_kho) p = kho.getTranslation(space='world') kw['position'] = common.Vector3(p.x*khanat_ok,p.y*khanat_ok,-1*p.z*khanat_ok) try: chue_parent = kho.getParent().fullPath() parent_index = dic_chue_nod_kho[chue_parent] kw['parent_index'] = parent_index except: parent_index = 0 kw['parent_index'] = 0 kw['flag'] += 4 # ให้ขยับได้อิสระ child = kho.getChildren() if(len(child)==1): kw['tail_index'] = dic_chue_nod_kho[child[0].fullPath()] kw['flag'] += 1 else: kw['tail_index'] = -1 jo = mc.getAttr(chue_nod_kho+'.jo')[0] mm = list_matrix_mun[parent_index] if(jo==(0,0,0)): if(not mm): kw['flag'] -= 2048 list_matrix_mun.append(mm) else: mm *= 1 if(mm): mm *= om.MEulerRotation(math.radians(jo[0]),math.radians(jo[1]),math.radians(jo[2])).asMatrix() else: mm = om.MEulerRotation(math.radians(jo[0]),math.radians(jo[1]),math.radians(jo[2])).asMatrix() list_matrix_mun.append(mm) if(mm): kw['local_x_vector'] = common.Vector3(mm(0,0),mm(0,1),-mm(0,2)) kw['local_z_vector'] = common.Vector3(mm(2,0),mm(2,1),-mm(2,2)) model_bon_ap(pmx.Bone(**kw)) # ใส่ข้อต่อลงในแผงควบคุม ถ้าไม่ใช่ท่อนปลายสุด if(child): model_slot_ap2((0,i_kho)) i_kho += 1 list_tamnaeng = [] list_norm = [] list_u = [] list_v = [] list_lek_tamnaeng_nai_na = [] list_na_to_poly = [] list_chut_to_poly = [] lai_lek_tamnaeng = 0 lai_lek_norm = 0 lai_lek_uv = 0 list_lek_chut_mai = [] dic_str_chut = {} lai_lek = 0 list_chue_nod_bs = mc.ls(typ='blendShape') i_poly = 0 # โพลิกอนอันที่เท่าไหร่ for chue_nod_poly in list_chue_nod_poly: chue_nod_shep = list_chue_nod_shep[i_poly] try: nod_shep = pm.PyNode(chue_nod_shep) except pm.MayaNodeError: print(u'特殊なポリゴンが含まれる可能性があります。ポリゴンを結合しておいてください') raise # กรณีที่เป็นโพลิกอนที่สร้างมาจากวิธีที่เหนือความคาดหมายอาจมีข้อผิดพลาด แก้ได้โดยรวมโพลิกอนที่มีปัญหา if(chai_kraduk): chue_nod_skin = list_chue_nod_skin[i_poly] if(chue_nod_skin): dic_kho = {} # ดิกเชื่อมโยงเลขข้อสำหรับสกินนี้ กับเลขดัชนีของข้อต่อที่ลำดับตามดิกที่สร้างตอนแรก for i,chue_nod_kho in enumerate(mc.skinCluster(chue_nod_skin,q=1,inf=1)): dic_kho[i] = dic_chue_nod_kho[pm.PyNode(chue_nod_kho).fullPath()] # โค้ดยาวๆก้อนนี้มีไว้เพื่อดึงข้อมูลน้ำหนักที่เชื่อมข้อต่อกับโพลิกอน nod_skin = pm.PyNode(chue_nod_skin) obj_skin = om.MObject() sl = om.MSelectionList() sl.add(nod_skin.name()) sl.getDependNode(0,obj_skin) fn_skin = oma.MFnSkinCluster(obj_skin) path_mesh = om.MDagPath() sl = om.MSelectionList() sl.add(nod_shep.fullPath()) sl.getDagPath(0,path_mesh) nod_shep.fullPath() path_inf = om.MDagPathArray() n_inf = fn_skin.influenceObjects(path_inf) util = om.MScriptUtil() util.createFromList(range(n_inf),n_inf) id_inf = om.MIntArray(util.asIntPtr(),n_inf) n_vert = nod_shep.numVertices() fn_comp = om.MFnSingleIndexedComponent() components = fn_comp.create(om.MFn.kMeshVertComponent) util = om.MScriptUtil() util.createFromList(range(n_vert),n_vert) id_vert = om.MIntArray(util.asIntPtr(),n_vert) fn_comp.addElements(id_vert) list_namnak = om.MDoubleArray() # ได้ข้อมูลน้ำหนักเป็นลิสต์ ยาว = จำนวนข้อ x จำนวนจุดยอด fn_skin.getWeights(path_mesh,components,id_inf,list_namnak) n_kho = len(dic_kho) # จำนวนข้อ if(chai_bs): w = [] # ลิสต์เก็บค่าน้ำหนักเดิมของเบลนด์เชปทั้งหมด # หาเบลนด์เชปคัดเอาเฉพาะที่เชื่อมกับโพลิกอนตัวนี้อยู่ list_chue_nod_bs_ni = [] for chue_nod_bs in list_chue_nod_bs: # ดูว่านี่เป็นโพลิกอนที่เชื่อมอยู่กับเบลนด์เชปอันนี้หรือเปล่า if(chue_nod_shep not in mc.blendShape(chue_nod_bs,q=1,g=1)): continue try: # try เพื่อกันกรณีที่มีโหนดเบลนด์เชปอยู่แต่ไม่มีเบลนด์เชปอยู่เลย ww = mc.getAttr(chue_nod_bs+'.w[*]') # เก็บค่าน้ำหนักปัจจุบันไว้ except: continue if(type(ww)==float): ww = [ww] # เพื่อกันกรณีที่มีอยู่แค่ตัวเดียว จะได้ค่าไม่เป็นลิสต์ ต้องทำให้เป็นลิสต์เหมือนกันหมด w.append(ww) mc.setAttr(chue_nod_bs+'.w[*]',*[0]*len(ww)) # ตั้งน้ำหนักให้เป็น 0 ไว้ก่อน list_chue_nod_bs_ni.append(chue_nod_bs) # เก็บค่าตำแหน่งจุด tamnaeng = nod_shep.getPoints(space='world') list_tamnaeng.extend(tamnaeng) list_chut_to_na,vertid = nod_shep.getVertices() chut_to_poly = len(vertid) # เก็บค่าเส้นตั้งฉาก norm = nod_shep.getNormals(space='world') list_norm.extend(norm) normid = nod_shep.getNormalIds()[1] # เก็บค่า uv u,v = nod_shep.getUVs() list_u.extend(u) list_v.extend(v) uvid = nod_shep.getAssignedUVs()[1] list_samliam_to_na,list_lek_chut = nod_shep.getTriangles() list_lek_tamnaeng_nai_na_to_poly = [] lai_samliam = 0 # ดึงข้อมูลเบลนด์เชป list_chue_bs = [] if(chai_bs): list_tamnaeng_bs = [] list_luean_bs = [] list_luean_bs_ap = [] for i,chue_nod_bs in enumerate(list_chue_nod_bs_ni): # ถ้ามีข้อมูลชื่อญี่ปุ่นหรือช่องให้ดึงมา if(mc.objExists(chue_nod_bs+'.namae')): try: dic_namae = dict(namae.split(u'๑',1) for namae in mc.getAttr(chue_nod_bs+'.namae').split(u'๐')) except: dic_namae = {} else: dic_namae = {} lenw = len(w[i]) # จำนวนเบลนด์เชปในโหนดนั้นๆ for i,bs in enumerate(mc.listAttr(chue_nod_bs+'.w',m=1)): # ตั้งให้น้ำหนักเป็น 1 แค่แบบเดียวทีละแบบ ที่เหลือเป็น 0 ไปก่อน ww = [0]*lenw ww[i] = 1 mc.setAttr(chue_nod_bs+'.w[*]',*ww) # ดึงข้อมูลตำแหน่งที่เลื่อนแล่้ว tamnaeng_bs = nod_shep.getPoints(space='world') list_tamnaeng_bs.append(tamnaeng_bs) if(bs in dic_namae): namae = dic_namae[bs].split(u'๑') try: list_chue_bs.append((namae[0],bs,int(namae[1]))) except: list_chue_bs.append((namae[0],bs,4)) # ถ้าไม่ได้มีชื่อที่ตั้งเก็บไว้ในโหนดแต่แรกก็ให้ใช้ทั้งชื่อญี่ปุ่นและชื่ออังกฤษเป็นชื่อเดียวกัน else: list_chue_bs.append((bs,bs,4)) luean_bs = [] list_luean_bs.append(luean_bs) list_luean_bs_ap.append(luean_bs.append) # เปลี่ยนรูปร่างกลับคืนเดิมด้วย for i,chue_nod_bs in enumerate(list_chue_nod_bs_ni): mc.setAttr(chue_nod_bs+'.w[*]',*w[i]) n_bs = len(list_chue_bs) list_lek_chut_mai_to_poly = [] i = 0 for samliam_to_na,chut_to_na in zip(list_samliam_to_na,list_chut_to_na): dic_lai_lek = {} for j in range(chut_to_na): lek_tamnaeng = vertid[i] lek_norm = normid[i] lek_uv = uvid[i] str_chut = '%d:%d:%d'%(lek_tamnaeng+lai_lek_tamnaeng,lek_norm+lai_lek_norm,lek_uv+lai_lek_uv) if(str_chut in dic_str_chut): lek_chut_mai = dic_str_chut[str_chut] else: lek_chut_mai = lai_lek dic_str_chut[str_chut] = lek_chut_mai #ถ้ามีเชื่อมสกินอยู่ก็ดึงน้ำหนักมาใช้ if(chai_kraduk and chue_nod_skin): w = [] # ลิสต์เก็บทูเพิลของ (ดัชนีข้อ,ค่าน้ำหนัก) # ดึงข้อมูลน้ำหนักจากลิสต์น้ำหนัก ความยาวเท่ากับจำนวนข้อ for i_namnak,namnak in enumerate(list_namnak[lek_tamnaeng*n_kho:(lek_tamnaeng+1)*n_kho]): # คัดเฉพาะที่ไม่น้อยจนเกือบ 0 เท่านั้น if(namnak>0.001): w.append((dic_kho[i_namnak],namnak)) if(len(w)>3): # ถ้ามากเกิน 4 ให้เรียงเอาอันที่มากก็พอ if(len(w)>4): w.sort(key=f_riang_namnak,reverse=1) w = w[:4] w_ruam = w[0][1]+w[1][1]+w[2][1]+w[3][1] ww0 = w[0][1]/w_ruam ww1 = w[1][1]/w_ruam ww2 = w[2][1]/w_ruam ww3 = w[3][1]/w_ruam deform = pmx.Bdef4(w[0][0],w[1][0],w[2][0],w[3][0],ww0,ww1,ww2,ww3) elif(len(w)==3): w_ruam = w[0][1]+w[1][1]+w[2][1] ww0 = w[0][1]/w_ruam ww1 = w[1][1]/w_ruam ww2 = w[2][1]/w_ruam deform = pmx.Bdef4(w[0][0],w[1][0],w[2][0],-1,ww0,ww1,ww2,0.) elif(len(w)==2): ww0 = w[0][1]/(w[0][1]+w[1][1]) deform = pmx.Bdef2(w[0][0],w[1][0],ww0) elif(len(w)==1): deform = pmx.Bdef1(w[0][0]) else: deform = pmx.Bdef1(0) # ถ้าไม่ได้เชื่อมกับสกินก็ให้ตรึงกับข้อรากฐานให้หมด else: deform = pmx.Bdef1(0) p = list_tamnaeng[lek_tamnaeng+lai_lek_tamnaeng] position = common.Vector3(p[0]*khanat_ok,p[1]*khanat_ok,-p[2]*khanat_ok) nm = list_norm[lek_norm+lai_lek_norm] normal = common.Vector3(nm[0],nm[1],-nm[2]) uv = common.Vector2(list_u[lek_uv+lai_lek_uv],1.-list_v[lek_uv+lai_lek_uv]) # สร้างจุดจากข้อมูลที่ดึงมาได้ แล้วเพื่มเข้าไปในลิสต์ของจุด vertex = pmx.Vertex(position,normal,uv,deform,edge_factor=1.) model_vert_ap(vertex) for i_bs in range(n_bs): p1 = list_tamnaeng_bs[i_bs][lek_tamnaeng] po = common.Vector3((p1[0]-p[0])*khanat_ok,(p1[1]-p[1])*khanat_ok,(p[2]-p1[2])*khanat_ok) # เอาข้อมูลเฉพาะจุดที่มีการเปลี่ยนตำแหน่ง if(po.getNorm()>0): list_luean_bs_ap[i_bs](pmx.VertexMorphOffset(lai_lek,po)) lai_lek += 1 dic_lai_lek[lek_tamnaeng+lai_lek_tamnaeng] = lek_chut_mai i += 1 ll = [] for j in range(lai_samliam*3,(lai_samliam+samliam_to_na)*3,3): for jj in range(3): lek_tamnaeng = list_lek_chut[j+2-jj] lek_chut_mai = dic_lai_lek[lek_tamnaeng+lai_lek_tamnaeng] ll.append(lek_chut_mai) lai_samliam += samliam_to_na list_lek_chut_mai_to_poly.append(ll) # สร้างมอร์ฟทั้งหมดจากข้อมูลเบลนด์เชปที่เตรียมไว้ if(chai_bs): for i_mor,(chue_bs,luean_bs) in enumerate(zip(list_chue_bs,list_luean_bs)): model_mor_ap(pmx.Morph(name=chue_bs[0],english_name=chue_bs[1],panel=chue_bs[2],morph_type=1,offsets=luean_bs)) model_slot_ap1((1,i_mor)) list_na_to_poly.append(vertid) list_chut_to_poly.append(chut_to_poly) lai_lek_tamnaeng += len(tamnaeng) lai_lek_norm += len(norm) lai_lek_uv += len(u) list_lek_tamnaeng_nai_na.append(list_lek_tamnaeng_nai_na_to_poly) list_lek_chut_mai.append(list_lek_chut_mai_to_poly) i_poly += 1 # ถ้าเลือกจะสร้างวัสดุด้วยก็สร้างแล้วเรียงจุดในหน้าตามวัสดุ if(chai_watsadu): list_chue_nod_mat = [] # ลิสต์เก็บโหนดวัสดุ list_chue_nod_sg = [] # ลิสต์เก็บโหนด sg i_tex = 0 # ดัชนีเท็กซ์เจอร์ i_mat = 0 # ดัชนีวัสดุ for mat in mc.ls(mat=1): # เอาเฉพาะวัสดุที่มี sg เท่านั้น try: liscon = mc.listConnections(mat+'.outColor') sg = liscon[0] list_na = mc.sets(sg,q=1) # ดูว่ามีหน้าไหนที่ใช้วัสดุนี้ if(not list_na): if(len(liscon)>1): sg = liscon[1] list_na = mc.sets(sg,q=1) # หากไม่ถูกใช้อยู่ก็ข้าม if(not list_na): continue except: continue n_chut_to_mat = 0 # จำนวนจุดของหน้านี้ (= 3 เท่าของจำนวนหน้า) for na in list_na: if('[' in na): chue_nod_poly,na0,na1 = re.findall(r'(\w+).f\[(\d+):?(\d+)?]',na)[0] na0 = int(na0) if(na1==''): na1 = na0 else: na1 = int(na1) else: chue_nod_poly = mc.listRelatives(na,p=1)[0] na0 = 0 na1 = mc.polyEvaluate(chue_nod_poly,f=1)-1 # ถ้าอยู่ในลิสต์ของโพลิกอนที่เลือกอยู่ให้หาเลขดัชนีของโพลิกอนนั้นในลิสต์ if(chue_nod_poly in list_chue_nod_poly): lek_nod_poly = list_chue_nod_poly.index(chue_nod_poly) # ถ้าไม่อยู่ในลิสต์ก็ข้ามไปเลย else: continue for lai_na in range(na0,na1+1): for lek in list_lek_chut_mai[lek_nod_poly][lai_na]: model_ind_ap(lek) n_chut_to_mat += 1 # ถ้าวัสดุนี้ไม่ถูกใช้ในโพลิกอนที่เลือกอยู่เลยก็ข้าม if(n_chut_to_mat==0): continue if(mc.objExists(mat+'.namae')): namae = mc.getAttr(mat+'.namae') else: namae = u'材質%d'%(i_mat+1) # ค่าองค์ประกอบต่างๆของวัสดุ เก็บไว้ในดิกก่อน kw = {'name':namae,'english_name':mat, 'diffuse_color':common.RGB(1,1,1),'alpha':1, 'specular_factor':0.5,'specular_color':common.RGB(0.,0.,0.), 'ambient_color':common.RGB(0.5,0.5,0.5), 'flag':1,'edge_color':common.RGBA(0.,0.,0.,1.),'edge_size':1, 'texture_index':-1,'sphere_texture_index':-1,'sphere_mode':0, 'toon_sharing_flag':0,'toon_texture_index':-1,'vertex_count':n_chut_to_mat} # ใส่ try กันกรณีที่เป็นวัสดุชนิดแปลกๆที่ไม่สามารถอ่านค่าได้ปกติ try: nodetype = mc.nodeType(mat) # ชนิดของวัสดุ # หาดูว่าวัสดุนี้ใช้เท็กซ์เจอร์หรือไม่ if(nodetype!='aiStandardSurface'): chue_nod_tex = mc.listConnections(mat+'.color') else: chue_nod_tex = mc.listConnections(mat+'.baseColor') # ถ้ามีเท็กซ์เจอร์ และเป็นไฟล์ if(chue_nod_tex): if(mc.nodeType(chue_nod_tex[0])=='file'): chue_tem_file_tex = mc.getAttr(chue_nod_tex[0]+'.ftn') # ชื่อไฟล์ # ถ้ามีชื่อไฟล์นี้อยู่แล้ว if(chue_tem_file_tex in model.textures): kw['texture_index'] = model.textures.index(chue_tem_file_tex) # ถ้ายังไม่มีก็เพิ่มเข้าไป else: chue_tex = os.path.basename(chue_tem_file_tex) model.textures.append(chue_tex) # ถ้าเลือกว่าจะคัดลอกไฟล์เท็กซ์เจอร์ก็ทำการคัดลอก if(lok_tex): shutil.copyfile(chue_tem_file_tex,os.path.join(chue_path_file,chue_tex)) kw['texture_index'] = i_tex i_tex += 1 # นับไล่ดัชนีเท็กซ์เจอร์ต่อ else: print(u'テクスチャ%sはファイルではないため使えません'%chue_nod_tex[0]) dc = [1.,1.,1.] # ถ้าไม่ใช้เท็กซ์เจอร์ไฟล์จึงกำหนดสีผิว else: if(nodetype!='aiStandardSurface'): dc = mc.getAttr(mat+'.color')[0] else: dc = mc.getAttr(mat+'.baseColor')[0] dc = [min(max(s,0.),1.) for s in dc] kw['diffuse_color'] = common.RGB(*dc) if(nodetype not in ['aiStandard','aiStandardSurface']): tran = sum(mc.getAttr(mat+'.transparency')[0])/3 # ความโปร่งใสใช้เป็นค่าเฉลี่ย kw['alpha'] = min(max(1-tran,0),1.) # ค่าสีแอมเบียนต์ให้คูณสีผิวไปด้วย ac = [min(max(s,0.),1.)*d for s,d in zip(mc.getAttr(mat+'.ambientColor')[0],dc)] kw['ambient_color'] = common.RGB(*ac) # เฉพาะ blinn เท่านั้นจึงเก็บค่าสเป็กคิวลาร์ นอกนั้นใช้ค่าตั้งต้น if(nodetype=='blinn'): sr = min(max(mc.getAttr(mat+'.specularRollOff'),0.1),1.) kw['specular_factor'] = round(math.pow(2,math.log(sr,0.75)-1)) kw['specular_color'] = common.RGB(*[min(max(s,0.),1.) for s in mc.getAttr(mat+'.specularColor')[0]]) # กรณี aiStandard else: opa = sum(mc.getAttr(mat+'.opacity')[0])/3 # ความทึบแสงใช้เป็นค่าเฉลี่ย kw['alpha'] = min(max(opa,0.),1.) if(nodetype!='aiStandardSurface'): kw['specular_color'] = common.RGB(*[min(max(s,0.),1.) for s in mc.getAttr(mat+'.KsColor')[0]]) else: kw['specular_color'] = common.RGB(*[min(max(s,0.),1.) for s in mc.getAttr(mat+'.specularColor')[0]]) sr = max(mc.getAttr(mat+'.specularRoughness'),0.1) kw['specular_factor'] = round(math.pow(2,math.log(sr,0.75)-1)) kw['ambient_color'] = common.RGB(0,0,0) except: print(u'材質%sに問題が見つかりました'%mat) model_mat_ap(pmx.Material(**kw)) # เพิ่มวัสดุเข้าไปในโมเดล list_chue_nod_mat.append(mat) list_chue_nod_sg.append(sg) i_mat += 1 if(mod_sph): i = len(model.textures) model.textures.append(tex_sph) for mat in model.materials: mat.sphere_mode = mod_sph mat.sphere_texture_index = i # ถ้าเลือกไม่เอาวัสดุก็ให้ใช้เป็นวัสดุตั้งต้นแบบเดียวกันหมด else: n_chut_to_mat = 0 for list_lek_chut_nai_poly in list_lek_chut_mai: for list_lek_chut_nai_na in list_lek_chut_nai_poly: n_chut_to_mat += len(list_lek_chut_nai_na) for lek_chut in list_lek_chut_nai_na: model_ind_ap(lek_chut) model_mat_ap(pmx.Material(name=u'材質1',english_name='', diffuse_color=common.RGB(0.5,0.5,0.5),alpha=1, specular_factor=0.5,specular_color=common.RGB(0.5,0.5,0.5), ambient_color=common.RGB(0.25,0.25,0.25), flag=1,edge_color=common.RGBA(0.,0.,0.,1.),edge_size=1, texture_index=-1,sphere_texture_index=-1,sphere_mode=0, toon_sharing_flag=0,toon_texture_index=-1,vertex_count=n_chut_to_mat)) chue_model = os.path.basename(chue_tem_file).split('.')[0] model.name = chue_model model.english_name = chue_model if(not model.display_slots[2].references): model.display_slots.pop() with io.open(chue_tem_file,'wb') as s: pmxwri(s,model) mc.select(list_chue_nod_poly) print(u'ファイル%s作成完了。%.2f秒かかりました'%(chue_tem_file,time.time()-t0))