LinkedNode.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // A scene node that can be linked to an external source and copy its transformations.
  4. //
  5. // Author: Ronen Ness.
  6. // Since: 2017.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. using Microsoft.Xna.Framework;
  10. using System.Collections.Generic;
  11. namespace GeonBit.Core.Graphics
  12. {
  13. /// <summary>
  14. /// An external transformations source we can attach to a LinkedNode to update its transformations.
  15. /// This is used to connect a node to a physical body, like a Bullet3d rigid body etc.
  16. /// </summary>
  17. public interface ITransformationsSource
  18. {
  19. /// <summary>
  20. /// Return if transformations are dirty and need update.
  21. /// </summary>
  22. bool IsDirty { get; }
  23. /// <summary>
  24. /// Get body transformations.
  25. /// </summary>
  26. Matrix WorldTransform { get; }
  27. /// <summary>
  28. /// Invoked after the node took the transformations from the source.
  29. /// </summary>
  30. void NodeAcceptedTransform();
  31. }
  32. /// <summary>
  33. /// A scene node designed to be integrated into GeonBit scene and receive updates from external source,
  34. /// like physical body. This is the default node we use everywhere in the engine.
  35. /// </summary>
  36. public class LinkedNode : CullingNode
  37. {
  38. /// <summary>
  39. /// Option to bind external transformations for this node, like a physical body etc.
  40. /// </summary>
  41. public ITransformationsSource TransformsBind = null;
  42. /// <summary>
  43. /// If true, will not copy scale transformations from source
  44. /// </summary>
  45. public bool KeepScale = true;
  46. /// <summary>
  47. /// Clone this scene node.
  48. /// </summary>
  49. /// <returns>Node copy.</returns>
  50. public override Node Clone()
  51. {
  52. LinkedNode ret = new LinkedNode();
  53. ret._transformations = _transformations.Clone();
  54. ret.Visible = Visible;
  55. return ret;
  56. }
  57. /// <summary>
  58. /// Calc final transformations for current frame.
  59. /// This uses an indicator to know if an update is needed, so no harm is done if you call it multiple times.
  60. /// </summary>
  61. protected override void UpdateTransformations()
  62. {
  63. // if got no transformations bind, call base update
  64. if (TransformsBind == null)
  65. {
  66. base.UpdateTransformations();
  67. return;
  68. }
  69. // if got here it means we need to get transformations from external source.
  70. // check if dirty
  71. if (TransformsBind.IsDirty)
  72. {
  73. // update world transform from bind
  74. if (KeepScale)
  75. {
  76. Vector3 prevScale = _parent.WorldScale * _transformations.Scale;
  77. _worldTransform = Matrix.CreateScale(prevScale) * TransformsBind.WorldTransform;
  78. }
  79. else
  80. {
  81. _worldTransform = TransformsBind.WorldTransform;
  82. }
  83. // notify parent that we accepted transformation and send world matrix change event
  84. TransformsBind.NodeAcceptedTransform();
  85. OnWorldMatrixChange();
  86. }
  87. // no longer dirty
  88. _isDirty = false;
  89. }
  90. }
  91. }