예제 #1
0
        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;
        }
예제 #2
0
        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);
        }