//-----------------------------------------------------------------------------
// RacingGameModelProcessor.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
using System;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Processors;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
namespace RacingGame.PipelineExtension
{
///
/// RacingGame model processor for x files. Loads models the same way as
/// the ModelProcessor class, but generates tangents and some additional
/// data too.
///
[ContentProcessor(DisplayName = "RacingGame Model (Tangent support)")]
public class RacingGameModelProcessor : ModelProcessor
{
///
/// Process the model
///
/// Input data
/// Context for logging
/// Model content
public override ModelContent Process(
NodeContent input, ContentProcessorContext context)
{
// First generate tangent data because x files don't store them
GenerateTangents(input, context);
// Use the name of the bone for our mesh name if it is not set
UseParentBoneNameIfMeshNameIsNotSet(input);
// Store the current selected technique and if the texture uses alpha
// into the mesh name for each mesh part.
StoreEffectTechniqueInMeshName(input, context);
// And let the rest be processed by the default model processor
return base.Process(input, context);
}
///
/// Generate tangents helper method, x files do not have tangents
/// exported, we have to generate them ourselfs.
///
/// Input data
/// Context for logging
private void GenerateTangents(
NodeContent input, ContentProcessorContext context)
{
MeshContent mesh = input as MeshContent;
if (mesh != null)
{
// Generate trangents for the mesh. We don't want binormals,
// so null is passed in for the last parameter.
MeshHelper.CalculateTangentFrames(mesh,
VertexChannelNames.TextureCoordinate(0),
VertexChannelNames.Tangent(0), null);
}
// Go through all childs
foreach (NodeContent child in input.Children)
{
GenerateTangents(child, context);
}
}
///
/// Use parent bone's name if mesh's name is not set.
///
///
private void UseParentBoneNameIfMeshNameIsNotSet(NodeContent input)
{
if (String.IsNullOrEmpty(input.Name) &&
input.Parent != null &&
String.IsNullOrEmpty(input.Parent.Name) == false)
input.Name = input.Parent.Name;
foreach (NodeContent node in input.Children)
UseParentBoneNameIfMeshNameIsNotSet(node);
}
///
/// Stores the current selected technique and if the texture uses alpha
/// into the mesh name for each mesh part.
///
private void StoreEffectTechniqueInMeshName(
NodeContent input, ContentProcessorContext context)
{
MeshContent mesh = input as MeshContent;
if (mesh != null)
{
foreach (GeometryContent geom in mesh.Geometry)
{
EffectMaterialContent effectMaterial =
geom.Material as EffectMaterialContent;
if (effectMaterial != null)
{
if (effectMaterial.OpaqueData.ContainsKey("technique"))
{
// Store technique here! (OpaqueData["technique"] is an
// int32) If we have multiple mesh parts in our mesh object,
// there will be multiple techniques listed at the end of
// our mesh name.
input.Name =
input.Name + effectMaterial.OpaqueData["technique"];
}
}
}
}
// Go through all childs
foreach (NodeContent child in input.Children)
{
StoreEffectTechniqueInMeshName(child, context);
}
}
}
}