123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- using System.IO;
- using System.Text;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.Rendering;
- using System;
- using System.Linq;
- using Object = UnityEngine.Object;
- namespace COM3D2.MeidoPhotoStudio.Plugin
- {
- public static partial class MenuFileUtility
- {
- private static GameObject CreateSeed() => Object.Instantiate(Resources.Load<GameObject>("seed"));
- private static bool InstantiateModel(string modelFilename, out GameObject modelParent)
- {
- byte[] buffer;
- modelParent = default;
- try { buffer = ReadAFileBase(modelFilename); }
- catch
- {
- Utility.LogError($"Could not load model file '{modelFilename}'");
- return false;
- }
-
- using var binaryReader = new BinaryReader(new MemoryStream(buffer), Encoding.UTF8);
- if (binaryReader.ReadString() != "CM3D2_MESH")
- {
- Utility.LogError($"{modelFilename} is not a model file");
- return false;
- }
- var modelVersion = binaryReader.ReadInt32();
- var modelName = binaryReader.ReadString();
-
- modelParent = CreateSeed();
- modelParent.layer = 1;
- modelParent.name = "_SM_" + modelName;
-
- var rootName = binaryReader.ReadString();
- var boneCount = binaryReader.ReadInt32();
- var boneDict = new Dictionary<string, GameObject>();
- var boneList = new List<GameObject>(boneCount);
- GameObject rootBone = null;
- try
- {
- // read bone data
- for (var i = 0; i < boneCount; i++)
- {
- GameObject bone = CreateSeed();
- bone.layer = 1;
- bone.name = binaryReader.ReadString();
- if (binaryReader.ReadByte() != 0)
- {
- GameObject otherBone = CreateSeed();
- otherBone.name = bone.name + "_SCL_";
- otherBone.transform.parent = bone.transform;
- boneDict[bone.name + "$_SCL_"] = otherBone;
- }
- boneList.Add(bone);
- boneDict[bone.name] = bone;
- if (bone.name == rootName) rootBone = bone;
- }
- for (var i = 0; i < boneCount; i++)
- {
- var parentIndex = binaryReader.ReadInt32();
- boneList[i].transform.parent = parentIndex >= 0
- ? boneList[parentIndex].transform
- : modelParent.transform;
- }
- for (var i = 0; i < boneCount; i++)
- {
- Transform transform = boneList[i].transform;
- transform.localPosition = binaryReader.ReadVector3();
- transform.localRotation = binaryReader.ReadQuaternion();
- if (modelVersion >= 2001 && binaryReader.ReadBoolean())
- transform.localScale = binaryReader.ReadVector3();
- }
-
- // read mesh data
- var meshRenderer = rootBone.AddComponent<SkinnedMeshRenderer>();
- meshRenderer.updateWhenOffscreen = true;
- meshRenderer.skinnedMotionVectors = false;
- meshRenderer.lightProbeUsage = LightProbeUsage.Off;
- meshRenderer.reflectionProbeUsage = ReflectionProbeUsage.Off;
- meshRenderer.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion;
-
- Mesh sharedMesh = meshRenderer.sharedMesh = new Mesh();
-
- var vertCount = binaryReader.ReadInt32();
- var subMeshCount = binaryReader.ReadInt32();
- var meshBoneCount = binaryReader.ReadInt32();
- var meshBones = new Transform[meshBoneCount];
- for (var i = 0; i < meshBoneCount; i++)
- {
- var boneName = binaryReader.ReadString();
-
- if (!boneDict.ContainsKey(boneName)) Debug.LogError("nullbone= " + boneName);
- else
- {
- var keyName = boneName + "$_SCL_";
- GameObject bone = boneDict.ContainsKey(keyName) ? boneDict[keyName] : boneDict[boneName];
- meshBones[i] = bone.transform;
- }
- }
- meshRenderer.bones = meshBones;
- var bindPoses = new Matrix4x4[meshBoneCount];
- for (var i = 0; i < meshBoneCount; i++) bindPoses[i] = binaryReader.ReadMatrix4x4();
-
- sharedMesh.bindposes = bindPoses;
- var vertices = new Vector3[vertCount];
- var normals = new Vector3[vertCount];
- var uv = new Vector2[vertCount];
- for (var i = 0; i < vertCount; i++)
- {
- vertices[i] = binaryReader.ReadVector3();
- normals[i] = binaryReader.ReadVector3();
- uv[i] = binaryReader.ReadVector2();
- }
- sharedMesh.vertices = vertices;
- sharedMesh.normals = normals;
- sharedMesh.uv = uv;
- var tangentCount = binaryReader.ReadInt32();
- if (tangentCount > 0)
- {
- var tangents = new Vector4[tangentCount];
- for (var i = 0; i < tangentCount; i++) tangents[i] = binaryReader.ReadVector4();
- sharedMesh.tangents = tangents;
- }
- var boneWeights = new BoneWeight[vertCount];
- for (var i = 0; i < vertCount; i++)
- {
- boneWeights[i].boneIndex0 = binaryReader.ReadUInt16();
- boneWeights[i].boneIndex1 = binaryReader.ReadUInt16();
- boneWeights[i].boneIndex2 = binaryReader.ReadUInt16();
- boneWeights[i].boneIndex3 = binaryReader.ReadUInt16();
- boneWeights[i].weight0 = binaryReader.ReadSingle();
- boneWeights[i].weight1 = binaryReader.ReadSingle();
- boneWeights[i].weight2 = binaryReader.ReadSingle();
- boneWeights[i].weight3 = binaryReader.ReadSingle();
- }
- sharedMesh.boneWeights = boneWeights;
- sharedMesh.subMeshCount = subMeshCount;
- for (var i = 0; i < subMeshCount; i++)
- {
- var pointCount = binaryReader.ReadInt32();
- var triangles = new int[pointCount];
- for (var j = 0; j < pointCount; j++) triangles[j] = binaryReader.ReadUInt16();
- sharedMesh.SetTriangles(triangles, i);
- }
- // read materials
- var materialCount = binaryReader.ReadInt32();
- var materials = new Material[materialCount];
- for (var i = 0; i < materialCount; i++) materials[i] = ImportCM.ReadMaterial(binaryReader);
- meshRenderer.materials = materials;
- modelParent.AddComponent<Animation>();
- return true;
- }
- catch (Exception e)
- {
- Utility.LogError($"Could not load mesh for '{modelFilename}' because {e.Message}\n{e.StackTrace}");
- foreach (GameObject bone in boneList.Where(bone => bone)) Object.Destroy(bone);
- if (modelParent) Object.Destroy(modelParent);
- modelParent = null;
- return false;
- }
- }
- }
- }
|