diff --git a/CMake/FindGLEW.cmake b/CMake/FindGLEW.cmake new file mode 100644 index 0000000..ce8c592 --- /dev/null +++ b/CMake/FindGLEW.cmake @@ -0,0 +1,31 @@ +# Tries to find GLEW +# +# Sets variables +# GLEW_FOUND +# GLEW_INCLUDE_DIR +# GLEW_LIBRARIES +# +SET (GLEW_FOUND FALSE) + +FIND_PATH (GLEW_INCLUDE_DIR glew.h /usr/include/ /usr/local/include/ /usr/include/GL /usr/local/include/GL $ENV{GLEW_PATH}/include $ENV{GLEW_INCLUDE_PATH}) + +FIND_LIBRARY (GLEW_LIBRARIES NAMES GLEW PATHS /usr/lib /usr/local/lib $ENV{GLEW_PATH} $ENV{GLEW_PATH}/lib ENV{GLEW_LIBRARY_PATH}) + +IF (GLEW_INCLUDE_DIR AND GLEW_LIBRARIES) + SET (GLEW_FOUND TRUE) +ENDIF (GLEW_INCLUDE_DIR AND GLEW_LIBRARIES) + +IF (GLEW_FOUND) + IF (NOT GLEW_FIND_QUIETLY) + MESSAGE(STATUS "Found GLEW: ${GLEW_LIBRARIES}") + ENDIF (NOT GLEW_FIND_QUIETLY) +ELSE (GLEW_FOUND) + IF (GLEW_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find GLEW") + ENDIF (GLEW_FIND_REQUIRED) +ENDIF (GLEW_FOUND) + +MARK_AS_ADVANCED ( + GLEW_INCLUDE_DIR + GLEW_LIBRARIES + ) diff --git a/CMakeLists.txt b/CMakeLists.txt index d4d6af6..d29d913 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,7 @@ SET (CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) FIND_PACKAGE (SDL REQUIRED) FIND_PACKAGE (SDL_net REQUIRED) +FIND_PACKAGE (GLEW REQUIRED) INCLUDE_DIRECTORIES ( engine/ @@ -21,6 +22,7 @@ INCLUDE_DIRECTORIES ( engine/libraries/coll2d/include engine/libraries/oglft/liboglft ${FREETYPE2_INCLUDE_DIR} + ${GLEW_INCLUDE_DIR} ) ADD_SUBDIRECTORY ( engine ) diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 69c1628..6dee331 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -6,6 +6,7 @@ FIND_PACKAGE (SDL REQUIRED) FIND_PACKAGE (SDL_mixer REQUIRED) FIND_PACKAGE (SDL_net REQUIRED) FIND_PACKAGE (OpenGL REQUIRED) +FIND_PACKAGE (GLEW REQUIRED) FIND_PACKAGE (PNG REQUIRED) FIND_PACKAGE (FreeType2 REQUIRED) FIND_PACKAGE (Boost COMPONENTS filesystem REQUIRED) @@ -51,6 +52,7 @@ INCLUDE_DIRECTORIES ( libraries/oglft/liboglft libraries/sha2/ ${FREETYPE2_INCLUDE_DIR} + ${GLEW_INCLUDE_DIR} ) ADD_LIBRARY ( Engine STATIC ${ENGINE_SRCS} ) @@ -60,6 +62,7 @@ TARGET_LINK_LIBRARIES ( Engine ${SDLMIXER_LIBRARY} ${SDLNET_LIBRARY} ${OPENGL_LIBRARIES} + ${GLEW_LIBRARIES} ${PNG_LIBRARIES} ${Boost_LIBRARIES} mathlib diff --git a/engine/Engine.h b/engine/Engine.h index ee2adae..97eb656 100644 --- a/engine/Engine.h +++ b/engine/Engine.h @@ -19,11 +19,15 @@ #include #include +#include #include "Module.h" #include "EngineEnums.h" #include "Utils.h" +// Note: glew.h must be included before any other OpenGL include file! +#include + // Some ugly #defines /** \brief Defines the number of keys that can be defined for an EntityController diff --git a/engine/Sprite.cc b/engine/Sprite.cc index 9fa50e7..25a86a5 100644 --- a/engine/Sprite.cc +++ b/engine/Sprite.cc @@ -125,8 +125,8 @@ bool Sprite::LoadFromPNG (const std::string &filename) { png_read_image(png_ptr, row_pointers); //Now generate the OpenGL texture object - glGenTextures(1, &mGlTextureName); - glBindTexture(GL_TEXTURE_2D, mGlTextureName); + glGenTextures(1, &mGLTextureName); + glBindTexture(GL_TEXTURE_2D, mGLTextureName); bool mipmap = false; @@ -151,6 +151,25 @@ bool Sprite::LoadFromPNG (const std::string &filename) { return true; } +void draw_sprite_helper (float u_start, float u_end, float width, float height) { + /* + // debug drawing with colors + glBegin(GL_QUADS); + glTexCoord2f (u_start, 0.f); glColor3f (1.f, 0.f, 0.f); glVertex3f (0.f, 0.f, 0.f); + glTexCoord2f (u_end, 0.f); glColor3f (0.f, 1.f, 0.f); glVertex3f (0.f, 0.f, height); + glTexCoord2f (u_end, 1.f); glColor3f (0.f, 0.f, 1.f); glVertex3f (width, 0.f, height); + glTexCoord2f (u_start, 1.f); glColor3f (1.f, 0.f, 1.f); glVertex3f (width, 0.f,0.f); + glEnd(); + */ + + glBegin(GL_QUADS); + glTexCoord2f (u_start, 0.f); glColor3f (1.f, 0.f, 0.f); glVertex3f (0.f, 0.f, 0.f); + glTexCoord2f (u_end, 0.f); glColor3f (0.f, 1.f, 0.f); glVertex3f (0.f, 0.f, height); + glTexCoord2f (u_end, 1.f); glColor3f (0.f, 0.f, 1.f); glVertex3f (width, 0.f, height); + glTexCoord2f (u_start, 1.f); glColor3f (1.f, 0.f, 1.f); glVertex3f (width, 0.f,0.f); + glEnd(); +} + void Sprite::DrawAt (float xpos, float ypos, float zpos) { float u_start = 0., u_end = 1.; if (mAnimation) { @@ -167,14 +186,9 @@ void Sprite::DrawAt (float xpos, float ypos, float zpos) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture (GL_TEXTURE_2D, mGlTextureName); + glBindTexture (GL_TEXTURE_2D, mGLTextureName); - glBegin(GL_QUADS); - glTexCoord2f (u_start, 0.); glVertex3f (0., 0., 0.); - glTexCoord2f (u_end, 0.); glVertex3f (0., 0., mHeight); - glTexCoord2f (u_end, 1.); glVertex3f (mWidth, 0., mHeight); - glTexCoord2f (u_start, 1.); glVertex3f (mWidth, 0.,0.); - glEnd(); + draw_sprite_helper (u_start, u_end, mWidth, mHeight); glPopMatrix(); @@ -200,15 +214,13 @@ void Sprite::DrawAt2D (float xpos, float ypos) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture (GL_TEXTURE_2D, mGlTextureName); - - glBegin(GL_QUADS); + glBindTexture (GL_TEXTURE_2D, mGLTextureName); + glBegin (GL_QUADS); glTexCoord2f (u_start, 0.); glVertex2f (0., 0.); glTexCoord2f (u_end, 0.); glVertex2f (0., mHeight); glTexCoord2f (u_end, 1.); glVertex2f (mWidth, mHeight); glTexCoord2f (u_start, 1.); glVertex2f (mWidth,0.); - glEnd(); - + glEnd (); glPopMatrix(); glDisable(GL_TEXTURE_2D); @@ -229,14 +241,9 @@ void Sprite::DrawSubAt (unsigned int index, float xpos, float ypos, float zpos) glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture (GL_TEXTURE_2D, mGlTextureName); + glBindTexture (GL_TEXTURE_2D, mGLTextureName); - glBegin(GL_QUADS); - glTexCoord2f (u_start, 0.); glVertex3f (0., 0., 0.); - glTexCoord2f (u_end, 0.); glVertex3f (0., 0., mHeight); - glTexCoord2f (u_end, 1.); glVertex3f (mWidth, 0., mHeight); - glTexCoord2f (u_start, 1.); glVertex3f (mWidth, 0.,0.); - glEnd(); + draw_sprite_helper (u_start, u_end, mWidth, mHeight); glPopMatrix(); diff --git a/engine/Sprite.h b/engine/Sprite.h index 8a2adfd..54c74fc 100644 --- a/engine/Sprite.h +++ b/engine/Sprite.h @@ -2,29 +2,70 @@ #define SPRITE_H #include +#include namespace Engine { +/** \brief A simple sprite class that allows animations and multiple sprites in one image + * + * Sprites are drawn aligned with the XZ-plane and the Y-axis pointing up. + * + */ class Sprite { public: - Sprite() { - mScale = 1.; - mWidth = 0; - mHeight = 0; - mGlTextureName = 0; + Sprite() : + mScale (1.f), + mWidth (0), + mHeight (0), + mGLTextureName (0), + mSubSpriteCount (1), + mAnimation (false), + mAnimationFrameCount(1), + mAnimationTimer(0.f), + mAnimationFrameRate(0.f) + { } + Sprite (const Sprite &othersprite) : + mScale (othersprite.mScale), + mWidth (othersprite.mWidth), + mHeight (othersprite.mHeight), + mGLTextureName (othersprite.mGLTextureName), + mSubSpriteCount (othersprite.mSubSpriteCount), + mAnimation (othersprite.mAnimation), + mAnimationFrameCount(othersprite.mAnimationFrameCount), + mAnimationTimer(othersprite.mAnimationTimer), + mAnimationFrameRate(othersprite.mAnimationFrameRate) + {} + Sprite& operator= (const Sprite &othersprite) { + if (this != &othersprite) { + mScale = othersprite.mScale; + mWidth = othersprite.mWidth; + mHeight = othersprite.mHeight; + mGLTextureName = othersprite.mGLTextureName; + mSubSpriteCount = othersprite.mSubSpriteCount; + mAnimation = othersprite.mAnimation; + mAnimationFrameCount= othersprite.mAnimationFrameCount; + mAnimationTimer= othersprite.mAnimationTimer; + mAnimationFrameRate= othersprite.mAnimationFrameRate; + } - mAnimation = false; - mSubSpriteCount = 1; + return *this; } + /** \brief Loads a Sprite from a .png file */ bool LoadFromPNG (const std::string &filename); + /** \brief Draws a sprite with the center at the given position */ void DrawAt (float xpos, float ypos, float zpos); void DrawAt2D (float xpos, float ypos); unsigned int GetWidth() { return mWidth; }; unsigned int GetHeight() { return mHeight; }; + void SetSize (unsigned int width, unsigned int height) { + mWidth = width; + mHeight = height; + } void SetScale (float scale) { mScale = scale; }; + /** \brief Marks the sprite as an animation and initializes its animation values */ void SetAnimation (int frame_count, float frame_rate) { mAnimation = true; mAnimationFrameCount = frame_count; @@ -42,6 +83,18 @@ class Sprite { } } + void SetGLTextureName (GLuint texture_name) { + mGLTextureName = texture_name; + } + GLuint GetGLTextureName () { + return mGLTextureName; + } + + /** \brief Marks the Sprite as a collection of sprites + * + * All sprites have to be aligned in a row and the SubSprite + * functionality eases retrieval and drawing of individual sprites + */ void SetSubSpriteCount (const unsigned int count) { mSubSpriteCount = count; mWidth = static_cast(ceil (static_cast (mWidth / mSubSpriteCount))); @@ -56,7 +109,7 @@ class Sprite { unsigned int mWidth; unsigned int mHeight; - unsigned int mGlTextureName; + GLuint mGLTextureName; unsigned int mSubSpriteCount; @@ -66,6 +119,8 @@ class Sprite { float mAnimationFrameRate; }; +typedef boost::shared_ptr SpritePtr; + } #endif /* SPRITE_H */ diff --git a/engine/ViewBase.cc b/engine/ViewBase.cc index dfb158b..66e038d 100644 --- a/engine/ViewBase.cc +++ b/engine/ViewBase.cc @@ -60,7 +60,78 @@ int ViewBase::OnInit (int argc, char* argv[]) { InitGL (); Resize (mWindowWidth, mWindowHeight); - + + // Initialize GLEW and check for anything we need + GLenum err = glewInit(); + if (GLEW_OK != err) { + LogError ("Could not init GLEW properly: %s", glewGetErrorString(err)); + } + + LogDebug ("Using GLEW version %s", glewGetString(GLEW_VERSION)); + if (glewIsExtensionSupported("GL_ARB_vertex_buffer_object")) { + } else { + LogError ("VBOs are not supported!"); + } + + // read OpenGL version + std::string gl_version (reinterpret_cast(glGetString(GL_VERSION))); + if (gl_version.size() == 0) + LogError ("Could not retrieve GL version!"); + + std::string major_number_str = gl_version.substr(0, gl_version.find('.')); + std::string minor_number_str = gl_version.substr(major_number_str.size() + 1, gl_version.find_first_of(". ", major_number_str.size())); + + mGLVersionInfo.GLMajor = atoi (major_number_str.c_str()); + mGLVersionInfo.GLMinor = atoi (minor_number_str.c_str()); + + // read GLSL version + std::string glsl_version (reinterpret_cast(glGetString(GL_SHADING_LANGUAGE_VERSION))); + if (glsl_version.size() == 0) + LogError ("Could not retrieve GLSL version!"); + + major_number_str = glsl_version.substr(0, glsl_version.find('.')); + minor_number_str = glsl_version.substr(major_number_str.size() + 1, glsl_version.find_first_of(". ", major_number_str.size())); + + mGLVersionInfo.GLSLMajor = atoi (major_number_str.c_str()); + mGLVersionInfo.GLSLMinor = atoi (minor_number_str.c_str()); + + LogMessage ("GL Version = %s, gl_major = %d, gl_minor = %d", gl_version.c_str(), mGLVersionInfo.GLMajor, mGLVersionInfo.GLMinor); + LogMessage ("GLSL Version = %s, gl_major = %d, gl_minor = %d", gl_version.c_str(), mGLVersionInfo.GLSLMajor, mGLVersionInfo.GLSLMinor); + + if (mGLVersionInfo.GLMajor >= 2 && mGLVersionInfo.GLMinor >= 0) + mUseShaders = true; + else + mUseShaders = false; + + /* + // load the shaders if possible + if (mUseShaders) { + mBlinnPhongShader = LoadShaderProgram ("./data/shaders/blinn_phong.glsl"); + mNormalMappingShader = LoadShaderProgram ("./data/shaders/normal_mapping.glsl"); + } else { + mBlinnPhongShader = 0; + mNormalMappingShader = 0; + } + */ + + // Create a null texture that can be used for objects without textures + // taken from http://www.dhpoware.com/demos/glslNormalMapping.html + int pitch = ((2 * 32 + 31) & ~31) >> 3; // align to 4-byte boundaries + std::vector pixels(pitch * 2, 255); + mNullTexture = 0; + + glGenTextures(1, &mNullTexture); + glBindTexture(GL_TEXTURE_2D, mNullTexture); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_BGRA, + GL_UNSIGNED_BYTE, &pixels[0]); + + // Load fonts etc. LoadFont ("console.ttf"); mCurrentFont = mFonts["console.ttf"]; @@ -381,6 +452,22 @@ void ViewBase::DrawGLStringMeasure (const char* str, float *width, float *height // LogDebug ("measure bbox '%s' = %f,%f %f,%f",str, bbox.x_min_, bbox.y_min_, bbox.x_max_, bbox.y_max_); } +GLuint ViewBase::LoadTextureFromPNG (const std::string &filename) { + std::map::iterator texture_iterator = mGLTextures.find(filename); + + if (texture_iterator != mGLTextures.end()) { + return texture_iterator->second; + } + + Sprite temp_sprite; + temp_sprite.LoadFromPNG (filename.c_str()); + + // register the texture in the View + mGLTextures[filename] = temp_sprite.GetGLTextureName(); + + return temp_sprite.GetGLTextureName(); +} + void ViewBase::GetCamereEye (float *eye_out) { assert (mCamera); mCamera->GetEye (eye_out); diff --git a/engine/ViewBase.h b/engine/ViewBase.h index 4024ac4..1217fa1 100644 --- a/engine/ViewBase.h +++ b/engine/ViewBase.h @@ -4,6 +4,7 @@ #include "Engine.h" #include "EngineEnums.h" #include "OverlayBase.h" +#include "Sprite.h" // forward declarations for the OGLFT fonts namespace OGLFT { @@ -76,16 +77,6 @@ class ViewBase : public Module{ bool GetDrawGrid () { return mDrawGrid; }; void SetGridSize (int x, int z) { mGridSizeX = x; mGridSizeZ = z; } -// void AddOverlay (OverlayBasePtr overlay) { mOverlays.push_back (overlay); }; - - /* Input forwarding for the overlays */ - /* - bool SendKeyDown (const SDL_keysym &keysym); - bool SendKeyUp (const SDL_keysym &keysym); - bool SendMouseButtonUp (Uint8 button, Uint16 xpos, Uint16 ypos); - bool SendMouseButtonDown (Uint8 button, Uint16 xpos, Uint16 ypos); - */ - private: protected: /** \brief Initializes the system */ @@ -138,6 +129,26 @@ class ViewBase : public Module{ /** \brief Contains all the fonts that are to be used */ std::map mFonts; + GLuint LoadTextureFromPNG (const std::string &filename); + + /** \brief All loaded textures */ + std::map mGLTextures; + + /** \brief Whether we can use shader programs */ + bool mUseShaders; + + GLuint mBlinnPhongShader; + GLuint mNormalMappingShader; + + struct OpenGLVersionInfo { + int GLMajor; + int GLMinor; + int GLSLMajor; + int GLSLMinor; + } mGLVersionInfo; + + GLuint mNullTexture; + friend class Engine; friend class ControllerBase; };