Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
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];

        Vector3 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);
    }
Exemplo n.º 3
0
        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);
        }