Refactor the rendering of GUI and other improvements of testbed application
This commit is contained in:
parent
7ff7b129e9
commit
1b7cadc245
|
@ -55,7 +55,12 @@ Gui::~Gui() {
|
|||
}
|
||||
|
||||
/// Initialize the GUI
|
||||
void Gui::init() {
|
||||
void Gui::init(GLFWwindow* window) {
|
||||
|
||||
mWindow = window;
|
||||
|
||||
mScreen = new Screen();
|
||||
mScreen->initialize(window, true);
|
||||
|
||||
// Create the Simulation panel
|
||||
createSimulationPanel();
|
||||
|
@ -66,12 +71,31 @@ void Gui::init() {
|
|||
// Create the Profiling panel
|
||||
createProfilingPanel();
|
||||
|
||||
mApp->set_visible(true);
|
||||
mApp->perform_layout();
|
||||
mScreen->set_visible(true);
|
||||
mScreen->perform_layout();
|
||||
|
||||
mTimeSinceLastProfilingDisplay = glfwGetTime();
|
||||
}
|
||||
|
||||
void Gui::drawAll() {
|
||||
mScreen->clear();
|
||||
mScreen->draw_all();
|
||||
}
|
||||
|
||||
void Gui::draw() {
|
||||
|
||||
mScreen->draw_setup();
|
||||
mScreen->clear();
|
||||
mScreen->draw_contents();
|
||||
}
|
||||
|
||||
void Gui::drawTearDown() {
|
||||
|
||||
mScreen->draw_widgets();
|
||||
mScreen->draw_teardown();
|
||||
}
|
||||
|
||||
|
||||
// Update the GUI values with the engine settings from the current scene
|
||||
void Gui::resetWithValuesFromCurrentScene() {
|
||||
|
||||
|
@ -126,7 +150,7 @@ void Gui::update() {
|
|||
|
||||
void Gui::createSimulationPanel() {
|
||||
|
||||
mSimulationPanel = new Window(mApp, "Simulation");
|
||||
mSimulationPanel = new Window(mScreen, "Simulation");
|
||||
mSimulationPanel->set_position(Vector2i(15, 15));
|
||||
mSimulationPanel->set_layout(new GroupLayout(10, 5, 10 , 20));
|
||||
//mSimulationPanel->setId("SimulationPanel");
|
||||
|
@ -164,17 +188,16 @@ void Gui::createSimulationPanel() {
|
|||
scenesNames.push_back(scenes[i]->getName().c_str());
|
||||
}
|
||||
new Label(mSimulationPanel, "Scene","sans-bold");
|
||||
ComboBox* comboBoxScenes = new ComboBox(mSimulationPanel, scenesNames);
|
||||
comboBoxScenes->set_fixed_width(150);
|
||||
comboBoxScenes->popup()->child_at(0)->set_fixed_height(800);
|
||||
comboBoxScenes->set_callback([&, scenes](int index) {
|
||||
|
||||
mComboBoxScenes = new ComboBox(mSimulationPanel, scenesNames);
|
||||
mComboBoxScenes->set_callback([&, scenes](int index) {
|
||||
mApp->switchScene(scenes[index]);
|
||||
});
|
||||
}
|
||||
|
||||
void Gui::createSettingsPanel() {
|
||||
|
||||
mSettingsPanel = new Window(mApp, "Settings");
|
||||
mSettingsPanel = new Window(mScreen, "Settings");
|
||||
mSettingsPanel->set_position(Vector2i(15, 180));
|
||||
mSettingsPanel->set_layout(new BoxLayout(Orientation::Vertical, Alignment::Middle, 10, 5));
|
||||
//mSettingsPanel->setId("SettingsPanel");
|
||||
|
@ -189,14 +212,14 @@ void Gui::createSettingsPanel() {
|
|||
buttonPhysics->set_change_callback([&](bool state) {
|
||||
mPhysicsPanel->set_visible(true);
|
||||
mRenderingPanel->set_visible(false);
|
||||
mApp->perform_layout();
|
||||
mScreen->perform_layout();
|
||||
});
|
||||
Button* buttonRendering = new Button(buttonsPanel, "Rendering");
|
||||
buttonRendering->set_flags(Button::RadioButton);
|
||||
buttonRendering->set_change_callback([&](bool state) {
|
||||
mRenderingPanel->set_visible(true);
|
||||
mPhysicsPanel->set_visible(false);
|
||||
mApp->perform_layout();
|
||||
mScreen->perform_layout();
|
||||
});
|
||||
|
||||
// ---------- Physics Panel ----------
|
||||
|
@ -509,7 +532,7 @@ void Gui::createSettingsPanel() {
|
|||
|
||||
void Gui::createProfilingPanel() {
|
||||
|
||||
Widget* profilingPanel = new Window(mApp, "Profiling");
|
||||
Widget* profilingPanel = new Window(mScreen, "Profiling");
|
||||
profilingPanel->set_position(Vector2i(15, 525));
|
||||
profilingPanel->set_layout(new BoxLayout(Orientation::Vertical, Alignment::Fill, 10, 5));
|
||||
//profilingPanel->setId("SettingsPanel");
|
||||
|
@ -530,3 +553,33 @@ void Gui::createProfilingPanel() {
|
|||
profilingPanel->set_visible(true);
|
||||
}
|
||||
|
||||
void Gui::onWindowResizeEvent(int width, int height) {
|
||||
mScreen->resize_callback_event(width, height);
|
||||
}
|
||||
|
||||
void Gui::onMouseMotionEvent(double x, double y) {
|
||||
mScreen->cursor_pos_callback_event(x, y);
|
||||
}
|
||||
|
||||
bool Gui::onScrollEvent(double x, double y) {
|
||||
|
||||
double xMouse, yMouse;
|
||||
glfwGetCursorPos(mWindow, &xMouse, &yMouse);
|
||||
|
||||
// If the mouse cursor is over the scenes choice scrolling menu
|
||||
const float pixelRatio = mScreen->pixel_ratio();
|
||||
if (mComboBoxScenes->visible() && mComboBoxScenes->popup()->contains(Vector2i(xMouse, yMouse) / pixelRatio)) {
|
||||
mScreen->scroll_callback_event(x, y);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Gui::onMouseButtonEvent(int button, int action, int modifiers) {
|
||||
mScreen->mouse_button_callback_event(button, action, modifiers);
|
||||
}
|
||||
|
||||
void Gui::onKeyboardEvent(int key, int scancode, int action, int modifiers) {
|
||||
mScreen->key_callback_event(key, scancode, action, modifiers);
|
||||
}
|
||||
|
|
|
@ -56,6 +56,11 @@ class Gui {
|
|||
// Pointer to the application
|
||||
TestbedApplication* mApp;
|
||||
|
||||
// Screen
|
||||
Screen* mScreen;
|
||||
|
||||
GLFWwindow* mWindow;
|
||||
|
||||
static double mScrollX, mScrollY;
|
||||
|
||||
// Simulation panel
|
||||
|
@ -81,7 +86,11 @@ class Gui {
|
|||
TextBox* mTextboxSleepLinearVel;
|
||||
TextBox* mTextboxSleepAngularVel;
|
||||
|
||||
ToolButton* mButtonPause;
|
||||
Widget* mPanelControls;
|
||||
|
||||
std::vector<CheckBox*> mCheckboxesScenes;
|
||||
ComboBox* mComboBoxScenes;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
|
@ -124,18 +133,31 @@ class Gui {
|
|||
~Gui();
|
||||
|
||||
/// Initialize the GUI
|
||||
void init();
|
||||
void init(GLFWwindow* window);
|
||||
|
||||
/// Update the GUI
|
||||
void update();
|
||||
|
||||
/// Display the GUI
|
||||
void render();
|
||||
void drawAll();
|
||||
|
||||
void draw();
|
||||
|
||||
void drawTearDown();
|
||||
|
||||
/// Update the GUI values with the engine settings from the current scene
|
||||
void resetWithValuesFromCurrentScene();
|
||||
|
||||
static void setScroll(double scrollX, double scrollY);
|
||||
|
||||
void onWindowResizeEvent(int width, int height);
|
||||
|
||||
void onMouseMotionEvent(double x, double y);
|
||||
|
||||
bool onScrollEvent(double x, double y);
|
||||
|
||||
void onMouseButtonEvent(int button, int action, int modifiers);
|
||||
|
||||
void onKeyboardEvent(int key, int scancode, int action, int modifiers);
|
||||
};
|
||||
|
||||
inline void Gui::resetScroll() {
|
||||
|
|
|
@ -26,39 +26,35 @@
|
|||
// Libraries
|
||||
#include "TestbedApplication.h"
|
||||
#include "nanogui/nanogui.h"
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
using namespace nanogui;
|
||||
|
||||
// GLFW
|
||||
//
|
||||
#if defined(NANOGUI_USE_OPENGL)
|
||||
# if defined(NANOGUI_GLAD)
|
||||
# if defined(NANOGUI_SHARED) && !defined(GLAD_GLAPI_EXPORT)
|
||||
# define GLAD_GLAPI_EXPORT
|
||||
# endif
|
||||
# include <glad/glad.h>
|
||||
# else
|
||||
# if defined(__APPLE__)
|
||||
# define GLFW_INCLUDE_GLCOREARB
|
||||
# else
|
||||
# define GL_GLEXT_PROTOTYPES
|
||||
# endif
|
||||
# endif
|
||||
#elif defined(NANOGUI_USE_GLES)
|
||||
# define GLFW_INCLUDE_ES2
|
||||
#endif
|
||||
|
||||
// Main function
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
|
||||
nanogui::init();
|
||||
|
||||
{
|
||||
bool isFullscreen = false;
|
||||
|
||||
// Get the primary monitor
|
||||
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
|
||||
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
|
||||
|
||||
// Window size
|
||||
int windowWidth = mode->width;
|
||||
int windowHeight = mode->height;
|
||||
|
||||
if (!isFullscreen) {
|
||||
|
||||
windowWidth *= 0.9;
|
||||
windowHeight *= 0.9;
|
||||
}
|
||||
|
||||
// Create and start the testbed application
|
||||
nanogui::ref<TestbedApplication> application = new TestbedApplication(isFullscreen, windowWidth, windowHeight);
|
||||
application->set_visible(true);
|
||||
|
||||
nanogui::mainloop(10);
|
||||
}
|
||||
|
||||
nanogui::shutdown();
|
||||
// Create and start the testbed application
|
||||
TestbedApplication application;
|
||||
application.start();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,8 @@ using namespace openglframework;
|
|||
|
||||
// Constructor
|
||||
Scene::Scene(const std::string& name, EngineSettings& engineSettings, bool isShadowMappingEnabled)
|
||||
: mName(name), mEngineSettings(engineSettings), mLastMouseX(0), mLastMouseY(0), mInterpolationFactor(0.0f), mViewportX(0), mViewportY(0),
|
||||
: mName(name), mEngineSettings(engineSettings), mLastMouseX(0), mLastMouseY(0), mInterpolationFactor(0.0f),
|
||||
mCurrentCameraVerticalAngle(0.0), mViewportX(0), mViewportY(0),
|
||||
mViewportWidth(0), mViewportHeight(0), mIsShadowMappingEnabled(isShadowMappingEnabled),
|
||||
mAreContactPointsDisplayed(true), mAreContactNormalsDisplayed(false), mAreBroadPhaseAABBsDisplayed(false),
|
||||
mAreCollidersAABBsDisplayed(false), mAreCollisionShapesDisplayed(false), mIsWireframeEnabled(false) {
|
||||
|
@ -97,10 +98,6 @@ bool Scene::mouseButtonEvent(int button, bool down, int mods, double mousePosX,
|
|||
if (down) {
|
||||
mLastMouseX = mousePosX;
|
||||
mLastMouseY = mousePosY;
|
||||
mIsLastPointOnSphereValid = mapMouseCoordinatesToSphere(mousePosX, mousePosY, mLastPointOnSphere);
|
||||
}
|
||||
else { // If the mouse button is released
|
||||
mIsLastPointOnSphereValid = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -133,7 +130,6 @@ bool Scene::mouseMotionEvent(double xMouse, double yMouse, int leftButtonState,
|
|||
// Remember the mouse position
|
||||
mLastMouseX = xMouse;
|
||||
mLastMouseY = yMouse;
|
||||
mIsLastPointOnSphereValid = mapMouseCoordinatesToSphere(xMouse, yMouse, mLastPointOnSphere);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -165,23 +161,25 @@ void Scene::translate(int xMouse, int yMouse) {
|
|||
// Rotate the camera
|
||||
void Scene::rotate(int xMouse, int yMouse) {
|
||||
|
||||
if (mIsLastPointOnSphereValid) {
|
||||
const double deltaXMouse = mLastMouseX - xMouse;
|
||||
const double deltaYMouse = mLastMouseY - yMouse;
|
||||
|
||||
Vector3 newPoint3D;
|
||||
bool isNewPointOK = mapMouseCoordinatesToSphere(xMouse, yMouse, newPoint3D);
|
||||
double deltaHorizRotationAngle = deltaXMouse / mWindowWidth * MOUSE_CAMERA_ROTATION_SCALING_FACTOR * M_PI;
|
||||
double deltaVertRotationAngle = deltaYMouse / mWindowHeight * MOUSE_CAMERA_ROTATION_SCALING_FACTOR * M_PI;
|
||||
|
||||
if (isNewPointOK) {
|
||||
Vector3 axis = mLastPointOnSphere.cross(newPoint3D);
|
||||
float cosAngle = mLastPointOnSphere.dot(newPoint3D);
|
||||
const double newVerticalAngle = mCurrentCameraVerticalAngle + deltaVertRotationAngle;
|
||||
|
||||
float epsilon = std::numeric_limits<float>::epsilon();
|
||||
if (std::abs(cosAngle) < 1.0f && axis.length() > epsilon) {
|
||||
axis.normalize();
|
||||
float angle = 2.0f * std::acos(cosAngle);
|
||||
|
||||
// Rotate the camera around the center of the scene
|
||||
mCamera.rotateAroundLocalPoint(axis, -angle, mCenterScene);
|
||||
}
|
||||
}
|
||||
// Limit Vertical angle
|
||||
constexpr double piOver2 = M_PI * 0.5f;
|
||||
if (newVerticalAngle > piOver2 || newVerticalAngle < -piOver2) {
|
||||
deltaVertRotationAngle = 0;
|
||||
}
|
||||
|
||||
Vector3 localVertAxis = mCamera.getTransformMatrix().getUpperLeft3x3Matrix().getInverse() * Vector3(0, 1, 0);
|
||||
mCamera.rotateAroundLocalPoint(Vector3(1, 0, 0), deltaVertRotationAngle, mCenterScene);
|
||||
mCamera.rotateAroundLocalPoint(localVertAxis, deltaHorizRotationAngle, mCenterScene);
|
||||
|
||||
mCurrentCameraVerticalAngle += deltaVertRotationAngle;
|
||||
std::cout << "Delta angle: " << deltaVertRotationAngle << std::endl;
|
||||
std::cout << "Horizon angle: " << mCurrentCameraVerticalAngle << std::endl;
|
||||
}
|
||||
|
|
|
@ -95,6 +95,10 @@ class Scene : public rp3d::EventListener {
|
|||
|
||||
protected:
|
||||
|
||||
// -------------------- Constants -------------------- //
|
||||
|
||||
static constexpr float MOUSE_CAMERA_ROTATION_SCALING_FACTOR = 1.0f;
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Scene name
|
||||
|
@ -118,12 +122,12 @@ class Scene : public rp3d::EventListener {
|
|||
/// Last point computed on a sphere (for camera rotation)
|
||||
openglframework::Vector3 mLastPointOnSphere;
|
||||
|
||||
/// True if the last point computed on a sphere (for camera rotation) is valid
|
||||
bool mIsLastPointOnSphereValid;
|
||||
|
||||
/// Interpolation factor for the bodies in the current frame
|
||||
float mInterpolationFactor;
|
||||
|
||||
/// Current camera vertical angle around the horizontal axis (in radians)
|
||||
double mCurrentCameraVerticalAngle;
|
||||
|
||||
/// Viewport x,y, width and height values
|
||||
int mViewportX, mViewportY, mViewportWidth, mViewportHeight;
|
||||
|
||||
|
|
|
@ -76,13 +76,11 @@ using namespace ropescene;
|
|||
const float TestbedApplication::SCROLL_SENSITIVITY = 0.08f;
|
||||
|
||||
// Constructor
|
||||
TestbedApplication::TestbedApplication(bool isFullscreen, int windowWidth, int windowHeight)
|
||||
: Screen(Vector2i(windowWidth, windowHeight), "Testbed ReactPhysics3D v" + rp3d::RP3D_VERSION, true, isFullscreen, true, true, false, 4, 1),
|
||||
mIsInitialized(false), mGui(this), mCurrentScene(nullptr),
|
||||
TestbedApplication::TestbedApplication()
|
||||
: mIsInitialized(false), mGui(this), mCurrentScene(nullptr),
|
||||
mDefaultEngineSettings(EngineSettings::defaultSettings()),
|
||||
mFPS(0), mNbFrames(0), mPreviousTime(0),
|
||||
mLastTimeComputedFPS(0), mFrameTime(0), mTotalPhysicsTime(0), mPhysicsStepTime(0),
|
||||
mWidth(windowWidth), mHeight(windowHeight),
|
||||
mSinglePhysicsStepEnabled(false), mSinglePhysicsStepDone(false),
|
||||
mWindowToFramebufferRatio(Vector2(1, 1)), mIsShadowMappingEnabled(true),
|
||||
mAreContactPointsDisplayed(false), mAreContactNormalsDisplayed(false),
|
||||
|
@ -91,8 +89,6 @@ TestbedApplication::TestbedApplication(bool isFullscreen, int windowWidth, int w
|
|||
mIsVSyncEnabled(false), mIsDebugRendererEnabled(false) {
|
||||
|
||||
init();
|
||||
|
||||
resize_event(Vector2i(0, 0));
|
||||
}
|
||||
|
||||
// Destructor
|
||||
|
@ -103,7 +99,62 @@ TestbedApplication::~TestbedApplication() {
|
|||
}
|
||||
|
||||
// Initialize the viewer
|
||||
void TestbedApplication::init() {
|
||||
void TestbedApplication::start() {
|
||||
|
||||
glfwInit();
|
||||
glfwSetTime(0);
|
||||
|
||||
// Get the primary monitor
|
||||
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
|
||||
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
|
||||
|
||||
// Window size
|
||||
mWidth = mode->width;
|
||||
mHeight = mode->height;
|
||||
|
||||
#if defined(NANOGUI_USE_OPENGL)
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
|
||||
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
#elif defined(NANOGUI_USE_GLES)
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
|
||||
|
||||
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
|
||||
#elif defined(NANOGUI_USE_METAL)
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
|
||||
metal_init();
|
||||
#endif
|
||||
|
||||
glfwWindowHint(GLFW_SAMPLES, 0);
|
||||
glfwWindowHint(GLFW_RED_BITS, 8);
|
||||
glfwWindowHint(GLFW_GREEN_BITS, 8);
|
||||
glfwWindowHint(GLFW_BLUE_BITS, 8);
|
||||
glfwWindowHint(GLFW_ALPHA_BITS, 8);
|
||||
glfwWindowHint(GLFW_STENCIL_BITS, 8);
|
||||
glfwWindowHint(GLFW_DEPTH_BITS, 24);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
|
||||
|
||||
// Create a the GLFW window object
|
||||
std::string title = "Testbed - ReactPhysics3D v" + rp3d::RP3D_VERSION;
|
||||
mWindow = glfwCreateWindow(mWidth, mHeight, title.c_str(), IS_FULLSCREEN ? monitor : nullptr, nullptr);
|
||||
if (mWindow == nullptr) {
|
||||
std::cout << "Failed to create GLFW window" << std::endl;
|
||||
glfwTerminate();
|
||||
}
|
||||
glfwMakeContextCurrent(mWindow);
|
||||
|
||||
#if defined(NANOGUI_GLAD)
|
||||
if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress))
|
||||
throw std::runtime_error("Could not initialize GLAD!");
|
||||
glGetError(); // pull and ignore unhandled errors like GL_INVALID_ENUM
|
||||
#endif
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// Logger
|
||||
rp3d::PhysicsCommon::setLogger(&mLogger);
|
||||
|
@ -112,12 +163,22 @@ void TestbedApplication::init() {
|
|||
createScenes();
|
||||
|
||||
// Initialize the GUI
|
||||
mGui.init();
|
||||
mGui.init(mWindow);
|
||||
|
||||
#if defined(NANOGUI_USE_OPENGL) || defined(NANOGUI_USE_GLES)
|
||||
int width, height;
|
||||
glfwGetFramebufferSize(mWindow, &width, &height);
|
||||
glViewport(0, 0, width, height);
|
||||
glfwSwapInterval(0);
|
||||
glfwSwapBuffers(mWindow);
|
||||
#endif
|
||||
|
||||
// Select the initial scene
|
||||
const int firstSceneIndex = 0;
|
||||
switchScene(mScenes[firstSceneIndex]);
|
||||
|
||||
mGui.drawAll();
|
||||
|
||||
mTimer.start();
|
||||
|
||||
int glMajorVersion, glMinorVersion;
|
||||
|
@ -134,7 +195,68 @@ void TestbedApplication::init() {
|
|||
}
|
||||
#endif
|
||||
|
||||
glfwSetWindowUserPointer(mWindow, this);
|
||||
|
||||
glfwSetCursorPosCallback(mWindow, [](GLFWwindow* window, double x, double y) {
|
||||
TestbedApplication* app = static_cast<TestbedApplication*>(glfwGetWindowUserPointer(window));
|
||||
app->mouse_motion_event(x, y);
|
||||
}
|
||||
);
|
||||
|
||||
glfwSetMouseButtonCallback(mWindow, [](GLFWwindow* window, int button, int action, int modifiers) {
|
||||
TestbedApplication* app = static_cast<TestbedApplication*>(glfwGetWindowUserPointer(window));
|
||||
app->mouse_button_event(button, action, modifiers);
|
||||
}
|
||||
);
|
||||
|
||||
glfwSetKeyCallback(mWindow, [](GLFWwindow* window, int key, int scancode, int action, int mods) {
|
||||
TestbedApplication* app = static_cast<TestbedApplication*>(glfwGetWindowUserPointer(window));
|
||||
app->keyboard_event(key, scancode, action, mods);
|
||||
}
|
||||
);
|
||||
|
||||
glfwSetScrollCallback(mWindow, [](GLFWwindow* window, double x, double y) {
|
||||
TestbedApplication* app = static_cast<TestbedApplication*>(glfwGetWindowUserPointer(window));
|
||||
app->scroll_event(x, y);
|
||||
}
|
||||
);
|
||||
|
||||
glfwSetFramebufferSizeCallback(mWindow, [](GLFWwindow* window, int width, int height) {
|
||||
TestbedApplication* app = static_cast<TestbedApplication*>(glfwGetWindowUserPointer(window));
|
||||
app->onWindowResized(width, height);
|
||||
}
|
||||
);
|
||||
|
||||
mCurrentScene->reshape(mWidth, mHeight);
|
||||
mCurrentScene->setWindowDimension(mWidth, mHeight);
|
||||
|
||||
mIsInitialized = true;
|
||||
|
||||
// Game loop
|
||||
while (!glfwWindowShouldClose(mWindow)) {
|
||||
|
||||
// Check if any events have been activated (key pressed, mouse moved etc.) and call corresponding response functions
|
||||
glfwPollEvents();
|
||||
|
||||
update();
|
||||
|
||||
mGui.update();
|
||||
|
||||
// Draw nanogui
|
||||
mGui.draw();
|
||||
|
||||
render();
|
||||
|
||||
mGui.drawTearDown();
|
||||
}
|
||||
|
||||
// Terminate GLFW, clearing any resources allocated by GLFW.
|
||||
glfwTerminate();
|
||||
|
||||
#if defined(NANOGUI_USE_METAL)
|
||||
metal_shutdown();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// Create all the scenes
|
||||
|
@ -357,44 +479,39 @@ void TestbedApplication::update() {
|
|||
|
||||
// Update the scene
|
||||
mCurrentScene->update();
|
||||
|
||||
// Compute the current framerate
|
||||
computeFPS();
|
||||
}
|
||||
|
||||
void TestbedApplication::draw_contents() {
|
||||
|
||||
update();
|
||||
void TestbedApplication::render() {
|
||||
|
||||
int bufferWidth, bufferHeight;
|
||||
glfwMakeContextCurrent(m_glfw_window);
|
||||
glfwGetFramebufferSize(m_glfw_window, &bufferWidth, &bufferHeight);
|
||||
glfwMakeContextCurrent(mWindow);
|
||||
glfwGetFramebufferSize(mWindow, &bufferWidth, &bufferHeight);
|
||||
|
||||
// Set the viewport of the scene
|
||||
mCurrentScene->setViewport(0, 0, bufferWidth, bufferHeight);
|
||||
|
||||
// Render the scene
|
||||
mCurrentScene->render();
|
||||
|
||||
mGui.update();
|
||||
|
||||
// Compute the current framerate
|
||||
computeFPS();
|
||||
}
|
||||
|
||||
/// Window resize event handler
|
||||
bool TestbedApplication::resize_event(const Vector2i &size) {
|
||||
bool TestbedApplication::onWindowResized(int width, int height) {
|
||||
|
||||
if (!mIsInitialized) return false;
|
||||
|
||||
// Get the framebuffer dimension
|
||||
int width, height;
|
||||
glfwGetFramebufferSize(m_glfw_window, &width, &height);
|
||||
mGui.onWindowResizeEvent(width, height);
|
||||
|
||||
// Resize the camera viewport
|
||||
mCurrentScene->reshape(width, height);
|
||||
|
||||
// Update the window size of the scene
|
||||
int windowWidth, windowHeight;
|
||||
glfwGetWindowSize(m_glfw_window, &windowWidth, &windowHeight);
|
||||
mCurrentScene->setWindowDimension(windowWidth, windowHeight);
|
||||
mCurrentScene->setWindowDimension(width, height);
|
||||
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -408,13 +525,18 @@ void TestbedApplication::switchScene(Scene* newScene) {
|
|||
|
||||
mTimer.reset();
|
||||
|
||||
// Resize the camera viewport
|
||||
mCurrentScene->reshape(mWidth, mHeight);
|
||||
|
||||
// Update the window size of the scene
|
||||
mCurrentScene->setWindowDimension(mWidth, mHeight);
|
||||
|
||||
// Reset the scene
|
||||
mCurrentScene->reset();
|
||||
|
||||
mGui.resetWithValuesFromCurrentScene();
|
||||
mCurrentScene->updateEngineSettings();
|
||||
|
||||
resize_event(Vector2i(0, 0));
|
||||
mGui.resetWithValuesFromCurrentScene();
|
||||
}
|
||||
|
||||
// Notify that the engine settings have changed
|
||||
|
@ -472,16 +594,14 @@ void TestbedApplication::computeFPS() {
|
|||
mPreviousTime = mCurrentTime;
|
||||
}
|
||||
|
||||
bool TestbedApplication::keyboard_event(int key, int scancode, int action, int modifiers) {
|
||||
void TestbedApplication::keyboard_event(int key, int scancode, int action, int modifiers) {
|
||||
|
||||
if (Screen::keyboard_event(key, scancode, action, modifiers)) {
|
||||
return true;
|
||||
}
|
||||
mGui.onKeyboardEvent(key, scancode, action, modifiers);
|
||||
|
||||
// Close application on escape key
|
||||
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
|
||||
glfwSetWindowShouldClose(m_glfw_window, GL_TRUE);
|
||||
return true;
|
||||
glfwSetWindowShouldClose(mWindow, GL_TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Close application on escape key
|
||||
|
@ -494,48 +614,45 @@ bool TestbedApplication::keyboard_event(int key, int scancode, int action, int m
|
|||
playSimulation();
|
||||
}
|
||||
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
return mCurrentScene->keyboardEvent(key, scancode, action, modifiers);
|
||||
mCurrentScene->keyboardEvent(key, scancode, action, modifiers);
|
||||
}
|
||||
|
||||
// Handle a mouse button event (default implementation: propagate to children)
|
||||
bool TestbedApplication::mouse_button_event(const Vector2i &p, int button, bool down, int modifiers) {
|
||||
void TestbedApplication::mouse_button_event(int button, int action, int modifiers) {
|
||||
|
||||
if (Screen::mouse_button_event(p, button, down, modifiers)) {
|
||||
return true;
|
||||
}
|
||||
mGui.onMouseButtonEvent(button, action, modifiers);
|
||||
|
||||
// Get the mouse cursor position
|
||||
double x, y;
|
||||
glfwGetCursorPos(m_glfw_window, &x, &y);
|
||||
glfwGetCursorPos(mWindow, &x, &y);
|
||||
|
||||
return mCurrentScene->mouseButtonEvent(button, down, modifiers, x, y);
|
||||
bool down = action == GLFW_PRESS;
|
||||
|
||||
mCurrentScene->mouseButtonEvent(button, down, modifiers, x, y);
|
||||
}
|
||||
|
||||
// Handle a mouse motion event (default implementation: propagate to children)
|
||||
bool TestbedApplication::mouse_motion_event(const Vector2i &p, const Vector2i &rel, int button, int modifiers) {
|
||||
void TestbedApplication::mouse_motion_event(double x, double y) {
|
||||
|
||||
if (Screen::mouse_motion_event(p, rel, button, modifiers)) {
|
||||
return true;
|
||||
}
|
||||
mGui.onMouseMotionEvent(x, y);
|
||||
|
||||
int leftButtonState = glfwGetMouseButton(m_glfw_window, GLFW_MOUSE_BUTTON_LEFT);
|
||||
int rightButtonState = glfwGetMouseButton(m_glfw_window, GLFW_MOUSE_BUTTON_RIGHT);
|
||||
int middleButtonState = glfwGetMouseButton(m_glfw_window, GLFW_MOUSE_BUTTON_MIDDLE);
|
||||
int altKeyState = glfwGetKey(m_glfw_window, GLFW_KEY_LEFT_ALT);
|
||||
int leftButtonState = glfwGetMouseButton(mWindow, GLFW_MOUSE_BUTTON_LEFT);
|
||||
int rightButtonState = glfwGetMouseButton(mWindow, GLFW_MOUSE_BUTTON_RIGHT);
|
||||
int middleButtonState = glfwGetMouseButton(mWindow, GLFW_MOUSE_BUTTON_MIDDLE);
|
||||
int altKeyState = glfwGetKey(mWindow, GLFW_KEY_LEFT_ALT);
|
||||
|
||||
return mCurrentScene->mouseMotionEvent(p[0], p[1], leftButtonState, rightButtonState,
|
||||
middleButtonState, altKeyState);
|
||||
mCurrentScene->mouseMotionEvent(x, y, leftButtonState, rightButtonState, middleButtonState, altKeyState);
|
||||
}
|
||||
|
||||
// Handle a mouse scroll event (default implementation: propagate to children)
|
||||
bool TestbedApplication::scroll_event(const Vector2i &p, const Vector2f &rel) {
|
||||
// Handle a mouse scroll event
|
||||
void TestbedApplication::scroll_event(double x, double y) {
|
||||
|
||||
if (Screen::scroll_event(p, rel)) {
|
||||
return true;
|
||||
}
|
||||
if (mGui.onScrollEvent(x, y)) {
|
||||
return;
|
||||
};
|
||||
|
||||
return mCurrentScene->scrollingEvent(rel[0], rel[1], SCROLL_SENSITIVITY);
|
||||
mCurrentScene->scrollingEvent(x, y, SCROLL_SENSITIVITY);
|
||||
}
|
||||
|
|
|
@ -36,22 +36,27 @@
|
|||
|
||||
using namespace nanogui;
|
||||
|
||||
|
||||
// Macro for OpenGL errors
|
||||
#define checkOpenGLErrors() checkOpenGLErrorsInternal(__FILE__,__LINE__)
|
||||
|
||||
/// Class TestbedApplication
|
||||
class TestbedApplication : public Screen {
|
||||
class TestbedApplication {
|
||||
|
||||
private :
|
||||
|
||||
// -------------------- Constants -------------------- //
|
||||
|
||||
static const float SCROLL_SENSITIVITY;
|
||||
static constexpr bool IS_FULLSCREEN = false;
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
bool mIsInitialized;
|
||||
|
||||
GLFWwindow* mWindow;
|
||||
Screen* mScreen;
|
||||
|
||||
Gui mGui;
|
||||
|
||||
/// Timer
|
||||
|
@ -186,31 +191,31 @@ class TestbedApplication : public Screen {
|
|||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Private constructor (for the singleton class)
|
||||
TestbedApplication(bool isFullscreen, int windowWidth, int windowHeight);
|
||||
TestbedApplication();
|
||||
|
||||
/// Destructor
|
||||
virtual ~TestbedApplication() override;
|
||||
~TestbedApplication();
|
||||
|
||||
/// Render the content of the application
|
||||
virtual void draw_contents() override;
|
||||
void render();
|
||||
|
||||
/// Window resize event handler
|
||||
virtual bool resize_event(const Vector2i& size) override;
|
||||
bool onWindowResized(int width, int height);
|
||||
|
||||
/// Default keyboard event handler
|
||||
virtual bool keyboard_event(int key, int scancode, int action, int modifiers) override;
|
||||
void keyboard_event(int key, int scancode, int action, int modifiers);
|
||||
|
||||
/// Handle a mouse button event (default implementation: propagate to children)
|
||||
virtual bool mouse_button_event(const Vector2i &p, int button, bool down, int modifiers) override;
|
||||
void mouse_button_event(int button, int action, int modifiers);
|
||||
|
||||
/// Handle a mouse motion event (default implementation: propagate to children)
|
||||
virtual bool mouse_motion_event(const Vector2i &p, const Vector2i &rel, int button, int modifiers) override;
|
||||
void mouse_motion_event(double x, double y);
|
||||
|
||||
/// Handle a mouse scroll event (default implementation: propagate to children)
|
||||
virtual bool scroll_event(const Vector2i &p, const Vector2f &rel) override;
|
||||
/// Handle a mouse scroll event
|
||||
void scroll_event(double x, double y);
|
||||
|
||||
/// Initialize the application
|
||||
void init();
|
||||
/// Start the application
|
||||
void start();
|
||||
|
||||
/// Change the current scene
|
||||
void switchScene(Scene* newScene);
|
||||
|
|
Loading…
Reference in New Issue
Block a user