#region File Description //----------------------------------------------------------------------------- // BoundingSphereRenderer.cs // // Microsoft XNA Community Game Platform // Copyright (C) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- #endregion #region Using Statements using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; #endregion namespace BoundingVolumeRendering { /// /// Provides a set of methods for rendering BoundingSpheres. /// public static class BoundingSphereRenderer { private static VertexBuffer vertBuffer; private static BasicEffect effect; private static int lineCount; /// /// Initializes the graphics objects for rendering BoundingSpheres. /// /// The graphics device to use when rendering. /// The number of line segments to use for each of the three circles. public static void Initialize(GraphicsDevice graphicsDevice, int sphereResolution) { // create our effect effect = new BasicEffect(graphicsDevice); effect.LightingEnabled = false; effect.VertexColorEnabled = true; // calculate the number of lines to draw for all circles lineCount = (sphereResolution + 1) * 3; // we need two vertices per line, so we can allocate our vertices VertexPositionColor[] verts = new VertexPositionColor[lineCount * 2]; // compute our step around each circle float step = MathHelper.TwoPi / sphereResolution; // used to track the index into our vertex array int index = 0; //create the loop on the XY plane first for (float a = 0f; a < MathHelper.TwoPi; a += step) { verts[index++] = new VertexPositionColor( new Vector3((float)Math.Cos(a), (float)Math.Sin(a), 0f), Color.Blue); verts[index++] = new VertexPositionColor( new Vector3((float)Math.Cos(a + step), (float)Math.Sin(a + step), 0f), Color.Blue); } //next on the XZ plane for (float a = 0f; a < MathHelper.TwoPi; a += step) { verts[index++] = new VertexPositionColor( new Vector3((float)Math.Cos(a), 0f, (float)Math.Sin(a)), Color.Red); verts[index++] = new VertexPositionColor( new Vector3((float)Math.Cos(a + step), 0f, (float)Math.Sin(a + step)), Color.Red); } //finally on the YZ plane for (float a = 0f; a < MathHelper.TwoPi; a += step) { verts[index++] = new VertexPositionColor( new Vector3(0f, (float)Math.Cos(a), (float)Math.Sin(a)), Color.Green); verts[index++] = new VertexPositionColor( new Vector3(0f, (float)Math.Cos(a + step), (float)Math.Sin(a + step)), Color.Green); } // now we create the vertex buffer and put the vertices in it vertBuffer = new VertexBuffer( graphicsDevice, typeof(VertexPositionColor), verts.Length, BufferUsage.WriteOnly); vertBuffer.SetData(verts); } /// /// Draws a BoundingSphere. /// /// /// This method is an extension method (note the 'this' keyword in front of our BoundingSphere parameter). /// This allows us to either call this method like a static method or like an instance method: /// /// BoundingSphereRenderer.Draw(sphere, view, projection); /// sphere.Draw(view, projection); /// /// The sphere to render. /// The current view matrix. /// The current projection matrix. public static void Draw(this BoundingSphere sphere, Matrix view, Matrix projection) { if (effect == null) throw new InvalidOperationException("You must call Initialize before you can render any spheres."); // set the vertex buffer effect.GraphicsDevice.SetVertexBuffer(vertBuffer); // update our effect matrices effect.World = Matrix.CreateScale(sphere.Radius) * Matrix.CreateTranslation(sphere.Center); effect.View = view; effect.Projection = projection; // draw the primitives with our effect effect.CurrentTechnique.Passes[0].Apply(); effect.GraphicsDevice.DrawPrimitives(PrimitiveType.LineList, 0, lineCount); } } }