public static void PreProcess(Model model, PreProcessOptions options)
        {
            if (options.HasFlag(PreProcessOptions.SplitMeshPart))
            {
                // Specific to C:R, I'll abstract this out as and when necessary
                foreach (ModelMesh mesh in model.Meshes)
                {
                    int partCount = mesh.MeshParts.Count;

                    for (int i = partCount - 1; i >= 0; i--)
                    {
                        ModelMeshPart part = mesh.MeshParts[i];

                        if (part.VertexBuffer.Data.Count > 16383)
                        {
                            while (part.IndexBuffer.Data.Count > 0)
                            {
                                var buffer = part.IndexBuffer.Data;
                                HashSet<int> usedVerts = new HashSet<int>();
                                int total = buffer.Count;

                                for (int j = 0; j < buffer.Count; j += 3)
                                {
                                    usedVerts.Add(buffer[j + 0]);
                                    usedVerts.Add(buffer[j + 1]);
                                    usedVerts.Add(buffer[j + 2]);

                                    int chunkSize = Math.Min(buffer.Count, 16383);

                                    if (j + 3 == buffer.Count || usedVerts.Count >= chunkSize)
                                    {
                                        if (usedVerts.Count == chunkSize) { j += 3; }

                                        Dictionary<int, int> indexLUT = new Dictionary<int, int>();

                                        var newPart = new ModelMeshPart();
                                        newPart.Material = part.Material;

                                        for (int k = 0; k < j; k++)
                                        {
                                            if (!indexLUT.ContainsKey(buffer[k]))
                                            {
                                                indexLUT.Add(buffer[k], newPart.VertexBuffer.AddVertex(part.VertexBuffer.Data[buffer[k]]));
                                            }

                                            newPart.IndexBuffer.AddIndex(indexLUT[buffer[k]]);
                                        }

                                        buffer.RemoveRange(0, j);

                                        mesh.AddModelMeshPart(newPart);

                                        SceneManager.Current.UpdateProgress(string.Format("Allocated {0:n0} of {1:n0}", j * chunkSize, total));
                                        break;
                                    }
                                }
                            }

                            mesh.MeshParts.RemoveAt(i);
                        }
                    }
                }
            }

            if (options.HasFlag(PreProcessOptions.Dedupe))
            {
                foreach (ModelMesh mesh in model.Meshes)
                {
                    foreach (ModelMeshPart part in mesh.MeshParts)
                    {
                        part.Optimise();
                    }
                }
            }

            if (options.HasFlag(PreProcessOptions.ResolveNonManifold))
            {
                foreach (ModelMesh mesh in model.Meshes)
                {
                    foreach (ModelMeshPart part in mesh.MeshParts)
                    {
                        Dictionary<int, int> edgeCounts = new Dictionary<int, int>();
                        List<int> buffer = part.IndexBuffer.Data;
                        bool bFixedNonManifoldMesh = false;

                        for (int i = 0; i < buffer.Count; i += 3)
                        {
                            int[] edges = new int[3];

                            for (int j = 0; j < 3; j++)
                            {
                                int oppositeIndex = (j + 1 < 3 ? j + 1 : 0);

                                edges[j] = Math.Max(buffer[i + j], buffer[i + oppositeIndex]) << 24 + Math.Min(buffer[i + j], buffer[i + oppositeIndex]);

                                if (edgeCounts.ContainsKey(edges[j]))
                                {
                                    if (edgeCounts[edges[j]] == 2)
                                    {
                                        buffer[i + j] = part.VertexBuffer.AddVertex(part.VertexBuffer.Data[buffer[i + j]].Clone());
                                        buffer[i + oppositeIndex] = part.VertexBuffer.AddVertex(part.VertexBuffer.Data[buffer[i + oppositeIndex]].Clone());

                                        j--;

                                        bFixedNonManifoldMesh = true;
                                    }
                                    else
                                    {
                                        edgeCounts[edges[j]]++;
                                    }
                                }
                                else
                                {
                                    edgeCounts.Add(edges[j], 1);
                                }
                            }
                        }

                        if (bFixedNonManifoldMesh)
                        {
                            part.IndexBuffer.Initialise();
                            part.VertexBuffer.Initialise();
                        }
                    }
                }
            }
        }
Example #2
0
        public static void PreProcess(Model model, PreProcessOptions options)
        {
            if (options.HasFlag(PreProcessOptions.SplitMeshPart))
            {
                // Specific to C:R, I'll abstract this out as and when necessary
                foreach (ModelMesh mesh in model.Meshes)
                {
                    int partCount = mesh.MeshParts.Count;

                    for (int i = partCount - 1; i >= 0; i--)
                    {
                        ModelMeshPart part = mesh.MeshParts[i];

                        if (part.VertexBuffer.Data.Count > 16383)
                        {
                            while (part.IndexBuffer.Data.Count > 0)
                            {
                                var           buffer    = part.IndexBuffer.Data;
                                HashSet <int> usedVerts = new HashSet <int>();
                                int           total     = buffer.Count;

                                for (int j = 0; j < buffer.Count; j += 3)
                                {
                                    usedVerts.Add(buffer[j + 0]);
                                    usedVerts.Add(buffer[j + 1]);
                                    usedVerts.Add(buffer[j + 2]);

                                    int chunkSize = Math.Min(buffer.Count, 16383);

                                    if (j + 3 == buffer.Count || usedVerts.Count >= chunkSize)
                                    {
                                        if (usedVerts.Count == chunkSize)
                                        {
                                            j += 3;
                                        }

                                        Dictionary <int, int> indexLUT = new Dictionary <int, int>();

                                        var newPart = new ModelMeshPart();
                                        newPart.Material = part.Material;

                                        for (int k = 0; k < j; k++)
                                        {
                                            if (!indexLUT.ContainsKey(buffer[k]))
                                            {
                                                indexLUT.Add(buffer[k], newPart.VertexBuffer.AddVertex(part.VertexBuffer.Data[buffer[k]]));
                                            }

                                            newPart.IndexBuffer.AddIndex(indexLUT[buffer[k]]);
                                        }

                                        buffer.RemoveRange(0, j);

                                        mesh.AddModelMeshPart(newPart);

                                        SceneManager.Current.UpdateProgress(string.Format("Allocated {0:n0} of {1:n0}", j * chunkSize, total));
                                        break;
                                    }
                                }
                            }

                            mesh.MeshParts.RemoveAt(i);
                        }
                    }
                }
            }

            if (options.HasFlag(PreProcessOptions.Dedupe))
            {
                foreach (ModelMesh mesh in model.Meshes)
                {
                    foreach (ModelMeshPart part in mesh.MeshParts)
                    {
                        part.Optimise();
                    }
                }
            }

            if (options.HasFlag(PreProcessOptions.ResolveNonManifold))
            {
                foreach (ModelMesh mesh in model.Meshes)
                {
                    foreach (ModelMeshPart part in mesh.MeshParts)
                    {
                        Dictionary <int, int> edgeCounts = new Dictionary <int, int>();
                        List <int>            buffer     = part.IndexBuffer.Data;
                        bool bFixedNonManifoldMesh       = false;

                        for (int i = 0; i < buffer.Count; i += 3)
                        {
                            int[] edges = new int[3];

                            for (int j = 0; j < 3; j++)
                            {
                                int oppositeIndex = (j + 1 < 3 ? j + 1 : 0);

                                edges[j] = Math.Max(buffer[i + j], buffer[i + oppositeIndex]) << 24 + Math.Min(buffer[i + j], buffer[i + oppositeIndex]);

                                if (edgeCounts.ContainsKey(edges[j]))
                                {
                                    if (edgeCounts[edges[j]] == 2)
                                    {
                                        buffer[i + j]             = part.VertexBuffer.AddVertex(part.VertexBuffer.Data[buffer[i + j]].Clone());
                                        buffer[i + oppositeIndex] = part.VertexBuffer.AddVertex(part.VertexBuffer.Data[buffer[i + oppositeIndex]].Clone());

                                        j--;

                                        bFixedNonManifoldMesh = true;
                                    }
                                    else
                                    {
                                        edgeCounts[edges[j]]++;
                                    }
                                }
                                else
                                {
                                    edgeCounts.Add(edges[j], 1);
                                }
                            }
                        }

                        if (bFixedNonManifoldMesh)
                        {
                            part.IndexBuffer.Initialise();
                            part.VertexBuffer.Initialise();
                        }
                    }
                }
            }
        }