reactphysics3d/testbed/TestbedApplication.cpp
2015-04-08 20:47:55 +02:00

264 lines
7.7 KiB
C++

/********************************************************************************
* 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 "TestbedApplication.h"
#include "openglframework.h"
#include <iostream>
#include <cstdlib>
#include <sstream>
using namespace openglframework;
// Initialization of static variables
const float TestbedApplication::SCROLL_SENSITIVITY = 0.02f;
// Create and return the singleton instance of this class
TestbedApplication& TestbedApplication::getInstance() {
static TestbedApplication instance;
return instance;
}
// Constructor
TestbedApplication::TestbedApplication() : mFPS(0), mNbFrames(0), mPreviousTime(0) {
mIsMultisamplingActive = true;
mWidth = 1000;
mHeight = 800;
}
// Destructor
TestbedApplication::~TestbedApplication() {
// TODO : Check that this method is called at the end
// Destroy the window
glfwDestroyWindow(mWindow);
// Terminate GLFW
glfwTerminate();
}
// Initialize the viewer
void TestbedApplication::init() {
// Set the GLFW error callback method
glfwSetErrorCallback(error_callback);
// Initialize the GLFW library
if (!glfwInit()) {
std::exit(EXIT_FAILURE);
}
// Active the multi-sampling by default
if (mIsMultisamplingActive) {
glfwWindowHint(GLFW_SAMPLES, 4);
}
// Create the GLFW window
mWindow = glfwCreateWindow(mWidth, mHeight,
"ReactPhysics3D Testbed", NULL, NULL);
if (!mWindow) {
glfwTerminate();
std::exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(mWindow);
// Disable Vertical Synchronization
glfwSwapInterval(0);
// Initialize the GLEW library
GLenum errorGLEW = glewInit();
if (errorGLEW != GLEW_OK) {
// Problem: glewInit failed, something is wrong
std::cerr << "GLEW Error : " << glewGetErrorString(errorGLEW) << std::endl;
assert(false);
std::exit(EXIT_FAILURE);
}
if (mIsMultisamplingActive) {
glEnable(GL_MULTISAMPLE);
}
glfwSetKeyCallback(mWindow, keyboard);
glfwSetMouseButtonCallback(mWindow, mouseButton);
glfwSetCursorPosCallback(mWindow, mouseMotion);
glfwSetScrollCallback(mWindow, scroll);
// Define the background color (black)
glClearColor(0.0, 0.0, 0.0, 1.0);
}
void TestbedApplication::update() {
// Physics simulation
mCurrentScene->update();
// Compute the current framerate
//application->computeFPS();
}
// Render
void TestbedApplication::render() {
// Render the scene
mCurrentScene->render();
// Display the GUI
mGUI.display();
// Check the OpenGL errors
checkOpenGLErrors();
}
// Set the dimension of the camera viewport
void TestbedApplication::reshape() {
// Get the framebuffer dimension
int width, height;
glfwGetFramebufferSize(mWindow, &width, &height);
// Resize the camera viewport of the current scene
mCurrentScene->reshape(width, height);
glViewport(0, 0, width, height);
}
// Start the main loop where rendering occur
void TestbedApplication::startMainLoop() {
// Loop until the user closes the window
while (!glfwWindowShouldClose(mWindow)) {
// Reshape the viewport
reshape();
// Call the update function
update();
// Swap front and back buffers
glfwSwapBuffers(mWindow);
// Process events
glfwPollEvents();
}
}
// Check the OpenGL errors
void TestbedApplication::checkOpenGLErrors() {
GLenum glError;
// Get the OpenGL errors
glError = glGetError();
// While there are errors
while (glError != GL_NO_ERROR) {
// Get the error string
const GLubyte* stringError = gluErrorString(glError);
// Display the error
if (stringError)
std::cerr << "OpenGL Error #" << glError << "(" << gluErrorString(glError) << std::endl;
else
std::cerr << "OpenGL Error #" << glError << " (no message available)" << std::endl;
// Get the next error
glError = glGetError();
}
}
// Compute the FPS
void TestbedApplication::computeFPS() {
mNbFrames++;
// Get the number of milliseconds since glutInit called
mCurrentTime = glfwGetTime();
// Calculate time passed
double timeInterval = mCurrentTime - mPreviousTime;
// Update the FPS counter each second
if(timeInterval > 1.0) {
// calculate the number of frames per second
mFPS = static_cast<double>(mNbFrames) / timeInterval;
// Set time
mPreviousTime = mCurrentTime;
// Reset frame count
mNbFrames = 0;
}
}
// GLFW error callback method
void TestbedApplication::error_callback(int error, const char* description) {
fputs(description, stderr);
}
// Display the GUI
void TestbedApplication::displayGUI() {
// Display the FPS
displayFPS();
}
// Display the FPS
void TestbedApplication::displayFPS() {
/*
std::stringstream ss;
ss << mFPS;
std::string fpsString = ss.str();
std::string windowTitle = mWindowTitle + " | FPS : " + fpsString;
glfwSetWindowTitle(mWindow, windowTitle.c_str());
*/
}
// Callback method to receive keyboard events
void TestbedApplication::keyboard(GLFWwindow* window, int key, int scancode,
int action, int mods) {
getInstance().mCurrentScene->keyboardEvent(key, scancode, action, mods);
}
// Callback method to receive scrolling events
void TestbedApplication::scroll(GLFWwindow* window, double xAxis, double yAxis) {
getInstance().mCurrentScene->scrollingEvent(xAxis, yAxis);
}
// Called when a mouse button event occurs
void TestbedApplication::mouseButton(GLFWwindow* window, int button, int action, int mods) {
getInstance().mCurrentScene->mouseButtonEvent(button, action, mods);
}
// Called when a mouse motion event occurs
void TestbedApplication::mouseMotion(GLFWwindow* window, double x, double y) {
getInstance().mCurrentScene->mouseMotionEvent(x, y);
}