Refactor contacts management
This commit is contained in:
parent
d8e9f15339
commit
bf3ca2c4d6
|
@ -81,6 +81,8 @@ SET (REACTPHYSICS3D_HEADERS
|
||||||
"src/body/CollisionBody.h"
|
"src/body/CollisionBody.h"
|
||||||
"src/body/RigidBody.h"
|
"src/body/RigidBody.h"
|
||||||
"src/collision/ContactPointInfo.h"
|
"src/collision/ContactPointInfo.h"
|
||||||
|
"src/collision/ContactManifoldInfo.h"
|
||||||
|
"src/collision/ContactPair.h"
|
||||||
"src/collision/broadphase/DynamicAABBTree.h"
|
"src/collision/broadphase/DynamicAABBTree.h"
|
||||||
"src/collision/narrowphase/CollisionDispatch.h"
|
"src/collision/narrowphase/CollisionDispatch.h"
|
||||||
"src/collision/narrowphase/GJK/VoronoiSimplex.h"
|
"src/collision/narrowphase/GJK/VoronoiSimplex.h"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
|
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
|
||||||
* Copyright (c) 2010-2018 Daniel Chappuis *
|
* Copyright (c) 2010-2018 Daniel Chappuis *
|
||||||
*********************************************************************************
|
*********************************************************************************
|
||||||
|
@ -30,6 +30,8 @@
|
||||||
#include "body/Body.h"
|
#include "body/Body.h"
|
||||||
#include "collision/shapes/BoxShape.h"
|
#include "collision/shapes/BoxShape.h"
|
||||||
#include "collision/shapes/ConcaveShape.h"
|
#include "collision/shapes/ConcaveShape.h"
|
||||||
|
#include "collision/ContactManifoldInfo.h"
|
||||||
|
#include "constraint/ContactPoint.h"
|
||||||
#include "body/RigidBody.h"
|
#include "body/RigidBody.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "collision/CollisionCallback.h"
|
#include "collision/CollisionCallback.h"
|
||||||
|
@ -55,7 +57,17 @@ CollisionDetection::CollisionDetection(CollisionWorld* world, ProxyShapeComponen
|
||||||
mOverlappingPairs(mMemoryManager.getPoolAllocator()),
|
mOverlappingPairs(mMemoryManager.getPoolAllocator()),
|
||||||
mBroadPhaseSystem(*this, mProxyShapesComponents, mTransformComponents, dynamicsComponents),
|
mBroadPhaseSystem(*this, mProxyShapesComponents, mTransformComponents, dynamicsComponents),
|
||||||
mNoCollisionPairs(mMemoryManager.getPoolAllocator()), mMapBroadPhaseIdToProxyShapeEntity(memoryManager.getPoolAllocator()),
|
mNoCollisionPairs(mMemoryManager.getPoolAllocator()), mMapBroadPhaseIdToProxyShapeEntity(memoryManager.getPoolAllocator()),
|
||||||
mNarrowPhaseInput(mMemoryManager.getSingleFrameAllocator()) {
|
mNarrowPhaseInput(mMemoryManager.getSingleFrameAllocator()), mPotentialContactPoints(mMemoryManager.getPoolAllocator()),
|
||||||
|
// TODO : We should probably use single frame allocator for mPotentialContactPoints, mPotentialContactManifolds, mMapPairIdToOverlappingPairContacts
|
||||||
|
mPotentialContactManifolds(mMemoryManager.getPoolAllocator()), mContactPairs1(mMemoryManager.getPoolAllocator()),
|
||||||
|
mContactPairs2(mMemoryManager.getPoolAllocator()), mPreviousContactPairs(&mContactPairs1), mCurrentContactPairs(&mContactPairs2),
|
||||||
|
mMapPairIdToContactPairIndex1(mMemoryManager.getPoolAllocator()), mMapPairIdToContactPairIndex2(mMemoryManager.getPoolAllocator()),
|
||||||
|
mPreviousMapPairIdToContactPairIndex(&mMapPairIdToContactPairIndex1), mCurrentMapPairIdToContactPairIndex(&mMapPairIdToContactPairIndex2),
|
||||||
|
mContactManifolds1(mMemoryManager.getPoolAllocator()), mContactManifolds2(mMemoryManager.getPoolAllocator()),
|
||||||
|
mPreviousContactManifolds(&mContactManifolds1), mCurrentContactManifolds(&mContactManifolds2),
|
||||||
|
mContactPoints1(mMemoryManager.getPoolAllocator()),
|
||||||
|
mContactPoints2(mMemoryManager.getPoolAllocator()), mPreviousContactPoints(&mContactPoints1),
|
||||||
|
mCurrentContactPoints(&mContactPoints2) {
|
||||||
|
|
||||||
#ifdef IS_PROFILING_ACTIVE
|
#ifdef IS_PROFILING_ACTIVE
|
||||||
|
|
||||||
|
@ -365,6 +377,9 @@ bool CollisionDetection::testNarrowPhaseCollision(NarrowPhaseInput& narrowPhaseI
|
||||||
// Process the potential contacts after narrow-phase collision detection
|
// Process the potential contacts after narrow-phase collision detection
|
||||||
void CollisionDetection::processAllPotentialContacts(NarrowPhaseInput& narrowPhaseInput, bool updateLastFrameInfo) {
|
void CollisionDetection::processAllPotentialContacts(NarrowPhaseInput& narrowPhaseInput, bool updateLastFrameInfo) {
|
||||||
|
|
||||||
|
assert(mCurrentContactPairs->size() == 0);
|
||||||
|
assert(mCurrentMapPairIdToContactPairIndex->size() == 0);
|
||||||
|
|
||||||
// get the narrow-phase batches to test for collision
|
// get the narrow-phase batches to test for collision
|
||||||
NarrowPhaseInfoBatch& sphereVsSphereBatch = narrowPhaseInput.getSphereVsSphereBatch();
|
NarrowPhaseInfoBatch& sphereVsSphereBatch = narrowPhaseInput.getSphereVsSphereBatch();
|
||||||
NarrowPhaseInfoBatch& sphereVsCapsuleBatch = narrowPhaseInput.getSphereVsCapsuleBatch();
|
NarrowPhaseInfoBatch& sphereVsCapsuleBatch = narrowPhaseInput.getSphereVsCapsuleBatch();
|
||||||
|
@ -389,6 +404,9 @@ void CollisionDetection::computeNarrowPhase() {
|
||||||
|
|
||||||
MemoryAllocator& allocator = mMemoryManager.getSingleFrameAllocator();
|
MemoryAllocator& allocator = mMemoryManager.getSingleFrameAllocator();
|
||||||
|
|
||||||
|
// Swap the previous and current contacts lists
|
||||||
|
swapPreviousAndCurrentContacts();
|
||||||
|
|
||||||
// Test the narrow-phase collision detection on the batches to be tested
|
// Test the narrow-phase collision detection on the batches to be tested
|
||||||
testNarrowPhaseCollision(mNarrowPhaseInput, false, true, allocator);
|
testNarrowPhaseCollision(mNarrowPhaseInput, false, true, allocator);
|
||||||
|
|
||||||
|
@ -396,7 +414,13 @@ void CollisionDetection::computeNarrowPhase() {
|
||||||
processAllPotentialContacts(mNarrowPhaseInput, true);
|
processAllPotentialContacts(mNarrowPhaseInput, true);
|
||||||
|
|
||||||
// Reduce the number of contact points in the manifolds
|
// Reduce the number of contact points in the manifolds
|
||||||
reduceContactManifolds(mOverlappingPairs);
|
reducePotentialContactManifolds(mOverlappingPairs);
|
||||||
|
|
||||||
|
// Create the actual contact manifolds and contacts (from potential contacts)
|
||||||
|
createContacts();
|
||||||
|
|
||||||
|
// Initialize the current contacts with the contacts from the previous frame (for warmstarting)
|
||||||
|
initContactsWithPreviousOnes();
|
||||||
|
|
||||||
// Add all the contact manifolds (between colliding bodies) to the bodies
|
// Add all the contact manifolds (between colliding bodies) to the bodies
|
||||||
addAllContactManifoldsToBodies();
|
addAllContactManifoldsToBodies();
|
||||||
|
@ -406,6 +430,193 @@ void CollisionDetection::computeNarrowPhase() {
|
||||||
|
|
||||||
// Clear the list of narrow-phase infos
|
// Clear the list of narrow-phase infos
|
||||||
mNarrowPhaseInput.clear();
|
mNarrowPhaseInput.clear();
|
||||||
|
|
||||||
|
// TODO : Do not forget to clear all the contact pair, contact manifolds and contact points lists
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap the previous and current contacts lists
|
||||||
|
void CollisionDetection::swapPreviousAndCurrentContacts() {
|
||||||
|
|
||||||
|
if (mPreviousContactPairs == &mContactPairs1) {
|
||||||
|
|
||||||
|
mPreviousContactPairs = &mContactPairs2;
|
||||||
|
mPreviousContactManifolds = &mContactManifolds2;
|
||||||
|
mPreviousContactPoints = &mContactPoints2;
|
||||||
|
mPreviousMapPairIdToContactPairIndex = &mMapPairIdToContactPairIndex2;
|
||||||
|
|
||||||
|
mCurrentContactPairs = &mContactPairs1;
|
||||||
|
mCurrentContactManifolds = &mContactManifolds1;
|
||||||
|
mCurrentContactPoints = &mContactPoints1;
|
||||||
|
mCurrentMapPairIdToContactPairIndex = &mMapPairIdToContactPairIndex1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
mPreviousContactPairs = &mContactPairs1;
|
||||||
|
mPreviousContactManifolds = &mContactManifolds1;
|
||||||
|
mPreviousContactPoints = &mContactPoints1;
|
||||||
|
mPreviousMapPairIdToContactPairIndex = &mMapPairIdToContactPairIndex1;
|
||||||
|
|
||||||
|
mCurrentContactPairs = &mContactPairs2;
|
||||||
|
mCurrentContactManifolds = &mContactManifolds2;
|
||||||
|
mCurrentContactPoints = &mContactPoints2;
|
||||||
|
mCurrentMapPairIdToContactPairIndex = &mMapPairIdToContactPairIndex2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the actual contact manifolds and contacts (from potential contacts)
|
||||||
|
void CollisionDetection::createContacts() {
|
||||||
|
|
||||||
|
RP3D_PROFILE("CollisionDetection::createContacts()", mProfiler);
|
||||||
|
|
||||||
|
assert(mCurrentContactManifolds->size() == 0);
|
||||||
|
assert(mCurrentContactPoints->size() == 0);
|
||||||
|
|
||||||
|
// For each contact pair
|
||||||
|
for (auto it = mCurrentMapPairIdToContactPairIndex->begin(); it != mCurrentMapPairIdToContactPairIndex->end(); ++it) {
|
||||||
|
|
||||||
|
const uint contactPairIndex = it->second;
|
||||||
|
assert(contactPairIndex < mCurrentContactPairs->size());
|
||||||
|
ContactPair& contactPair = (*mCurrentContactPairs)[contactPairIndex];
|
||||||
|
|
||||||
|
assert(contactPair.potentialContactManifoldsIndices.size() > 0);
|
||||||
|
|
||||||
|
// Start index and numnber of contact manifolds for this contact pair
|
||||||
|
contactPair.contactManifoldsIndex = mCurrentContactManifolds->size();
|
||||||
|
contactPair.nbContactManifolds = contactPair.potentialContactManifoldsIndices.size();
|
||||||
|
contactPair.contactPointsIndex = mCurrentContactPoints->size();
|
||||||
|
|
||||||
|
// For each potential contact manifold of the pair
|
||||||
|
for (uint m=0; m < contactPair.potentialContactManifoldsIndices.size(); m++) {
|
||||||
|
|
||||||
|
ContactManifoldInfo& potentialManifold = mPotentialContactManifolds[contactPair.potentialContactManifoldsIndices[m]];
|
||||||
|
|
||||||
|
// Start index and number of contact points for this manifold
|
||||||
|
const uint contactPointsIndex = mCurrentContactPoints->size();
|
||||||
|
const int8 nbContactPoints = potentialManifold.potentialContactPointsIndices.size();
|
||||||
|
|
||||||
|
// We create a new contact manifold
|
||||||
|
ContactManifold contactManifold(contactPointsIndex, nbContactPoints, mMemoryManager.getPoolAllocator(), mWorld->mConfig);
|
||||||
|
|
||||||
|
// Add the contact manifold
|
||||||
|
mCurrentContactManifolds->add(contactManifold);
|
||||||
|
|
||||||
|
// Increase the number of total contact point of the contact pair
|
||||||
|
contactPair.nbToTalContactPoints += potentialManifold.potentialContactPointsIndices.size();
|
||||||
|
|
||||||
|
assert(potentialManifold.potentialContactPointsIndices.size() > 0);
|
||||||
|
|
||||||
|
// For each contact point of the manifold
|
||||||
|
for (uint c=0; c < potentialManifold.potentialContactPointsIndices.size(); c++) {
|
||||||
|
|
||||||
|
ContactPointInfo& potentialContactPoint = mPotentialContactPoints[potentialManifold.potentialContactPointsIndices[c]];
|
||||||
|
|
||||||
|
// Create a new contact point
|
||||||
|
ContactPoint contactPoint(potentialContactPoint, mWorld->mConfig);
|
||||||
|
|
||||||
|
// Add the contact point
|
||||||
|
mCurrentContactPoints->add(contactPoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the potential contacts
|
||||||
|
mPotentialContactPoints.clear();
|
||||||
|
mPotentialContactManifolds.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the current contacts with the contacts from the previous frame (for warmstarting)
|
||||||
|
void CollisionDetection::initContactsWithPreviousOnes() {
|
||||||
|
|
||||||
|
// For each contact pair of the current frame
|
||||||
|
for (uint i=0; i < mCurrentContactPairs->size(); i++) {
|
||||||
|
|
||||||
|
ContactPair& currentContactPair = (*mCurrentContactPairs)[i];
|
||||||
|
|
||||||
|
// Find the corresponding contact pair in the previous frame (if any)
|
||||||
|
auto itPrevContactPair = mPreviousMapPairIdToContactPairIndex->find(currentContactPair.pairId);
|
||||||
|
|
||||||
|
// If we have found a corresponding contact pair in the previous frame
|
||||||
|
if (itPrevContactPair != mPreviousMapPairIdToContactPairIndex->end()) {
|
||||||
|
|
||||||
|
const uint previousContactPairIndex = itPrevContactPair->second;
|
||||||
|
ContactPair& previousContactPair = (*mPreviousContactPairs)[previousContactPairIndex];
|
||||||
|
|
||||||
|
// --------------------- Contact Manifolds --------------------- //
|
||||||
|
|
||||||
|
const uint contactManifoldsIndex = currentContactPair.contactManifoldsIndex;
|
||||||
|
const uint nbContactManifolds = currentContactPair.nbContactManifolds;
|
||||||
|
|
||||||
|
// For each current contact manifold of the contact pair
|
||||||
|
for (uint m=contactManifoldsIndex; m < contactManifoldsIndex + nbContactManifolds; m++) {
|
||||||
|
|
||||||
|
assert(m < mCurrentContactManifolds->size());
|
||||||
|
ContactManifold& currentContactManifold = (*mCurrentContactManifolds)[m];
|
||||||
|
assert(currentContactManifold.mNbContactPoints > 0);
|
||||||
|
ContactPoint& currentContactPoint = (*mCurrentContactPoints)[currentContactManifold.mContactPointsIndex];
|
||||||
|
const Vector3& currentContactPointNormal = currentContactPoint.getNormal();
|
||||||
|
|
||||||
|
// Find a similar contact manifold among the contact manifolds from the previous frame (for warmstarting)
|
||||||
|
const uint previousContactManifoldIndex = previousContactPair.contactManifoldsIndex;
|
||||||
|
const uint previousNbContactManifolds = previousContactPair.nbContactManifolds;
|
||||||
|
for (uint p=previousContactManifoldIndex; p < previousContactManifoldIndex + previousNbContactManifolds; p++) {
|
||||||
|
|
||||||
|
ContactManifold& previousContactManifold = (*mPreviousContactManifolds)[p];
|
||||||
|
assert(previousContactManifold.mNbContactPoints > 0);
|
||||||
|
ContactPoint& previousContactPoint = (*mPreviousContactPoints)[previousContactManifold.mContactPointsIndex];
|
||||||
|
|
||||||
|
// If the previous contact manifold has a similar contact normal with the current manifold
|
||||||
|
if (previousContactPoint.getNormal().dot(currentContactPointNormal) >= mWorld->mConfig.cosAngleSimilarContactManifold) {
|
||||||
|
|
||||||
|
// Transfer data from the previous contact manifold to the current one
|
||||||
|
currentContactManifold.mFrictionVector1 = previousContactManifold.mFrictionVector1;
|
||||||
|
currentContactManifold.mFrictionVector2 = previousContactManifold.mFrictionVector2;
|
||||||
|
currentContactManifold.mFrictionImpulse1 = previousContactManifold.mFrictionImpulse1;
|
||||||
|
currentContactManifold.mFrictionImpulse2 = previousContactManifold.mFrictionImpulse2;
|
||||||
|
currentContactManifold.mFrictionTwistImpulse = previousContactManifold.mFrictionTwistImpulse;
|
||||||
|
currentContactManifold.mRollingResistanceImpulse = previousContactManifold.mRollingResistanceImpulse;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------- Contact Points --------------------- //
|
||||||
|
|
||||||
|
const uint contactPointsIndex = currentContactPair.contactPointsIndex;
|
||||||
|
const uint nbTotalContactPoints = currentContactPair.nbToTalContactPoints;
|
||||||
|
|
||||||
|
// For each current contact point of the contact pair
|
||||||
|
for (uint c=contactPointsIndex; c < contactPointsIndex + nbTotalContactPoints; c++) {
|
||||||
|
|
||||||
|
assert(c < mCurrentContactPoints->size());
|
||||||
|
ContactPoint& currentContactPoint = (*mCurrentContactPoints)[c];
|
||||||
|
|
||||||
|
// Find a similar contact point among the contact points from the previous frame (for warmstarting)
|
||||||
|
const uint previousContactPointsIndex = previousContactPair.contactPointsIndex;
|
||||||
|
const uint previousNbContactPoints = previousContactPair.nbToTalContactPoints;
|
||||||
|
for (uint p=previousContactPointsIndex; p < previousContactPointsIndex + previousNbContactPoints; p++) {
|
||||||
|
|
||||||
|
ContactPoint& previousContactPoint = (*mPreviousContactPoints)[p];
|
||||||
|
|
||||||
|
// If the previous contact point is very close to th current one
|
||||||
|
const decimal distSquare = (currentContactPoint.getLocalPointOnShape1() - previousContactPoint.getLocalPointOnShape1()).lengthSquare();
|
||||||
|
if (distSquare <= mWorld->mConfig.persistentContactDistanceThreshold * mWorld->mConfig.persistentContactDistanceThreshold) {
|
||||||
|
|
||||||
|
// Transfer data from the previous contact point to the current one
|
||||||
|
currentContactPoint.setPenetrationImpulse(previousContactPoint.getPenetrationImpulse());
|
||||||
|
currentContactPoint.setIsRestingContact(previousContactPoint.getIsRestingContact());
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mPreviousContactPoints->clear();
|
||||||
|
mPreviousContactManifolds->clear();
|
||||||
|
mPreviousContactPairs->clear();
|
||||||
|
mPreviousMapPairIdToContactPairIndex->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove a body from the collision detection
|
// Remove a body from the collision detection
|
||||||
|
@ -506,7 +717,7 @@ void CollisionDetection::addContactManifoldToBody(OverlappingPair* pair) {
|
||||||
/// Convert the potential contact into actual contacts
|
/// Convert the potential contact into actual contacts
|
||||||
void CollisionDetection::processPotentialContacts(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, bool updateLastFrameInfo) {
|
void CollisionDetection::processPotentialContacts(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, bool updateLastFrameInfo) {
|
||||||
|
|
||||||
RP3D_PROFILE("CollisionDetection::processAllPotentialContacts()", mProfiler);
|
RP3D_PROFILE("CollisionDetection::processPotentialContacts()", mProfiler);
|
||||||
|
|
||||||
// For each narrow phase info object
|
// For each narrow phase info object
|
||||||
for(uint i=0; i < narrowPhaseInfoBatch.getNbObjects(); i++) {
|
for(uint i=0; i < narrowPhaseInfoBatch.getNbObjects(); i++) {
|
||||||
|
@ -518,21 +729,116 @@ void CollisionDetection::processPotentialContacts(NarrowPhaseInfoBatch& narrowPh
|
||||||
narrowPhaseInfoBatch.lastFrameCollisionInfos[i]->isValid = true;
|
narrowPhaseInfoBatch.lastFrameCollisionInfos[i]->isValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----- START OLD ----- //
|
||||||
|
|
||||||
if (narrowPhaseInfoBatch.isColliding[i]) {
|
if (narrowPhaseInfoBatch.isColliding[i]) {
|
||||||
|
|
||||||
assert(narrowPhaseInfoBatch.contactPoints[i].size() > 0);
|
assert(narrowPhaseInfoBatch.contactPoints[i].size() > 0);
|
||||||
|
|
||||||
// Transfer the contact points from the narrow phase info to the overlapping pair
|
// Transfer the contact points from the narrow phase info to the overlapping pair
|
||||||
|
// TOOD : COMMENT THIS
|
||||||
narrowPhaseInfoBatch.overlappingPairs[i]->addPotentialContactPoints(narrowPhaseInfoBatch, i);
|
narrowPhaseInfoBatch.overlappingPairs[i]->addPotentialContactPoints(narrowPhaseInfoBatch, i);
|
||||||
|
|
||||||
// Remove the contacts points from the narrow phase info object.
|
// Remove the contacts points from the narrow phase info object.
|
||||||
narrowPhaseInfoBatch.resetContactPoints(i);
|
//narrowPhaseInfoBatch.resetContactPoints(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----- END OLD ----- //
|
||||||
|
|
||||||
|
// Add the potential contacts
|
||||||
|
for (uint j=0; j < narrowPhaseInfoBatch.contactPoints[i].size(); j++) {
|
||||||
|
|
||||||
|
if (narrowPhaseInfoBatch.isColliding[i]) {
|
||||||
|
|
||||||
|
const ContactPointInfo& contactPoint = *(narrowPhaseInfoBatch.contactPoints[i][j]);
|
||||||
|
|
||||||
|
// Add the contact point to the list of potential contact points
|
||||||
|
const uint contactPointIndex = static_cast<uint>(mPotentialContactPoints.size());
|
||||||
|
|
||||||
|
// TODO : We should probably use single frame allocator here for mPotentialContactPoints
|
||||||
|
mPotentialContactPoints.add(contactPoint);
|
||||||
|
|
||||||
|
bool similarManifoldFound = false;
|
||||||
|
|
||||||
|
// If there are already potential contact manifolds for this overlapping pair
|
||||||
|
OverlappingPair::OverlappingPairId pairId = narrowPhaseInfoBatch.overlappingPairs[i]->getId();
|
||||||
|
auto it = mCurrentMapPairIdToContactPairIndex->find(pairId);
|
||||||
|
ContactPair* pairContact = nullptr;
|
||||||
|
if (it != mCurrentMapPairIdToContactPairIndex->end()) {
|
||||||
|
|
||||||
|
const uint pairContactIndex = it->second;
|
||||||
|
pairContact = &((*mCurrentContactPairs)[pairContactIndex]);
|
||||||
|
|
||||||
|
assert(pairContact->potentialContactManifoldsIndices.size() > 0);
|
||||||
|
|
||||||
|
// For each contact manifold of the overlapping pair
|
||||||
|
for (uint m=0; m < pairContact->potentialContactManifoldsIndices.size(); m++) {
|
||||||
|
uint contactManifoldIndex = pairContact->potentialContactManifoldsIndices[m];
|
||||||
|
|
||||||
|
// Get the first contact point of the current manifold
|
||||||
|
assert(mPotentialContactManifolds[contactManifoldIndex].potentialContactPointsIndices.size() > 0);
|
||||||
|
const uint manifoldContactPointIndex = mPotentialContactManifolds[contactManifoldIndex].potentialContactPointsIndices[0];
|
||||||
|
const ContactPointInfo& manifoldContactPoint = mPotentialContactPoints[manifoldContactPointIndex];
|
||||||
|
|
||||||
|
// If we have found a corresponding manifold for the new contact point
|
||||||
|
// (a manifold with a similar contact normal direction)
|
||||||
|
if (manifoldContactPoint.normal.dot(contactPoint.normal) >= mWorld->mConfig.cosAngleSimilarContactManifold) {
|
||||||
|
|
||||||
|
// Add the contact point to the manifold
|
||||||
|
mPotentialContactManifolds[m].potentialContactPointsIndices.add(contactPointIndex);
|
||||||
|
|
||||||
|
similarManifoldFound = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have not found a manifold with a similar contact normal for the contact point
|
||||||
|
if (!similarManifoldFound) {
|
||||||
|
|
||||||
|
// Create a new contact manifold for the overlapping pair
|
||||||
|
// TODO : We should probably use single frame allocator here
|
||||||
|
ContactManifoldInfo contactManifoldInfo(pairId, mMemoryManager.getPoolAllocator());
|
||||||
|
|
||||||
|
// Add the contact point to the manifold
|
||||||
|
contactManifoldInfo.potentialContactPointsIndices.add(contactPointIndex);
|
||||||
|
|
||||||
|
// If the overlapping pair contact does not exists yet
|
||||||
|
if (pairContact == nullptr) {
|
||||||
|
|
||||||
|
// TODO : We should probably use a single frame allocator here
|
||||||
|
ContactPair overlappingPairContact(pairId, mMemoryManager.getPoolAllocator());
|
||||||
|
const uint newContactPairIndex = mCurrentContactPairs->size();
|
||||||
|
mCurrentContactPairs->add(overlappingPairContact);
|
||||||
|
pairContact = &((*mCurrentContactPairs)[newContactPairIndex]);
|
||||||
|
mCurrentMapPairIdToContactPairIndex->add(Pair<OverlappingPair::OverlappingPairId, uint>(pairId, newContactPairIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(pairContact != nullptr);
|
||||||
|
|
||||||
|
// Add the potential contact manifold
|
||||||
|
uint contactManifoldIndex = static_cast<uint>(mPotentialContactManifolds.size());
|
||||||
|
mPotentialContactManifolds.add(contactManifoldInfo);
|
||||||
|
|
||||||
|
// Add the contact manifold to the overlapping pair contact
|
||||||
|
pairContact->potentialContactManifoldsIndices.add(contactManifoldIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(pairContact->potentialContactManifoldsIndices.size() > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
narrowPhaseInfoBatch.resetContactPoints(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the obsolete manifolds and contact points and reduce the number of contacts points of the remaining manifolds
|
// Clear the obsolete manifolds and contact points and reduce the number of contacts points of the remaining manifolds
|
||||||
void CollisionDetection::reduceContactManifolds(const OverlappingPairMap& overlappingPairs) {
|
void CollisionDetection::reducePotentialContactManifolds(const OverlappingPairMap& overlappingPairs) {
|
||||||
|
|
||||||
|
RP3D_PROFILE("CollisionDetection::reducePotentialContactManifolds()", mProfiler);
|
||||||
|
|
||||||
|
// ----- OLD ----- //
|
||||||
|
|
||||||
// For each overlapping pairs in contact during the narrow-phase
|
// For each overlapping pairs in contact during the narrow-phase
|
||||||
for (auto it = overlappingPairs.begin(); it != overlappingPairs.end(); ++it) {
|
for (auto it = overlappingPairs.begin(); it != overlappingPairs.end(); ++it) {
|
||||||
|
@ -546,6 +852,260 @@ void CollisionDetection::reduceContactManifolds(const OverlappingPairMap& overla
|
||||||
pair->reduceContactManifolds();
|
pair->reduceContactManifolds();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----- OLD ----- //
|
||||||
|
|
||||||
|
// Reduce the number of potential contact manifolds in a contact pair
|
||||||
|
for (uint i=0; i < mCurrentContactPairs->size(); i++) {
|
||||||
|
|
||||||
|
ContactPair& contactPair = (*mCurrentContactPairs)[i];
|
||||||
|
|
||||||
|
assert(contactPair.potentialContactManifoldsIndices.size() > 0);
|
||||||
|
|
||||||
|
// While there are too many manifolds
|
||||||
|
while(contactPair.potentialContactManifoldsIndices.size() > mWorld->mConfig.nbMaxContactManifolds) {
|
||||||
|
|
||||||
|
// Look for a manifold with the smallest contact penetration depth.
|
||||||
|
decimal minDepth = DECIMAL_LARGEST;
|
||||||
|
int minDepthManifoldIndex = -1;
|
||||||
|
for (uint i=0; i < contactPair.potentialContactManifoldsIndices.size(); i++) {
|
||||||
|
|
||||||
|
ContactManifoldInfo& manifold = mPotentialContactManifolds[contactPair.potentialContactManifoldsIndices[i]];
|
||||||
|
|
||||||
|
// Get the largest contact point penetration depth of the manifold
|
||||||
|
const decimal depth = computePotentialManifoldLargestContactDepth(manifold);
|
||||||
|
|
||||||
|
if (depth < minDepth) {
|
||||||
|
minDepth = depth;
|
||||||
|
minDepthManifoldIndex = static_cast<int>(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the non optimal manifold
|
||||||
|
assert(minDepthManifoldIndex >= 0);
|
||||||
|
contactPair.potentialContactManifoldsIndices.removeAt(minDepthManifoldIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reduce the number of potential contact points in the manifolds
|
||||||
|
for (uint i=0; i < mCurrentContactPairs->size(); i++) {
|
||||||
|
|
||||||
|
const ContactPair& pairContact = (*mCurrentContactPairs)[i];
|
||||||
|
|
||||||
|
// For each potential contact manifold
|
||||||
|
for (uint i=0; i < pairContact.potentialContactManifoldsIndices.size(); i++) {
|
||||||
|
|
||||||
|
ContactManifoldInfo& manifold = mPotentialContactManifolds[pairContact.potentialContactManifoldsIndices[i]];
|
||||||
|
|
||||||
|
// If there are two many contact points in the manifold
|
||||||
|
if (manifold.potentialContactPointsIndices.size() > MAX_CONTACT_POINTS_IN_MANIFOLD) {
|
||||||
|
|
||||||
|
Transform shape1LocalToWorldTransoform = mOverlappingPairs[manifold.pairId]->getShape1()->getLocalToWorldTransform();
|
||||||
|
|
||||||
|
// Reduce the number of contact points in the manifold
|
||||||
|
reduceContactPoints(manifold, shape1LocalToWorldTransoform);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(manifold.potentialContactPointsIndices.size() <= MAX_CONTACT_POINTS_IN_MANIFOLD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the largest depth of all the contact points of a potential manifold
|
||||||
|
decimal CollisionDetection::computePotentialManifoldLargestContactDepth(const ContactManifoldInfo& manifold) const {
|
||||||
|
|
||||||
|
decimal largestDepth = 0.0f;
|
||||||
|
|
||||||
|
assert(manifold.potentialContactPointsIndices.size() > 0);
|
||||||
|
|
||||||
|
for (uint i=0; i < manifold.potentialContactPointsIndices.size(); i++) {
|
||||||
|
decimal depth = mPotentialContactPoints[manifold.potentialContactPointsIndices[i]].penetrationDepth;
|
||||||
|
|
||||||
|
if (depth > largestDepth) {
|
||||||
|
largestDepth = depth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return largestDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reduce the number of contact points of a potential contact manifold
|
||||||
|
// This is based on the technique described by Dirk Gregorius in his
|
||||||
|
// "Contacts Creation" GDC presentation. This method will reduce the number of
|
||||||
|
// contact points to a maximum of 4 points (but it can be less).
|
||||||
|
void CollisionDetection::reduceContactPoints(ContactManifoldInfo& manifold, const Transform& shape1ToWorldTransform) {
|
||||||
|
|
||||||
|
assert(manifold.potentialContactPointsIndices.size() > MAX_CONTACT_POINTS_IN_MANIFOLD);
|
||||||
|
|
||||||
|
// The following algorithm only works to reduce to a maximum of 4 contact points
|
||||||
|
assert(MAX_CONTACT_POINTS_IN_MANIFOLD == 4);
|
||||||
|
|
||||||
|
// List of the candidate contact points indices in the manifold. Every time that we have found a
|
||||||
|
// point we want to keep, we will remove it from this list
|
||||||
|
List<uint> candidatePointsIndices(manifold.potentialContactPointsIndices);
|
||||||
|
|
||||||
|
int8 nbReducedPoints = 0;
|
||||||
|
|
||||||
|
uint pointsToKeepIndices[MAX_CONTACT_POINTS_IN_MANIFOLD];
|
||||||
|
for (int8 i=0; i<MAX_CONTACT_POINTS_IN_MANIFOLD; i++) {
|
||||||
|
pointsToKeepIndices[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute the initial contact point we need to keep.
|
||||||
|
// The first point we keep is always the point in a given
|
||||||
|
// constant direction (in order to always have same contact points
|
||||||
|
// between frames for better stability)
|
||||||
|
|
||||||
|
const Transform worldToShape1Transform = shape1ToWorldTransform.getInverse();
|
||||||
|
|
||||||
|
// Compute the contact normal of the manifold (we use the first contact point)
|
||||||
|
// in the local-space of the first collision shape
|
||||||
|
const Vector3 contactNormalShape1Space = worldToShape1Transform.getOrientation() * mPotentialContactPoints[candidatePointsIndices[0]].normal;
|
||||||
|
|
||||||
|
// Compute a search direction
|
||||||
|
const Vector3 searchDirection(1, 1, 1);
|
||||||
|
decimal maxDotProduct = DECIMAL_SMALLEST;
|
||||||
|
uint elementIndexToKeep = 0;
|
||||||
|
for (uint i=0; i < candidatePointsIndices.size(); i++) {
|
||||||
|
|
||||||
|
const ContactPointInfo& element = mPotentialContactPoints[candidatePointsIndices[i]];
|
||||||
|
decimal dotProduct = searchDirection.dot(element.localPoint1);
|
||||||
|
if (dotProduct > maxDotProduct) {
|
||||||
|
maxDotProduct = dotProduct;
|
||||||
|
elementIndexToKeep = i;
|
||||||
|
nbReducedPoints = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pointsToKeepIndices[0] = candidatePointsIndices[elementIndexToKeep];
|
||||||
|
candidatePointsIndices.removeAt(elementIndexToKeep);
|
||||||
|
assert(nbReducedPoints == 1);
|
||||||
|
|
||||||
|
// Compute the second contact point we need to keep.
|
||||||
|
// The second point we keep is the one farthest away from the first point.
|
||||||
|
|
||||||
|
decimal maxDistance = decimal(0.0);
|
||||||
|
elementIndexToKeep = 0;
|
||||||
|
for (uint i=0; i < candidatePointsIndices.size(); i++) {
|
||||||
|
|
||||||
|
const ContactPointInfo& element = mPotentialContactPoints[candidatePointsIndices[i]];
|
||||||
|
const ContactPointInfo& pointToKeep0 = mPotentialContactPoints[pointsToKeepIndices[0]];
|
||||||
|
|
||||||
|
assert(candidatePointsIndices[i] != pointsToKeepIndices[0]);
|
||||||
|
|
||||||
|
const decimal distance = (pointToKeep0.localPoint1 - element.localPoint1).lengthSquare();
|
||||||
|
if (distance >= maxDistance) {
|
||||||
|
maxDistance = distance;
|
||||||
|
elementIndexToKeep = i;
|
||||||
|
nbReducedPoints = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
pointsToKeepIndices[1] = candidatePointsIndices[elementIndexToKeep];
|
||||||
|
candidatePointsIndices.removeAt(elementIndexToKeep);
|
||||||
|
assert(nbReducedPoints == 2);
|
||||||
|
|
||||||
|
// Compute the third contact point we need to keep.
|
||||||
|
// The third point is the one producing the triangle with the larger area
|
||||||
|
// with first and second point.
|
||||||
|
|
||||||
|
// We compute the most positive or most negative triangle area (depending on winding)
|
||||||
|
uint thirdPointMaxAreaIndex = 0;
|
||||||
|
uint thirdPointMinAreaIndex = 0;
|
||||||
|
decimal minArea = decimal(0.0);
|
||||||
|
decimal maxArea = decimal(0.0);
|
||||||
|
bool isPreviousAreaPositive = true;
|
||||||
|
for (uint i=0; i < candidatePointsIndices.size(); i++) {
|
||||||
|
|
||||||
|
const ContactPointInfo& element = mPotentialContactPoints[candidatePointsIndices[i]];
|
||||||
|
const ContactPointInfo& pointToKeep0 = mPotentialContactPoints[pointsToKeepIndices[0]];
|
||||||
|
const ContactPointInfo& pointToKeep1 = mPotentialContactPoints[pointsToKeepIndices[1]];
|
||||||
|
|
||||||
|
assert(candidatePointsIndices[i] != pointsToKeepIndices[0]);
|
||||||
|
assert(candidatePointsIndices[i] != pointsToKeepIndices[1]);
|
||||||
|
|
||||||
|
const Vector3 newToFirst = pointToKeep0.localPoint1 - element.localPoint1;
|
||||||
|
const Vector3 newToSecond = pointToKeep1.localPoint1 - element.localPoint1;
|
||||||
|
|
||||||
|
// Compute the triangle area
|
||||||
|
decimal area = newToFirst.cross(newToSecond).dot(contactNormalShape1Space);
|
||||||
|
|
||||||
|
if (area >= maxArea) {
|
||||||
|
maxArea = area;
|
||||||
|
thirdPointMaxAreaIndex = i;
|
||||||
|
}
|
||||||
|
if (area <= minArea) {
|
||||||
|
minArea = area;
|
||||||
|
thirdPointMinAreaIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(minArea <= decimal(0.0));
|
||||||
|
assert(maxArea >= decimal(0.0));
|
||||||
|
if (maxArea > (-minArea)) {
|
||||||
|
isPreviousAreaPositive = true;
|
||||||
|
pointsToKeepIndices[2] = candidatePointsIndices[thirdPointMaxAreaIndex];
|
||||||
|
candidatePointsIndices.removeAt(thirdPointMaxAreaIndex);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
isPreviousAreaPositive = false;
|
||||||
|
pointsToKeepIndices[2] = candidatePointsIndices[thirdPointMinAreaIndex];
|
||||||
|
candidatePointsIndices.removeAt(thirdPointMinAreaIndex);
|
||||||
|
}
|
||||||
|
nbReducedPoints = 3;
|
||||||
|
|
||||||
|
// Compute the 4th point by choosing the triangle that add the most
|
||||||
|
// triangle area to the previous triangle and has opposite sign area (opposite winding)
|
||||||
|
|
||||||
|
decimal largestArea = decimal(0.0); // Largest area (positive or negative)
|
||||||
|
elementIndexToKeep = 0;
|
||||||
|
|
||||||
|
// For each remaining candidate points
|
||||||
|
for (uint i=0; i < candidatePointsIndices.size(); i++) {
|
||||||
|
|
||||||
|
const ContactPointInfo& element = mPotentialContactPoints[candidatePointsIndices[i]];
|
||||||
|
|
||||||
|
assert(candidatePointsIndices[i] != pointsToKeepIndices[0]);
|
||||||
|
assert(candidatePointsIndices[i] != pointsToKeepIndices[1]);
|
||||||
|
assert(candidatePointsIndices[i] != pointsToKeepIndices[2]);
|
||||||
|
|
||||||
|
// For each edge of the triangle made by the first three points
|
||||||
|
for (uint i=0; i<3; i++) {
|
||||||
|
|
||||||
|
uint edgeVertex1Index = i;
|
||||||
|
uint edgeVertex2Index = i < 2 ? i + 1 : 0;
|
||||||
|
|
||||||
|
const ContactPointInfo& pointToKeepEdgeV1 = mPotentialContactPoints[pointsToKeepIndices[edgeVertex1Index]];
|
||||||
|
const ContactPointInfo& pointToKeepEdgeV2 = mPotentialContactPoints[pointsToKeepIndices[edgeVertex2Index]];
|
||||||
|
|
||||||
|
const Vector3 newToFirst = pointToKeepEdgeV1.localPoint1 - element.localPoint1;
|
||||||
|
const Vector3 newToSecond = pointToKeepEdgeV2.localPoint1 - element.localPoint1;
|
||||||
|
|
||||||
|
// Compute the triangle area
|
||||||
|
const decimal area = newToFirst.cross(newToSecond).dot(contactNormalShape1Space);
|
||||||
|
|
||||||
|
// We are looking at the triangle with maximal area (positive or negative).
|
||||||
|
// If the previous area is positive, we are looking at negative area now.
|
||||||
|
// If the previous area is negative, we are looking at the positive area now.
|
||||||
|
if (isPreviousAreaPositive && area <= largestArea) {
|
||||||
|
largestArea = area;
|
||||||
|
elementIndexToKeep = i;
|
||||||
|
nbReducedPoints = 4;
|
||||||
|
}
|
||||||
|
else if (!isPreviousAreaPositive && area >= largestArea) {
|
||||||
|
largestArea = area;
|
||||||
|
elementIndexToKeep = i;
|
||||||
|
nbReducedPoints = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pointsToKeepIndices[3] = candidatePointsIndices[elementIndexToKeep];
|
||||||
|
candidatePointsIndices.removeAt(elementIndexToKeep);
|
||||||
|
assert(nbReducedPoints == 4);
|
||||||
|
|
||||||
|
// Only keep the four selected contact points in the manifold
|
||||||
|
manifold.potentialContactPointsIndices.clear();
|
||||||
|
manifold.potentialContactPointsIndices.add(pointsToKeepIndices[0]);
|
||||||
|
manifold.potentialContactPointsIndices.add(pointsToKeepIndices[1]);
|
||||||
|
manifold.potentialContactPointsIndices.add(pointsToKeepIndices[2]);
|
||||||
|
manifold.potentialContactPointsIndices.add(pointsToKeepIndices[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report contacts for all the colliding overlapping pairs
|
// Report contacts for all the colliding overlapping pairs
|
||||||
|
@ -814,7 +1374,7 @@ void CollisionDetection::testCollision(CollisionBody* body1, CollisionBody* body
|
||||||
processAllPotentialContacts(narrowPhaseInput, false);
|
processAllPotentialContacts(narrowPhaseInput, false);
|
||||||
|
|
||||||
// Reduce the number of contact points in the manifolds
|
// Reduce the number of contact points in the manifolds
|
||||||
reduceContactManifolds(overlappingPairs);
|
reducePotentialContactManifolds(overlappingPairs);
|
||||||
|
|
||||||
// For each overlapping pair
|
// For each overlapping pair
|
||||||
for (auto it = overlappingPairs.begin(); it != overlappingPairs.end(); ++it) {
|
for (auto it = overlappingPairs.begin(); it != overlappingPairs.end(); ++it) {
|
||||||
|
@ -909,7 +1469,7 @@ void CollisionDetection::testCollision(CollisionBody* body, CollisionCallback* c
|
||||||
processAllPotentialContacts(narrowPhaseInput, false);
|
processAllPotentialContacts(narrowPhaseInput, false);
|
||||||
|
|
||||||
// Reduce the number of contact points in the manifolds
|
// Reduce the number of contact points in the manifolds
|
||||||
reduceContactManifolds(overlappingPairs);
|
reducePotentialContactManifolds(overlappingPairs);
|
||||||
|
|
||||||
// For each overlapping pair
|
// For each overlapping pair
|
||||||
for (auto it = overlappingPairs.begin(); it != overlappingPairs.end(); ++it) {
|
for (auto it = overlappingPairs.begin(); it != overlappingPairs.end(); ++it) {
|
||||||
|
@ -988,7 +1548,7 @@ void CollisionDetection::testCollision(CollisionCallback* callback) {
|
||||||
processAllPotentialContacts(narrowPhaseInput, false);
|
processAllPotentialContacts(narrowPhaseInput, false);
|
||||||
|
|
||||||
// Reduce the number of contact points in the manifolds
|
// Reduce the number of contact points in the manifolds
|
||||||
reduceContactManifolds(overlappingPairs);
|
reducePotentialContactManifolds(overlappingPairs);
|
||||||
|
|
||||||
// For each overlapping pair
|
// For each overlapping pair
|
||||||
for (auto it = overlappingPairs.begin(); it != overlappingPairs.end(); ++it) {
|
for (auto it = overlappingPairs.begin(); it != overlappingPairs.end(); ++it) {
|
||||||
|
|
|
@ -30,6 +30,11 @@
|
||||||
#include "body/CollisionBody.h"
|
#include "body/CollisionBody.h"
|
||||||
#include "systems/BroadPhaseSystem.h"
|
#include "systems/BroadPhaseSystem.h"
|
||||||
#include "collision/shapes/CollisionShape.h"
|
#include "collision/shapes/CollisionShape.h"
|
||||||
|
#include "collision/ContactPointInfo.h"
|
||||||
|
#include "constraint/ContactPoint.h"
|
||||||
|
#include "collision/ContactManifoldInfo.h"
|
||||||
|
#include "collision/ContactManifold.h"
|
||||||
|
#include "collision/ContactPair.h"
|
||||||
#include "engine/OverlappingPair.h"
|
#include "engine/OverlappingPair.h"
|
||||||
#include "collision/narrowphase/NarrowPhaseInput.h"
|
#include "collision/narrowphase/NarrowPhaseInput.h"
|
||||||
#include "collision/narrowphase/CollisionDispatch.h"
|
#include "collision/narrowphase/CollisionDispatch.h"
|
||||||
|
@ -64,6 +69,11 @@ class CollisionDetection {
|
||||||
|
|
||||||
using OverlappingPairMap = Map<Pair<uint, uint>, OverlappingPair*>;
|
using OverlappingPairMap = Map<Pair<uint, uint>, OverlappingPair*>;
|
||||||
|
|
||||||
|
// -------------------- Constants -------------------- //
|
||||||
|
|
||||||
|
/// Maximum number of contact points in a reduced contact manifold
|
||||||
|
const int8 MAX_CONTACT_POINTS_IN_MANIFOLD = 4;
|
||||||
|
|
||||||
// -------------------- Attributes -------------------- //
|
// -------------------- Attributes -------------------- //
|
||||||
|
|
||||||
/// Memory manager
|
/// Memory manager
|
||||||
|
@ -96,6 +106,62 @@ class CollisionDetection {
|
||||||
/// Narrow-phase collision detection input
|
/// Narrow-phase collision detection input
|
||||||
NarrowPhaseInput mNarrowPhaseInput;
|
NarrowPhaseInput mNarrowPhaseInput;
|
||||||
|
|
||||||
|
/// List of the potential contact points
|
||||||
|
List<ContactPointInfo> mPotentialContactPoints;
|
||||||
|
|
||||||
|
/// List of the potential contact manifolds
|
||||||
|
List<ContactManifoldInfo> mPotentialContactManifolds;
|
||||||
|
|
||||||
|
/// First list of narrow-phase pair contacts
|
||||||
|
List<ContactPair> mContactPairs1;
|
||||||
|
|
||||||
|
/// Second list of narrow-phase pair contacts
|
||||||
|
List<ContactPair> mContactPairs2;
|
||||||
|
|
||||||
|
/// Pointer to the list of contact pairs of the previous frame (either mContactPairs1 or mContactPairs2)
|
||||||
|
List<ContactPair>* mPreviousContactPairs;
|
||||||
|
|
||||||
|
/// Pointer to the list of contact pairs of the current frame (either mContactPairs1 or mContactPairs2)
|
||||||
|
List<ContactPair>* mCurrentContactPairs;
|
||||||
|
|
||||||
|
/// First map of overlapping pair id to the index of the corresponding pair contact
|
||||||
|
Map<OverlappingPair::OverlappingPairId, uint> mMapPairIdToContactPairIndex1;
|
||||||
|
|
||||||
|
/// Second map of overlapping pair id to the index of the corresponding pair contact
|
||||||
|
Map<OverlappingPair::OverlappingPairId, uint> mMapPairIdToContactPairIndex2;
|
||||||
|
|
||||||
|
/// Pointer to the map of overlappingPairId to the index of contact pair of the previous frame
|
||||||
|
/// (either mMapPairIdToContactPairIndex1 or mMapPairIdToContactPairIndex2)
|
||||||
|
Map<OverlappingPair::OverlappingPairId, uint>* mPreviousMapPairIdToContactPairIndex;
|
||||||
|
|
||||||
|
/// Pointer to the map of overlappingPairId to the index of contact pair of the current frame
|
||||||
|
/// (either mMapPairIdToContactPairIndex1 or mMapPairIdToContactPairIndex2)
|
||||||
|
Map<OverlappingPair::OverlappingPairId, uint>* mCurrentMapPairIdToContactPairIndex;
|
||||||
|
|
||||||
|
/// First list with the contact manifolds
|
||||||
|
List<ContactManifold> mContactManifolds1;
|
||||||
|
|
||||||
|
/// Second list with the contact manifolds
|
||||||
|
List<ContactManifold> mContactManifolds2;
|
||||||
|
|
||||||
|
/// Pointer to the list of contact manifolds from the previous frame (either mContactManifolds1 or mContactManifolds2)
|
||||||
|
List<ContactManifold>* mPreviousContactManifolds;
|
||||||
|
|
||||||
|
/// Pointer to the list of contact manifolds from the current frame (either mContactManifolds1 or mContactManifolds2)
|
||||||
|
List<ContactManifold>* mCurrentContactManifolds;
|
||||||
|
|
||||||
|
/// Second list of contact points (contact points from either the current frame of the previous frame)
|
||||||
|
List<ContactPoint> mContactPoints1;
|
||||||
|
|
||||||
|
/// Second list of contact points (contact points from either the current frame of the previous frame)
|
||||||
|
List<ContactPoint> mContactPoints2;
|
||||||
|
|
||||||
|
/// Pointer to the contact points of the previous frame (either mContactPoints1 or mContactPoints2)
|
||||||
|
List<ContactPoint>* mPreviousContactPoints;
|
||||||
|
|
||||||
|
/// Pointer to the contact points of the current frame (either mContactPoints1 or mContactPoints2)
|
||||||
|
List<ContactPoint>* mCurrentContactPoints;
|
||||||
|
|
||||||
#ifdef IS_PROFILING_ACTIVE
|
#ifdef IS_PROFILING_ACTIVE
|
||||||
|
|
||||||
/// Pointer to the profiler
|
/// Pointer to the profiler
|
||||||
|
@ -135,6 +201,9 @@ class CollisionDetection {
|
||||||
/// Compute the middle-phase collision detection between two proxy shapes
|
/// Compute the middle-phase collision detection between two proxy shapes
|
||||||
void computeMiddlePhaseForProxyShapes(OverlappingPair* pair, NarrowPhaseInput& outNarrowPhaseInput);
|
void computeMiddlePhaseForProxyShapes(OverlappingPair* pair, NarrowPhaseInput& outNarrowPhaseInput);
|
||||||
|
|
||||||
|
/// Swap the previous and current contacts lists
|
||||||
|
void swapPreviousAndCurrentContacts();
|
||||||
|
|
||||||
/// Convert the potential contact into actual contacts
|
/// Convert the potential contact into actual contacts
|
||||||
void processPotentialContacts(NarrowPhaseInfoBatch& narrowPhaseInfoBatch,
|
void processPotentialContacts(NarrowPhaseInfoBatch& narrowPhaseInfoBatch,
|
||||||
bool updateLastFrameInfo);
|
bool updateLastFrameInfo);
|
||||||
|
@ -142,12 +211,24 @@ class CollisionDetection {
|
||||||
/// Process the potential contacts after narrow-phase collision detection
|
/// Process the potential contacts after narrow-phase collision detection
|
||||||
void processAllPotentialContacts(NarrowPhaseInput& narrowPhaseInput, bool updateLastFrameInfo);
|
void processAllPotentialContacts(NarrowPhaseInput& narrowPhaseInput, bool updateLastFrameInfo);
|
||||||
|
|
||||||
/// Clear the obsolete manifolds and contact points and reduce the number of contacts points of the remaining manifolds
|
/// Reduce the potential contact manifolds and contact points of the overlapping pair contacts
|
||||||
void reduceContactManifolds(const OverlappingPairMap& overlappingPairs);
|
void reducePotentialContactManifolds(const OverlappingPairMap& overlappingPairs);
|
||||||
|
|
||||||
|
/// Create the actual contact manifolds and contacts (from potential contacts)
|
||||||
|
void createContacts();
|
||||||
|
|
||||||
|
/// Initialize the current contacts with the contacts from the previous frame (for warmstarting)
|
||||||
|
void initContactsWithPreviousOnes();
|
||||||
|
|
||||||
|
/// Reduce the number of contact points of a potential contact manifold
|
||||||
|
void reduceContactPoints(ContactManifoldInfo& manifold, const Transform& shape1ToWorldTransform);
|
||||||
|
|
||||||
/// Report contacts for all the colliding overlapping pairs
|
/// Report contacts for all the colliding overlapping pairs
|
||||||
void reportAllContacts();
|
void reportAllContacts();
|
||||||
|
|
||||||
|
/// Return the largest depth of all the contact points of a potential manifold
|
||||||
|
decimal computePotentialManifoldLargestContactDepth(const ContactManifoldInfo& manifold) const;
|
||||||
|
|
||||||
/// Process the potential contacts where one collion is a concave shape
|
/// Process the potential contacts where one collion is a concave shape
|
||||||
void processSmoothMeshContacts(OverlappingPair* pair);
|
void processSmoothMeshContacts(OverlappingPair* pair);
|
||||||
|
|
||||||
|
|
|
@ -26,20 +26,35 @@
|
||||||
// Libraries
|
// Libraries
|
||||||
#include "ContactManifold.h"
|
#include "ContactManifold.h"
|
||||||
#include "constraint/ContactPoint.h"
|
#include "constraint/ContactPoint.h"
|
||||||
|
#include "collision/ContactManifoldInfo.h"
|
||||||
|
|
||||||
using namespace reactphysics3d;
|
using namespace reactphysics3d;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
|
// TODO : REMOVE THIS CONSTRUCTOR
|
||||||
ContactManifold::ContactManifold(ProxyShape* shape1, ProxyShape* shape2,
|
ContactManifold::ContactManifold(ProxyShape* shape1, ProxyShape* shape2,
|
||||||
MemoryAllocator& memoryAllocator, const WorldSettings& worldSettings)
|
MemoryAllocator& memoryAllocator, const WorldSettings& worldSettings)
|
||||||
: mShape1(shape1), mShape2(shape2), mContactPoints(nullptr),
|
: mMemoryAllocator(memoryAllocator), mContactPointsIndex(0), mShape1(shape1), mShape2(shape2), mContactPoints(nullptr),
|
||||||
mNbContactPoints(0), mFrictionImpulse1(0.0), mFrictionImpulse2(0.0),
|
mNbContactPoints(0), mFrictionImpulse1(0.0), mFrictionImpulse2(0.0),
|
||||||
mFrictionTwistImpulse(0.0), mIsAlreadyInIsland(false),
|
mFrictionTwistImpulse(0.0), mIsAlreadyInIsland(false),
|
||||||
mMemoryAllocator(memoryAllocator), mNext(nullptr), mPrevious(nullptr), mIsObsolete(false),
|
mNext(nullptr), mPrevious(nullptr), mIsObsolete(false),
|
||||||
mWorldSettings(worldSettings) {
|
mWorldSettings(worldSettings) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
// TODO : REMOVE worldSettings from this constructor
|
||||||
|
ContactManifold::ContactManifold(uint contactPointsIndex, int8 nbContactPoints, MemoryAllocator& allocator, const WorldSettings& worldSettings)
|
||||||
|
:mMemoryAllocator(allocator), mContactPointsIndex(0), mWorldSettings(worldSettings) {
|
||||||
|
|
||||||
|
|
||||||
|
mContactPoints = nullptr;
|
||||||
|
mNext = nullptr;
|
||||||
|
mPrevious = nullptr;
|
||||||
|
mContactPointsIndex = contactPointsIndex;
|
||||||
|
mNbContactPoints = nbContactPoints;
|
||||||
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
ContactManifold::~ContactManifold() {
|
ContactManifold::~ContactManifold() {
|
||||||
|
|
||||||
|
@ -192,6 +207,7 @@ void ContactManifold::clearObsoleteContactPoints() {
|
||||||
// This is based on the technique described by Dirk Gregorius in his
|
// This is based on the technique described by Dirk Gregorius in his
|
||||||
// "Contacts Creation" GDC presentation. This method will reduce the number of
|
// "Contacts Creation" GDC presentation. This method will reduce the number of
|
||||||
// contact points to a maximum of 4 points (but it can be less).
|
// contact points to a maximum of 4 points (but it can be less).
|
||||||
|
// TODO : REMOVE THIS METHOD
|
||||||
void ContactManifold::reduce(const Transform& shape1ToWorldTransform) {
|
void ContactManifold::reduce(const Transform& shape1ToWorldTransform) {
|
||||||
|
|
||||||
assert(mContactPoints != nullptr);
|
assert(mContactPoints != nullptr);
|
||||||
|
|
|
@ -100,6 +100,14 @@ class ContactManifold {
|
||||||
|
|
||||||
// -------------------- Attributes -------------------- //
|
// -------------------- Attributes -------------------- //
|
||||||
|
|
||||||
|
// TODO : For each of the attributes, check if we need to keep it or not
|
||||||
|
|
||||||
|
/// Reference to the memory allocator
|
||||||
|
MemoryAllocator& mMemoryAllocator;
|
||||||
|
|
||||||
|
/// Index of the first contact point of the manifold in the list of contact points
|
||||||
|
uint mContactPointsIndex;
|
||||||
|
|
||||||
/// Pointer to the first proxy shape of the contact
|
/// Pointer to the first proxy shape of the contact
|
||||||
ProxyShape* mShape1;
|
ProxyShape* mShape1;
|
||||||
|
|
||||||
|
@ -133,9 +141,6 @@ class ContactManifold {
|
||||||
/// True if the contact manifold has already been added into an island
|
/// True if the contact manifold has already been added into an island
|
||||||
bool mIsAlreadyInIsland;
|
bool mIsAlreadyInIsland;
|
||||||
|
|
||||||
/// Reference to the memory allocator
|
|
||||||
MemoryAllocator& mMemoryAllocator;
|
|
||||||
|
|
||||||
/// Pointer to the next contact manifold in the linked-list
|
/// Pointer to the next contact manifold in the linked-list
|
||||||
ContactManifold* mNext;
|
ContactManifold* mNext;
|
||||||
|
|
||||||
|
@ -224,14 +229,17 @@ class ContactManifold {
|
||||||
ContactManifold(ProxyShape* shape1, ProxyShape* shape2, MemoryAllocator& memoryAllocator,
|
ContactManifold(ProxyShape* shape1, ProxyShape* shape2, MemoryAllocator& memoryAllocator,
|
||||||
const WorldSettings& worldSettings);
|
const WorldSettings& worldSettings);
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
ContactManifold(uint contactPointsIndex, int8 nbContactPoints, MemoryAllocator& allocator, const WorldSettings& worldSettings);
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~ContactManifold();
|
~ContactManifold();
|
||||||
|
|
||||||
/// Deleted copy-constructor
|
/// Copy-constructor
|
||||||
ContactManifold(const ContactManifold& contactManifold) = delete;
|
ContactManifold(const ContactManifold& contactManifold) = default;
|
||||||
|
|
||||||
/// Deleted assignment operator
|
/// Assignment operator
|
||||||
ContactManifold& operator=(const ContactManifold& contactManifold) = delete;
|
ContactManifold& operator=(const ContactManifold& contactManifold) = default;
|
||||||
|
|
||||||
/// Return a pointer to the first proxy shape of the contact
|
/// Return a pointer to the first proxy shape of the contact
|
||||||
ProxyShape* getShape1() const;
|
ProxyShape* getShape1() const;
|
||||||
|
@ -264,6 +272,7 @@ class ContactManifold {
|
||||||
friend class CollisionBody;
|
friend class CollisionBody;
|
||||||
friend class ContactManifoldSet;
|
friend class ContactManifoldSet;
|
||||||
friend class ContactSolver;
|
friend class ContactSolver;
|
||||||
|
friend class CollisionDetection;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return a pointer to the first proxy shape of the contact
|
// Return a pointer to the first proxy shape of the contact
|
||||||
|
|
67
src/collision/ContactManifoldInfo.h
Normal file
67
src/collision/ContactManifoldInfo.h
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/********************************************************************************
|
||||||
|
* 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_CONTACT_MANIFOLD_INFO_H
|
||||||
|
#define REACTPHYSICS3D_CONTACT_MANIFOLD_INFO_H
|
||||||
|
|
||||||
|
// Libraries
|
||||||
|
#include "mathematics/mathematics.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
#include "engine/OverlappingPair.h"
|
||||||
|
|
||||||
|
/// ReactPhysics3D namespace
|
||||||
|
namespace reactphysics3d {
|
||||||
|
|
||||||
|
// Structure ContactManifoldInfo
|
||||||
|
/**
|
||||||
|
* This structure contains informations about a collision contact
|
||||||
|
* manifold computed during the narrow-phase collision detection.
|
||||||
|
*/
|
||||||
|
struct ContactManifoldInfo {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// -------------------- Attributes -------------------- //
|
||||||
|
|
||||||
|
/// Indices of the contact points in the mPotentialContactPoints array
|
||||||
|
List<uint> potentialContactPointsIndices;
|
||||||
|
|
||||||
|
/// Overlapping pair id
|
||||||
|
OverlappingPair::OverlappingPairId pairId;
|
||||||
|
|
||||||
|
// -------------------- Methods -------------------- //
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
ContactManifoldInfo(OverlappingPair::OverlappingPairId pairId, MemoryAllocator& allocator)
|
||||||
|
: potentialContactPointsIndices(allocator), pairId(pairId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -110,8 +110,12 @@ int ContactManifoldSet::getTotalNbContactPoints() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the maximum number of contact manifolds allowed between to collision shapes
|
// Return the maximum number of contact manifolds allowed between to collision shapes
|
||||||
|
// TODO : Remove this method
|
||||||
int ContactManifoldSet::computeNbMaxContactManifolds(const CollisionShape* shape1, const CollisionShape* shape2) {
|
int ContactManifoldSet::computeNbMaxContactManifolds(const CollisionShape* shape1, const CollisionShape* shape2) {
|
||||||
|
|
||||||
|
return mWorldSettings.nbMaxContactManifolds;
|
||||||
|
|
||||||
|
/*
|
||||||
// If both shapes are convex
|
// If both shapes are convex
|
||||||
if (shape1->isConvex() && shape2->isConvex()) {
|
if (shape1->isConvex() && shape2->isConvex()) {
|
||||||
return mWorldSettings.nbMaxContactManifoldsConvexShape;
|
return mWorldSettings.nbMaxContactManifoldsConvexShape;
|
||||||
|
@ -120,6 +124,7 @@ int ContactManifoldSet::computeNbMaxContactManifolds(const CollisionShape* shape
|
||||||
else {
|
else {
|
||||||
return mWorldSettings.nbMaxContactManifoldsConcaveShape;
|
return mWorldSettings.nbMaxContactManifoldsConcaveShape;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove a contact manifold that is the least optimal (smaller penetration depth)
|
// Remove a contact manifold that is the least optimal (smaller penetration depth)
|
||||||
|
|
|
@ -33,7 +33,6 @@ namespace reactphysics3d {
|
||||||
|
|
||||||
// Declarations
|
// Declarations
|
||||||
class ContactManifold;
|
class ContactManifold;
|
||||||
class ContactManifoldInfo;
|
|
||||||
class ProxyShape;
|
class ProxyShape;
|
||||||
class MemoryAllocator;
|
class MemoryAllocator;
|
||||||
struct WorldSettings;
|
struct WorldSettings;
|
||||||
|
|
77
src/collision/ContactPair.h
Normal file
77
src/collision/ContactPair.h
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/********************************************************************************
|
||||||
|
* 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_OVERLAPPING_PAIR_CONTACT_H
|
||||||
|
#define REACTPHYSICS3D_OVERLAPPING_PAIR_CONTACT_H
|
||||||
|
|
||||||
|
// Libraries
|
||||||
|
#include "mathematics/mathematics.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
#include "engine/OverlappingPair.h"
|
||||||
|
|
||||||
|
/// ReactPhysics3D namespace
|
||||||
|
namespace reactphysics3d {
|
||||||
|
|
||||||
|
// Structure ContactPair
|
||||||
|
/**
|
||||||
|
* This structure represents a pair of shapes that are in contact during narrow-phase.
|
||||||
|
*/
|
||||||
|
struct ContactPair {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// -------------------- Attributes -------------------- //
|
||||||
|
|
||||||
|
/// Overlapping pair Id
|
||||||
|
OverlappingPair::OverlappingPairId pairId;
|
||||||
|
|
||||||
|
/// Indices of the potential contact manifolds
|
||||||
|
List<uint> potentialContactManifoldsIndices;
|
||||||
|
|
||||||
|
/// Index of the first contact manifold in the array
|
||||||
|
uint contactManifoldsIndex;
|
||||||
|
|
||||||
|
/// Number of contact manifolds
|
||||||
|
int8 nbContactManifolds;
|
||||||
|
|
||||||
|
/// Index of the first contact point in the array of contact points
|
||||||
|
uint contactPointsIndex;
|
||||||
|
|
||||||
|
/// Total number of contact points in all the manifolds of the contact pair
|
||||||
|
uint nbToTalContactPoints;
|
||||||
|
|
||||||
|
// -------------------- Methods -------------------- //
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
ContactPair(OverlappingPair::OverlappingPairId pairId, MemoryAllocator& allocator)
|
||||||
|
: pairId(pairId), potentialContactManifoldsIndices(allocator), contactManifoldsIndex(0), nbContactManifolds(0),
|
||||||
|
contactPointsIndex(0), nbToTalContactPoints(0) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -65,9 +65,11 @@ struct ContactPointInfo {
|
||||||
/// Contact point of body 2 in local space of body 2
|
/// Contact point of body 2 in local space of body 2
|
||||||
Vector3 localPoint2;
|
Vector3 localPoint2;
|
||||||
|
|
||||||
|
// TODO : Remove this field
|
||||||
/// Pointer to the next contact point info
|
/// Pointer to the next contact point info
|
||||||
ContactPointInfo* next;
|
ContactPointInfo* next;
|
||||||
|
|
||||||
|
// TODO : Remove this field
|
||||||
/// True if the contact point has already been inserted into a manifold
|
/// True if the contact point has already been inserted into a manifold
|
||||||
bool isUsed;
|
bool isUsed;
|
||||||
|
|
||||||
|
|
|
@ -154,13 +154,8 @@ struct WorldSettings {
|
||||||
/// might enter sleeping mode
|
/// might enter sleeping mode
|
||||||
decimal defaultSleepAngularVelocity = decimal(3.0) * (PI / decimal(180.0));
|
decimal defaultSleepAngularVelocity = decimal(3.0) * (PI / decimal(180.0));
|
||||||
|
|
||||||
/// Maximum number of contact manifolds in an overlapping pair that involves two
|
/// Maximum number of contact manifolds in an overlapping pair
|
||||||
/// convex collision shapes.
|
uint nbMaxContactManifolds = 3;
|
||||||
int nbMaxContactManifoldsConvexShape = 1;
|
|
||||||
|
|
||||||
/// Maximum number of contact manifolds in an overlapping pair that involves at
|
|
||||||
/// least one concave collision shape.
|
|
||||||
int nbMaxContactManifoldsConcaveShape = 3;
|
|
||||||
|
|
||||||
/// This is used to test if two contact manifold are similar (same contact normal) in order to
|
/// This is used to test if two contact manifold are similar (same contact normal) in order to
|
||||||
/// merge them. If the cosine of the angle between the normals of the two manifold are larger
|
/// merge them. If the cosine of the angle between the normals of the two manifold are larger
|
||||||
|
@ -184,8 +179,7 @@ struct WorldSettings {
|
||||||
ss << "defaultTimeBeforeSleep=" << defaultTimeBeforeSleep << std::endl;
|
ss << "defaultTimeBeforeSleep=" << defaultTimeBeforeSleep << std::endl;
|
||||||
ss << "defaultSleepLinearVelocity=" << defaultSleepLinearVelocity << std::endl;
|
ss << "defaultSleepLinearVelocity=" << defaultSleepLinearVelocity << std::endl;
|
||||||
ss << "defaultSleepAngularVelocity=" << defaultSleepAngularVelocity << std::endl;
|
ss << "defaultSleepAngularVelocity=" << defaultSleepAngularVelocity << std::endl;
|
||||||
ss << "nbMaxContactManifoldsConvexShape=" << nbMaxContactManifoldsConvexShape << std::endl;
|
ss << "nbMaxContactManifolds=" << nbMaxContactManifolds << std::endl;
|
||||||
ss << "nbMaxContactManifoldsConcaveShape=" << nbMaxContactManifoldsConcaveShape << std::endl;
|
|
||||||
ss << "cosAngleSimilarContactManifold=" << cosAngleSimilarContactManifold << std::endl;
|
ss << "cosAngleSimilarContactManifold=" << cosAngleSimilarContactManifold << std::endl;
|
||||||
|
|
||||||
return ss.str();
|
return ss.str();
|
||||||
|
|
|
@ -45,6 +45,21 @@ ContactPoint::ContactPoint(const ContactPointInfo* contactInfo, const WorldSetti
|
||||||
mIsObsolete = false;
|
mIsObsolete = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
ContactPoint::ContactPoint(const ContactPointInfo& contactInfo, const WorldSettings& worldSettings)
|
||||||
|
: mNormal(contactInfo.normal),
|
||||||
|
mPenetrationDepth(contactInfo.penetrationDepth),
|
||||||
|
mLocalPointOnShape1(contactInfo.localPoint1),
|
||||||
|
mLocalPointOnShape2(contactInfo.localPoint2),
|
||||||
|
mIsRestingContact(false), mIsObsolete(false),
|
||||||
|
mWorldSettings(worldSettings) {
|
||||||
|
|
||||||
|
assert(mPenetrationDepth > decimal(0.0));
|
||||||
|
assert(mNormal.lengthSquare() > decimal(0.8));
|
||||||
|
|
||||||
|
mIsObsolete = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Update the contact point with a new one that is similar (very close)
|
// Update the contact point with a new one that is similar (very close)
|
||||||
/// The idea is to keep the cache impulse (for warm starting the contact solver)
|
/// The idea is to keep the cache impulse (for warm starting the contact solver)
|
||||||
void ContactPoint::update(const ContactPointInfo* contactInfo) {
|
void ContactPoint::update(const ContactPointInfo* contactInfo) {
|
||||||
|
|
|
@ -112,17 +112,20 @@ class ContactPoint {
|
||||||
/// Constructor
|
/// Constructor
|
||||||
ContactPoint(const ContactPointInfo* contactInfo, const WorldSettings& worldSettings);
|
ContactPoint(const ContactPointInfo* contactInfo, const WorldSettings& worldSettings);
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
ContactPoint(const ContactPointInfo& contactInfo, const WorldSettings& worldSettings);
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~ContactPoint() = default;
|
~ContactPoint() = default;
|
||||||
|
|
||||||
/// Deleted copy-constructor
|
/// Copy-constructor
|
||||||
ContactPoint(const ContactPoint& contact) = delete;
|
ContactPoint(const ContactPoint& contact) = default;
|
||||||
|
|
||||||
/// Deleted assignment operator
|
/// Assignment operator
|
||||||
ContactPoint& operator=(const ContactPoint& contact) = delete;
|
ContactPoint& operator=(const ContactPoint& contact) = default;
|
||||||
|
|
||||||
/// Return the normal vector of the contact
|
/// Return the normal vector of the contact
|
||||||
Vector3 getNormal() const;
|
const Vector3& getNormal() const;
|
||||||
|
|
||||||
/// Return the contact point on the first proxy shape in the local-space of the proxy shape
|
/// Return the contact point on the first proxy shape in the local-space of the proxy shape
|
||||||
const Vector3& getLocalPointOnShape1() const;
|
const Vector3& getLocalPointOnShape1() const;
|
||||||
|
@ -152,13 +155,14 @@ class ContactPoint {
|
||||||
friend class ContactManifold;
|
friend class ContactManifold;
|
||||||
friend class ContactManifoldSet;
|
friend class ContactManifoldSet;
|
||||||
friend class ContactSolver;
|
friend class ContactSolver;
|
||||||
|
friend class CollisionDetection;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return the normal vector of the contact
|
// Return the normal vector of the contact
|
||||||
/**
|
/**
|
||||||
* @return The contact normal
|
* @return The contact normal
|
||||||
*/
|
*/
|
||||||
inline Vector3 ContactPoint::getNormal() const {
|
inline const Vector3& ContactPoint::getNormal() const {
|
||||||
return mNormal;
|
return mNormal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -146,6 +146,9 @@ class OverlappingPair {
|
||||||
/// Deleted assignment operator
|
/// Deleted assignment operator
|
||||||
OverlappingPair& operator=(const OverlappingPair& pair) = delete;
|
OverlappingPair& operator=(const OverlappingPair& pair) = delete;
|
||||||
|
|
||||||
|
/// Return the Id of the pair
|
||||||
|
OverlappingPairId getId() const;
|
||||||
|
|
||||||
/// Return the pointer to first proxy collision shape
|
/// Return the pointer to first proxy collision shape
|
||||||
ProxyShape* getShape1() const;
|
ProxyShape* getShape1() const;
|
||||||
|
|
||||||
|
@ -202,6 +205,11 @@ class OverlappingPair {
|
||||||
friend class DynamicsWorld;
|
friend class DynamicsWorld;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Return the Id of the pair
|
||||||
|
inline OverlappingPair::OverlappingPairId OverlappingPair::getId() const {
|
||||||
|
return mPairID;
|
||||||
|
}
|
||||||
|
|
||||||
// Return the pointer to first body
|
// Return the pointer to first body
|
||||||
inline ProxyShape* OverlappingPair::getShape1() const {
|
inline ProxyShape* OverlappingPair::getShape1() const {
|
||||||
return mContactManifoldSet.getShape1();
|
return mContactManifoldSet.getShape1();
|
||||||
|
|
|
@ -50,6 +50,10 @@ class DefaultAllocator : public MemoryAllocator {
|
||||||
/// Allocate memory of a given size (in bytes) and return a pointer to the
|
/// Allocate memory of a given size (in bytes) and return a pointer to the
|
||||||
/// allocated memory.
|
/// allocated memory.
|
||||||
virtual void* allocate(size_t size) override {
|
virtual void* allocate(size_t size) override {
|
||||||
|
|
||||||
|
// TODO : Make sure to reduce the calls to default allocator is not called within a frame. For instance by a call
|
||||||
|
// to a pool allocator with size too large
|
||||||
|
|
||||||
return malloc(size);
|
return malloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user