public static unsafe int[] GenerateIndexBufferAEN(IndexBufferBinding indexBuffer, VertexBufferBinding vertexBuffer, CommandList commandList = null)
        {
            // More info at http://developer.download.nvidia.com/whitepapers/2010/PN-AEN-Triangles-Whitepaper.pdf
            // This implementation might need some performance improvements

            var triangleCount = indexBuffer.Count / 3;
            var newIndices    = new int[triangleCount * 12];

            var positionMapping  = GenerateIndexMapping(vertexBuffer, commandList, "POSITION");
            var dominantEdges    = new Dictionary <EdgeKeyAEN, EdgeAEN>();
            var dominantVertices = new Dictionary <int, int>();
            var indexSize        = indexBuffer.Is32Bit? 4: 2;

            fixed(byte *indexBufferStart = &indexBuffer.Buffer.GetDataSafe(commandList)[indexBuffer.Offset])
            {
                var triangleIndices = stackalloc int[3];
                var positionIndices = stackalloc int[3];

                // Step 2: prepare initial data
                for (int i = 0; i < triangleCount; ++i)
                {
                    var oldIndices = indexBufferStart + i * 3 * indexSize;
                    if (indexSize == 2)
                    {
                        var oldIndicesShort = (short *)oldIndices;
                        triangleIndices[0] = oldIndicesShort[0];
                        triangleIndices[1] = oldIndicesShort[1];
                        triangleIndices[2] = oldIndicesShort[2];
                    }
                    else
                    {
                        var oldIndicesShort = (int *)oldIndices;
                        triangleIndices[0] = oldIndicesShort[0];
                        triangleIndices[1] = oldIndicesShort[1];
                        triangleIndices[2] = oldIndicesShort[2];
                    }

                    positionIndices[0] = positionMapping.Indices[triangleIndices[0]];
                    positionIndices[1] = positionMapping.Indices[triangleIndices[1]];
                    positionIndices[2] = positionMapping.Indices[triangleIndices[2]];

                    newIndices[i * 12 + 0]  = triangleIndices[0];
                    newIndices[i * 12 + 1]  = triangleIndices[1];
                    newIndices[i * 12 + 2]  = triangleIndices[2];
                    newIndices[i * 12 + 3]  = triangleIndices[0];
                    newIndices[i * 12 + 4]  = triangleIndices[1];
                    newIndices[i * 12 + 5]  = triangleIndices[1];
                    newIndices[i * 12 + 6]  = triangleIndices[2];
                    newIndices[i * 12 + 7]  = triangleIndices[2];
                    newIndices[i * 12 + 8]  = triangleIndices[0];
                    newIndices[i * 12 + 9]  = triangleIndices[0];
                    newIndices[i * 12 + 10] = triangleIndices[1];
                    newIndices[i * 12 + 11] = triangleIndices[2];

                    // Step 2b/2c: Build dominant vertex/edge list
                    for (int j = 0; j < 3; ++j)
                    {
                        dominantVertices[positionIndices[j]] = triangleIndices[j];

                        var edge = new EdgeAEN(
                            triangleIndices[((j + 0) % 3)],
                            triangleIndices[((j + 1) % 3)],
                            positionIndices[((j + 0) % 3)],
                            positionIndices[((j + 1) % 3)]);

                        dominantEdges[new EdgeKeyAEN(edge)] = edge;

                        edge = edge.Reverse();
                        dominantEdges[new EdgeKeyAEN(edge)] = edge;
                    }
                }

                // Step3: Find dominant vertex/edge
                for (int i = 0; i < triangleCount; ++i)
                {
                    var oldIndices = indexBufferStart + i * 3 * indexSize;
                    if (indexSize == 2)
                    {
                        var oldIndicesShort = (short *)oldIndices;
                        triangleIndices[0] = oldIndicesShort[0];
                        triangleIndices[1] = oldIndicesShort[1];
                        triangleIndices[2] = oldIndicesShort[2];
                    }
                    else
                    {
                        var oldIndicesShort = (int *)oldIndices;
                        triangleIndices[0] = oldIndicesShort[0];
                        triangleIndices[1] = oldIndicesShort[1];
                        triangleIndices[2] = oldIndicesShort[2];
                    }

                    positionIndices[0] = positionMapping.Indices[triangleIndices[0]];
                    positionIndices[1] = positionMapping.Indices[triangleIndices[1]];
                    positionIndices[2] = positionMapping.Indices[triangleIndices[2]];

                    for (int j = 0; j < 3; ++j)
                    {
                        // Dominant edge
                        int vertexKey;
                        if (dominantVertices.TryGetValue(positionIndices[j], out vertexKey))
                        {
                            newIndices[i * 12 + 9 + j] = vertexKey;
                        }

                        // Dominant vertex
                        EdgeAEN edge;
                        var     edgeKey = new EdgeKeyAEN(positionIndices[((j + 0) % 3)], positionIndices[((j + 1) % 3)]);
                        if (dominantEdges.TryGetValue(edgeKey, out edge))
                        {
                            newIndices[i * 12 + 3 + j * 2 + 0] = edge.Index0;
                            newIndices[i * 12 + 3 + j * 2 + 1] = edge.Index1;
                        }
                    }
                }
            }

            return(newIndices);
        }
 public EdgeKeyAEN(EdgeAEN edge)
     : this(edge.PositionIndex0, edge.PositionIndex1)
 {
 }
Beispiel #3
0
        /// <summary>
        /// Generates the index buffer with dominant edge and vertex informations.
        /// Each triangle gets its indices expanded to 12 control points, with 0 to 2 being original triangle,
        /// 3 to 8 being dominant edges and 9 to 11 being dominant vertices.
        /// </summary>
        /// <param name="meshData">The mesh data.</param>
        public static unsafe void GenerateIndexBufferAEN(this MeshDrawData meshData)
        {
            // For now, require a MeshData with only one vertex buffer and one index buffer
            if (meshData.VertexBuffers.Length != 1 || meshData.IndexBuffer == null)
            {
                throw new NotImplementedException();
            }

            // More info at http://developer.download.nvidia.com/whitepapers/2010/PN-AEN-Triangles-Whitepaper.pdf
            // This implementation might need some performance improvements
            var indexBuffer = meshData.IndexBuffer;

            var triangleCount = indexBuffer.Count / 3;
            var newIndices    = new int[triangleCount * 12];

            var positionMapping  = GenerateIndexMapping(meshData.VertexBuffers[0], "POSITION");
            var dominantEdges    = new Dictionary <EdgeKeyAEN, EdgeAEN>();
            var dominantVertices = new Dictionary <int, int>();

            fixed(byte *indexBufferStart = &indexBuffer.Buffer.Value.Content[indexBuffer.Offset])
            {
                var oldIndices      = (int *)indexBufferStart;
                var triangleIndices = stackalloc int[3];
                var positionIndices = stackalloc int[3];

                // Step 2: prepare initial data
                for (int i = 0; i < triangleCount; ++i)
                {
                    triangleIndices[0] = oldIndices[i * 3 + 0];
                    triangleIndices[1] = oldIndices[i * 3 + 1];
                    triangleIndices[2] = oldIndices[i * 3 + 2];

                    positionIndices[0] = positionMapping.Indices[triangleIndices[0]];
                    positionIndices[1] = positionMapping.Indices[triangleIndices[1]];
                    positionIndices[2] = positionMapping.Indices[triangleIndices[2]];

                    newIndices[i * 12 + 0]  = triangleIndices[0];
                    newIndices[i * 12 + 1]  = triangleIndices[1];
                    newIndices[i * 12 + 2]  = triangleIndices[2];
                    newIndices[i * 12 + 3]  = triangleIndices[0];
                    newIndices[i * 12 + 4]  = triangleIndices[1];
                    newIndices[i * 12 + 5]  = triangleIndices[1];
                    newIndices[i * 12 + 6]  = triangleIndices[2];
                    newIndices[i * 12 + 7]  = triangleIndices[2];
                    newIndices[i * 12 + 8]  = triangleIndices[0];
                    newIndices[i * 12 + 9]  = triangleIndices[0];
                    newIndices[i * 12 + 10] = triangleIndices[1];
                    newIndices[i * 12 + 11] = triangleIndices[2];

                    // Step 2b/2c: Build dominant vertex/edge list
                    for (int j = 0; j < 3; ++j)
                    {
                        dominantVertices[positionIndices[j]] = triangleIndices[j];

                        var edge = new EdgeAEN(
                            triangleIndices[((j + 0) % 3)],
                            triangleIndices[((j + 1) % 3)],
                            positionIndices[((j + 0) % 3)],
                            positionIndices[((j + 1) % 3)]);

                        dominantEdges[new EdgeKeyAEN(edge)] = edge;

                        edge = edge.Reverse();
                        dominantEdges[new EdgeKeyAEN(edge)] = edge;
                    }
                }

                // Step3: Find dominant vertex/edge
                for (int i = 0; i < triangleCount; ++i)
                {
                    triangleIndices[0] = oldIndices[i * 3 + 0];
                    triangleIndices[1] = oldIndices[i * 3 + 1];
                    triangleIndices[2] = oldIndices[i * 3 + 2];

                    positionIndices[0] = positionMapping.Indices[triangleIndices[0]];
                    positionIndices[1] = positionMapping.Indices[triangleIndices[1]];
                    positionIndices[2] = positionMapping.Indices[triangleIndices[2]];

                    for (int j = 0; j < 3; ++j)
                    {
                        // Dominant edge
                        int vertexKey;
                        if (dominantVertices.TryGetValue(positionIndices[j], out vertexKey))
                        {
                            newIndices[i * 12 + 9 + j] = vertexKey;
                        }

                        // Dominant vertex
                        EdgeAEN edge;
                        var     edgeKey = new EdgeKeyAEN(positionIndices[((j + 0) % 3)], positionIndices[((j + 1) % 3)]);
                        if (dominantEdges.TryGetValue(edgeKey, out edge))
                        {
                            newIndices[i * 12 + 3 + j * 2 + 0] = edge.Index0;
                            newIndices[i * 12 + 3 + j * 2 + 1] = edge.Index1;
                        }
                    }
                }
            }

            // Generate index buffer
            var indexBufferData = new byte[triangleCount * 12 * Utilities.SizeOf <int>()];

            fixed(int *indexDataStart = &newIndices[0])
            fixed(byte *indexBufferDataStart = &indexBufferData[0])
            {
                Utilities.CopyMemory((IntPtr)indexBufferDataStart, (IntPtr)indexDataStart, indexBufferData.Length);
                meshData.IndexBuffer = new IndexBufferBindingData(new BufferData(BufferFlags.IndexBuffer, indexBufferData), true, triangleCount * 12);
            }

            meshData.DrawCount     = triangleCount * 12;
            meshData.PrimitiveType = PrimitiveType.PatchList.ControlPointCount(12);
        }