public static void AddRegularPolygon(this MeshGeometry3D mesh,
                                             int numSides, Point3D center, Vector3D vx, Vector3D vy,
                                             Dictionary <Point3D, int> pointDict = null,
                                             Point[] textureCoords = null)
        {
            // Generate the points.
            Point3D[] points = G3.MakePolygonPoints(numSides, center, vx, vy);

            // Make the polygon.
            mesh.AddPolygon(points, textureCoords);
        }
        // Make a tetrahedron without texture coordinates or smoothing.
        public static void AddTetrahedron(this MeshGeometry3D mesh, bool centered = true)
        {
            // Get the points.
            Point3D A, B, C, D;

            G3.TetrahedronPoints(out A, out B, out C, out D, centered);

            // Make the triangles.
            mesh.AddPolygon(A, B, C);
            mesh.AddPolygon(A, C, D);
            mesh.AddPolygon(A, D, B);
            mesh.AddPolygon(D, C, B);
        }
        public static void VerifyTetrahedron()
        {
            // Get the points.
            Point3D A, B, C, D;

            G3.TetrahedronPoints(out A, out B, out C, out D, true);

            // Verify the points.
            G3.VerifyPoints(A, B, C, D);

            // Verify the faces.
            G3.VerifyPolygon(A, B, C);
            G3.VerifyPolygon(A, C, D);
            G3.VerifyPolygon(A, D, B);
            G3.VerifyPolygon(D, C, B);
        }
        // Make a torus without texture coordinates.
        public static void AddTorus(this MeshGeometry3D mesh,
                                    Point3D center, double R, double r, int numTheta, int numPhi,
                                    bool smooth = false)
        {
            // Make a point dictionary if needed.
            Dictionary <Point3D, int> pointDict = null;

            if (smooth)
            {
                pointDict = new Dictionary <Point3D, int>();
            }

            // Generate the points.
            double dtheta = 2 * Math.PI / numTheta;
            double dphi   = 2 * Math.PI / numPhi;
            double theta  = 0;

            for (int t = 0; t < numTheta; t++)
            {
                double phi = 0;
                for (int p = 0; p < numPhi; p++)
                {
                    // Find this piece's points.
                    Point3D[] points =
                    {
                        G3.TorusPoint(center, R, r, theta + dtheta, phi),
                        G3.TorusPoint(center, R, r, theta + dtheta, phi + dphi),
                        G3.TorusPoint(center, R, r, theta,          phi + dphi),
                        G3.TorusPoint(center, R, r, theta,          phi),
                    };

                    // Make the polygon.
                    mesh.AddPolygon(pointDict, points);

                    phi += dphi;
                }
                theta += dtheta;
            }
        }
        // Add a textured torus.
        public static void AddTexturedTorus(this MeshGeometry3D mesh,
                                            Point3D center, double R, double r, int numTheta, int numPhi,
                                            bool smooth = false)
        {
            double dtheta = 2 * Math.PI / numTheta;
            double dphi   = 2 * Math.PI / numPhi;
            double theta  = Math.PI;        // Puts the texture's top/bottom on the inside.

            for (int t = 0; t < numTheta; t++)
            {
                double phi = 0;
                for (int p = 0; p < numPhi; p++)
                {
                    // Find this piece's points.
                    Point3D point1 = G3.TorusPoint(center, R, r, theta, phi).Round();
                    Point3D point2 = G3.TorusPoint(center, R, r, theta + dtheta, phi).Round();
                    Point3D point3 = G3.TorusPoint(center, R, r, theta + dtheta, phi + dphi).Round();
                    Point3D point4 = G3.TorusPoint(center, R, r, theta, phi + dphi).Round();

                    // Find this piece's normals.
                    Vector3D normal1 = G3.TorusNormal(D3.Origin, R, r, theta, phi);
                    Vector3D normal2 = G3.TorusNormal(D3.Origin, R, r, theta + dtheta, phi);
                    Vector3D normal3 = G3.TorusNormal(D3.Origin, R, r, theta + dtheta, phi + dphi);
                    Vector3D normal4 = G3.TorusNormal(D3.Origin, R, r, theta, phi + dphi);

                    // Find this piece's texture coordinates.
                    Point coords1 = new Point(1 - (double)p / numPhi, 1 - (double)t / numTheta);
                    Point coords2 = new Point(1 - (double)p / numPhi, 1 - (double)(t + 1) / numTheta);
                    Point coords3 = new Point(1 - (double)(p + 1) / numPhi, 1 - (double)(t + 1) / numTheta);
                    Point coords4 = new Point(1 - (double)(p + 1) / numPhi, 1 - (double)t / numTheta);

                    // Make the first triangle.
                    int index = mesh.Positions.Count;
                    mesh.Positions.Add(point1);
                    if (smooth)
                    {
                        mesh.Normals.Add(normal1);
                    }
                    mesh.TextureCoordinates.Add(coords1);

                    mesh.Positions.Add(point2);
                    if (smooth)
                    {
                        mesh.Normals.Add(normal2);
                    }
                    mesh.TextureCoordinates.Add(coords2);

                    mesh.Positions.Add(point3);
                    if (smooth)
                    {
                        mesh.Normals.Add(normal3);
                    }
                    mesh.TextureCoordinates.Add(coords3);

                    mesh.TriangleIndices.Add(index++);
                    mesh.TriangleIndices.Add(index++);
                    mesh.TriangleIndices.Add(index++);

                    // Make the second triangle.
                    mesh.Positions.Add(point1);
                    if (smooth)
                    {
                        mesh.Normals.Add(normal1);
                    }
                    mesh.TextureCoordinates.Add(coords1);

                    mesh.Positions.Add(point3);
                    if (smooth)
                    {
                        mesh.Normals.Add(normal3);
                    }
                    mesh.TextureCoordinates.Add(coords3);

                    mesh.Positions.Add(point4);
                    if (smooth)
                    {
                        mesh.Normals.Add(normal4);
                    }
                    mesh.TextureCoordinates.Add(coords4);

                    mesh.TriangleIndices.Add(index++);
                    mesh.TriangleIndices.Add(index++);
                    mesh.TriangleIndices.Add(index++);

                    phi += dphi;
                }
                theta += dtheta;
            }

            // Add texture coordinates 1.01 to prevent "seams."
            mesh.Positions.Add(new Point3D());
            mesh.TextureCoordinates.Add(new Point(1.01, 1.01));
        }
        // Add a sphere with texture coordinates.
        public static void AddTexturedSphere(this MeshGeometry3D mesh,
                                             Point3D center, double radius, int numTheta, int numPhi,
                                             bool smooth = false)
        {
            double dtheta = 2 * Math.PI / numTheta;
            double dphi   = Math.PI / numPhi;
            double theta  = 0;

            for (int t = 0; t < numTheta; t++)
            {
                double phi = 0;
                for (int p = 0; p < numPhi; p++)
                {
                    // Find this piece's points.
                    Point3D point1 = G3.SpherePoint(center, radius, theta, phi).Round();
                    Point3D point2 = G3.SpherePoint(center, radius, theta, phi + dphi).Round();
                    Point3D point3 = G3.SpherePoint(center, radius, theta + dtheta, phi + dphi).Round();
                    Point3D point4 = G3.SpherePoint(center, radius, theta + dtheta, phi).Round();

                    // Find this piece's texture coordinates.
                    Point coords1 = new Point((double)t / numTheta, (double)p / numPhi);
                    Point coords2 = new Point((double)t / numTheta, (double)(p + 1) / numPhi);
                    Point coords3 = new Point((double)(t + 1) / numTheta, (double)(p + 1) / numPhi);
                    Point coords4 = new Point((double)(t + 1) / numTheta, (double)p / numPhi);

                    // Find this piece's normals.
                    Vector3D normal1 = (Vector3D)G3.SpherePoint(D3.Origin, 1, theta, phi).Round();
                    Vector3D normal2 = (Vector3D)G3.SpherePoint(D3.Origin, 1, theta, phi + dphi).Round();
                    Vector3D normal3 = (Vector3D)G3.SpherePoint(D3.Origin, 1, theta + dtheta, phi + dphi).Round();
                    Vector3D normal4 = (Vector3D)G3.SpherePoint(D3.Origin, 1, theta + dtheta, phi).Round();

                    // Make the first triangle.
                    int index = mesh.Positions.Count;
                    mesh.Positions.Add(point1);
                    if (smooth)
                    {
                        mesh.Normals.Add(normal1);
                    }
                    mesh.TextureCoordinates.Add(coords1);

                    mesh.Positions.Add(point2);
                    if (smooth)
                    {
                        mesh.Normals.Add(normal2);
                    }
                    mesh.TextureCoordinates.Add(coords2);

                    mesh.Positions.Add(point3);
                    if (smooth)
                    {
                        mesh.Normals.Add(normal3);
                    }
                    mesh.TextureCoordinates.Add(coords3);

                    mesh.TriangleIndices.Add(index++);
                    mesh.TriangleIndices.Add(index++);
                    mesh.TriangleIndices.Add(index++);

                    // Make the second triangle.
                    mesh.Positions.Add(point1);
                    if (smooth)
                    {
                        mesh.Normals.Add(normal1);
                    }
                    mesh.TextureCoordinates.Add(coords1);

                    mesh.Positions.Add(point3);
                    if (smooth)
                    {
                        mesh.Normals.Add(normal3);
                    }
                    mesh.TextureCoordinates.Add(coords3);

                    mesh.Positions.Add(point4);
                    if (smooth)
                    {
                        mesh.Normals.Add(normal4);
                    }
                    mesh.TextureCoordinates.Add(coords4);

                    mesh.TriangleIndices.Add(index++);
                    mesh.TriangleIndices.Add(index++);
                    mesh.TriangleIndices.Add(index++);

                    phi += dphi;
                }
                theta += dtheta;
            }
        }