public static Submesh CreateIcosphere(GraphicsDevice graphicsDevice, int numberOfSubdivisions)
        {
            if (graphicsDevice == null)
            {
                throw new ArgumentNullException("graphicsDevice");
            }
            if (numberOfSubdivisions < 1)
            {
                throw new ArgumentOutOfRangeException("numberOfSubdivisions", "numberOfSegments must be greater than 0");
            }

            var submesh = new Submesh
            {
                PrimitiveType = PrimitiveType.TriangleList,
            };

            var mesh             = GeometryHelper.CreateIcosphere(numberOfSubdivisions, false);
            int numberOfVertices = mesh.Vertices.Count;
            var vertexData       = new VertexPositionNormal[numberOfVertices];

            for (int i = 0; i < numberOfVertices; i++)
            {
                Vector3 v = (Vector3)mesh.Vertices[i];
                vertexData[i] = new VertexPositionNormal(v, v);
            }

            submesh.VertexBuffer = new VertexBuffer(
                graphicsDevice,
                VertexPositionNormal.VertexDeclaration,
                vertexData.Length,
                BufferUsage.None);
            submesh.VertexBuffer.SetData(vertexData);

            submesh.VertexCount = submesh.VertexBuffer.VertexCount;

            int numberOfTriangles = mesh.NumberOfTriangles;
            int numberOfIndices   = mesh.Indices.Count;
            var indexData         = new ushort[numberOfIndices];

            for (int i = 0; i < numberOfTriangles; i++)
            {
                // Flip vertex order. (DigitalRune Geometry uses CCW, XNA uses CW.)
                indexData[3 * i + 0] = (ushort)mesh.Indices[3 * i + 0];
                indexData[3 * i + 2] = (ushort)mesh.Indices[3 * i + 1];
                indexData[3 * i + 1] = (ushort)mesh.Indices[3 * i + 2];
            }

            submesh.IndexBuffer = new IndexBuffer(
                graphicsDevice,
                IndexElementSize.SixteenBits,
                indexData.Length,
                BufferUsage.None);
            submesh.IndexBuffer.SetData(indexData);

            submesh.PrimitiveCount = indexData.Length / 3;

            return(submesh);
        }
        public static Submesh CreateIcosphere(GraphicsDevice graphicsDevice, int numberOfSubdivisions)
        {
            if (graphicsDevice == null)
            throw new ArgumentNullException("graphicsDevice");
              if (numberOfSubdivisions < 1)
            throw new ArgumentOutOfRangeException("numberOfSubdivisions", "numberOfSegments must be greater than 0");

              var submesh = new Submesh
              {
            PrimitiveType = PrimitiveType.TriangleList,
              };

              var mesh = GeometryHelper.CreateIcosphere(numberOfSubdivisions, false);
              int numberOfVertices = mesh.Vertices.Count;
              var vertexData = new VertexPositionNormal[numberOfVertices];
              for (int i = 0; i < numberOfVertices; i++)
              {
            Vector3 v = (Vector3)mesh.Vertices[i];
            vertexData[i] = new VertexPositionNormal(v, v);
              }

              submesh.VertexBuffer = new VertexBuffer(
            graphicsDevice,
            VertexPositionNormal.VertexDeclaration,
            vertexData.Length,
            BufferUsage.None);
              submesh.VertexBuffer.SetData(vertexData);

              submesh.VertexCount = submesh.VertexBuffer.VertexCount;

              int numberOfTriangles = mesh.NumberOfTriangles;
              int numberOfIndices = mesh.Indices.Count;
              var indexData = new ushort[numberOfIndices];
              for (int i = 0; i < numberOfTriangles; i++)
              {
            // Flip vertex order. (DigitalRune Geometry uses CCW, XNA uses CW.)
            indexData[3* i + 0] = (ushort)mesh.Indices[3 * i + 0];
            indexData[3 * i + 2] = (ushort)mesh.Indices[3 * i + 1];
            indexData[3 * i + 1] = (ushort)mesh.Indices[3 * i + 2];
              }

              submesh.IndexBuffer = new IndexBuffer(
            graphicsDevice,
            IndexElementSize.SixteenBits,
            indexData.Length,
            BufferUsage.None);
              submesh.IndexBuffer.SetData(indexData);

              submesh.PrimitiveCount = indexData.Length / 3;

              return submesh;
        }
Beispiel #3
0
        internal static void CreateVertexBuffer(GraphicsDevice graphicsDevice, TriangleMesh mesh, float angleLimit, out VertexBuffer vertexBuffer, out PrimitiveType primitiveType, out int primitiveCount)
        {
            // Note: We do not use shared vertices and an IndexBuffer because a vertex can be used by
              // several triangles with different normals.

              if (graphicsDevice == null)
            throw new ArgumentNullException("graphicsDevice");
              if (mesh == null)
            throw new ArgumentNullException("mesh");

              var numberOfTriangles = mesh.NumberOfTriangles;

              if (numberOfTriangles == 0)
              {
            primitiveType = PrimitiveType.TriangleList;
            primitiveCount = 0;
            vertexBuffer = null;
            return;
              }

              primitiveType = PrimitiveType.TriangleList;
              primitiveCount = numberOfTriangles;
              int vertexCount = numberOfTriangles * 3;

              // Create vertex data for a triangle list.
              var vertices = new VertexPositionNormal[vertexCount];

              // Create vertex normals.
              var normals = mesh.ComputeNormals(false, angleLimit);

              for (int i = 0; i < numberOfTriangles; i++)
              {
            var i0 = mesh.Indices[i * 3 + 0];
            var i1 = mesh.Indices[i * 3 + 1];
            var i2 = mesh.Indices[i * 3 + 2];

            var v0 = mesh.Vertices[i0];
            var v1 = mesh.Vertices[i1];
            var v2 = mesh.Vertices[i2];

            Vector3F n0, n1, n2;
            if (angleLimit < 0)
            {
              // If the angle limit is negative, ComputeNormals() returns one normal per vertex.
              n0 = normals[i0];
              n1 = normals[i1];
              n2 = normals[i2];
            }
            else
            {
              // If the angle limits is >= 0, ComputeNormals() returns 3 normals per triangle.
              n0 = normals[i * 3 + 0];
              n1 = normals[i * 3 + 1];
              n2 = normals[i * 3 + 2];
            }

            // Add new vertex data.
            // DigitalRune.Geometry uses counter-clockwise front faces. XNA uses
            // clockwise front faces (CullMode.CullCounterClockwiseFace) per default.
            // Therefore we change the vertex orientation of the triangles.
            vertices[i * 3 + 0] = new VertexPositionNormal((Vector3)v0, (Vector3)n0);
            vertices[i * 3 + 1] = new VertexPositionNormal((Vector3)v2, (Vector3)n2);  // v2 instead of v1!
            vertices[i * 3 + 2] = new VertexPositionNormal((Vector3)v1, (Vector3)n1);
              }

              // Create a vertex buffer.
              vertexBuffer = new VertexBuffer(graphicsDevice, typeof(VertexPositionNormal), vertexCount, BufferUsage.None);
              vertexBuffer.SetData(vertices);
        }
Beispiel #4
0
        internal static void CreateVertexBuffer(GraphicsDevice graphicsDevice, TriangleMesh mesh, float angleLimit, out VertexBuffer vertexBuffer, out PrimitiveType primitiveType, out int primitiveCount)
        {
            // Note: We do not use shared vertices and an IndexBuffer because a vertex can be used by
            // several triangles with different normals.

            if (graphicsDevice == null)
            {
                throw new ArgumentNullException("graphicsDevice");
            }
            if (mesh == null)
            {
                throw new ArgumentNullException("mesh");
            }

            var numberOfTriangles = mesh.NumberOfTriangles;

            if (numberOfTriangles == 0)
            {
                primitiveType  = PrimitiveType.TriangleList;
                primitiveCount = 0;
                vertexBuffer   = null;
                return;
            }

            primitiveType  = PrimitiveType.TriangleList;
            primitiveCount = numberOfTriangles;
            int vertexCount = numberOfTriangles * 3;

            // Create vertex data for a triangle list.
            var vertices = new VertexPositionNormal[vertexCount];

            // Create vertex normals.
            var normals = mesh.ComputeNormals(false, angleLimit);

            for (int i = 0; i < numberOfTriangles; i++)
            {
                var i0 = mesh.Indices[i * 3 + 0];
                var i1 = mesh.Indices[i * 3 + 1];
                var i2 = mesh.Indices[i * 3 + 2];

                var v0 = mesh.Vertices[i0];
                var v1 = mesh.Vertices[i1];
                var v2 = mesh.Vertices[i2];

                Vector3F n0, n1, n2;
                if (angleLimit < 0)
                {
                    // If the angle limit is negative, ComputeNormals() returns one normal per vertex.
                    n0 = normals[i0];
                    n1 = normals[i1];
                    n2 = normals[i2];
                }
                else
                {
                    // If the angle limits is >= 0, ComputeNormals() returns 3 normals per triangle.
                    n0 = normals[i * 3 + 0];
                    n1 = normals[i * 3 + 1];
                    n2 = normals[i * 3 + 2];
                }

                // Add new vertex data.
                // DigitalRune.Geometry uses counter-clockwise front faces. XNA uses
                // clockwise front faces (CullMode.CullCounterClockwiseFace) per default.
                // Therefore we change the vertex orientation of the triangles.
                vertices[i * 3 + 0] = new VertexPositionNormal((Vector3)v0, (Vector3)n0);
                vertices[i * 3 + 1] = new VertexPositionNormal((Vector3)v2, (Vector3)n2); // v2 instead of v1!
                vertices[i * 3 + 2] = new VertexPositionNormal((Vector3)v1, (Vector3)n1);
            }

            // Create a vertex buffer.
            vertexBuffer = new VertexBuffer(graphicsDevice, typeof(VertexPositionNormal), vertexCount, BufferUsage.None);
            vertexBuffer.SetData(vertices);
        }
        public static Submesh CreateHemisphere(GraphicsDevice graphicsDevice, int numberOfSegments)
        {
            if (graphicsDevice == null)
            {
                throw new ArgumentNullException("graphicsDevice");
            }
            if (numberOfSegments < 3)
            {
                throw new ArgumentOutOfRangeException("numberOfSegments", "numberOfSegments must be greater than 2");
            }

            var submesh = new Submesh
            {
                PrimitiveType = PrimitiveType.TriangleList,
            };

            // The number of rings.
            int numberOfRings = numberOfSegments / 4;

            int numberOfVertices = numberOfSegments * numberOfRings + 1;
            var vertices         = new VertexPositionNormal[numberOfVertices];

            // Create rings.
            float angle = ConstantsF.TwoPi / numberOfSegments;

            // Next free index in vertices.
            int i = 0;

            // Top vertex.
            vertices[i++] = new VertexPositionNormal(new Vector3(0, 1, 0), new Vector3(0, 1, 0));

            // Compute vertices for rings from pole to equator and from the x-axis in
            // counterclockwise direction (when viewed from top).
            for (int ring = 0; ring < numberOfRings; ring++)
            {
                float upAngle    = angle * (ring + 1);
                float y          = (float)Math.Cos(upAngle);
                float ringRadius = (float)Math.Sin(upAngle);

                for (int segment = 0; segment < numberOfSegments; segment++)
                {
                    float x = ringRadius * (float)Math.Cos(angle * segment);
                    float z = ringRadius * (float)Math.Sin(angle * segment);
                    vertices[i++] = new VertexPositionNormal(new Vector3(x, y, z), new Vector3(x, y, z));
                }
            }

            Debug.Assert(i == numberOfVertices);

            submesh.VertexBuffer = new VertexBuffer(
                graphicsDevice,
                VertexPositionNormal.VertexDeclaration,
                vertices.Length,
                BufferUsage.None);
            submesh.VertexBuffer.SetData(vertices);

            submesh.VertexCount = submesh.VertexBuffer.VertexCount;

            // Build array of indices.
            int numberOfTriangles = numberOfSegments // Triangles in top cap.
                                    + numberOfSegments * 2 * (numberOfRings - 1);
            int numberOfIndices = 3 * numberOfTriangles;

            var indices = new ushort[numberOfIndices];

            i = 0;

            // Indices for top cap.
            for (int segment = 0; segment < numberOfSegments; segment++)
            {
                indices[i++] = 0;
                indices[i++] = (ushort)(segment + 1);
                if (segment + 1 < numberOfSegments)
                {
                    indices[i++] = (ushort)(segment + 2);
                }
                else
                {
                    indices[i++] = 1; // Wrap around to first vertex of the first ring.
                }
            }

            // Indices for rings between the caps.
            for (int ring = 1; ring < numberOfRings; ring++)
            {
                for (int segment = 0; segment < numberOfSegments; segment++)
                {
                    // Each segment has 2 triangles.
                    if (segment + 1 < numberOfSegments)
                    {
                        indices[i++] = (ushort)(1 + (ring - 1) * numberOfSegments + segment);
                        indices[i++] = (ushort)(1 + ring * numberOfSegments + segment);
                        indices[i++] = (ushort)(1 + ring * numberOfSegments + segment + 1);

                        indices[i++] = (ushort)(1 + ring * numberOfSegments + segment + 1);
                        indices[i++] = (ushort)(1 + (ring - 1) * numberOfSegments + segment + 1);
                        indices[i++] = (ushort)(1 + (ring - 1) * numberOfSegments + segment);
                    }
                    else
                    {
                        // Handle wrap around.
                        indices[i++] = (ushort)(1 + (ring - 1) * numberOfSegments + segment);
                        indices[i++] = (ushort)(1 + ring * numberOfSegments + segment);
                        indices[i++] = (ushort)(1 + ring * numberOfSegments);

                        indices[i++] = (ushort)(1 + ring * numberOfSegments);
                        indices[i++] = (ushort)(1 + (ring - 1) * numberOfSegments);
                        indices[i++] = (ushort)(1 + (ring - 1) * numberOfSegments + segment);
                    }
                }
            }

            Debug.Assert(i == numberOfIndices);

            submesh.IndexBuffer = new IndexBuffer(
                graphicsDevice,
                IndexElementSize.SixteenBits,
                indices.Length,
                BufferUsage.None);
            submesh.IndexBuffer.SetData(indices);

            submesh.PrimitiveCount = indices.Length / 3;

            return(submesh);
        }
        public static Submesh CreateUVSphere(GraphicsDevice graphicsDevice, int numberOfSegments)
        {
            if (graphicsDevice == null)
            throw new ArgumentNullException("graphicsDevice");
              if (numberOfSegments < 3)
            throw new ArgumentOutOfRangeException("numberOfSegments", "numberOfSegments must be greater than 2");

              var submesh = new Submesh
              {
            PrimitiveType = PrimitiveType.TriangleList,
              };

              // The number of slices (horizontal cuts, not including the poles).
              int numberOfSlices = numberOfSegments / 2 - 1;

              // The number of rings (horizontal bands of triangles).
              int numberOfRings = numberOfSegments / 2;

              int numberOfVertices = numberOfSegments * numberOfSlices + 2;
              var vertices = new VertexPositionNormal[numberOfVertices];

              // Create rings.
              float angle = ConstantsF.TwoPi / numberOfSegments;

              // Next free index in vertices.
              int i = 0;

              // Top vertex.
              vertices[i++] = new VertexPositionNormal(new Vector3(0, 1, 0), new Vector3(0, 1, 0));

              // Compute vertices for rings from top to bottom and from the x-axis in
              // clockwise direction (when viewed from top).
              for (int slice = 0; slice < numberOfSlices; slice++)
              {
            float upAngle = angle * (slice + 1);
            float y = (float)Math.Cos(upAngle);
            float ringRadius = (float)Math.Sin(upAngle);

            for (int segment = 0; segment < numberOfSegments; segment++)
            {
              float x = ringRadius * (float)Math.Cos(angle * segment);
              float z = ringRadius * (float)Math.Sin(angle * segment);
              vertices[i++] = new VertexPositionNormal(new Vector3(x, y, z), new Vector3(x, y, z));
            }
              }

              // Bottom vertex.
              vertices[i++] = new VertexPositionNormal(new Vector3(0, -1, 0), new Vector3(0, -1, 0));

              Debug.Assert(i == numberOfVertices);

              submesh.VertexBuffer = new VertexBuffer(
            graphicsDevice,
            VertexPositionNormal.VertexDeclaration,
            vertices.Length,
            BufferUsage.None);
              submesh.VertexBuffer.SetData(vertices);

              submesh.VertexCount = submesh.VertexBuffer.VertexCount;

              // Build array of indices.
              int numberOfTriangles = numberOfSegments * 2 // Triangles in top and bottom cap.
                              + numberOfSegments * 2 * (numberOfRings - 2);
              int numberOfIndices = 3 * numberOfTriangles;

              var indices = new ushort[numberOfIndices];
              i = 0;

              // Indices for top cap.
              for (int segment = 0; segment < numberOfSegments; segment++)
              {
            indices[i++] = 0;
            indices[i++] = (ushort)(segment + 1);
            if (segment + 1 < numberOfSegments)
              indices[i++] = (ushort)(segment + 2);
            else
              indices[i++] = 1; // Wrap around to first vertex of the first ring.
              }

              // Indices for rings between the caps.
              for (int ring = 1; ring < numberOfRings - 1; ring++)
              {
            for (int segment = 0; segment < numberOfSegments; segment++)
            {
              // Each segment has 2 triangles.
              if (segment + 1 < numberOfSegments)
              {
            indices[i++] = (ushort)(1 + (ring - 1) * numberOfSegments + segment);
            indices[i++] = (ushort)(1 + ring * numberOfSegments + segment);
            indices[i++] = (ushort)(1 + ring * numberOfSegments + segment + 1);

            indices[i++] = (ushort)(1 + ring * numberOfSegments + segment + 1);
            indices[i++] = (ushort)(1 + (ring - 1) * numberOfSegments + segment + 1);
            indices[i++] = (ushort)(1 + (ring - 1) * numberOfSegments + segment);
              }
              else
              {
            // Handle wrap around.
            indices[i++] = (ushort)(1 + (ring - 1) * numberOfSegments + segment);
            indices[i++] = (ushort)(1 + ring * numberOfSegments + segment);
            indices[i++] = (ushort)(1 + ring * numberOfSegments);

            indices[i++] = (ushort)(1 + ring * numberOfSegments);
            indices[i++] = (ushort)(1 + (ring - 1) * numberOfSegments);
            indices[i++] = (ushort)(1 + (ring - 1) * numberOfSegments + segment);
              }
            }
              }

              // Index of first vertex on last slice.
              int baseIndex = numberOfVertices - numberOfSegments - 1;

              // Indices for bottom cap.
              for (int segment = 0; segment < numberOfSegments; segment++)
              {
            indices[i++] = (ushort)(numberOfVertices - 1);
            if (segment + 1 < numberOfSegments)
              indices[i++] = (ushort)(baseIndex + segment + 1);
            else
              indices[i++] = (ushort)baseIndex;   // Wrap around to first vertex.

            indices[i++] = (ushort)(baseIndex + segment);
              }

              Debug.Assert(i == numberOfIndices);

              submesh.IndexBuffer = new IndexBuffer(
            graphicsDevice,
            IndexElementSize.SixteenBits,
            indices.Length,
            BufferUsage.None);
              submesh.IndexBuffer.SetData(indices);

              submesh.PrimitiveCount = indices.Length / 3;

              return submesh;
        }