diff --git a/common/controls.cpp b/common/controls.cpp index 2f57df5b4..b12be700f 100644 --- a/common/controls.cpp +++ b/common/controls.cpp @@ -1,6 +1,3 @@ -// Include GLFW -#include - // Include GLM #include #include @@ -28,11 +25,92 @@ float verticalAngle = 0.0f; // Initial Field of View float initialFoV = 45.0f; +#ifdef __USE_SDL_PLEASE +float speed = 1000.0f; +float mouseSpeed = 0.01f; + +void computeMatricesFromInputs( SDLApp& app ){ + + // SDL_GetTicks is called only once, the first time this function is called + static float lastTime = float( SDL_GetTicks() ) / 1000.0f; + + // Compute time difference between current and last frame + float currentTime = float( SDL_GetTicks() ) / 1000.0f; + float deltaTime = (currentTime - lastTime) / 1000.0f; + + // Get mouse position + int xpos, ypos; + app.getMouse( &xpos, &ypos ); + + // Reset mouse position for next frame + app.setMouse( -1, -1 ); + + int resx=0, resy=0; + + app.getResolution( &resx, &resy ); + + // Compute new orientation + horizontalAngle += (mouseSpeed*-1.5) * float( (resx/2) - xpos ); + verticalAngle += mouseSpeed * float( (resy/2) - ypos ); + + // Direction : Spherical coordinates to Cartesian coordinates conversion + glm::vec3 direction( + cos(verticalAngle) * sin(horizontalAngle), + sin(verticalAngle), + cos(verticalAngle) * cos(horizontalAngle) + ); + + // Right vector + glm::vec3 right = glm::vec3( + sin(horizontalAngle - 3.14f/2.0f), + 0, + cos(horizontalAngle - 3.14f/2.0f) + ); + + // Up vector + glm::vec3 up = glm::cross( right, direction ); + + bool d_forward = app.getKey( SDLK_UP ) || app.getKey( SDLK_w ); + bool d_backward = app.getKey( SDLK_DOWN ) || app.getKey( SDLK_s ); + bool d_right = app.getKey( SDLK_RIGHT ) || app.getKey( SDLK_d ); + bool d_left = app.getKey( SDLK_LEFT ) || app.getKey( SDLK_a ); + + // Move forward + if ( d_forward ){ + position += direction * deltaTime * speed; + } + // Move backward + if ( d_backward ){ + position -= direction * deltaTime * speed; + } + // Strafe right + if ( d_right ){ + position += right * deltaTime * speed; + } + // Strafe left + if ( d_left ){ + position -= right * deltaTime * speed; + } + + float FoV = initialFoV - 5 * app.getMouseWheel(); + + // Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units + ProjectionMatrix = glm::perspective(FoV, 4.0f / 3.0f, 0.1f, 100.0f); + // Camera matrix + ViewMatrix = glm::lookAt( + position, // Camera is here + position+direction, // and looks here : at the same position, plus "direction" + up // Head is up (set to 0,-1,0 to look upside-down) + ); + + // For the next frame, the "last time" will be "now" + lastTime = currentTime; +} +#else float speed = 3.0f; // 3 units / second float mouseSpeed = 0.005f; - -void computeMatricesFromInputs(){ +void computeMatricesFromInputs( ) { // glfwGetTime is called only once, the first time this function is called static double lastTime = glfwGetTime(); @@ -99,4 +177,5 @@ void computeMatricesFromInputs(){ // For the next frame, the "last time" will be "now" lastTime = currentTime; -} \ No newline at end of file +} +#endif diff --git a/common/controls.hpp b/common/controls.hpp index 539d679a1..6fddd473e 100644 --- a/common/controls.hpp +++ b/common/controls.hpp @@ -1,7 +1,15 @@ #ifndef CONTROLS_HPP #define CONTROLS_HPP +// *NEW - Can now target either glfw or SDL 1.3! +#ifdef __USE_SDL_PLEASE +#include +#include "sdlapp.hpp" +void computeMatricesFromInputs( SDLApp& app ); +#else +#include void computeMatricesFromInputs(); +#endif glm::mat4 getViewMatrix(); glm::mat4 getProjectionMatrix(); diff --git a/common/sdlapp.cpp b/common/sdlapp.cpp new file mode 100644 index 000000000..6d4908f37 --- /dev/null +++ b/common/sdlapp.cpp @@ -0,0 +1,161 @@ +#include "sdlapp.hpp" + +SDLApp::SDLApp( std::string wtitle, int w, int h, int depth, int glVersion[], bool doubleBuffer, bool vsync, bool fullscreen ) +: running(true), _mousewheel(0), rx(w), ry(h), frames(0), fps(0) +{ + Uint32 flags = SDL_WasInit( 0 ); + if( !( flags & SDL_INIT_VIDEO ) && !( flags & SDL_INIT_TIMER ) ) { + if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER ) != 0 ) throw SDLexc(); + } + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, glVersion[0]); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, glVersion[1]); + + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); + + if( doubleBuffer == true ) SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1 ); + //SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, depth); // This seems to crash the OpenGL context + // May or may not be a SDL problem + + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + + Uint32 windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN; + if( fullscreen == true ) windowFlags |= SDL_WINDOW_FULLSCREEN; + this->wnd = SDL_CreateWindow( + wtitle.c_str(), + SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + w, h, + windowFlags + ); + + if( this->wnd == NULL ) { + this->setErrorFromSDL( ); + return; + } + + this->ctx = SDL_GL_CreateContext( this->wnd ); + + if( SDL_GL_MakeCurrent( this->wnd, this->ctx ) != 0 ) { + this->setErrorFromSDL( ); + return; + } + + glewExperimental = GL_TRUE; + if( glewInit() != GLEW_OK ) { + this->setError( "Could not initialize glew" ); + return; + } + + SDL_GL_SetSwapInterval( (vsync==true)?1:0 ); + + SDL_ShowCursor(0); + + this->timer = SDL_GetTicks()+1000; +} +SDLApp::~SDLApp( ) { + if( this->wnd != NULL ) SDL_DestroyWindow( this->wnd ); + this->wnd = NULL; + SDL_Quit( ); +} +void SDLApp::setWindowTitle( const std::string& newtitle ) { + SDL_SetWindowTitle( this->wnd, newtitle.c_str() ); +} +void SDLApp::getResolution( int *x, int *y ) { + *x = rx; + *y = ry; +} +void SDLApp::setMouse( int x, int y ) { + int appw=0, apph=0; + int px=0, py=0; + SDL_GetWindowSize( this->wnd, &appw, &apph ); + px = x; + py = y; + if( x < 0 ) px = appw/2; + if( y < 0 ) py = apph/2; + SDL_WarpMouseInWindow( this->wnd, px, py ); +} +Uint8 SDLApp::getMouse( int *x, int *y ) { + return SDL_GetMouseState( x, y ); +} +bool SDLApp::getKey( int key ) { + for( std::vector< int >::iterator it = this->keys.begin(); it != this->keys.end(); ++it) { + if( *it == key ) return true; + } + return false; +} +int SDLApp::getMouseWheel( void ) { + return this->_mousewheel; +} +void SDLApp::handleInput( void ) { + SDL_Event e; + bool found = false; + + while( SDL_PollEvent( &e ) ) { + switch( e.type ) { + case SDL_KEYDOWN: + found = false; + for( std::vector< int >::iterator it = this->keys.begin(); it != this->keys.end(); ++it) { + if( *it == e.key.keysym.sym ) { found = true; break; } + } + if( found == false ) { this->keys.push_back( e.key.keysym.sym ); } + if( e.key.keysym.sym == SDLK_ESCAPE ) { + this->running = false; + return; + } + break; + case SDL_KEYUP: + for( std::vector< int >::iterator it = this->keys.begin(); it != this->keys.end(); ++it) { + if( *it == e.key.keysym.sym ) { + this->keys.erase( it ); + break; + } + } + break; + case SDL_MOUSEWHEEL: + this->_mousewheel += ((e.wheel.y<0)?-1:((e.wheel.y>0)?1:0)); + break; + case SDL_QUIT: + this->running = false; + break; + } + } + + return; +} +void SDLApp::glSwap( ) { + SDL_GL_SwapWindow( this->wnd ); + this->frames++; + Uint32 now = SDL_GetTicks(); + if( now > (this->timer) ) { + this->timer = now + 1000; + this->fps = this->frames; + this->frames = 0; + } +} +bool SDLApp::keepRunning( void ) { + return this->running; +} +bool SDLApp::hasError( std::string& errorStr ) { + errorStr = this->errorMessage; + return (this->errorMessage.size()>0)?true:false; +} +int SDLApp::getFramesPerSecond( void ) { + return this->fps; +} +void SDLApp::setErrorFromSDL( void ) { + if( SDL_HasError( ) ) + this->SetError( "SDL Error: " + std::string( SDL_GetError( ) ) ); + else + this->clearError( ); +} +void SDLApp::setError( std::string message ) { + this->errorMessage = message; + if( message.size()>0 ) this->running = false; // Kill app if there's an error. (Necessary?) +} +void SDLApp::clearError( void ) { + this->setError( "" ); +} diff --git a/common/sdlapp.hpp b/common/sdlapp.hpp new file mode 100644 index 000000000..34573c5a6 --- /dev/null +++ b/common/sdlapp.hpp @@ -0,0 +1,56 @@ + +#include + +#include +#include +#include + +#ifndef __opengltutorial_sdlapp +#define __opengltutorial_sdlapp 1 + + class SDLApp { + public: + SDLApp( std::string wtitle, int w, int h, int depth, int glVersion[], bool doubleBuffer=true, bool vsync=false, bool fullscreen=false ); + + ~SDLApp( ); + + void setWindowTitle( const std::string& newtitle ); + + void getResolution( int *x, int *y ); + + void setMouse( int x, int y ); + + Uint8 getMouse( int *x, int *y ); + + bool getKey( int key ); + + int getMouseWheel( void ); + + void handleInput( void ); + + void glSwap( ); + + bool keepRunning( void ); + + bool hasError( std::string& errorStr ); + + int getFramesPerSecond( void ); + + private: + void setErrorFromSDL( void ); + void setError( std::string message ); + void clearError( void ); + + SDL_Window *wnd; + SDL_GLContext ctx; + bool running; + std::vector< int > keys; + int _mousewheel; + int rx, ry; + Uint32 timer; + int frames; + int fps; + std::string errorMessage; + }; + +#endif \ No newline at end of file diff --git a/common/texture.cpp b/common/texture.cpp index 806d4488f..0f09e7992 100644 --- a/common/texture.cpp +++ b/common/texture.cpp @@ -1,10 +1,49 @@ -#include -#include -#include - #include +#include + +// *NEW - Can now target either glfw or SDL 1.3! + +#ifdef __USE_SDL_PLEASE + +#include +#include + +GLuint loadTexture(const char* path) { + GLuint texture; + + glPixelStorei( GL_UNPACK_ALIGNMENT, 4 ); + + glGenTextures( 1, &texture ); + glBindTexture( GL_TEXTURE_2D, texture ); + + SDL_Surface* surface = IMG_Load( path ); + + SDL_PixelFormat *format = surface->format; + + if( format->Amask ) { + glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); + //gluBuild2DMipmaps( GL_TEXTURE_2D, 4, surface->w, surface->h, GL_RGBA,GL_UNSIGNED_BYTE, surface->pixels ); + } else { + glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, surface->w, surface->h, 0, GL_RGB, GL_UNSIGNED_BYTE, surface->pixels ); + //gluBuild2DMipmaps( GL_TEXTURE_2D, 3, surface->w, surface->h, GL_RGB, GL_UNSIGNED_BYTE, surface->pixels ); + } + SDL_FreeSurface( surface ); + + // Nice trilinear filtering. + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); + glGenerateMipmap( GL_TEXTURE_2D ); + + return texture; +} +#else + #include +#include +#include GLuint loadBMP_custom(const char * imagepath){ @@ -196,4 +235,7 @@ GLuint loadDDS(const char * imagepath){ return textureID; -} \ No newline at end of file +} + + #endif + \ No newline at end of file diff --git a/common/texture.hpp b/common/texture.hpp index 38e0d423a..170a68cea 100644 --- a/common/texture.hpp +++ b/common/texture.hpp @@ -1,6 +1,11 @@ #ifndef TEXTURE_HPP #define TEXTURE_HPP +#ifdef __USE_SDL_PLEASE + +GLuint loadTexture(const char * imagepath); + +#else // Load a .BMP file using our custom loader GLuint loadBMP_custom(const char * imagepath); @@ -9,6 +14,6 @@ GLuint loadTGA_glfw(const char * imagepath); // Load a .DDS file using GLFW's own loader GLuint loadDDS(const char * imagepath); - +#endif #endif \ No newline at end of file diff --git a/tutorial06_keyboard_and_mouse/tutorial06.cpp b/tutorial06_keyboard_and_mouse/tutorial06.cpp index 07247a967..037c1ce41 100644 --- a/tutorial06_keyboard_and_mouse/tutorial06.cpp +++ b/tutorial06_keyboard_and_mouse/tutorial06.cpp @@ -5,8 +5,17 @@ // Include GLEW #include +#define __USE_SDL_PLEASE + +// *NEW - Use SDL rather than glfw as a compile-time switch +#ifdef __USE_SDL_PLEASE +// Include SDL +# include +# include +#else // Include GLFW -#include +# include +#endif // Include GLM #include @@ -17,39 +26,19 @@ using namespace glm; #include #include -int main( void ) -{ - // Initialise GLFW - if( !glfwInit() ) - { - fprintf( stderr, "Failed to initialize GLFW\n" ); - return -1; - } - - glfwOpenWindowHint(GLFW_FSAA_SAMPLES, 4); - glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3); - glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3); - glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); +#ifndef __USE_SDL_PLEASE +bool setup_glfw_window( std::string wtitle, int w, int h, int depth, int glVersion[] ); +#endif - // Open a window and create its OpenGL context - if( !glfwOpenWindow( 1024, 768, 0,0,0,0, 32,0, GLFW_WINDOW ) ) - { - fprintf( stderr, "Failed to open GLFW window\n" ); - glfwTerminate(); - return -1; - } - - // Initialize GLEW - if (glewInit() != GLEW_OK) { - fprintf(stderr, "Failed to initialize GLEW\n"); - return -1; - } +int main( int argc, char *argv[] ) +{ + int glVersion[2] = {3, 3}; // Make sure we're requesting OpenGL version 3.3 - glfwSetWindowTitle( "Tutorial 06" ); - - // Ensure we can capture the escape key being pressed below - glfwEnable( GLFW_STICKY_KEYS ); - glfwSetMousePos(1024/2, 768/2); +#ifdef __USE_SDL_PLEASE + SDLApp app( "Tutorial 06", 1024, 768, 32, glVersion, true, false, false ); +#else + setup_glfw_window( "Tutorial 06", 1024, 768, 32, glVersion ); +#endif // Dark blue background glClearColor(0.0f, 0.0f, 0.3f, 0.0f); @@ -178,7 +167,11 @@ int main( void ) glUseProgram(programID); // Compute the MVP matrix from keyboard and mouse input +#ifdef __USE_SDL_PLEASE + computeMatricesFromInputs( app ); +#else computeMatricesFromInputs(); +#endif glm::mat4 ProjectionMatrix = getProjectionMatrix(); glm::mat4 ViewMatrix = getViewMatrix(); glm::mat4 ModelMatrix = glm::mat4(1.0); @@ -224,12 +217,20 @@ int main( void ) glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); +#ifdef __USE_SDL_PLEASE + // *New: Gather and process input + app.handleInput( ); + + //*New: Swap buffers (The SDLApp way) + app.glSwap( ); +#else // Swap buffers glfwSwapBuffers(); } // Check if the ESC key was pressed or the window was closed while( glfwGetKey( GLFW_KEY_ESC ) != GLFW_PRESS && glfwGetWindowParam( GLFW_OPENED ) ); +#endif // Cleanup VBO and shader glDeleteBuffers(1, &vertexbuffer); @@ -243,3 +244,40 @@ int main( void ) return 0; } +#ifndef __USE_SDL_PLEASE +bool setup_glfw_window( std::string wtitle, int w, int h, int depth, int glVersion[] ) { + // Initialise GLFW + if( !glfwInit() ) + { + fprintf( stderr, "Failed to initialize GLFW\n" ); + return false; + } + + glfwOpenWindowHint(GLFW_FSAA_SAMPLES, 4); + glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, glVersion[0]); + glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, glVersion[1]); + glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + + // Open a window and create its OpenGL context + if( !glfwOpenWindow( w, h, 0, 0, 0, 0, depth, 0, GLFW_WINDOW ) ) + { + fprintf( stderr, "Failed to open GLFW window\n" ); + glfwTerminate(); + return false; + } + + // Initialize GLEW + if (glewInit() != GLEW_OK) { + fprintf(stderr, "Failed to initialize GLEW\n"); + return false; + } + + glfwSetWindowTitle( wtitle.c_str() ); + + // Ensure we can capture the escape key being pressed below + glfwEnable( GLFW_STICKY_KEYS ); + glfwSetMousePos(w/2, h/2); + + return true; +} +#endif \ No newline at end of file