예제 #1
0
        /// <summary>
        /// Generates a sphere by progressively refining a tetrahedral mesh.
        /// </summary>
        /// <param name="subdivisionCount">Number of recursive splits to perform on the triangles.</param>
        /// <param name="vertices">Vertex buffer of the sphere.</param>
        /// <param name="triangles">Index buffer of the sphere. Each group of three integers represents one triangle.</param>
        public static void GenerateSphere(int subdivisionCount, out System.Numerics.Vector3[] vertices, out int[] triangles)
        {
            //int finalSize = 3 * (4 << (subdivisionCount << 1));
            //int secondToLastSize = finalSize >> 2;

            int finalSize        = 3 * (20 << (subdivisionCount * 2));
            int secondToLastSize = finalSize >> 2;


            triangles = new int[finalSize];
            //Grabbing a RawList<int> for this purpose is a little gross. Really, just an int[] is desired.
            var swapTriangles = new int[secondToLastSize];

            int[] currentTriangles, nextTriangles;
            if ((subdivisionCount & 1) == 0)
            {
                //Subdivision count is even.
                //The "currentTriangles" reference will end up being the final container.
                currentTriangles = triangles;
                nextTriangles    = swapTriangles;
            }
            else
            {
                //Subdivision count is odd.
                //The "nextTriangles" reference will end up being the final container.
                currentTriangles = swapTriangles;
                nextTriangles    = triangles;
            }

            //The number of vertices that we'll end up with is known analytically.
            vertices = new System.Numerics.Vector3[GetExpectedVertexCount(subdivisionCount)];

            ////Create the regular tetrahedron vertices.
            //float x = (float)(1 / Math.Sqrt(3));
            //float z = (float)(-1 / (2 * Math.Sqrt(6)));
            //vertices[0] = System.Numerics.Vector3.Normalize(new System.Numerics.Vector3(0, 0, (float)(Math.Sqrt(2.0 / 3.0) + z)));
            //vertices[1] = System.Numerics.Vector3.Normalize(new System.Numerics.Vector3(-0.5f * x, -0.5f, z));
            //vertices[2] = System.Numerics.Vector3.Normalize(new System.Numerics.Vector3(-0.5f * x, 0.5f, z));
            //vertices[3] = System.Numerics.Vector3.Normalize(new System.Numerics.Vector3(x, 0, z));
            ////Just treat this array as a list.
            //int vertexCount = 4;

            ////Create the regular tetrahedron triangles.
            ////The winding matters. They should be consistent so that the end result is consistent.
            //currentTriangles[0] = 0;
            //currentTriangles[1] = 1;
            //currentTriangles[2] = 2;

            //currentTriangles[3] = 0;
            //currentTriangles[4] = 2;
            //currentTriangles[5] = 3;

            //currentTriangles[6] = 1;
            //currentTriangles[7] = 3;
            //currentTriangles[8] = 2;

            //currentTriangles[9] = 0;
            //currentTriangles[10] = 3;
            //currentTriangles[11] = 1;

            //int currentTriangleIndexCount = 12;
            //int nextTriangleIndexCount = 0;

            //Create the regular icosahedron vertices.
            //System.Numerics.Vector3[] vertices = new System.Numerics.Vector3[12];
            var   goldenRatio = (1 + (float)Math.Sqrt(5)) / 2;
            float length      = (float)Math.Sqrt(1 + goldenRatio * goldenRatio);
            float x           = 1 / length;
            float y           = goldenRatio / length;

            vertices[0] = new System.Numerics.Vector3(0, x, y);
            vertices[1] = new System.Numerics.Vector3(0, -x, y);
            vertices[2] = new System.Numerics.Vector3(0, x, -y);
            vertices[3] = new System.Numerics.Vector3(0, -x, -y);

            vertices[4] = new System.Numerics.Vector3(x, y, 0);
            vertices[5] = new System.Numerics.Vector3(-x, y, 0);
            vertices[6] = new System.Numerics.Vector3(x, -y, 0);
            vertices[7] = new System.Numerics.Vector3(-x, -y, 0);

            vertices[8]  = new System.Numerics.Vector3(y, 0, x);
            vertices[9]  = new System.Numerics.Vector3(-y, 0, x);
            vertices[10] = new System.Numerics.Vector3(y, 0, -x);
            vertices[11] = new System.Numerics.Vector3(-y, 0, -x);

            //Just treat this array as a list.
            int vertexCount = 12;

            //The winding matters. They should be consistent so that the end result is consistent.
            //[This was generated using GetConvexHull on the above vertices, so it's known to be consistent with GetConvexHull!]
            currentTriangles[0]  = 8;
            currentTriangles[1]  = 10;
            currentTriangles[2]  = 6;
            currentTriangles[3]  = 2;
            currentTriangles[4]  = 3;
            currentTriangles[5]  = 10;
            currentTriangles[6]  = 8;
            currentTriangles[7]  = 6;
            currentTriangles[8]  = 1;
            currentTriangles[9]  = 9;
            currentTriangles[10] = 11;
            currentTriangles[11] = 5;
            currentTriangles[12] = 6;
            currentTriangles[13] = 10;
            currentTriangles[14] = 3;
            currentTriangles[15] = 9;
            currentTriangles[16] = 5;
            currentTriangles[17] = 0;
            currentTriangles[18] = 2;
            currentTriangles[19] = 5;
            currentTriangles[20] = 11;
            currentTriangles[21] = 8;
            currentTriangles[22] = 4;
            currentTriangles[23] = 10;
            currentTriangles[24] = 8;
            currentTriangles[25] = 0;
            currentTriangles[26] = 4;
            currentTriangles[27] = 2;
            currentTriangles[28] = 10;
            currentTriangles[29] = 4;
            currentTriangles[30] = 2;
            currentTriangles[31] = 11;
            currentTriangles[32] = 3;
            currentTriangles[33] = 8;
            currentTriangles[34] = 1;
            currentTriangles[35] = 0;
            currentTriangles[36] = 9;
            currentTriangles[37] = 0;
            currentTriangles[38] = 1;
            currentTriangles[39] = 5;
            currentTriangles[40] = 2;
            currentTriangles[41] = 4;
            currentTriangles[42] = 5;
            currentTriangles[43] = 4;
            currentTriangles[44] = 0;
            currentTriangles[45] = 9;
            currentTriangles[46] = 1;
            currentTriangles[47] = 7;
            currentTriangles[48] = 6;
            currentTriangles[49] = 7;
            currentTriangles[50] = 1;
            currentTriangles[51] = 9;
            currentTriangles[52] = 7;
            currentTriangles[53] = 11;
            currentTriangles[54] = 11;
            currentTriangles[55] = 7;
            currentTriangles[56] = 3;
            currentTriangles[57] = 6;
            currentTriangles[58] = 3;
            currentTriangles[59] = 7;

            int currentTriangleIndexCount = 60;
            int nextTriangleIndexCount    = 0;


            var edges = new Dictionary <TriangleMeshConvexContactManifold.Edge, int>();

            for (int i = 0; i < subdivisionCount; ++i)
            {
                for (int triangleIndex = 0; triangleIndex < currentTriangleIndexCount; triangleIndex += 3)
                {
                    //For each edge of this triangle, insert a new vertex if the edge hasn't already been taken care of.
                    var aIndex = currentTriangles[triangleIndex];
                    var bIndex = currentTriangles[triangleIndex + 1];
                    var cIndex = currentTriangles[triangleIndex + 2];
                    var a      = vertices[aIndex];
                    var b      = vertices[bIndex];
                    var c      = vertices[cIndex];
                    int abMidIndex;
                    var edge = new TriangleMeshConvexContactManifold.Edge(aIndex, bIndex);
                    if (!edges.TryGetValue(edge, out abMidIndex))
                    {
                        //This edge hasn't yet been handled by another triangle.
                        //Create a vertex.
                        System.Numerics.Vector3 mid;
                        Vector3Ex.Add(ref a, ref b, out mid);
                        mid.Normalize();
                        abMidIndex = vertexCount;
                        vertices.Add(ref mid, ref vertexCount);

                        //Mark this edge as handled.
                        edges.Add(edge, abMidIndex);
                    }

                    int bcMidIndex;
                    edge = new TriangleMeshConvexContactManifold.Edge(bIndex, cIndex);
                    if (!edges.TryGetValue(edge, out bcMidIndex))
                    {
                        //This edge hasn't yet been handled by another triangle.
                        //Create a vertex.
                        System.Numerics.Vector3 mid;
                        Vector3Ex.Add(ref b, ref c, out mid);
                        mid.Normalize();
                        bcMidIndex = vertexCount;
                        vertices.Add(ref mid, ref vertexCount);

                        //Mark this edge as handled.
                        edges.Add(edge, bcMidIndex);
                    }

                    int acMidIndex;
                    edge = new TriangleMeshConvexContactManifold.Edge(aIndex, cIndex);
                    if (!edges.TryGetValue(edge, out acMidIndex))
                    {
                        //This edge hasn't yet been handled by another triangle.
                        System.Numerics.Vector3 mid;
                        Vector3Ex.Add(ref a, ref c, out mid);
                        mid.Normalize();
                        acMidIndex = vertexCount;
                        vertices.Add(ref mid, ref vertexCount);

                        //Mark this edge as handled.
                        edges.Add(edge, acMidIndex);
                    }

                    //Create the new triangles with consistent winding.
                    nextTriangles.Add(aIndex, ref nextTriangleIndexCount);
                    nextTriangles.Add(abMidIndex, ref nextTriangleIndexCount);
                    nextTriangles.Add(acMidIndex, ref nextTriangleIndexCount);

                    nextTriangles.Add(abMidIndex, ref nextTriangleIndexCount);
                    nextTriangles.Add(bIndex, ref nextTriangleIndexCount);
                    nextTriangles.Add(bcMidIndex, ref nextTriangleIndexCount);

                    nextTriangles.Add(abMidIndex, ref nextTriangleIndexCount);
                    nextTriangles.Add(bcMidIndex, ref nextTriangleIndexCount);
                    nextTriangles.Add(acMidIndex, ref nextTriangleIndexCount);

                    nextTriangles.Add(acMidIndex, ref nextTriangleIndexCount);
                    nextTriangles.Add(bcMidIndex, ref nextTriangleIndexCount);
                    nextTriangles.Add(cIndex, ref nextTriangleIndexCount);
                }

                //Clear out the edges collection. It will get reused when we iterate through the next deeper set of triangles.
                edges.Clear();

                //Swap the triangle buffer references.
                currentTriangleIndexCount = nextTriangleIndexCount;
                nextTriangleIndexCount    = 0;
                var swap = currentTriangles;
                currentTriangles = nextTriangles;
                nextTriangles    = swap;
            }

            //RawList<int> indices = new RawList<int>(SampleTriangleIndices.Length);
            //RawList<System.Numerics.Vector3> surfacePoints = new RawList<System.Numerics.Vector3>();
            //ConvexHullHelper.GetConvexHull(vertices, indices, surfacePoints);
            //indices.CopyTo(SampleTriangleIndices, 0);
        }