diff --git a/graphics.cc b/graphics.cc index 4832d62..35513f5 100644 --- a/graphics.cc +++ b/graphics.cc @@ -1,100 +1,151 @@ #include "graphics.hh" +#include +#include +#include +#include + +#include +#include +#include + #include "model.hh" -#include using namespace std; -ACGL::OpenGL::SharedShaderProgram shader; -Level level; - -// gets called after the OpenGL window is prepared: -void initCustomResources() -{ - // define where shaders and textures can be found: - ACGL::Base::Settings::the()->setResourcePath("../"); - ACGL::Base::Settings::the()->setShaderPath("Shader/"); - ACGL::Base::Settings::the()->setTexturePath("Geometry/"); - ACGL::Base::Settings::the()->setGeometryPath("Geometry/"); - - // load Model to give shader correct Attribute locations - // TODO look up if this is really necessary, since this looks really stupid. - Model model = Model("Bunny.obj"); - - // look up all shader files starting with 'phong' and build a ShaderProgram from it: - shader = ACGL::OpenGL::ShaderProgramCreator("phong").attributeLocations( - model.getReference()->getAttributeLocations()).create(); - shader->use(); - - // load Level - level.load(shader); - - // just in case: check for errors - openGLCriticalError(); +Graphics::Graphics() { } -void deleteCustomResources() -{ - // we have memory management via reference counting, so nothing to do here +GLFWwindow* Graphics::getWindow() { + return window; } -void draw(float runTime) +void Graphics::setGLFWHintsForOpenGLVersion( unsigned int _version ) { - // update Level first TODO: move this with the rest of the stuff that doesn't belong here to main - level.update(runTime); +#ifdef __APPLE__ +#if (ACGL_OPENGL_VERSION >= 30) + // request OpenGL 3.2, will return a 4.1 context on Mavericks + glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 ); + glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 2 ); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); +#endif +#else +// non-apple + glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, _version / 10 ); + glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, _version % 10 ); + #ifdef ACGL_OPENGL_PROFILE_CORE + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + #endif +#endif +} +bool Graphics::createWindow() +{ + ///////////////////////////////////////////////////////////////////////////////////// + // Initialise GLFW + // + if ( !glfwInit() ) + { + ACGL::Utils::error() << "Failed to initialize GLFW" << endl; + exit( -1 ); + } + + ///////////////////////////////////////////////////////////////////////////////////// + // Configure OpenGL context + // + setGLFWHintsForOpenGLVersion( ACGL_OPENGL_VERSION ); + + // activate multisampling (second parameter is the number of samples): + //glfwWindowHint( GLFW_SAMPLES, 8 ); + + // request an OpenGL debug context: + glfwWindowHint( GLFW_OPENGL_DEBUG_CONTEXT, true ); + + // define whether the window can get resized: + glfwWindowHint(GLFW_RESIZABLE, false); + + // non-decorated windows can be used as splash screens: + //glfwWindowHint( GLFW_DECORATED, false ); + + ///////////////////////////////////////////////////////////////////////////////////// + // try to create an OpenGL context in a window and check the supported OpenGL version: + // R,G,B,A, Depth,Stencil + window = glfwCreateWindow(windowSize.x, windowSize.y, "SWP MarbleGame Group C", NULL, NULL); + if (!getWindow()) { + ACGL::Utils::error() << "Failed to open a GLFW window - requested OpenGL: " << ACGL_OPENGL_VERSION << endl; + return false; + } + glfwMakeContextCurrent(window); + ACGL::init(); + return true; +} + +Graphics::Graphics(glm::uvec2 windowSize, float nearPlane, float farPlane) { + this->windowSize = windowSize; + this->nearPlane = nearPlane; + this->farPlane = farPlane; +} + + +void Graphics::render(Level* level, ACGL::OpenGL::SharedShaderProgram shader) +{ // clear the framebuffer: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //set view and projection matrix - shader->setUniform("projectionMatrix", buildFrustum(75.0, 0.1, 100.0, (float)g_windowSize.x/(float)g_windowSize.y) ); - // the + (0,1,0) compensates bunny doesn't have its center at it's center - shader->setUniform("viewMatrix", buildViewMatrix()); + shader->setUniform("projectionMatrix", buildFrustum(75.0f, 0.1f, 100.0f, (float)windowSize.x/(float)windowSize.y) ); + shader->setUniform("viewMatrix", buildViewMatrix(level)); //set lighting parameters - if (level.getLights().size() > 0) { - shader->setUniform("lightCount", (int) level.getLights().size()); + if (level->getLights().size() > 0) { + shader->setUniform("lightCount", (int) level->getLights().size()); // TODO look into doing this less often // Build light position array - glm::vec3 lightSources[level.getLights().size()]; - for(unsigned int i = 0; igetLights().size()]; + for(unsigned int i = 0; igetLights().size(); i++) { + lightSources[i] = level->getLights()[i].getPosition(); } glUniform3fv(shader->getUniformLocation("lightSources"), sizeof(lightSources), (GLfloat*) lightSources); // Build light colour array - glm::vec3 lightColours[level.getLights().size()]; - for(unsigned int i = 0; igetLights().size()]; + for(unsigned int i = 0; igetLights().size(); i++) { + lightColours[i] = level->getLights()[i].getColour(); } glUniform3fv(shader->getUniformLocation("lightColors"), sizeof(lightColours), (GLfloat*) lightColours); // Build light attenuation array - float lightIntensities[level.getLights().size()]; - for(unsigned int i = 0; igetLights().size()]; + for(unsigned int i = 0; igetLights().size(); i++) { + lightIntensities[i] = level->getLights()[i].getIntensity(); } glUniform1fv(shader->getUniformLocation("lightIntensities"), sizeof(lightIntensities), (GLfloat*) lightIntensities); } // set Material Parameters - shader->setUniform("ambientColor", level.getAmbientLight()); + shader->setUniform("ambientColor", level->getAmbientLight()); shader->setUniform("camera", glm::vec3(0.0f, 0.0f, 0.0f)); // render the level(currently only a bunny): - level.render(); + level->render(); } -void resizeCallback( GLFWwindow *, int newWidth, int newHeight ) +void Graphics::setWindowSize(glm::uvec2 windowSize) { + this->windowSize = windowSize; +} + +void resizeCallback(Graphics* graphics, int newWidth, int newHeight) { // store the new window size and adjust the viewport: - g_windowSize = glm::uvec2( newWidth, newHeight); - glViewport( 0, 0, g_windowSize.x, g_windowSize.y ); + graphics->setWindowSize(glm::uvec2( newWidth, newHeight)); + glViewport( 0, 0, newWidth, newHeight); } -glm::mat4 buildFrustum( float phiInDegree, float _near, float _far, float aspectRatio) { +glm::mat4 Graphics::buildFrustum( float phiInDegree, float _near, float _far, float aspectRatio) { float phiHalfInRadians = 0.5*phiInDegree * (M_PI/180.0); float top = _near * tan( phiHalfInRadians ); @@ -105,12 +156,12 @@ glm::mat4 buildFrustum( float phiInDegree, float _near, float _far, float aspect return glm::frustum(left, right, bottom, top, _near, _far); } -glm::mat4 buildViewMatrix() { - glm::vec4 cameraVector = glm::vec4(0.0f, 0.0f, level.getCamera().getDistance(), 0.0f); +glm::mat4 Graphics::buildViewMatrix(Level* level) { + glm::vec4 cameraVector = glm::vec4(0.0f, 0.0f, level->getCamera().getDistance(), 0.0f); // rotate vector - glm::mat4 rotationMatrix = glm::rotate(level.getCamera().getRotation()[0], glm::vec3(1.0f, 0.0f, 0.0f)) * - glm::rotate(level.getCamera().getRotation()[1], glm::vec3(0.0f, 1.0f, 0.0f)) * glm::rotate(level.getCamera().getRotation()[2], glm::vec3(0.0f, 0.0f, 1.0f)); + glm::mat4 rotationMatrix = glm::rotate(level->getCamera().getRotation()[0], glm::vec3(1.0f, 0.0f, 0.0f)) * + glm::rotate(level->getCamera().getRotation()[1], glm::vec3(0.0f, 1.0f, 0.0f)) * glm::rotate(level->getCamera().getRotation()[2], glm::vec3(0.0f, 0.0f, 1.0f)); cameraVector = rotationMatrix * cameraVector; //construct lookAt (cameraPosition = cameraCenter + cameraVector - return glm::lookAt(level.getCameraCenter()->getPosition() + glm::vec3(cameraVector), level.getCameraCenter()->getPosition(), glm::vec3(0.0f, 1.0f, 0.0f)); + return glm::lookAt(level->getCameraCenter()->getPosition() + glm::vec3(cameraVector), level->getCameraCenter()->getPosition(), glm::vec3(0.0f, 1.0f, 0.0f)); } diff --git a/graphics.hh b/graphics.hh index 09a3a8b..c161227 100644 --- a/graphics.hh +++ b/graphics.hh @@ -1,26 +1,33 @@ #ifndef GRAPHICS_HH_INCLUDED #define GRAPHICS_HH_INCLUDED +#include -#include "main.hh" - -#include +#include #include +#include "level.hh" -// gets called after the OpenGL window is prepared, init of example specific stuff: -void initCustomResources(); +class Graphics { + public: + Graphics(glm::uvec2 windowSize, float nearPlane, float farPlane); + Graphics(); + void render(Level* level, ACGL::OpenGL::SharedShaderProgram shader); + // gets called at window resize: + void resizeCallback( GLFWwindow *, int newWidth, int newHeight ); + // to build the projection matrix: + glm::mat4 buildFrustum( float phiInDegree, float near, float far, float aspectRatio); + glm::mat4 buildViewMatrix(Level* level); + glm::uvec2 getWindowSize(); + bool createWindow(); + GLFWwindow* getWindow(); + void setWindowSize(glm::uvec2 windowSize); + private: + void setGLFWHintsForOpenGLVersion( unsigned int _version ); + glm::uvec2 windowSize; + float nearPlane; + float farPlane; + GLFWwindow* window; +}; -// gets called at application shutdown: -void deleteCustomResources(); - -// gets called ech frame, runTime is in seconds: -void draw(float runTime); - -// gets called at window resize: -void resizeCallback( GLFWwindow *, int newWidth, int newHeight ); - -// to build the projection matrix: -glm::mat4 buildFrustum( float phiInDegree, float near, float far, float aspectRatio); - -glm::mat4 buildViewMatrix(); +void resizeCallback(Graphics* graphics, int newWidth, int newHeight); #endif diff --git a/main.cc b/main.cc index 535705f..6efddf7 100644 --- a/main.cc +++ b/main.cc @@ -10,108 +10,63 @@ #include #include #include +#include +#include #include +#include + +#include "model.hh" using namespace std; using namespace ACGL::OpenGL; using namespace ACGL::Base; using namespace ACGL::Utils; -glm::uvec2 g_windowSize( 1024, 786 ); -float g_nearPlane = 0.1f; -float g_farPlane = 100.0f; -bool glfwWindowClosed = false; +Application::Application() { + graphics = Graphics(glm::uvec2(1024, 786), 0.1f, 100.0f); +} -GLFWwindow* g_window; +Graphics* Application::getGraphics() { + return &graphics; +} -void setGLFWHintsForOpenGLVersion( unsigned int _version ) +Level* Application::getLevel() { + return &level; +} + +ACGL::OpenGL::SharedShaderProgram Application::getShader() { + return shader; +} + +void Application::init() { -#ifdef __APPLE__ -#if (ACGL_OPENGL_VERSION >= 30) - // request OpenGL 3.2, will return a 4.1 context on Mavericks - glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 ); - glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 2 ); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); -#endif -#else -// non-apple - glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, _version / 10 ); - glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, _version % 10 ); - #ifdef ACGL_OPENGL_PROFILE_CORE - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - #endif -#endif + // define where shaders and textures can be found: + ACGL::Base::Settings::the()->setResourcePath("../"); + ACGL::Base::Settings::the()->setShaderPath("Shader/"); + ACGL::Base::Settings::the()->setTexturePath("Geometry/"); + ACGL::Base::Settings::the()->setGeometryPath("Geometry/"); + + // load Model to give shader correct Attribute locations + // TODO look up if this is really necessary, since this looks really stupid. + Model model = Model("Bunny.obj"); + + // look up all shader files starting with 'phong' and build a ShaderProgram from it: + shader = ACGL::OpenGL::ShaderProgramCreator("phong").attributeLocations( + model.getReference()->getAttributeLocations()).create(); + shader->use(); + + // load Level + level.load(shader); + + // just in case: check for errors + openGLCriticalError(); } /********************************************************************************************************************** * Returns true if a window with the desired context could get created. * Requested OpenGL version gets set by ACGL defines. */ -bool createWindow() -{ - ///////////////////////////////////////////////////////////////////////////////////// - // Initialise GLFW - // - if ( !glfwInit() ) - { - error() << "Failed to initialize GLFW" << endl; - exit( -1 ); - } - - ///////////////////////////////////////////////////////////////////////////////////// - // Configure OpenGL context - // - setGLFWHintsForOpenGLVersion( ACGL_OPENGL_VERSION ); - - // activate multisampling (second parameter is the number of samples): - //glfwWindowHint( GLFW_SAMPLES, 8 ); - - // request an OpenGL debug context: - glfwWindowHint( GLFW_OPENGL_DEBUG_CONTEXT, true ); - - // define whether the window can get resized: - //glfwWindowHint( GLFW_RESIZABLE, true ); - - // non-decorated windows can be used as splash screens: - //glfwWindowHint( GLFW_DECORATED, false ); - - // request an sRGB framebuffer: - //glfwWindowHint( GLFW_SRGB_CAPABLE, true ); - - //glfwWindowHint( , true ); - //glfwWindowHint( , true ); - //glfwWindowHint( , true ); - //glfwWindowHint( , true ); - - - ///////////////////////////////////////////////////////////////////////////////////// - // try to create an OpenGL context in a window and check the supported OpenGL version: - // R,G,B,A, Depth,Stencil - g_window = glfwCreateWindow( g_windowSize.x, g_windowSize.y, "ACGL GLFWExamples", NULL, NULL); - if (!g_window) { - error() << "Failed to open a GLFW window - requested OpenGL: " << ACGL_OPENGL_VERSION << endl; - return false; - } - glfwMakeContextCurrent(g_window); - ACGL::init(); - - ///////////////////////////////////////////////////////////////////////////////////// - // Init debug-extension - // - if (ACGL_ARB_debug_output()) { - //debug() << "GL_ARB_DEBUG_OUTPUT is supported, register callback" << endl; - //glDebugMessageCallbackARB( debugCallback, NULL); - - // filter out the strange performance warnings about shader recompiles: - //glDebugMessageControlARB( GL_DEBUG_SOURCE_API_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, GL_DEBUG_SEVERITY_MEDIUM_ARB, 0, NULL, GL_FALSE ); - } else { - //debug() << "GL_ARB_DEBUG_OUTPUT is missing!" << endl; - } - return true; -} static void keyCallback(GLFWwindow* _window, int _key, int, int _action, int) { @@ -121,15 +76,14 @@ static void keyCallback(GLFWwindow* _window, int _key, int, int _action, int) } -/********************************************************************************************************************** - * Generic main for different example apps - */ int main( int argc, char *argv[] ) { + Application app = Application(); + ///////////////////////////////////////////////////////////////////////////////////// // Create OpenGL capable window: // - if ( !createWindow() ) { + if ( !app.getGraphics()->createWindow() ) { glfwTerminate(); exit( -1 ); } @@ -138,11 +92,11 @@ int main( int argc, char *argv[] ) // Set window title to binary name (without the path): // std::vector tmp = StringHelpers::split( std::string( argv[0] ), '/' ); - glfwSetWindowTitle( g_window, tmp[tmp.size()-1].c_str() ); + glfwSetWindowTitle(app.getGraphics()->getWindow(), tmp[tmp.size()-1].c_str() ); // Ensure we can capture the escape key being pressed below - glfwSetInputMode( g_window, GLFW_STICKY_KEYS, 1 ); - glfwSetWindowSizeCallback( g_window, resizeCallback ); - glfwSetKeyCallback( g_window, keyCallback ); + glfwSetInputMode(app.getGraphics()->getWindow(), GLFW_STICKY_KEYS, 1 ); + //glfwSetWindowSizeCallback(app.getGraphics(), resizeCallback); + glfwSetKeyCallback(app.getGraphics()->getWindow(), keyCallback ); // Enable vertical sync (on cards that support it) with parameter 1 - 0 means off glfwSwapInterval( 0 ); @@ -152,7 +106,7 @@ int main( int argc, char *argv[] ) // glClearColor( 0.0, 0.0, 0.0, 1.0 ); glEnable( GL_DEPTH_TEST ); - initCustomResources(); + app.init(); int frameCount = 0; @@ -167,23 +121,23 @@ int main( int argc, char *argv[] ) stringstream sstream (stringstream::in | stringstream::out); sstream << setprecision(1) << std::fixed << tmp[tmp.size()-1] << " - FPS: " << frameCount / (now-showNextFPS + FPSdelay) << " " << 1000 * (now-showNextFPS + FPSdelay)/frameCount << " msec"; - glfwSetWindowTitle( g_window, sstream.str().c_str() ); + glfwSetWindowTitle(app.getGraphics()->getWindow(), sstream.str().c_str() ); showNextFPS = now + FPSdelay; frameCount = 0; } - draw( now - startTimeInSeconds ); + app.getLevel()->update(now - startTimeInSeconds); + app.getGraphics()->render(app.getLevel(), app.getShader()); + openGLCriticalError(); // MacOS X will not swap correctly is another FBO is bound: glBindFramebuffer( GL_FRAMEBUFFER, 0 ); - glfwSwapBuffers( g_window ); + glfwSwapBuffers(app.getGraphics()->getWindow()); glfwPollEvents(); frameCount++; } // Check if the window was closed - while( !glfwWindowShouldClose( g_window ) ); - - deleteCustomResources(); + while( !glfwWindowShouldClose(app.getGraphics()->getWindow()) ); glfwTerminate(); exit(0); diff --git a/main.hh b/main.hh index dfc33d3..17e8fad 100644 --- a/main.hh +++ b/main.hh @@ -1,27 +1,28 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////// -// -// headers needed: -// -#include +#ifndef MAIN_HH_INCLUDED +#define MAIN_HH_INCLUDED #include +#include #include #include -// -/////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// #include "physics.hh" #include "graphics.hh" #include "level.hh" -/////////////////////////////////////////////////////////////////////////////////////////////////// -// -// implement the following functions: -// +///////////////////////////////////////////////////////////////// +class Application { + public: + Application(); + Graphics* getGraphics(); + Level* getLevel(); + ACGL::OpenGL::SharedShaderProgram getShader(); + void init(); + private: + Graphics graphics; + Level level; + ACGL::OpenGL::SharedShaderProgram shader; +}; -// global variables exported by the generic main: -extern glm::uvec2 g_windowSize; -extern float g_nearPlane; -extern float g_farPlane; -// -/////////////////////////////////////////////////////////////////////////////////////////////////// +#endif