Working on debug renderer

This commit is contained in:
Daniel Chappuis 2020-05-06 00:34:56 +02:00
parent fb0d3b52e9
commit 56077bba6b
34 changed files with 1111 additions and 44 deletions

View File

@ -181,6 +181,7 @@ SET (REACTPHYSICS3D_HEADERS
"include/reactphysics3d/utils/Profiler.h"
"include/reactphysics3d/utils/Logger.h"
"include/reactphysics3d/utils/DefaultLogger.h"
"include/reactphysics3d/utils/DebugRenderer.h"
)
# Source files
@ -271,6 +272,7 @@ SET (REACTPHYSICS3D_SOURCES
"src/memory/MemoryManager.cpp"
"src/utils/Profiler.cpp"
"src/utils/DefaultLogger.cpp"
"src/utils/DebugRenderer.cpp"
)
# Create the library

View File

@ -37,7 +37,6 @@
namespace reactphysics3d {
// Declarations
struct ContactManifoldListElement;
class Collider;
class CollisionShape;
class PhysicsWorld;

View File

@ -37,7 +37,6 @@ namespace reactphysics3d {
// Declarations
class OverlappingPair;
class ContactManifold;
struct ContactManifoldListElement;
class CollisionBody;
class Collider;
class MemoryManager;

View File

@ -208,6 +208,7 @@ class ConcaveMeshShape : public ConcaveShape {
friend class ConvexTriangleAABBOverlapCallback;
friend class ConcaveMeshRaycastCallback;
friend class PhysicsCommon;
friend class DebugRenderer;
};
// Return the number of bytes used by the collision shape

View File

@ -189,6 +189,9 @@ inline size_t HeightFieldShape::getSizeInBytes() const {
// Return the height of a given (x,y) point in the height field
inline decimal HeightFieldShape::getHeightAt(int x, int y) const {
assert(x >= 0 && x < mNbColumns);
assert(y >= 0 && y < mNbRows);
switch(mHeightDataType) {
case HeightDataType::HEIGHT_FLOAT_TYPE : return ((float*)mHeightFieldData)[y * mNbColumns + x];
case HeightDataType::HEIGHT_DOUBLE_TYPE : return ((double*)mHeightFieldData)[y * mNbColumns + x];

View File

@ -50,6 +50,7 @@
#include <reactphysics3d/systems/ContactSolverSystem.h>
#include <reactphysics3d/systems/DynamicsSystem.h>
#include <reactphysics3d/engine/Islands.h>
#include <reactphysics3d/utils/DebugRenderer.h>
#include <sstream>
/// Namespace ReactPhysics3D
@ -183,6 +184,12 @@ class PhysicsWorld {
/// Entity Manager for the ECS
EntityManager mEntityManager;
/// Debug renderer
DebugRenderer mDebugRenderer;
/// True if debug rendering is enabled
bool mIsDebugRenderingEnabled;
/// Collision Body Components
CollisionBodyComponents mCollisionBodyComponents;
@ -452,6 +459,15 @@ class PhysicsWorld {
/// Return a pointer to a given RigidBody of the world
RigidBody* getRigidBody(uint index) ;
/// Return true if the debug rendering is enabled
bool getIsDebugRenderingEnabled() const;
/// Set to true if debug rendering is enabled
void setIsDebugRenderingEnabled(bool isEnabled);
/// Return a reference to the Debug Renderer of the world
DebugRenderer& getDebugRenderer();
#ifdef IS_PROFILING_ACTIVE
/// Return a reference to the profiler
@ -483,6 +499,7 @@ class PhysicsWorld {
friend class SliderJoint;
friend class CollisionCallback::CallbackData;
friend class OverlapCallback::CallbackData;
friend class DebugRenderer;
};
// Set the collision dispatch configuration
@ -864,6 +881,21 @@ inline RigidBody* PhysicsWorld::getRigidBody(uint index) {
return mRigidBodies[index];
}
// Return true if the debug rendering is enabled
inline bool PhysicsWorld::getIsDebugRenderingEnabled() const {
return mIsDebugRenderingEnabled;
}
// Set to true if debug rendering is enabled
inline void PhysicsWorld::setIsDebugRenderingEnabled(bool isEnabled) {
mIsDebugRenderingEnabled = isEnabled;
}
// Return a reference to the Debug Renderer of the world
inline DebugRenderer& PhysicsWorld::getDebugRenderer() {
return mDebugRenderer;
}
}
#endif

View File

@ -73,7 +73,7 @@ class CollisionDetectionSystem {
// -------------------- Constants -------------------- //
/// Maximum number of contact points in a reduced contact manifold
const int8 MAX_CONTACT_POINTS_IN_MANIFOLD = 4;
static const int8 MAX_CONTACT_POINTS_IN_MANIFOLD = 4;
// -------------------- Attributes -------------------- //
@ -263,6 +263,9 @@ class CollisionDetectionSystem {
/// Report all triggers
void reportTriggers(EventListener& eventListener, List<ContactPair>* contactPairs, List<ContactPair>& lostContactPairs);
/// Report all contacts for debug rendering
void reportDebugRenderingContacts(List<ContactPair>* contactPairs, List<ContactManifold>* manifolds, List<ContactPoint>* contactPoints, List<ContactPair>& lostContactPairs);
/// Return the largest depth of all the contact points of a potential manifold
decimal computePotentialManifoldLargestContactDepth(const ContactManifoldInfo& manifold,
const List<ContactPointInfo>& potentialContactPoints) const;
@ -373,6 +376,7 @@ class CollisionDetectionSystem {
friend class PhysicsWorld;
friend class ConvexMeshShape;
friend class RigidBody;
friend class DebugRenderer;
};
// Return a reference to the collision dispatch configuration

View File

@ -0,0 +1,300 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2019 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef REACTPHYSICS3D_DEBUG_RENDERER_H
#define REACTPHYSICS3D_DEBUG_RENDERER_H
// Libraries
#include <reactphysics3d/containers/List.h>
#include <reactphysics3d/containers/Map.h>
#include <reactphysics3d/mathematics/mathematics.h>
#include <reactphysics3d/engine/EventListener.h>
#include <string>
/// ReactPhysics3D namespace
namespace reactphysics3d {
// Forward declarations
class ConcaveMeshShape;
class ConvexMeshShape;
class HeightFieldShape;
class Collider;
class PhysicsWorld;
// Class DebugRenderer
/**
* This class is used to display physics debug information directly into the user application view.
* For instance, it is possible to display AABBs of colliders, colliders or contact points. This class
* can be used to get the debug information as lists of basic primitives (points, linges, triangles, ...).
* You can use this to render physics debug information in your simulation on top of your object. Note that
* you should use this only for debugging purpose and you should disable it when you compile the final release
* version of your application because computing/rendering phyiscs debug information can be expensive.
*/
class DebugRenderer : public EventListener {
public:
/// Enumeration with basic colors
enum class DebugColor {
RED = 0xff0000,
GREEN = 0x00ff00,
BLUE = 0x0000ff,
BLACK = 0x000000,
WHITE = 0xffffff,
YELLOW = 0xffff00,
MAGENTA = 0xff00ff,
CYAN = 0x00ffff,
};
/// Enumeration with debug item to renderer
enum class DebugItem {
COLLIDER_AABB = 1 << 0,
COLLIDER_BROADPHASE_AABB = 1 << 1,
COLLISION_SHAPE = 1 << 2,
CONTACT_POINT = 1 << 3,
};
/// 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 {
/// Constructor
DebugLine(const Vector3& point1, const Vector3& point2, uint32 color)
:point1(point1), color1(color), point2(point2), color2(color) {
}
Vector3 point1;
uint32 color1;
Vector3 point2;
uint32 color2;
};
/// Struture that represents a triangle of the DebugRenderer
struct DebugTriangle {
/// Constructor
DebugTriangle(const Vector3& point1, const Vector3& point2, const Vector3& point3, uint32 color)
:point1(point1), color1(color), point2(point2), color2(color), point3(point3), color3(color) {
}
Vector3 point1;
uint32 color1;
Vector3 point2;
uint32 color2;
Vector3 point3;
uint32 color3;
};
private:
// -------------------- Constants -------------------- //
/// Number of sectors used to draw a sphere or a capsule
static constexpr int NB_SECTORS_SPHERE = 18;
/// Number of stacks used to draw a sphere or a capsule
static constexpr int NB_STACKS_SPHERE = 10;
/// Default radius of the sphere displayed to represent contact points
static constexpr decimal DEFAULT_CONTACT_POINT_SPHERE_RADIUS = decimal(0.1);
// -------------------- Attributes -------------------- //
/// Memory allocator
MemoryAllocator& mAllocator;
/// List with all the debug lines
List<DebugLine> mLines;
/// List with all the debug triangles
List<DebugTriangle> mTriangles;
/// 32-bits integer that contains all the flags of debug items to display
uint32 mDisplayedDebugItems;
/// Map a debug item with the color used to display it
Map<DebugItem, uint32> mMapDebugItemWithColor;
/// Radius of the sphere displayed to represent contact points
decimal mContactPointSphereRadius;
// -------------------- Methods -------------------- //
/// Draw an AABB
void drawAABB(const AABB& aabb, uint32 color);
/// Draw a box
void drawBox(const Transform& transform, const Vector3& extents, uint32 color);
/// Draw a sphere
void drawSphere(const Vector3& position, decimal radius, uint32 color);
/// Draw a capsule
void drawCapsule(const Transform& transform, decimal radius, decimal height, uint32 color);
/// Draw a convex mesh
void drawConvexMesh(const Transform& transform, const ConvexMeshShape* convexMesh, uint32 color);
/// Draw a concave mesh shape
void drawConcaveMeshShape(const Transform& transform, const ConcaveMeshShape* concaveMeshShape, uint32 color);
/// Draw a height field shape
void drawHeightFieldShape(const Transform& transform, const HeightFieldShape* heightFieldShape, uint32 color);
/// Draw the collision shape of a collider
void drawCollisionShapeOfCollider(const Collider* collider, uint32 color);
public :
// -------------------- Methods -------------------- //
/// Constructor
DebugRenderer(MemoryAllocator& allocator);
/// 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;
/// Return a reference to the list of lines
const List<DebugLine>& getLines() const;
/// Return a pointer to the array of lines
const DebugLine* getLinesArray() const;
/// Return the number of triangles
uint32 getNbTriangles() const;
/// Return a reference to the list of triangles
const List<DebugTriangle>& getTriangles() const;
/// Return a pointer to the array of triangles
const DebugTriangle* getTrianglesArray() const;
/// Return whether a debug item is displayed or not
bool getIsDebugItemDisplayed(DebugItem item) const;
/// Set whether a debug info is displayed or not
void setIsDebugItemDisplayed(DebugItem item, bool isDisplayed);
/// Get the contact point sphere radius
decimal getContactPointSphereRadius() const;
/// Set the contact point sphere radius
void setContactPointSphereRadius(decimal radius);
/// Generate the rendering primitives (triangles, lines, ...) of a physics world
void computeDebugRenderingPrimitives(const PhysicsWorld& world);
/// Clear all the debugging primitives (points, lines, triangles, ...)
void reset();
/// Called when some contacts occur
virtual void onContact(const CollisionCallback::CallbackData& callbackData) override;
};
// Return the number of lines
inline uint32 DebugRenderer::getNbLines() const {
return mLines.size();
}
// Return a reference to the list of lines
inline const List<DebugRenderer::DebugLine>& DebugRenderer::getLines() const {
return mLines;
}
// Return a pointer to the array of lines
inline const DebugRenderer::DebugLine* DebugRenderer::getLinesArray() const {
return &(mLines[0]);
}
// Return the number of triangles
inline uint32 DebugRenderer::getNbTriangles() const {
return mTriangles.size();
}
// Return a reference to the list of triangles
inline const List<DebugRenderer::DebugTriangle>& DebugRenderer::getTriangles() const {
return mTriangles;
}
// Return a pointer to the array of triangles
inline const DebugRenderer::DebugTriangle* DebugRenderer::getTrianglesArray() const {
return &(mTriangles[0]);
}
// Return whether a debug item is displayed or not
inline bool DebugRenderer::getIsDebugItemDisplayed(DebugItem item) const {
return mDisplayedDebugItems & static_cast<uint32>(item);
}
// Set whether a debug info is displayed or not
inline void DebugRenderer::setIsDebugItemDisplayed(DebugItem item, bool isDisplayed) {
const uint32 itemFlag = static_cast<uint32>(item);
uint32 resetBit = ~(itemFlag);
mDisplayedDebugItems &= resetBit;
if (isDisplayed) {
mDisplayedDebugItems |= itemFlag;
}
}
// Get the contact point sphere radius
inline decimal DebugRenderer::getContactPointSphereRadius() const {
return mContactPointSphereRadius;
}
// Set the contact point sphere radius
inline void DebugRenderer::setContactPointSphereRadius(decimal radius) {
assert(radius > decimal(0.0));
mContactPointSphereRadius = radius;
}
}
#endif

View File

@ -51,7 +51,7 @@ uint PhysicsWorld::mNbWorlds = 0;
* @param profiler Pointer to the profiler
*/
PhysicsWorld::PhysicsWorld(MemoryManager& memoryManager, const WorldSettings& worldSettings, Logger* logger, Profiler* profiler)
: mMemoryManager(memoryManager), mConfig(worldSettings), mEntityManager(mMemoryManager.getHeapAllocator()),
: mMemoryManager(memoryManager), mConfig(worldSettings), mEntityManager(mMemoryManager.getHeapAllocator()), mDebugRenderer(mMemoryManager.getHeapAllocator()),
mCollisionBodyComponents(mMemoryManager.getHeapAllocator()), mRigidBodyComponents(mMemoryManager.getHeapAllocator()),
mTransformComponents(mMemoryManager.getHeapAllocator()), mCollidersComponents(mMemoryManager.getHeapAllocator()),
mJointsComponents(mMemoryManager.getHeapAllocator()), mBallAndSocketJointsComponents(mMemoryManager.getHeapAllocator()),
@ -331,6 +331,11 @@ void PhysicsWorld::update(decimal timeStep) {
RP3D_PROFILE("PhysicsWorld::update()", mProfiler);
// Reset the debug renderer
if (mIsDebugRenderingEnabled) {
mDebugRenderer.reset();
}
// Compute the collision detection
mCollisionDetection.computeCollisionDetection();
@ -369,6 +374,11 @@ void PhysicsWorld::update(decimal timeStep) {
// Reset the islands
mIslands.clear();
// Generate debug rendering primitives (if enabled)
if (mIsDebugRenderingEnabled) {
mDebugRenderer.computeDebugRenderingPrimitives(*this);
}
// Reset the single frame memory allocator
mMemoryManager.resetFrameAllocator();
}

View File

@ -1386,18 +1386,25 @@ void CollisionDetectionSystem::reduceContactPoints(ContactManifoldInfo& manifold
// Report contacts and triggers
void CollisionDetectionSystem::reportContactsAndTriggers() {
if (mWorld->mEventListener != nullptr) {
// Report contacts and triggers to the user
if (mWorld->mEventListener != nullptr) {
reportContacts(*(mWorld->mEventListener), mCurrentContactPairs, mCurrentContactManifolds, mCurrentContactPoints, mLostContactPairs);
reportTriggers(*(mWorld->mEventListener), mCurrentContactPairs, mLostContactPairs);
}
}
mOverlappingPairs.updateCollidingInPreviousFrame();
// Report contacts for debug rendering (if enabled)
if (mWorld->mIsDebugRenderingEnabled) {
mLostContactPairs.clear(true);
reportDebugRenderingContacts(mCurrentContactPairs, mCurrentContactManifolds, mCurrentContactPoints, mLostContactPairs);
}
mOverlappingPairs.updateCollidingInPreviousFrame();
mLostContactPairs.clear(true);
}
// Report all contacts
// Report all contacts to the user
void CollisionDetectionSystem::reportContacts(CollisionCallback& callback, List<ContactPair>* contactPairs,
List<ContactManifold>* manifolds, List<ContactPoint>* contactPoints, List<ContactPair>& lostContactPairs) {
@ -1413,7 +1420,7 @@ void CollisionDetectionSystem::reportContacts(CollisionCallback& callback, List<
}
}
// Report all triggers
// Report all triggers to the user
void CollisionDetectionSystem::reportTriggers(EventListener& eventListener, List<ContactPair>* contactPairs, List<ContactPair>& lostContactPairs) {
RP3D_PROFILE("CollisionDetectionSystem::reportTriggers()", mProfiler);
@ -1428,6 +1435,21 @@ void CollisionDetectionSystem::reportTriggers(EventListener& eventListener, List
}
}
// Report all contacts for debug rendering
void CollisionDetectionSystem::reportDebugRenderingContacts(List<ContactPair>* contactPairs, List<ContactManifold>* manifolds, List<ContactPoint>* contactPoints, List<ContactPair>& lostContactPairs) {
RP3D_PROFILE("CollisionDetectionSystem::reportDebugRenderingContacts()", mProfiler);
// If there are contacts
if (contactPairs->size() + lostContactPairs.size() > 0) {
CollisionCallback::CallbackData callbackData(contactPairs, manifolds, contactPoints, lostContactPairs, *mWorld);
// Call the callback method to report the contacts
mWorld->mDebugRenderer.onContact(callbackData);
}
}
// Return true if two bodies overlap (collide)
bool CollisionDetectionSystem::testOverlap(CollisionBody* body1, CollisionBody* body2) {

462
src/utils/DebugRenderer.cpp Normal file
View File

@ -0,0 +1,462 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2019 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include <reactphysics3d/utils/DebugRenderer.h>
#include <reactphysics3d/memory/MemoryManager.h>
#include <cassert>
#include <reactphysics3d/collision/shapes/ConvexMeshShape.h>
#include <reactphysics3d/collision/shapes/ConcaveMeshShape.h>
#include <reactphysics3d/collision/shapes/HeightFieldShape.h>
#include <reactphysics3d/collision/shapes/BoxShape.h>
#include <reactphysics3d/collision/shapes/SphereShape.h>
#include <reactphysics3d/collision/shapes/CapsuleShape.h>
#include <reactphysics3d/collision/Collider.h>
#include <reactphysics3d/engine/PhysicsWorld.h>
#include <reactphysics3d/containers/Pair.h>
using namespace reactphysics3d;
// Constructor
DebugRenderer::DebugRenderer(MemoryAllocator& allocator)
:mAllocator(allocator), mLines(allocator), mTriangles(allocator), mDisplayedDebugItems(0), mMapDebugItemWithColor(allocator),
mContactPointSphereRadius(DEFAULT_CONTACT_POINT_SPHERE_RADIUS) {
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::COLLISION_SHAPE, static_cast<uint32>(DebugColor::GREEN)));
mMapDebugItemWithColor.add(Pair<DebugItem, uint32>(DebugItem::CONTACT_POINT, static_cast<uint32>(DebugColor::RED)));
}
// Destructor
DebugRenderer::~DebugRenderer() {
}
// Clear all the debugging primitives (points, lines, triangles, ...)
void DebugRenderer::reset() {
mLines.clear();
mTriangles.clear();
}
// Draw an AABB
void DebugRenderer::drawAABB(const AABB& aabb, uint32 color) {
const Vector3& min = aabb.getMin();
const Vector3& max = aabb.getMax();
// Bottom edges
mLines.add(DebugLine(Vector3(min.x, min.y, max.z), Vector3(max.x, min.y, max.z), color));
mLines.add(DebugLine(Vector3(max.x, min.y, max.z), Vector3(max.x, min.y, min.z), color));
mLines.add(DebugLine(Vector3(max.x, min.y, min.z), Vector3(min.x, min.y, min.z), color));
mLines.add(DebugLine(Vector3(min.x, min.y, min.z), Vector3(min.x, min.y, max.z), color));
// Top edges
mLines.add(DebugLine(Vector3(min.x, max.y, max.z), Vector3(max.x, max.y, max.z), color));
mLines.add(DebugLine(Vector3(max.x, max.y, max.z), Vector3(max.x, max.y, min.z), color));
mLines.add(DebugLine(Vector3(max.x, max.y, min.z), Vector3(min.x, max.y, min.z), color));
mLines.add(DebugLine(Vector3(min.x, max.y, min.z), Vector3(min.x, max.y, max.z), color));
// Side edges
mLines.add(DebugLine(Vector3(min.x, min.y, max.z), Vector3(min.x, max.y, max.z), color));
mLines.add(DebugLine(Vector3(max.x, min.y, max.z), Vector3(max.x, max.y, max.z), color));
mLines.add(DebugLine(Vector3(max.x, min.y, min.z), Vector3(max.x, max.y, min.z), color));
mLines.add(DebugLine(Vector3(min.x, min.y, min.z), Vector3(min.x, max.y, min.z), color));
}
// Draw a box
void DebugRenderer::drawBox(const Transform& transform, const Vector3& halfExtents, uint32 color) {
Vector3 vertices[8];
// Vertices
vertices[0] = transform * Vector3(-halfExtents.x, -halfExtents.y, halfExtents.z);
vertices[1] = transform * Vector3(halfExtents.x, -halfExtents.y, halfExtents.z);
vertices[2] = transform * Vector3(halfExtents.x, -halfExtents.y, -halfExtents.z);
vertices[3] = transform * Vector3(-halfExtents.x, -halfExtents.y, -halfExtents.z);
vertices[4] = transform * Vector3(-halfExtents.x, halfExtents.y, halfExtents.z);
vertices[5] = transform * Vector3(halfExtents.x, halfExtents.y, halfExtents.z);
vertices[6] = transform * Vector3(halfExtents.x, halfExtents.y, -halfExtents.z);
vertices[7] = transform * Vector3(-halfExtents.x, halfExtents.y, -halfExtents.z);
// Triangle faces
mTriangles.add(DebugTriangle(vertices[0], vertices[1], vertices[5], color));
mTriangles.add(DebugTriangle(vertices[0], vertices[5], vertices[4], color));
mTriangles.add(DebugTriangle(vertices[1], vertices[2], vertices[6], color));
mTriangles.add(DebugTriangle(vertices[1], vertices[6], vertices[5], color));
mTriangles.add(DebugTriangle(vertices[2], vertices[3], vertices[6], color));
mTriangles.add(DebugTriangle(vertices[3], vertices[7], vertices[6], color));
mTriangles.add(DebugTriangle(vertices[0], vertices[7], vertices[3], color));
mTriangles.add(DebugTriangle(vertices[0], vertices[4], vertices[7], color));
mTriangles.add(DebugTriangle(vertices[0], vertices[2], vertices[1], color));
mTriangles.add(DebugTriangle(vertices[0], vertices[3], vertices[2], color));
mTriangles.add(DebugTriangle(vertices[5], vertices[6], vertices[4], color));
mTriangles.add(DebugTriangle(vertices[4], vertices[6], vertices[7], color));
}
/// Draw a sphere
void DebugRenderer::drawSphere(const Vector3& position, decimal radius, uint32 color) {
Vector3 vertices[(NB_SECTORS_SPHERE + 1) * (NB_STACKS_SPHERE + 1) + (NB_SECTORS_SPHERE + 1)];
// Vertices
const decimal sectorStep = 2 * PI / NB_SECTORS_SPHERE;
const decimal stackStep = PI / NB_STACKS_SPHERE;
for (uint i = 0; i <= NB_STACKS_SPHERE; i++) {
const decimal stackAngle = PI / 2 - i * stackStep;
const decimal radiusCosStackAngle = radius * std::cos(stackAngle);
const decimal z = radius * std::sin(stackAngle);
for (uint j = 0; j <= NB_SECTORS_SPHERE; j++) {
const decimal sectorAngle = j * sectorStep;
const decimal x = radiusCosStackAngle * std::cos(sectorAngle);
const decimal y = radiusCosStackAngle * std::sin(sectorAngle);
vertices[i * (NB_SECTORS_SPHERE + 1) + j] = position + Vector3(x, y, z);
}
}
// Faces
for (uint i = 0; i < NB_STACKS_SPHERE; i++) {
uint a1 = i * (NB_SECTORS_SPHERE + 1);
uint a2 = a1 + NB_SECTORS_SPHERE + 1;
for (uint j = 0; j < NB_SECTORS_SPHERE; j++, a1++, a2++) {
// 2 triangles per sector except for the first and last stacks
if (i != 0) {
mTriangles.add(DebugTriangle(vertices[a1], vertices[a2], vertices[a1 + 1], color));
}
if (i != (NB_STACKS_SPHERE - 1)) {
mTriangles.add(DebugTriangle(vertices[a1 + 1], vertices[a2], vertices[a2 + 1], color));
}
}
}
}
// Draw a capsule
void DebugRenderer::drawCapsule(const Transform& transform, decimal radius, decimal height, uint32 color) {
Vector3 vertices[(NB_SECTORS_SPHERE + 1) * (NB_STACKS_SPHERE + 1) + (NB_SECTORS_SPHERE + 1)];
const decimal halfHeight = 0.5 * height;
// Use an even number of stacks
const uint nbStacks = NB_STACKS_SPHERE % 2 == 0 ? NB_STACKS_SPHERE : NB_STACKS_SPHERE - 1;
const uint nbHalfStacks = nbStacks / 2;
// Vertices
const decimal sectorStep = 2 * PI / NB_SECTORS_SPHERE;
const decimal stackStep = PI / nbStacks;
uint vertexIndex = 0;
// Top cap sphere vertices
for (uint i = 0; i <= nbHalfStacks; i++) {
const decimal stackAngle = PI / 2 - i * stackStep;
const decimal radiusCosStackAngle = radius * std::cos(stackAngle);
const decimal y = radius * std::sin(stackAngle);
for (uint j = 0; j <= NB_SECTORS_SPHERE; j++) {
const decimal sectorAngle = j * sectorStep;
const decimal x = radiusCosStackAngle * std::sin(sectorAngle);
const decimal z = radiusCosStackAngle * std::cos(sectorAngle);
assert(vertexIndex < (NB_SECTORS_SPHERE + 1) * (nbStacks + 1) + (NB_SECTORS_SPHERE + 1));
vertices[vertexIndex] = transform * Vector3(x, y + halfHeight, z);
vertexIndex++;
}
}
// Bottom cap sphere vertices
for (uint i = 0; i <= nbHalfStacks; i++) {
const decimal stackAngle = PI / 2 - (nbHalfStacks + i) * stackStep;
const decimal radiusCosStackAngle = radius * std::cos(stackAngle);
const decimal y = radius * std::sin(stackAngle);
for (uint j = 0; j <= NB_SECTORS_SPHERE; j++) {
const decimal sectorAngle = j * sectorStep;
const decimal x = radiusCosStackAngle * std::sin(sectorAngle);
const decimal z = radiusCosStackAngle * std::cos(sectorAngle);
assert(vertexIndex < (NB_SECTORS_SPHERE + 1) * (nbStacks + 1) + (NB_SECTORS_SPHERE + 1));
vertices[vertexIndex] = transform * Vector3(x, y - halfHeight, z);
vertexIndex++;
}
}
// Faces of the top cap sphere
for (uint i = 0; i < nbHalfStacks; i++) {
uint a1 = i * (NB_SECTORS_SPHERE + 1);
uint a2 = a1 + NB_SECTORS_SPHERE + 1;
for (uint j = 0; j < NB_SECTORS_SPHERE; j++, a1++, a2++) {
// 2 triangles per sector except for the first stack
if (i != 0) {
mTriangles.add(DebugTriangle(vertices[a1], vertices[a2], vertices[a1 + 1], color));
}
mTriangles.add(DebugTriangle(vertices[a1 + 1], vertices[a2], vertices[a2 + 1], color));
}
}
// Faces of the bottom cap sphere
for (uint i = 0; i < nbHalfStacks; i++) {
uint a1 = (nbHalfStacks + 1) * (NB_SECTORS_SPHERE + 1) + i * (NB_SECTORS_SPHERE + 1);
uint a2 = a1 + NB_SECTORS_SPHERE + 1;
for (uint j = 0; j < NB_SECTORS_SPHERE; j++, a1++, a2++) {
// 2 triangles per sector except for the last stack
mTriangles.add(DebugTriangle(vertices[a1], vertices[a2], vertices[a1 + 1], color));
if (i != (nbHalfStacks - 1)) {
mTriangles.add(DebugTriangle(vertices[a1 + 1], vertices[a2], vertices[a2 + 1], color));
}
}
}
// Faces of the cylinder between the two spheres
uint a1 = nbHalfStacks * (NB_SECTORS_SPHERE + 1);
uint a2 = a1 + NB_SECTORS_SPHERE + 1;
for (uint i = 0; i < NB_SECTORS_SPHERE; i++, a1++, a2++) {
mTriangles.add(DebugTriangle(vertices[a1 + 1], vertices[a2], vertices[a2 + 1], color));
}
}
// Draw a convex mesh
void DebugRenderer::drawConvexMesh(const Transform& transform, const ConvexMeshShape* convexMesh, uint32 color) {
// For each face of the convex mesh
for (uint32 f = 0; f < convexMesh->getNbFaces(); f++) {
const HalfEdgeStructure::Face& face = convexMesh->getFace(f);
assert(face.faceVertices.size() >= 3);
// Perform a fan triangulation of the convex polygon face
for (uint32 v = 2; v < face.faceVertices.size(); v++) {
uint v1Index = face.faceVertices[v - 2];
uint v2Index = face.faceVertices[v - 1];
uint v3Index = face.faceVertices[v];
Vector3 v1 = convexMesh->getVertexPosition(v1Index);
Vector3 v2 = convexMesh->getVertexPosition(v2Index);
Vector3 v3 = convexMesh->getVertexPosition(v3Index);
v1 = transform * v1;
v2 = transform * v2;
v3 = transform * v3;
mTriangles.add(DebugTriangle(v1, v2, v3, color));
}
}
}
// Draw a concave mesh shape
void DebugRenderer::drawConcaveMeshShape(const Transform& transform, const ConcaveMeshShape* concaveMeshShape, uint32 color) {
// For each sub-part of the mesh
for (uint p = 0; p < concaveMeshShape->getNbSubparts(); p++) {
// For each triangle of the sub-part
for (uint t = 0; t < concaveMeshShape->getNbTriangles(p); t++) {
Vector3 triangleVertices[3];
concaveMeshShape->getTriangleVertices(p, t, triangleVertices);
triangleVertices[0] = transform * triangleVertices[0];
triangleVertices[1] = transform * triangleVertices[1];
triangleVertices[2] = transform * triangleVertices[2];
mTriangles.add(DebugTriangle(triangleVertices[0], triangleVertices[1], triangleVertices[2], color));
}
}
}
// Draw a height field shape
void DebugRenderer::drawHeightFieldShape(const Transform& transform, const HeightFieldShape* heightFieldShape, uint32 color) {
// For each sub-grid points (except the last ones one each dimension)
for (int i = 0; i < heightFieldShape->getNbColumns() - 1; i++) {
for (int j = 0; j < heightFieldShape->getNbRows() - 1; j++) {
// Compute the four point of the current quad
Vector3 p1 = heightFieldShape->getVertexAt(i, j);
Vector3 p2 = heightFieldShape->getVertexAt(i, j + 1);
Vector3 p3 = heightFieldShape->getVertexAt(i + 1, j);
Vector3 p4 = heightFieldShape->getVertexAt(i + 1, j + 1);
p1 = transform * p1;
p2 = transform * p2;
p3 = transform * p3;
p4 = transform * p4;
mTriangles.add(DebugTriangle(p1, p2, p3, color));
mTriangles.add(DebugTriangle(p3, p2, p4, color));
}
}
}
// Draw the collision shape of a collider
void DebugRenderer::drawCollisionShapeOfCollider(const Collider* collider, uint32 color) {
switch (collider->getCollisionShape()->getName()) {
case CollisionShapeName::BOX:
{
const BoxShape* boxShape = static_cast<const BoxShape*>(collider->getCollisionShape());
drawBox(collider->getLocalToWorldTransform(), boxShape->getHalfExtents(), color);
break;
}
case CollisionShapeName::SPHERE:
{
const SphereShape* sphereShape = static_cast<const SphereShape*>(collider->getCollisionShape());
drawSphere(collider->getLocalToWorldTransform().getPosition(), sphereShape->getRadius(), color);
break;
}
case CollisionShapeName::CAPSULE:
{
const CapsuleShape* capsuleShape = static_cast<const CapsuleShape*>(collider->getCollisionShape());
drawCapsule(collider->getLocalToWorldTransform(), capsuleShape->getRadius(), capsuleShape->getHeight(), color);
break;
}
case CollisionShapeName::CONVEX_MESH:
{
const ConvexMeshShape* convexMeshShape = static_cast<const ConvexMeshShape*>(collider->getCollisionShape());
drawConvexMesh(collider->getLocalToWorldTransform(), convexMeshShape, color);
break;
}
case CollisionShapeName::TRIANGLE_MESH:
{
const ConcaveMeshShape* concaveMeshShape = static_cast<const ConcaveMeshShape*>(collider->getCollisionShape());
drawConcaveMeshShape(collider->getLocalToWorldTransform(), concaveMeshShape, color);
break;
}
case CollisionShapeName::HEIGHTFIELD:
{
const HeightFieldShape* heighFieldShape = static_cast<const HeightFieldShape*>(collider->getCollisionShape());
drawHeightFieldShape(collider->getLocalToWorldTransform(), heighFieldShape, color);
break;
}
default:
{
assert(false);
}
}
}
// Generate the rendering primitives (triangles, lines, ...) of a physics world
void DebugRenderer::computeDebugRenderingPrimitives(const PhysicsWorld& world) {
const bool drawColliderAABB = getIsDebugItemDisplayed(DebugItem::COLLIDER_AABB);
const bool drawColliderBroadphaseAABB = getIsDebugItemDisplayed(DebugItem::COLLIDER_BROADPHASE_AABB);
const bool drawCollisionShape = getIsDebugItemDisplayed(DebugItem::COLLISION_SHAPE);
const uint nbCollisionBodies = world.getNbCollisionBodies();
const uint nbRigidBodies = world.getNbRigidBodies();
// For each body of the world
for (uint b = 0; b < nbCollisionBodies + nbRigidBodies; b++) {
// 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++) {
// Get a collider
const Collider* collider = body->getCollider(c);
// 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) {
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]);
}
}
}
}
// Called when some contacts occur
void DebugRenderer::onContact(const CollisionCallback::CallbackData& callbackData) {
// If we need to draw contact points
if (getIsDebugItemDisplayed(DebugItem::CONTACT_POINT)) {
// For each contact pair
for (uint p = 0; p < callbackData.getNbContactPairs(); p++) {
CollisionCallback::ContactPair contactPair = callbackData.getContactPair(p);
if (contactPair.getEventType() != CollisionCallback::ContactPair::EventType::ContactExit) {
// For each contact point of the contact pair
for (uint c = 0; c < contactPair.getNbContactPoints(); c++) {
CollisionCallback::ContactPoint contactPoint = contactPair.getContactPoint(c);
Vector3 point = contactPair.getCollider1()->getLocalToWorldTransform() * contactPoint.getLocalPointOnShape1();
drawSphere(point, DEFAULT_CONTACT_POINT_SPHERE_RADIUS, mMapDebugItemWithColor[DebugItem::CONTACT_POINT]);
}
}
}
}
}

View File

@ -87,7 +87,8 @@ void AABB::render(const openglframework::Vector3& position, const openglframewor
// Set the vertex color
openglframework::Vector4 colorVec(color.r, color.g, color.b, color.a);
shader.setVector4Uniform("vertexColor", colorVec, false);
shader.setIntUniform("isGlobalVertexColorEnabled", 1, false);
shader.setVector4Uniform("globalVertexColor", colorVec, false);
// Bind the VAO
mVAO.bind();

View File

@ -122,7 +122,7 @@ void Box::render(openglframework::Shader& shader, const openglframework::Matrix4
rp3d::RigidBody* rigidBody = dynamic_cast<rp3d::RigidBody*>(mBody);
openglframework::Color currentColor = rigidBody != nullptr && rigidBody->isSleeping() ? mSleepingColor : mColor;
openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
shader.setVector4Uniform("vertexColor", color, false);
shader.setVector4Uniform("globalVertexColor", color, false);
// Bind the VAO
mVAO.bind();

View File

@ -117,7 +117,7 @@ void Capsule::render(openglframework::Shader& shader,
rp3d::RigidBody* rigidBody = dynamic_cast<rp3d::RigidBody*>(mBody);
openglframework::Color currentColor = rigidBody != nullptr && rigidBody->isSleeping() ? mSleepingColor : mColor;
openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
shader.setVector4Uniform("vertexColor", color, false);
shader.setVector4Uniform("globalVertexColor", color, false);
// Bind the VAO
mVAO.bind();

View File

@ -118,7 +118,7 @@ void ConcaveMesh::render(openglframework::Shader& shader,
rp3d::RigidBody* rigidBody = dynamic_cast<rp3d::RigidBody*>(mBody);
openglframework::Color currentColor = rigidBody != nullptr && rigidBody->isSleeping() ? mSleepingColor : mColor;
openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
shader.setVector4Uniform("vertexColor", color, false);
shader.setVector4Uniform("globalVertexColor", color, false);
// Bind the VAO
mVAO.bind();

View File

@ -136,7 +136,7 @@ void ConvexMesh::render(openglframework::Shader& shader,
rp3d::RigidBody* rigidBody = dynamic_cast<rp3d::RigidBody*>(mBody);
openglframework::Color currentColor = rigidBody != nullptr && rigidBody->isSleeping() ? mSleepingColor : mColor;
openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
shader.setVector4Uniform("vertexColor", color, false);
shader.setVector4Uniform("globalVertexColor", color, false);
// Bind the VAO
mVAO.bind();

View File

@ -139,7 +139,7 @@ void Dumbbell::render(openglframework::Shader& shader,
rp3d::RigidBody* rigidBody = dynamic_cast<rp3d::RigidBody*>(mBody);
openglframework::Color currentColor = rigidBody != nullptr && rigidBody->isSleeping() ? mSleepingColor : mColor;
openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
shader.setVector4Uniform("vertexColor", color, false);
shader.setVector4Uniform("globalVertexColor", color, false);
// Bind the VAO
mVAO.bind();

View File

@ -108,7 +108,7 @@ void HeightField::render(openglframework::Shader& shader,
rp3d::RigidBody* rigidBody = dynamic_cast<rp3d::RigidBody*>(mBody);
openglframework::Color currentColor = rigidBody != nullptr && rigidBody->isSleeping() ? mSleepingColor : mColor;
openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
shader.setVector4Uniform("vertexColor", color, false);
shader.setVector4Uniform("globalVertexColor", color, false);
// Bind the VAO
mVAO.bind();

View File

@ -40,8 +40,7 @@ Line::~Line() {
}
// Render the sphere at the correct position and with the correct orientation
void Line::render(openglframework::Shader& shader,
const openglframework::Matrix4& worldToCameraMatrix) {
void Line::render(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix) {
// Bind the shader
shader.bind();
@ -52,7 +51,8 @@ void Line::render(openglframework::Shader& shader,
// Set the vertex color
openglframework::Vector4 color(1, 0, 0, 1);
shader.setVector4Uniform("vertexColor", color, false);
shader.setIntUniform("isGlobalVertexColorEnabled", 1, false);
shader.setVector4Uniform("globalVertexColor", color, false);
/*
glBegin(GL_LINES);

View File

@ -115,7 +115,7 @@ void Sphere::render(openglframework::Shader& shader, const openglframework::Matr
rp3d::RigidBody* rigidBody = dynamic_cast<rp3d::RigidBody*>(mBody);
openglframework::Color currentColor = rigidBody != nullptr && rigidBody->isSleeping() ? mSleepingColor : mColor;
openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
shader.setVector4Uniform("vertexColor", color, false);
shader.setVector4Uniform("globalVertexColor", color, false);
// Bind the VAO
mVAO.bind();

View File

@ -101,7 +101,8 @@ void VisualContactPoint::render(openglframework::Shader& shader, const openglfra
// Set the vertex color
openglframework::Vector4 color(mColor.r, mColor.g, mColor.b, mColor.a);
shader.setVector4Uniform("vertexColor", color, false);
shader.setIntUniform("isGlobalVertexColorEnabled", 1, false);
shader.setVector4Uniform("globalVertexColor", color, false);
mVBOVertices.bind();
@ -172,7 +173,8 @@ void VisualContactPoint::renderContactNormalLine(openglframework::Shader& shader
// Set the vertex color
openglframework::Vector4 color(0, 1, 0, 1);
shader.setVector4Uniform("vertexColor", color, false);
shader.setIntUniform("isGlobalVertexColorEnabled", 1, false);
shader.setVector4Uniform("globalVertexColor", color, false);
// Get the location of shader attribute variables
GLint vertexPositionLoc = shader.getAttribLocation("vertexPosition");

View File

@ -176,7 +176,7 @@ inline GLint Shader::getAttribLocation(const std::string& variableName, bool err
GLint location = glGetAttribLocation(mProgramObjectID, variableName.c_str());
if (location == -1 && errorIfMissing) {
std::cerr << "Error in vertex shader " << mFilenameVertexShader << " or in fragment shader"
<< mFilenameFragmentShader << " : No Uniform variable : " << variableName
<< mFilenameFragmentShader << " : No variable : " << variableName
<< std::endl;
throw std::logic_error("Error in Shader");
}

View File

@ -67,6 +67,16 @@ void VertexBufferObject::copyDataIntoVBO(GLsizei size, const void* data, GLenum
glBufferData(mTargetData, size, data, usage);
}
// Map VBO data memory into client's memory
void* VertexBufferObject::mapBuffer(GLenum access) {
return glMapBuffer(mTargetData, access);
}
// Unmap VBO data memory from client's memory
void VertexBufferObject::unmapBuffer() {
glUnmapBuffer(mTargetData);
}
// Destroy the VBO
void VertexBufferObject::destroy() {

View File

@ -65,6 +65,12 @@ class VertexBufferObject {
/// Copy data into the VBO
void copyDataIntoVBO(GLsizei size, const void* data, GLenum usage);
/// Map VBO data memory into client's memory
void* mapBuffer(GLenum access);
/// Unmap VBO data memory from client's memory
void unmapBuffer();
/// Bind the VBO
void bind() const;

View File

@ -53,6 +53,13 @@ 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);
for (int i=0; i<NB_COMPOUND_SHAPES; i++) {
// Create a convex mesh and a corresponding rigid in the physics world

View File

@ -42,11 +42,11 @@ namespace collisionshapesscene {
// Constants
const float SCENE_RADIUS = 30.0f;
const int NB_BOXES = 5;
const int NB_SPHERES = 5;
const int NB_CAPSULES = 5;
const int NB_MESHES = 4;
const int NB_COMPOUND_SHAPES = 3;
const int NB_BOXES = 2;
const int NB_SPHERES = 2;
const int NB_CAPSULES = 2;
const int NB_MESHES = 2;
const int NB_COMPOUND_SHAPES = 1;
const openglframework::Vector3 BOX_SIZE(2, 2, 2);
const float SPHERE_RADIUS = 1.5f;
const float CONE_RADIUS = 2.0f;

View File

@ -36,7 +36,7 @@ namespace cubesscene {
// Constants
const float SCENE_RADIUS = 30.0f; // Radius of the scene in meters
const int NB_CUBES = 30; // Number of boxes in the scene
const int NB_CUBES = 1; // Number of boxes in the scene
const openglframework::Vector3 BOX_SIZE(2, 2, 2); // Box dimensions in meters
const openglframework::Vector3 FLOOR_SIZE(50, 1, 50); // Floor dimensions in meters

View File

@ -53,7 +53,7 @@ HeightFieldScene::HeightFieldScene(const std::string& name, EngineSettings& sett
physicsWorld->setEventListener(this);
mPhysicsWorld = physicsWorld;
for (int i = 0; i<NB_COMPOUND_SHAPES; i++) {
for (int i = 0; i<NB_COMPOUND_SHAPES; i++) {
// Create a convex mesh and a corresponding rigid in the physics world
Dumbbell* dumbbell = new Dumbbell(true, mPhysicsCommon, mPhysicsWorld, meshFolderPath);

View File

@ -309,7 +309,8 @@ void RaycastScene::renderSinglePass(openglframework::Shader& shader, const openg
// Set the vertex color
openglframework::Vector4 color(1, 0.55f, 0, 1);
mColorShader.setVector4Uniform("vertexColor", color, false);
mColorShader.setIntUniform("isGlobalVertexColorEnabled", 1, false);
mColorShader.setVector4Uniform("globalVertexColor", color, false);
// Get the location of shader attribute variables
GLint vertexPositionLoc = mColorShader.getAttribLocation("vertexPosition");

View File

@ -26,13 +26,22 @@
********************************************************************************/
// Uniform variables
uniform vec4 vertexColor; // Vertex color
uniform bool isGlobalVertexColorEnabled; // True if we need to use the global vertex color
uniform vec4 globalVertexColor; // Vertex color
// Out variable
// In variables
in vec4 vertexColorOut;
// Out variables
out vec4 color; // Output color
void main() {
// Compute the final color
color = vertexColor;
if (isGlobalVertexColorEnabled) {
color = globalVertexColor;
}
else {
color = vertexColorOut;
}
}

View File

@ -32,6 +32,10 @@ uniform mat4 projectionMatrix; // Projection matrix
// In variables
in vec4 vertexPosition;
in uint vertexColor;
// Out variables
out vec4 vertexColorOut;
void main() {
@ -40,4 +44,7 @@ void main() {
// Compute the clip-space vertex coordinates
gl_Position = projectionMatrix * positionCameraSpace;
// Transfer the vertex color to the fragment shader
vertexColorOut = vec4((vertexColor & 0xFF0000u) >> 16, (vertexColor & 0x00FF00u) >> 8, vertexColor & 0x0000FFu, 0xFF);
}

View File

@ -38,7 +38,7 @@ uniform sampler2D shadowMapSampler0; // Shadow map texture sampler
uniform sampler2D shadowMapSampler1; // Shadow map texture sampler
uniform sampler2D shadowMapSampler2; // Shadow map texture sampler
uniform bool isTexture; // True if we need to use the texture
uniform vec4 vertexColor; // Vertex color
uniform vec4 globalVertexColor; // Vertex color
uniform bool isShadowEnabled; // True if shadow mapping is enabled
uniform vec2 shadowMapDimension; // Shadow map dimension
@ -64,7 +64,7 @@ void main() {
vec3 ambient = lightAmbientColor;
// Get the texture color
vec3 textureColor = vertexColor.rgb;
vec3 textureColor = globalVertexColor.rgb;
if (isTexture) textureColor = texture(textureSampler, texCoords).rgb;
// Compute the surface normal vector

View File

@ -45,8 +45,8 @@ SceneDemo::SceneDemo(const std::string& name, EngineSettings& settings, bool isP
mPhongShader("shaders/phong.vert", "shaders/phong.frag"),
mColorShader("shaders/color.vert", "shaders/color.frag"),
mQuadShader("shaders/quad.vert", "shaders/quad.frag"),
mVBOQuad(GL_ARRAY_BUFFER), mMeshFolderPath("meshes/"),
mPhysicsWorld(nullptr), mIsPhysicsWorldSimulated(isPhysicsWorldSimulated) {
mVBOQuad(GL_ARRAY_BUFFER), mDebugVBOLinesVertices(GL_ARRAY_BUFFER), mDebugVBOTrianglesVertices(GL_ARRAY_BUFFER),
mMeshFolderPath("meshes/"), mPhysicsWorld(nullptr), mIsPhysicsWorldSimulated(isPhysicsWorldSimulated) {
shadowMapTextureLevel++;
@ -91,6 +91,8 @@ SceneDemo::SceneDemo(const std::string& name, EngineSettings& settings, bool isP
createQuadVBO();
createDebugVBO();
// Init rendering for the AABBs
AABB::init();
@ -153,6 +155,9 @@ void SceneDemo::updatePhysics() {
// Render the scene (in multiple passes for shadow mapping)
void SceneDemo::render() {
// Update the VBO for the debug infos
updateDebugVBO();
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
@ -274,6 +279,11 @@ void SceneDemo::render() {
renderAABBs(worldToCameraMatrix);
}
// Render the debug infos
if (mPhysicsWorld->getIsDebugRenderingEnabled()) {
renderDebugInfos(mColorShader, worldToCameraMatrix);
}
// Is shadow mapping is enabled
if (mIsShadowMappingEnabled) {
@ -367,6 +377,44 @@ void SceneDemo::createQuadVBO() {
mVAOQuad.unbind();
}
// Create a the VAO and VBOs to render the debug infos
void SceneDemo::createDebugVBO() {
// ----- Lines ----- //
// Create the VBO for the vertices data
mDebugVBOLinesVertices.create();
// Create the VAO for both VBOs
mDebugLinesVAO.create();
mDebugLinesVAO.bind();
// Bind the VBO of vertices
mDebugVBOLinesVertices.bind();
// Unbind the VAO
mDebugLinesVAO.unbind();
mDebugVBOLinesVertices.unbind();
// ----- Triangles ----- //
// Create the VBO for the vertices data
mDebugVBOTrianglesVertices.create();
// Create the VAO for both VBOs
mDebugTrianglesVAO.create();
mDebugTrianglesVAO.bind();
// Bind the VBO of vertices
mDebugVBOTrianglesVertices.bind();
// Unbind the VAO
mDebugTrianglesVAO.unbind();
mDebugVBOTrianglesVertices.unbind();
}
void SceneDemo::drawTextureQuad() {
glViewport(mViewportX, mViewportY, mViewportWidth, mViewportHeight);
@ -437,6 +485,127 @@ void SceneDemo::renderContactPoints(openglframework::Shader& shader, const openg
}
}
// Update VBO with vertices and indices of debug info
void SceneDemo::updateDebugVBO() {
rp3d::DebugRenderer& debugRenderer = mPhysicsWorld->getDebugRenderer();
if (mPhysicsWorld->getIsDebugRenderingEnabled()) {
// ----- Lines ---- //
const uint nbLines = debugRenderer.getNbLines();
if (nbLines > 0) {
// Vertices
mDebugVBOLinesVertices.bind();
GLsizei sizeVertices = static_cast<GLsizei>(nbLines * sizeof(rp3d::DebugRenderer::DebugLine));
mDebugVBOLinesVertices.copyDataIntoVBO(sizeVertices, debugRenderer.getLinesArray(), GL_STREAM_DRAW);
mDebugVBOLinesVertices.unbind();
}
// ----- Triangles ---- //
const uint nbTriangles = debugRenderer.getNbTriangles();
if (nbTriangles > 0) {
// Vertices
mDebugVBOTrianglesVertices.bind();
GLsizei sizeVertices = static_cast<GLsizei>(nbTriangles * sizeof(rp3d::DebugRenderer::DebugTriangle));
mDebugVBOTrianglesVertices.copyDataIntoVBO(sizeVertices, debugRenderer.getTrianglesArray(), GL_STREAM_DRAW);
mDebugVBOTrianglesVertices.unbind();
}
}
}
// Render Debug Infos
void SceneDemo::renderDebugInfos(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix) {
rp3d::DebugRenderer& debugRenderer = mPhysicsWorld->getDebugRenderer();
// Render in wireframe mode
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// Bind the shader
shader.bind();
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
// model-view matrix)
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix;
const openglframework::Matrix3 normalMatrix = localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
// Set the model to camera matrix
shader.setMatrix4x4Uniform("localToWorldMatrix", openglframework::Matrix4::identity());
shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
shader.setIntUniform("isGlobalVertexColorEnabled", 0, false);
// Get the location of shader attribute variables
GLint vertexPositionLoc = shader.getAttribLocation("vertexPosition");
GLint vertexColorLoc = shader.getAttribLocation("vertexColor");
// Lines
if (debugRenderer.getNbLines() > 0) {
// Bind the VAO
mDebugLinesVAO.bind();
mDebugVBOLinesVertices.bind();
glEnableVertexAttribArray(vertexPositionLoc);
glVertexAttribPointer(vertexPositionLoc, 3, GL_FLOAT, GL_FALSE, sizeof(rp3d::Vector3) + sizeof(rp3d::uint32), (char*)nullptr);
glEnableVertexAttribArray(vertexColorLoc);
glVertexAttribIPointer(vertexColorLoc, 3, GL_UNSIGNED_INT, sizeof(rp3d::Vector3) + sizeof(rp3d::uint32), (void*)sizeof(rp3d::Vector3));
// Draw the lines geometry
glDrawArrays(GL_LINES, 0, debugRenderer.getNbLines() * 2);
glDisableVertexAttribArray(vertexPositionLoc);
glDisableVertexAttribArray(vertexColorLoc);
mDebugVBOLinesVertices.unbind();
// Unbind the VAO
mDebugLinesVAO.unbind();
}
// Triangles
if (debugRenderer.getNbTriangles() > 0) {
// Bind the VAO
mDebugTrianglesVAO.bind();
mDebugVBOTrianglesVertices.bind();
glEnableVertexAttribArray(vertexPositionLoc);
glVertexAttribPointer(vertexPositionLoc, 3, GL_FLOAT, GL_FALSE, sizeof(rp3d::Vector3) + sizeof(rp3d::uint32), (char*)nullptr);
glEnableVertexAttribArray(vertexColorLoc);
glVertexAttribIPointer(vertexColorLoc, 3, GL_UNSIGNED_INT, sizeof(rp3d::Vector3) + sizeof(rp3d::uint32), (void*)sizeof(rp3d::Vector3));
// Draw the triangles geometry
glDrawArrays(GL_TRIANGLES, 0, debugRenderer.getNbTriangles() * 3);
glDisableVertexAttribArray(vertexPositionLoc);
glDisableVertexAttribArray(vertexColorLoc);
mDebugVBOTrianglesVertices.unbind();
// Unbind the VAO
mDebugTrianglesVAO.unbind();
}
// Unbind the shader
shader.unbind();
// Disable wireframe mode
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
// Render the AABBs
void SceneDemo::renderAABBs(const openglframework::Matrix4& worldToCameraMatrix) {

View File

@ -95,6 +95,18 @@ class SceneDemo : public Scene {
openglframework::VertexBufferObject mVBOQuad;
/// Vertex Buffer Object for the debug info lines vertices data
openglframework::VertexBufferObject mDebugVBOLinesVertices;
/// Vertex Array Object for the lines vertex data
openglframework::VertexArrayObject mDebugLinesVAO;
/// Vertex Buffer Object for the debug info trinangles vertices data
openglframework::VertexBufferObject mDebugVBOTrianglesVertices;
/// Vertex Array Object for the triangles vertex data
openglframework::VertexArrayObject mDebugTrianglesVAO;
static openglframework::Color mObjectColorDemo;
static openglframework::Color mFloorColorDemo;
static openglframework::Color mSleepingColorDemo;
@ -113,22 +125,31 @@ class SceneDemo : public Scene {
// -------------------- Methods -------------------- //
// Create the Shadow map FBO and texture
/// Create the Shadow map FBO and texture
void createShadowMapFBOAndTexture();
// Used for debugging shadow maps
/// Used for debugging shadow maps
void createQuadVBO();
// TODO : Delete this
/// Create a the VAO and VBOs to render the debug infos
void createDebugVBO();
/// TODO : Delete this
void drawTextureQuad();
// Update the contact points
/// Update the contact points
void updateContactPoints();
// Render the contact points
/// Render the contact points
void renderContactPoints(openglframework::Shader& shader,
const openglframework::Matrix4& worldToCameraMatrix);
/// Update VBO with vertices and indices of debug info
void updateDebugVBO();
/// Render Debug Infos
void renderDebugInfos(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix);
/// Render the AABBs
void renderAABBs(const openglframework::Matrix4& worldToCameraMatrix);