Working on debug renderer

This commit is contained in:
Daniel Chappuis 2020-05-07 15:12:59 +02:00
parent 0321cf4f89
commit 67e89e081b
15 changed files with 267 additions and 223 deletions

View File

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

View File

@ -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<DebugPoint>& getPoints() const;
/// Return a pointer to the array of points
const DebugPoint* getPointsArray() const;
/// Return the number of lines
uint32 getNbLines() const;

View File

@ -45,7 +45,7 @@ DebugRenderer::DebugRenderer(MemoryAllocator& allocator)
mContactPointSphereRadius(DEFAULT_CONTACT_POINT_SPHERE_RADIUS), mContactNormalLength(DEFAULT_CONTACT_NORMAL_LENGTH) {
mMapDebugItemWithColor.add(Pair<DebugItem, uint32>(DebugItem::COLLIDER_AABB, static_cast<uint32>(DebugColor::MAGENTA)));
mMapDebugItemWithColor.add(Pair<DebugItem, uint32>(DebugItem::COLLIDER_BROADPHASE_AABB, static_cast<uint32>(DebugColor::YELLOW)));
mMapDebugItemWithColor.add(Pair<DebugItem, uint32>(DebugItem::COLLIDER_BROADPHASE_AABB, static_cast<uint32>(DebugColor::YELLOW)));
mMapDebugItemWithColor.add(Pair<DebugItem, uint32>(DebugItem::COLLISION_SHAPE, static_cast<uint32>(DebugColor::GREEN)));
mMapDebugItemWithColor.add(Pair<DebugItem, uint32>(DebugItem::CONTACT_POINT, static_cast<uint32>(DebugColor::RED)));
mMapDebugItemWithColor.add(Pair<DebugItem, uint32>(DebugItem::CONTACT_NORMAL, static_cast<uint32>(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]);
}
}
}
}
}

View File

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

View File

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

View File

@ -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; i<NB_COMPOUND_SHAPES; i++) {
// Create a convex mesh and a corresponding rigid in the physics world

View File

@ -33,11 +33,9 @@ using namespace raycastscene;
// Constructor
RaycastScene::RaycastScene(const std::string& name, EngineSettings& settings)
: SceneDemo(name, settings, SCENE_RADIUS, false), mMeshFolderPath("meshes/"),
mRaycastManager(mPhongShader, mMeshFolderPath, mContactPoints), mCurrentBodyIndex(-1),
mRaycastManager(mMeshFolderPath, mSnapshotsContactPoints), mCurrentBodyIndex(-1),
mAreNormalsDisplayed(false), mVBOVertices(GL_ARRAY_BUFFER) {
mIsContactPointsDisplayed = true;
// Compute the radius and the center of the scene
openglframework::Vector3 center(0, 0, 0);
@ -267,11 +265,14 @@ RaycastScene::~RaycastScene() {
// Take a step for the simulation
void RaycastScene::update() {
// Compute debug rendering primitives
mPhysicsWorld->getDebugRenderer().reset();
mPhysicsWorld->getDebugRenderer().computeDebugRenderingPrimitives(*mPhysicsWorld);
mRaycastManager.resetPoints();
// For each line of the scene
for (std::vector<Line*>::iterator it = mLines.begin(); it != mLines.end();
++it) {
for (std::vector<Line*>::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.

View File

@ -72,9 +72,8 @@ class RaycastManager : public rp3d::RaycastCallback {
public:
RaycastManager(openglframework::Shader& shader, const std::string& meshFolderPath,
std::vector<SceneContactPoint>& hitPoints)
: mMeshFolderPath(meshFolderPath), mHitPoints(hitPoints) {
RaycastManager(const std::string& meshFolderPath, std::vector<SceneContactPoint>& hitPoints)
: mHitPoints(hitPoints), mMeshFolderPath(meshFolderPath) {
}
@ -94,10 +93,6 @@ class RaycastManager : public rp3d::RaycastCallback {
mHitPoints.clear();
}
std::vector<SceneContactPoint> 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);
}
}

View File

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

View File

@ -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) {
}

View File

@ -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<SceneContactPoint> mContactPoints;
/// Snapshots Contact points (computed with PhysicsWorld::testCollision() or PhysicsWorld::raycast() methods)
std::vector<SceneContactPoint> 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;
}

View File

@ -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<PhysicsObject*>::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<SceneContactPoint>::const_iterator it;
for (it = mSnapshotsContactPoints.begin(); it != mSnapshotsContactPoints.end(); ++it) {
// For each contact point
std::vector<SceneContactPoint>::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<VisualContactPoint*>::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<PhysicsObject*>::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

View File

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

View File

@ -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() {

View File

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