|
@@ -0,0 +1,209 @@
|
|
|
|
|
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
|
|
|
|
|
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
|
|
|
|
|
+#include "BsCCollider.h"
|
|
|
|
|
+#include "BsSceneObject.h"
|
|
|
|
|
+#include "BsCRigidbody.h"
|
|
|
|
|
+#include "BsPhysics.h"
|
|
|
|
|
+#include "BsCColliderRTTI.h"
|
|
|
|
|
+
|
|
|
|
|
+namespace BansheeEngine
|
|
|
|
|
+{
|
|
|
|
|
+ CCollider::CCollider(const HSceneObject& parent)
|
|
|
|
|
+ : Component(parent)
|
|
|
|
|
+ {
|
|
|
|
|
+ setName("Collider");
|
|
|
|
|
+
|
|
|
|
|
+ mNotifyFlags = (TransformChangedFlags)(TCF_Parent | TCF_Transform);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void CCollider::setIsTrigger(bool value)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (mIsTrigger == value)
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
|
|
+ mIsTrigger = value;
|
|
|
|
|
+
|
|
|
|
|
+ if (mInternal != nullptr)
|
|
|
|
|
+ {
|
|
|
|
|
+ mInternal->setIsTrigger(value);
|
|
|
|
|
+
|
|
|
|
|
+ updateParentRigidbody();
|
|
|
|
|
+ updateTransform();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void CCollider::setMass(float mass)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (mMass == mass)
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
|
|
+ mMass = mass;
|
|
|
|
|
+
|
|
|
|
|
+ if (mInternal != nullptr)
|
|
|
|
|
+ {
|
|
|
|
|
+ mInternal->setMass(mass);
|
|
|
|
|
+
|
|
|
|
|
+ if (mParent != nullptr)
|
|
|
|
|
+ mParent->_updateMassDistribution();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void CCollider::setMaterial(const HPhysicsMaterial& material)
|
|
|
|
|
+ {
|
|
|
|
|
+ mMaterial = material;
|
|
|
|
|
+
|
|
|
|
|
+ if (mInternal != nullptr)
|
|
|
|
|
+ mInternal->setMaterial(material);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void CCollider::setContactOffset(float value)
|
|
|
|
|
+ {
|
|
|
|
|
+ mContactOffset = value;
|
|
|
|
|
+
|
|
|
|
|
+ if (mInternal != nullptr)
|
|
|
|
|
+ mInternal->setContactOffset(value);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void CCollider::setRestOffset(float value)
|
|
|
|
|
+ {
|
|
|
|
|
+ mRestOffset = value;
|
|
|
|
|
+
|
|
|
|
|
+ if (mInternal != nullptr)
|
|
|
|
|
+ mInternal->setRestOffset(value);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void CCollider::setLayer(UINT64 layer)
|
|
|
|
|
+ {
|
|
|
|
|
+ mLayer = layer;
|
|
|
|
|
+
|
|
|
|
|
+ if (mInternal != nullptr)
|
|
|
|
|
+ mInternal->setLayer(layer);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void CCollider::onInitialized()
|
|
|
|
|
+ {
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void CCollider::onDestroyed()
|
|
|
|
|
+ {
|
|
|
|
|
+ // This should release the last reference and destroy the internal collider
|
|
|
|
|
+ mInternal = nullptr;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void CCollider::onDisabled()
|
|
|
|
|
+ {
|
|
|
|
|
+ mParent = nullptr;
|
|
|
|
|
+
|
|
|
|
|
+ // This should release the last reference and destroy the internal collider
|
|
|
|
|
+ mInternal = nullptr;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void CCollider::onEnabled()
|
|
|
|
|
+ {
|
|
|
|
|
+ restoreInternal();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void CCollider::onTransformChanged(TransformChangedFlags flags)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (!SO()->getActive())
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
|
|
+ if ((flags & TCF_Parent) != 0)
|
|
|
|
|
+ updateParentRigidbody();
|
|
|
|
|
+
|
|
|
|
|
+ // Don't update the transform if it's due to Physics update since then we can guarantee it will remain at the same
|
|
|
|
|
+ // relative transform to its parent
|
|
|
|
|
+ if (gPhysics()._isUpdateInProgress())
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
|
|
+ if ((flags & (TCF_Parent | TCF_Transform)) != 0)
|
|
|
|
|
+ updateTransform();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void CCollider::restoreInternal()
|
|
|
|
|
+ {
|
|
|
|
|
+ if(mInternal == nullptr)
|
|
|
|
|
+ mInternal = createInternal();
|
|
|
|
|
+
|
|
|
|
|
+ mInternal->setIsTrigger(mIsTrigger);
|
|
|
|
|
+ mInternal->setMass(mMass);
|
|
|
|
|
+ mInternal->setMaterial(mMaterial);
|
|
|
|
|
+ mInternal->setContactOffset(mContactOffset);
|
|
|
|
|
+ mInternal->setRestOffset(mRestOffset);
|
|
|
|
|
+ mInternal->setLayer(mLayer);
|
|
|
|
|
+
|
|
|
|
|
+ updateParentRigidbody();
|
|
|
|
|
+
|
|
|
|
|
+ if (mParent != nullptr)
|
|
|
|
|
+ mInternal->setRigidbody(mParent->_getInternal());
|
|
|
|
|
+
|
|
|
|
|
+ updateTransform();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void CCollider::updateParentRigidbody()
|
|
|
|
|
+ {
|
|
|
|
|
+ mParent = nullptr;
|
|
|
|
|
+
|
|
|
|
|
+ if (mIsTrigger)
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
|
|
+ HSceneObject currentSO = SO();
|
|
|
|
|
+ while (currentSO != nullptr)
|
|
|
|
|
+ {
|
|
|
|
|
+ mParent = currentSO->getComponent<CRigidbody>();
|
|
|
|
|
+ if (mParent != nullptr)
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
|
|
+ currentSO = currentSO->getParent();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void CCollider::updateTransform()
|
|
|
|
|
+ {
|
|
|
|
|
+ if (mParent != nullptr)
|
|
|
|
|
+ {
|
|
|
|
|
+ Vector3 parentPos = mParent->SO()->getWorldPosition();
|
|
|
|
|
+ Quaternion parentRot = mParent->SO()->getWorldRotation();
|
|
|
|
|
+
|
|
|
|
|
+ Vector3 myPos = SO()->getWorldPosition();
|
|
|
|
|
+ Quaternion myRot = SO()->getWorldRotation();
|
|
|
|
|
+
|
|
|
|
|
+ Vector3 scale = mParent->SO()->getWorldScale();
|
|
|
|
|
+ Vector3 invScale = scale;
|
|
|
|
|
+ if (invScale.x != 0) invScale.x = 1.0f / invScale.x;
|
|
|
|
|
+ if (invScale.y != 0) invScale.y = 1.0f / invScale.y;
|
|
|
|
|
+ if (invScale.z != 0) invScale.z = 1.0f / invScale.z;
|
|
|
|
|
+
|
|
|
|
|
+ Quaternion invRotation = parentRot.inverse();
|
|
|
|
|
+
|
|
|
|
|
+ Vector3 relativePos = invRotation.rotate(myPos - parentPos) * invScale;
|
|
|
|
|
+ Quaternion relativeRot = invRotation * myRot;
|
|
|
|
|
+
|
|
|
|
|
+ relativePos = relativePos + myRot.rotate(mLocalPosition * scale);
|
|
|
|
|
+ relativeRot = relativeRot * mLocalRotation;
|
|
|
|
|
+
|
|
|
|
|
+ mInternal->setTransform(relativePos, relativeRot);
|
|
|
|
|
+ mParent->_updateMassDistribution();
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ Vector3 myScale = SO()->getWorldScale();
|
|
|
|
|
+ Quaternion myRot = SO()->getWorldRotation();
|
|
|
|
|
+ Vector3 myPos = SO()->getWorldPosition() + myRot.rotate(mLocalPosition * myScale);
|
|
|
|
|
+ myRot = myRot * mLocalRotation;
|
|
|
|
|
+
|
|
|
|
|
+ mInternal->setTransform(myPos, myRot);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ RTTITypeBase* CCollider::getRTTIStatic()
|
|
|
|
|
+ {
|
|
|
|
|
+ return CColliderRTTI::instance();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ RTTITypeBase* CCollider::getRTTI() const
|
|
|
|
|
+ {
|
|
|
|
|
+ return CCollider::getRTTIStatic();
|
|
|
|
|
+ }
|
|
|
|
|
+}
|