From 9978cbeff518543dce29db72dd96af0b62ebbae5 Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Mon, 1 Nov 2010 16:44:05 +0000 Subject: [PATCH] - added some initial work to support FBO (frame buffer objects) - added many NULL check guards throughout the code - added a safe mutex around ptr access of background thread on custom menu --- source/glest_game/ai/path_finder.cpp | 4 +- source/glest_game/game/game_camera.cpp | 3 + source/glest_game/graphics/renderer.cpp | 198 +++++++-- source/glest_game/graphics/renderer.h | 4 +- .../menu/menu_state_custom_game.cpp | 80 +++- .../glest_game/menu/menu_state_custom_game.h | 6 + source/glest_game/type_instances/faction.cpp | 361 ++++++++-------- source/glest_game/type_instances/object.cpp | 1 - source/glest_game/type_instances/unit.cpp | 1 - source/glest_game/world/map.cpp | 55 ++- source/glest_game/world/map.h | 8 +- source/glest_game/world/tileset.cpp | 33 +- source/glest_game/world/world.cpp | 388 +++++++++++------- .../include/graphics/gl/texture_gl.h | 34 +- source/shared_lib/include/graphics/texture.h | 17 +- .../sources/graphics/gl/texture_gl.cpp | 147 ++++++- 16 files changed, 946 insertions(+), 394 deletions(-) diff --git a/source/glest_game/ai/path_finder.cpp b/source/glest_game/ai/path_finder.cpp index 31384a7c..96805a1d 100644 --- a/source/glest_game/ai/path_finder.cpp +++ b/source/glest_game/ai/path_finder.cpp @@ -413,7 +413,9 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout } else { canUnitMoveToCell = map->aproxCanMove(unit, node->pos, sucPos); - localCacheForUnitCellMovement[node->pos][sucPos] = canUnitMoveToCell; + if(Config::getInstance().getBool("DisableCaching","false") == false) { + localCacheForUnitCellMovement[node->pos][sucPos] = canUnitMoveToCell; + } } if(openPos(sucPos) == false && canUnitMoveToCell == true) { diff --git a/source/glest_game/game/game_camera.cpp b/source/glest_game/game/game_camera.cpp index 1e722136..2ac12417 100644 --- a/source/glest_game/game/game_camera.cpp +++ b/source/glest_game/game/game_camera.cpp @@ -50,6 +50,9 @@ GameCamera::GameCamera() : pos(0.f, defaultHeight, 0.f), cacheVisibleQuad.clear(); MaxVisibleQuadItemCache = config.getInt("MaxVisibleQuadItemCache",intToStr(-1).c_str()); + if(Config::getInstance().getBool("DisableCaching","false") == true) { + MaxVisibleQuadItemCache = 0; + } //config speed= 15.f / GameConstants::cameraFps; diff --git a/source/glest_game/graphics/renderer.cpp b/source/glest_game/graphics/renderer.cpp index 00339b7e..140dfe1d 100644 --- a/source/glest_game/graphics/renderer.cpp +++ b/source/glest_game/graphics/renderer.cpp @@ -32,6 +32,7 @@ using namespace Shared::Graphics; using namespace Shared::Graphics::Gl; using namespace Shared::Util; +using namespace Shared::Graphics; namespace Glest { namespace Game{ @@ -2960,7 +2961,7 @@ void Renderer::clearZBuffer(){ glClear(GL_DEPTH_BUFFER_BIT); } -void Renderer::loadConfig(){ +void Renderer::loadConfig() { Config &config= Config::getInstance(); //cache most used config params @@ -2986,6 +2987,36 @@ void Renderer::loadConfig(){ } } +Texture2D *Renderer::saveScreenToTexture(int x, int y, int width, int height) { + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + + Config &config= Config::getInstance(); + Texture2D::Filter textureFilter = strToTextureFilter(config.getString("Filter")); + int maxAnisotropy = config.getInt("FilterMaxAnisotropy"); + + Texture2D *texture = GraphicsInterface::getInstance().getFactory()->newTexture2D(); + //texture->setFormat(Texture::fRgba); + texture->setForceCompressionDisabled(true); + texture->setMipmap(false); + //Pixmap2D *pixmapScreenShot = new Pixmap2D(width, height, 3); + Pixmap2D *pixmapScreenShot = texture->getPixmap(); + pixmapScreenShot->init(width, height, 3); + //const Metrics &sm= Metrics::getInstance(); + //pixmapScreenShot->init(sm.getScreenW(), sm.getScreenH(), 3); + texture->init(textureFilter,maxAnisotropy); + + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + //glFinish(); + + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + glReadPixels(x, y, pixmapScreenShot->getW(), pixmapScreenShot->getH(), + GL_RGB, GL_UNSIGNED_BYTE, pixmapScreenShot->getPixels()); + + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + + return texture; +} + void Renderer::saveScreen(const string &path) { const Metrics &sm= Metrics::getInstance(); @@ -3834,6 +3865,14 @@ void Renderer::renderTile(const Vec2i &pos) { } void Renderer::renderQuad(int x, int y, int w, int h, const Texture2D *texture) { + + if(w < 0) { + w = texture->getPixmap()->getW(); + } + if(h < 0) { + h = texture->getPixmap()->getH(); + } + glBindTexture(GL_TEXTURE_2D, static_cast(texture)->getHandle()); glBegin(GL_TRIANGLE_STRIP); glTexCoord2i(0, 1); @@ -4055,7 +4094,8 @@ VisibleQuadContainerCache & Renderer::getQuadCache( bool updateOnDirtyFrame, } void Renderer::renderMapPreview( const MapPreview *map, bool renderAll, - int screenPosX, int screenPosY) { + int screenPosX, int screenPosY, + Texture2D **renderToTexture) { float alt=0; float showWater=0; int renderMapHeight=64; @@ -4077,23 +4117,75 @@ void Renderer::renderMapPreview( const MapPreview *map, bool renderAll, assertGl(); +/* + if(renderToTexture != NULL) { + Config &config= Config::getInstance(); + Texture2D::Filter textureFilter = strToTextureFilter(config.getString("Filter")); + int maxAnisotropy = config.getInt("FilterMaxAnisotropy"); + + *renderToTexture = GraphicsInterface::getInstance().getFactory()->newTexture2D(); + Texture2DGl *texture = static_cast(*renderToTexture); + //texture->setFormat(Texture::fAlpha); + texture->setMipmap(false); + Pixmap2D *pixmapScreenShot = texture->getPixmap(); + pixmapScreenShot->init(metrics.getVirtualW(), metrics.getVirtualH(), 3); + //pixmapScreenShot->init(map->getW(),map->getH(),3); + //pixmapScreenShot->init(200, 360, 3); + texture->setForceCompressionDisabled(true); + texture->init(textureFilter,maxAnisotropy); + + + //texture->initFrameBuffer(); + //texture->attachFrameBufferToTexture(); + + //texture->initRenderBuffer(); + //texture->attachRenderBuffer(); + + texture->setup_FBO_RBO(); + + if(texture->checkFrameBufferStatus() == false) { + //printf("******************** WARNING CANNOT Attach to FBO!\n"); + texture->end(); + delete texture; + *renderToTexture=NULL; + } + } +*/ + glFrontFace(GL_CW); glEnable(GL_CULL_FACE); + //glDisable(GL_DEPTH_TEST); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); - // glViewport(screenPosX, screenPosY, sizeH,sizeW); + //glViewport(screenPosX, screenPosY, metrics.getVirtualW(),metrics.getVirtualH()); // glOrtho(0, clientW, 0, clientH, -1, 1); + + //glOrtho(screenPosX, screenPosX+clientW, screenPosY+clientH, screenPosY, 0, 1); glOrtho(0, metrics.getVirtualW(), 0, metrics.getVirtualH(), 0, 1); - + //gluOrtho2D (0, metrics.getVirtualW(), 0, metrics.getVirtualH()); + + //glEnable( GL_SCISSOR_TEST ); + //glScissor(screenPosX, screenPosY,metrics.getVirtualW(), metrics.getVirtualH()); + glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); + glTranslatef(static_cast(screenPosX),static_cast(screenPosY)-clientH,0.0f); + + //glEnable( GL_SCISSOR_TEST ); + //glScissor(screenPosX, screenPosY,screenPosX-clientW, screenPosY-clientH); + //int newX = screenPosX - (metrics.getVirtualW() / 2); + //int newY = screenPosY - (metrics.getVirtualH() / 2); + //int newX = 0; + //int newY = 0; + //glTranslatef(static_cast(newX),static_cast(newY),0.0f); + glPushAttrib(GL_CURRENT_BIT); //glTranslatef(static_cast(x), static_cast(y), 0.0f); glLineWidth(1); @@ -4108,11 +4200,21 @@ void Renderer::renderMapPreview( const MapPreview *map, bool renderAll, showWater = (showWater > 0)? showWater:0; Vec3f surfColor; switch (map->getSurface(i, j)) { - case st_Grass: surfColor = Vec3f(0.0, 0.8f * alt, 0.f + showWater); break; - case st_Secondary_Grass: surfColor = Vec3f(0.4f * alt, 0.6f * alt, 0.f + showWater); break; - case st_Road: surfColor = Vec3f(0.6f * alt, 0.3f * alt, 0.f + showWater); break; - case st_Stone: surfColor = Vec3f(0.7f * alt, 0.7f * alt, 0.7f * alt + showWater); break; - case st_Ground: surfColor = Vec3f(0.7f * alt, 0.5f * alt, 0.3f * alt + showWater); break; + case st_Grass: + surfColor = Vec3f(0.0, 0.8f * alt, 0.f + showWater); + break; + case st_Secondary_Grass: + surfColor = Vec3f(0.4f * alt, 0.6f * alt, 0.f + showWater); + break; + case st_Road: + surfColor = Vec3f(0.6f * alt, 0.3f * alt, 0.f + showWater); + break; + case st_Stone: + surfColor = Vec3f(0.7f * alt, 0.7f * alt, 0.7f * alt + showWater); + break; + case st_Ground: + surfColor = Vec3f(0.7f * alt, 0.5f * alt, 0.3f * alt + showWater); + break; } glColor3fv(surfColor.ptr()); @@ -4127,20 +4229,42 @@ void Renderer::renderMapPreview( const MapPreview *map, bool renderAll, //objects if(renderAll == true) { switch (map->getObject(i, j)) { - case 0: glColor3f(0.f, 0.f, 0.f); break; - case 1: glColor3f(1.f, 0.f, 0.f); break; - case 2: glColor3f(1.f, 1.f, 1.f); break; - case 3: glColor3f(0.5f, 0.5f, 1.f); break; - case 4: glColor3f(0.f, 0.f, 1.f); break; - case 5: glColor3f(0.5f, 0.5f, 0.5f); break; - case 6: glColor3f(1.f, 0.8f, 0.5f); break; - case 7: glColor3f(0.f, 1.f, 1.f); break; - case 8: glColor3f(0.7f, 0.1f, 0.3f); break; - case 9: glColor3f(0.5f, 1.f, 0.1f); break; - case 10: glColor3f(1.f, 0.2f, 0.8f); break;// we don't render unvisible blocking objects + case 0: + glColor3f(0.f, 0.f, 0.f); + break; + case 1: + glColor3f(1.f, 0.f, 0.f); + break; + case 2: + glColor3f(1.f, 1.f, 1.f); + break; + case 3: + glColor3f(0.5f, 0.5f, 1.f); + break; + case 4: + glColor3f(0.f, 0.f, 1.f); + break; + case 5: + glColor3f(0.5f, 0.5f, 0.5f); + break; + case 6: + glColor3f(1.f, 0.8f, 0.5f); + break; + case 7: + glColor3f(0.f, 1.f, 1.f); + break; + case 8: + glColor3f(0.7f, 0.1f, 0.3f); + break; + case 9: + glColor3f(0.5f, 1.f, 0.1f); + break; + case 10: + glColor3f(1.f, 0.2f, 0.8f); + break;// we don't render unvisible blocking objects } - if ( renderAll && (map->getObject(i, j) != 0) && (map->getObject(i, j) != 10) ){ + if ( renderAll && (map->getObject(i, j) != 0) && (map->getObject(i, j) != 10) ) { glPointSize(cellSize / 2.f); glBegin(GL_POINTS); glVertex2f(i * cellSize + cellSize / 2.f, clientH - j * cellSize - cellSize / 2.f); @@ -4211,15 +4335,16 @@ void Renderer::renderMapPreview( const MapPreview *map, bool renderAll, } - //start locations glLineWidth(3); // force playerCrossSize to be at least of size 4 - if(cellSize<4) - playerCrossSize=4; - else - playerCrossSize=cellSize; + if(cellSize < 4) { + playerCrossSize = 4; + } + else { + playerCrossSize = cellSize; + } for (int i = 0; i < map->getMaxFactions(); i++) { switch (i) { @@ -4245,8 +4370,29 @@ void Renderer::renderMapPreview( const MapPreview *map, bool renderAll, glMatrixMode(GL_PROJECTION); glPopMatrix(); + //glDisable( GL_SCISSOR_TEST ); //glViewport(0, 0, 0, 0); + if(renderToTexture != NULL) { + + //*renderToTexture = saveScreenToTexture(screenPosX, screenPosY, metrics.getVirtualW(), metrics.getVirtualH()); + //*renderToTexture = saveScreenToTexture(0, 0, metrics.getVirtualW(), metrics.getVirtualH()); +/* + Texture2DGl *texture = static_cast(*renderToTexture); + if(texture != NULL) { + //*renderToTexture = saveScreenToTexture(screenPosX, screenPosY, clientW, clientH); + texture->dettachFrameBufferFromTexture(); + + // Signal the threads queue to add a screenshot save request + //MutexSafeWrapper safeMutex(&saveScreenShotThreadAccessor); + //saveScreenQueue.push_back(make_pair("bob.png",texture->getPixmap())); + //*renderToTexture=NULL; + //safeMutex.ReleaseLock(); + + //texture->teardown_FBO_RBO(); + } +*/ + } assertGl(); } diff --git a/source/glest_game/graphics/renderer.h b/source/glest_game/graphics/renderer.h index cdad27de..3b82daa2 100644 --- a/source/glest_game/graphics/renderer.h +++ b/source/glest_game/graphics/renderer.h @@ -339,7 +339,7 @@ public: void renderMinimap(); void renderDisplay(); void renderMenuBackground(const MenuBackground *menuBackground); - void renderMapPreview(const MapPreview *map, bool renderAll, int screenX, int screenY); + void renderMapPreview(const MapPreview *map, bool renderAll, int screenX, int screenY,Texture2D **renderToTexture=NULL); //computing bool computePosition(const Vec2i &screenPos, Vec2i &worldPos); @@ -392,6 +392,8 @@ public: uint64 getCurrentPixelByteCount(ResourceScope rs=rsGame) const; unsigned int getSaveScreenQueueSize(); + Texture2D *saveScreenToTexture(int x, int y, int width, int height); + private: //private misc float computeSunAngle(float time); diff --git a/source/glest_game/menu/menu_state_custom_game.cpp b/source/glest_game/menu/menu_state_custom_game.cpp index 00ae4b3e..3e05fab8 100644 --- a/source/glest_game/menu/menu_state_custom_game.cpp +++ b/source/glest_game/menu/menu_state_custom_game.cpp @@ -59,6 +59,7 @@ MenuStateCustomGame::MenuStateCustomGame(Program *program, MainMenu *mainMenu, b factionTexture=NULL; currentTechName_factionPreview=""; currentFactionName_factionPreview=""; + mapPreviewTexture=NULL; publishToMasterserverThread = NULL; Lang &lang= Lang::getInstance(); @@ -487,6 +488,9 @@ MenuStateCustomGame::MenuStateCustomGame(Program *program, MainMenu *mainMenu, b GraphicComponent::applyAllCustomProperties(containerName); + MutexSafeWrapper safeMutexPtr(&publishToMasterserverThreadPtrChangeAccessor); + publishToMasterserverThreadInDeletion = false; + publishToMasterserverThread = new SimpleTaskThread(this,0,25); publishToMasterserverThread->setUniqueID(__FILE__); publishToMasterserverThread->start(); @@ -497,16 +501,28 @@ MenuStateCustomGame::MenuStateCustomGame(Program *program, MainMenu *mainMenu, b MenuStateCustomGame::~MenuStateCustomGame() { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); - needToBroadcastServerSettings = false; - needToRepublishToMasterserver = false; + if(publishToMasterserverThreadInDeletion == false) { + MutexSafeWrapper safeMutexPtr(&publishToMasterserverThreadPtrChangeAccessor); - //BaseThread::shutdownAndWait(publishToMasterserverThread); - delete publishToMasterserverThread; - publishToMasterserverThread = NULL; + if(publishToMasterserverThread != NULL) { + needToBroadcastServerSettings = false; + needToRepublishToMasterserver = false; + + //BaseThread::shutdownAndWait(publishToMasterserverThread); + delete publishToMasterserverThread; + publishToMasterserverThread = NULL; + publishToMasterserverThreadInDeletion = false; + safeMutexPtr.ReleaseLock(); + } + else { + safeMutexPtr.ReleaseLock(); + } + } SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); cleanupFactionTexture(); + cleanupMapPreviewTexture(); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); } @@ -514,6 +530,9 @@ MenuStateCustomGame::~MenuStateCustomGame() { void MenuStateCustomGame::returnToParentMenu(){ SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); + MutexSafeWrapper safeMutexPtr(&publishToMasterserverThreadPtrChangeAccessor); + publishToMasterserverThreadInDeletion = true; + needToBroadcastServerSettings = false; needToRepublishToMasterserver = false; bool returnToMasterServerMenu = parentMenuIsMs; @@ -521,6 +540,8 @@ void MenuStateCustomGame::returnToParentMenu(){ //BaseThread::shutdownAndWait(publishToMasterserverThread); delete publishToMasterserverThread; publishToMasterserverThread = NULL; + publishToMasterserverThreadInDeletion = false; + safeMutexPtr.ReleaseLock(); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); @@ -563,9 +584,13 @@ void MenuStateCustomGame::mouseClick(int x, int y, MouseButton mouseButton){ needToRepublishToMasterserver = false; safeMutex.ReleaseLock(); + MutexSafeWrapper safeMutexPtr(&publishToMasterserverThreadPtrChangeAccessor); + publishToMasterserverThreadInDeletion = true; //BaseThread::shutdownAndWait(publishToMasterserverThread); delete publishToMasterserverThread; publishToMasterserverThread = NULL; + publishToMasterserverThreadInDeletion = false; + safeMutexPtr.ReleaseLock(); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); @@ -1024,8 +1049,13 @@ void MenuStateCustomGame::PlayNow() { needToRepublishToMasterserver = false; safeMutex.ReleaseLock(); + MutexSafeWrapper safeMutexPtr(&publishToMasterserverThreadPtrChangeAccessor); + publishToMasterserverThreadInDeletion = true; + //BaseThread::shutdownAndWait(publishToMasterserverThread); delete publishToMasterserverThread; publishToMasterserverThread = NULL; + publishToMasterserverThreadInDeletion = false; + safeMutexPtr.ReleaseLock(); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); @@ -1090,7 +1120,12 @@ void MenuStateCustomGame::render() { Renderer &renderer= Renderer::getInstance(); if(factionTexture != NULL) { - renderer.renderTextureQuad(800,600,200,150,factionTexture,1); + renderer.renderTextureQuad(800,600,200,150,factionTexture,0.7); + } + if(mapPreviewTexture != NULL) { + //renderer.renderTextureQuad(10,350,-1,-1,mapPreviewTexture,0.7); + renderer.renderTextureQuad(800,300,200,150,mapPreviewTexture,0.7); + //printf("=================> Rendering map preview texture\n"); } if(mainMessageBox.getEnabled()){ @@ -1179,7 +1214,8 @@ void MenuStateCustomGame::render() { if(program != NULL) program->renderProgramMsgBox(); - if(enableMapPreview && (mapPreview.hasFileLoaded() == true)) { + if( enableMapPreview == true && + mapPreview.hasFileLoaded() == true) { int mouseX = mainMenu->getMouseX(); int mouseY = mainMenu->getMouseY(); @@ -1187,7 +1223,15 @@ void MenuStateCustomGame::render() { renderer.renderMouse2d(mouseX, mouseY, mouse2dAnim); bool renderAll = (listBoxFogOfWar.getSelectedItemIndex() == 1); - renderer.renderMapPreview(&mapPreview, renderAll, 10, 350); + + if(mapPreviewTexture == NULL) { + //printf("=================> Rendering map preview into a texture BEFORE (%p)\n", mapPreviewTexture); + renderer.renderMapPreview(&mapPreview, renderAll, 10, 350,&mapPreviewTexture); + //printf("=================> Rendering map preview into a texture AFTER (%p)\n", mapPreviewTexture); + } + else { + renderer.renderMapPreview(&mapPreview, renderAll, 10, 350); + } } renderer.renderChatManager(&chatManager); @@ -2214,6 +2258,9 @@ void MenuStateCustomGame::loadMapInfo(string file, MapInfo *mapInfo, bool loadMa if(loadMapPreview == true) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); mapPreview.loadFromFile(file.c_str()); + + //printf("Loading map preview MAP\n"); + cleanupMapPreviewTexture(); } } catch(exception &e) { @@ -2625,4 +2672,21 @@ void MenuStateCustomGame::cleanupFactionTexture() { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } +void MenuStateCustomGame::cleanupMapPreviewTexture() { + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + + //printf("CLEANUP map preview texture\n"); + + if(mapPreviewTexture != NULL) { + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + + mapPreviewTexture->end(); + + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + delete mapPreviewTexture; + mapPreviewTexture = NULL; + } + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); +} + }}//end namespace diff --git a/source/glest_game/menu/menu_state_custom_game.h b/source/glest_game/menu/menu_state_custom_game.h index 371701d1..a1c9f74e 100644 --- a/source/glest_game/menu/menu_state_custom_game.h +++ b/source/glest_game/menu/menu_state_custom_game.h @@ -101,6 +101,8 @@ private: std::map publishToServerInfo; SimpleTaskThread *publishToMasterserverThread; Mutex masterServerThreadAccessor; + Mutex publishToMasterserverThreadPtrChangeAccessor; + bool publishToMasterserverThreadInDeletion; bool parentMenuIsMs; int soundConnectionCount; @@ -132,6 +134,8 @@ private: Texture2D *factionTexture; MapPreview mapPreview; + Texture2D *mapPreviewTexture; + bool autostart; std::map lastSelectedTeamIndex; @@ -157,6 +161,8 @@ private: bool hasNetworkGameSettings(); void loadGameSettings(GameSettings *gameSettings); void loadMapInfo(string file, MapInfo *mapInfo,bool loadMapPreview); + void cleanupMapPreviewTexture(); + void reloadFactions(bool keepExistingSelectedItem); void updateControlers(); void closeUnusedSlots(); diff --git a/source/glest_game/type_instances/faction.cpp b/source/glest_game/type_instances/faction.cpp index d0cd562f..94bf6678 100644 --- a/source/glest_game/type_instances/faction.cpp +++ b/source/glest_game/type_instances/faction.cpp @@ -20,8 +20,9 @@ #include "sound_renderer.h" #include "renderer.h" #include "tech_tree.h" -#include "leak_dumper.h" #include "game.h" +#include "config.h" +#include "leak_dumper.h" using namespace Shared::Util; @@ -672,148 +673,123 @@ void Faction::resetResourceAmount(const ResourceType *rt){ bool Faction::isResourceTargetInCache(const Vec2i &pos, bool incrementUseCounter) { bool result = false; - if(cacheResourceTargetList.size() > 0) { - std::map::iterator iter = cacheResourceTargetList.find(pos); - result = (iter != cacheResourceTargetList.end()); - if(result == true && incrementUseCounter == true) { - iter->second++; + if(Config::getInstance().getBool("DisableCaching","false") == false) { + if(cacheResourceTargetList.size() > 0) { + std::map::iterator iter = cacheResourceTargetList.find(pos); + result = (iter != cacheResourceTargetList.end()); + if(result == true && incrementUseCounter == true) { + iter->second++; + } } } - return result; } void Faction::addResourceTargetToCache(const Vec2i &pos) { - bool duplicateEntry = isResourceTargetInCache(pos,true); - if(duplicateEntry == false) { - cacheResourceTargetList[pos] = 1; + if(Config::getInstance().getBool("DisableCaching","false") == false) { + bool duplicateEntry = isResourceTargetInCache(pos,true); + if(duplicateEntry == false) { + cacheResourceTargetList[pos] = 1; + } } } void Faction::removeResourceTargetFromCache(const Vec2i &pos) { - if(cacheResourceTargetList.size() > 0) { - std::map::iterator iter = cacheResourceTargetList.find(pos); - if(iter != cacheResourceTargetList.end()) { - cacheResourceTargetList.erase(pos); + if(Config::getInstance().getBool("DisableCaching","false") == false) { + if(cacheResourceTargetList.size() > 0) { + std::map::iterator iter = cacheResourceTargetList.find(pos); + if(iter != cacheResourceTargetList.end()) { + cacheResourceTargetList.erase(pos); + } } } } void Faction::addCloseResourceTargetToCache(const Vec2i &pos) { - if(cachedCloseResourceTargetLookupList.find(pos) == cachedCloseResourceTargetLookupList.end()) { - const Map *map = world->getMap(); - const int harvestDistance = 5; - for(int j = -harvestDistance; j <= harvestDistance; ++j) { - for(int k = -harvestDistance; k <= harvestDistance; ++k) { - Vec2i newPos = pos + Vec2i(j,k); - if(isResourceTargetInCache(newPos) == false) { - if(map->isInside(newPos.x, newPos.y)) { - Resource *r = map->getSurfaceCell(map->toSurfCoords(newPos))->getResource(); - if(r != NULL) { - //addResourceTargetToCache(newPos); - cacheResourceTargetList[newPos] = 1; + if(Config::getInstance().getBool("DisableCaching","false") == false) { + if(cachedCloseResourceTargetLookupList.find(pos) == cachedCloseResourceTargetLookupList.end()) { + const Map *map = world->getMap(); + const int harvestDistance = 5; + for(int j = -harvestDistance; j <= harvestDistance; ++j) { + for(int k = -harvestDistance; k <= harvestDistance; ++k) { + Vec2i newPos = pos + Vec2i(j,k); + if(isResourceTargetInCache(newPos) == false) { + if(map->isInside(newPos.x, newPos.y)) { + Resource *r = map->getSurfaceCell(map->toSurfCoords(newPos))->getResource(); + if(r != NULL) { + //addResourceTargetToCache(newPos); + cacheResourceTargetList[newPos] = 1; + } } } } } - } - cachedCloseResourceTargetLookupList[pos] = true; + cachedCloseResourceTargetLookupList[pos] = true; + } } } Vec2i Faction::getClosestResourceTypeTargetFromCache(Unit *unit, const ResourceType *type) { Vec2i result(-1); - if(cacheResourceTargetList.size() > 0) { - std::vector deleteList; + if(Config::getInstance().getBool("DisableCaching","false") == false) { + if(cacheResourceTargetList.size() > 0) { + std::vector deleteList; - const int harvestDistance = 5; - const Map *map = world->getMap(); - Vec2i pos = unit->getPos(); + const int harvestDistance = 5; + const Map *map = world->getMap(); + Vec2i pos = unit->getPos(); - bool foundCloseResource = false; - // First look immediately around the unit's position - for(int j = -harvestDistance; j <= harvestDistance && foundCloseResource == false; ++j) { - for(int k = -harvestDistance; k <= harvestDistance && foundCloseResource == false; ++k) { - Vec2i newPos = pos + Vec2i(j,k); - if(map->isInside(newPos) == true && isResourceTargetInCache(newPos) == false) { - const SurfaceCell *sc = map->getSurfaceCell(map->toSurfCoords(newPos)); - if( sc != NULL && sc->getResource() != NULL) { - const Resource *resource = sc->getResource(); - if(resource->getType() != NULL && resource->getType() == type) { - if(result.x < 0 || unit->getPos().dist(newPos) < unit->getPos().dist(result)) { - if(unit->isBadHarvestPos(newPos) == false) { - result = newPos; - foundCloseResource = true; - break; - } - } - } - } - else { - deleteList.push_back(newPos); - } - } - } - } - - if(foundCloseResource == false) { - // Now check the whole cache - for(std::map::iterator iter = cacheResourceTargetList.begin(); - iter != cacheResourceTargetList.end() && foundCloseResource == false; - ++iter) { - const Vec2i &cache = iter->first; - if(map->isInside(cache) == true) { - const SurfaceCell *sc = map->getSurfaceCell(map->toSurfCoords(cache)); - if( sc != NULL && sc->getResource() != NULL) { - const Resource *resource = sc->getResource(); - if(resource->getType() != NULL && resource->getType() == type) { - if(result.x < 0 || unit->getPos().dist(cache) < unit->getPos().dist(result)) { - if(unit->isBadHarvestPos(cache) == false) { - result = cache; - // Close enough to our position, no more looking - if(unit->getPos().dist(result) <= (harvestDistance * 2)) { + bool foundCloseResource = false; + // First look immediately around the unit's position + for(int j = -harvestDistance; j <= harvestDistance && foundCloseResource == false; ++j) { + for(int k = -harvestDistance; k <= harvestDistance && foundCloseResource == false; ++k) { + Vec2i newPos = pos + Vec2i(j,k); + if(map->isInside(newPos) == true && isResourceTargetInCache(newPos) == false) { + const SurfaceCell *sc = map->getSurfaceCell(map->toSurfCoords(newPos)); + if( sc != NULL && sc->getResource() != NULL) { + const Resource *resource = sc->getResource(); + if(resource->getType() != NULL && resource->getType() == type) { + if(result.x < 0 || unit->getPos().dist(newPos) < unit->getPos().dist(result)) { + if(unit->isBadHarvestPos(newPos) == false) { + result = newPos; foundCloseResource = true; break; } } } } - } - else { - deleteList.push_back(cache); + else { + deleteList.push_back(newPos); + } } } - else { - deleteList.push_back(cache); - } } - } - if(deleteList.size() > 0) { - cleanupResourceTypeTargetCache(&deleteList); - } - } - return result; -} - -void Faction::cleanupResourceTypeTargetCache(std::vector *deleteListPtr) { - if(cacheResourceTargetList.size() > 0) { - if(deleteListPtr != NULL || difftime(time(NULL),lastResourceTargettListPurge) >= 120) { - lastResourceTargettListPurge = time(NULL); - std::vector deleteList; - - if(deleteListPtr != NULL) { - deleteList = *deleteListPtr; - } - else { + if(foundCloseResource == false) { + // Now check the whole cache for(std::map::iterator iter = cacheResourceTargetList.begin(); - iter != cacheResourceTargetList.end(); ++iter) { + iter != cacheResourceTargetList.end() && foundCloseResource == false; + ++iter) { const Vec2i &cache = iter->first; - - if(world->getMap()->getSurfaceCell(world->getMap()->toSurfCoords(cache)) != NULL) { - Resource *resource = world->getMap()->getSurfaceCell(world->getMap()->toSurfCoords(cache))->getResource(); - if(resource == NULL) { + if(map->isInside(cache) == true) { + const SurfaceCell *sc = map->getSurfaceCell(map->toSurfCoords(cache)); + if( sc != NULL && sc->getResource() != NULL) { + const Resource *resource = sc->getResource(); + if(resource->getType() != NULL && resource->getType() == type) { + if(result.x < 0 || unit->getPos().dist(cache) < unit->getPos().dist(result)) { + if(unit->isBadHarvestPos(cache) == false) { + result = cache; + // Close enough to our position, no more looking + if(unit->getPos().dist(result) <= (harvestDistance * 2)) { + foundCloseResource = true; + break; + } + } + } + } + } + else { deleteList.push_back(cache); } } @@ -822,9 +798,44 @@ void Faction::cleanupResourceTypeTargetCache(std::vector *deleteListPtr) } } } - for(int i = 0; i < deleteList.size(); ++i) { - Vec2i &cache = deleteList[i]; - cacheResourceTargetList.erase(cache); + if(deleteList.size() > 0) { + cleanupResourceTypeTargetCache(&deleteList); + } + } + } + return result; +} + +void Faction::cleanupResourceTypeTargetCache(std::vector *deleteListPtr) { + if(Config::getInstance().getBool("DisableCaching","false") == false) { + if(cacheResourceTargetList.size() > 0) { + if(deleteListPtr != NULL || difftime(time(NULL),lastResourceTargettListPurge) >= 120) { + lastResourceTargettListPurge = time(NULL); + std::vector deleteList; + + if(deleteListPtr != NULL) { + deleteList = *deleteListPtr; + } + else { + for(std::map::iterator iter = cacheResourceTargetList.begin(); + iter != cacheResourceTargetList.end(); ++iter) { + const Vec2i &cache = iter->first; + + if(world->getMap()->getSurfaceCell(world->getMap()->toSurfCoords(cache)) != NULL) { + Resource *resource = world->getMap()->getSurfaceCell(world->getMap()->toSurfCoords(cache))->getResource(); + if(resource == NULL) { + deleteList.push_back(cache); + } + } + else { + deleteList.push_back(cache); + } + } + } + for(int i = 0; i < deleteList.size(); ++i) { + Vec2i &cache = deleteList[i]; + cacheResourceTargetList.erase(cache); + } } } } @@ -832,40 +843,42 @@ void Faction::cleanupResourceTypeTargetCache(std::vector *deleteListPtr) std::vector Faction::findCachedPath(const Vec2i &target, Unit *unit) { std::vector result; - if(successfulPathFinderTargetList.find(target) == successfulPathFinderTargetList.end()) { - // Lets find the shortest and most successful path already taken by a - // similar sized unit + if(Config::getInstance().getBool("DisableCaching","false") == false) { + if(successfulPathFinderTargetList.find(target) == successfulPathFinderTargetList.end()) { + // Lets find the shortest and most successful path already taken by a + // similar sized unit - bool foundCachedPath = false; + bool foundCachedPath = false; - std::vector &cacheList = successfulPathFinderTargetList[target]; - int unitSize = unit->getType()->getSize(); - for(int i = 0; i < cacheList.size(); ++i) { - FactionPathSuccessCache &cache = cacheList[i]; - if(cache.unitSize <= unitSize) { - vector, int> > &pathQueue = cache.pathQueue; + std::vector &cacheList = successfulPathFinderTargetList[target]; + int unitSize = unit->getType()->getSize(); + for(int i = 0; i < cacheList.size(); ++i) { + FactionPathSuccessCache &cache = cacheList[i]; + if(cache.unitSize <= unitSize) { + vector, int> > &pathQueue = cache.pathQueue; - for(int j = 0; j < pathQueue.size(); ++j) { - // Now start at the end of the path and see how many nodes - // until we reach a cell near the unit's current position - std::pair, int> &path = pathQueue[j]; + for(int j = 0; j < pathQueue.size(); ++j) { + // Now start at the end of the path and see how many nodes + // until we reach a cell near the unit's current position + std::pair, int> &path = pathQueue[j]; - for(int k = path.first.size() - 1; k >= 0; --k) { - if(world->getMap()->canMove(unit, unit->getPos(), path.first[k]) == true) { - if(foundCachedPath == false) { - for(int l = k; l < path.first.size(); ++l) { - result.push_back(path.first[l]); - } - } - else { - if(result.size() > (path.first.size() - k)) { + for(int k = path.first.size() - 1; k >= 0; --k) { + if(world->getMap()->canMove(unit, unit->getPos(), path.first[k]) == true) { + if(foundCachedPath == false) { for(int l = k; l < path.first.size(); ++l) { result.push_back(path.first[l]); } } + else { + if(result.size() > (path.first.size() - k)) { + for(int l = k; l < path.first.size(); ++l) { + result.push_back(path.first[l]); + } + } + } + foundCachedPath = true; + break; } - foundCachedPath = true; - break; } } } @@ -876,53 +889,55 @@ std::vector Faction::findCachedPath(const Vec2i &target, Unit *unit) { } void Faction::addCachedPath(const Vec2i &target, Unit *unit) { - if(successfulPathFinderTargetList.find(target) == successfulPathFinderTargetList.end()) { - FactionPathSuccessCache cache; - cache.unitSize = unit->getType()->getSize(); - cache.pathQueue.push_back(make_pair, int>(unit->getCurrentTargetPathTaken().second,1)); - successfulPathFinderTargetList[target].push_back(cache); - } - else { - bool finishedAdd = false; - std::pair > currentTargetPathTaken = unit->getCurrentTargetPathTaken(); - std::vector &cacheList = successfulPathFinderTargetList[target]; - int unitSize = unit->getType()->getSize(); - for(int i = 0; i < cacheList.size() && finishedAdd == false; ++i) { - FactionPathSuccessCache &cache = cacheList[i]; - if(cache.unitSize <= unitSize) { - vector, int> > &pathQueue = cache.pathQueue; + if(Config::getInstance().getBool("DisableCaching","false") == false) { + if(successfulPathFinderTargetList.find(target) == successfulPathFinderTargetList.end()) { + FactionPathSuccessCache cache; + cache.unitSize = unit->getType()->getSize(); + cache.pathQueue.push_back(make_pair, int>(unit->getCurrentTargetPathTaken().second,1)); + successfulPathFinderTargetList[target].push_back(cache); + } + else { + bool finishedAdd = false; + std::pair > currentTargetPathTaken = unit->getCurrentTargetPathTaken(); + std::vector &cacheList = successfulPathFinderTargetList[target]; + int unitSize = unit->getType()->getSize(); + for(int i = 0; i < cacheList.size() && finishedAdd == false; ++i) { + FactionPathSuccessCache &cache = cacheList[i]; + if(cache.unitSize <= unitSize) { + vector, int> > &pathQueue = cache.pathQueue; - for(int j = 0; j < pathQueue.size() && finishedAdd == false; ++j) { - // Now start at the end of the path and see how many nodes are the same - std::pair, int> &path = pathQueue[j]; - int minPathSize = std::min(path.first.size(),currentTargetPathTaken.second.size()); - int intersectIndex = -1; + for(int j = 0; j < pathQueue.size() && finishedAdd == false; ++j) { + // Now start at the end of the path and see how many nodes are the same + std::pair, int> &path = pathQueue[j]; + int minPathSize = std::min(path.first.size(),currentTargetPathTaken.second.size()); + int intersectIndex = -1; - for(int k = 0; k < minPathSize; ++k) { - if(path.first[path.first.size() - k - 1] != currentTargetPathTaken.second[currentTargetPathTaken.second.size() - k - 1]) { - intersectIndex = k; - break; + for(int k = 0; k < minPathSize; ++k) { + if(path.first[path.first.size() - k - 1] != currentTargetPathTaken.second[currentTargetPathTaken.second.size() - k - 1]) { + intersectIndex = k; + break; + } + } + + // New path is same or longer than old path so replace + // old path with new + if(intersectIndex + 1 == path.first.size()) { + path.first = currentTargetPathTaken.second; + path.second++; + finishedAdd = true; + } + // Old path is same or longer than new path so + // do nothing + else if(intersectIndex + 1 == currentTargetPathTaken.second.size()) { + path.second++; + finishedAdd = true; } } - // New path is same or longer than old path so replace - // old path with new - if(intersectIndex + 1 == path.first.size()) { - path.first = currentTargetPathTaken.second; - path.second++; - finishedAdd = true; + // If new path is >= 10 cells add it + if(finishedAdd == false && currentTargetPathTaken.second.size() >= 10) { + pathQueue.push_back(make_pair, int>(currentTargetPathTaken.second,1)); } - // Old path is same or longer than new path so - // do nothing - else if(intersectIndex + 1 == currentTargetPathTaken.second.size()) { - path.second++; - finishedAdd = true; - } - } - - // If new path is >= 10 cells add it - if(finishedAdd == false && currentTargetPathTaken.second.size() >= 10) { - pathQueue.push_back(make_pair, int>(currentTargetPathTaken.second,1)); } } } diff --git a/source/glest_game/type_instances/object.cpp b/source/glest_game/type_instances/object.cpp index 974e7132..a4980404 100644 --- a/source/glest_game/type_instances/object.cpp +++ b/source/glest_game/type_instances/object.cpp @@ -50,7 +50,6 @@ Object::~Object(){ delete resource; Renderer &renderer= Renderer::getInstance(); - //renderer.setQuadCacheDirty(true); renderer.removeObjectFromQuadCache(this); } diff --git a/source/glest_game/type_instances/unit.cpp b/source/glest_game/type_instances/unit.cpp index 8cab5694..45edcd73 100644 --- a/source/glest_game/type_instances/unit.cpp +++ b/source/glest_game/type_instances/unit.cpp @@ -296,7 +296,6 @@ Unit::~Unit(){ SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); Renderer &renderer= Renderer::getInstance(); - //renderer.setQuadCacheDirty(true); renderer.removeUnitFromQuadCache(this); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); diff --git a/source/glest_game/world/map.cpp b/source/glest_game/world/map.cpp index 912144e4..c71ddad5 100644 --- a/source/glest_game/world/map.cpp +++ b/source/glest_game/world/map.cpp @@ -106,8 +106,53 @@ Map::~Map(){ Logger::getInstance().add("Cells", true); delete [] cells; + cells = NULL; delete [] surfaceCells; + surfaceCells = NULL; delete [] startLocations; + startLocations = NULL; +} + +int Map::getSurfaceCellArraySize() const { + return (surfaceW * surfaceH); +} + +SurfaceCell *Map::getSurfaceCell(int sx, int sy) const { + int arrayIndex = sy * surfaceW + sx; + if(arrayIndex >= getSurfaceCellArraySize()) { + throw runtime_error("arrayIndex >= getSurfaceCellArraySize()"); + } + else if(surfaceCells == NULL) { + throw runtime_error("surfaceCells == NULL"); + } + return &surfaceCells[arrayIndex]; +} + +int Map::getCellArraySize() const { + return (w * h); +} + +Cell *Map::getCell(int x, int y) const { + int arrayIndex = y * w + x; + if(arrayIndex >= getCellArraySize()) { + throw runtime_error("arrayIndex >= getCellArraySize()"); + } + else if(cells == NULL) { + throw runtime_error("cells == NULL"); + } + + return &cells[arrayIndex]; +} + +Vec2i Map::getStartLocation(int locationIndex) const { + if(locationIndex >= maxPlayers) { + throw runtime_error("locationIndex >= maxPlayers"); + } + else if(startLocations == NULL) { + throw runtime_error("startLocations == NULL"); + } + + return startLocations[locationIndex]; } void Map::load(const string &path, TechTree *techTree, Tileset *tileset){ @@ -152,7 +197,7 @@ void Map::load(const string &path, TechTree *techTree, Tileset *tileset){ //start locations startLocations= new Vec2i[maxPlayers]; - for(int i=0; igetHeight()getHeight()getHeight()addFile(path); - try{ + try { Logger::getInstance().add("Tileset: "+formatString(name), true); Renderer &renderer= Renderer::getInstance(); @@ -242,13 +242,13 @@ void Tileset::load(const string &dir, Checksum *checksum){ SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - if(rndonTimerTriggerEvent(); //units - for(int i=0; igetUnitCount(); ++j) { - unitUpdater.updateUnit(getFaction(i)->getUnit(j)); + int factionCount = getFactionCount(); + for(int i = 0; i < factionCount; ++i) { + Faction *faction = getFaction(i); + if(faction == NULL) { + throw runtime_error("faction == NULL"); + } + + int unitCount = faction->getUnitCount(); + for(int j = 0; j < unitCount; ++j) { + Unit *unit = faction->getUnit(j); + if(unit == NULL) { + throw runtime_error("unit == NULL"); + } + + unitUpdater.updateUnit(unit); } } } @@ -262,17 +274,27 @@ void World::underTakeDeadFactionUnits() { } } - SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] factionIdxToTick = %d\n",__FILE__,__FUNCTION__,__LINE__,factionIdxToTick); + int factionCount = getFactionCount(); + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] factionIdxToTick = %d, factionCount = %d\n",__FILE__,__FUNCTION__,__LINE__,factionIdxToTick,factionCount); //undertake the dead - for(int i=0; igetUnitCount(); + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] factionIdxToTick = %d, i = %d, unitCount = %d\n",__FILE__,__FUNCTION__,__LINE__,factionIdxToTick,i,unitCount); - int unitCount = getFaction(i)->getUnitCount(); - for(int j= unitCount - 1; j >= 0; j--){ - Unit *unit= getFaction(i)->getUnit(j); - if(unit->getToBeUndertaken()) { + for(int j= unitCount - 1; j >= 0; j--) { + Unit *unit= faction->getUnit(j); + + if(unit == NULL) { + throw runtime_error("unit == NULL"); + } + + if(unit->getToBeUndertaken() == true) { unit->undertake(); delete unit; //j--; @@ -284,11 +306,18 @@ void World::underTakeDeadFactionUnits() { void World::updateAllFactionConsumableCosts() { //food costs - for(int i=0; igetResourceTypeCount(); ++i){ - const ResourceType *rt= techTree->getResourceType(i); - if(rt->getClass() == rcConsumable && frameCount % (rt->getInterval() * GameConstants::updateFps)==0){ - for(int i=0; iapplyCostsOnInterval(rt); + int resourceTypeCount = techTree->getResourceTypeCount(); + int factionCount = getFactionCount(); + for(int i = 0; i < resourceTypeCount; ++i) { + const ResourceType *rt = techTree->getResourceType(i); + if(rt != NULL && rt->getClass() == rcConsumable && frameCount % (rt->getInterval() * GameConstants::updateFps) == 0) { + for(int j = 0; j < factionCount; ++j) { + Faction *faction = getFaction(j); + if(faction == NULL) { + throw runtime_error("faction == NULL"); + } + + faction->applyCostsOnInterval(rt); } } } @@ -415,35 +444,51 @@ void World::tick() { //increase hp //int i = factionIdxToTick; - for(int i=0; igetUnitCount(); ++j) { - getFaction(i)->getUnit(j)->tick(); + Faction *faction = getFaction(i); + if(faction == NULL) { + throw runtime_error("faction == NULL"); + } + int unitCount = faction->getUnitCount(); + + for(int j = 0; j < unitCount; ++j) { + Unit *unit = faction->getUnit(j); + if(unit == NULL) { + throw runtime_error("unit == NULL"); + } + + unit->tick(); } } } //compute resources balance //int k = factionIdxToTick; - for(int k=0; kgetResourceTypeCount(); ++i) { + for(int i = 0; i < techTree->getResourceTypeCount(); ++i) { const ResourceType *rt= techTree->getResourceType(i); //if consumable - if(rt->getClass()==rcConsumable) { + if(rt != NULL && rt->getClass()==rcConsumable) { int balance= 0; - for(int j=0; jgetUnitCount(); ++j) { + for(int j = 0; j < faction->getUnitCount(); ++j) { //if unit operative and has this cost const Unit *u= faction->getUnit(j); - if(u->isOperative()) { + if(u != NULL && u->isOperative()) { const Resource *r= u->getType()->getCost(rt); - if(r!=NULL) { - balance-= u->getType()->getCost(rt)->getAmount(); + if(r != NULL) { + balance -= u->getType()->getCost(rt)->getAmount(); } } } @@ -459,7 +504,7 @@ void World::tick() { } Unit* World::findUnitById(int id) const { - for(int i= 0; ifindUnit(id); if(unit != NULL) { @@ -469,36 +514,42 @@ Unit* World::findUnitById(int id) const { return NULL; } -const UnitType* World::findUnitTypeById(const FactionType* factionType, int id){ - for(int i= 0; igetUnitTypeCount(); ++i){ - const UnitType* unitType= factionType->getUnitType(i); - - if(unitType->getId()==id){ +const UnitType* World::findUnitTypeById(const FactionType* factionType, int id) { + if(factionType == NULL) { + throw runtime_error("factionType == NULL"); + } + for(int i= 0; i < factionType->getUnitTypeCount(); ++i) { + const UnitType *unitType = factionType->getUnitType(i); + if(unitType != NULL && unitType->getId() == id) { return unitType; } } return NULL; } -//looks for a place for a unit around a start lociacion, returns true if succeded -bool World::placeUnit(const Vec2i &startLoc, int radius, Unit *unit, bool spaciated){ - bool freeSpace=false; +//looks for a place for a unit around a start location, returns true if succeded +bool World::placeUnit(const Vec2i &startLoc, int radius, Unit *unit, bool spaciated) { + if(unit == NULL) { + throw runtime_error("unit == NULL"); + } + + bool freeSpace=false; int size= unit->getType()->getSize(); Field currField= unit->getCurrField(); - for(int r=1; rsetPos(pos); unit->setMeetingPos(pos-Vec2i(1)); return true; @@ -510,12 +561,16 @@ bool World::placeUnit(const Vec2i &startLoc, int radius, Unit *unit, bool spacia } //clears a unit old position from map and places new position -void World::moveUnitCells(Unit *unit){ +void World::moveUnitCells(Unit *unit) { + if(unit == NULL) { + throw runtime_error("unit == NULL"); + } + Vec2i newPos= unit->getTargetPos(); //newPos must be free or the same pos as current assert(map.getCell(unit->getPos())->getUnit(unit->getCurrField())==unit || map.isFreeCell(newPos, unit->getCurrField())); - // Only change cell plaement in map if the new position is different + // Only change cell placement in map if the new position is different // from the old one if(newPos != unit->getPos()) { map.clearUnitCells(unit, unit->getPos()); @@ -525,10 +580,10 @@ void World::moveUnitCells(Unit *unit){ unit->getFaction()->addCloseResourceTargetToCache(newPos); //water splash - if(tileset.getWaterEffects() && unit->getCurrField()==fLand){ - if(map.getSubmerged(map.getCell(unit->getLastPos()))){ - int unitSize=unit->getType()->getSize(); - for(int i=0; i<3; ++i){ + if(tileset.getWaterEffects() && unit->getCurrField() == fLand) { + if(map.getSubmerged(map.getCell(unit->getLastPos()))) { + int unitSize= unit->getType()->getSize(); + for(int i = 0; i < 3; ++i) { waterEffects.addWaterSplash( Vec2f(unit->getLastPos().x+(float)unitSize/2.0f+random.randRange(-0.9f, -0.1f), unit->getLastPos().y+random.randRange(-0.9f, -0.1f)+(float)unitSize/2.0f), unit->getType()->getSize()); } @@ -539,29 +594,40 @@ void World::moveUnitCells(Unit *unit){ } //returns the nearest unit that can store a type of resource given a position and a faction -Unit *World::nearestStore(const Vec2i &pos, int factionIndex, const ResourceType *rt){ +Unit *World::nearestStore(const Vec2i &pos, int factionIndex, const ResourceType *rt) { float currDist= infinity; Unit *currUnit= NULL; - for(int i=0; igetUnitCount(); ++i){ + if(factionIndex >= getFactionCount()) { + throw runtime_error("factionIndex >= getFactionCount()"); + } + + for(int i=0; i < getFaction(factionIndex)->getUnitCount(); ++i) { Unit *u= getFaction(factionIndex)->getUnit(i); - float tmpDist= u->getPos().dist(pos); - if(tmpDistgetType()->getStore(rt)>0 && u->isOperative()){ - currDist= tmpDist; - currUnit= u; - } + if(u != NULL) { + float tmpDist= u->getPos().dist(pos); + if(tmpDist < currDist && u->getType()->getStore(rt) > 0 && u->isOperative()) { + currDist= tmpDist; + currUnit= u; + } + } } return currUnit; } -bool World::toRenderUnit(const Unit *unit, const Quad2i &visibleQuad) const{ - //a unit is rendered if it is in a visible cell or is attacking a unit in a visible cell - return - visibleQuad.isInside(unit->getPos()) && - toRenderUnit(unit); +bool World::toRenderUnit(const Unit *unit, const Quad2i &visibleQuad) const { + if(unit == NULL) { + throw runtime_error("unit == NULL"); + } + + //a unit is rendered if it is in a visible cell or is attacking a unit in a visible cell + return visibleQuad.isInside(unit->getPos()) && toRenderUnit(unit); } -bool World::toRenderUnit(const Unit *unit) const{ +bool World::toRenderUnit(const Unit *unit) const { + if(unit == NULL) { + throw runtime_error("unit == NULL"); + } return (map.getSurfaceCell(Map::toSurfCoords(unit->getCenteredPos()))->isVisible(thisTeamIndex) && @@ -571,10 +637,10 @@ bool World::toRenderUnit(const Unit *unit) const{ map.getSurfaceCell(Map::toSurfCoords(unit->getTargetPos()))->isExplored(thisTeamIndex)); } -void World::createUnit(const string &unitName, int factionIndex, const Vec2i &pos){ +void World::createUnit(const string &unitName, int factionIndex, const Vec2i &pos) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] unitName [%s] factionIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,unitName.c_str(),factionIndex); - if(factionIndexgetIndex() != factionIndex) { @@ -600,49 +666,47 @@ void World::createUnit(const string &unitName, int factionIndex, const Vec2i &po SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] unit created for unit [%s]\n",__FILE__,__FUNCTION__,__LINE__,unit->toString().c_str()); - if(placeUnit(pos, generationArea, unit, true)){ + if(placeUnit(pos, generationArea, unit, true)) { unit->create(true); unit->born(); scriptManager->onUnitCreated(unit); } - else{ + else { throw runtime_error("Unit cant be placed"); } SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] unit created for unit [%s]\n",__FILE__,__FUNCTION__,__LINE__,unit->toString().c_str()); } - else - { + else { throw runtime_error("Invalid faction index in createUnitAtPosition: " + intToStr(factionIndex)); } SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } -void World::giveResource(const string &resourceName, int factionIndex, int amount){ - if(factionIndexgetResourceType(resourceName); faction->incResourceAmount(rt, amount); } - else - { + else { throw runtime_error("Invalid faction index in giveResource: " + intToStr(factionIndex)); } } -void World::givePositionCommand(int unitId, const string &commandName, const Vec2i &pos){ +void World::givePositionCommand(int unitId, const string &commandName, const Vec2i &pos) { Unit* unit= findUnitById(unitId); - if(unit!=NULL){ + if(unit != NULL) { CommandClass cc; - if(commandName=="move"){ + if(commandName=="move") { cc= ccMove; } - else if(commandName=="attack"){ + else if(commandName=="attack") { cc= ccAttack; } - else{ + else { throw runtime_error("Invalid position commmand: " + commandName); } @@ -650,140 +714,158 @@ void World::givePositionCommand(int unitId, const string &commandName, const Vec unit->giveCommand(new Command( unit->getType()->getFirstCtOfClass(cc), pos )); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } + else { + throw runtime_error("Invalid unitId index in givePositionCommand: " + intToStr(unitId) + " commandName = " + commandName); + } } void World::giveAttackCommand(int unitId, int unitToAttackId) { Unit* unit= findUnitById(unitId); - if(unit != NULL){ + if(unit != NULL) { Unit* targetUnit = findUnitById(unitToAttackId); if(targetUnit != NULL) { - const CommandType *ct= unit->getType()->getFirstAttackCommand(targetUnit->getCurrField()); + const CommandType *ct = unit->getType()->getFirstAttackCommand(targetUnit->getCurrField()); if(ct != NULL) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Unit [%s] is attacking [%s]\n",__FILE__,__FUNCTION__,__LINE__,unit->getFullName().c_str(),targetUnit->getFullName().c_str()); unit->giveCommand(new Command(ct,targetUnit)); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } + else { + throw runtime_error("Invalid ct in giveAttackCommand: " + intToStr(unitId) + " unitToAttackId = " + intToStr(unitToAttackId)); + } } + else { + throw runtime_error("Invalid unitToAttackId index in giveAttackCommand: " + intToStr(unitId) + " unitToAttackId = " + intToStr(unitToAttackId)); + } + } + else { + throw runtime_error("Invalid unitId index in giveAttackCommand: " + intToStr(unitId) + " unitToAttackId = " + intToStr(unitToAttackId)); } } -void World::giveProductionCommand(int unitId, const string &producedName){ +void World::giveProductionCommand(int unitId, const string &producedName) { Unit *unit= findUnitById(unitId); - if(unit!=NULL){ + if(unit != NULL) { const UnitType *ut= unit->getType(); //Search for a command that can produce the unit - for(int i= 0; igetCommandTypeCount(); ++i){ + for(int i= 0; i< ut->getCommandTypeCount(); ++i) { const CommandType* ct= ut->getCommandType(i); - if(ct->getClass()==ccProduce){ + if(ct != NULL && ct->getClass() == ccProduce) { const ProduceCommandType *pct= static_cast(ct); - if(pct->getProducedUnit()->getName()==producedName){ + if(pct != NULL && pct->getProducedUnit()->getName() == producedName) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + unit->giveCommand(new Command(pct)); + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); break; } } } } + else { + throw runtime_error("Invalid unitId index in giveProductionCommand: " + intToStr(unitId) + " producedName = " + producedName); + } } -void World::giveUpgradeCommand(int unitId, const string &upgradeName){ +void World::giveUpgradeCommand(int unitId, const string &upgradeName) { Unit *unit= findUnitById(unitId); - if(unit!=NULL){ + if(unit != NULL) { const UnitType *ut= unit->getType(); //Search for a command that can produce the unit - for(int i= 0; igetCommandTypeCount(); ++i){ + for(int i= 0; i < ut->getCommandTypeCount(); ++i) { const CommandType* ct= ut->getCommandType(i); - if(ct->getClass()==ccUpgrade){ + if(ct != NULL && ct->getClass() == ccUpgrade) { const UpgradeCommandType *uct= static_cast(ct); - if(uct->getProducedUpgrade()->getName()==upgradeName){ + if(uct != NULL && uct->getProducedUpgrade()->getName() == upgradeName) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + unit->giveCommand(new Command(uct)); + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); break; } } } } + else { + throw runtime_error("Invalid unitId index in giveUpgradeCommand: " + intToStr(unitId) + " upgradeName = " + upgradeName); + } } -int World::getResourceAmount(const string &resourceName, int factionIndex){ - if(factionIndexgetResourceType(resourceName); return faction->getResource(rt)->getAmount(); } - else - { - throw runtime_error("Invalid faction index in giveResource: " + intToStr(factionIndex)); + else { + throw runtime_error("Invalid faction index in giveResource: " + intToStr(factionIndex) + " resourceName = " + resourceName); } } -Vec2i World::getStartLocation(int factionIndex){ - if(factionIndexgetStartLocationIndex()); } - else - { + else { throw runtime_error("Invalid faction index in getStartLocation: " + intToStr(factionIndex)); } } -Vec2i World::getUnitPosition(int unitId){ +Vec2i World::getUnitPosition(int unitId) { Unit* unit= findUnitById(unitId); - if(unit==NULL){ - throw runtime_error("Can not find unit to get position"); + if(unit == NULL) { + throw runtime_error("Can not find unit to get position unitId = " + intToStr(unitId)); } return unit->getPos(); } -int World::getUnitFactionIndex(int unitId){ +int World::getUnitFactionIndex(int unitId) { Unit* unit= findUnitById(unitId); - if(unit==NULL){ - throw runtime_error("Can not find unit to get position"); + if(unit == NULL) { + throw runtime_error("Can not find Faction unit to get position unitId = " + intToStr(unitId)); } return unit->getFactionIndex(); } -int World::getUnitCount(int factionIndex){ - if(factionIndexgetUnitCount(); ++i){ + for(int i= 0; i < faction->getUnitCount(); ++i) { const Unit* unit= faction->getUnit(i); - if(unit->isAlive()){ + if(unit != NULL && unit->isAlive()) { ++count; } } return count; } - else - { + else { throw runtime_error("Invalid faction index in getUnitCount: " + intToStr(factionIndex)); } } -int World::getUnitCountOfType(int factionIndex, const string &typeName){ - if(factionIndexgetUnitCount(); ++i){ + for(int i= 0; i< faction->getUnitCount(); ++i) { const Unit* unit= faction->getUnit(i); - if(unit->isAlive() && unit->getType()->getName()==typeName){ + if(unit != NULL && unit->isAlive() && unit->getType()->getName() == typeName) { ++count; } } return count; } - else - { + else { throw runtime_error("Invalid faction index in getUnitCountOfType: " + intToStr(factionIndex)); } } @@ -793,7 +875,7 @@ int World::getUnitCountOfType(int factionIndex, const string &typeName){ // ==================== private init ==================== //init basic cell state -void World::initCells(bool fogOfWar){ +void World::initCells(bool fogOfWar) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); Logger::getInstance().add("State cells", true); @@ -801,6 +883,9 @@ void World::initCells(bool fogOfWar){ for(int j=0; j< map.getSurfaceH(); ++j) { SurfaceCell *sc= map.getSurfaceCell(i, j); + if(sc == NULL) { + throw runtime_error("sc == NULL"); + } sc->setFowTexCoord(Vec2f( i/(next2Power(map.getSurfaceW())-1.f), @@ -820,22 +905,35 @@ void World::initCells(bool fogOfWar){ } //init surface textures -void World::initSplattedTextures(){ +void World::initSplattedTextures() { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - for(int i=0; igetSurfaceType(), - sc10->getSurfaceType(), - sc01->getSurfaceType(), - sc11->getSurfaceType(), - coord, texture); + + if(sc00 == NULL) { + throw runtime_error("sc00 == NULL"); + } + if(sc10 == NULL) { + throw runtime_error("sc10 == NULL"); + } + if(sc01 == NULL) { + throw runtime_error("sc01 == NULL"); + } + if(sc11 == NULL) { + throw runtime_error("sc11 == NULL"); + } + + tileset.addSurfTex( sc00->getSurfaceType(), + sc10->getSurfaceType(), + sc01->getSurfaceType(), + sc11->getSurfaceType(), + coord, texture); sc00->setSurfTexCoord(coord); sc00->setSurfaceTexture(texture); } @@ -844,11 +942,15 @@ void World::initSplattedTextures(){ } //creates each faction looking at each faction name contained in GameSettings -void World::initFactionTypes(GameSettings *gs){ +void World::initFactionTypes(GameSettings *gs) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); Logger::getInstance().add("Faction types", true); - if(gs->getFactionCount() > map.getMaxPlayers()){ + if(gs == NULL) { + throw runtime_error("gs == NULL"); + } + + if(gs->getFactionCount() > map.getMaxPlayers()) { throw runtime_error("This map only supports "+intToStr(map.getMaxPlayers())+" players"); } @@ -865,9 +967,11 @@ void World::initFactionTypes(GameSettings *gs){ for(int i=0; i < factions.size(); ++i) { FactionType *ft= techTree->getTypeByName(gs->getFactionTypeName(i)); - factions[i].init( - ft, gs->getFactionControl(i), techTree, game, i, gs->getTeam(i), - gs->getStartLocationIndex(i), i==thisFactionIndex, gs->getDefaultResources()); + if(ft == NULL) { + throw runtime_error("ft == NULL"); + } + factions[i].init(ft, gs->getFactionControl(i), techTree, game, i, gs->getTeam(i), + gs->getStartLocationIndex(i), i==thisFactionIndex, gs->getDefaultResources()); stats.setTeam(i, gs->getTeam(i)); stats.setFactionTypeName(i, formatString(gs->getFactionTypeName(i))); @@ -885,26 +989,30 @@ void World::initFactionTypes(GameSettings *gs){ SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } -void World::initMinimap(){ +void World::initMinimap() { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - minimap.init(map.getW(), map.getH(), this, game->getGameSettings()->getFogOfWar()); + + minimap.init(map.getW(), map.getH(), this, game->getGameSettings()->getFogOfWar()); Logger::getInstance().add("Compute minimap surface", true); + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } //place units randomly aroud start location -void World::initUnits(){ +void World::initUnits() { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); Logger::getInstance().add("Generate elements", true); //put starting units - for(int i=0; igetType(); - for(int j=0; jgetStartingUnitCount(); ++j){ + + for(int j = 0; j < ft->getStartingUnitCount(); ++j) { const UnitType *ut= ft->getStartingUnit(j); int initNumber= ft->getStartingUnitAmount(j); - for(int l=0; lgetGameSettings()->getPathFinderType()) { @@ -922,11 +1030,11 @@ void World::initUnits(){ int startLocationIndex= f->getStartLocationIndex(); - if(placeUnit(map.getStartLocation(startLocationIndex), generationArea, unit, true)){ + if(placeUnit(map.getStartLocation(startLocationIndex), generationArea, unit, true)) { unit->create(true); unit->born(); } - else{ + else { throw runtime_error("Unit cant be placed, this error is caused because there is no enough place to put the units near its start location, make a better map: "+unit->getType()->getName() + " Faction: "+intToStr(i)); } if (unit->getType()->hasSkillClass(scBeBuilt)) { @@ -944,7 +1052,7 @@ void World::initUnits(){ SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } -void World::initMap(){ +void World::initMap() { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); map.init(); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); @@ -952,7 +1060,7 @@ void World::initMap(){ // ==================== exploration ==================== -void World::exploreCells(const Vec2i &newPos, int sightRange, int teamIndex){ +void World::exploreCells(const Vec2i &newPos, int sightRange, int teamIndex) { Chrono chrono; chrono.start(); diff --git a/source/shared_lib/include/graphics/gl/texture_gl.h b/source/shared_lib/include/graphics/gl/texture_gl.h index 7b7294e4..8e125285 100644 --- a/source/shared_lib/include/graphics/gl/texture_gl.h +++ b/source/shared_lib/include/graphics/gl/texture_gl.h @@ -25,10 +25,29 @@ namespace Shared{ namespace Graphics{ namespace Gl{ class TextureGl { protected: GLuint handle; + GLuint renderBufferId; + GLuint frameBufferId; public: TextureGl(); - GLuint getHandle() const {return handle;} + virtual ~TextureGl(); + + GLuint getHandle() const {return handle;} + GLuint getRenderBufferHandle() const {return renderBufferId;} + GLuint getFrameBufferHandle() const {return frameBufferId;} + + void initRenderBuffer(); + void initFrameBuffer(); + void attachRenderBuffer(); + void attachFrameBufferToTexture(); + bool checkFrameBufferStatus(); + void dettachFrameBufferFromTexture(); + + void setup_FBO_RBO(); + void teardown_FBO_RBO(); + + virtual int getTextureWidth() const = 0; + virtual int getTextureHeight() const = 0; void OutputTextureDebugInfo(Texture::Format format, int components, const string path,uint64 rawSize,GLenum texType); }; @@ -44,6 +63,9 @@ public: virtual void init(Filter filter, int maxAnisotropy= 1); virtual void end(bool deletePixelBuffer=true); + + virtual int getTextureWidth() const { return Texture1D::getTextureWidth();} + virtual int getTextureHeight() const { return Texture1D::getTextureHeight();} }; // ===================================================== @@ -57,6 +79,9 @@ public: virtual void init(Filter filter, int maxAnisotropy= 1); virtual void end(bool deletePixelBuffer=true); + + virtual int getTextureWidth() const { return Texture2D::getTextureWidth();} + virtual int getTextureHeight() const { return Texture2D::getTextureHeight();} }; // ===================================================== @@ -71,6 +96,9 @@ public: virtual void init(Filter filter, int maxAnisotropy= 1); virtual void end(bool deletePixelBuffer=true); + + virtual int getTextureWidth() const { return Texture3D::getTextureWidth();} + virtual int getTextureHeight() const { return Texture3D::getTextureHeight();} }; // ===================================================== @@ -85,6 +113,10 @@ public: virtual void init(Filter filter, int maxAnisotropy= 1); virtual void end(bool deletePixelBuffer=true); + + virtual int getTextureWidth() const { return TextureCube::getTextureWidth();} + virtual int getTextureHeight() const { return TextureCube::getTextureHeight();} + }; }}}//end namespace diff --git a/source/shared_lib/include/graphics/texture.h b/source/shared_lib/include/graphics/texture.h index 58a97531..048065e0 100644 --- a/source/shared_lib/include/graphics/texture.h +++ b/source/shared_lib/include/graphics/texture.h @@ -95,7 +95,7 @@ public: // class Texture1D // ===================================================== -class Texture1D: public Texture{ +class Texture1D: public Texture { protected: Pixmap1D pixmap; @@ -107,6 +107,10 @@ public: virtual string getPath() const; virtual void deletePixels(); virtual uint64 getPixelByteCount() const {return pixmap.getPixelByteCount();} + + virtual int getTextureWidth() const {return pixmap.getW();} + virtual int getTextureHeight() const {return -1;} + }; // ===================================================== @@ -125,13 +129,16 @@ public: virtual string getPath() const; virtual void deletePixels(); virtual uint64 getPixelByteCount() const {return pixmap.getPixelByteCount();} + + virtual int getTextureWidth() const {return pixmap.getW();} + virtual int getTextureHeight() const {return pixmap.getH();} }; // ===================================================== // class Texture3D // ===================================================== -class Texture3D: public Texture{ +class Texture3D: public Texture { protected: Pixmap3D pixmap; @@ -143,6 +150,9 @@ public: virtual string getPath() const; virtual void deletePixels(); virtual uint64 getPixelByteCount() const {return pixmap.getPixelByteCount();} + + virtual int getTextureWidth() const {return pixmap.getW();} + virtual int getTextureHeight() const {return pixmap.getH();} }; // ===================================================== @@ -161,6 +171,9 @@ public: virtual string getPath() const; virtual void deletePixels(); virtual uint64 getPixelByteCount() const {return pixmap.getPixelByteCount();} + + virtual int getTextureWidth() const {return -1;} + virtual int getTextureHeight() const {return -1;} }; }}//end namespace diff --git a/source/shared_lib/sources/graphics/gl/texture_gl.cpp b/source/shared_lib/sources/graphics/gl/texture_gl.cpp index 24626017..a2de2af9 100644 --- a/source/shared_lib/sources/graphics/gl/texture_gl.cpp +++ b/source/shared_lib/sources/graphics/gl/texture_gl.cpp @@ -421,7 +421,130 @@ GLint toInternalFormatGl(Texture::Format format, int components){ } TextureGl::TextureGl() { - handle=0; + handle = 0; + renderBufferId = 0; + frameBufferId = 0; +} + +void TextureGl::setup_FBO_RBO() { + if(getTextureWidth() < 0 || getTextureHeight() < 0) { + throw runtime_error("getTextureWidth() < 0 || getTextureHeight() < 0"); + } + + printf("getTextureWidth() = %d, getTextureHeight() = %d\n",getTextureWidth(),getTextureHeight()); + + GLint width=0; + glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&width); + GLint height=0; + glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&height); + + printf("width = %d, height = %d\n",width,height); + + //RGBA8 2D texture, 24 bit depth texture, 256x256 + //glGenTextures(1, &color_tex); + //glBindTexture(GL_TEXTURE_2D, color_tex); + //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_MIN_FILTER, GL_NEAREST); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + //NULL means reserve texture memory, but texels are undefined + //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); + //------------------------- + glGenFramebuffersEXT(1, &frameBufferId); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBufferId); + //Attach 2D texture to this FBO + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, handle, 0); + //------------------------- + glGenRenderbuffersEXT(1, &renderBufferId); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderBufferId); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, getTextureWidth(), getTextureHeight()); + //------------------------- + //Attach depth buffer to FBO + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderBufferId); + //------------------------- + //Does the GPU support current FBO configuration? + GLenum status; + status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + switch(status) + { + case GL_FRAMEBUFFER_COMPLETE_EXT: + printf("FBO attachment OK!\n"); + break; + default: + printf("FBO attachment BAD!\n"); + break; + } + //------------------------- + //and now you can render to GL_TEXTURE_2D + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBufferId); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +void TextureGl::teardown_FBO_RBO() { + //---------------- + //Bind 0, which means render to back buffer + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + //And in the end, cleanup + //Delete resources + //glDeleteTextures(1, &handle); + glDeleteRenderbuffersEXT(1, &frameBufferId); + //Bind 0, which means render to back buffer, as a result, fb is unbound + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glDeleteFramebuffersEXT(1, &frameBufferId); +} + +void TextureGl::initRenderBuffer() { + // create a renderbuffer object to store depth info + glGenRenderbuffersEXT(1, &renderBufferId); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderBufferId); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,getTextureWidth(), getTextureHeight()); + //glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); +} + +void TextureGl::initFrameBuffer() { + // create a framebuffer object + glGenFramebuffersEXT(1, &frameBufferId); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBufferId); +} + +void TextureGl::attachRenderBuffer() { + // attach the renderbuffer to depth attachment point + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,GL_RENDERBUFFER_EXT, renderBufferId); +} + +void TextureGl::attachFrameBufferToTexture() { + // attach the texture to FBO color attachment point + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,GL_TEXTURE_2D, handle, 0); +} + +bool TextureGl::checkFrameBufferStatus() { + // check FBO status + // Does the GPU support current FBO configuration? + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + if(status != GL_FRAMEBUFFER_COMPLETE_EXT) { + printf("checkFrameBufferStatus() status = %d [%X]\n",status,status); + return false; + } + return true; +} + +void TextureGl::dettachFrameBufferFromTexture() { + // switch back to window-system-provided framebuffer + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); +} + +TextureGl::~TextureGl() { + if(renderBufferId != 0) { + glDeleteRenderbuffersEXT(1, &renderBufferId); + renderBufferId = 0; + } + if(frameBufferId != 0) { + glDeleteFramebuffersEXT(1, &frameBufferId); + frameBufferId = 0; + } + + //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } // ===================================================== @@ -492,7 +615,7 @@ void Texture1DGl::init(Filter filter, int maxAnisotropy) { if(error!=GL_NO_ERROR){ //throw runtime_error("Error creating texture 1D"); char szBuf[1024]=""; - sprintf(szBuf,"Error creating texture 1D, returned: %d [%s] w = %d, glCompressionFormat = %d",error,pixmap.getPath().c_str(),pixmap.getW(),glCompressionFormat); + sprintf(szBuf,"Error creating texture 1D, returned: %d (%X) [%s] w = %d, glCompressionFormat = %d",error,error,pixmap.getPath().c_str(),pixmap.getW(),glCompressionFormat); throw runtime_error(szBuf); } } @@ -579,17 +702,15 @@ void Texture2DGl::init(Filter filter, int maxAnisotropy) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D( - GL_TEXTURE_2D, 0, glCompressionFormat, - pixmap.getW(), pixmap.getH(), - 0, glFormat, GL_UNSIGNED_BYTE, pixels); - GLint error= glGetError(); + glTexImage2D(GL_TEXTURE_2D, 0, glCompressionFormat,pixmap.getW(), + pixmap.getH(),0, glFormat, GL_UNSIGNED_BYTE, pixels); + GLint error= glGetError(); //throw runtime_error("TEST!"); if(error != GL_NO_ERROR) { char szBuf[1024]=""; - sprintf(szBuf,"Error creating texture 2D, returned: %d [%s] w = %d, h = %d, glInternalFormat = %d, glFormat = %d, glCompressionFormat = %d",error,pixmap.getPath().c_str(),pixmap.getW(),pixmap.getH(),glInternalFormat,glFormat,glCompressionFormat); + sprintf(szBuf,"Error creating texture 2D, returned: %d (%X) [%s] w = %d, h = %d, glInternalFormat = %d, glFormat = %d, glCompressionFormat = %d",error,error,pixmap.getPath().c_str(),pixmap.getW(),pixmap.getH(),glInternalFormat,glFormat,glCompressionFormat); throw runtime_error(szBuf); } } @@ -665,7 +786,7 @@ void Texture3DGl::init(Filter filter, int maxAnisotropy) { if(error != GL_NO_ERROR) { //throw runtime_error("Error creating texture 3D"); char szBuf[1024]=""; - sprintf(szBuf,"Error creating texture 3D, returned: %d [%s] w = %d, h = %d, d = %d, glCompressionFormat = %d",error,pixmap.getPath().c_str(),pixmap.getW(),pixmap.getH(),pixmap.getD(),glCompressionFormat); + sprintf(szBuf,"Error creating texture 3D, returned: %d (%X) [%s] w = %d, h = %d, d = %d, glCompressionFormat = %d",error,error,pixmap.getPath().c_str(),pixmap.getW(),pixmap.getH(),pixmap.getD(),glCompressionFormat); throw runtime_error(szBuf); } inited= true; @@ -762,7 +883,7 @@ void TextureCubeGl::init(Filter filter, int maxAnisotropy) { if(error != GL_NO_ERROR) { //throw runtime_error("Error creating texture cube"); char szBuf[1024]=""; - sprintf(szBuf,"Error creating texture cube, returned: %d [%s] w = %d, h = %d, glCompressionFormat = %d",error,currentPixmap->getPath().c_str(),currentPixmap->getW(),currentPixmap->getH(),glCompressionFormat); + sprintf(szBuf,"Error creating texture cube, returned: %d (%X) [%s] w = %d, h = %d, glCompressionFormat = %d",error,error,currentPixmap->getPath().c_str(),currentPixmap->getW(),currentPixmap->getH(),glCompressionFormat); throw runtime_error(szBuf); } @@ -798,7 +919,7 @@ void TextureGl::OutputTextureDebugInfo(Texture::Format format, int components,co glGetTexLevelParameteriv(texType, 0, GL_TEXTURE_COMPRESSED, &compressed); int error = glGetError(); - printf("**** Texture compressed status: %d, error [%d]\n",compressed,error); + printf("**** Texture compressed status: %d, error [%d] (%X)\n",compressed,error,error); bool isCompressed = (compressed == 1); compressed=0; @@ -810,12 +931,12 @@ void TextureGl::OutputTextureDebugInfo(Texture::Format format, int components,co percent = ((double)compressed / (double)rawSize) * (double)100.0; } - printf("**** Texture image size in video RAM: %d [%.2f%%], error [%d]\n",compressed,percent,error); + printf("**** Texture image size in video RAM: %d [%.2f%%], error [%d] (%X)\n",compressed,percent,error,error); compressed=0; glGetTexLevelParameteriv(texType, 0, GL_TEXTURE_INTERNAL_FORMAT, &compressed); error = glGetError(); - printf("**** Texture image compression format used: %d, error [%d]\n",compressed,error); + printf("**** Texture image compression format used: %d, error [%d] (%X)\n",compressed,error,error); } }