//Load all the date into the object public M2 LoadModel(byte[] dataBytes, byte[] skinBytes, byte[] skelBytes) { M2 model = new M2(); model.LoadFile(dataBytes); model.Skin.LoadFile(skinBytes); model.Skeleton.LoadFile(model.SkelFileID == 0 ? dataBytes : skelBytes, model.SkelFileID); return(model); }
public override void OnImportAsset(UnityEditor.AssetImporters.AssetImportContext ctx) { //Load file contents M2 file = new M2(); file.LoadFile(ctx.assetPath); //Prepare blank asset GameObject model = new GameObject(); model.AddComponent <Animator>(); model.AddComponent <SkinnedMeshRenderer>(); SkinnedMeshRenderer renderer = model.GetComponent <SkinnedMeshRenderer>(); Mesh mesh = new Mesh(); mesh.name = file.Name + "_mesh"; //Fill vertex data Vector3[] vertices = new Vector3[file.Vertices.Length]; Vector3[] normals = new Vector3[file.Vertices.Length]; BoneWeight[] weights = new BoneWeight[file.Vertices.Length]; Vector2[] uv = new Vector2[file.Vertices.Length]; Vector2[] uv2 = new Vector2[file.Vertices.Length]; for (int i = 0; i < file.Vertices.Length; i++) { vertices[i] = new Vector3(-file.Vertices[i].Position.X / 2, file.Vertices[i].Position.Z / 2, -file.Vertices[i].Position.Y / 2); normals[i] = new Vector3(-file.Vertices[i].Normal.X, file.Vertices[i].Normal.Z, -file.Vertices[i].Normal.Y); BoneWeight weight = new BoneWeight { boneIndex0 = file.Vertices[i].Bones[0], boneIndex1 = file.Vertices[i].Bones[1], boneIndex2 = file.Vertices[i].Bones[2], boneIndex3 = file.Vertices[i].Bones[3], weight0 = file.Vertices[i].Weights[0] / 255f, weight1 = file.Vertices[i].Weights[1] / 255f, weight2 = file.Vertices[i].Weights[2] / 255f, weight3 = file.Vertices[i].Weights[3] / 255f }; weights[i] = weight; uv[i] = new Vector2(file.Vertices[i].UV[0].X, 1 - file.Vertices[i].UV[0].Y); uv2[i] = new Vector2(file.Vertices[i].UV[1].X, 1 - file.Vertices[i].UV[1].Y); } mesh.vertices = vertices; mesh.normals = normals; mesh.boneWeights = weights; mesh.uv = uv; mesh.uv2 = uv2; //Fill Submesh data mesh.subMeshCount = file.Skin.Submeshes.Length; for (int i = 0; i < mesh.subMeshCount; i++) { int[] triangles = new int[file.Skin.Submeshes[i].Count]; for (int j = 0; j < triangles.Length; j++) { triangles[j] = file.Skin.Indices[file.Skin.Submeshes[i].Start + j]; } mesh.SetTriangles(triangles, i); } //Generate bones Transform[] bones = new Transform[file.Skeleton.Bones.Length]; for (int i = 0; i < bones.Length; i++) { bones[i] = new GameObject("Bone" + i).transform; bones[i].position = new Vector3(-file.Skeleton.Bones[i].Pivot.X / 2, file.Skeleton.Bones[i].Pivot.Z / 2, -file.Skeleton.Bones[i].Pivot.Y / 2); } GameObject skeleton = new GameObject("Skeleton"); for (int i = 0; i < bones.Length; i++) { if (file.Skeleton.Bones[i].Parent == -1) { bones[i].parent = skeleton.transform; } else { bones[i].parent = bones[file.Skeleton.Bones[i].Parent]; } } Matrix4x4[] bind = new Matrix4x4[bones.Length]; for (int i = 0; i < bones.Length; i++) { bind[i] = bones[i].worldToLocalMatrix * model.transform.localToWorldMatrix; } skeleton.transform.parent = model.transform; renderer.materials = new Material[mesh.subMeshCount]; renderer.sharedMesh = mesh; renderer.bones = bones; renderer.rootBone = bones[0]; mesh.bindposes = bind; //Seralize data in json so they can be accessible at runtime TextAsset json = new TextAsset(JsonConvert.SerializeObject(file)); json.name = file.Name + "_data"; model.AddComponent <M2Model>(); model.GetComponent <M2Model>().json = json; //Fill particle effect data if (file.Particles.Length > 0) { GameObject[] particles = new GameObject[file.Particles.Length]; for (int i = 0; i < particles.Length; i++) { particles[i] = ParticleEffect(file.Particles[i]); particles[i].transform.parent = bones[file.Particles[i].Bone]; particles[i].transform.localPosition = Vector3.zero; particles[i].name = "Particle" + i; ctx.AddObjectToAsset(particles[i].name, particles[i]); } } //Populate the asset ctx.AddObjectToAsset(file.Name, model); ctx.AddObjectToAsset(mesh.name, mesh); ctx.AddObjectToAsset(skeleton.name, skeleton); ctx.AddObjectToAsset(json.name, json); }
public override void OnImportAsset(AssetImportContext ctx) { //Load file contents BoneLib.Bone file = new BoneLib.Bone(); file.LoadFile(ctx.assetPath); //Load skel file for reference M2 model = new M2(); model.LoadFile(ctx.assetPath.Substring(0, ctx.assetPath.Length - 8) + ".m2"); Skel skeleton = model.Skeleton; //Create empty animation clip AnimationClip clip = new AnimationClip(); AnimationCurve curve; Matrix4x4 matrix; Vector4[] columns = new Vector4[4]; float value; //Generate temporary bones Transform[] bones = new Transform[skeleton.Bones.Length]; for (int i = 0; i < bones.Length; i++) { bones[i] = new GameObject("Bone" + i).transform; bones[i].position = new Vector3(-skeleton.Bones[i].Pivot.X / 2, skeleton.Bones[i].Pivot.Z / 2, -skeleton.Bones[i].Pivot.Y / 2); } GameObject rig = new GameObject("Skeleton"); for (int i = 0; i < bones.Length; i++) { if (skeleton.Bones[i].Parent == -1) { bones[i].parent = rig.transform; } else { bones[i].parent = bones[skeleton.Bones[i].Parent]; } } //Fill animation data for each bone for (int i = 0; i < file.Bones.Length; i++) { string path = GetBonePath(skeleton.Bones[file.Bones[i]].Parent, skeleton.Bones) + "Bone" + file.Bones[i]; for (int j = 0; j < 4; j++) { columns[j] = new Vector4(file.Transformations[i][j][0], file.Transformations[i][j][1], file.Transformations[i][j][2], file.Transformations[i][j][3]); } matrix = new Matrix4x4(columns[0], columns[1], columns[2], columns[3]); value = -matrix.m03 / 2 + bones[file.Bones[i]].localPosition.x; curve = AnimationCurve.Linear(0f, value, 0.1f, value); clip.SetCurve(path, typeof(Transform), "localPosition.x", curve); value = matrix.m23 / 2 + bones[file.Bones[i]].localPosition.y; curve = AnimationCurve.Linear(0f, value, 0.1f, value); clip.SetCurve(path, typeof(Transform), "localPosition.y", curve); value = -matrix.m13 / 2 + bones[file.Bones[i]].localPosition.z; curve = AnimationCurve.Linear(0f, value, 0.1f, value); clip.SetCurve(path, typeof(Transform), "localPosition.z", curve); UnityEngine.Quaternion rotation = matrix.rotation; curve = AnimationCurve.Linear(0f, -rotation.x, 1f, rotation.x); clip.SetCurve(path, typeof(Transform), "localRotation.x", curve); curve = AnimationCurve.Linear(0f, -rotation.z, 0.1f, rotation.z); clip.SetCurve(path, typeof(Transform), "localRotation.y", curve); curve = AnimationCurve.Linear(0f, rotation.y, 0.1f, rotation.y); clip.SetCurve(path, typeof(Transform), "localRotation.z", curve); curve = AnimationCurve.Linear(0f, rotation.w, 0.1f, rotation.w); clip.SetCurve(path, typeof(Transform), "localRotation.w", curve); Vector3 scale = matrix.lossyScale; curve = AnimationCurve.Linear(0f, scale.x, 0.1f, scale.x); clip.SetCurve(path, typeof(Transform), "localScale.x", curve); curve = AnimationCurve.Linear(0f, scale.z, 0.1f, scale.z); clip.SetCurve(path, typeof(Transform), "localScale.y", curve); curve = AnimationCurve.Linear(0f, scale.y, 0.1f, scale.y); clip.SetCurve(path, typeof(Transform), "localScale.z", curve); } //Clear temporary bones and add animation clip to the asset DestroyImmediate(rig); ctx.AddObjectToAsset(Path.GetFileNameWithoutExtension(ctx.assetPath.Replace("/", "\\")), clip); }
public override void OnImportAsset(AssetImportContext ctx) { //Load file contents M2 file = new M2(); file.LoadFile(ctx.assetPath); //Prepare blank asset GameObject model = new GameObject(); model.AddComponent <Animator>(); model.AddComponent <SkinnedMeshRenderer>(); SkinnedMeshRenderer renderer = model.GetComponent <SkinnedMeshRenderer>(); Mesh mesh = new Mesh(); mesh.name = file.Name + "_mesh"; //Fill vertex data Vector3[] vertices = new Vector3[file.Vertices.Length]; Vector3[] normals = new Vector3[file.Vertices.Length]; BoneWeight[] weights = new BoneWeight[file.Vertices.Length]; Vector2[] uv = new Vector2[file.Vertices.Length]; Vector2[] uv2 = new Vector2[file.Vertices.Length]; for (int i = 0; i < file.Vertices.Length; i++) { vertices[i] = new Vector3(-file.Vertices[i].Position.X / 2, file.Vertices[i].Position.Z / 2, -file.Vertices[i].Position.Y / 2); normals[i] = new Vector3(-file.Vertices[i].Normal.X, file.Vertices[i].Normal.Z, -file.Vertices[i].Normal.Y); BoneWeight weight = new BoneWeight { boneIndex0 = file.Vertices[i].Bones[0], boneIndex1 = file.Vertices[i].Bones[1], boneIndex2 = file.Vertices[i].Bones[2], boneIndex3 = file.Vertices[i].Bones[3], weight0 = file.Vertices[i].Weights[0] / 255f, weight1 = file.Vertices[i].Weights[1] / 255f, weight2 = file.Vertices[i].Weights[2] / 255f, weight3 = file.Vertices[i].Weights[3] / 255f }; weights[i] = weight; uv[i] = new Vector2(file.Vertices[i].UV[0].X, 1 - file.Vertices[i].UV[0].Y); uv2[i] = new Vector2(file.Vertices[i].UV[1].X, 1 - file.Vertices[i].UV[1].Y); } mesh.vertices = vertices; mesh.normals = normals; mesh.boneWeights = weights; mesh.uv = uv; mesh.uv2 = uv2; //Fill Submesh data mesh.subMeshCount = file.Skin.Submeshes.Length; for (int i = 0; i < mesh.subMeshCount; i++) { int[] triangles = new int[file.Skin.Submeshes[i].Count]; for (int j = 0; j < triangles.Length; j++) { triangles[j] = file.Skin.Indices[file.Skin.Submeshes[i].Start + j]; } mesh.SetTriangles(triangles, i); } //Generate bones Transform[] bones = new Transform[file.Skeleton.Bones.Length]; for (int i = 0; i < bones.Length; i++) { bones[i] = new GameObject("Bone" + i).transform; bones[i].position = new Vector3(-file.Skeleton.Bones[i].Pivot.X / 2, file.Skeleton.Bones[i].Pivot.Z / 2, -file.Skeleton.Bones[i].Pivot.Y / 2); } GameObject skeleton = new GameObject("Skeleton"); for (int i = 0; i < bones.Length; i++) { if (file.Skeleton.Bones[i].Parent == -1) { bones[i].parent = skeleton.transform; } else { bones[i].parent = bones[file.Skeleton.Bones[i].Parent]; } } //Add Attachment points if (character) { AddAttachmentPoint(shield, bones[file.Skeleton.Attachments[file.Skeleton.AttachmentLookup[0]].Bone]); AddAttachmentPoint(handRight, bones[file.Skeleton.Attachments[file.Skeleton.AttachmentLookup[1]].Bone]); AddAttachmentPoint(handLeft, bones[file.Skeleton.Attachments[file.Skeleton.AttachmentLookup[2]].Bone]); AddAttachmentPoint(shoulderRight, bones[file.Skeleton.Attachments[file.Skeleton.AttachmentLookup[5]].Bone]); AddAttachmentPoint(shoulderLeft, bones[file.Skeleton.Attachments[file.Skeleton.AttachmentLookup[6]].Bone]); AddAttachmentPoint(helm, bones[file.Skeleton.Attachments[file.Skeleton.AttachmentLookup[11]].Bone]); AddAttachmentPoint(quiver, bones[file.Skeleton.Attachments[file.Skeleton.AttachmentLookup[26]].Bone]); AddAttachmentPoint(buckle, bones[file.Skeleton.Attachments[file.Skeleton.AttachmentLookup[53]].Bone]);; AddAttachmentPoint(book, bones[file.Skeleton.Attachments[file.Skeleton.AttachmentLookup[53]].Bone]); AddAttachmentPoint(backpack, bones[file.Skeleton.Attachments[file.Skeleton.AttachmentLookup[57]].Bone]); } Matrix4x4[] bind = new Matrix4x4[bones.Length]; for (int i = 0; i < bones.Length; i++) { bind[i] = bones[i].worldToLocalMatrix * model.transform.localToWorldMatrix; } skeleton.transform.parent = model.transform; renderer.materials = new Material[mesh.subMeshCount]; renderer.sharedMesh = mesh; renderer.bones = bones; renderer.rootBone = bones[0]; mesh.bindposes = bind; //Load *.bytes files so data can be easly accessible at runtime string path = Path.GetDirectoryName(ctx.assetPath); TextAsset data = AssetDatabase.LoadAssetAtPath <TextAsset>(path + "\\data.bytes"); TextAsset skin = AssetDatabase.LoadAssetAtPath <TextAsset>(path + "\\skin.bytes"); TextAsset skel = new TextAsset(""); skel.name = "skel"; if (file.SkelFileID != 0) { skel = AssetDatabase.LoadAssetAtPath <TextAsset>(path + "\\skel.bytes"); } M2Model m2 = model.AddComponent <M2Model>(); m2.data = data; m2.skin = skin; m2.skel = skel; //Populate the asset ctx.AddObjectToAsset(file.Name, model); ctx.AddObjectToAsset(mesh.name, mesh); ctx.AddObjectToAsset(skeleton.name, skeleton); ctx.AddObjectToAsset(data.name, data); ctx.AddObjectToAsset(skin.name, skin); ctx.AddObjectToAsset(skel.name, skel); }
//Load the model from CASC public IEnumerator LoadModel(int file, int texture, CASCHandler casc) { File = file; if (file != 0) { Texture = texture; this.casc = casc; converter = new System.Drawing.ImageConverter(); byte[] bytes; yield return(null); using (BinaryReader reader = new BinaryReader(casc.OpenFile(file))) { bytes = reader.ReadBytes((int)reader.BaseStream.Length); } yield return(null); Model = new M2(); Model.LoadFile(bytes); yield return(null); if (Model.SkelFileID != 0) { using (BinaryReader reader = new BinaryReader(casc.OpenFile(Model.SkelFileID))) { bytes = reader.ReadBytes((int)reader.BaseStream.Length); } } yield return(null); Model.Skeleton.LoadFile(bytes, Model.SkelFileID); yield return(null); using (BinaryReader reader = new BinaryReader(casc.OpenFile(Model.SkinFileID))) { bytes = reader.ReadBytes((int)reader.BaseStream.Length); } yield return(null); Model.Skin.LoadFile(bytes); yield return(null); //Array.Sort(Model.Skin.Textures, (a, b) => Model.Materials[a.Material].Blend.CompareTo(Model.Materials[b.Material].Blend)); LoadColors(); yield return(null); textures = new Texture2D[Model.Textures.Length]; mesh = WoWHelper.Generate3DMesh(Model); mesh.transform.parent = GetComponent <Transform>(); mesh.transform.localPosition = Vector3.zero; mesh.transform.localEulerAngles = Vector3.zero; mesh.transform.localScale = Vector3.one; renderer = GetComponentInChildren <SkinnedMeshRenderer>(); yield return(null); Transform[] bones = GetComponentInChildren <SkinnedMeshRenderer>().bones; if (Model.Particles.Length > 0) { GameObject[] particles = new GameObject[Model.Particles.Length]; for (int i = 0; i < particles.Length; i++) { particles[i] = WoWHelper.ParticleEffect(Model.Particles[i]); particles[i].transform.parent = bones[Model.Particles[i].Bone]; particles[i].transform.localPosition = Vector3.zero; particles[i].name = $"Particle{i}"; yield return(null); } } if (character.Form == 7) { MatchBones(gilnean); } else { MatchBones(character); } time = new float[Model.TextureAnimations.Length]; frame = new int[Model.TextureAnimations.Length]; for (int i = 0; i < time.Length; i++) { time[i] = 0f; frame[i] = 0; yield return(null); } Loaded = true; Change = true; } }