Compute the fat AABB by adding a percentage of the size of the initial AABB instead of using a constant offset. Do not use linear displacement anymore in inflate the AABB in direction of the motion in the broad-phase

This commit is contained in:
Daniel Chappuis 2020-02-14 17:08:02 +01:00
parent 7477460e4f
commit 0ec26f5184
6 changed files with 42 additions and 80 deletions

View File

@ -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

View File

@ -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;

View File

@ -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");

View File

@ -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;
}

View File

@ -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

View File

@ -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));