Rendering Bounding Spheres

From XNAWiki
Jump to: navigation, search

This is a basic static class that allows easy rendering of BoundingSpheres.

/// <summary>
    /// Provides a set of methods for rendering BoundingSpheres.
    /// </summary>
    public static class BoundingSphereRenderer
    {
        static VertexBuffer vertBuffer;
        static VertexDeclaration vertDecl;
        static BasicEffect effect;
        static int sphereResolution;
 
        /// <summary>
        /// Initializes the graphics objects for rendering the spheres. If this method isn't
        /// run manually, it will be called the first time you render a sphere.
        /// </summary>
        /// <param name="graphicsDevice">The graphics device to use when rendering.</param>
        /// <param name="sphereResolution">The number of line segments 
        ///     to use for each of the three circles.</param>
        public static void InitializeGraphics(GraphicsDevice graphicsDevice, int sphereResolution)
        {
            BoundingSphereRenderer.sphereResolution = sphereResolution;
 
            vertDecl = new VertexDeclaration(graphicsDevice, VertexPositionColor.VertexElements);
            effect = new BasicEffect(graphicsDevice, null);
            effect.LightingEnabled = false;
            effect.VertexColorEnabled = false;
 
            VertexPositionColor[] verts = new VertexPositionColor[(sphereResolution + 1) * 3];
 
            int index = 0;
 
            float step = MathHelper.TwoPi / (float)sphereResolution;
 
            //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.White);
            }
 
            //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.White);
            }
 
            //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.White);
            }
 
            vertBuffer = new VertexBuffer(
                graphicsDevice,
                verts.Length * VertexPositionColor.SizeInBytes,
                BufferUsage.None);
            vertBuffer.SetData(verts);
        }
 
        /// <summary>
        /// Renders a bounding sphere using different colors for each axis.
        /// </summary>
        /// <param name="sphere">The sphere to render.</param>
        /// <param name="graphicsDevice">The graphics device to use when rendering.</param>
        /// <param name="view">The current view matrix.</param>
        /// <param name="projection">The current projection matrix.</param>
        /// <param name="xyColor">The color for the XY circle.</param>
        /// <param name="xzColor">The color for the XZ circle.</param>
        /// <param name="yzColor">The color for the YZ circle.</param>
        public static void Render(
            BoundingSphere sphere,
            GraphicsDevice graphicsDevice,
            Matrix view,
            Matrix projection,
            Color xyColor,
            Color xzColor,
            Color yzColor)
        {
            if (vertBuffer == null)
                InitializeGraphics(graphicsDevice, 30);
 
            graphicsDevice.VertexDeclaration = vertDecl;
            graphicsDevice.Vertices[0].SetSource(
                vertBuffer, 
                0, 
                VertexPositionColor.SizeInBytes);
 
            effect.World = 
                Matrix.CreateScale(sphere.Radius) * 
                Matrix.CreateTranslation(sphere.Center);
            effect.View = view;
            effect.Projection = projection;
            effect.DiffuseColor = xyColor.ToVector3();
 
            effect.Begin();
            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Begin();
 
                //render each circle individually
                graphicsDevice.DrawPrimitives(
                      PrimitiveType.LineStrip, 
                      0, 
                      sphereResolution);
 
                effect.DiffuseColor = xzColor.ToVector3();
                effect.CommitChanges();
                graphicsDevice.DrawPrimitives(
                      PrimitiveType.LineStrip, 
                      sphereResolution + 1, 
                      sphereResolution);
 
                effect.DiffuseColor = yzColor.ToVector3();
                effect.CommitChanges();
                graphicsDevice.DrawPrimitives(
                      PrimitiveType.LineStrip, 
                      (sphereResolution + 1) * 2, 
                      sphereResolution);
 
                pass.End();
            }
            effect.End();
        }
 
        /// <summary>
        /// Renders a bounding sphere using a single color for all three axis.
        /// </summary>
        /// <param name="sphere">The sphere to render.</param>
        /// <param name="graphicsDevice">The graphics device to use when rendering.</param>
        /// <param name="view">The current view matrix.</param>
        /// <param name="projection">The current projection matrix.</param>
        /// <param name="color">The color to use for rendering the circles.</param>
        public static void Render(
            BoundingSphere sphere,
            GraphicsDevice graphicsDevice,
            Matrix view,
            Matrix projection,
            Color color)
        {
            if (vertBuffer == null)
                InitializeGraphics(graphicsDevice, 30);
 
            graphicsDevice.VertexDeclaration = vertDecl;
            graphicsDevice.Vertices[0].SetSource(
                  vertBuffer, 
                  0, 
                  VertexPositionColor.SizeInBytes);
 
            effect.World = 
                  Matrix.CreateScale(sphere.Radius) * 
                  Matrix.CreateTranslation(sphere.Center);
            effect.View = view;
            effect.Projection = projection;
            effect.DiffuseColor = color.ToVector3();
 
            effect.Begin();
            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Begin();
 
                //render each circle individually
                graphicsDevice.DrawPrimitives(
                      PrimitiveType.LineStrip, 
                      0, 
                      sphereResolution);
                graphicsDevice.DrawPrimitives(
                      PrimitiveType.LineStrip, 
                      sphereResolution + 1, 
                      sphereResolution);
                graphicsDevice.DrawPrimitives(
                      PrimitiveType.LineStrip, 
                      (sphereResolution + 1) * 2, 
                      sphereResolution);
 
                pass.End();
            }
            effect.End();
        }
    }