//-----------------------------------------------------------------------------
// SpherePrimitive.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace PerformanceMeasuring
{
///
/// Geometric primitive class for drawing spheres.
///
/// This class is borrowed from the Primitives3D sample.
///
public class SpherePrimitive : GeometricPrimitive
{
///
/// Constructs a new sphere primitive, using default settings.
///
public SpherePrimitive(GraphicsDevice graphicsDevice)
: this(graphicsDevice, 1, 16)
{
}
///
/// Constructs a new sphere primitive,
/// with the specified size and tessellation level.
///
public SpherePrimitive(GraphicsDevice graphicsDevice, float diameter, int tessellation)
{
if (tessellation < 3)
throw new ArgumentOutOfRangeException("tessellation");
int verticalSegments = tessellation;
int horizontalSegments = tessellation * 2;
float radius = diameter / 2;
// Start with a single vertex at the bottom of the sphere.
AddVertex(Vector3.Down * radius, Vector3.Down);
// 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);
// Create a single ring of vertices at this latitude.
for (int j = 0; j < horizontalSegments; j++)
{
float longitude = j * MathHelper.TwoPi / horizontalSegments;
float dx = (float)Math.Cos(longitude) * dxz;
float dz = (float)Math.Sin(longitude) * dxz;
Vector3 normal = new Vector3(dx, dy, dz);
AddVertex(normal * radius, normal);
}
}
// Finish with a single vertex at the top of the sphere.
AddVertex(Vector3.Up * radius, Vector3.Up);
// Create a fan connecting the bottom vertex to the bottom latitude ring.
for (int i = 0; i < horizontalSegments; i++)
{
AddIndex(0);
AddIndex(1 + (i + 1) % horizontalSegments);
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;
AddIndex(1 + i * horizontalSegments + j);
AddIndex(1 + i * horizontalSegments + nextJ);
AddIndex(1 + nextI * horizontalSegments + j);
AddIndex(1 + i * horizontalSegments + nextJ);
AddIndex(1 + nextI * horizontalSegments + nextJ);
AddIndex(1 + nextI * horizontalSegments + j);
}
}
// Create a fan connecting the top vertex to the top latitude ring.
for (int i = 0; i < horizontalSegments; i++)
{
AddIndex(CurrentVertex - 1);
AddIndex(CurrentVertex - 2 - (i + 1) % horizontalSegments);
AddIndex(CurrentVertex - 2 - i);
}
InitializePrimitive(graphicsDevice);
}
}
}