From 2e28b5ad8fb18c637094d11ece969f69367ce89a Mon Sep 17 00:00:00 2001 From: Daniel Chappuis Date: Thu, 15 Mar 2018 23:11:26 +0100 Subject: [PATCH] Refactor profiler and add logger --- src/configuration.h | 4 + src/engine/CollisionWorld.cpp | 53 +++++-- src/engine/CollisionWorld.h | 25 ++-- src/engine/DynamicsWorld.cpp | 37 ++--- src/engine/DynamicsWorld.h | 4 +- src/utils/Logger.cpp | 6 +- src/utils/Logger.h | 130 +++++++++++++++--- .../CollisionDetectionScene.cpp | 5 +- .../collisionshapes/CollisionShapesScene.cpp | 5 +- .../scenes/concavemesh/ConcaveMeshScene.cpp | 5 +- testbed/scenes/cubes/CubesScene.cpp | 5 +- testbed/scenes/cubestack/CubeStackScene.cpp | 5 +- .../scenes/heightfield/HeightFieldScene.cpp | 5 +- testbed/scenes/joints/JointsScene.cpp | 5 +- testbed/scenes/raycast/RaycastScene.cpp | 5 +- testbed/src/Gui.cpp | 8 ++ testbed/src/Scene.h | 3 + testbed/src/SceneDemo.cpp | 31 +++-- testbed/src/SceneDemo.h | 3 + testbed/src/TestbedApplication.cpp | 7 + testbed/src/TestbedApplication.h | 3 + 21 files changed, 277 insertions(+), 77 deletions(-) diff --git a/src/configuration.h b/src/configuration.h index 539f66b9..aa71e88a 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -31,6 +31,7 @@ #include #include #include +#include #include "decimal.h" #include "containers/Pair.h" @@ -110,6 +111,9 @@ constexpr decimal DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER = decimal(1.7); */ struct WorldSettings { + /// Name of the world + std::string worldName = ""; + /// Distance threshold for two contact points for a valid persistent contact (in meters) decimal persistentContactDistanceThreshold = decimal(0.03); diff --git a/src/engine/CollisionWorld.cpp b/src/engine/CollisionWorld.cpp index 7fb223e2..1dbf1b6f 100644 --- a/src/engine/CollisionWorld.cpp +++ b/src/engine/CollisionWorld.cpp @@ -36,9 +36,11 @@ using namespace std; uint CollisionWorld::mNbWorlds = 0; // Constructor -CollisionWorld::CollisionWorld(const string& name, const WorldSettings& worldSettings) +CollisionWorld::CollisionWorld(const WorldSettings& worldSettings, Logger* logger, Profiler* profiler) : mConfig(worldSettings), mCollisionDetection(this, mMemoryManager), mBodies(mMemoryManager.getPoolAllocator()), mCurrentBodyId(0), - mFreeBodiesIds(mMemoryManager.getPoolAllocator()), mEventListener(nullptr), mName(name) { + mFreeBodiesIds(mMemoryManager.getPoolAllocator()), mEventListener(nullptr), mName(worldSettings.worldName), + mProfiler(profiler), mLogger(logger), mIsProfilerCreatedByUser(profiler != nullptr), + mIsLoggerCreatedByUser(logger != nullptr) { // Automatically generate a name for the world if (mName == "") { @@ -55,20 +57,33 @@ CollisionWorld::CollisionWorld(const string& name, const WorldSettings& worldSet #ifdef IS_PROFILING_ACTIVE - // Add a destination file for the profiling data - mProfiler.addFileDestination("rp3d_profiling_" + mName + ".txt", Profiler::Format::Text); + // If the user has not provided its own profiler, we create one + if (mProfiler == nullptr) { + + mProfiler = new Profiler(); + + // Add a destination file for the profiling data + mProfiler->addFileDestination("rp3d_profiling_" + mName + ".txt", Profiler::Format::Text); + } + // Set the profiler - mCollisionDetection.setProfiler(&mProfiler); + mCollisionDetection.setProfiler(mProfiler); #endif #ifdef IS_LOGGING_ACTIVE - // Add a log destination file - uint logLevel = static_cast(Logger::Level::Info) | static_cast(Logger::Level::Warning) | - static_cast(Logger::Level::Error); - mLogger.addFileDestination("rp3d_log_" + mName + ".html", logLevel, Logger::Format::HTML); + // If the user has not provided its own logger, we create one + if (mLogger == nullptr) { + + mLogger = new Logger(); + + // Add a log destination file + uint logLevel = static_cast(Logger::Level::Info) | static_cast(Logger::Level::Warning) | + static_cast(Logger::Level::Error); + mLogger->addFileDestination("rp3d_log_" + mName + ".html", logLevel, Logger::Format::HTML); + } #endif @@ -89,6 +104,24 @@ CollisionWorld::~CollisionWorld() { destroyCollisionBody(mBodies[i]); } +#ifdef IS_PROFILING_ACTIVE + + /// Delete the profiler + if (!mIsProfilerCreatedByUser) { + delete mProfiler; + } + +#endif + +#ifdef IS_LOGGING_ACTIVE + + /// Delete the logger + if (!mIsLoggerCreatedByUser) { + delete mLogger; + } + +#endif + assert(mBodies.size() == 0); } @@ -117,7 +150,7 @@ CollisionBody* CollisionWorld::createCollisionBody(const Transform& transform) { #ifdef IS_PROFILING_ACTIVE - collisionBody->setProfiler(&mProfiler); + collisionBody->setProfiler(mProfiler); #endif diff --git a/src/engine/CollisionWorld.h b/src/engine/CollisionWorld.h index f85d2fc6..ad3549fe 100644 --- a/src/engine/CollisionWorld.h +++ b/src/engine/CollisionWorld.h @@ -87,15 +87,21 @@ class CollisionWorld { #ifdef IS_PROFILING_ACTIVE /// Real-time hierarchical profiler - Profiler mProfiler; + Profiler* mProfiler; #endif #ifdef IS_LOGGING_ACTIVE /// Logger - Logger mLogger; + Logger* mLogger; #endif + /// True if the profiler has been created by the user + bool mIsProfilerCreatedByUser; + + /// True if the logger has been created by the user + bool mIsLoggerCreatedByUser; + /// Total number of worlds static uint mNbWorlds; @@ -112,7 +118,8 @@ class CollisionWorld { // -------------------- Methods -------------------- // /// Constructor - CollisionWorld(const std::string& name = "", const WorldSettings& worldSettings = WorldSettings()); + CollisionWorld(const WorldSettings& worldSettings = WorldSettings(), Logger* logger = nullptr, + Profiler* profiler = nullptr); /// Destructor virtual ~CollisionWorld(); @@ -161,14 +168,14 @@ class CollisionWorld { #ifdef IS_PROFILING_ACTIVE /// Return a reference to the profiler - Profiler& getProfiler(); + Profiler* getProfiler(); #endif #ifdef IS_LOGGING_ACTIVE /// Return a reference to the logger - Logger& getLogger(); + Logger* getLogger(); #endif @@ -255,8 +262,8 @@ inline const std::string& CollisionWorld::getName() const { #ifdef IS_PROFILING_ACTIVE -// Return a reference to the profiler -inline Profiler& CollisionWorld::getProfiler() { +// Return a pointer to the profiler +inline Profiler* CollisionWorld::getProfiler() { return mProfiler; } @@ -264,8 +271,8 @@ inline Profiler& CollisionWorld::getProfiler() { #ifdef IS_LOGGING_ACTIVE -// Return a reference to the logger -inline Logger& CollisionWorld::getLogger() { +// Return a pointer to the logger +inline Logger* CollisionWorld::getLogger() { return mLogger; } diff --git a/src/engine/DynamicsWorld.cpp b/src/engine/DynamicsWorld.cpp index f8ac6033..7164458d 100644 --- a/src/engine/DynamicsWorld.cpp +++ b/src/engine/DynamicsWorld.cpp @@ -39,8 +39,9 @@ using namespace std; /** * @param gravity Gravity vector in the world (in meters per second squared) */ -DynamicsWorld::DynamicsWorld(const Vector3& gravity, const string& name, const WorldSettings& worldSettings) - : CollisionWorld(name, worldSettings), +DynamicsWorld::DynamicsWorld(const Vector3& gravity, const WorldSettings& worldSettings, + Logger* logger, Profiler* profiler) + : CollisionWorld(worldSettings, logger, profiler), mContactSolver(mMemoryManager, mConfig), mNbVelocitySolverIterations(mConfig.defaultVelocitySolverNbIterations), mNbPositionSolverIterations(mConfig.defaultPositionSolverNbIterations), @@ -58,13 +59,13 @@ DynamicsWorld::DynamicsWorld(const Vector3& gravity, const string& name, const W #ifdef IS_PROFILING_ACTIVE // Set the profiler - mConstraintSolver.setProfiler(&mProfiler); - mContactSolver.setProfiler(&mProfiler); + mConstraintSolver.setProfiler(mProfiler); + mContactSolver.setProfiler(mProfiler); #endif RP3D_LOG(mLogger, Logger::Level::Info, Logger::Category::World, - "Dynamics world " + mName + " has been created"); + "Dynamics World: Dynamics world " + mName + " has been created"); } @@ -87,11 +88,11 @@ DynamicsWorld::~DynamicsWorld() { #ifdef IS_PROFILING_ACTIVE // Print the profiling report into the destinations - mProfiler.printReport(); + mProfiler->printReport(); #endif RP3D_LOG(mLogger, Logger::Level::Info, Logger::Category::World, - "Dynamics world " + mName + " has been destroyed"); + "Dynamics World: Dynamics world " + mName + " has been destroyed"); } // Update the physics simulation @@ -102,10 +103,10 @@ void DynamicsWorld::update(decimal timeStep) { #ifdef IS_PROFILING_ACTIVE // Increment the frame counter of the profiler - mProfiler.incrementFrameCounter(); + mProfiler->incrementFrameCounter(); #endif - RP3D_PROFILE("DynamicsWorld::update()", &mProfiler); + RP3D_PROFILE("DynamicsWorld::update()", mProfiler); mTimeStep = timeStep; @@ -153,7 +154,7 @@ void DynamicsWorld::update(decimal timeStep) { /// the sympletic Euler time stepping scheme. void DynamicsWorld::integrateRigidBodiesPositions() { - RP3D_PROFILE("DynamicsWorld::integrateRigidBodiesPositions()", &mProfiler); + RP3D_PROFILE("DynamicsWorld::integrateRigidBodiesPositions()", mProfiler); // For each island of the world for (uint i=0; i < mNbIslands; i++) { @@ -192,7 +193,7 @@ void DynamicsWorld::integrateRigidBodiesPositions() { // Update the postion/orientation of the bodies void DynamicsWorld::updateBodiesState() { - RP3D_PROFILE("DynamicsWorld::updateBodiesState()", &mProfiler); + RP3D_PROFILE("DynamicsWorld::updateBodiesState()", mProfiler); // For each island of the world for (uint islandIndex = 0; islandIndex < mNbIslands; islandIndex++) { @@ -229,7 +230,7 @@ void DynamicsWorld::updateBodiesState() { // Initialize the bodies velocities arrays for the next simulation step. void DynamicsWorld::initVelocityArrays() { - RP3D_PROFILE("DynamicsWorld::initVelocityArrays()", &mProfiler); + RP3D_PROFILE("DynamicsWorld::initVelocityArrays()", mProfiler); // Allocate memory for the bodies velocity arrays uint nbBodies = mRigidBodies.size(); @@ -271,7 +272,7 @@ void DynamicsWorld::initVelocityArrays() { /// contact solver. void DynamicsWorld::integrateRigidBodiesVelocities() { - RP3D_PROFILE("DynamicsWorld::integrateRigidBodiesVelocities()", &mProfiler); + RP3D_PROFILE("DynamicsWorld::integrateRigidBodiesVelocities()", mProfiler); // Initialize the bodies velocity arrays initVelocityArrays(); @@ -333,7 +334,7 @@ void DynamicsWorld::integrateRigidBodiesVelocities() { // Solve the contacts and constraints void DynamicsWorld::solveContactsAndConstraints() { - RP3D_PROFILE("DynamicsWorld::solveContactsAndConstraints()", &mProfiler); + RP3D_PROFILE("DynamicsWorld::solveContactsAndConstraints()", mProfiler); // Set the velocities arrays mContactSolver.setSplitVelocitiesArrays(mSplitLinearVelocities, mSplitAngularVelocities); @@ -383,7 +384,7 @@ void DynamicsWorld::solveContactsAndConstraints() { // Solve the position error correction of the constraints void DynamicsWorld::solvePositionCorrection() { - RP3D_PROFILE("DynamicsWorld::solvePositionCorrection()", &mProfiler); + RP3D_PROFILE("DynamicsWorld::solvePositionCorrection()", mProfiler); // Do not continue if there is no constraints if (mJoints.size() == 0) return; @@ -426,7 +427,7 @@ RigidBody* DynamicsWorld::createRigidBody(const Transform& transform) { #ifdef IS_PROFILING_ACTIVE - rigidBody->setProfiler(&mProfiler); + rigidBody->setProfiler(mProfiler); #endif @@ -645,7 +646,7 @@ uint DynamicsWorld::computeNextAvailableJointId() { /// it). Then, we create an island with this group of connected bodies. void DynamicsWorld::computeIslands() { - RP3D_PROFILE("DynamicsWorld::computeIslands()", &mProfiler); + RP3D_PROFILE("DynamicsWorld::computeIslands()", mProfiler); uint nbBodies = mRigidBodies.size(); @@ -792,7 +793,7 @@ void DynamicsWorld::computeIslands() { /// time, we put all the bodies of the island to sleep. void DynamicsWorld::updateSleepingBodies() { - RP3D_PROFILE("DynamicsWorld::updateSleepingBodies()", &mProfiler); + RP3D_PROFILE("DynamicsWorld::updateSleepingBodies()", mProfiler); const decimal sleepLinearVelocitySquare = mSleepLinearVelocity * mSleepLinearVelocity; const decimal sleepAngularVelocitySquare = mSleepAngularVelocity * mSleepAngularVelocity; diff --git a/src/engine/DynamicsWorld.h b/src/engine/DynamicsWorld.h index f8016fdc..f435f4b9 100644 --- a/src/engine/DynamicsWorld.h +++ b/src/engine/DynamicsWorld.h @@ -162,8 +162,8 @@ class DynamicsWorld : public CollisionWorld { // -------------------- Methods -------------------- // /// Constructor - DynamicsWorld(const Vector3& mGravity, const std::string& name = "", - const WorldSettings& worldSettings = WorldSettings()); + DynamicsWorld(const Vector3& mGravity, const WorldSettings& worldSettings = WorldSettings(), + Logger* logger = nullptr, Profiler* profiler = nullptr); /// Destructor virtual ~DynamicsWorld() override; diff --git a/src/utils/Logger.cpp b/src/utils/Logger.cpp index 89634598..9410cc29 100644 --- a/src/utils/Logger.cpp +++ b/src/utils/Logger.cpp @@ -92,10 +92,14 @@ void Logger::removeAllDestinations() { // Log something void Logger::log(Level level, Category category, const std::string& message) { + // Get current time + auto now = std::chrono::system_clock::now(); + auto time = std::chrono::system_clock::to_time_t(now); + // For each destination for (auto it = mDestinations.begin(); it != mDestinations.end(); ++it) { - (*it)->write(message, level, category); + (*it)->write(time, message, level, category); } } diff --git a/src/utils/Logger.h b/src/utils/Logger.h index 9c6421db..908da806 100644 --- a/src/utils/Logger.h +++ b/src/utils/Logger.h @@ -26,7 +26,6 @@ #ifndef REACTPHYSICS3D_LOGGER_H #define REACTPHYSICS3D_LOGGER_H -#ifdef IS_LOGGING_ACTIVE // Libraries #include "containers/List.h" @@ -35,6 +34,7 @@ #include #include #include +#include /// ReactPhysics3D namespace namespace reactphysics3d { @@ -57,6 +57,26 @@ class Logger { /// Log verbosity level enum class Format {Text, HTML}; + /// Return the name of a category + static std::string getCategoryName(Category category) { + + switch(category) { + case Category::World: return "World"; + case Category::Body: return "Body"; + case Category::Joint: return "Joint"; + } + } + + /// Return the name of a level + static std::string getLevelName(Level level) { + + switch(level) { + case Level::Info: return "Information"; + case Level::Warning: return "Warning"; + case Level::Error: return "Error"; + } + } + /// Log formatter class Formatter { @@ -83,7 +103,7 @@ class Logger { } /// Format a log message - virtual std::string format(const std::string& message, Level level, Category category) = 0; + virtual std::string format(const time_t& time, const std::string& message, Level level, Category category) = 0; }; class TextFormatter : public Formatter { @@ -101,8 +121,8 @@ class Logger { } /// Format a log message - virtual std::string format(const std::string& message, Level level, - Category category) override { + virtual std::string format(const time_t& time, const std::string& message, + Level level, Category category) override { return message; } }; @@ -120,6 +140,7 @@ class Logger { ss << "" << std::endl; ss << "" << std::endl; ss << "ReactPhysics3D Logs" << std::endl; + ss << "" << std::endl; ss << "" << std::endl; ss << "" << std::endl; @@ -137,6 +158,60 @@ class Logger { return ss.str(); } + std::string generateCSS() const { + return "body {" + " background-color: #f7f7f9;" + "} " + "body > div { clear:both; } " + "body > div > div { float: left; } " + ".line { " + "font-family: SFMono-Regular,Menlo,Monaco,Consolas,'Liberation Mono','Courier New',monospace; " + "font-size: 13px; " + "color: #212529; " + "margin: 0px 5px 2px 5px; " + "} " + ".time { " + "margin-right: 10px; " + "width:100px; " + "} " + ".level { " + "margin-right: 10px; " + "width: 110px; " + "}" + ".category { " + "margin-right: 10px; " + "width: 120px; " + "font-weight: bold; " + "}" + ".message { " + "color: #2e2e2e; " + "word-wrap: break-word; " + "max-width: 800px; " + "} " + ".body > .category { " + "color: #007bff; " + "} " + ".world > .category { " + "color: #4f9fcf; " + "} " + ".joint > .category { " + "color: #6c757d; " + "} " + ".warning { " + "color: #f0ad4e; " + "} " + ".error { " + "color: #d44950; " + "} "; + } + + /// Convert a string to lower case + std::string toLowerCase(const std::string& text) { + std::string textLower = text; + std::transform(textLower.begin(), textLower.end(), textLower.begin(), ::tolower); + return textLower; + } + public: /// Constructor @@ -150,14 +225,34 @@ class Logger { } /// Format a log message - virtual std::string format(const std::string& message, Level level, - Category category) override { + virtual std::string format(const time_t& time, const std::string& message, + Level level, Category category) override { std::stringstream ss; - ss << "

"; + ss << "

"; + + // Time + ss << "
"; + ss << std::put_time(std::localtime(&time), "%X"); + ss << "
"; + + // Level + ss << "
"; + ss << getLevelName(level); + ss << "
"; + + // Category + ss << "
"; + ss << getCategoryName(category); + ss << "
"; + + // Message + ss << "
"; ss << message; - ss << "

"; + ss << "
"; + + ss << "
"; return ss.str(); } @@ -187,7 +282,7 @@ class Logger { } /// Write a message into the output stream - virtual void write(const std::string& message, Level level, Category category) = 0; + virtual void write(const time_t& time, const std::string& message, Level level, Category category) = 0; }; class FileDestination : public Destination { @@ -228,8 +323,8 @@ class Logger { } /// Write a message into the output stream - virtual void write(const std::string& message, Level level, Category category) override { - mFileStream << formatter->format(message, level, category) << std::endl; + virtual void write(const time_t& time, const std::string& message, Level level, Category category) override { + mFileStream << formatter->format(time, message, level, category) << std::endl << std::flush; } }; @@ -259,8 +354,9 @@ class Logger { } /// Write a message into the output stream - virtual void write(const std::string& message, Level level, Category category) override { - mOutputStream << message << std::endl; + virtual void write(const time_t& time, const std::string& message, Level level, Category category) override { + mOutputStream << std::put_time(std::localtime(&time), "%Y-%m-%d %X") << ": "; + mOutputStream << message << std::endl << std::flush; } }; @@ -303,12 +399,12 @@ class Logger { void log(Level level, Category category, const std::string& message); }; +} + +#ifdef IS_LOGGING_ACTIVE // Use this macro to log something -#define RP3D_LOG(logger, level, category, message) logger.log(level, category, message) - - -} +#define RP3D_LOG(logger, level, category, message) logger->log(level, category, message) #else // If logger is not active diff --git a/testbed/scenes/collisiondetection/CollisionDetectionScene.cpp b/testbed/scenes/collisiondetection/CollisionDetectionScene.cpp index 644b378f..3b4c7fc5 100755 --- a/testbed/scenes/collisiondetection/CollisionDetectionScene.cpp +++ b/testbed/scenes/collisiondetection/CollisionDetectionScene.cpp @@ -46,8 +46,11 @@ CollisionDetectionScene::CollisionDetectionScene(const std::string& name, Engine // Set the center of the scene setScenePosition(center, SCENE_RADIUS); + rp3d::WorldSettings worldSettings; + worldSettings.worldName = name; + // Create the dynamics world for the physics simulation - mPhysicsWorld = new rp3d::CollisionWorld(name); + mPhysicsWorld = new rp3d::CollisionWorld(worldSettings); // ---------- Sphere 1 ---------- // diff --git a/testbed/scenes/collisionshapes/CollisionShapesScene.cpp b/testbed/scenes/collisionshapes/CollisionShapesScene.cpp index e5fb3110..cffe7b50 100644 --- a/testbed/scenes/collisionshapes/CollisionShapesScene.cpp +++ b/testbed/scenes/collisionshapes/CollisionShapesScene.cpp @@ -45,8 +45,11 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name, EngineSettin // Gravity vector in the dynamics world rp3d::Vector3 gravity(0, -9.81f, 0); + rp3d::WorldSettings worldSettings; + worldSettings.worldName = name; + // Create the dynamics world for the physics simulation - mPhysicsWorld = new rp3d::DynamicsWorld(gravity, name); + mPhysicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings); for (int i=0; isetChecked(mApp->mEngineSettings.isSleepingEnabled); checkboxSleeping->setCallback([&](bool value) { mApp->mEngineSettings.isSleepingEnabled = value; + mApp->notifyEngineSetttingsChanged(); }); // Enabled/Disable Gravity @@ -177,6 +178,7 @@ void Gui::createSettingsPanel() { checkboxGravity->setChecked(mApp->mEngineSettings.isGravityEnabled); checkboxGravity->setCallback([&](bool value) { mApp->mEngineSettings.isGravityEnabled = value; + mApp->notifyEngineSetttingsChanged(); }); // Timestep @@ -202,6 +204,7 @@ void Gui::createSettingsPanel() { if (finalValue < 1 || finalValue > 1000) return false; mApp->mEngineSettings.timeStep = finalValue / 1000.0f; + mApp->notifyEngineSetttingsChanged(); textboxTimeStep->setValue(out.str()); } catch (...) { @@ -233,6 +236,7 @@ void Gui::createSettingsPanel() { if (value < 1 || value > 1000) return false; mApp->mEngineSettings.nbVelocitySolverIterations = value; + mApp->notifyEngineSetttingsChanged(); textboxVelocityIterations->setValue(out.str()); } catch (...) { @@ -264,6 +268,7 @@ void Gui::createSettingsPanel() { if (value < 1 || value > 1000) return false; mApp->mEngineSettings.nbPositionSolverIterations = value; + mApp->notifyEngineSetttingsChanged(); textboxPositionIterations->setValue(out.str()); } catch (...) { @@ -298,6 +303,7 @@ void Gui::createSettingsPanel() { if (finalValue < 1 || finalValue > 100000) return false; mApp->mEngineSettings.timeBeforeSleep = finalValue / 1000.0f; + mApp->notifyEngineSetttingsChanged(); textboxTimeSleep->setValue(out.str()); } catch (...) { @@ -332,6 +338,7 @@ void Gui::createSettingsPanel() { if (finalValue < 0 || finalValue > 10000) return false; mApp->mEngineSettings.sleepLinearVelocity = finalValue; + mApp->notifyEngineSetttingsChanged(); textboxSleepLinearVel->setValue(out.str()); } catch (...) { @@ -366,6 +373,7 @@ void Gui::createSettingsPanel() { if (finalValue < 0 || finalValue > 10000) return false; mApp->mEngineSettings.sleepAngularVelocity = finalValue; + mApp->notifyEngineSetttingsChanged(); textboxSleepAngularVel->setValue(out.str()); } catch (...) { diff --git a/testbed/src/Scene.h b/testbed/src/Scene.h index 5471379e..8fffff2a 100644 --- a/testbed/src/Scene.h +++ b/testbed/src/Scene.h @@ -232,6 +232,9 @@ class Scene { /// Return all the contact points of the scene std::vector virtual getContactPoints(); + + /// Update the engine settings + virtual void updateEngineSettings() = 0; }; // Called when a keyboard event occurs diff --git a/testbed/src/SceneDemo.cpp b/testbed/src/SceneDemo.cpp index 8e2a92da..e4f13d99 100644 --- a/testbed/src/SceneDemo.cpp +++ b/testbed/src/SceneDemo.cpp @@ -123,18 +123,6 @@ void SceneDemo::updatePhysics() { if (getDynamicsWorld() != nullptr) { - // Update the physics engine parameters - getDynamicsWorld()->setIsGratityEnabled(mEngineSettings.isGravityEnabled); - rp3d::Vector3 gravity(mEngineSettings.gravity.x, mEngineSettings.gravity.y, - mEngineSettings.gravity.z); - getDynamicsWorld()->setGravity(gravity); - getDynamicsWorld()->enableSleeping(mEngineSettings.isSleepingEnabled); - getDynamicsWorld()->setSleepLinearVelocity(mEngineSettings.sleepLinearVelocity); - getDynamicsWorld()->setSleepAngularVelocity(mEngineSettings.sleepAngularVelocity); - getDynamicsWorld()->setNbIterationsPositionSolver(mEngineSettings.nbPositionSolverIterations); - getDynamicsWorld()->setNbIterationsVelocitySolver(mEngineSettings.nbVelocitySolverIterations); - getDynamicsWorld()->setTimeBeforeSleep(mEngineSettings.timeBeforeSleep); - // Take a simulation step getDynamicsWorld()->update(mEngineSettings.timeStep); } @@ -448,3 +436,22 @@ std::vector SceneDemo::computeContactPointsOfWorld(rp3d::DynamicsW return contactPoints; } + +// Update the engine settings +void SceneDemo::updateEngineSettings() { + + if (getDynamicsWorld() != nullptr) { + + // Update the physics engine parameters + getDynamicsWorld()->setIsGratityEnabled(mEngineSettings.isGravityEnabled); + rp3d::Vector3 gravity(mEngineSettings.gravity.x, mEngineSettings.gravity.y, + mEngineSettings.gravity.z); + getDynamicsWorld()->setGravity(gravity); + getDynamicsWorld()->enableSleeping(mEngineSettings.isSleepingEnabled); + getDynamicsWorld()->setSleepLinearVelocity(mEngineSettings.sleepLinearVelocity); + getDynamicsWorld()->setSleepAngularVelocity(mEngineSettings.sleepAngularVelocity); + getDynamicsWorld()->setNbIterationsPositionSolver(mEngineSettings.nbPositionSolverIterations); + getDynamicsWorld()->setNbIterationsVelocitySolver(mEngineSettings.nbVelocitySolverIterations); + getDynamicsWorld()->setTimeBeforeSleep(mEngineSettings.timeBeforeSleep); + } +} diff --git a/testbed/src/SceneDemo.h b/testbed/src/SceneDemo.h index 1eaa30b9..95e1ece0 100644 --- a/testbed/src/SceneDemo.h +++ b/testbed/src/SceneDemo.h @@ -151,6 +151,9 @@ class SceneDemo : public Scene { /// Render the scene (possibly in multiple passes for shadow mapping) virtual void render() override; + /// Update the engine settings + virtual void updateEngineSettings() override; + /// Render the scene in a single pass virtual void renderSinglePass(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix); diff --git a/testbed/src/TestbedApplication.cpp b/testbed/src/TestbedApplication.cpp index 63230e0c..7240ad7e 100644 --- a/testbed/src/TestbedApplication.cpp +++ b/testbed/src/TestbedApplication.cpp @@ -271,9 +271,16 @@ void TestbedApplication::switchScene(Scene* newScene) { // Reset the scene mCurrentScene->reset(); + mCurrentScene->updateEngineSettings(); + resizeEvent(Vector2i(0, 0)); } +// Notify that the engine settings have changed +void TestbedApplication::notifyEngineSetttingsChanged() { + mCurrentScene->updateEngineSettings(); +} + // Check the OpenGL errors void TestbedApplication::checkOpenGLErrorsInternal(const char* file, int line) { GLenum glError; diff --git a/testbed/src/TestbedApplication.h b/testbed/src/TestbedApplication.h index 3a9fe071..26a04bdd 100644 --- a/testbed/src/TestbedApplication.h +++ b/testbed/src/TestbedApplication.h @@ -199,6 +199,9 @@ class TestbedApplication : public Screen { /// Enable/Disable Vertical synchronization void enableVSync(bool enable); + /// Notify that the engine settings have changed + void notifyEngineSetttingsChanged(); + // -------------------- Friendship -------------------- // friend class Gui;