public static GpuMesh ToGpuMesh(this IMesh source) { if (source is GpuMesh) { return((GpuMesh)source); } return(GpuMesh.Optimize(source)); }
public void Optimize_IdIsSet_KeepsId() { var index = new GpuMesh("id1"); var gpuMesh = IndexedMesh.Optimize(index); Assert.AreEqual(index.Id, gpuMesh.Id); }
public void Optimize_TwoTriangles_4VerticesAnd6IndicesCreated() { var builder = new IndexedMeshBuilder(); builder.BeginBuffer(); builder.BeginPrimitive(PrimitiveTopology.TriangleList); builder.Position(new Vector3(0, 0, 0)); builder.Position(new Vector3(1, 0, 0)); builder.Position(new Vector3(0, 1, 0)); builder.Position(new Vector3(1, 0, 0)); builder.Position(new Vector3(1, 1, 0)); builder.Position(new Vector3(0, 1, 0)); var mesh = GpuMesh.Optimize(builder.Complete()); Assert.AreEqual(1, mesh.Primitives.Count); Assert.AreEqual(6, mesh.Primitives[0].Count); Assert.AreEqual(4, mesh.Primitives[0].BufferView.GetStreamReader <Vector3>(StreamKey.Position).Count); }
public static IReadOnlyCollection <BufferViewAndPrimitiveIndices <GpuPrimitive> > GroupPrimitives( this GpuMesh mesh) { var map = new Dictionary <IBufferView, BufferViewAndPrimitiveIndices <GpuPrimitive> >(mesh.Primitives.Count); for (var index = 0; index < mesh.Primitives.Count; index++) { var meshPrimitive = mesh.Primitives[index]; var bufferView = meshPrimitive.BufferView; if (!map.TryGetValue(bufferView, out var indices)) { map.Add(bufferView, indices = new BufferViewAndPrimitiveIndices <GpuPrimitive> { BufferView = bufferView }); } indices.Primitives.Add(new PrimitiveAndIndex <GpuPrimitive>(meshPrimitive, index)); } return(map.Values); }
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); }
public void Optimize_EmptyMesh_DoesntThrow() { var index = new GpuMesh(); Assert.DoesNotThrow(() => IndexedMesh.Optimize(index)); }