public static IndexedMesh Optimize(IMesh mesh) { var result = new IndexedMesh(mesh.Id); var resultPrimitives = new IndexMeshPrimitive[mesh.Primitives.Count]; var primitiveGroups = mesh.GroupPrimitives(); foreach (var primitiveGroup in primitiveGroups) { var resultBufferView = new MeshBufferView(); var bufferView = primitiveGroup.BufferView; var streamKeys = bufferView.GetStreams().ToList(); var sourceStreams = streamKeys.Select(x => bufferView.GetStream(x)).ToList(); var dictionaryStreams = sourceStreams.Select(_ => _.CreateDictionaryMeshStreamOfTheSameType()).ToList(); for (var index = 0; index < dictionaryStreams.Count; index++) { resultBufferView.SetStream(streamKeys[index], dictionaryStreams[index]); } foreach (var primitiveAndIndex in primitiveGroup.Primitives) { var meshPrimitive = new IndexMeshPrimitive(resultBufferView); resultPrimitives[primitiveAndIndex.Index] = meshPrimitive; var submesh = primitiveAndIndex.Primitive; meshPrimitive.Topology = submesh.Topology; for (var keyIndex = 0; keyIndex < streamKeys.Count; ++keyIndex) { var key = streamKeys[keyIndex]; var sourceIndices = submesh.GetIndexReader(key); var dataStream = dictionaryStreams[keyIndex]; var sourceStream = sourceStreams[keyIndex]; var stream = new List <int>(sourceIndices.Count); for (var i = 0; i < sourceIndices.Count; ++i) { stream.Add(dataStream.Add(sourceStream[sourceIndices[i]])); } meshPrimitive.SetIndexStream(key, stream); } } for (var keyIndex = 0; keyIndex < streamKeys.Count; ++keyIndex) { bufferView.SetStream(streamKeys[keyIndex], dictionaryStreams[keyIndex]); } } foreach (var indexMeshPrimitive in resultPrimitives) { result.Primitives.Add(indexMeshPrimitive); } return(result); }
public static GpuMesh Optimize(IMesh source) { var optimalIndexedMesh = IndexedMesh.Optimize(source); var resultPrimitives = new GpuPrimitive[optimalIndexedMesh.Primitives.Count]; var result = new GpuMesh(source.Id); var indices = new List <int>(); foreach (var primitiveGroup in optimalIndexedMesh.GroupPrimitives()) { var sourceBuffer = primitiveGroup.BufferView; var gpuBufferView = new MeshBufferView(); var streamKeys = sourceBuffer.GetStreams(); var copiers = streamKeys.Project((streamKey, streamIndex) => { var meshStream = sourceBuffer.GetStream(streamKey); var destination = meshStream.CreateListMeshStreamOfTheSameType(); gpuBufferView.SetStream(streamKey, destination); return(new BoxingtMeshStreamCopier(meshStream, destination)); }); var expectedCapacityEsitmation = primitiveGroup.Select(_ => _.GetIndexReader(StreamKey.Position).Count).Sum() * streamKeys.Count; indices.Clear(); if (indices.Capacity < expectedCapacityEsitmation) { indices.Capacity = expectedCapacityEsitmation; } var vertexMap = new Dictionary <IndexSet, int>(); foreach (var primitiveAndIndex in primitiveGroup.Primitives) { var primitive = primitiveAndIndex.Primitive; var setReader = new IndexSetReader(indices, streamKeys, primitive); var ints = primitive.GetIndexReader(StreamKey.Position); var gpuIndices = new List <int>(); for (var index = 0; index < ints.Count; index++) { var set = setReader.Read(index); if (vertexMap.TryGetValue(set, out var vertexIndex)) { setReader.Position = set.Offset; } else { for (var streamIndex = 0; streamIndex < streamKeys.Count; streamIndex++) { vertexIndex = copiers[streamIndex].Copy(set[streamIndex]); } vertexMap.Add(set, vertexIndex); } gpuIndices.Add(vertexIndex); } var gpuPrimitive = new GpuPrimitive(primitive.Topology, gpuIndices, gpuBufferView); resultPrimitives[primitiveAndIndex.Index] = gpuPrimitive; } } foreach (var indexMeshPrimitive in resultPrimitives) { result.Primitives.Add(indexMeshPrimitive); } return(result); }