public override GeometryData GenerateGeometry()
        {
            GeometryData GeometryData = new GeometryData();
            int verticalSegments = (int)Tessellation;
            int horizontalSegments = (int)Tessellation * 2;

            // Start with a single vertex at the bottom of the sphere.
            GeometryData.AddVertex(new VertexPosNorTexTanBin(MathHelper.Down * Radius, MathHelper.Down, new Vector2(0.5f, 1.0f), new Vector3(0, 0, -1), new Vector3(-1, 0, 0)));

            float maxlat = ((verticalSegments) * MathHelper.Pi /
                                        verticalSegments) - MathHelper.PiOver2;
            float maxlon = horizontalSegments * MathHelper.TwoPi / horizontalSegments;

            // Create rings of vertices at progressively higher latitudes.
            for (int i = 0; i < verticalSegments - 1; i++)
            {
                float latitude = ((i + 1) * MathHelper.Pi / verticalSegments) - MathHelper.PiOver2;

                float dy = (float)Math.Sin(latitude);
                float dxz = (float)Math.Cos(latitude);
                float dyb = (float)Math.Atan2((float)Math.Sin(-latitude), (float)Math.Cos(-latitude));

                // Create a single ring of vertices at this latitude.
                for (int j = -(horizontalSegments / 2) + 1; j < (horizontalSegments / 2) + 1; j++)
                {
                    float longitude = j * MathHelper.TwoPi / horizontalSegments;

                    float dx = (float)Math.Cos(longitude) * dxz;
                    float dxt = (float)Math.Cos(longitude + MathHelper.PiOver2);
                    float dz = (float)Math.Sin(longitude) * dxz;
                    float dzt = (float)Math.Sin(longitude + MathHelper.PiOver2);
                    Vector3 normal = new Vector3(dx, dy, dz);
                    Vector3 position = normal * Radius;
                    Vector2 texcoord = GeometryData.GenerateUV(ProjectionType.Spherical, position, normal, new Vector2(1, 1));
                    GeometryData.AddVertex(new VertexPosNorTexTanBin(position, normal, texcoord,
                        new Vector3(dxt, 0, dzt), Vector3.Normalize(Vector3.Cross(normal, new Vector3(dxt, 0, dzt)))));
                }
            }

            // Finish with a single vertex at the top of the sphere.
            GeometryData.AddVertex(new VertexPosNorTexTanBin(MathHelper.Up * Radius, MathHelper.Up, new Vector2(0.5f, 1.0f), new Vector3(0, 0, 1), new Vector3(1, 0, 0)));

            // Create a fan connecting the bottom vertex to the bottom latitude ring.
            for (int i = 0; i < horizontalSegments; i++)
            {
                GeometryData.AddIndex(0);
                GeometryData.AddIndex(1 + (i + 1) % horizontalSegments);
                GeometryData.AddIndex(1 + i);
            }

            // Fill the sphere body with triangles joining each pair of latitude rings.
            for (int i = 0; i < verticalSegments - 2; i++)
            {
                for (int j = 0; j < horizontalSegments; j++)
                {
                    int nextI = i + 1;
                    int nextJ = (j + 1) % horizontalSegments;

                    GeometryData.AddIndex(1 + i * horizontalSegments + j);
                    GeometryData.AddIndex(1 + i * horizontalSegments + nextJ);
                    GeometryData.AddIndex(1 + nextI * horizontalSegments + j);

                    GeometryData.AddIndex(1 + i * horizontalSegments + nextJ);
                    GeometryData.AddIndex(1 + nextI * horizontalSegments + nextJ);
                    GeometryData.AddIndex(1 + nextI * horizontalSegments + j);
                }
            }

            // Create a fan connecting the top vertex to the top latitude ring.
            for (int i = 0; i < horizontalSegments; i++)
            {
                GeometryData.AddIndex(GeometryData.CurrentVertex - 1);
                GeometryData.AddIndex(GeometryData.CurrentVertex - 2 - (i + 1) % horizontalSegments);
                GeometryData.AddIndex(GeometryData.CurrentVertex - 2 - i);
            }

            return GeometryData;
        }
 public GeometricPrimitive()
 {
     geometryData = new GeometryData();
     matrixWorld = Matrix.Identity;
 }
        public override GeometryData GenerateGeometry()
        {
            GeometryData GeometryData = new GeometryData();

            Vector3[] normals =
            {
                new Vector3(0, 0, 1),
                new Vector3(0, 0, -1),
                new Vector3(1, 0, 0),
                new Vector3(-1, 0, 0),
                new Vector3(0, 1, 0),
                new Vector3(0, -1, 0),
            };

            Vector2[] texcoords =
            {
                new Vector2(1, 1),
                new Vector2(0, 1),
                new Vector2(0, 0),
                new Vector2(1, 0),

                new Vector2(0, 0),
                new Vector2(1, 0),
                new Vector2(1, 1),
                new Vector2(0, 1),

                new Vector2(1, 0),
                new Vector2(1, 1),
                new Vector2(0, 1),
                new Vector2(0, 0),

                new Vector2(1, 0),
                new Vector2(1, 1),
                new Vector2(0, 1),
                new Vector2(0, 0),

                new Vector2(1, 1),
                new Vector2(0, 1),
                new Vector2(0, 0),
                new Vector2(1, 0),

                new Vector2(1, 1),
                new Vector2(0, 1),
                new Vector2(0, 0),
                new Vector2(1, 0),
            };

            int i = 0;
            foreach (Vector3 normal in normals)
            {
                // Get two vectors perpendicular to the face normal and to each other.
                Vector3 side1 = new Vector3(normal.Y, normal.Z, normal.X);
                Vector3 side2 = Vector3.Cross(normal, side1);

                // Six indices (two triangles) per face.
                GeometryData.AddIndex(GeometryData.CurrentVertex + 0);
                GeometryData.AddIndex(GeometryData.CurrentVertex + 1);
                GeometryData.AddIndex(GeometryData.CurrentVertex + 2);

                GeometryData.AddIndex(GeometryData.CurrentVertex + 0);
                GeometryData.AddIndex(GeometryData.CurrentVertex + 2);
                GeometryData.AddIndex(GeometryData.CurrentVertex + 3);

                // Four vertices per face.
                float size = Dimensions.X;
                if (normal.Z != 0)
                    size = Dimensions.Z;
                else if (normal.Y != 0)
                    size = Dimensions.Y;

                GeometryData.AddVertex(new VertexPosNorTexTanBin((normal - side1 - side2) * size / 2, normal, texcoords[i], side2, side1));
                GeometryData.AddVertex(new VertexPosNorTexTanBin((normal - side1 + side2) * size / 2, normal, texcoords[i + 1], side2, side1));
                GeometryData.AddVertex(new VertexPosNorTexTanBin((normal + side1 + side2) * size / 2, normal, texcoords[i + 2], side2, side1));
                GeometryData.AddVertex(new VertexPosNorTexTanBin((normal + side1 - side2) * size / 2, normal, texcoords[i + 3], side2, side1));
                i += 4;
            }
            return GeometryData;
        }