ModelEntity.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // A basic renderable model.
  4. //
  5. // Author: Ronen Ness.
  6. // Since: 2017.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. using Microsoft.Xna.Framework;
  10. using Microsoft.Xna.Framework.Graphics;
  11. using System.Collections.Generic;
  12. namespace MonoGameSceneGraph
  13. {
  14. /// <summary>
  15. /// A basic renderable model.
  16. /// Note: this object is more of an example of how to create a renderable entity, you will probably
  17. /// need to implement something more sophisticated on your own.
  18. /// </summary>
  19. public class ModelEntity : IEntity
  20. {
  21. /// <summary>
  22. /// The model to render.
  23. /// </summary>
  24. public Model Model;
  25. /// <summary>
  26. /// Projection matrix to use with model.
  27. /// </summary>
  28. public Matrix Projection;
  29. /// <summary>
  30. /// View matrix to use with model.
  31. /// </summary>
  32. public Matrix View;
  33. /// <summary>
  34. /// Enable / disable default lighting on model.
  35. /// </summary>
  36. public bool EnableLighting = true;
  37. /// <summary>
  38. /// Create the model entity.
  39. /// </summary>
  40. /// <param name="model">Model to draw.</param>
  41. public ModelEntity(Model model)
  42. {
  43. // visible by default
  44. Visible = true;
  45. // store model
  46. Model = model;
  47. // Create default Projection matrix (viewport)
  48. float aspectRatio = 1f;
  49. float fieldOfView = Microsoft.Xna.Framework.MathHelper.PiOver4;
  50. float nearClipPlane = 1;
  51. float farClipPlane = 200;
  52. Projection = Matrix.CreatePerspectiveFieldOfView(
  53. fieldOfView, aspectRatio, nearClipPlane, farClipPlane);
  54. // Create default View matrix (camera)
  55. var cameraPosition = new Vector3(0, 20, 0);
  56. var cameraLookAtVector = Vector3.Zero;
  57. var cameraUpVector = Vector3.UnitZ;
  58. View = Matrix.CreateLookAt(cameraPosition, cameraLookAtVector, cameraUpVector);
  59. }
  60. /// <summary>
  61. /// Draw this model.
  62. /// </summary>
  63. /// <param name="parent">Parent node that's currently drawing this entity.</param>
  64. /// <param name="localTransformations">Local transformations from the direct parent node.</param>
  65. /// <param name="worldTransformations">World transformations to apply on this entity (this is what you should use to draw this entity).</param>
  66. public void Draw(Node parent, Matrix localTransformations, Matrix worldTransformations)
  67. {
  68. // iterate model meshes
  69. foreach (var mesh in Model.Meshes)
  70. {
  71. // iterate effect in mesh
  72. foreach (BasicEffect effect in mesh.Effects)
  73. {
  74. // enable lights
  75. if (EnableLighting)
  76. {
  77. // set default lightings
  78. effect.EnableDefaultLighting();
  79. // This makes lighting look more realistic on
  80. // round surfaces, but at a slight performance cost:
  81. effect.PreferPerPixelLighting = true;
  82. }
  83. // set world matrix
  84. effect.World = worldTransformations;
  85. // set view matrix
  86. effect.View = View;
  87. // set projection matrix
  88. effect.Projection = Projection;
  89. }
  90. // draw current mesh
  91. mesh.Draw();
  92. }
  93. }
  94. /// <summary>
  95. /// Return if the entity is currently visible.
  96. /// </summary>
  97. /// <returns>If the entity is visible or not.</returns>
  98. public bool Visible
  99. {
  100. get; set;
  101. }
  102. /// <summary>
  103. /// Get the bounding box of this entity.
  104. /// </summary>
  105. /// <param name="parent">Parent node that's currently drawing this entity.</param>
  106. /// <param name="localTransformations">Local transformations from the direct parent node.</param>
  107. /// <param name="worldTransformations">World transformations to apply on this entity (this is what you should use to draw this entity).</param>
  108. /// <returns>Bounding box of the entity.</returns>
  109. public BoundingBox GetBoundingBox(Node parent, Matrix localTransformations, Matrix worldTransformations)
  110. {
  111. // initialize minimum and maximum corners of the bounding box to max and min values
  112. Vector3 min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
  113. Vector3 max = new Vector3(float.MinValue, float.MinValue, float.MinValue);
  114. // iterate over mesh parts
  115. foreach (ModelMesh mesh in Model.Meshes)
  116. {
  117. foreach (ModelMeshPart meshPart in mesh.MeshParts)
  118. {
  119. // vertex buffer parameters
  120. int vertexStride = meshPart.VertexBuffer.VertexDeclaration.VertexStride;
  121. int vertexBufferSize = meshPart.NumVertices * vertexStride;
  122. // get vertex data as float
  123. float[] vertexData = new float[vertexBufferSize / sizeof(float)];
  124. meshPart.VertexBuffer.GetData<float>(vertexData);
  125. // iterate through vertices (possibly) growing bounding box
  126. for (int i = 0; i < vertexBufferSize / sizeof(float); i += vertexStride / sizeof(float))
  127. {
  128. // get curr position and update min / max
  129. Vector3 currPosition = new Vector3(vertexData[i], vertexData[i + 1], vertexData[i + 2]);
  130. currPosition = Vector3.Transform(currPosition, worldTransformations);
  131. min = Vector3.Min(min, currPosition);
  132. max = Vector3.Max(max, currPosition);
  133. }
  134. }
  135. }
  136. // return bounding box
  137. return new BoundingBox(min, max);
  138. }
  139. }
  140. }