From 67e89e081bebc26e5d472257ff257d48918b7ab6 Mon Sep 17 00:00:00 2001 From: Daniel Chappuis Date: Thu, 7 May 2020 15:12:59 +0200 Subject: [PATCH] Working on debug renderer --- CHANGELOG.md | 1 + include/reactphysics3d/utils/DebugRenderer.h | 51 ++++++++------ src/utils/DebugRenderer.cpp | 47 +++++++------ .../CollisionDetectionScene.cpp | 10 ++- .../CollisionDetectionScene.h | 6 +- .../collisionshapes/CollisionShapesScene.cpp | 8 --- testbed/scenes/raycast/RaycastScene.cpp | 19 +++-- testbed/scenes/raycast/RaycastScene.h | 16 ++--- testbed/src/Gui.cpp | 64 +++++++++++++---- testbed/src/Scene.cpp | 29 +------- testbed/src/Scene.h | 69 ++++++++++++++----- testbed/src/SceneDemo.cpp | 66 +++++------------- testbed/src/SceneDemo.h | 15 ++-- testbed/src/TestbedApplication.cpp | 62 ++++++++--------- testbed/src/TestbedApplication.h | 27 ++++++-- 15 files changed, 267 insertions(+), 223 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c415f9a5..23eac7c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ - A Collider can now be a trigger. This collider will be used to only report collisions with another collider but no collision response will be applied. You can use the Collider::setIsTrigger() method for this. - The EventListener class now has a onTrigger() method that is called when a trigger collider is colling with another collider. - In the EventListener, the onContact() and onTrigger() method now reports the type of event (start, stay, exit) for each contact. This way the user can know whether it's a new contact or not or when two colliders are not in contact anymore. + - A DebugRenderer class has been added in order to display debug info (colliders, AABBs, contacts, ...) using graphics primities (lines, triangles). ### Fixed diff --git a/include/reactphysics3d/utils/DebugRenderer.h b/include/reactphysics3d/utils/DebugRenderer.h index 01344d7e..93f22b5c 100644 --- a/include/reactphysics3d/utils/DebugRenderer.h +++ b/include/reactphysics3d/utils/DebugRenderer.h @@ -71,25 +71,23 @@ class DebugRenderer : public EventListener { /// Enumeration with debug item to renderer enum class DebugItem { + + /// Display the AABB for each collider COLLIDER_AABB = 1 << 0, + + /// Display the fat AABB of the broad phase collision detection for each collider COLLIDER_BROADPHASE_AABB = 1 << 1, + + /// Display the collision shape of each collider COLLISION_SHAPE = 1 << 2, + + /// Display the contact points CONTACT_POINT = 1 << 3, + + /// Display the contact normals CONTACT_NORMAL = 1 << 4, }; - /// Struture that represents a point of the DebugRenderer - struct DebugPoint { - - /// Constructor - DebugPoint(const Vector3& point, uint32 color) :point(point), color(color) { - - } - - Vector3 point; - uint32 color; - }; - /// Struture that represents a line of the DebugRenderer struct DebugLine { @@ -99,9 +97,16 @@ class DebugRenderer : public EventListener { } + /// First point of the line Vector3 point1; + + /// Color of the first point uint32 color1; + + /// Second point of the line Vector3 point2; + + /// Color of the second point uint32 color2; }; @@ -114,11 +119,22 @@ class DebugRenderer : public EventListener { } - Vector3 point1; + /// First point of the triangle + Vector3 point1; + + /// Color of the first point uint32 color1; + + /// Second point of the triangle Vector3 point2; + + /// Color of the second point uint32 color2; + + /// Third point of the triangle Vector3 point3; + + /// Color of the third point uint32 color3; }; @@ -197,15 +213,6 @@ class DebugRenderer : public EventListener { /// Destructor ~DebugRenderer(); - /// Return the number of points - uint32 getNbPoints() const; - - /// Return a reference to the list of points - const List& getPoints() const; - - /// Return a pointer to the array of points - const DebugPoint* getPointsArray() const; - /// Return the number of lines uint32 getNbLines() const; diff --git a/src/utils/DebugRenderer.cpp b/src/utils/DebugRenderer.cpp index 979920ba..4a811cbb 100644 --- a/src/utils/DebugRenderer.cpp +++ b/src/utils/DebugRenderer.cpp @@ -45,7 +45,7 @@ DebugRenderer::DebugRenderer(MemoryAllocator& allocator) mContactPointSphereRadius(DEFAULT_CONTACT_POINT_SPHERE_RADIUS), mContactNormalLength(DEFAULT_CONTACT_NORMAL_LENGTH) { mMapDebugItemWithColor.add(Pair(DebugItem::COLLIDER_AABB, static_cast(DebugColor::MAGENTA))); - mMapDebugItemWithColor.add(Pair(DebugItem::COLLIDER_BROADPHASE_AABB, static_cast(DebugColor::YELLOW))); + mMapDebugItemWithColor.add(Pair(DebugItem::COLLIDER_BROADPHASE_AABB, static_cast(DebugColor::YELLOW))); mMapDebugItemWithColor.add(Pair(DebugItem::COLLISION_SHAPE, static_cast(DebugColor::GREEN))); mMapDebugItemWithColor.add(Pair(DebugItem::CONTACT_POINT, static_cast(DebugColor::RED))); mMapDebugItemWithColor.add(Pair(DebugItem::CONTACT_NORMAL, static_cast(DebugColor::WHITE))); @@ -408,30 +408,35 @@ void DebugRenderer::computeDebugRenderingPrimitives(const PhysicsWorld& world) { // Get a body const CollisionBody* body = b < nbCollisionBodies ? world.getCollisionBody(b) : world.getRigidBody(b - nbCollisionBodies); - // For each collider of the body - for (uint c = 0; c < body->getNbColliders(); c++) { + if (body->isActive()) { - // Get a collider - const Collider* collider = body->getCollider(c); + // For each collider of the body + for (uint c = 0; c < body->getNbColliders(); c++) { - // If we need to draw the collider AABB - if (drawColliderAABB) { + // Get a collider + const Collider* collider = body->getCollider(c); - drawAABB(collider->getWorldAABB(), mMapDebugItemWithColor[DebugItem::COLLIDER_AABB]); + // If we need to draw the collider AABB + if (drawColliderAABB) { + + drawAABB(collider->getWorldAABB(), mMapDebugItemWithColor[DebugItem::COLLIDER_AABB]); + } + + // If we need to draw the collider broad-phase AABB + if (drawColliderBroadphaseAABB) { + + if (collider->getBroadPhaseId() != -1) { + drawAABB(world.mCollisionDetection.mBroadPhaseSystem.getFatAABB(collider->getBroadPhaseId()), mMapDebugItemWithColor[DebugItem::COLLIDER_BROADPHASE_AABB]); + } + } + + // If we need to draw the collision shape + if (drawCollisionShape) { + + drawCollisionShapeOfCollider(collider, mMapDebugItemWithColor[DebugItem::COLLISION_SHAPE]); + } } - - // If we need to draw the collider broad-phase AABB - if (drawColliderBroadphaseAABB) { - - drawAABB(world.mCollisionDetection.mBroadPhaseSystem.getFatAABB(collider->getBroadPhaseId()), mMapDebugItemWithColor[DebugItem::COLLIDER_BROADPHASE_AABB]); - } - - // If we need to draw the collision shape - if (drawCollisionShape) { - - drawCollisionShapeOfCollider(collider, mMapDebugItemWithColor[DebugItem::COLLISION_SHAPE]); - } - } + } } } diff --git a/testbed/scenes/collisiondetection/CollisionDetectionScene.cpp b/testbed/scenes/collisiondetection/CollisionDetectionScene.cpp index 88bda0d4..6b9e4e18 100644 --- a/testbed/scenes/collisiondetection/CollisionDetectionScene.cpp +++ b/testbed/scenes/collisiondetection/CollisionDetectionScene.cpp @@ -35,11 +35,12 @@ using namespace collisiondetectionscene; // Constructor CollisionDetectionScene::CollisionDetectionScene(const std::string& name, EngineSettings& settings) : SceneDemo(name, settings, SCENE_RADIUS, false), mMeshFolderPath("meshes/"), - mContactManager(mPhongShader, mMeshFolderPath, mContactPoints), + mContactManager(mPhongShader, mMeshFolderPath, mSnapshotsContactPoints), mAreNormalsDisplayed(false) { mSelectedShapeIndex = 0; - mIsContactPointsDisplayed = true; + mAreContactPointsDisplayed = true; + mAreContactNormalsDisplayed = false; mIsWireframeEnabled = true; // Compute the radius and the center of the scene @@ -218,7 +219,10 @@ CollisionDetectionScene::~CollisionDetectionScene() { // Take a step for the simulation void CollisionDetectionScene::update() { - mContactPoints.clear(); + // Compute debug rendering primitives + mPhysicsWorld->getDebugRenderer().reset(); + mPhysicsWorld->getDebugRenderer().computeDebugRenderingPrimitives(*mPhysicsWorld); + mSnapshotsContactPoints.clear(); mPhysicsWorld->testCollision(mContactManager); diff --git a/testbed/scenes/collisiondetection/CollisionDetectionScene.h b/testbed/scenes/collisiondetection/CollisionDetectionScene.h index 613ddd33..83dc6bef 100644 --- a/testbed/scenes/collisiondetection/CollisionDetectionScene.h +++ b/testbed/scenes/collisiondetection/CollisionDetectionScene.h @@ -142,7 +142,7 @@ class CollisionDetectionScene : public SceneDemo { virtual void setIsShadowMappingEnabled(bool isShadowMappingEnabled) override; /// Display/Hide the contact points - virtual void setIsContactPointsDisplayed(bool display) override; + virtual void setAreContactPointsDisplayed(bool display) override; }; // Display or not the surface normals at hit points @@ -156,8 +156,8 @@ inline void CollisionDetectionScene::setIsShadowMappingEnabled(bool isShadowMapp } // Display/Hide the contact points -inline void CollisionDetectionScene::setIsContactPointsDisplayed(bool display) { - SceneDemo::setIsContactPointsDisplayed(true); +inline void CollisionDetectionScene::setAreContactPointsDisplayed(bool display) { + SceneDemo::setAreContactPointsDisplayed(true); } } diff --git a/testbed/scenes/collisionshapes/CollisionShapesScene.cpp b/testbed/scenes/collisionshapes/CollisionShapesScene.cpp index 1958bb76..d4aac4b3 100644 --- a/testbed/scenes/collisionshapes/CollisionShapesScene.cpp +++ b/testbed/scenes/collisionshapes/CollisionShapesScene.cpp @@ -53,14 +53,6 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name, EngineSettin physicsWorld->setEventListener(this); mPhysicsWorld = physicsWorld; - // TODO : Do not enable by default - mPhysicsWorld->setIsDebugRenderingEnabled(true); - mPhysicsWorld->getDebugRenderer().setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::COLLIDER_AABB, true); - mPhysicsWorld->getDebugRenderer().setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::COLLIDER_BROADPHASE_AABB, true); - mPhysicsWorld->getDebugRenderer().setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::COLLISION_SHAPE, true); - mPhysicsWorld->getDebugRenderer().setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_POINT, true); - mPhysicsWorld->getDebugRenderer().setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_NORMAL, true); - for (int i=0; igetDebugRenderer().reset(); + mPhysicsWorld->getDebugRenderer().computeDebugRenderingPrimitives(*mPhysicsWorld); + mRaycastManager.resetPoints(); // For each line of the scene - for (std::vector::iterator it = mLines.begin(); it != mLines.end(); - ++it) { + for (std::vector::iterator it = mLines.begin(); it != mLines.end(); ++it) { Line* line = *it; @@ -294,6 +295,10 @@ void RaycastScene::update() { // Render the scene void RaycastScene::renderSinglePass(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix) { + if (mIsWireframeEnabled) { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + } + // Bind the VAO mVAO.bind(); @@ -342,6 +347,10 @@ void RaycastScene::renderSinglePass(openglframework::Shader& shader, const openg // Unbind the shader shader.unbind(); + + if (mIsWireframeEnabled) { + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } } // Create the Vertex Buffer Objects used to render with OpenGL. diff --git a/testbed/scenes/raycast/RaycastScene.h b/testbed/scenes/raycast/RaycastScene.h index b516fe63..9317b026 100644 --- a/testbed/scenes/raycast/RaycastScene.h +++ b/testbed/scenes/raycast/RaycastScene.h @@ -72,9 +72,8 @@ class RaycastManager : public rp3d::RaycastCallback { public: - RaycastManager(openglframework::Shader& shader, const std::string& meshFolderPath, - std::vector& hitPoints) - : mMeshFolderPath(meshFolderPath), mHitPoints(hitPoints) { + RaycastManager(const std::string& meshFolderPath, std::vector& hitPoints) + : mHitPoints(hitPoints), mMeshFolderPath(meshFolderPath) { } @@ -94,10 +93,6 @@ class RaycastManager : public rp3d::RaycastCallback { mHitPoints.clear(); } - - std::vector getHitPoints() const { - return mHitPoints; - } }; // Class RaycastScene @@ -146,7 +141,6 @@ class RaycastScene : public SceneDemo { // Create the Vertex Buffer Objects used to render with OpenGL. void createVBOAndVAO(); - public: // -------------------- Methods -------------------- // @@ -180,7 +174,7 @@ class RaycastScene : public SceneDemo { virtual void setIsShadowMappingEnabled(bool isShadowMappingEnabled) override; /// Display/Hide the contact points - virtual void setIsContactPointsDisplayed(bool display) override; + virtual void setAreContactPointsDisplayed(bool display) override; }; // Display or not the surface normals at hit points @@ -194,8 +188,8 @@ inline void RaycastScene::setIsShadowMappingEnabled(bool isShadowMappingEnabled) } // Display/Hide the contact points -inline void RaycastScene::setIsContactPointsDisplayed(bool display) { - SceneDemo::setIsContactPointsDisplayed(true); +inline void RaycastScene::setAreContactPointsDisplayed(bool display) { + SceneDemo::setAreContactPointsDisplayed(true); } } diff --git a/testbed/src/Gui.cpp b/testbed/src/Gui.cpp index d6ab6fe0..2a139062 100644 --- a/testbed/src/Gui.cpp +++ b/testbed/src/Gui.cpp @@ -399,19 +399,55 @@ void Gui::createSettingsPanel() { mRenderingPanel = new Widget(mSettingsPanel); mRenderingPanel->setLayout(new BoxLayout(Orientation::Vertical, Alignment::Fill, 0, 5)); + // Display/Hide contact points + CheckBox* checkboxDebugRendererEnabled = new CheckBox(mRenderingPanel, "Debug rendering"); + checkboxDebugRendererEnabled->setChecked(mApp->mIsDebugRendererEnabled); + // Display/Hide contact points CheckBox* checkboxContactPoints = new CheckBox(mRenderingPanel, "Contact points"); - checkboxContactPoints->setChecked(mApp->mIsContactPointsDisplayed); + checkboxContactPoints->setChecked(mApp->mAreContactPointsDisplayed); + checkboxContactPoints->setEnabled(false); checkboxContactPoints->setCallback([&](bool value) { - mApp->mIsContactPointsDisplayed = value; + mApp->mAreContactPointsDisplayed = value; }); + // Display/Hide contact normals + CheckBox* checkboxContactNormals = new CheckBox(mRenderingPanel, "Contact normals"); + checkboxContactNormals->setChecked(mApp->mAreContactNormalsDisplayed); + checkboxContactNormals->setEnabled(false); + checkboxContactNormals->setCallback([&](bool value) { + mApp->mAreContactNormalsDisplayed = value; + }); - // Display/Hide the AABBs - CheckBox* checkboxAABBs = new CheckBox(mRenderingPanel, "AABBs"); - checkboxAABBs->setChecked(mApp->mIsAABBsDisplayed); - checkboxAABBs->setCallback([&](bool value) { - mApp->mIsAABBsDisplayed = value; + // Display/Hide the Broad-phase AABBs + CheckBox* checkboxBroadPhaseAABBs = new CheckBox(mRenderingPanel, "Broad phase AABBs"); + checkboxBroadPhaseAABBs->setChecked(mApp->mAreBroadPhaseAABBsDisplayed); + checkboxBroadPhaseAABBs->setEnabled(false); + checkboxBroadPhaseAABBs->setCallback([&](bool value) { + mApp->mAreBroadPhaseAABBsDisplayed = value; + }); + + // Display/Hide the colliders AABBs + CheckBox* checkboxColliderAABBs = new CheckBox(mRenderingPanel, "Colliders AABBs"); + checkboxColliderAABBs->setChecked(mApp->mAreCollidersAABBsDisplayed); + checkboxColliderAABBs->setEnabled(false); + checkboxColliderAABBs->setCallback([&](bool value) { + mApp->mAreCollidersAABBsDisplayed = value; + }); + + // Display/Hide the collision shapes + CheckBox* checkboxCollisionShapes = new CheckBox(mRenderingPanel, "Collision shapes"); + checkboxCollisionShapes->setChecked(mApp->mAreCollisionShapesDisplayed); + checkboxCollisionShapes->setEnabled(false); + checkboxCollisionShapes->setCallback([&](bool value) { + mApp->mAreCollisionShapesDisplayed = value; + }); + + // Enable/Disable wireframe mode + CheckBox* checkboxWireframe = new CheckBox(mRenderingPanel, "Objects Wireframe"); + checkboxWireframe->setChecked(mApp->mAreObjectsWireframeEnabled); + checkboxWireframe->setCallback([&](bool value) { + mApp->mAreObjectsWireframeEnabled = value; }); // Enabled/Disable VSync @@ -428,11 +464,15 @@ void Gui::createSettingsPanel() { mApp->mIsShadowMappingEnabled = value; }); - // Enable/Disable wireframe mode - CheckBox* checkboxWireframe = new CheckBox(mRenderingPanel, "Wireframe"); - checkboxWireframe->setChecked(mApp->mIsWireframeEnabled); - checkboxWireframe->setCallback([&](bool value) { - mApp->mIsWireframeEnabled = value; + checkboxDebugRendererEnabled->setCallback([&, checkboxContactPoints, checkboxContactNormals, + checkboxBroadPhaseAABBs, checkboxColliderAABBs, + checkboxCollisionShapes](bool value) { + mApp->mIsDebugRendererEnabled = value; + checkboxContactPoints->setEnabled(value); + checkboxContactNormals->setEnabled(value); + checkboxBroadPhaseAABBs->setEnabled(value); + checkboxColliderAABBs->setEnabled(value); + checkboxCollisionShapes->setEnabled(value); }); mPhysicsPanel->setVisible(true); diff --git a/testbed/src/Scene.cpp b/testbed/src/Scene.cpp index c3883d04..fe2b8b71 100644 --- a/testbed/src/Scene.cpp +++ b/testbed/src/Scene.cpp @@ -33,7 +33,8 @@ using namespace openglframework; Scene::Scene(const std::string& name, EngineSettings& engineSettings, bool isShadowMappingEnabled) : mName(name), mEngineSettings(engineSettings), mLastMouseX(0), mLastMouseY(0), mInterpolationFactor(0.0f), mViewportX(0), mViewportY(0), mViewportWidth(0), mViewportHeight(0), mIsShadowMappingEnabled(isShadowMappingEnabled), - mIsContactPointsDisplayed(true), mIsAABBsDisplayed(false), mIsWireframeEnabled(false) { + mAreContactPointsDisplayed(true), mAreContactNormalsDisplayed(false), mAreBroadPhaseAABBsDisplayed(false), + mAreCollidersAABBsDisplayed(false), mAreCollisionShapesDisplayed(false), mIsWireframeEnabled(false) { } @@ -185,29 +186,3 @@ void Scene::rotate(int xMouse, int yMouse) { } } } - -// Called when some contacts occur -void Scene::onContact(const rp3d::CollisionCallback::CallbackData& callbackData) { - - // For each contact pair - for (uint p=0; p < callbackData.getNbContactPairs(); p++) { - - rp3d::CollisionCallback::ContactPair contactPair = callbackData.getContactPair(p); - - // For each contact point of the contact pair - for (uint c=0; c < contactPair.getNbContactPoints(); c++) { - - rp3d::CollisionCallback::ContactPoint contactPoint = contactPair.getContactPoint(c); - - rp3d::Vector3 point = contactPair.getCollider1()->getLocalToWorldTransform() * contactPoint.getLocalPointOnShape1(); - rp3d::Vector3 normalWorld = contactPoint.getWorldNormal(); - openglframework::Vector3 normal = openglframework::Vector3(normalWorld.x, normalWorld.y, normalWorld.z); - SceneContactPoint contact(openglframework::Vector3(point.x, point.y, point.z), normal, openglframework::Color::red()); - mContactPoints.push_back(contact); - } - } -} - -void Scene::onTrigger(const rp3d::OverlapCallback::CallbackData& callbackData) { - -} diff --git a/testbed/src/Scene.h b/testbed/src/Scene.h index a2d920c8..58e31f83 100644 --- a/testbed/src/Scene.h +++ b/testbed/src/Scene.h @@ -128,16 +128,25 @@ class Scene : public rp3d::EventListener { bool mIsShadowMappingEnabled; /// True if contact points are displayed - bool mIsContactPointsDisplayed; + bool mAreContactPointsDisplayed; - /// True if the AABBs of the physics objects are displayed - bool mIsAABBsDisplayed; + /// True if contact normals are displayed + bool mAreContactNormalsDisplayed; + + /// True if the broad phase AABBs of the physics objects are displayed + bool mAreBroadPhaseAABBsDisplayed; + + /// True if the AABBs of the colliders are displayed + bool mAreCollidersAABBsDisplayed; + + /// True if the AABBs of the colliders are displayed + bool mAreCollisionShapesDisplayed; /// True if we render shapes in wireframe mode bool mIsWireframeEnabled; - /// Contact points - std::vector mContactPoints; + /// Snapshots Contact points (computed with PhysicsWorld::testCollision() or PhysicsWorld::raycast() methods) + std::vector mSnapshotsContactPoints; // -------------------- Methods -------------------- // @@ -222,10 +231,19 @@ class Scene : public rp3d::EventListener { void virtual setIsShadowMappingEnabled(bool isShadowMappingEnabled); /// Display/Hide the contact points - void virtual setIsContactPointsDisplayed(bool display); + void virtual setAreContactPointsDisplayed(bool display); + + /// Display/Hide the contact normals + void setAreContactNormalsDisplayed(bool display); /// Display/Hide the AABBs - void setIsAABBsDisplayed(bool display); + void setAreBroadPhaseAABBsDisplayed(bool display); + + /// Display/Hide the colliders AABBs + void setAreCollidersAABBsDisplayed(bool display); + + /// Display/Hide the collision shapes + void setAreCollisionShapesDisplayed(bool display); /// Return true if wireframe rendering is enabled bool getIsWireframeEnabled() const; @@ -233,13 +251,11 @@ class Scene : public rp3d::EventListener { /// Enable/disbale wireframe rendering void setIsWireframeEnabled(bool isEnabled); + /// Enable/disable debug rendering + virtual void setIsDebugRendererEnabled(bool isEnabled)=0; + /// Update the engine settings virtual void updateEngineSettings() = 0; - - /// Called when some contacts occur - virtual void onContact(const rp3d::CollisionCallback::CallbackData& callbackData) override; - - virtual void onTrigger(const rp3d::OverlapCallback::CallbackData& callbackData) override; }; // Called when a keyboard event occurs @@ -254,7 +270,7 @@ inline void Scene::reshape(int width, int height) { // Reset the scene inline void Scene::reset() { - mContactPoints.clear(); + mSnapshotsContactPoints.clear(); } // Return a reference to the camera @@ -297,13 +313,28 @@ inline void Scene::setIsShadowMappingEnabled(bool isShadowMappingEnabled) { } // Display/Hide the contact points -inline void Scene::setIsContactPointsDisplayed(bool display) { - mIsContactPointsDisplayed = display; +inline void Scene::setAreContactPointsDisplayed(bool display) { + mAreContactPointsDisplayed = display; } -// Display/Hide the AABBs -inline void Scene::setIsAABBsDisplayed(bool display) { - mIsAABBsDisplayed = display; +// Display/Hide the contact normals +inline void Scene::setAreContactNormalsDisplayed(bool display) { + mAreContactNormalsDisplayed = display; +} + +// Display/Hide the broad phase AABBs +inline void Scene::setAreBroadPhaseAABBsDisplayed(bool display) { + mAreBroadPhaseAABBsDisplayed = display; +} + +// Display/Hide the colliders AABBs +inline void Scene::setAreCollidersAABBsDisplayed(bool display) { + mAreCollidersAABBsDisplayed = display; +} + +// Display/Hide the collision shapes +inline void Scene::setAreCollisionShapesDisplayed(bool display) { + mAreCollisionShapesDisplayed = display; } // Return true if wireframe rendering is enabled @@ -311,7 +342,7 @@ inline bool Scene::getIsWireframeEnabled() const { return mIsWireframeEnabled; } -// Enable/disbale wireframe rendering +// Enable/disable wireframe rendering inline void Scene::setIsWireframeEnabled(bool isEnabled) { mIsWireframeEnabled = isEnabled; } diff --git a/testbed/src/SceneDemo.cpp b/testbed/src/SceneDemo.cpp index e1ff38ca..5e825a16 100644 --- a/testbed/src/SceneDemo.cpp +++ b/testbed/src/SceneDemo.cpp @@ -127,8 +127,14 @@ SceneDemo::~SceneDemo() { // Update the scene void SceneDemo::update() { + mPhysicsWorld->getDebugRenderer().setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_POINT, mAreContactPointsDisplayed); + mPhysicsWorld->getDebugRenderer().setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_NORMAL, mAreContactNormalsDisplayed); + mPhysicsWorld->getDebugRenderer().setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::COLLIDER_BROADPHASE_AABB, mAreBroadPhaseAABBsDisplayed); + mPhysicsWorld->getDebugRenderer().setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::COLLIDER_AABB, mAreCollidersAABBsDisplayed); + mPhysicsWorld->getDebugRenderer().setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::COLLISION_SHAPE, mAreCollisionShapesDisplayed); + // Update the contact points - updateContactPoints(); + updateSnapshotContactPoints(); // Update the position and orientation of the physics objects for (std::vector::iterator it = mPhysicsObjects.begin(); it != mPhysicsObjects.end(); ++it) { @@ -143,7 +149,7 @@ void SceneDemo::update() { void SceneDemo::updatePhysics() { // Clear contacts points - mContactPoints.clear(); + mSnapshotsContactPoints.clear(); if (mIsPhysicsWorldSimulated) { @@ -269,15 +275,8 @@ void SceneDemo::render() { // Render the objects of the scene renderSinglePass(mPhongShader, worldToCameraMatrix); - // Render the contact points - if (mIsContactPointsDisplayed) { - renderContactPoints(mPhongShader, worldToCameraMatrix); - } - - // Render the AABBs - if (mIsAABBsDisplayed) { - renderAABBs(worldToCameraMatrix); - } + // Render the snapshots contact points + renderSnapshotsContactPoints(mPhongShader, worldToCameraMatrix); // Render the debug infos if (mPhysicsWorld->getIsDebugRenderingEnabled()) { @@ -456,27 +455,24 @@ void SceneDemo::drawTextureQuad() { mVAOQuad.unbind(); } -// Gather and create contact points -void SceneDemo::updateContactPoints() { +// Gather and create snapshots contact points +void SceneDemo::updateSnapshotContactPoints() { // Remove the previous contact points removeAllVisualContactPoints(); - if (mIsContactPointsDisplayed) { + // For each contact point + std::vector::const_iterator it; + for (it = mSnapshotsContactPoints.begin(); it != mSnapshotsContactPoints.end(); ++it) { - // For each contact point - std::vector::const_iterator it; - for (it = mContactPoints.begin(); it != mContactPoints.end(); ++it) { - - // Create a visual contact point for rendering - VisualContactPoint* point = new VisualContactPoint(it->point, mMeshFolderPath, it->point + it->normal, it->color); - mVisualContactPoints.push_back(point); - } + // Create a visual contact point for rendering + VisualContactPoint* point = new VisualContactPoint(it->point, mMeshFolderPath, it->point + it->normal, it->color); + mVisualContactPoints.push_back(point); } } // Render the contact points -void SceneDemo::renderContactPoints(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix) { +void SceneDemo::renderSnapshotsContactPoints(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix) { // Render all the contact points for (std::vector::iterator it = mVisualContactPoints.begin(); @@ -606,30 +602,6 @@ void SceneDemo::renderDebugInfos(openglframework::Shader& shader, const openglfr glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } -// Render the AABBs -void SceneDemo::renderAABBs(const openglframework::Matrix4& worldToCameraMatrix) { - - // For each physics object of the scene - for (std::vector::iterator it = mPhysicsObjects.begin(); it != mPhysicsObjects.end(); ++it) { - - // For each collider of the object - for (uint i=0; i < (*it)->getCollisionBody()->getNbColliders(); i++) { - - rp3d::Collider* collider = (*it)->getCollisionBody()->getCollider(i); - - // Get the broad-phase AABB corresponding to the collider - rp3d::AABB aabb = mPhysicsWorld->getWorldAABB(collider); - - openglframework::Vector3 aabbCenter(aabb.getCenter().x, aabb.getCenter().y, aabb.getCenter().z); - openglframework::Vector3 aabbMin(aabb.getMin().x, aabb.getMin().y, aabb.getMin().z); - openglframework::Vector3 aabbMax(aabb.getMax().x, aabb.getMax().y, aabb.getMax().z); - - // Render the AABB - AABB::render(aabbCenter, aabbMax - aabbMin, Color::green(), mColorShader, worldToCameraMatrix); - } - } -} - void SceneDemo::removeAllVisualContactPoints() { // Destroy all the visual contact points diff --git a/testbed/src/SceneDemo.h b/testbed/src/SceneDemo.h index 84f202f0..34b78155 100644 --- a/testbed/src/SceneDemo.h +++ b/testbed/src/SceneDemo.h @@ -138,10 +138,10 @@ class SceneDemo : public Scene { void drawTextureQuad(); /// Update the contact points - void updateContactPoints(); + void updateSnapshotContactPoints(); /// Render the contact points - void renderContactPoints(openglframework::Shader& shader, + void renderSnapshotsContactPoints(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix); /// Update VBO with vertices and indices of debug info @@ -150,9 +150,6 @@ class SceneDemo : public Scene { /// Render Debug Infos void renderDebugInfos(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix); - /// Render the AABBs - void renderAABBs(const openglframework::Matrix4& worldToCameraMatrix); - /// Remove all contact points void removeAllVisualContactPoints(); @@ -184,6 +181,9 @@ class SceneDemo : public Scene { /// Enabled/Disable the shadow mapping virtual void setIsShadowMappingEnabled(bool isShadowMappingEnabled) override; + + /// Enable/disable debug rendering + virtual void setIsDebugRendererEnabled(bool isEnabled) override; }; // Enabled/Disable the shadow mapping @@ -196,4 +196,9 @@ inline void SceneDemo::setIsShadowMappingEnabled(bool isShadowMappingEnabled) { } } +// Enable/disable debug rendering +inline void SceneDemo::setIsDebugRendererEnabled(bool isEnabled) { + mPhysicsWorld->setIsDebugRenderingEnabled(isEnabled); +} + #endif diff --git a/testbed/src/TestbedApplication.cpp b/testbed/src/TestbedApplication.cpp index 0842e715..1f29f583 100644 --- a/testbed/src/TestbedApplication.cpp +++ b/testbed/src/TestbedApplication.cpp @@ -63,8 +63,10 @@ TestbedApplication::TestbedApplication(bool isFullscreen, int windowWidth, int w mWidth(windowWidth), mHeight(windowHeight), mSinglePhysicsStepEnabled(false), mSinglePhysicsStepDone(false), mWindowToFramebufferRatio(Vector2(1, 1)), mIsShadowMappingEnabled(true), - mIsContactPointsDisplayed(false), mIsAABBsDisplayed(false), mIsWireframeEnabled(false), - mIsVSyncEnabled(true) { + mAreContactPointsDisplayed(false), mAreContactNormalsDisplayed(false), + mAreBroadPhaseAABBsDisplayed(false), mAreCollidersAABBsDisplayed(false), + mAreCollisionShapesDisplayed(false), mAreObjectsWireframeEnabled(false), + mIsVSyncEnabled(true), mIsDebugRendererEnabled(false) { init(); @@ -89,6 +91,10 @@ void TestbedApplication::init() { mTimer.start(); + // Enable OpenGL error reporting + glEnable(GL_DEBUG_OUTPUT); + glDebugMessageCallback(onOpenGLError, 0); + mIsInitialized = true; } @@ -185,6 +191,8 @@ void TestbedApplication::update() { double currentTime = glfwGetTime(); + mCurrentScene->setIsDebugRendererEnabled(mIsDebugRendererEnabled); + // Update the physics if (mSinglePhysicsStepEnabled && !mSinglePhysicsStepDone) { updateSinglePhysicsStep(); @@ -208,13 +216,22 @@ void TestbedApplication::update() { mCurrentScene->setIsShadowMappingEnabled(mIsShadowMappingEnabled); // Display/Hide contact points - mCurrentScene->setIsContactPointsDisplayed(mIsContactPointsDisplayed); + mCurrentScene->setAreContactPointsDisplayed(mAreContactPointsDisplayed); - // Display/Hide the AABBs - mCurrentScene->setIsAABBsDisplayed(mIsAABBsDisplayed); + // Display/Hide contact normals + mCurrentScene->setAreContactNormalsDisplayed(mAreContactNormalsDisplayed); + + // Display/Hide the broad phase AABBs + mCurrentScene->setAreBroadPhaseAABBsDisplayed(mAreBroadPhaseAABBsDisplayed); + + // Display/Hide the colliders AABBs + mCurrentScene->setAreCollidersAABBsDisplayed(mAreCollidersAABBsDisplayed); + + // Display/Hide the collision shapes + mCurrentScene->setAreCollisionShapesDisplayed(mAreCollisionShapesDisplayed); // Enable/Disable wireframe mode - mCurrentScene->setIsWireframeEnabled(mIsWireframeEnabled); + mCurrentScene->setIsWireframeEnabled(mAreObjectsWireframeEnabled); // Update the scene mCurrentScene->update(); @@ -234,9 +251,6 @@ void TestbedApplication::drawContents() { // Render the scene mCurrentScene->render(); - // Check the OpenGL errors - checkOpenGLErrors(); - mGui.update(); // Compute the current framerate @@ -283,34 +297,16 @@ void TestbedApplication::notifyEngineSetttingsChanged() { mCurrentScene->updateEngineSettings(); } -// Check the OpenGL errors -void TestbedApplication::checkOpenGLErrorsInternal(const char* file, int line) { - GLenum glError; +void GLAPIENTRY TestbedApplication::onOpenGLError(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, + const GLchar* message, const void* userParam ) { - // Get the OpenGL errors - glError = glGetError(); - - // While there are errors - while (glError != GL_NO_ERROR) { - - std::string error; - - switch(glError) { - case GL_INVALID_OPERATION: error="INVALID_OPERATION"; break; - case GL_INVALID_ENUM: error="INVALID_ENUM"; break; - case GL_INVALID_VALUE: error="INVALID_VALUE"; break; - case GL_OUT_OF_MEMORY: error="OUT_OF_MEMORY"; break; - case GL_INVALID_FRAMEBUFFER_OPERATION: error="INVALID_FRAMEBUFFER_OPERATION"; break; - } - - std::cerr << "OpenGL Error #" << error.c_str() << " - " << file << ": " << line << std::endl; - - // Get the next error - glError = glGetError(); + if (type == GL_DEBUG_TYPE_ERROR) { + fprintf( stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", + ("** GL ERROR **" ), + type, severity, message ); } } - // Compute the FPS void TestbedApplication::computeFPS() { diff --git a/testbed/src/TestbedApplication.h b/testbed/src/TestbedApplication.h index 505de188..93e99257 100644 --- a/testbed/src/TestbedApplication.h +++ b/testbed/src/TestbedApplication.h @@ -104,17 +104,29 @@ class TestbedApplication : public Screen { bool mIsShadowMappingEnabled; /// True if contact points are displayed - bool mIsContactPointsDisplayed; + bool mAreContactPointsDisplayed; - /// True if the AABBs of physics objects are displayed - bool mIsAABBsDisplayed; + /// True if contact normals are displayed + bool mAreContactNormalsDisplayed; + + /// True if the broad phase AABBs are displayed + bool mAreBroadPhaseAABBsDisplayed; + + /// True if the AABBs of the colliders are displayed + bool mAreCollidersAABBsDisplayed; + + /// True if the collision shapes are displayed + bool mAreCollisionShapesDisplayed; /// True if the wireframe rendering is enabled - bool mIsWireframeEnabled; + bool mAreObjectsWireframeEnabled; /// True if vsync is enabled bool mIsVSyncEnabled; + /// True if the debug renderer is enabled + bool mIsDebugRendererEnabled; + // -------------------- Methods -------------------- // /// Private copy-constructor (for the singleton class) @@ -132,9 +144,6 @@ class TestbedApplication : public Screen { /// Update the simulation by taking a single physics step void updateSinglePhysicsStep(); - /// Check the OpenGL errors - static void checkOpenGLErrorsInternal(const char* file, int line); - /// Compute the FPS void computeFPS(); @@ -202,6 +211,10 @@ class TestbedApplication : public Screen { /// Notify that the engine settings have changed void notifyEngineSetttingsChanged(); + /// Called when an OpenGL Error occurs + static void GLAPIENTRY onOpenGLError(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, + const GLchar* message, const void* userParam ); + // -------------------- Friendship -------------------- // friend class Gui;