/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Benjamin Grauer co-programmer: ... */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_GRAPHICS #include "graphics_engine.h" #include "resource_manager.h" #include "debug.h" #include "text_engine.h" using namespace std; /** \brief standard constructor \todo this constructor is not jet implemented - do it */ GraphicsEngine::GraphicsEngine () { this->setClassID(CL_GRAPHICS_ENGINE, "GraphicsEngine"); this->setName("GraphicsEngine"); this->bDisplayFPS = false; this->minFPS = 9999; this->maxFPS = 0; this->fullscreen = false; this->initVideo(); this->listModes(); } /** \brief The Pointer to this GraphicsEngine */ GraphicsEngine* GraphicsEngine::singletonRef = NULL; /** \brief destructs the graphicsEngine. */ GraphicsEngine::~GraphicsEngine () { // delete what has to be deleted here } /** \brief initializes the Video for openGL. This has to be done only once when starting orxonox. */ int GraphicsEngine::initVideo() { // initialize SDL_VIDEO if (SDL_Init(SDL_INIT_VIDEO) == -1) { PRINTF(1)("could not initialize SDL Video\n"); // return -1; } // initialize SDL_GL-settings this->setGLattribs(); // setting the Video Flags. this->videoFlags = SDL_OPENGL | SDL_HWPALETTE | SDL_RESIZABLE | SDL_DOUBLEBUF; /* query SDL for information about our video hardware */ const SDL_VideoInfo* videoInfo = SDL_GetVideoInfo (); if( videoInfo == NULL) { PRINTF(1)("Failed getting Video Info :%s\n", SDL_GetError()); SDL_Quit (); } if( videoInfo->hw_available) this->videoFlags |= SDL_HWSURFACE; else this->videoFlags |= SDL_SWSURFACE; /* if(VideoInfo -> blit_hw) VideoFlags |= SDL_HWACCEL; */ // setting up the Resolution this->setResolution(800, 450, 16); // TO DO: Create a cool icon and use it here char* loadPic = new char[strlen(ResourceManager::getInstance()->getDataDir())+ 100]; sprintf(loadPic, "%s%s", ResourceManager::getInstance()->getDataDir(), "pictures/orxonox-icon32x32.bmp"); SDL_WM_SetIcon(SDL_LoadBMP(loadPic), NULL); delete loadPic; // Enable default GL stuff glEnable(GL_DEPTH_TEST); } /** * sets the Window Captions and the Name of the icon. * @param windowName The name of the Window * @param icon The name of the Icon on the Disc */ void GraphicsEngine::setWindowName(const char* windowName, const char* icon) { // Set window labeling SDL_WM_SetCaption (windowName, icon); } /** \brief Sets the GL-attributes */ int GraphicsEngine::setGLattribs() { // Set video mode // TO DO: parse arguments for settings //SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); //SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); //SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); //SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16); SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, 0); SDL_GL_SetAttribute( SDL_GL_ACCUM_RED_SIZE, 0); SDL_GL_SetAttribute( SDL_GL_ACCUM_GREEN_SIZE, 0); SDL_GL_SetAttribute( SDL_GL_ACCUM_BLUE_SIZE, 0); SDL_GL_SetAttribute( SDL_GL_ACCUM_ALPHA_SIZE, 0); } /** \brief sets the Resolution of the Screen to display the Graphics to. \param width The width of the window \param height The height of the window \param bpp bits per pixel */ int GraphicsEngine::setResolution(int width, int height, int bpp) { Uint32 fullscreenFlag; this->resolutionX = width; this->resolutionY = height; this->bitsPerPixel = bpp; if (this->fullscreen) fullscreenFlag = SDL_FULLSCREEN; else fullscreenFlag = 0; if((this->screen = SDL_SetVideoMode(this->resolutionX, this->resolutionY, this->bitsPerPixel, this->videoFlags | fullscreenFlag)) == NULL) { PRINTF(1)("Could not SDL_SetVideoMode(%d, %d, %d, %d): %s\n", this->resolutionX, this->resolutionY, this->bitsPerPixel, this->videoFlags, SDL_GetError()); SDL_Quit(); // return -1; } } /** \brief sets Fullscreen mode \param fullscreen true if fullscreen, false if windowed */ void GraphicsEngine::setFullscreen(bool fullscreen) { this->fullscreen = fullscreen; this->setResolution(this->resolutionX, this->resolutionY, this->bitsPerPixel); } /** \brief sets the background color \param red the red part of the background \param blue the blue part of the background \param green the green part of the background \param alpha the alpha part of the background */ void GraphicsEngine::setBackgroundColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { glClearColor(red, green, blue, alpha); } /** \brief Signalhandler, for when the resolution has changed \param resizeInfo SDL information about the size of the new screen size */ int GraphicsEngine::resolutionChanged(SDL_ResizeEvent* resizeInfo) { this->setResolution(resizeInfo->w, resizeInfo->h, this->bitsPerPixel); } /** \brief if Textures should be enabled */ bool GraphicsEngine::texturesEnabled = true; /** \brief entering 2D Mode this is a GL-Projection-mode, that is orthogonal, for placing the font in fron of everything else */ void GraphicsEngine::enter2DMode() { GraphicsEngine::storeMatrices(); SDL_Surface *screen = SDL_GetVideoSurface(); /* Note, there may be other things you need to change, depending on how you have your OpenGL state set up. */ glPushAttrib(GL_ENABLE_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glDisable(GL_LIGHTING); // will be set back when leaving 2D-mode glEnable(GL_TEXTURE_2D); /* This allows alpha blending of 2D textures with the scene */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glViewport(0, 0, screen->w, screen->h); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0.0, (GLdouble)screen->w, (GLdouble)screen->h, 0.0, 0.0, 1.0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } /** \brief leaves the 2DMode again also \see Font::enter2DMode() */ void GraphicsEngine::leave2DMode() { glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); } /** \brief stores the GL_matrices */ void GraphicsEngine::storeMatrices() { glGetDoublev(GL_PROJECTION_MATRIX, GraphicsEngine::projMat); glGetDoublev(GL_MODELVIEW_MATRIX, GraphicsEngine::modMat); glGetIntegerv(GL_VIEWPORT, GraphicsEngine::viewPort); } //! the stored ModelView Matrix. GLdouble GraphicsEngine::modMat[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //! the stored Projection Matrix GLdouble GraphicsEngine::projMat[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //! The ViewPort GLint GraphicsEngine::viewPort[4] = {0,0,0,0}; /** \brief outputs all the Fullscreen modes. */ void GraphicsEngine::listModes() { /* Get available fullscreen/hardware modes */ this->videoModes=SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_HWSURFACE); /* Check is there are any modes available */ if(this->videoModes == (SDL_Rect **)0){ PRINTF(1)("No modes available!\n"); exit(-1); } /* Check if our resolution is restricted */ if(this->videoModes == (SDL_Rect **)-1){ PRINTF(2)("All resolutions available.\n"); } else{ /* Print valid modes */ PRINT(0)("Available Resoulution Modes are\n"); for(int i = 0; this->videoModes[i]; ++i) PRINT(4)(" | %d x %d\n", this->videoModes[i]->w, this->videoModes[i]->h); } } /** \brief ticks the Text \param dt the time passed */ void GraphicsEngine::tick(float dt) { if( unlikely(this->bDisplayFPS)) { this->currentFPS = 1.0/dt; if( unlikely(this->currentFPS > this->maxFPS)) this->maxFPS = this->currentFPS; if( unlikely(this->currentFPS < this->minFPS)) this->minFPS = this->currentFPS; #ifndef NO_TEXT char tmpChar1[20]; sprintf(tmpChar1, "Current: %4.0f", this->currentFPS); this->geTextCFPS->setText(tmpChar1); char tmpChar2[20]; sprintf(tmpChar2, "Max: %4.0f", this->maxFPS); this->geTextMaxFPS->setText(tmpChar2); char tmpChar3[20]; sprintf(tmpChar3, "Min: %4.0f", this->minFPS); this->geTextMinFPS->setText(tmpChar3); #endif /* NO_TEXT */ } } /** \brief displays the Frames per second \param display if the text should be displayed \todo this is dangerous */ void GraphicsEngine::displayFPS(bool display) { if( display) { #ifndef NO_TEXT this->geTextCFPS = TextEngine::getInstance()->createText("fonts/arial_black.ttf", 15, TEXT_DYNAMIC, 0, 255, 0); this->geTextCFPS->setAlignment(TEXT_ALIGN_LEFT); this->geTextCFPS->setPosition(5, 500); this->geTextMaxFPS = TextEngine::getInstance()->createText("fonts/arial_black.ttf", 15, TEXT_DYNAMIC, 0, 255, 0); this->geTextMaxFPS->setAlignment(TEXT_ALIGN_LEFT); this->geTextMaxFPS->setPosition(5, 530); this->geTextMinFPS = TextEngine::getInstance()->createText("fonts/arial_black.ttf", 35, TEXT_DYNAMIC, 0, 255, 0); this->geTextMinFPS->setAlignment(TEXT_ALIGN_LEFT); this->geTextMinFPS->setPosition(5, 560); #endif /* NO_TEXT */ } this->bDisplayFPS = display; }