private static PMXFormat.MorphList ConvertMorphList(PMDFormat pmd) { PMXFormat.MorphList result = new PMXFormat.MorphList(); //頂点インデックス用辞書の作成 PMDFormat.SkinData pmd_skin_data_base = pmd.skin_list.skin_data.Where(x => 0 == x.skin_type).First(); Dictionary <uint, uint> morph_vertex_index_dictionary = new Dictionary <uint, uint>(pmd_skin_data_base.skin_vert_data.Length); for (uint i = 0, i_max = (uint)pmd_skin_data_base.skin_vert_data.Length; i < i_max; ++i) { morph_vertex_index_dictionary.Add(i, pmd_skin_data_base.skin_vert_data[i].skin_vert_index); } //base以外の変換 result.morph_data = new PMXFormat.MorphData[pmd.skin_list.skin_data.Where(x => 0 != x.skin_type).Count()]; //base分を除外 int morph_data_count = 0; for (int i = 0, i_max = pmd.skin_list.skin_data.Length; i < i_max; ++i) { if (0 != pmd.skin_list.skin_data[i].skin_type) { //base以外なら string eg_skin_name = (((null != pmd.eg_skin_name_list) && (1 <= i))? pmd.eg_skin_name_list.skin_name_eg[i - 1]: null); result.morph_data[morph_data_count++] = ConvertMorphData(pmd.skin_list.skin_data[i], eg_skin_name, morph_vertex_index_dictionary); } } return(result); }
private static PMXFormat.Rigidbody ConvertRigidbody(PMDFormat pmd, int rigidbody_index) { PMXFormat.Rigidbody result = new PMXFormat.Rigidbody(); PMDFormat.Rigidbody pmd_rigidbody = pmd.rigidbody_list.rigidbody[rigidbody_index]; result.name = pmd_rigidbody.rigidbody_name; result.english_name = ""; result.rel_bone_index = (uint)pmd_rigidbody.rigidbody_rel_bone_index; result.group_index = pmd_rigidbody.rigidbody_group_index; result.ignore_collision_group = pmd_rigidbody.rigidbody_group_target; result.shape_type = (PMXFormat.Rigidbody.ShapeType)pmd_rigidbody.shape_type; result.shape_size = new Vector3(pmd_rigidbody.shape_w, pmd_rigidbody.shape_h, pmd_rigidbody.shape_d); result.collider_position = pmd_rigidbody.pos_pos; if (pmd_rigidbody.rigidbody_rel_bone_index < pmd.bone_list.bone.Length) { result.collider_position += pmd.bone_list.bone[pmd_rigidbody.rigidbody_rel_bone_index].bone_head_pos; } else { result.collider_position += pmd.bone_list.bone[0].bone_head_pos; } result.collider_rotation = pmd_rigidbody.pos_rot; result.weight = pmd_rigidbody.rigidbody_weight; result.position_dim = pmd_rigidbody.rigidbody_pos_dim; result.rotation_dim = pmd_rigidbody.rigidbody_rot_dim; result.recoil = pmd_rigidbody.rigidbody_recoil; result.friction = pmd_rigidbody.rigidbody_friction; result.operation_type = (PMXFormat.Rigidbody.OperationType)pmd_rigidbody.rigidbody_type; return(result); }
private static PMXFormat.Bone ConvertBone(PMDFormat pmd, int bone_index) { PMXFormat.Bone result = new PMXFormat.Bone(); PMDFormat.Bone pmd_bone = pmd.bone_list.bone[bone_index]; result.bone_name = pmd_bone.bone_name; result.bone_english_name = ((null != pmd.eg_bone_name_list)? pmd.eg_bone_name_list.bone_name_eg[bone_index]: null); result.bone_position = pmd_bone.bone_head_pos; result.parent_bone_index = ((ushort.MaxValue == pmd_bone.parent_bone_index)? uint.MaxValue: (uint)pmd_bone.parent_bone_index); result.transform_level = 0; switch (pmd_bone.bone_type) { case 0: //回転 result.bone_flag = PMXFormat.Bone.Flag.Movable | PMXFormat.Bone.Flag.DisplayFlag | PMXFormat.Bone.Flag.CanOperate; break; case 1: //回転と移動 result.bone_flag = PMXFormat.Bone.Flag.Movable | PMXFormat.Bone.Flag.Rotatable | PMXFormat.Bone.Flag.DisplayFlag | PMXFormat.Bone.Flag.CanOperate; break; case 2: //IK result.bone_flag = PMXFormat.Bone.Flag.IkFlag | PMXFormat.Bone.Flag.DisplayFlag | PMXFormat.Bone.Flag.CanOperate; break; case 3: //不明 goto default; case 4: //IK影響下 goto default; case 5: //回転影響下 goto default; //付与親に変換しないといけないのかも case 6: //IK接続先 goto default; case 7: //非表示 goto default; case 8: //捻り goto default; case 9: //回転運動 goto default; default: result.bone_flag = new PMXFormat.Bone.Flag(); break; } result.position_offset = Vector3.zero; result.connection_index = 0; result.additional_parent_index = 0; result.additional_rate = 0.0f; result.axis_vector = Vector3.zero; result.x_axis_vector = Vector3.zero; result.z_axis_vector = Vector3.zero; result.key_value = 0; result.ik_data = ConvertIKData(pmd.ik_list.ik_data.Where(x => x.ik_bone_index == bone_index).FirstOrDefault()); return(result); }
private PMDFormat Read() { format_ = new PMDFormat(); EntryPathes(); try { format_.head = ReadHeader(); format_.vertex_list = ReadVertexList(); format_.face_vertex_list = ReadFaceVertexList(); format_.material_list = ReadMaterialList(); format_.bone_list = ReadBoneList(); format_.ik_list = ReadIKList(); format_.skin_list = ReadSkinList(); format_.skin_name_list = ReadSkinNameList(); format_.bone_name_list = ReadBoneNameList(); format_.bone_display_list = ReadBoneDisplayList(); format_.eg_head = ReadEnglishHeader(); if (format_.eg_head.english_name_compatibility != 0) { format_.eg_bone_name_list = ReadEnglishBoneNameList(format_.bone_list.bone_count); format_.eg_skin_name_list = ReadEnglishSkinNameList(format_.skin_list.skin_count); format_.eg_bone_display_list = ReadEnglishBoneDisplayList(format_.bone_name_list.bone_disp_name_count); } format_.toon_texture_list = ReadToonTextureList(); format_.rigidbody_list = ReadRigidbodyList(); format_.rigidbody_joint_list = ReadRigidbodyJointList(); } catch { Debug.Log("Don't read full format"); } return(format_); }
private static PMXFormat.MetaHeader CreateMetaHeader(PMDFormat pmd) { PMXFormat.MetaHeader result = new PMXFormat.MetaHeader(); result.path = pmd.path; result.name = pmd.name; result.folder = pmd.folder; return result; }
private PMDFormat Read() { format_ = new PMDFormat(); EntryPathes(); try { format_.head = ReadHeader(); format_.vertex_list = ReadVertexList(); format_.face_vertex_list = ReadFaceVertexList(); format_.material_list = ReadMaterialList(); format_.bone_list = ReadBoneList(); format_.ik_list = ReadIKList(); format_.skin_list = ReadSkinList(); format_.skin_name_list = ReadSkinNameList(); format_.bone_name_list = ReadBoneNameList(); format_.bone_display_list = ReadBoneDisplayList(); format_.eg_head = ReadEnglishHeader(); if (format_.eg_head.english_name_compatibility != 0) { format_.eg_bone_name_list = ReadEnglishBoneNameList(format_.bone_list.bone_count); format_.eg_skin_name_list = ReadEnglishSkinNameList(format_.skin_list.skin_count); format_.eg_bone_display_list = ReadEnglishBoneDisplayList(format_.bone_name_list.bone_disp_name_count); } format_.toon_texture_list = ReadToonTextureList(); format_.rigidbody_list = ReadRigidbodyList(); format_.rigidbody_joint_list = ReadRigidbodyJointList(); } catch { Debug.Log("Don't read full format"); } return format_; }
private static PMXFormat.MetaHeader CreateMetaHeader(PMDFormat pmd) { PMXFormat.MetaHeader result = new PMXFormat.MetaHeader(); result.path = pmd.path; result.name = pmd.name; result.folder = pmd.folder; return(result); }
private static PMXFormat.DisplayFrameList ConvertDisplayFrameList(PMDFormat pmd) { PMXFormat.DisplayFrameList result = new PMXFormat.DisplayFrameList(); result.display_frame = new PMXFormat.DisplayFrame[pmd.bone_display_list.bone_disp.Length]; for (int i = 0, i_max = result.display_frame.Length; i < i_max; ++i) { result.display_frame[i] = ConvertDisplayFrame(pmd, i); } return(result); }
private static PMXFormat.BoneList ConvertBoneList(PMDFormat pmd) { PMXFormat.BoneList result = new PMXFormat.BoneList(); result.bone = new PMXFormat.Bone[pmd.bone_list.bone.Length]; for (int i = 0, i_max = pmd.bone_list.bone.Length; i < i_max; ++i) { result.bone[i] = ConvertBone(pmd, i); } return(result); }
private static PMXFormat.RigidbodyList ConvertRigidbodyList(PMDFormat pmd) { PMXFormat.RigidbodyList result = new PMXFormat.RigidbodyList(); result.rigidbody = new PMXFormat.Rigidbody[pmd.rigidbody_list.rigidbody.Length]; for (int i = 0, i_max = result.rigidbody.Length; i < i_max; ++i) { result.rigidbody[i] = ConvertRigidbody(pmd, i); } return(result); }
private static PMXFormat.MaterialList ConvertMaterialList(PMDFormat pmd, System.Func <string, uint> get_texture_index) { PMXFormat.MaterialList result = new PMXFormat.MaterialList(); result.material = new PMXFormat.Material[pmd.material_list.material.Length]; for (int i = 0; i < result.material.Length; i++) { result.material[i] = ConvertMaterial(pmd, i, get_texture_index); } return(result); }
private static PMXFormat.Material ConvertMaterial(PMDFormat pmd, int material_index, System.Func <string, uint> get_texture_index) { PMXFormat.Material result = new PMXFormat.Material(); PMDFormat.Material pmd_material = pmd.material_list.material[material_index]; result.name = "材質_" + material_index.ToString(); result.english_name = "Material_" + material_index.ToString(); result.diffuse_color = new Color(pmd_material.diffuse_color.r, pmd_material.diffuse_color.g, pmd_material.diffuse_color.b, pmd_material.alpha); result.specularity = pmd_material.specularity; result.specular_color = pmd_material.specular_color; result.ambient_color = pmd_material.mirror_color; result.flag = new PMXFormat.Material.Flag(); if (pmd_material.alpha < 1.0f) { result.flag |= PMXFormat.Material.Flag.Reversible; } if (0 != pmd_material.edge_flag) { result.flag |= PMXFormat.Material.Flag.Edge | PMXFormat.Material.Flag.CastShadow | PMXFormat.Material.Flag.CastSelfShadow; } if (!(0.98f == pmd_material.alpha)) //浮動小数点の比較だけど、0.98fとの同値確認でPMXエディタの0.98と一致したので一旦これで。 { result.flag |= PMXFormat.Material.Flag.ReceiveSelfShadow; } result.edge_color = Color.black; result.edge_size = 1.0f; //result.usually_texture_index = uint.MaxValue; if (!string.IsNullOrEmpty(pmd_material.texture_file_name)) { result.usually_texture_index = get_texture_index(pmd_material.texture_file_name); } result.sphere_texture_index = uint.MaxValue; result.sphere_mode = PMXFormat.Material.SphereMode.Null; if (!string.IsNullOrEmpty(pmd_material.sphere_map_name)) { result.sphere_texture_index = get_texture_index(pmd_material.sphere_map_name); switch (System.IO.Path.GetExtension(pmd_material.sphere_map_name)) { case ".sph": result.sphere_mode = PMXFormat.Material.SphereMode.MulSphere; break; case ".spa": result.sphere_mode = PMXFormat.Material.SphereMode.AddSphere; break; default: break; } } result.common_toon = pmd_material.toon_index; result.toon_texture_index = ((0 < pmd_material.toon_index)? pmd_material.toon_index: uint.MaxValue); result.memo = ""; result.face_vert_count = pmd_material.face_vert_count; return(result); }
private static PMXFormat.DisplayFrame ConvertDisplayFrame(PMDFormat pmd, int bone_display_index) { PMXFormat.DisplayFrame result = new PMXFormat.DisplayFrame(); PMDFormat.BoneDisplay pmd_bone_display = pmd.bone_display_list.bone_disp[bone_display_index]; result.display_name = pmd.bone_name_list.disp_name[pmd_bone_display.bone_disp_frame_index - 1]; result.display_english_name = ((null != pmd.eg_bone_display_list)? pmd.eg_bone_display_list.disp_name_eg[pmd_bone_display.bone_disp_frame_index - 1]: null); result.special_frame_flag = new byte(); result.display_element = new [] { new PMXFormat.DisplayElement() }; result.display_element[0].element_target = pmd_bone_display.bone_disp_frame_index; result.display_element[0].element_target_index = pmd_bone_display.bone_index; return(result); }
/// <summary> /// PMXファイルの取得 /// </summary> /// <param name='pmd'>PMDファイル</param> /// <returns>内部形式データ</returns> public static PMXFormat PMD2PMX(PMDFormat pmd) { PMXFormat result = new PMXFormat(); result.meta_header = CreateMetaHeader(pmd); result.header = ConvertHeader(pmd.head, pmd.eg_head, pmd); result.vertex_list = ConvertVertexList(pmd); result.face_vertex_list = ConvertFaceVertexList(pmd); result.texture_list = ConvertTextureList(pmd); result.material_list = ConvertMaterialList(pmd, x=>CreateTextureIndex(ref result.texture_list.texture_file, x)); result.bone_list = ConvertBoneList(pmd); result.morph_list = ConvertMorphList(pmd); result.display_frame_list = ConvertDisplayFrameList(pmd); result.rigidbody_list = ConvertRigidbodyList(pmd); result.rigidbody_joint_list = ConvertRigidbodyJointList(pmd); return result; }
/// <summary> /// PMXファイルの取得 /// </summary> /// <param name='pmd'>PMDファイル</param> /// <returns>内部形式データ</returns> public static PMXFormat PMD2PMX(PMDFormat pmd) { PMXFormat result = new PMXFormat(); result.meta_header = CreateMetaHeader(pmd); result.header = ConvertHeader(pmd.head, pmd.eg_head, pmd); result.vertex_list = ConvertVertexList(pmd); result.face_vertex_list = ConvertFaceVertexList(pmd); result.texture_list = ConvertTextureList(pmd); result.material_list = ConvertMaterialList(pmd, x => CreateTextureIndex(ref result.texture_list.texture_file, x)); result.bone_list = ConvertBoneList(pmd); result.morph_list = ConvertMorphList(pmd); result.display_frame_list = ConvertDisplayFrameList(pmd); result.rigidbody_list = ConvertRigidbodyList(pmd); result.rigidbody_joint_list = ConvertRigidbodyJointList(pmd); return(result); }
/// <summary> /// PMDファイルの取得 /// </summary> /// <param name='pmx'>PMXファイル</param> /// <returns>内部形式データ</returns> public static PMDFormat PMX2PMD(PMXFormat pmx) { PMDFormat result = new PMDFormat(); ConvertPathes(result, pmx); result.head = ConvertHeader(pmx.header); result.vertex_list = ConvertVertexList(pmx); result.face_vertex_list = ConvertFaceVertexList(pmx); result.material_list = ConvertMaterialList(pmx); result.bone_list = ConvertBoneList(pmx); result.ik_list = ConvertIKList(pmx); result.skin_list = ConvertSkinList(pmx); result.skin_name_list = ConvertSkinNameList(pmx); result.bone_name_list = ConvertBoneNameList(pmx); result.bone_display_list = ConvertBoneDisplayList(pmx); result.eg_head = ConvertEnglishHeader(pmx); result.eg_bone_name_list = ConvertEnglishBoneNameList(pmx); result.eg_skin_name_list = ConvertEnglishSkinNameList(pmx); result.eg_bone_display_list = ConvertEnglishBoneDisplayList(pmx); result.toon_texture_list = ConvertToonTextureList(pmx); result.rigidbody_list = ConvertRigidbodyList(pmx); result.rigidbody_joint_list = ConvertRigidbodyJointList(pmx); return result; }
/// <summary> /// PMDファイルの取得 /// </summary> /// <param name='pmx'>PMXファイル</param> /// <returns>内部形式データ</returns> public static PMDFormat PMX2PMD(PMXFormat pmx) { PMDFormat result = new PMDFormat(); ConvertPathes(result, pmx); result.head = ConvertHeader(pmx.header); result.vertex_list = ConvertVertexList(pmx); result.face_vertex_list = ConvertFaceVertexList(pmx); result.material_list = ConvertMaterialList(pmx); result.bone_list = ConvertBoneList(pmx); result.ik_list = ConvertIKList(pmx); result.skin_list = ConvertSkinList(pmx); result.skin_name_list = ConvertSkinNameList(pmx); result.bone_name_list = ConvertBoneNameList(pmx); result.bone_display_list = ConvertBoneDisplayList(pmx); result.eg_head = ConvertEnglishHeader(pmx); result.eg_bone_name_list = ConvertEnglishBoneNameList(pmx); result.eg_skin_name_list = ConvertEnglishSkinNameList(pmx); result.eg_bone_display_list = ConvertEnglishBoneDisplayList(pmx); result.toon_texture_list = ConvertToonTextureList(pmx); result.rigidbody_list = ConvertRigidbodyList(pmx); result.rigidbody_joint_list = ConvertRigidbodyJointList(pmx); return(result); }
private static PMXFormat.Header ConvertHeader(PMDFormat.Header pmd_header, PMDFormat.EnglishHeader pmd_english_header, PMDFormat pmd) { PMXFormat.Header result = new PMXFormat.Header(); result.magic = pmd_header.magic; result.version = pmd_header.version; result.dataSize = 0; result.encodeMethod = PMXFormat.Header.StringCode.Utf16le; result.additionalUV = 0; result.vertexIndexSize = PMXFormat.Header.IndexSize.Byte1; result.textureIndexSize = PMXFormat.Header.IndexSize.Byte1; result.materialIndexSize = PMXFormat.Header.IndexSize.Byte1; result.boneIndexSize = PMXFormat.Header.IndexSize.Byte1; result.morphIndexSize = PMXFormat.Header.IndexSize.Byte1; result.rigidbodyIndexSize = PMXFormat.Header.IndexSize.Byte1; if (null != pmd) { result.vertexIndexSize = GetIndexSize(pmd.vertex_list.vertex.Length); result.textureIndexSize = GetIndexSize(pmd.toon_texture_list.toon_texture_file.Length); result.materialIndexSize = GetIndexSize(pmd.material_list.material.Length); result.boneIndexSize = GetIndexSize(pmd.bone_list.bone.Length); result.morphIndexSize = GetIndexSize(pmd.skin_list.skin_data.Length); result.rigidbodyIndexSize = GetIndexSize(pmd.rigidbody_list.rigidbody.Length); } result.model_name = pmd_header.model_name; result.comment = pmd_header.comment; result.model_english_name = ""; result.english_comment = ""; if (null != pmd_english_header) { result.model_english_name = pmd_english_header.model_name_eg; result.english_comment = pmd_english_header.comment_eg; } else if (null != pmd) { result.model_english_name = pmd.eg_head.model_name_eg; result.english_comment = pmd.eg_head.comment_eg; } return result; }
private static PMXFormat.Header ConvertHeader(PMDFormat.Header pmd_header, PMDFormat.EnglishHeader pmd_english_header, PMDFormat pmd) { PMXFormat.Header result = new PMXFormat.Header(); result.magic = pmd_header.magic; result.version = pmd_header.version; result.dataSize = 0; result.encodeMethod = PMXFormat.Header.StringCode.Utf16le; result.additionalUV = 0; result.vertexIndexSize = PMXFormat.Header.IndexSize.Byte1; result.textureIndexSize = PMXFormat.Header.IndexSize.Byte1; result.materialIndexSize = PMXFormat.Header.IndexSize.Byte1; result.boneIndexSize = PMXFormat.Header.IndexSize.Byte1; result.morphIndexSize = PMXFormat.Header.IndexSize.Byte1; result.rigidbodyIndexSize = PMXFormat.Header.IndexSize.Byte1; if (null != pmd) { result.vertexIndexSize = GetIndexSize(pmd.vertex_list.vertex.Length); result.textureIndexSize = GetIndexSize(pmd.toon_texture_list.toon_texture_file.Length); result.materialIndexSize = GetIndexSize(pmd.material_list.material.Length); result.boneIndexSize = GetIndexSize(pmd.bone_list.bone.Length); result.morphIndexSize = GetIndexSize(pmd.skin_list.skin_data.Length); result.rigidbodyIndexSize = GetIndexSize(pmd.rigidbody_list.rigidbody.Length); } result.model_name = pmd_header.model_name; result.comment = pmd_header.comment; result.model_english_name = ""; result.english_comment = ""; if (null != pmd_english_header) { result.model_english_name = pmd_english_header.model_name_eg; result.english_comment = pmd_english_header.comment_eg; } else if (null != pmd) { result.model_english_name = pmd.eg_head.model_name_eg; result.english_comment = pmd.eg_head.comment_eg; } return(result); }
private static void ConvertPathes(PMDFormat pmd, PMXFormat pmx) { pmd.path = pmx.meta_header.path; pmd.name = pmx.meta_header.name; pmd.folder = pmx.meta_header.folder; }
// グループターゲット public int[] GetRigidbodyGroupTargets(PMDFormat format, GameObject[] rigids) { int[] result = new int[rigids.Length]; for (int i = 0; i < rigids.Length; i++) { result[i] = format.rigidbody_list.rigidbody[i].rigidbody_group_target; } return result; }
// ジョイントの設定 // ジョイントはボーンに対して適用される public void SettingJointComponent(PMDFormat format, GameObject[] bones, GameObject[] rigids) { // ConfigurableJointの設定 SetupConfigurableJoint(format, bones); // FixedJointの設定 SetupFixedJoint(format, bones); // ボーンを総なめして空のConfigurableJointが存在するか調べる NullTestConfigurableJoint(bones); }
// ConfigurableJointの値を設定する, addedは既に設定がある void SetAttributeConfigurableJoint(PMDFormat.Joint joint, ConfigurableJoint conf, bool added) { if (!added) { SetMotionAngularLock(joint, conf); SetDrive(joint, conf); } else { //Debug.Log("added"); } }
// 移動や回転制限 void SetMotionAngularLock(PMDFormat.Joint joint, ConfigurableJoint conf) { SoftJointLimit jlim; // Motionの固定 if (joint.constrain_pos_1.x == 0f && joint.constrain_pos_2.x == 0f) conf.xMotion = ConfigurableJointMotion.Locked; else conf.xMotion = ConfigurableJointMotion.Limited; if (joint.constrain_pos_1.y == 0f && joint.constrain_pos_2.y == 0f) conf.yMotion = ConfigurableJointMotion.Locked; else conf.yMotion = ConfigurableJointMotion.Limited; if (joint.constrain_pos_1.z == 0f && joint.constrain_pos_2.z == 0f) conf.zMotion = ConfigurableJointMotion.Locked; else conf.zMotion = ConfigurableJointMotion.Limited; // 角度の固定 if (joint.constrain_rot_1.x == 0f && joint.constrain_rot_2.x == 0f) conf.angularXMotion = ConfigurableJointMotion.Locked; else { conf.angularXMotion = ConfigurableJointMotion.Limited; float hlim = joint.constrain_rot_1.x > joint.constrain_rot_2.x ? joint.constrain_rot_1.x : joint.constrain_rot_2.x; float llim = joint.constrain_rot_1.x < joint.constrain_rot_2.x ? joint.constrain_rot_1.x : joint.constrain_rot_2.x; SoftJointLimit jhlim = new SoftJointLimit(); jhlim.limit = hlim * Mathf.Rad2Deg; conf.highAngularXLimit = jhlim; SoftJointLimit jllim = new SoftJointLimit(); jllim.limit = -llim * Mathf.Rad2Deg; conf.lowAngularXLimit = jllim; } if (joint.constrain_rot_1.y == 0f && joint.constrain_rot_2.y == 0f) conf.angularYMotion = ConfigurableJointMotion.Locked; else { // 値がマイナスだとエラーが出るので注意 conf.angularYMotion = ConfigurableJointMotion.Limited; float lim = joint.constrain_rot_1.y > joint.constrain_rot_2.y ? joint.constrain_rot_1.y : joint.constrain_rot_2.y; jlim = new SoftJointLimit(); jlim.limit = lim * Mathf.Rad2Deg; conf.angularYLimit = jlim; } if (joint.constrain_rot_1.z == 0f && joint.constrain_rot_2.z == 0f) conf.angularZMotion = ConfigurableJointMotion.Locked; else { conf.angularZMotion = ConfigurableJointMotion.Limited; float lim = joint.constrain_rot_1.z > joint.constrain_rot_2.z ? joint.constrain_rot_1.z : joint.constrain_rot_2.z; jlim = new SoftJointLimit(); jlim.limit = lim * Mathf.Rad2Deg; conf.angularZLimit = jlim; } }
void SearchEqualJoint(PMDFormat format, int jointIndex, GameObject[] bones) { // 対象のJointに親のジョイントがいなければ末端のジョイント // 対象のJointの接続剛体Aが差している関連ボーンにFixedJointを設定する if (jointIndex == ushort.MaxValue) return; // 存在しない値の場合は飛ばす PMDFormat.Joint targetJoint = format.rigidbody_joint_list.joint[jointIndex]; for (int connectRigidAJoint = 0; connectRigidAJoint < format.rigidbody_joint_list.joint_count; connectRigidAJoint++) { if (connectRigidAJoint == ushort.MaxValue) continue; PMDFormat.Joint parentJoint = format.rigidbody_joint_list.joint[connectRigidAJoint]; if (targetJoint.joint_rigidbody_a == parentJoint.joint_rigidbody_b) { // targetJointが末端のジョイントだったのでFixedJointを追加する PMDFormat.Rigidbody tailRigid = format.rigidbody_list.rigidbody[targetJoint.joint_rigidbody_a]; int parentIndex = format.bone_list.bone[tailRigid.rigidbody_rel_bone_index].parent_bone_index; // 既にジョイントが追加されている場合は抜ける ConfigurableJoint c = bones[parentIndex].GetComponent<ConfigurableJoint>(); if (c != null) break; FixedJoint j = bones[parentIndex].GetComponent<FixedJoint>(); if (j != null) break; var joint = bones[parentIndex].AddComponent<FixedJoint>(); // 対象の親ボーンにFixed bones[parentIndex].GetComponent<Rigidbody>().isKinematic = true; return; } } }
// Sphere Colliderの設定 Collider EntrySphereCollider(PMDFormat.Rigidbody rigid, GameObject obj) { SphereCollider collider = obj.AddComponent<SphereCollider>(); collider.radius = rigid.shape_w; return collider; }
// ConfigurableJointの値を設定する void SetAttributeConfigurableJoint(PMDFormat.Joint joint, ConfigurableJoint conf) { SetMotionAngularLock(joint, conf); SetDrive(joint, conf); }
private static PMXFormat.VertexList ConvertVertexList(PMDFormat pmd) { PMXFormat.VertexList result = new PMXFormat.VertexList(); result.vertex = pmd.vertex_list.vertex.Select(x => ConvertVertex(x)).ToArray(); return(result); }
// 移動や回転制限 void SetMotionAngularLock(PMDFormat.Joint joint, ConfigurableJoint conf) { SoftJointLimit jlim; // Motionの固定 if (joint.constrain_pos_1.x == 0f && joint.constrain_pos_2.x == 0f) conf.xMotion = ConfigurableJointMotion.Locked; else conf.xMotion = ConfigurableJointMotion.Limited; if (joint.constrain_pos_1.y == 0f && joint.constrain_pos_2.y == 0f) conf.yMotion = ConfigurableJointMotion.Locked; else conf.yMotion = ConfigurableJointMotion.Limited; if (joint.constrain_pos_1.z == 0f && joint.constrain_pos_2.z == 0f) conf.zMotion = ConfigurableJointMotion.Locked; else conf.zMotion = ConfigurableJointMotion.Limited; // 角度の固定 if (joint.constrain_rot_1.x == 0f && joint.constrain_rot_2.x == 0f) conf.angularXMotion = ConfigurableJointMotion.Locked; else { conf.angularXMotion = ConfigurableJointMotion.Limited; float hlim = Mathf.Max(-joint.constrain_rot_1.x, -joint.constrain_rot_2.x); //回転方向が逆なので負数 float llim = Mathf.Min(-joint.constrain_rot_1.x, -joint.constrain_rot_2.x); SoftJointLimit jhlim = new SoftJointLimit(); jhlim.limit = Mathf.Clamp(hlim * Mathf.Rad2Deg, -180.0f, 180.0f); conf.highAngularXLimit = jhlim; SoftJointLimit jllim = new SoftJointLimit(); jllim.limit = Mathf.Clamp(llim * Mathf.Rad2Deg, -180.0f, 180.0f); conf.lowAngularXLimit = jllim; } if (joint.constrain_rot_1.y == 0f && joint.constrain_rot_2.y == 0f) conf.angularYMotion = ConfigurableJointMotion.Locked; else { // 値がマイナスだとエラーが出るので注意 conf.angularYMotion = ConfigurableJointMotion.Limited; float lim = Mathf.Min(Mathf.Abs(joint.constrain_rot_1.y), Mathf.Abs(joint.constrain_rot_2.y));//絶対値の小さい方 jlim = new SoftJointLimit(); jlim.limit = lim * Mathf.Clamp(Mathf.Rad2Deg, 0.0f, 180.0f); conf.angularYLimit = jlim; } if (joint.constrain_rot_1.z == 0f && joint.constrain_rot_2.z == 0f) conf.angularZMotion = ConfigurableJointMotion.Locked; else { conf.angularZMotion = ConfigurableJointMotion.Limited; float lim = Mathf.Min(Mathf.Abs(-joint.constrain_rot_1.z), Mathf.Abs(-joint.constrain_rot_2.z));//絶対値の小さい方//回転方向が逆なので負数 jlim = new SoftJointLimit(); jlim.limit = Mathf.Clamp(lim * Mathf.Rad2Deg, 0.0f, 180.0f); conf.angularZLimit = jlim; } }
private GameObject CreateGameObject_(PMDFormat format, ShaderType shader_type, bool use_rigidbody, bool use_mecanim, bool use_ik, float scale) { format_ = format; shader_type_ = shader_type; use_rigidbody_ = use_rigidbody; use_mecanim_ = use_mecanim; use_ik_ = use_ik; scale_ = scale; root_game_object_ = new GameObject(format_.name); Mesh mesh = CreateMesh(); // メッシュの生成・設定 Material[] materials = CreateMaterials(); // マテリアルの生成・設定 GameObject[] bones = CreateBones(); // ボーンの生成・設定 // バインドポーズの作成 BuildingBindpose(mesh, materials, bones); MMDEngine engine = root_game_object_.AddComponent<MMDEngine>(); //スケール・エッジ幅 engine.scale = scale_; engine.outline_width = default_outline_width; engine.material_outline_widths = Enumerable.Repeat(1.0f, materials.Length).ToArray(); // IKの登録 if (use_ik_) engine.ik_list = EntryIKSolver(bones); // 剛体関連 if (use_rigidbody_) { try { var rigids = CreateRigids(bones); AssignRigidbodyToBone(bones, rigids); SetRigidsSettings(bones, rigids); GameObject[] joints = SettingJointComponent(bones, rigids); GlobalizeRigidbody(joints); // 非衝突グループ List<int>[] ignoreGroups = SettingIgnoreRigidGroups(rigids); int[] groupTarget = GetRigidbodyGroupTargets(rigids); MMDEngine.Initialize(engine, groupTarget, ignoreGroups, rigids); } catch { } } // Mecanim設定 if (use_mecanim_) { AvatarSettingScript avatar_setting = new AvatarSettingScript(root_game_object_, bones); avatar_setting.SettingHumanAvatar(); string path = format_.folder + "/"; string name = GetFilePathString(format_.name); string file_name = path + name + ".avatar.asset"; avatar_setting.CreateAsset(file_name); } else { root_game_object_.AddComponent<Animation>(); // アニメーション追加 } return root_game_object_; }
/// <summary> /// GameObjectを作成する /// </summary> /// <param name='format'>内部形式データ</param> /// <param name='shader_type'>シェーダーの種類</param> /// <param name='use_rigidbody'>剛体を使用するか</param> /// <param name='use_mecanim'>Mecanimを使用するか</param> /// <param name='use_ik'>IKを使用するか</param> /// <param name='scale'>スケール</param> public static GameObject CreateGameObject(PMDFormat format, ShaderType shader_type, bool use_rigidbody, bool use_mecanim, bool use_ik, float scale) { PMDConverter converter = new PMDConverter(); return converter.CreateGameObject_(format, shader_type, use_rigidbody, use_mecanim, use_ik, scale); }
// 関連ボーンなしの剛体から親のボーンを探してくる // rigidIndexは剛体番号 int GetTargetRigidBone(int rigidIndex, PMDFormat format) { // 接続剛体Aを探す int targetRigid = SearchConnectRigidA(rigidIndex, format); // 接続剛体Aの関連ボーンを探す int ind = format.rigidbody_list.rigidbody[targetRigid].rigidbody_rel_bone_index; // MaxValueを引けば接続剛体Aの関連ボーンに接続されるようになっている if (ind >= ushort.MaxValue) format.rigidbody_list.rigidbody[rigidIndex].rigidbody_rel_bone_index = ushort.MaxValue + (ushort)ind; return (int)ind; }
// Capsule Colliderの設定 Collider EntryCapsuleCollider(PMDFormat.Rigidbody rigid, GameObject obj) { CapsuleCollider collider = obj.AddComponent<CapsuleCollider>(); collider.radius = rigid.shape_w; collider.height = rigid.shape_h + rigid.shape_w * 2; return collider; }
// 剛体ボーンを public void AssignRigidbodyToBone(PMDFormat format, GameObject[] bones, GameObject[] rigids) { // 剛体の数だけ回す for (int i = 0; i < rigids.Length; i++) { // 剛体を親ボーンに格納 int refIndex = format.rigidbody_list.rigidbody[i].rigidbody_rel_bone_index; if (refIndex != ushort.MaxValue) { // 65535が最大値 rigids[i].transform.parent = bones[refIndex].transform; } else { // ジョイントから接続剛体B=現在の剛体名で探し出す int boneIndex = GetTargetRigidBone(i, format); // 接続剛体Aの関連ボーンに剛体を接続 rigids[i].transform.parent = bones[boneIndex].transform; } } }
// 物理素材の定義 PhysicMaterial CreatePhysicMaterial(PMDFormat format, PMDFormat.Rigidbody rigid) { PhysicMaterial material = new PhysicMaterial(format.name + "_r" + rigid.rigidbody_name); material.bounciness = rigid.rigidbody_recoil; material.staticFriction = rigid.rigidbody_friction; material.dynamicFriction = rigid.rigidbody_friction; AssetDatabase.CreateAsset(material, format.folder + "/Physics/" + material.name + ".asset"); return material; }
// FixedJointの設定 void SetupFixedJoint(PMDFormat format, GameObject[] bones) { // 全てのJointを探索する for (int jointIndex = 0; jointIndex < format.rigidbody_joint_list.joint_count; jointIndex++) { SearchEqualJoint(format, jointIndex, bones); } }
// Unity側のRigidbodyの設定を行う void UnityRigidbodySetting(PMDFormat.Rigidbody rigidbody, GameObject targetBone, bool setted=false) { // rigidbodyの調整 if (!setted) { targetBone.rigidbody.isKinematic = rigidbody.rigidbody_type != 0 ? false : true; targetBone.rigidbody.mass = rigidbody.rigidbody_weight; targetBone.rigidbody.drag = rigidbody.rigidbody_pos_dim; targetBone.rigidbody.angularDrag = rigidbody.rigidbody_rot_dim; } else { // Rigidbodyはボーンに対して適用されるので複数ある場合は平均を取る targetBone.rigidbody.mass += rigidbody.rigidbody_weight; targetBone.rigidbody.drag += rigidbody.rigidbody_pos_dim; targetBone.rigidbody.angularDrag += rigidbody.rigidbody_rot_dim; targetBone.rigidbody.mass *= 0.5f; targetBone.rigidbody.drag *= 0.5f; targetBone.rigidbody.angularDrag *= 0.5f; } }
// ばねの設定など void SetDrive(PMDFormat.Joint joint, ConfigurableJoint conf) { JointDrive drive; // Position if (joint.spring_pos.x != 0f) { drive = new JointDrive(); drive.positionSpring = joint.spring_pos.x; conf.xDrive = drive; } if (joint.spring_pos.y != 0f) { drive = new JointDrive(); drive.positionSpring = joint.spring_pos.y; conf.yDrive = drive; } if (joint.spring_pos.z != 0f) { drive = new JointDrive(); drive.positionSpring = joint.spring_pos.z; conf.zDrive = drive; } // Angular if (joint.spring_rot.x != 0f) { drive = new JointDrive(); drive.mode = JointDriveMode.PositionAndVelocity; drive.positionSpring = joint.spring_rot.x; conf.angularXDrive = drive; } if (joint.spring_rot.y != 0f || joint.spring_rot.z != 0f) { drive = new JointDrive(); drive.mode = JointDriveMode.PositionAndVelocity; drive.positionSpring = (joint.spring_rot.y + joint.spring_rot.z) * 0.5f; conf.angularYZDrive = drive; } }
// 剛体の値を代入する public void SetRigidsSettings(PMDFormat format, GameObject[] bones, GameObject[] rigid) { PMDFormat.RigidbodyList list = format.rigidbody_list; for (int i = 0; i < list.rigidbody_count; i++) // iは剛体番号 { // 剛体の関連ボーンのインデックス int rigidRefIndex = list.rigidbody[i].rigidbody_rel_bone_index; // ローカル座標の確定 Vector3 localPos = list.rigidbody[i].pos_pos;// - rigid[i].transform.position; // ここで位置の決定 if (rigidRefIndex >= ushort.MaxValue) { // indexが見つからない場合、関連ボーンが存在しないのでなんとかする // 関連ボーンなしの剛体はセンターボーンに接続している rigid[i].transform.position = localPos + format.bone_list.bone[0].bone_head_pos; } else { // とりあえずここで剛体を追加・設定 if (bones[rigidRefIndex].rigidbody == null) bones[rigidRefIndex].AddComponent<Rigidbody>(); UnityRigidbodySetting(list.rigidbody[i], bones[rigidRefIndex]); rigid[i].transform.localPosition = localPos; } // 回転の値を決める Vector3 rot = list.rigidbody[i].pos_rot * Mathf.Rad2Deg; rigid[i].transform.rotation = Quaternion.Euler(rot); } }
// ConfigurableJointの設定 // 先に設定してからFixedJointを設定する void SetupConfigurableJoint(PMDFormat format, GameObject[] bones) { for (int jointIndex = 0; jointIndex < format.rigidbody_joint_list.joint_count; jointIndex++) { PMDFormat.Joint joint = format.rigidbody_joint_list.joint[jointIndex]; ConfigurableJoint configurate = null; int jointedBone = format.rigidbody_list.rigidbody[joint.joint_rigidbody_b].rigidbody_rel_bone_index; if (jointedBone >= ushort.MaxValue) { // ボーンがないので飛ばす continue; } else { configurate = bones[jointedBone].GetComponent<ConfigurableJoint>(); if (configurate != null) { // すでに追加されていた場合 SetAttributeConfigurableJoint(joint, configurate, true); continue; } configurate = bones[jointedBone].AddComponent<ConfigurableJoint>(); SetAttributeConfigurableJoint(joint, configurate, false); // ここでジョイントに接続するrigidbodyを設定 configurate.connectedBody = GetParentBone(bones, bones[jointedBone]).rigidbody; // nullってたら自動的に親ボーンの剛体に設定する //NullTestJointForRigid(configurate, bones[jointedBone]); } } }
// 非衝突剛体の設定 public List<int>[] SettingIgnoreRigidGroups(PMDFormat format, GameObject[] rigids) { // 非衝突グループ用リストの初期化 const int MaxGroup = 16; // グループの最大数 List<int>[] ignoreRigid = new List<int>[MaxGroup]; for (int i = 0; i < 16; i++) ignoreRigid[i] = new List<int>(); // それぞれの剛体が所属している非衝突グループを追加していく PMDFormat.RigidbodyList list = format.rigidbody_list; for (int i = 0; i < list.rigidbody_count; i++) ignoreRigid[list.rigidbody[i].rigidbody_group_index].Add(i); // リジッドボディのチェック for (int i = 0; i < list.rigidbody_count; i++) { PMDFormat.Rigidbody rigid = list.rigidbody[i]; for (int shift = 0; shift < MaxGroup; shift++) { // フラグチェック if ((rigid.rigidbody_group_target & (1 << shift)) == (1 << shift)) { foreach (var rig in ignoreRigid[shift]) { if (i == rig) continue; Physics.IgnoreCollision(rigids[i].collider, rigids[rig].collider, true); } } } } return ignoreRigid; }
private GameObject CreateGameObject_(PMDFormat format, ShaderType shader_type, bool use_rigidbody, bool use_mecanim, bool use_ik, float scale) { format_ = format; shader_type_ = shader_type; use_rigidbody_ = use_rigidbody; use_mecanim_ = use_mecanim; use_ik_ = use_ik; scale_ = scale; root_game_object_ = new GameObject(format_.name); Mesh mesh = CreateMesh(); // メッシュの生成・設定 Material[] materials = CreateMaterials(); // マテリアルの生成・設定 GameObject[] bones = CreateBones(); // ボーンの生成・設定 // バインドポーズの作成 BuildingBindpose(mesh, materials, bones); MMDEngine engine = root_game_object_.AddComponent <MMDEngine>(); //スケール・エッジ幅 engine.scale = scale_; engine.outline_width = default_outline_width; engine.material_outline_widths = Enumerable.Repeat(1.0f, materials.Length).ToArray(); // IKの登録 if (use_ik_) { engine.ik_list = EntryIKSolver(bones); } // 剛体関連 if (use_rigidbody_) { try { var rigids = CreateRigids(bones); AssignRigidbodyToBone(bones, rigids); SetRigidsSettings(bones, rigids); GameObject[] joints = SettingJointComponent(bones, rigids); GlobalizeRigidbody(joints); // 非衝突グループ List <int>[] ignoreGroups = SettingIgnoreRigidGroups(rigids); int[] groupTarget = GetRigidbodyGroupTargets(rigids); MMDEngine.Initialize(engine, groupTarget, ignoreGroups, rigids); } catch { } } // Mecanim設定 if (use_mecanim_) { AvatarSettingScript avatar_setting = new AvatarSettingScript(root_game_object_, bones); avatar_setting.SettingHumanAvatar(); string path = format_.folder + "/"; string name = GetFilePathString(format_.name); string file_name = path + name + ".avatar.asset"; avatar_setting.CreateAsset(file_name); } else { root_game_object_.AddComponent <Animation>(); // アニメーション追加 } return(root_game_object_); }
private static PMXFormat.RigidbodyJointList ConvertRigidbodyJointList(PMDFormat pmx) { PMXFormat.RigidbodyJointList result = new PMXFormat.RigidbodyJointList(); result.joint = pmx.rigidbody_joint_list.joint.Select(x => ConvertJoint(x)).ToArray(); return(result); }
private static PMXFormat.TextureList ConvertTextureList(PMDFormat pmd) { PMXFormat.TextureList result = new PMXFormat.TextureList(); result.texture_file = pmd.toon_texture_list.toon_texture_file.ToArray(); //複製する return(result); }
// 剛体の生成 public GameObject[] CreateRigids(PMDFormat format, GameObject[] bones) { PMDFormat.RigidbodyList list = format.rigidbody_list; AssetDatabase.CreateFolder(format.folder, "Physics"); // 剛体の登録 GameObject[] rigid = new GameObject[list.rigidbody_count]; for (int i = 0; i < list.rigidbody_count; i++) { rigid[i] = new GameObject("r" + list.rigidbody[i].rigidbody_name); //rigid[i].AddComponent<Rigidbody>(); // 剛体本体にはrigidbodyは適用しない // 各種Colliderの設定 Collider collider = null; switch (list.rigidbody[i].shape_type) { case 0: collider = EntrySphereCollider(list.rigidbody[i], rigid[i]); break; case 1: collider = EntryBoxCollider(list.rigidbody[i], rigid[i]); break; case 2: collider = EntryCapsuleCollider(list.rigidbody[i], rigid[i]); break; } // マテリアルの設定 collider.material = CreatePhysicMaterial(format, list.rigidbody[i]); } return rigid; }
private static PMXFormat.FaceVertexList ConvertFaceVertexList(PMDFormat pmd) { PMXFormat.FaceVertexList result = new PMXFormat.FaceVertexList(); result.face_vert_index = pmd.face_vertex_list.face_vert_index.Select(x => (uint)x).ToArray(); return(result); }
/// <summary> /// GameObjectを作成する /// </summary> /// <param name='format'>内部形式データ</param> /// <param name='shader_type'>シェーダーの種類</param> /// <param name='use_rigidbody'>剛体を使用するか</param> /// <param name='use_mecanim'>Mecanimを使用するか</param> /// <param name='use_ik'>IKを使用するか</param> /// <param name='scale'>スケール</param> public static GameObject CreateGameObject(PMDFormat format, ShaderType shader_type, bool use_rigidbody, bool use_mecanim, bool use_ik, float scale) { PMDConverter converter = new PMDConverter(); return(converter.CreateGameObject_(format, shader_type, use_rigidbody, use_mecanim, use_ik, scale)); }
// 接続剛体Bの番号と一致するJointを探し出す int SearchConnectJointByConnectB(int connectBIndex, PMDFormat format) { for (int i = 0; i < format.rigidbody_joint_list.joint_count; i++) { if (format.rigidbody_joint_list.joint[i].joint_rigidbody_b == connectBIndex) return i; } return -1; }
// Box Colliderの設定 Collider EntryBoxCollider(PMDFormat.Rigidbody rigid, GameObject obj) { BoxCollider collider = obj.AddComponent<BoxCollider>(); collider.size = new Vector3( rigid.shape_w * 2f, rigid.shape_h * 2f, rigid.shape_d * 2f); return collider; }
// 接続剛体Aの剛体番号を検索する int SearchConnectRigidA(int rigidIndex, PMDFormat format) { // ジョイントから接続剛体B=現在の剛体名で探し出す int jointB; for (jointB = 0; jointB < format.rigidbody_joint_list.joint_count; jointB++) { if (format.rigidbody_joint_list.joint[jointB].joint_rigidbody_b == rigidIndex) { break; } } // targetRigidは接続剛体A return (int)format.rigidbody_joint_list.joint[jointB].joint_rigidbody_a; }