ModelUtility.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. using System.IO;
  2. using System.Text;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEngine.Rendering;
  6. using System;
  7. using System.Linq;
  8. using Object = UnityEngine.Object;
  9. namespace COM3D2.MeidoPhotoStudio.Plugin
  10. {
  11. public static partial class MenuFileUtility
  12. {
  13. private static GameObject CreateSeed() => Object.Instantiate(Resources.Load<GameObject>("seed"));
  14. private static bool InstantiateModel(string modelFilename, out GameObject modelParent)
  15. {
  16. byte[] buffer;
  17. modelParent = default;
  18. try { buffer = ReadAFileBase(modelFilename); }
  19. catch
  20. {
  21. Utility.LogError($"Could not load model file '{modelFilename}'");
  22. return false;
  23. }
  24. using var binaryReader = new BinaryReader(new MemoryStream(buffer), Encoding.UTF8);
  25. if (binaryReader.ReadString() != "CM3D2_MESH")
  26. {
  27. Utility.LogError($"{modelFilename} is not a model file");
  28. return false;
  29. }
  30. var modelVersion = binaryReader.ReadInt32();
  31. var modelName = binaryReader.ReadString();
  32. modelParent = CreateSeed();
  33. modelParent.layer = 1;
  34. modelParent.name = "_SM_" + modelName;
  35. var rootName = binaryReader.ReadString();
  36. var boneCount = binaryReader.ReadInt32();
  37. var boneDict = new Dictionary<string, GameObject>();
  38. var boneList = new List<GameObject>(boneCount);
  39. GameObject rootBone = null;
  40. try
  41. {
  42. // read bone data
  43. for (var i = 0; i < boneCount; i++)
  44. {
  45. GameObject bone = CreateSeed();
  46. bone.layer = 1;
  47. bone.name = binaryReader.ReadString();
  48. if (binaryReader.ReadByte() != 0)
  49. {
  50. GameObject otherBone = CreateSeed();
  51. otherBone.name = bone.name + "_SCL_";
  52. otherBone.transform.parent = bone.transform;
  53. boneDict[bone.name + "$_SCL_"] = otherBone;
  54. }
  55. boneList.Add(bone);
  56. boneDict[bone.name] = bone;
  57. if (bone.name == rootName) rootBone = bone;
  58. }
  59. for (var i = 0; i < boneCount; i++)
  60. {
  61. var parentIndex = binaryReader.ReadInt32();
  62. boneList[i].transform.parent = parentIndex >= 0
  63. ? boneList[parentIndex].transform
  64. : modelParent.transform;
  65. }
  66. for (var i = 0; i < boneCount; i++)
  67. {
  68. Transform transform = boneList[i].transform;
  69. transform.localPosition = binaryReader.ReadVector3();
  70. transform.localRotation = binaryReader.ReadQuaternion();
  71. if (modelVersion >= 2001 && binaryReader.ReadBoolean())
  72. transform.localScale = binaryReader.ReadVector3();
  73. }
  74. // read mesh data
  75. var meshRenderer = rootBone.AddComponent<SkinnedMeshRenderer>();
  76. meshRenderer.updateWhenOffscreen = true;
  77. meshRenderer.skinnedMotionVectors = false;
  78. meshRenderer.lightProbeUsage = LightProbeUsage.Off;
  79. meshRenderer.reflectionProbeUsage = ReflectionProbeUsage.Off;
  80. meshRenderer.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion;
  81. Mesh sharedMesh = meshRenderer.sharedMesh = new Mesh();
  82. var vertCount = binaryReader.ReadInt32();
  83. var subMeshCount = binaryReader.ReadInt32();
  84. var meshBoneCount = binaryReader.ReadInt32();
  85. var meshBones = new Transform[meshBoneCount];
  86. for (var i = 0; i < meshBoneCount; i++)
  87. {
  88. var boneName = binaryReader.ReadString();
  89. if (!boneDict.ContainsKey(boneName)) Debug.LogError("nullbone= " + boneName);
  90. else
  91. {
  92. var keyName = boneName + "$_SCL_";
  93. GameObject bone = boneDict.ContainsKey(keyName) ? boneDict[keyName] : boneDict[boneName];
  94. meshBones[i] = bone.transform;
  95. }
  96. }
  97. meshRenderer.bones = meshBones;
  98. var bindPoses = new Matrix4x4[meshBoneCount];
  99. for (var i = 0; i < meshBoneCount; i++) bindPoses[i] = binaryReader.ReadMatrix4x4();
  100. sharedMesh.bindposes = bindPoses;
  101. var vertices = new Vector3[vertCount];
  102. var normals = new Vector3[vertCount];
  103. var uv = new Vector2[vertCount];
  104. for (var i = 0; i < vertCount; i++)
  105. {
  106. vertices[i] = binaryReader.ReadVector3();
  107. normals[i] = binaryReader.ReadVector3();
  108. uv[i] = binaryReader.ReadVector2();
  109. }
  110. sharedMesh.vertices = vertices;
  111. sharedMesh.normals = normals;
  112. sharedMesh.uv = uv;
  113. var tangentCount = binaryReader.ReadInt32();
  114. if (tangentCount > 0)
  115. {
  116. var tangents = new Vector4[tangentCount];
  117. for (var i = 0; i < tangentCount; i++) tangents[i] = binaryReader.ReadVector4();
  118. sharedMesh.tangents = tangents;
  119. }
  120. var boneWeights = new BoneWeight[vertCount];
  121. for (var i = 0; i < vertCount; i++)
  122. {
  123. boneWeights[i].boneIndex0 = binaryReader.ReadUInt16();
  124. boneWeights[i].boneIndex1 = binaryReader.ReadUInt16();
  125. boneWeights[i].boneIndex2 = binaryReader.ReadUInt16();
  126. boneWeights[i].boneIndex3 = binaryReader.ReadUInt16();
  127. boneWeights[i].weight0 = binaryReader.ReadSingle();
  128. boneWeights[i].weight1 = binaryReader.ReadSingle();
  129. boneWeights[i].weight2 = binaryReader.ReadSingle();
  130. boneWeights[i].weight3 = binaryReader.ReadSingle();
  131. }
  132. sharedMesh.boneWeights = boneWeights;
  133. sharedMesh.subMeshCount = subMeshCount;
  134. for (var i = 0; i < subMeshCount; i++)
  135. {
  136. var pointCount = binaryReader.ReadInt32();
  137. var triangles = new int[pointCount];
  138. for (var j = 0; j < pointCount; j++) triangles[j] = binaryReader.ReadUInt16();
  139. sharedMesh.SetTriangles(triangles, i);
  140. }
  141. // read materials
  142. var materialCount = binaryReader.ReadInt32();
  143. var materials = new Material[materialCount];
  144. for (var i = 0; i < materialCount; i++) materials[i] = ImportCM.ReadMaterial(binaryReader);
  145. meshRenderer.materials = materials;
  146. modelParent.AddComponent<Animation>();
  147. return true;
  148. }
  149. catch (Exception e)
  150. {
  151. Utility.LogError($"Could not load mesh for '{modelFilename}' because {e.Message}\n{e.StackTrace}");
  152. foreach (GameObject bone in boneList.Where(bone => bone)) Object.Destroy(bone);
  153. if (modelParent) Object.Destroy(modelParent);
  154. modelParent = null;
  155. return false;
  156. }
  157. }
  158. }
  159. }