MonoGameModelInstance.cs 3.9 KB

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