SpherePrimitive.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. //-----------------------------------------------------------------------------
  2. // SpherePrimitive.cs
  3. //
  4. // Microsoft XNA Community Game Platform
  5. // Copyright (C) Microsoft Corporation. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. using System;
  8. using Microsoft.Xna.Framework;
  9. using Microsoft.Xna.Framework.Graphics;
  10. namespace PerformanceMeasuring
  11. {
  12. /// <summary>
  13. /// Geometric primitive class for drawing spheres.
  14. ///
  15. /// This class is borrowed from the Primitives3D sample.
  16. /// </summary>
  17. public class SpherePrimitive : GeometricPrimitive
  18. {
  19. /// <summary>
  20. /// Constructs a new sphere primitive, using default settings.
  21. /// </summary>
  22. public SpherePrimitive(GraphicsDevice graphicsDevice)
  23. : this(graphicsDevice, 1, 16)
  24. {
  25. }
  26. /// <summary>
  27. /// Constructs a new sphere primitive,
  28. /// with the specified size and tessellation level.
  29. /// </summary>
  30. public SpherePrimitive(GraphicsDevice graphicsDevice, float diameter, int tessellation)
  31. {
  32. if (tessellation < 3)
  33. throw new ArgumentOutOfRangeException("tessellation");
  34. int verticalSegments = tessellation;
  35. int horizontalSegments = tessellation * 2;
  36. float radius = diameter / 2;
  37. // Start with a single vertex at the bottom of the sphere.
  38. AddVertex(Vector3.Down * radius, Vector3.Down);
  39. // Create rings of vertices at progressively higher latitudes.
  40. for (int i = 0; i < verticalSegments - 1; i++)
  41. {
  42. float latitude = ((i + 1) * MathHelper.Pi / verticalSegments) - MathHelper.PiOver2;
  43. float dy = (float)Math.Sin(latitude);
  44. float dxz = (float)Math.Cos(latitude);
  45. // Create a single ring of vertices at this latitude.
  46. for (int j = 0; j < horizontalSegments; j++)
  47. {
  48. float longitude = j * MathHelper.TwoPi / horizontalSegments;
  49. float dx = (float)Math.Cos(longitude) * dxz;
  50. float dz = (float)Math.Sin(longitude) * dxz;
  51. Vector3 normal = new Vector3(dx, dy, dz);
  52. AddVertex(normal * radius, normal);
  53. }
  54. }
  55. // Finish with a single vertex at the top of the sphere.
  56. AddVertex(Vector3.Up * radius, Vector3.Up);
  57. // Create a fan connecting the bottom vertex to the bottom latitude ring.
  58. for (int i = 0; i < horizontalSegments; i++)
  59. {
  60. AddIndex(0);
  61. AddIndex(1 + (i + 1) % horizontalSegments);
  62. AddIndex(1 + i);
  63. }
  64. // Fill the sphere body with triangles joining each pair of latitude rings.
  65. for (int i = 0; i < verticalSegments - 2; i++)
  66. {
  67. for (int j = 0; j < horizontalSegments; j++)
  68. {
  69. int nextI = i + 1;
  70. int nextJ = (j + 1) % horizontalSegments;
  71. AddIndex(1 + i * horizontalSegments + j);
  72. AddIndex(1 + i * horizontalSegments + nextJ);
  73. AddIndex(1 + nextI * horizontalSegments + j);
  74. AddIndex(1 + i * horizontalSegments + nextJ);
  75. AddIndex(1 + nextI * horizontalSegments + nextJ);
  76. AddIndex(1 + nextI * horizontalSegments + j);
  77. }
  78. }
  79. // Create a fan connecting the top vertex to the top latitude ring.
  80. for (int i = 0; i < horizontalSegments; i++)
  81. {
  82. AddIndex(CurrentVertex - 1);
  83. AddIndex(CurrentVertex - 2 - (i + 1) % horizontalSegments);
  84. AddIndex(CurrentVertex - 2 - i);
  85. }
  86. InitializePrimitive(graphicsDevice);
  87. }
  88. }
  89. }