CustomModelProcessor.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // CustomModelProcessor.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.Collections.Generic;
  11. using Microsoft.Xna.Framework;
  12. using Microsoft.Xna.Framework.Graphics;
  13. using Microsoft.Xna.Framework.Content.Pipeline;
  14. using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
  15. using Microsoft.Xna.Framework.Content.Pipeline.Processors;
  16. #endregion
  17. namespace CustomModelPipeline
  18. {
  19. /// <summary>
  20. /// Content Pipeline processor converts incoming
  21. /// graphics data into our custom model format.
  22. /// </summary>
  23. [ContentProcessor(DisplayName = "Custom Model")]
  24. public class CustomModelProcessor : ContentProcessor<NodeContent,
  25. CustomModelContent>
  26. {
  27. #region Fields
  28. ContentProcessorContext context;
  29. CustomModelContent outputModel;
  30. // A single material may be reused on more than one piece of geometry.
  31. // This dictionary keeps track of materials we have already converted,
  32. // to make sure we only bother processing each of them once.
  33. Dictionary<MaterialContent, MaterialContent> processedMaterials =
  34. new Dictionary<MaterialContent, MaterialContent>();
  35. #endregion
  36. /// <summary>
  37. /// Converts incoming graphics data into our custom model format.
  38. /// </summary>
  39. public override CustomModelContent Process(NodeContent input,
  40. ContentProcessorContext context)
  41. {
  42. this.context = context;
  43. outputModel = new CustomModelContent();
  44. ProcessNode(input);
  45. return outputModel;
  46. }
  47. /// <summary>
  48. /// Recursively processes a node from the input data tree.
  49. /// </summary>
  50. void ProcessNode(NodeContent node)
  51. {
  52. // Meshes can contain internal hierarchy (nested tranforms, joints, bones,
  53. // etc), but this sample isn't going to bother storing any of that data.
  54. // Instead we will just bake any node transforms into the geometry, after
  55. // which we can reset them to identity and forget all about them.
  56. MeshHelper.TransformScene(node, node.Transform);
  57. node.Transform = Matrix.Identity;
  58. // Is this node in fact a mesh?
  59. MeshContent mesh = node as MeshContent;
  60. if (mesh != null)
  61. {
  62. // Reorder vertex and index data so triangles will render in
  63. // an order that makes efficient use of the GPU vertex cache.
  64. MeshHelper.OptimizeForCache(mesh);
  65. // Process all the geometry in the mesh.
  66. foreach (GeometryContent geometry in mesh.Geometry)
  67. {
  68. ProcessGeometry(geometry);
  69. }
  70. }
  71. // Recurse over any child nodes.
  72. foreach (NodeContent child in node.Children)
  73. {
  74. ProcessNode(child);
  75. }
  76. }
  77. /// <summary>
  78. /// Converts a single piece of input geometry into our custom format.
  79. /// </summary>
  80. void ProcessGeometry(GeometryContent geometry)
  81. {
  82. int triangleCount = geometry.Indices.Count / 3;
  83. int vertexCount = geometry.Vertices.VertexCount;
  84. // Flatten the flexible input vertex channel data into
  85. // a simple GPU style vertex buffer byte array.
  86. VertexBufferContent vertexBufferContent = geometry.Vertices.CreateVertexBuffer();
  87. // Convert the input material.
  88. MaterialContent material = ProcessMaterial(geometry.Material);
  89. // Add the new piece of geometry to our output model.
  90. outputModel.AddModelPart(triangleCount, vertexCount,
  91. vertexBufferContent, geometry.Indices, material);
  92. }
  93. /// <summary>
  94. /// Converts an input material by chaining to the built-in MaterialProcessor
  95. /// class. This will automatically go off and build any effects or textures
  96. /// that are referenced by the material. When you load the resulting material
  97. /// at runtime, you will get back an Effect instance that has the appropriate
  98. /// textures already loaded into it and ready to go.
  99. /// </summary>
  100. MaterialContent ProcessMaterial(MaterialContent material)
  101. {
  102. // Have we already processed this material?
  103. if (!processedMaterials.ContainsKey(material))
  104. {
  105. // If not, process it now.
  106. processedMaterials[material] =
  107. context.Convert<MaterialContent,
  108. MaterialContent>(material, "MaterialProcessor");
  109. }
  110. return processedMaterials[material];
  111. }
  112. }
  113. }