#region File Description //----------------------------------------------------------------------------- // SkyProcessor.cs // // Microsoft XNA Community Game Platform // Copyright (C) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- #endregion #region Using Statements using System; using System.IO; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content.Pipeline; using Microsoft.Xna.Framework.Content.Pipeline.Graphics; using Microsoft.Xna.Framework.Content.Pipeline.Processors; #endregion namespace GeneratedGeometryPipeline { /// /// Custom content processor for creating skydome meshes. Given an /// input sky texture, this processor uses the MeshBuilder class to /// programatically generate skydome geometry. It creates a cylinder, /// texture maps the sky image around it, and assigns a custom effect /// that will be used to render the sky. /// [ContentProcessor] public class SkyProcessor : ContentProcessor { const float cylinderSize = 100; const int cylinderSegments = 32; const float texCoordTop = 0.1f; const float texCoordBottom = 0.9f; /// /// Generates skydome geometry for an input sky texture. /// public override SkyContent Process(Texture2DContent input, ContentProcessorContext context) { MeshBuilder builder = MeshBuilder.StartMesh("sky"); // Create two rings of vertices around the top and bottom of the cylinder. List topVertices = new List(); List bottomVertices = new List(); for (int i = 0; i < cylinderSegments; i++) { float angle = MathHelper.TwoPi * i / cylinderSegments; float x = (float)Math.Cos(angle) * cylinderSize; float z = (float)Math.Sin(angle) * cylinderSize; topVertices.Add(builder.CreatePosition(x, cylinderSize * 5 / 12, z)); bottomVertices.Add(builder.CreatePosition(x, -cylinderSize * 5 / 12, z)); } // Create two center vertices, used for closing the top and bottom. int topCenterVertex = builder.CreatePosition(0, cylinderSize, 0); int bottomCenterVertex = builder.CreatePosition(0, -cylinderSize, 0); // Create a vertex channel for holding texture coordinates. int texCoordId = builder.CreateVertexChannel( VertexChannelNames.TextureCoordinate(0)); // Create the individual triangles that make up our skydome. for (int i = 0; i < cylinderSegments; i++) { int j = (i + 1) % cylinderSegments; // Calculate texture coordinates for this segment of the cylinder. float u1 = (float)i / (float)cylinderSegments; float u2 = (float)(i + 1) / (float)cylinderSegments; // Two triangles form a quad, one side segment of the cylinder. AddVertex(builder, topVertices[i], texCoordId, u1, texCoordTop); AddVertex(builder, topVertices[j], texCoordId, u2, texCoordTop); AddVertex(builder, bottomVertices[i], texCoordId, u1, texCoordBottom); AddVertex(builder, topVertices[j], texCoordId, u2, texCoordTop); AddVertex(builder, bottomVertices[j], texCoordId, u2, texCoordBottom); AddVertex(builder, bottomVertices[i], texCoordId, u1, texCoordBottom); // Triangle fanning inward to fill the top above this segment. AddVertex(builder, topCenterVertex, texCoordId, u1, 0); AddVertex(builder, topVertices[j], texCoordId, u2, texCoordTop); AddVertex(builder, topVertices[i], texCoordId, u1, texCoordTop); // Triangle fanning inward to fill the bottom below this segment. AddVertex(builder, bottomCenterVertex, texCoordId, u1, 1); AddVertex(builder, bottomVertices[i], texCoordId, u1, texCoordBottom); AddVertex(builder, bottomVertices[j], texCoordId, u2, texCoordBottom); } // Create the output object. SkyContent sky = new SkyContent(); // Chain to the ModelProcessor so it can convert the mesh we just generated. MeshContent skyMesh = builder.FinishMesh(); sky.Model = context.Convert(skyMesh, "ModelProcessor"); input.ConvertBitmapType(typeof(Dxt1BitmapContent)); sky.Texture = input; return sky; } /// /// Helper for adding a new triangle vertex to a MeshBuilder, /// along with an associated texture coordinate value. /// static void AddVertex(MeshBuilder builder, int vertex, int texCoordId, float u, float v) { builder.SetVertexChannelData(texCoordId, new Vector2(u, v)); builder.AddTriangleVertex(vertex); } } }