From 0ec26f5184706ec72d3e1b1f87594ff8fdbba911 Mon Sep 17 00:00:00 2001 From: Daniel Chappuis Date: Fri, 14 Feb 2020 17:08:02 +0100 Subject: [PATCH] =?UTF-8?q?Compute=20the=20fat=20AABB=20by=20adding=20a=20?= =?UTF-8?q?percentage=20of=20the=20size=20of=20the=20initial=20AABB=20inst?= =?UTF-8?q?ead=20of=20using=20a=20constant=20offset.=C2=A0Do=20not=20use?= =?UTF-8?q?=20linear=20displacement=20anymore=20in=20inflate=20the=20AABB?= =?UTF-8?q?=20in=20direction=20of=20the=20motion=20in=20the=20broad-phase?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/collision/broadphase/DynamicAABBTree.cpp | 39 +++++-------------- src/collision/broadphase/DynamicAABBTree.h | 10 ++--- src/configuration.h | 11 ++---- src/systems/BroadPhaseSystem.cpp | 20 +++------- src/systems/BroadPhaseSystem.h | 2 +- test/tests/collision/TestDynamicAABBTree.h | 40 ++++++++++---------- 6 files changed, 42 insertions(+), 80 deletions(-) diff --git a/src/collision/broadphase/DynamicAABBTree.cpp b/src/collision/broadphase/DynamicAABBTree.cpp index 60d2c568..4c0e667a 100644 --- a/src/collision/broadphase/DynamicAABBTree.cpp +++ b/src/collision/broadphase/DynamicAABBTree.cpp @@ -35,8 +35,8 @@ using namespace reactphysics3d; const int32 TreeNode::NULL_TREE_NODE = -1; // Constructor -DynamicAABBTree::DynamicAABBTree(MemoryAllocator& allocator, decimal extraAABBGap) - : mAllocator(allocator), mExtraAABBGap(extraAABBGap) { +DynamicAABBTree::DynamicAABBTree(MemoryAllocator& allocator, decimal fatAABBInflatePercentage) + : mAllocator(allocator), mFatAABBInflatePercentage(fatAABBInflatePercentage) { init(); } @@ -135,8 +135,8 @@ int32 DynamicAABBTree::addObjectInternal(const AABB& aabb) { // Get the next available node (or allocate new ones if necessary) int32 nodeID = allocateNode(); - // Create the fat aabb to use in the tree - const Vector3 gap(mExtraAABBGap, mExtraAABBGap, mExtraAABBGap); + // Create the fat aabb to use in the tree (inflate the aabb by a constant percentage of its size) + const Vector3 gap(aabb.getExtent() * mFatAABBInflatePercentage * decimal(0.5f)); mNodes[nodeID].aabb.setMin(aabb.getMin() - gap); mNodes[nodeID].aabb.setMax(aabb.getMax() + gap); @@ -167,12 +167,11 @@ void DynamicAABBTree::removeObject(int32 nodeID) { // Update the dynamic tree after an object has moved. /// If the new AABB of the object that has moved is still inside its fat AABB, then /// nothing is done. Otherwise, the corresponding node is removed and reinserted into the tree. -/// The method returns true if the object has been reinserted into the tree. The "displacement" -/// argument is the linear velocity of the AABB multiplied by the elapsed time between two -/// frames. If the "forceReInsert" parameter is true, we force the existing AABB to take the size +/// The method returns true if the object has been reinserted into the tree. +/// If the "forceReInsert" parameter is true, we force the existing AABB to take the size /// of the "newAABB" parameter even if it is larger than "newAABB". This can be used to shrink the /// AABB in the tree for instance if the corresponding collision shape has been shrunk. -bool DynamicAABBTree::updateObject(int32 nodeID, const AABB& newAABB, const Vector3& displacement, bool forceReinsert) { +bool DynamicAABBTree::updateObject(int32 nodeID, const AABB& newAABB, bool forceReinsert) { RP3D_PROFILE("DynamicAABBTree::updateObject()", mProfiler); @@ -188,32 +187,12 @@ bool DynamicAABBTree::updateObject(int32 nodeID, const AABB& newAABB, const Vect // If the new AABB is outside the fat AABB, we remove the corresponding node removeLeafNode(nodeID); - // Compute the fat AABB by inflating the AABB with a constant gap + // Compute the fat AABB by inflating the AABB with by a constant percentage of the size of the AABB mNodes[nodeID].aabb = newAABB; - const Vector3 gap(mExtraAABBGap, mExtraAABBGap, mExtraAABBGap); + const Vector3 gap(newAABB.getExtent() * mFatAABBInflatePercentage * decimal(0.5f)); mNodes[nodeID].aabb.mMinCoordinates -= gap; mNodes[nodeID].aabb.mMaxCoordinates += gap; - // Inflate the fat AABB in direction of the linear motion of the AABB - if (displacement.x < decimal(0.0)) { - mNodes[nodeID].aabb.mMinCoordinates.x += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER * displacement.x; - } - else { - mNodes[nodeID].aabb.mMaxCoordinates.x += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER * displacement.x; - } - if (displacement.y < decimal(0.0)) { - mNodes[nodeID].aabb.mMinCoordinates.y += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER * displacement.y; - } - else { - mNodes[nodeID].aabb.mMaxCoordinates.y += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER * displacement.y; - } - if (displacement.z < decimal(0.0)) { - mNodes[nodeID].aabb.mMinCoordinates.z += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER * displacement.z; - } - else { - mNodes[nodeID].aabb.mMaxCoordinates.z += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER * displacement.z; - } - assert(mNodes[nodeID].aabb.contains(newAABB)); // Reinsert the node into the tree diff --git a/src/collision/broadphase/DynamicAABBTree.h b/src/collision/broadphase/DynamicAABBTree.h index 3f6415b5..84dc25cc 100644 --- a/src/collision/broadphase/DynamicAABBTree.h +++ b/src/collision/broadphase/DynamicAABBTree.h @@ -158,9 +158,8 @@ class DynamicAABBTree { /// Number of nodes in the tree int32 mNbNodes; - /// Extra AABB Gap used to allow the collision shape to move a little bit - /// without triggering a large modification of the tree which can be costly - decimal mExtraAABBGap; + /// The fat AABB is the initial AABB inflated by a given percentage of its size. + decimal mFatAABBInflatePercentage; #ifdef IS_PROFILING_ACTIVE @@ -210,7 +209,7 @@ class DynamicAABBTree { // -------------------- Methods -------------------- // /// Constructor - DynamicAABBTree(MemoryAllocator& allocator, decimal extraAABBGap = decimal(0.0)); + DynamicAABBTree(MemoryAllocator& allocator, decimal fatAABBInflatePercentage = decimal(0.0)); /// Destructor ~DynamicAABBTree(); @@ -225,8 +224,7 @@ class DynamicAABBTree { void removeObject(int32 nodeID); /// Update the dynamic tree after an object has moved. - bool updateObject(int32 nodeID, const AABB& newAABB, const Vector3& displacement, - bool forceReinsert = false); + bool updateObject(int32 nodeID, const AABB& newAABB, bool forceReinsert = false); /// Return the fat AABB corresponding to a given node ID const AABB& getFatAABB(int32 nodeID) const; diff --git a/src/configuration.h b/src/configuration.h index 554eeab7..339c875e 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -100,14 +100,9 @@ constexpr decimal PI = decimal(3.14159265); constexpr decimal PI_TIMES_2 = decimal(6.28318530); /// In the broad-phase collision detection (dynamic AABB tree), the AABBs are -/// inflated with a constant gap to allow the collision shape to move a little bit -/// without triggering a large modification of the tree which can be costly -constexpr decimal DYNAMIC_TREE_AABB_GAP = decimal(0.1); - -/// In the broad-phase collision detection (dynamic AABB tree), the AABBs are -/// also inflated in direction of the linear motion of the body by mutliplying the -/// followin constant with the linear velocity and the elapsed time between two frames. -constexpr decimal DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER = decimal(1.7); +/// inflated by a constant percentage of its size to allow the collision shape to move a little bit +/// without triggering a large modification of the tree each frame which can be costly +constexpr decimal DYNAMIC_TREE_FAT_AABB_INFLATE_PERCENTAGE = decimal(0.08); /// Current version of ReactPhysics3D const std::string RP3D_VERSION = std::string("0.7.1"); diff --git a/src/systems/BroadPhaseSystem.cpp b/src/systems/BroadPhaseSystem.cpp index 2e6cb7bd..06459032 100644 --- a/src/systems/BroadPhaseSystem.cpp +++ b/src/systems/BroadPhaseSystem.cpp @@ -36,8 +36,8 @@ using namespace reactphysics3d; // Constructor BroadPhaseSystem::BroadPhaseSystem(CollisionDetectionSystem& collisionDetection, ColliderComponents& collidersComponents, - TransformComponents& transformComponents, RigidBodyComponents &rigidBodyComponents) - :mDynamicAABBTree(collisionDetection.getMemoryManager().getPoolAllocator(), DYNAMIC_TREE_AABB_GAP), + TransformComponents& transformComponents, RigidBodyComponents& rigidBodyComponents) + :mDynamicAABBTree(collisionDetection.getMemoryManager().getPoolAllocator(), DYNAMIC_TREE_FAT_AABB_INFLATE_PERCENTAGE), mCollidersComponents(collidersComponents), mTransformsComponents(transformComponents), mRigidBodyComponents(rigidBodyComponents), mMovedShapes(collisionDetection.getMemoryManager().getPoolAllocator()), mCollisionDetection(collisionDetection) { @@ -133,13 +133,13 @@ void BroadPhaseSystem::updateColliders(decimal timeStep) { } // Notify the broad-phase that a collision shape has moved and need to be updated -void BroadPhaseSystem::updateColliderInternal(int32 broadPhaseId, Collider* collider, const AABB& aabb, const Vector3& displacement, +void BroadPhaseSystem::updateColliderInternal(int32 broadPhaseId, Collider* collider, const AABB& aabb, bool forceReInsert) { assert(broadPhaseId >= 0); // Update the dynamic AABB tree according to the movement of the collision shape - bool hasBeenReInserted = mDynamicAABBTree.updateObject(broadPhaseId, aabb, displacement, forceReInsert); + bool hasBeenReInserted = mDynamicAABBTree.updateObject(broadPhaseId, aabb, forceReInsert); // If the collision shape has moved out of its fat AABB (and therefore has been reinserted // into the tree). @@ -176,16 +176,6 @@ void BroadPhaseSystem::updateCollidersComponents(uint32 startIndex, uint32 nbIte const Entity& bodyEntity = mCollidersComponents.mBodiesEntities[i]; const Transform& transform = mTransformsComponents.getTransform(bodyEntity); - // If there is a dynamics component for the current entity - Vector3 displacement(0, 0, 0); - if (mRigidBodyComponents.hasComponent(bodyEntity)) { - - // Get the linear velocity from the dynamics component - const Vector3& linearVelocity = mRigidBodyComponents.getLinearVelocity(bodyEntity); - - displacement = timeStep * linearVelocity; - } - // Recompute the world-space AABB of the collision shape AABB aabb; mCollidersComponents.mCollisionShapes[i]->computeAABB(aabb, transform * mCollidersComponents.mLocalToBodyTransforms[i]); @@ -195,7 +185,7 @@ void BroadPhaseSystem::updateCollidersComponents(uint32 startIndex, uint32 nbIte const bool forceReInsert = mCollidersComponents.mHasCollisionShapeChangedSize[i]; // Update the broad-phase state of the collider - updateColliderInternal(broadPhaseId, mCollidersComponents.mColliders[i], aabb, displacement, forceReInsert); + updateColliderInternal(broadPhaseId, mCollidersComponents.mColliders[i], aabb, forceReInsert); mCollidersComponents.mHasCollisionShapeChangedSize[i] = false; } diff --git a/src/systems/BroadPhaseSystem.h b/src/systems/BroadPhaseSystem.h index b550b62f..f37efe56 100644 --- a/src/systems/BroadPhaseSystem.h +++ b/src/systems/BroadPhaseSystem.h @@ -140,7 +140,7 @@ class BroadPhaseSystem { // -------------------- Methods -------------------- // /// Notify the Dynamic AABB tree that a collider needs to be updated - void updateColliderInternal(int32 broadPhaseId, Collider* collider, const AABB& aabb, const Vector3& displacement, + void updateColliderInternal(int32 broadPhaseId, Collider* collider, const AABB& aabb, bool forceReInsert); /// Update the broad-phase state of some colliders components diff --git a/test/tests/collision/TestDynamicAABBTree.h b/test/tests/collision/TestDynamicAABBTree.h index 15c04edd..465ae241 100755 --- a/test/tests/collision/TestDynamicAABBTree.h +++ b/test/tests/collision/TestDynamicAABBTree.h @@ -238,10 +238,10 @@ class TestDynamicAABBTree : public Test { // ---- Update the object AABBs with the initial AABBs (no reinsertion) ----- // - tree.updateObject(object1Id, aabb1, Vector3::zero()); - tree.updateObject(object2Id, aabb2, Vector3::zero()); - tree.updateObject(object3Id, aabb3, Vector3::zero()); - tree.updateObject(object4Id, aabb4, Vector3::zero()); + tree.updateObject(object1Id, aabb1); + tree.updateObject(object2Id, aabb2); + tree.updateObject(object3Id, aabb3); + tree.updateObject(object4Id, aabb4); // AABB overlapping nothing overlappingNodes.clear(); @@ -285,10 +285,10 @@ class TestDynamicAABBTree : public Test { // ---- Update the object AABBs with the initial AABBs (with reinsertion) ----- // - tree.updateObject(object1Id, aabb1, Vector3::zero()); - tree.updateObject(object2Id, aabb2, Vector3::zero()); - tree.updateObject(object3Id, aabb3, Vector3::zero()); - tree.updateObject(object4Id, aabb4, Vector3::zero()); + tree.updateObject(object1Id, aabb1); + tree.updateObject(object2Id, aabb2); + tree.updateObject(object3Id, aabb3); + tree.updateObject(object4Id, aabb4); // AABB overlapping nothing overlappingNodes.clear(); @@ -333,10 +333,10 @@ class TestDynamicAABBTree : public Test { // ---- Move objects 2 and 3 ----- // AABB newAABB2(Vector3(-7, 10, -3), Vector3(1, 13, 3)); - tree.updateObject(object2Id, newAABB2, Vector3::zero()); + tree.updateObject(object2Id, newAABB2); AABB newAABB3(Vector3(7, -6, -3), Vector3(9, 1, 3)); - tree.updateObject(object3Id, newAABB3, Vector3::zero()); + tree.updateObject(object3Id, newAABB3); // AABB overlapping object 3 overlappingNodes.clear(); @@ -424,10 +424,10 @@ class TestDynamicAABBTree : public Test { // ---- Update the object AABBs with the initial AABBs (no reinsertion) ----- // - tree.updateObject(object1Id, aabb1, Vector3::zero()); - tree.updateObject(object2Id, aabb2, Vector3::zero()); - tree.updateObject(object3Id, aabb3, Vector3::zero()); - tree.updateObject(object4Id, aabb4, Vector3::zero()); + tree.updateObject(object1Id, aabb1); + tree.updateObject(object2Id, aabb2); + tree.updateObject(object3Id, aabb3); + tree.updateObject(object4Id, aabb4); // Ray with no hits mRaycastCallback.reset(); @@ -463,10 +463,10 @@ class TestDynamicAABBTree : public Test { // ---- Update the object AABBs with the initial AABBs (with reinsertion) ----- // - tree.updateObject(object1Id, aabb1, Vector3::zero()); - tree.updateObject(object2Id, aabb2, Vector3::zero()); - tree.updateObject(object3Id, aabb3, Vector3::zero()); - tree.updateObject(object4Id, aabb4, Vector3::zero()); + tree.updateObject(object1Id, aabb1); + tree.updateObject(object2Id, aabb2); + tree.updateObject(object3Id, aabb3); + tree.updateObject(object4Id, aabb4); // Ray with no hits mRaycastCallback.reset(); @@ -503,10 +503,10 @@ class TestDynamicAABBTree : public Test { // ---- Move objects 2 and 3 ----- // AABB newAABB2(Vector3(-7, 10, -3), Vector3(1, 13, 3)); - tree.updateObject(object2Id, newAABB2, Vector3::zero()); + tree.updateObject(object2Id, newAABB2); AABB newAABB3(Vector3(7, -6, -3), Vector3(9, 1, 3)); - tree.updateObject(object3Id, newAABB3, Vector3::zero()); + tree.updateObject(object3Id, newAABB3); // Ray that hits object 1, 2 Ray ray5(Vector3(-4, -5, 0), Vector3(-4, 12, 0));