Simplify broad-phase
This commit is contained in:
parent
f9451e1fe1
commit
d8e9f15339
|
@ -466,9 +466,6 @@ void RigidBody::setAngularVelocity(const Vector3& angularVelocity) {
|
||||||
*/
|
*/
|
||||||
void RigidBody::setTransform(const Transform& transform) {
|
void RigidBody::setTransform(const Transform& transform) {
|
||||||
|
|
||||||
// Update the transform of the body
|
|
||||||
mWorld.mTransformComponents.setTransform(mEntity, transform);
|
|
||||||
|
|
||||||
const Vector3 oldCenterOfMass = mCenterOfMassWorld;
|
const Vector3 oldCenterOfMass = mCenterOfMassWorld;
|
||||||
|
|
||||||
// Compute the new center of mass in world-space coordinates
|
// Compute the new center of mass in world-space coordinates
|
||||||
|
@ -480,14 +477,13 @@ void RigidBody::setTransform(const Transform& transform) {
|
||||||
linearVelocity += angularVelocity.cross(mCenterOfMassWorld - oldCenterOfMass);
|
linearVelocity += angularVelocity.cross(mCenterOfMassWorld - oldCenterOfMass);
|
||||||
mWorld.mDynamicsComponents.setLinearVelocity(mEntity, linearVelocity);
|
mWorld.mDynamicsComponents.setLinearVelocity(mEntity, linearVelocity);
|
||||||
|
|
||||||
|
CollisionBody::setTransform(transform);
|
||||||
|
|
||||||
|
// Update the transform of the body
|
||||||
|
mWorld.mTransformComponents.setTransform(mEntity, transform);
|
||||||
|
|
||||||
// Update the world inverse inertia tensor
|
// Update the world inverse inertia tensor
|
||||||
updateInertiaTensorInverseWorld();
|
updateInertiaTensorInverseWorld();
|
||||||
|
|
||||||
// Update the broad-phase state of the body
|
|
||||||
updateBroadPhaseState();
|
|
||||||
|
|
||||||
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
|
|
||||||
"Body " + std::to_string(mID) + ": Set transform=" + transform.to_string());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recompute the center of mass, total mass and inertia tensor of the body using all
|
// Recompute the center of mass, total mass and inertia tensor of the body using all
|
||||||
|
|
|
@ -54,7 +54,7 @@ CollisionDetection::CollisionDetection(CollisionWorld* world, ProxyShapeComponen
|
||||||
mCollisionDispatch(mMemoryManager.getPoolAllocator()), mWorld(world),
|
mCollisionDispatch(mMemoryManager.getPoolAllocator()), mWorld(world),
|
||||||
mOverlappingPairs(mMemoryManager.getPoolAllocator()),
|
mOverlappingPairs(mMemoryManager.getPoolAllocator()),
|
||||||
mBroadPhaseSystem(*this, mProxyShapesComponents, mTransformComponents, dynamicsComponents),
|
mBroadPhaseSystem(*this, mProxyShapesComponents, mTransformComponents, dynamicsComponents),
|
||||||
mNoCollisionPairs(mMemoryManager.getPoolAllocator()), mIsCollisionShapesAdded(false),
|
mNoCollisionPairs(mMemoryManager.getPoolAllocator()), mMapBroadPhaseIdToProxyShapeEntity(memoryManager.getPoolAllocator()),
|
||||||
mNarrowPhaseInput(mMemoryManager.getSingleFrameAllocator()) {
|
mNarrowPhaseInput(mMemoryManager.getSingleFrameAllocator()) {
|
||||||
|
|
||||||
#ifdef IS_PROFILING_ACTIVE
|
#ifdef IS_PROFILING_ACTIVE
|
||||||
|
@ -86,13 +86,84 @@ void CollisionDetection::computeBroadPhase() {
|
||||||
|
|
||||||
RP3D_PROFILE("CollisionDetection::computeBroadPhase()", mProfiler);
|
RP3D_PROFILE("CollisionDetection::computeBroadPhase()", mProfiler);
|
||||||
|
|
||||||
// If new collision shapes have been added to bodies
|
// Ask the broad-phase to compute all the shapes overlapping the shapes that
|
||||||
if (mIsCollisionShapesAdded) {
|
// have moved or have been added in the last frame. This call can only add new
|
||||||
|
// overlapping pairs in the collision detection.
|
||||||
|
List<Pair<int, int>> overlappingNodes(mMemoryManager.getPoolAllocator(), 32);
|
||||||
|
mBroadPhaseSystem.computeOverlappingPairs(mMemoryManager, overlappingNodes);
|
||||||
|
|
||||||
// Ask the broad-phase to recompute the overlapping pairs of collision
|
// Create new overlapping pairs if necessary
|
||||||
// shapes. This call can only add new overlapping pairs in the collision
|
updateOverlappingPairs(overlappingNodes);
|
||||||
// detection.
|
}
|
||||||
mBroadPhaseSystem.computeOverlappingPairs(mMemoryManager);
|
|
||||||
|
// Take a list of overlapping nodes in the broad-phase and create new overlapping pairs if necessary
|
||||||
|
void CollisionDetection::updateOverlappingPairs(List<Pair<int, int>>& overlappingNodes) {
|
||||||
|
|
||||||
|
List<OverlappingPair*> newOverlappingPairs(mMemoryManager.getPoolAllocator(), overlappingNodes.size());
|
||||||
|
|
||||||
|
// For each overlapping pair of nodes
|
||||||
|
for (uint i=0; i < overlappingNodes.size(); i++) {
|
||||||
|
|
||||||
|
Pair<int, int> nodePair = overlappingNodes[i];
|
||||||
|
|
||||||
|
assert(nodePair.first != -1);
|
||||||
|
assert(nodePair.second != -1);
|
||||||
|
|
||||||
|
// Skip pairs with same overlapping nodes
|
||||||
|
if (nodePair.first != nodePair.second) {
|
||||||
|
|
||||||
|
// Get the two proxy-shapes
|
||||||
|
Entity proxyShape1Entity = mMapBroadPhaseIdToProxyShapeEntity[nodePair.first];
|
||||||
|
Entity proxyShape2Entity = mMapBroadPhaseIdToProxyShapeEntity[nodePair.second];
|
||||||
|
|
||||||
|
// Get the two bodies
|
||||||
|
Entity body1Entity = mProxyShapesComponents.getBody(proxyShape1Entity);
|
||||||
|
Entity body2Entity = mProxyShapesComponents.getBody(proxyShape2Entity);
|
||||||
|
|
||||||
|
// If the two proxy collision shapes are from the same body, skip it
|
||||||
|
if (body1Entity != body2Entity) {
|
||||||
|
|
||||||
|
// Compute the overlapping pair ID
|
||||||
|
Pair<uint, uint> pairID = OverlappingPair::computeID(nodePair.first, nodePair.second);
|
||||||
|
|
||||||
|
// Check if the overlapping pair already exists
|
||||||
|
if (!mOverlappingPairs.containsKey(pairID)) {
|
||||||
|
|
||||||
|
unsigned short shape1CollideWithMaskBits = mProxyShapesComponents.getCollideWithMaskBits(proxyShape1Entity);
|
||||||
|
unsigned short shape2CollideWithMaskBits = mProxyShapesComponents.getCollideWithMaskBits(proxyShape2Entity);
|
||||||
|
|
||||||
|
unsigned short shape1CollisionCategoryBits = mProxyShapesComponents.getCollisionCategoryBits(proxyShape1Entity);
|
||||||
|
unsigned short shape2CollisionCategoryBits = mProxyShapesComponents.getCollisionCategoryBits(proxyShape2Entity);
|
||||||
|
|
||||||
|
// Check if the collision filtering allows collision between the two shapes
|
||||||
|
if ((shape1CollideWithMaskBits & shape2CollisionCategoryBits) != 0 &&
|
||||||
|
(shape1CollisionCategoryBits & shape2CollideWithMaskBits) != 0) {
|
||||||
|
|
||||||
|
ProxyShape* shape1 = mProxyShapesComponents.getProxyShape(proxyShape1Entity);
|
||||||
|
ProxyShape* shape2 = mProxyShapesComponents.getProxyShape(proxyShape2Entity);
|
||||||
|
|
||||||
|
// Create the overlapping pair and add it into the set of overlapping pairs
|
||||||
|
OverlappingPair* newPair = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(OverlappingPair)))
|
||||||
|
OverlappingPair(shape1, shape2, mMemoryManager.getPoolAllocator(),
|
||||||
|
mMemoryManager.getSingleFrameAllocator(), mWorld->mConfig);
|
||||||
|
|
||||||
|
assert(newPair != nullptr);
|
||||||
|
|
||||||
|
// Add the new overlapping pair
|
||||||
|
mOverlappingPairs.add(Pair<Pair<uint, uint>, OverlappingPair*>(pairID, newPair));
|
||||||
|
newOverlappingPairs.add(newPair);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For each new overlapping pair
|
||||||
|
for (uint i=0; i < newOverlappingPairs.size(); i++) {
|
||||||
|
|
||||||
|
// Wake up the two bodies of the new overlapping pair
|
||||||
|
mWorld->notifyBodyDisabled(newOverlappingPairs[i]->getShape1()->getBody()->getEntity(), false);
|
||||||
|
mWorld->notifyBodyDisabled(newOverlappingPairs[i]->getShape1()->getBody()->getEntity(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,43 +408,11 @@ void CollisionDetection::computeNarrowPhase() {
|
||||||
mNarrowPhaseInput.clear();
|
mNarrowPhaseInput.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow the broadphase to notify the collision detection about an overlapping pair.
|
|
||||||
/// This method is called by the broad-phase collision detection algorithm
|
|
||||||
void CollisionDetection::broadPhaseNotifyOverlappingPair(ProxyShape* shape1, ProxyShape* shape2) {
|
|
||||||
|
|
||||||
assert(shape1->getBroadPhaseId() != -1);
|
|
||||||
assert(shape2->getBroadPhaseId() != -1);
|
|
||||||
assert(shape1->getBroadPhaseId() != shape2->getBroadPhaseId());
|
|
||||||
|
|
||||||
// Compute the overlapping pair ID
|
|
||||||
Pair<uint, uint> pairID = OverlappingPair::computeID(shape1, shape2);
|
|
||||||
|
|
||||||
// Check if the overlapping pair already exists
|
|
||||||
if (mOverlappingPairs.containsKey(pairID)) return;
|
|
||||||
|
|
||||||
// Check if the collision filtering allows collision between the two shapes
|
|
||||||
if ((shape1->getCollideWithMaskBits() & shape2->getCollisionCategoryBits()) == 0 ||
|
|
||||||
(shape1->getCollisionCategoryBits() & shape2->getCollideWithMaskBits()) == 0) return;
|
|
||||||
|
|
||||||
// Create the overlapping pair and add it into the set of overlapping pairs
|
|
||||||
OverlappingPair* newPair = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(OverlappingPair)))
|
|
||||||
OverlappingPair(shape1, shape2, mMemoryManager.getPoolAllocator(),
|
|
||||||
mMemoryManager.getSingleFrameAllocator(), mWorld->mConfig);
|
|
||||||
|
|
||||||
assert(newPair != nullptr);
|
|
||||||
|
|
||||||
// Add the new overlapping pair
|
|
||||||
mOverlappingPairs.add(Pair<Pair<uint, uint>, OverlappingPair*>(pairID, newPair));
|
|
||||||
|
|
||||||
// Wake up the two bodies
|
|
||||||
shape1->getBody()->setIsSleeping(false);
|
|
||||||
shape2->getBody()->setIsSleeping(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove a body from the collision detection
|
// Remove a body from the collision detection
|
||||||
void CollisionDetection::removeProxyCollisionShape(ProxyShape* proxyShape) {
|
void CollisionDetection::removeProxyCollisionShape(ProxyShape* proxyShape) {
|
||||||
|
|
||||||
assert(proxyShape->getBroadPhaseId() != -1);
|
assert(proxyShape->getBroadPhaseId() != -1);
|
||||||
|
assert(mMapBroadPhaseIdToProxyShapeEntity.containsKey(proxyShape->getBroadPhaseId()));
|
||||||
|
|
||||||
// Remove all the overlapping pairs involving this proxy shape
|
// Remove all the overlapping pairs involving this proxy shape
|
||||||
for (auto it = mOverlappingPairs.begin(); it != mOverlappingPairs.end(); ) {
|
for (auto it = mOverlappingPairs.begin(); it != mOverlappingPairs.end(); ) {
|
||||||
|
@ -395,6 +434,8 @@ void CollisionDetection::removeProxyCollisionShape(ProxyShape* proxyShape) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mMapBroadPhaseIdToProxyShapeEntity.remove(proxyShape->getBroadPhaseId());
|
||||||
|
|
||||||
// Remove the body from the broad-phase
|
// Remove the body from the broad-phase
|
||||||
mBroadPhaseSystem.removeProxyCollisionShape(proxyShape);
|
mBroadPhaseSystem.removeProxyCollisionShape(proxyShape);
|
||||||
}
|
}
|
||||||
|
@ -739,7 +780,7 @@ void CollisionDetection::testCollision(CollisionBody* body1, CollisionBody* body
|
||||||
if (aabb1.testCollision(aabb2)) {
|
if (aabb1.testCollision(aabb2)) {
|
||||||
|
|
||||||
OverlappingPair* pair;
|
OverlappingPair* pair;
|
||||||
const Pair<uint, uint> pairID = OverlappingPair::computeID(body1ProxyShape, body2ProxyShape);
|
const Pair<uint, uint> pairID = OverlappingPair::computeID(body1ProxyShape->getBroadPhaseId(), body2ProxyShape->getBroadPhaseId());
|
||||||
|
|
||||||
// Try to retrieve a corresponding copy of the overlapping pair (if it exists)
|
// Try to retrieve a corresponding copy of the overlapping pair (if it exists)
|
||||||
auto itPair = overlappingPairs.find(pairID);
|
auto itPair = overlappingPairs.find(pairID);
|
||||||
|
@ -832,7 +873,7 @@ void CollisionDetection::testCollision(CollisionBody* body, CollisionCallback* c
|
||||||
if ((proxyShape->getCollisionCategoryBits() & categoryMaskBits) != 0) {
|
if ((proxyShape->getCollisionCategoryBits() & categoryMaskBits) != 0) {
|
||||||
|
|
||||||
OverlappingPair* pair;
|
OverlappingPair* pair;
|
||||||
const Pair<uint, uint> pairID = OverlappingPair::computeID(bodyProxyShape, proxyShape);
|
const Pair<uint, uint> pairID = OverlappingPair::computeID(bodyProxyShape->getBroadPhaseId(), proxyShape->getBroadPhaseId());
|
||||||
|
|
||||||
// Try to retrieve a corresponding copy of the overlapping pair (if it exists)
|
// Try to retrieve a corresponding copy of the overlapping pair (if it exists)
|
||||||
auto itPair = overlappingPairs.find(pairID);
|
auto itPair = overlappingPairs.find(pairID);
|
||||||
|
@ -905,7 +946,7 @@ void CollisionDetection::testCollision(CollisionCallback* callback) {
|
||||||
OverlappingPair* originalPair = it->second;
|
OverlappingPair* originalPair = it->second;
|
||||||
|
|
||||||
OverlappingPair* pair;
|
OverlappingPair* pair;
|
||||||
const Pair<uint, uint> pairID = OverlappingPair::computeID(originalPair->getShape1(), originalPair->getShape2());
|
const Pair<uint, uint> pairID = OverlappingPair::computeID(originalPair->getShape1()->getBroadPhaseId(), originalPair->getShape2()->getBroadPhaseId());
|
||||||
|
|
||||||
// Try to retrieve a corresponding copy of the overlapping pair (if it exists)
|
// Try to retrieve a corresponding copy of the overlapping pair (if it exists)
|
||||||
auto itPair = overlappingPairs.find(pairID);
|
auto itPair = overlappingPairs.find(pairID);
|
||||||
|
|
|
@ -90,8 +90,8 @@ class CollisionDetection {
|
||||||
/// Set of pair of bodies that cannot collide between each other
|
/// Set of pair of bodies that cannot collide between each other
|
||||||
Set<bodyindexpair> mNoCollisionPairs;
|
Set<bodyindexpair> mNoCollisionPairs;
|
||||||
|
|
||||||
/// True if some collision shapes have been added previously
|
/// Map a broad-phase id with the corresponding entity of the proxy-shape
|
||||||
bool mIsCollisionShapesAdded;
|
Map<int, Entity> mMapBroadPhaseIdToProxyShapeEntity;
|
||||||
|
|
||||||
/// Narrow-phase collision detection input
|
/// Narrow-phase collision detection input
|
||||||
NarrowPhaseInput mNarrowPhaseInput;
|
NarrowPhaseInput mNarrowPhaseInput;
|
||||||
|
@ -114,6 +114,9 @@ class CollisionDetection {
|
||||||
/// Compute the narrow-phase collision detection
|
/// Compute the narrow-phase collision detection
|
||||||
void computeNarrowPhase();
|
void computeNarrowPhase();
|
||||||
|
|
||||||
|
/// Take a list of overlapping nodes in the broad-phase and create new overlapping pairs if necessary
|
||||||
|
void updateOverlappingPairs(List<Pair<int, int> >& overlappingNodes);
|
||||||
|
|
||||||
/// Execute the narrow-phase collision detection algorithm on batches
|
/// Execute the narrow-phase collision detection algorithm on batches
|
||||||
bool testNarrowPhaseCollision(NarrowPhaseInput& narrowPhaseInput, bool stopFirstContactFound,
|
bool testNarrowPhaseCollision(NarrowPhaseInput& narrowPhaseInput, bool stopFirstContactFound,
|
||||||
bool reportContacts, MemoryAllocator& allocator);
|
bool reportContacts, MemoryAllocator& allocator);
|
||||||
|
@ -215,9 +218,6 @@ class CollisionDetection {
|
||||||
/// Test and report collisions between all shapes of the world
|
/// Test and report collisions between all shapes of the world
|
||||||
void testCollision(CollisionCallback* callback);
|
void testCollision(CollisionCallback* callback);
|
||||||
|
|
||||||
/// Allow the broadphase to notify the collision detection about an overlapping pair.
|
|
||||||
void broadPhaseNotifyOverlappingPair(ProxyShape* shape1, ProxyShape* shape2);
|
|
||||||
|
|
||||||
/// Return a reference to the memory manager
|
/// Return a reference to the memory manager
|
||||||
MemoryManager& getMemoryManager() const;
|
MemoryManager& getMemoryManager() const;
|
||||||
|
|
||||||
|
@ -249,14 +249,18 @@ inline CollisionDispatch& CollisionDetection::getCollisionDispatch() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a body to the collision detection
|
// Add a body to the collision detection
|
||||||
inline void CollisionDetection::addProxyCollisionShape(ProxyShape* proxyShape,
|
inline void CollisionDetection::addProxyCollisionShape(ProxyShape* proxyShape, const AABB& aabb) {
|
||||||
const AABB& aabb) {
|
|
||||||
|
|
||||||
// Add the body to the broad-phase
|
// Add the body to the broad-phase
|
||||||
mBroadPhaseSystem.addProxyCollisionShape(proxyShape, aabb);
|
mBroadPhaseSystem.addProxyCollisionShape(proxyShape, aabb);
|
||||||
|
|
||||||
mIsCollisionShapesAdded = true;
|
int broadPhaseId = mProxyShapesComponents.getBroadPhaseId(proxyShape->getEntity());
|
||||||
}
|
|
||||||
|
assert(!mMapBroadPhaseIdToProxyShapeEntity.containsKey(broadPhaseId));
|
||||||
|
|
||||||
|
// Add the mapping between the proxy-shape broad-phase id and its entity
|
||||||
|
mMapBroadPhaseIdToProxyShapeEntity.add(Pair<int, Entity>(broadPhaseId, proxyShape->getEntity()));
|
||||||
|
}
|
||||||
|
|
||||||
// Add a pair of bodies that cannot collide with each other
|
// Add a pair of bodies that cannot collide with each other
|
||||||
inline void CollisionDetection::addNoCollisionPair(CollisionBody* body1,
|
inline void CollisionDetection::addNoCollisionPair(CollisionBody* body1,
|
||||||
|
|
|
@ -592,15 +592,66 @@ int DynamicAABBTree::balanceSubTreeAtNode(int nodeID) {
|
||||||
return nodeID;
|
return nodeID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Take a list of shapes to be tested for broad-phase overlap and return a list of pair of overlapping shapes
|
||||||
|
void DynamicAABBTree::reportAllShapesOverlappingWithShapes(const List<int>& nodesToTest, size_t startIndex,
|
||||||
|
size_t endIndex, List<Pair<int, int>>& outOverlappingNodes) const {
|
||||||
|
|
||||||
|
// Create a stack with the nodes to visit
|
||||||
|
Stack<int> stack(mAllocator, 64);
|
||||||
|
|
||||||
|
// For each shape to be tested for overlap
|
||||||
|
for (uint i=startIndex; i < endIndex; i++) {
|
||||||
|
|
||||||
|
assert(nodesToTest[i] != -1);
|
||||||
|
|
||||||
|
stack.push(mRootNodeID);
|
||||||
|
|
||||||
|
const AABB& shapeAABB = getFatAABB(nodesToTest[i]);
|
||||||
|
|
||||||
|
// While there are still nodes to visit
|
||||||
|
while(stack.size() > 0) {
|
||||||
|
|
||||||
|
// Get the next node ID to visit
|
||||||
|
const int nodeIDToVisit = stack.pop();
|
||||||
|
|
||||||
|
// Skip it if it is a null node
|
||||||
|
if (nodeIDToVisit == TreeNode::NULL_TREE_NODE) continue;
|
||||||
|
|
||||||
|
// Get the corresponding node
|
||||||
|
const TreeNode* nodeToVisit = mNodes + nodeIDToVisit;
|
||||||
|
|
||||||
|
// If the AABB in parameter overlaps with the AABB of the node to visit
|
||||||
|
if (shapeAABB.testCollision(nodeToVisit->aabb)) {
|
||||||
|
|
||||||
|
// If the node is a leaf
|
||||||
|
if (nodeToVisit->isLeaf()) {
|
||||||
|
|
||||||
|
// Add the node in the list of overlapping nodes
|
||||||
|
outOverlappingNodes.add(Pair<int, int>(nodesToTest[i], nodeIDToVisit));
|
||||||
|
}
|
||||||
|
else { // If the node is not a leaf
|
||||||
|
|
||||||
|
// We need to visit its children
|
||||||
|
stack.push(nodeToVisit->children[0]);
|
||||||
|
stack.push(nodeToVisit->children[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stack.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Report all shapes overlapping with the AABB given in parameter.
|
/// Report all shapes overlapping with the AABB given in parameter.
|
||||||
|
// TODO : Do not use this method anymore. Use
|
||||||
void DynamicAABBTree::reportAllShapesOverlappingWithAABB(const AABB& aabb, DynamicAABBTreeOverlapCallback& callback) const {
|
void DynamicAABBTree::reportAllShapesOverlappingWithAABB(const AABB& aabb, DynamicAABBTreeOverlapCallback& callback) const {
|
||||||
|
|
||||||
// Create a stack with the nodes to visit
|
// Create a stack with the nodes to visit
|
||||||
Stack<int, 64> stack(mAllocator);
|
Stack<int> stack(mAllocator, 64);
|
||||||
stack.push(mRootNodeID);
|
stack.push(mRootNodeID);
|
||||||
|
|
||||||
// While there are still nodes to visit
|
// While there are still nodes to visit
|
||||||
while(stack.getNbElements() > 0) {
|
while(stack.size() > 0) {
|
||||||
|
|
||||||
// Get the next node ID to visit
|
// Get the next node ID to visit
|
||||||
const int nodeIDToVisit = stack.pop();
|
const int nodeIDToVisit = stack.pop();
|
||||||
|
@ -637,12 +688,12 @@ void DynamicAABBTree::raycast(const Ray& ray, DynamicAABBTreeRaycastCallback &ca
|
||||||
|
|
||||||
decimal maxFraction = ray.maxFraction;
|
decimal maxFraction = ray.maxFraction;
|
||||||
|
|
||||||
Stack<int, 128> stack(mAllocator);
|
Stack<int> stack(mAllocator, 128);
|
||||||
stack.push(mRootNodeID);
|
stack.push(mRootNodeID);
|
||||||
|
|
||||||
// Walk through the tree from the root looking for proxy shapes
|
// Walk through the tree from the root looking for proxy shapes
|
||||||
// that overlap with the ray AABB
|
// that overlap with the ray AABB
|
||||||
while (stack.getNbElements() > 0) {
|
while (stack.size() > 0) {
|
||||||
|
|
||||||
// Get the next node in the stack
|
// Get the next node in the stack
|
||||||
int nodeID = stack.pop();
|
int nodeID = stack.pop();
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
// Libraries
|
// Libraries
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "collision/shapes/AABB.h"
|
#include "collision/shapes/AABB.h"
|
||||||
|
#include "containers/Set.h"
|
||||||
|
|
||||||
/// Namespace ReactPhysics3D
|
/// Namespace ReactPhysics3D
|
||||||
namespace reactphysics3d {
|
namespace reactphysics3d {
|
||||||
|
@ -236,6 +237,10 @@ class DynamicAABBTree {
|
||||||
/// Return the data pointer of a given leaf node of the tree
|
/// Return the data pointer of a given leaf node of the tree
|
||||||
void* getNodeDataPointer(int nodeID) const;
|
void* getNodeDataPointer(int nodeID) const;
|
||||||
|
|
||||||
|
/// Report all shapes overlapping with all the shapes in the map in parameter
|
||||||
|
void reportAllShapesOverlappingWithShapes(const List<int>& nodesToTest, size_t startIndex,
|
||||||
|
size_t endIndex, List<Pair<int, int>>& outOverlappingNodes) const;
|
||||||
|
|
||||||
/// Report all shapes overlapping with the AABB given in parameter.
|
/// Report all shapes overlapping with the AABB given in parameter.
|
||||||
void reportAllShapesOverlappingWithAABB(const AABB& aabb, DynamicAABBTreeOverlapCallback& callback) const;
|
void reportAllShapesOverlappingWithAABB(const AABB& aabb, DynamicAABBTreeOverlapCallback& callback) const;
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,10 @@ class Components {
|
||||||
/// Remove a component
|
/// Remove a component
|
||||||
void removeComponent(Entity entity);
|
void removeComponent(Entity entity);
|
||||||
|
|
||||||
/// Notify if a given entity is disabled (sleeping or inactive) or not
|
/// Return true if an entity is sleeping
|
||||||
|
bool getIsEntityDisabled(Entity entity) const;
|
||||||
|
|
||||||
|
/// Notify if a given entity is sleeping
|
||||||
void setIsEntityDisabled(Entity entity, bool isDisabled);
|
void setIsEntityDisabled(Entity entity, bool isDisabled);
|
||||||
|
|
||||||
/// Return true if there is a component for a given entity
|
/// Return true if there is a component for a given entity
|
||||||
|
@ -120,6 +123,12 @@ class Components {
|
||||||
uint32 getNbEnabledComponents() const;
|
uint32 getNbEnabledComponents() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Return true if an entity is sleeping
|
||||||
|
inline bool Components::getIsEntityDisabled(Entity entity) const {
|
||||||
|
assert(hasComponent(entity));
|
||||||
|
return mMapEntityToComponentIndex[entity] >= mDisabledStartIndex;
|
||||||
|
}
|
||||||
|
|
||||||
// Return true if there is a component for a given entity
|
// Return true if there is a component for a given entity
|
||||||
inline bool Components::hasComponent(Entity entity) const {
|
inline bool Components::hasComponent(Entity entity) const {
|
||||||
return mMapEntityToComponentIndex.containsKey(entity);
|
return mMapEntityToComponentIndex.containsKey(entity);
|
||||||
|
|
|
@ -55,10 +55,10 @@ class ProxyShapeComponents : public Components {
|
||||||
|
|
||||||
// -------------------- Attributes -------------------- //
|
// -------------------- Attributes -------------------- //
|
||||||
|
|
||||||
/// Array of entities of each component
|
/// Array of body entity of each component
|
||||||
Entity* mBodiesEntities;
|
Entity* mBodiesEntities;
|
||||||
|
|
||||||
/// Array of entities of each component
|
/// Array of proxy-shape entity of each component
|
||||||
Entity* mProxyShapesEntities;
|
Entity* mProxyShapesEntities;
|
||||||
|
|
||||||
/// Array of pointer to the proxy-shapes
|
/// Array of pointer to the proxy-shapes
|
||||||
|
@ -140,6 +140,9 @@ class ProxyShapeComponents : public Components {
|
||||||
/// Add a component
|
/// Add a component
|
||||||
void addComponent(Entity proxyShapeEntity, bool isSleeping, const ProxyShapeComponent& component);
|
void addComponent(Entity proxyShapeEntity, bool isSleeping, const ProxyShapeComponent& component);
|
||||||
|
|
||||||
|
/// Return the body entity of a given proxy-shape
|
||||||
|
Entity getBody(Entity proxyShapeEntity) const;
|
||||||
|
|
||||||
/// Return the mass of a proxy-shape
|
/// Return the mass of a proxy-shape
|
||||||
decimal getMass(Entity proxyShapeEntity) const;
|
decimal getMass(Entity proxyShapeEntity) const;
|
||||||
|
|
||||||
|
@ -178,6 +181,14 @@ class ProxyShapeComponents : public Components {
|
||||||
friend class BroadPhaseSystem;
|
friend class BroadPhaseSystem;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Return the body entity of a given proxy-shape
|
||||||
|
inline Entity ProxyShapeComponents::getBody(Entity proxyShapeEntity) const {
|
||||||
|
|
||||||
|
assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
|
||||||
|
|
||||||
|
return mBodiesEntities[mMapEntityToComponentIndex[proxyShapeEntity]];
|
||||||
|
}
|
||||||
|
|
||||||
// Return the mass of a proxy-shape
|
// Return the mass of a proxy-shape
|
||||||
inline decimal ProxyShapeComponents::getMass(Entity proxyShapeEntity) const {
|
inline decimal ProxyShapeComponents::getMass(Entity proxyShapeEntity) const {
|
||||||
|
|
||||||
|
|
|
@ -250,6 +250,8 @@ void CollisionWorld::resetContactManifoldListsOfBodies() {
|
||||||
// Notify the world if a body is disabled (sleeping or inactive) or not
|
// Notify the world if a body is disabled (sleeping or inactive) or not
|
||||||
void CollisionWorld::notifyBodyDisabled(Entity bodyEntity, bool isDisabled) {
|
void CollisionWorld::notifyBodyDisabled(Entity bodyEntity, bool isDisabled) {
|
||||||
|
|
||||||
|
if (isDisabled == mBodyComponents.getIsEntityDisabled(bodyEntity)) return;
|
||||||
|
|
||||||
// TODO : Make sure we notify all the components here ...
|
// TODO : Make sure we notify all the components here ...
|
||||||
|
|
||||||
// Notify all the components
|
// Notify all the components
|
||||||
|
|
|
@ -35,7 +35,7 @@ using namespace reactphysics3d;
|
||||||
OverlappingPair::OverlappingPair(ProxyShape* shape1, ProxyShape* shape2,
|
OverlappingPair::OverlappingPair(ProxyShape* shape1, ProxyShape* shape2,
|
||||||
MemoryAllocator& persistentMemoryAllocator, MemoryAllocator& temporaryMemoryAllocator,
|
MemoryAllocator& persistentMemoryAllocator, MemoryAllocator& temporaryMemoryAllocator,
|
||||||
const WorldSettings& worldSettings)
|
const WorldSettings& worldSettings)
|
||||||
: mPairID(computeID(shape1, shape2)), mContactManifoldSet(shape1, shape2, persistentMemoryAllocator, worldSettings),
|
: mPairID(computeID(shape1->getBroadPhaseId(), shape2->getBroadPhaseId())), mContactManifoldSet(shape1, shape2, persistentMemoryAllocator, worldSettings),
|
||||||
mPersistentAllocator(persistentMemoryAllocator), mTempMemoryAllocator(temporaryMemoryAllocator),
|
mPersistentAllocator(persistentMemoryAllocator), mTempMemoryAllocator(temporaryMemoryAllocator),
|
||||||
mLastFrameCollisionInfos(mPersistentAllocator), mWorldSettings(worldSettings) {
|
mLastFrameCollisionInfos(mPersistentAllocator), mWorldSettings(worldSettings) {
|
||||||
|
|
||||||
|
|
|
@ -192,7 +192,7 @@ class OverlappingPair {
|
||||||
void makeLastFrameCollisionInfosObsolete();
|
void makeLastFrameCollisionInfosObsolete();
|
||||||
|
|
||||||
/// Return the pair of bodies index
|
/// Return the pair of bodies index
|
||||||
static OverlappingPairId computeID(ProxyShape* shape1, ProxyShape* shape2);
|
static OverlappingPairId computeID(int shape1BroadPhaseId, int shape2BroadPhaseId);
|
||||||
|
|
||||||
/// Return the pair of bodies index of the pair
|
/// Return the pair of bodies index of the pair
|
||||||
static bodyindexpair computeBodiesIndexPair(CollisionBody* body1, CollisionBody* body2);
|
static bodyindexpair computeBodiesIndexPair(CollisionBody* body1, CollisionBody* body2);
|
||||||
|
@ -234,13 +234,13 @@ inline void OverlappingPair::makeContactsObsolete() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the pair of bodies index
|
// Return the pair of bodies index
|
||||||
inline OverlappingPair::OverlappingPairId OverlappingPair::computeID(ProxyShape* shape1, ProxyShape* shape2) {
|
inline OverlappingPair::OverlappingPairId OverlappingPair::computeID(int shape1BroadPhaseId, int shape2BroadPhaseId) {
|
||||||
assert(shape1->getBroadPhaseId() >= 0 && shape2->getBroadPhaseId() >= 0);
|
assert(shape1BroadPhaseId >= 0 && shape2BroadPhaseId >= 0);
|
||||||
|
|
||||||
// Construct the pair of body index
|
// Construct the pair of body index
|
||||||
OverlappingPairId pairID = shape1->getBroadPhaseId() < shape2->getBroadPhaseId() ?
|
OverlappingPairId pairID = shape1BroadPhaseId < shape2BroadPhaseId ?
|
||||||
OverlappingPairId(shape1->getBroadPhaseId(), shape2->getBroadPhaseId()) :
|
OverlappingPairId(shape1BroadPhaseId, shape2BroadPhaseId) :
|
||||||
OverlappingPairId(shape2->getBroadPhaseId(), shape1->getBroadPhaseId());
|
OverlappingPairId(shape2BroadPhaseId, shape1BroadPhaseId);
|
||||||
assert(pairID.first != pairID.second);
|
assert(pairID.first != pairID.second);
|
||||||
return pairID;
|
return pairID;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ bool BroadPhaseSystem::testOverlappingShapes(const ProxyShape* shape1,
|
||||||
void BroadPhaseSystem::raycast(const Ray& ray, RaycastTest& raycastTest,
|
void BroadPhaseSystem::raycast(const Ray& ray, RaycastTest& raycastTest,
|
||||||
unsigned short raycastWithCategoryMaskBits) const {
|
unsigned short raycastWithCategoryMaskBits) const {
|
||||||
|
|
||||||
RP3D_PROFILE("BroadPhaseAlgorithm::raycast()", mProfiler);
|
RP3D_PROFILE("BroadPhaseSystem::raycast()", mProfiler);
|
||||||
|
|
||||||
BroadPhaseRaycastCallback broadPhaseRaycastCallback(mDynamicAABBTree, raycastWithCategoryMaskBits, raycastTest);
|
BroadPhaseRaycastCallback broadPhaseRaycastCallback(mDynamicAABBTree, raycastWithCategoryMaskBits, raycastTest);
|
||||||
|
|
||||||
|
@ -203,60 +203,19 @@ void BroadPhaseSystem::reportAllShapesOverlappingWithAABB(const AABB& aabb, List
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute all the overlapping pairs of collision shapes
|
// Compute all the overlapping pairs of collision shapes
|
||||||
void BroadPhaseSystem::computeOverlappingPairs(MemoryManager& memoryManager) {
|
void BroadPhaseSystem::computeOverlappingPairs(MemoryManager& memoryManager, List<Pair<int, int>>& overlappingNodes) {
|
||||||
|
|
||||||
List<int> overlappingNodes(memoryManager.getPoolAllocator());
|
// Get the list of the proxy-shapes that have moved or have been created in the last frame
|
||||||
|
List<int> shapesToTest = mMovedShapes.toList(memoryManager.getPoolAllocator());
|
||||||
|
|
||||||
// For all collision shapes that have moved (or have been created) during the last simulation step
|
// Ask the dynamic AABB tree to report all collision shapes that overlap with the shapes to test
|
||||||
for (auto it = mMovedShapes.begin(); it != mMovedShapes.end(); ++it) {
|
mDynamicAABBTree.reportAllShapesOverlappingWithShapes(shapesToTest, 0, shapesToTest.size(), overlappingNodes);
|
||||||
int shapeID = *it;
|
|
||||||
|
|
||||||
if (shapeID == -1) continue;
|
|
||||||
|
|
||||||
AABBOverlapCallback callback(overlappingNodes);
|
|
||||||
|
|
||||||
// Get the AABB of the shape
|
|
||||||
const AABB& shapeAABB = mDynamicAABBTree.getFatAABB(shapeID);
|
|
||||||
|
|
||||||
// Ask the dynamic AABB tree to report all collision shapes that overlap with
|
|
||||||
// this AABB. The method BroadPhase::notifiyOverlappingPair() will be called
|
|
||||||
// by the dynamic AABB tree for each potential overlapping pair.
|
|
||||||
mDynamicAABBTree.reportAllShapesOverlappingWithAABB(shapeAABB, callback);
|
|
||||||
|
|
||||||
// Add the potential overlapping pairs
|
|
||||||
addOverlappingNodes(shapeID, overlappingNodes);
|
|
||||||
|
|
||||||
// Remove all the elements of the linked list of overlapping nodes
|
|
||||||
overlappingNodes.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset the array of collision shapes that have move (or have been created) during the
|
// Reset the array of collision shapes that have move (or have been created) during the
|
||||||
// last simulation step
|
// last simulation step
|
||||||
mMovedShapes.clear();
|
mMovedShapes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify the broad-phase about a potential overlapping pair in the dynamic AABB tree
|
|
||||||
void BroadPhaseSystem::addOverlappingNodes(int referenceNodeId, const List<int>& overlappingNodes) {
|
|
||||||
|
|
||||||
// For each overlapping node in the list
|
|
||||||
for (uint i=0; i < overlappingNodes.size(); i++) {
|
|
||||||
|
|
||||||
if (referenceNodeId != overlappingNodes[i]) {
|
|
||||||
|
|
||||||
// Get the two collision shapes of the pair
|
|
||||||
ProxyShape* shape1 = static_cast<ProxyShape*>(mDynamicAABBTree.getNodeDataPointer(referenceNodeId));
|
|
||||||
ProxyShape* shape2 = static_cast<ProxyShape*>(mDynamicAABBTree.getNodeDataPointer(overlappingNodes[i]));
|
|
||||||
|
|
||||||
// If the two proxy collision shapes are from the same body, skip it
|
|
||||||
if (shape1->getBody()->getId() != shape2->getBody()->getId()) {
|
|
||||||
|
|
||||||
// Notify the collision detection about the overlapping pair
|
|
||||||
mCollisionDetection.broadPhaseNotifyOverlappingPair(shape1, shape2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when a overlapping node has been found during the call to
|
// Called when a overlapping node has been found during the call to
|
||||||
// DynamicAABBTree:reportAllShapesOverlappingWithAABB()
|
// DynamicAABBTree:reportAllShapesOverlappingWithAABB()
|
||||||
void AABBOverlapCallback::notifyOverlappingNode(int nodeId) {
|
void AABBOverlapCallback::notifyOverlappingNode(int nodeId) {
|
||||||
|
|
|
@ -182,14 +182,11 @@ class BroadPhaseSystem {
|
||||||
/// step and that need to be tested again for broad-phase overlapping.
|
/// step and that need to be tested again for broad-phase overlapping.
|
||||||
void removeMovedCollisionShape(int broadPhaseID);
|
void removeMovedCollisionShape(int broadPhaseID);
|
||||||
|
|
||||||
/// Add potential overlapping pairs in the dynamic AABB tree
|
|
||||||
void addOverlappingNodes(int broadPhaseId1, const List<int>& overlappingNodes);
|
|
||||||
|
|
||||||
/// Report all the shapes that are overlapping with a given AABB
|
/// Report all the shapes that are overlapping with a given AABB
|
||||||
void reportAllShapesOverlappingWithAABB(const AABB& aabb, List<int>& overlappingNodes) const;
|
void reportAllShapesOverlappingWithAABB(const AABB& aabb, List<int>& overlappingNodes) const;
|
||||||
|
|
||||||
/// Compute all the overlapping pairs of collision shapes
|
/// Compute all the overlapping pairs of collision shapes
|
||||||
void computeOverlappingPairs(MemoryManager& memoryManager);
|
void computeOverlappingPairs(MemoryManager& memoryManager, List<Pair<int, int> >& overlappingNodes);
|
||||||
|
|
||||||
/// Return the proxy shape corresponding to the broad-phase node id in parameter
|
/// Return the proxy shape corresponding to the broad-phase node id in parameter
|
||||||
ProxyShape* getProxyShapeForBroadPhaseId(int broadPhaseId) const;
|
ProxyShape* getProxyShapeForBroadPhaseId(int broadPhaseId) const;
|
||||||
|
@ -221,6 +218,8 @@ inline const AABB& BroadPhaseSystem::getFatAABB(int broadPhaseId) const {
|
||||||
// and that need to be tested again for broad-phase overlapping.
|
// and that need to be tested again for broad-phase overlapping.
|
||||||
inline void BroadPhaseSystem::addMovedCollisionShape(int broadPhaseID) {
|
inline void BroadPhaseSystem::addMovedCollisionShape(int broadPhaseID) {
|
||||||
|
|
||||||
|
assert(broadPhaseID != -1);
|
||||||
|
|
||||||
// Store the broad-phase ID into the array of shapes that have moved
|
// Store the broad-phase ID into the array of shapes that have moved
|
||||||
mMovedShapes.add(broadPhaseID);
|
mMovedShapes.add(broadPhaseID);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user