2
0

GeometricPrimitive.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // GeometricPrimitive.cs
  4. //
  5. // Microsoft XNA Community Game Platform
  6. // Copyright (C) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. #region Using Statements
  10. using System;
  11. using System.Collections.Generic;
  12. using Microsoft.Xna.Framework;
  13. using Microsoft.Xna.Framework.Graphics;
  14. #endregion
  15. namespace Primitives3D
  16. {
  17. /// <summary>
  18. /// Base class for simple geometric primitive models. This provides a vertex
  19. /// buffer, an index buffer, plus methods for drawing the model. Classes for
  20. /// specific types of primitive (CubePrimitive, SpherePrimitive, etc.) are
  21. /// derived from this common base, and use the AddVertex and AddIndex methods
  22. /// to specify their geometry.
  23. /// </summary>
  24. public abstract class GeometricPrimitive : IDisposable
  25. {
  26. #region Fields
  27. // During the process of constructing a primitive model, vertex
  28. // and index data is stored on the CPU in these managed lists.
  29. List<VertexPositionNormal> vertices = new List<VertexPositionNormal>();
  30. List<ushort> indices = new List<ushort>();
  31. // Once all the geometry has been specified, the InitializePrimitive
  32. // method copies the vertex and index data into these buffers, which
  33. // store it on the GPU ready for efficient rendering.
  34. VertexBuffer vertexBuffer;
  35. IndexBuffer indexBuffer;
  36. BasicEffect basicEffect;
  37. #endregion
  38. #region Initialization
  39. /// <summary>
  40. /// Adds a new vertex to the primitive model. This should only be called
  41. /// during the initialization process, before InitializePrimitive.
  42. /// </summary>
  43. protected void AddVertex(Vector3 position, Vector3 normal)
  44. {
  45. vertices.Add(new VertexPositionNormal(position, normal));
  46. }
  47. /// <summary>
  48. /// Adds a new index to the primitive model. This should only be called
  49. /// during the initialization process, before InitializePrimitive.
  50. /// </summary>
  51. protected void AddIndex(int index)
  52. {
  53. if (index > ushort.MaxValue)
  54. throw new ArgumentOutOfRangeException("index");
  55. indices.Add((ushort)index);
  56. }
  57. /// <summary>
  58. /// Queries the index of the current vertex. This starts at
  59. /// zero, and increments every time AddVertex is called.
  60. /// </summary>
  61. protected int CurrentVertex
  62. {
  63. get { return vertices.Count; }
  64. }
  65. /// <summary>
  66. /// Once all the geometry has been specified by calling AddVertex and AddIndex,
  67. /// this method copies the vertex and index data into GPU format buffers, ready
  68. /// for efficient rendering.
  69. protected void InitializePrimitive(GraphicsDevice graphicsDevice)
  70. {
  71. // Create a vertex declaration, describing the format of our vertex data.
  72. // Create a vertex buffer, and copy our vertex data into it.
  73. vertexBuffer = new VertexBuffer(graphicsDevice,
  74. typeof(VertexPositionNormal),
  75. vertices.Count, BufferUsage.None);
  76. vertexBuffer.SetData(vertices.ToArray());
  77. // Create an index buffer, and copy our index data into it.
  78. indexBuffer = new IndexBuffer(graphicsDevice, typeof(ushort),
  79. indices.Count, BufferUsage.None);
  80. indexBuffer.SetData(indices.ToArray());
  81. // Create a BasicEffect, which will be used to render the primitive.
  82. basicEffect = new BasicEffect(graphicsDevice);
  83. basicEffect.EnableDefaultLighting();
  84. basicEffect.PreferPerPixelLighting = true;
  85. }
  86. /// <summary>
  87. /// Finalizer.
  88. /// </summary>
  89. ~GeometricPrimitive()
  90. {
  91. Dispose(false);
  92. }
  93. /// <summary>
  94. /// Frees resources used by this object.
  95. /// </summary>
  96. public void Dispose()
  97. {
  98. Dispose(true);
  99. GC.SuppressFinalize(this);
  100. }
  101. /// <summary>
  102. /// Frees resources used by this object.
  103. /// </summary>
  104. protected virtual void Dispose(bool disposing)
  105. {
  106. if (disposing)
  107. {
  108. if (vertexBuffer != null)
  109. vertexBuffer.Dispose();
  110. if (indexBuffer != null)
  111. indexBuffer.Dispose();
  112. if (basicEffect != null)
  113. basicEffect.Dispose();
  114. }
  115. }
  116. #endregion
  117. #region Draw
  118. /// <summary>
  119. /// Draws the primitive model, using the specified effect. Unlike the other
  120. /// Draw overload where you just specify the world/view/projection matrices
  121. /// and color, this method does not set any renderstates, so you must make
  122. /// sure all states are set to sensible values before you call it.
  123. /// </summary>
  124. public void Draw(Effect effect)
  125. {
  126. GraphicsDevice graphicsDevice = effect.GraphicsDevice;
  127. // Set our vertex declaration, vertex buffer, and index buffer.
  128. graphicsDevice.SetVertexBuffer(vertexBuffer);
  129. graphicsDevice.Indices = indexBuffer;
  130. foreach (EffectPass effectPass in effect.CurrentTechnique.Passes)
  131. {
  132. effectPass.Apply();
  133. int primitiveCount = indices.Count / 3;
  134. graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0,
  135. vertices.Count, 0, primitiveCount);
  136. }
  137. }
  138. /// <summary>
  139. /// Draws the primitive model, using a BasicEffect shader with default
  140. /// lighting. Unlike the other Draw overload where you specify a custom
  141. /// effect, this method sets important renderstates to sensible values
  142. /// for 3D model rendering, so you do not need to set these states before
  143. /// you call it.
  144. /// </summary>
  145. public void Draw(Matrix world, Matrix view, Matrix projection, Color color)
  146. {
  147. // Set BasicEffect parameters.
  148. basicEffect.World = world;
  149. basicEffect.View = view;
  150. basicEffect.Projection = projection;
  151. basicEffect.DiffuseColor = color.ToVector3();
  152. basicEffect.Alpha = color.A / 255.0f;
  153. GraphicsDevice device = basicEffect.GraphicsDevice;
  154. device.DepthStencilState = DepthStencilState.Default;
  155. if (color.A < 255)
  156. {
  157. // Set renderstates for alpha blended rendering.
  158. device.BlendState = BlendState.AlphaBlend;
  159. }
  160. else
  161. {
  162. // Set renderstates for opaque rendering.
  163. device.BlendState = BlendState.Opaque;
  164. }
  165. // Draw the model, using BasicEffect.
  166. Draw(basicEffect);
  167. }
  168. #endregion
  169. }
  170. }