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(); } } } } }
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(); } } } } }