diff --git a/testbed/CMakeLists.txt b/testbed/CMakeLists.txt index ff842cff..9f6ed161 100644 --- a/testbed/CMakeLists.txt +++ b/testbed/CMakeLists.txt @@ -43,6 +43,8 @@ SET(TESTBED_SOURCES src/SceneDemo.cpp src/Timer.h src/Timer.cpp + src/PhysicsEventListener.h + src/PhysicsEventListener.cpp ) # IMGUI source files diff --git a/testbed/common/Box.h b/testbed/common/Box.h index d5759bb1..90d4a203 100644 --- a/testbed/common/Box.h +++ b/testbed/common/Box.h @@ -30,19 +30,6 @@ #include "openglframework.h" #include "reactphysics3d.h" -// Structure VertexData -struct VertexData { - - /// Vertex position - openglframework::Vector3 position; - - /// Vertex normal - openglframework::Vector3 normal; - - // Vertex color - openglframework::Color color; -}; - // Class Box class Box : public openglframework::Object3D { diff --git a/testbed/scenes/collisionshapes/CollisionShapesScene.cpp b/testbed/scenes/collisionshapes/CollisionShapesScene.cpp index 1fc06b7e..baf7559d 100644 --- a/testbed/scenes/collisionshapes/CollisionShapesScene.cpp +++ b/testbed/scenes/collisionshapes/CollisionShapesScene.cpp @@ -202,6 +202,7 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name) // Create the floor openglframework::Vector3 floorPosition(0, 0, 0); mFloor = new Box(FLOOR_SIZE, floorPosition, FLOOR_MASS, mDynamicsWorld); + mFloor->setColor(Color(0.70f, 0.70f, 0.7f, 1.0f)); // The floor must be a static rigid body mFloor->getRigidBody()->setType(rp3d::STATIC); diff --git a/testbed/scenes/collisionshapes/CollisionShapesScene.h b/testbed/scenes/collisionshapes/CollisionShapesScene.h index a75528e7..0befba55 100644 --- a/testbed/scenes/collisionshapes/CollisionShapesScene.h +++ b/testbed/scenes/collisionshapes/CollisionShapesScene.h @@ -46,12 +46,12 @@ namespace collisionshapesscene { // Constants const float SCENE_RADIUS = 30.0f; const int NB_BOXES = 3; -const int NB_CUBES = 0; -const int NB_CONES = 0; -const int NB_CYLINDERS = 0; -const int NB_CAPSULES = 0; -const int NB_MESHES = 0; -const int NB_COMPOUND_SHAPES = 0; +const int NB_CUBES = 5; +const int NB_CONES = 3; +const int NB_CYLINDERS = 3; +const int NB_CAPSULES = 4; +const int NB_MESHES = 4; +const int NB_COMPOUND_SHAPES = 3; const openglframework::Vector3 BOX_SIZE(2, 2, 2); const float SPHERE_RADIUS = 1.5f; const float CONE_RADIUS = 2.0f; diff --git a/testbed/scenes/cubes/CubesScene.cpp b/testbed/scenes/cubes/CubesScene.cpp index 0215e6d3..1cd18ef3 100644 --- a/testbed/scenes/cubes/CubesScene.cpp +++ b/testbed/scenes/cubes/CubesScene.cpp @@ -77,6 +77,7 @@ CubesScene::CubesScene(const std::string& name) // Create the floor openglframework::Vector3 floorPosition(0, 0, 0); mFloor = new Box(FLOOR_SIZE, floorPosition, FLOOR_MASS, mDynamicsWorld); + mFloor->setColor(Color(0.70f, 0.70f, 0.7f, 1.0f)); // The floor must be a static rigid body mFloor->getRigidBody()->setType(rp3d::STATIC); @@ -202,3 +203,11 @@ void CubesScene::reset() { mBoxes[i]->resetTransform(transform); } } + +// Return all the contact points of the scene +std::vector CubesScene::getContactPoints() const { + + std::vector contactPoints; + + return contactPoints; +} diff --git a/testbed/scenes/cubes/CubesScene.h b/testbed/scenes/cubes/CubesScene.h index 02db7d4c..07d4c770 100644 --- a/testbed/scenes/cubes/CubesScene.h +++ b/testbed/scenes/cubes/CubesScene.h @@ -81,6 +81,9 @@ class CubesScene : public SceneDemo { /// Reset the scene virtual void reset(); + + /// Return all the contact points of the scene + std::vector virtual getContactPoints() const; }; } diff --git a/testbed/scenes/joints/JointsScene.cpp b/testbed/scenes/joints/JointsScene.cpp index 50d7deb1..be0ae28f 100644 --- a/testbed/scenes/joints/JointsScene.cpp +++ b/testbed/scenes/joints/JointsScene.cpp @@ -447,6 +447,7 @@ void JointsScene::createFloor() { // Create the floor openglframework::Vector3 floorPosition(0, 0, 0); mFloor = new Box(FLOOR_SIZE, floorPosition, FLOOR_MASS, mDynamicsWorld); + mFloor->setColor(Color(0.70f, 0.70f, 0.7f, 1.0f)); // The floor must be a static rigid body mFloor->getRigidBody()->setType(rp3d::STATIC); diff --git a/testbed/scenes/raycast/RaycastScene.cpp b/testbed/scenes/raycast/RaycastScene.cpp index 4e82fb6a..caa0b4ab 100644 --- a/testbed/scenes/raycast/RaycastScene.cpp +++ b/testbed/scenes/raycast/RaycastScene.cpp @@ -32,7 +32,7 @@ using namespace raycastscene; // Constructor RaycastScene::RaycastScene(const std::string& name) - : SceneDemo(name, SCENE_RADIUS), mCurrentBodyIndex(-1), mAreNormalsDisplayed(false), + : SceneDemo(name, SCENE_RADIUS, false), mCurrentBodyIndex(-1), mAreNormalsDisplayed(false), mMeshFolderPath("meshes/"), mRaycastManager(mPhongShader, mMeshFolderPath), mVBOVertices(GL_ARRAY_BUFFER) { diff --git a/testbed/scenes/raycast/RaycastScene.h b/testbed/scenes/raycast/RaycastScene.h index 9110a5bb..67e0f873 100644 --- a/testbed/scenes/raycast/RaycastScene.h +++ b/testbed/scenes/raycast/RaycastScene.h @@ -221,6 +221,9 @@ class RaycastScene : public SceneDemo { /// Called when a keyboard event occurs virtual void keyboardEvent(int key, int scancode, int action, int mods); + + /// Enabled/Disable the shadow mapping + void virtual setIsShadowMappingEnabled(bool isShadowMappingEnabled); }; // Display or not the surface normals at hit points @@ -228,6 +231,12 @@ inline void RaycastScene::showHideNormals() { mAreNormalsDisplayed = !mAreNormalsDisplayed; } +// Enabled/Disable the shadow mapping +inline void RaycastScene::setIsShadowMappingEnabled(bool isShadowMappingEnabled) { + + SceneDemo::setIsShadowMappingEnabled(false); +} + } #endif diff --git a/testbed/src/Gui.cpp b/testbed/src/Gui.cpp index 290bca0d..d45e0fce 100644 --- a/testbed/src/Gui.cpp +++ b/testbed/src/Gui.cpp @@ -26,6 +26,8 @@ // Libraries #include "Gui.h" #include +#include +#include #include "TestbedApplication.h" GLFWwindow* Gui::mWindow = NULL; @@ -42,6 +44,10 @@ openglframework::VertexArrayObject Gui::mVAO; Gui::LeftPane Gui::mLeftPane = SCENES; double Gui::mScrollX = 0.0; double Gui::mScrollY = 0.0; +double Gui::mTimeSinceLastProfilingDisplay = 0; +double Gui::mCachedFPS = 0; +double Gui::mCachedUpdateTime = 0; +double Gui::mCachedPhysicsUpdateTime = 0; // Constructor Gui::Gui() { @@ -80,47 +86,8 @@ void Gui::init() { fprintf(stderr, "Could not init GUI renderer.\n"); exit(EXIT_FAILURE); } -} -void Gui::displayHeader() { - - TestbedApplication& app = TestbedApplication::getInstance(); - - int windowWidth, windowHeight; - glfwGetWindowSize(mWindow, &windowWidth, &windowHeight); - - const int button_width = 150; - - int scrollarea = 0; - imguiBeginScrollArea(NULL, 0, app.mWindowToFramebufferRatio.y * (windowHeight - HEADER_HEIGHT), - app.mWindowToFramebufferRatio.x * windowWidth, - app.mWindowToFramebufferRatio.y * HEADER_HEIGHT, &scrollarea); - - imguiHorizontalSpace(10); - imguiVerticalSpace(20); - imguiStartLine(); - - // ----- Left Pane Header ----- // - - // Play/Pause - if (imguiButton(app.mTimer.isRunning() ? "Pause" : "Play", true, button_width)) { - app.togglePlayPauseSimulation(); - } - imguiHorizontalSpace(5); - - // Step - if (imguiButton("Step", !app.mTimer.isRunning(), button_width)) { - app.toggleTakeSinglePhysicsStep(); - } - imguiHorizontalSpace(5); - - // Restart - if (imguiButton("Restart", true, button_width)) { - app.restartSimulation(); - } - - imguiEndLine(); - imguiEndScrollArea(); + mTimeSinceLastProfilingDisplay = glfwGetTime(); } void Gui::displayLeftPane() { @@ -131,7 +98,7 @@ void Gui::displayLeftPane() { glfwGetWindowSize(mWindow, &windowWidth, &windowHeight); int scrollarea = 0; - imguiBeginScrollArea(NULL, 0, app.mWindowToFramebufferRatio.y * (windowHeight - HEADER_HEIGHT - LEFT_PANE_HEADER_HEIGHT), + imguiBeginScrollArea(NULL, 0, app.mWindowToFramebufferRatio.y * (windowHeight - LEFT_PANE_HEADER_HEIGHT), app.mWindowToFramebufferRatio.x * LEFT_PANE_WIDTH, app.mWindowToFramebufferRatio.y * LEFT_PANE_HEADER_HEIGHT, &scrollarea); @@ -161,6 +128,7 @@ void Gui::displayLeftPane() { } imguiEndLine(); + imguiVerticalSpace(70); imguiSeparatorLine(); imguiVerticalSpace(5); @@ -179,10 +147,14 @@ void Gui::displayLeftPane() { } imguiHorizontalSpace(5); - imguiButton("Rendering", true, widthButton); + if (imguiButton("Rendering", true, widthButton)) { + mLeftPane = RENDERING; + } imguiHorizontalSpace(5); - imguiButton("Profiling", true, widthButton); + if (imguiButton("Profiling", true, widthButton)) { + mLeftPane = PROFILING; + } imguiEndLine(); imguiVerticalSpace(BUTTON_HEIGHT + 8); @@ -213,7 +185,7 @@ void Gui::displayScenesPane() { imguiBeginScrollArea("Scenes", 0, 0, app.mWindowToFramebufferRatio.x * LEFT_PANE_WIDTH, - app.mWindowToFramebufferRatio.y * (windowHeight - HEADER_HEIGHT - LEFT_PANE_HEADER_HEIGHT), + app.mWindowToFramebufferRatio.y * (windowHeight - LEFT_PANE_HEADER_HEIGHT), &scrollarea); imguiVerticalSpace(15); @@ -243,7 +215,7 @@ void Gui::displayPhysicsPane() { int scrollarea = 2; imguiBeginScrollArea("Physics Engine Parameters", 0, 0, app.mWindowToFramebufferRatio.x * LEFT_PANE_WIDTH, - app.mWindowToFramebufferRatio.y * (windowHeight - HEADER_HEIGHT - LEFT_PANE_HEADER_HEIGHT), + app.mWindowToFramebufferRatio.y * (windowHeight - LEFT_PANE_HEADER_HEIGHT), &scrollarea); imguiVerticalSpace(15); @@ -314,10 +286,77 @@ void Gui::displayPhysicsPane() { void Gui::displayRenderingPane() { + TestbedApplication& app = TestbedApplication::getInstance(); + + int windowWidth, windowHeight; + glfwGetWindowSize(mWindow, &windowWidth, &windowHeight); + + int scrollarea = 2; + imguiBeginScrollArea("Rendering Parameters", 0, 0, + app.mWindowToFramebufferRatio.x * LEFT_PANE_WIDTH, + app.mWindowToFramebufferRatio.y * (windowHeight - LEFT_PANE_HEADER_HEIGHT), + &scrollarea); + + imguiVerticalSpace(15); + + // Enabled/Disable VSync + bool toggleVSync = imguiCheck("V Sync", app.mIsVSyncEnabled); + if (toggleVSync) { + app.enableVSync(!app.mIsVSyncEnabled); + } + + // Enabled/Disable Shadows + bool toggleShadows = imguiCheck("Shadows", app.mIsShadowMappingEnabled); + if (toggleShadows) { + app.enableShadows(!app.mIsShadowMappingEnabled); + } + + imguiEndScrollArea(); } void Gui::displayProfilingPane() { + TestbedApplication& app = TestbedApplication::getInstance(); + + double currentTime = glfwGetTime(); + if ((currentTime - mTimeSinceLastProfilingDisplay) > TIME_INTERVAL_DISPLAY_PROFILING_INFO) { + mTimeSinceLastProfilingDisplay = currentTime; + mCachedFPS = app.mFPS; + mCachedUpdateTime = app.mUpdateTime; + mCachedPhysicsUpdateTime = app.mPhysicsUpdateTime; + } + + int windowWidth, windowHeight; + glfwGetWindowSize(mWindow, &windowWidth, &windowHeight); + + int scrollarea = 2; + imguiBeginScrollArea("Profiling", 0, 0, + app.mWindowToFramebufferRatio.x * LEFT_PANE_WIDTH, + app.mWindowToFramebufferRatio.y * (windowHeight - LEFT_PANE_HEADER_HEIGHT), + &scrollarea); + + imguiVerticalSpace(15); + + // Framerate (FPS) + std::stringstream ss; + ss << std::setprecision(4) << mCachedFPS; + std::string fps = std::string("FPS : ") + ss.str(); + imguiItem(fps.c_str()); + + // Update time + std::stringstream ss1; + double updateTime = mCachedUpdateTime * 1000.0; + ss1 << std::setprecision(4) << updateTime; + std::string updateTimeStr = std::string("Update time (ms) : ") + ss1.str(); + imguiItem(updateTimeStr.c_str()); + + // Update time (physics) + std::stringstream ss2; + ss2 << std::setprecision(4) << (mCachedPhysicsUpdateTime * 1000.0); + std::string updatePhysicsTimeStr = std::string("Update physics time (ms) : ") + ss2.str(); + imguiItem(updatePhysicsTimeStr.c_str()); + + imguiEndScrollArea(); } // Display the GUI diff --git a/testbed/src/Gui.h b/testbed/src/Gui.h index 0b2183a7..52354eb1 100644 --- a/testbed/src/Gui.h +++ b/testbed/src/Gui.h @@ -35,9 +35,9 @@ // Constants const float GUI_SCALING = 2.0f; -const int HEADER_HEIGHT = 80; const int LEFT_PANE_WIDTH = 300; -const int LEFT_PANE_HEADER_HEIGHT = 50; +const int LEFT_PANE_HEADER_HEIGHT = 90; +const double TIME_INTERVAL_DISPLAY_PROFILING_INFO = 1.0; using namespace openglframework; @@ -64,7 +64,6 @@ class Gui { static bool g_MousePressed[3]; static float g_MouseWheel; static GLuint g_FontTexture; - //static int g_ShaderHandle, g_VertHandle, g_FragHandle; static int g_AttribLocationTex, g_AttribLocationProjMtx; static int g_AttribLocationPosition, g_AttribLocationUV, g_AttribLocationColor; static size_t g_VboSize; @@ -76,7 +75,6 @@ class Gui { // -------------------- Methods -------------------- // - static void displayHeader(); static void displayLeftPane(); /// Display the list of scenes @@ -88,6 +86,18 @@ class Gui { static void resetScroll(); + /// Current time (in seconds) from last profiling time display + static double mTimeSinceLastProfilingDisplay; + + /// Cached Framerate + static double mCachedFPS; + + /// Cached update time + static double mCachedUpdateTime; + + // Cached update physics time + static double mCachedPhysicsUpdateTime; + public : diff --git a/testbed/src/PhysicsEventListener.cpp b/testbed/src/PhysicsEventListener.cpp new file mode 100644 index 00000000..8d34b9b0 --- /dev/null +++ b/testbed/src/PhysicsEventListener.cpp @@ -0,0 +1,38 @@ + +/******************************************************************************** +* ReactPhysics3D physics library, http://www.reactphysics3d.com * +* Copyright (c) 2010-2015 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 "PhysicsEventListener.h" + +// Called when a new contact point is found between two bodies that were separated before +void PhysicsEventListener::beginContact(const rp3d::ContactPointInfo& contact) { + +} + +// Called when a new contact point is found between two bodies +void PhysicsEventListener::newContact(const rp3d::ContactPointInfo& contact) { + +} diff --git a/testbed/src/PhysicsEventListener.h b/testbed/src/PhysicsEventListener.h new file mode 100644 index 00000000..d9227feb --- /dev/null +++ b/testbed/src/PhysicsEventListener.h @@ -0,0 +1,66 @@ +/******************************************************************************** +* ReactPhysics3D physics library, http://www.reactphysics3d.com * +* Copyright (c) 2010-2015 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 PHYSICSEVENTLISTENER_H +#define PHYSICSEVENTLISTENER_H + +// Libraries +#include "reactphysics3d.h" +#include "openglframework.h" + +// Structure ContactPoint +struct ContactPoint { + + public: + openglframework::Vector3 point; + + /// Constructor + ContactPoint(const openglframework::Vector3& contactPoint) : point(contactPoint) { + + } +}; + +// Class PhysicsEventListener +// This class inherits from the EventListener class +// of ReactPhysics3D in order to be notified of events +// that occured in a physics world +class PhysicsEventListener : rp3d::EventListener { + + private: + + // Current contact points + std::vector mCurrentContactPoints; + + public: + + /// Called when a new contact point is found between two bodies that were separated before + virtual void beginContact(const rp3d::ContactPointInfo& contact); + + /// Called when a new contact point is found between two bodies + virtual void newContact(const rp3d::ContactPointInfo& contact); +}; + +#endif + diff --git a/testbed/src/Scene.cpp b/testbed/src/Scene.cpp index ea64fc13..65ac681f 100644 --- a/testbed/src/Scene.cpp +++ b/testbed/src/Scene.cpp @@ -30,9 +30,9 @@ using namespace openglframework; // Constructor -Scene::Scene(const std::string& name) +Scene::Scene(const std::string& name, bool isShadowMappingEnabled) : mName(name), mInterpolationFactor(0.0f), mViewportX(0), mViewportY(0), - mViewportWidth(0), mViewportHeight(0) { + mViewportWidth(0), mViewportHeight(0), mIsShadowMappingEnabled(isShadowMappingEnabled) { } diff --git a/testbed/src/Scene.h b/testbed/src/Scene.h index d4e05892..a558f95b 100644 --- a/testbed/src/Scene.h +++ b/testbed/src/Scene.h @@ -28,6 +28,7 @@ // Libraries #include "openglframework.h" +#include "PhysicsEventListener.h" /// Structure EngineSettings /// This structure contains several physics engine parameters @@ -90,6 +91,9 @@ class Scene { /// Viewport x,y, width and height values int mViewportX, mViewportY, mViewportWidth, mViewportHeight; + /// True if the shadow mapping is enabled + bool mIsShadowMappingEnabled; + // -------------------- Methods -------------------- // /// Set the scene position (where the camera needs to look at) @@ -117,7 +121,7 @@ class Scene { // -------------------- Methods -------------------- // /// Constructor - Scene(const std::string& name); + Scene(const std::string& name, bool isShadowMappingEnabled = false); /// Destructor virtual ~Scene(); @@ -172,6 +176,15 @@ class Scene { /// Return the name of the scene std::string getName() const; + + /// Return true if the shadow mapping is enabled + bool getIsShadowMappingEnabled() const; + + /// Enabled/Disable the shadow mapping + void virtual setIsShadowMappingEnabled(bool isShadowMappingEnabled); + + /// Return all the contact points of the scene + std::vector virtual getContactPoints() const; }; // Called when a keyboard event occurs @@ -223,4 +236,21 @@ inline std::string Scene::getName() const { return mName; } +// Return true if the shadow mapping is enabled +inline bool Scene::getIsShadowMappingEnabled() const { + return mIsShadowMappingEnabled; +} + +// Enabled/Disable the shadow mapping +inline void Scene::setIsShadowMappingEnabled(bool isShadowMappingEnabled) { + mIsShadowMappingEnabled = isShadowMappingEnabled; +} + +// Return all the contact points of the scene +inline std::vector Scene::getContactPoints() const { + + // Return an empty list of contact points + return std::vector(); +} + #endif diff --git a/testbed/src/SceneDemo.cpp b/testbed/src/SceneDemo.cpp index 6a5ddfbe..d4c88503 100644 --- a/testbed/src/SceneDemo.cpp +++ b/testbed/src/SceneDemo.cpp @@ -32,8 +32,9 @@ using namespace openglframework; int SceneDemo::shadowMapTextureLevel = 0; // Constructor -SceneDemo::SceneDemo(const std::string& name, float sceneRadius) : Scene(name), - mLight0(0), mIsShadowMappingEnabled(true), mIsShadowMappingInitialized(false), +SceneDemo::SceneDemo(const std::string& name, float sceneRadius, bool isShadowMappingEnabled) + : Scene(name, isShadowMappingEnabled), + mLight0(0), mIsShadowMappingInitialized(false), mDepthShader("shaders/depth.vert", "shaders/depth.frag"), mPhongShader("shaders/phong.vert", "shaders/phong.frag"), mQuadShader("shaders/quad.vert", "shaders/quad.frag"), diff --git a/testbed/src/SceneDemo.h b/testbed/src/SceneDemo.h index 8893e26c..f8439431 100644 --- a/testbed/src/SceneDemo.h +++ b/testbed/src/SceneDemo.h @@ -30,8 +30,8 @@ #include "Scene.h" // Constants -const int SHADOWMAP_WIDTH = 2048; -const int SHADOWMAP_HEIGHT = 2048; +const int SHADOWMAP_WIDTH = 1024; +const int SHADOWMAP_HEIGHT = 1024; // Class SceneDemo // Abstract class that represents a 3D scene for the ReactPhysics3D examples. @@ -45,9 +45,6 @@ class SceneDemo : public Scene { /// Light 0 openglframework::Light mLight0; - /// True if the shadow mapping is enabled - bool mIsShadowMappingEnabled; - /// True if the shadows FBO, textures have been created bool mIsShadowMappingInitialized; @@ -96,7 +93,7 @@ class SceneDemo : public Scene { // -------------------- Methods -------------------- // /// Constructor - SceneDemo(const std::string& name, float sceneRadius); + SceneDemo(const std::string& name, float sceneRadius, bool isShadowMappingEnabled = true); /// Destructor virtual ~SceneDemo(); @@ -108,21 +105,14 @@ class SceneDemo : public Scene { virtual void renderSinglePass(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix)=0; - /// Return true if the shadow mapping is enabled - bool getIsShadowMappingEnabled() const; - /// Enabled/Disable the shadow mapping - void setIsShadowMappingEnabled(bool isShadowMappingEnabled); + void virtual setIsShadowMappingEnabled(bool isShadowMappingEnabled); }; -// Return true if the shadow mapping is enabled -inline bool SceneDemo::getIsShadowMappingEnabled() const { - return mIsShadowMappingEnabled; -} - // Enabled/Disable the shadow mapping inline void SceneDemo::setIsShadowMappingEnabled(bool isShadowMappingEnabled) { - mIsShadowMappingEnabled = isShadowMappingEnabled; + + Scene::setIsShadowMappingEnabled(isShadowMappingEnabled); if (mIsShadowMappingEnabled && !mIsShadowMappingInitialized) { createShadowMapFBOAndTexture(); diff --git a/testbed/src/TestbedApplication.cpp b/testbed/src/TestbedApplication.cpp index 6cbeb41a..973d648e 100644 --- a/testbed/src/TestbedApplication.cpp +++ b/testbed/src/TestbedApplication.cpp @@ -50,7 +50,9 @@ TestbedApplication& TestbedApplication::getInstance() { } // Constructor -TestbedApplication::TestbedApplication() : mFPS(0), mNbFrames(0), mPreviousTime(0) { +TestbedApplication::TestbedApplication() + : mFPS(0), mNbFrames(0), mPreviousTime(0), + mUpdateTime(0), mPhysicsUpdateTime(0) { mCurrentScene = NULL; mIsMultisamplingActive = true; @@ -59,6 +61,8 @@ TestbedApplication::TestbedApplication() : mFPS(0), mNbFrames(0), mPreviousTime( mSinglePhysicsStepEnabled = false; mSinglePhysicsStepDone = false; mWindowToFramebufferRatio = Vector2(1, 1); + mIsShadowMappingEnabled = true; + mIsVSyncEnabled = true; } // Destructor @@ -107,8 +111,8 @@ void TestbedApplication::init() { } glfwMakeContextCurrent(mWindow); - // Disable Vertical Synchronization - glfwSwapInterval(0); + // Vertical Synchronization + enableVSync(mIsVSyncEnabled); // Initialize the GLEW library glewExperimental = GL_TRUE; @@ -214,6 +218,8 @@ void TestbedApplication::updatePhysics() { void TestbedApplication::update() { + double currentTime = glfwGetTime(); + // Update the physics if (mSinglePhysicsStepEnabled && !mSinglePhysicsStepDone) { updateSinglePhysicsStep(); @@ -223,6 +229,9 @@ void TestbedApplication::update() { updatePhysics(); } + // Compute the physics update time + mPhysicsUpdateTime = glfwGetTime() - currentTime; + // Compute the interpolation factor float factor = mTimer.computeInterpolationFactor(mEngineSettings.timeStep); assert(factor >= 0.0f && factor <= 1.0f); @@ -230,11 +239,11 @@ void TestbedApplication::update() { // Notify the scene about the interpolation factor mCurrentScene->setInterpolationFactor(factor); + // Enable/Disable shadow mapping + mCurrentScene->setIsShadowMappingEnabled(mIsShadowMappingEnabled); + // Update the scene mCurrentScene->update(); - - // Compute the current framerate - //application->computeFPS(); } // Render @@ -254,7 +263,7 @@ void TestbedApplication::render() { mCurrentScene->setViewport(mWindowToFramebufferRatio.x * LEFT_PANE_WIDTH, 0, bufferWidth - mWindowToFramebufferRatio.x * LEFT_PANE_WIDTH, - bufferHeight - mWindowToFramebufferRatio.y * HEADER_HEIGHT); + bufferHeight); // Render the scene mCurrentScene->render(); @@ -274,7 +283,7 @@ void TestbedApplication::reshape() { glfwGetFramebufferSize(mWindow, &width, &height); // Resize the camera viewport - mCurrentScene->reshape(width - LEFT_PANE_WIDTH, height - HEADER_HEIGHT); + mCurrentScene->reshape(width - LEFT_PANE_WIDTH, height); // Update the window size of the scene int windowWidth, windowHeight; @@ -305,6 +314,9 @@ void TestbedApplication::startMainLoop() { // Process events glfwPollEvents(); + // Compute the current framerate + computeFPS(); + checkOpenGLErrors(); } } @@ -355,17 +367,19 @@ void TestbedApplication::computeFPS() { mNbFrames++; - // Get the number of milliseconds since glutInit called + // Get the number of seconds since start mCurrentTime = glfwGetTime(); // Calculate time passed - double timeInterval = mCurrentTime - mPreviousTime; + mUpdateTime = mCurrentTime - mPreviousTime; + double timeInterval = mUpdateTime * 1000.0; // Update the FPS counter each second - if(timeInterval > 1.0) { + if(timeInterval > 0.0001) { // calculate the number of frames per second mFPS = static_cast(mNbFrames) / timeInterval; + mFPS *= 1000.0; // Set time mPreviousTime = mCurrentTime; diff --git a/testbed/src/TestbedApplication.h b/testbed/src/TestbedApplication.h index 1c2d22c0..75d14918 100644 --- a/testbed/src/TestbedApplication.h +++ b/testbed/src/TestbedApplication.h @@ -69,12 +69,18 @@ class TestbedApplication { /// Number of frames during the last second int mNbFrames; - /// Current time for fps computation + /// Current time for fps computation (in seconds) double mCurrentTime; - /// Previous time for fps computation + /// Previous time for fps computation (in seconds) double mPreviousTime; + /// Update time (in seconds) + double mUpdateTime; + + /// Physics update time (in seconds) + double mPhysicsUpdateTime; + /// True if multisampling is active bool mIsMultisamplingActive; @@ -89,6 +95,12 @@ class TestbedApplication { openglframework::Vector2 mWindowToFramebufferRatio; + /// True if shadow mapping is enabled + bool mIsShadowMappingEnabled; + + /// True if vsync is enabled + bool mIsVSyncEnabled; + // -------------------- Methods -------------------- // /// Private constructor (for the singleton class) @@ -160,6 +172,9 @@ class TestbedApplication { /// Set the variable to know if we need to take a single physics step void toggleTakeSinglePhysicsStep(); + /// Enable/Disable shadow mapping + void enableShadows(bool enable); + public : // -------------------- Methods -------------------- // @@ -179,6 +194,9 @@ class TestbedApplication { /// Change the current scene void switchScene(Scene* newScene); + /// Enable/Disable Vertical synchronization + void enableVSync(bool enable); + // -------------------- Friendship -------------------- // friend class Gui; @@ -216,4 +234,20 @@ inline void TestbedApplication::toggleTakeSinglePhysicsStep() { } } +// Enable/Disable shadow mapping +inline void TestbedApplication::enableShadows(bool enable) { + mIsShadowMappingEnabled = enable; +} + +// Enable/Disable Vertical synchronization +inline void TestbedApplication::enableVSync(bool enable) { + mIsVSyncEnabled = enable; + if (mIsVSyncEnabled) { + glfwSwapInterval(1); + } + else { + glfwSwapInterval(0); + } +} + #endif