Mesh Combine(Mesh mesh) { Mesh combinedMesh = InstanceMesh(mesh); SubmeshInfo[] initialSubmeshData = new SubmeshInfo[mesh.subMeshCount]; for (int submeshIndex = 0; submeshIndex < mesh.subMeshCount; submeshIndex++) { initialSubmeshData[submeshIndex].triangles = new List <int>(); int[] submeshTriangles = mesh.GetTriangles(submeshIndex); for (int triangleIndex = 0; triangleIndex < submeshTriangles.Length; triangleIndex++) { initialSubmeshData[submeshIndex].triangles.Add(submeshTriangles[triangleIndex]); } } List <int> affectedSubmeshes = new List <int>(); SubmeshInfo[] combinedSubInfo = new SubmeshInfo[submeshesToCombine.Length]; for (int combinedSubmeshesIndex = 0; combinedSubmeshesIndex < submeshesToCombine.Length; combinedSubmeshesIndex++) { combinedSubInfo[combinedSubmeshesIndex].triangles = new List <int>(); for (int affectedSubmeshesIndex = 0; affectedSubmeshesIndex < submeshesToCombine[combinedSubmeshesIndex].submeshesToCombine.Length; affectedSubmeshesIndex++) { int affectedSubmesh = submeshesToCombine[combinedSubmeshesIndex].submeshesToCombine[affectedSubmeshesIndex]; combinedSubInfo[combinedSubmeshesIndex].triangles.AddRange(initialSubmeshData[affectedSubmesh].triangles); affectedSubmeshes.Add(affectedSubmesh); } } int unaffectedSubmeshCount = mesh.subMeshCount - affectedSubmeshes.Count; int newSubmeshCount = submeshesToCombine.Length + unaffectedSubmeshCount; combinedMesh.subMeshCount = newSubmeshCount; int currentSubmesh = 0; for (int combinedSubmeshesIndex = 0; combinedSubmeshesIndex < combinedSubInfo.Length; combinedSubmeshesIndex++) { combinedMesh.SetTriangles(combinedSubInfo[combinedSubmeshesIndex].triangles, currentSubmesh); currentSubmesh++; } for (int originalSubmeshIndex = 0; originalSubmeshIndex < mesh.subMeshCount; originalSubmeshIndex++) { if (!affectedSubmeshes.Contains(originalSubmeshIndex)) { combinedMesh.SetTriangles(initialSubmeshData[originalSubmeshIndex].triangles, currentSubmesh); currentSubmesh++; } } return(combinedMesh); }
public int Compare(SubmeshInfo x, SubmeshInfo y) { int result = x.VertexBufferIndex - y.VertexBufferIndex; if (result == 0) { result = x.MaterialIndex - y.MaterialIndex; } if (result == 0) { result = x.OriginalIndex - y.OriginalIndex; } return(result); }
Mesh Combine (Mesh mesh) { Mesh combinedMesh = InstanceMesh(mesh); SubmeshInfo[] initialSubmeshData = new SubmeshInfo[mesh.subMeshCount]; for (int submeshIndex = 0; submeshIndex < mesh.subMeshCount; submeshIndex++) { initialSubmeshData[submeshIndex].triangles = new List<int>(); int[] submeshTriangles = mesh.GetTriangles(submeshIndex); for (int triangleIndex = 0; triangleIndex < submeshTriangles.Length; triangleIndex++) { initialSubmeshData[submeshIndex].triangles.Add(submeshTriangles[triangleIndex]); } } List<int> affectedSubmeshes = new List<int>(); SubmeshInfo[] combinedSubInfo = new SubmeshInfo[submeshesToCombine.Length]; for (int combinedSubmeshesIndex = 0; combinedSubmeshesIndex < submeshesToCombine.Length; combinedSubmeshesIndex++) { combinedSubInfo[combinedSubmeshesIndex].triangles = new List<int>(); for (int affectedSubmeshesIndex = 0; affectedSubmeshesIndex < submeshesToCombine[combinedSubmeshesIndex].submeshesToCombine.Length; affectedSubmeshesIndex++) { int affectedSubmesh = submeshesToCombine[combinedSubmeshesIndex].submeshesToCombine[affectedSubmeshesIndex]; combinedSubInfo[combinedSubmeshesIndex].triangles.AddRange(initialSubmeshData[affectedSubmesh].triangles); affectedSubmeshes.Add(affectedSubmesh); } } int unaffectedSubmeshCount = mesh.subMeshCount - affectedSubmeshes.Count; int newSubmeshCount = submeshesToCombine.Length + unaffectedSubmeshCount; combinedMesh.subMeshCount = newSubmeshCount; int currentSubmesh = 0; for (int combinedSubmeshesIndex = 0; combinedSubmeshesIndex < combinedSubInfo.Length; combinedSubmeshesIndex++) { combinedMesh.SetTriangles(combinedSubInfo[combinedSubmeshesIndex].triangles, currentSubmesh); currentSubmesh++; } for (int originalSubmeshIndex = 0; originalSubmeshIndex < mesh.subMeshCount; originalSubmeshIndex++) { if (!affectedSubmeshes.Contains(originalSubmeshIndex)) { combinedMesh.SetTriangles(initialSubmeshData[originalSubmeshIndex].triangles, currentSubmesh); currentSubmesh++; } } return combinedMesh; }
// Build a SubmeshInfo for each GeometryContent. private SubmeshInfo[] BuildSubmeshInfos(MeshContent mesh, List <MeshContent> inputMorphs) { bool hasMorphTargets = (inputMorphs != null && inputMorphs.Count > 0); // A lookup table that maps each material to its index. // The key is the name of the XML file (string) or the local material (MaterialContent). var materialLookupTable = new Dictionary <object, int>(); int numberOfSubmeshes = mesh.Geometry.Count; var submeshInfos = new SubmeshInfo[numberOfSubmeshes]; for (int i = 0; i < numberOfSubmeshes; i++) { var geometry = mesh.Geometry[i]; // Build morph targets for current submesh. List <DRMorphTargetContent> morphTargets = null; if (hasMorphTargets) { morphTargets = BuildMorphTargets(geometry, inputMorphs, i); if (morphTargets != null && morphTargets.Count > 0) { // When morph targets are used remove the "BINORMAL" channel. (Otherwise, // the number of vertex attributes would exceed the limit. Binormals need // to be reconstructed from normal and tangent in the vertex shader.) string binormalName = VertexChannelNames.Binormal(0); bool containsTangentFrames = geometry.Vertices.Channels.Remove(binormalName); if (containsTangentFrames) { // A submesh cannot use vertex colors and tangents at the same time. // This would also exceed the vertex attribute limit. string colorName = VertexChannelNames.Color(0); if (geometry.Vertices.Channels.Contains(colorName)) { geometry.Vertices.Channels.Remove(colorName); } } } } var submeshInfo = new SubmeshInfo { Geometry = geometry, OriginalIndex = i, VertexBuffer = geometry.Vertices.CreateVertexBuffer(), MorphTargets = morphTargets }; submeshInfo.VertexBufferIndex = GetVertexBufferIndex(submeshInfo.VertexBuffer.VertexDeclaration); // Get material file or local material. object material = (object)GetExternalMaterial(mesh, geometry) ?? geometry.Material; if (material == null) { var message = string.Format(CultureInfo.InvariantCulture, "Mesh \"{0}\" does not have a material.", mesh); throw new InvalidContentException(message, mesh.Identity); } int materialIndex; if (!materialLookupTable.TryGetValue(material, out materialIndex)) { materialIndex = materialLookupTable.Count; materialLookupTable.Add(material, materialIndex); } submeshInfo.MaterialIndex = materialIndex; submeshInfo.Material = material; submeshInfos[i] = submeshInfo; } return(submeshInfos); }
public void EndSubmesh() { if (currentSubmesh != null) { submeshes.Add(currentSubmesh); currentSubmesh = null; } }
public void BeginSubmesh() { if(currentSubmesh == null) currentSubmesh = new SubmeshInfo(); }