ModelMeshReplacement.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using Microsoft.Xna.Framework.Graphics;
  7. namespace SharpGLTF.Runtime
  8. {
  9. /// <summary>
  10. /// Replaces <see cref="ModelMeshPart"/>.
  11. /// </summary>
  12. sealed class RuntimeModelMeshPart
  13. {
  14. #region lifecycle
  15. internal RuntimeModelMeshPart(RuntimeModelMesh parent)
  16. {
  17. _Parent = parent;
  18. }
  19. #endregion
  20. #region data
  21. private readonly RuntimeModelMesh _Parent;
  22. private Effect _Effect;
  23. private IndexBuffer _IndexBuffer;
  24. private int _IndexOffset;
  25. private int _PrimitiveCount;
  26. private VertexBuffer _VertexBuffer;
  27. private int _VertexOffset;
  28. private int _VertexCount;
  29. public object Tag { get; set; }
  30. #endregion
  31. #region properties
  32. public Effect Effect
  33. {
  34. get => _Effect;
  35. set
  36. {
  37. if (_Effect == value) return;
  38. _Effect = value;
  39. _Parent.InvalidateEffectCollection(); // if we change this property, we need to invalidate the parent's effect collection.
  40. }
  41. }
  42. public GraphicsDevice Device => _Parent._GraphicsDevice;
  43. #endregion
  44. #region API
  45. public void SetVertexBuffer(VertexBuffer vb, int offset, int count)
  46. {
  47. this._VertexBuffer = vb;
  48. this._VertexOffset = offset;
  49. this._VertexCount = count;
  50. }
  51. public void SetIndexBuffer(IndexBuffer ib, int offset, int count)
  52. {
  53. this._IndexBuffer = ib;
  54. this._IndexOffset = offset;
  55. this._PrimitiveCount = count;
  56. }
  57. public void Draw(GraphicsDevice device)
  58. {
  59. if (_PrimitiveCount > 0)
  60. {
  61. device.SetVertexBuffer(_VertexBuffer);
  62. device.Indices = _IndexBuffer;
  63. for (int j = 0; j < _Effect.CurrentTechnique.Passes.Count; j++)
  64. {
  65. _Effect.CurrentTechnique.Passes[j].Apply();
  66. device.DrawIndexedPrimitives(PrimitiveType.TriangleList, _VertexOffset, _IndexOffset, _PrimitiveCount);
  67. }
  68. }
  69. }
  70. #endregion
  71. }
  72. /// <summary>
  73. /// Replaces <see cref="ModelMesh"/>
  74. /// </summary>
  75. sealed class RuntimeModelMesh
  76. {
  77. #region lifecycle
  78. public RuntimeModelMesh(GraphicsDevice graphicsDevice)
  79. {
  80. this._GraphicsDevice = graphicsDevice;
  81. }
  82. #endregion
  83. #region data
  84. internal GraphicsDevice _GraphicsDevice;
  85. private readonly List<RuntimeModelMeshPart> _Primitives = new List<RuntimeModelMeshPart>();
  86. private IReadOnlyList<Effect> _Effects;
  87. private Microsoft.Xna.Framework.BoundingSphere? _Sphere;
  88. #endregion
  89. #region properties
  90. public IReadOnlyCollection<Effect> Effects
  91. {
  92. get
  93. {
  94. if (_Effects != null) return _Effects;
  95. // Create the shared effects collection on demand.
  96. _Effects = _Primitives
  97. .Select(item => item.Effect)
  98. .Distinct()
  99. .ToArray();
  100. return _Effects;
  101. }
  102. }
  103. public Microsoft.Xna.Framework.BoundingSphere BoundingSphere
  104. {
  105. set => _Sphere = value;
  106. get
  107. {
  108. if (_Sphere.HasValue) return _Sphere.Value;
  109. return default;
  110. }
  111. }
  112. public IReadOnlyList<RuntimeModelMeshPart> MeshParts => _Primitives;
  113. public string Name { get; set; }
  114. public ModelBone ParentBone { get; set; }
  115. public object Tag { get; set; }
  116. #endregion
  117. #region API
  118. internal void InvalidateEffectCollection() { _Effects = null; }
  119. public RuntimeModelMeshPart CreateMeshPart()
  120. {
  121. var primitive = new RuntimeModelMeshPart(this);
  122. _Primitives.Add(primitive);
  123. InvalidateEffectCollection();
  124. _Sphere = null;
  125. return primitive;
  126. }
  127. public void Draw()
  128. {
  129. for (int i = 0; i < _Primitives.Count; i++)
  130. {
  131. _Primitives[i].Draw(_GraphicsDevice);
  132. }
  133. }
  134. #endregion
  135. }
  136. }