2
0

BsCCollider.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsCCollider.h"
  4. #include "BsSceneObject.h"
  5. #include "BsCRigidbody.h"
  6. #include "BsPhysics.h"
  7. #include "BsCColliderRTTI.h"
  8. namespace BansheeEngine
  9. {
  10. CCollider::CCollider(const HSceneObject& parent)
  11. : Component(parent)
  12. {
  13. setName("Collider");
  14. mNotifyFlags = (TransformChangedFlags)(TCF_Parent | TCF_Transform);
  15. }
  16. void CCollider::setIsTrigger(bool value)
  17. {
  18. if (mIsTrigger == value)
  19. return;
  20. mIsTrigger = value;
  21. if (mInternal != nullptr)
  22. {
  23. mInternal->setIsTrigger(value);
  24. updateParentRigidbody();
  25. updateTransform();
  26. }
  27. }
  28. void CCollider::setMass(float mass)
  29. {
  30. if (mMass == mass)
  31. return;
  32. mMass = mass;
  33. if (mInternal != nullptr)
  34. {
  35. mInternal->setMass(mass);
  36. if (mParent != nullptr)
  37. mParent->_updateMassDistribution();
  38. }
  39. }
  40. void CCollider::setMaterial(const HPhysicsMaterial& material)
  41. {
  42. mMaterial = material;
  43. if (mInternal != nullptr)
  44. mInternal->setMaterial(material);
  45. }
  46. void CCollider::setContactOffset(float value)
  47. {
  48. mContactOffset = value;
  49. if (mInternal != nullptr)
  50. mInternal->setContactOffset(value);
  51. }
  52. void CCollider::setRestOffset(float value)
  53. {
  54. mRestOffset = value;
  55. if (mInternal != nullptr)
  56. mInternal->setRestOffset(value);
  57. }
  58. void CCollider::setLayer(UINT64 layer)
  59. {
  60. mLayer = layer;
  61. if (mInternal != nullptr)
  62. mInternal->setLayer(layer);
  63. }
  64. void CCollider::onInitialized()
  65. {
  66. }
  67. void CCollider::onDestroyed()
  68. {
  69. // This should release the last reference and destroy the internal collider
  70. mInternal = nullptr;
  71. }
  72. void CCollider::onDisabled()
  73. {
  74. mParent = nullptr;
  75. // This should release the last reference and destroy the internal collider
  76. mInternal = nullptr;
  77. }
  78. void CCollider::onEnabled()
  79. {
  80. restoreInternal();
  81. }
  82. void CCollider::onTransformChanged(TransformChangedFlags flags)
  83. {
  84. if (!SO()->getActive())
  85. return;
  86. if ((flags & TCF_Parent) != 0)
  87. updateParentRigidbody();
  88. // Don't update the transform if it's due to Physics update since then we can guarantee it will remain at the same
  89. // relative transform to its parent
  90. if (gPhysics()._isUpdateInProgress())
  91. return;
  92. if ((flags & (TCF_Parent | TCF_Transform)) != 0)
  93. updateTransform();
  94. }
  95. void CCollider::restoreInternal()
  96. {
  97. if(mInternal == nullptr)
  98. mInternal = createInternal();
  99. mInternal->setIsTrigger(mIsTrigger);
  100. mInternal->setMass(mMass);
  101. mInternal->setMaterial(mMaterial);
  102. mInternal->setContactOffset(mContactOffset);
  103. mInternal->setRestOffset(mRestOffset);
  104. mInternal->setLayer(mLayer);
  105. updateParentRigidbody();
  106. if (mParent != nullptr)
  107. mInternal->setRigidbody(mParent->_getInternal());
  108. updateTransform();
  109. }
  110. void CCollider::updateParentRigidbody()
  111. {
  112. mParent = nullptr;
  113. if (mIsTrigger)
  114. return;
  115. HSceneObject currentSO = SO();
  116. while (currentSO != nullptr)
  117. {
  118. mParent = currentSO->getComponent<CRigidbody>();
  119. if (mParent != nullptr)
  120. return;
  121. currentSO = currentSO->getParent();
  122. }
  123. }
  124. void CCollider::updateTransform()
  125. {
  126. if (mParent != nullptr)
  127. {
  128. Vector3 parentPos = mParent->SO()->getWorldPosition();
  129. Quaternion parentRot = mParent->SO()->getWorldRotation();
  130. Vector3 myPos = SO()->getWorldPosition();
  131. Quaternion myRot = SO()->getWorldRotation();
  132. Vector3 scale = mParent->SO()->getWorldScale();
  133. Vector3 invScale = scale;
  134. if (invScale.x != 0) invScale.x = 1.0f / invScale.x;
  135. if (invScale.y != 0) invScale.y = 1.0f / invScale.y;
  136. if (invScale.z != 0) invScale.z = 1.0f / invScale.z;
  137. Quaternion invRotation = parentRot.inverse();
  138. Vector3 relativePos = invRotation.rotate(myPos - parentPos) * invScale;
  139. Quaternion relativeRot = invRotation * myRot;
  140. relativePos = relativePos + myRot.rotate(mLocalPosition * scale);
  141. relativeRot = relativeRot * mLocalRotation;
  142. mInternal->setTransform(relativePos, relativeRot);
  143. mParent->_updateMassDistribution();
  144. }
  145. else
  146. {
  147. Vector3 myScale = SO()->getWorldScale();
  148. Quaternion myRot = SO()->getWorldRotation();
  149. Vector3 myPos = SO()->getWorldPosition() + myRot.rotate(mLocalPosition * myScale);
  150. myRot = myRot * mLocalRotation;
  151. mInternal->setTransform(myPos, myRot);
  152. }
  153. }
  154. RTTITypeBase* CCollider::getRTTIStatic()
  155. {
  156. return CColliderRTTI::instance();
  157. }
  158. RTTITypeBase* CCollider::getRTTI() const
  159. {
  160. return CCollider::getRTTIStatic();
  161. }
  162. }