// This file is part of Glest (www.glest.org) // // Copyright (C) 2001-2008 MartiƱo Figueroa // // You can redistribute this code and/or modify it under // the terms of the GNU General Public License as published // by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version // ============================================================== #define NOMINMAX #include "renderer.h" #include "texture_gl.h" #include "main_menu.h" #include "config.h" #include "components.h" #include "time_flow.h" #include "graphics_interface.h" #include "object.h" #include "core_data.h" #include "game.h" #include "metrics.h" #include "opengl.h" #include "faction.h" #include "factory_repository.h" #include #include "cache_manager.h" #include "network_manager.h" #include #include #include "leak_dumper.h" using namespace Shared::Graphics; using namespace Shared::Graphics::Gl; using namespace Shared::Util; using namespace Shared::Graphics; namespace Glest { namespace Game{ uint32 Renderer::SurfaceData::nextUniqueId = 1; bool Renderer::renderText3DEnabled = true; //const float SKIP_INTERPOLATION_DISTANCE = 20.0f; const string DEFAULT_CHAR_FOR_WIDTH_CALC = "V"; enum PROJECTION_TO_INFINITY { pti_D_IS_ZERO, pti_N_OVER_D_IS_OUTSIDE }; // ===================================================== // class MeshCallbackTeamColor // ===================================================== bool MeshCallbackTeamColor::noTeamColors = false; void MeshCallbackTeamColor::execute(const Mesh *mesh) { //team color if( mesh->getCustomTexture() && teamTexture != NULL && MeshCallbackTeamColor::noTeamColors == false) { //texture 0 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); //set color to interpolation glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE1); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA); //set alpha to 1 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); //texture 1 glActiveTexture(GL_TEXTURE1); glMultiTexCoord2f(GL_TEXTURE1, 0.f, 0.f); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, static_cast(teamTexture)->getHandle()); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); //set alpha to 1 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); glActiveTexture(GL_TEXTURE0); } else { glActiveTexture(GL_TEXTURE1); glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } } // =========================================================== // class Renderer // =========================================================== // ===================== PUBLIC ======================== const int Renderer::maxProgressBar= 100; const Vec4f Renderer::progressBarBack1= Vec4f(0.7f, 0.7f, 0.7f, 0.7f); const Vec4f Renderer::progressBarBack2= Vec4f(0.7f, 0.7f, 0.7f, 1.f); const Vec4f Renderer::progressBarFront1= Vec4f(0.f, 0.5f, 0.f, 1.f); const Vec4f Renderer::progressBarFront2= Vec4f(0.f, 0.1f, 0.f, 1.f); const float Renderer::sunDist= 10e6; const float Renderer::moonDist= 10e6; const float Renderer::lightAmbFactor= 0.4f; const int Renderer::maxMouse2dAnim= 100; const GLenum Renderer::baseTexUnit= GL_TEXTURE0; const GLenum Renderer::fowTexUnit= GL_TEXTURE1; const GLenum Renderer::shadowTexUnit= GL_TEXTURE2; const float Renderer::selectionCircleRadius= 0.7f; const float Renderer::magicCircleRadius= 1.f; //perspective values const float Renderer::perspFov= 60.f; const float Renderer::perspNearPlane= 1.f; //const float Renderer::perspFarPlane= 50.f; float Renderer::perspFarPlane= 1000000.f; const float Renderer::ambFactor= 0.7f; const Vec4f Renderer::fowColor= Vec4f(0.0f, 0.0f, 0.0f, 1.0f); const Vec4f Renderer::defSpecularColor= Vec4f(0.8f, 0.8f, 0.8f, 1.f); const Vec4f Renderer::defDiffuseColor= Vec4f(1.f, 1.f, 1.f, 1.f); const Vec4f Renderer::defAmbientColor= Vec4f(1.f * ambFactor, 1.f * ambFactor, 1.f * ambFactor, 1.f); const Vec4f Renderer::defColor= Vec4f(1.f, 1.f, 1.f, 1.f); //const float Renderer::maxLightDist= 100.f; const float Renderer::maxLightDist= 100.f; bool Renderer::rendererEnded = true; const int MIN_FPS_NORMAL_RENDERING = 15; const int MIN_FPS_NORMAL_RENDERING_TOP_THRESHOLD = 25; const int OBJECT_SELECT_OFFSET=100000000; bool VisibleQuadContainerCache::enableFrustumCalcs = true; // ==================== constructor and destructor ==================== Renderer::Renderer() : BaseRenderer(), saveScreenShotThreadAccessor(new Mutex(CODE_AT_LINE)) { //this->masterserverMode = masterserverMode; //printf("this->masterserverMode = %d\n",this->masterserverMode); //assert(0==1); Renderer::rendererEnded = false; shadowIntensity = 0; shadowFrameSkip = 0; triangleCount = 0; smoothedRenderFps = 0; shadowTextureSize = 0; shadows = sDisabled; shadowMapFrame = 0; textures3D = false; photoMode = false; focusArrows = false; pointCount = 0; maxLights = 0; waterAnim = 0; this->allowRenderUnitTitles = false; this->menu = NULL; this->game = NULL; this->gameCamera = NULL; showDebugUI = false; showDebugUILevel = debugui_fps; modelRenderer = NULL; textRenderer = NULL; textRenderer3D = NULL; particleRenderer = NULL; saveScreenShotThread = NULL; mapSurfaceData.clear(); visibleFrameUnitList.clear(); visibleFrameUnitListCameraKey = ""; quadCache = VisibleQuadContainerCache(); quadCache.clearFrustumData(); lastRenderFps=MIN_FPS_NORMAL_RENDERING; shadowsOffDueToMinRender=false; shadowMapHandle=0; shadowMapHandleValid=false; //list3d=0; //list3dValid=false; //list2d=0; //list2dValid=false; //list3dMenu=0; //list3dMenuValid=false; //customlist3dMenu=NULL; //this->mm3d = NULL; this->custom_mm3d = NULL; this->program = NULL; //resources for(int i=0; i < rsCount; ++i) { modelManager[i] = NULL; textureManager[i] = NULL; particleManager[i] = NULL; fontManager[i] = NULL; } Config &config= Config::getInstance(); Renderer::perspFarPlane = config.getFloat("PerspectiveFarPlane",floatToStr(Renderer::perspFarPlane).c_str()); this->no2DMouseRendering = config.getBool("No2DMouseRendering","false"); this->maxConsoleLines= config.getInt("ConsoleMaxLines"); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] Renderer::perspFarPlane [%f] this->no2DMouseRendering [%d] this->maxConsoleLines [%d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,Renderer::perspFarPlane,this->no2DMouseRendering,this->maxConsoleLines); GraphicsInterface &gi= GraphicsInterface::getInstance(); FactoryRepository &fr= FactoryRepository::getInstance(); gi.setFactory(fr.getGraphicsFactory(config.getString("FactoryGraphics"))); GraphicsFactory *graphicsFactory= GraphicsInterface::getInstance().getFactory(); if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) { modelRenderer= graphicsFactory->newModelRenderer(); textRenderer= graphicsFactory->newTextRenderer2D(); textRenderer3D = graphicsFactory->newTextRenderer3D(); particleRenderer= graphicsFactory->newParticleRenderer(); } //resources for(int i=0; i< rsCount; ++i) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) { modelManager[i]= graphicsFactory->newModelManager(); textureManager[i]= graphicsFactory->newTextureManager(); modelManager[i]->setTextureManager(textureManager[i]); fontManager[i]= graphicsFactory->newFontManager(); } particleManager[i]= graphicsFactory->newParticleManager(); } if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) { static string mutexOwnerId = string(extractFileFromDirectoryPath(__FILE__).c_str()) + string("_") + intToStr(__LINE__); saveScreenShotThread = new SimpleTaskThread(this,0,25); saveScreenShotThread->setUniqueID(mutexOwnerId); saveScreenShotThread->start(); } } void Renderer::cleanupScreenshotThread() { if(saveScreenShotThread) { saveScreenShotThread->signalQuit(); // for(time_t elapsed = time(NULL); // getSaveScreenQueueSize() > 0 && difftime((long int)time(NULL),elapsed) <= 7;) { // sleep(0); // } // if(saveScreenShotThread->canShutdown(true) == true && // saveScreenShotThread->shutdownAndWait() == true) { // //printf("IN MenuStateCustomGame cleanup - C\n"); // delete saveScreenShotThread; // } // saveScreenShotThread = NULL; if(saveScreenShotThread->shutdownAndWait() == true) { delete saveScreenShotThread; } saveScreenShotThread = NULL; if(getSaveScreenQueueSize() > 0) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d] FORCING MEMORY CLEANUP and NOT SAVING screenshots, saveScreenQueue.size() = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,saveScreenQueue.size()); static string mutexOwnerId = string(extractFileFromDirectoryPath(__FILE__).c_str()) + string("_") + intToStr(__LINE__); MutexSafeWrapper safeMutex(saveScreenShotThreadAccessor,mutexOwnerId); for(std::list >::iterator iter = saveScreenQueue.begin(); iter != saveScreenQueue.end(); ++iter) { delete iter->second; } saveScreenQueue.clear(); } } } Renderer::~Renderer() { try{ if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); delete modelRenderer; modelRenderer = NULL; delete textRenderer; textRenderer = NULL; delete textRenderer3D; textRenderer3D = NULL; delete particleRenderer; particleRenderer = NULL; if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //resources for(int i=0; imenu = NULL; this->game = NULL; this->gameCamera = NULL; delete saveScreenShotThreadAccessor; saveScreenShotThreadAccessor = NULL; } catch(const exception &e) { char szBuf[8096]=""; snprintf(szBuf,8096,"In [%s::%s Line: %d]\nError [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,e.what()); SystemFlags::OutputDebug(SystemFlags::debugError,szBuf); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf); throw megaglest_runtime_error(szBuf); } } void Renderer::simpleTask(BaseThread *callingThread,void *userdata) { // This code reads pixmaps from a queue and saves them to disk Pixmap2D *savePixMapBuffer=NULL; string path=""; static string mutexOwnerId = string(extractFileFromDirectoryPath(__FILE__).c_str()) + string("_") + intToStr(__LINE__); MutexSafeWrapper safeMutex(saveScreenShotThreadAccessor,mutexOwnerId); if(saveScreenQueue.empty() == false) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d] saveScreenQueue.size() = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,saveScreenQueue.size()); savePixMapBuffer = saveScreenQueue.front().second; path = saveScreenQueue.front().first; saveScreenQueue.pop_front(); } safeMutex.ReleaseLock(); if(savePixMapBuffer != NULL) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d] about to save [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,path.c_str()); savePixMapBuffer->save(path); delete savePixMapBuffer; } } bool Renderer::isEnded() { return Renderer::rendererEnded; } Renderer &Renderer::getInstance() { static Renderer renderer; return renderer; } void Renderer::reinitAll() { //resources if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } for(int i=0; iinit(); textureManager[i]->init(true); //particleManager[i]->init(); //fontManager[i]->init(); } } // ==================== init ==================== void Renderer::init() { if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); Config &config= Config::getInstance(); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); loadConfig(); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); if(config.getBool("CheckGlCaps")){ if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); checkGlCaps(); } if(glActiveTexture == NULL) { char szBuf[8096]=""; snprintf(szBuf,8096,"Error: glActiveTexture == NULL\nglActiveTexture is only supported if the GL version is 1.3 or greater,\nor if the ARB_multitexture extension is supported!"); throw megaglest_runtime_error(szBuf); } if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); if(config.getBool("FirstTime")){ if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); config.setBool("FirstTime", false); autoConfig(); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); config.save(); } if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); modelManager[rsGlobal]->init(); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); textureManager[rsGlobal]->init(); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); fontManager[rsGlobal]->init(); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); init2dList(); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); glHint(GL_FOG_HINT, GL_FASTEST); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //glHint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST); glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); //glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST); //glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST); glHint(GL_TEXTURE_COMPRESSION_HINT, GL_FASTEST); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); } void Renderer::initGame(const Game *game, GameCamera *gameCamera) { if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); this->gameCamera = gameCamera; VisibleQuadContainerCache::enableFrustumCalcs = Config::getInstance().getBool("EnableFrustrumCalcs","true"); quadCache = VisibleQuadContainerCache(); quadCache.clearFrustumData(); SurfaceData::nextUniqueId = 1; mapSurfaceData.clear(); this->game= game; worldToScreenPosCache.clear(); //vars shadowMapFrame= 0; waterAnim= 0; if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } //check gl caps if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); checkGlOptionalCaps(); //shadows if(shadows == sProjected || shadows == sShadowMapping) { static_cast(modelRenderer)->setSecondaryTexCoordUnit(2); Config &config= Config::getInstance(); glGenTextures(1, &shadowMapHandle); shadowMapHandleValid=true; shadowIntensity= config.getFloat("ShadowIntensity","1.0"); if(game!=NULL){ shadowIntensity=shadowIntensity*game->getWorld()->getTileset()->getShadowIntense(); if(shadowIntensity > 1.0f){ shadowIntensity=1.0f; } } glBindTexture(GL_TEXTURE_2D, shadowMapHandle); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); if(shadows == sShadowMapping) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //shadow mapping glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, 1.0f-shadowAlpha); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, shadowTextureSize, shadowTextureSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); } else { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //projected glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, shadowTextureSize, shadowTextureSize, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); } shadowMapFrame= -1; } if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); IF_DEBUG_EDITION( getDebugRenderer().init(); ) //texture init modelManager[rsGame]->init(); textureManager[rsGame]->init(); fontManager[rsGame]->init(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); init3dList(); } void Renderer::manageDeferredParticleSystems() { // if(deferredParticleSystems.empty() == false) { // printf("deferredParticleSystems.size() = %d\n",(int)deferredParticleSystems.size()); // } for(unsigned int i = 0; i < deferredParticleSystems.size(); ++i) { std::pair &deferredParticleSystem = deferredParticleSystems[i]; ParticleSystem *ps = deferredParticleSystem.first; ResourceScope rs = deferredParticleSystem.second; if(ps->getTextureFileLoadDeferred() != "" && ps->getTexture() == NULL) { CoreData::TextureSystemType textureSystemId = static_cast( ps->getTextureFileLoadDeferredSystemId()); //printf("Load DEFERRED particle i = %d textureSystemId = %d\n",i,textureSystemId); if(textureSystemId != CoreData::tsyst_NONE) { Texture2D *texture= CoreData::getInstance().getTextureBySystemId(textureSystemId); //printf("Loading texture from system [%d] [%p]\n",textureSystemId,texture); ps->setTexture(texture); //printf("#2 Load DEFERRED particle i = %d textureSystemId = %d, texture = %p\n",i,textureSystemId,texture); } else { Texture2D *texture= newTexture2D(rs); if(texture) { texture->setFormat(ps->getTextureFileLoadDeferredFormat()); texture->getPixmap()->init(ps->getTextureFileLoadDeferredComponents()); } if(texture) { string textureFile = ps->getTextureFileLoadDeferred(); if(fileExists(textureFile) == false) { textureFile = Config::findValidLocalFileFromPath(textureFile); } texture->load(textureFile); ps->setTexture(texture); } //printf("#3 Load DEFERRED particle i = %d textureSystemId = %d, texture = %p\n",i,textureSystemId,texture); } } if(dynamic_cast(ps) != NULL) { GameParticleSystem *gps = dynamic_cast(ps); if(gps != NULL && gps->getModelFileLoadDeferred() != "" && gps->getModel() == NULL) { std::map > > loadedFileList; Model *model= newModel(rsGame, gps->getModelFileLoadDeferred(), false, &loadedFileList, NULL); if(model) gps->setModel(model); } } manageParticleSystem(ps, rs); //printf("Managing ps [%p]\n",ps); } deferredParticleSystems.clear(); //printf("After deferredParticleSystems.size() = %d\n",deferredParticleSystems.size()); } void Renderer::initMenu(const MainMenu *mm) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); this->menu = mm; if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } modelManager[rsMenu]->init(); textureManager[rsMenu]->init(); fontManager[rsMenu]->init(); //modelRenderer->setCustomTexture(CoreData::getInstance().getCustomTexture()); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //init3dListMenu(mm); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); } void Renderer::reset3d() { assertGl(); glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); //glCallList(list3d); render3dSetup(); pointCount= 0; triangleCount= 0; assertGl(); } void Renderer::reset2d() { assertGl(); glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); //glCallList(list2d); render2dMenuSetup(); assertGl(); } void Renderer::reset3dMenu() { assertGl(); glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); //printf("In [%s::%s Line: %d] this->custom_mm3d [%p] this->mm3d [%p]\n",__FILE__,__FUNCTION__,__LINE__,this->custom_mm3d,this->mm3d); if(this->custom_mm3d != NULL) { render3dMenuSetup(this->custom_mm3d); //glCallList(*this->customlist3dMenu); } else { render3dMenuSetup(this->menu); //render3dMenuSetup(this->mm3d); //glCallList(list3dMenu); } assertGl(); } // ==================== end ==================== void Renderer::end() { quadCache = VisibleQuadContainerCache(); quadCache.clearFrustumData(); if(Renderer::rendererEnded == true) { return; } std::map &crcFactionPreviewTextureCache = CacheManager::getCachedItem< std::map >(GameConstants::factionPreviewTextureCacheLookupKey); crcFactionPreviewTextureCache.clear(); // Wait for the queue to become empty or timeout the thread at 7 seconds cleanupScreenshotThread(); mapSurfaceData.clear(); //delete resources if(modelManager[rsGlobal]) { modelManager[rsGlobal]->end(); } if(textureManager[rsGlobal]) { textureManager[rsGlobal]->end(); } if(fontManager[rsGlobal]) { fontManager[rsGlobal]->end(); } if(particleManager[rsGlobal]) { particleManager[rsGlobal]->end(); } //delete 2d list //if(list2dValid == true) { // glDeleteLists(list2d, 1); // list2dValid=false; //} Renderer::rendererEnded = true; } void Renderer::endScenario() { this->game= NULL; this->gameCamera = NULL; quadCache = VisibleQuadContainerCache(); quadCache.clearFrustumData(); if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } //delete resources //modelManager[rsGame]->end(); //textureManager[rsGame]->end(); //fontManager[rsGame]->end(); //particleManager[rsGame]->end(); if(shadowMapHandleValid == true && (shadows == sProjected || shadows == sShadowMapping)) { glDeleteTextures(1, &shadowMapHandle); shadowMapHandleValid=false; } //if(list3dValid == true) { // glDeleteLists(list3d, 1); // list3dValid=false; //} worldToScreenPosCache.clear(); ReleaseSurfaceVBOs(); mapSurfaceData.clear(); } void Renderer::endGame(bool isFinalEnd) { this->game= NULL; this->gameCamera = NULL; Config &config= Config::getInstance(); try { quadCache = VisibleQuadContainerCache(); quadCache.clearFrustumData(); } catch(const exception &e) { char szBuf[8096]=""; snprintf(szBuf,8096,"In [%s::%s Line: %d]\nError [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,e.what()); SystemFlags::OutputDebug(SystemFlags::debugError,szBuf); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf); abort(); } if(isFinalEnd) { //delete resources if(modelManager[rsGame] != NULL) { modelManager[rsGame]->end(); } if(textureManager[rsGame] != NULL) { textureManager[rsGame]->end(); } if(fontManager[rsGame] != NULL) { fontManager[rsGame]->end(); } if(particleManager[rsGame] != NULL) { particleManager[rsGame]->end(); } } if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(shadowMapHandleValid == true && (shadows == sProjected || shadows == sShadowMapping)) { glDeleteTextures(1, &shadowMapHandle); shadowMapHandleValid=false; } shadowIntensity= config.getFloat("ShadowIntensity","1.0"); //if(list3dValid == true) { // glDeleteLists(list3d, 1); // list3dValid=false; //} worldToScreenPosCache.clear(); ReleaseSurfaceVBOs(); mapSurfaceData.clear(); } void Renderer::endMenu() { this->menu = NULL; //delete resources if(modelManager[rsMenu]) { modelManager[rsMenu]->end(); } if(textureManager[rsMenu]) { textureManager[rsMenu]->end(); } if(fontManager[rsMenu]) { fontManager[rsMenu]->end(); } if(particleManager[rsMenu]) { particleManager[rsMenu]->end(); } if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } //if(this->customlist3dMenu != NULL) { // glDeleteLists(*this->customlist3dMenu,1); //} //else { // glDeleteLists(list3dMenu, 1); //} } //void Renderer::reloadResources() { // if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { // return; // } // // for(int i=0; iend(); // textureManager[i]->end(); // fontManager[i]->end(); // } // // for(int i=0; iinit(); // textureManager[i]->init(); // fontManager[i]->init(); // } //} // ==================== engine interface ==================== void Renderer::initTexture(ResourceScope rs, Texture *texture) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } textureManager[rs]->initTexture(texture); } void Renderer::endTexture(ResourceScope rs, Texture *texture, bool mustExistInList) { string textureFilename = texture->getPath(); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] free texture from manager [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,textureFilename.c_str()); if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } textureManager[rs]->endTexture(texture,mustExistInList); if(rs == rsGlobal) { std::map &crcFactionPreviewTextureCache = CacheManager::getCachedItem< std::map >(GameConstants::factionPreviewTextureCacheLookupKey); if(crcFactionPreviewTextureCache.find(textureFilename) != crcFactionPreviewTextureCache.end()) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] textureFilename [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,textureFilename.c_str()); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] free texture from cache [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,textureFilename.c_str()); crcFactionPreviewTextureCache.erase(textureFilename); } } } void Renderer::endLastTexture(ResourceScope rs, bool mustExistInList) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } textureManager[rs]->endLastTexture(mustExistInList); } Model *Renderer::newModel(ResourceScope rs,const string &path,bool deletePixMapAfterLoad,std::map > > *loadedFileList, string *sourceLoader){ if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return NULL; } return modelManager[rs]->newModel(path,deletePixMapAfterLoad,loadedFileList,sourceLoader); } void Renderer::endModel(ResourceScope rs, Model *model,bool mustExistInList) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } modelManager[rs]->endModel(model,mustExistInList); } void Renderer::endLastModel(ResourceScope rs, bool mustExistInList) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } modelManager[rs]->endLastModel(mustExistInList); } Texture2D *Renderer::newTexture2D(ResourceScope rs){ if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return NULL; } return textureManager[rs]->newTexture2D(); } Texture3D *Renderer::newTexture3D(ResourceScope rs){ if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return NULL; } return textureManager[rs]->newTexture3D(); } Font2D *Renderer::newFont(ResourceScope rs){ if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return NULL; } return fontManager[rs]->newFont2D(); } Font3D *Renderer::newFont3D(ResourceScope rs){ if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return NULL; } return fontManager[rs]->newFont3D(); } void Renderer::endFont(::Shared::Graphics::Font *font, ResourceScope rs, bool mustExistInList) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } fontManager[rs]->endFont(font,mustExistInList); } //void Renderer::resetFontManager(ResourceScope rs) { // if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { // return; // } // fontManager[rs]->end(); // fontManager[rsGlobal]->init(); //} void Renderer::addToDeferredParticleSystemList(std::pair deferredParticleSystem) { deferredParticleSystems.push_back(deferredParticleSystem); } void Renderer::manageParticleSystem(ParticleSystem *particleSystem, ResourceScope rs){ particleManager[rs]->manage(particleSystem); } bool Renderer::validateParticleSystemStillExists(ParticleSystem * particleSystem,ResourceScope rs) const { return particleManager[rs]->validateParticleSystemStillExists(particleSystem); } void Renderer::removeParticleSystemsForParticleOwner(ParticleOwner * particleOwner,ResourceScope rs) { particleManager[rs]->removeParticleSystemsForParticleOwner(particleOwner); } void Renderer::cleanupParticleSystems(vector &particleSystems, ResourceScope rs) { particleManager[rs]->cleanupParticleSystems(particleSystems); } void Renderer::cleanupUnitParticleSystems(vector &particleSystems, ResourceScope rs) { particleManager[rs]->cleanupUnitParticleSystems(particleSystems); } void Renderer::updateParticleManager(ResourceScope rs, int renderFps) { particleManager[rs]->update(renderFps); } void Renderer::renderParticleManager(ResourceScope rs){ if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glDepthFunc(GL_LESS); particleRenderer->renderManager(particleManager[rs], modelRenderer); glPopAttrib(); } void Renderer::swapBuffers() { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } //glFlush(); // should not be required - http://www.opengl.org/wiki/Common_Mistakes //glFlush(); GraphicsInterface::getInstance().getCurrentContext()->swapBuffers(); } // ==================== lighting ==================== //places all the opengl lights void Renderer::setupLighting() { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } int lightCount= 0; const World *world= game->getWorld(); const GameCamera *gameCamera= game->getGameCamera(); const TimeFlow *timeFlow= world->getTimeFlow(); float time= timeFlow->getTime(); assertGl(); //sun/moon light Vec3f lightColor= timeFlow->computeLightColor(); Vec3f fogColor= world->getTileset()->getFogColor(); Vec4f lightPos= timeFlow->isDay()? computeSunPos(time): computeMoonPos(time); nearestLightPos= lightPos; glLightfv(GL_LIGHT0, GL_POSITION, lightPos.ptr()); glLightfv(GL_LIGHT0, GL_AMBIENT, Vec4f(lightColor*lightAmbFactor, 1.f).ptr()); glLightfv(GL_LIGHT0, GL_DIFFUSE, Vec4f(lightColor, 1.f).ptr()); glLightfv(GL_LIGHT0, GL_SPECULAR, Vec4f(0.0f, 0.0f, 0.f, 1.f).ptr()); glFogfv(GL_FOG_COLOR, Vec4f(fogColor*lightColor, 1.f).ptr()); lightCount++; //disable all secondary lights for(int i= 1; i < maxLights; ++i) { glDisable(GL_LIGHT0 + i); } //unit lights (not projectiles) if(timeFlow->isTotalNight()) { VisibleQuadContainerCache &qCache = getQuadCache(); if(qCache.visibleQuadUnitList.empty() == false) { //bool modelRenderStarted = false; for(int visibleUnitIndex = 0; visibleUnitIndex < (int)qCache.visibleQuadUnitList.size() && lightCount < maxLights; ++visibleUnitIndex) { Unit *unit = qCache.visibleQuadUnitList[visibleUnitIndex]; if(world->toRenderUnit(unit) && unit->getCurrMidHeightVector().dist(gameCamera->getPos()) < maxLightDist && unit->getType()->getLight() && unit->isOperative()) { //printf("$$$ Show light for faction: %s # %d / %d for Unit [%d - %s]\n",world->getFaction(i)->getType()->getName().c_str(),lightCount,maxLights,unit->getId(),unit->getFullName().c_str()); Vec4f pos= Vec4f(unit->getCurrMidHeightVector()); pos.y+=4.f; GLenum lightEnum= GL_LIGHT0 + lightCount; glEnable(lightEnum); glLightfv(lightEnum, GL_POSITION, pos.ptr()); glLightfv(lightEnum, GL_AMBIENT, Vec4f(unit->getType()->getLightColor()).ptr()); glLightfv(lightEnum, GL_DIFFUSE, Vec4f(unit->getType()->getLightColor()).ptr()); glLightfv(lightEnum, GL_SPECULAR, Vec4f(unit->getType()->getLightColor()*0.3f).ptr()); glLightf(lightEnum, GL_QUADRATIC_ATTENUATION, 0.05f); ++lightCount; const GameCamera *gameCamera= game->getGameCamera(); if(Vec3f(pos).dist(gameCamera->getPos())getPos())){ nearestLightPos= pos; } } } } } assertGl(); } //void Renderer::setupLightingForRotatedModel() { // if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { // return; // } // // const World *world= game->getWorld(); // //const GameCamera *gameCamera= game->getGameCamera(); // const TimeFlow *timeFlow= world->getTimeFlow(); // float time= timeFlow->getTime(); // // assertGl(); // // //sun/moon light // Vec3f lightColor= timeFlow->computeLightColor(); // Vec3f fogColor= world->getTileset()->getFogColor(); // Vec4f lightPos= timeFlow->isDay()? computeSunPos(time): computeMoonPos(time); // //nearestLightPos= lightPos; // // glLightfv(GL_LIGHT0, GL_POSITION, lightPos.ptr()); // glLightfv(GL_LIGHT0, GL_AMBIENT, Vec4f(lightColor*lightAmbFactor, 1.f).ptr()); // glLightfv(GL_LIGHT0, GL_DIFFUSE, Vec4f(lightColor, 1.f).ptr()); // glLightfv(GL_LIGHT0, GL_SPECULAR, Vec4f(0.0f, 0.0f, 0.f, 1.f).ptr()); // // glFogfv(GL_FOG_COLOR, Vec4f(fogColor*lightColor, 1.f).ptr()); // // assertGl(); //} void Renderer::loadGameCameraMatrix() { const GameCamera *gameCamera= game->getGameCamera(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); if(gameCamera != NULL) { glRotatef(gameCamera->getVAng(), -1, 0, 0); glRotatef(gameCamera->getHAng(), 0, 1, 0); glTranslatef(-(gameCamera->getPos().x + gameCamera->getShakeOffset().x), -gameCamera->getPos().y, -(gameCamera->getPos().z + gameCamera->getShakeOffset().y)); } } void Renderer::loadCameraMatrix(const Camera *camera) { const Vec3f &position= camera->getConstPosition(); Quaternion orientation= camera->getOrientation().conjugate(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMultMatrixf(orientation.toMatrix4().ptr()); glTranslatef(-position.x, -position.y, -position.z); } static Vec2i _unprojectMap(const Vec2i& pt,const GLdouble* model,const GLdouble* projection,const GLint* viewport,const char* label=NULL) { Vec3d a,b; /* note viewport[3] is height of window in pixels */ GLint realy = viewport[3] - (GLint) pt.y; gluUnProject(pt.x,realy,0,model,projection,viewport,&a.x,&a.y,&a.z); gluUnProject(pt.x,realy,1,model,projection,viewport,&b.x,&b.y,&b.z); // junk values if you were looking parallel to the XZ plane; this shouldn't happen as the camera can't do this? const Vec3f start(a.x,a.y,a.z), stop(b.x,b.y,b.z), plane(0,0,0), norm(0,1,0), u = stop-start, w = start-plane; const float d = norm.x*u.x + norm.y*u.y + norm.z*u.z; if(std::fabs(d) < 0.00001) throw pti_D_IS_ZERO; const float nd = -(norm.x*w.x + norm.y*w.y + norm.z*w.z) / d; if(nd < 0.0 || nd >= 1.0) throw pti_N_OVER_D_IS_OUTSIDE; const Vec3f i = start + u*nd; //const Vec2i pos(i.x,i.z); Vec2i pos; if(strcmp(label,"tl") == 0) { pos = Vec2i(std::floor(i.x),std::floor(i.z)); } else if(strcmp(label,"tr") == 0) { pos = Vec2i(std::ceil(i.x),std::floor(i.z)); } else if(strcmp(label,"bl") == 0) { pos = Vec2i(std::floor(i.x),std::ceil(i.z)); } else if(strcmp(label,"br") == 0) { pos = Vec2i(std::ceil(i.x),std::ceil(i.z)); } if(false) { // print debug info if(label) printf("%s ",label); printf("%d,%d -> %f,%f,%f -> %f,%f,%f -> %f,%f,%f -> %d,%d\n", pt.x,pt.y, start.x,start.y,start.z, stop.x,stop.y,stop.z, i.x,i.y,i.z, pos.x,pos.y); } return pos; } bool Renderer::ExtractFrustum(VisibleQuadContainerCache &quadCacheItem) { bool frustumChanged = false; vector proj(16,0); vector modl(16,0); /* Get the current PROJECTION matrix from OpenGL */ glGetFloatv( GL_PROJECTION_MATRIX, &proj[0] ); /* Get the current MODELVIEW matrix from OpenGL */ glGetFloatv( GL_MODELVIEW_MATRIX, &modl[0] ); // for(unsigned int i = 0; i < proj.size(); ++i) { // //printf("\ni = %d proj [%f][%f] modl [%f][%f]\n",i,proj[i],quadCacheItem.proj[i],modl[i],quadCacheItem.modl[i]); // if(proj[i] != quadCacheItem.proj[i]) { // frustumChanged = true; // break; // } // if(modl[i] != quadCacheItem.modl[i]) { // frustumChanged = true; // break; // } // } // Check the frustum cache const bool useFrustumCache = Config::getInstance().getBool("EnableFrustrumCache","false"); pair,vector > lookupKey; if(useFrustumCache == true) { lookupKey = make_pair(proj,modl); map,vector >, vector > >::iterator iterFind = quadCacheItem.frustumDataCache.find(lookupKey); if(iterFind != quadCacheItem.frustumDataCache.end()) { if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\nCalc Frustum found in cache\n"); quadCacheItem.frustumData = iterFind->second; frustumChanged = (quadCacheItem.proj != proj || quadCacheItem.modl != modl); if(frustumChanged == true) { quadCacheItem.proj = proj; quadCacheItem.modl = modl; } return frustumChanged; } } if(quadCacheItem.proj != proj || quadCacheItem.modl != modl) { //if(frustumChanged == true) { frustumChanged = true; vector > &frustum = quadCacheItem.frustumData; //assert(frustum.size() == 6); //assert(frustum[0].size() == 4); quadCacheItem.proj = proj; quadCacheItem.modl = modl; float clip[16]; float t=0; /* Combine the two matrices (multiply projection by modelview) */ clip[ 0] = modl[ 0] * proj[ 0] + modl[ 1] * proj[ 4] + modl[ 2] * proj[ 8] + modl[ 3] * proj[12]; clip[ 1] = modl[ 0] * proj[ 1] + modl[ 1] * proj[ 5] + modl[ 2] * proj[ 9] + modl[ 3] * proj[13]; clip[ 2] = modl[ 0] * proj[ 2] + modl[ 1] * proj[ 6] + modl[ 2] * proj[10] + modl[ 3] * proj[14]; clip[ 3] = modl[ 0] * proj[ 3] + modl[ 1] * proj[ 7] + modl[ 2] * proj[11] + modl[ 3] * proj[15]; clip[ 4] = modl[ 4] * proj[ 0] + modl[ 5] * proj[ 4] + modl[ 6] * proj[ 8] + modl[ 7] * proj[12]; clip[ 5] = modl[ 4] * proj[ 1] + modl[ 5] * proj[ 5] + modl[ 6] * proj[ 9] + modl[ 7] * proj[13]; clip[ 6] = modl[ 4] * proj[ 2] + modl[ 5] * proj[ 6] + modl[ 6] * proj[10] + modl[ 7] * proj[14]; clip[ 7] = modl[ 4] * proj[ 3] + modl[ 5] * proj[ 7] + modl[ 6] * proj[11] + modl[ 7] * proj[15]; clip[ 8] = modl[ 8] * proj[ 0] + modl[ 9] * proj[ 4] + modl[10] * proj[ 8] + modl[11] * proj[12]; clip[ 9] = modl[ 8] * proj[ 1] + modl[ 9] * proj[ 5] + modl[10] * proj[ 9] + modl[11] * proj[13]; clip[10] = modl[ 8] * proj[ 2] + modl[ 9] * proj[ 6] + modl[10] * proj[10] + modl[11] * proj[14]; clip[11] = modl[ 8] * proj[ 3] + modl[ 9] * proj[ 7] + modl[10] * proj[11] + modl[11] * proj[15]; clip[12] = modl[12] * proj[ 0] + modl[13] * proj[ 4] + modl[14] * proj[ 8] + modl[15] * proj[12]; clip[13] = modl[12] * proj[ 1] + modl[13] * proj[ 5] + modl[14] * proj[ 9] + modl[15] * proj[13]; clip[14] = modl[12] * proj[ 2] + modl[13] * proj[ 6] + modl[14] * proj[10] + modl[15] * proj[14]; clip[15] = modl[12] * proj[ 3] + modl[13] * proj[ 7] + modl[14] * proj[11] + modl[15] * proj[15]; /* Extract the numbers for the RIGHT plane */ frustum[0][0] = clip[ 3] - clip[ 0]; frustum[0][1] = clip[ 7] - clip[ 4]; frustum[0][2] = clip[11] - clip[ 8]; frustum[0][3] = clip[15] - clip[12]; if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\nCalc Frustum #%da: [%f][%f][%f][%f]\n",0,frustum[0][0],frustum[0][1],frustum[0][2],frustum[0][3]); /* Normalize the result */ t = std::sqrt( frustum[0][0] * frustum[0][0] + frustum[0][1] * frustum[0][1] + frustum[0][2] * frustum[0][2] ); if(t != 0.0) { frustum[0][0] /= t; frustum[0][1] /= t; frustum[0][2] /= t; frustum[0][3] /= t; if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\nCalc Frustum #%db: [%f][%f][%f][%f] t = %f\n",0,frustum[0][0],frustum[0][1],frustum[0][2],frustum[0][3],t); } /* Extract the numbers for the LEFT plane */ frustum[1][0] = clip[ 3] + clip[ 0]; frustum[1][1] = clip[ 7] + clip[ 4]; frustum[1][2] = clip[11] + clip[ 8]; frustum[1][3] = clip[15] + clip[12]; if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\nCalc Frustum #%da: [%f][%f][%f][%f]\n",1,frustum[1][0],frustum[1][1],frustum[1][2],frustum[1][3]); /* Normalize the result */ t = std::sqrt( frustum[1][0] * frustum[1][0] + frustum[1][1] * frustum[1][1] + frustum[1][2] * frustum[1][2] ); if(t != 0.0) { frustum[1][0] /= t; frustum[1][1] /= t; frustum[1][2] /= t; frustum[1][3] /= t; if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\nCalc Frustum #%db: [%f][%f][%f][%f] t = %f\n",1,frustum[1][0],frustum[1][1],frustum[1][2],frustum[1][3],t); } /* Extract the BOTTOM plane */ frustum[2][0] = clip[ 3] + clip[ 1]; frustum[2][1] = clip[ 7] + clip[ 5]; frustum[2][2] = clip[11] + clip[ 9]; frustum[2][3] = clip[15] + clip[13]; if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\nCalc Frustum #%da: [%f][%f][%f][%f]\n",2,frustum[2][0],frustum[2][1],frustum[2][2],frustum[2][3]); /* Normalize the result */ t = std::sqrt( frustum[2][0] * frustum[2][0] + frustum[2][1] * frustum[2][1] + frustum[2][2] * frustum[2][2] ); if(t != 0.0) { frustum[2][0] /= t; frustum[2][1] /= t; frustum[2][2] /= t; frustum[2][3] /= t; if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\nCalc Frustum #%db: [%f][%f][%f][%f] t = %f\n",2,frustum[2][0],frustum[2][1],frustum[2][2],frustum[2][3],t); } /* Extract the TOP plane */ frustum[3][0] = clip[ 3] - clip[ 1]; frustum[3][1] = clip[ 7] - clip[ 5]; frustum[3][2] = clip[11] - clip[ 9]; frustum[3][3] = clip[15] - clip[13]; if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\nCalc Frustum #%da: [%f][%f][%f][%f]\n",3,frustum[3][0],frustum[3][1],frustum[3][2],frustum[3][3]); /* Normalize the result */ t = std::sqrt( frustum[3][0] * frustum[3][0] + frustum[3][1] * frustum[3][1] + frustum[3][2] * frustum[3][2] ); if(t != 0.0) { frustum[3][0] /= t; frustum[3][1] /= t; frustum[3][2] /= t; frustum[3][3] /= t; if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\nCalc Frustum #%db: [%f][%f][%f][%f] t = %f\n",3,frustum[3][0],frustum[3][1],frustum[3][2],frustum[3][3],t); } /* Extract the FAR plane */ frustum[4][0] = clip[ 3] - clip[ 2]; frustum[4][1] = clip[ 7] - clip[ 6]; frustum[4][2] = clip[11] - clip[10]; frustum[4][3] = clip[15] - clip[14]; if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\nCalc Frustum #%da: [%f][%f][%f][%f]\n",4,frustum[4][0],frustum[4][1],frustum[4][2],frustum[4][3]); /* Normalize the result */ t = std::sqrt( frustum[4][0] * frustum[4][0] + frustum[4][1] * frustum[4][1] + frustum[4][2] * frustum[4][2] ); if(t != 0.0) { frustum[4][0] /= t; frustum[4][1] /= t; frustum[4][2] /= t; frustum[4][3] /= t; if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\nCalc Frustum #%db: [%f][%f][%f][%f] t = %f\n",4,frustum[4][0],frustum[4][1],frustum[4][2],frustum[4][3],t); } /* Extract the NEAR plane */ frustum[5][0] = clip[ 3] + clip[ 2]; frustum[5][1] = clip[ 7] + clip[ 6]; frustum[5][2] = clip[11] + clip[10]; frustum[5][3] = clip[15] + clip[14]; if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\nCalc Frustum #%da: [%f][%f][%f][%f]\n",5,frustum[5][0],frustum[5][1],frustum[5][2],frustum[5][3]); /* Normalize the result */ t = std::sqrt( frustum[5][0] * frustum[5][0] + frustum[5][1] * frustum[5][1] + frustum[5][2] * frustum[5][2] ); if(t != 0.0) { frustum[5][0] /= t; frustum[5][1] /= t; frustum[5][2] /= t; frustum[5][3] /= t; if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\nCalc Frustum #%db: [%f][%f][%f][%f] t = %f\n",5,frustum[5][0],frustum[5][1],frustum[5][2],frustum[5][3],t); } if(useFrustumCache == true) { quadCacheItem.frustumDataCache[lookupKey] = frustum; } } return frustumChanged; } //bool Renderer::PointInFrustum(vector > &frustum, float x, float y, float z ) { // unsigned int p=0; // // for( p = 0; p < frustum.size(); p++ ) { // if( frustum[p][0] * x + frustum[p][1] * y + frustum[p][2] * z + frustum[p][3] <= 0 ) { // return false; // } // } // return true; //} // //bool Renderer::SphereInFrustum(vector > &frustum, float x, float y, float z, float radius) { // // Go through all the sides of the frustum // for(int i = 0; i < (int)frustum.size(); i++ ) { // // If the center of the sphere is farther away from the plane than the radius // if(frustum[i][0] * x + frustum[i][1] * y + frustum[i][2] * z + frustum[i][3] <= -radius ) { // // The distance was greater than the radius so the sphere is outside of the frustum // return false; // } // } // // // The sphere was inside of the frustum! // return true; //} bool Renderer::CubeInFrustum(vector > &frustum, float x, float y, float z, float size ) { unsigned int p=0; for( p = 0; p < frustum.size(); p++ ) { if( frustum[p][0] * (x - size) + frustum[p][1] * (y - size) + frustum[p][2] * (z - size) + frustum[p][3] > 0 ) continue; if( frustum[p][0] * (x + size) + frustum[p][1] * (y - size) + frustum[p][2] * (z - size) + frustum[p][3] > 0 ) continue; if( frustum[p][0] * (x - size) + frustum[p][1] * (y + size) + frustum[p][2] * (z - size) + frustum[p][3] > 0 ) continue; if( frustum[p][0] * (x + size) + frustum[p][1] * (y + size) + frustum[p][2] * (z - size) + frustum[p][3] > 0 ) continue; if( frustum[p][0] * (x - size) + frustum[p][1] * (y - size) + frustum[p][2] * (z + size) + frustum[p][3] > 0 ) continue; if( frustum[p][0] * (x + size) + frustum[p][1] * (y - size) + frustum[p][2] * (z + size) + frustum[p][3] > 0 ) continue; if( frustum[p][0] * (x - size) + frustum[p][1] * (y + size) + frustum[p][2] * (z + size) + frustum[p][3] > 0 ) continue; if( frustum[p][0] * (x + size) + frustum[p][1] * (y + size) + frustum[p][2] * (z + size) + frustum[p][3] > 0 ) continue; return false; } return true; } void Renderer::computeVisibleQuad() { visibleQuad = this->gameCamera->computeVisibleQuad(); bool frustumChanged = false; if(VisibleQuadContainerCache::enableFrustumCalcs == true) { frustumChanged = ExtractFrustum(quadCache); } if(frustumChanged && SystemFlags::VERBOSE_MODE_ENABLED) { printf("\nCamera: %d,%d %d,%d %d,%d %d,%d\n", visibleQuad.p[0].x,visibleQuad.p[0].y, visibleQuad.p[1].x,visibleQuad.p[1].y, visibleQuad.p[2].x,visibleQuad.p[2].y, visibleQuad.p[3].x,visibleQuad.p[3].y); for(unsigned int i = 0; i < quadCache.frustumData.size(); ++i) { printf("\nFrustum #%u [" MG_SIZE_T_SPECIFIER "]: ",i,quadCache.frustumData.size()); vector &frustumDataInner = quadCache.frustumData[i]; for(unsigned int j = 0; j < frustumDataInner.size(); ++j) { printf("[%f]",quadCache.frustumData[i][j]); } } printf("\nEND\n"); } const bool newVisibleQuadCalc = false; if(newVisibleQuadCalc) { const bool debug = false; try { if(debug) { visibleQuad = gameCamera->computeVisibleQuad(); printf("Camera: %d,%d %d,%d %d,%d %d,%d\n", visibleQuad.p[0].x,visibleQuad.p[0].y, visibleQuad.p[1].x,visibleQuad.p[1].y, visibleQuad.p[2].x,visibleQuad.p[2].y, visibleQuad.p[3].x,visibleQuad.p[3].y); } // compute the four corners using OpenGL GLdouble model[16], projection[16]; GLint viewport[4]; glGetDoublev(GL_MODELVIEW_MATRIX,model); glGetDoublev(GL_PROJECTION_MATRIX,projection); glGetIntegerv(GL_VIEWPORT,viewport); Vec2i tl = _unprojectMap(Vec2i(0,0),model,projection,viewport,"tl"), tr = _unprojectMap(Vec2i(viewport[2],0),model,projection,viewport,"tr"), br = _unprojectMap(Vec2i(viewport[2],viewport[3]),model,projection,viewport,"br"), bl = _unprojectMap(Vec2i(0,viewport[3]),model,projection,viewport,"bl"); // orientate it for map iterator //bool swapRequiredX = false; bool swapRequiredY = false; int const cellBuffer = 4; if((tl.x > tr.x) || (bl.x > br.x)) { if(debug) printf("Swap X???\n"); //std::swap(tl,bl); //std::swap(tr,br); if(tl.x > tr.x) { if(debug) printf("Swap X1???\n"); tr.x += cellBuffer; tl.x -= cellBuffer; std::swap(tl.x,tr.x); //swapRequiredX = true; } else { tl.x += cellBuffer; tr.x -= cellBuffer; } if(bl.x > br.x) { if(debug) printf("Swap X2???\n"); bl.x += cellBuffer; br.x -= cellBuffer; std::swap(bl.x,br.x); //swapRequiredX = true; } else { br.x += cellBuffer; bl.x -= cellBuffer; } } if((tl.y > bl.y) || (tr.y > br.y)) { visibleQuad = this->gameCamera->computeVisibleQuad(); if(debug) printf("Swap Y???\n"); if(tl.y > bl.y) { if(debug) printf("Swap Y1???\n"); tl.y += cellBuffer; bl.y -= cellBuffer; std::swap(tl.y,bl.y); swapRequiredY = true; } else { bl.y += cellBuffer; tl.y -= cellBuffer; } if(tr.y > br.y) { if(debug) printf("Swap Y2???\n"); tr.y += cellBuffer; br.y -= cellBuffer; std::swap(tr.y,br.y); swapRequiredY = true; } else { br.y += cellBuffer; tr.y -= cellBuffer; } //std::swap(tl,tr); //std::swap(bl,br); } if(swapRequiredY == false) { tl.y -= cellBuffer; tr.y -= cellBuffer; bl.y += cellBuffer; br.y += cellBuffer; } // set it as the frustum visibleQuad = Quad2i(tl,bl,tr,br); // strange order if(debug) { printf("Will: %d,%d %d,%d %d,%d %d,%d\n", visibleQuad.p[0].x,visibleQuad.p[0].y, visibleQuad.p[1].x,visibleQuad.p[1].y, visibleQuad.p[2].x,visibleQuad.p[2].y, visibleQuad.p[3].x,visibleQuad.p[3].y); } } catch(PROJECTION_TO_INFINITY &e) { if(debug) printf("hmm staring at the horizon %d\n",(int)e); // use historic code solution visibleQuad = this->gameCamera->computeVisibleQuad(); } } } // ======================================= // basic rendering // ======================================= void Renderer::renderMouse2d(int x, int y, int anim, float fade) { if(no2DMouseRendering == true) { return; } if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } // float blue=0.0f; // float green=0.4f; if(game != NULL && game->getGui() != NULL) { const Gui *gui=game->getGui(); const Display *display=gui->getDisplay(); int downPos= display->getDownSelectedPos(); if(downPos != Display::invalidPos){ // in state of doing something const Texture2D *texture= display->getDownImage(downPos); renderTextureQuad(x+18,y-50,32,32,texture,0.8f); } // else { // // Display current commandtype // const Unit *unit=NULL; // if(gui->getSelection()->isEmpty()){ // blue=0.0f; // green=0.1f; // } // else{ // unit=gui->getSelection()->getFrontUnit(); // if(unit->getCurrCommand()!=NULL && unit->getCurrCommand()->getCommandType()->getImage()!=NULL){ // const Texture2D *texture = unit->getCurrCommand()->getCommandType()->getImage(); // renderTextureQuad(x+18,y-50,32,32,texture,0.2f); // } // } // } if(game->isMarkCellMode() == true) { const Texture2D *texture= game->getMarkCellTexture(); renderTextureQuad(x,y,texture->getTextureWidth(),texture->getTextureHeight(),texture,0.8f); } if(game->isUnMarkCellMode() == true) { const Texture2D *texture= game->getUnMarkCellTexture(); renderTextureQuad(x,y,texture->getTextureWidth(),texture->getTextureHeight(),texture,0.8f); } } float fadeFactor = fade + 1.f; anim= anim * 2 - maxMouse2dAnim; float color2= (abs(anim*(int)fadeFactor)/static_cast(maxMouse2dAnim))/2.f+0.4f; float color1= (abs(anim*(int)fadeFactor)/static_cast(maxMouse2dAnim))/2.f+0.8f; glPushAttrib(GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT | GL_LINE_BIT); glEnable(GL_BLEND); //inside glColor4f(0.4f*fadeFactor, 0.2f*fadeFactor, 0.2f*fadeFactor, 0.5f*fadeFactor); glBegin(GL_TRIANGLES); glVertex2i(x, y); glVertex2i(x+20, y-10); glVertex2i(x+10, y-20); glEnd(); //border glLineWidth(2); glBegin(GL_LINE_LOOP); glColor4f(1.f, 0.2f, 0, color1); glVertex2i(x, y); glColor4f(1.f, 0.4f, 0, color2); glVertex2i(x+20, y-10); glColor4f(1.f, 0.4f, 0, color2); glVertex2i(x+10, y-20); glEnd(); glPopAttrib(); /* if(no2DMouseRendering == true) { return; } float color1 = 0.0, color2 = 0.0; float fadeFactor = fade + 1.f; anim= anim * 2 - maxMouse2dAnim; color2= (abs(anim*(int)fadeFactor)/static_cast(maxMouse2dAnim))/2.f+0.4f; color1= (abs(anim*(int)fadeFactor)/static_cast(maxMouse2dAnim))/2.f+0.8f; glPushAttrib(GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT | GL_LINE_BIT); glEnable(GL_BLEND); //inside Vec2i vertices[3]; vertices[0] = Vec2i(x, y); vertices[1] = Vec2i(x+20, y-10); vertices[2] = Vec2i(x+10, y-20); glColor4f(0.4f*fadeFactor, 0.2f*fadeFactor, 0.2f*fadeFactor, 0.5f*fadeFactor); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_INT, 0, &vertices[0]); glDrawArrays(GL_TRIANGLES, 0, 3); glDisableClientState(GL_VERTEX_ARRAY); //border vertices[0] = Vec2i(x, y); vertices[1] = Vec2i(x+20, y-10); vertices[2] = Vec2i(x+10, y-20); Vec4f colors[4]; colors[0] = Vec4f(1.f, 0.2f, 0, color1); colors[1] = Vec4f(1.f, 0.4f, 0, color2); colors[2] = Vec4f(1.f, 0.4f, 0, color2); glLineWidth(2); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_INT, 0, &vertices[0]); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(4, GL_FLOAT, 0, &colors[0]); glDrawArrays(GL_LINE_LOOP, 0, 3); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glPopAttrib(); */ } void Renderer::renderMouse3d() { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } Config &config= Config::getInstance(); if(config.getBool("RecordMode","false") == true) { return; } if(game == NULL) { char szBuf[8096]=""; snprintf(szBuf,8096,"In [%s::%s] Line: %d game == NULL",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); throw megaglest_runtime_error(szBuf); } else if(game->getGui() == NULL) { char szBuf[8096]=""; snprintf(szBuf,8096,"In [%s::%s] Line: %d game->getGui() == NULL",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); throw megaglest_runtime_error(szBuf); } else if(game->getGui()->getMouse3d() == NULL) { char szBuf[8096]=""; snprintf(szBuf,8096,"In [%s::%s] Line: %d game->getGui()->getMouse3d() == NULL",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); throw megaglest_runtime_error(szBuf); } const Gui *gui= game->getGui(); const Mouse3d *mouse3d= gui->getMouse3d(); const Map *map= game->getWorld()->getMap(); if(map == NULL) { char szBuf[8096]=""; snprintf(szBuf,8096,"In [%s::%s] Line: %d map == NULL",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); throw megaglest_runtime_error(szBuf); } assertGl(); if((mouse3d->isEnabled() || gui->isPlacingBuilding()) && gui->isValidPosObjWorld()) { const Vec2i &pos= gui->getPosObjWorld(); glMatrixMode(GL_MODELVIEW); glPushAttrib(GL_CURRENT_BIT | GL_LIGHTING_BIT | GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_BLEND); glDisable(GL_STENCIL_TEST); glDepthFunc(GL_LESS); glEnable(GL_COLOR_MATERIAL); glDepthMask(GL_FALSE); if(gui->isPlacingBuilding()) { modelRenderer->begin(true, true, false, false); const UnitType *building= gui->getBuilding(); const Gui *gui= game->getGui(); renderGhostModel(building, pos, gui->getSelectedFacing()); modelRenderer->end(); glDisable(GL_COLOR_MATERIAL); glPopAttrib(); } else { glPushMatrix(); Vec3f pos3f= Vec3f(pos.x, map->getCell(pos)->getHeight(), pos.y); Vec4f color; GLUquadricObj *cilQuadric; //standard mouse glDisable(GL_TEXTURE_2D); glDisable(GL_CULL_FACE); color= Vec4f(1.f, 0.f, 0.f, 1.f-mouse3d->getFade()); glColor4fv(color.ptr()); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color.ptr()); glTranslatef(pos3f.x, pos3f.y+2.f, pos3f.z); glRotatef(90.f, 1.f, 0.f, 0.f); glRotatef(static_cast(mouse3d->getRot()), 0.f, 0.f, 1.f); cilQuadric= gluNewQuadric(); gluQuadricDrawStyle(cilQuadric, GLU_FILL); gluCylinder(cilQuadric, 0.5f, 0.f, 2.f, 4, 1); gluCylinder(cilQuadric, 0.5f, 0.f, 0.f, 4, 1); glTranslatef(0.f, 0.f, 1.f); gluCylinder(cilQuadric, 0.7f, 0.f, 1.f, 4, 1); gluCylinder(cilQuadric, 0.7f, 0.f, 0.f, 4, 1); gluDeleteQuadric(cilQuadric); glPopAttrib(); glPopMatrix(); } } } void Renderer::renderBackground(const Texture2D *texture) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } const Metrics &metrics= Metrics::getInstance(); assertGl(); glPushAttrib(GL_ENABLE_BIT); glDisable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); renderQuad(0, 0, metrics.getVirtualW(), metrics.getVirtualH(), texture); glPopAttrib(); assertGl(); } void Renderer::renderTextureQuad(int x, int y, int w, int h, const Texture2D *texture, float alpha,const Vec3f *color) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } assertGl(); glPushAttrib(GL_ENABLE_BIT); glDisable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); if(color != NULL) { Vec4f newColor(*color); newColor.w = alpha; glColor4fv(newColor.ptr()); } else { glColor4f(1.f, 1.f, 1.f, alpha); } renderQuad(x, y, w, h, texture); glPopAttrib(); assertGl(); } void Renderer::renderConsoleLine3D(int lineIndex, int xPosition, int yPosition, int lineHeight, Font3D* font, string stringToHightlight, const ConsoleLineInfo *lineInfo) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } Vec4f fontColor; Lang &lang= Lang::getInstance(); //const Metrics &metrics= Metrics::getInstance(); FontMetrics *fontMetrics= font->getMetrics(); if(game != NULL) { fontColor = game->getGui()->getDisplay()->getColor(); } else { // white shadowed is default ( in the menu for example ) //fontColor=Vec4f(1.f, 1.f, 1.f, 0.0f); fontColor=Vec4f(lineInfo->color.x,lineInfo->color.y,lineInfo->color.z, 0.0f); } Vec4f defaultFontColor = fontColor; if(lineInfo->PlayerIndex >= 0) { std::map &crcPlayerTextureCache = CacheManager::getCachedItem< std::map >(GameConstants::playerTextureCacheLookupKey); Vec3f playerColor = crcPlayerTextureCache[lineInfo->PlayerIndex]->getPixmap()->getPixel3f(0, 0); fontColor.x = playerColor.x; fontColor.y = playerColor.y; fontColor.z = playerColor.z; GameNetworkInterface *gameNetInterface = NetworkManager::getInstance().getGameNetworkInterface(); if(gameNetInterface != NULL && gameNetInterface->getGameSettings() != NULL) { const GameSettings *gameSettings = gameNetInterface->getGameSettings(); string playerName = gameSettings->getNetworkPlayerNameByPlayerIndex(lineInfo->PlayerIndex); if(playerName != lineInfo->originalPlayerName && lineInfo->originalPlayerName != "") { playerName = lineInfo->originalPlayerName; } if(playerName == GameConstants::NETWORK_SLOT_UNCONNECTED_SLOTNAME) { playerName = lang.getString("SystemUser"); } //printf("playerName [%s], line [%s]\n",playerName.c_str(),line.c_str()); //string headerLine = "*" + playerName + ":"; //string headerLine = playerName + ": "; string headerLine = playerName; if(lineInfo->teamMode == true) { headerLine += " (" + lang.getString("Team") + ")"; } headerLine += ": "; if(fontMetrics == NULL) { throw megaglest_runtime_error("fontMetrics == NULL"); } renderTextShadow3D( headerLine, font, fontColor, xPosition, lineIndex * lineHeight + yPosition); fontColor = defaultFontColor; //xPosition += (8 * (playerName.length() + 2)); // Proper font spacing after username portion of chat text rendering //xPosition += (metrics.toVirtualX(fontMetrics->getTextWidth(headerLine))); xPosition += fontMetrics->getTextWidth(headerLine); } } else if(lineInfo->originalPlayerName != "") { string playerName = lineInfo->originalPlayerName; //string headerLine = playerName + ": "; string headerLine = playerName; if(lineInfo->teamMode == true) { headerLine += " (" + lang.getString("Team") + ")"; } headerLine += ": "; if(fontMetrics == NULL) { throw megaglest_runtime_error("fontMetrics == NULL"); } renderTextShadow3D( headerLine, font, fontColor, xPosition, lineIndex * lineHeight + yPosition); fontColor = defaultFontColor; //xPosition += (8 * (playerName.length() + 2)); // Proper font spacing after username portion of chat text rendering //xPosition += (metrics.toVirtualX(fontMetrics->getTextWidth(headerLine))); xPosition += fontMetrics->getTextWidth(headerLine); } else { fontColor = defaultFontColor; } if(stringToHightlight!="" && lineInfo->text.find(stringToHightlight)!=string::npos){ fontColor=Vec4f(1.f, 0.5f, 0.5f, 0.0f); } renderTextShadow3D( lineInfo->text, font, fontColor, xPosition, (lineIndex * lineHeight) + yPosition); } void Renderer::renderConsoleLine(int lineIndex, int xPosition, int yPosition, int lineHeight, Font2D* font, string stringToHightlight, const ConsoleLineInfo *lineInfo) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } Vec4f fontColor; Lang &lang= Lang::getInstance(); const Metrics &metrics= Metrics::getInstance(); FontMetrics *fontMetrics= font->getMetrics(); if(game != NULL) { fontColor = game->getGui()->getDisplay()->getColor(); } else { // white shadowed is default ( in the menu for example ) //fontColor=Vec4f(1.f, 1.f, 1.f, 0.0f); fontColor=Vec4f(lineInfo->color.x,lineInfo->color.y,lineInfo->color.z, 0.0f); } Vec4f defaultFontColor = fontColor; if(lineInfo->PlayerIndex >= 0) { std::map &crcPlayerTextureCache = CacheManager::getCachedItem< std::map >(GameConstants::playerTextureCacheLookupKey); Vec3f playerColor = crcPlayerTextureCache[lineInfo->PlayerIndex]->getPixmap()->getPixel3f(0, 0); fontColor.x = playerColor.x; fontColor.y = playerColor.y; fontColor.z = playerColor.z; GameNetworkInterface *gameNetInterface = NetworkManager::getInstance().getGameNetworkInterface(); if(gameNetInterface != NULL && gameNetInterface->getGameSettings() != NULL) { const GameSettings *gameSettings = gameNetInterface->getGameSettings(); string playerName = gameSettings->getNetworkPlayerNameByPlayerIndex(lineInfo->PlayerIndex); if(playerName != lineInfo->originalPlayerName && lineInfo->originalPlayerName != "") { playerName = lineInfo->originalPlayerName; } //printf("playerName [%s], line [%s]\n",playerName.c_str(),line.c_str()); //string headerLine = "*" + playerName + ":"; //string headerLine = playerName + ": "; string headerLine = playerName; if(lineInfo->teamMode == true) { headerLine += " (" + lang.getString("Team") + ")"; } headerLine += ": "; if(fontMetrics == NULL) { throw megaglest_runtime_error("fontMetrics == NULL"); } renderTextShadow( headerLine, font, fontColor, xPosition, lineIndex * lineHeight + yPosition); fontColor = defaultFontColor; //xPosition += (8 * (playerName.length() + 2)); // Proper font spacing after username portion of chat text rendering xPosition += (metrics.toVirtualX(fontMetrics->getTextWidth(headerLine))); } } else if(lineInfo->originalPlayerName != "") { string playerName = lineInfo->originalPlayerName; //string headerLine = playerName + ": "; string headerLine = playerName; if(lineInfo->teamMode == true) { headerLine += " (" + lang.getString("Team") + ")"; } headerLine += ": "; if(fontMetrics == NULL) { throw megaglest_runtime_error("fontMetrics == NULL"); } renderTextShadow( headerLine, font, fontColor, xPosition, lineIndex * lineHeight + yPosition); fontColor = defaultFontColor; //xPosition += (8 * (playerName.length() + 2)); // Proper font spacing after username portion of chat text rendering xPosition += (metrics.toVirtualX(fontMetrics->getTextWidth(headerLine))); } else { fontColor = defaultFontColor; } if(stringToHightlight!="" && lineInfo->text.find(stringToHightlight)!=string::npos){ fontColor=Vec4f(1.f, 0.5f, 0.5f, 0.0f); } renderTextShadow( lineInfo->text, font, fontColor, xPosition, (lineIndex * lineHeight) + yPosition); } void Renderer::renderConsole(const Console *console, ConsoleMode mode , int overrideMaxConsoleLines){ if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(console == NULL) { throw megaglest_runtime_error("console == NULL"); } glPushAttrib(GL_ENABLE_BIT); glEnable(GL_BLEND); if(mode==consoleFull) { int x= console->getXPos()-5; int y= console->getYPos()-5; int h= console->getLineHeight()*console->getStoredLineCount(); if(h > 0) { int w= 1000; //background glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT); glEnable(GL_BLEND); glColor4f(0.0f, 0.0f, 0.0f, 0.8f) ; glBegin(GL_TRIANGLE_STRIP); glVertex2i(x, y); glVertex2i(x, y+h); glVertex2i(x+w, y); glVertex2i(x+w, y+h); glEnd(); glPopAttrib(); } for(int i = 0; i < console->getStoredLineCount(); ++i) { const ConsoleLineInfo &lineInfo = console->getStoredLineItem(i); if(renderText3DEnabled == true) { renderConsoleLine3D(i, console->getXPos(), console->getYPos(), console->getLineHeight(), console->getFont3D(), console->getStringToHighlight(), &lineInfo); } else { renderConsoleLine(i, console->getXPos(), console->getYPos(), console->getLineHeight(), console->getFont(), console->getStringToHighlight(), &lineInfo); } } } else if(mode==consoleStoredOnly) { int allowedMaxLines = (overrideMaxConsoleLines >= 0 ? overrideMaxConsoleLines : maxConsoleLines); for(int i = 0; i < console->getStoredLineCount() && i < allowedMaxLines; ++i) { const ConsoleLineInfo &lineInfo = console->getStoredLineItem(i); if(renderText3DEnabled == true) { renderConsoleLine3D(i, console->getXPos(), console->getYPos(), console->getLineHeight(), console->getFont3D(), console->getStringToHighlight(), &lineInfo); } else { renderConsoleLine(i, console->getXPos(), console->getYPos(), console->getLineHeight(), console->getFont(), console->getStringToHighlight(), &lineInfo); } } } else if(mode==consoleStoredAndNormal) { int allowedMaxLines = (overrideMaxConsoleLines >= 0 ? overrideMaxConsoleLines : maxConsoleLines); float starttimestamp=-1; int consoleIndex=0; for(int i = 0; i < console->getLineCount() && i < allowedMaxLines; ++i) { const ConsoleLineInfo &lineInfo = console->getLineItem(i); if(starttimestamp>lineInfo.timeStamp || starttimestamp==-1) starttimestamp=lineInfo.timeStamp; if(renderText3DEnabled == true) { renderConsoleLine3D(i, console->getXPos(), console->getYPos(), console->getLineHeight(), console->getFont3D(), console->getStringToHighlight(), &lineInfo); } else { renderConsoleLine(i, console->getXPos(), console->getYPos(), console->getLineHeight(), console->getFont(), console->getStringToHighlight(), &lineInfo); } consoleIndex++; } for(int i = 0; i < console->getStoredLineCount() && consoleIndex < allowedMaxLines; ++i) { const ConsoleLineInfo &lineInfo = console->getStoredLineItem(i); if( lineInfo.timeStampgetXPos(), console->getYPos(), console->getLineHeight(), console->getFont3D(), console->getStringToHighlight(), &lineInfo); } else { renderConsoleLine(consoleIndex, console->getXPos(), console->getYPos(), console->getLineHeight(), console->getFont(), console->getStringToHighlight(), &lineInfo); } consoleIndex++; } } } else if(mode==consoleNormal) { for(int i = 0; i < console->getLineCount(); ++i) { const ConsoleLineInfo &lineInfo = console->getLineItem(i); if(renderText3DEnabled == true) { renderConsoleLine3D(i, console->getXPos(), console->getYPos(), console->getLineHeight(), console->getFont3D(), console->getStringToHighlight(), &lineInfo); } else { renderConsoleLine(i, console->getXPos(), console->getYPos(), console->getLineHeight(), console->getFont(), console->getStringToHighlight(), &lineInfo); } } } glPopAttrib(); } void Renderer::renderChatManager(const ChatManager *chatManager) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } Vec4f fontColor; Lang &lang= Lang::getInstance(); if(chatManager->getEditEnabled()) { Vec4f color=Vec4f(0.0f,0.0f,0.0f,0.6f); string text=""; if(chatManager->isInCustomInputMode() == true) { text += lang.getString("CellHint"); } else if(chatManager->getInMenu()) { text += lang.getString("Chat"); } else if(chatManager->getTeamMode()) { text += lang.getString("Team"); } else { text += lang.getString("All"); } text += ": " + chatManager->getText() + "_"; if(game != NULL) { fontColor = game->getGui()->getDisplay()->getColor(); } else { // white shadowed is default ( in the menu for example ) fontColor=Vec4f(1.f, 1.f, 1.f, 0.0f); } // render Background int x=chatManager->getXPos(); int y=chatManager->getYPos()-6; int h=22; int w=830; glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT); glEnable(GL_BLEND); glColor4f(color.x, color.y, color.z, color.w) ; glBegin(GL_TRIANGLE_STRIP); glVertex2i(x, y); glVertex2i(x, y+h); glVertex2i(x+w, y); glVertex2i(x+w, y+h); glEnd(); glPopAttrib(); if(renderText3DEnabled == true) { renderTextShadow3D( text, chatManager->getFont3D(), fontColor, chatManager->getXPos(), chatManager->getYPos()); } else { renderTextShadow( text, chatManager->getFont(), fontColor, chatManager->getXPos(), chatManager->getYPos()); } } else { if (chatManager->getInMenu()) { string text = "\t\t\t\t\t>> "+lang.getString("PressEnterToChat")+" <<"; fontColor = Vec4f(0.5f, 0.5f, 0.5f, 0.5f); if(renderText3DEnabled == true) { renderTextShadow3D(text, chatManager->getFont3D(), fontColor, chatManager->getXPos(), chatManager->getYPos()); } else { renderTextShadow(text, chatManager->getFont(), fontColor, chatManager->getXPos(), chatManager->getYPos()); } } } } void Renderer::renderPerformanceStats() { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } const Metrics &metrics = Metrics::getInstance(); const Vec4f fontColor = game->getGui()->getDisplay()->getColor(); char szBuf[200]=""; snprintf(szBuf,200,"Frame: %d",game->getWorld()->getFrameCount() / 20); string str = string(szBuf) + string("\n"); static time_t lastGamePerfCheck = time(NULL); static string gamePerfStats = ""; if(difftime((long int)time(NULL),lastGamePerfCheck) > 3) { lastGamePerfCheck = time(NULL); gamePerfStats = game->getGamePerformanceCounts(true); } if(gamePerfStats != "") { str += gamePerfStats + "\n"; } if(renderText3DEnabled == true) { renderTextShadow3D( str, CoreData::getInstance().getDisplayFontSmall3D(), fontColor, 10, metrics.getVirtualH()-180, false); } else { renderTextShadow( str, CoreData::getInstance().getDisplayFontSmall(), fontColor, 10, metrics.getVirtualH()-180, false); } } void Renderer::renderClock() { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } Config &config= Config::getInstance(); if(config.getBool("InGameClock","true") == false && config.getBool("InGameLocalClock","true") == false && config.getBool("InGameFrameCounter","false") == false) { return; } string str = ""; const Metrics &metrics = Metrics::getInstance(); const World *world = game->getWorld(); const Vec4f fontColor = game->getGui()->getDisplay()->getColor(); if(config.getBool("InGameClock","true") == true) { Lang &lang= Lang::getInstance(); char szBuf[501]=""; //int hours = world->getTimeFlow()->getTime(); //int minutes = (world->getTimeFlow()->getTime() - hours) * 100 * 0.6; // scale 100 to 60 //snprintf(szBuf,200,"%s %.2d:%.2d",lang.getString("GameTime","",true).c_str(),hours,minutes); // string header2 = lang.getString("GameDurationTime","",true) + ": " + getTimeString(stats.getFramesToCalculatePlaytime()); snprintf(szBuf,500,"%s %s",lang.getString("GameDurationTime","",true).c_str(),getTimeDuationString(world->getFrameCount(),GameConstants::updateFps).c_str()); if(str != "") { str += " "; } str += szBuf; } if(config.getBool("InGameLocalClock","true") == true) { //time_t nowTime = time(NULL); //struct tm *loctime = localtime(&nowTime); struct tm loctime = threadsafe_localtime(systemtime_now()); char szBuf2[100]=""; strftime(szBuf2,100,"%H:%M",&loctime); Lang &lang= Lang::getInstance(); char szBuf[200]=""; snprintf(szBuf,200,"%s %s",lang.getString("LocalTime","",true).c_str(),szBuf2); if(str != "") { str += " "; } str += szBuf; } if(config.getBool("InGameFrameCounter","false") == true) { char szBuf[200]=""; snprintf(szBuf,200,"Frame: %d",game->getWorld()->getFrameCount() / 20); if(str != "") { str += " "; } str += szBuf; } //string str = szBuf; if(renderText3DEnabled == true) { renderTextShadow3D( str, CoreData::getInstance().getDisplayFontSmall3D(), fontColor, 10, metrics.getVirtualH()-160, false); } else { renderTextShadow( str, CoreData::getInstance().getDisplayFontSmall(), fontColor, 10, metrics.getVirtualH()-160, false); } } void Renderer::renderResourceStatus() { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } const World *world = game->getWorld(); Config &config= Config::getInstance(); if(world->getThisFactionIndex() < 0 || world->getThisFactionIndex() >= world->getFactionCount()) { return; } const Faction *thisFaction = world->getFaction(world->getThisFactionIndex()); if(thisFaction->getPersonalityType() == fpt_Observer){ // render resources of selected units faction const Gui *gui = game->getGui(); if(gui != NULL) { const Selection *selection = gui->getSelection(); if(selection != NULL && selection->getCount() > 0 && selection->getFrontUnit() != NULL) { const Unit *selectedUnit = selection->getFrontUnit(); thisFaction=selectedUnit->getFaction(); } } } assertGl(); glPushAttrib(GL_ENABLE_BIT); int rowsRendered = 0; int resourceCountRendered = 0; bool twoRessourceLines=false; bool sharedTeamUnits = game != NULL && game->getGui() != NULL && game->isFlagType1BitEnabled(ft1_allow_shared_team_units) == true; bool sharedTeamResources = game != NULL && game->getGui() != NULL && game->isFlagType1BitEnabled( ft1_allow_shared_team_resources) == true; bool renderSharedTeamResources=false; bool renderSharedTeamUnits=false; bool renderLocalFactionResources=false; if(config.getBool("TwoLineTeamResourceRendering","false") == true) { if( sharedTeamResources == true || sharedTeamUnits == true){ twoRessourceLines=true; } if(sharedTeamResources == true){ renderSharedTeamResources=true; renderSharedTeamUnits=true; } else if(sharedTeamUnits == true){ renderSharedTeamUnits=true; renderLocalFactionResources=true; } else{ renderLocalFactionResources=true; } } else { if(sharedTeamResources == true) renderSharedTeamResources=true; else if(sharedTeamUnits == true) renderSharedTeamUnits=true; else renderLocalFactionResources=true; } if(renderSharedTeamResources == true) { resourceCountRendered = 0; for(int techTreeResourceTypeIndex = 0; techTreeResourceTypeIndex < world->getTechTree()->getResourceTypeCount(); ++techTreeResourceTypeIndex) { const ResourceType *rt = world->getTechTree()->getResourceType(techTreeResourceTypeIndex); if ( rt->getDisplayInHud() == false ) { continue; } bool showResource = world->showResourceTypeForTeam(rt, thisFaction->getTeam()); if(showResource == true) { rowsRendered = renderResource(thisFaction, false, twoRessourceLines, rt, 0, resourceCountRendered); } } if(resourceCountRendered > 0) { rowsRendered++; } } if(renderLocalFactionResources == true){ resourceCountRendered = 0; const Faction *factionForResourceView = thisFaction; bool localFactionResourcesOnly = true; for(int techTreeResourceTypeIndex = 0; techTreeResourceTypeIndex < world->getTechTree()->getResourceTypeCount(); ++techTreeResourceTypeIndex) { const ResourceType *rt = world->getTechTree()->getResourceType(techTreeResourceTypeIndex); if ( rt->getDisplayInHud() == false ) { continue; } //if any unit produces the resource bool showResource; if (twoRessourceLines) showResource = world->showResourceTypeForTeam(rt, factionForResourceView->getTeam()); else showResource = world->showResourceTypeForFaction(rt, factionForResourceView); if(showResource == true) { renderResource(factionForResourceView, localFactionResourcesOnly, twoRessourceLines, rt, rowsRendered, resourceCountRendered); } } if(resourceCountRendered > 0) { rowsRendered++; } } if(renderSharedTeamUnits == true){ resourceCountRendered = 0; const Faction *factionForResourceView = thisFaction; bool localFactionResourcesOnly = true; const Gui *gui = game->getGui(); if(gui != NULL) { const Selection *selection = gui->getSelection(); if(selection != NULL && selection->getCount() > 0 && selection->getFrontUnit() != NULL) { const Unit *selectedUnit = selection->getFrontUnit(); if(selectedUnit != NULL && selectedUnit->getFaction()->isAlly(thisFaction) == true) { factionForResourceView = selectedUnit->getFaction(); } } } for(int techTreeResourceTypeIndex = 0; techTreeResourceTypeIndex < world->getTechTree()->getResourceTypeCount(); ++techTreeResourceTypeIndex) { const ResourceType *rt = world->getTechTree()->getResourceType(techTreeResourceTypeIndex); if ( rt->getDisplayInHud() == false ) { continue; } //if any unit produces the resource bool showResource; if (twoRessourceLines) showResource = world->showResourceTypeForTeam(rt, factionForResourceView->getTeam()); else showResource = world->showResourceTypeForFaction(rt, factionForResourceView); if(showResource == true) { renderResource(factionForResourceView, localFactionResourcesOnly, twoRessourceLines, rt, rowsRendered, resourceCountRendered); } } //if(resourceCountRendered > 0) { // rowsRendered++; //} } glPopAttrib(); assertGl(); } int Renderer::renderResource(const Faction *factionForResourceView,bool localFactionResourcesOnly, bool twoResourceLines, const ResourceType *rt, int startRow, int &resourceCountRendered) { const Metrics &metrics = Metrics::getInstance(); const int MAX_RESOURCES_PER_ROW = 6; int resourceRowHeigth=30; int resourceYStart=metrics.getVirtualH()-30; if(twoResourceLines){ // we need to save some space resourceYStart=metrics.getVirtualH()-22; resourceRowHeigth=16; } //draw resource status if(localFactionResourcesOnly == true) { Vec4f resourceFontColor = Vec4f(factionForResourceView->getTexture()->getPixmapConst()->getPixel3f(0,0)); int resourceCol = 0; int resourceRow = startRow; int x=resourceCol * 100 + 190; int y=resourceYStart - (resourceRowHeigth * resourceRow); int h=16; int w=8; glColor3f(resourceFontColor.x,resourceFontColor.y,resourceFontColor.z); glBegin(GL_TRIANGLE_STRIP); glVertex2i(x, y+h); glVertex2i(x, y); glVertex2i(x+w, y+h/2); glEnd(); } const Resource *r = factionForResourceView->getResource(rt,localFactionResourcesOnly); string str = intToStr(r->getAmount()); glEnable(GL_TEXTURE_2D); const Vec4f fontColor = game->getGui()->getDisplay()->getColor(); Vec4f resourceFontColor = fontColor; bool isNegativeConsumableDisplayCycle = false; if(rt->getClass() == rcConsumable) { // Show in yellow/orange/red font if negative if(r->getBalance() * 5 + r->getAmount() < 0) { if(time(NULL) % 2 == 0) { isNegativeConsumableDisplayCycle = true; if(r->getBalance() * 1 + r->getAmount() < 0) { glColor3f(RED.x,RED.y,RED.z); resourceFontColor = RED; } else if(r->getBalance() * 3 + r->getAmount() < 0) { glColor3f(ORANGE.x,ORANGE.y,ORANGE.z); resourceFontColor = ORANGE; } else if(r->getBalance() * 5 + r->getAmount() < 0) { glColor3f(YELLOW.x,YELLOW.y,YELLOW.z); resourceFontColor = YELLOW; } } } } if(isNegativeConsumableDisplayCycle == false) { glColor3f(1.f, 1.f, 1.f); } int resourceRow = startRow + (resourceCountRendered > 0 ? resourceCountRendered / MAX_RESOURCES_PER_ROW : 0); int resourceCol = resourceCountRendered % MAX_RESOURCES_PER_ROW; renderQuad(resourceCol * 100 + 200, resourceYStart - (resourceRowHeigth * resourceRow), 16, 16, rt->getImage()); if(rt->getClass() != rcStatic) { str+= "/" + intToStr(factionForResourceView->getStoreAmount(rt,localFactionResourcesOnly)); } if(rt->getClass() == rcConsumable) { str+= "("; if(r->getBalance() > 0) { str+= "+"; } str+= intToStr(r->getBalance()) + ")"; } glDisable(GL_TEXTURE_2D); if(renderText3DEnabled == true) { renderTextShadow3D( str, CoreData::getInstance().getDisplayFontSmall3D(), resourceFontColor, resourceCol * 100 + 220, resourceYStart - (resourceRowHeigth * resourceRow), false); } else { renderTextShadow( str, CoreData::getInstance().getDisplayFontSmall(), resourceFontColor, resourceCol * 100 + 220, resourceYStart - (resourceRowHeigth * resourceRow), false); } ++resourceCountRendered; return resourceRow; } void Renderer::renderSelectionQuad() { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } Config &config= Config::getInstance(); if(config.getBool("RecordMode","false") == true) { return; } const Gui *gui= game->getGui(); const SelectionQuad *sq= gui->getSelectionQuad(); Vec2i down= sq->getPosDown(); Vec2i up= sq->getPosUp(); if(gui->isSelecting()) { glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT); Vec2i vertices[4]; vertices[0] = Vec2i(down.x, down.y); vertices[1] = Vec2i(up.x, down.y); vertices[2] = Vec2i(up.x, up.y); vertices[3] = Vec2i(down.x, up.y); glColor3f(0,1,0); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_INT, 0, &vertices[0]); glDrawArrays(GL_LINE_LOOP, 0, 4); glDisableClientState(GL_VERTEX_ARRAY); /* glColor3f(0,1,0); glBegin(GL_LINE_LOOP); glVertex2i(down.x, down.y); glVertex2i(up.x, down.y); glVertex2i(up.x, up.y); glVertex2i(down.x, up.y); glEnd(); */ glPopAttrib(); } } Vec2i computeCenteredPos(const string &text, Font2D *font, int x, int y) { if(font == NULL) { //abort(); throw megaglest_runtime_error("font == NULL (1) text = " + text); } const Metrics &metrics= Metrics::getInstance(); FontMetrics *fontMetrics= font->getMetrics(); if(fontMetrics == NULL) { throw megaglest_runtime_error("fontMetrics == NULL (1) text = " + text); } int virtualX = (fontMetrics->getTextWidth(text) > 0 ? static_cast(fontMetrics->getTextWidth(text)/2.f) : 5); int virtualY = (fontMetrics->getHeight(text) > 0 ? static_cast(fontMetrics->getHeight(text)/2.f) : 5); Vec2i textPos( x-metrics.toVirtualX(virtualX), y-metrics.toVirtualY(virtualY)); //printf("text [%s] x = %d y = %d virtualX = %d virtualY = %d fontMetrics->getHeight() = %f\n",text.c_str(),x,y,virtualX,virtualY,fontMetrics->getHeight()); return textPos; } Vec2i computeCenteredPos(const string &text, Font3D *font, int x, int y) { if(font == NULL) { throw megaglest_runtime_error("font == NULL (2) text = " + text); } const Metrics &metrics= Metrics::getInstance(); FontMetrics *fontMetrics= font->getMetrics(); if(fontMetrics == NULL) { throw megaglest_runtime_error("fontMetrics == NULL (2) text = " + text); } int virtualX = (fontMetrics->getTextWidth(text) > 0 ? static_cast(fontMetrics->getTextWidth(text) / 2.f) : 5); int virtualY = (fontMetrics->getHeight(text) > 0 ? static_cast(fontMetrics->getHeight(text) / 2.f) : 5); Vec2i textPos( x-metrics.toVirtualX(virtualX), y-metrics.toVirtualY(virtualY)); return textPos; } void Renderer::renderTextSurroundingBox(int x, int y, int w, int h, int maxEditWidth, int maxEditRenderWidth) { //glColor4fv(color.ptr()); //glBegin(GL_QUADS); // Start drawing a quad primitive //printf("A w = %d maxEditWidth = %d maxEditRenderWidth = %d\n",w,maxEditWidth,maxEditRenderWidth); if(maxEditWidth >= 0 || maxEditRenderWidth >= 0) { //printf("B w = %d maxEditWidth = %d maxEditRenderWidth = %d\n",w,maxEditWidth,maxEditRenderWidth); if(maxEditRenderWidth >= 0) { w = maxEditRenderWidth; } else { w = maxEditWidth; } } //printf("HI!!!\n"); glPointSize(20.0f); int margin = 4; //glBegin(GL_POINTS); // Start drawing a point primitive glBegin(GL_LINE_LOOP); // Start drawing a line primitive glVertex3f(x, y+h, 0.0f); // The bottom left corner glVertex3f(x, y-margin, 0.0f); // The top left corner glVertex3f(x+w, y-margin, 0.0f); // The top right corner glVertex3f(x+w, y+h, 0.0f); // The bottom right corner glEnd(); } // // renderTextBoundingBox3D // void Renderer::renderTextBoundingBox3D(const string &text, Font3D *font, float alpha, int x, int y, int w, int h, bool centeredW, bool centeredH, bool editModeEnabled, int maxEditWidth, int maxEditRenderWidth) { renderTextBoundingBox3D(text, font, Vec4f(1.f, 1.f, 1.f, alpha), x, y, w, h, centeredW, centeredH, editModeEnabled, maxEditRenderWidth, maxEditRenderWidth); } void Renderer::renderTextBoundingBox3D(const string &text, Font3D *font, const Vec3f &color, int x, int y, int w, int h, bool centeredW, bool centeredH, bool editModeEnabled, int maxEditWidth, int maxEditRenderWidth) { renderTextBoundingBox3D(text, font, Vec4f(color.x, color.y, color.z, 1.f), x, y, w, h, centeredW, centeredH, editModeEnabled, maxEditRenderWidth, maxEditRenderWidth); } void Renderer::renderTextBoundingBox3D(const string &text, Font3D *font, const Vec4f &color, int x, int y, int w, int h, bool centeredW, bool centeredH, bool editModeEnabled, int maxEditWidth, int maxEditRenderWidth) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT); glEnable(GL_BLEND); glColor4fv(color.ptr()); Vec2f pos= Vec2f(x, y); //Vec2i pos= centered? computeCenteredPos(text, font, x, y): Vec2i(x, y); if(centeredW == true || centeredH == true) { getCentered3DPos(text, font, pos, w, h,centeredW,centeredH); } if(editModeEnabled) { if(maxEditWidth >= 0 || maxEditRenderWidth >= 0) { int useWidth = maxEditWidth; string temp = ""; for(int i = 0; i < useWidth; ++i) { temp += DEFAULT_CHAR_FOR_WIDTH_CALC; } float lineWidth = (font->getTextHandler()->Advance(temp.c_str()) * ::Shared::Graphics::Font::scaleFontValue); useWidth = (int)lineWidth; maxEditWidth = useWidth; } renderTextSurroundingBox(pos.x, pos.y, w, h,maxEditWidth,maxEditRenderWidth); } glColor4fv(color.ptr()); TextRendererSafeWrapper safeTextRender(textRenderer3D,font); textRenderer3D->render(text, pos.x, pos.y); safeTextRender.end(); glDisable(GL_BLEND); glPopAttrib(); } // // renderText3D // void Renderer::renderText3D(const string &text, Font3D *font, float alpha, int x, int y, bool centered) { renderText3D(text,font,Vec4f(1.f, 1.f, 1.f, alpha),x,y,centered); } void Renderer::renderText3D(const string &text, Font3D *font, const Vec3f &color, int x, int y, bool centered) { renderText3D(text,font,Vec4f(color.x, color.y, color.z, 1.f),x,y,centered); } void Renderer::renderText3D(const string &text, Font3D *font, const Vec4f &color, int x, int y, bool centered) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT); glEnable(GL_BLEND); glColor4fv(color.ptr()); Vec2i pos= Vec2i(x, y); //Vec2i pos= centered? computeCenteredPos(text, font, x, y): Vec2i(x, y); TextRendererSafeWrapper safeTextRender(textRenderer3D,font); textRenderer3D->render(text, pos.x, pos.y, centered); safeTextRender.end(); glDisable(GL_BLEND); glPopAttrib(); } // // renderText // void Renderer::renderText(const string &text, Font2D *font, float alpha, int x, int y, bool centered) { renderText(text,font,Vec4f(1.f, 1.f, 1.f, alpha),x,y,centered); } void Renderer::renderText(const string &text, Font2D *font, const Vec3f &color, int x, int y, bool centered){ renderText(text,font,Vec4f(color.x, color.y, color.z, 1.f),x,y,centered); } void Renderer::renderText(const string &text, Font2D *font, const Vec4f &color, int x, int y, bool centered){ if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT); glEnable(GL_BLEND); glColor4fv(color.ptr()); Vec2i pos= centered? computeCenteredPos(text, font, x, y): Vec2i(x, y); TextRendererSafeWrapper safeTextRender(textRenderer,font); textRenderer->render(text, pos.x, pos.y); safeTextRender.end(); glPopAttrib(); } Vec2f Renderer::getCentered3DPos(const string &text, Font3D *font, Vec2f &pos, int w, int h,bool centeredW, bool centeredH) { if(centeredW == true) { if(font == NULL) { //abort(); throw megaglest_runtime_error("font == NULL (5) text = " + text); } else if(font->getTextHandler() == NULL) { char szBuf[8096] = ""; snprintf(szBuf, 8096, "font->getTextHandler() == NULL(5) text = [%s] FontPtr = [%p]\n", text.c_str(),font); throw megaglest_runtime_error(szBuf); } float lineWidth = (font->getTextHandler()->Advance(text.c_str()) * ::Shared::Graphics::Font::scaleFontValue); if(lineWidth < w) { pos.x += ((w / 2.f) - (lineWidth / 2.f)); } } if(centeredH) { if(font == NULL) { throw megaglest_runtime_error("font == NULL (6) text = " + text); } else if(font->getTextHandler() == NULL) { throw megaglest_runtime_error("font->getTextHandler() == NULL (6) text = " + text); } //const Metrics &metrics= Metrics::getInstance(); //float lineHeight = (font->getTextHandler()->LineHeight(text.c_str()) * Font::scaleFontValue); float lineHeight = (font->getTextHandler()->LineHeight(text.c_str()) * ::Shared::Graphics::Font::scaleFontValue); //lineHeight=metrics.toVirtualY(lineHeight); //lineHeight= lineHeight / (2.f + 0.2f * FontMetrics::DEFAULT_Y_OFFSET_FACTOR); //pos.y += (h / 2.f) - (lineHeight / 2.f); //pos.y += (h / 2.f) - (lineHeight); //pos.y += (lineHeight / 2.f); // y starts at the middle of the render position, so only move up 1/2 the font height if(lineHeight < h) { //printf("line %d, lineHeight [%f] h [%d] text [%s]\n",__LINE__,lineHeight,h,text.c_str()); //if(Font::forceFTGLFonts == true) { // First go to top of bounding box pos.y += (h - lineHeight); pos.y -= ((h - lineHeight) / ::Shared::Graphics::Font::scaleFontValueCenterHFactor); // } // else { // pos.y += (float)(((float)h) / 2.0); // float heightGap = (float)(((float)h - lineHeight) / 2.0); // pos.y -= heightGap; // // //printf("h = %d lineHeight = %f heightGap = %f\n",h,lineHeight,heightGap); // // // Now calculate till we get text to middle // //pos.y -= (realHeight / 2); // //pos.y += (lineHeight / 2); // } } else if(lineHeight > h) { //printf("line %d, lineHeight [%f] h [%d] text [%s]\n",__LINE__,lineHeight,h,text.c_str()); pos.y += (std::ceil(lineHeight - h)); } } return pos; } void Renderer::renderTextShadow3D(const string &text, Font3D *font,const Vec4f &color, int x, int y, bool centered) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(font == NULL) { throw megaglest_runtime_error("font == NULL (3) text = " + text); } glPushAttrib(GL_CURRENT_BIT); Vec2i pos= centered? computeCenteredPos(text, font, x, y): Vec2i(x, y); TextRendererSafeWrapper safeTextRender(textRenderer3D,font); if(color.w < 0.5) { glColor3f(0.0f, 0.0f, 0.0f); textRenderer3D->render(text, pos.x-1.0f, pos.y-1.0f); } glColor3f(color.x,color.y,color.z); textRenderer3D->render(text, pos.x, pos.y); //textRenderer3D->end(); safeTextRender.end(); glPopAttrib(); } void Renderer::renderTextShadow(const string &text, Font2D *font,const Vec4f &color, int x, int y, bool centered){ if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(font == NULL) { throw megaglest_runtime_error("font == NULL (4) text = " + text); } glPushAttrib(GL_CURRENT_BIT); Vec2i pos= centered? computeCenteredPos(text, font, x, y): Vec2i(x, y); TextRendererSafeWrapper safeTextRender(textRenderer,font); if(color.w < 0.5) { glColor3f(0.0f, 0.0f, 0.0f); textRenderer->render(text, pos.x-1.0f, pos.y-1.0f); } glColor3f(color.x,color.y,color.z); textRenderer->render(text, pos.x, pos.y); //textRenderer->end(); safeTextRender.end(); glPopAttrib(); } // ============= COMPONENTS ============================= void Renderer::renderLabel(GraphicLabel *label) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if( label->getVisible()==false){ return; } if(label->getEditable() && label->getMaxEditRenderWidth()>0) { int x= label->getX(); int y= label->getY(); int h= label->getH(); int w= label->getMaxEditRenderWidth(); if(h>0){ //background glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT); glEnable(GL_BLEND); glColor4f(0.2f, 0.2f, 0.2f, 0.6f*label->getFade()) ; glBegin(GL_TRIANGLE_STRIP); glVertex2i(x, y); glVertex2i(x, y+h); glVertex2i(x+w, y); glVertex2i(x+w, y+h); glEnd(); glPopAttrib(); } } if(label->getRenderBackground()) { int x= label->getX(); int y= label->getY(); int h= label->getH(); int w= label->getW(); if(label->getMaxEditRenderWidth()>0){ w= label->getMaxEditRenderWidth(); } Vec4f color=label->getBackgroundColor(); if(h>0){ //background glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT); glEnable(GL_BLEND); glColor4f(color.x, color.y, color.z, color.w*label->getFade()) ; glBegin(GL_TRIANGLE_STRIP); glVertex2i(x, y); glVertex2i(x, y+h); glVertex2i(x+w, y); glVertex2i(x+w, y+h); glEnd(); glPopAttrib(); } } if(label->getTexture()!=NULL ) { int x= label->getX(); int y= label->getY(); int h= label->getH(); int w= label->getW(); if(h>0){ //background glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT); glEnable(GL_BLEND); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, static_cast( label->getTexture())->getHandle()); glColor4f(1.0f, 1.0f, 1.0f, 1.0f*label->getFade()) ; glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(0.f, 0.f); glVertex2f(x, y); glTexCoord2f(0.f, 1.f); glVertex2f(x, y+h); glTexCoord2f(1.f, 0.f); glVertex2f(x+w, y); glTexCoord2f(1.f, 1.f); glVertex2f(x+w, y+h); glEnd(); glDisable(GL_TEXTURE_2D); glPopAttrib(); } } Vec3f labelColor=label->getTextColor(); Vec4f colorWithAlpha = Vec4f(labelColor.x,labelColor.y,labelColor.z,GraphicComponent::getFade()); renderLabel(label,&colorWithAlpha); } void Renderer::renderLabel(GraphicLabel *label,const Vec3f *color) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(color != NULL) { Vec4f colorWithAlpha = Vec4f(*color); colorWithAlpha.w = GraphicComponent::getFade(); renderLabel(label,&colorWithAlpha); } else { Vec4f *colorWithAlpha = NULL; renderLabel(label,colorWithAlpha); } } void Renderer::renderLabel(GraphicLabel *label,const Vec4f *color) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(label->getVisible() == false) { return; } try { glPushAttrib(GL_ENABLE_BIT); glEnable(GL_BLEND); vector lines; string renderTextString = (label->getTextNativeTranslation() != "" ? label->getTextNativeTranslation() : label->getText()); if(label->getWordWrap() == true) { Tokenize(renderTextString,lines,"\n"); } else { lines.push_back(renderTextString); } for(unsigned int i = 0; i < lines.size(); ++i) { Vec2i textPos; int x= label->getX(); int y= label->getY() - (i * label->getH()); int h= label->getH(); int w= label->getW(); //if(label->getInstanceName() == "modDescrLabel") printf("~~~ lines.size() [%u] i = %d lines[i] [%s] y = %d\n",lines.size(),i,lines[i].c_str(),y); if(label->getCentered()) { textPos= Vec2i(x+w/2, y+h/2); } else { textPos= Vec2i(x, y+h/4); } string renderTextStr = lines[i]; if(label->getIsPassword() == true) { if(renderTextStr != "") { renderTextStr = "*****"; } } if(color != NULL) { if(renderText3DEnabled == true) { //renderText3D(lines[i], label->getFont3D(), (*color), textPos.x, textPos.y, label->getCentered()); //printf("Text Render3D [%s] font3d [%p]\n",lines[i].c_str(),label->getFont3D()); //printf("Label render C\n"); renderTextBoundingBox3D(renderTextStr, label->getFont3D(), (*color), x, y, w, h, label->getCenteredW(),label->getCenteredH(), label->getEditModeEnabled(),label->getMaxEditWidth(), label->getMaxEditRenderWidth()); } else { //printf("Label render D\n"); renderText(renderTextStr, label->getFont(), (*color), textPos.x, textPos.y, label->getCentered()); } } else { if(renderText3DEnabled == true) { //renderText3D(lines[i], label->getFont3D(), GraphicComponent::getFade(), textPos.x, textPos.y, label->getCentered()); //printf("Text Render3D [%s] font3d [%p]\n",lines[i].c_str(),label->getFont3D()); //printf("Label render E\n"); renderTextBoundingBox3D(renderTextStr, label->getFont3D(), GraphicComponent::getFade(), x, y, w, h, label->getCenteredW(),label->getCenteredH(), label->getEditModeEnabled(),label->getMaxEditWidth(), label->getMaxEditRenderWidth()); } else { //printf("Label render F\n"); renderText(renderTextStr, label->getFont(), GraphicComponent::getFade(), textPos.x, textPos.y, label->getCentered()); } } } glPopAttrib(); } catch(const exception &e) { char szBuf[8096]=""; snprintf(szBuf,8096,"In [%s::%s Line: %d]\nError [%s] For Control [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,e.what(),label->getInstanceName().c_str()); SystemFlags::OutputDebug(SystemFlags::debugError,szBuf); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf); throw megaglest_runtime_error(szBuf); } } void Renderer::renderButton(GraphicButton *button, const Vec4f *fontColorOverride, bool *lightedOverride) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(button->getVisible() == false) { return; } try { //char szBuf[8096]=""; //snprintf(szBuf,8096,"In [%s::%s Line: %d]\n For Control container [%s] name [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,button->getContainerName().c_str(), button->getInstanceName().c_str()); //printf(szBuf); int x= button->getX(); int y= button->getY(); int h= button->getH(); int w= button->getW(); const Vec3f disabledTextColor= Vec3f(0.25f,0.25f,0.25f); glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT); //background CoreData &coreData= CoreData::getInstance(); Texture2D *backTexture = NULL; if(button->getUseCustomTexture() == true) { backTexture = dynamic_cast(button->getCustomTexture()); } else { backTexture = w > 3 * h / 2 ? coreData.getButtonBigTexture(): coreData.getButtonSmallTexture(); } glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); if(backTexture != NULL) { glBindTexture(GL_TEXTURE_2D, static_cast(backTexture)->getHandle()); } else { glBindTexture(GL_TEXTURE_2D, 0); } //button Vec4f fontColor(GraphicComponent::getCustomTextColor()); if(fontColorOverride != NULL) { fontColor= *fontColorOverride; } else { // white shadowed is default ( in the menu for example ) fontColor.w = GraphicComponent::getFade(); } //Vec4f color= Vec4f(1.f, 1.f, 1.f, GraphicComponent::getFade()); Vec4f color= fontColor; glColor4fv(color.ptr()); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(0.f, 0.f); glVertex2f(x, y); glTexCoord2f(0.f, 1.f); glVertex2f(x, y+h); glTexCoord2f(1.f, 0.f); glVertex2f(x+w, y); glTexCoord2f(1.f, 1.f); glVertex2f(x+w, y+h); glEnd(); glDisable(GL_TEXTURE_2D); //lighting float anim= GraphicComponent::getAnim(); if(anim>0.5f) anim= 1.f-anim; bool renderLighted = (button->getLighted() && button->getEditable()); if(lightedOverride != NULL) { renderLighted = *lightedOverride; } if(renderLighted) { const int lightSize= 0; const Vec4f color1= Vec4f(color.x, color.y, color.z, 0.1f+anim*0.5f); const Vec4f color2= Vec4f(color.x, color.y, color.z, 0.3f+anim); glBegin(GL_TRIANGLE_FAN); glColor4fv(color2.ptr()); glVertex2f(x+w/2, y+h/2); glColor4fv(color1.ptr()); glVertex2f(x-lightSize, y-lightSize); glColor4fv(color1.ptr()); glVertex2f(x+w+lightSize, y-lightSize); glColor4fv(color1.ptr()); glVertex2f(x+w+lightSize, y+h+lightSize); glColor4fv(color1.ptr()); glVertex2f(x+w+lightSize, y+h+lightSize); glColor4fv(color1.ptr()); glVertex2f(x-lightSize, y+h+lightSize); glColor4fv(color1.ptr()); glVertex2f(x-lightSize, y-lightSize); glEnd(); } //Vec2i textPos= Vec2i(x + w / 2, y + h / 2); if(button->getEditable()) { if(renderText3DEnabled == true) { //renderText3D(button->getText(), button->getFont3D(), color,x + (w / 2), y + (h / 2), true); renderTextBoundingBox3D(button->getText(), button->getFont3D(), color, x, y, w, h, true, true,false,-1,-1); } else { renderText(button->getText(), button->getFont(), color,x + (w / 2), y + (h / 2), true); } } else { if(renderText3DEnabled == true) { //renderText3D(button->getText(), button->getFont3D(),disabledTextColor, // x + (w / 2), y + (h / 2), true); renderTextBoundingBox3D(button->getText(), button->getFont3D(),disabledTextColor, x, y, w, h, true, true,false,-1,-1); } else { renderText(button->getText(), button->getFont(),disabledTextColor, x + (w / 2), y + (h / 2), true); } } glPopAttrib(); } catch(const exception &e) { char szBuf[8096]=""; snprintf(szBuf,8096,"In [%s::%s Line: %d]\nError [%s] For Control container [%s] name [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,e.what(),button->getContainerName().c_str(), button->getInstanceName().c_str()); SystemFlags::OutputDebug(SystemFlags::debugError,szBuf); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf); throw megaglest_runtime_error(szBuf); } } void Renderer::renderCheckBox(const GraphicCheckBox *box) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(box->getVisible() == false) { return; } int x= box->getX(); int y= box->getY(); int h= box->getH(); int w= box->getW(); //const Vec3f disabledTextColor= Vec3f(0.25f,0.25f,0.25f); glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT); //background CoreData &coreData= CoreData::getInstance(); Texture2D *backTexture= box->getValue()? coreData.getCheckedCheckBoxTexture(): coreData.getCheckBoxTexture(); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, static_cast(backTexture)->getHandle()); //box Vec4f fontColor; //if(game!=NULL){ // fontColor=game->getGui()->getDisplay()->getColor(); // fontColor.w = GraphicComponent::getFade(); //} //else { // white shadowed is default ( in the menu for example ) fontColor=Vec4f(1.f, 1.f, 1.f, GraphicComponent::getFade()); //} //Vec4f color= Vec4f(1.f, 1.f, 1.f, GraphicComponent::getFade()); Vec4f color= fontColor; glColor4fv(color.ptr()); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(0.f, 0.f); glVertex2f(x, y); glTexCoord2f(0.f, 1.f); glVertex2f(x, y+h); glTexCoord2f(1.f, 0.f); glVertex2f(x+w, y); glTexCoord2f(1.f, 1.f); glVertex2f(x+w, y+h); glEnd(); glDisable(GL_TEXTURE_2D); //lighting float anim= GraphicComponent::getAnim(); if(anim > 0.5f) { anim = 1.f - anim; } if(box->getLighted() && box->getEditable()) { const int lightSize= 0; const Vec4f color1= Vec4f(color.x, color.y, color.z, 0.1f+anim*0.5f); const Vec4f color2= Vec4f(color.x, color.y, color.z, 0.3f+anim); glBegin(GL_TRIANGLE_FAN); glColor4fv(color2.ptr()); glVertex2f(x+w/2, y+h/2); glColor4fv(color1.ptr()); glVertex2f(x-lightSize, y-lightSize); glColor4fv(color1.ptr()); glVertex2f(x+w+lightSize, y-lightSize); glColor4fv(color1.ptr()); glVertex2f(x+w+lightSize, y+h+lightSize); glColor4fv(color1.ptr()); glVertex2f(x+w+lightSize, y+h+lightSize); glColor4fv(color1.ptr()); glVertex2f(x-lightSize, y+h+lightSize); glColor4fv(color1.ptr()); glVertex2f(x-lightSize, y-lightSize); glEnd(); } glPopAttrib(); } void Renderer::renderLine(const GraphicLine *line) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(line->getVisible() == false) { return; } int x= line->getX(); int y= line->getY(); int h= line->getH(); int w= line->getW(); //const Vec3f disabledTextColor= Vec3f(0.25f,0.25f,0.25f); glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT); //background CoreData &coreData= CoreData::getInstance(); Texture2D *backTexture= line->getHorizontal()? coreData.getHorizontalLineTexture(): coreData.getVerticalLineTexture(); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, static_cast(backTexture)->getHandle()); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(0.f, 0.f); glVertex2f(x, y); glTexCoord2f(0.f, 1.f); glVertex2f(x, y+h); glTexCoord2f(1.f, 0.f); glVertex2f(x+w, y); glTexCoord2f(1.f, 1.f); glVertex2f(x+w, y+h); glEnd(); glDisable(GL_TEXTURE_2D); glPopAttrib(); } void Renderer::renderScrollBar(const GraphicScrollBar *sb) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(sb->getVisible() == false) { return; } int x= sb->getX(); int y= sb->getY(); int h= sb->getH(); int w= sb->getW(); // calc real length if(sb->getElementCount()getVisibleSize()){ int realLength=sb->getElementCount()*sb->getLength()/ sb->getVisibleSize(); if (sb->getHorizontal()) { x=x-(w-realLength); } else { y=y+(h-realLength); h=realLength; }; } glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT); ///////////////////// //background //////////////////// CoreData &coreData= CoreData::getInstance(); Texture2D *backTexture= coreData.getHorizontalLineTexture(); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); Vec4f fontColor; fontColor=Vec4f(1.f, 1.f, 1.f, GraphicComponent::getFade()); Vec4f color= fontColor; glColor4fv(color.ptr()); glBindTexture(GL_TEXTURE_2D, static_cast(backTexture)->getHandle()); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(0.f, 0.f); glVertex2f(x, y); glTexCoord2f(0.f, 1.f); glVertex2f(x, y+h); glTexCoord2f(1.f, 0.f); glVertex2f(x+w, y); glTexCoord2f(1.f, 1.f); glVertex2f(x+w, y+h); glEnd(); //////////////////// // selectBlock //////////////////// if (sb->getElementCount() >= sb->getVisibleSize()) { if (sb->getHorizontal()) { x = x + sb->getVisibleCompPosStart(); w = sb->getVisibleCompPosEnd() - sb->getVisibleCompPosStart(); } else { y = y + sb->getVisibleCompPosStart(); h = sb->getVisibleCompPosEnd() - sb->getVisibleCompPosStart(); } } Texture2D *selectTexture= coreData.getButtonBigTexture(); assert(selectTexture != NULL); glBindTexture(GL_TEXTURE_2D, static_cast(selectTexture)->getHandle()); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(0.f, 0.f); glVertex2f(x, y); glTexCoord2f(0.f, 1.f); glVertex2f(x, y+h); glTexCoord2f(1.f, 0.f); glVertex2f(x+w, y); glTexCoord2f(1.f, 1.f); glVertex2f(x+w, y+h); glEnd(); glDisable(GL_TEXTURE_2D); //lighting float anim= GraphicComponent::getAnim(); if(anim>0.5f) anim= 1.f-anim; if(sb->getLighted() && sb->getEditable()){ const int lightSize= 0; const Vec4f color1= Vec4f(color.x, color.y, color.z, 0.1f+anim*0.5f); const Vec4f color2= Vec4f(color.x, color.y, color.z, 0.3f+anim); glBegin(GL_TRIANGLE_FAN); glColor4fv(color2.ptr()); glVertex2f(x+w/2, y+h/2); glColor4fv(color1.ptr()); glVertex2f(x-lightSize, y-lightSize); glColor4fv(color1.ptr()); glVertex2f(x+w+lightSize, y-lightSize); glColor4fv(color1.ptr()); glVertex2f(x+w+lightSize, y+h+lightSize); glColor4fv(color1.ptr()); glVertex2f(x+w+lightSize, y+h+lightSize); glColor4fv(color1.ptr()); glVertex2f(x-lightSize, y+h+lightSize); glColor4fv(color1.ptr()); glVertex2f(x-lightSize, y-lightSize); glEnd(); } glPopAttrib(); } void Renderer::renderListBox(GraphicListBox *listBox) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(listBox->getVisible() == false) { return; } //if(listBox->getLeftControlled()==true) { int x= listBox->getX(); int y= listBox->getY(); int h= listBox->getH(); int w= listBox->getW(); if(h>0){ //background glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT); glEnable(GL_BLEND); glColor4f(0.0f, 0.0f, 0.0f, 0.6f*listBox->getFade()) ; glBegin(GL_TRIANGLE_STRIP); glVertex2i(x, y); glVertex2i(x, y+h); glVertex2i(x+w, y); glVertex2i(x+w, y+h); glEnd(); glPopAttrib(); } } renderButton(listBox->getButton1()); renderButton(listBox->getButton2()); glPushAttrib(GL_ENABLE_BIT); glEnable(GL_BLEND); GraphicLabel label("ListBox_render_label","label",false); //label.setInstanceName("ListBox_render_label"); if(listBox->getLeftControlled()==true){ label.init(listBox->getX()+listBox->getButton1()->getW()+listBox->getButton2()->getW()+2, listBox->getY(), listBox->getW(), listBox->getH(), false,listBox->getTextColor()); } else { label.init(listBox->getX(), listBox->getY(), listBox->getW(), listBox->getH(), true,listBox->getTextColor()); } label.setText(listBox->getText()); label.setTextNativeTranslation(listBox->getTextNativeTranslation()); label.setFont(listBox->getFont()); label.setFont3D(listBox->getFont3D()); renderLabel(&label); //lighting bool renderLighted= (listBox->getLighted()); if(renderLighted) { float anim= GraphicComponent::getAnim(); if(anim>0.5f) anim= 1.f-anim; Vec3f color=listBox->getTextColor(); int x= listBox->getX()+listBox->getButton1()->getW(); int y= listBox->getY(); int h= listBox->getH(); int w= listBox->getW()-listBox->getButton1()->getW()-listBox->getButton2()->getW(); const int lightSize= 0; const Vec4f color1= Vec4f(color.x, color.y, color.z, 0.1f+anim*0.5f); const Vec4f color2= Vec4f(color.x, color.y, color.z, 0.3f+anim); glBegin(GL_TRIANGLE_FAN); glColor4fv(color2.ptr()); glVertex2f(x+w/2, y+h/2); glColor4fv(color1.ptr()); glVertex2f(x-lightSize, y-lightSize); glColor4fv(color1.ptr()); glVertex2f(x+w+lightSize, y-lightSize); glColor4fv(color1.ptr()); glVertex2f(x+w+lightSize, y+h+lightSize); glColor4fv(color1.ptr()); glVertex2f(x+w+lightSize, y+h+lightSize); glColor4fv(color1.ptr()); glVertex2f(x-lightSize, y+h+lightSize); glColor4fv(color1.ptr()); glVertex2f(x-lightSize, y-lightSize); glEnd(); } glPopAttrib(); } void Renderer::renderComboBox(GraphicComboBox *comboBox) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(comboBox->getVisible() == false) { return; } int x= comboBox->getX(); int y= comboBox->getY(); int h= comboBox->getH(); int w= comboBox->getW(); if(h>0){ //background glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT); glEnable(GL_BLEND); glColor4f(0.0f, 0.0f, 0.0f, 0.6f*comboBox->getFade()) ; glBegin(GL_TRIANGLE_STRIP); glVertex2i(x, y); glVertex2i(x, y+h); glVertex2i(x+w, y); glVertex2i(x+w, y+h); glEnd(); glPopAttrib(); } renderButton(comboBox->getButton()); if( comboBox->isDropDownShowing()){ renderScrollBar(comboBox->getScrollbar()); if(comboBox->getPopupButtons()->size() != 0) { for(int i = comboBox->getScrollbar()->getVisibleStart(); i <= comboBox->getScrollbar()->getVisibleEnd(); ++i) { renderButton((* comboBox->getPopupButtons())[i]); } } } glPushAttrib(GL_ENABLE_BIT); glEnable(GL_BLEND); GraphicLabel label("ComboBox_render_label","label",false); //label.setInstanceName("ComboBox_render_label"); label.init(comboBox->getX(), comboBox->getY(), comboBox->getW(), comboBox->getH(), true,comboBox->getTextColor()); label.setText(comboBox->getText()); label.setTextNativeTranslation(comboBox->getTextNativeTranslation()); label.setFont(comboBox->getFont()); label.setFont3D(comboBox->getFont3D()); renderLabel(&label); //lighting bool renderLighted= (comboBox->getLighted()); if(renderLighted) { float anim= GraphicComponent::getAnim(); if(anim>0.5f) anim= 1.f-anim; Vec3f color=comboBox->getTextColor(); int x= comboBox->getX()+comboBox->getButton()->getW(); int y= comboBox->getY(); int h= comboBox->getH(); int w= comboBox->getW()-comboBox->getButton()->getW(); const int lightSize= 0; const Vec4f color1= Vec4f(color.x, color.y, color.z, 0.1f+anim*0.5f); const Vec4f color2= Vec4f(color.x, color.y, color.z, 0.3f+anim); glBegin(GL_TRIANGLE_FAN); glColor4fv(color2.ptr()); glVertex2f(x+w/2, y+h/2); glColor4fv(color1.ptr()); glVertex2f(x-lightSize, y-lightSize); glColor4fv(color1.ptr()); glVertex2f(x+w+lightSize, y-lightSize); glColor4fv(color1.ptr()); glVertex2f(x+w+lightSize, y+h+lightSize); glColor4fv(color1.ptr()); glVertex2f(x+w+lightSize, y+h+lightSize); glColor4fv(color1.ptr()); glVertex2f(x-lightSize, y+h+lightSize); glColor4fv(color1.ptr()); glVertex2f(x-lightSize, y-lightSize); glEnd(); } glPopAttrib(); } void Renderer::renderMessageBox(GraphicMessageBox *messageBox) { const int headerHeight=25; if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } try { if(messageBox->getVisible() == false) { return; } if((renderText3DEnabled == false && messageBox->getFont() == NULL) || (renderText3DEnabled == true && messageBox->getFont3D() == NULL)) { messageBox->setFont(CoreData::getInstance().getMenuFontNormal()); messageBox->setFont3D(CoreData::getInstance().getMenuFontNormal3D()); } string wrappedText = messageBox->getText(); if(messageBox->getAutoWordWrap() == true) { if(renderText3DEnabled == false) { wrappedText = messageBox->getFont()->getMetrics()->wordWrapText(wrappedText,messageBox->getW() * 0.90); } else { wrappedText = messageBox->getFont3D()->getMetrics()->wordWrapText(wrappedText,messageBox->getW() * 0.90); } } //background glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT); glEnable(GL_BLEND); glColor4f(0.0f, 0.0f, 0.0f, 0.8f) ; glBegin(GL_TRIANGLE_STRIP); glVertex2i(messageBox->getX(), messageBox->getY()+messageBox->getH()-headerHeight); glVertex2i(messageBox->getX(), messageBox->getY()); glVertex2i(messageBox->getX() + messageBox->getW(), messageBox->getY() + messageBox->getH()-headerHeight); glVertex2i(messageBox->getX() + messageBox->getW(), messageBox->getY()); glEnd(); glColor4f(0.0f, 0.0f, 0.0f, 0.8f) ; glBegin(GL_TRIANGLE_STRIP); glVertex2i(messageBox->getX(), messageBox->getY()+messageBox->getH()); glVertex2i(messageBox->getX(), messageBox->getY()+messageBox->getH()-headerHeight); glVertex2i(messageBox->getX() + messageBox->getW(), messageBox->getY() + messageBox->getH()); glVertex2i(messageBox->getX() + messageBox->getW(), messageBox->getY()+messageBox->getH()-headerHeight); glEnd(); glBegin(GL_LINE_LOOP); glColor4f(0.5f, 0.5f, 0.5f, 0.25f) ; glVertex2i(messageBox->getX(), messageBox->getY()); glColor4f(0.0f, 0.0f, 0.0f, 0.25f) ; glVertex2i(messageBox->getX()+ messageBox->getW(), messageBox->getY()); glColor4f(0.5f, 0.5f, 0.5f, 0.25f) ; glVertex2i(messageBox->getX()+ messageBox->getW(), messageBox->getY() + messageBox->getH()); glColor4f(0.25f, 0.25f, 0.25f, 0.25f) ; glVertex2i(messageBox->getX(), messageBox->getY() + messageBox->getH()); glEnd(); glBegin(GL_LINE_STRIP); glColor4f(1.0f, 1.0f, 1.0f, 0.25f) ; glVertex2i(messageBox->getX(), messageBox->getY() + messageBox->getH()-headerHeight); glColor4f(0.5f, 0.5f, 0.5f, 0.25f) ; glVertex2i(messageBox->getX()+ messageBox->getW(), messageBox->getY() + messageBox->getH()-headerHeight); glEnd(); glPopAttrib(); //buttons for(int i=0; igetButtonCount();i++){ if((renderText3DEnabled == false && messageBox->getButton(i)->getFont() == NULL) || (renderText3DEnabled == true && messageBox->getButton(i)->getFont3D() == NULL)) { messageBox->getButton(i)->setFont(CoreData::getInstance().getMenuFontNormal()); messageBox->getButton(i)->setFont3D(CoreData::getInstance().getMenuFontNormal3D()); } renderButton(messageBox->getButton(i)); } Vec4f fontColor; //if(game!=NULL){ // fontColor=game->getGui()->getDisplay()->getColor(); //} //else { // white shadowed is default ( in the menu for example ) fontColor=Vec4f(1.f, 1.f, 1.f, 1.0f); //} if(renderText3DEnabled == true) { //text renderTextShadow3D( wrappedText, messageBox->getFont3D(), fontColor, messageBox->getX()+15, messageBox->getY()+messageBox->getH()-headerHeight*2, false ); renderTextShadow3D( messageBox->getHeader(), messageBox->getFont3D(),fontColor, messageBox->getX()+15, messageBox->getY()+messageBox->getH()-headerHeight+8, false ); } else { //text renderTextShadow( wrappedText, messageBox->getFont(), fontColor, messageBox->getX()+15, messageBox->getY()+messageBox->getH()-headerHeight*2, false ); renderTextShadow( messageBox->getHeader(), messageBox->getFont(),fontColor, messageBox->getX()+15, messageBox->getY()+messageBox->getH()-headerHeight+8, false ); } } catch(const exception &e) { char szBuf[8096]=""; snprintf(szBuf,8096,"In [%s::%s Line: %d]\nError [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,e.what()); SystemFlags::OutputDebug(SystemFlags::debugError,szBuf); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf); throw megaglest_runtime_error(szBuf); } } // ==================== complex rendering ==================== //VisibleQuadContainerVBOCache * Renderer::GetSurfaceVBOs(SurfaceData *cellData) { // std::map::iterator iterFind = mapSurfaceVBOCache.find(cellData->uniqueId); // if(iterFind == mapSurfaceVBOCache.end()) { // Vec2f *texCoords = &cellData->texCoords[0]; // Vec2f *texCoordsSurface = &cellData->texCoordsSurface[0]; // Vec3f *vertices = &cellData->vertices[0]; // Vec3f *normals = &cellData->normals[0]; // // VisibleQuadContainerVBOCache vboCache; // // // Generate And Bind The Vertex Buffer // glGenBuffersARB( 1, (GLuint*)&vboCache.m_nVBOVertices ); // Get A Valid Name // glBindBufferARB( GL_ARRAY_BUFFER_ARB, vboCache.m_nVBOVertices ); // Bind The Buffer // // Load The Data // glBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof(Vec3f) * cellData->bufferCount, vertices, GL_STATIC_DRAW_ARB ); // glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); // // assertGl(); // // Generate And Bind The Texture Coordinate Buffer // glGenBuffersARB( 1, (GLuint*)&vboCache.m_nVBOFowTexCoords ); // Get A Valid Name // glBindBufferARB( GL_ARRAY_BUFFER_ARB, vboCache.m_nVBOFowTexCoords ); // Bind The Buffer // // Load The Data // glBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof(Vec2f) * cellData->bufferCount, texCoords, GL_STATIC_DRAW_ARB ); // glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); // // assertGl(); // // Generate And Bind The Texture Coordinate Buffer // glGenBuffersARB( 1, (GLuint*)&vboCache.m_nVBOSurfaceTexCoords ); // Get A Valid Name // glBindBufferARB( GL_ARRAY_BUFFER_ARB, vboCache.m_nVBOSurfaceTexCoords ); // Bind The Buffer // // Load The Data // glBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof(Vec2f) * cellData->bufferCount, texCoordsSurface, GL_STATIC_DRAW_ARB ); // glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); // // assertGl(); // // Generate And Bind The Normal Buffer // glGenBuffersARB( 1, (GLuint*)&vboCache.m_nVBONormals ); // Get A Valid Name // glBindBufferARB( GL_ARRAY_BUFFER_ARB, vboCache.m_nVBONormals ); // Bind The Buffer // // Load The Data // glBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof(Vec3f) * cellData->bufferCount, normals, GL_STATIC_DRAW_ARB ); // glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); // // vboCache.hasBuiltVBOs = true; // // mapSurfaceVBOCache[cellData->uniqueId] = vboCache; // // // don't need the data in computer RAM anymore its in the GPU now // cellData->texCoords.clear(); // cellData->texCoordsSurface.clear(); // cellData->vertices.clear(); // cellData->normals.clear(); // } // // return &mapSurfaceVBOCache[cellData->uniqueId]; //} void Renderer::ReleaseSurfaceVBOs() { for(std::map::iterator iterFind = mapSurfaceVBOCache.begin(); iterFind != mapSurfaceVBOCache.end(); ++iterFind) { VisibleQuadContainerVBOCache &item = iterFind->second; if(item.hasBuiltVBOs == true) { glDeleteBuffersARB( 1, (GLuint*)&item.m_nVBOVertices ); // Get A Valid Name glDeleteBuffersARB( 1, (GLuint*)&item.m_nVBOFowTexCoords ); // Get A Valid Name glDeleteBuffersARB( 1, (GLuint*)&item.m_nVBOSurfaceTexCoords ); // Get A Valid Name glDeleteBuffersARB( 1, (GLuint*)&item.m_nVBONormals ); // Get A Valid Name //glDeleteBuffersARB( 1, &item.m_nVBOIndexes ); // Get A Valid Name } } mapSurfaceVBOCache.clear(); } Renderer::MapRenderer::Layer::~Layer() { if(vbo_vertices) glDeleteBuffersARB(1,&vbo_vertices); if(vbo_normals) glDeleteBuffersARB(1,&vbo_normals); if(vbo_fowTexCoords) glDeleteBuffersARB(1,&vbo_fowTexCoords); if(vbo_surfTexCoords) glDeleteBuffersARB(1,&vbo_surfTexCoords); if(vbo_indices) glDeleteBuffersARB(1,&vbo_indices); } template void _loadVBO(GLuint &vbo,std::vector buf,int target=GL_ARRAY_BUFFER_ARB) { assert(buf.size()); if(true /* vbo enabled? */) { glGenBuffersARB(1,&vbo); assert(vbo); glBindBufferARB(target,vbo); glBufferDataARB(target,sizeof(T)*buf.size(),&buf[0],GL_STATIC_DRAW_ARB); glBindBufferARB(target,0); assertGl(); buf.clear(); } } void Renderer::MapRenderer::Layer::load_vbos(bool vboEnabled) { indexCount = (int)indices.size(); if(vboEnabled) { _loadVBO(vbo_vertices,vertices); _loadVBO(vbo_normals,normals); _loadVBO(vbo_fowTexCoords,fowTexCoords); _loadVBO(vbo_surfTexCoords,surfTexCoords); _loadVBO(vbo_indices,indices,GL_ELEMENT_ARRAY_BUFFER_ARB); } else { vbo_vertices = 0; vbo_normals = 0; vbo_fowTexCoords = 0; vbo_surfTexCoords = 0; vbo_indices = 0; } } void Renderer::MapRenderer::loadVisibleLayers(float coordStep,VisibleQuadContainerCache &qCache) { int totalCellCount = 0; // we create a layer for each visible texture in the map for(int visibleIndex = 0; visibleIndex < (int)qCache.visibleScaledCellList.size(); ++visibleIndex) { Vec2i &pos = qCache.visibleScaledCellList[visibleIndex]; totalCellCount++; SurfaceCell *tc00= map->getSurfaceCell(pos.x, pos.y); SurfaceCell *tc10= map->getSurfaceCell(pos.x+1, pos.y); SurfaceCell *tc01= map->getSurfaceCell(pos.x, pos.y+1); SurfaceCell *tc11= map->getSurfaceCell(pos.x+1, pos.y+1); const Vec2f &surfCoord= tc00->getSurfTexCoord(); SurfaceCell *tc[4] = { tc00, tc10, tc01, tc11 }; int textureHandle = static_cast(tc[0]->getSurfaceTexture())->getHandle(); string texturePath = static_cast(tc[0]->getSurfaceTexture())->getPath(); //int32 textureCRC = CalculatePixelsCRC(static_cast(tc[0]->getSurfaceTexture())); Layer* layer = NULL; for(Layers::iterator it= layers.begin(); it!= layers.end(); ++it) { if((*it)->textureHandle == textureHandle) { //if((*it)->texturePath == texturePath) { //if((*it)->textureCRC == textureCRC) { layer = *it; break; } } if(!layer) { layer = new Layer(textureHandle); layer->texturePath = texturePath; //layer->textureCRC = textureCRC; layers.push_back(layer); //printf("Ading new unique texture [%s]\n",texturePath.c_str()); } // we'll be super-lazy and re-emit all four corners just because its easier int index[4]; int loopIndexes[4] = { 2,0,3,1 }; for(int i=0; i < 4; i++) { index[i] = (int)layer->vertices.size(); SurfaceCell *corner = tc[loopIndexes[i]]; layer->vertices.push_back(corner->getVertex()); layer->normals.push_back(corner->getNormal()); layer->fowTexCoords.push_back(corner->getFowTexCoord()); } layer->surfTexCoords.push_back(Vec2f(surfCoord.x, surfCoord.y + coordStep)); layer->surfTexCoords.push_back(Vec2f(surfCoord.x, surfCoord.y)); layer->surfTexCoords.push_back(Vec2f(surfCoord.x+coordStep, surfCoord.y+coordStep)); layer->surfTexCoords.push_back(Vec2f(surfCoord.x+coordStep, surfCoord.y)); // and make two triangles (no strip, we may be disjoint) layer->indices.push_back(index[0]); layer->indices.push_back(index[1]); layer->indices.push_back(index[2]); layer->indices.push_back(index[1]); layer->indices.push_back(index[3]); layer->indices.push_back(index[2]); } // turn them into vbos (actually this method will just calc the index count) for(Layers::iterator layer= layers.begin(); layer!= layers.end(); ++layer){ (*layer)->load_vbos(false); } //printf("Total # of layers for this map = %d totalCellCount = %d overall render reduction ratio = %d times\n",layers.size(),totalCellCount,(totalCellCount / layers.size())); } void Renderer::MapRenderer::load(float coordStep) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } int totalCellCount = 0; // we create a layer for each texture in the map for(int y=0; ygetSurfaceH()-1; y++) { for(int x=0; xgetSurfaceW()-1; x++) { totalCellCount++; SurfaceCell *tc[4] = { map->getSurfaceCell(x,y), map->getSurfaceCell(x+1,y), map->getSurfaceCell(x,y+1), map->getSurfaceCell(x+1,y+1) }; int textureHandle = static_cast(tc[0]->getSurfaceTexture())->getHandle(); string texturePath = static_cast(tc[0]->getSurfaceTexture())->getPath(); //int32 textureCRC = CalculatePixelsCRC(static_cast(tc[0]->getSurfaceTexture())); Layer* layer = NULL; for(Layers::iterator it= layers.begin(); it!= layers.end(); ++it) { if((*it)->textureHandle == textureHandle) { //if((*it)->texturePath == texturePath) { //if((*it)->textureCRC == textureCRC) { layer = *it; break; } } if(!layer) { layer = new Layer(textureHandle); layer->texturePath = texturePath; //layer->textureCRC = textureCRC; layers.push_back(layer); //printf("Ading new unique texture [%s]\n",texturePath.c_str()); } // we'll be super-lazy and re-emit all four corners just because its easier int index[4]; int loopIndexes[4] = { 2,0,3,1 }; for(int i=0; i < 4; i++) { index[i] = (int)layer->vertices.size(); SurfaceCell *corner = tc[loopIndexes[i]]; layer->vertices.push_back(corner->getVertex()); layer->normals.push_back(corner->getNormal()); } // the texture coords are all on the current texture obviously layer->fowTexCoords.push_back(tc[loopIndexes[0]]->getFowTexCoord()); layer->fowTexCoords.push_back(tc[loopIndexes[1]]->getFowTexCoord()); layer->fowTexCoords.push_back(tc[loopIndexes[2]]->getFowTexCoord()); layer->fowTexCoords.push_back(tc[loopIndexes[3]]->getFowTexCoord()); layer->surfTexCoords.push_back(tc[0]->getSurfTexCoord()+Vec2f(0,coordStep)); layer->surfTexCoords.push_back(tc[0]->getSurfTexCoord()+Vec2f(0,0)); layer->surfTexCoords.push_back(tc[0]->getSurfTexCoord()+Vec2f(coordStep,coordStep)); layer->surfTexCoords.push_back(tc[0]->getSurfTexCoord()+Vec2f(coordStep,0)); layer->cellToIndicesMap[Vec2i(x,y)] = (int)layer->indices.size(); // and make two triangles (no strip, we may be disjoint) layer->indices.push_back(index[0]); layer->indices.push_back(index[1]); layer->indices.push_back(index[2]); layer->indices.push_back(index[1]); layer->indices.push_back(index[3]); layer->indices.push_back(index[2]); } } // turn them into vbos for(Layers::iterator layer= layers.begin(); layer!= layers.end(); ++layer){ (*layer)->load_vbos(true); } //printf("Total # of layers for this map = %d totalCellCount = %d overall render reduction ratio = %d times\n",layers.size(),totalCellCount,(totalCellCount / layers.size())); } template void* _bindVBO(GLuint vbo,std::vector &buf,int target=GL_ARRAY_BUFFER_ARB) { void* result = NULL; if(vbo) { glBindBuffer(target,vbo); } else { result = &buf[0]; } return result; } void Renderer::MapRenderer::Layer::renderVisibleLayer() { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } //glBindTexture(GL_TEXTURE_2D, static_cast(fowTex)->getHandle()); glClientActiveTexture(Renderer::fowTexUnit); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0,&fowTexCoords[0]); glBindTexture(GL_TEXTURE_2D, textureHandle); glClientActiveTexture(Renderer::baseTexUnit); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, &surfTexCoords[0]); glVertexPointer(3, GL_FLOAT, 0, &vertices[0]); glNormalPointer(GL_FLOAT, 0, &normals[0]); //glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size()); //unsigned short faceIndices[4] = {0, 1, 2, 3}; //glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, &faceIndices[0]); glDrawElements(GL_TRIANGLES,indexCount,GL_UNSIGNED_INT,&indices[0]); glClientActiveTexture(Renderer::fowTexUnit); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTexture(Renderer::baseTexUnit); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } void Renderer::MapRenderer::Layer::render(VisibleQuadContainerCache &qCache) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } // const bool renderOnlyVisibleQuad = true; // // if(renderOnlyVisibleQuad == true) { vector > rowsToRender; if(rowsToRenderCache.find(qCache.lastVisibleQuad) != rowsToRenderCache.end()) { rowsToRender = rowsToRenderCache[qCache.lastVisibleQuad]; } else { int startIndex = -1; int lastValidIndex = -1; for(int visibleIndex = 0; visibleIndex < (int)qCache.visibleScaledCellList.size(); ++visibleIndex) { Vec2i &pos = qCache.visibleScaledCellList[visibleIndex]; if(cellToIndicesMap.find(pos) != cellToIndicesMap.end()) { //printf("Layer Render, visibleindex = %d pos [%s] cellToIndicesMap[pos] = %d lastValidIndex = %d\n",visibleIndex,pos.getString().c_str(),cellToIndicesMap[pos],lastValidIndex); if(startIndex < 0 || cellToIndicesMap[pos] == lastValidIndex + 6) { lastValidIndex = cellToIndicesMap[pos]; if(startIndex < 0) { startIndex = lastValidIndex; } } else if(startIndex >= 0) { rowsToRender.push_back(make_pair(startIndex,lastValidIndex)); lastValidIndex = cellToIndicesMap[pos]; startIndex = lastValidIndex; } } } if(startIndex >= 0) { rowsToRender.push_back(make_pair(startIndex,lastValidIndex)); } rowsToRenderCache[qCache.lastVisibleQuad] = rowsToRender; } if(rowsToRender.empty() == false) { //printf("Layer has %d rows in visible quad, visible quad has %d cells\n",rowsToRender.size(),qCache.visibleScaledCellList.size()); glVertexPointer(3,GL_FLOAT,0,_bindVBO(vbo_vertices,vertices)); glNormalPointer(GL_FLOAT,0,_bindVBO(vbo_normals,normals)); glClientActiveTexture(Renderer::fowTexUnit); glTexCoordPointer(2,GL_FLOAT,0,_bindVBO(vbo_fowTexCoords,fowTexCoords)); glClientActiveTexture(Renderer::baseTexUnit); glBindTexture(GL_TEXTURE_2D,textureHandle); glTexCoordPointer(2,GL_FLOAT,0,_bindVBO(vbo_surfTexCoords,surfTexCoords)); for(unsigned int i = 0; i < rowsToRender.size(); ++i) { //glDrawElements(GL_TRIANGLES,indexCount,GL_UNSIGNED_INT,_bindVBO(vbo_indices,indices,GL_ELEMENT_ARRAY_BUFFER_ARB)); glDrawRangeElements(GL_TRIANGLES,rowsToRender[i].first,rowsToRender[i].second,indexCount,GL_UNSIGNED_INT,_bindVBO(vbo_indices,indices,GL_ELEMENT_ARRAY_BUFFER_ARB)); } } // } // else { // glVertexPointer(3,GL_FLOAT,0,_bindVBO(vbo_vertices,vertices)); // glNormalPointer(GL_FLOAT,0,_bindVBO(vbo_normals,normals)); // // glClientActiveTexture(Renderer::fowTexUnit); // glTexCoordPointer(2,GL_FLOAT,0,_bindVBO(vbo_fowTexCoords,fowTexCoords)); // // glClientActiveTexture(Renderer::baseTexUnit); // glBindTexture(GL_TEXTURE_2D,textureHandle); // glTexCoordPointer(2,GL_FLOAT,0,_bindVBO(vbo_surfTexCoords,surfTexCoords)); // // glDrawElements(GL_TRIANGLES,indexCount,GL_UNSIGNED_INT,_bindVBO(vbo_indices,indices,GL_ELEMENT_ARRAY_BUFFER_ARB)); // } } void Renderer::MapRenderer::renderVisibleLayers(const Map* map,float coordStep,VisibleQuadContainerCache &qCache) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(map != this->map) { //printf("New Map loading\n"); destroy(); // clear any previous map data this->map = map; loadVisibleLayers(coordStep,qCache); } else if(lastVisibleQuad != qCache.lastVisibleQuad) { //printf("New Visible Quad loading\n"); destroy(); // clear any previous map data this->map = map; loadVisibleLayers(coordStep,qCache); } lastVisibleQuad = qCache.lastVisibleQuad; //printf("About to render %d layers\n",layers.size()); glClientActiveTexture(fowTexUnit); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTexture(baseTexUnit); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); for(Layers::iterator layer= layers.begin(); layer!= layers.end(); ++layer) (*layer)->renderVisibleLayer(); glDisableClientState(GL_VERTEX_ARRAY); glBindBuffer(GL_ARRAY_BUFFER_ARB,0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,0); glDisableClientState(GL_NORMAL_ARRAY); glClientActiveTexture(fowTexUnit); glBindTexture(GL_TEXTURE_2D,0); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTexture(baseTexUnit); glBindTexture(GL_TEXTURE_2D,0); glDisableClientState(GL_TEXTURE_COORD_ARRAY); assertGl(); } void Renderer::MapRenderer::render(const Map* map,float coordStep,VisibleQuadContainerCache &qCache) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(map != this->map) { destroy(); // clear any previous map data this->map = map; load(coordStep); } //printf("About to render %d layers\n",layers.size()); glClientActiveTexture(fowTexUnit); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTexture(baseTexUnit); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); for(Layers::iterator layer= layers.begin(); layer!= layers.end(); ++layer) (*layer)->render(qCache); glDisableClientState(GL_VERTEX_ARRAY); glBindBuffer(GL_ARRAY_BUFFER_ARB,0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,0); glDisableClientState(GL_NORMAL_ARRAY); glClientActiveTexture(fowTexUnit); glBindTexture(GL_TEXTURE_2D,0); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTexture(baseTexUnit); glBindTexture(GL_TEXTURE_2D,0); glDisableClientState(GL_TEXTURE_COORD_ARRAY); assertGl(); } void Renderer::MapRenderer::destroy() { while(layers.empty() == false) { delete layers.back(); layers.pop_back(); } map = NULL; } void Renderer::renderSurface(const int renderFps) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } IF_DEBUG_EDITION( if (getDebugRenderer().willRenderSurface()) { getDebugRenderer().renderSurface(visibleQuad / Map::cellScale); } else { ) assertGl(); const World *world= game->getWorld(); const Map *map= world->getMap(); float coordStep= world->getTileset()->getSurfaceAtlas()->getCoordStep(); const Texture2D *fowTex= world->getMinimap()->getFowTexture(); if(fowTex == NULL) { return; } glPushAttrib(GL_LIGHTING_BIT | GL_ENABLE_BIT | GL_FOG_BIT | GL_TEXTURE_BIT); glEnable(GL_BLEND); glEnable(GL_COLOR_MATERIAL); glDisable(GL_ALPHA_TEST); glEnable(GL_CULL_FACE); //fog of war tex unit glActiveTexture(fowTexUnit); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, static_cast(fowTex)->getHandle()); glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, fowTex->getPixmapConst()->getW(), fowTex->getPixmapConst()->getH(), GL_ALPHA, GL_UNSIGNED_BYTE, fowTex->getPixmapConst()->getPixels()); if(shadowsOffDueToMinRender == false) { //shadow texture if(shadows == sProjected || shadows == sShadowMapping) { glActiveTexture(shadowTexUnit); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, shadowMapHandle); static_cast(modelRenderer)->setDuplicateTexCoords(true); enableProjectiveTexturing(); } } const Rect2i mapBounds(0, 0, map->getSurfaceW()-1, map->getSurfaceH()-1); glActiveTexture(baseTexUnit); VisibleQuadContainerCache &qCache = getQuadCache(); bool useVBORendering = getVBOSupported(); if(useVBORendering == true) { VisibleQuadContainerCache &qCache = getQuadCache(); //mapRenderer.render(map,coordStep,qCache); mapRenderer.renderVisibleLayers(map,coordStep,qCache); } else if(qCache.visibleScaledCellList.empty() == false) { int lastTex=-1; //int currTex=-1; //Quad2i snapshotOfvisibleQuad = visibleQuad; //bool useVertexArrayRendering = getVBOSupported(); //bool useVertexArrayRendering = false; //if(useVertexArrayRendering == false) { //printf("\LEGACY qCache.visibleScaledCellList.size() = %d \n",qCache.visibleScaledCellList.size()); Vec2f texCoords[4]; Vec2f texCoordsSurface[4]; Vec3f vertices[4]; Vec3f normals[4]; glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); std::map uniqueVisibleTextures; for(int visibleIndex = 0; visibleIndex < (int)qCache.visibleScaledCellList.size(); ++visibleIndex) { Vec2i &pos = qCache.visibleScaledCellList[visibleIndex]; SurfaceCell *tc00= map->getSurfaceCell(pos.x, pos.y); int cellTex= static_cast(tc00->getSurfaceTexture())->getHandle(); uniqueVisibleTextures[cellTex]++; } //printf("Current renders = %d possible = %d\n",qCache.visibleScaledCellList.size(),uniqueVisibleTextures.size()); for(int visibleIndex = 0; visibleIndex < (int)qCache.visibleScaledCellList.size(); ++visibleIndex) { Vec2i &pos = qCache.visibleScaledCellList[visibleIndex]; SurfaceCell *tc00= map->getSurfaceCell(pos.x, pos.y); SurfaceCell *tc10= map->getSurfaceCell(pos.x+1, pos.y); SurfaceCell *tc01= map->getSurfaceCell(pos.x, pos.y+1); SurfaceCell *tc11= map->getSurfaceCell(pos.x+1, pos.y+1); if(tc00 == NULL) { throw megaglest_runtime_error("tc00 == NULL"); } if(tc10 == NULL) { throw megaglest_runtime_error("tc10 == NULL"); } if(tc01 == NULL) { throw megaglest_runtime_error("tc01 == NULL"); } if(tc11 == NULL) { throw megaglest_runtime_error("tc11 == NULL"); } triangleCount+= 2; pointCount+= 4; //set texture if(tc00->getSurfaceTexture() == NULL) { throw megaglest_runtime_error("tc00->getSurfaceTexture() == NULL"); } int currTex= static_cast(tc00->getSurfaceTexture())->getHandle(); if(currTex != lastTex) { lastTex = currTex; //glBindTexture(GL_TEXTURE_2D, lastTex); } const Vec2f &surfCoord= tc00->getSurfTexCoord(); texCoords[0] = tc01->getFowTexCoord(); texCoordsSurface[0] = Vec2f(surfCoord.x, surfCoord.y + coordStep); vertices[0] = tc01->getVertex(); normals[0] = tc01->getNormal();; texCoords[1] = tc00->getFowTexCoord(); texCoordsSurface[1] = Vec2f(surfCoord.x, surfCoord.y); vertices[1] = tc00->getVertex(); normals[1] = tc00->getNormal(); texCoords[2] = tc11->getFowTexCoord(); texCoordsSurface[2] = Vec2f(surfCoord.x+coordStep, surfCoord.y+coordStep); vertices[2] = tc11->getVertex(); normals[2] = tc11->getNormal(); texCoords[3] = tc10->getFowTexCoord(); texCoordsSurface[3] = Vec2f(surfCoord.x+coordStep, surfCoord.y); vertices[3] = tc10->getVertex(); normals[3] = tc10->getNormal(); //glBindTexture(GL_TEXTURE_2D, static_cast(fowTex)->getHandle()); glClientActiveTexture(fowTexUnit); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0,&texCoords[0]); glBindTexture(GL_TEXTURE_2D, lastTex); glClientActiveTexture(baseTexUnit); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, &texCoordsSurface[0]); glVertexPointer(3, GL_FLOAT, 0, &vertices[0]); glNormalPointer(GL_FLOAT, 0, &normals[0]); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); //unsigned short faceIndices[4] = {0, 1, 2, 3}; //glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, &faceIndices[0]); glClientActiveTexture(fowTexUnit); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTexture(baseTexUnit); glDisableClientState(GL_TEXTURE_COORD_ARRAY); /* glBegin(GL_TRIANGLE_STRIP); //draw quad using immediate mode glMultiTexCoord2fv(fowTexUnit, tc01->getFowTexCoord().ptr()); glMultiTexCoord2f(baseTexUnit, surfCoord.x, surfCoord.y + coordStep); glNormal3fv(tc01->getNormal().ptr()); glVertex3fv(tc01->getVertex().ptr()); glMultiTexCoord2fv(fowTexUnit, tc00->getFowTexCoord().ptr()); glMultiTexCoord2f(baseTexUnit, surfCoord.x, surfCoord.y); glNormal3fv(tc00->getNormal().ptr()); glVertex3fv(tc00->getVertex().ptr()); glMultiTexCoord2fv(fowTexUnit, tc11->getFowTexCoord().ptr()); glMultiTexCoord2f(baseTexUnit, surfCoord.x+coordStep, surfCoord.y+coordStep); glNormal3fv(tc11->getNormal().ptr()); glVertex3fv(tc11->getVertex().ptr()); glMultiTexCoord2fv(fowTexUnit, tc10->getFowTexCoord().ptr()); glMultiTexCoord2f(baseTexUnit, surfCoord.x + coordStep, surfCoord.y); glNormal3fv(tc10->getNormal().ptr()); glVertex3fv(tc10->getVertex().ptr()); glEnd(); */ } glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); // } // else { // const bool useVBOs = false; // const bool useSurfaceCache = false; // // std::vector surfaceData; // bool recalcSurface = false; // // if(useSurfaceCache == true) { // std::map > >::iterator iterFind = mapSurfaceData.find(snapshotOfvisibleQuad.getString()); // if(iterFind == mapSurfaceData.end()) { // recalcSurface = true; // //printf("#1 Calculating surface for Rendering using VA's [%s]\n",snapshotOfvisibleQuad.getString().c_str()); // } ///* // else if(iterFind->second.first.getMillis() >= 250) { // recalcSurface = true; // mapSurfaceData.erase(snapshotOfvisibleQuad.getString()); // //printf("#2 RE-Calculating surface for Rendering using VA's [%s]\n",snapshotOfvisibleQuad.getString().c_str()); // } //*/ // } // else { // recalcSurface = true; // } // // if(recalcSurface == true) { // //printf("Calculating surface for Rendering using VA's [%s]\n",snapshotOfvisibleQuad.getString().c_str()); // // std::vector *surface = &surfaceData; // if(useSurfaceCache == true) { // std::pair > &surfaceCacheEntity = mapSurfaceData[snapshotOfvisibleQuad.getString()]; // surface = &surfaceCacheEntity.second; // //surface.reserve(qCache.visibleScaledCellList.size()); // } // surface->reserve(qCache.visibleScaledCellList.size()); // // int lastSurfaceDataIndex = -1; // for(int visibleIndex = 0; // visibleIndex < (int)qCache.visibleScaledCellList.size(); ++visibleIndex) { // Vec2i &pos = qCache.visibleScaledCellList[visibleIndex]; // // SurfaceCell *tc00= map->getSurfaceCell(pos.x, pos.y); // SurfaceCell *tc10= map->getSurfaceCell(pos.x+1, pos.y); // SurfaceCell *tc01= map->getSurfaceCell(pos.x, pos.y+1); // SurfaceCell *tc11= map->getSurfaceCell(pos.x+1, pos.y+1); // // if(tc00 == NULL) { // throw megaglest_runtime_error("tc00 == NULL"); // } // if(tc10 == NULL) { // throw megaglest_runtime_error("tc10 == NULL"); // } // if(tc01 == NULL) { // throw megaglest_runtime_error("tc01 == NULL"); // } // if(tc11 == NULL) { // throw megaglest_runtime_error("tc11 == NULL"); // } // // triangleCount+= 2; // pointCount+= 4; // // //set texture // if(tc00->getSurfaceTexture() == NULL) { // throw megaglest_runtime_error("tc00->getSurfaceTexture() == NULL"); // } // // int surfaceDataIndex = -1; // currTex= static_cast(tc00->getSurfaceTexture())->getHandle(); // if(currTex != lastTex) { // lastTex = currTex; // } // else { // surfaceDataIndex = lastSurfaceDataIndex; // } // // if(surfaceDataIndex < 0) { // SurfaceData newData; // newData.uniqueId = SurfaceData::nextUniqueId; // SurfaceData::nextUniqueId++; // newData.bufferCount=0; // newData.textureHandle = currTex; // surface->push_back(newData); // // surfaceDataIndex = (int)surface->size() - 1; // } // // lastSurfaceDataIndex = surfaceDataIndex; // // SurfaceData *cellData = &(*surface)[surfaceDataIndex]; // // const Vec2f &surfCoord= tc00->getSurfTexCoord(); // // cellData->texCoords.push_back(tc01->getFowTexCoord()); // cellData->texCoordsSurface.push_back(Vec2f(surfCoord.x, surfCoord.y + coordStep)); // cellData->vertices.push_back(tc01->getVertex()); // cellData->normals.push_back(tc01->getNormal()); // cellData->bufferCount++; // // cellData->texCoords.push_back(tc00->getFowTexCoord()); // cellData->texCoordsSurface.push_back(Vec2f(surfCoord.x, surfCoord.y)); // cellData->vertices.push_back(tc00->getVertex()); // cellData->normals.push_back(tc00->getNormal()); // cellData->bufferCount++; // // cellData->texCoords.push_back(tc11->getFowTexCoord()); // cellData->texCoordsSurface.push_back(Vec2f(surfCoord.x+coordStep, surfCoord.y+coordStep)); // cellData->vertices.push_back(tc11->getVertex()); // cellData->normals.push_back(tc11->getNormal()); // cellData->bufferCount++; // // cellData->texCoords.push_back(tc10->getFowTexCoord()); // cellData->texCoordsSurface.push_back(Vec2f(surfCoord.x+coordStep, surfCoord.y)); // cellData->vertices.push_back(tc10->getVertex()); // cellData->normals.push_back(tc10->getNormal()); // cellData->bufferCount++; // } // } // // std::vector *surface = &surfaceData; // if(useSurfaceCache == true) { // std::pair > &surfaceCacheEntity = mapSurfaceData[snapshotOfvisibleQuad.getString()]; // surface = &surfaceCacheEntity.second; // } // // glEnableClientState(GL_VERTEX_ARRAY); // glEnableClientState(GL_NORMAL_ARRAY); // // for(int i = 0; i < (int)surface->size(); ++i) { // SurfaceData &data = (*surface)[i]; // // if(useVBOs == true) { // VisibleQuadContainerVBOCache *vboCache = GetSurfaceVBOs(&data); // // //glBindTexture(GL_TEXTURE_2D, static_cast(fowTex)->getHandle()); // glClientActiveTexture(fowTexUnit); // glEnableClientState(GL_TEXTURE_COORD_ARRAY); // // glBindBufferARB( GL_ARRAY_BUFFER_ARB, vboCache->m_nVBOFowTexCoords); // glTexCoordPointer(2, GL_FLOAT, 0,(char *) NULL); // // glBindTexture(GL_TEXTURE_2D, data.textureHandle); // glClientActiveTexture(baseTexUnit); // glEnableClientState(GL_TEXTURE_COORD_ARRAY); // // glBindBufferARB( GL_ARRAY_BUFFER_ARB, vboCache->m_nVBOSurfaceTexCoords); // glTexCoordPointer(2, GL_FLOAT, 0, (char *) NULL); // // glBindBufferARB( GL_ARRAY_BUFFER_ARB, vboCache->m_nVBOVertices); // glVertexPointer(3, GL_FLOAT, 0, (char *) NULL); // // glBindBufferARB( GL_ARRAY_BUFFER_ARB, vboCache->m_nVBONormals); // glNormalPointer(GL_FLOAT, 0, (char *) NULL); // // glDrawArrays(GL_TRIANGLE_STRIP, 0, data.bufferCount); // // glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); // // glClientActiveTexture(fowTexUnit); // glDisableClientState(GL_TEXTURE_COORD_ARRAY); // glClientActiveTexture(baseTexUnit); // glDisableClientState(GL_TEXTURE_COORD_ARRAY); // // } // else { // Vec2f *texCoords = &data.texCoords[0]; // Vec2f *texCoordsSurface = &data.texCoordsSurface[0]; // Vec3f *vertices = &data.vertices[0]; // Vec3f *normals = &data.normals[0]; // // //glBindTexture(GL_TEXTURE_2D, static_cast(fowTex)->getHandle()); // glClientActiveTexture(fowTexUnit); // glEnableClientState(GL_TEXTURE_COORD_ARRAY); // glTexCoordPointer(2, GL_FLOAT, 0,texCoords); // // glBindTexture(GL_TEXTURE_2D, data.textureHandle); // glClientActiveTexture(baseTexUnit); // glEnableClientState(GL_TEXTURE_COORD_ARRAY); // glTexCoordPointer(2, GL_FLOAT, 0, texCoordsSurface); // // glVertexPointer(3, GL_FLOAT, 0, vertices); // glNormalPointer(GL_FLOAT, 0, normals); // // glDrawArrays(GL_TRIANGLE_STRIP, 0, data.bufferCount); // // glClientActiveTexture(fowTexUnit); // glDisableClientState(GL_TEXTURE_COORD_ARRAY); // glClientActiveTexture(baseTexUnit); // glDisableClientState(GL_TEXTURE_COORD_ARRAY); // } // } // // glDisableClientState(GL_NORMAL_ARRAY); // glDisableClientState(GL_VERTEX_ARRAY); // // //printf("Surface Render before [%d] after [%d]\n",qCache.visibleScaledCellList.size(),surface.size()); // } } //Restore static_cast(modelRenderer)->setDuplicateTexCoords(false); glDisable(GL_TEXTURE_2D); glPopAttrib(); //assert GLenum glresult = glGetError(); //remove when first mtex problem solved if(glresult) { assertGl(); } assertGl(); IF_DEBUG_EDITION( } // end else, if not renderering debug textures instead of regular terrain getDebugRenderer().renderEffects(visibleQuad / Map::cellScale); ) } void Renderer::renderObjects(const int renderFps) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } const World *world= game->getWorld(); //const Map *map= world->getMap(); Config &config= Config::getInstance(); int tilesetObjectsToAnimate=config.getInt("AnimatedTilesetObjects","-1"); assertGl(); const Texture2D *fowTex = world->getMinimap()->getFowTexture(); const Pixmap2D *fowTexPixmap = fowTex->getPixmapConst(); Vec3f baseFogColor = world->getTileset()->getFogColor() * world->getTimeFlow()->computeLightColor(); bool modelRenderStarted = false; VisibleQuadContainerCache &qCache = getQuadCache(); // for(int visibleIndex = 0; // visibleIndex < qCache.visibleObjectList.size(); ++visibleIndex) { // render from last to first object so animated objects which are on bottom of screen are // rendered first which looks better for limited number of animated tileset objects for(int visibleIndex = (int)qCache.visibleObjectList.size()-1; visibleIndex >= 0 ; --visibleIndex) { Object *o = qCache.visibleObjectList[visibleIndex]; Model *objModel= o->getModelPtr(); //objModel->updateInterpolationData(o->getAnimProgress(), true); const Vec3f v= o->getConstPos(); if(modelRenderStarted == false) { modelRenderStarted = true; glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_FOG_BIT | GL_LIGHTING_BIT | GL_TEXTURE_BIT); if(shadowsOffDueToMinRender == false && shadows == sShadowMapping) { glActiveTexture(shadowTexUnit); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, shadowMapHandle); static_cast(modelRenderer)->setDuplicateTexCoords(true); enableProjectiveTexturing(); } glActiveTexture(baseTexUnit); glEnable(GL_COLOR_MATERIAL); glAlphaFunc(GL_GREATER, 0.5f); modelRenderer->begin(true, true, false, false); } //ambient and diffuse color is taken from cell color float fowFactor= fowTexPixmap->getPixelf(o->getMapPos().x / Map::cellScale, o->getMapPos().y / Map::cellScale); Vec4f color= Vec4f(Vec3f(fowFactor), 1.f); glColor4fv(color.ptr()); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (color * ambFactor).ptr()); glFogfv(GL_FOG_COLOR, (baseFogColor * fowFactor).ptr()); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(v.x, v.y, v.z); glRotatef(o->getRotation(), 0.f, 1.f, 0.f); //We use OpenGL Lights so no manual action is needed here. In fact this call did bad things on lighting big rocks for example // if(o->getRotation() != 0.0) { // setupLightingForRotatedModel(); // } //objModel->updateInterpolationData(0.f, true); //if(this->gameCamera->getPos().dist(o->getPos()) <= SKIP_INTERPOLATION_DISTANCE) { if (tilesetObjectsToAnimate == -1) { objModel->updateInterpolationData(o->getAnimProgress(), true); } else if (tilesetObjectsToAnimate > 0 && o->isAnimated()) { tilesetObjectsToAnimate--; objModel->updateInterpolationData(o->getAnimProgress(), true); } else { objModel->updateInterpolationData(0, true); } // objModel->updateInterpolationData(o->getAnimProgress(), true); //} modelRenderer->render(objModel); triangleCount+= objModel->getTriangleCount(); pointCount+= objModel->getVertexCount(); glPopMatrix(); } if(modelRenderStarted == true) { modelRenderer->end(); glPopAttrib(); } //restore static_cast(modelRenderer)->setDuplicateTexCoords(true); assertGl(); } void Renderer::renderWater() { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } const World *world= game->getWorld(); const Map *map= world->getMap(); const Texture2D *fowTex= world->getMinimap()->getFowTexture(); if(fowTex == NULL) { return; } float waterAnim= world->getWaterEffects()->getAmin(); //assert assertGl(); glPushAttrib(GL_TEXTURE_BIT | GL_ENABLE_BIT | GL_CURRENT_BIT); //water texture nit glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); if(textures3D) { Texture3D *waterTex= world->getTileset()->getWaterTex(); if(waterTex == NULL) { throw megaglest_runtime_error("waterTex == NULL"); } glEnable(GL_TEXTURE_3D); glBindTexture(GL_TEXTURE_3D, static_cast(waterTex)->getHandle()); } else{ glEnable(GL_COLOR_MATERIAL); glColor4f(0.5f, 0.5f, 1.0f, 0.5f); glBindTexture(GL_TEXTURE_3D, 0); } assertGl(); //fog of War texture Unit //const Texture2D *fowTex= world->getMinimap()->getFowTexture(); glActiveTexture(fowTexUnit); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, static_cast(fowTex)->getHandle()); glActiveTexture(baseTexUnit); assertGl(); int thisTeamIndex= world->getThisTeamIndex(); bool cellExplored = world->showWorldForPlayer(world->getThisFactionIndex()); bool closed= false; Rect2i boundingRect= visibleQuad.computeBoundingRect(); Rect2i scaledRect= boundingRect/Map::cellScale; scaledRect.clamp(0, 0, map->getSurfaceW()-1, map->getSurfaceH()-1); float waterLevel= world->getMap()->getWaterLevel(); for(int j=scaledRect.p[0].y; jgetSurfaceCell(i, j); SurfaceCell *tc1= map->getSurfaceCell(i, j+1); if(tc0 == NULL) { throw megaglest_runtime_error("tc0 == NULL"); } if(tc1 == NULL) { throw megaglest_runtime_error("tc1 == NULL"); } if(cellExplored == false) { cellExplored = (tc0->isExplored(thisTeamIndex) || tc1->isExplored(thisTeamIndex)); } if(cellExplored == true && tc0->getNearSubmerged()) { glNormal3f(0.f, 1.f, 0.f); closed= false; triangleCount+= 2; pointCount+= 2; //vertex 1 glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, computeWaterColor(waterLevel, tc1->getHeight()).ptr()); glMultiTexCoord2fv(GL_TEXTURE1, tc1->getFowTexCoord().ptr()); glTexCoord3f(i, 1.f, waterAnim); glVertex3f( static_cast(i)*Map::mapScale, waterLevel, static_cast(j+1)*Map::mapScale); //vertex 2 glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, computeWaterColor(waterLevel, tc0->getHeight()).ptr()); glMultiTexCoord2fv(GL_TEXTURE1, tc0->getFowTexCoord().ptr()); glTexCoord3f(i, 0.f, waterAnim); glVertex3f( static_cast(i)*Map::mapScale, waterLevel, static_cast(j)*Map::mapScale); } else{ if(closed == false) { pointCount+= 2; //vertex 1 glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, computeWaterColor(waterLevel, tc1->getHeight()).ptr()); glMultiTexCoord2fv(GL_TEXTURE1, tc1->getFowTexCoord().ptr()); glTexCoord3f(i, 1.f, waterAnim); glVertex3f( static_cast(i)*Map::mapScale, waterLevel, static_cast(j+1)*Map::mapScale); //vertex 2 glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, computeWaterColor(waterLevel, tc0->getHeight()).ptr()); glMultiTexCoord2fv(GL_TEXTURE1, tc0->getFowTexCoord().ptr()); glTexCoord3f(i, 0.f, waterAnim); glVertex3f( static_cast(i)*Map::mapScale, waterLevel, static_cast(j)*Map::mapScale); glEnd(); glBegin(GL_TRIANGLE_STRIP); closed= true; } } } glEnd(); } //restore glPopAttrib(); assertGl(); } void Renderer::renderTeamColorCircle(){ if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } VisibleQuadContainerCache &qCache = getQuadCache(); if(qCache.visibleQuadUnitList.empty() == false) { glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glDepthFunc(GL_ALWAYS); glDisable(GL_STENCIL_TEST); glDisable(GL_CULL_FACE); glEnable(GL_BLEND); glLineWidth(2.f); for(int visibleUnitIndex = 0; visibleUnitIndex < (int)qCache.visibleQuadUnitList.size(); ++visibleUnitIndex) { Unit *unit = qCache.visibleQuadUnitList[visibleUnitIndex]; Vec3f currVec= unit->getCurrVectorFlat(); Vec3f color=unit->getFaction()->getTexture()->getPixmapConst()->getPixel3f(0,0); glColor4f(color.x, color.y, color.z, 0.7f); renderSelectionCircle(currVec, unit->getType()->getSize(), 0.8f, 0.05f); } glPopAttrib(); } } void Renderer::renderSpecialHighlightUnits(std::map unitHighlightList) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true || unitHighlightList.empty() == true) { return; } VisibleQuadContainerCache &qCache = getQuadCache(); if(qCache.visibleQuadUnitList.empty() == false) { glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glDepthFunc(GL_ALWAYS); glDisable(GL_STENCIL_TEST); glDisable(GL_CULL_FACE); glEnable(GL_BLEND); glLineWidth(2.f); for(int visibleUnitIndex = 0; visibleUnitIndex < (int)qCache.visibleQuadUnitList.size(); ++visibleUnitIndex) { Unit *unit = qCache.visibleQuadUnitList[visibleUnitIndex]; std::map::iterator iterFindSpecialUnit = unitHighlightList.find(unit->getId()); if(iterFindSpecialUnit != unitHighlightList.end()) { Vec3f color=unit->getFaction()->getTexture()->getPixmapConst()->getPixel3f(0,0); float radius = 1.0f; float thickness = 0.1f; float alpha = 0.65f; HighlightSpecialUnitInfo &specialInfo = iterFindSpecialUnit->second; if(specialInfo.color.x >= 0) { color.x = specialInfo.color.x; color.y = specialInfo.color.y; color.z = specialInfo.color.z; } if(specialInfo.color.w >= 0) { alpha = specialInfo.color.w; } if(specialInfo.radius > 0) { radius = specialInfo.radius; } if(specialInfo.thickness > 0) { thickness = specialInfo.thickness; } glColor4f(color.x, color.y, color.z, alpha); Vec3f currVec= unit->getCurrVectorFlat(); renderSelectionCircle(currVec, unit->getType()->getSize(), radius, thickness); } } glPopAttrib(); } } void Renderer::renderTeamColorPlane(){ if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } VisibleQuadContainerCache &qCache = getQuadCache(); if(qCache.visibleQuadUnitList.empty() == false){ glPushAttrib(GL_ENABLE_BIT); glDisable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glEnable(GL_COLOR_MATERIAL); const Texture2D *texture=CoreData::getInstance().getTeamColorTexture(); for(int visibleUnitIndex = 0; visibleUnitIndex < (int)qCache.visibleQuadUnitList.size(); ++visibleUnitIndex){ Unit *unit = qCache.visibleQuadUnitList[visibleUnitIndex]; if( unit->isAlive()){ Vec3f currVec= unit->getCurrVectorFlat(); renderTeamColorEffect(currVec,visibleUnitIndex,unit->getType()->getSize(), unit->getFaction()->getTexture()->getPixmapConst()->getPixel3f(0,0),texture); } } glDisable(GL_COLOR_MATERIAL); glPopAttrib(); } } void Renderer::renderGhostModel(const UnitType *building, const Vec2i pos,CardinalDir facing, Vec4f *forceColor) { //const UnitType *building= gui->getBuilding(); //const Vec2i &pos= gui->getPosObjWorld(); //const Gui *gui= game->getGui(); //const Mouse3d *mouse3d= gui->getMouse3d(); const Map *map= game->getWorld()->getMap(); if(map == NULL) { char szBuf[8096]=""; snprintf(szBuf,8096,"In [%s::%s] Line: %d map == NULL",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); throw megaglest_runtime_error(szBuf); } glPushMatrix(); Vec3f pos3f= Vec3f(pos.x, map->getCell(pos)->getHeight(), pos.y); //selection building placement float offset= building->getSize()/2.f-0.5f; glTranslatef(pos3f.x+offset, pos3f.y, pos3f.z+offset); //choose color Vec4f color; if(forceColor != NULL) { color = *forceColor; } else { if(map->isFreeCells(pos, building->getSize(), fLand)) { color= Vec4f(1.f, 1.f, 1.f, 0.5f); } else { // Uint64 tc=game->getTickCount(); // float red=0.49f+((tc%4*1.0f)/2); color= Vec4f(1.0f, 0.f, 0.f, 0.5f); } } glColor4fv(color.ptr()); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color.ptr()); Model *buildingModel= building->getFirstStOfClass(scStop)->getAnimation(); if(facing != CardinalDir::NORTH) { float rotateAmount = facing * 90.f; if(rotateAmount > 0) { glRotatef(rotateAmount, 0.f, 1.f, 0.f); } } buildingModel->updateInterpolationData(0.f, false); modelRenderer->render(buildingModel); glPopMatrix(); } void Renderer::renderUnits(bool airUnits, const int renderFps) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } //Unit *unit=NULL; //const World *world= game->getWorld(); MeshCallbackTeamColor meshCallbackTeamColor; //assert assertGl(); if(visibleFrameUnitList.empty() == false) { visibleFrameUnitList.clear(); //visibleFrameUnitListCameraKey = ""; //if(visibleFrameUnitListCameraKey != game->getGameCamera()->getCameraMovementKey()) { // worldToScreenPosCache.clear(); //} } VisibleQuadContainerCache &qCache = getQuadCache(); if(qCache.visibleQuadUnitList.empty() == false) { bool modelRenderStarted = false; for(int visibleUnitIndex = 0; visibleUnitIndex < (int)qCache.visibleQuadUnitList.size(); ++visibleUnitIndex) { Unit *unit = qCache.visibleQuadUnitList[visibleUnitIndex]; if(( airUnits==false && unit->getType()->getField()==fAir) || ( airUnits==true && unit->getType()->getField()!=fAir)){ continue; } meshCallbackTeamColor.setTeamTexture(unit->getFaction()->getTexture()); if(modelRenderStarted == false) { modelRenderStarted = true; glPushAttrib(GL_ENABLE_BIT | GL_FOG_BIT | GL_LIGHTING_BIT | GL_TEXTURE_BIT); glEnable(GL_COLOR_MATERIAL); if(!shadowsOffDueToMinRender) { if(shadows == sShadowMapping) { glActiveTexture(shadowTexUnit); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, shadowMapHandle); static_cast(modelRenderer)->setDuplicateTexCoords(true); enableProjectiveTexturing(); } } glActiveTexture(baseTexUnit); modelRenderer->begin(true, true, true, false, &meshCallbackTeamColor); } glMatrixMode(GL_MODELVIEW); glPushMatrix(); //translate Vec3f currVec= unit->getCurrVectorFlat(); glTranslatef(currVec.x, currVec.y, currVec.z); //rotate float zrot=unit->getRotationZ(); float xrot=unit->getRotationX(); if(zrot!=.0f){ glRotatef(zrot, 0.f, 0.f, 1.f); } if(xrot!=.0f){ glRotatef(xrot, 1.f, 0.f, 0.f); } glRotatef(unit->getRotation(), 0.f, 1.f, 0.f); //dead alpha const SkillType *st= unit->getCurrSkill(); if(st->getClass() == scDie && static_cast(st)->getFade()) { float alpha= 1.0f - unit->getAnimProgressAsFloat(); glDisable(GL_COLOR_MATERIAL); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Vec4f(1.0f, 1.0f, 1.0f, alpha).ptr()); } else { glEnable(GL_COLOR_MATERIAL); // we cut off a tiny bit here to avoid problems with fully transparent texture parts cutting units in background rendered later. glAlphaFunc(GL_GREATER, 0.02f); } //render Model *model= unit->getCurrentModelPtr(); //printf("Rendering model [%d - %s]\n[%s]\nCamera [%s]\nDistance: %f\n",unit->getId(),unit->getType()->getName().c_str(),unit->getCurrVector().getString().c_str(),this->gameCamera->getPos().getString().c_str(),this->gameCamera->getPos().dist(unit->getCurrVector())); //if(this->gameCamera->getPos().dist(unit->getCurrVector()) <= SKIP_INTERPOLATION_DISTANCE) { model->updateInterpolationData(unit->getAnimProgressAsFloat(), unit->isAlive() && !unit->isAnimProgressBound()); //} modelRenderer->render(model); triangleCount+= model->getTriangleCount(); pointCount+= model->getVertexCount(); glPopMatrix(); unit->setVisible(true); if( showDebugUI == true && (showDebugUILevel & debugui_unit_titles) == debugui_unit_titles) { unit->setScreenPos(computeScreenPosition(currVec)); visibleFrameUnitList.push_back(unit); visibleFrameUnitListCameraKey = game->getGameCamera()->getCameraMovementKey(); } } if(modelRenderStarted == true) { modelRenderer->end(); glPopAttrib(); } } //restore static_cast(modelRenderer)->setDuplicateTexCoords(true); // reset alpha glAlphaFunc(GL_GREATER, 0.0f); //assert assertGl(); } void Renderer::renderUnitsToBuild(const int renderFps) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } //assert assertGl(); VisibleQuadContainerCache &qCache = getQuadCache(); if(qCache.visibleQuadUnitBuildList.empty() == false) { glMatrixMode(GL_MODELVIEW); glPushAttrib(GL_CURRENT_BIT | GL_LIGHTING_BIT | GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_BLEND); glDisable(GL_STENCIL_TEST); glDepthFunc(GL_LESS); glEnable(GL_COLOR_MATERIAL); glDepthMask(GL_FALSE); modelRenderer->begin(true, true, false, false); for(int visibleUnitIndex = 0; visibleUnitIndex < (int)qCache.visibleQuadUnitBuildList.size(); ++visibleUnitIndex) { const UnitBuildInfo &buildUnit = qCache.visibleQuadUnitBuildList[visibleUnitIndex]; //Vec4f modelColor= Vec4f(0.f, 1.f, 0.f, 0.5f); const Vec3f teamColor = buildUnit.unit->getFaction()->getTexture()->getPixmapConst()->getPixel3f(0,0); Vec4f modelColor= Vec4f(teamColor.x,teamColor.y,teamColor.z,0.4f); renderGhostModel(buildUnit.buildUnit, buildUnit.pos, buildUnit.facing, &modelColor); //printf("Rendering to build unit index = %d\n",visibleUnitIndex); } modelRenderer->end(); glDisable(GL_COLOR_MATERIAL); glPopAttrib(); } //assert assertGl(); } void Renderer::renderTeamColorEffect(Vec3f &v, int heigth, int size, Vec3f color, const Texture2D *texture) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } //GLUquadricObj *disc; float halfSize=size; //halfSize=halfSize; float heigthoffset=0.5+heigth%25*0.004; glPushMatrix(); glBindTexture(GL_TEXTURE_2D, static_cast(texture)->getHandle()); glColor4f(color.x, color.y, color.z, 1.0f); glBegin(GL_TRIANGLE_STRIP); glTexCoord2i(0, 1); glVertex3f(v.x-halfSize,v.y+heigthoffset,v.z+halfSize); glTexCoord2i(0, 0); glVertex3f(v.x-halfSize,v.y+heigthoffset, v.z-halfSize); glTexCoord2i(1, 1); glVertex3f(v.x+halfSize,v.y+heigthoffset, v.z+halfSize); glTexCoord2i(1, 0); glVertex3f(v.x+halfSize,v.y+heigthoffset, v.z-halfSize); glEnd(); glPopMatrix(); } void Renderer::renderMorphEffects(){ if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } VisibleQuadContainerCache &qCache = getQuadCache(); if(qCache.visibleQuadUnitList.empty() == false) { bool initialized=false; int frameCycle=0; for(int visibleUnitIndex = 0; visibleUnitIndex < (int)qCache.visibleQuadUnitList.size(); ++visibleUnitIndex) { Unit *unit = qCache.visibleQuadUnitList[visibleUnitIndex]; if(unit->getCurrSkill() != NULL && unit->getCurrSkill()->getClass() == scMorph) { Command *command= unit->getCurrCommand(); if(command != NULL && command->getCommandType()->commandTypeClass == ccMorph){ const MorphCommandType *mct= static_cast(command->getCommandType()); const UnitType* mType=mct->getMorphUnit(); if(mType->getSize()>unit->getType()->getSize() || mType->getField()!=unit->getType()->getField()){ if(!initialized){ const World *world= game->getWorld(); frameCycle=world->getFrameCount() % 40; glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glDepthFunc(GL_ALWAYS); glDisable(GL_STENCIL_TEST); glDisable(GL_CULL_FACE); glEnable(GL_BLEND); glLineWidth(2.f); initialized=true; } Vec3f currVec= unit->getCurrVectorFlat(); currVec=Vec3f(currVec.x,currVec.y+0.3f,currVec.z); if(mType->getField() == fAir && unit->getType()->getField()== fLand) { currVec=Vec3f(currVec.x,currVec.y+game->getWorld()->getTileset()->getAirHeight(),currVec.z); } if(mType->getField() == fLand && unit->getType()->getField()== fAir) { currVec=Vec3f(currVec.x,currVec.y-game->getWorld()->getTileset()->getAirHeight(),currVec.z); } float color=frameCycle*0.4f/40; glColor4f(color,color, 0.4f, 0.4f); renderSelectionCircle(currVec, mType->getSize(), frameCycle*0.85f/40, 0.2f); } } } } if(initialized) { glPopAttrib(); } } } void Renderer::renderSelectionEffects(int healthbarMode) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } Config &config= Config::getInstance(); if(config.getBool("RecordMode","false") == true) { return; } const World *world= game->getWorld(); const Map *map= world->getMap(); const Selection *selection= game->getGui()->getSelection(); const Object *selectedResourceObject= game->getGui()->getSelectedResourceObject(); glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glDepthFunc(GL_ALWAYS); glDisable(GL_STENCIL_TEST); glDisable(GL_CULL_FACE); glEnable(GL_BLEND); glLineWidth(2.f); //units for(int i=0; igetCount(); ++i){ const Unit *unit= selection->getUnit(i); if(unit != NULL) { //translate Vec3f currVec= unit->getCurrVectorFlat(); currVec.y+= 0.3f; //selection circle int finalHealthbarMode = hbvUndefined; if(healthbarMode == hbvUndefined) { finalHealthbarMode = unit->getFaction()->getType()->getHealthbarVisible(); } else { finalHealthbarMode = healthbarMode; } bool healthbarsVisible =((finalHealthbarMode & hbvAlways) || (finalHealthbarMode & hbvSelected) || (finalHealthbarMode & hbvIfNeeded)); float selectionCircleThickness = 0.2f; float hpRatio = unit->getHpRatio(); if(healthbarsVisible) { selectionCircleThickness = 0.05f; hpRatio = 1.0f; } if(world->getThisFactionIndex() == unit->getFactionIndex()) { if( showDebugUI == true && ((showDebugUILevel & debugui_unit_titles) == debugui_unit_titles) && unit->getCommandSize() > 0 && dynamic_cast(unit->getCurrCommand()->getCommandType()) != NULL) { glColor4f(hpRatio, hpRatio, hpRatio, 0.3f); } else { glColor4f(0, hpRatio, 0, 0.3f); } } else if ( world->getThisTeamIndex() == unit->getTeam()) { glColor4f(hpRatio, hpRatio, 0, 0.3f); } else { glColor4f(hpRatio, 0, 0, 0.3f); } renderSelectionCircle(currVec, unit->getType()->getSize(), selectionCircleRadius,selectionCircleThickness); if( showDebugUI == true && (showDebugUILevel & debugui_unit_titles) == debugui_unit_titles) { const UnitPathInterface *path= unit->getPath(); const UnitPathBasic *pathfinder = (path == NULL ? NULL : dynamic_cast(path)); if(pathfinder != NULL) { vector pathList = pathfinder->getQueue(); Vec2i lastPosValue; for(int i = 0; i < (int)pathList.size(); ++i) { Vec2i curPosValue = pathList[i]; if(i == 0) { lastPosValue = curPosValue; } Vec3f currVec2 = unit->getVectorFlat(lastPosValue,curPosValue); currVec2.y+= 0.3f; renderSelectionCircle(currVec2, 1, selectionCircleRadius); } } } //magic circle if(!healthbarsVisible && world->getThisFactionIndex() == unit->getFactionIndex() && unit->getType()->getMaxEp() > 0) { glColor4f(unit->getEpRatio()/2.f, unit->getEpRatio(), unit->getEpRatio(), 0.5f); renderSelectionCircle(currVec, unit->getType()->getSize(), magicCircleRadius); } // Render Attack-boost circles if(showDebugUI == true) { //const std::pair > ¤tAttackBoostUnits = unit->getCurrentAttackBoostUnits(); const UnitAttackBoostEffectOriginator &effect = unit->getAttackBoostOriginatorEffect(); if(effect.skillType->isAttackBoostEnabled() == true) { glColor4f(MAGENTA.x,MAGENTA.y,MAGENTA.z,MAGENTA.w); renderSelectionCircle(currVec, 1, effect.skillType->getAttackBoost()->radius, .25f/effect.skillType->getAttackBoost()->radius); for(unsigned int i = 0; i < effect.currentAttackBoostUnits.size(); ++i) { // Remove attack boost upgrades from unit int findUnitId = effect.currentAttackBoostUnits[i]; Unit *affectedUnit = game->getWorld()->findUnitById(findUnitId); if(affectedUnit != NULL) { Vec3f currVecBoost = affectedUnit->getCurrVectorFlat(); currVecBoost.y += 0.3f; renderSelectionCircle(currVecBoost, affectedUnit->getType()->getSize(), 1.f); } } } } //meeting point arrow if(unit->getType()->getMeetingPoint()) { Vec2i pos= unit->getMeetingPos(); map->clampPos(pos); Vec3f arrowTarget= Vec3f(pos.x, map->getCell(pos)->getHeight(), pos.y); renderArrow(unit->getCurrVectorFlat(), arrowTarget, Vec3f(0.f, 0.f, 1.f), 0.3f); } } } if(selectedResourceObject != NULL && selectedResourceObject->getResource() != NULL && selection->getCount() < 1) { Resource *r= selectedResourceObject->getResource(); int defaultValue= r->getType()->getDefResPerPatch(); float colorValue=static_cast(r->getAmount())/static_cast(defaultValue); glColor4f(0.1f, 0.1f , colorValue, 0.4f); renderSelectionCircle(selectedResourceObject->getPos(),2, selectionCircleRadius); } //target arrow if(selection->getCount() == 1) { const Unit *unit= selection->getUnit(0); if(unit != NULL) { //comand arrow if(focusArrows && unit->anyCommand()) { const CommandType *ct= unit->getCurrCommand()->getCommandType(); if(ct->getClicks() != cOne){ //arrow color Vec3f arrowColor; switch(ct->getClass()) { case ccMove: arrowColor= Vec3f(0.f, 1.f, 0.f); break; case ccAttack: case ccAttackStopped: arrowColor= Vec3f(1.f, 0.f, 0.f); break; default: arrowColor= Vec3f(1.f, 1.f, 0.f); break; } //arrow target Vec3f arrowTarget; Command *c= unit->getCurrCommand(); if(c->getUnit() != NULL) { arrowTarget= c->getUnit()->getCurrVectorFlat(); } else { Vec2i pos= c->getPos(); map->clampPos(pos); arrowTarget= Vec3f(pos.x, map->getCell(pos)->getHeight(), pos.y); } renderArrow(unit->getCurrVectorFlat(), arrowTarget, arrowColor, 0.3f); } } } } //render selection hightlights if(game->getGui()->getHighlightedUnit() != NULL) { const Unit *unit=game->getGui()->getHighlightedUnit() ; if(unit->isHighlighted()) { float highlight= unit->getHightlight(); if(game->getWorld()->getThisFactionIndex() == unit->getFactionIndex()) { glColor4f(0.f, 1.f, 0.f, highlight); } else{ glColor4f(1.f, 0.f, 0.f, highlight); } Vec3f v= unit->getCurrVectorFlat(); v.y+= 0.3f; renderSelectionCircle(v, unit->getType()->getSize(), 0.5f+0.4f*highlight ); } } // old inefficient way to render highlights // for(int i=0; i < world->getFactionCount(); ++i) { // for(int j=0; j < world->getFaction(i)->getUnitCount(); ++j) { // const Unit *unit= world->getFaction(i)->getUnit(j); // // if(unit->isHighlighted()) { // float highlight= unit->getHightlight(); // if(game->getWorld()->getThisFactionIndex() == unit->getFactionIndex()) { // glColor4f(0.f, 1.f, 0.f, highlight); // } // else{ // glColor4f(1.f, 0.f, 0.f, highlight); // } // // Vec3f v= unit->getCurrVectorFlat(); // v.y+= 0.3f; // renderSelectionCircle(v, unit->getType()->getSize(), 0.5f+0.4f*highlight ); // } // } // } //render resource selection highlight if(game->getGui()->getHighlightedResourceObject() != NULL) { const Object* object=game->getGui()->getHighlightedResourceObject(); if(object->isHighlighted()) { float highlight= object->getHightlight(); glColor4f(0.1f, 0.1f , 1.0f, highlight); Vec3f v= object->getPos(); v.y+= 0.3f; renderSelectionCircle(v, 2, 0.4f+0.4f*highlight ); } } glPopAttrib(); } void Renderer::renderHealthBars(int healthbarMode){ if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } Config &config= Config::getInstance(); if(config.getBool("RecordMode","false") == true) { return; } if(config.getBool("PhotoMode")) { return; } glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glDepthFunc(GL_ALWAYS); glDisable(GL_STENCIL_TEST); glDisable(GL_CULL_FACE); glEnable(GL_BLEND); glLineWidth(2.f); VisibleQuadContainerCache &qCache = getQuadCache(); if(qCache.visibleQuadUnitList.empty() == false) { for(int visibleUnitIndex = 0; visibleUnitIndex < (int)qCache.visibleQuadUnitList.size(); ++visibleUnitIndex) { Unit *unit = qCache.visibleQuadUnitList[visibleUnitIndex]; if(isHealthBarVisible(unit,healthbarMode)) { float healthbarheight; float healthbarthickness; const Texture2D *healthbarTexture; const Texture2D *healthbarBackgroundTexture; bool healthbarLineBorder; //get settings of the faction healthbarheight=unit->getFaction()->getType()->getHealthbarHeight(); healthbarthickness=unit->getFaction()->getType()->getHealthbarThickness(); healthbarLineBorder=unit->getFaction()->getType()->isHealthbarLineBorder(); CoreData &coreData= CoreData::getInstance(); //First try faction texture then use core Texture if(unit->getFaction()->getType()->isHealthbarBorderTextureEnabled()) { healthbarTexture=unit->getFaction()->getType()->getHealthbarTexture(); if(healthbarTexture==NULL) { healthbarTexture=coreData.getHealthbarTexture(); } } else { healthbarTexture=NULL; } if(unit->getFaction()->getType()->isHealthbarBackgroundTextureEnabled()) { healthbarBackgroundTexture=unit->getFaction()->getType()->getHealthbarBackgroundTexture(); if(healthbarBackgroundTexture==NULL) { healthbarBackgroundTexture=coreData.getHealthbarBackgroundTexture(); } } else { healthbarBackgroundTexture=NULL; } //replace them by the ones from the unit if existent if(unit->getType()->getHealthbarVisible()!=hbvOff && unit->getType()->getHealthbarVisible()!=hbvUndefined) { if(unit->getType()->getHealthbarHeight()!=-100.0f) { healthbarheight=unit->getType()->getHealthbarHeight(); } if(unit->getType()->getHealthbarThickness()!=-1.0f) { healthbarthickness=unit->getType()->getHealthbarThickness(); } } Vec3f currVec= unit->getCurrVectorFlat(); if(healthbarheight==-100.0f) { currVec.y+=unit->getType()->getHeight(); } else { currVec.y+=healthbarheight; } renderHealthBar(currVec,unit,healthbarthickness,healthbarLineBorder,healthbarTexture,healthbarBackgroundTexture); } } } glPopAttrib(); } bool Renderer::isHealthBarVisible(const Unit *unit,int healthbarMode){ int healthbarVisible=hbvUndefined; //check options (hotkey) if(healthbarMode==hbvUndefined) { healthbarVisible=unit->getFaction()->getType()->getHealthbarVisible(); } else { healthbarVisible=healthbarMode; } //replace them by the ones from the unit if existent if(unit->getType()->getHealthbarVisible()!=hbvOff && unit->getType()->getHealthbarVisible()!=hbvUndefined) { if(healthbarMode==hbvUndefined) { //don't override the visible setting when hotkey is not hbvUndefined healthbarVisible=unit->getType()->getHealthbarVisible(); } } bool settingsWantToRenderThem=!(healthbarVisible==hbvUndefined || (healthbarVisible&hbvOff)) && ((healthbarVisible&hbvAlways) || ((healthbarVisible&hbvIfNeeded) && unit->getHp()getType()->getMaxHp()+unit->getTotalUpgrade()->getMaxHp()) || ((healthbarVisible&hbvIfNeeded) && unit->getType()->getMaxEp() > 0 && unit->getEp()getType()->getMaxEp()+unit->getTotalUpgrade()->getMaxEp()) || ((healthbarVisible&hbvIfNeeded) && unit->getProductionPercent() > 0) || ((healthbarVisible&hbvSelected) && game->getGui()->isSelected(unit))); if(unit->isAlive() && (settingsWantToRenderThem)) { return true; } return false; } void Renderer::renderWaterEffects(){ if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } const World *world= game->getWorld(); const WaterEffects *we= world->getWaterEffects(); const Map *map= world->getMap(); CoreData &coreData= CoreData::getInstance(); float height= map->getWaterLevel()+0.001f; assertGl(); glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_BLEND); glDisable(GL_ALPHA_TEST); glDepthMask(GL_FALSE); glDepthFunc(GL_LEQUAL); glEnable(GL_COLOR_MATERIAL); //glNormal3f(0.f, 1.f, 0.f); //splashes glBindTexture(GL_TEXTURE_2D, static_cast(coreData.getWaterSplashTexture())->getHandle()); //!!! Vec2f texCoords[4]; Vec3f vertices[4]; Vec3f normals[4]; glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); for(int i=0; igetWaterSplashCount(); ++i){ const WaterSplash *ws= we->getWaterSplash(i); //render only if enabled if(ws->getEnabled()){ //render only if visible Vec2i intPos= Vec2i(static_cast(ws->getPos().x), static_cast(ws->getPos().y)); const Vec2i &mapPos = Map::toSurfCoords(intPos); bool visible = map->getSurfaceCell(mapPos)->isVisible(world->getThisTeamIndex()); if(visible == false && world->showWorldForPlayer(world->getThisFactionIndex()) == true) { visible = true; } if(visible == true) { float scale= ws->getAnim()*ws->getSize(); texCoords[0] = Vec2f(0.f, 1.f); vertices[0] = Vec3f(ws->getPos().x-scale, height, ws->getPos().y+scale); normals[0] = Vec3f(0.f, 1.f, 0.f); texCoords[1] = Vec2f(0.f, 0.f); vertices[1] = Vec3f(ws->getPos().x-scale, height, ws->getPos().y-scale); normals[1] = Vec3f(0.f, 1.f, 0.f); texCoords[2] = Vec2f(1.f, 1.f); vertices[2] = Vec3f(ws->getPos().x+scale, height, ws->getPos().y+scale); normals[2] = Vec3f(0.f, 1.f, 0.f); texCoords[3] = Vec2f(1.f, 0.f); vertices[3] = Vec3f(ws->getPos().x+scale, height, ws->getPos().y-scale); normals[3] = Vec3f(0.f, 1.f, 0.f); glColor4f(1.f, 1.f, 1.f, 1.f - ws->getAnim()); glTexCoordPointer(2, GL_FLOAT, 0,&texCoords[0]); glVertexPointer(3, GL_FLOAT, 0, &vertices[0]); glNormalPointer(GL_FLOAT, 0, &normals[0]); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); /* glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(0.f, 1.f); glVertex3f(ws->getPos().x-scale, height, ws->getPos().y+scale); glTexCoord2f(0.f, 0.f); glVertex3f(ws->getPos().x-scale, height, ws->getPos().y-scale); glTexCoord2f(1.f, 1.f); glVertex3f(ws->getPos().x+scale, height, ws->getPos().y+scale); glTexCoord2f(1.f, 0.f); glVertex3f(ws->getPos().x+scale, height, ws->getPos().y-scale); glEnd(); */ } } } glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glPopAttrib(); assertGl(); } void Renderer::renderHud(){ if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } Texture2D *hudTexture=game->getGui()->getHudTexture(); if(hudTexture!=NULL){ const Metrics &metrics= Metrics::getInstance(); renderTextureQuad(0, 0, metrics.getVirtualW(), metrics.getVirtualH(),hudTexture,1.0f); } } void Renderer::renderMinimap(){ if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } const World *world= game->getWorld(); const Minimap *minimap= world->getMinimap(); if(minimap == NULL || minimap->getTexture() == NULL) { return; } const GameCamera *gameCamera= game->getGameCamera(); const Pixmap2D *pixmap= minimap->getTexture()->getPixmapConst(); const Metrics &metrics= Metrics::getInstance(); const WaterEffects *attackEffects= world->getAttackEffects(); int mx= metrics.getMinimapX(); int my= metrics.getMinimapY(); int mw= metrics.getMinimapW(); int mh= metrics.getMinimapH(); Vec2f zoom= Vec2f( static_cast(mw)/ pixmap->getW(), static_cast(mh)/ pixmap->getH()); assertGl(); // render minimap border Vec4f col= game->getGui()->getDisplay()->getColor(); glColor4f(col.x*0.5f,col.y*0.5f,col.z*0.5f,1.0 ); int borderWidth=2; glBegin(GL_QUADS); glVertex2i(mx-borderWidth, my-borderWidth); glVertex2i(mx-borderWidth, my); glVertex2i(mx+mw+borderWidth, my); glVertex2i(mx+mw+borderWidth, my-borderWidth); glEnd(); glBegin(GL_QUADS); glVertex2i(mx-borderWidth, my+mh+borderWidth); glVertex2i(mx-borderWidth, my+mh); glVertex2i(mx+mw+borderWidth, my+mh); glVertex2i(mx+mw+borderWidth, my+mh+borderWidth); glEnd(); glBegin(GL_QUADS); glVertex2i(mx-borderWidth, my); glVertex2i(mx-borderWidth, my+mh); glVertex2i(mx, my+mh); glVertex2i(mx, my); glEnd(); glBegin(GL_QUADS); glVertex2i(mx+mw, my); glVertex2i(mx+mw, my+mh); glVertex2i(mx+mw+borderWidth, my+mh); glVertex2i(mx+mw+borderWidth, my); glEnd(); assertGl(); glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_LINE_BIT | GL_TEXTURE_BIT); //draw map glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glActiveTexture(fowTexUnit); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, static_cast(minimap->getFowTexture())->getHandle()); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_ADD); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE); glActiveTexture(baseTexUnit); glBindTexture(GL_TEXTURE_2D, static_cast(minimap->getTexture())->getHandle()); glColor4f(0.5f, 0.5f, 0.5f, 0.2f); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(0.0f, 1.0f); glMultiTexCoord2f(fowTexUnit, 0.0f, 1.0f); glVertex2i(mx, my); glTexCoord2f(0.0f, 0.0f); glMultiTexCoord2f(fowTexUnit, 0.0f, 0.0f); glVertex2i(mx, my+mh); glTexCoord2f(1.0f, 1.0f); glMultiTexCoord2f(fowTexUnit, 1.0f, 1.0f); glVertex2i(mx+mw, my); glTexCoord2f(1.0f, 0.0f); glMultiTexCoord2f(fowTexUnit, 1.0f, 0.0f); glVertex2i(mx+mw, my+mh); glEnd(); glDisable(GL_BLEND); glActiveTexture(fowTexUnit); glDisable(GL_TEXTURE_2D); glActiveTexture(baseTexUnit); glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); const int itemCount = attackEffects->getWaterSplashCount() * 12; if(itemCount > 0) { vector vertices; vertices.resize(itemCount); vector colors; colors.resize(itemCount); // draw attack alarm int vertexIndex = 0; for(int i = 0; i < attackEffects->getWaterSplashCount(); ++i) { const WaterSplash *ws = attackEffects->getWaterSplash(i); float scale= (1/ws->getAnim()*ws->getSize())*5; //glColor4f(1.f, 1.f, 0.f, 1.f-ws->getAnim()); float alpha=(1.f-ws->getAnim())*0.01f; Vec2f pos= ws->getPos()/Map::cellScale; float attackX=mx +pos.x*zoom.x; float attackY=my +mh -pos.y*zoom.y; if(ws->getEnabled()){ // glBegin(GL_QUADS); // glVertex2f(attackX-scale, attackY-scale); // glVertex2f(attackX-scale, attackY+scale); // glVertex2f(attackX+scale, attackY+scale); // glVertex2f(attackX+scale, attackY-scale); // glEnd(); colors[vertexIndex] = Vec4f(1.f, 1.f, 0.f, alpha); vertices[vertexIndex] = Vec2f(attackX-scale, attackY-scale); vertexIndex++; colors[vertexIndex] = Vec4f(1.f, 1.f, 0.f, alpha); vertices[vertexIndex] = Vec2f(attackX-scale, attackY+scale); vertexIndex++; colors[vertexIndex] = Vec4f(1.f, 1.f, 0.f, 0.8f); vertices[vertexIndex] = Vec2f(attackX, attackY); vertexIndex++; colors[vertexIndex] = Vec4f(1.f, 1.f, 0.f, alpha); vertices[vertexIndex] = Vec2f(attackX+scale, attackY+scale); vertexIndex++; colors[vertexIndex] = Vec4f(1.f, 1.f, 0.f, alpha); vertices[vertexIndex] = Vec2f(attackX-scale, attackY+scale); vertexIndex++; colors[vertexIndex] = Vec4f(1.f, 1.f, 0.f, 0.8f); vertices[vertexIndex] = Vec2f(attackX, attackY); vertexIndex++; colors[vertexIndex] = Vec4f(1.f, 1.f, 0.f, alpha); vertices[vertexIndex] = Vec2f(attackX+scale, attackY+scale); vertexIndex++; colors[vertexIndex] = Vec4f(1.f, 1.f, 0.f, alpha); vertices[vertexIndex] = Vec2f(attackX+scale, attackY-scale); vertexIndex++; colors[vertexIndex] = Vec4f(1.f, 1.f, 0.f, 0.8f); vertices[vertexIndex] = Vec2f(attackX, attackY); vertexIndex++; colors[vertexIndex] = Vec4f(1.f, 1.f, 0.f, alpha); vertices[vertexIndex] = Vec2f(attackX+scale, attackY-scale); vertexIndex++; colors[vertexIndex] = Vec4f(1.f, 1.f, 0.f, alpha); vertices[vertexIndex] = Vec2f(attackX-scale, attackY-scale); vertexIndex++; colors[vertexIndex] = Vec4f(1.f, 1.f, 0.f, 0.8f); vertices[vertexIndex] = Vec2f(attackX, attackY); vertexIndex++; /* glBegin(GL_TRIANGLES); glColor4f(1.f, 1.f, 0.f, alpha); glVertex2f(attackX-scale, attackY-scale); glVertex2f(attackX-scale, attackY+scale); glColor4f(1.f, 1.f, 0.f, 0.8f); glVertex2f(attackX, attackY); glEnd(); glBegin(GL_TRIANGLES); glColor4f(1.f, 1.f, 0.f, alpha); glVertex2f(attackX-scale, attackY+scale); glVertex2f(attackX+scale, attackY+scale); glColor4f(1.f, 1.f, 0.f, 0.8f); glVertex2f(attackX, attackY); glEnd(); glBegin(GL_TRIANGLES); glColor4f(1.f, 1.f, 0.f, alpha); glVertex2f(attackX+scale, attackY+scale); glVertex2f(attackX+scale, attackY-scale); glColor4f(1.f, 1.f, 0.f, 0.8f); glVertex2f(attackX, attackY); glEnd(); glBegin(GL_TRIANGLES); glColor4f(1.f, 1.f, 0.f, alpha); glVertex2f(attackX+scale, attackY-scale); glVertex2f(attackX-scale, attackY-scale); glColor4f(1.f, 1.f, 0.f, 0.8f); glVertex2f(attackX, attackY); glEnd(); */ } } if(vertexIndex > 0) { glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); glColorPointer(4,GL_FLOAT, 0, &colors[0]); glVertexPointer(2, GL_FLOAT, 0, &vertices[0]); glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexIndex); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); } } glDisable(GL_BLEND); //draw units VisibleQuadContainerCache &qCache = getQuadCache(); std::vector visibleUnitList = qCache.visibleUnitList; const bool showAllUnitsInMinimap = Config::getInstance().getBool("DebugGameSynchUI","false"); if(showAllUnitsInMinimap == true) { visibleUnitList.clear(); const World *world= game->getWorld(); for(unsigned int i = 0; i < (unsigned int)world->getFactionCount(); ++i) { const Faction *faction = world->getFaction(i); for(unsigned int j = 0; j < (unsigned int)faction->getUnitCount(); ++j) { Unit *unit = faction->getUnit(j); visibleUnitList.push_back(unit); } } } if(visibleUnitList.empty() == false) { uint32 unitIdx=0; vector unit_vertices; unit_vertices.resize(visibleUnitList.size()*4); vector unit_colors; unit_colors.resize(visibleUnitList.size()*4); for(int visibleIndex = 0; visibleIndex < (int)visibleUnitList.size(); ++visibleIndex) { Unit *unit = visibleUnitList[visibleIndex]; if (unit->isAlive() == false) { continue; } Vec2i pos= unit->getPos() / Map::cellScale; int size= unit->getType()->getSize(); Vec3f color= unit->getFaction()->getTexture()->getPixmapConst()->getPixel3f(0, 0); unit_colors[unitIdx] = color; unit_vertices[unitIdx] = Vec2f(mx + pos.x*zoom.x, my + mh - (pos.y*zoom.y)); unitIdx++; unit_colors[unitIdx] = color; unit_vertices[unitIdx] = Vec2f(mx + (pos.x+1)*zoom.x+size, my + mh - (pos.y*zoom.y)); unitIdx++; unit_colors[unitIdx] = color; unit_vertices[unitIdx] = Vec2f(mx + (pos.x+1)*zoom.x+size, my + mh - ((pos.y+size)*zoom.y)); unitIdx++; unit_colors[unitIdx] = color; unit_vertices[unitIdx] = Vec2f(mx + pos.x*zoom.x, my + mh - ((pos.y+size)*zoom.y)); unitIdx++; } if(unitIdx > 0) { glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); glColorPointer(3,GL_FLOAT, 0, &unit_colors[0]); glVertexPointer(2, GL_FLOAT, 0, &unit_vertices[0]); glDrawArrays(GL_QUADS, 0, unitIdx); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); } } renderMarkedCellsOnMinimap(); //draw camera float wRatio= static_cast(metrics.getMinimapW()) / world->getMap()->getW(); float hRatio= static_cast(metrics.getMinimapH()) / world->getMap()->getH(); int x= static_cast(gameCamera->getPos().x * wRatio); int y= static_cast(gameCamera->getPos().z * hRatio); float ang= degToRad(gameCamera->getHAng()); glEnable(GL_BLEND); int x1; int y1; x1 = mx + x + static_cast(20*std::sin(ang-pi/5)); y1 = my + mh - (y-static_cast(20*std::cos(ang-pi/5))); int x2; int y2; x2 = mx + x + static_cast(20*std::sin(ang+pi/5)); y2 = my + mh - (y-static_cast(20*std::cos(ang+pi/5))); glColor4f(1.f, 1.f, 1.f, 1.f); glBegin(GL_TRIANGLES); glVertex2i(mx+x, my+mh-y); glColor4f(1.f, 1.f, 1.f, 0.0f); glVertex2i(x1,y1); glColor4f(1.f, 1.f, 1.f, 0.0f); glVertex2i(x2,y2); glEnd(); glPopAttrib(); assertGl(); } void Renderer::renderHighlightedCellsOnMinimap() { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } // Draw marked cells const std::vector *highlightedCells = game->getHighlightedCells(); if(highlightedCells->empty() == false) { //const Map *map= game->getWorld()->getMap(); const World *world= game->getWorld(); const Minimap *minimap= world->getMinimap(); int pointersize=10; if(minimap == NULL || minimap->getTexture() == NULL) { return; } //const GameCamera *gameCamera= game->getGameCamera(); const Pixmap2D *pixmap= minimap->getTexture()->getPixmapConst(); const Metrics &metrics= Metrics::getInstance(); //int mx= metrics.getMinimapX(); int my= metrics.getMinimapY(); int mw= metrics.getMinimapW(); int mh= metrics.getMinimapH(); Vec2f zoom= Vec2f( static_cast(mw)/ pixmap->getW()/2, static_cast(mh)/ pixmap->getH()/2); for(int i = 0;i < (int)highlightedCells->size(); i++) { const MarkedCell *mc=&highlightedCells->at(i); if(mc->getFaction() == NULL || (mc->getFaction()->getTeam() == game->getWorld()->getThisFaction()->getTeam())) { const Texture2D *texture= game->getHighlightCellTexture(); Vec3f color(MarkedCell::static_system_marker_color); if(mc->getFaction() != NULL) { color= mc->getFaction()->getTexture()->getPixmapConst()->getPixel3f(0, 0); } int lighting=(mc->getAliveCount()%15); Vec3f myColor=Vec3f(color.x/2+.5f/lighting,color.y/2+.5f/lighting,color.z/2+.5f/lighting); Vec2i pos=mc->getTargetPos(); if(texture != NULL) { //float alpha = 0.49f+0.5f/(mc->getAliveCount()%15); float alpha=1.0f; renderTextureQuad((int)(pos.x*zoom.x)+pointersize, my + mh-(int)(pos.y*zoom.y), pointersize, pointersize, texture, alpha,&myColor); } } } } } void Renderer::renderMarkedCellsOnMinimap() { // Draw marked cells std::map markedCells = game->getMapMarkedCellList(); if(markedCells.empty() == false) { //const Map *map= game->getWorld()->getMap(); const World *world= game->getWorld(); const Minimap *minimap= world->getMinimap(); if(minimap == NULL || minimap->getTexture() == NULL) { return; } //const GameCamera *gameCamera= game->getGameCamera(); const Pixmap2D *pixmap= minimap->getTexture()->getPixmapConst(); const Metrics &metrics= Metrics::getInstance(); //const WaterEffects *attackEffects= world->getAttackEffects(); int mx= metrics.getMinimapX(); int my= metrics.getMinimapY(); int mw= metrics.getMinimapW(); int mh= metrics.getMinimapH(); Vec2f zoom= Vec2f( static_cast(mw)/ pixmap->getW(), static_cast(mh)/ pixmap->getH()); uint32 unitIdx=0; vector unit_vertices; unit_vertices.resize(markedCells.size()*4); vector unit_colors; unit_colors.resize(markedCells.size()*4); for(std::map::iterator iterMap =markedCells.begin(); iterMap != markedCells.end(); ++iterMap) { MarkedCell &bm = iterMap->second; if(bm.getPlayerIndex() < 0 || (bm.getFaction() != NULL && bm.getFaction()->getTeam() == game->getWorld()->getThisFaction()->getTeam())) { Vec2i pos= bm.getTargetPos() / Map::cellScale; float size= 0.5f; Vec3f color(MarkedCell::static_system_marker_color); if(bm.getFaction() != NULL) { color= bm.getFaction()->getTexture()->getPixmapConst()->getPixel3f(0, 0); } float alpha = 0.65f; unit_colors[unitIdx] = Vec4f(color.x,color.y,color.z,alpha); unit_vertices[unitIdx] = Vec2f(mx + pos.x*zoom.x, my + mh - (pos.y*zoom.y)); unitIdx++; unit_colors[unitIdx] = Vec4f(color.x,color.y,color.z,alpha); unit_vertices[unitIdx] = Vec2f(mx + (pos.x+1)*zoom.x+size, my + mh - (pos.y*zoom.y)); unitIdx++; unit_colors[unitIdx] = Vec4f(color.x,color.y,color.z,alpha); unit_vertices[unitIdx] = Vec2f(mx + (pos.x+1)*zoom.x+size, my + mh - ((pos.y+size)*zoom.y)); unitIdx++; unit_colors[unitIdx] = Vec4f(color.x,color.y,color.z,alpha); unit_vertices[unitIdx] = Vec2f(mx + pos.x*zoom.x, my + mh - ((pos.y+size)*zoom.y)); unitIdx++; } } if(unitIdx > 0) { glEnable(GL_BLEND); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); glColorPointer(4,GL_FLOAT, 0, &unit_colors[0]); glVertexPointer(2, GL_FLOAT, 0, &unit_vertices[0]); glDrawArrays(GL_QUADS, 0, unitIdx); //glDrawArrays(GL_TRIANGLE_STRIP, 0, unitIdx); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glDisable(GL_BLEND); } } } void Renderer::renderVisibleMarkedCells(bool renderTextHint,int x, int y) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } // Draw marked cells std::map markedCells = game->getMapMarkedCellList(); if(markedCells.empty() == false) { const Texture2D *texture= game->getMarkCellTexture(); const int yOffset = -40; for(std::map::iterator iterMap =markedCells.begin(); iterMap != markedCells.end(); ++iterMap) { MarkedCell &bm = iterMap->second; if(bm.getPlayerIndex() < 0 || (bm.getFaction() != NULL && bm.getFaction()->getTeam() == game->getWorld()->getThisFaction()->getTeam())) { const Map *map= game->getWorld()->getMap(); std::pair bmVisible = posInCellQuadCache( map->toSurfCoords(bm.getTargetPos())); if(bmVisible.first == true) { if(renderTextHint == true) { if(bm.getNote() != "") { bool validPosObjWorld= x > bmVisible.second.x && y > bmVisible.second.y + yOffset && x < bmVisible.second.x + texture->getTextureWidth() && y < bmVisible.second.y + yOffset + texture->getTextureHeight(); if(validPosObjWorld) { //printf("Checking for hint text render mouse [%d,%d] marker pos [%d,%d] validPosObjWorld = %d, hint [%s]\n",x,y,bm.getTargetPos().x,bm.getTargetPos().y,validPosObjWorld,bm.getNote().c_str()); //Lang &lang= Lang::getInstance(); Vec4f fontColor = Vec4f(1.0f, 1.0f, 1.0f, 0.25f); if(renderText3DEnabled == true) { renderTextShadow3D(bm.getNote(), CoreData::getInstance().getConsoleFont3D(), fontColor, bmVisible.second.x, bmVisible.second.y); } else { renderTextShadow(bm.getNote(), CoreData::getInstance().getConsoleFont(), fontColor, bmVisible.second.x, bmVisible.second.y); } } } } else { /* //texture 0 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); //set color to interpolation glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE1); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA); //set alpha to 1 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); //texture 1 glActiveTexture(GL_TEXTURE1); glMultiTexCoord2f(GL_TEXTURE1, 0.f, 0.f); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, static_cast(bm.getFaction()->getTexture())->getHandle()); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); //set alpha to 1 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); glActiveTexture(GL_TEXTURE0); */ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); Vec3f color(MarkedCell::static_system_marker_color); if(bm.getFaction() != NULL) { color = bm.getFaction()->getTexture()->getPixmapConst()->getPixel3f(0,0); } renderTextureQuad( bmVisible.second.x,bmVisible.second.y + yOffset, texture->getTextureWidth(),texture->getTextureHeight(),texture,0.8f,&color); /* glActiveTexture(GL_TEXTURE1); glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); */ } } } } } } void Renderer::renderDisplay() { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } CoreData &coreData= CoreData::getInstance(); const Metrics &metrics= Metrics::getInstance(); const Display *display= game->getGui()->getDisplay(); glPushAttrib(GL_ENABLE_BIT); if(renderText3DEnabled == true) { //infoString renderTextShadow3D( display->getInfoText().c_str(), coreData.getDisplayFont3D(), display->getColor(), metrics.getDisplayX(), metrics.getDisplayY()+Display::infoStringY); //title renderTextShadow3D( display->getTitle().c_str(), coreData.getDisplayFont3D(), display->getColor(), metrics.getDisplayX()+40, metrics.getDisplayY() + metrics.getDisplayH() - 20); glColor3f(0.0f, 0.0f, 0.0f); //text renderTextShadow3D( display->getText().c_str(), coreData.getDisplayFont3D(), display->getColor(), metrics.getDisplayX() -1, metrics.getDisplayY() + metrics.getDisplayH() - 56); //progress Bar if(display->getProgressBar() != -1) { renderProgressBar3D( display->getProgressBar(), metrics.getDisplayX(), metrics.getDisplayY() + metrics.getDisplayH()-50, coreData.getDisplayFontSmall3D(), 175); } } else { //infoString renderTextShadow( display->getInfoText().c_str(), coreData.getDisplayFont(), display->getColor(), metrics.getDisplayX(), metrics.getDisplayY()+Display::infoStringY); //title renderTextShadow( display->getTitle().c_str(), coreData.getDisplayFont(), display->getColor(), metrics.getDisplayX()+40, metrics.getDisplayY() + metrics.getDisplayH() - 20); glColor3f(0.0f, 0.0f, 0.0f); //text renderTextShadow( display->getText().c_str(), coreData.getDisplayFont(), display->getColor(), metrics.getDisplayX() -1, metrics.getDisplayY() + metrics.getDisplayH() - 56); //progress Bar if(display->getProgressBar()!=-1){ renderProgressBar( display->getProgressBar(), metrics.getDisplayX(), metrics.getDisplayY() + metrics.getDisplayH()-50, coreData.getDisplayFontSmall()); } } //up images glEnable(GL_TEXTURE_2D); glColor3f(1.f, 1.f, 1.f); for(int i=0; igetUpImage(i)!=NULL){ renderQuad( metrics.getDisplayX()+display->computeUpX(i), metrics.getDisplayY()+display->computeUpY(i), display->getUpImageSize(), display->getUpImageSize(), display->getUpImage(i)); } } //down images for(int i=0; igetDownImage(i)!=NULL){ Vec3f c=display->getDownImageColor(i); glColor3f(c.x,c.y,c.z ); int x= metrics.getDisplayX()+display->computeDownX(i); int y= metrics.getDisplayY()+display->computeDownY(i); int size= Display::imageSize; if(display->getDownSelectedPos()==i){ x-= 3; y-= 3; size+= 6; } renderQuad(x, y, size, size, display->getDownImage(i)); } } //selection int downPos= display->getDownSelectedPos(); if(downPos!=Display::invalidPos){ const Texture2D *texture= display->getDownImage(downPos); if(texture!=NULL){ int x= metrics.getDisplayX()+display->computeDownX(downPos)-3; int y= metrics.getDisplayY()+display->computeDownY(downPos)-3; int size= Display::imageSize+6; renderQuad(x, y, size, size, display->getDownImage(downPos)); } } glPopAttrib(); } void Renderer::renderMenuBackground(const MenuBackground *menuBackground) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } assertGl(); const Vec3f &cameraPosition= menuBackground->getCamera()->getConstPosition(); glPushAttrib(GL_LIGHTING_BIT | GL_ENABLE_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT); //clear Vec4f fogColor= Vec4f(0.4f, 0.4f, 0.4f, 1.f) * menuBackground->getFade(); glClearColor(fogColor.x, fogColor.y, fogColor.z, 1.f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glFogfv(GL_FOG_COLOR, fogColor.ptr()); //light Vec4f lightPos= Vec4f(10.f, 10.f, 10.f, 1.f)* menuBackground->getFade(); Vec4f diffLight= Vec4f(0.9f, 0.9f, 0.9f, 1.f)* menuBackground->getFade(); Vec4f ambLight= Vec4f(0.3f, 0.3f, 0.3f, 1.f)* menuBackground->getFade(); Vec4f specLight= Vec4f(0.1f, 0.1f, 0.1f, 1.f)* menuBackground->getFade(); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_POSITION, lightPos.ptr()); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffLight.ptr()); glLightfv(GL_LIGHT0, GL_AMBIENT, ambLight.ptr()); glLightfv(GL_LIGHT0, GL_SPECULAR, specLight.ptr()); //main model glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.5f); modelRenderer->begin(true, true, true, false); menuBackground->getMainModelPtr()->updateInterpolationData(menuBackground->getAnim(), true); modelRenderer->render(menuBackground->getMainModelPtr()); modelRenderer->end(); glDisable(GL_ALPHA_TEST); //characters float dist= menuBackground->getAboutPosition().dist(cameraPosition); float minDist= 3.f; if(dist < minDist) { glAlphaFunc(GL_GREATER, 0.0f); float alpha= clamp((minDist-dist) / minDist, 0.f, 1.f); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Vec4f(1.0f, 1.0f, 1.0f, alpha).ptr()); std::vector &characterMenuScreenPositionListCache = CacheManager::getCachedItem< std::vector >(GameConstants::characterMenuScreenPositionListCacheLookupKey); characterMenuScreenPositionListCache.clear(); modelRenderer->begin(true, true, false, false); for(int i=0; i < MenuBackground::characterCount; ++i) { glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); Vec3f worldPos(i*2.f-4.f, -1.4f, -7.5f); glTranslatef(worldPos.x,worldPos.y,worldPos.z); // // Get the screen coordinates for each character model - START //std::vector projection(16); //std::vector modelview(16); //std::vector screen_coords(3); //glGetDoublev(GL_PROJECTION_MATRIX, projection.data()); //glGetDoublev(GL_MODELVIEW_MATRIX, modelview.data()); const Metrics &metrics= Metrics::getInstance(); GLint viewport[]= {0, 0, metrics.getVirtualW(), metrics.getVirtualH()}; //get matrices GLdouble projection[16]; glGetDoublev(GL_PROJECTION_MATRIX, projection); GLdouble modelview[16]; glGetDoublev(GL_MODELVIEW_MATRIX, modelview); //get the screen coordinates GLdouble screen_coords[3]; gluProject(worldPos.x, worldPos.y, worldPos.z, modelview, projection, viewport, &screen_coords[0], &screen_coords[1], &screen_coords[2]); characterMenuScreenPositionListCache.push_back(Vec3f(screen_coords[0],screen_coords[1],screen_coords[2])); // Get the screen coordinates for each character model - END // menuBackground->getCharacterModelPtr(i)->updateInterpolationData(menuBackground->getAnim(), true); modelRenderer->render(menuBackground->getCharacterModelPtr(i)); glPopMatrix(); } modelRenderer->end(); } //water if(menuBackground->getWater()) { //water surface const int waterTesselation= 10; const int waterSize= 250; const int waterQuadSize= 2*waterSize/waterTesselation; const float waterHeight= menuBackground->getWaterHeight(); glEnable(GL_BLEND); glNormal3f(0.f, 1.f, 0.f); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Vec4f(1.f, 1.f, 1.f, 1.f).ptr()); GLuint waterHandle= static_cast(menuBackground->getWaterTexture())->getHandle(); glBindTexture(GL_TEXTURE_2D, waterHandle); for(int i=1; i < waterTesselation; ++i) { glBegin(GL_TRIANGLE_STRIP); for(int j=1; j < waterTesselation; ++j) { glTexCoord2i(1, 2 % j); glVertex3f(-waterSize+i*waterQuadSize, waterHeight, -waterSize+j*waterQuadSize); glTexCoord2i(0, 2 % j); glVertex3f(-waterSize+(i+1)*waterQuadSize, waterHeight, -waterSize+j*waterQuadSize); } glEnd(); } glDisable(GL_BLEND); //raindrops if(menuBackground->getRain()) { const float maxRaindropAlpha= 0.5f; glEnable(GL_BLEND); glDisable(GL_LIGHTING); glDisable(GL_ALPHA_TEST); glDepthMask(GL_FALSE); //splashes CoreData &coreData= CoreData::getInstance(); glBindTexture(GL_TEXTURE_2D, static_cast(coreData.getWaterSplashTexture())->getHandle()); for(int i=0; i< MenuBackground::raindropCount; ++i) { Vec2f pos= menuBackground->getRaindropPos(i); float scale= menuBackground->getRaindropState(i); float alpha= maxRaindropAlpha-scale*maxRaindropAlpha; glMatrixMode(GL_MODELVIEW); glPushMatrix(); glColor4f(1.f, 1.f, 1.f, alpha); glTranslatef(pos.x, waterHeight+0.01f, pos.y); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(0.f, 1.f); glVertex3f(-scale, 0, scale); glTexCoord2f(0.f, 0.f); glVertex3f(-scale, 0, -scale); glTexCoord2f(1.f, 1.f); glVertex3f(scale, 0, scale); glTexCoord2f(1.f, 0.f); glVertex3f(scale, 0, -scale); glEnd(); glPopMatrix(); } } } glPopAttrib(); assertGl(); } void Renderer::renderMenuBackground(Camera *camera, float fade, Model *mainModel, vector characterModels,const Vec3f characterPosition, float anim) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } assertGl(); const Vec3f &cameraPosition= camera->getConstPosition(); glPushAttrib(GL_LIGHTING_BIT | GL_ENABLE_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT); //clear //Vec4f fogColor= Vec4f(0.4f, 0.4f, 0.4f, 1.f) * fade; // Show black bacground Vec4f fogColor= Vec4f(0.f, 0.f, 0.f, 1.f); glClearColor(fogColor.x, fogColor.y, fogColor.z, 1.f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glFogfv(GL_FOG_COLOR, fogColor.ptr()); //light Vec4f lightPos= Vec4f(10.f, 10.f, 10.f, 1.f) * fade; Vec4f diffLight= Vec4f(0.9f, 0.9f, 0.9f, 1.f) * fade; Vec4f ambLight= Vec4f(0.3f, 0.3f, 0.3f, 1.f) * fade; Vec4f specLight= Vec4f(0.1f, 0.1f, 0.1f, 1.f) * fade; glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_POSITION, lightPos.ptr()); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffLight.ptr()); glLightfv(GL_LIGHT0, GL_AMBIENT, ambLight.ptr()); glLightfv(GL_LIGHT0, GL_SPECULAR, specLight.ptr()); //main model if(mainModel) { glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.5f); modelRenderer->begin(true, true, true, false); mainModel->updateInterpolationData(anim, true); modelRenderer->render(mainModel); modelRenderer->end(); glDisable(GL_ALPHA_TEST); } //characters if(characterModels.empty() == false) { float dist= characterPosition.dist(cameraPosition); float minDist= 3.f; if(dist < minDist) { glAlphaFunc(GL_GREATER, 0.0f); float alpha= clamp((minDist-dist) / minDist, 0.f, 1.f); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Vec4f(1.0f, 1.0f, 1.0f, alpha).ptr()); modelRenderer->begin(true, true, false, false); for(unsigned int i = 0; i < characterModels.size(); ++i) { if(characterModels[i]) { glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glTranslatef(i*2.f-4.f, -1.4f, -7.5f); characterModels[i]->updateInterpolationData(anim, true); modelRenderer->render(characterModels[i]); glPopMatrix(); } } modelRenderer->end(); } } glPopAttrib(); assertGl(); } // ==================== computing ==================== bool Renderer::ccomputePosition(const Vec2i &screenPos, Vec2i &worldPos, bool exactCoords) { assertGl(); const Map* map= game->getWorld()->getMap(); const Metrics &metrics= Metrics::getInstance(); float depth= 0.0f; GLdouble modelviewMatrix[16]; GLdouble projectionMatrix[16]; GLint viewport[4]= {0, 0, metrics.getScreenW(), metrics.getScreenH()}; GLdouble worldX; GLdouble worldY; GLdouble worldZ; GLint screenX= (screenPos.x * metrics.getScreenW() / metrics.getVirtualW()); GLint screenY= (screenPos.y * metrics.getScreenH() / metrics.getVirtualH()); //get the depth in the cursor pixel glReadPixels(screenX, screenY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth); //load matrices loadProjectionMatrix(); loadGameCameraMatrix(); //get matrices glGetDoublev(GL_MODELVIEW_MATRIX, modelviewMatrix); glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix); //get the world coordinates gluUnProject( screenX, screenY, depth, modelviewMatrix, projectionMatrix, viewport, &worldX, &worldY, &worldZ); //conver coords to int if(exactCoords == true) { worldPos= Vec2i(static_cast(worldX), static_cast(worldZ)); } else { worldPos= Vec2i(static_cast(worldX+0.5f), static_cast(worldZ+0.5f)); } //clamp coords to map size return map->isInside(worldPos); } // This method takes world co-ordinates and translates them to screen co-ords Vec3f Renderer::computeScreenPosition(const Vec3f &worldPos) { if(worldToScreenPosCache.find(worldPos) != worldToScreenPosCache.end()) { return worldToScreenPosCache[worldPos]; } assertGl(); const Metrics &metrics= Metrics::getInstance(); GLint viewport[]= {0, 0, metrics.getVirtualW(), metrics.getVirtualH()}; GLdouble worldX = worldPos.x; GLdouble worldY = worldPos.y; GLdouble worldZ = worldPos.z; //load matrices loadProjectionMatrix(); loadGameCameraMatrix(); //get matrices GLdouble modelviewMatrix[16]; glGetDoublev(GL_MODELVIEW_MATRIX, modelviewMatrix); GLdouble projectionMatrix[16]; glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix); //get the screen coordinates GLdouble screenX; GLdouble screenY; GLdouble screenZ; gluProject(worldX, worldY, worldZ, modelviewMatrix, projectionMatrix, viewport, &screenX, &screenY, &screenZ); Vec3f screenPos(screenX,screenY,screenZ); worldToScreenPosCache[worldPos]=screenPos; return screenPos; } void Renderer::computeSelected( Selection::UnitContainer &units, const Object *&obj, const bool withObjectSelection, const Vec2i &posDown, const Vec2i &posUp) { const string selectionType=toLower(Config::getInstance().getString("SelectionType",Config::colorPicking)); if(selectionType==Config::colorPicking) { selectUsingColorPicking(units,obj, withObjectSelection,posDown, posUp); } /// Frustum approach --> Currently not accurate enough else if(selectionType==Config::frustumPicking) { selectUsingFrustumSelection(units,obj, withObjectSelection,posDown, posUp); } else { selectUsingSelectionBuffer(units,obj, withObjectSelection,posDown, posUp); } } void Renderer::selectUsingFrustumSelection(Selection::UnitContainer &units, const Object *&obj, const bool withObjectSelection, const Vec2i &posDown, const Vec2i &posUp) { glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); const Metrics &metrics= Metrics::getInstance(); GLint view[]= {0, 0, metrics.getVirtualW(), metrics.getVirtualH()}; //compute center and dimensions of selection rectangle int x = (posDown.x+posUp.x) / 2; int y = (posDown.y+posUp.y) / 2; int w = abs(posDown.x-posUp.x); int h = abs(posDown.y-posUp.y); if(w < 2) { w = 2; } if(h < 2) { h = 2; } gluPickMatrix(x, y, w, h, view); gluPerspective(perspFov, metrics.getAspectRatio(), perspNearPlane, perspFarPlane); loadGameCameraMatrix(); VisibleQuadContainerCache quadSelectionCacheItem; ExtractFrustum(quadSelectionCacheItem); //pop matrices glMatrixMode(GL_PROJECTION); glPopMatrix(); VisibleQuadContainerCache &qCache = getQuadCache(); if(qCache.visibleQuadUnitList.empty() == false) { for(int visibleUnitIndex = 0; visibleUnitIndex < (int)qCache.visibleQuadUnitList.size(); ++visibleUnitIndex) { Unit *unit = qCache.visibleQuadUnitList[visibleUnitIndex]; if(unit != NULL && unit->isAlive()) { Vec3f unitPos = unit->getCurrMidHeightVector(); bool insideQuad = CubeInFrustum(quadSelectionCacheItem.frustumData, unitPos.x, unitPos.y, unitPos.z, unit->getType()->getRenderSize()); if(insideQuad == true) { units.push_back(unit); } } } } if(withObjectSelection == true) { if(qCache.visibleObjectList.empty() == false) { for(int visibleIndex = 0; visibleIndex < (int)qCache.visibleObjectList.size(); ++visibleIndex) { Object *object = qCache.visibleObjectList[visibleIndex]; if(object != NULL) { bool insideQuad = CubeInFrustum(quadSelectionCacheItem.frustumData, object->getPos().x, object->getPos().y, object->getPos().z, 1); if(insideQuad == true) { obj = object; //if(withObjectSelection == true) { break; //} } } } } } } void Renderer::selectUsingSelectionBuffer(Selection::UnitContainer &units, const Object *&obj, const bool withObjectSelection, const Vec2i &posDown, const Vec2i &posUp) { //compute center and dimensions of selection rectangle int x = (posDown.x+posUp.x) / 2; int y = (posDown.y+posUp.y) / 2; int w = abs(posDown.x-posUp.x); int h = abs(posDown.y-posUp.y); if(w < 2) { w = 2; } if(h < 2) { h = 2; } //declarations GLuint selectBuffer[Gui::maxSelBuff]; //setup matrices glSelectBuffer(Gui::maxSelBuff, selectBuffer); //glMatrixMode(GL_PROJECTION); //glPushMatrix(); GLint renderModeResult = glRenderMode(GL_SELECT); if(renderModeResult < 0) { const char *errorString= reinterpret_cast(gluErrorString(renderModeResult)); char szBuf[8096]=""; snprintf(szBuf,8096,"OpenGL error #%d [0x%X] : [%s] at file: [%s], line: %d",renderModeResult,renderModeResult,errorString,extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__); printf("%s\n",szBuf); } glPushMatrix(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); const Metrics &metrics= Metrics::getInstance(); GLint view[]= {0, 0, metrics.getVirtualW(), metrics.getVirtualH()}; //GLint view[4]; //glGetIntegerv(GL_VIEWPORT, view); gluPickMatrix(x, y, w, h, view); gluPerspective(perspFov, metrics.getAspectRatio(), perspNearPlane, perspFarPlane); //gluPerspective(perspFov, metrics.getAspectRatio(), 0.0001, 1000.0); //gluPerspective(perspFov, (float)view[2]/(float)view[3], perspNearPlane, perspFarPlane); loadGameCameraMatrix(); //render units to find which ones should be selected renderUnitsFast(); if(withObjectSelection == true) { renderObjectsFast(false,true); } //pop matrices glPopMatrix(); // Added this to ensure all the selection calls are done now // (see http://www.unknownroad.com/rtfm/graphics/glselection.html section: [0x4]) //glFlush(); //select units by checking the selected buffer int selCount= glRenderMode(GL_RENDER); if(selCount > 0) { VisibleQuadContainerCache &qCache = getQuadCache(); for(int i = 1; i <= selCount; ++i) { int index = selectBuffer[i*4-1]; if(index >= OBJECT_SELECT_OFFSET) { Object *object = qCache.visibleObjectList[index - OBJECT_SELECT_OFFSET]; if(object != NULL) { obj = object; if(withObjectSelection == true) { break; } } } else { Unit *unit = qCache.visibleQuadUnitList[index]; if(unit != NULL && unit->isAlive()) { units.push_back(unit); } } } } else if(selCount < 0) { const char *errorString= reinterpret_cast(gluErrorString(selCount)); char szBuf[8096]=""; snprintf(szBuf,8096,"OpenGL error #%d [0x%X] : [%s] at file: [%s], line: %d",selCount,selCount,errorString,extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__); printf("%s\n",szBuf); } } void Renderer::selectUsingColorPicking(Selection::UnitContainer &units, const Object *&obj, const bool withObjectSelection, const Vec2i &posDown, const Vec2i &posUp) { int x1 = posDown.x; int y1 = posDown.y; int x2 = posUp.x; int y2 = posUp.y; int x = min(x1,x2); int y = min(y1,y2); int w = max(x1,x2) - min(x1,x2); int h = max(y1,y2) - min(y1,y2); if(w < 2) { w = 2; } if(h < 2) { h = 2; } const Metrics &metrics= Metrics::getInstance(); x= (x * metrics.getScreenW() / metrics.getVirtualW()); y= (y * metrics.getScreenH() / metrics.getVirtualH()); w= (w * metrics.getScreenW() / metrics.getVirtualW()); h= (h * metrics.getScreenH() / metrics.getVirtualH()); PixelBufferWrapper::begin(); glPushMatrix(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); //GLint view[]= {0, 0, metrics.getVirtualW(), metrics.getVirtualH()}; //gluPickMatrix(x, y, w, h, view); gluPerspective(perspFov, metrics.getAspectRatio(), perspNearPlane, perspFarPlane); loadGameCameraMatrix(); //render units to find which ones should be selected //printf("In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); vector rendererUnits = renderUnitsFast(false, true); //printf("In [%s::%s] Line: %d rendererUnits = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,rendererUnits.size()); // Added this to ensure all the selection calls are done now // (see http://www.unknownroad.com/rtfm/graphics/glselection.html section: [0x4]) //glFlush(); //GraphicsInterface::getInstance().getCurrentContext()->swapBuffers(); PixelBufferWrapper::end(); vector unitsVector; bool unitFound=false; if(rendererUnits.empty() == false) { copy(rendererUnits.begin(), rendererUnits.end(), std::inserter(unitsVector, unitsVector.begin())); } if(unitsVector.empty() == false) { vector pickedList = BaseColorPickEntity::getPickedList(x,y,w,h, unitsVector); //printf("In [%s::%s] Line: %d pickedList = %d models rendered = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,pickedList.size(),rendererModels.size()); if(pickedList.empty() == false) { units.reserve(pickedList.size()); for(unsigned int i = 0; i < pickedList.size(); ++i) { int index = pickedList[i]; //printf("In [%s::%s] Line: %d searching for selected object i = %d index = %d units = %d objects = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,i,index,rendererUnits.size(),rendererObjects.size()); if(rendererUnits.empty() == false && index < (int)rendererUnits.size()) { Unit *unit = rendererUnits[index]; if(unit != NULL && unit->isAlive()) { unitFound=true; units.push_back(unit); } } } } } if(withObjectSelection == true && unitFound==false) { vector rendererObjects; vector objectsVector; rendererObjects = renderObjectsFast(false,true,true); if(rendererObjects.empty() == false) { copy(rendererObjects.begin(), rendererObjects.end(), std::inserter(objectsVector, objectsVector.begin())); } if(objectsVector.empty() == false) { vector pickedList = BaseColorPickEntity::getPickedList(x,y,w,h, objectsVector); //printf("In [%s::%s] Line: %d pickedList = %d models rendered = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,pickedList.size(),rendererModels.size()); if(pickedList.empty() == false) { for(unsigned int i = 0; i < pickedList.size(); ++i) { int index = pickedList[i]; //printf("In [%s::%s] Line: %d searching for selected object i = %d index = %d units = %d objects = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,i,index,rendererUnits.size(),rendererObjects.size()); if(rendererObjects.empty() == false && index < (int)rendererObjects.size()) { Object *object = rendererObjects[index]; //printf("In [%s::%s] Line: %d searching for selected object i = %d index = %d [%p]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,i,index,object); if(object != NULL) { obj = object; break; } } } } } } //pop matrices glPopMatrix(); } // ==================== shadows ==================== void Renderer::renderShadowsToTexture(const int renderFps){ if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(shadowsOffDueToMinRender == false && (shadows == sProjected || shadows == sShadowMapping)) { shadowMapFrame= (shadowMapFrame + 1) % (shadowFrameSkip + 1); if(shadowMapFrame == 0){ assertGl(); glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT | GL_VIEWPORT_BIT | GL_POLYGON_BIT); if(shadows == sShadowMapping) { glClear(GL_DEPTH_BUFFER_BIT); } else { float color= 1.0f-shadowIntensity; glColor3f(color, color, color); glClearColor(1.f, 1.f, 1.f, 1.f); glDisable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT); } //assertGl(); //clear color buffer // //set viewport, we leave one texel always in white to avoid problems glViewport(1, 1, shadowTextureSize-2, shadowTextureSize-2); //assertGl(); if(nearestLightPos.w == 0.f) { //directional light //light pos assert(game != NULL); assert(game->getWorld() != NULL); const TimeFlow *tf= game->getWorld()->getTimeFlow(); assert(tf != NULL); float ang= tf->isDay()? computeSunAngle(tf->getTime()): computeMoonAngle(tf->getTime()); ang= radToDeg(ang); //push and set projection glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); //assertGl(); if(game->getGameCamera()->getState()==GameCamera::sGame){ //glOrtho(-35, 5, -15, 15, -1000, 1000); //glOrtho(-30, 30, -20, 20, -1000, 1000); glOrtho(-30, 5, -20, 20, -1000, 1000); } else{ glOrtho(-30, 30, -20, 20, -1000, 1000); } //assertGl(); //push and set modelview glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glRotatef(15, 0, 1, 0); glRotatef(ang, 1, 0, 0); glRotatef(90, 0, 1, 0); const Vec3f &pos= game->getGameCamera()->getPos(); glTranslatef(static_cast(-pos.x), 0, static_cast(-pos.z)); //assertGl(); } else { //non directional light //push projection glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); //assertGl(); gluPerspective(perspFov, 1.f, perspNearPlane, perspFarPlane); //const Metrics &metrics= Metrics::getInstance(); //gluPerspective(perspFov, metrics.getAspectRatio(), perspNearPlane, perspFarPlane); assertGl(); //push modelview glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glRotatef(-90, -1, 0, 0); glTranslatef(-nearestLightPos.x, -nearestLightPos.y-2, -nearestLightPos.z); //assertGl(); } if(shadows == sShadowMapping) { glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.0f, 16.0f); //assertGl(); } //render 3d renderUnitsFast(true); renderObjectsFast(true,false); //assertGl(); //read color buffer glBindTexture(GL_TEXTURE_2D, shadowMapHandle); assertGl(); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, shadowTextureSize, shadowTextureSize); GLenum error = glGetError(); // This error can happen when a Linux user switches from an X session // back to a running game, and 'seems' to be safe to ignore it if(error != GL_INVALID_OPERATION) { assertGlWithErrorNumber(error); } //get elemental matrices static Matrix4f matrix1; static bool matrix1Populate = true; if(matrix1Populate == true) { matrix1Populate = false; matrix1[0]= 0.5f; matrix1[4]= 0.f; matrix1[8]= 0.f; matrix1[12]= 0.5f; matrix1[1]= 0.f; matrix1[5]= 0.5f; matrix1[9]= 0.f; matrix1[13]= 0.5f; matrix1[2]= 0.f; matrix1[6]= 0.f; matrix1[10]= 0.5f; matrix1[14]= 0.5f; matrix1[3]= 0.f; matrix1[7]= 0.f; matrix1[11]= 0.f; matrix1[15]= 1.f; } Matrix4f matrix2; glGetFloatv(GL_PROJECTION_MATRIX, matrix2.ptr()); //assertGl(); Matrix4f matrix3; glGetFloatv(GL_MODELVIEW_MATRIX, matrix3.ptr()); //pop both matrices glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPushMatrix(); //assertGl(); //compute texture matrix glLoadMatrixf(matrix1.ptr()); glMultMatrixf(matrix2.ptr()); glMultMatrixf(matrix3.ptr()); glGetFloatv(GL_TRANSPOSE_PROJECTION_MATRIX_ARB, shadowMapMatrix.ptr()); //assertGl(); //if(shadows == sShadowMapping) { // glDisable(GL_POLYGON_OFFSET_FILL); // glPolygonOffset(0.0f, 0.0f); //} //pop glPopMatrix(); //assertGl(); glPopAttrib(); assertGl(); } } } // ==================== gl wrap ==================== string Renderer::getGlInfo(){ string infoStr=""; Lang &lang= Lang::getInstance(); if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) { infoStr+= lang.getString("OpenGlInfo")+":\n"; infoStr+= " "+lang.getString("OpenGlVersion")+": "; infoStr+= string((getGlVersion() != NULL ? getGlVersion() : "?"))+"\n"; infoStr+= " "+lang.getString("OpenGlRenderer")+": "; infoStr+= string((getGlVersion() != NULL ? getGlVersion() : "?"))+"\n"; infoStr+= " "+lang.getString("OpenGlVendor")+": "; infoStr+= string((getGlVendor() != NULL ? getGlVendor() : "?"))+"\n"; infoStr+= " "+lang.getString("OpenGlMaxLights")+": "; infoStr+= intToStr(getGlMaxLights())+"\n"; infoStr+= " "+lang.getString("OpenGlMaxTextureSize")+": "; infoStr+= intToStr(getGlMaxTextureSize())+"\n"; infoStr+= " "+lang.getString("OpenGlMaxTextureUnits")+": "; infoStr+= intToStr(getGlMaxTextureUnits())+"\n"; infoStr+= " "+lang.getString("OpenGlModelviewStack")+": "; infoStr+= intToStr(getGlModelviewMatrixStackDepth())+"\n"; infoStr+= " "+lang.getString("OpenGlProjectionStack")+": "; infoStr+= intToStr(getGlProjectionMatrixStackDepth())+"\n"; } return infoStr; } string Renderer::getGlMoreInfo(){ string infoStr=""; Lang &lang= Lang::getInstance(); if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) { //gl extensions infoStr+= lang.getString("OpenGlExtensions")+":\n "; string extensions= getGlExtensions(); int charCount= 0; for(int i = 0; i < (int)extensions.size(); ++i) { infoStr+= extensions[i]; if(charCount>120 && extensions[i]==' '){ infoStr+= "\n "; charCount= 0; } ++charCount; } //platform extensions infoStr+= "\n\n"; infoStr+= lang.getString("OpenGlPlatformExtensions")+":\n "; charCount= 0; string platformExtensions= getGlPlatformExtensions(); for(int i = 0; i < (int)platformExtensions.size(); ++i) { infoStr+= platformExtensions[i]; if(charCount>120 && platformExtensions[i]==' '){ infoStr+= "\n "; charCount= 0; } ++charCount; } } return infoStr; } void Renderer::autoConfig() { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) { Config &config= Config::getInstance(); bool nvidiaCard= toLower(getGlVendor()).find("nvidia")!=string::npos; bool atiCard= toLower(getGlVendor()).find("ati")!=string::npos; //bool shadowExtensions = isGlExtensionSupported("GL_ARB_shadow") && isGlExtensionSupported("GL_ARB_shadow_ambient"); bool shadowExtensions = isGlExtensionSupported("GL_ARB_shadow"); //3D textures config.setBool("Textures3D", isGlExtensionSupported("GL_EXT_texture3D")); //shadows string shadows=""; if(getGlMaxTextureUnits()>=3){ if(nvidiaCard && shadowExtensions){ shadows= shadowsToStr(sShadowMapping); } else{ shadows= shadowsToStr(sProjected); } } else{ shadows=shadowsToStr(sDisabled); } config.setString("Shadows", shadows); //lights config.setInt("MaxLights", atiCard? 1: 4); //filter config.setString("Filter", "Bilinear"); } } void Renderer::clearBuffers() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } void Renderer::clearZBuffer() { glClear(GL_DEPTH_BUFFER_BIT); } void Renderer::loadConfig() { Config &config= Config::getInstance(); //cache most used config params maxLights= config.getInt("MaxLights"); photoMode= config.getBool("PhotoMode"); focusArrows= config.getBool("FocusArrows"); textures3D= config.getBool("Textures3D"); float gammaValue=config.getFloat("GammaValue","0.0"); if(this->program == NULL) { throw megaglest_runtime_error("this->program == NULL"); } if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) { //if(this->program != NULL) { if(gammaValue != 0.0) { this->program->getWindow()->setGamma(gammaValue); } //} } //load shadows shadows= strToShadows(config.getString("Shadows")); if(shadows==sProjected || shadows==sShadowMapping){ shadowTextureSize= config.getInt("ShadowTextureSize"); shadowFrameSkip= config.getInt("ShadowFrameSkip"); shadowIntensity= config.getFloat("ShadowIntensity","1.0"); } //load filter settings Texture2D::Filter textureFilter= strToTextureFilter(config.getString("Filter")); int maxAnisotropy= config.getInt("FilterMaxAnisotropy"); if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) { for(int i=0; isetFilter(textureFilter); textureManager[i]->setMaxAnisotropy(maxAnisotropy); } } } //Texture2D *Renderer::saveScreenToTexture(int x, int y, int width, int height) { // if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__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->setForceCompressionDisabled(true); // texture->setMipmap(false); // Pixmap2D *pixmapScreenShot = texture->getPixmap(); // pixmapScreenShot->init(width, height, 3); // texture->init(textureFilter,maxAnisotropy); // // if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); // //glFinish(); // // if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); // glReadPixels(x, y, pixmapScreenShot->getW(), pixmapScreenShot->getH(), // GL_RGB, GL_UNSIGNED_BYTE, pixmapScreenShot->getPixels()); // // if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); // // return texture; //} void Renderer::saveScreen(const string &path,int w, int h) { const Metrics &sm= Metrics::getInstance(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); Pixmap2D *pixmapScreenShot = new Pixmap2D(sm.getScreenW(),sm.getScreenH(), 3); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //glFinish(); glPixelStorei(GL_PACK_ALIGNMENT, 1); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); glReadPixels(0, 0, pixmapScreenShot->getW(), pixmapScreenShot->getH(), GL_RGB, GL_UNSIGNED_BYTE, pixmapScreenShot->getPixels()); if(w==0 || h==0){ h=sm.getScreenH(); w=sm.getScreenW(); } else{ pixmapScreenShot->Scale(GL_RGB,w,h); } if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Signal the threads queue to add a screenshot save request MutexSafeWrapper safeMutex(saveScreenShotThreadAccessor,string(extractFileFromDirectoryPath(__FILE__).c_str()) + "_" + intToStr(__LINE__)); saveScreenQueue.push_back(make_pair(path,pixmapScreenShot)); safeMutex.ReleaseLock(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); } unsigned int Renderer::getSaveScreenQueueSize() { MutexSafeWrapper safeMutex(saveScreenShotThreadAccessor,string(extractFileFromDirectoryPath(__FILE__).c_str()) + "_" + intToStr(__LINE__)); int queueSize = (int)saveScreenQueue.size(); safeMutex.ReleaseLock(); return queueSize; } // ==================== PRIVATE ==================== float Renderer::computeSunAngle(float time) { float dayTime= TimeFlow::dusk-TimeFlow::dawn; float fTime= (time-TimeFlow::dawn)/dayTime; return clamp(fTime*pi, pi/8.f, 7.f*pi/8.f); } float Renderer::computeMoonAngle(float time) { float nightTime= 24-(TimeFlow::dusk-TimeFlow::dawn); if(time Renderer::renderUnitsFast(bool renderingShadows, bool colorPickingSelection) { vector unitsList; if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return unitsList; } assert(game != NULL); //const World *world= game->getWorld(); //assert(world != NULL); VisibleQuadContainerCache &qCache = getQuadCache(); if(qCache.visibleQuadUnitList.empty() == false) { if(colorPickingSelection == true) { unitsList.reserve(qCache.visibleQuadUnitList.size()); } bool modelRenderStarted = false; bool renderOnlyBuildings=true; for(int k=0; k<2 ;k++) { if(k==0){ //glDisable(GL_DEPTH_TEST); renderOnlyBuildings=true; } else { if(colorPickingSelection == true){ // clear depth buffer to get units behind buildings rendered in front of them glClear(GL_DEPTH_BUFFER_BIT); } //glEnable(GL_DEPTH_TEST); renderOnlyBuildings=false; } for(int visibleUnitIndex = 0; visibleUnitIndex < (int)qCache.visibleQuadUnitList.size(); ++visibleUnitIndex) { Unit *unit = qCache.visibleQuadUnitList[visibleUnitIndex]; if(renderingShadows==false && unit->isAlive()==false){ // no need to render dead units for selection continue; } if(renderOnlyBuildings==true && unit->getType()->hasSkillClass(scMove)){ continue; } if(renderOnlyBuildings==false && !unit->getType()->hasSkillClass(scMove)){ continue; } if(modelRenderStarted == false) { modelRenderStarted = true; if(colorPickingSelection == false) { //glPushAttrib(GL_ENABLE_BIT| GL_TEXTURE_BIT); glDisable(GL_LIGHTING); if (renderingShadows == false) { glPushAttrib(GL_ENABLE_BIT); glDisable(GL_TEXTURE_2D); } else { glPushAttrib(GL_ENABLE_BIT| GL_TEXTURE_BIT); glEnable(GL_TEXTURE_2D); glAlphaFunc(GL_GREATER, 0.4f); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); //set color to the texture alpha glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); //set alpha to the texture alpha glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); } } modelRenderer->begin(false, renderingShadows, false, colorPickingSelection); if(colorPickingSelection == false) { glInitNames(); } } if(colorPickingSelection == false) { glPushName(visibleUnitIndex); } //assertGl(); glMatrixMode(GL_MODELVIEW); //debuxar modelo glPushMatrix(); //translate Vec3f currVec= unit->getCurrVectorFlat(); glTranslatef(currVec.x, currVec.y, currVec.z); //rotate glRotatef(unit->getRotation(), 0.f, 1.f, 0.f); //render Model *model= unit->getCurrentModelPtr(); //if(this->gameCamera->getPos().dist(unit->getCurrVector()) <= SKIP_INTERPOLATION_DISTANCE) { // ***MV don't think this is needed below 2013/01/11 model->updateInterpolationVertices(unit->getAnimProgressAsFloat(), unit->isAlive() && !unit->isAnimProgressBound()); //} if(colorPickingSelection == true) { unit->setUniquePickingColor(); unitsList.push_back(unit); } modelRenderer->render(model,renderingShadows?rmShadows:rmSelection); glPopMatrix(); if(colorPickingSelection == false) { glPopName(); } } } if(modelRenderStarted == true) { modelRenderer->end(); if(colorPickingSelection == false) { glPopAttrib(); } } } //glDisable(GL_DEPTH_TEST); return unitsList; } //render objects for selection purposes vector Renderer::renderObjectsFast(bool renderingShadows, bool resourceOnly, bool colorPickingSelection) { vector objectList; if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return objectList; } VisibleQuadContainerCache &qCache = getQuadCache(); if(qCache.visibleObjectList.empty() == false) { if(colorPickingSelection == true) { objectList.reserve(qCache.visibleObjectList.size()); } bool modelRenderStarted = false; for(int visibleIndex = 0; visibleIndex < (int)qCache.visibleObjectList.size(); ++visibleIndex) { Object *o = qCache.visibleObjectList[visibleIndex]; if(modelRenderStarted == false) { modelRenderStarted = true; if(colorPickingSelection == false) { glDisable(GL_LIGHTING); if (renderingShadows == false){ glPushAttrib(GL_ENABLE_BIT); glDisable(GL_TEXTURE_2D); } else { glPushAttrib(GL_ENABLE_BIT| GL_TEXTURE_BIT); glAlphaFunc(GL_GREATER, 0.5f); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); //set color to the texture alpha glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); //set alpha to the texture alpha glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); } } modelRenderer->begin(false, renderingShadows, false, colorPickingSelection); if(colorPickingSelection == false) { glInitNames(); } } if(resourceOnly == false || o->getResource()!= NULL) { Model *objModel= o->getModelPtr(); //if(this->gameCamera->getPos().dist(o->getPos()) <= SKIP_INTERPOLATION_DISTANCE) { // ***MV don't think this is needed below 2013/01/11 //objModel->updateInterpolationData(o->getAnimProgress(), true); //} const Vec3f v= o->getConstPos(); if(colorPickingSelection == false) { glPushName(OBJECT_SELECT_OFFSET+visibleIndex); } glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(v.x, v.y, v.z); glRotatef(o->getRotation(), 0.f, 1.f, 0.f); if(colorPickingSelection == true) { o->setUniquePickingColor(); objectList.push_back(o); } modelRenderer->render(objModel,resourceOnly?rmSelection:rmNormal); glPopMatrix(); if(colorPickingSelection == false) { glPopName(); } } } if(modelRenderStarted == true) { modelRenderer->end(); if(colorPickingSelection == false) { glPopAttrib(); } } } return objectList; } // ==================== gl caps ==================== void Renderer::checkGlCaps() { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(glActiveTexture == NULL) { string message; message += "Your system supports OpenGL version ["; message += getGlVersion() + string("]\n"); message += "MegaGlest needs a version that supports\n"; message += "glActiveTexture (OpenGL 1.3) or the ARB_multitexture extension."; throw megaglest_runtime_error(message.c_str(),true); } //opengl 2.1 if(glewIsSupported("GL_VERSION_2_1") == false) { string message; message += "Your system supports OpenGL version ["; message += getGlVersion() + string("]\n"); message += "MegaGlest needs at least version 2.1 to work\n"; message += "You may solve this problem by installing your latest video card drivers"; throw megaglest_runtime_error(message.c_str(),true); } //opengl 1.4 or extension //if(!isGlVersionSupported(1, 4, 0)){ if(glewIsSupported("GL_VERSION_1_4") == false) { checkExtension("GL_ARB_texture_env_crossbar", "MegaGlest"); } } void Renderer::checkGlOptionalCaps() { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //shadows if(shadows == sProjected || shadows == sShadowMapping) { if(getGlMaxTextureUnits() < 3) { throw megaglest_runtime_error("Your system doesn't support 3 texture units, required for shadows"); } } if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //shadow mapping if(shadows == sShadowMapping) { checkExtension("GL_ARB_shadow", "Shadow Mapping"); //checkExtension("GL_ARB_shadow_ambient", "Shadow Mapping"); //checkExtension("GL_ARB_depth_texture", "Shadow Mapping"); } if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); } void Renderer::checkExtension(const string &extension, const string &msg) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); if(!isGlExtensionSupported(extension.c_str())) { string str= "OpenGL extension not supported: " + extension + ", required for " + msg; throw megaglest_runtime_error(str); } if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); } // ==================== init 3d lists ==================== void Renderer::init3dList() { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); render3dSetup(); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //const Metrics &metrics= Metrics::getInstance(); //assertGl(); //if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //list3d= glGenLists(1); //assertGl(); //list3dValid=true; //if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //glNewList(list3d, GL_COMPILE_AND_EXECUTE); //need to execute, because if not gluPerspective takes no effect and gluLoadMatrix is wrong //render3dSetup(); //glEndList(); //if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //assert //assertGl(); } void Renderer::render3dSetup() { //if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); const Metrics &metrics= Metrics::getInstance(); //if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //misc glViewport(0, 0, metrics.getScreenW(), metrics.getScreenH()); glClearColor(fowColor.x, fowColor.y, fowColor.z, fowColor.w); glFrontFace(GL_CW); glEnable(GL_CULL_FACE); loadProjectionMatrix(); //if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //texture state glActiveTexture(shadowTexUnit); glDisable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glActiveTexture(fowTexUnit); glDisable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glActiveTexture(baseTexUnit); glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); //if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //material state glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, defSpecularColor.ptr()); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, defAmbientColor.ptr()); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, defDiffuseColor.ptr()); glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); glColor4fv(defColor.ptr()); //blend state glDisable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //alpha test state glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.f); //depth test state glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); glDepthFunc(GL_LESS); //if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //lighting state glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); //matrix mode glMatrixMode(GL_MODELVIEW); //stencil test glDisable(GL_STENCIL_TEST); //if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //fog const Tileset *tileset= NULL; if(game != NULL && game->getWorld() != NULL) { //if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); tileset = game->getWorld()->getTileset(); } //if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); if(tileset != NULL && tileset->getFog()) { //if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); glEnable(GL_FOG); if(tileset->getFogMode()==fmExp) { glFogi(GL_FOG_MODE, GL_EXP); } else { glFogi(GL_FOG_MODE, GL_EXP2); } glFogf(GL_FOG_DENSITY, tileset->getFogDensity()); glFogfv(GL_FOG_COLOR, tileset->getFogColor().ptr()); } //if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); } void Renderer::init2dList() { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } // //this list sets the state for the 2d rendering // list2d= glGenLists(1); // assertGl(); // list2dValid=true; // // glNewList(list2d, GL_COMPILE); // render2dMenuSetup(); // glEndList(); // // assertGl(); } void Renderer::render2dMenuSetup() { //if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); const Metrics &metrics= Metrics::getInstance(); //projection glViewport(0, 0, metrics.getScreenW(), metrics.getScreenH()); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, metrics.getVirtualW(), 0, metrics.getVirtualH(), 0, 1); //if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //modelview glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //disable everything glDisable(GL_BLEND); glDisable(GL_LIGHTING); glDisable(GL_ALPHA_TEST); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); glDisable(GL_FOG); glDisable(GL_CULL_FACE); glFrontFace(GL_CCW); //if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); if(glActiveTexture != NULL) { glActiveTexture(baseTexUnit); } else { char szBuf[8096]=""; snprintf(szBuf,8096,"In [%s::%s] Line: %d\nglActiveTexture == NULL\nglActiveTexture is only supported if the GL version is 1.3 or greater,\nor if the ARB_multitexture extension is supported!",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); throw megaglest_runtime_error(szBuf); } //if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glDisable(GL_TEXTURE_2D); //if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //blend func glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //color glColor4f(1.f, 1.f, 1.f, 1.f); //if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); } //void Renderer::init3dListMenu(const MainMenu *mm) { // if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { // return; // } // // //this->mm3d = mm; // //printf("In [%s::%s Line: %d] this->custom_mm3d [%p] this->mm3d [%p]\n",__FILE__,__FUNCTION__,__LINE__,this->custom_mm3d,this->mm3d); // ///* // assertGl(); // // if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); // // const Metrics &metrics= Metrics::getInstance(); // //const MenuBackground *mb= mm->getConstMenuBackground(); // const MenuBackground *mb = NULL; // if(mm != NULL) { // mb = mm->getConstMenuBackground(); // } // // if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); // // if(this->customlist3dMenu != NULL) { // *this->customlist3dMenu = glGenLists(1); // assertGl(); // } // else { // list3dMenu= glGenLists(1); // assertGl(); // list3dMenuValid=true; // } // // if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); // // if(this->customlist3dMenu != NULL) { // glNewList(*this->customlist3dMenu, GL_COMPILE); // } // else { // glNewList(list3dMenu, GL_COMPILE); // } // // if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); // //misc // glViewport(0, 0, metrics.getScreenW(), metrics.getScreenH()); // glClearColor(0.4f, 0.4f, 0.4f, 1.f); // glFrontFace(GL_CW); // glEnable(GL_CULL_FACE); // glMatrixMode(GL_PROJECTION); // glLoadIdentity(); // gluPerspective(perspFov, metrics.getAspectRatio(), perspNearPlane, 1000000); // // //texture state // glEnable(GL_TEXTURE_2D); // glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // // //material state // glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, defSpecularColor.ptr()); // glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, defAmbientColor.ptr()); // glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, defDiffuseColor.ptr()); // glColor4fv(defColor.ptr()); // glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); // // //blend state // glDisable(GL_BLEND); // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // // //alpha test state // glEnable(GL_ALPHA_TEST); // glAlphaFunc(GL_GREATER, 0.f); // // //depth test state // glEnable(GL_DEPTH_TEST); // glDepthMask(GL_TRUE); // glDepthFunc(GL_LESS); // // //lighting state // glEnable(GL_LIGHTING); // // //matrix mode // glMatrixMode(GL_MODELVIEW); // // //stencil test // glDisable(GL_STENCIL_TEST); // // if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); // // //fog // if(mb != NULL && mb->getFog()){ // if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); // // glEnable(GL_FOG); // glFogi(GL_FOG_MODE, GL_EXP2); // glFogf(GL_FOG_DENSITY, mb->getFogDensity()); // } // // if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); // // glEndList(); // // if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); // // //assert // assertGl(); //*/ //} void Renderer::render3dMenuSetup(const MainMenu *mm) { //if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); const Metrics &metrics= Metrics::getInstance(); const MenuBackground *mb = NULL; if(mm != NULL) { mb = mm->getConstMenuBackground(); } //if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //misc glViewport(0, 0, metrics.getScreenW(), metrics.getScreenH()); glClearColor(0.4f, 0.4f, 0.4f, 1.f); glFrontFace(GL_CW); glEnable(GL_CULL_FACE); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(perspFov, metrics.getAspectRatio(), perspNearPlane, 1000000); //texture state glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); //material state glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, defSpecularColor.ptr()); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, defAmbientColor.ptr()); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, defDiffuseColor.ptr()); glColor4fv(defColor.ptr()); glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); //blend state glDisable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //alpha test state glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.f); //depth test state glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); glDepthFunc(GL_LESS); //lighting state glEnable(GL_LIGHTING); //matrix mode glMatrixMode(GL_MODELVIEW); //stencil test glDisable(GL_STENCIL_TEST); //if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //fog if(mb != NULL && mb->getFog()) { //if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); glEnable(GL_FOG); glFogi(GL_FOG_MODE, GL_EXP2); glFogf(GL_FOG_DENSITY, mb->getFogDensity()); } //assert assertGl(); //if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); } // ==================== misc ==================== void Renderer::loadProjectionMatrix() { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } GLdouble clipping; const Metrics &metrics= Metrics::getInstance(); assertGl(); clipping= photoMode ? perspFarPlane*100 : perspFarPlane; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(perspFov, metrics.getAspectRatio(), perspNearPlane, clipping); assertGl(); } void Renderer::enableProjectiveTexturing() { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } glTexGenfv(GL_S, GL_EYE_PLANE, &shadowMapMatrix[0]); glTexGenfv(GL_T, GL_EYE_PLANE, &shadowMapMatrix[4]); glTexGenfv(GL_R, GL_EYE_PLANE, &shadowMapMatrix[8]); glTexGenfv(GL_Q, GL_EYE_PLANE, &shadowMapMatrix[12]); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glEnable(GL_TEXTURE_GEN_R); glEnable(GL_TEXTURE_GEN_Q); } // ==================== private aux drawing ==================== void Renderer::renderHealthBar(Vec3f v, Unit *unit, float height, bool lineBorder, const Texture2D *texture, const Texture2D *backgroundTexture) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } int numberOfBars=1; int barCount=0; float hp=unit->getHpRatio(); float ep=-1.f; if(unit->getType()->getTotalMaxEp(unit->getTotalUpgrade()) !=0 ) { ep=unit->getEpRatio(); numberOfBars++; } int productionPercent=unit->getProductionPercent(); if(productionPercent!=-1) { numberOfBars++; } int size=unit->getType()->getSize(); Vec3f rightVector; Vec3f upVector; Vec3f rightVectorTexture; Vec3f upVectorTexture; v.y+=1; float modelview[16]; float width=(float)size/6+0.25f; float red; float green; float brightness=0.8f; glMatrixMode(GL_MODELVIEW); glPushMatrix(); // get the current modelview state glGetFloatv(GL_MODELVIEW_MATRIX , modelview); rightVector= Vec3f(modelview[0], modelview[4], modelview[8]); upVector= Vec3f(modelview[1], modelview[5], modelview[9]); rightVectorTexture=rightVector*2; upVectorTexture=upVector*4; //from green to yellow to red if(hp >= 0.75f) { green=1; red=1-((2*hp-1)-0.5f); } else { red=1; green=0.5f+(2*hp-1); } if(red>1.0f) red=1.0f; if(green>1.0f) green=1.0f; float yOffset=(float)numberOfBars/2.f; if(backgroundTexture!=NULL) { //backgroundTexture glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, static_cast(backgroundTexture)->getHandle()); glColor4f(1.f,1.f,1.f,1.f); //glColor4f(red+0.1f,green+0.1f,0.1f,0.5f); glBegin(GL_QUADS); glTexCoord2i(0,1); glVertex3fv((v - (rightVectorTexture*width - upVectorTexture*height*yOffset)).ptr()); glTexCoord2i(0,0); glVertex3fv((v - (rightVectorTexture*width + upVectorTexture*height*yOffset)).ptr()); glTexCoord2i(1,0); glVertex3fv((v + (rightVectorTexture*width - upVectorTexture*height*yOffset)).ptr()); glTexCoord2i(1,1); glVertex3fv((v + (rightVectorTexture*width + upVectorTexture*height*yOffset)).ptr()); glEnd(); glDisable(GL_TEXTURE_2D); } //healthbar glColor4f(red*brightness,green*brightness,0.0f,0.4f); //hpbar barCount++; internalRenderHp(numberOfBars,barCount,hp,v,width,height,rightVector,upVector); if(ep > -1.0f) { //epbar barCount++; //glColor4f(brightness,0,brightness,0.5f); glColor4f(.15f*brightness,0.3f*brightness,0.8f*brightness,0.7f); internalRenderHp(numberOfBars,barCount,ep,v,width,height,rightVector,upVector); } if(productionPercent!=-1) { barCount++; glColor4f(brightness,0,brightness,0.6f); //glColor4f(0.0f*brightness,0.4f*brightness,0.2f*brightness,0.8f); internalRenderHp(numberOfBars,barCount,(float)productionPercent/100,v,width,height,rightVector,upVector); } // glBegin(GL_QUADS); // if(ep < -2.0f) { // //hpbar // glVertex3fv((v - (rightVector*width - upVector*height)).ptr()); // glVertex3fv((v - (rightVector*width + upVector*height)).ptr()); // glVertex3fv((v + (rightVector*hp*width - upVector*height)).ptr()); // glVertex3fv((v + (rightVector*hp*width + upVector*height)).ptr()); // // } else { // //hpbar // glVertex3fv((v - (rightVector*width - upVector*height)).ptr()); // glVertex3fv((v - (rightVector*width + upVector*height*0.0f)).ptr()); // glVertex3fv((v + (rightVector*hp*width - upVector*height*0.0f)).ptr()); // glVertex3fv((v + (rightVector*hp*width + upVector*height)).ptr()); // //epbar // glColor4f(brightness,0,brightness,0.4f); // glVertex3fv((v - (rightVector*width + upVector*height*0.0f)).ptr()); // glVertex3fv((v - (rightVector*width + upVector*height)).ptr()); // glVertex3fv((v + (rightVector*ep*width - upVector*height)).ptr()); // glVertex3fv((v + (rightVector*ep*width - upVector*height*0.0f)).ptr()); // } // glEnd(); if(lineBorder) { //border glColor4f(red*brightness,green*brightness,0.1f*brightness,0.5f); glBegin(GL_LINE_LOOP); glVertex3fv((v - (rightVector*width - upVector*height*yOffset)).ptr()); glVertex3fv((v - (rightVector*width + upVector*height*yOffset)).ptr()); glVertex3fv((v + (rightVector*width - upVector*height*yOffset)).ptr()); glVertex3fv((v + (rightVector*width + upVector*height*yOffset)).ptr()); glEnd(); } if(texture!=NULL) { //BorderTexture glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, static_cast(texture)->getHandle()); glColor4f(1.f,1.f,1.f,1.f); //glColor4f(red+0.1f,green+0.1f,0.1f,0.5f); glBegin(GL_QUADS); glTexCoord2i(0,1); glVertex3fv((v - (rightVectorTexture*width - upVectorTexture*height*yOffset)).ptr()); glTexCoord2i(0,0); glVertex3fv((v - (rightVectorTexture*width + upVectorTexture*height*yOffset)).ptr()); glTexCoord2i(1,0); glVertex3fv((v + (rightVectorTexture*width - upVectorTexture*height*yOffset)).ptr()); glTexCoord2i(1,1); glVertex3fv((v + (rightVectorTexture*width + upVectorTexture*height*yOffset)).ptr()); glEnd(); glDisable(GL_TEXTURE_2D); } glPopMatrix(); } void Renderer::internalRenderHp(int numberOfBars, int barNumber, float hp, Vec3f posVector, float width, float singleHPheight, Vec3f rightVector, Vec3f upVector) { float yOffset=(float)numberOfBars*singleHPheight/2; float offsetTop=yOffset-singleHPheight*(barNumber-1); float offsetBottom=yOffset-singleHPheight*barNumber; offsetBottom=offsetBottom*-1; hp=hp*2-1; glBegin(GL_QUADS); glVertex3fv((posVector - (rightVector*width - upVector*offsetTop)).ptr()); glVertex3fv((posVector - (rightVector*width + upVector*offsetBottom)).ptr()); glVertex3fv((posVector + (rightVector*hp*width - upVector*offsetBottom)).ptr()); glVertex3fv((posVector + (rightVector*hp*width + upVector*offsetTop)).ptr()); glEnd(); } void Renderer::renderSelectionCircle(Vec3f v, int size, float radius, float thickness) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } GLUquadricObj *disc; glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(v.x, v.y, v.z); glRotatef(90.f, 1.f, 0.f, 0.f); disc= gluNewQuadric(); gluQuadricDrawStyle(disc, GLU_FILL); gluCylinder(disc, radius*(size-thickness), radius*size, thickness, 30, 1); gluDeleteQuadric(disc); glPopMatrix(); // glBegin (GL_QUAD_STRIP); // for (float k = 0; k <= 180; k=k+1) { // float j=degToRad(k); // glVertex3f(v.x+std::cos(j)*.9*radius*size, v.y+thickness, v.z+std::sin(j)*.9*radius*size); // glVertex3f(v.x+std::cos(j)*radius*size, v.y, v.z+std::sin(j)*radius*size); // } // glEnd(); } void Renderer::renderArrow(const Vec3f &pos1, const Vec3f &pos2, const Vec3f &color, float width) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } Config &config= Config::getInstance(); if(config.getBool("RecordMode","false") == true) { return; } const int tesselation= 3; const float arrowEndSize= 0.4f; const float maxlen= 25; const float blendDelay= 5.f; Vec3f dir= Vec3f(pos2-pos1); float len= dir.length(); if(len>maxlen) { return; } float alphaFactor= clamp((maxlen-len)/blendDelay, 0.f, 1.f); dir.normalize(); Vec3f normal= dir.cross(Vec3f(0, 1, 0)); Vec3f pos2Left= pos2 + normal*(width-0.05f) - dir*arrowEndSize*width; Vec3f pos2Right= pos2 - normal*(width-0.05f) - dir*arrowEndSize*width; Vec3f pos1Left= pos1 + normal*(width+0.05f); Vec3f pos1Right= pos1 - normal*(width+0.05f); //arrow body glBegin(GL_TRIANGLE_STRIP); for(int i=0; i<=tesselation; ++i) { float t= static_cast(i)/tesselation; Vec3f a= pos1Left.lerp(t, pos2Left); Vec3f b= pos1Right.lerp(t, pos2Right); Vec4f c= Vec4f(color, t*0.25f*alphaFactor); glColor4fv(c.ptr()); glVertex3fv(a.ptr()); glVertex3fv(b.ptr()); } glEnd(); //arrow end glBegin(GL_TRIANGLES); glVertex3fv((pos2Left + normal*(arrowEndSize-0.1f)).ptr()); glVertex3fv((pos2Right - normal*(arrowEndSize-0.1f)).ptr()); glVertex3fv((pos2 + dir*(arrowEndSize-0.1f)).ptr()); glEnd(); } void Renderer::renderProgressBar3D(int size, int x, int y, Font3D *font, int customWidth, string prefixLabel,bool centeredText,int customHeight) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } // Makiong this smaller than 14 is a bad idea (since the font size is never smaller than that) int progressbarHeight = (customHeight > 0 ? customHeight : 14); int currentSize = size; int maxSize = maxProgressBar; string renderText = intToStr(static_cast(size)) + "%"; if(customWidth > 0) { if(size > 0) { currentSize = (int)((double)customWidth * ((double)size / 100.0)); } maxSize = customWidth; //if(maxSize <= 0) { // maxSize = maxProgressBar; //} } if(prefixLabel != "") { renderText = prefixLabel + renderText; } //bar glBegin(GL_QUADS); glColor4fv(progressBarFront2.ptr()); glVertex2i(x, y); glVertex2i(x, y + progressbarHeight); glColor4fv(progressBarFront1.ptr()); glVertex2i(x + currentSize, y + progressbarHeight); glVertex2i(x + currentSize, y); glEnd(); //transp bar glEnable(GL_BLEND); glBegin(GL_QUADS); glColor4fv(progressBarBack2.ptr()); glVertex2i(x + currentSize, y); glVertex2i(x + currentSize, y + progressbarHeight); glColor4fv(progressBarBack1.ptr()); glVertex2i(x + maxSize, y + progressbarHeight); glVertex2i(x + maxSize, y); glEnd(); glDisable(GL_BLEND); //text //glColor3fv(defColor.ptr()); //printf("Render progress bar3d renderText [%s] y = %d, centeredText = %d\n",renderText.c_str(),y, centeredText); renderTextBoundingBox3D(renderText, font, defColor, x, y, maxSize, progressbarHeight, true, true, false,-1,-1); } void Renderer::renderProgressBar(int size, int x, int y, Font2D *font, int customWidth, string prefixLabel,bool centeredText) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } int currentSize = size; int maxSize = maxProgressBar; string renderText = intToStr(static_cast(size)) + "%"; if(customWidth > 0) { if(size > 0) { currentSize = (int)((double)customWidth * ((double)size / 100.0)); } maxSize = customWidth; //if(maxSize <= 0) { // maxSize = maxProgressBar; //} } if(prefixLabel != "") { renderText = prefixLabel + renderText; } //bar glBegin(GL_QUADS); glColor4fv(progressBarFront2.ptr()); glVertex2i(x, y); glVertex2i(x, y+10); glColor4fv(progressBarFront1.ptr()); glVertex2i(x + currentSize, y+10); glVertex2i(x + currentSize, y); glEnd(); //transp bar glEnable(GL_BLEND); glBegin(GL_QUADS); glColor4fv(progressBarBack2.ptr()); glVertex2i(x + currentSize, y); glVertex2i(x + currentSize, y+10); glColor4fv(progressBarBack1.ptr()); glVertex2i(x + maxSize, y+10); glVertex2i(x + maxSize, y); glEnd(); glDisable(GL_BLEND); //text glColor3fv(defColor.ptr()); //textRenderer->begin(font); TextRendererSafeWrapper safeTextRender(textRenderer,font); if(centeredText == true) { textRenderer->render(renderText.c_str(), x + maxSize / 2, y, centeredText); } else { textRenderer->render(renderText.c_str(), x, y, centeredText); } //textRenderer->end(); safeTextRender.end(); } //void Renderer::renderTile(const Vec2i &pos) { // if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { // return; // } // // const Map *map= game->getWorld()->getMap(); // Vec2i scaledPos= pos * Map::cellScale; // // glMatrixMode(GL_MODELVIEW); // glPushMatrix(); // glTranslatef(-0.5f, 0.f, -0.5f); // // glInitNames(); // for(int i=0; i < Map::cellScale; ++i) { // for(int j=0; j < Map::cellScale; ++j) { // // Vec2i renderPos= scaledPos + Vec2i(i, j); // // glPushName(renderPos.y); // glPushName(renderPos.x); // // glDisable(GL_CULL_FACE); // // float h1 = map->getCell(renderPos.x, renderPos.y)->getHeight(); // float h2 = map->getCell(renderPos.x, renderPos.y+1)->getHeight(); // float h3 = map->getCell(renderPos.x+1, renderPos.y)->getHeight(); // float h4 = map->getCell(renderPos.x+1, renderPos.y+1)->getHeight(); // // glBegin(GL_TRIANGLE_STRIP); // glVertex3f( // static_cast(renderPos.x), // h1, // static_cast(renderPos.y)); // glVertex3f( // static_cast(renderPos.x), // h2, // static_cast(renderPos.y+1)); // glVertex3f( // static_cast(renderPos.x+1), // h3, // static_cast(renderPos.y)); // glVertex3f( // static_cast(renderPos.x+1), // h4, // static_cast(renderPos.y+1)); // glEnd(); // // glPopName(); // glPopName(); // } // } // // glPopMatrix(); //} void Renderer::renderQuad(int x, int y, int w, int h, const Texture2D *texture) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(texture == NULL) { printf("\n**WARNING** detected a null texture to render in renderQuad!\n"); return; } if(w < 0) { w = texture->getPixmapConst()->getW(); } if(h < 0) { h = texture->getPixmapConst()->getH(); } glBindTexture(GL_TEXTURE_2D, static_cast(texture)->getHandle()); glBegin(GL_TRIANGLE_STRIP); glTexCoord2i(0, 1); glVertex2i(x, y+h); glTexCoord2i(0, 0); glVertex2i(x, y); glTexCoord2i(1, 1); glVertex2i(x+w, y+h); glTexCoord2i(1, 0); glVertex2i(x+w, y); glEnd(); } Renderer::Shadows Renderer::strToShadows(const string &s){ if(s=="Projected"){ return sProjected; } else if(s=="ShadowMapping"){ return sShadowMapping; } return sDisabled; } string Renderer::shadowsToStr(Shadows shadows){ switch(shadows){ case sDisabled: return "Disabled2"; case sProjected: return "Projected"; case sShadowMapping: return "ShadowMapping"; default: assert(false); return ""; } } Texture2D::Filter Renderer::strToTextureFilter(const string &s){ if(s=="Bilinear"){ return Texture2D::fBilinear; } else if(s=="Trilinear"){ return Texture2D::fTrilinear; } throw megaglest_runtime_error("Error converting from string to FilterType, found: "+s); } void Renderer::setAllowRenderUnitTitles(bool value) { allowRenderUnitTitles = value; } // This method renders titles for units void Renderer::renderUnitTitles3D(Font3D *font, Vec3f color) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } //std::map unitRenderedList; if(visibleFrameUnitList.empty() == false) { //printf("Render Unit titles ON\n"); for(int idx = 0; idx < (int)visibleFrameUnitList.size(); idx++) { const Unit *unit = visibleFrameUnitList[idx]; if(unit != NULL) { if(unit->getVisible() == true) { if(unit->getCurrentUnitTitle() != "") { //get the screen coordinates Vec3f screenPos = unit->getScreenPos(); renderText3D(unit->getCurrentUnitTitle(), font, color, std::fabs(screenPos.x) + 5, std::fabs(screenPos.y) + 5, false); //unitRenderedList[unit->getId()] = true; } else { string str = unit->getFullName(unit->showTranslatedTechTree()) + " - " + intToStr(unit->getId()) + " [" + unit->getPosNotThreadSafe().getString() + "]"; Vec3f screenPos = unit->getScreenPos(); renderText3D(str, font, color, std::fabs(screenPos.x) + 5, std::fabs(screenPos.y) + 5, false); } } } } visibleFrameUnitList.clear(); } /* if(renderUnitTitleList.empty() == false) { for(int idx = 0; idx < renderUnitTitleList.size(); idx++) { std::pair &unitInfo = renderUnitTitleList[idx]; Unit *unit = unitInfo.first; const World *world= game->getWorld(); Unit *validUnit = world->findUnitById(unit->getId()); if(validUnit != NULL && unitRenderedList.find(validUnit->getId()) == unitRenderedList.end()) { string str = validUnit->getFullName() + " - " + intToStr(validUnit->getId()); //get the screen coordinates Vec3f &screenPos = unitInfo.second; renderText(str, font, color, fabs(screenPos.x) + 5, fabs(screenPos.y) + 5, false); //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] screenPos.x = %f, screenPos.y = %f, screenPos.z = %f\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,screenPos.x,screenPos.y,screenPos.z); } } renderUnitTitleList.clear(); } */ } // This method renders titles for units void Renderer::renderUnitTitles(Font2D *font, Vec3f color) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } //std::map unitRenderedList; if(visibleFrameUnitList.empty() == false) { //printf("Render Unit titles ON\n"); for(int idx = 0; idx < (int)visibleFrameUnitList.size(); idx++) { const Unit *unit = visibleFrameUnitList[idx]; if(unit != NULL) { if(unit->getCurrentUnitTitle() != "") { //get the screen coordinates Vec3f screenPos = unit->getScreenPos(); renderText(unit->getCurrentUnitTitle(), font, color, std::fabs(screenPos.x) + 5, std::fabs(screenPos.y) + 5, false); //unitRenderedList[unit->getId()] = true; } else { string str = unit->getFullName(unit->showTranslatedTechTree()) + " - " + intToStr(unit->getId()) + " [" + unit->getPosNotThreadSafe().getString() + "]"; Vec3f screenPos = unit->getScreenPos(); renderText(str, font, color, std::fabs(screenPos.x) + 5, std::fabs(screenPos.y) + 5, false); } } } visibleFrameUnitList.clear(); } /* if(renderUnitTitleList.empty() == false) { for(int idx = 0; idx < renderUnitTitleList.size(); idx++) { std::pair &unitInfo = renderUnitTitleList[idx]; Unit *unit = unitInfo.first; const World *world= game->getWorld(); Unit *validUnit = world->findUnitById(unit->getId()); if(validUnit != NULL && unitRenderedList.find(validUnit->getId()) == unitRenderedList.end()) { string str = validUnit->getFullName() + " - " + intToStr(validUnit->getId()); //get the screen coordinates Vec3f &screenPos = unitInfo.second; renderText(str, font, color, fabs(screenPos.x) + 5, fabs(screenPos.y) + 5, false); //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] screenPos.x = %f, screenPos.y = %f, screenPos.z = %f\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,screenPos.x,screenPos.y,screenPos.z); } } renderUnitTitleList.clear(); } */ } void Renderer::removeObjectFromQuadCache(const Object *o) { VisibleQuadContainerCache &qCache = getQuadCache(); for(int visibleIndex = 0; visibleIndex < (int)qCache.visibleObjectList.size(); ++visibleIndex) { Object *currentObj = qCache.visibleObjectList[visibleIndex]; if(currentObj == o) { qCache.visibleObjectList.erase(qCache.visibleObjectList.begin() + visibleIndex); break; } } } void Renderer::removeUnitFromQuadCache(const Unit *unit) { VisibleQuadContainerCache &qCache = getQuadCache(); for(int visibleIndex = 0; visibleIndex < (int)qCache.visibleQuadUnitList.size(); ++visibleIndex) { Unit *currentUnit = qCache.visibleQuadUnitList[visibleIndex]; if(currentUnit == unit) { qCache.visibleQuadUnitList.erase(qCache.visibleQuadUnitList.begin() + visibleIndex); break; } } for(int visibleIndex = 0; visibleIndex < (int)qCache.visibleUnitList.size(); ++visibleIndex) { Unit *currentUnit = qCache.visibleUnitList[visibleIndex]; if(currentUnit == unit) { qCache.visibleUnitList.erase(qCache.visibleUnitList.begin() + visibleIndex); break; } } } VisibleQuadContainerCache & Renderer::getQuadCache( bool updateOnDirtyFrame, bool forceNew) { //forceNew = true; if(game != NULL && game->getWorld() != NULL) { const World *world= game->getWorld(); if(forceNew == true || (updateOnDirtyFrame == true && (world->getFrameCount() != quadCache.cacheFrame || visibleQuad != quadCache.lastVisibleQuad))) { // Dump cached info //if(forceNew == true || visibleQuad != quadCache.lastVisibleQuad) { //quadCache.clearCacheData(); //} //else { quadCache.clearVolatileCacheData(); worldToScreenPosCache.clear(); //} // Unit calculations for(int i = 0; i < world->getFactionCount(); ++i) { const Faction *faction = world->getFaction(i); for(int j = 0; j < faction->getUnitCount(); ++j) { Unit *unit= faction->getUnit(j); bool unitCheckedForRender = false; if(VisibleQuadContainerCache::enableFrustumCalcs == true) { //bool insideQuad = PointInFrustum(quadCache.frustumData, unit->getCurrVector().x, unit->getCurrVector().y, unit->getCurrVector().z ); bool insideQuad = CubeInFrustum(quadCache.frustumData, unit->getCurrMidHeightVector().x, unit->getCurrMidHeightVector().y, unit->getCurrMidHeightVector().z, unit->getType()->getRenderSize()); bool renderInMap = world->toRenderUnit(unit); if(insideQuad == false || renderInMap == false) { unit->setVisible(false); if(renderInMap == true) { quadCache.visibleUnitList.push_back(unit); } unitCheckedForRender = true; // no more need to check any further; // Currently don't need this list //quadCache.inVisibleUnitList.push_back(unit); } } if(unitCheckedForRender == false) { bool insideQuad = visibleQuad.isInside(unit->getPos()); bool renderInMap = world->toRenderUnit(unit); if(insideQuad == true && renderInMap == true) { quadCache.visibleQuadUnitList.push_back(unit); } else { unit->setVisible(false); // Currently don't need this list //quadCache.inVisibleUnitList.push_back(unit); } if(renderInMap == true) { quadCache.visibleUnitList.push_back(unit); } } bool unitBuildPending = unit->isBuildCommandPending(); if(unitBuildPending == true) { const UnitBuildInfo &pendingUnit = unit->getBuildCommandPendingInfo(); const Vec2i &pos = pendingUnit.pos; const Map *map= world->getMap(); bool unitBuildCheckedForRender = false; //printf("#1 Unit is about to build another unit\n"); if(VisibleQuadContainerCache::enableFrustumCalcs == true) { Vec3f pos3f= Vec3f(pos.x, map->getCell(pos)->getHeight(), pos.y); //bool insideQuad = PointInFrustum(quadCache.frustumData, unit->getCurrVector().x, unit->getCurrVector().y, unit->getCurrVector().z ); bool insideQuad = CubeInFrustum(quadCache.frustumData, pos3f.x, pos3f.y, pos3f.z, pendingUnit.buildUnit->getRenderSize()); bool renderInMap = world->toRenderUnit(pendingUnit); if(insideQuad == false || renderInMap == false) { if(renderInMap == true) { quadCache.visibleQuadUnitBuildList.push_back(pendingUnit); } unitBuildCheckedForRender = true; // no more need to check any further; // Currently don't need this list //quadCache.inVisibleUnitList.push_back(unit); } //printf("#2 Unit build added? insideQuad = %d, renderInMap = %d\n",insideQuad,renderInMap); } if(unitBuildCheckedForRender == false) { bool insideQuad = visibleQuad.isInside(pos); bool renderInMap = world->toRenderUnit(pendingUnit); if(insideQuad == true && renderInMap == true) { quadCache.visibleQuadUnitBuildList.push_back(pendingUnit); } else { //unit->setVisible(false); // Currently don't need this list //quadCache.inVisibleUnitList.push_back(unit); } //printf("#3 Unit build added? insideQuad = %d, renderInMap = %d\n",insideQuad,renderInMap); } //printf("#4 quadCache.visibleQuadUnitBuildList.size() = %d\n",quadCache.visibleQuadUnitBuildList.size()); } } } if(forceNew == true || visibleQuad != quadCache.lastVisibleQuad) { // Object calculations const Map *map= world->getMap(); // clear visibility of old objects for(int visibleIndex = 0; visibleIndex < (int)quadCache.visibleObjectList.size(); ++visibleIndex){ quadCache.visibleObjectList[visibleIndex]->setVisible(false); } quadCache.clearNonVolatileCacheData(); //int loops1=0; PosQuadIterator pqi(map,visibleQuad, Map::cellScale); while(pqi.next()) { const Vec2i &pos= pqi.getPos(); if(map->isInside(pos)) { //loops1++; const Vec2i &mapPos = Map::toSurfCoords(pos); //quadCache.visibleCellList.push_back(mapPos); SurfaceCell *sc = map->getSurfaceCell(mapPos); Object *o = sc->getObject(); if(VisibleQuadContainerCache::enableFrustumCalcs == true) { if(o != NULL) { //bool insideQuad = PointInFrustum(quadCache.frustumData, o->getPos().x, o->getPos().y, o->getPos().z ); bool insideQuad = CubeInFrustum(quadCache.frustumData, o->getPos().x, o->getPos().y, o->getPos().z, 1); if(insideQuad == false) { o->setVisible(false); continue; } } } bool cellExplored = world->showWorldForPlayer(world->getThisFactionIndex()); if(cellExplored == false) { cellExplored = sc->isExplored(world->getThisTeamIndex()); } bool isExplored = (cellExplored == true && o != NULL); //bool isVisible = (sc->isVisible(world->getThisTeamIndex()) && o != NULL); bool isVisible = true; if(isExplored == true && isVisible == true) { quadCache.visibleObjectList.push_back(o); o->setVisible(true); } } } //printf("Frame # = %d loops1 = %d\n",world->getFrameCount(),loops1); //int loops2=0; std::map markedCells = game->getMapMarkedCellList(); const Rect2i mapBounds(0, 0, map->getSurfaceW()-1, map->getSurfaceH()-1); Quad2i scaledQuad = visibleQuad / Map::cellScale; PosQuadIterator pqis(map,scaledQuad); while(pqis.next()) { const Vec2i &pos= pqis.getPos(); if(mapBounds.isInside(pos)) { //loops2++; if(VisibleQuadContainerCache::enableFrustumCalcs == false) { quadCache.visibleScaledCellList.push_back(pos); if(markedCells.empty() == false) { if(markedCells.find(pos) != markedCells.end()) { //printf("#1 ******** VISIBLE SCALED CELL FOUND in marked list pos [%s] markedCells.size() = " MG_SIZE_T_SPECIFIER "\n",pos.getString().c_str(),markedCells.size()); //if(markedCells.empty() == false) { //SurfaceCell *sc = map->getSurfaceCell(pos); //quadCache.visibleScaledCellToScreenPosList[pos]=computeScreenPosition(sc->getVertex()); updateMarkedCellScreenPosQuadCache(pos); } else { //printf("#1 VISIBLE SCALED CELL NOT FOUND in marked list pos [%s] markedCells.size() = " MG_SIZE_T_SPECIFIER "\n",pos.getString().c_str(),markedCells.size()); } } } else { //bool insideQuad = false; //if( !insideQuad) { SurfaceCell *sc = map->getSurfaceCell(pos.x, pos.y); bool insideQuad = CubeInFrustum(quadCache.frustumData, sc->getVertex().x, sc->getVertex().y, sc->getVertex().z, 0); //} if( !insideQuad) { SurfaceCell *sc = map->getSurfaceCell(pos.x+1, pos.y); insideQuad = CubeInFrustum(quadCache.frustumData, sc->getVertex().x, sc->getVertex().y, sc->getVertex().z, 0); } if( !insideQuad) { SurfaceCell *sc = map->getSurfaceCell(pos.x, pos.y+1); insideQuad = CubeInFrustum(quadCache.frustumData, sc->getVertex().x, sc->getVertex().y, sc->getVertex().z, 0); } if( !insideQuad) { SurfaceCell *sc = map->getSurfaceCell(pos.x+1, pos.y+1); insideQuad = CubeInFrustum(quadCache.frustumData, sc->getVertex().x, sc->getVertex().y, sc->getVertex().z, 0); } if(insideQuad == true) { quadCache.visibleScaledCellList.push_back(pos); if(markedCells.empty() == false) { if(markedCells.find(pos) != markedCells.end()) { //printf("#2 ******** VISIBLE SCALED CELL FOUND in marked list pos [%s] markedCells.size() = " MG_SIZE_T_SPECIFIER "\n",pos.getString().c_str(),markedCells.size()); //if(markedCells.empty() == false) { //quadCache.visibleScaledCellToScreenPosList[pos]=computeScreenPosition(sc->getVertex()); updateMarkedCellScreenPosQuadCache(pos); } else { //printf("#2 VISIBLE SCALED CELL NOT FOUND in marked list pos [%s] markedCells.size() = " MG_SIZE_T_SPECIFIER "\n",pos.getString().c_str(),markedCells.size()); } } } } } } //printf("Frame # = %d loops2 = %d\n",world->getFrameCount(),loops2); } quadCache.cacheFrame = world->getFrameCount(); quadCache.lastVisibleQuad = visibleQuad; } } return quadCache; } void Renderer::updateMarkedCellScreenPosQuadCache(Vec2i pos) { const World *world= game->getWorld(); const Map *map= world->getMap(); SurfaceCell *sc = map->getSurfaceCell(pos); quadCache.visibleScaledCellToScreenPosList[pos]=computeScreenPosition(sc->getVertex()); } void Renderer::forceQuadCacheUpdate() { quadCache.cacheFrame = -1; Vec2i clearPos(-1,-1); quadCache.lastVisibleQuad.p[0] = clearPos; quadCache.lastVisibleQuad.p[1] = clearPos; quadCache.lastVisibleQuad.p[2] = clearPos; quadCache.lastVisibleQuad.p[3] = clearPos; } std::pair Renderer::posInCellQuadCache(Vec2i pos) { std::pair result = make_pair(false,Vec3f()); if(std::find( quadCache.visibleScaledCellList.begin(), quadCache.visibleScaledCellList.end(), pos) != quadCache.visibleScaledCellList.end()) { result.first = true; result.second = quadCache.visibleScaledCellToScreenPosList[pos]; } return result; } //Vec3f Renderer::getMarkedCellScreenPosQuadCache(Vec2i pos) { // Vec3f result(-1,-1,-1); // if(std::find( // quadCache.visibleScaledCellList.begin(), // quadCache.visibleScaledCellList.end(), // pos) != quadCache.visibleScaledCellList.end()) { // result = quadCache.visibleScaledCellToScreenPosList[pos]; // } // return result; //} void Renderer::beginRenderToTexture(Texture2D **renderToTexture) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } static bool supportFBOs = Texture2DGl().supports_FBO_RBO(); if(supportFBOs == true && renderToTexture != NULL) { Config &config= Config::getInstance(); Texture2D::Filter textureFilter = strToTextureFilter(config.getString("Filter")); int maxAnisotropy = config.getInt("FilterMaxAnisotropy"); const Metrics &metrics = Metrics::getInstance(); *renderToTexture = GraphicsInterface::getInstance().getFactory()->newTexture2D(); Texture2DGl *texture = static_cast(*renderToTexture); texture->setMipmap(false); Pixmap2D *pixmapScreenShot = texture->getPixmap(); pixmapScreenShot->init(metrics.getScreenW(), metrics.getScreenH(), 4); texture->setForceCompressionDisabled(true); texture->init(textureFilter,maxAnisotropy); texture->setup_FBO_RBO(); assertGl(); if(texture->checkFrameBufferStatus() == false) { //printf("******************** WARNING CANNOT Attach to FBO!\n"); texture->end(); delete texture; *renderToTexture=NULL; } } } void Renderer::endRenderToTexture(Texture2D **renderToTexture) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } static bool supportFBOs = Texture2DGl().supports_FBO_RBO(); if(supportFBOs == true && renderToTexture != NULL && *renderToTexture != NULL) { Texture2DGl *texture = static_cast(*renderToTexture); if(texture != NULL) { texture->dettachFrameBufferFromTexture(); } assertGl(); } } void Renderer::renderMapPreview( const MapPreview *map, bool renderAll, int screenPosX, int screenPosY, Texture2D **renderToTexture) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } static bool supportFBOs = Texture2DGl().supports_FBO_RBO(); if(Config::getInstance().getBool("LegacyMapPreviewRendering","false") == true) { supportFBOs = false; } //static bool supportFBOs = false; const Metrics &metrics= Metrics::getInstance(); float alt = 0; float showWater = 0; int renderMapHeight = 64; int renderMapWidth = 64; float cellSize = 2; float playerCrossSize = 2; float clientW = renderMapWidth * cellSize; float clientH = renderMapHeight * cellSize;; float minDimension = std::min(metrics.getVirtualW(), metrics.getVirtualH()); // stretch small maps to 128x128 if(map->getW() < map->getH()) { cellSize = cellSize * renderMapHeight / map->getH(); } else { cellSize = cellSize * renderMapWidth / map->getW(); } assertGl(); if(supportFBOs == true && 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->setMipmap(false); Pixmap2D *pixmapScreenShot = texture->getPixmap(); pixmapScreenShot->init(minDimension, minDimension, 4); texture->setForceCompressionDisabled(true); texture->init(textureFilter,maxAnisotropy); texture->setup_FBO_RBO(); assertGl(); if(texture->checkFrameBufferStatus() == false) { //printf("******************** WARNING CANNOT Attach to FBO!\n"); texture->end(); delete texture; *renderToTexture=NULL; } } if(supportFBOs == true && renderToTexture != NULL && *renderToTexture != NULL) { cellSize =1; clientW = minDimension; clientH = minDimension; int mapMaxDimensionSize = std::max(map->getW(),map->getH()); switch(mapMaxDimensionSize) { case 8: cellSize = 96; break; case 16: cellSize = 48; break; case 32: cellSize = 24; break; case 64: cellSize = 12; break; case 128: cellSize = 6; break; case 256: cellSize = 3; break; case 512: cellSize = 2; break; } } glFrontFace(GL_CW); glEnable(GL_CULL_FACE); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); assertGl(); GLint viewport[4]; // Where The original Viewport Values Will Be Stored if(supportFBOs == true && renderToTexture != NULL && *renderToTexture != NULL) { glGetIntegerv(GL_VIEWPORT, viewport); glOrtho(0, clientW, 0, clientH, 0, 1); glViewport(0, 0, clientW, clientH); } else { glOrtho(0, metrics.getVirtualW(), 0, metrics.getVirtualH(), 0, 1); } glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); if(supportFBOs == false || renderToTexture == NULL || *renderToTexture == NULL) { glTranslatef(static_cast(screenPosX),static_cast(screenPosY)-clientH,0.0f); } assertGl(); glPushAttrib(GL_CURRENT_BIT); glLineWidth(1); glColor3f(0, 0, 0); for (int j = 0; j < map->getH(); j++) { for (int i = 0; i < map->getW(); i++) { //surface alt = map->getHeight(i, j) / 20.f; showWater = map->getWaterLevel()/ 20.f - alt; 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; } glColor3fv(surfColor.ptr()); glBegin(GL_TRIANGLE_STRIP); glVertex2f(i * cellSize, clientH - j * cellSize - cellSize); glVertex2f(i * cellSize, clientH - j * cellSize); glVertex2f(i * cellSize + cellSize, clientH - j * cellSize - cellSize); glVertex2f(i * cellSize + cellSize, clientH - j * cellSize); glEnd(); //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 } 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); glEnd(); } } // bool found = false; //height lines // if (!found) { //left if (i > 0 && map->getHeight(i - 1, j) > map->getHeight(i, j)) { glColor3fv((surfColor*0.5f).ptr()); glBegin(GL_LINES); glVertex2f(i * cellSize, clientH - (j + 1) * cellSize); glVertex2f(i * cellSize, clientH - j * cellSize); glEnd(); } //down if (j > 0 && map->getHeight(i, j - 1) > map->getHeight(i, j)) { glColor3fv((surfColor*0.5f).ptr()); glBegin(GL_LINES); glVertex2f(i * cellSize, clientH - j * cellSize); glVertex2f((i + 1) * cellSize, clientH - j * cellSize); glEnd(); } //left if (i > 0 && map->getHeight(i - 1, j) < map->getHeight(i, j)) { glColor3fv((surfColor*2.f).ptr()); glBegin(GL_LINES); glVertex2f(i * cellSize, clientH - (j + 1) * cellSize); glVertex2f(i * cellSize, clientH - j * cellSize); glEnd(); } if (j > 0 && map->getHeight(i, j - 1) < map->getHeight(i, j)) { glColor3fv((surfColor*2.f).ptr()); glBegin(GL_LINES); glVertex2f(i * cellSize, clientH - j * cellSize); glVertex2f((i + 1) * cellSize, clientH - j * cellSize); glEnd(); } // } //resources if(renderAll == true) { switch (map->getResource(i, j)) { case 1: glColor3f(1.f, 1.f, 0.f); break; case 2: glColor3f(0.5f, 0.5f, 0.5f); break; case 3: glColor3f(1.f, 0.f, 0.f); break; case 4: glColor3f(0.f, 0.f, 1.f); break; case 5: glColor3f(0.5f, 0.5f, 1.f); break; } if (renderAll && map->getResource(i, j) != 0) { glBegin(GL_LINES); glVertex2f(i * cellSize, clientH - j * cellSize - cellSize); glVertex2f(i * cellSize + cellSize, clientH - j * cellSize); glVertex2f(i * cellSize, clientH - j * cellSize); glVertex2f(i * cellSize + cellSize, clientH - j * cellSize - cellSize); glEnd(); } } } } //start locations glLineWidth(3); assertGl(); if(supportFBOs == true && renderToTexture != NULL && *renderToTexture != NULL) { glLineWidth(14); playerCrossSize = 24; } else { // force playerCrossSize to be at least of size 4 if(cellSize < 4) { playerCrossSize = 4; } else { playerCrossSize = cellSize; } } assertGl(); Vec2f *vertices = new Vec2f[map->getMaxFactions() * 4]; Vec3f *colors = new Vec3f[map->getMaxFactions() * 4]; for (int i = 0; i < map->getMaxFactions(); i++) { Vec3f color; switch (i) { case 0: color = Vec3f(1.f, 0.f, 0.f); break; case 1: color = Vec3f(0.f, 0.f, 1.f); break; case 2: color = Vec3f(0.f, 1.f, 0.f); break; case 3: color = Vec3f(1.f, 1.f, 0.f); break; case 4: color = Vec3f(1.f, 1.f, 1.f); break; case 5: color = Vec3f(0.f, 1.f, 0.8f); break; case 6: color = Vec3f(1.f, 0.5f, 0.f); break; case 7: color = Vec3f(1.f, 0.5f, 1.f); break; } colors[i*4] = color; colors[(i*4)+1] = color; colors[(i*4)+2] = color; colors[(i*4)+3] = color; vertices[i*4] = Vec2f((map->getStartLocationX(i) - 1) * cellSize, clientH - (map->getStartLocationY(i) - 1) * cellSize); vertices[(i*4)+1] = Vec2f((map->getStartLocationX(i) + 1) * cellSize + playerCrossSize, clientH - (map->getStartLocationY(i) + 1) * cellSize - playerCrossSize); vertices[(i*4)+2] = Vec2f((map->getStartLocationX(i) - 1) * cellSize, clientH - (map->getStartLocationY(i) + 1) * cellSize - playerCrossSize); vertices[(i*4)+3] = Vec2f((map->getStartLocationX(i) + 1) * cellSize + playerCrossSize, clientH - (map->getStartLocationY(i) - 1) * cellSize); } glEnableClientState(GL_COLOR_ARRAY); glColorPointer(3, GL_FLOAT, 0, &colors[0]); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, &vertices[0]); glDrawArrays(GL_LINES, 0, 4 * map->getMaxFactions()); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); assertGl(); glLineWidth(1); glPopMatrix(); glPopAttrib(); glMatrixMode(GL_PROJECTION); glPopMatrix(); if(supportFBOs == true && renderToTexture != NULL && *renderToTexture != NULL) { Texture2DGl *texture = static_cast(*renderToTexture); if(texture != NULL) { texture->dettachFrameBufferFromTexture(); } glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); assertGl(); } delete [] vertices; delete [] colors; assertGl(); } // setLastRenderFps and calculate shadowsOffDueToMinRender void Renderer::setLastRenderFps(int value) { lastRenderFps = value; smoothedRenderFps=(MIN_FPS_NORMAL_RENDERING*smoothedRenderFps+lastRenderFps)/(MIN_FPS_NORMAL_RENDERING+1.0f); if(smoothedRenderFps>=MIN_FPS_NORMAL_RENDERING_TOP_THRESHOLD){ shadowsOffDueToMinRender=false; } if(smoothedRenderFps<=MIN_FPS_NORMAL_RENDERING){ shadowsOffDueToMinRender=true; } } std::size_t Renderer::getCurrentPixelByteCount(ResourceScope rs) const { std::size_t result = 0; for(int i = (rs == rsCount ? 0 : rs); i < rsCount; ++i) { if(textureManager[i] != NULL) { const ::Shared::Graphics::TextureContainer &textures = textureManager[i]->getTextures(); for(int j = 0; j < (int)textures.size(); ++j) { const Texture *texture = textures[j]; result += texture->getPixelByteCount(); } if(rs != rsCount) { break; } } } return result; } Texture2D * Renderer::preloadTexture(string logoFilename) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] logoFilename [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,logoFilename.c_str()); Texture2D *result = NULL; if(logoFilename != "") { // Cache faction preview textures string data_path = getGameReadWritePath(GameConstants::path_data_CacheLookupKey); std::map &crcFactionPreviewTextureCache = CacheManager::getCachedItem< std::map >(GameConstants::factionPreviewTextureCacheLookupKey); if(crcFactionPreviewTextureCache.find(logoFilename) != crcFactionPreviewTextureCache.end()) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] logoFilename [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,logoFilename.c_str()); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] load texture from cache [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,logoFilename.c_str()); result = crcFactionPreviewTextureCache[logoFilename]; } else { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] logoFilename [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,logoFilename.c_str()); Renderer &renderer= Renderer::getInstance(); result = renderer.newTexture2D(rsGlobal); if(result) { result->setMipmap(true); result->load(logoFilename); //renderer.initTexture(rsGlobal,result); } if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] add texture to manager and cache [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,logoFilename.c_str()); crcFactionPreviewTextureCache[logoFilename] = result; } } return result; } Texture2D * Renderer::findTexture(string logoFilename) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] logoFilename [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,logoFilename.c_str()); Texture2D *result = preloadTexture(logoFilename); if(result != NULL && result->getInited() == false) { Renderer &renderer= Renderer::getInstance(); renderer.initTexture(rsGlobal,result); } return result; } void Renderer::cycleShowDebugUILevel() { //printf("#1 showDebugUILevel = %d, debugui_fps = %d, debugui_unit_titles = %d\n",showDebugUILevel,debugui_fps,debugui_unit_titles); //if(showDebugUI == false) { // showDebugUI = true; //} if((showDebugUILevel & debugui_fps) != debugui_fps || (showDebugUILevel & debugui_unit_titles) != debugui_unit_titles) { showDebugUILevel |= debugui_fps; showDebugUILevel |= debugui_unit_titles; } else { showDebugUILevel = debugui_fps; } //printf("#2 showDebugUILevel = %d, debugui_fps = %d, debugui_unit_titles = %d\n",showDebugUILevel,debugui_fps,debugui_unit_titles); } void Renderer::renderFPSWhenEnabled(int lastFps) { if(getShowDebugUI() == true) { CoreData &coreData= CoreData::getInstance(); if(Renderer::renderText3DEnabled) { renderText3D( "FPS: " + intToStr(lastFps), coreData.getMenuFontNormal3D(), Vec3f(1.f), 10, 10, false); } else { renderText( "FPS: " + intToStr(lastFps), coreData.getMenuFontNormal(), Vec3f(1.f), 10, 10, false); } } } void Renderer::renderPopupMenu(PopupMenu *menu) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; } if(menu->getVisible() == false || menu->getEnabled() == false) { return; } //background glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT); glEnable(GL_BLEND); glColor4f(0.0f, 0.0f, 0.0f, 0.8f) ; glBegin(GL_TRIANGLE_STRIP); glVertex2i(menu->getX(), menu->getY() + 9 * menu->getH() / 10); glVertex2i(menu->getX(), menu->getY()); glVertex2i(menu->getX() + menu->getW(), menu->getY() + 9 * menu->getH() / 10); glVertex2i(menu->getX() + menu->getW(), menu->getY()); glEnd(); glColor4f(0.0f, 0.0f, 0.0f, 0.8f) ; glBegin(GL_TRIANGLE_STRIP); glVertex2i(menu->getX(), menu->getY() + menu->getH()); glVertex2i(menu->getX(), menu->getY() + 9 * menu->getH() / 10); glVertex2i(menu->getX() + menu->getW(), menu->getY() + menu->getH()); glVertex2i(menu->getX() + menu->getW(), menu->getY() + 9 * menu->getH() / 10); glEnd(); glBegin(GL_LINE_LOOP); glColor4f(0.5f, 0.5f, 0.5f, 0.25f) ; glVertex2i(menu->getX(), menu->getY()); glColor4f(0.0f, 0.0f, 0.0f, 0.25f) ; glVertex2i(menu->getX() + menu->getW(), menu->getY()); glColor4f(0.5f, 0.5f, 0.5f, 0.25f) ; glVertex2i(menu->getX() + menu->getW(), menu->getY() + menu->getH()); glColor4f(0.25f, 0.25f, 0.25f, 0.25f) ; glVertex2i(menu->getX(), menu->getY() + menu->getH()); glEnd(); glBegin(GL_LINE_STRIP); glColor4f(1.0f, 1.0f, 1.0f, 0.25f) ; glVertex2i(menu->getX(), menu->getY() + 90*menu->getH()/100); glColor4f(0.5f, 0.5f, 0.5f, 0.25f) ; glVertex2i(menu->getX()+ menu->getW(), menu->getY() + 90*menu->getH()/100); glEnd(); glPopAttrib(); Vec4f fontColor; //if(game!=NULL){ // fontColor=game->getGui()->getDisplay()->getColor(); //} //else { // white shadowed is default ( in the menu for example ) fontColor=Vec4f(1.f, 1.f, 1.f, 1.0f); //} if(renderText3DEnabled == true) { //text renderTextBoundingBox3D( menu->getHeader(), menu->getFont3D(),fontColor, menu->getX(), menu->getY()+93*menu->getH()/100,menu->getW(),0, true,false, false,-1,-1); } else { //text int renderX = (menu->getX() + (menu->getW() / 2)); //int renderY = (menu->getY() + (menu->getH() / 2)); FontMetrics *fontMetrics= menu->getFont()->getMetrics(); int renderY = menu->getY() + menu->getH() - fontMetrics->getHeight(menu->getHeader()); renderTextShadow( menu->getHeader(), menu->getFont(),fontColor, renderX, renderY, true); //renderText(button->getText(), button->getFont(), color,x + (w / 2), y + (h / 2), true); } //buttons // int maxButtonWidth = -1; std::vector &menuItems = menu->getMenuItems(); // for(unsigned int i = 0; i < menuItems.size(); ++i) { // GraphicButton *button = &menuItems[i]; // int currentButtonWidth = -1; // if(renderText3DEnabled == true) { // FontMetrics *fontMetrics= menu->getFont3D()->getMetrics(); // currentButtonWidth = fontMetrics->getTextWidth(button->getText()); // } // else { // FontMetrics *fontMetrics= menu->getFont()->getMetrics(); // currentButtonWidth = fontMetrics->getTextWidth(button->getText()); // } // // if(maxButtonWidth < 0 || currentButtonWidth > maxButtonWidth) { // maxButtonWidth = currentButtonWidth + 5; // } // } for(unsigned int i = 0; i < menuItems.size(); ++i) { GraphicButton *button = &menuItems[i]; //button->setW(maxButtonWidth); renderButton(button); } } void Renderer::setupRenderForVideo() { clearBuffers(); //3d reset3dMenu(); clearZBuffer(); //2d reset2d(); glClearColor(0.f, 0.f, 0.f, 1.f); } void Renderer::renderVideoLoading(int progressPercent) { //printf("Rendering progress progressPercent = %d\n",progressPercent); setupRenderForVideo(); Lang &lang= Lang::getInstance(); string textToRender = lang.getString("PleaseWait"); const Metrics &metrics= Metrics::getInstance(); static Chrono cycle(true); static float anim = 0.0f; if(CoreData::getInstance().getMenuFontBig3D() != NULL) { int w= metrics.getVirtualW(); int renderX = (w / 2) - (CoreData::getInstance().getMenuFontBig3D()->getMetrics()->getTextWidth(textToRender) / 2); int h= metrics.getVirtualH(); int renderY = (h / 2) + (CoreData::getInstance().getMenuFontBig3D()->getMetrics()->getHeight(textToRender) / 2); renderText3D( textToRender, CoreData::getInstance().getMenuFontBig3D(), Vec4f(1.f, 1.f, 0.f,anim), renderX, renderY, false); } else { renderText( textToRender, CoreData::getInstance().getMenuFontBig(), Vec4f(1.f, 1.f, 0.f,anim), (metrics.getScreenW() / 2), (metrics.getScreenH() / 2), true); } swapBuffers(); if(cycle.getCurMillis() % 50 == 0) { static bool animCycleUp = true; if(animCycleUp == true) { anim += 0.1f; if(anim > 1.f) { anim= 1.f; cycle.reset(); animCycleUp = false; } } else { anim -= 0.1f; if(anim < 0.f) { anim= 0.f; cycle.reset(); animCycleUp = true; } } } } }}//end namespace