SkyProcessor.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // SkyProcessor.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.IO;
  12. using System.Collections.Generic;
  13. using Microsoft.Xna.Framework;
  14. using Microsoft.Xna.Framework.Content.Pipeline;
  15. using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
  16. using Microsoft.Xna.Framework.Content.Pipeline.Processors;
  17. #endregion
  18. namespace GeneratedGeometryPipeline
  19. {
  20. /// <summary>
  21. /// Custom content processor for creating skydome meshes. Given an
  22. /// input sky texture, this processor uses the MeshBuilder class to
  23. /// programatically generate skydome geometry. It creates a cylinder,
  24. /// texture maps the sky image around it, and assigns a custom effect
  25. /// that will be used to render the sky.
  26. /// </summary>
  27. [ContentProcessor]
  28. public class SkyProcessor : ContentProcessor<Texture2DContent, SkyContent>
  29. {
  30. const float cylinderSize = 100;
  31. const int cylinderSegments = 32;
  32. const float texCoordTop = 0.1f;
  33. const float texCoordBottom = 0.9f;
  34. /// <summary>
  35. /// Generates skydome geometry for an input sky texture.
  36. /// </summary>
  37. public override SkyContent Process(Texture2DContent input,
  38. ContentProcessorContext context)
  39. {
  40. MeshBuilder builder = MeshBuilder.StartMesh("sky");
  41. // Create two rings of vertices around the top and bottom of the cylinder.
  42. List<int> topVertices = new List<int>();
  43. List<int> bottomVertices = new List<int>();
  44. for (int i = 0; i < cylinderSegments; i++)
  45. {
  46. float angle = MathHelper.TwoPi * i / cylinderSegments;
  47. float x = (float)Math.Cos(angle) * cylinderSize;
  48. float z = (float)Math.Sin(angle) * cylinderSize;
  49. topVertices.Add(builder.CreatePosition(x, cylinderSize * 5 / 12, z));
  50. bottomVertices.Add(builder.CreatePosition(x, -cylinderSize * 5 / 12, z));
  51. }
  52. // Create two center vertices, used for closing the top and bottom.
  53. int topCenterVertex = builder.CreatePosition(0, cylinderSize, 0);
  54. int bottomCenterVertex = builder.CreatePosition(0, -cylinderSize, 0);
  55. // Create a vertex channel for holding texture coordinates.
  56. int texCoordId = builder.CreateVertexChannel<Vector2>(
  57. VertexChannelNames.TextureCoordinate(0));
  58. // Create the individual triangles that make up our skydome.
  59. for (int i = 0; i < cylinderSegments; i++)
  60. {
  61. int j = (i + 1) % cylinderSegments;
  62. // Calculate texture coordinates for this segment of the cylinder.
  63. float u1 = (float)i / (float)cylinderSegments;
  64. float u2 = (float)(i + 1) / (float)cylinderSegments;
  65. // Two triangles form a quad, one side segment of the cylinder.
  66. AddVertex(builder, topVertices[i], texCoordId, u1, texCoordTop);
  67. AddVertex(builder, topVertices[j], texCoordId, u2, texCoordTop);
  68. AddVertex(builder, bottomVertices[i], texCoordId, u1, texCoordBottom);
  69. AddVertex(builder, topVertices[j], texCoordId, u2, texCoordTop);
  70. AddVertex(builder, bottomVertices[j], texCoordId, u2, texCoordBottom);
  71. AddVertex(builder, bottomVertices[i], texCoordId, u1, texCoordBottom);
  72. // Triangle fanning inward to fill the top above this segment.
  73. AddVertex(builder, topCenterVertex, texCoordId, u1, 0);
  74. AddVertex(builder, topVertices[j], texCoordId, u2, texCoordTop);
  75. AddVertex(builder, topVertices[i], texCoordId, u1, texCoordTop);
  76. // Triangle fanning inward to fill the bottom below this segment.
  77. AddVertex(builder, bottomCenterVertex, texCoordId, u1, 1);
  78. AddVertex(builder, bottomVertices[i], texCoordId, u1, texCoordBottom);
  79. AddVertex(builder, bottomVertices[j], texCoordId, u2, texCoordBottom);
  80. }
  81. // Create the output object.
  82. SkyContent sky = new SkyContent();
  83. // Chain to the ModelProcessor so it can convert the mesh we just generated.
  84. MeshContent skyMesh = builder.FinishMesh();
  85. sky.Model = context.Convert<MeshContent, ModelContent>(skyMesh,
  86. "ModelProcessor");
  87. input.ConvertBitmapType(typeof(Dxt1BitmapContent));
  88. sky.Texture = input;
  89. return sky;
  90. }
  91. /// <summary>
  92. /// Helper for adding a new triangle vertex to a MeshBuilder,
  93. /// along with an associated texture coordinate value.
  94. /// </summary>
  95. static void AddVertex(MeshBuilder builder, int vertex,
  96. int texCoordId, float u, float v)
  97. {
  98. builder.SetVertexChannelData(texCoordId, new Vector2(u, v));
  99. builder.AddTriangleVertex(vertex);
  100. }
  101. }
  102. }