public static Mesh Compute(int numberOfSubdivisions, SubdivisionSphereVertexAttributes vertexAttributes) { if (numberOfSubdivisions < 0) { throw new ArgumentOutOfRangeException("numberOfSubdivisions"); } if ((vertexAttributes & SubdivisionSphereVertexAttributes.Position) != SubdivisionSphereVertexAttributes.Position) { throw new ArgumentException("Positions must be provided.", "vertexAttributes"); } Mesh mesh = new Mesh(); mesh.PrimitiveType = PrimitiveType.Triangles; mesh.FrontFaceWindingOrder = WindingOrder.Counterclockwise; int numberOfVertices = SubdivisionUtility.NumberOfVertices(numberOfSubdivisions); VertexAttributeDoubleVector3 positionsAttribute = new VertexAttributeDoubleVector3("position", numberOfVertices); mesh.Attributes.Add(positionsAttribute); IndicesUnsignedInt indices = new IndicesUnsignedInt(3 * SubdivisionUtility.NumberOfTriangles(numberOfSubdivisions)); mesh.Indices = indices; SubdivisionMesh subdivisionMesh = new SubdivisionMesh(); subdivisionMesh.Positions = positionsAttribute.Values; subdivisionMesh.Indices = indices; if ((vertexAttributes & SubdivisionSphereVertexAttributes.Normal) == SubdivisionSphereVertexAttributes.Normal) { VertexAttributeHalfFloatVector3 normalsAttribute = new VertexAttributeHalfFloatVector3("normal", numberOfVertices); mesh.Attributes.Add(normalsAttribute); subdivisionMesh.Normals = normalsAttribute.Values; } if ((vertexAttributes & SubdivisionSphereVertexAttributes.TextureCoordinate) == SubdivisionSphereVertexAttributes.TextureCoordinate) { VertexAttributeHalfFloatVector2 textureCoordinateAttribute = new VertexAttributeHalfFloatVector2("textureCoordinate", numberOfVertices); mesh.Attributes.Add(textureCoordinateAttribute); subdivisionMesh.TextureCoordinate = textureCoordinateAttribute.Values; } // // Initial tetrahedron // double negativeRootTwoOverThree = -Math.Sqrt(2.0) / 3.0; const double negativeOneThird = -1.0 / 3.0; double rootSixOverThree = Math.Sqrt(6.0) / 3.0; Vector3D p0 = new Vector3D(0, 0, 1); Vector3D p1 = new Vector3D(0, (2.0 * Math.Sqrt(2.0)) / 3.0, negativeOneThird); Vector3D p2 = new Vector3D(-rootSixOverThree, negativeRootTwoOverThree, negativeOneThird); Vector3D p3 = new Vector3D(rootSixOverThree, negativeRootTwoOverThree, negativeOneThird); subdivisionMesh.Positions.Add(p0); subdivisionMesh.Positions.Add(p1); subdivisionMesh.Positions.Add(p2); subdivisionMesh.Positions.Add(p3); if (subdivisionMesh.Normals != null) { subdivisionMesh.Normals.Add(p0.ToVector3H()); subdivisionMesh.Normals.Add(p1.ToVector3H()); subdivisionMesh.Normals.Add(p2.ToVector3H()); subdivisionMesh.Normals.Add(p3.ToVector3H()); } if (subdivisionMesh.TextureCoordinate != null) { subdivisionMesh.TextureCoordinate.Add(SubdivisionUtility.ComputeTextureCoordinate(p0)); subdivisionMesh.TextureCoordinate.Add(SubdivisionUtility.ComputeTextureCoordinate(p1)); subdivisionMesh.TextureCoordinate.Add(SubdivisionUtility.ComputeTextureCoordinate(p2)); subdivisionMesh.TextureCoordinate.Add(SubdivisionUtility.ComputeTextureCoordinate(p3)); } Subdivide(subdivisionMesh, new TriangleIndicesUnsignedInt(0, 1, 2), numberOfSubdivisions); Subdivide(subdivisionMesh, new TriangleIndicesUnsignedInt(0, 2, 3), numberOfSubdivisions); Subdivide(subdivisionMesh, new TriangleIndicesUnsignedInt(0, 3, 1), numberOfSubdivisions); Subdivide(subdivisionMesh, new TriangleIndicesUnsignedInt(1, 3, 2), numberOfSubdivisions); return(mesh); }
public static Mesh Compute(int numberOfSubdivisions, SubdivisionSphereVertexAttributes vertexAttributes) { if (numberOfSubdivisions < 0) { throw new ArgumentOutOfRangeException("numberOfSubdivisions"); } if ((vertexAttributes & SubdivisionSphereVertexAttributes.Position) != SubdivisionSphereVertexAttributes.Position) { throw new ArgumentException("Positions must be provided.", "vertexAttributes"); } Mesh mesh = new Mesh(); mesh.PrimitiveType = PrimitiveType.Triangles; mesh.FrontFaceWindingOrder = WindingOrder.Counterclockwise; int numberOfVertices = SubdivisionUtility.NumberOfVertices(numberOfSubdivisions); VertexAttributeDoubleVector3 positionsAttribute = new VertexAttributeDoubleVector3("position", numberOfVertices); mesh.Attributes.Add(positionsAttribute); IndicesUnsignedInt indices = new IndicesUnsignedInt(3 * SubdivisionUtility.NumberOfTriangles(numberOfSubdivisions)); mesh.Indices = indices; SubdivisionMesh subdivisionMesh = new SubdivisionMesh(); subdivisionMesh.Positions = positionsAttribute.Values; subdivisionMesh.Indices = indices; if ((vertexAttributes & SubdivisionSphereVertexAttributes.Normal) == SubdivisionSphereVertexAttributes.Normal) { VertexAttributeHalfFloatVector3 normalsAttribute = new VertexAttributeHalfFloatVector3("normal", numberOfVertices); mesh.Attributes.Add(normalsAttribute); subdivisionMesh.Normals = normalsAttribute.Values; } if ((vertexAttributes & SubdivisionSphereVertexAttributes.TextureCoordinate) == SubdivisionSphereVertexAttributes.TextureCoordinate) { VertexAttributeHalfFloatVector2 textureCoordinateAttribute = new VertexAttributeHalfFloatVector2("textureCoordinate", numberOfVertices); mesh.Attributes.Add(textureCoordinateAttribute); subdivisionMesh.TextureCoordinate = textureCoordinateAttribute.Values; } // // Initial tetrahedron // double negativeRootTwoOverThree = -Math.Sqrt(2.0) / 3.0; const double negativeOneThird = -1.0 / 3.0; double rootSixOverThree = Math.Sqrt(6.0) / 3.0; Vector3D p0 = new Vector3D(0, 0, 1); Vector3D p1 = new Vector3D(0, (2.0 * Math.Sqrt(2.0)) / 3.0, negativeOneThird); Vector3D p2 = new Vector3D(-rootSixOverThree, negativeRootTwoOverThree, negativeOneThird); Vector3D p3 = new Vector3D(rootSixOverThree, negativeRootTwoOverThree, negativeOneThird); subdivisionMesh.Positions.Add(p0); subdivisionMesh.Positions.Add(p1); subdivisionMesh.Positions.Add(p2); subdivisionMesh.Positions.Add(p3); if (subdivisionMesh.Normals != null) { subdivisionMesh.Normals.Add(p0.ToVector3H()); subdivisionMesh.Normals.Add(p1.ToVector3H()); subdivisionMesh.Normals.Add(p2.ToVector3H()); subdivisionMesh.Normals.Add(p3.ToVector3H()); } if (subdivisionMesh.TextureCoordinate != null) { subdivisionMesh.TextureCoordinate.Add(SubdivisionUtility.ComputeTextureCoordinate(p0)); subdivisionMesh.TextureCoordinate.Add(SubdivisionUtility.ComputeTextureCoordinate(p1)); subdivisionMesh.TextureCoordinate.Add(SubdivisionUtility.ComputeTextureCoordinate(p2)); subdivisionMesh.TextureCoordinate.Add(SubdivisionUtility.ComputeTextureCoordinate(p3)); } Subdivide(subdivisionMesh, new TriangleIndicesUnsignedInt(0, 1, 2), numberOfSubdivisions); Subdivide(subdivisionMesh, new TriangleIndicesUnsignedInt(0, 2, 3), numberOfSubdivisions); Subdivide(subdivisionMesh, new TriangleIndicesUnsignedInt(0, 3, 1), numberOfSubdivisions); Subdivide(subdivisionMesh, new TriangleIndicesUnsignedInt(1, 3, 2), numberOfSubdivisions); return mesh; }