RacingGameModelProcessor.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. //-----------------------------------------------------------------------------
  2. // RacingGameModelProcessor.cs
  3. //
  4. // Microsoft XNA Community Game Platform
  5. // Copyright (C) Microsoft Corporation. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. using System;
  8. using Microsoft.Xna.Framework.Content.Pipeline;
  9. using Microsoft.Xna.Framework.Content.Pipeline.Processors;
  10. using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
  11. namespace RacingGame.PipelineExtension
  12. {
  13. /// <summary>
  14. /// RacingGame model processor for x files. Loads models the same way as
  15. /// the ModelProcessor class, but generates tangents and some additional
  16. /// data too.
  17. /// </summary>
  18. [ContentProcessor(DisplayName = "RacingGame Model (Tangent support)")]
  19. public class RacingGameModelProcessor : ModelProcessor
  20. {
  21. /// <summary>
  22. /// Process the model
  23. /// </summary>
  24. /// <param name="input">Input data</param>
  25. /// <param name="context">Context for logging</param>
  26. /// <returns>Model content</returns>
  27. public override ModelContent Process(
  28. NodeContent input, ContentProcessorContext context)
  29. {
  30. // First generate tangent data because x files don't store them
  31. GenerateTangents(input, context);
  32. // Use the name of the bone for our mesh name if it is not set
  33. UseParentBoneNameIfMeshNameIsNotSet(input);
  34. // Store the current selected technique and if the texture uses alpha
  35. // into the mesh name for each mesh part.
  36. StoreEffectTechniqueInMeshName(input, context);
  37. // And let the rest be processed by the default model processor
  38. return base.Process(input, context);
  39. }
  40. /// <summary>
  41. /// Generate tangents helper method, x files do not have tangents
  42. /// exported, we have to generate them ourselfs.
  43. /// </summary>
  44. /// <param name="input">Input data</param>
  45. /// <param name="context">Context for logging</param>
  46. private void GenerateTangents(
  47. NodeContent input, ContentProcessorContext context)
  48. {
  49. MeshContent mesh = input as MeshContent;
  50. if (mesh != null)
  51. {
  52. // Generate trangents for the mesh. We don't want binormals,
  53. // so null is passed in for the last parameter.
  54. MeshHelper.CalculateTangentFrames(mesh,
  55. VertexChannelNames.TextureCoordinate(0),
  56. VertexChannelNames.Tangent(0), null);
  57. }
  58. // Go through all childs
  59. foreach (NodeContent child in input.Children)
  60. {
  61. GenerateTangents(child, context);
  62. }
  63. }
  64. /// <summary>
  65. /// Use parent bone's name if mesh's name is not set.
  66. /// </summary>
  67. /// <param name="input"></param>
  68. private void UseParentBoneNameIfMeshNameIsNotSet(NodeContent input)
  69. {
  70. if (String.IsNullOrEmpty(input.Name) &&
  71. input.Parent != null &&
  72. String.IsNullOrEmpty(input.Parent.Name) == false)
  73. input.Name = input.Parent.Name;
  74. foreach (NodeContent node in input.Children)
  75. UseParentBoneNameIfMeshNameIsNotSet(node);
  76. }
  77. /// <summary>
  78. /// Stores the current selected technique and if the texture uses alpha
  79. /// into the mesh name for each mesh part.
  80. /// </summary>
  81. private void StoreEffectTechniqueInMeshName(
  82. NodeContent input, ContentProcessorContext context)
  83. {
  84. MeshContent mesh = input as MeshContent;
  85. if (mesh != null)
  86. {
  87. foreach (GeometryContent geom in mesh.Geometry)
  88. {
  89. EffectMaterialContent effectMaterial =
  90. geom.Material as EffectMaterialContent;
  91. if (effectMaterial != null)
  92. {
  93. if (effectMaterial.OpaqueData.ContainsKey("technique"))
  94. {
  95. // Store technique here! (OpaqueData["technique"] is an
  96. // int32) If we have multiple mesh parts in our mesh object,
  97. // there will be multiple techniques listed at the end of
  98. // our mesh name.
  99. input.Name =
  100. input.Name + effectMaterial.OpaqueData["technique"];
  101. }
  102. }
  103. }
  104. }
  105. // Go through all childs
  106. foreach (NodeContent child in input.Children)
  107. {
  108. StoreEffectTechniqueInMeshName(child, context);
  109. }
  110. }
  111. }
  112. }