//----------------------------------------------------------------------------- // GeometricPrimitive.cs // // Microsoft XNA Community Game Platform // Copyright (C) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace PerformanceMeasuring { /// /// Base class for simple geometric primitive models. This provides a vertex /// buffer, an index buffer, plus methods for drawing the model. Classes for /// specific types of primitive (CubePrimitive, SpherePrimitive, etc.) are /// derived from this common base, and use the AddVertex and AddIndex methods /// to specify their geometry. /// /// This class is borrowed from the Primitives3D sample. /// public abstract class GeometricPrimitive : IDisposable { // During the process of constructing a primitive model, vertex // and index data is stored on the CPU in these managed lists. List vertices = new List(); List indices = new List(); // Once all the geometry has been specified, the InitializePrimitive // method copies the vertex and index data into these buffers, which // store it on the GPU ready for efficient rendering. VertexBuffer vertexBuffer; IndexBuffer indexBuffer; BasicEffect basicEffect; /// /// Adds a new vertex to the primitive model. This should only be called /// during the initialization process, before InitializePrimitive. /// protected void AddVertex(Vector3 position, Vector3 normal) { vertices.Add(new VertexPositionNormal(position, normal)); } /// /// Adds a new index to the primitive model. This should only be called /// during the initialization process, before InitializePrimitive. /// protected void AddIndex(int index) { if (index > ushort.MaxValue) throw new ArgumentOutOfRangeException("index"); indices.Add((ushort)index); } /// /// Queries the index of the current vertex. This starts at /// zero, and increments every time AddVertex is called. /// protected int CurrentVertex { get { return vertices.Count; } } /// /// Once all the geometry has been specified by calling AddVertex and AddIndex, /// this method copies the vertex and index data into GPU format buffers, ready /// for efficient rendering. protected void InitializePrimitive(GraphicsDevice graphicsDevice) { // Create a vertex declaration, describing the format of our vertex data. // Create a vertex buffer, and copy our vertex data into it. vertexBuffer = new VertexBuffer(graphicsDevice, typeof(VertexPositionNormal), vertices.Count, BufferUsage.None); vertexBuffer.SetData(vertices.ToArray()); // Create an index buffer, and copy our index data into it. indexBuffer = new IndexBuffer(graphicsDevice, typeof(ushort), indices.Count, BufferUsage.None); indexBuffer.SetData(indices.ToArray()); // Create a BasicEffect, which will be used to render the primitive. basicEffect = new BasicEffect(graphicsDevice); basicEffect.EnableDefaultLighting(); basicEffect.PreferPerPixelLighting = false; } /// /// Finalizer. /// ~GeometricPrimitive() { Dispose(false); } /// /// Frees resources used by this object. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Frees resources used by this object. /// protected virtual void Dispose(bool disposing) { if (disposing) { if (vertexBuffer != null) vertexBuffer.Dispose(); if (indexBuffer != null) indexBuffer.Dispose(); if (basicEffect != null) basicEffect.Dispose(); } } /// /// Draws the primitive model, using the specified effect. Unlike the other /// Draw overload where you just specify the world/view/projection matrices /// and color, this method does not set any renderstates, so you must make /// sure all states are set to sensible values before you call it. /// public void Draw(Effect effect) { GraphicsDevice graphicsDevice = effect.GraphicsDevice; // Set our vertex declaration, vertex buffer, and index buffer. graphicsDevice.SetVertexBuffer(vertexBuffer); graphicsDevice.Indices = indexBuffer; foreach (EffectPass effectPass in effect.CurrentTechnique.Passes) { effectPass.Apply(); int primitiveCount = indices.Count / 3; graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertices.Count, 0, primitiveCount); } } /// /// Draws the primitive model, using a BasicEffect shader with default /// lighting. Unlike the other Draw overload where you specify a custom /// effect, this method sets important renderstates to sensible values /// for 3D model rendering, so you do not need to set these states before /// you call it. /// public void Draw(Matrix world, Matrix view, Matrix projection, Color color) { // Set BasicEffect parameters. basicEffect.World = world; basicEffect.View = view; basicEffect.Projection = projection; basicEffect.DiffuseColor = color.ToVector3(); basicEffect.Alpha = color.A / 255.0f; GraphicsDevice device = basicEffect.GraphicsDevice; device.DepthStencilState = DepthStencilState.Default; if (color.A < 255) { // Set renderstates for alpha blended rendering. device.BlendState = BlendState.AlphaBlend; } else { // Set renderstates for opaque rendering. device.BlendState = BlendState.Opaque; } // Draw the model, using BasicEffect. Draw(basicEffect); } } }