public void Optimize_TwoTrianglesOfDifferentColor_5Positions2ColorsAnd6IndicesCreated() { var builder = new IndexedMeshBuilder(); builder.BeginBuffer(); builder.BeginPrimitive(PrimitiveTopology.TriangleList); builder.Color(Vector4.Zero); builder.Position(new Vector3(0, 0, 0)); builder.Color(Vector4.Zero); builder.Position(new Vector3(1, 0, 0)); builder.Color(Vector4.Zero); builder.Position(new Vector3(0, 1, 0)); builder.Color(Vector4.One); builder.Position(new Vector3(1, 0, 0)); builder.Color(Vector4.One); builder.Position(new Vector3(1, 1, 0)); builder.Color(Vector4.One); builder.Position(new Vector3(0, 1, 0)); var mesh = IndexedMesh.Optimize(builder.Complete()); Assert.AreEqual(1, mesh.Primitives.Count); Assert.AreEqual(6, mesh.Primitives[0].GetIndexReader(StreamKey.Position).Count); Assert.AreEqual(6, mesh.Primitives[0].GetIndexReader(StreamKey.Color).Count); Assert.AreEqual(4, mesh.Primitives[0].BufferView.GetStreamReader <Vector3>(StreamKey.Position).Count); Assert.AreEqual(2, mesh.Primitives[0].BufferView.GetStreamReader <Vector3>(StreamKey.Color).Count); }
public static IndexedMesh ToIndexedMesh(this IMesh source) { if (source is IndexedMesh) { return((IndexedMesh)source); } return(IndexedMesh.Optimize(source)); }
public void Optimize_IdIsSet_KeepsId() { var index = new GpuMesh("id1"); var gpuMesh = IndexedMesh.Optimize(index); Assert.AreEqual(index.Id, gpuMesh.Id); }
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)); }