public static void ExtractModel(M2 wowModel) { var initialTime = MAnimControl.currentTime; MAnimControl.currentTime = 0; MGlobal.displayInfo("Building model " + wowModel.Name); var seqList = ExtractSequences(); var jointMap = ExtractJoints(seqList); var globalVertexList = new List <MayaM2Vertex>(); var meshList = new List <MayaM2Mesh>(); ExtractStandardMeshes(meshList, jointMap, globalVertexList); //To WoW proper classes InjectCollisionMesh(wowModel); MayaM2Sequence.NormalizeProbability(seqList); foreach (var seq in seqList) { //TODO SubAnimationId? wowModel.Sequences.Add(seq.ToWoW()); } foreach (var bone in jointMap.Values) { bone.GlobalIndex = wowModel.Bones.Count; wowModel.Bones.Add(bone.ToBone()); } foreach (var vert in globalVertexList) { vert.GlobalIndex = wowModel.GlobalVertexList.Count; wowModel.GlobalVertexList.Add(vert.ToWoW()); } foreach (var lod in MaxBones) { var view = new M2SkinProfile { Bones = (uint)lod }; var partition = MayaM2Mesh.PartitionBones(meshList, lod); foreach (var part in partition) { part.startBone = wowModel.BoneLookup.Count; foreach (var bone in part) { wowModel.BoneLookup.Add((short)bone.GlobalIndex); } } foreach (var mesh in meshList) { var submeshes = mesh.DivideMesh(partition); foreach (var submesh in submeshes) { var wowSubmesh = new M2SkinSection(); wowSubmesh.StartVertex = (ushort)view.Indices.Count; var viewRelativeIndices = new Dictionary <MayaM2Vertex, int>(); foreach (var face in submesh.Faces) { foreach (var vert in face.Vertices) { Debug.Assert(vert.GlobalIndex >= 0, "Global index not set."); if (viewRelativeIndices.ContainsKey(vert)) { continue; } viewRelativeIndices[vert] = view.Indices.Count; view.Indices.Add((ushort)vert.GlobalIndex); wowSubmesh.NVertices++; } } wowSubmesh.StartTriangle = (ushort)view.Triangles.Count; foreach (var face in submesh.Faces) { foreach (var vert in face.Vertices) { view.Triangles.Add((ushort)viewRelativeIndices[vert]); wowSubmesh.NTriangles++; } } view.Submeshes.Add(wowSubmesh); } //TODO what's needed along with submesh (shader, tex..) //TODO Batch } wowModel.Views.Add(view); } //Static models requirements if (wowModel.Sequences.Count == 0) { wowModel.Sequences.Add(new M2Sequence()); //For non-animated models, basic "Stand" } if (wowModel.Bones.Count == 0) { wowModel.Bones.Add(new M2Bone()); //For jointless static models } if (wowModel.TexUnitLookup.Count == 0) { wowModel.TexUnitLookup.Add(0); } if (wowModel.UvAnimLookup.Count == 0) { wowModel.UvAnimLookup.Add(-1); } MAnimControl.currentTime = initialTime; }
public M2SkinProfile GetSkin() { var geos = _model.Get <GEOS>().ToList(); var materials = _model.Get <MTLS>()?.ToArray(); var geoa = _model.Get <GEOA>()?.ToList(); M2SkinProfile profile = new M2SkinProfile() { Bones = 256, Indices = Enumerable.Range(0, geos.Sum(x => x.Vertices.Count)).Select(x => (ushort)x).ToM2Array(), Triangles = new M2Array <ushort>() }; ushort offset = 0; foreach (var geo in geos) { profile.Triangles.AddRange(geo.FaceVertices.SelectMany(y => y.ToArray(offset))); offset += (ushort)geo.NrOfVertices; M2SkinSection section = new M2SkinSection() { StartBones = (ushort)(profile.Submeshes?.Sum(x => x.NBones) ?? 0), StartTriangle = (ushort)(profile.Submeshes?.Sum(x => x.NTriangles) ?? 0), StartVertex = (ushort)(profile.Submeshes?.Sum(x => x.NVertices) ?? 0), NBones = (ushort)geo.GroupedVertices.Count, NTriangles = (ushort)geo.NrOfFaceVertices, NVertices = (ushort)geo.NrOfVertices, CenterBoundingBox = geo.GetCenter(), CenterMass = geo.GetCenter(), }; section.Radius = geo.Vertices.Select(x => x.ToC3Vector).Max(x => x.Distance(section.CenterBoundingBox)); profile.Submeshes.Add(section); } //M2 Batches if (materials == null) { return(profile); } for (int m = 0; m < materials.Length; m++) { for (int l = 0; l < materials[m].Layers.Count; l++) { var layer = materials[m].Layers[l]; M2Batch batch = new M2Batch() { Flags = 16, //Usually 16 for static textures Flags2 = (byte)layer.PriorityPlane, ShaderId = 0, SubmeshIndex = (ushort)geos.FindIndex(x => x.MaterialId == m), SubmeshIndex2 = (ushort)geos.FindIndex(x => x.MaterialId == m), ColorIndex = -1, OpCount = 1, RenderFlags = (ushort)profile.TextureUnits.Count, Texture = (ushort)layer.TextureId, TexUnitNumber2 = (ushort)layer.TextureId, Layer = (ushort)l, TextureAnim = (ushort)(layer.TextureAnimationId + 1), //MDX is -1 based }; if (batch.TextureAnim > 0) { batch.Flags = 0; //0 for animated textures } if (geoa != null) { batch.ColorIndex = (short)geoa.FindIndex(x => x.GeosetId - 1 == batch.SubmeshIndex); } Model.TransLookup.Add((short)Model.TransLookup.Count); profile.TextureUnits.Add(batch); } } return(profile); }