Example #1
0
        public Submesh3D Clone()
        {
            var clone = new Submesh3D();

            clone.Mesh          = Mesh.ShallowClone();
            clone.BoneNames     = new List <string>(BoneNames);
            clone.BoneBindPoses = new List <Matrix44>(BoneBindPoses);
            clone.Material      = Material.Clone();
            clone.Owner         = null;
            return(clone);
        }
Example #2
0
        public static Submesh3D Combine(params Submesh3D[] submeshes)
        {
            var firstMesh  = submeshes.First();
            var newSubmesh = new Submesh3D {
                Material = firstMesh.Material
            };
            var numVertices   = submeshes.Select(sm => sm.Mesh).Sum(m => m.Vertices.Length);
            var numIndices    = submeshes.Select(sm => sm.Mesh).Sum(m => m.Indices.Length);
            var outVertices   = new Mesh3D.Vertex[numVertices];
            var outIndices    = new ushort[numIndices];
            var currentVertex = 0;
            var currentIndex  = 0;

            foreach (var sm in submeshes)
            {
                var m       = sm.Mesh;
                var indices = m.Indices;
                for (var i = currentIndex; i < currentIndex + indices.Length; i++)
                {
                    outIndices[i] = (ushort)(indices[i - currentIndex] + currentVertex);
                }
                var idx = (byte)newSubmesh.BoneNames.Count;
                for (var i = 0; i < sm.BoneNames.Count; i++)
                {
                    newSubmesh.BoneNames.Add(sm.BoneNames[i]);
                    newSubmesh.BoneBindPoses.Add(sm.BoneBindPoses[i]);
                }
                currentIndex += indices.Length;
                var vertices = m.Vertices;
                vertices.CopyTo(outVertices, currentVertex);
                for (var j = currentVertex; j < currentVertex + vertices.Length; j++)
                {
                    var bi = outVertices[j].BlendIndices;
                    bi.Index0 += idx;
                    bi.Index1 += idx;
                    bi.Index2 += idx;
                    bi.Index3 += idx;
                    outVertices[j].BlendIndices = bi;
                }
                currentVertex += vertices.Length;
            }

            newSubmesh.Mesh = new Mesh <Mesh3D.Vertex> {
                Vertices           = outVertices,
                Indices            = outIndices,
                AttributeLocations = firstMesh.Mesh.AttributeLocations,
                DirtyFlags         = MeshDirtyFlags.All
            };
            return(newSubmesh);
        }
Example #3
0
        private void MergeMeshes(Dictionary <int, List <Mesh3D> > map, Node3D model)
        {
            const int meshLimit  = ushort.MaxValue;
            const int bonesLimit = 50;

            if (map.Count == 0)
            {
                return;
            }
            foreach (var pair in map)
            {
                var materialsMap = new Dictionary <IMaterial, Dictionary <Mesh3D, List <Submesh3D> > >();
                foreach (var mesh in pair.Value)
                {
                    foreach (var submesh in mesh.Submeshes)
                    {
                        var material = submesh.Material;
                        if (!materialsMap.ContainsKey(material))
                        {
                            materialsMap[material] = new Dictionary <Mesh3D, List <Submesh3D> >();
                        }
                        if (!materialsMap[material].ContainsKey(mesh))
                        {
                            materialsMap[material][mesh] = new List <Submesh3D>();
                        }
                        materialsMap[material][mesh].Add(submesh);
                    }
                }

                foreach (var meshDescriptor in materialsMap.Values)
                {
                    var first   = meshDescriptor.First().Key;
                    var newMesh = new Mesh3D {
                        Opaque        = first.Opaque,
                        CullMode      = first.CullMode,
                        SkinningMode  = first.SkinningMode,
                        HitTestTarget = first.HitTestTarget
                    };
                    Submesh3D curSubmesh = null;
                    foreach (var meshAndSubmeshes in meshDescriptor)
                    {
                        var meshIdx = 0;
                        while (meshIdx < meshAndSubmeshes.Value.Count)
                        {
                            var submeshToMerge     = meshAndSubmeshes.Value[meshIdx];
                            var meshLocalTransform = meshAndSubmeshes.Key.LocalTransform;
                            MeshUtils.TransformVertices(submeshToMerge.Mesh, (ref Mesh3D.Vertex v) => {
                                v.Pos = meshLocalTransform.TransformVector(v.Pos);
                            });
                            if (curSubmesh == null)
                            {
                                curSubmesh = submeshToMerge;
                                meshAndSubmeshes.Value.RemoveAt(meshIdx);
                                meshIdx++;
                                continue;
                            }
                            if (curSubmesh.Mesh.Indices.Length + submeshToMerge.Mesh.Indices.Length < meshLimit &&
                                curSubmesh.BoneNames.Count + submeshToMerge.BoneNames.Count < bonesLimit
                                )
                            {
                                curSubmesh = Combine(curSubmesh, submeshToMerge);
                                meshAndSubmeshes.Value.RemoveAt(meshIdx);
                            }
                            else
                            {
                                newMesh.Submeshes.Add(curSubmesh);
                                curSubmesh = null;
                            }
                        }
                        newMesh.Id += (newMesh.Id == null ? "" : "|") + meshAndSubmeshes.Key.Id;
                    }
                    newMesh.Submeshes.Add(curSubmesh);
                    model.AddNode(newMesh);
                }
                foreach (var mesh in materialsMap.Values.SelectMany(kv => kv.Keys))
                {
                    mesh.UnlinkAndDispose();
                }
            }
        }