TerrainProcessor.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // TerrainProcessor.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.IO;
  11. using Microsoft.Xna.Framework;
  12. using Microsoft.Xna.Framework.Content.Pipeline;
  13. using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
  14. using Microsoft.Xna.Framework.Content.Pipeline.Processors;
  15. #endregion
  16. namespace GeneratedGeometryPipeline
  17. {
  18. /// <summary>
  19. /// Custom content processor for creating terrain meshes. Given an
  20. /// input heightfield texture, this processor uses the MeshBuilder
  21. /// class to programatically generate terrain geometry.
  22. /// </summary>
  23. [ContentProcessor]
  24. public class TerrainProcessor : ContentProcessor<Texture2DContent, ModelContent>
  25. {
  26. const float terrainScale = 4;
  27. const float terrainBumpiness = 64;
  28. const float texCoordScale = 0.1f;
  29. const string terrainTexture = "rocks.bmp";
  30. /// <summary>
  31. /// Generates a terrain mesh from an input heightfield texture.
  32. /// </summary>
  33. public override ModelContent Process(Texture2DContent input,
  34. ContentProcessorContext context)
  35. {
  36. MeshBuilder builder = MeshBuilder.StartMesh("terrain");
  37. // Convert the input texture to float format, for ease of processing.
  38. input.ConvertBitmapType(typeof(PixelBitmapContent<float>));
  39. PixelBitmapContent<float> heightfield;
  40. heightfield = (PixelBitmapContent<float>)input.Mipmaps[0];
  41. // Create the terrain vertices.
  42. for (int y = 0; y < heightfield.Height; y++)
  43. {
  44. for (int x = 0; x < heightfield.Width; x++)
  45. {
  46. Vector3 position;
  47. position.X = (x - heightfield.Width / 2) * terrainScale;
  48. position.Z = (y - heightfield.Height / 2) * terrainScale;
  49. position.Y = (heightfield.GetPixel(x, y) - 1) * terrainBumpiness;
  50. builder.CreatePosition(position);
  51. }
  52. }
  53. // Create a material, and point it at our terrain texture.
  54. BasicMaterialContent material = new BasicMaterialContent();
  55. string directory = Path.GetDirectoryName(input.Identity.SourceFilename);
  56. string texture = Path.Combine(directory, terrainTexture);
  57. material.Texture = new ExternalReference<TextureContent>(texture);
  58. builder.SetMaterial(material);
  59. // Create a vertex channel for holding texture coordinates.
  60. int texCoordId = builder.CreateVertexChannel<Vector2>(
  61. VertexChannelNames.TextureCoordinate(0));
  62. // Create the individual triangles that make up our terrain.
  63. for (int y = 0; y < heightfield.Height - 1; y++)
  64. {
  65. for (int x = 0; x < heightfield.Width - 1; x++)
  66. {
  67. AddVertex(builder, texCoordId, heightfield.Width, x, y);
  68. AddVertex(builder, texCoordId, heightfield.Width, x + 1, y);
  69. AddVertex(builder, texCoordId, heightfield.Width, x + 1, y + 1);
  70. AddVertex(builder, texCoordId, heightfield.Width, x, y);
  71. AddVertex(builder, texCoordId, heightfield.Width, x + 1, y + 1);
  72. AddVertex(builder, texCoordId, heightfield.Width, x, y + 1);
  73. }
  74. }
  75. // Chain to the ModelProcessor so it can convert the mesh we just generated.
  76. MeshContent terrainMesh = builder.FinishMesh();
  77. return context.Convert<MeshContent, ModelContent>(terrainMesh,
  78. "ModelProcessor");
  79. }
  80. /// <summary>
  81. /// Helper for adding a new triangle vertex to a MeshBuilder,
  82. /// along with an associated texture coordinate value.
  83. /// </summary>
  84. static void AddVertex(MeshBuilder builder, int texCoordId, int w, int x, int y)
  85. {
  86. builder.SetVertexChannelData(texCoordId, new Vector2(x, y) * texCoordScale);
  87. builder.AddTriangleVertex(x + y * w);
  88. }
  89. }
  90. }