MonoGameModelInstance.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Microsoft.Xna.Framework;
  5. using Microsoft.Xna.Framework.Graphics;
  6. namespace SharpGLTF.Runtime
  7. {
  8. public sealed class MonoGameModelInstance
  9. {
  10. #region lifecycle
  11. internal MonoGameModelInstance(MonoGameModelTemplate template, SceneInstance instance)
  12. {
  13. _Template = template;
  14. _Controller = instance;
  15. }
  16. #endregion
  17. #region data
  18. private readonly MonoGameModelTemplate _Template;
  19. private readonly SceneInstance _Controller;
  20. #endregion
  21. #region properties
  22. /// <summary>
  23. /// Gets a reference to the template used to create this <see cref="MonoGameModelInstance"/>.
  24. /// </summary>
  25. public MonoGameModelTemplate Template => _Template;
  26. /// <summary>
  27. /// Gets a reference to the animation controller of this <see cref="MonoGameModelInstance"/>.
  28. /// </summary>
  29. public SceneInstance Controller => _Controller;
  30. #endregion
  31. #region API
  32. /// <summary>
  33. /// Draws this <see cref="MonoGameModelInstance"/> into the current <see cref="GraphicsDevice"/>.
  34. /// </summary>
  35. /// <param name="projection">The projection matrix.</param>
  36. /// <param name="view">The view matrix.</param>
  37. /// <param name="world">The world matrix.</param>
  38. public void Draw(Matrix projection, Matrix view, Matrix world)
  39. {
  40. foreach (var d in _Controller.DrawableReferences)
  41. {
  42. Draw(_Template._Meshes[d.MeshIndex], projection, view, world, d.Transform);
  43. }
  44. }
  45. private void Draw(ModelMesh mesh, Matrix projectionXform, Matrix viewXform, Matrix worldXform, Transforms.IGeometryTransform modelXform)
  46. {
  47. if (modelXform is Transforms.SkinnedTransform skinXform)
  48. {
  49. var skinTransforms = skinXform.SkinMatrices.Select(item => item.ToXna()).ToArray();
  50. foreach (var effect in mesh.Effects)
  51. {
  52. UpdateTransforms(effect, projectionXform, viewXform, worldXform, skinTransforms);
  53. }
  54. }
  55. if (modelXform is Transforms.RigidTransform statXform)
  56. {
  57. var statTransform = statXform.WorldMatrix.ToXna();
  58. worldXform = Matrix.Multiply(statTransform, worldXform);
  59. foreach (var effect in mesh.Effects)
  60. {
  61. UpdateTransforms(effect, projectionXform, viewXform, worldXform);
  62. }
  63. }
  64. mesh.Draw();
  65. }
  66. private static void UpdateTransforms(Effect effect, Matrix projectionXform, Matrix viewXform, Matrix worldXform, Matrix[] skinTransforms = null)
  67. {
  68. if (effect is IEffectMatrices matrices)
  69. {
  70. matrices.Projection = projectionXform;
  71. matrices.View = viewXform;
  72. matrices.World = worldXform;
  73. }
  74. if (effect is SkinnedEffect skin && skinTransforms != null)
  75. {
  76. var xposed = skinTransforms.Select(item => Matrix.Transpose(item)).ToArray();
  77. skin.SetBoneTransforms(skinTransforms);
  78. }
  79. }
  80. #endregion
  81. }
  82. }