Merge branch 'logs' into develop

This commit is contained in:
Daniel Chappuis 2018-03-28 22:55:32 +02:00
commit b1e5c029f7
91 changed files with 1922 additions and 668 deletions

View File

@ -21,6 +21,7 @@ ENABLE_TESTING()
OPTION(COMPILE_TESTBED "Select this if you want to build the testbed application" OFF)
OPTION(COMPILE_TESTS "Select this if you want to build the tests" OFF)
OPTION(PROFILING_ENABLED "Select this if you want to compile with enabled profiling" OFF)
OPTION(LOGS_ENABLED "Select this if you want to compile with logs enabled during execution" OFF)
OPTION(DOUBLE_PRECISION_ENABLED "Select this if you want to compile using double precision floating
values" OFF)
@ -45,6 +46,10 @@ IF(PROFILING_ENABLED)
ADD_DEFINITIONS(-DIS_PROFILING_ACTIVE)
ENDIF(PROFILING_ENABLED)
IF(LOGS_ENABLED)
ADD_DEFINITIONS(-DIS_LOGGING_ACTIVE)
ENDIF(LOGS_ENABLED)
IF(DOUBLE_PRECISION_ENABLED)
ADD_DEFINITIONS(-DIS_DOUBLE_PRECISION_ENABLED)
ENDIF(DOUBLE_PRECISION_ENABLED)
@ -164,8 +169,6 @@ SET (REACTPHYSICS3D_SOURCES
"src/engine/Material.cpp"
"src/engine/OverlappingPair.h"
"src/engine/OverlappingPair.cpp"
"src/engine/Profiler.h"
"src/engine/Profiler.cpp"
"src/engine/Timer.h"
"src/engine/Timer.cpp"
"src/collision/CollisionCallback.h"
@ -201,6 +204,10 @@ SET (REACTPHYSICS3D_SOURCES
"src/containers/Map.h"
"src/containers/Set.h"
"src/containers/Pair.h"
"src/utils/Profiler.h"
"src/utils/Profiler.cpp"
"src/utils/Logger.h"
"src/utils/Logger.cpp"
)
# Create the library

View File

@ -30,6 +30,7 @@
#include <stdexcept>
#include <cassert>
#include "configuration.h"
#include "utils/Logger.h"
/// Namespace reactphysics3d
namespace reactphysics3d {
@ -75,6 +76,12 @@ class Body {
/// Pointer that can be used to attach user data to the body
void* mUserData;
#ifdef IS_LOGGING_ACTIVE
/// Logger
Logger* mLogger;
#endif
public :
// -------------------- Methods -------------------- //
@ -92,7 +99,7 @@ class Body {
virtual ~Body() = default;
/// Return the ID of the body
bodyindex getID() const;
bodyindex getId() const;
/// Return whether or not the body is allowed to sleep
bool isAllowedToSleep() const;
@ -118,6 +125,12 @@ class Body {
/// Attach user data to this body
void setUserData(void* userData);
#ifdef IS_LOGGING_ACTIVE
/// Set the logger
void setLogger(Logger* logger);
#endif
/// Smaller than operator
bool operator<(const Body& body2) const;
@ -137,9 +150,9 @@ class Body {
// Return the id of the body
/**
* @return The ID of the body
* @return The id of the body
*/
inline bodyindex Body::getID() const {
inline bodyindex Body::getId() const {
return mID;
}
@ -159,6 +172,10 @@ inline void Body::setIsAllowedToSleep(bool isAllowedToSleep) {
mIsAllowedToSleep = isAllowedToSleep;
if (!mIsAllowedToSleep) setIsSleeping(false);
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Set isAllowedToSleep=" +
(mIsAllowedToSleep ? "true" : "false"));
}
// Return whether or not the body is sleeping
@ -183,6 +200,10 @@ inline bool Body::isActive() const {
*/
inline void Body::setIsActive(bool isActive) {
mIsActive = isActive;
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Set isActive=" +
(mIsActive ? "true" : "false"));
}
// Set the variable to know whether or not the body is sleeping
@ -197,7 +218,14 @@ inline void Body::setIsSleeping(bool isSleeping) {
}
}
if (mIsSleeping != isSleeping) {
mIsSleeping = isSleeping;
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Set isSleeping=" +
(mIsSleeping ? "true" : "false"));
}
}
// Return a pointer to the user data attached to this body
@ -216,6 +244,15 @@ inline void Body::setUserData(void* userData) {
mUserData = userData;
}
#ifdef IS_LOGGING_ACTIVE
// Set the logger
inline void Body::setLogger(Logger* logger) {
mLogger = logger;
}
#endif
// Smaller than operator
inline bool Body::operator<(const Body& body2) const {
return (mID < body2.mID);

View File

@ -79,6 +79,13 @@ ProxyShape* CollisionBody::addCollisionShape(CollisionShape* collisionShape,
// Set the profiler
proxyShape->setProfiler(mProfiler);
#endif
#ifdef IS_LOGGING_ACTIVE
// Set the logger
proxyShape->setLogger(mLogger);
#endif
// Add it to the list of proxy collision shapes of the body
@ -99,6 +106,13 @@ ProxyShape* CollisionBody::addCollisionShape(CollisionShape* collisionShape,
mNbCollisionShapes++;
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Proxy shape " + std::to_string(proxyShape->getBroadPhaseId()) + " added to body");
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::ProxyShape,
"ProxyShape " + std::to_string(proxyShape->getBroadPhaseId()) + ": collisionShape=" +
proxyShape->getCollisionShape()->to_string());
// Return a pointer to the collision shape
return proxyShape;
}
@ -114,11 +128,14 @@ void CollisionBody::removeCollisionShape(const ProxyShape* proxyShape) {
ProxyShape* current = mProxyCollisionShapes;
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Proxy shape " + std::to_string(proxyShape->getBroadPhaseId()) + " removed from body");
// If the the first proxy shape is the one to remove
if (current == proxyShape) {
mProxyCollisionShapes = current->mNext;
if (mIsActive && proxyShape->mBroadPhaseID != -1) {
if (mIsActive && proxyShape->getBroadPhaseId() != -1) {
mWorld.mCollisionDetection.removeProxyCollisionShape(current);
}
@ -138,7 +155,7 @@ void CollisionBody::removeCollisionShape(const ProxyShape* proxyShape) {
ProxyShape* elementToRemove = current->mNext;
current->mNext = elementToRemove->mNext;
if (mIsActive && proxyShape->mBroadPhaseID != -1) {
if (mIsActive && proxyShape->getBroadPhaseId() != -1) {
mWorld.mCollisionDetection.removeProxyCollisionShape(elementToRemove);
}
@ -164,7 +181,7 @@ void CollisionBody::removeAllCollisionShapes() {
// Remove the proxy collision shape
ProxyShape* nextElement = current->mNext;
if (mIsActive && current->mBroadPhaseID != -1) {
if (mIsActive && current->getBroadPhaseId() != -1) {
mWorld.mCollisionDetection.removeProxyCollisionShape(current);
}
@ -209,7 +226,7 @@ void CollisionBody::updateBroadPhaseState() const {
// Update the broad-phase state of a proxy collision shape of the body
void CollisionBody::updateProxyShapeInBroadPhase(ProxyShape* proxyShape, bool forceReinsert) const {
if (proxyShape->mBroadPhaseID != -1) {
if (proxyShape->getBroadPhaseId() != -1) {
// Recompute the world-space AABB of the collision shape
AABB aabb;
@ -250,7 +267,7 @@ void CollisionBody::setIsActive(bool isActive) {
// For each proxy shape of the body
for (ProxyShape* shape = mProxyCollisionShapes; shape != nullptr; shape = shape->mNext) {
if (shape->mBroadPhaseID != -1) {
if (shape->getBroadPhaseId() != -1) {
// Remove the proxy shape from the collision detection
mWorld.mCollisionDetection.removeProxyCollisionShape(shape);
@ -260,6 +277,10 @@ void CollisionBody::setIsActive(bool isActive) {
// Reset the contact manifold list of the body
resetContactManifoldsList();
}
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Set isActive=" +
(mIsActive ? "true" : "false"));
}
// Ask the broad-phase to test again the collision shapes of the body for collision

View File

@ -36,7 +36,7 @@
#include "collision/RaycastInfo.h"
#include "memory/PoolAllocator.h"
#include "configuration.h"
#include "engine/Profiler.h"
#include "utils/Profiler.h"
/// Namespace reactphysics3d
namespace reactphysics3d {
@ -231,6 +231,10 @@ inline void CollisionBody::setType(BodyType type) {
// Update the broad-phase state of the body
updateBroadPhaseState();
}
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Set type=" +
(mType == BodyType::STATIC ? "Static" : (mType == BodyType::DYNAMIC ? "Dynamic" : "Kinematic")));
}
// Return the current position and orientation
@ -254,6 +258,9 @@ inline void CollisionBody::setTransform(const Transform& transform) {
// Update the broad-phase state of the body
updateBroadPhaseState();
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Set transform=" + mTransform.to_string());
}
// Return the first element of the linked list of contact manifolds involving this body

View File

@ -139,6 +139,9 @@ void RigidBody::setInertiaTensorLocal(const Matrix3x3& inertiaTensorLocal) {
// Update the world inverse inertia tensor
updateInertiaTensorInverseWorld();
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Set inertiaTensorLocal=" + inertiaTensorLocal.to_string());
}
// Set the inverse local inertia tensor of the body (in local-space coordinates)
@ -160,6 +163,9 @@ void RigidBody::setInverseInertiaTensorLocal(const Matrix3x3& inverseInertiaTens
// Update the world inverse inertia tensor
updateInertiaTensorInverseWorld();
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Set inverseInertiaTensorLocal=" + inverseInertiaTensorLocal.to_string());
}
// Set the local center of mass of the body (in local-space coordinates)
@ -183,6 +189,9 @@ void RigidBody::setCenterOfMassLocal(const Vector3& centerOfMassLocal) {
// Update the linear velocity of the center of mass
mLinearVelocity += mAngularVelocity.cross(mCenterOfMassWorld - oldCenterOfMass);
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Set centerOfMassLocal=" + centerOfMassLocal.to_string());
}
// Set the mass of the rigid body
@ -202,6 +211,9 @@ void RigidBody::setMass(decimal mass) {
mInitMass = decimal(1.0);
mMassInverse = decimal(1.0);
}
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Set mass=" + std::to_string(mass));
}
// Remove a joint from the joints list
@ -264,6 +276,13 @@ ProxyShape* RigidBody::addCollisionShape(CollisionShape* collisionShape,
// Set the profiler
proxyShape->setProfiler(mProfiler);
#endif
#ifdef IS_LOGGING_ACTIVE
// Set the logger
proxyShape->setLogger(mLogger);
#endif
// Add it to the list of proxy collision shapes of the body
@ -288,6 +307,13 @@ ProxyShape* RigidBody::addCollisionShape(CollisionShape* collisionShape,
// collision shape
recomputeMassInformation();
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Proxy shape " + std::to_string(proxyShape->getBroadPhaseId()) + " added to body");
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::ProxyShape,
"ProxyShape " + std::to_string(proxyShape->getBroadPhaseId()) + ": collisionShape=" +
proxyShape->getCollisionShape()->to_string());
// Return a pointer to the proxy collision shape
return proxyShape;
}
@ -324,6 +350,9 @@ void RigidBody::setLinearVelocity(const Vector3& linearVelocity) {
if (mLinearVelocity.lengthSquare() > decimal(0.0)) {
setIsSleeping(false);
}
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Set linearVelocity=" + mLinearVelocity.to_string());
}
// Set the angular velocity.
@ -342,6 +371,9 @@ void RigidBody::setAngularVelocity(const Vector3& angularVelocity) {
if (mAngularVelocity.lengthSquare() > decimal(0.0)) {
setIsSleeping(false);
}
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Set angularVelocity=" + mAngularVelocity.to_string());
}
// Set the current position and orientation
@ -367,6 +399,9 @@ void RigidBody::setTransform(const Transform& transform) {
// Update the broad-phase state of the body
updateBroadPhaseState();
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Set transform=" + mTransform.to_string());
}
// Recompute the center of mass, total mass and inertia tensor of the body using all
@ -459,7 +494,7 @@ void RigidBody::recomputeMassInformation() {
// Update the broad-phase state for this body (because it has moved for instance)
void RigidBody::updateBroadPhaseState() const {
PROFILE("RigidBody::updateBroadPhaseState()", mProfiler);
RP3D_PROFILE("RigidBody::updateBroadPhaseState()", mProfiler);
DynamicsWorld& world = static_cast<DynamicsWorld&>(mWorld);
const Vector3 displacement = world.mTimeStep * mLinearVelocity;
@ -469,7 +504,7 @@ void RigidBody::updateBroadPhaseState() const {
// Recompute the world-space AABB of the collision shape
AABB aabb;
shape->getCollisionShape()->computeAABB(aabb, mTransform *shape->getLocalToBodyTransform());
shape->getCollisionShape()->computeAABB(aabb, mTransform * shape->getLocalToBodyTransform());
// Update the broad-phase state for the proxy collision shape
mWorld.mCollisionDetection.updateProxyCollisionShape(shape, aabb, displacement);
@ -494,4 +529,3 @@ void RigidBody::setProfiler(Profiler* profiler) {
}
#endif

View File

@ -325,6 +325,10 @@ inline bool RigidBody::isGravityEnabled() const {
*/
inline void RigidBody::enableGravity(bool isEnabled) {
mIsGravityEnabled = isEnabled;
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Set isGravityEnabled=" +
(mIsGravityEnabled ? "true" : "false"));
}
// Return a reference to the material properties of the rigid body
@ -341,6 +345,9 @@ inline Material& RigidBody::getMaterial() {
*/
inline void RigidBody::setMaterial(const Material& material) {
mMaterial = material;
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Set Material" + mMaterial.to_string());
}
// Return the linear velocity damping factor
@ -359,6 +366,9 @@ inline decimal RigidBody::getLinearDamping() const {
inline void RigidBody::setLinearDamping(decimal linearDamping) {
assert(linearDamping >= decimal(0.0));
mLinearDamping = linearDamping;
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Set linearDamping=" + std::to_string(mLinearDamping));
}
// Return the angular velocity damping factor
@ -377,6 +387,9 @@ inline decimal RigidBody::getAngularDamping() const {
inline void RigidBody::setAngularDamping(decimal angularDamping) {
assert(angularDamping >= decimal(0.0));
mAngularDamping = angularDamping;
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Set angularDamping=" + std::to_string(mAngularDamping));
}
// Return the first element of the linked list of joints involving this body

View File

@ -68,7 +68,7 @@ CollisionDetection::CollisionDetection(CollisionWorld* world, MemoryManager& mem
// Compute the collision detection
void CollisionDetection::computeCollisionDetection() {
PROFILE("CollisionDetection::computeCollisionDetection()", mProfiler);
RP3D_PROFILE("CollisionDetection::computeCollisionDetection()", mProfiler);
// Compute the broad-phase collision detection
computeBroadPhase();
@ -86,7 +86,7 @@ void CollisionDetection::computeCollisionDetection() {
// Compute the broad-phase collision detection
void CollisionDetection::computeBroadPhase() {
PROFILE("CollisionDetection::computeBroadPhase()", mProfiler);
RP3D_PROFILE("CollisionDetection::computeBroadPhase()", mProfiler);
// If new collision shapes have been added to bodies
if (mIsCollisionShapesAdded) {
@ -101,7 +101,7 @@ void CollisionDetection::computeBroadPhase() {
// Compute the middle-phase collision detection
void CollisionDetection::computeMiddlePhase() {
PROFILE("CollisionDetection::computeMiddlePhase()", mProfiler);
RP3D_PROFILE("CollisionDetection::computeMiddlePhase()", mProfiler);
// For each possible collision pair of bodies
Map<Pair<uint, uint>, OverlappingPair*>::Iterator it;
@ -118,9 +118,9 @@ void CollisionDetection::computeMiddlePhase() {
ProxyShape* shape1 = pair->getShape1();
ProxyShape* shape2 = pair->getShape2();
assert(shape1->mBroadPhaseID != -1);
assert(shape2->mBroadPhaseID != -1);
assert(shape1->mBroadPhaseID != shape2->mBroadPhaseID);
assert(shape1->getBroadPhaseId() != -1);
assert(shape2->getBroadPhaseId() != -1);
assert(shape1->getBroadPhaseId() != shape2->getBroadPhaseId());
// Check if the two shapes are still overlapping. Otherwise, we destroy the
// overlapping pair
@ -251,7 +251,7 @@ void CollisionDetection::computeConvexVsConcaveMiddlePhase(OverlappingPair* pair
// Compute the narrow-phase collision detection
void CollisionDetection::computeNarrowPhase() {
PROFILE("CollisionDetection::computeNarrowPhase()", mProfiler);
RP3D_PROFILE("CollisionDetection::computeNarrowPhase()", mProfiler);
NarrowPhaseInfo* currentNarrowPhaseInfo = mNarrowPhaseInfoList;
while (currentNarrowPhaseInfo != nullptr) {
@ -308,9 +308,9 @@ void CollisionDetection::computeNarrowPhase() {
/// This method is called by the broad-phase collision detection algorithm
void CollisionDetection::broadPhaseNotifyOverlappingPair(ProxyShape* shape1, ProxyShape* shape2) {
assert(shape1->mBroadPhaseID != -1);
assert(shape2->mBroadPhaseID != -1);
assert(shape1->mBroadPhaseID != shape2->mBroadPhaseID);
assert(shape1->getBroadPhaseId() != -1);
assert(shape2->getBroadPhaseId() != -1);
assert(shape1->getBroadPhaseId() != shape2->getBroadPhaseId());
// Check if the collision filtering allows collision between the two shapes
if ((shape1->getCollideWithMaskBits() & shape2->getCollisionCategoryBits()) == 0 ||
@ -338,13 +338,13 @@ void CollisionDetection::broadPhaseNotifyOverlappingPair(ProxyShape* shape1, Pro
// Remove a body from the collision detection
void CollisionDetection::removeProxyCollisionShape(ProxyShape* proxyShape) {
assert(proxyShape->mBroadPhaseID != -1);
assert(proxyShape->getBroadPhaseId() != -1);
// Remove all the overlapping pairs involving this proxy shape
Map<Pair<uint, uint>, OverlappingPair*>::Iterator it;
for (it = mOverlappingPairs.begin(); it != mOverlappingPairs.end(); ) {
if (it->second->getShape1()->mBroadPhaseID == proxyShape->mBroadPhaseID||
it->second->getShape2()->mBroadPhaseID == proxyShape->mBroadPhaseID) {
if (it->second->getShape1()->getBroadPhaseId() == proxyShape->getBroadPhaseId()||
it->second->getShape2()->getBroadPhaseId() == proxyShape->getBroadPhaseId()) {
// TODO : Remove all the contact manifold of the overlapping pair from the contact manifolds list of the two bodies involved
@ -364,7 +364,7 @@ void CollisionDetection::removeProxyCollisionShape(ProxyShape* proxyShape) {
void CollisionDetection::addAllContactManifoldsToBodies() {
PROFILE("CollisionDetection::addAllContactManifoldsToBodies()", mProfiler);
RP3D_PROFILE("CollisionDetection::addAllContactManifoldsToBodies()", mProfiler);
// For each overlapping pairs in contact during the narrow-phase
Map<Pair<uint, uint>, OverlappingPair*>::Iterator it;
@ -415,7 +415,7 @@ void CollisionDetection::addContactManifoldToBody(OverlappingPair* pair) {
/// Convert the potential contact into actual contacts
void CollisionDetection::processAllPotentialContacts() {
PROFILE("CollisionDetection::processAllPotentialContacts()", mProfiler);
RP3D_PROFILE("CollisionDetection::processAllPotentialContacts()", mProfiler);
// For each overlapping pairs in contact during the narrow-phase
Map<Pair<uint, uint>, OverlappingPair*>::Iterator it;
@ -454,7 +454,7 @@ void CollisionDetection::processPotentialContacts(OverlappingPair* pair) {
// Report contacts for all the colliding overlapping pairs
void CollisionDetection::reportAllContacts() {
PROFILE("CollisionDetection::reportAllContacts()", mProfiler);
RP3D_PROFILE("CollisionDetection::reportAllContacts()", mProfiler);
// For each overlapping pairs in contact during the narrow-phase
Map<Pair<uint, uint>, OverlappingPair*>::Iterator it;
@ -532,13 +532,13 @@ void CollisionDetection::testAABBOverlap(const AABB& aabb, OverlapCallback* over
CollisionBody* overlapBody = proxyShape->getBody();
// If the proxy shape is from a body that we have not already reported collision
if (reportedBodies.find(overlapBody->getID()) == reportedBodies.end()) {
if (reportedBodies.find(overlapBody->getId()) == reportedBodies.end()) {
// Check if the collision filtering allows collision between the two shapes
if ((proxyShape->getCollisionCategoryBits() & categoryMaskBits) != 0) {
// Add the body into the set of reported bodies
reportedBodies.add(overlapBody->getID());
reportedBodies.add(overlapBody->getId());
// Notify the overlap to the user
overlapCallback->notifyOverlap(overlapBody);
@ -637,16 +637,16 @@ void CollisionDetection::testOverlap(CollisionBody* body, OverlapCallback* overl
ProxyShape* bodyProxyShape = body->getProxyShapesList();
while (bodyProxyShape != nullptr) {
if (bodyProxyShape->mBroadPhaseID != -1) {
if (bodyProxyShape->getBroadPhaseId() != -1) {
// Get the AABB of the shape
const AABB& shapeAABB = mBroadPhaseAlgorithm.getFatAABB(bodyProxyShape->mBroadPhaseID);
const AABB& shapeAABB = mBroadPhaseAlgorithm.getFatAABB(bodyProxyShape->getBroadPhaseId());
// Ask the broad-phase to get all the overlapping shapes
LinkedList<int> overlappingNodes(mMemoryManager.getPoolAllocator());
mBroadPhaseAlgorithm.reportAllShapesOverlappingWithAABB(shapeAABB, overlappingNodes);
const bodyindex bodyId = body->getID();
const bodyindex bodyId = body->getId();
// For each overlaping proxy shape
LinkedList<int>::ListElement* element = overlappingNodes.getListHead();
@ -658,8 +658,8 @@ void CollisionDetection::testOverlap(CollisionBody* body, OverlapCallback* overl
// If the proxy shape is from a body that we have not already reported collision and the
// two proxy collision shapes are not from the same body
if (reportedBodies.find(proxyShape->getBody()->getID()) == reportedBodies.end() &&
proxyShape->getBody()->getID() != bodyId) {
if (reportedBodies.find(proxyShape->getBody()->getId()) == reportedBodies.end() &&
proxyShape->getBody()->getId() != bodyId) {
// Check if the collision filtering allows collision between the two shapes
if ((proxyShape->getCollisionCategoryBits() & categoryMaskBits) != 0) {
@ -711,7 +711,7 @@ void CollisionDetection::testOverlap(CollisionBody* body, OverlapCallback* overl
CollisionBody* overlapBody = proxyShape->getBody();
// Add the body into the set of reported bodies
reportedBodies.add(overlapBody->getID());
reportedBodies.add(overlapBody->getId());
// Notify the overlap to the user
overlapCallback->notifyOverlap(overlapBody);
@ -817,16 +817,16 @@ void CollisionDetection::testCollision(CollisionBody* body, CollisionCallback* c
ProxyShape* bodyProxyShape = body->getProxyShapesList();
while (bodyProxyShape != nullptr) {
if (bodyProxyShape->mBroadPhaseID != -1) {
if (bodyProxyShape->getBroadPhaseId() != -1) {
// Get the AABB of the shape
const AABB& shapeAABB = mBroadPhaseAlgorithm.getFatAABB(bodyProxyShape->mBroadPhaseID);
const AABB& shapeAABB = mBroadPhaseAlgorithm.getFatAABB(bodyProxyShape->getBroadPhaseId());
// Ask the broad-phase to get all the overlapping shapes
LinkedList<int> overlappingNodes(mMemoryManager.getPoolAllocator());
mBroadPhaseAlgorithm.reportAllShapesOverlappingWithAABB(shapeAABB, overlappingNodes);
const bodyindex bodyId = body->getID();
const bodyindex bodyId = body->getId();
// For each overlaping proxy shape
LinkedList<int>::ListElement* element = overlappingNodes.getListHead();
@ -837,7 +837,7 @@ void CollisionDetection::testCollision(CollisionBody* body, CollisionCallback* c
ProxyShape* proxyShape = mBroadPhaseAlgorithm.getProxyShapeForBroadPhaseId(broadPhaseId);
// If the two proxy collision shapes are not from the same body
if (proxyShape->getBody()->getID() != bodyId) {
if (proxyShape->getBody()->getId() != bodyId) {
// Check if the collision filtering allows collision between the two shapes
if ((proxyShape->getCollisionCategoryBits() & categoryMaskBits) != 0) {
@ -996,6 +996,6 @@ EventListener* CollisionDetection::getWorldEventListener() {
// Return the world-space AABB of a given proxy shape
const AABB CollisionDetection::getWorldAABB(const ProxyShape* proxyShape) const {
assert(proxyShape->mBroadPhaseID > -1);
return mBroadPhaseAlgorithm.getFatAABB(proxyShape->mBroadPhaseID);
assert(proxyShape->getBroadPhaseId() > -1);
return mBroadPhaseAlgorithm.getFatAABB(proxyShape->getBroadPhaseId());
}

View File

@ -279,8 +279,8 @@ inline void CollisionDetection::removeNoCollisionPair(CollisionBody* body1,
/// previous frame so that it is tested for collision again in the broad-phase.
inline void CollisionDetection::askForBroadPhaseCollisionCheck(ProxyShape* shape) {
if (shape->mBroadPhaseID != -1) {
mBroadPhaseAlgorithm.addMovedCollisionShape(shape->mBroadPhaseID);
if (shape->getBroadPhaseId() != -1) {
mBroadPhaseAlgorithm.addMovedCollisionShape(shape->getBroadPhaseId());
}
}
@ -314,7 +314,7 @@ inline void CollisionDetection::raycast(RaycastCallback* raycastCallback,
const Ray& ray,
unsigned short raycastWithCategoryMaskBits) const {
PROFILE("CollisionDetection::raycast()", mProfiler);
RP3D_PROFILE("CollisionDetection::raycast()", mProfiler);
RaycastTest rayCastTest(raycastCallback);

View File

@ -93,6 +93,12 @@ class ProxyShape {
#endif
#ifdef IS_LOGGING_ACTIVE
/// Logger
Logger* mLogger;
#endif
// -------------------- Methods -------------------- //
/// Return the collision shape
@ -169,11 +175,8 @@ class ProxyShape {
/// Return the next proxy shape in the linked list of proxy shapes
const ProxyShape* getNext() const;
/// Return the local scaling vector of the collision shape
Vector3 getLocalScaling() const;
/// Set the local scaling vector of the collision shape
virtual void setLocalScaling(const Vector3& scaling);
/// Return the broad-phase id
int getBroadPhaseId() const;
#ifdef IS_PROFILING_ACTIVE
@ -182,6 +185,12 @@ class ProxyShape {
#endif
#ifdef IS_LOGGING_ACTIVE
/// Set the logger
void setLogger(Logger* logger);
#endif
// -------------------- Friendship -------------------- //
friend class OverlappingPair;
@ -265,6 +274,10 @@ inline void ProxyShape::setLocalToBodyTransform(const Transform& transform) {
// Notify the body that the proxy shape has to be updated in the broad-phase
mBody->updateProxyShapeInBroadPhase(this, true);
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::ProxyShape,
"ProxyShape " + std::to_string(mBroadPhaseID) + ": Set localToBodyTransform=" +
mLocalToBodyTransform.to_string());
}
// Return the local to world transform
@ -316,6 +329,10 @@ inline unsigned short ProxyShape::getCollisionCategoryBits() const {
*/
inline void ProxyShape::setCollisionCategoryBits(unsigned short collisionCategoryBits) {
mCollisionCategoryBits = collisionCategoryBits;
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::ProxyShape,
"ProxyShape " + std::to_string(mBroadPhaseID) + ": Set collisionCategoryBits=" +
std::to_string(mCollisionCategoryBits));
}
// Return the collision bits mask
@ -332,29 +349,15 @@ inline unsigned short ProxyShape::getCollideWithMaskBits() const {
*/
inline void ProxyShape::setCollideWithMaskBits(unsigned short collideWithMaskBits) {
mCollideWithMaskBits = collideWithMaskBits;
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::ProxyShape,
"ProxyShape " + std::to_string(mBroadPhaseID) + ": Set collideWithMaskBits=" +
std::to_string(mCollideWithMaskBits));
}
// Return the local scaling vector of the collision shape
/**
* @return The local scaling vector
*/
inline Vector3 ProxyShape::getLocalScaling() const {
return mCollisionShape->getLocalScaling();
}
// Set the local scaling vector of the collision shape
/**
* @param scaling The new local scaling vector
*/
inline void ProxyShape::setLocalScaling(const Vector3& scaling) {
// Set the local scaling of the collision shape
mCollisionShape->setLocalScaling(scaling);
mBody->setIsSleeping(false);
// Notify the body that the proxy shape has to be updated in the broad-phase
mBody->updateProxyShapeInBroadPhase(this, true);
// Return the broad-phase id
inline int ProxyShape::getBroadPhaseId() const {
return mBroadPhaseID;
}
/// Test if the proxy shape overlaps with a given AABB
@ -378,6 +381,16 @@ inline void ProxyShape::setProfiler(Profiler* profiler) {
#endif
#ifdef IS_LOGGING_ACTIVE
// Set the logger
inline void ProxyShape::setLogger(Logger* logger) {
mLogger = logger;
}
#endif
}
#endif

View File

@ -280,3 +280,55 @@ void TriangleVertexArray::getTriangleVerticesNormals(uint triangleIndex, Vector3
}
}
}
// Return a vertex of the array
void TriangleVertexArray::getVertex(uint vertexIndex, Vector3* outVertex) {
assert(vertexIndex < mNbVertices);
const uchar* vertexPointerChar = mVerticesStart + vertexIndex * mVerticesStride;
const void* vertexPointer = static_cast<const void*>(vertexPointerChar);
// Get the vertices components of the triangle
if (mVertexDataType == TriangleVertexArray::VertexDataType::VERTEX_FLOAT_TYPE) {
const float* vertices = static_cast<const float*>(vertexPointer);
(*outVertex)[0] = decimal(vertices[0]);
(*outVertex)[1] = decimal(vertices[1]);
(*outVertex)[2] = decimal(vertices[2]);
}
else if (mVertexDataType == TriangleVertexArray::VertexDataType::VERTEX_DOUBLE_TYPE) {
const double* vertices = static_cast<const double*>(vertexPointer);
(*outVertex)[0] = decimal(vertices[0]);
(*outVertex)[1] = decimal(vertices[1]);
(*outVertex)[2] = decimal(vertices[2]);
}
else {
assert(false);
}
}
// Return a vertex normal of the array
void TriangleVertexArray::getNormal(uint vertexIndex, Vector3* outNormal) {
assert(vertexIndex < mNbVertices);
const uchar* vertexNormalPointerChar = mVerticesNormalsStart + vertexIndex * mVerticesNormalsStride;
const void* vertexNormalPointer = static_cast<const void*>(vertexNormalPointerChar);
// Get the normals from the array
if (mVertexNormaldDataType == TriangleVertexArray::NormalDataType::NORMAL_FLOAT_TYPE) {
const float* normal = static_cast<const float*>(vertexNormalPointer);
(*outNormal)[0] = decimal(normal[0]);
(*outNormal)[1] = decimal(normal[1]);
(*outNormal)[2] = decimal(normal[2]);
}
else if (mVertexNormaldDataType == TriangleVertexArray::NormalDataType::NORMAL_DOUBLE_TYPE) {
const double* normal = static_cast<const double*>(vertexNormalPointer);
(*outNormal)[0] = decimal(normal[0]);
(*outNormal)[1] = decimal(normal[1]);
(*outNormal)[2] = decimal(normal[2]);
}
else {
assert(false);
}
}

View File

@ -169,6 +169,12 @@ class TriangleVertexArray {
/// Return the indices of the three vertices of a given triangle in the array
void getTriangleVerticesIndices(uint triangleIndex, uint* outVerticesIndices) const;
/// Return a vertex of the array
void getVertex(uint vertexIndex, Vector3* outVertex);
/// Return a vertex normal of the array
void getNormal(uint vertexIndex, Vector3* outNormal);
};
// Return the vertex data type

View File

@ -26,7 +26,7 @@
// Libraries
#include "BroadPhaseAlgorithm.h"
#include "collision/CollisionDetection.h"
#include "engine/Profiler.h"
#include "utils/Profiler.h"
// We want to use the ReactPhysics3D namespace
using namespace reactphysics3d;
@ -140,7 +140,7 @@ void BroadPhaseAlgorithm::removeMovedCollisionShape(int broadPhaseID) {
// Add a proxy collision shape into the broad-phase collision detection
void BroadPhaseAlgorithm::addProxyCollisionShape(ProxyShape* proxyShape, const AABB& aabb) {
assert(proxyShape->mBroadPhaseID == -1);
assert(proxyShape->getBroadPhaseId() == -1);
// Add the collision shape into the dynamic AABB tree and get its broad-phase ID
int nodeId = mDynamicAABBTree.addObject(aabb, proxyShape);
@ -150,15 +150,15 @@ void BroadPhaseAlgorithm::addProxyCollisionShape(ProxyShape* proxyShape, const A
// Add the collision shape into the array of bodies that have moved (or have been created)
// during the last simulation step
addMovedCollisionShape(proxyShape->mBroadPhaseID);
addMovedCollisionShape(proxyShape->getBroadPhaseId());
}
// Remove a proxy collision shape from the broad-phase collision detection
void BroadPhaseAlgorithm::removeProxyCollisionShape(ProxyShape* proxyShape) {
assert(proxyShape->mBroadPhaseID != -1);
assert(proxyShape->getBroadPhaseId() != -1);
int broadPhaseID = proxyShape->mBroadPhaseID;
int broadPhaseID = proxyShape->getBroadPhaseId();
proxyShape->mBroadPhaseID = -1;
@ -174,7 +174,7 @@ void BroadPhaseAlgorithm::removeProxyCollisionShape(ProxyShape* proxyShape) {
void BroadPhaseAlgorithm::updateProxyCollisionShape(ProxyShape* proxyShape, const AABB& aabb,
const Vector3& displacement, bool forceReinsert) {
int broadPhaseID = proxyShape->mBroadPhaseID;
int broadPhaseID = proxyShape->getBroadPhaseId();
assert(broadPhaseID >= 0);
@ -257,7 +257,7 @@ void BroadPhaseAlgorithm::computeOverlappingPairs(MemoryManager& memoryManager)
ProxyShape* shape2 = static_cast<ProxyShape*>(mDynamicAABBTree.getNodeDataPointer(pair->collisionShape2ID));
// If the two proxy collision shapes are from the same body, skip it
if (shape1->getBody()->getID() != shape2->getBody()->getID()) {
if (shape1->getBody()->getId() != shape2->getBody()->getId()) {
// Notify the collision detection about the overlapping pair
mCollisionDetection.broadPhaseNotifyOverlappingPair(shape1, shape2);

View File

@ -30,7 +30,7 @@
#include "body/CollisionBody.h"
#include "collision/ProxyShape.h"
#include "DynamicAABBTree.h"
#include "engine/Profiler.h"
#include "utils/Profiler.h"
#include "containers/LinkedList.h"
/// Namespace ReactPhysics3D
@ -246,11 +246,11 @@ inline bool BroadPhasePair::smallerThan(const BroadPhasePair& pair1, const Broad
inline bool BroadPhaseAlgorithm::testOverlappingShapes(const ProxyShape* shape1,
const ProxyShape* shape2) const {
if (shape1->mBroadPhaseID == -1 || shape2->mBroadPhaseID == -1) return false;
if (shape1->getBroadPhaseId() == -1 || shape2->getBroadPhaseId() == -1) return false;
// Get the two AABBs of the collision shapes
const AABB& aabb1 = mDynamicAABBTree.getFatAABB(shape1->mBroadPhaseID);
const AABB& aabb2 = mDynamicAABBTree.getFatAABB(shape2->mBroadPhaseID);
const AABB& aabb1 = mDynamicAABBTree.getFatAABB(shape1->getBroadPhaseId());
const AABB& aabb2 = mDynamicAABBTree.getFatAABB(shape2->getBroadPhaseId());
// Check if the two AABBs are overlapping
return aabb1.testCollision(aabb2);
@ -265,7 +265,7 @@ inline const AABB& BroadPhaseAlgorithm::getFatAABB(int broadPhaseId) const {
inline void BroadPhaseAlgorithm::raycast(const Ray& ray, RaycastTest& raycastTest,
unsigned short raycastWithCategoryMaskBits) const {
PROFILE("BroadPhaseAlgorithm::raycast()", mProfiler);
RP3D_PROFILE("BroadPhaseAlgorithm::raycast()", mProfiler);
BroadPhaseRaycastCallback broadPhaseRaycastCallback(mDynamicAABBTree, raycastWithCategoryMaskBits, raycastTest);

View File

@ -27,7 +27,7 @@
#include "DynamicAABBTree.h"
#include "BroadPhaseAlgorithm.h"
#include "containers/Stack.h"
#include "engine/Profiler.h"
#include "utils/Profiler.h"
using namespace reactphysics3d;
@ -173,7 +173,7 @@ void DynamicAABBTree::removeObject(int nodeID) {
/// (this can be useful if the shape AABB has become much smaller than the previous one for instance).
bool DynamicAABBTree::updateObject(int nodeID, const AABB& newAABB, const Vector3& displacement, bool forceReinsert) {
PROFILE("DynamicAABBTree::updateObject()", mProfiler);
RP3D_PROFILE("DynamicAABBTree::updateObject()", mProfiler);
assert(nodeID >= 0 && nodeID < mNbAllocatedNodes);
assert(mNodes[nodeID].isLeaf());
@ -635,7 +635,7 @@ void DynamicAABBTree::reportAllShapesOverlappingWithAABB(const AABB& aabb,
// Ray casting method
void DynamicAABBTree::raycast(const Ray& ray, DynamicAABBTreeRaycastCallback &callback) const {
PROFILE("DynamicAABBTree::raycast()", mProfiler);
RP3D_PROFILE("DynamicAABBTree::raycast()", mProfiler);
decimal maxFraction = ray.maxFraction;

View File

@ -29,7 +29,7 @@
#include "engine/OverlappingPair.h"
#include "collision/shapes/TriangleShape.h"
#include "configuration.h"
#include "engine/Profiler.h"
#include "utils/Profiler.h"
#include <algorithm>
#include <cmath>
#include <cfloat>
@ -49,7 +49,7 @@ using namespace reactphysics3d;
/// the correct penetration depth and contact points between the enlarged objects.
GJKAlgorithm::GJKResult GJKAlgorithm::testCollision(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts) {
PROFILE("GJKAlgorithm::testCollision()", mProfiler);
RP3D_PROFILE("GJKAlgorithm::testCollision()", mProfiler);
Vector3 suppA; // Support point of object A
Vector3 suppB; // Support point of object B

View File

@ -32,7 +32,7 @@
#include "engine/OverlappingPair.h"
#include "collision/shapes/TriangleShape.h"
#include "configuration.h"
#include "engine/Profiler.h"
#include "utils/Profiler.h"
#include <algorithm>
#include <cmath>
#include <cfloat>
@ -52,7 +52,7 @@ SATAlgorithm::SATAlgorithm(MemoryAllocator& memoryAllocator) : mMemoryAllocator(
// Test collision between a sphere and a convex mesh
bool SATAlgorithm::testCollisionSphereVsConvexPolyhedron(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts) const {
PROFILE("SATAlgorithm::testCollisionSphereVsConvexPolyhedron()", mProfiler);
RP3D_PROFILE("SATAlgorithm::testCollisionSphereVsConvexPolyhedron()", mProfiler);
bool isSphereShape1 = narrowPhaseInfo->collisionShape1->getType() == CollisionShapeType::SPHERE;
@ -127,7 +127,7 @@ bool SATAlgorithm::testCollisionSphereVsConvexPolyhedron(NarrowPhaseInfo* narrow
decimal SATAlgorithm::computePolyhedronFaceVsSpherePenetrationDepth(uint faceIndex, const ConvexPolyhedronShape* polyhedron,
const SphereShape* sphere, const Vector3& sphereCenter) const {
PROFILE("SATAlgorithm::computePolyhedronFaceVsSpherePenetrationDepth)", mProfiler);
RP3D_PROFILE("SATAlgorithm::computePolyhedronFaceVsSpherePenetrationDepth)", mProfiler);
// Get the face
const HalfEdgeStructure::Face& face = polyhedron->getFace(faceIndex);
@ -144,7 +144,7 @@ decimal SATAlgorithm::computePolyhedronFaceVsSpherePenetrationDepth(uint faceInd
// Test collision between a capsule and a convex mesh
bool SATAlgorithm::testCollisionCapsuleVsConvexPolyhedron(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts) const {
PROFILE("SATAlgorithm::testCollisionCapsuleVsConvexPolyhedron()", mProfiler);
RP3D_PROFILE("SATAlgorithm::testCollisionCapsuleVsConvexPolyhedron()", mProfiler);
bool isCapsuleShape1 = narrowPhaseInfo->collisionShape1->getType() == CollisionShapeType::CAPSULE;
@ -304,7 +304,7 @@ decimal SATAlgorithm::computeEdgeVsCapsuleInnerSegmentPenetrationDepth(const Con
const Vector3& edgeDirectionCapsuleSpace,
const Transform& polyhedronToCapsuleTransform, Vector3& outAxis) const {
PROFILE("SATAlgorithm::computeEdgeVsCapsuleInnerSegmentPenetrationDepth)", mProfiler);
RP3D_PROFILE("SATAlgorithm::computeEdgeVsCapsuleInnerSegmentPenetrationDepth)", mProfiler);
decimal penetrationDepth = DECIMAL_LARGEST;
@ -338,7 +338,7 @@ decimal SATAlgorithm::computePolyhedronFaceVsCapsulePenetrationDepth(uint polyhe
const CapsuleShape* capsule, const Transform& polyhedronToCapsuleTransform,
Vector3& outFaceNormalCapsuleSpace) const {
PROFILE("SATAlgorithm::computePolyhedronFaceVsCapsulePenetrationDepth", mProfiler);
RP3D_PROFILE("SATAlgorithm::computePolyhedronFaceVsCapsulePenetrationDepth", mProfiler);
// Get the face
const HalfEdgeStructure::Face& face = polyhedron->getFace(polyhedronFaceIndex);
@ -364,7 +364,7 @@ bool SATAlgorithm::computeCapsulePolyhedronFaceContactPoints(uint referenceFaceI
const Vector3& capsuleSegAPolyhedronSpace, const Vector3& capsuleSegBPolyhedronSpace,
NarrowPhaseInfo* narrowPhaseInfo, bool isCapsuleShape1) const {
PROFILE("SATAlgorithm::computeCapsulePolyhedronFaceContactPoints", mProfiler);
RP3D_PROFILE("SATAlgorithm::computeCapsulePolyhedronFaceContactPoints", mProfiler);
const HalfEdgeStructure::Face& face = polyhedron->getFace(referenceFaceIndex);
@ -459,7 +459,7 @@ bool SATAlgorithm::isMinkowskiFaceCapsuleVsEdge(const Vector3& capsuleSegment, c
// Test collision between two convex polyhedrons
bool SATAlgorithm::testCollisionConvexPolyhedronVsConvexPolyhedron(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts) const {
PROFILE("SATAlgorithm::testCollisionConvexPolyhedronVsConvexPolyhedron()", mProfiler);
RP3D_PROFILE("SATAlgorithm::testCollisionConvexPolyhedronVsConvexPolyhedron()", mProfiler);
assert(narrowPhaseInfo->collisionShape1->getType() == CollisionShapeType::CONVEX_POLYHEDRON);
assert(narrowPhaseInfo->collisionShape2->getType() == CollisionShapeType::CONVEX_POLYHEDRON);
@ -804,7 +804,7 @@ bool SATAlgorithm::computePolyhedronVsPolyhedronFaceContactPoints(bool isMinPene
const Transform& polyhedron1ToPolyhedron2, const Transform& polyhedron2ToPolyhedron1,
uint minFaceIndex, NarrowPhaseInfo* narrowPhaseInfo, decimal minPenetrationDepth) const {
PROFILE("SATAlgorithm::computePolyhedronVsPolyhedronFaceContactPoints", mProfiler);
RP3D_PROFILE("SATAlgorithm::computePolyhedronVsPolyhedronFaceContactPoints", mProfiler);
const ConvexPolyhedronShape* referencePolyhedron = isMinPenetrationFaceNormalPolyhedron1 ? polyhedron1 : polyhedron2;
const ConvexPolyhedronShape* incidentPolyhedron = isMinPenetrationFaceNormalPolyhedron1 ? polyhedron2 : polyhedron1;
@ -919,7 +919,7 @@ decimal SATAlgorithm::computeDistanceBetweenEdges(const Vector3& edge1A, const V
const Vector3& edge1Direction, const Vector3& edge2Direction,
Vector3& outSeparatingAxisPolyhedron2Space) const {
PROFILE("SATAlgorithm::computeDistanceBetweenEdges", mProfiler);
RP3D_PROFILE("SATAlgorithm::computeDistanceBetweenEdges", mProfiler);
// If the two edges are parallel
if (areParallelVectors(edge1Direction, edge2Direction)) {
@ -948,7 +948,7 @@ decimal SATAlgorithm::testSingleFaceDirectionPolyhedronVsPolyhedron(const Convex
const Transform& polyhedron1ToPolyhedron2,
uint faceIndex) const {
PROFILE("SATAlgorithm::testSingleFaceDirectionPolyhedronVsPolyhedron", mProfiler);
RP3D_PROFILE("SATAlgorithm::testSingleFaceDirectionPolyhedronVsPolyhedron", mProfiler);
const HalfEdgeStructure::Face& face = polyhedron1->getFace(faceIndex);
@ -974,7 +974,7 @@ decimal SATAlgorithm::testFacesDirectionPolyhedronVsPolyhedron(const ConvexPolyh
const Transform& polyhedron1ToPolyhedron2,
uint& minFaceIndex) const {
PROFILE("SATAlgorithm::testFacesDirectionPolyhedronVsPolyhedron", mProfiler);
RP3D_PROFILE("SATAlgorithm::testFacesDirectionPolyhedronVsPolyhedron", mProfiler);
decimal minPenetrationDepth = DECIMAL_LARGEST;
@ -1006,7 +1006,7 @@ bool SATAlgorithm::testEdgesBuildMinkowskiFace(const ConvexPolyhedronShape* poly
const ConvexPolyhedronShape* polyhedron2, const HalfEdgeStructure::Edge& edge2,
const Transform& polyhedron1ToPolyhedron2) const {
PROFILE("SATAlgorithm::testEdgesBuildMinkowskiFace", mProfiler);
RP3D_PROFILE("SATAlgorithm::testEdgesBuildMinkowskiFace", mProfiler);
const Vector3 a = polyhedron1ToPolyhedron2.getOrientation() * polyhedron1->getFaceNormal(edge1.faceIndex);
const Vector3 b = polyhedron1ToPolyhedron2.getOrientation() * polyhedron1->getFaceNormal(polyhedron1->getHalfEdge(edge1.twinEdgeIndex).faceIndex);
@ -1039,7 +1039,7 @@ bool SATAlgorithm::testEdgesBuildMinkowskiFace(const ConvexPolyhedronShape* poly
bool SATAlgorithm::testGaussMapArcsIntersect(const Vector3& a, const Vector3& b, const Vector3& c, const Vector3& d,
const Vector3& bCrossA, const Vector3& dCrossC) const {
PROFILE("SATAlgorithm::testGaussMapArcsIntersect", mProfiler);
RP3D_PROFILE("SATAlgorithm::testGaussMapArcsIntersect", mProfiler);
const decimal cba = c.dot(bCrossA);
const decimal dba = d.dot(bCrossA);

View File

@ -88,9 +88,6 @@ class BoxShape : public ConvexPolyhedronShape {
/// Return the extents of the box
Vector3 getExtent() const;
/// Set the scaling vector of the collision shape
virtual void setLocalScaling(const Vector3& scaling) override;
/// Return the local bounds of the shape in x, y and z directions
virtual void getLocalBounds(Vector3& min, Vector3& max) const override;
@ -123,6 +120,9 @@ class BoxShape : public ConvexPolyhedronShape {
/// Return the centroid of the polyhedron
virtual Vector3 getCentroid() const override;
/// Return the string representation of the shape
virtual std::string to_string() const override;
};
// Return the extents of the box
@ -133,14 +133,6 @@ inline Vector3 BoxShape::getExtent() const {
return mExtent;
}
// Set the scaling vector of the collision shape
inline void BoxShape::setLocalScaling(const Vector3& scaling) {
mExtent = (mExtent / mScaling) * scaling;
CollisionShape::setLocalScaling(scaling);
}
// Return the local bounds of the shape in x, y and z directions
/// This method is used to compute the AABB of the box
/**
@ -237,6 +229,11 @@ inline Vector3 BoxShape::getCentroid() const {
return Vector3::zero();
}
// Return the string representation of the shape
inline std::string BoxShape::to_string() const {
return "BoxShape{extents=" + mExtent.to_string() + "}";
}
// Return the number of half-edges of the polyhedron
inline uint BoxShape::getNbHalfEdges() const {
return 24;

View File

@ -94,9 +94,6 @@ class CapsuleShape : public ConvexShape {
/// Return the height of the capsule
decimal getHeight() const;
/// Set the scaling vector of the collision shape
virtual void setLocalScaling(const Vector3& scaling) override;
/// Return the local bounds of the shape in x, y and z directions
virtual void getLocalBounds(Vector3& min, Vector3& max) const override;
@ -105,6 +102,9 @@ class CapsuleShape : public ConvexShape {
/// Return the local inertia tensor of the collision shape
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, decimal mass) const override;
/// Return the string representation of the shape
virtual std::string to_string() const override;
};
// Get the radius of the capsule
@ -123,15 +123,6 @@ inline decimal CapsuleShape::getHeight() const {
return mHalfHeight + mHalfHeight;
}
// Set the scaling vector of the collision shape
inline void CapsuleShape::setLocalScaling(const Vector3& scaling) {
mHalfHeight = (mHalfHeight / mScaling.y) * scaling.y;
mMargin = (mMargin / mScaling.x) * scaling.x;
CollisionShape::setLocalScaling(scaling);
}
// Return the number of bytes used by the collision shape
inline size_t CapsuleShape::getSizeInBytes() const {
return sizeof(CapsuleShape);
@ -185,6 +176,11 @@ inline Vector3 CapsuleShape::getLocalSupportPointWithoutMargin(const Vector3& di
}
}
// Return the string representation of the shape
inline std::string CapsuleShape::to_string() const {
return "CapsuleShape{halfHeight=" + std::to_string(mHalfHeight) + ", radius=" + std::to_string(getRadius()) + "}";
}
}
#endif

View File

@ -25,7 +25,7 @@
// Libraries
#include "CollisionShape.h"
#include "engine/Profiler.h"
#include "utils/Profiler.h"
#include "body/CollisionBody.h"
// We want to use the ReactPhysics3D namespace
@ -33,7 +33,7 @@ using namespace reactphysics3d;
// Constructor
CollisionShape::CollisionShape(CollisionShapeName name, CollisionShapeType type)
: mType(type), mName(name), mScaling(1.0, 1.0, 1.0), mId(0) {
: mType(type), mName(name), mId(0) {
}
@ -48,7 +48,7 @@ CollisionShape::CollisionShape(CollisionShapeName name, CollisionShapeType type)
*/
void CollisionShape::computeAABB(AABB& aabb, const Transform& transform) const {
PROFILE("CollisionShape::computeAABB()", mProfiler);
RP3D_PROFILE("CollisionShape::computeAABB()", mProfiler);
// Get the local bounds in x,y and z direction
Vector3 minBounds;

View File

@ -35,7 +35,7 @@
#include "AABB.h"
#include "collision/RaycastInfo.h"
#include "memory/PoolAllocator.h"
#include "engine/Profiler.h"
#include "utils/Profiler.h"
/// ReactPhysics3D namespace
namespace reactphysics3d {
@ -68,9 +68,6 @@ class CollisionShape {
/// Name of the colision shape
CollisionShapeName mName;
/// Scaling vector of the collision shape
Vector3 mScaling;
/// Unique identifier of the shape inside an overlapping pair
uint mId;
@ -126,9 +123,6 @@ class CollisionShape {
/// Return the scaling vector of the collision shape
Vector3 getLocalScaling() const;
/// Set the local scaling vector of the collision shape
virtual void setLocalScaling(const Vector3& scaling);
/// Return the id of the shape
uint getId() const;
@ -138,6 +132,9 @@ class CollisionShape {
/// Compute the world-space AABB of the collision shape given a transform
virtual void computeAABB(AABB& aabb, const Transform& transform) const;
/// Return the string representation of the shape
virtual std::string to_string() const=0;
#ifdef IS_PROFILING_ACTIVE
/// Set the profiler
@ -167,16 +164,6 @@ inline CollisionShapeType CollisionShape::getType() const {
return mType;
}
// Return the scaling vector of the collision shape
inline Vector3 CollisionShape::getLocalScaling() const {
return mScaling;
}
// Set the scaling vector of the collision shape
inline void CollisionShape::setLocalScaling(const Vector3& scaling) {
mScaling = scaling;
}
// Return the id of the shape
inline uint CollisionShape::getId() const {
return mId;

View File

@ -30,8 +30,9 @@
using namespace reactphysics3d;
// Constructor
ConcaveMeshShape::ConcaveMeshShape(TriangleMesh* triangleMesh)
: ConcaveShape(CollisionShapeName::TRIANGLE_MESH), mDynamicAABBTree(MemoryManager::getBaseAllocator()) {
ConcaveMeshShape::ConcaveMeshShape(TriangleMesh* triangleMesh, const Vector3& scaling)
: ConcaveShape(CollisionShapeName::TRIANGLE_MESH), mDynamicAABBTree(MemoryManager::getBaseAllocator()),
mScaling(scaling) {
mTriangleMesh = triangleMesh;
mRaycastTestType = TriangleRaycastSide::FRONT;
@ -114,7 +115,7 @@ void ConcaveMeshShape::testAllTriangles(TriangleCallback& callback, const AABB&
/// the ray hits many triangles.
bool ConcaveMeshShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, MemoryAllocator& allocator) const {
PROFILE("ConcaveMeshShape::raycast()", mProfiler);
RP3D_PROFILE("ConcaveMeshShape::raycast()", mProfiler);
// Create the callback object that will compute ray casting against triangles
ConcaveMeshRaycastCallback raycastCallback(mDynamicAABBTree, *this, proxyShape, raycastInfo, ray, allocator);
@ -214,3 +215,68 @@ void ConcaveMeshRaycastCallback::raycastTriangles() {
}
}
// Return the string representation of the shape
std::string ConcaveMeshShape::to_string() const {
std::stringstream ss;
ss << "ConcaveMeshShape{" << std::endl;
ss << "nbSubparts=" << mTriangleMesh->getNbSubparts() << std::endl;
// Vertices array
for (uint subPart=0; subPart<mTriangleMesh->getNbSubparts(); subPart++) {
// Get the triangle vertex array of the current sub-part
TriangleVertexArray* triangleVertexArray = mTriangleMesh->getSubpart(subPart);
ss << "subpart" << subPart << "={" << std::endl;
ss << "nbVertices=" << triangleVertexArray->getNbVertices() << std::endl;
ss << "nbTriangles=" << triangleVertexArray->getNbTriangles() << std::endl;
ss << "vertices=[";
// For each triangle of the concave mesh
for (uint v=0; v<triangleVertexArray->getNbVertices(); v++) {
Vector3 vertex;
triangleVertexArray->getVertex(v, &vertex);
ss << vertex.to_string() << ", ";
}
ss << "], " << std::endl;
ss << "normals=[";
// For each triangle of the concave mesh
for (uint v=0; v<triangleVertexArray->getNbVertices(); v++) {
Vector3 normal;
triangleVertexArray->getNormal(v, &normal);
ss << normal.to_string() << ", ";
}
ss << "], " << std::endl;
ss << "triangles=[";
// For each triangle of the concave mesh
// For each triangle of the concave mesh
for (uint triangleIndex=0; triangleIndex<triangleVertexArray->getNbTriangles(); triangleIndex++) {
uint indices[3];
triangleVertexArray->getTriangleVerticesIndices(triangleIndex, indices);
ss << "(" << indices[0] << "," << indices[1] << "," << indices[2] << "), ";
}
ss << "], " << std::endl;
ss << "}" << std::endl;
}
return ss.str();
}

View File

@ -32,7 +32,7 @@
#include "collision/TriangleMesh.h"
#include "collision/shapes/TriangleShape.h"
#include "containers/List.h"
#include "engine/Profiler.h"
#include "utils/Profiler.h"
namespace reactphysics3d {
@ -140,6 +140,9 @@ class ConcaveMeshShape : public ConcaveShape {
/// if the user did not provide its own vertices normals)
Vector3** mComputedVerticesNormals;
/// Scaling
const Vector3 mScaling;
// -------------------- Methods -------------------- //
/// Raycast method with feedback information
@ -163,7 +166,7 @@ class ConcaveMeshShape : public ConcaveShape {
public:
/// Constructor
ConcaveMeshShape(TriangleMesh* triangleMesh);
ConcaveMeshShape(TriangleMesh* triangleMesh, const Vector3& scaling = Vector3(1, 1, 1));
/// Destructor
virtual ~ConcaveMeshShape() = default;
@ -174,18 +177,21 @@ class ConcaveMeshShape : public ConcaveShape {
/// Deleted assignment operator
ConcaveMeshShape& operator=(const ConcaveMeshShape& shape) = delete;
/// Return the scaling vector
const Vector3& getScaling() const;
/// Return the local bounds of the shape in x, y and z directions.
virtual void getLocalBounds(Vector3& min, Vector3& max) const override;
/// Set the local scaling vector of the collision shape
virtual void setLocalScaling(const Vector3& scaling) override;
/// 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;
#ifdef IS_PROFILING_ACTIVE
/// Set the profiler
@ -204,6 +210,11 @@ inline size_t ConcaveMeshShape::getSizeInBytes() const {
return sizeof(ConcaveMeshShape);
}
// Return the scaling vector
inline const Vector3& ConcaveMeshShape::getScaling() const {
return mScaling;
}
// Return the local bounds of the shape in x, y and z directions.
// This method is used to compute the AABB of the box
/**
@ -219,18 +230,6 @@ inline void ConcaveMeshShape::getLocalBounds(Vector3& min, Vector3& max) const {
max = treeAABB.getMax();
}
// Set the local scaling vector of the collision shape
inline void ConcaveMeshShape::setLocalScaling(const Vector3& scaling) {
CollisionShape::setLocalScaling(scaling);
// Reset the Dynamic AABB Tree
mDynamicAABBTree.reset();
// Rebuild Dynamic AABB Tree here
initBVHTree();
}
// Return the local inertia tensor of the shape
/**
* @param[out] tensor The 3x3 inertia tensor matrix of the shape in local-space
@ -277,6 +276,7 @@ inline void ConcaveMeshShape::setProfiler(Profiler* profiler) {
mDynamicAABBTree.setProfiler(profiler);
}
#endif
}

View File

@ -38,8 +38,9 @@ using namespace reactphysics3d;
* @param stride Stride between the beginning of two elements in the vertices array
* @param margin Collision margin (in meters) around the collision shape
*/
ConvexMeshShape::ConvexMeshShape(PolyhedronMesh* polyhedronMesh)
: ConvexPolyhedronShape(CollisionShapeName::CONVEX_MESH), mPolyhedronMesh(polyhedronMesh), mMinBounds(0, 0, 0), mMaxBounds(0, 0, 0) {
ConvexMeshShape::ConvexMeshShape(PolyhedronMesh* polyhedronMesh, const Vector3& scaling)
: ConvexPolyhedronShape(CollisionShapeName::CONVEX_MESH), mPolyhedronMesh(polyhedronMesh),
mMinBounds(0, 0, 0), mMaxBounds(0, 0, 0), mScaling(scaling) {
// Recalculate the bounds of the mesh
recalculateBounds();
@ -201,3 +202,47 @@ bool ConvexMeshShape::testPointInside(const Vector3& localPoint, ProxyShape* pro
return true;
}
// Return the string representation of the shape
std::string ConvexMeshShape::to_string() const {
std::stringstream ss;
ss << "ConvexMeshShape{" << std::endl;
ss << "nbVertices=" << mPolyhedronMesh->getNbVertices() << std::endl;
ss << "nbFaces=" << mPolyhedronMesh->getNbFaces() << std::endl;
ss << "vertices=[";
for (uint v=0; v < mPolyhedronMesh->getNbVertices(); v++) {
Vector3 vertex = mPolyhedronMesh->getVertex(v);
ss << vertex.to_string();
if (v != mPolyhedronMesh->getNbVertices() - 1) {
ss << ", ";
}
}
ss << "], faces=[";
HalfEdgeStructure halfEdgeStruct = mPolyhedronMesh->getHalfEdgeStructure();
for (uint f=0; f < mPolyhedronMesh->getNbFaces(); f++) {
const HalfEdgeStructure::Face& face = halfEdgeStruct.getFace(f);
ss << "[";
for (uint v=0; v < face.faceVertices.size(); v++) {
ss << face.faceVertices[v];
if (v != face.faceVertices.size() - 1) {
ss << ",";
}
}
ss << "]";
}
ss << "]}";
return ss.str();
}

View File

@ -30,7 +30,7 @@
#include "ConvexPolyhedronShape.h"
#include "engine/CollisionWorld.h"
#include "mathematics/mathematics.h"
#include "collision/TriangleMesh.h"
#include "collision/PolyhedronMesh.h"
#include "collision/narrowphase/GJK/GJKAlgorithm.h"
@ -62,6 +62,9 @@ class ConvexMeshShape : public ConvexPolyhedronShape {
/// Mesh maximum bounds in the three local x, y and z directions
Vector3 mMaxBounds;
/// Local scaling
const Vector3 mScaling;
// -------------------- Methods -------------------- //
/// Recompute the bounds of the mesh
@ -84,7 +87,7 @@ class ConvexMeshShape : public ConvexPolyhedronShape {
// -------------------- Methods -------------------- //
/// Constructor
ConvexMeshShape(PolyhedronMesh* polyhedronMesh);
ConvexMeshShape(PolyhedronMesh* polyhedronMesh, const Vector3& scaling = Vector3(1,1,1));
/// Destructor
virtual ~ConvexMeshShape() override = default;
@ -95,8 +98,8 @@ class ConvexMeshShape : public ConvexPolyhedronShape {
/// Deleted assignment operator
ConvexMeshShape& operator=(const ConvexMeshShape& shape) = delete;
/// Set the scaling vector of the collision shape
virtual void setLocalScaling(const Vector3& scaling) override;
/// Return the scaling vector
const Vector3& getScaling() const;
/// Return the local bounds of the shape in x, y and z directions
virtual void getLocalBounds(Vector3& min, Vector3& max) const override;
@ -130,19 +133,21 @@ class ConvexMeshShape : public ConvexPolyhedronShape {
/// Return the centroid of the polyhedron
virtual Vector3 getCentroid() const override;
};
/// Set the scaling vector of the collision shape
inline void ConvexMeshShape::setLocalScaling(const Vector3& scaling) {
ConvexShape::setLocalScaling(scaling);
recalculateBounds();
}
/// Return the string representation of the shape
virtual std::string to_string() const override;
};
// Return the number of bytes used by the collision shape
inline size_t ConvexMeshShape::getSizeInBytes() const {
return sizeof(ConvexMeshShape);
}
// Return the scaling vector
inline const Vector3& ConvexMeshShape::getScaling() const {
return mScaling;
}
// Return the local bounds of the shape in x, y and z directions
/**
* @param min The minimum bounds of the shape in local-space coordinates

View File

@ -41,11 +41,11 @@ using namespace reactphysics3d;
*/
HeightFieldShape::HeightFieldShape(int nbGridColumns, int nbGridRows, decimal minHeight, decimal maxHeight,
const void* heightFieldData, HeightDataType dataType, int upAxis,
decimal integerHeightScale)
decimal integerHeightScale, const Vector3& scaling)
: ConcaveShape(CollisionShapeName::HEIGHTFIELD), mNbColumns(nbGridColumns), mNbRows(nbGridRows),
mWidth(nbGridColumns - 1), mLength(nbGridRows - 1), mMinHeight(minHeight),
mMaxHeight(maxHeight), mUpAxis(upAxis), mIntegerHeightScale(integerHeightScale),
mHeightDataType(dataType) {
mHeightDataType(dataType), mScaling(scaling) {
assert(nbGridColumns >= 2);
assert(nbGridRows >= 2);
@ -217,7 +217,7 @@ bool HeightFieldShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxySh
// TODO : Implement raycasting without using an AABB for the ray
// but using a dynamic AABB tree or octree instead
PROFILE("HeightFieldShape::raycast()", mProfiler);
RP3D_PROFILE("HeightFieldShape::raycast()", mProfiler);
TriangleOverlapCallback triangleCallback(ray, proxyShape, raycastInfo, *this, allocator);
@ -297,3 +297,23 @@ void TriangleOverlapCallback::testTriangle(const Vector3* trianglePoints, const
mIsHit = true;
}
}
// Return the string representation of the shape
std::string HeightFieldShape::to_string() const {
std::stringstream ss;
ss << "HeightFieldShape{" << std::endl;
ss << "nbColumns=" << mNbColumns << std::endl;
ss << ", nbRows=" << mNbRows << std::endl;
ss << ", width=" << mWidth << std::endl;
ss << ", length=" << mLength << std::endl;
ss << ", minHeight=" << mMinHeight << std::endl;
ss << ", maxHeight=" << mMaxHeight << std::endl;
ss << ", upAxis=" << mUpAxis << std::endl;
ss << ", integerHeightScale=" << mIntegerHeightScale << std::endl;
ss << "}";
return ss.str();
}

View File

@ -29,7 +29,7 @@
// Libraries
#include "ConcaveShape.h"
#include "collision/shapes/TriangleShape.h"
#include "engine/Profiler.h"
#include "utils/Profiler.h"
namespace reactphysics3d {
@ -141,6 +141,9 @@ class HeightFieldShape : public ConcaveShape {
/// Local AABB of the height field (without scaling)
AABB mAABB;
/// Scaling vector
const Vector3 mScaling;
// -------------------- Methods -------------------- //
/// Raycast method with feedback information
@ -177,7 +180,8 @@ class HeightFieldShape : public ConcaveShape {
/// Constructor
HeightFieldShape(int nbGridColumns, int nbGridRows, decimal minHeight, decimal maxHeight,
const void* heightFieldData, HeightDataType dataType,
int upAxis = 1, decimal integerHeightScale = 1.0f);
int upAxis = 1, decimal integerHeightScale = 1.0f,
const Vector3& scaling = Vector3(1,1,1));
/// Destructor
virtual ~HeightFieldShape() override = default;
@ -188,6 +192,9 @@ class HeightFieldShape : public ConcaveShape {
/// Deleted assignment operator
HeightFieldShape& operator=(const HeightFieldShape& shape) = delete;
/// Return the scaling factor
const Vector3& getScaling() const;
/// Return the number of rows in the height field
int getNbRows() const;
@ -200,21 +207,26 @@ class HeightFieldShape : public ConcaveShape {
/// Return the local bounds of the shape in x, y and z directions.
virtual void getLocalBounds(Vector3& min, Vector3& max) const override;
/// Set the local scaling vector of the collision shape
virtual void setLocalScaling(const Vector3& scaling) override;
/// 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;
// ---------- Friendship ----------- //
friend class ConvexTriangleAABBOverlapCallback;
friend class ConcaveMeshRaycastCallback;
};
// Return the scaling factor
inline const Vector3& HeightFieldShape::getScaling() const {
return mScaling;
}
// Return the number of rows in the height field
inline int HeightFieldShape::getNbRows() const {
return mNbRows;
@ -235,11 +247,6 @@ inline size_t HeightFieldShape::getSizeInBytes() const {
return sizeof(HeightFieldShape);
}
// Set the local scaling vector of the collision shape
inline void HeightFieldShape::setLocalScaling(const Vector3& scaling) {
CollisionShape::setLocalScaling(scaling);
}
// Return the height of a given (x,y) point in the height field
inline decimal HeightFieldShape::getHeightAt(int x, int y) const {

View File

@ -82,9 +82,6 @@ class SphereShape : public ConvexShape {
/// Return true if the collision shape is a polyhedron
virtual bool isPolyhedron() const override;
/// Set the scaling vector of the collision shape
virtual void setLocalScaling(const Vector3& scaling) override;
/// Return the local bounds of the shape in x, y and z directions.
virtual void getLocalBounds(Vector3& min, Vector3& max) const override;
@ -93,6 +90,9 @@ class SphereShape : public ConvexShape {
/// Update the AABB of a body using its collision shape
virtual void computeAABB(AABB& aabb, const Transform& transform) const override;
/// Return the string representation of the shape
virtual std::string to_string() const override;
};
// Get the radius of the sphere
@ -108,14 +108,6 @@ inline bool SphereShape::isPolyhedron() const {
return false;
}
// Set the scaling vector of the collision shape
inline void SphereShape::setLocalScaling(const Vector3& scaling) {
mMargin = (mMargin / mScaling.x) * scaling.x;
CollisionShape::setLocalScaling(scaling);
}
// Return the number of bytes used by the collision shape
inline size_t SphereShape::getSizeInBytes() const {
return sizeof(SphereShape);
@ -181,6 +173,11 @@ inline bool SphereShape::testPointInside(const Vector3& localPoint, ProxyShape*
return (localPoint.lengthSquare() < mMargin * mMargin);
}
// Return the string representation of the shape
inline std::string SphereShape::to_string() const {
return "SphereShape{radius=" + std::to_string(getRadius()) + "}";
}
}
#endif

View File

@ -27,7 +27,7 @@
#include "TriangleShape.h"
#include "collision/ProxyShape.h"
#include "mathematics/mathematics_functions.h"
#include "engine/Profiler.h"
#include "utils/Profiler.h"
#include "configuration.h"
#include <cassert>
@ -213,7 +213,7 @@ Vector3 TriangleShape::computeSmoothLocalContactNormalForTriangle(const Vector3&
/// Real-time Collision Detection by Christer Ericson.
bool TriangleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, MemoryAllocator& allocator) const {
PROFILE("TriangleShape::raycast()", mProfiler);
RP3D_PROFILE("TriangleShape::raycast()", mProfiler);
const Vector3 pq = ray.point2 - ray.point1;
const Vector3 pa = mPoints[0] - ray.point1;

View File

@ -127,9 +127,6 @@ class TriangleShape : public ConvexPolyhedronShape {
/// Return the local bounds of the shape in x, y and z directions.
virtual void getLocalBounds(Vector3& min, Vector3& max) const override;
/// Set the local scaling vector of the collision shape
virtual void setLocalScaling(const Vector3& scaling) override;
/// Return the local inertia tensor of the collision shape
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, decimal mass) const override;
@ -175,6 +172,9 @@ class TriangleShape : public ConvexPolyhedronShape {
const Transform& shape1ToWorld, const Transform& shape2ToWorld,
decimal penetrationDepth, Vector3& outSmoothVertexNormal);
/// Return the string representation of the shape
virtual std::string to_string() const override;
// ---------- Friendship ---------- //
friend class ConcaveMeshRaycastCallback;
@ -211,16 +211,6 @@ inline void TriangleShape::getLocalBounds(Vector3& min, Vector3& max) const {
max += Vector3(mMargin, mMargin, mMargin);
}
// Set the local scaling vector of the collision shape
inline void TriangleShape::setLocalScaling(const Vector3& scaling) {
mPoints[0] = (mPoints[0] / mScaling) * scaling;
mPoints[1] = (mPoints[1] / mScaling) * scaling;
mPoints[2] = (mPoints[2] / mScaling) * scaling;
CollisionShape::setLocalScaling(scaling);
}
// Return the local inertia tensor of the triangle shape
/**
* @param[out] tensor The 3x3 inertia tensor matrix of the shape in local-space
@ -325,6 +315,12 @@ inline void TriangleShape::setRaycastTestType(TriangleRaycastSide testType) {
mRaycastTestType = testType;
}
// Return the string representation of the shape
inline std::string TriangleShape::to_string() const {
return "TriangleShape{v1=" + mPoints[0].to_string() + ", v2=" + mPoints[1].to_string() + "," +
"v3=" + mPoints[2].to_string() + "}";
}
}
#endif

View File

@ -31,6 +31,8 @@
#include <cfloat>
#include <utility>
#include <cstdint>
#include <sstream>
#include <string>
#include "decimal.h"
#include "containers/Pair.h"
@ -104,12 +106,18 @@ constexpr decimal DYNAMIC_TREE_AABB_GAP = decimal(0.1);
/// followin constant with the linear velocity and the elapsed time between two frames.
constexpr decimal DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER = decimal(1.7);
/// Current version of ReactPhysics3D
const std::string RP3D_VERSION = std::string("0.7.0");
/// Structure WorldSettings
/**
* This class is used to describe some settings of a physics world.
*/
struct WorldSettings {
/// Name of the world
std::string worldName = "";
/// Distance threshold for two contact points for a valid persistent contact (in meters)
decimal persistentContactDistanceThreshold = decimal(0.03);
@ -157,6 +165,30 @@ struct WorldSettings {
/// merge them. If the cosine of the angle between the normals of the two manifold are larger
/// than the value bellow, the manifold are considered to be similar.
decimal cosAngleSimilarContactManifold = decimal(0.95);
/// Return a string with the world settings
std::string to_string() const {
std::stringstream ss;
ss << "worldName=" << worldName << std::endl;
ss << "persistentContactDistanceThreshold=" << persistentContactDistanceThreshold << std::endl;
ss << "defaultFrictionCoefficient=" << defaultFrictionCoefficient << std::endl;
ss << "defaultBounciness=" << defaultBounciness << std::endl;
ss << "restitutionVelocityThreshold=" << restitutionVelocityThreshold << std::endl;
ss << "defaultRollingRestistance=" << defaultRollingRestistance << std::endl;
ss << "isSleepingEnabled=" << isSleepingEnabled << std::endl;
ss << "defaultVelocitySolverNbIterations=" << defaultVelocitySolverNbIterations << std::endl;
ss << "defaultPositionSolverNbIterations=" << defaultPositionSolverNbIterations << std::endl;
ss << "defaultTimeBeforeSleep=" << defaultTimeBeforeSleep << std::endl;
ss << "defaultSleepLinearVelocity=" << defaultSleepLinearVelocity << std::endl;
ss << "defaultSleepAngularVelocity=" << defaultSleepAngularVelocity << std::endl;
ss << "nbMaxContactManifoldsConvexShape=" << nbMaxContactManifoldsConvexShape << std::endl;
ss << "nbMaxContactManifoldsConcaveShape=" << nbMaxContactManifoldsConcaveShape << std::endl;
ss << "cosAngleSimilarContactManifold=" << cosAngleSimilarContactManifold << std::endl;
return ss.str();
}
};
}

View File

@ -33,8 +33,8 @@ using namespace reactphysics3d;
const decimal BallAndSocketJoint::BETA = decimal(0.2);
// Constructor
BallAndSocketJoint::BallAndSocketJoint(const BallAndSocketJointInfo& jointInfo)
: Joint(jointInfo), mImpulse(Vector3(0, 0, 0)) {
BallAndSocketJoint::BallAndSocketJoint(uint id, const BallAndSocketJointInfo& jointInfo)
: Joint(id, jointInfo), mImpulse(Vector3(0, 0, 0)) {
// Compute the local-space anchor point for each body
mLocalAnchorPointBody1 = mBody1->getTransform().getInverse() * jointInfo.anchorPointWorldSpace;

View File

@ -125,7 +125,7 @@ class BallAndSocketJoint : public Joint {
// -------------------- Methods -------------------- //
/// Constructor
BallAndSocketJoint(const BallAndSocketJointInfo& jointInfo);
BallAndSocketJoint(uint id, const BallAndSocketJointInfo& jointInfo);
/// Destructor
virtual ~BallAndSocketJoint() override = default;
@ -133,6 +133,9 @@ class BallAndSocketJoint : public Joint {
/// Deleted copy-constructor
BallAndSocketJoint(const BallAndSocketJoint& constraint) = delete;
/// Return a string representation
virtual std::string to_string() const override;
/// Deleted assignment operator
BallAndSocketJoint& operator=(const BallAndSocketJoint& constraint) = delete;
};
@ -142,6 +145,12 @@ inline size_t BallAndSocketJoint::getSizeInBytes() const {
return sizeof(BallAndSocketJoint);
}
// Return a string representation
inline std::string BallAndSocketJoint::to_string() const {
return "BallAndSocketJoint{ localAnchorPointBody1=" + mLocalAnchorPointBody1.to_string() +
", localAnchorPointBody2=" + mLocalAnchorPointBody2.to_string() + "}";
}
}
#endif

View File

@ -33,8 +33,8 @@ using namespace reactphysics3d;
const decimal FixedJoint::BETA = decimal(0.2);
// Constructor
FixedJoint::FixedJoint(const FixedJointInfo& jointInfo)
: Joint(jointInfo), mImpulseTranslation(0, 0, 0), mImpulseRotation(0, 0, 0) {
FixedJoint::FixedJoint(uint id, const FixedJointInfo& jointInfo)
: Joint(id, jointInfo), mImpulseTranslation(0, 0, 0), mImpulseRotation(0, 0, 0) {
// Compute the local-space anchor point for each body
const Transform& transform1 = mBody1->getTransform();

View File

@ -136,7 +136,7 @@ class FixedJoint : public Joint {
// -------------------- Methods -------------------- //
/// Constructor
FixedJoint(const FixedJointInfo& jointInfo);
FixedJoint(uint id, const FixedJointInfo& jointInfo);
/// Destructor
virtual ~FixedJoint() override = default;
@ -144,6 +144,9 @@ class FixedJoint : public Joint {
/// Deleted copy-constructor
FixedJoint(const FixedJoint& constraint) = delete;
/// Return a string representation
virtual std::string to_string() const override;
/// Deleted assignment operator
FixedJoint& operator=(const FixedJoint& constraint) = delete;
};
@ -153,6 +156,14 @@ inline size_t FixedJoint::getSizeInBytes() const {
return sizeof(FixedJoint);
}
// Return a string representation
inline std::string FixedJoint::to_string() const {
return "FixedJoint{ localAnchorPointBody1=" + mLocalAnchorPointBody1.to_string() +
", localAnchorPointBody2=" + mLocalAnchorPointBody2.to_string() +
", initOrientationDifferenceInv=" + mInitOrientationDifferenceInv.to_string() +
"}";
}
}
#endif

View File

@ -34,16 +34,16 @@ using namespace reactphysics3d;
const decimal HingeJoint::BETA = decimal(0.2);
// Constructor
HingeJoint::HingeJoint(const HingeJointInfo& jointInfo)
: Joint(jointInfo), mImpulseTranslation(0, 0, 0), mImpulseRotation(0, 0),
HingeJoint::HingeJoint(uint id, const HingeJointInfo& jointInfo)
: Joint(id, jointInfo), mImpulseTranslation(0, 0, 0), mImpulseRotation(0, 0),
mImpulseLowerLimit(0), mImpulseUpperLimit(0), mImpulseMotor(0),
mIsLimitEnabled(jointInfo.isLimitEnabled), mIsMotorEnabled(jointInfo.isMotorEnabled),
mLowerLimit(jointInfo.minAngleLimit), mUpperLimit(jointInfo.maxAngleLimit),
mIsLowerLimitViolated(false), mIsUpperLimitViolated(false),
mMotorSpeed(jointInfo.motorSpeed), mMaxMotorTorque(jointInfo.maxMotorTorque) {
assert(mLowerLimit <= 0 && mLowerLimit >= -2.0 * PI);
assert(mUpperLimit >= 0 && mUpperLimit <= 2.0 * PI);
assert(mLowerLimit <= decimal(0) && mLowerLimit >= decimal(-2.0) * PI);
assert(mUpperLimit >= decimal(0) && mUpperLimit <= decimal(2.0) * PI);
// Compute the local-space anchor point for each body
Transform transform1 = mBody1->getTransform();

View File

@ -287,7 +287,7 @@ class HingeJoint : public Joint {
// -------------------- Methods -------------------- //
/// Constructor
HingeJoint(const HingeJointInfo& jointInfo);
HingeJoint(uint id, const HingeJointInfo& jointInfo);
/// Destructor
virtual ~HingeJoint() override = default;
@ -336,6 +336,9 @@ class HingeJoint : public Joint {
/// Return the intensity of the current torque applied for the joint motor
decimal getMotorTorque(decimal timeStep) const;
/// Return a string representation
virtual std::string to_string() const override;
};
// Return true if the limits of the joint are enabled
@ -400,6 +403,17 @@ inline size_t HingeJoint::getSizeInBytes() const {
return sizeof(HingeJoint);
}
// Return a string representation
inline std::string HingeJoint::to_string() const {
return "HingeJoint{ lowerLimit=" + std::to_string(mLowerLimit) + ", upperLimit=" + std::to_string(mUpperLimit) +
"localAnchorPointBody1=" + mLocalAnchorPointBody1.to_string() + ", localAnchorPointBody2=" +
mLocalAnchorPointBody2.to_string() + ", hingeLocalAxisBody1=" + mHingeLocalAxisBody1.to_string() +
", hingeLocalAxisBody2=" + mHingeLocalAxisBody2.to_string() + ", initOrientationDifferenceInv=" +
mInitOrientationDifferenceInv.to_string() + ", motorSpeed=" + std::to_string(mMotorSpeed) +
", maxMotorTorque=" + std::to_string(mMaxMotorTorque) + ", isLimitEnabled=" +
(mIsLimitEnabled ? "true" : "false") + ", isMotorEnabled=" + (mIsMotorEnabled ? "true" : "false") + "}";
}
}

View File

@ -29,8 +29,8 @@
using namespace reactphysics3d;
// Constructor
Joint::Joint(const JointInfo& jointInfo)
:mBody1(jointInfo.body1), mBody2(jointInfo.body2), mType(jointInfo.type),
Joint::Joint(uint id, const JointInfo& jointInfo)
:mId(id), mBody1(jointInfo.body1), mBody2(jointInfo.body2), mType(jointInfo.type),
mPositionCorrectionTechnique(jointInfo.positionCorrectionTechnique),
mIsCollisionEnabled(jointInfo.isCollisionEnabled), mIsAlreadyInIsland(false) {

View File

@ -120,6 +120,9 @@ class Joint {
// -------------------- Attributes -------------------- //
/// Id of the joint
uint mId;
/// Pointer to the first body of the joint
RigidBody* const mBody1;
@ -144,6 +147,9 @@ class Joint {
/// True if the joint has already been added into an island
bool mIsAlreadyInIsland;
/// Total number of joints
static uint mNbTotalNbJoints;
// -------------------- Methods -------------------- //
/// Return true if the joint has already been added into an island
@ -169,7 +175,7 @@ class Joint {
// -------------------- Methods -------------------- //
/// Constructor
Joint(const JointInfo& jointInfo);
Joint(uint id, const JointInfo& jointInfo);
/// Destructor
virtual ~Joint() = default;
@ -195,6 +201,12 @@ class Joint {
/// Return true if the collision between the two bodies of the joint is enabled
bool isCollisionEnabled() const;
/// Return the id of the joint
uint getId() const;
/// Return a string representation
virtual std::string to_string() const=0;
// -------------------- Friendship -------------------- //
friend class DynamicsWorld;
@ -243,6 +255,14 @@ inline bool Joint::isCollisionEnabled() const {
return mIsCollisionEnabled;
}
// Return the id of the joint
/**
* @return The id of the joint
*/
inline uint Joint::getId() const {
return mId;
}
// Return true if the joint has already been added into an island
inline bool Joint::isAlreadyInIsland() const {
return mIsAlreadyInIsland;

View File

@ -32,8 +32,8 @@ using namespace reactphysics3d;
const decimal SliderJoint::BETA = decimal(0.2);
// Constructor
SliderJoint::SliderJoint(const SliderJointInfo& jointInfo)
: Joint(jointInfo), mImpulseTranslation(0, 0), mImpulseRotation(0, 0, 0),
SliderJoint::SliderJoint(uint id, const SliderJointInfo& jointInfo)
: Joint(id, jointInfo), mImpulseTranslation(0, 0), mImpulseRotation(0, 0, 0),
mImpulseLowerLimit(0), mImpulseUpperLimit(0), mImpulseMotor(0),
mIsLimitEnabled(jointInfo.isLimitEnabled), mIsMotorEnabled(jointInfo.isMotorEnabled),
mLowerLimit(jointInfo.minTranslationLimit),
@ -41,9 +41,9 @@ SliderJoint::SliderJoint(const SliderJointInfo& jointInfo)
mIsUpperLimitViolated(false), mMotorSpeed(jointInfo.motorSpeed),
mMaxMotorForce(jointInfo.maxMotorForce){
assert(mUpperLimit >= 0.0);
assert(mLowerLimit <= 0.0);
assert(mMaxMotorForce >= 0.0);
assert(mUpperLimit >= decimal(0.0));
assert(mLowerLimit <= decimal(0.0));
assert(mMaxMotorForce >= decimal(0.0));
// Compute the local-space anchor point for each body
const Transform& transform1 = mBody1->getTransform();

View File

@ -285,7 +285,7 @@ class SliderJoint : public Joint {
// -------------------- Methods -------------------- //
/// Constructor
SliderJoint(const SliderJointInfo& jointInfo);
SliderJoint(uint id, const SliderJointInfo& jointInfo);
/// Destructor
virtual ~SliderJoint() override = default;
@ -337,6 +337,9 @@ class SliderJoint : public Joint {
/// Return the intensity of the current force applied for the joint motor
decimal getMotorForce(decimal timeStep) const;
/// Return a string representation
virtual std::string to_string() const override;
};
// Return true if the limits or the joint are enabled
@ -401,6 +404,17 @@ inline size_t SliderJoint::getSizeInBytes() const {
return sizeof(SliderJoint);
}
// Return a string representation
inline std::string SliderJoint::to_string() const {
return "SliderJoint{ lowerLimit=" + std::to_string(mLowerLimit) + ", upperLimit=" + std::to_string(mUpperLimit) +
"localAnchorPointBody1=" + mLocalAnchorPointBody1.to_string() + ", localAnchorPointBody2=" +
mLocalAnchorPointBody2.to_string() + ", sliderAxisBody1=" + mSliderAxisBody1.to_string() +
", initOrientationDifferenceInv=" +
mInitOrientationDifferenceInv.to_string() + ", motorSpeed=" + std::to_string(mMotorSpeed) +
", maxMotorForce=" + std::to_string(mMaxMotorForce) + ", isLimitEnabled=" +
(mIsLimitEnabled ? "true" : "false") + ", isMotorEnabled=" + (mIsMotorEnabled ? "true" : "false") + "}";
}
}
#endif

View File

@ -29,6 +29,7 @@
// Libraries
#include "configuration.h"
#include "memory/MemoryAllocator.h"
#include <cassert>
#include <cstring>
#include <iterator>

View File

@ -86,7 +86,7 @@ class Pair {
}
// Hash function for struct VerticesPair
// Hash function for a reactphysics3d Pair
namespace std {
template <typename T1, typename T2> struct hash<reactphysics3d::Pair<T1, T2>> {

View File

@ -26,33 +26,104 @@
// Libraries
#include "CollisionWorld.h"
#include <algorithm>
#include <sstream>
// Namespaces
using namespace reactphysics3d;
using namespace std;
// Initialization of static fields
uint CollisionWorld::mNbWorlds = 0;
// Constructor
CollisionWorld::CollisionWorld(const WorldSettings& worldSettings)
: mConfig(worldSettings), mCollisionDetection(this, mMemoryManager), mBodies(mMemoryManager.getPoolAllocator()), mCurrentBodyID(0),
mFreeBodiesIDs(mMemoryManager.getPoolAllocator()), mEventListener(nullptr) {
CollisionWorld::CollisionWorld(const WorldSettings& worldSettings, Logger* logger, Profiler* profiler)
: mConfig(worldSettings), mCollisionDetection(this, mMemoryManager), mBodies(mMemoryManager.getPoolAllocator()), mCurrentBodyId(0),
mFreeBodiesIds(mMemoryManager.getPoolAllocator()), mEventListener(nullptr), mName(worldSettings.worldName),
mProfiler(profiler), mLogger(logger), mIsProfilerCreatedByUser(profiler != nullptr),
mIsLoggerCreatedByUser(logger != nullptr) {
// Automatically generate a name for the world
if (mName == "") {
std::stringstream ss;
ss << "world";
if (mNbWorlds > 0) {
ss << mNbWorlds;
}
mName = ss.str();
}
#ifdef IS_PROFILING_ACTIVE
// If the user has not provided its own profiler, we create one
if (mProfiler == nullptr) {
mProfiler = new Profiler();
// Add a destination file for the profiling data
mProfiler->addFileDestination("rp3d_profiling_" + mName + ".txt", Profiler::Format::Text);
}
// Set the profiler
mCollisionDetection.setProfiler(&mProfiler);
mCollisionDetection.setProfiler(mProfiler);
#endif
#ifdef IS_LOGGING_ACTIVE
// If the user has not provided its own logger, we create one
if (mLogger == nullptr) {
mLogger = new Logger();
// Add a log destination file
uint logLevel = static_cast<uint>(Logger::Level::Information) | static_cast<uint>(Logger::Level::Warning) |
static_cast<uint>(Logger::Level::Error);
mLogger->addFileDestination("rp3d_log_" + mName + ".html", logLevel, Logger::Format::HTML);
}
#endif
mNbWorlds++;
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Collision World: Collision world " + mName + " has been created");
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Collision World: Initial world settings: " + worldSettings.to_string());
}
// Destructor
CollisionWorld::~CollisionWorld() {
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Collision World: Collision world " + mName + " has been destroyed");
// Destroy all the collision bodies that have not been removed
for (int i=mBodies.size() - 1 ; i >= 0; i--) {
destroyCollisionBody(mBodies[i]);
}
#ifdef IS_PROFILING_ACTIVE
/// Delete the profiler
if (!mIsProfilerCreatedByUser) {
delete mProfiler;
}
#endif
#ifdef IS_LOGGING_ACTIVE
/// Delete the logger
if (!mIsLoggerCreatedByUser) {
delete mLogger;
}
#endif
assert(mBodies.size() == 0);
}
@ -64,7 +135,7 @@ CollisionWorld::~CollisionWorld() {
CollisionBody* CollisionWorld::createCollisionBody(const Transform& transform) {
// Get the next available body ID
bodyindex bodyID = computeNextAvailableBodyID();
bodyindex bodyID = computeNextAvailableBodyId();
// Largest index cannot be used (it is used for invalid index)
assert(bodyID < std::numeric_limits<reactphysics3d::bodyindex>::max());
@ -81,10 +152,17 @@ CollisionBody* CollisionWorld::createCollisionBody(const Transform& transform) {
#ifdef IS_PROFILING_ACTIVE
collisionBody->setProfiler(&mProfiler);
collisionBody->setProfiler(mProfiler);
#endif
#ifdef IS_LOGGING_ACTIVE
collisionBody->setLogger(mLogger);
#endif
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(bodyID) + ": New collision body created");
// Return the pointer to the rigid body
return collisionBody;
}
@ -95,11 +173,14 @@ CollisionBody* CollisionWorld::createCollisionBody(const Transform& transform) {
*/
void CollisionWorld::destroyCollisionBody(CollisionBody* collisionBody) {
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(collisionBody->getId()) + ": collision body destroyed");
// Remove all the collision shapes of the body
collisionBody->removeAllCollisionShapes();
// Add the body ID to the list of free IDs
mFreeBodiesIDs.add(collisionBody->getID());
mFreeBodiesIds.add(collisionBody->getId());
// Call the destructor of the collision body
collisionBody->~CollisionBody();
@ -112,17 +193,17 @@ void CollisionWorld::destroyCollisionBody(CollisionBody* collisionBody) {
}
// Return the next available body ID
bodyindex CollisionWorld::computeNextAvailableBodyID() {
bodyindex CollisionWorld::computeNextAvailableBodyId() {
// Compute the body ID
bodyindex bodyID;
if (mFreeBodiesIDs.size() != 0) {
bodyID = mFreeBodiesIDs[mFreeBodiesIDs.size() - 1];
mFreeBodiesIDs.removeAt(mFreeBodiesIDs.size() - 1);
if (mFreeBodiesIds.size() != 0) {
bodyID = mFreeBodiesIds[mFreeBodiesIds.size() - 1];
mFreeBodiesIds.removeAt(mFreeBodiesIds.size() - 1);
}
else {
bodyID = mCurrentBodyID;
mCurrentBodyID++;
bodyID = mCurrentBodyId;
mCurrentBodyId++;
}
return bodyID;
@ -178,7 +259,7 @@ bool CollisionWorld::testOverlap(CollisionBody* body1, CollisionBody* body2) {
// Return the current world-space AABB of given proxy shape
AABB CollisionWorld::getWorldAABB(const ProxyShape* proxyShape) const {
if (proxyShape->mBroadPhaseID == -1) {
if (proxyShape->getBroadPhaseId() == -1) {
return AABB();
}

View File

@ -30,7 +30,8 @@
#include <algorithm>
#include "mathematics/mathematics.h"
#include "containers/List.h"
#include "Profiler.h"
#include "utils/Profiler.h"
#include "utils/Logger.h"
#include "body/CollisionBody.h"
#include "collision/RaycastInfo.h"
#include "OverlappingPair.h"
@ -71,25 +72,43 @@ class CollisionWorld {
/// All the bodies (rigid and soft) of the world
List<CollisionBody*> mBodies;
/// Current body ID
bodyindex mCurrentBodyID;
/// Current body id
bodyindex mCurrentBodyId;
/// List of free ID for rigid bodies
List<luint> mFreeBodiesIDs;
/// List of free ids for rigid bodies
List<luint> mFreeBodiesIds;
/// Pointer to an event listener object
EventListener* mEventListener;
/// Name of the collision world
std::string mName;
#ifdef IS_PROFILING_ACTIVE
/// Real-time hierarchical profiler
Profiler mProfiler;
Profiler* mProfiler;
#endif
#ifdef IS_LOGGING_ACTIVE
/// Logger
Logger* mLogger;
#endif
/// True if the profiler has been created by the user
bool mIsProfilerCreatedByUser;
/// True if the logger has been created by the user
bool mIsLoggerCreatedByUser;
/// Total number of worlds
static uint mNbWorlds;
// -------------------- Methods -------------------- //
/// Return the next available body ID
bodyindex computeNextAvailableBodyID();
/// Return the next available body id
bodyindex computeNextAvailableBodyId();
/// Reset all the contact manifolds linked list of each body
void resetContactManifoldListsOfBodies();
@ -99,7 +118,8 @@ class CollisionWorld {
// -------------------- Methods -------------------- //
/// Constructor
CollisionWorld(const WorldSettings& worldSettings = WorldSettings());
CollisionWorld(const WorldSettings& worldSettings = WorldSettings(), Logger* logger = nullptr,
Profiler* profiler = nullptr);
/// Destructor
virtual ~CollisionWorld();
@ -147,13 +167,24 @@ class CollisionWorld {
#ifdef IS_PROFILING_ACTIVE
/// Set the name of the profiler
void setProfilerName(std::string name);
/// Return a reference to the profiler
Profiler* getProfiler();
#endif
#ifdef IS_LOGGING_ACTIVE
/// Return a reference to the logger
Logger* getLogger();
#endif
/// Return the current world-space AABB of given proxy shape
AABB getWorldAABB(const ProxyShape* proxyShape) const;
/// Return the name of the world
const std::string& getName() const;
// -------------------- Friendship -------------------- //
friend class CollisionDetection;
@ -224,11 +255,25 @@ inline void CollisionWorld::testOverlap(CollisionBody* body, OverlapCallback* ov
mCollisionDetection.testOverlap(body, overlapCallback, categoryMaskBits);
}
// Return the name of the world
inline const std::string& CollisionWorld::getName() const {
return mName;
}
#ifdef IS_PROFILING_ACTIVE
// Set the name of the profiler
inline void CollisionWorld::setProfilerName(std::string name) {
mProfiler.setName(name);
// Return a pointer to the profiler
inline Profiler* CollisionWorld::getProfiler() {
return mProfiler;
}
#endif
#ifdef IS_LOGGING_ACTIVE
// Return a pointer to the logger
inline Logger* CollisionWorld::getLogger() {
return mLogger;
}
#endif

View File

@ -25,7 +25,7 @@
// Libraries
#include "ConstraintSolver.h"
#include "Profiler.h"
#include "utils/Profiler.h"
using namespace reactphysics3d;
@ -43,7 +43,7 @@ ConstraintSolver::ConstraintSolver() : mIsWarmStartingActive(true) {
// Initialize the constraint solver for a given island
void ConstraintSolver::initializeForIsland(decimal dt, Island* island) {
PROFILE("ConstraintSolver::initializeForIsland()", mProfiler);
RP3D_PROFILE("ConstraintSolver::initializeForIsland()", mProfiler);
assert(island != nullptr);
assert(island->getNbBodies() > 0);
@ -73,7 +73,7 @@ void ConstraintSolver::initializeForIsland(decimal dt, Island* island) {
// Solve the velocity constraints
void ConstraintSolver::solveVelocityConstraints(Island* island) {
PROFILE("ConstraintSolver::solveVelocityConstraints()", mProfiler);
RP3D_PROFILE("ConstraintSolver::solveVelocityConstraints()", mProfiler);
assert(island != nullptr);
assert(island->getNbJoints() > 0);
@ -90,7 +90,7 @@ void ConstraintSolver::solveVelocityConstraints(Island* island) {
// Solve the position constraints
void ConstraintSolver::solvePositionConstraints(Island* island) {
PROFILE("ConstraintSolver::solvePositionConstraints()", mProfiler);
RP3D_PROFILE("ConstraintSolver::solvePositionConstraints()", mProfiler);
assert(island != nullptr);
assert(island->getNbJoints() > 0);

View File

@ -27,7 +27,7 @@
#include "ContactSolver.h"
#include "DynamicsWorld.h"
#include "body/RigidBody.h"
#include "Profiler.h"
#include "utils/Profiler.h"
#include <limits>
using namespace reactphysics3d;
@ -50,7 +50,7 @@ ContactSolver::ContactSolver(MemoryManager& memoryManager, const WorldSettings&
// Initialize the contact constraints
void ContactSolver::init(Island** islands, uint nbIslands, decimal timeStep) {
PROFILE("ContactSolver::init()", mProfiler);
RP3D_PROFILE("ContactSolver::init()", mProfiler);
mTimeStep = timeStep;
@ -98,7 +98,7 @@ void ContactSolver::init(Island** islands, uint nbIslands, decimal timeStep) {
// Initialize the constraint solver for a given island
void ContactSolver::initializeForIsland(Island* island) {
PROFILE("ContactSolver::initializeForIsland()", mProfiler);
RP3D_PROFILE("ContactSolver::initializeForIsland()", mProfiler);
assert(island != nullptr);
assert(island->getNbBodies() > 0);
@ -326,7 +326,7 @@ void ContactSolver::initializeForIsland(Island* island) {
/// the solution of the linear system
void ContactSolver::warmStart() {
PROFILE("ContactSolver::warmStart()", mProfiler);
RP3D_PROFILE("ContactSolver::warmStart()", mProfiler);
uint contactPointIndex = 0;
@ -479,7 +479,7 @@ void ContactSolver::warmStart() {
// Solve the contacts
void ContactSolver::solve() {
PROFILE("ContactSolver::solve()", mProfiler);
RP3D_PROFILE("ContactSolver::solve()", mProfiler);
decimal deltaLambda;
decimal lambdaTemp;
@ -758,7 +758,7 @@ void ContactSolver::solve() {
// warm start the solver at the next iteration
void ContactSolver::storeImpulses() {
PROFILE("ContactSolver::storeImpulses()", mProfiler);
RP3D_PROFILE("ContactSolver::storeImpulses()", mProfiler);
uint contactPointIndex = 0;
@ -786,7 +786,7 @@ void ContactSolver::storeImpulses() {
void ContactSolver::computeFrictionVectors(const Vector3& deltaVelocity,
ContactManifoldSolver& contact) const {
PROFILE("ContactSolver::computeFrictionVectors()", mProfiler);
RP3D_PROFILE("ContactSolver::computeFrictionVectors()", mProfiler);
assert(contact.normal.length() > decimal(0.0));

View File

@ -39,8 +39,9 @@ using namespace std;
/**
* @param gravity Gravity vector in the world (in meters per second squared)
*/
DynamicsWorld::DynamicsWorld(const Vector3 &gravity, const WorldSettings& worldSettings)
: CollisionWorld(worldSettings),
DynamicsWorld::DynamicsWorld(const Vector3& gravity, const WorldSettings& worldSettings,
Logger* logger, Profiler* profiler)
: CollisionWorld(worldSettings, logger, profiler),
mContactSolver(mMemoryManager, mConfig),
mNbVelocitySolverIterations(mConfig.defaultVelocitySolverNbIterations),
mNbPositionSolverIterations(mConfig.defaultPositionSolverNbIterations),
@ -52,16 +53,20 @@ DynamicsWorld::DynamicsWorld(const Vector3 &gravity, const WorldSettings& worldS
mConstrainedOrientations(nullptr), mNbIslands(0), mIslands(nullptr),
mSleepLinearVelocity(mConfig.defaultSleepLinearVelocity),
mSleepAngularVelocity(mConfig.defaultSleepAngularVelocity),
mTimeBeforeSleep(mConfig.defaultTimeBeforeSleep) {
mTimeBeforeSleep(mConfig.defaultTimeBeforeSleep),
mFreeJointsIDs(mMemoryManager.getPoolAllocator()), mCurrentJointId(0) {
#ifdef IS_PROFILING_ACTIVE
// Set the profiler
mConstraintSolver.setProfiler(&mProfiler);
mContactSolver.setProfiler(&mProfiler);
mConstraintSolver.setProfiler(mProfiler);
mContactSolver.setProfiler(mProfiler);
#endif
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: Dynamics world " + mName + " has been created");
}
// Destructor
@ -82,13 +87,12 @@ DynamicsWorld::~DynamicsWorld() {
#ifdef IS_PROFILING_ACTIVE
// Print the profiling report
ofstream myfile;
myfile.open(mProfiler.getName() + ".txt");
mProfiler.printReport(myfile);
myfile.close();
// Print the profiling report into the destinations
mProfiler->printReport();
#endif
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: Dynamics world " + mName + " has been destroyed");
}
// Update the physics simulation
@ -99,10 +103,10 @@ void DynamicsWorld::update(decimal timeStep) {
#ifdef IS_PROFILING_ACTIVE
// Increment the frame counter of the profiler
mProfiler.incrementFrameCounter();
mProfiler->incrementFrameCounter();
#endif
PROFILE("DynamicsWorld::update()", &mProfiler);
RP3D_PROFILE("DynamicsWorld::update()", mProfiler);
mTimeStep = timeStep;
@ -150,7 +154,7 @@ void DynamicsWorld::update(decimal timeStep) {
/// the sympletic Euler time stepping scheme.
void DynamicsWorld::integrateRigidBodiesPositions() {
PROFILE("DynamicsWorld::integrateRigidBodiesPositions()", &mProfiler);
RP3D_PROFILE("DynamicsWorld::integrateRigidBodiesPositions()", mProfiler);
// For each island of the world
for (uint i=0; i < mNbIslands; i++) {
@ -189,7 +193,7 @@ void DynamicsWorld::integrateRigidBodiesPositions() {
// Update the postion/orientation of the bodies
void DynamicsWorld::updateBodiesState() {
PROFILE("DynamicsWorld::updateBodiesState()", &mProfiler);
RP3D_PROFILE("DynamicsWorld::updateBodiesState()", mProfiler);
// For each island of the world
for (uint islandIndex = 0; islandIndex < mNbIslands; islandIndex++) {
@ -226,7 +230,7 @@ void DynamicsWorld::updateBodiesState() {
// Initialize the bodies velocities arrays for the next simulation step.
void DynamicsWorld::initVelocityArrays() {
PROFILE("DynamicsWorld::initVelocityArrays()", &mProfiler);
RP3D_PROFILE("DynamicsWorld::initVelocityArrays()", mProfiler);
// Allocate memory for the bodies velocity arrays
uint nbBodies = mRigidBodies.size();
@ -268,7 +272,7 @@ void DynamicsWorld::initVelocityArrays() {
/// contact solver.
void DynamicsWorld::integrateRigidBodiesVelocities() {
PROFILE("DynamicsWorld::integrateRigidBodiesVelocities()", &mProfiler);
RP3D_PROFILE("DynamicsWorld::integrateRigidBodiesVelocities()", mProfiler);
// Initialize the bodies velocity arrays
initVelocityArrays();
@ -330,7 +334,7 @@ void DynamicsWorld::integrateRigidBodiesVelocities() {
// Solve the contacts and constraints
void DynamicsWorld::solveContactsAndConstraints() {
PROFILE("DynamicsWorld::solveContactsAndConstraints()", &mProfiler);
RP3D_PROFILE("DynamicsWorld::solveContactsAndConstraints()", mProfiler);
// Set the velocities arrays
mContactSolver.setSplitVelocitiesArrays(mSplitLinearVelocities, mSplitAngularVelocities);
@ -380,7 +384,7 @@ void DynamicsWorld::solveContactsAndConstraints() {
// Solve the position error correction of the constraints
void DynamicsWorld::solvePositionCorrection() {
PROFILE("DynamicsWorld::solvePositionCorrection()", &mProfiler);
RP3D_PROFILE("DynamicsWorld::solvePositionCorrection()", mProfiler);
// Do not continue if there is no constraints
if (mJoints.size() == 0) return;
@ -407,7 +411,7 @@ void DynamicsWorld::solvePositionCorrection() {
RigidBody* DynamicsWorld::createRigidBody(const Transform& transform) {
// Compute the body ID
bodyindex bodyID = computeNextAvailableBodyID();
bodyindex bodyID = computeNextAvailableBodyId();
// Largest index cannot be used (it is used for invalid index)
assert(bodyID < std::numeric_limits<reactphysics3d::bodyindex>::max());
@ -422,11 +426,16 @@ RigidBody* DynamicsWorld::createRigidBody(const Transform& transform) {
mRigidBodies.add(rigidBody);
#ifdef IS_PROFILING_ACTIVE
rigidBody->setProfiler(&mProfiler);
rigidBody->setProfiler(mProfiler);
#endif
#ifdef IS_LOGGING_ACTIVE
rigidBody->setLogger(mLogger);
#endif
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(bodyID) + ": New collision body created");
// Return the pointer to the rigid body
return rigidBody;
}
@ -437,11 +446,14 @@ RigidBody* DynamicsWorld::createRigidBody(const Transform& transform) {
*/
void DynamicsWorld::destroyRigidBody(RigidBody* rigidBody) {
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(rigidBody->getId()) + ": rigid body destroyed");
// Remove all the collision shapes of the body
rigidBody->removeAllCollisionShapes();
// Add the body ID to the list of free IDs
mFreeBodiesIDs.add(rigidBody->getID());
mFreeBodiesIds.add(rigidBody->getId());
// Destroy all the joints in which the rigid body to be destroyed is involved
JointListElement* element;
@ -472,6 +484,9 @@ Joint* DynamicsWorld::createJoint(const JointInfo& jointInfo) {
Joint* newJoint = nullptr;
// Get the next available joint ID
uint jointId = computeNextAvailableJointId();
// Allocate memory to create the new joint
switch(jointInfo.type) {
@ -482,7 +497,7 @@ Joint* DynamicsWorld::createJoint(const JointInfo& jointInfo) {
sizeof(BallAndSocketJoint));
const BallAndSocketJointInfo& info = static_cast<const BallAndSocketJointInfo&>(
jointInfo);
newJoint = new (allocatedMemory) BallAndSocketJoint(info);
newJoint = new (allocatedMemory) BallAndSocketJoint(jointId, info);
break;
}
@ -492,7 +507,7 @@ Joint* DynamicsWorld::createJoint(const JointInfo& jointInfo) {
void* allocatedMemory = mMemoryManager.allocate(MemoryManager::AllocationType::Pool,
sizeof(SliderJoint));
const SliderJointInfo& info = static_cast<const SliderJointInfo&>(jointInfo);
newJoint = new (allocatedMemory) SliderJoint(info);
newJoint = new (allocatedMemory) SliderJoint(jointId, info);
break;
}
@ -502,7 +517,7 @@ Joint* DynamicsWorld::createJoint(const JointInfo& jointInfo) {
void* allocatedMemory = mMemoryManager.allocate(MemoryManager::AllocationType::Pool,
sizeof(HingeJoint));
const HingeJointInfo& info = static_cast<const HingeJointInfo&>(jointInfo);
newJoint = new (allocatedMemory) HingeJoint(info);
newJoint = new (allocatedMemory) HingeJoint(jointId, info);
break;
}
@ -512,7 +527,7 @@ Joint* DynamicsWorld::createJoint(const JointInfo& jointInfo) {
void* allocatedMemory = mMemoryManager.allocate(MemoryManager::AllocationType::Pool,
sizeof(FixedJoint));
const FixedJointInfo& info = static_cast<const FixedJointInfo&>(jointInfo);
newJoint = new (allocatedMemory) FixedJoint(info);
newJoint = new (allocatedMemory) FixedJoint(jointId, info);
break;
}
@ -533,6 +548,11 @@ Joint* DynamicsWorld::createJoint(const JointInfo& jointInfo) {
// Add the joint into the world
mJoints.add(newJoint);
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Joint,
"Joint " + std::to_string(newJoint->getId()) + ": New joint created");
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Joint,
"Joint " + std::to_string(newJoint->getId()) + ": " + newJoint->to_string());
// Add the joint into the joint list of the bodies involved in the joint
addJointToBody(newJoint);
@ -548,6 +568,9 @@ void DynamicsWorld::destroyJoint(Joint* joint) {
assert(joint != nullptr);
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Joint,
"Joint " + std::to_string(joint->getId()) + ": joint destroyed");
// If the collision between the two bodies of the constraint was disabled
if (!joint->isCollisionEnabled()) {
@ -568,9 +591,15 @@ void DynamicsWorld::destroyJoint(Joint* joint) {
size_t nbBytes = joint->getSizeInBytes();
// Add the joint ID to the list of free IDs
mFreeJointsIDs.add(joint->getId());
// Call the destructor of the joint
joint->~Joint();
// Add the joint ID to the list of free IDs
mFreeJointsIDs.add(joint->getId());
// Release the allocated memory
mMemoryManager.release(MemoryManager::AllocationType::Pool, joint, nbBytes);
}
@ -587,12 +616,37 @@ void DynamicsWorld::addJointToBody(Joint* joint) {
joint->mBody1->mJointsList);
joint->mBody1->mJointsList = jointListElement1;
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(joint->mBody1->getId()) + ": Joint " + std::to_string(joint->getId()) +
" added to body");
// Add the joint at the beginning of the linked list of joints of the second body
void* allocatedMemory2 = mMemoryManager.allocate(MemoryManager::AllocationType::Pool,
sizeof(JointListElement));
JointListElement* jointListElement2 = new (allocatedMemory2) JointListElement(joint,
joint->mBody2->mJointsList);
joint->mBody2->mJointsList = jointListElement2;
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(joint->mBody2->getId()) + ": Joint " + std::to_string(joint->getId()) +
" added to body");
}
// Return the next available joint Id
uint DynamicsWorld::computeNextAvailableJointId() {
// Compute the joint ID
uint jointId;
if (mFreeJointsIDs.size() != 0) {
jointId = mFreeJointsIDs[mFreeJointsIDs.size() - 1];
mFreeJointsIDs.removeAt(mFreeJointsIDs.size() - 1);
}
else {
jointId = mCurrentJointId;
mCurrentJointId++;
}
return jointId;
}
// Compute the islands of awake bodies.
@ -604,7 +658,7 @@ void DynamicsWorld::addJointToBody(Joint* joint) {
/// it). Then, we create an island with this group of connected bodies.
void DynamicsWorld::computeIslands() {
PROFILE("DynamicsWorld::computeIslands()", &mProfiler);
RP3D_PROFILE("DynamicsWorld::computeIslands()", mProfiler);
uint nbBodies = mRigidBodies.size();
@ -693,7 +747,7 @@ void DynamicsWorld::computeIslands() {
// Get the other body of the contact manifold
RigidBody* body1 = static_cast<RigidBody*>(contactManifold->getBody1());
RigidBody* body2 = static_cast<RigidBody*>(contactManifold->getBody2());
RigidBody* otherBody = (body1->getID() == bodyToVisit->getID()) ? body2 : body1;
RigidBody* otherBody = (body1->getId() == bodyToVisit->getId()) ? body2 : body1;
// Check if the other body has already been added to the island
if (otherBody->mIsAlreadyInIsland) continue;
@ -721,7 +775,7 @@ void DynamicsWorld::computeIslands() {
// Get the other body of the contact manifold
RigidBody* body1 = static_cast<RigidBody*>(joint->getBody1());
RigidBody* body2 = static_cast<RigidBody*>(joint->getBody2());
RigidBody* otherBody = (body1->getID() == bodyToVisit->getID()) ? body2 : body1;
RigidBody* otherBody = (body1->getId() == bodyToVisit->getId()) ? body2 : body1;
// Check if the other body has already been added to the island
if (otherBody->mIsAlreadyInIsland) continue;
@ -751,7 +805,7 @@ void DynamicsWorld::computeIslands() {
/// time, we put all the bodies of the island to sleep.
void DynamicsWorld::updateSleepingBodies() {
PROFILE("DynamicsWorld::updateSleepingBodies()", &mProfiler);
RP3D_PROFILE("DynamicsWorld::updateSleepingBodies()", mProfiler);
const decimal sleepLinearVelocitySquare = mSleepLinearVelocity * mSleepLinearVelocity;
const decimal sleepAngularVelocitySquare = mSleepAngularVelocity * mSleepAngularVelocity;
@ -820,6 +874,9 @@ void DynamicsWorld::enableSleeping(bool isSleepingEnabled) {
(*it)->setIsSleeping(false);
}
}
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: isSleepingEnabled=" + (isSleepingEnabled ? std::string("true") : std::string("false")) );
}
/// Return the list of all contacts of the world

View File

@ -116,6 +116,12 @@ class DynamicsWorld : public CollisionWorld {
/// becomes smaller than the sleep velocity.
decimal mTimeBeforeSleep;
/// List of free ID for joints
List<luint> mFreeJointsIDs;
/// Current joint id
uint mCurrentJointId;
// -------------------- Methods -------------------- //
/// Integrate the positions and orientations of rigid bodies.
@ -148,12 +154,16 @@ class DynamicsWorld : public CollisionWorld {
/// Add the joint to the list of joints of the two bodies involved in the joint
void addJointToBody(Joint* joint);
/// Return the next available joint id
uint computeNextAvailableJointId();
public :
// -------------------- Methods -------------------- //
/// Constructor
DynamicsWorld(const Vector3& mGravity, const WorldSettings& worldSettings = WorldSettings());
DynamicsWorld(const Vector3& mGravity, const WorldSettings& worldSettings = WorldSettings(),
Logger* logger = nullptr, Profiler* profiler = nullptr);
/// Destructor
virtual ~DynamicsWorld() override;
@ -272,6 +282,9 @@ inline uint DynamicsWorld::getNbIterationsVelocitySolver() const {
*/
inline void DynamicsWorld::setNbIterationsVelocitySolver(uint nbIterations) {
mNbVelocitySolverIterations = nbIterations;
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: Set nb iterations velocity solver to " + std::to_string(nbIterations));
}
// Get the number of iterations for the position constraint solver
@ -285,6 +298,9 @@ inline uint DynamicsWorld::getNbIterationsPositionSolver() const {
*/
inline void DynamicsWorld::setNbIterationsPositionSolver(uint nbIterations) {
mNbPositionSolverIterations = nbIterations;
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: Set nb iterations position solver to " + std::to_string(nbIterations));
}
// Set the position correction technique used for contacts
@ -329,6 +345,9 @@ inline Vector3 DynamicsWorld::getGravity() const {
*/
inline void DynamicsWorld::setGravity(Vector3& gravity) {
mGravity = gravity;
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: Set gravity vector to " + gravity.to_string());
}
// Return if the gravity is enaled
@ -346,6 +365,9 @@ inline bool DynamicsWorld::isGravityEnabled() const {
*/
inline void DynamicsWorld::setIsGratityEnabled(bool isGravityEnabled) {
mIsGravityEnabled = isGravityEnabled;
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: isGravityEnabled= " + (isGravityEnabled ? std::string("true") : std::string("false")));
}
// Return the number of rigid bodies in the world
@ -390,6 +412,9 @@ inline decimal DynamicsWorld::getSleepLinearVelocity() const {
inline void DynamicsWorld::setSleepLinearVelocity(decimal sleepLinearVelocity) {
assert(sleepLinearVelocity >= decimal(0.0));
mSleepLinearVelocity = sleepLinearVelocity;
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: sleepLinearVelocity= " + std::to_string(sleepLinearVelocity));
}
// Return the current sleep angular velocity
@ -410,6 +435,9 @@ inline decimal DynamicsWorld::getSleepAngularVelocity() const {
inline void DynamicsWorld::setSleepAngularVelocity(decimal sleepAngularVelocity) {
assert(sleepAngularVelocity >= decimal(0.0));
mSleepAngularVelocity = sleepAngularVelocity;
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: sleepAngularVelocity= " + std::to_string(sleepAngularVelocity));
}
// Return the time a body is required to stay still before sleeping
@ -428,6 +456,9 @@ inline decimal DynamicsWorld::getTimeBeforeSleep() const {
inline void DynamicsWorld::setTimeBeforeSleep(decimal timeBeforeSleep) {
assert(timeBeforeSleep >= decimal(0.0));
mTimeBeforeSleep = timeBeforeSleep;
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: timeBeforeSleep= " + std::to_string(timeBeforeSleep));
}
// Set an event listener object to receive events callbacks.

View File

@ -84,6 +84,9 @@ class Material {
/// Set the rolling resistance factor
void setRollingResistance(decimal rollingResistance);
/// Return a string representation for the material
std::string to_string() const;
/// Overloaded assignment operator
Material& operator=(const Material& material);
};
@ -147,6 +150,18 @@ inline void Material::setRollingResistance(decimal rollingResistance) {
mRollingResistance = rollingResistance;
}
// Return a string representation for the material
inline std::string Material::to_string() const {
std::stringstream ss;
ss << "frictionCoefficient=" << mFrictionCoefficient << std::endl;
ss << "rollingResistance=" << mRollingResistance << std::endl;
ss << "bounciness=" << mBounciness << std::endl;
return ss.str();
}
// Overloaded assignment operator
inline Material& Material::operator=(const Material& material) {

View File

@ -248,12 +248,12 @@ inline void OverlappingPair::makeContactsObsolete() {
// Return the pair of bodies index
inline OverlappingPair::OverlappingPairId OverlappingPair::computeID(ProxyShape* shape1, ProxyShape* shape2) {
assert(shape1->mBroadPhaseID >= 0 && shape2->mBroadPhaseID >= 0);
assert(shape1->getBroadPhaseId() >= 0 && shape2->getBroadPhaseId() >= 0);
// Construct the pair of body index
OverlappingPairId pairID = shape1->mBroadPhaseID < shape2->mBroadPhaseID ?
OverlappingPairId(shape1->mBroadPhaseID, shape2->mBroadPhaseID) :
OverlappingPairId(shape2->mBroadPhaseID, shape1->mBroadPhaseID);
OverlappingPairId pairID = shape1->getBroadPhaseId() < shape2->getBroadPhaseId() ?
OverlappingPairId(shape1->getBroadPhaseId(), shape2->getBroadPhaseId()) :
OverlappingPairId(shape2->getBroadPhaseId(), shape1->getBroadPhaseId());
assert(pairID.first != pairID.second);
return pairID;
}
@ -263,9 +263,9 @@ inline bodyindexpair OverlappingPair::computeBodiesIndexPair(CollisionBody* body
CollisionBody* body2) {
// Construct the pair of body index
bodyindexpair indexPair = body1->getID() < body2->getID() ?
bodyindexpair(body1->getID(), body2->getID()) :
bodyindexpair(body2->getID(), body1->getID());
bodyindexpair indexPair = body1->getId() < body2->getId() ?
bodyindexpair(body1->getId(), body2->getId()) :
bodyindexpair(body2->getId(), body1->getId());
assert(indexPair.first != indexPair.second);
return indexPair;
}

View File

@ -28,6 +28,7 @@
// Libraries
#include <cassert>
#include <string>
#include "Vector2.h"
/// ReactPhysics3D namespace
@ -145,6 +146,9 @@ class Matrix2x2 {
/// Overloaded operator to read/write element of the matrix.
Vector2& operator[](int row);
/// Return the string representation
std::string to_string() const;
};
// Constructor of the class Matrix2x2
@ -340,6 +344,12 @@ inline Vector2& Matrix2x2::operator[](int row) {
return mRows[row];
}
// Get the string representation
inline std::string Matrix2x2::to_string() const {
return "Matrix2x2(" + std::to_string(mRows[0][0]) + "," + std::to_string(mRows[0][1]) + "," +
std::to_string(mRows[1][0]) + "," + std::to_string(mRows[1][1]) + ")";
}
}
#endif

View File

@ -29,6 +29,7 @@
// Libraries
#include <cassert>
#include <string>
#include "Vector3.h"
/// ReactPhysics3D namespace
@ -153,6 +154,9 @@ class Matrix3x3 {
/// Overloaded operator to read/write element of the matrix.
Vector3& operator[](int row);
/// Return the string representation
std::string to_string() const;
};
// Constructor of the class Matrix3x3
@ -392,6 +396,13 @@ inline Vector3& Matrix3x3::operator[](int row) {
return mRows[row];
}
// Get the string representation
inline std::string Matrix3x3::to_string() const {
return "Matrix3x3(" + std::to_string(mRows[0][0]) + "," + std::to_string(mRows[0][1]) + "," + std::to_string(mRows[0][2]) + "," +
std::to_string(mRows[1][0]) + "," + std::to_string(mRows[1][1]) + "," + std::to_string(mRows[1][2]) + "," +
std::to_string(mRows[2][0]) + "," + std::to_string(mRows[2][1]) + "," + std::to_string(mRows[2][2]) + ")";
}
}
#endif

View File

@ -163,6 +163,9 @@ struct Quaternion {
/// Overloaded operator for equality condition
bool operator==(const Quaternion& quaternion) const;
/// Return the string representation
std::string to_string() const;
private:
/// Initialize the quaternion using Euler angles
@ -379,6 +382,12 @@ inline bool Quaternion::operator==(const Quaternion& quaternion) const {
z == quaternion.z && w == quaternion.w);
}
// Get the string representation
inline std::string Quaternion::to_string() const {
return "Quaternion(" + std::to_string(x) + "," + std::to_string(y) + "," + std::to_string(z) + "," +
std::to_string(w) + ")";
}
}
#endif

View File

@ -116,6 +116,9 @@ class Transform {
/// Assignment operator
Transform& operator=(const Transform& transform);
/// Return the string representation
std::string to_string() const;
};
// Constructor
@ -268,6 +271,11 @@ inline Transform& Transform::operator=(const Transform& transform) {
return *this;
}
// Get the string representation
inline std::string Transform::to_string() const {
return "Transform(" + mPosition.to_string() + "," + mOrientation.to_string() + ")";
}
}
#endif

View File

@ -29,6 +29,7 @@
// Libraries
#include <cmath>
#include <cassert>
#include <string>
#include "mathematics_functions.h"
#include "decimal.h"
@ -135,6 +136,9 @@ struct Vector2 {
/// Overloaded less than operator for ordering to be used inside std::set for instance
bool operator<(const Vector2& vector) const;
/// Return the string representation
std::string to_string() const;
/// Return a vector taking the minimum components of two vectors
static Vector2 min(const Vector2& vector1, const Vector2& vector2);
@ -352,6 +356,11 @@ inline Vector2 Vector2::max(const Vector2& vector1, const Vector2& vector2) {
std::max(vector1.y, vector2.y));
}
// Get the string representation
inline std::string Vector2::to_string() const {
return "Vector2(" + std::to_string(x) + "," + std::to_string(y) + ")";
}
// Return the zero vector
inline Vector2 Vector2::zero() {
return Vector2(0, 0);

View File

@ -29,6 +29,7 @@
// Libraries
#include <cmath>
#include <cassert>
#include <string>
#include "mathematics_functions.h"
#include "decimal.h"
@ -147,6 +148,9 @@ struct Vector3 {
/// Overloaded less than operator for ordering to be used inside std::set for instance
bool operator<(const Vector3& vector) const;
/// Get the string representation
std::string to_string() const;
/// Return a vector taking the minimum components of two vectors
static Vector3 min(const Vector3& vector1, const Vector3& vector2);
@ -391,6 +395,11 @@ inline decimal Vector3::getMaxValue() const {
return std::max(std::max(x, y), z);
}
// Get the string representation
inline std::string Vector3::to_string() const {
return "Vector3(" + std::to_string(x) + "," + std::to_string(y) + "," + std::to_string(z) + ")";
}
// Return the zero vector
inline Vector3 Vector3::zero() {
return Vector3(0, 0, 0);

110
src/utils/Logger.cpp Normal file
View File

@ -0,0 +1,110 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 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. *
* *
********************************************************************************/
#ifdef IS_LOGGING_ACTIVE
// Libraries
#include "Logger.h"
#include "memory/MemoryManager.h"
using namespace reactphysics3d;
// Constructor
Logger::Logger()
: mDestinations(MemoryManager::getBaseAllocator()), mFormatters(MemoryManager::getBaseAllocator())
{
// Create the log formatters
mFormatters.add(Pair<Format, Formatter*>(Format::Text, new TextFormatter()));
mFormatters.add(Pair<Format, Formatter*>(Format::HTML, new HtmlFormatter()));
}
// Destructor
Logger::~Logger() {
removeAllDestinations();
// Remove all the loggers
for (auto it = mFormatters.begin(); it != mFormatters.end(); ++it) {
delete it->second;
}
}
// Return the corresponding formatter
Logger::Formatter* Logger::getFormatter(Format format) const {
auto it = mFormatters.find(format);
if (it != mFormatters.end()) {
return it->second;
}
return nullptr;
}
// Add a log file destination to the logger
void Logger::addFileDestination(const std::string& filePath, uint logLevelFlag, Format format) {
FileDestination* destination = new FileDestination(filePath, logLevelFlag, getFormatter(format));
mDestinations.add(destination);
}
/// Add a stream destination to the logger
void Logger::addStreamDestination(std::ostream& outputStream, uint logLevelFlag, Format format) {
StreamDestination* destination = new StreamDestination(outputStream, logLevelFlag, getFormatter(format));
mDestinations.add(destination);
}
// Remove all logs destination previously set
void Logger::removeAllDestinations() {
// Delete all the destinations
for (uint i=0; i<mDestinations.size(); i++) {
delete mDestinations[i];
}
mDestinations.clear();
}
// Log something
void Logger::log(Level level, Category category, const std::string& message) {
// Get current time
auto now = std::chrono::system_clock::now();
auto time = std::chrono::system_clock::to_time_t(now);
mMutex.lock();
// For each destination
for (auto it = mDestinations.begin(); it != mDestinations.end(); ++it) {
(*it)->write(time, message, level, category);
}
mMutex.unlock();
}
#endif

482
src/utils/Logger.h Normal file
View File

@ -0,0 +1,482 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 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_LOGGER_H
#define REACTPHYSICS3D_LOGGER_H
// Libraries
#include "containers/List.h"
#include "containers/Map.h"
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <mutex>
/// ReactPhysics3D namespace
namespace reactphysics3d {
// Class Logger
/**
* This class is used to log information, warnings or errors during the execution of the
* library code for easier debugging.
*/
class Logger {
public:
/// Log verbosity levels
enum class Level {Error = 1, Warning = 2, Information = 4};
/// Log categories
enum class Category {World, Body, Joint, ProxyShape};
/// Log verbosity level
enum class Format {Text, HTML};
/// Return the name of a category
static std::string getCategoryName(Category category) {
switch(category) {
case Category::World: return "World";
case Category::Body: return "Body";
case Category::Joint: return "Joint";
case Category::ProxyShape: return "ProxyShape";
}
}
/// Return the name of a level
static std::string getLevelName(Level level) {
switch(level) {
case Level::Information: return "Information";
case Level::Warning: return "Warning";
case Level::Error: return "Error";
}
}
/// Log formatter
class Formatter {
public:
/// Constructor
Formatter() {
}
/// Destructor
virtual ~Formatter() {
}
/// Return the header to write at the beginning of the stream
virtual std::string getHeader() const {
return "";
}
/// Return the tail to write at the end of the stream
virtual std::string getTail() const {
return "";
}
/// Format a log message
virtual std::string format(const time_t& time, const std::string& message, Level level, Category category) = 0;
};
class TextFormatter : public Formatter {
public:
/// Constructor
TextFormatter() {
}
/// Destructor
virtual ~TextFormatter() {
}
/// Return the header to write at the beginning of the stream
virtual std::string getHeader() const override {
// Get current date
auto now = std::chrono::system_clock::now();
auto time = std::chrono::system_clock::to_time_t(now);
std::stringstream ss;
ss << "ReactPhysics3D Logs" << std::endl;
ss << "ReactPhysics3D Version: " << RP3D_VERSION << std::endl;
ss << "Date: " << std::put_time(std::localtime(&time), "%Y-%m-%d") << std::endl;
ss << "---------------------------------------------------------" << std::endl;
return ss.str();
}
/// Format a log message
virtual std::string format(const time_t& time, const std::string& message,
Level level, Category category) override {
std::stringstream ss;
// Time
ss << std::put_time(std::localtime(&time), "%X") << " ";
// Level
ss << getLevelName(level) << " ";
// Category
ss << getCategoryName(category) << " ";
// Message
ss << message << std::endl;
return ss.str();
}
};
class HtmlFormatter : public Formatter {
private:
/// Return the header to write at the beginning of the stream
virtual std::string getHeader() const override {
// Get current date
auto now = std::chrono::system_clock::now();
auto time = std::chrono::system_clock::to_time_t(now);
std::stringstream ss;
ss << "<!DOCTYPE HTML>" << std::endl;
ss << "<html>" << std::endl;
ss << "<head>" << std::endl;
ss << "<title>ReactPhysics3D Logs</title>" << std::endl;
ss << "<style>" << generateCSS() << "</style>" << std::endl;
ss << "</head>" << std::endl;
ss << "<body>" << std::endl;
ss << "<h1>ReactPhysics3D Logs</h1>" << std::endl;
ss << "<div class='general_info'>" << std::endl;
ss << "<p>ReactPhysics3D version: " << RP3D_VERSION << "</p>" << std::endl;
ss << "<p>Date: " << std::put_time(std::localtime(&time), "%Y-%m-%d") << "</p>" << std::endl;
ss << "</div>" << std::endl;
ss << "<hr>";
return ss.str();
}
/// Return the tail to write at the end of the stream
virtual std::string getTail() const override {
std::stringstream ss;
ss << "</body>" << std::endl;
ss << "</html>" << std::endl;
return ss.str();
}
std::string generateCSS() const {
return "body {"
" background-color: #e6e6e6;"
" font-family: SFMono-Regular,Menlo,Monaco,Consolas,'Liberation Mono','Courier New',monospace; "
"} "
"body > div { clear:both; } "
"body > div > div { float: left; } "
"h1 {"
" margin: 5px 5px 5px 5px;"
"} "
".general_info > p {"
"margin: 5px;"
"font-weight: bold;"
"} "
".line { "
"font-size: 13px; "
"color: #212529; "
"margin: 0px 5px 2px 5px; "
"} "
".time { "
"margin-right: 20px; "
"width:80px; "
"} "
".level { "
"margin-right: 20px; "
"width: 90px; "
"}"
".category { "
"margin-right: 20px; "
"width: 100px; "
"font-weight: bold; "
"}"
".message { "
"color: #2e2e2e; "
"word-wrap: break-word; "
"max-width: 800px; "
"} "
".body > .category, .body > .message { "
"color: #00994d;"
"} "
".world > .category, .world > .message { "
"color: #3477DB; "
"} "
".joint .category, .joint > .message { "
"color: #bf8040; "
"} "
".proxyshape .category, .proxyshape > .message { "
"color: #9933ff; "
"} "
".warning { "
"color: #ff9900 !important; "
"} "
".error { "
"color: red !important; "
"} ";
}
/// Convert a string to lower case
std::string toLowerCase(const std::string& text) {
std::string textLower = text;
std::transform(textLower.begin(), textLower.end(), textLower.begin(), ::tolower);
return textLower;
}
public:
/// Constructor
HtmlFormatter() {
}
/// Destructor
virtual ~HtmlFormatter() {
}
/// Format a log message
virtual std::string format(const time_t& time, const std::string& message,
Level level, Category category) override {
std::stringstream ss;
ss << "<div class='line " + toLowerCase(getCategoryName(category)) + " " + toLowerCase(getLevelName(level)) + "'>";
// Time
ss << "<div class='time'>";
ss << std::put_time(std::localtime(&time), "%X");
ss << "</div>";
// Level
ss << "<div class='level'>";
ss << getLevelName(level);
ss << "</div>";
// Category
ss << "<div class='category'>";
ss << getCategoryName(category);
ss << "</div>";
// Message
ss << "<div class='message " << toLowerCase(getCategoryName(category)) <<
" " + toLowerCase(getLevelName(level)) << "'>" << std::endl;
ss << message;
ss << "</div>";
ss << "</div>";
return ss.str();
}
};
/// Log destination
class Destination {
public:
/// Log level flag for this destination
uint levelFlag;
/// Pointer to the formatter
Formatter* formatter;
/// Constructor
Destination(uint levelFlag, Formatter* logFormatter)
: levelFlag(levelFlag), formatter(logFormatter) {
}
/// Destructor
virtual ~Destination() {
}
/// Write a message into the output stream
virtual void write(const time_t& time, const std::string& message, Level level, Category category) = 0;
};
class FileDestination : public Destination {
private:
std::string mFilePath;
/// Output file stream
std::ofstream mFileStream;
public:
/// Constructor
FileDestination(const std::string& filePath, uint levelFlag, Formatter* formatter)
:Destination(levelFlag, formatter), mFilePath(filePath),
mFileStream(filePath, std::ios::binary) {
if(!mFileStream.is_open()) {
throw(std::runtime_error("ReactPhysics3D Logger: Unable to open an output stream to file " + mFilePath));
}
// Writer the head
mFileStream << formatter->getHeader() << std::endl;
}
/// Destructor
virtual ~FileDestination() override {
// Writer the tail
mFileStream << formatter->getTail() << std::endl;
if (mFileStream.is_open()) {
// Close the stream
mFileStream.close();
}
}
/// Write a message into the output stream
virtual void write(const time_t& time, const std::string& message, Level level, Category category) override {
mFileStream << formatter->format(time, message, level, category) << std::endl << std::flush;
}
};
/// Stream destination to output the logs into a stream
class StreamDestination : public Destination {
private:
/// Output stream
std::ostream& mOutputStream;
public:
/// Constructor
StreamDestination(std::ostream& outputStream, uint levelFlag, Formatter* formatter)
:Destination(levelFlag, formatter), mOutputStream(outputStream) {
// Writer the head
mOutputStream << formatter->getHeader() << std::endl;
}
/// Destructor
virtual ~StreamDestination() override {
// Writer the tail
mOutputStream << formatter->getTail() << std::endl;
}
/// Write a message into the output stream
virtual void write(const time_t& time, const std::string& message, Level level, Category category) override {
mOutputStream << formatter->format(time, message, level, category) << std::endl << std::flush;
}
};
private:
// -------------------- Attributes -------------------- //
/// All the log destinations
List<Destination*> mDestinations;
/// Map a log format to the given formatter object
Map<Format, Formatter*> mFormatters;
/// Mutex
std::mutex mMutex;
// -------------------- Methods -------------------- //
/// Return the corresponding formatter
Formatter* getFormatter(Format format) const;
public :
// -------------------- Methods -------------------- //
/// Constructor
Logger();
/// Destructor
~Logger();
/// Add a file destination to the logger
void addFileDestination(const std::string& filePath, uint logLevelFlag, Format format);
/// Add a stream destination to the logger
void addStreamDestination(std::ostream& outputStream, uint logLevelFlag, Format format);
/// Remove all logs destination previously set
void removeAllDestinations();
/// Log something
void log(Level level, Category category, const std::string& message);
};
}
#ifdef IS_LOGGING_ACTIVE
// Use this macro to log something
#define RP3D_LOG(logger, level, category, message) logger->log(level, category, message)
#else // If logger is not active
// Empty macro in case logs are not enabled
#define RP3D_LOG(logger, level, message)
#endif
// Hash function for struct VerticesPair
namespace std {
template<> struct hash<reactphysics3d::Logger::Format> {
size_t operator()(const reactphysics3d::Logger::Format format) const {
return static_cast<size_t>(format);
}
};
}
#endif

View File

@ -28,12 +28,10 @@
// Libraries
#include "Profiler.h"
#include <string>
#include "memory/MemoryManager.h"
using namespace reactphysics3d;
// Initialization of static variables
int Profiler::mNbProfilers = 0;
// Constructor
ProfileNode::ProfileNode(const char* name, ProfileNode* parentNode)
:mName(name), mNbTotalCalls(0), mStartingTime(0), mTotalTime(0),
@ -79,7 +77,7 @@ void ProfileNode::enterBlockOfCode() {
// Get the current system time to initialize the starting time of
// the profiling of the current block of code
mStartingTime = Timer::getCurrentSystemTime() * 1000.0;
mStartingTime = Timer::getCurrentSystemTime() * 1000.0L;
}
mRecursionCounter++;
@ -92,7 +90,7 @@ bool ProfileNode::exitBlockOfCode() {
if (mRecursionCounter == 0 && mNbTotalCalls != 0) {
// Get the current system time
long double currentTime = Timer::getCurrentSystemTime() * 1000.0;
long double currentTime = Timer::getCurrentSystemTime() * 1000.0L;
// Increase the total elasped time in the current block of code
mTotalTime += currentTime - mStartingTime;
@ -105,7 +103,7 @@ bool ProfileNode::exitBlockOfCode() {
// Reset the profiling of the node
void ProfileNode::reset() {
mNbTotalCalls = 0;
mTotalTime = 0.0;
mTotalTime = 0.0L;
// Reset the child node
if (mChildNode != nullptr) {
@ -156,27 +154,11 @@ void ProfileNodeIterator::enterParent() {
}
// Constructor
Profiler::Profiler(std::string name) :mRootNode("Root", nullptr) {
// Set the name of the profiler
if (name == "") {
if (mNbProfilers == 0) {
mName = "profiler";
}
else {
mName = std::string("profiler") + std::to_string(mNbProfilers);
}
}
else {
mName = name;
}
Profiler::Profiler() :mRootNode("Root", nullptr), mDestinations(MemoryManager::getBaseAllocator()) {
mCurrentNode = &mRootNode;
mProfilingStartTime = Timer::getCurrentSystemTime() * 1000.0;
mProfilingStartTime = Timer::getCurrentSystemTime() * 1000.0L;
mFrameCounter = 0;
mNbProfilers++;
}
// Destructor
@ -213,18 +195,48 @@ void Profiler::reset() {
mRootNode.reset();
mRootNode.enterBlockOfCode();
mFrameCounter = 0;
mProfilingStartTime = Timer::getCurrentSystemTime() * 1000.0;
mProfilingStartTime = Timer::getCurrentSystemTime() * 1000.0L;
}
// Print the report of the profiler in a given output stream
void Profiler::printReport(std::ostream& outputStream) {
void Profiler::printReport() {
// For each destination
for (auto it = mDestinations.begin(); it != mDestinations.end(); ++it) {
ProfileNodeIterator* iterator = Profiler::getIterator();
// Recursively print the report of each node of the profiler tree
printRecursiveNodeReport(iterator, 0, outputStream);
printRecursiveNodeReport(iterator, 0, (*it)->getOutputStream());
// Destroy the iterator
destroyIterator(iterator);
}
}
// Remove all output profiling destinations previously set
void Profiler::removeAllDestinations() {
// Delete all the destinations
for (size_t i=0; i<mDestinations.size(); i++) {
delete mDestinations[i];
}
mDestinations.clear();
}
// Add a file destination to the profiler
void Profiler::addFileDestination(const std::string& filePath, Format format) {
FileDestination* destination = new FileDestination(filePath, format);
mDestinations.add(destination);
}
// Add a stream destination to the profiler
void Profiler::addStreamDestination(std::ostream& outputStream, Format format) {
StreamDestination* destination = new StreamDestination(outputStream, format);
mDestinations.add(destination);
}
// Recursively print the report of a given node of the profiler tree
@ -240,14 +252,14 @@ void Profiler::printRecursiveNodeReport(ProfileNodeIterator* iterator,
long double parentTime = iterator->isRoot() ? getElapsedTimeSinceStart() :
iterator->getCurrentParentTotalTime();
long double accumulatedTime = 0.0;
long double accumulatedTime = 0.0L;
uint nbFrames = Profiler::getNbFrames();
for (int i=0; i<spacing; i++) outputStream << " ";
outputStream << "---------------" << std::endl;
for (int i=0; i<spacing; i++) outputStream << " ";
outputStream << "| Profiling : " << iterator->getCurrentParentName() <<
" (total running time : " << parentTime << " ms) ---" << std::endl;
long double totalTime = 0.0;
long double totalTime = 0.0L;
// Recurse over the children of the current node
int nbChildren = 0;
@ -256,7 +268,7 @@ void Profiler::printRecursiveNodeReport(ProfileNodeIterator* iterator,
long double currentTotalTime = iterator->getCurrentTotalTime();
accumulatedTime += currentTotalTime;
long double fraction = parentTime > std::numeric_limits<long double>::epsilon() ?
(currentTotalTime / parentTime) * 100.0 : 0.0;
(currentTotalTime / parentTime) * 100.0L : 0.0L;
for (int j=0; j<spacing; j++) outputStream << " ";
outputStream << "| " << i << " -- " << iterator->getCurrentName() << " : " <<
fraction << " % | " << (currentTotalTime / (long double) (nbFrames)) <<
@ -270,7 +282,7 @@ void Profiler::printRecursiveNodeReport(ProfileNodeIterator* iterator,
}
for (int i=0; i<spacing; i++) outputStream << " ";
long double percentage = parentTime > std::numeric_limits<long double>::epsilon() ?
((parentTime - accumulatedTime) / parentTime) * 100.0 : 0.0;
((parentTime - accumulatedTime) / parentTime) * 100.0L : 0.0L;
long double difference = parentTime - accumulatedTime;
outputStream << "| Unaccounted : " << difference << " ms (" << percentage << " %)" << std::endl;

View File

@ -30,7 +30,9 @@
// Libraries
#include "configuration.h"
#include "Timer.h"
#include "engine/Timer.h"
#include <fstream>
#include "containers/List.h"
/// ReactPhysics3D namespace
namespace reactphysics3d {
@ -180,16 +182,102 @@ class ProfileNodeIterator {
*/
class Profiler {
public:
/// Format of the profiling data (text, ...)
enum class Format {Text};
/// Profile destination
class Destination {
public:
/// Log format (text, ...)
Format format;
/// Constructor
Destination(Format logFormat) : format(logFormat) {
}
/// Destructor
virtual ~Destination() {
}
/// Return the current output stream
virtual std::ostream& getOutputStream() = 0;
};
/// File destination to output profiling data into a file
class FileDestination : public Destination {
private:
std::string mFilePath;
/// Output file stream
std::ofstream mFileStream;
public:
/// Constructor
FileDestination(const std::string& filePath, Format format)
:Destination(format), mFilePath(filePath),
mFileStream(filePath, std::ios::binary) {
if(!mFileStream.is_open()) {
throw(std::runtime_error("ReactPhysics3D Logger: Unable to open an output stream to file " + mFilePath));
}
}
/// Destructor
virtual ~FileDestination() override {
if (mFileStream.is_open()) {
// Close the stream
mFileStream.close();
}
}
/// Return the current output stream
virtual std::ostream& getOutputStream() override {
return mFileStream;
}
};
/// Stream destination to output profiling data into a stream
class StreamDestination : public Destination {
private:
/// Output stream
std::ostream& mOutputStream;
public:
/// Constructor
StreamDestination(std::ostream& outputStream, Format format)
:Destination(format), mOutputStream(outputStream) {
}
/// Destructor
virtual ~StreamDestination() override {
}
/// Return the current output stream
virtual std::ostream& getOutputStream() override {
return mOutputStream;
}
};
private :
// -------------------- Attributes -------------------- //
/// Profiler name
std::string mName;
/// Total number of profilers
static int mNbProfilers;
/// Root node of the profiler tree
ProfileNode mRootNode;
@ -202,8 +290,12 @@ class Profiler {
/// Starting profiling time
long double mProfilingStartTime;
/// All the output destinations
List<Destination*> mDestinations;
/// Recursively print the report of a given node of the profiler tree
void printRecursiveNodeReport(ProfileNodeIterator* iterator, int spacing, std::ostream& outputStream);
void printRecursiveNodeReport(ProfileNodeIterator* iterator, int spacing,
std::ostream &outputStream);
/// Destroy a previously allocated iterator
void destroyIterator(ProfileNodeIterator* iterator);
@ -216,7 +308,7 @@ class Profiler {
// -------------------- Methods -------------------- //
/// Constructor
Profiler(std::string name = "");
Profiler();
/// Destructor
~Profiler();
@ -234,12 +326,6 @@ class Profiler {
/// Return the number of frames
uint getNbFrames();
/// Get the name of the profiler
std::string getName() const;
/// Set the name of the profiler
void setName(std::string name);
/// Return the elasped time since the start/reset of the profiling
long double getElapsedTimeSinceStart();
@ -249,8 +335,17 @@ class Profiler {
/// Return an iterator over the profiler tree starting at the root
ProfileNodeIterator* getIterator();
/// Print the report of the profiler in a given output stream
void printReport(std::ostream& outputStream);
// Add a file destination to the profiler
void addFileDestination(const std::string& filePath, Format format);
// Add a stream destination to the profiler
void addStreamDestination(std::ostream& outputStream, Format format);
/// Remove all logs destination previously set
void removeAllDestinations();
/// Print the report of the profiler in every output destinations
void printReport();
};
// Class ProfileSample
@ -287,7 +382,7 @@ class ProfileSample {
};
// Use this macro to start profile a block of code
#define PROFILE(name, profiler) ProfileSample profileSample(name, profiler)
#define RP3D_PROFILE(name, profiler) ProfileSample profileSample(name, profiler)
// Return true if we are at the root of the profiler tree
inline bool ProfileNodeIterator::isRoot() {
@ -374,19 +469,9 @@ inline uint Profiler::getNbFrames() {
return mFrameCounter;
}
// Get the name of the profiler
inline std::string Profiler::getName() const {
return mName;
}
// Set the name of the profiler
inline void Profiler::setName(std::string name) {
mName = name;
}
// Return the elasped time since the start/reset of the profiling
inline long double Profiler::getElapsedTimeSinceStart() {
long double currentTime = Timer::getCurrentSystemTime() * 1000.0;
long double currentTime = Timer::getCurrentSystemTime() * 1000.0L;
return currentTime - mProfilingStartTime;
}
@ -412,10 +497,10 @@ inline void Profiler::destroy() {
}
#else // In profile is not active
#else // If profile is not active
// Empty macro in case profiling is not active
#define PROFILE(name, profiler)
#define RP3D_PROFILE(name, profiler)
#endif

View File

@ -639,7 +639,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
bool swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
bool swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
Vector3 localBody1Point(3, 0, 0);
@ -663,7 +663,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -684,7 +684,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -705,7 +705,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -759,7 +759,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
bool swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
bool swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
Vector3 localBody1Point(3, 0, 0);
@ -783,7 +783,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -804,7 +804,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -825,7 +825,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -869,7 +869,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
localBody1Point = std::sqrt(4.5f) * Vector3(1, -1, 0);
@ -893,7 +893,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -914,7 +914,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -935,7 +935,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -979,7 +979,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
localBody1Point = std::sqrt(9.0f / 3.0f) * Vector3(1, -1, -1);
@ -1003,7 +1003,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1024,7 +1024,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1045,7 +1045,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1099,7 +1099,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
bool swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
bool swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
Vector3 localBody1Point(0, -3, 0);
@ -1123,7 +1123,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1144,7 +1144,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1165,7 +1165,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1209,7 +1209,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
localBody1Point = Vector3(3, 0, 0);
@ -1233,7 +1233,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1254,7 +1254,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1275,7 +1275,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1329,7 +1329,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
bool swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
bool swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
Vector3 localBody1Point(3, 0, 0);
@ -1353,7 +1353,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1374,7 +1374,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1395,7 +1395,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1439,7 +1439,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
localBody1Point = std::sqrt(4.5f) * Vector3(1, -1, 0);
@ -1463,7 +1463,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1484,7 +1484,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1505,7 +1505,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1549,7 +1549,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
localBody1Point = std::sqrt(9.0f / 3.0f) * Vector3(1, -1, -1);
@ -1573,7 +1573,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1594,7 +1594,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1615,7 +1615,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1669,7 +1669,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
bool swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
bool swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
Vector3 localBody1Point(0, -3, 0);
@ -1693,7 +1693,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1714,7 +1714,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1735,7 +1735,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mSphereBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mSphereBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -1789,7 +1789,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 4);
// True if the bodies are swapped in the collision callback response
bool swappedBodiesCollisionData = collisionData->getBody1()->getID() != mBoxBody1->getID();
bool swappedBodiesCollisionData = collisionData->getBody1()->getId() != mBoxBody1->getId();
// Test contact points
Vector3 localBody1Point1(-3, -2, -2);
@ -1831,7 +1831,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 4);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mBoxBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mBoxBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point1 : localBody1Point1,
@ -1860,7 +1860,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 4);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mBoxBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mBoxBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point1 : localBody1Point1,
@ -1890,7 +1890,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 4);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mBoxBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mBoxBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point1 : localBody1Point1,
@ -1953,7 +1953,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 4);
// True if the bodies are swapped in the collision callback response
bool swappedBodiesCollisionData = collisionData->getBody1()->getID() != mBoxBody1->getID();
bool swappedBodiesCollisionData = collisionData->getBody1()->getId() != mBoxBody1->getId();
// Test contact points
Vector3 localBody1Point1(-3, -2, -2);
@ -1995,7 +1995,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 4);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mBoxBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mBoxBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point1 : localBody1Point1,
@ -2024,7 +2024,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 4);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mBoxBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mBoxBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point1 : localBody1Point1,
@ -2054,7 +2054,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 4);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mBoxBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mBoxBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point1 : localBody1Point1,
@ -2117,7 +2117,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 4);
// True if the bodies are swapped in the collision callback response
bool swappedBodiesCollisionData = collisionData->getBody1()->getID() != mConvexMeshBody1->getID();
bool swappedBodiesCollisionData = collisionData->getBody1()->getId() != mConvexMeshBody1->getId();
// Test contact points
Vector3 localBody1Point1(-3, -2, -2);
@ -2159,7 +2159,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 4);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mConvexMeshBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mConvexMeshBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point1 : localBody1Point1,
@ -2188,7 +2188,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 4);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mConvexMeshBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mConvexMeshBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point1 : localBody1Point1,
@ -2218,7 +2218,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 4);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mConvexMeshBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mConvexMeshBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point1 : localBody1Point1,
@ -2281,7 +2281,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
bool swappedBodiesCollisionData = collisionData->getBody1()->getID() != mBoxBody1->getID();
bool swappedBodiesCollisionData = collisionData->getBody1()->getId() != mBoxBody1->getId();
// Test contact points
Vector3 localBody1Point1(3, 1, 0);
@ -2304,7 +2304,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mBoxBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mBoxBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point1 : localBody1Point1,
@ -2325,7 +2325,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mBoxBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mBoxBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point1 : localBody1Point1,
@ -2346,7 +2346,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mBoxBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mBoxBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point1 : localBody1Point1,
@ -2400,7 +2400,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
bool swappedBodiesCollisionData = collisionData->getBody1()->getID() != mConvexMeshBody1->getID();
bool swappedBodiesCollisionData = collisionData->getBody1()->getId() != mConvexMeshBody1->getId();
// Test contact points
Vector3 localBody1Point1(3, 1, 0);
@ -2423,7 +2423,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mConvexMeshBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mConvexMeshBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point1 : localBody1Point1,
@ -2444,7 +2444,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mConvexMeshBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mConvexMeshBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point1 : localBody1Point1,
@ -2465,7 +2465,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mConvexMeshBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mConvexMeshBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point1 : localBody1Point1,
@ -2519,7 +2519,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 4);
// True if the bodies are swapped in the collision callback response
bool swappedBodiesCollisionData = collisionData->getBody1()->getID() != mBoxBody1->getID();
bool swappedBodiesCollisionData = collisionData->getBody1()->getId() != mBoxBody1->getId();
for (int i=0; i<collisionData->contactManifolds[0].contactPoints.size(); i++) {
test(approxEqual(collisionData->contactManifolds[0].contactPoints[i].penetrationDepth, 1.0f));
@ -2539,7 +2539,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 4);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mBoxBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mBoxBody1->getId();
for (int i=0; i<collisionData->contactManifolds[0].contactPoints.size(); i++) {
test(approxEqual(collisionData->contactManifolds[0].contactPoints[i].penetrationDepth, 1.0f));
@ -2559,7 +2559,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 4);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mBoxBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mBoxBody1->getId();
for (int i=0; i<collisionData->contactManifolds[0].contactPoints.size(); i++) {
test(approxEqual(collisionData->contactManifolds[0].contactPoints[i].penetrationDepth, 1.0f));
@ -2579,7 +2579,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 4);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mBoxBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mBoxBody1->getId();
// Test contact points
for (int i=0; i<collisionData->contactManifolds[0].contactPoints.size(); i++) {
@ -2633,7 +2633,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 4);
// True if the bodies are swapped in the collision callback response
bool swappedBodiesCollisionData = collisionData->getBody1()->getID() != mConvexMeshBody1->getID();
bool swappedBodiesCollisionData = collisionData->getBody1()->getId() != mConvexMeshBody1->getId();
for (int i=0; i<collisionData->contactManifolds[0].contactPoints.size(); i++) {
test(approxEqual(collisionData->contactManifolds[0].contactPoints[i].penetrationDepth, 1.0f));
@ -2653,7 +2653,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 4);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mConvexMeshBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mConvexMeshBody1->getId();
for (int i=0; i<collisionData->contactManifolds[0].contactPoints.size(); i++) {
test(approxEqual(collisionData->contactManifolds[0].contactPoints[i].penetrationDepth, 1.0f));
@ -2673,7 +2673,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 4);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mConvexMeshBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mConvexMeshBody1->getId();
for (int i=0; i<collisionData->contactManifolds[0].contactPoints.size(); i++) {
test(approxEqual(collisionData->contactManifolds[0].contactPoints[i].penetrationDepth, 1.0f));
@ -2693,7 +2693,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 4);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mConvexMeshBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mConvexMeshBody1->getId();
// Test contact points
for (int i=0; i<collisionData->contactManifolds[0].contactPoints.size(); i++) {
@ -2747,7 +2747,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
bool swappedBodiesCollisionData = collisionData->getBody1()->getID() != mCapsuleBody1->getID();
bool swappedBodiesCollisionData = collisionData->getBody1()->getId() != mCapsuleBody1->getId();
// Test contact points
Vector3 localBody1Point(2, 3, 0);
@ -2771,7 +2771,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mCapsuleBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mCapsuleBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -2792,7 +2792,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mCapsuleBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mCapsuleBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -2813,7 +2813,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mCapsuleBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mCapsuleBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -2857,7 +2857,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mCapsuleBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mCapsuleBody1->getId();
// Test contact points
localBody1Point = Vector3(0, 5, 0);
@ -2881,7 +2881,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mCapsuleBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mCapsuleBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -2902,7 +2902,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mCapsuleBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mCapsuleBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -2923,7 +2923,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mCapsuleBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mCapsuleBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -2977,7 +2977,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
bool swappedBodiesCollisionData = collisionData->getBody1()->getID() != mCapsuleBody1->getID();
bool swappedBodiesCollisionData = collisionData->getBody1()->getId() != mCapsuleBody1->getId();
// Test contact points
Vector3 localBody1Point(0, -5, 0);
@ -3001,7 +3001,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mCapsuleBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mCapsuleBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -3022,7 +3022,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mCapsuleBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mCapsuleBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,
@ -3043,7 +3043,7 @@ class TestCollisionWorld : public Test {
test(collisionData->getTotalNbContactPoints() == 1);
// True if the bodies are swapped in the collision callback response
swappedBodiesCollisionData = collisionData->getBody1()->getID() != mCapsuleBody1->getID();
swappedBodiesCollisionData = collisionData->getBody1()->getId() != mCapsuleBody1->getId();
// Test contact points
test(collisionData->hasContactPointSimilarTo(swappedBodiesCollisionData ? localBody2Point : localBody1Point,

View File

@ -63,7 +63,7 @@ class WorldRaycastCallback : public RaycastCallback {
virtual decimal notifyRaycastHit(const RaycastInfo& info) override {
if (shapeToTest->getBody()->getID() == info.body->getID()) {
if (shapeToTest->getBody()->getId() == info.body->getId()) {
raycastInfo.body = info.body;
raycastInfo.hitFraction = info.hitFraction;
raycastInfo.proxyShape = info.proxyShape;
@ -1303,14 +1303,12 @@ class TestRaycast : public Test {
Vector3 point2 = mLocalShapeToWorld * Vector3(1, 2, -4);
Ray ray(point1, point2);
Vector3 hitPoint = mLocalShapeToWorld * Vector3(1, 2, 4);
Transform inverse = mLocalShapeToWorld.getInverse();
mCallback.shapeToTest = mConvexMeshProxyShape;
// CollisionWorld::raycast()
mCallback.reset();
mWorld->raycast(ray, &mCallback);
Vector3 localTest = inverse * mCallback.raycastInfo.worldPoint;
test(mCallback.isHit);
test(mCallback.raycastInfo.body == mConvexMeshBody);
test(mCallback.raycastInfo.proxyShape == mConvexMeshProxyShape);

View File

@ -255,16 +255,3 @@ void Box::createVBOAndVAO() {
// Unbind the VAO
mVAO.unbind();
}
// Set the scaling of the object
void Box::setScaling(const openglframework::Vector3& scaling) {
// Scale the collision shape
mProxyShape->setLocalScaling(rp3d::Vector3(scaling.x, scaling.y, scaling.z));
// Scale the graphics object
mScalingMatrix = openglframework::Matrix4(mSize[0] * scaling.x, 0, 0, 0,
0, mSize[1] * scaling.y, 0, 0,
0, 0, mSize[2] * scaling.z, 0,
0, 0, 0, 1);
}

View File

@ -88,9 +88,6 @@ class Box : public PhysicsObject {
/// Update the transform matrix of the object
virtual void updateTransform(float interpolationFactor) override;
/// Set the scaling of the object
void setScaling(const openglframework::Vector3& scaling) override;
};
// Update the transform matrix of the object

View File

@ -235,16 +235,3 @@ void Capsule::createVBOAndVAO() {
// Unbind the VAO
mVAO.unbind();
}
// Set the scaling of the object
void Capsule::setScaling(const openglframework::Vector3& scaling) {
// Scale the collision shape
mProxyShape->setLocalScaling(rp3d::Vector3(scaling.x, scaling.y, scaling.z));
// Scale the graphics object
mScalingMatrix = openglframework::Matrix4(mRadius * scaling.x, 0, 0, 0,
0, (mHeight * scaling.y + 2.0f * mRadius * scaling.x) / 3, 0,0,
0, 0, mRadius * scaling.x, 0,
0, 0, 0, 1.0f);
}

View File

@ -96,9 +96,6 @@ class Capsule : public PhysicsObject {
/// Update the transform matrix of the object
virtual void updateTransform(float interpolationFactor) override;
/// Set the scaling of the object
void setScaling(const openglframework::Vector3& scaling) override;
};
// Update the transform matrix of the object

View File

@ -244,17 +244,3 @@ void ConcaveMesh::createVBOAndVAO() {
// Unbind the VAO
mVAO.unbind();
}
// Set the scaling of the object
void ConcaveMesh::setScaling(const openglframework::Vector3& scaling) {
// Scale the collision shape
mProxyShape->setLocalScaling(rp3d::Vector3(scaling.x, scaling.y, scaling.z));
// Scale the graphics object
mScalingMatrix = openglframework::Matrix4(scaling.x, 0, 0, 0,
0, scaling.y, 0,0,
0, 0, scaling.z, 0,
0, 0, 0, 1.0f);
}

View File

@ -90,9 +90,6 @@ class ConcaveMesh : public PhysicsObject {
/// Update the transform matrix of the object
virtual void updateTransform(float interpolationFactor) override;
/// Set the scaling of the object
void setScaling(const openglframework::Vector3& scaling) override;
};
// Update the transform matrix of the object

View File

@ -254,16 +254,3 @@ void ConvexMesh::createVBOAndVAO() {
// Unbind the VAO
mVAO.unbind();
}
// Set the scaling of the object
void ConvexMesh::setScaling(const openglframework::Vector3& scaling) {
// Scale the collision shape
mProxyShape->setLocalScaling(rp3d::Vector3(scaling.x, scaling.y, scaling.z));
// Scale the graphics object
mScalingMatrix = openglframework::Matrix4(scaling.x, 0, 0, 0,
0, scaling.y, 0, 0,
0, 0, scaling.z, 0,
0, 0, 0, 1);
}

View File

@ -92,9 +92,6 @@ class ConvexMesh : public PhysicsObject {
/// Update the transform matrix of the object
virtual void updateTransform(float interpolationFactor) override;
/// Set the scaling of the object
void setScaling(const openglframework::Vector3& scaling) override;
};
// Update the transform matrix of the object

View File

@ -272,30 +272,3 @@ void Dumbbell::createVBOAndVAO() {
// Unbind the VAO
mVAO.unbind();
}
// Set the scaling of the object
void Dumbbell::setScaling(const openglframework::Vector3& scaling) {
// Scale the collision shape
rp3d::Vector3 newScaling(scaling.x, scaling.y, scaling.z);
mProxyShapeCapsule->setLocalScaling(newScaling);
mProxyShapeSphere1->setLocalScaling(newScaling);
mProxyShapeSphere2->setLocalScaling(newScaling);
mDistanceBetweenSphere = (mDistanceBetweenSphere / mScalingMatrix.getValue(1, 1)) * scaling.y;
// Initial transform of the first sphere collision shape of the dumbbell (in local-space)
rp3d::Transform transformSphereShape1(rp3d::Vector3(0, mDistanceBetweenSphere / 2.0f, 0), rp3d::Quaternion::identity());
// Initial transform of the second sphere collision shape of the dumbell (in local-space)
rp3d::Transform transformSphereShape2(rp3d::Vector3(0, -mDistanceBetweenSphere / 2.0f, 0), rp3d::Quaternion::identity());
mProxyShapeSphere1->setLocalToBodyTransform(transformSphereShape1);
mProxyShapeSphere2->setLocalToBodyTransform(transformSphereShape2);
// Scale the graphics object
mScalingMatrix = openglframework::Matrix4(scaling.x, 0, 0, 0,
0, scaling.y, 0, 0,
0, 0, scaling.z, 0,
0, 0, 0, 1);
}

View File

@ -95,9 +95,6 @@ class Dumbbell : public PhysicsObject {
/// Update the transform matrix of the object
virtual void updateTransform(float interpolationFactor) override;
/// Set the scaling of the object
void setScaling(const openglframework::Vector3& scaling) override;
};
// Update the transform matrix of the object

View File

@ -303,16 +303,3 @@ void HeightField::createVBOAndVAO() {
// Unbind the VAO
mVAO.unbind();
}
// Set the scaling of the object
void HeightField::setScaling(const openglframework::Vector3& scaling) {
// Scale the collision shape
mProxyShape->setLocalScaling(rp3d::Vector3(scaling.x, scaling.y, scaling.z));
// Scale the graphics object
mScalingMatrix = openglframework::Matrix4(scaling.x, 0, 0, 0,
0, scaling.y, 0,0,
0, 0, scaling.z, 0,
0, 0, 0, 1.0f);
}

View File

@ -103,9 +103,6 @@ class HeightField : public PhysicsObject {
/// Update the transform matrix of the object
virtual void updateTransform(float interpolationFactor) override;
/// Set the scaling of the object
void setScaling(const openglframework::Vector3& scaling) override;
};
// Update the transform matrix of the object

View File

@ -82,9 +82,6 @@ class PhysicsObject : public openglframework::Mesh {
/// Return a pointer to the rigid body of the box
reactphysics3d::RigidBody* getRigidBody();
/// Set the scaling of the object
virtual void setScaling(const openglframework::Vector3& scaling)=0;
};
// Set the color of the box

View File

@ -234,16 +234,3 @@ void Sphere::createVBOAndVAO() {
// Unbind the VAO
mVAO.unbind();
}
// Set the scaling of the object
void Sphere::setScaling(const openglframework::Vector3& scaling) {
// Scale the collision shape
mProxyShape->setLocalScaling(rp3d::Vector3(scaling.x, scaling.y, scaling.z));
// Scale the graphics object
mScalingMatrix = openglframework::Matrix4(mRadius * scaling.x, 0, 0, 0,
0, mRadius * scaling.y, 0, 0,
0, 0, mRadius * scaling.z, 0,
0, 0, 0, 1);
}

View File

@ -92,9 +92,6 @@ class Sphere : public PhysicsObject {
/// Update the transform matrix of the object
virtual void updateTransform(float interpolationFactor) override;
/// Set the scaling of the object
void setScaling(const openglframework::Vector3& scaling) override;
};
// Update the transform matrix of the object

View File

@ -46,14 +46,11 @@ CollisionDetectionScene::CollisionDetectionScene(const std::string& name, Engine
// Set the center of the scene
setScenePosition(center, SCENE_RADIUS);
rp3d::WorldSettings worldSettings;
worldSettings.worldName = name;
// Create the dynamics world for the physics simulation
mPhysicsWorld = new rp3d::CollisionWorld();
#ifdef IS_PROFILING_ACTIVE
mPhysicsWorld->setProfilerName(name + "_profiler");
#endif
mPhysicsWorld = new rp3d::CollisionWorld(worldSettings);
// ---------- Sphere 1 ---------- //

View File

@ -45,15 +45,11 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name, EngineSettin
// Gravity vector in the dynamics world
rp3d::Vector3 gravity(0, -9.81f, 0);
rp3d::WorldSettings worldSettings;
worldSettings.worldName = name;
// Create the dynamics world for the physics simulation
mPhysicsWorld = new rp3d::DynamicsWorld(gravity);
#ifdef IS_PROFILING_ACTIVE
mPhysicsWorld->setProfilerName(name + "_profiler");
#endif
mPhysicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings);
for (int i=0; i<NB_COMPOUND_SHAPES; i++) {

View File

@ -45,14 +45,11 @@ ConcaveMeshScene::ConcaveMeshScene(const std::string& name, EngineSettings& sett
// Gravity vector in the dynamics world
rp3d::Vector3 gravity(0, rp3d::decimal(-9.81), 0);
rp3d::WorldSettings worldSettings;
worldSettings.worldName = name;
// Create the dynamics world for the physics simulation
mPhysicsWorld = new rp3d::DynamicsWorld(gravity);
#ifdef IS_PROFILING_ACTIVE
mPhysicsWorld->setProfilerName(name + "_profiler");
#endif
mPhysicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings);
// ---------- Create the boxes ----------- //
for (int i = 0; i<NB_COMPOUND_SHAPES; i++) {

View File

@ -43,14 +43,11 @@ CubesScene::CubesScene(const std::string& name, EngineSettings& settings)
// Gravity vector in the dynamics world
rp3d::Vector3 gravity(0, rp3d::decimal(-9.81), 0);
rp3d::WorldSettings worldSettings;
worldSettings.worldName = name;
// Create the dynamics world for the physics simulation
mPhysicsWorld = new rp3d::DynamicsWorld(gravity);
#ifdef IS_PROFILING_ACTIVE
mPhysicsWorld->setProfilerName(name + "_profiler");
#endif
mPhysicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings);
// Create all the cubes of the scene
for (int i=0; i<NB_CUBES; i++) {

View File

@ -43,14 +43,11 @@ CubeStackScene::CubeStackScene(const std::string& name, EngineSettings& settings
// Gravity vector in the dynamics world
rp3d::Vector3 gravity(0, rp3d::decimal(-9.81), 0);
rp3d::WorldSettings worldSettings;
worldSettings.worldName = name;
// Create the dynamics world for the physics simulation
mPhysicsWorld = new rp3d::DynamicsWorld(gravity);
#ifdef IS_PROFILING_ACTIVE
mPhysicsWorld->setProfilerName(name + "_profiler");
#endif
mPhysicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings);
// Create all the cubes of the scene
for (int i=1; i<=NB_FLOORS; i++) {

View File

@ -45,15 +45,11 @@ HeightFieldScene::HeightFieldScene(const std::string& name, EngineSettings& sett
// Gravity vector in the dynamics world
rp3d::Vector3 gravity(0, rp3d::decimal(-9.81), 0);
rp3d::WorldSettings worldSettings;
worldSettings.worldName = name;
// Create the dynamics world for the physics simulation
mPhysicsWorld = new rp3d::DynamicsWorld(gravity);
#ifdef IS_PROFILING_ACTIVE
mPhysicsWorld->setProfilerName(name + "_profiler");
#endif
mPhysicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings);
for (int i = 0; i<NB_COMPOUND_SHAPES; i++) {

View File

@ -44,14 +44,11 @@ JointsScene::JointsScene(const std::string& name, EngineSettings& settings)
// Gravity vector in the dynamics world
rp3d::Vector3 gravity(0, rp3d::decimal(-9.81), 0);
rp3d::WorldSettings worldSettings;
worldSettings.worldName = name;
// Create the dynamics world for the physics simulation
mPhysicsWorld = new rp3d::DynamicsWorld(gravity);
#ifdef IS_PROFILING_ACTIVE
mPhysicsWorld->setProfilerName(name + "_profiler");
#endif
mPhysicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings);
// Create the Ball-and-Socket joint
createBallAndSocketJoints();

View File

@ -44,14 +44,11 @@ RaycastScene::RaycastScene(const std::string& name, EngineSettings& settings)
// Set the center of the scene
setScenePosition(center, SCENE_RADIUS);
rp3d::WorldSettings worldSettings;
worldSettings.worldName = name;
// Create the dynamics world for the physics simulation
mPhysicsWorld = new rp3d::CollisionWorld();
#ifdef IS_PROFILING_ACTIVE
mPhysicsWorld->setProfilerName(name + "_profiler");
#endif
mPhysicsWorld = new rp3d::CollisionWorld(worldSettings);
// ---------- Dumbbell ---------- //

View File

@ -170,6 +170,7 @@ void Gui::createSettingsPanel() {
checkboxSleeping->setChecked(mApp->mEngineSettings.isSleepingEnabled);
checkboxSleeping->setCallback([&](bool value) {
mApp->mEngineSettings.isSleepingEnabled = value;
mApp->notifyEngineSetttingsChanged();
});
// Enabled/Disable Gravity
@ -177,6 +178,7 @@ void Gui::createSettingsPanel() {
checkboxGravity->setChecked(mApp->mEngineSettings.isGravityEnabled);
checkboxGravity->setCallback([&](bool value) {
mApp->mEngineSettings.isGravityEnabled = value;
mApp->notifyEngineSetttingsChanged();
});
// Timestep
@ -202,6 +204,7 @@ void Gui::createSettingsPanel() {
if (finalValue < 1 || finalValue > 1000) return false;
mApp->mEngineSettings.timeStep = finalValue / 1000.0f;
mApp->notifyEngineSetttingsChanged();
textboxTimeStep->setValue(out.str());
}
catch (...) {
@ -233,6 +236,7 @@ void Gui::createSettingsPanel() {
if (value < 1 || value > 1000) return false;
mApp->mEngineSettings.nbVelocitySolverIterations = value;
mApp->notifyEngineSetttingsChanged();
textboxVelocityIterations->setValue(out.str());
}
catch (...) {
@ -264,6 +268,7 @@ void Gui::createSettingsPanel() {
if (value < 1 || value > 1000) return false;
mApp->mEngineSettings.nbPositionSolverIterations = value;
mApp->notifyEngineSetttingsChanged();
textboxPositionIterations->setValue(out.str());
}
catch (...) {
@ -298,6 +303,7 @@ void Gui::createSettingsPanel() {
if (finalValue < 1 || finalValue > 100000) return false;
mApp->mEngineSettings.timeBeforeSleep = finalValue / 1000.0f;
mApp->notifyEngineSetttingsChanged();
textboxTimeSleep->setValue(out.str());
}
catch (...) {
@ -332,6 +338,7 @@ void Gui::createSettingsPanel() {
if (finalValue < 0 || finalValue > 10000) return false;
mApp->mEngineSettings.sleepLinearVelocity = finalValue;
mApp->notifyEngineSetttingsChanged();
textboxSleepLinearVel->setValue(out.str());
}
catch (...) {
@ -366,6 +373,7 @@ void Gui::createSettingsPanel() {
if (finalValue < 0 || finalValue > 10000) return false;
mApp->mEngineSettings.sleepAngularVelocity = finalValue;
mApp->notifyEngineSetttingsChanged();
textboxSleepAngularVel->setValue(out.str());
}
catch (...) {

View File

@ -232,6 +232,9 @@ class Scene {
/// Return all the contact points of the scene
std::vector<ContactPoint> virtual getContactPoints();
/// Update the engine settings
virtual void updateEngineSettings() = 0;
};
// Called when a keyboard event occurs

View File

@ -123,18 +123,6 @@ void SceneDemo::updatePhysics() {
if (getDynamicsWorld() != nullptr) {
// Update the physics engine parameters
getDynamicsWorld()->setIsGratityEnabled(mEngineSettings.isGravityEnabled);
rp3d::Vector3 gravity(mEngineSettings.gravity.x, mEngineSettings.gravity.y,
mEngineSettings.gravity.z);
getDynamicsWorld()->setGravity(gravity);
getDynamicsWorld()->enableSleeping(mEngineSettings.isSleepingEnabled);
getDynamicsWorld()->setSleepLinearVelocity(mEngineSettings.sleepLinearVelocity);
getDynamicsWorld()->setSleepAngularVelocity(mEngineSettings.sleepAngularVelocity);
getDynamicsWorld()->setNbIterationsPositionSolver(mEngineSettings.nbPositionSolverIterations);
getDynamicsWorld()->setNbIterationsVelocitySolver(mEngineSettings.nbVelocitySolverIterations);
getDynamicsWorld()->setTimeBeforeSleep(mEngineSettings.timeBeforeSleep);
// Take a simulation step
getDynamicsWorld()->update(mEngineSettings.timeStep);
}
@ -448,3 +436,22 @@ std::vector<ContactPoint> SceneDemo::computeContactPointsOfWorld(rp3d::DynamicsW
return contactPoints;
}
// Update the engine settings
void SceneDemo::updateEngineSettings() {
if (getDynamicsWorld() != nullptr) {
// Update the physics engine parameters
getDynamicsWorld()->setIsGratityEnabled(mEngineSettings.isGravityEnabled);
rp3d::Vector3 gravity(mEngineSettings.gravity.x, mEngineSettings.gravity.y,
mEngineSettings.gravity.z);
getDynamicsWorld()->setGravity(gravity);
getDynamicsWorld()->enableSleeping(mEngineSettings.isSleepingEnabled);
getDynamicsWorld()->setSleepLinearVelocity(mEngineSettings.sleepLinearVelocity);
getDynamicsWorld()->setSleepAngularVelocity(mEngineSettings.sleepAngularVelocity);
getDynamicsWorld()->setNbIterationsPositionSolver(mEngineSettings.nbPositionSolverIterations);
getDynamicsWorld()->setNbIterationsVelocitySolver(mEngineSettings.nbVelocitySolverIterations);
getDynamicsWorld()->setTimeBeforeSleep(mEngineSettings.timeBeforeSleep);
}
}

View File

@ -151,6 +151,9 @@ class SceneDemo : public Scene {
/// Render the scene (possibly in multiple passes for shadow mapping)
virtual void render() override;
/// Update the engine settings
virtual void updateEngineSettings() override;
/// Render the scene in a single pass
virtual void renderSinglePass(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix);

View File

@ -271,9 +271,16 @@ void TestbedApplication::switchScene(Scene* newScene) {
// Reset the scene
mCurrentScene->reset();
mCurrentScene->updateEngineSettings();
resizeEvent(Vector2i(0, 0));
}
// Notify that the engine settings have changed
void TestbedApplication::notifyEngineSetttingsChanged() {
mCurrentScene->updateEngineSettings();
}
// Check the OpenGL errors
void TestbedApplication::checkOpenGLErrorsInternal(const char* file, int line) {
GLenum glError;

View File

@ -199,6 +199,9 @@ class TestbedApplication : public Screen {
/// Enable/Disable Vertical synchronization
void enableVSync(bool enable);
/// Notify that the engine settings have changed
void notifyEngineSetttingsChanged();
// -------------------- Friendship -------------------- //
friend class Gui;