private static void _createSphere( Mesh mesh )
{
// sphere creation code taken from the DeferredShading sample, originally from the [Ogre] wiki
SubMesh pSphereVertex = mesh.CreateSubMesh();
const int NUM_SEGMENTS = 16;
const int NUM_RINGS = 16;
const float SPHERE_RADIUS = 50.0f;
mesh.SharedVertexData = new VertexData();
VertexData vertexData = mesh.SharedVertexData;
// define the vertex format
VertexDeclaration vertexDecl = vertexData.vertexDeclaration;
int offset = 0;
// positions
vertexDecl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Position );
offset += VertexElement.GetTypeSize( VertexElementType.Float3 );
// normals
vertexDecl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Normal );
offset += VertexElement.GetTypeSize( VertexElementType.Float3 );
// two dimensional texture coordinates
vertexDecl.AddElement( 0, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 0 );
offset += VertexElement.GetTypeSize( VertexElementType.Float2 );
// allocate the vertex buffer
vertexData.vertexCount = ( NUM_RINGS + 1 ) * ( NUM_SEGMENTS + 1 );
HardwareVertexBuffer vBuf = HardwareBufferManager.Instance.CreateVertexBuffer( vertexDecl.Clone( 0 ), vertexData.vertexCount, BufferUsage.StaticWriteOnly, false );
VertexBufferBinding binding = vertexData.vertexBufferBinding;
binding.SetBinding( 0, vBuf );
// allocate index buffer
pSphereVertex.IndexData.indexCount = 6 * NUM_RINGS * ( NUM_SEGMENTS + 1 );
pSphereVertex.IndexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, pSphereVertex.IndexData.indexCount, BufferUsage.StaticWriteOnly, false );
HardwareIndexBuffer iBuf = pSphereVertex.IndexData.indexBuffer;
unsafe
{
float* pVertex = (float*)vBuf.Lock( BufferLocking.Discard );
ushort* pIndices =(ushort*)iBuf.Lock( BufferLocking.Discard );
float fDeltaRingAngle = ( Utility.PI / NUM_RINGS );
float fDeltaSegAngle = ( 2 * Utility.PI / NUM_SEGMENTS );
ushort wVerticeIndex = 0;
// Generate the group of rings for the sphere
for ( int ring = 0; ring <= NUM_RINGS; ring++ )
{
float r0 = SPHERE_RADIUS * Utility.Sin( ring * fDeltaRingAngle );
float y0 = SPHERE_RADIUS * Utility.Cos( ring * fDeltaRingAngle );
// Generate the group of segments for the current ring
for ( int seg = 0; seg <= NUM_SEGMENTS; seg++ )
{
float x0 = r0 * Utility.Sin( seg * fDeltaSegAngle );
float z0 = r0 * Utility.Cos( seg * fDeltaSegAngle );
// Add one vertex to the strip which makes up the sphere
*pVertex++ = x0;
*pVertex++ = y0;
*pVertex++ = z0;
Vector3 vNormal = new Vector3( x0, y0, z0 );
vNormal.Normalize();
*pVertex++ = vNormal.x;
*pVertex++ = vNormal.y;
*pVertex++ = vNormal.z;
*pVertex++ = (float)seg / (float)NUM_SEGMENTS;
*pVertex++ = (float)ring / (float)NUM_RINGS;
if ( ring != NUM_RINGS )
{
// each vertex (except the last) has six indicies pointing to it
*pIndices++ = (ushort)( wVerticeIndex + NUM_SEGMENTS + 1 );
*pIndices++ = (ushort)( wVerticeIndex );
*pIndices++ = (ushort)( wVerticeIndex + NUM_SEGMENTS );
*pIndices++ = (ushort)( wVerticeIndex + NUM_SEGMENTS + 1 );
*pIndices++ = (ushort)( wVerticeIndex + 1 );
*pIndices++ = (ushort)( wVerticeIndex );
wVerticeIndex++;
}
}; // end for seg
} // end for ring
}
// Unlock
vBuf.Unlock();
iBuf.Unlock();
// Generate face list
pSphereVertex.useSharedVertices = true;
// the original code was missing this line:
mesh.BoundingBox = new AxisAlignedBox( new Vector3( -SPHERE_RADIUS, -SPHERE_RADIUS, -SPHERE_RADIUS ),
new Vector3( SPHERE_RADIUS, SPHERE_RADIUS, SPHERE_RADIUS ) );
mesh.BoundingSphereRadius = SPHERE_RADIUS;
}