Refactor profiler and add logger

This commit is contained in:
Daniel Chappuis 2018-03-15 23:11:26 +01:00
parent 393bb0ed88
commit 2e28b5ad8f
21 changed files with 277 additions and 77 deletions

View File

@ -31,6 +31,7 @@
#include <cfloat>
#include <utility>
#include <cstdint>
#include <string>
#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);

View File

@ -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<uint>(Logger::Level::Info) | static_cast<uint>(Logger::Level::Warning) |
static_cast<uint>(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<uint>(Logger::Level::Info) | static_cast<uint>(Logger::Level::Warning) |
static_cast<uint>(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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
/// 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 << "<html>" << std::endl;
ss << "<head>" << std::endl;
ss << "<title>ReactPhysics3D Logs</title>" << std::endl;
ss << "<style>" << generateCSS() << "</style>" << std::endl;
ss << "</head>" << std::endl;
ss << "<body>" << 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 << "<p>";
ss << "<div class='line " + toLowerCase(getCategoryName(category)) + " " + toLowerCase(getLevelName(level)) + "'>";
// Time
ss << "<div class='time'>";
ss << std::put_time(std::localtime(&time), "%X");
ss << "</div>";
// Level
ss << "<div class='level'>";
ss << getLevelName(level);
ss << "</div>";
// Category
ss << "<div class='category'>";
ss << getCategoryName(category);
ss << "</div>";
// Message
ss << "<div class='message'>";
ss << message;
ss << "</p>";
ss << "</div>";
ss << "</div>";
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

View File

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

View File

@ -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; i<NB_COMPOUND_SHAPES; i++) {

View File

@ -45,8 +45,11 @@ ConcaveMeshScene::ConcaveMeshScene(const std::string& name, EngineSettings& sett
// Gravity vector in the dynamics world
rp3d::Vector3 gravity(0, rp3d::decimal(-9.81), 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);
// ---------- Create the boxes ----------- //
for (int i = 0; i<NB_COMPOUND_SHAPES; i++) {

View File

@ -43,8 +43,11 @@ CubesScene::CubesScene(const std::string& name, EngineSettings& settings)
// Gravity vector in the dynamics world
rp3d::Vector3 gravity(0, rp3d::decimal(-9.81), 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);
// Create all the cubes of the scene
for (int i=0; i<NB_CUBES; i++) {

View File

@ -43,8 +43,11 @@ CubeStackScene::CubeStackScene(const std::string& name, EngineSettings& settings
// Gravity vector in the dynamics world
rp3d::Vector3 gravity(0, rp3d::decimal(-9.81), 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);
// Create all the cubes of the scene
for (int i=1; i<=NB_FLOORS; i++) {

View File

@ -45,8 +45,11 @@ HeightFieldScene::HeightFieldScene(const std::string& name, EngineSettings& sett
// Gravity vector in the dynamics world
rp3d::Vector3 gravity(0, rp3d::decimal(-9.81), 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; i<NB_COMPOUND_SHAPES; i++) {

View File

@ -44,8 +44,11 @@ JointsScene::JointsScene(const std::string& name, EngineSettings& settings)
// Gravity vector in the dynamics world
rp3d::Vector3 gravity(0, rp3d::decimal(-9.81), 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);
// Create the Ball-and-Socket joint
createBallAndSocketJoints();

View File

@ -44,8 +44,11 @@ RaycastScene::RaycastScene(const std::string& name, EngineSettings& settings)
// 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);
// ---------- Dumbbell ---------- //

View File

@ -170,6 +170,7 @@ void Gui::createSettingsPanel() {
checkboxSleeping->setChecked(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 (...) {

View File

@ -232,6 +232,9 @@ class Scene {
/// Return all the contact points of the scene
std::vector<ContactPoint> virtual getContactPoints();
/// Update the engine settings
virtual void updateEngineSettings() = 0;
};
// Called when a keyboard event occurs

View File

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

View File

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

View File

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

View File

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