From db995ea52cad8c10a70174ae41e11f77113866e3 Mon Sep 17 00:00:00 2001 From: Daniel Chappuis Date: Sun, 4 Aug 2019 23:24:48 +0200 Subject: [PATCH] Do not use callbacks for middle-phase collision detection --- CMakeLists.txt | 2 - src/body/CollisionBody.cpp | 2 +- src/collision/CollisionDetection.cpp | 64 +++-- src/collision/ContactPointInfo.h | 10 +- src/collision/MiddlePhaseTriangleCallback.cpp | 59 ----- src/collision/MiddlePhaseTriangleCallback.h | 118 --------- src/collision/broadphase/DynamicAABBTree.cpp | 9 +- src/collision/broadphase/DynamicAABBTree.h | 2 +- src/collision/shapes/ConcaveMeshShape.cpp | 41 ++- src/collision/shapes/ConcaveMeshShape.h | 10 +- src/collision/shapes/ConcaveShape.h | 4 +- src/collision/shapes/HeightFieldShape.cpp | 127 +++++----- src/collision/shapes/HeightFieldShape.h | 55 +--- src/collision/shapes/TriangleShape.h | 1 + src/systems/BroadPhaseSystem.cpp | 22 +- src/systems/BroadPhaseSystem.h | 5 +- test/tests/collision/TestDynamicAABBTree.h | 236 ++++++++---------- 17 files changed, 286 insertions(+), 481 deletions(-) delete mode 100644 src/collision/MiddlePhaseTriangleCallback.cpp delete mode 100644 src/collision/MiddlePhaseTriangleCallback.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c0a8403..e5a12319 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -120,7 +120,6 @@ SET (REACTPHYSICS3D_HEADERS "src/collision/HalfEdgeStructure.h" "src/collision/CollisionDetection.h" "src/collision/ContactManifold.h" - "src/collision/MiddlePhaseTriangleCallback.h" "src/constraint/BallAndSocketJoint.h" "src/constraint/ContactPoint.h" "src/constraint/FixedJoint.h" @@ -213,7 +212,6 @@ SET (REACTPHYSICS3D_SOURCES "src/collision/HalfEdgeStructure.cpp" "src/collision/CollisionDetection.cpp" "src/collision/ContactManifold.cpp" - "src/collision/MiddlePhaseTriangleCallback.cpp" "src/constraint/BallAndSocketJoint.cpp" "src/constraint/ContactPoint.cpp" "src/constraint/FixedJoint.cpp" diff --git a/src/body/CollisionBody.cpp b/src/body/CollisionBody.cpp index 39dae6a4..b436ddb5 100644 --- a/src/body/CollisionBody.cpp +++ b/src/body/CollisionBody.cpp @@ -90,7 +90,7 @@ ProxyShape* CollisionBody::addCollisionShape(CollisionShape* collisionShape, con AABB(localBoundsMin, localBoundsMax), transform, collisionShape, decimal(1), 0x0001, 0xFFFF); bool isActive = mWorld.mCollisionBodyComponents.getIsActive(mEntity); - mWorld.mProxyShapesComponents.addComponent(proxyShapeEntity, isActive, proxyShapeComponent); + mWorld.mProxyShapesComponents.addComponent(proxyShapeEntity, !isActive, proxyShapeComponent); mWorld.mCollisionBodyComponents.addProxyShapeToBody(mEntity, proxyShapeEntity); diff --git a/src/collision/CollisionDetection.cpp b/src/collision/CollisionDetection.cpp index f4e911e8..a74010c4 100644 --- a/src/collision/CollisionDetection.cpp +++ b/src/collision/CollisionDetection.cpp @@ -34,7 +34,6 @@ #include "body/RigidBody.h" #include "configuration.h" #include "collision/CollisionCallback.h" -#include "collision/MiddlePhaseTriangleCallback.h" #include "collision/OverlapCallback.h" #include "collision/narrowphase/NarrowPhaseInfoBatch.h" #include "collision/ContactManifold.h" @@ -289,26 +288,28 @@ void CollisionDetection::computeMiddlePhase(OverlappingPairMap& overlappingPairs void CollisionDetection::computeConvexVsConcaveMiddlePhase(OverlappingPair* pair, MemoryAllocator& allocator, NarrowPhaseInput& narrowPhaseInput) { + RP3D_PROFILE("CollisionDetection::computeConvexVsConcaveMiddlePhase()", mProfiler); + ProxyShape* shape1 = pair->getShape1(); ProxyShape* shape2 = pair->getShape2(); ProxyShape* convexProxyShape; ProxyShape* concaveProxyShape; - const ConvexShape* convexShape; - const ConcaveShape* concaveShape; + ConvexShape* convexShape; + ConcaveShape* concaveShape; // Collision shape 1 is convex, collision shape 2 is concave if (shape1->getCollisionShape()->isConvex()) { convexProxyShape = shape1; - convexShape = static_cast(shape1->getCollisionShape()); + convexShape = static_cast(shape1->getCollisionShape()); concaveProxyShape = shape2; - concaveShape = static_cast(shape2->getCollisionShape()); + concaveShape = static_cast(shape2->getCollisionShape()); } else { // Collision shape 2 is convex, collision shape 1 is concave convexProxyShape = shape2; - convexShape = static_cast(shape2->getCollisionShape()); + convexShape = static_cast(shape2->getCollisionShape()); concaveProxyShape = shape1; - concaveShape = static_cast(shape1->getCollisionShape()); + concaveShape = static_cast(shape1->getCollisionShape()); } // Select the narrow phase algorithm to use according to the two collision shapes @@ -317,25 +318,48 @@ void CollisionDetection::computeConvexVsConcaveMiddlePhase(OverlappingPair* pair assert(algorithmType != NarrowPhaseAlgorithmType::None); - // Set the parameters of the callback object - MiddlePhaseTriangleCallback middlePhaseCallback(pair, concaveProxyShape, convexProxyShape, - concaveShape, narrowPhaseInput, algorithmType, allocator); - -#ifdef IS_PROFILING_ACTIVE - - // Set the profiler - middlePhaseCallback.setProfiler(mProfiler); - -#endif - // Compute the convex shape AABB in the local-space of the convex shape const Transform convexToConcaveTransform = concaveProxyShape->getLocalToWorldTransform().getInverse() * convexProxyShape->getLocalToWorldTransform(); AABB aabb; convexShape->computeAABB(aabb, convexToConcaveTransform); - // Call the convex vs triangle callback for each triangle of the concave shape - concaveShape->testAllTriangles(middlePhaseCallback, aabb); + // Compute the concave shape triangles that are overlapping with the convex mesh AABB + List triangleVertices(allocator); + List triangleVerticesNormals(allocator); + List shapeIds(allocator); + concaveShape->computeOverlappingTriangles(aabb, triangleVertices, triangleVerticesNormals, shapeIds, allocator); + + assert(triangleVertices.size() == triangleVerticesNormals.size()); + assert(shapeIds.size() == triangleVertices.size() / 3); + assert(triangleVertices.size() % 3 == 0); + assert(triangleVerticesNormals.size() % 3 == 0); + + // For each overlapping triangle + for (uint i=0; i < shapeIds.size(); i++) + { + // Create a triangle collision shape (the allocated memory for the TriangleShape will be released in the + // destructor of the corresponding NarrowPhaseInfo. + TriangleShape* triangleShape = new (allocator.allocate(sizeof(TriangleShape))) + TriangleShape(&(triangleVertices[i * 3]), &(triangleVerticesNormals[i * 3]), shapeIds[i], allocator); + + #ifdef IS_PROFILING_ACTIVE + + // Set the profiler to the triangle shape + triangleShape->setProfiler(mProfiler); + + #endif + + bool isShape1Convex = pair->getShape1()->getCollisionShape()->isConvex(); + ProxyShape* shape1 = isShape1Convex ? convexProxyShape : concaveProxyShape; + ProxyShape* shape2 = isShape1Convex ? concaveProxyShape : convexProxyShape; + + // Create a narrow phase info for the narrow-phase collision detection + narrowPhaseInput.addNarrowPhaseTest(pair, isShape1Convex ? convexShape : triangleShape, + isShape1Convex ? triangleShape : convexShape, + shape1->getLocalToWorldTransform(), shape2->getLocalToWorldTransform(), + algorithmType, allocator); + } } // Execute the narrow-phase collision detection algorithm on batches diff --git a/src/collision/ContactPointInfo.h b/src/collision/ContactPointInfo.h index 6e81783c..4957a77a 100644 --- a/src/collision/ContactPointInfo.h +++ b/src/collision/ContactPointInfo.h @@ -65,21 +65,13 @@ struct ContactPointInfo { /// Contact point of body 2 in local space of body 2 Vector3 localPoint2; - // TODO : Remove this field - /// Pointer to the next contact point info - ContactPointInfo* next; - - // TODO : Remove this field - /// True if the contact point has already been inserted into a manifold - bool isUsed; - // -------------------- Methods -------------------- // /// Constructor ContactPointInfo(const Vector3& contactNormal, decimal penDepth, const Vector3& localPt1, const Vector3& localPt2) : normal(contactNormal), penetrationDepth(penDepth), - localPoint1(localPt1), localPoint2(localPt2), next(nullptr), isUsed(false) { + localPoint1(localPt1), localPoint2(localPt2) { assert(contactNormal.lengthSquare() > decimal(0.8)); assert(penDepth > decimal(0.0)); diff --git a/src/collision/MiddlePhaseTriangleCallback.cpp b/src/collision/MiddlePhaseTriangleCallback.cpp deleted file mode 100644 index c363ef1b..00000000 --- a/src/collision/MiddlePhaseTriangleCallback.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************** -* ReactPhysics3D physics library, http://www.reactphysics3d.com * -* Copyright (c) 2010-2018 Daniel Chappuis * -********************************************************************************* -* * -* This software is provided 'as-is', without any express or implied warranty. * -* In no event will the authors be held liable for any damages arising from the * -* use of this software. * -* * -* Permission is granted to anyone to use this software for any purpose, * -* including commercial applications, and to alter it and redistribute it * -* freely, subject to the following restrictions: * -* * -* 1. The origin of this software must not be misrepresented; you must not claim * -* that you wrote the original software. If you use this software in a * -* product, an acknowledgment in the product documentation would be * -* appreciated but is not required. * -* * -* 2. Altered source versions must be plainly marked as such, and must not be * -* misrepresented as being the original software. * -* * -* 3. This notice may not be removed or altered from any source distribution. * -* * -********************************************************************************/ - -// Libraries -#include "collision/MiddlePhaseTriangleCallback.h" -#include "engine/OverlappingPair.h" -#include "collision/shapes/TriangleShape.h" -#include "collision/narrowphase/NarrowPhaseInput.h" - -using namespace reactphysics3d; - -// Report collision between a triangle of a concave shape and the convex mesh shape (for middle-phase) -void MiddlePhaseTriangleCallback::testTriangle(const Vector3* trianglePoints, const Vector3* verticesNormals, uint shapeId) { - - // Create a triangle collision shape (the allocated memory for the TriangleShape will be released in the - // destructor of the corresponding NarrowPhaseInfo. - TriangleShape* triangleShape = new (mAllocator.allocate(sizeof(TriangleShape))) - TriangleShape(trianglePoints, verticesNormals, shapeId, mAllocator); - -#ifdef IS_PROFILING_ACTIVE - - // Set the profiler to the triangle shape - triangleShape->setProfiler(mProfiler); - -#endif - - bool isShape1Convex = mOverlappingPair->getShape1()->getCollisionShape()->isConvex(); - ProxyShape* shape1 = isShape1Convex ? mConvexProxyShape : mConcaveProxyShape; - ProxyShape* shape2 = isShape1Convex ? mConcaveProxyShape : mConvexProxyShape; - - // Create a narrow phase info for the narrow-phase collision detection - mOutNarrowPhaseInput.addNarrowPhaseTest(mOverlappingPair, - isShape1Convex ? mConvexProxyShape->getCollisionShape() : triangleShape, - isShape1Convex ? triangleShape : mConvexProxyShape->getCollisionShape(), - shape1->getLocalToWorldTransform(), shape2->getLocalToWorldTransform(), - mNarrowPhaseAlgorithmType, mAllocator); -} diff --git a/src/collision/MiddlePhaseTriangleCallback.h b/src/collision/MiddlePhaseTriangleCallback.h deleted file mode 100644 index 1c417a60..00000000 --- a/src/collision/MiddlePhaseTriangleCallback.h +++ /dev/null @@ -1,118 +0,0 @@ -/******************************************************************************** -* ReactPhysics3D physics library, http://www.reactphysics3d.com * -* Copyright (c) 2010-2018 Daniel Chappuis * -********************************************************************************* -* * -* This software is provided 'as-is', without any express or implied warranty. * -* In no event will the authors be held liable for any damages arising from the * -* use of this software. * -* * -* Permission is granted to anyone to use this software for any purpose, * -* including commercial applications, and to alter it and redistribute it * -* freely, subject to the following restrictions: * -* * -* 1. The origin of this software must not be misrepresented; you must not claim * -* that you wrote the original software. If you use this software in a * -* product, an acknowledgment in the product documentation would be * -* appreciated but is not required. * -* * -* 2. Altered source versions must be plainly marked as such, and must not be * -* misrepresented as being the original software. * -* * -* 3. This notice may not be removed or altered from any source distribution. * -* * -********************************************************************************/ - -#ifndef REACTPHYSICS3D_MIDDLE_PHASE_TRIANGLE_CALLBACK_H -#define REACTPHYSICS3D_MIDDLE_PHASE_TRIANGLE_CALLBACK_H - -#include "configuration.h" -#include "collision/shapes/ConcaveShape.h" - -/// Namespace ReactPhysics3D -namespace reactphysics3d { - -// Libraries - -// Declarations -class ConcaveShape; -class OverlappingPair; -class NarrowPhaseAlgorithm; -class ProxyShape; -class MemoryAllocator; -class Profiler; -class NarrowPhaseInput; -enum class NarrowPhaseAlgorithmType; -struct Vector3; - -// Class ConvexVsTriangleCallback -/** - * This class is used to report a collision between the triangle - * of a concave mesh shape and a convex shape during the - * middle-phase algorithm. - */ -class MiddlePhaseTriangleCallback : public TriangleCallback { - - protected: - - /// Broadphase overlapping pair - OverlappingPair* mOverlappingPair; - - /// Pointer to the concave proxy shape - ProxyShape* mConcaveProxyShape; - - /// Pointer to the convex proxy shape - ProxyShape* mConvexProxyShape; - - /// Pointer to the concave collision shape - const ConcaveShape* mConcaveShape; - - /// Reference to the narrow phase input - NarrowPhaseInput& mOutNarrowPhaseInput; - - /// Type of narrow-phase algorithm to use - NarrowPhaseAlgorithmType mNarrowPhaseAlgorithmType; - - /// Reference to the single-frame memory allocator - MemoryAllocator& mAllocator; - -#ifdef IS_PROFILING_ACTIVE - - /// Pointer to the profiler - Profiler* mProfiler; - -#endif - - public: - - /// Constructor - MiddlePhaseTriangleCallback(OverlappingPair* overlappingPair, - ProxyShape* concaveProxyShape, - ProxyShape* convexProxyShape, const ConcaveShape* concaveShape, - NarrowPhaseInput& outNarrowPhaseInput, - NarrowPhaseAlgorithmType algorithmType, - MemoryAllocator& allocator) - :mOverlappingPair(overlappingPair), mConcaveProxyShape(concaveProxyShape), - mConvexProxyShape(convexProxyShape), mConcaveShape(concaveShape), - mOutNarrowPhaseInput(outNarrowPhaseInput), mNarrowPhaseAlgorithmType(algorithmType), - mAllocator(allocator) { - - } - - /// Test collision between a triangle and the convex mesh shape - virtual void testTriangle(const Vector3* trianglePoints, const Vector3* verticesNormals, uint shapeId) override; - -#ifdef IS_PROFILING_ACTIVE - - /// Set the profiler - void setProfiler(Profiler* profiler) { - mProfiler = profiler; - } - -#endif - -}; - -} - -#endif diff --git a/src/collision/broadphase/DynamicAABBTree.cpp b/src/collision/broadphase/DynamicAABBTree.cpp index dbf09e3b..82dc16e9 100644 --- a/src/collision/broadphase/DynamicAABBTree.cpp +++ b/src/collision/broadphase/DynamicAABBTree.cpp @@ -642,9 +642,8 @@ void DynamicAABBTree::reportAllShapesOverlappingWithShapes(const List& node } } -/// 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 { +// Report all shapes overlapping with the AABB given in parameter. +void DynamicAABBTree::reportAllShapesOverlappingWithAABB(const AABB& aabb, List& overlappingNodes) const { // Create a stack with the nodes to visit Stack stack(mAllocator, 64); @@ -669,7 +668,7 @@ void DynamicAABBTree::reportAllShapesOverlappingWithAABB(const AABB& aabb, Dynam if (nodeToVisit->isLeaf()) { // Notify the broad-phase about a new potential overlapping pair - callback.notifyOverlappingNode(nodeIDToVisit); + overlappingNodes.add(nodeIDToVisit); } else { // If the node is not a leaf @@ -682,7 +681,7 @@ void DynamicAABBTree::reportAllShapesOverlappingWithAABB(const AABB& aabb, Dynam } // Ray casting method -void DynamicAABBTree::raycast(const Ray& ray, DynamicAABBTreeRaycastCallback &callback) const { +void DynamicAABBTree::raycast(const Ray& ray, DynamicAABBTreeRaycastCallback& callback) const { RP3D_PROFILE("DynamicAABBTree::raycast()", mProfiler); diff --git a/src/collision/broadphase/DynamicAABBTree.h b/src/collision/broadphase/DynamicAABBTree.h index 8a09a1db..0bc16e8e 100644 --- a/src/collision/broadphase/DynamicAABBTree.h +++ b/src/collision/broadphase/DynamicAABBTree.h @@ -242,7 +242,7 @@ class DynamicAABBTree { size_t endIndex, List>& outOverlappingNodes) const; /// Report all shapes overlapping with the AABB given in parameter. - void reportAllShapesOverlappingWithAABB(const AABB& aabb, DynamicAABBTreeOverlapCallback& callback) const; + void reportAllShapesOverlappingWithAABB(const AABB& aabb, List& overlappingNodes) const; /// Ray casting method void raycast(const Ray& ray, DynamicAABBTreeRaycastCallback& callback) const; diff --git a/src/collision/shapes/ConcaveMeshShape.cpp b/src/collision/shapes/ConcaveMeshShape.cpp index 42d7ddd1..bf5d2eeb 100644 --- a/src/collision/shapes/ConcaveMeshShape.cpp +++ b/src/collision/shapes/ConcaveMeshShape.cpp @@ -84,8 +84,7 @@ void ConcaveMeshShape::initBVHTree() { } // Return the three vertices coordinates (in the array outTriangleVertices) of a triangle -void ConcaveMeshShape::getTriangleVertices(uint subPart, uint triangleIndex, - Vector3* outTriangleVertices) const { +void ConcaveMeshShape::getTriangleVertices(uint subPart, uint triangleIndex, Vector3* outTriangleVertices) const { // Get the triangle vertex array of the current sub-part TriangleVertexArray* triangleVertexArray = mTriangleMesh->getSubpart(subPart); @@ -116,14 +115,40 @@ void ConcaveMeshShape::getTriangleVerticesNormals(uint subPart, uint triangleInd } -// Use a callback method on all triangles of the concave shape inside a given AABB -void ConcaveMeshShape::testAllTriangles(TriangleCallback& callback, const AABB& localAABB) const { +// Compute all the triangles of the mesh that are overlapping with the AABB in parameter +void ConcaveMeshShape::computeOverlappingTriangles(const AABB& localAABB, List& triangleVertices, + List& triangleVerticesNormals, List& shapeIds, + MemoryAllocator& allocator) const { - ConvexTriangleAABBOverlapCallback overlapCallback(callback, *this, mDynamicAABBTree); + // Compute the nodes of the internal AABB tree that are overlapping with the AABB + List overlappingNodes(allocator); + mDynamicAABBTree.reportAllShapesOverlappingWithAABB(localAABB, overlappingNodes); - // Ask the Dynamic AABB Tree to report all the triangles that are overlapping - // with the AABB of the convex shape. - mDynamicAABBTree.reportAllShapesOverlappingWithAABB(localAABB, overlapCallback); + // For each overlapping node + for (uint i=0; i < overlappingNodes.size(); i++) { + + int nodeId = overlappingNodes[i]; + + // Get the node data (triangle index and mesh subpart index) + int32* data = mDynamicAABBTree.getNodeDataInt(nodeId); + + // Get the triangle vertices for this node from the concave mesh shape + Vector3 trianglePoints[3]; + getTriangleVertices(data[0], data[1], trianglePoints); + triangleVertices.add(trianglePoints[0]); + triangleVertices.add(trianglePoints[1]); + triangleVertices.add(trianglePoints[2]); + + // Get the vertices normals of the triangle + Vector3 verticesNormals[3]; + getTriangleVerticesNormals(data[0], data[1], verticesNormals); + triangleVerticesNormals.add(verticesNormals[0]); + triangleVerticesNormals.add(verticesNormals[1]); + triangleVerticesNormals.add(verticesNormals[2]); + + // Compute the triangle shape ID + shapeIds.add(computeTriangleShapeId(data[0], data[1])); + } } // Raycast method with feedback information diff --git a/src/collision/shapes/ConcaveMeshShape.h b/src/collision/shapes/ConcaveMeshShape.h index d5353d6f..27276bcb 100644 --- a/src/collision/shapes/ConcaveMeshShape.h +++ b/src/collision/shapes/ConcaveMeshShape.h @@ -155,7 +155,7 @@ class ConcaveMeshShape : public ConcaveShape { /// Insert all the triangles into the dynamic AABB tree void initBVHTree(); - /// Return the three vertices coordinates (in the array outTriangleVertices) of a triangle + /// Return the three vertices coordinates (in the list outTriangleVertices) of a triangle void getTriangleVertices(uint subPart, uint triangleIndex, Vector3* outTriangleVertices) const; /// Return the three vertex normals (in the array outVerticesNormals) of a triangle @@ -164,6 +164,11 @@ class ConcaveMeshShape : public ConcaveShape { /// Compute the shape Id for a given triangle of the mesh uint computeTriangleShapeId(uint subPart, uint triangleIndex) const; + /// Compute all the triangles of the mesh that are overlapping with the AABB in parameter + virtual void computeOverlappingTriangles(const AABB& localAABB, List &triangleVertices, + List &triangleVerticesNormals, List& shapeIds, + MemoryAllocator& allocator) const override; + public: /// Constructor @@ -187,9 +192,6 @@ class ConcaveMeshShape : public ConcaveShape { /// Return the local inertia tensor of the collision shape virtual void computeLocalInertiaTensor(Matrix3x3& tensor, decimal mass) const override; - /// Use a callback method on all triangles of the concave shape inside a given AABB - virtual void testAllTriangles(TriangleCallback& callback, const AABB& localAABB) const override; - /// Return the string representation of the shape virtual std::string to_string() const override; diff --git a/src/collision/shapes/ConcaveShape.h b/src/collision/shapes/ConcaveShape.h index 705d454f..aeae3764 100644 --- a/src/collision/shapes/ConcaveShape.h +++ b/src/collision/shapes/ConcaveShape.h @@ -99,7 +99,9 @@ class ConcaveShape : public CollisionShape { virtual bool isPolyhedron() const override; /// Use a callback method on all triangles of the concave shape inside a given AABB - virtual void testAllTriangles(TriangleCallback& callback, const AABB& localAABB) const=0; + virtual void computeOverlappingTriangles(const AABB& localAABB, List& triangleVertices, + List& triangleVerticesNormals, List& shapeIds, + MemoryAllocator& allocator) const=0; }; // Return true if the collision shape is convex, false if it is concave diff --git a/src/collision/shapes/HeightFieldShape.cpp b/src/collision/shapes/HeightFieldShape.cpp index 0a341f81..7662bb1e 100644 --- a/src/collision/shapes/HeightFieldShape.cpp +++ b/src/collision/shapes/HeightFieldShape.cpp @@ -91,7 +91,9 @@ void HeightFieldShape::getLocalBounds(Vector3& min, Vector3& max) const { // of the body when need to test and see against which triangles of the height-field we need // to test for collision. We compute the sub-grid points that are inside the other body's AABB // and then for each rectangle in the sub-grid we generate two triangles that we use to test collision. -void HeightFieldShape::testAllTriangles(TriangleCallback& callback, const AABB& localAABB) const { +void HeightFieldShape::computeOverlappingTriangles(const AABB& localAABB, List& triangleVertices, + List& triangleVerticesNormals, List& shapeIds, + MemoryAllocator& allocator) const { // Compute the non-scaled AABB Vector3 inverseScaling(decimal(1.0) / mScaling.x, decimal(1.0) / mScaling.y, decimal(1.0) / mScaling.z); @@ -141,7 +143,9 @@ void HeightFieldShape::testAllTriangles(TriangleCallback& callback, const AABB& const Vector3 p4 = getVertexAt(i + 1, j + 1); // Generate the first triangle for the current grid rectangle - Vector3 trianglePoints[3] = {p1, p2, p3}; + triangleVertices.add(p1); + triangleVertices.add(p2); + triangleVertices.add(p3); // Compute the triangle normal Vector3 triangle1Normal = (p2 - p1).cross(p3 - p1).getUnit(); @@ -153,15 +157,17 @@ void HeightFieldShape::testAllTriangles(TriangleCallback& callback, const AABB& // and compute the angle of incident edges with asin(). Maybe we could also precompute the // vertices normal at the HeightFieldShape constructor but it will require extra memory to // store them. - Vector3 verticesNormals1[3] = {triangle1Normal, triangle1Normal, triangle1Normal}; + triangleVerticesNormals.add(triangle1Normal); + triangleVerticesNormals.add(triangle1Normal); + triangleVerticesNormals.add(triangle1Normal); - // Test collision against the first triangle - callback.testTriangle(trianglePoints, verticesNormals1, computeTriangleShapeId(i, j, 0)); + // Compute the shape ID + shapeIds.add(computeTriangleShapeId(i, j, 0)); // Generate the second triangle for the current grid rectangle - trianglePoints[0] = p3; - trianglePoints[1] = p2; - trianglePoints[2] = p4; + triangleVertices.add(p3); + triangleVertices.add(p2); + triangleVertices.add(p4); // Compute the triangle normal Vector3 triangle2Normal = (p2 - p3).cross(p4 - p3).getUnit(); @@ -173,10 +179,12 @@ void HeightFieldShape::testAllTriangles(TriangleCallback& callback, const AABB& // and compute the angle of incident edges with asin(). Maybe we could also precompute the // vertices normal at the HeightFieldShape constructor but it will require extra memory to // store them. - Vector3 verticesNormals2[3] = {triangle2Normal, triangle2Normal, triangle2Normal}; + triangleVerticesNormals.add(triangle2Normal); + triangleVerticesNormals.add(triangle2Normal); + triangleVerticesNormals.add(triangle2Normal); - // Test collision against the second triangle - callback.testTriangle(trianglePoints, verticesNormals2, computeTriangleShapeId(i, j, 1)); + // Compute the shape ID + shapeIds.add(computeTriangleShapeId(i, j, 1)); } } } @@ -221,22 +229,61 @@ bool HeightFieldShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxySh RP3D_PROFILE("HeightFieldShape::raycast()", mProfiler); - TriangleOverlapCallback triangleCallback(ray, proxyShape, raycastInfo, *this, allocator); - -#ifdef IS_PROFILING_ACTIVE - - // Set the profiler - triangleCallback.setProfiler(mProfiler); - -#endif - // Compute the AABB for the ray const Vector3 rayEnd = ray.point1 + ray.maxFraction * (ray.point2 - ray.point1); const AABB rayAABB(Vector3::min(ray.point1, rayEnd), Vector3::max(ray.point1, rayEnd)); - testAllTriangles(triangleCallback, rayAABB); + // Compute the triangles overlapping with the ray AABB + List triangleVertices(allocator); + List triangleVerticesNormals(allocator); + List shapeIds(allocator); + computeOverlappingTriangles(rayAABB, triangleVertices, triangleVerticesNormals, shapeIds, allocator); - return triangleCallback.getIsHit(); + assert(triangleVertices.size() == triangleVerticesNormals.size()); + assert(shapeIds.size() == triangleVertices.size() / 3); + assert(triangleVertices.size() % 3 == 0); + assert(triangleVerticesNormals.size() % 3 == 0); + + bool isHit = false; + decimal smallestHitFraction = ray.maxFraction; + + // For each overlapping triangle + for (uint i=0; i < shapeIds.size(); i++) + { + // Create a triangle collision shape + TriangleShape triangleShape(&(triangleVertices[i * 3]), &(triangleVerticesNormals[i * 3]), shapeIds[i], allocator); + triangleShape.setRaycastTestType(getRaycastTestType()); + + #ifdef IS_PROFILING_ACTIVE + + // Set the profiler to the triangle shape + triangleShape.setProfiler(mProfiler); + + #endif + + // Ray casting test against the collision shape + RaycastInfo triangleRaycastInfo; + bool isTriangleHit = triangleShape.raycast(ray, triangleRaycastInfo, proxyShape, allocator); + + // If the ray hit the collision shape + if (isTriangleHit && triangleRaycastInfo.hitFraction <= smallestHitFraction) { + + assert(triangleRaycastInfo.hitFraction >= decimal(0.0)); + + raycastInfo.body = triangleRaycastInfo.body; + raycastInfo.proxyShape = triangleRaycastInfo.proxyShape; + raycastInfo.hitFraction = triangleRaycastInfo.hitFraction; + raycastInfo.worldPoint = triangleRaycastInfo.worldPoint; + raycastInfo.worldNormal = triangleRaycastInfo.worldNormal; + raycastInfo.meshSubpart = -1; + raycastInfo.triangleIndex = -1; + + smallestHitFraction = triangleRaycastInfo.hitFraction; + isHit = true; + } + } + + return isHit; } // Return the vertex (local-coordinates) of the height field at a given (x,y) position @@ -264,42 +311,6 @@ Vector3 HeightFieldShape::getVertexAt(int x, int y) const { return vertex * mScaling; } -// Raycast test between a ray and a triangle of the heightfield -void TriangleOverlapCallback::testTriangle(const Vector3* trianglePoints, const Vector3* verticesNormals, uint shapeId) { - - // Create a triangle collision shape - TriangleShape triangleShape(trianglePoints, verticesNormals, shapeId, mAllocator); - triangleShape.setRaycastTestType(mHeightFieldShape.getRaycastTestType()); - -#ifdef IS_PROFILING_ACTIVE - - // Set the profiler to the triangle shape - triangleShape.setProfiler(mProfiler); - -#endif - - // Ray casting test against the collision shape - RaycastInfo raycastInfo; - bool isTriangleHit = triangleShape.raycast(mRay, raycastInfo, mProxyShape, mAllocator); - - // If the ray hit the collision shape - if (isTriangleHit && raycastInfo.hitFraction <= mSmallestHitFraction) { - - assert(raycastInfo.hitFraction >= decimal(0.0)); - - mRaycastInfo.body = raycastInfo.body; - mRaycastInfo.proxyShape = raycastInfo.proxyShape; - mRaycastInfo.hitFraction = raycastInfo.hitFraction; - mRaycastInfo.worldPoint = raycastInfo.worldPoint; - mRaycastInfo.worldNormal = raycastInfo.worldNormal; - mRaycastInfo.meshSubpart = -1; - mRaycastInfo.triangleIndex = -1; - - mSmallestHitFraction = raycastInfo.hitFraction; - mIsHit = true; - } -} - // Return the string representation of the shape std::string HeightFieldShape::to_string() const { diff --git a/src/collision/shapes/HeightFieldShape.h b/src/collision/shapes/HeightFieldShape.h index d8149a9e..142165a5 100644 --- a/src/collision/shapes/HeightFieldShape.h +++ b/src/collision/shapes/HeightFieldShape.h @@ -36,57 +36,6 @@ class HeightFieldShape; class Profiler; class TriangleShape; -// Class TriangleOverlapCallback -/** - * This class is used for testing AABB and triangle overlap for raycasting - */ -class TriangleOverlapCallback : public TriangleCallback { - - protected: - - const Ray& mRay; - ProxyShape* mProxyShape; - RaycastInfo& mRaycastInfo; - bool mIsHit; - decimal mSmallestHitFraction; - const HeightFieldShape& mHeightFieldShape; - MemoryAllocator& mAllocator; - -#ifdef IS_PROFILING_ACTIVE - - /// Pointer to the profiler - Profiler* mProfiler; - -#endif - - public: - - // Constructor - TriangleOverlapCallback(const Ray& ray, ProxyShape* proxyShape, RaycastInfo& raycastInfo, - const HeightFieldShape& heightFieldShape, MemoryAllocator& allocator) - : mRay(ray), mProxyShape(proxyShape), mRaycastInfo(raycastInfo), - mHeightFieldShape (heightFieldShape), mAllocator(allocator) { - mIsHit = false; - mSmallestHitFraction = mRay.maxFraction; - } - - bool getIsHit() const {return mIsHit;} - - /// Raycast test between a ray and a triangle of the heightfield - virtual void testTriangle(const Vector3* trianglePoints, const Vector3* verticesNormals, uint shapeId) override; - -#ifdef IS_PROFILING_ACTIVE - - /// Set the profiler - void setProfiler(Profiler* profiler) { - mProfiler = profiler; - } - -#endif - -}; - - // Class HeightFieldShape /** * This class represents a static height field that can be used to represent @@ -212,7 +161,9 @@ class HeightFieldShape : public ConcaveShape { virtual void computeLocalInertiaTensor(Matrix3x3& tensor, decimal mass) const override; /// Use a callback method on all triangles of the concave shape inside a given AABB - virtual void testAllTriangles(TriangleCallback& callback, const AABB& localAABB) const override; + virtual void computeOverlappingTriangles(const AABB& localAABB, List& triangleVertices, + List& triangleVerticesNormals, List& shapeIds, + MemoryAllocator& allocator) const override; /// Return the string representation of the shape virtual std::string to_string() const override; diff --git a/src/collision/shapes/TriangleShape.h b/src/collision/shapes/TriangleShape.h index 4c69edaf..a9f51839 100644 --- a/src/collision/shapes/TriangleShape.h +++ b/src/collision/shapes/TriangleShape.h @@ -180,6 +180,7 @@ class TriangleShape : public ConvexPolyhedronShape { friend class ConcaveMeshRaycastCallback; friend class TriangleOverlapCallback; friend class MiddlePhaseTriangleCallback; + friend class HeightFieldShape; }; // Return the number of bytes used by the collision shape diff --git a/src/systems/BroadPhaseSystem.cpp b/src/systems/BroadPhaseSystem.cpp index e9374b0a..e8cddde7 100644 --- a/src/systems/BroadPhaseSystem.cpp +++ b/src/systems/BroadPhaseSystem.cpp @@ -117,7 +117,7 @@ void BroadPhaseSystem::updateProxyShape(Entity proxyShapeEntity) { uint32 index = mProxyShapesComponents.mMapEntityToComponentIndex[proxyShapeEntity]; // Update the proxy-shape component - updateProxyShapesComponents(index, index + 1); + updateProxyShapesComponents(index, 1); } // Update the broad-phase state of all the enabled proxy-shapes @@ -146,15 +146,17 @@ void BroadPhaseSystem::updateProxyShapeInternal(int broadPhaseId, const AABB& aa } // Update the broad-phase state of some proxy-shapes components -void BroadPhaseSystem::updateProxyShapesComponents(uint32 startIndex, uint32 endIndex) { +void BroadPhaseSystem::updateProxyShapesComponents(uint32 startIndex, uint32 nbItems) { - assert(startIndex <= endIndex); + assert(nbItems > 0); assert(startIndex < mProxyShapesComponents.getNbComponents()); - assert(endIndex <= mProxyShapesComponents.getNbComponents()); + assert(startIndex + nbItems <= mProxyShapesComponents.getNbComponents()); // Make sure we do not update disabled components startIndex = std::min(startIndex, mProxyShapesComponents.getNbEnabledComponents()); - endIndex = std::min(endIndex, mProxyShapesComponents.getNbEnabledComponents()); + uint32 endIndex = std::min(startIndex + nbItems, mProxyShapesComponents.getNbEnabledComponents()); + nbItems = endIndex - startIndex; + assert(nbItems >= 0); // Get the time step if we are in a dynamics world DynamicsWorld* dynamicsWorld = dynamic_cast(mCollisionDetection.getWorld()); @@ -164,7 +166,7 @@ void BroadPhaseSystem::updateProxyShapesComponents(uint32 startIndex, uint32 end } // For each proxy-shape component to update - for (uint32 i = startIndex; i < endIndex; i++) { + for (uint32 i = startIndex; i < startIndex + nbItems; i++) { const int broadPhaseId = mProxyShapesComponents.mBroadPhaseIds[i]; if (broadPhaseId != -1) { @@ -193,14 +195,6 @@ void BroadPhaseSystem::updateProxyShapesComponents(uint32 startIndex, uint32 end } } -void BroadPhaseSystem::reportAllShapesOverlappingWithAABB(const AABB& aabb, List& overlappingNodes) const { - - AABBOverlapCallback callback(overlappingNodes); - - // Ask the dynamic AABB tree to report all collision shapes that overlap with this AABB - mDynamicAABBTree.reportAllShapesOverlappingWithAABB(aabb, callback); -} - // Compute all the overlapping pairs of collision shapes void BroadPhaseSystem::computeOverlappingPairs(MemoryManager& memoryManager, List>& overlappingNodes) { diff --git a/src/systems/BroadPhaseSystem.h b/src/systems/BroadPhaseSystem.h index abcc7490..62484033 100644 --- a/src/systems/BroadPhaseSystem.h +++ b/src/systems/BroadPhaseSystem.h @@ -143,7 +143,7 @@ class BroadPhaseSystem { void updateProxyShapeInternal(int broadPhaseId, const AABB& aabb, const Vector3& displacement); /// Update the broad-phase state of some proxy-shapes components - void updateProxyShapesComponents(uint32 startIndex, uint32 endIndex); + void updateProxyShapesComponents(uint32 startIndex, uint32 nbItems); public : @@ -182,9 +182,6 @@ class BroadPhaseSystem { /// step and that need to be tested again for broad-phase overlapping. void removeMovedCollisionShape(int broadPhaseID); - /// Report all the shapes that are overlapping with a given AABB - void reportAllShapesOverlappingWithAABB(const AABB& aabb, List& overlappingNodes) const; - /// Compute all the overlapping pairs of collision shapes void computeOverlappingPairs(MemoryManager& memoryManager, List>& overlappingNodes); diff --git a/test/tests/collision/TestDynamicAABBTree.h b/test/tests/collision/TestDynamicAABBTree.h index dd453bd4..5e5033b7 100755 --- a/test/tests/collision/TestDynamicAABBTree.h +++ b/test/tests/collision/TestDynamicAABBTree.h @@ -31,32 +31,11 @@ #include "collision/broadphase/DynamicAABBTree.h" #include "memory/MemoryManager.h" #include "utils/Profiler.h" +#include /// Reactphysics3D namespace namespace reactphysics3d { -class TestOverlapCallback : public DynamicAABBTreeOverlapCallback { - - public : - - // TODO : Replace this by rp3d::List - std::vector mOverlapNodes; - - // Called when a overlapping node has been found during the call to - // DynamicAABBTree:reportAllShapesOverlappingWithAABB() - virtual void notifyOverlappingNode(int nodeId) override { - mOverlapNodes.push_back(nodeId); - } - - void reset() { - mOverlapNodes.clear(); - } - - bool isOverlapping(int nodeId) const { - return std::find(mOverlapNodes.begin(), mOverlapNodes.end(), nodeId) != mOverlapNodes.end(); - } -}; - class DynamicTreeRaycastCallback : public DynamicAABBTreeRaycastCallback { public: @@ -78,6 +57,7 @@ class DynamicTreeRaycastCallback : public DynamicAABBTreeRaycastCallback { } }; + // Class TestDynamicAABBTree /** * Unit test for the dynamic AABB tree @@ -88,8 +68,8 @@ class TestDynamicAABBTree : public Test { // ---------- Atributes ---------- // - TestOverlapCallback mOverlapCallback; DynamicTreeRaycastCallback mRaycastCallback; + PoolAllocator mAllocator; public : @@ -101,6 +81,10 @@ class TestDynamicAABBTree : public Test { } + bool isOverlapping(int nodeId, const List& overlappingNodes) const { + return std::find(overlappingNodes.begin(), overlappingNodes.end(), nodeId) != overlappingNodes.end(); + } + /// Run the tests void run() { @@ -202,45 +186,47 @@ class TestDynamicAABBTree : public Test { // ---------- Tests ---------- // + List overlappingNodes(mAllocator); + // AABB overlapping nothing - mOverlapCallback.reset(); - tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-10, 12, -4), Vector3(10, 50, 4)), mOverlapCallback); - rp3d_test(!mOverlapCallback.isOverlapping(object1Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object2Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object3Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object4Id)); + overlappingNodes.clear(); + tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-10, 12, -4), Vector3(10, 50, 4)), overlappingNodes); + rp3d_test(!isOverlapping(object1Id, overlappingNodes)); + rp3d_test(!isOverlapping(object2Id, overlappingNodes)); + rp3d_test(!isOverlapping(object3Id, overlappingNodes)); + rp3d_test(!isOverlapping(object4Id, overlappingNodes)); // AABB overlapping everything - mOverlapCallback.reset(); - tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-15, -15, -4), Vector3(15, 15, 4)), mOverlapCallback); - rp3d_test(mOverlapCallback.isOverlapping(object1Id)); - rp3d_test(mOverlapCallback.isOverlapping(object2Id)); - rp3d_test(mOverlapCallback.isOverlapping(object3Id)); - rp3d_test(mOverlapCallback.isOverlapping(object4Id)); + overlappingNodes.clear(); + tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-15, -15, -4), Vector3(15, 15, 4)), overlappingNodes); + rp3d_test(isOverlapping(object1Id, overlappingNodes)); + rp3d_test(isOverlapping(object2Id, overlappingNodes)); + rp3d_test(isOverlapping(object3Id, overlappingNodes)); + rp3d_test(isOverlapping(object4Id, overlappingNodes)); // AABB overlapping object 1 and 3 - mOverlapCallback.reset(); - tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-4, 2, -4), Vector3(-1, 7, 4)), mOverlapCallback); - rp3d_test(mOverlapCallback.isOverlapping(object1Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object2Id)); - rp3d_test(mOverlapCallback.isOverlapping(object3Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object4Id)); + overlappingNodes.clear(); + tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-4, 2, -4), Vector3(-1, 7, 4)), overlappingNodes); + rp3d_test(isOverlapping(object1Id, overlappingNodes)); + rp3d_test(!isOverlapping(object2Id, overlappingNodes)); + rp3d_test(isOverlapping(object3Id, overlappingNodes)); + rp3d_test(!isOverlapping(object4Id, overlappingNodes)); // AABB overlapping object 3 and 4 - mOverlapCallback.reset(); - tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-6, -5, -2), Vector3(2, 2, 0)), mOverlapCallback); - rp3d_test(!mOverlapCallback.isOverlapping(object1Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object2Id)); - rp3d_test(mOverlapCallback.isOverlapping(object3Id)); - rp3d_test(mOverlapCallback.isOverlapping(object4Id)); + overlappingNodes.clear(); + tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-6, -5, -2), Vector3(2, 2, 0)), overlappingNodes); + rp3d_test(!isOverlapping(object1Id, overlappingNodes)); + rp3d_test(!isOverlapping(object2Id, overlappingNodes)); + rp3d_test(isOverlapping(object3Id, overlappingNodes)); + rp3d_test(isOverlapping(object4Id, overlappingNodes)); // AABB overlapping object 2 - mOverlapCallback.reset(); - tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(5, -10, -2), Vector3(7, 10, 9)), mOverlapCallback); - rp3d_test(!mOverlapCallback.isOverlapping(object1Id)); - rp3d_test(mOverlapCallback.isOverlapping(object2Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object3Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object4Id)); + overlappingNodes.clear(); + tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(5, -10, -2), Vector3(7, 10, 9)), overlappingNodes); + rp3d_test(!isOverlapping(object1Id, overlappingNodes)); + rp3d_test(isOverlapping(object2Id, overlappingNodes)); + rp3d_test(!isOverlapping(object3Id, overlappingNodes)); + rp3d_test(!isOverlapping(object4Id, overlappingNodes)); // ---- Update the object AABBs with the initial AABBs (no reinsertion) ----- // @@ -250,44 +236,44 @@ class TestDynamicAABBTree : public Test { tree.updateObject(object4Id, aabb4, Vector3::zero()); // AABB overlapping nothing - mOverlapCallback.reset(); - tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-10, 12, -4), Vector3(10, 50, 4)), mOverlapCallback); - rp3d_test(!mOverlapCallback.isOverlapping(object1Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object2Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object3Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object4Id)); + overlappingNodes.clear(); + tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-10, 12, -4), Vector3(10, 50, 4)), overlappingNodes); + rp3d_test(!isOverlapping(object1Id, overlappingNodes)); + rp3d_test(!isOverlapping(object2Id, overlappingNodes)); + rp3d_test(!isOverlapping(object3Id, overlappingNodes)); + rp3d_test(!isOverlapping(object4Id, overlappingNodes)); // AABB overlapping everything - mOverlapCallback.reset(); - tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-15, -15, -4), Vector3(15, 15, 4)), mOverlapCallback); - rp3d_test(mOverlapCallback.isOverlapping(object1Id)); - rp3d_test(mOverlapCallback.isOverlapping(object2Id)); - rp3d_test(mOverlapCallback.isOverlapping(object3Id)); - rp3d_test(mOverlapCallback.isOverlapping(object4Id)); + overlappingNodes.clear(); + tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-15, -15, -4), Vector3(15, 15, 4)), overlappingNodes); + rp3d_test(isOverlapping(object1Id, overlappingNodes)); + rp3d_test(isOverlapping(object2Id, overlappingNodes)); + rp3d_test(isOverlapping(object3Id, overlappingNodes)); + rp3d_test(isOverlapping(object4Id, overlappingNodes)); // AABB overlapping object 1 and 3 - mOverlapCallback.reset(); - tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-4, 2, -4), Vector3(-1, 7, 4)), mOverlapCallback); - rp3d_test(mOverlapCallback.isOverlapping(object1Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object2Id)); - rp3d_test(mOverlapCallback.isOverlapping(object3Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object4Id)); + overlappingNodes.clear(); + tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-4, 2, -4), Vector3(-1, 7, 4)), overlappingNodes); + rp3d_test(isOverlapping(object1Id, overlappingNodes)); + rp3d_test(!isOverlapping(object2Id, overlappingNodes)); + rp3d_test(isOverlapping(object3Id, overlappingNodes)); + rp3d_test(!isOverlapping(object4Id, overlappingNodes)); // AABB overlapping object 3 and 4 - mOverlapCallback.reset(); - tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-6, -5, -2), Vector3(2, 2, 0)), mOverlapCallback); - rp3d_test(!mOverlapCallback.isOverlapping(object1Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object2Id)); - rp3d_test(mOverlapCallback.isOverlapping(object3Id)); - rp3d_test(mOverlapCallback.isOverlapping(object4Id)); + overlappingNodes.clear(); + tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-6, -5, -2), Vector3(2, 2, 0)), overlappingNodes); + rp3d_test(!isOverlapping(object1Id, overlappingNodes)); + rp3d_test(!isOverlapping(object2Id, overlappingNodes)); + rp3d_test(isOverlapping(object3Id, overlappingNodes)); + rp3d_test(isOverlapping(object4Id, overlappingNodes)); // AABB overlapping object 2 - mOverlapCallback.reset(); - tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(5, -10, -2), Vector3(7, 10, 9)), mOverlapCallback); - rp3d_test(!mOverlapCallback.isOverlapping(object1Id)); - rp3d_test(mOverlapCallback.isOverlapping(object2Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object3Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object4Id)); + overlappingNodes.clear(); + tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(5, -10, -2), Vector3(7, 10, 9)), overlappingNodes); + rp3d_test(!isOverlapping(object1Id, overlappingNodes)); + rp3d_test(isOverlapping(object2Id, overlappingNodes)); + rp3d_test(!isOverlapping(object3Id, overlappingNodes)); + rp3d_test(!isOverlapping(object4Id, overlappingNodes)); // ---- Update the object AABBs with the initial AABBs (with reinsertion) ----- // @@ -297,44 +283,44 @@ class TestDynamicAABBTree : public Test { tree.updateObject(object4Id, aabb4, Vector3::zero()); // AABB overlapping nothing - mOverlapCallback.reset(); - tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-10, 12, -4), Vector3(10, 50, 4)), mOverlapCallback); - rp3d_test(!mOverlapCallback.isOverlapping(object1Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object2Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object3Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object4Id)); + overlappingNodes.clear(); + tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-10, 12, -4), Vector3(10, 50, 4)), overlappingNodes); + rp3d_test(!isOverlapping(object1Id, overlappingNodes)); + rp3d_test(!isOverlapping(object2Id, overlappingNodes)); + rp3d_test(!isOverlapping(object3Id, overlappingNodes)); + rp3d_test(!isOverlapping(object4Id, overlappingNodes)); // AABB overlapping everything - mOverlapCallback.reset(); - tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-15, -15, -4), Vector3(15, 15, 4)), mOverlapCallback); - rp3d_test(mOverlapCallback.isOverlapping(object1Id)); - rp3d_test(mOverlapCallback.isOverlapping(object2Id)); - rp3d_test(mOverlapCallback.isOverlapping(object3Id)); - rp3d_test(mOverlapCallback.isOverlapping(object4Id)); + overlappingNodes.clear(); + tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-15, -15, -4), Vector3(15, 15, 4)), overlappingNodes); + rp3d_test(isOverlapping(object1Id, overlappingNodes)); + rp3d_test(isOverlapping(object2Id, overlappingNodes)); + rp3d_test(isOverlapping(object3Id, overlappingNodes)); + rp3d_test(isOverlapping(object4Id, overlappingNodes)); // AABB overlapping object 1 and 3 - mOverlapCallback.reset(); - tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-4, 2, -4), Vector3(-1, 7, 4)), mOverlapCallback); - rp3d_test(mOverlapCallback.isOverlapping(object1Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object2Id)); - rp3d_test(mOverlapCallback.isOverlapping(object3Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object4Id)); + overlappingNodes.clear(); + tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-4, 2, -4), Vector3(-1, 7, 4)), overlappingNodes); + rp3d_test(isOverlapping(object1Id, overlappingNodes)); + rp3d_test(!isOverlapping(object2Id, overlappingNodes)); + rp3d_test(isOverlapping(object3Id, overlappingNodes)); + rp3d_test(!isOverlapping(object4Id, overlappingNodes)); // AABB overlapping object 3 and 4 - mOverlapCallback.reset(); - tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-6, -5, -2), Vector3(2, 2, 0)), mOverlapCallback); - rp3d_test(!mOverlapCallback.isOverlapping(object1Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object2Id)); - rp3d_test(mOverlapCallback.isOverlapping(object3Id)); - rp3d_test(mOverlapCallback.isOverlapping(object4Id)); + overlappingNodes.clear(); + tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-6, -5, -2), Vector3(2, 2, 0)), overlappingNodes); + rp3d_test(!isOverlapping(object1Id, overlappingNodes)); + rp3d_test(!isOverlapping(object2Id, overlappingNodes)); + rp3d_test(isOverlapping(object3Id, overlappingNodes)); + rp3d_test(isOverlapping(object4Id, overlappingNodes)); // AABB overlapping object 2 - mOverlapCallback.reset(); - tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(5, -10, -2), Vector3(7, 10, 9)), mOverlapCallback); - rp3d_test(!mOverlapCallback.isOverlapping(object1Id)); - rp3d_test(mOverlapCallback.isOverlapping(object2Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object3Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object4Id)); + overlappingNodes.clear(); + tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(5, -10, -2), Vector3(7, 10, 9)), overlappingNodes); + rp3d_test(!isOverlapping(object1Id, overlappingNodes)); + rp3d_test(isOverlapping(object2Id, overlappingNodes)); + rp3d_test(!isOverlapping(object3Id, overlappingNodes)); + rp3d_test(!isOverlapping(object4Id, overlappingNodes)); // ---- Move objects 2 and 3 ----- // @@ -345,20 +331,20 @@ class TestDynamicAABBTree : public Test { tree.updateObject(object3Id, newAABB3, Vector3::zero()); // AABB overlapping object 3 - mOverlapCallback.reset(); - tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(6, -10, -2), Vector3(8, 5, 3)), mOverlapCallback); - rp3d_test(!mOverlapCallback.isOverlapping(object1Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object2Id)); - rp3d_test(mOverlapCallback.isOverlapping(object3Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object4Id)); + overlappingNodes.clear(); + tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(6, -10, -2), Vector3(8, 5, 3)), overlappingNodes); + rp3d_test(!isOverlapping(object1Id, overlappingNodes)); + rp3d_test(!isOverlapping(object2Id, overlappingNodes)); + rp3d_test(isOverlapping(object3Id, overlappingNodes)); + rp3d_test(!isOverlapping(object4Id, overlappingNodes)); // AABB overlapping objects 1, 2 - mOverlapCallback.reset(); - tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-8, 5, -3), Vector3(-2, 11, 3)), mOverlapCallback); - rp3d_test(mOverlapCallback.isOverlapping(object1Id)); - rp3d_test(mOverlapCallback.isOverlapping(object2Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object3Id)); - rp3d_test(!mOverlapCallback.isOverlapping(object4Id)); + overlappingNodes.clear(); + tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-8, 5, -3), Vector3(-2, 11, 3)), overlappingNodes); + rp3d_test(isOverlapping(object1Id, overlappingNodes)); + rp3d_test(isOverlapping(object2Id, overlappingNodes)); + rp3d_test(!isOverlapping(object3Id, overlappingNodes)); + rp3d_test(!isOverlapping(object4Id, overlappingNodes)); #ifdef IS_PROFILING_ACTIVE delete profiler;