Working on logger

This commit is contained in:
Daniel Chappuis 2018-03-19 23:02:13 +01:00
parent 2e28b5ad8f
commit 1bc50de2c9
30 changed files with 551 additions and 81 deletions

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 -------------------- //
@ -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;
@ -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
@ -198,6 +219,10 @@ inline void Body::setIsSleeping(bool 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 +241,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,9 @@ 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");
// Return a pointer to the collision shape
return proxyShape;
}
@ -114,11 +124,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 +151,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 +177,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 +222,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 +263,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 +273,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

@ -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,9 @@ 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");
// Return a pointer to the proxy collision shape
return proxyShape;
}
@ -324,6 +346,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 +367,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 +395,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
@ -494,4 +525,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

@ -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
@ -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
@ -637,10 +637,10 @@ 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());
@ -817,10 +817,10 @@ 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());
@ -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());
}
}

View File

@ -93,6 +93,12 @@ class ProxyShape {
#endif
#ifdef IS_LOGGING_ACTIVE
/// Logger
Logger* mLogger;
#endif
// -------------------- Methods -------------------- //
/// Return the collision shape
@ -175,6 +181,9 @@ class ProxyShape {
/// 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
/// Set the profiler
@ -182,6 +191,12 @@ class ProxyShape {
#endif
#ifdef IS_LOGGING_ACTIVE
/// Set the logger
void setLogger(Logger* logger);
#endif
// -------------------- Friendship -------------------- //
friend class OverlappingPair;
@ -265,6 +280,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 +335,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,6 +355,10 @@ 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
@ -348,6 +375,8 @@ inline Vector3 ProxyShape::getLocalScaling() const {
*/
inline void ProxyShape::setLocalScaling(const Vector3& scaling) {
// TODO : Do not use a local of the collision shape in case of shared collision shapes
// Set the local scaling of the collision shape
mCollisionShape->setLocalScaling(scaling);
@ -355,6 +384,15 @@ inline void ProxyShape::setLocalScaling(const Vector3& scaling) {
// 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 localScaling=" +
mCollisionShape->getLocalScaling().to_string());
}
// Return the broad-phase id
inline int ProxyShape::getBroadPhaseId() const {
return mBroadPhaseID;
}
/// Test if the proxy shape overlaps with a given AABB
@ -378,6 +416,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

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

View File

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

View File

@ -123,6 +123,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
@ -237,6 +240,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

@ -105,6 +105,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
@ -185,6 +188,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

@ -138,6 +138,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

View File

@ -214,3 +214,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

@ -186,6 +186,9 @@ class ConcaveMeshShape : public ConcaveShape {
/// 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
@ -277,6 +280,7 @@ inline void ConcaveMeshShape::setProfiler(Profiler* profiler) {
mDynamicAABBTree.setProfiler(profiler);
}
#endif
}

View File

@ -201,3 +201,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

@ -130,6 +130,9 @@ class ConvexMeshShape : 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;
};
/// Set the scaling vector of the collision shape

View File

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

@ -209,6 +209,9 @@ class HeightFieldShape : public ConcaveShape {
/// 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;

View File

@ -93,6 +93,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
@ -181,6 +184,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

@ -175,6 +175,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;
@ -325,6 +328,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,7 @@
#include <cfloat>
#include <utility>
#include <cstdint>
#include <sstream>
#include <string>
#include "decimal.h"
#include "containers/Pair.h"
@ -105,6 +106,9 @@ 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.
@ -161,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

@ -80,7 +80,7 @@ CollisionWorld::CollisionWorld(const WorldSettings& worldSettings, Logger* logge
mLogger = new Logger();
// Add a log destination file
uint logLevel = static_cast<uint>(Logger::Level::Info) | static_cast<uint>(Logger::Level::Warning) |
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);
}
@ -89,14 +89,16 @@ CollisionWorld::CollisionWorld(const WorldSettings& worldSettings, Logger* logge
mNbWorlds++;
RP3D_LOG(mLogger, Logger::Level::Info, Logger::Category::World,
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::Info, Logger::Category::World,
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
@ -154,8 +156,12 @@ CollisionBody* CollisionWorld::createCollisionBody(const Transform& transform) {
#endif
RP3D_LOG(mLogger, Logger::Level::Info, Logger::Category::Body,
"Collision Body " + std::to_string(bodyID) + ": New collision body created");
#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;
@ -167,8 +173,8 @@ CollisionBody* CollisionWorld::createCollisionBody(const Transform& transform) {
*/
void CollisionWorld::destroyCollisionBody(CollisionBody* collisionBody) {
RP3D_LOG(mLogger, Logger::Level::Info, Logger::Category::Body,
"Collision Body " + std::to_string(collisionBody->getId()) + ": collision body destroyed");
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();
@ -253,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

@ -64,7 +64,7 @@ DynamicsWorld::DynamicsWorld(const Vector3& gravity, const WorldSettings& worldS
#endif
RP3D_LOG(mLogger, Logger::Level::Info, Logger::Category::World,
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: Dynamics world " + mName + " has been created");
}
@ -91,7 +91,7 @@ DynamicsWorld::~DynamicsWorld() {
mProfiler->printReport();
#endif
RP3D_LOG(mLogger, Logger::Level::Info, Logger::Category::World,
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: Dynamics world " + mName + " has been destroyed");
}
@ -426,13 +426,15 @@ RigidBody* DynamicsWorld::createRigidBody(const Transform& transform) {
mRigidBodies.add(rigidBody);
#ifdef IS_PROFILING_ACTIVE
rigidBody->setProfiler(mProfiler);
#endif
RP3D_LOG(mLogger, Logger::Level::Info, Logger::Category::Body,
"Rigid Body " + std::to_string(bodyID) + ": New collision body created");
#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;
@ -444,8 +446,8 @@ RigidBody* DynamicsWorld::createRigidBody(const Transform& transform) {
*/
void DynamicsWorld::destroyRigidBody(RigidBody* rigidBody) {
RP3D_LOG(mLogger, Logger::Level::Info, Logger::Category::Body,
"Rigid Body " + std::to_string(rigidBody->getId()) + ": rigid body destroyed");
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();
@ -549,7 +551,7 @@ Joint* DynamicsWorld::createJoint(const JointInfo& jointInfo) {
// Add the joint into the joint list of the bodies involved in the joint
addJointToBody(newJoint);
RP3D_LOG(mLogger, Logger::Level::Info, Logger::Category::Joint,
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Joint,
"Joint " + std::to_string(newJoint->getId()) + ": New joint created");
// Return the pointer to the created joint
@ -564,7 +566,7 @@ void DynamicsWorld::destroyJoint(Joint* joint) {
assert(joint != nullptr);
RP3D_LOG(mLogger, Logger::Level::Info, Logger::Category::Joint,
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
@ -863,7 +865,7 @@ void DynamicsWorld::enableSleeping(bool isSleepingEnabled) {
}
}
RP3D_LOG(mLogger, Logger::Level::Info, Logger::Category::World,
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: isSleepingEnabled=" + (isSleepingEnabled ? std::string("true") : std::string("false")) );
}

View File

@ -283,7 +283,7 @@ inline uint DynamicsWorld::getNbIterationsVelocitySolver() const {
inline void DynamicsWorld::setNbIterationsVelocitySolver(uint nbIterations) {
mNbVelocitySolverIterations = nbIterations;
RP3D_LOG(mLogger, Logger::Level::Info, Logger::Category::World,
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: Set nb iterations velocity solver to " + std::to_string(nbIterations));
}
@ -299,7 +299,7 @@ inline uint DynamicsWorld::getNbIterationsPositionSolver() const {
inline void DynamicsWorld::setNbIterationsPositionSolver(uint nbIterations) {
mNbPositionSolverIterations = nbIterations;
RP3D_LOG(mLogger, Logger::Level::Info, Logger::Category::World,
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: Set nb iterations position solver to " + std::to_string(nbIterations));
}
@ -346,7 +346,7 @@ inline Vector3 DynamicsWorld::getGravity() const {
inline void DynamicsWorld::setGravity(Vector3& gravity) {
mGravity = gravity;
RP3D_LOG(mLogger, Logger::Level::Info, Logger::Category::World,
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: Set gravity vector to " + gravity.to_string());
}
@ -366,7 +366,7 @@ inline bool DynamicsWorld::isGravityEnabled() const {
inline void DynamicsWorld::setIsGratityEnabled(bool isGravityEnabled) {
mIsGravityEnabled = isGravityEnabled;
RP3D_LOG(mLogger, Logger::Level::Info, Logger::Category::World,
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: isGravityEnabled= " + (isGravityEnabled ? std::string("true") : std::string("false")));
}
@ -413,7 +413,7 @@ inline void DynamicsWorld::setSleepLinearVelocity(decimal sleepLinearVelocity) {
assert(sleepLinearVelocity >= decimal(0.0));
mSleepLinearVelocity = sleepLinearVelocity;
RP3D_LOG(mLogger, Logger::Level::Info, Logger::Category::World,
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: sleepLinearVelocity= " + std::to_string(sleepLinearVelocity));
}
@ -436,7 +436,7 @@ inline void DynamicsWorld::setSleepAngularVelocity(decimal sleepAngularVelocity)
assert(sleepAngularVelocity >= decimal(0.0));
mSleepAngularVelocity = sleepAngularVelocity;
RP3D_LOG(mLogger, Logger::Level::Info, Logger::Category::World,
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: sleepAngularVelocity= " + std::to_string(sleepAngularVelocity));
}
@ -457,7 +457,7 @@ inline void DynamicsWorld::setTimeBeforeSleep(decimal timeBeforeSleep) {
assert(timeBeforeSleep >= decimal(0.0));
mTimeBeforeSleep = timeBeforeSleep;
RP3D_LOG(mLogger, Logger::Level::Info, Logger::Category::World,
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: timeBeforeSleep= " + std::to_string(timeBeforeSleep));
}

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

View File

@ -49,10 +49,10 @@ class Logger {
public:
/// Log verbosity levels
enum class Level {Error = 1, Warning = 2, Info = 4};
enum class Level {Error = 1, Warning = 2, Information = 4};
/// Log categories
enum class Category {World, Body, Joint};
enum class Category {World, Body, Joint, ProxyShape};
/// Log verbosity level
enum class Format {Text, HTML};
@ -64,6 +64,7 @@ class Logger {
case Category::World: return "World";
case Category::Body: return "Body";
case Category::Joint: return "Joint";
case Category::ProxyShape: return "ProxyShape";
}
}
@ -71,7 +72,7 @@ class Logger {
static std::string getLevelName(Level level) {
switch(level) {
case Level::Info: return "Information";
case Level::Information: return "Information";
case Level::Warning: return "Warning";
case Level::Error: return "Error";
}
@ -120,6 +121,22 @@ class Logger {
}
/// 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 {
@ -134,8 +151,11 @@ class Logger {
/// Return the header to write at the beginning of the stream
virtual std::string getHeader() const override {
std::stringstream ss;
// 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;
@ -143,6 +163,12 @@ class Logger {
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();
}
@ -161,26 +187,33 @@ class Logger {
std::string generateCSS() const {
return "body {"
" background-color: #f7f7f9;"
" 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-family: SFMono-Regular,Menlo,Monaco,Consolas,'Liberation Mono','Courier New',monospace; "
"font-size: 13px; "
"color: #212529; "
"margin: 0px 5px 2px 5px; "
"} "
".time { "
"margin-right: 10px; "
"width:100px; "
"margin-right: 20px; "
"width:80px; "
"} "
".level { "
"margin-right: 10px; "
"width: 110px; "
"margin-right: 20px; "
"width: 90px; "
"}"
".category { "
"margin-right: 10px; "
"width: 120px; "
"margin-right: 20px; "
"width: 100px; "
"font-weight: bold; "
"}"
".message { "
@ -188,20 +221,23 @@ class Logger {
"word-wrap: break-word; "
"max-width: 800px; "
"} "
".body > .category { "
"color: #007bff; "
".body > .category, .body > .message { "
"color: #8bc34a;"
"} "
".world > .category { "
".world > .category, .world > .message { "
"color: #4f9fcf; "
"} "
".joint > .category { "
"color: #6c757d; "
".joint .category, .joint > .message { "
"color: #aa00ff; "
"} "
".proxyshape .category, .proxyshape > .message { "
"color: #009933; "
"} "
".warning { "
"color: #f0ad4e; "
"color: #ff9900 !important; "
"} "
".error { "
"color: #d44950; "
"color: red !important; "
"} ";
}
@ -248,7 +284,8 @@ class Logger {
ss << "</div>";
// Message
ss << "<div class='message'>";
ss << "<div class='message " << toLowerCase(getCategoryName(category)) <<
" " + toLowerCase(getLevelName(level)) << "'>" << std::endl;
ss << message;
ss << "</div>";