#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);
}
}
}