// This file is part of Glest (www.glest.org) // // Copyright (C) 2001-2008 Martio 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 // ============================================================== #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 #include "cache_manager.h" #include "network_manager.h" #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; // ===================================================== // 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; // ==================== constructor and destructor ==================== Renderer::Renderer() { Renderer::rendererEnded = false; this->allowRenderUnitTitles = false; this->menu = NULL; this->game = NULL; list2d = 0; showDebugUI = false; showDebugUILevel = debugui_fps; modelRenderer = NULL; textRenderer = NULL; particleRenderer = NULL; saveScreenShotThread = NULL; mapSurfaceData.clear(); visibleFrameUnitList.clear(); visibleFrameUnitListCameraKey = ""; lastRenderFps=MIN_FPS_NORMAL_RENDERING; shadowsOffDueToMinRender=false; //resources for(int i=0; i < rsCount; ++i) { modelManager[i] = NULL; textureManager[i] = NULL; particleManager[i] = NULL; fontManager[i] = NULL; } GraphicsInterface &gi= GraphicsInterface::getInstance(); FactoryRepository &fr= FactoryRepository::getInstance(); 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",__FILE__,__FUNCTION__,__LINE__,Renderer::perspFarPlane,this->no2DMouseRendering,this->maxConsoleLines); gi.setFactory(fr.getGraphicsFactory(config.getString("FactoryGraphics"))); GraphicsFactory *graphicsFactory= GraphicsInterface::getInstance().getFactory(); modelRenderer= graphicsFactory->newModelRenderer(); textRenderer= graphicsFactory->newTextRenderer2D(); particleRenderer= graphicsFactory->newParticleRenderer(); //resources for(int i=0; i< rsCount; ++i) { modelManager[i]= graphicsFactory->newModelManager(); textureManager[i]= graphicsFactory->newTextureManager(); modelManager[i]->setTextureManager(textureManager[i]); particleManager[i]= graphicsFactory->newParticleManager(); fontManager[i]= graphicsFactory->newFontManager(); } saveScreenShotThread = new SimpleTaskThread(this,0,25); saveScreenShotThread->setUniqueID(__FILE__); saveScreenShotThread->start(); } void Renderer::cleanupScreenshotThread() { if(saveScreenShotThread) { saveScreenShotThread->signalQuit(); for(time_t elapsed = time(NULL); getSaveScreenQueueSize() > 0 && difftime(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(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",__FILE__,__FUNCTION__,__LINE__,saveScreenQueue.size()); for(std::list >::iterator iter = saveScreenQueue.begin(); iter != saveScreenQueue.end(); ++iter) { delete iter->second; } saveScreenQueue.clear(); } } } Renderer::~Renderer() { delete modelRenderer; modelRenderer = NULL; delete textRenderer; textRenderer = NULL; delete particleRenderer; particleRenderer = NULL; //resources for(int i=0; imenu = NULL; this->game = NULL; } void Renderer::simpleTask(BaseThread *callingThread) { // This code reads pixmaps from a queue and saves them to disk Pixmap2D *savePixMapBuffer=NULL; string path=""; static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__); MutexSafeWrapper safeMutex(&saveScreenShotThreadAccessor,mutexOwnerId); if(saveScreenQueue.size() > 0) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d] saveScreenQueue.size() = %d\n",__FILE__,__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",__FILE__,__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 for(int i=0; iinit(); textureManager[i]->init(true); //particleManager[i]->init(); //fontManager[i]->init(); } } // ==================== init ==================== void Renderer::init() { Config &config= Config::getInstance(); loadConfig(); if(config.getBool("CheckGlCaps")){ checkGlCaps(); } if(config.getBool("FirstTime")){ config.setBool("FirstTime", false); autoConfig(); config.save(); } modelManager[rsGlobal]->init(); textureManager[rsGlobal]->init(); fontManager[rsGlobal]->init(); init2dList(); glHint(GL_FOG_HINT, GL_FASTEST); //glHint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST); glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST); //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); } void Renderer::initGame(const Game *game){ if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SurfaceData::nextUniqueId = 1; mapSurfaceData.clear(); this->game= game; //worldToScreenPosCache.clear(); //check gl caps checkGlOptionalCaps(); //vars shadowMapFrame= 0; waterAnim= 0; if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); //shadows if(shadows == sProjected || shadows == sShadowMapping) { static_cast(modelRenderer)->setSecondaryTexCoordUnit(2); glGenTextures(1, &shadowMapHandle); 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",__FILE__,__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",__FILE__,__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",__FILE__,__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",__FILE__,__FUNCTION__,__LINE__); init3dList(); } void Renderer::initMenu(const MainMenu *mm) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); this->menu = mm; if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); 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",__FILE__,__FUNCTION__,__LINE__); init3dListMenu(mm); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } void Renderer::reset3d() { assertGl(); glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); glCallList(list3d); pointCount= 0; triangleCount= 0; assertGl(); } void Renderer::reset2d() { assertGl(); glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); glCallList(list2d); assertGl(); } void Renderer::reset3dMenu() { assertGl(); glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); glCallList(list3dMenu); assertGl(); } // ==================== end ==================== void Renderer::end() { 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(list2d > 0) { glDeleteLists(list2d, 1); list2d = 0; } Renderer::rendererEnded = true; } void Renderer::endGame() { game= NULL; //delete resources modelManager[rsGame]->end(); textureManager[rsGame]->end(); fontManager[rsGame]->end(); particleManager[rsGame]->end(); if(shadows == sProjected || shadows == sShadowMapping) { glDeleteTextures(1, &shadowMapHandle); } glDeleteLists(list3d, 1); //worldToScreenPosCache.clear(); ReleaseSurfaceVBOs(); mapSurfaceData.clear(); } void Renderer::endMenu() { this->menu = NULL; //delete resources modelManager[rsMenu]->end(); textureManager[rsMenu]->end(); fontManager[rsMenu]->end(); particleManager[rsMenu]->end(); glDeleteLists(list3dMenu, 1); } void Renderer::reloadResources() { 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) { 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",__FILE__,__FUNCTION__,__LINE__,textureFilename.c_str()); 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",__FILE__,__FUNCTION__,__LINE__,textureFilename.c_str()); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] free texture from cache [%s]\n",__FILE__,__FUNCTION__,__LINE__,textureFilename.c_str()); crcFactionPreviewTextureCache.erase(textureFilename); } } } void Renderer::endLastTexture(ResourceScope rs, bool mustExistInList) { textureManager[rs]->endLastTexture(mustExistInList); } Model *Renderer::newModel(ResourceScope rs){ return modelManager[rs]->newModel(); } void Renderer::endModel(ResourceScope rs, Model *model,bool mustExistInList) { modelManager[rs]->endModel(model,mustExistInList); } void Renderer::endLastModel(ResourceScope rs, bool mustExistInList) { modelManager[rs]->endLastModel(mustExistInList); } Texture2D *Renderer::newTexture2D(ResourceScope rs){ return textureManager[rs]->newTexture2D(); } Texture3D *Renderer::newTexture3D(ResourceScope rs){ return textureManager[rs]->newTexture3D(); } Font2D *Renderer::newFont(ResourceScope rs){ return fontManager[rs]->newFont2D(); } 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::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){ glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glDepthFunc(GL_LESS); particleRenderer->renderManager(particleManager[rs], modelRenderer); glPopAttrib(); } void Renderer::swapBuffers() { //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() { 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= computeLightColor(time); 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()) { for(int i = 0; i < world->getFactionCount() && lightCount < maxLights; ++i) { for(int j = 0; j < world->getFaction(i)->getUnitCount() && lightCount < maxLights; ++j) { Unit *unit= world->getFaction(i)->getUnit(j); if(world->toRenderUnit(unit) && unit->getCurrVector().dist(gameCamera->getPos()) < maxLightDist && unit->getType()->getLight() && unit->isOperative()){ //printf("$$$ Show light # %d / %d for Unit [%d - %s]\n",lightCount,maxLights,unit->getId(),unit->getFullName().c_str()); Vec4f pos= Vec4f(unit->getCurrVector()); 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::loadGameCameraMatrix() { const GameCamera *gameCamera= game->getGameCamera(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glRotatef(gameCamera->getVAng(), -1, 0, 0); glRotatef(gameCamera->getHAng(), 0, 1, 0); glTranslatef(-gameCamera->getPos().x, -gameCamera->getPos().y, -gameCamera->getPos().z); } 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); } void Renderer::computeVisibleQuad() { const GameCamera *gameCamera = game->getGameCamera(); visibleQuad = gameCamera->computeVisibleQuad(); } // ======================================= // basic rendering // ======================================= void Renderer::renderMouse2d(int x, int y, int anim, float fade) { 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 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(game == NULL) { char szBuf[1024]=""; sprintf(szBuf,"In [%s::%s] Line: %d game == NULL",__FILE__,__FUNCTION__,__LINE__); throw runtime_error(szBuf); } else if(game->getGui() == NULL) { char szBuf[1024]=""; sprintf(szBuf,"In [%s::%s] Line: %d game->getGui() == NULL",__FILE__,__FUNCTION__,__LINE__); throw runtime_error(szBuf); } else if(game->getGui()->getMouse3d() == NULL) { char szBuf[1024]=""; sprintf(szBuf,"In [%s::%s] Line: %d game->getGui()->getMouse3d() == NULL",__FILE__,__FUNCTION__,__LINE__); throw runtime_error(szBuf); } const Gui *gui= game->getGui(); const Mouse3d *mouse3d= gui->getMouse3d(); const Map *map= game->getWorld()->getMap(); if(map == NULL) { char szBuf[1024]=""; sprintf(szBuf,"In [%s::%s] Line: %d map == NULL",__FILE__,__FUNCTION__,__LINE__); throw runtime_error(szBuf); } GLUquadricObj *cilQuadric; Vec4f color; assertGl(); if((mouse3d->isEnabled() || gui->isPlacingBuilding()) && gui->isValidPosObjWorld()) { glMatrixMode(GL_MODELVIEW); glPushMatrix(); 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); const Vec2i &pos= gui->getPosObjWorld(); Vec3f pos3f= Vec3f(pos.x, map->getCell(pos)->getHeight(), pos.y); if(gui->isPlacingBuilding()) { const UnitType *building= gui->getBuilding(); //selection building emplacement float offset= building->getSize()/2.f-0.5f; glTranslatef(pos3f.x+offset, pos3f.y, pos3f.z+offset); //choose color if(map->isFreeCells(pos, building->getSize(), fLand)){ color= Vec4f(1.f, 1.f, 1.f, 0.5f); } else { color= Vec4f(1.f, 0.f, 0.f, 0.5f); } modelRenderer->begin(true, true, false); glColor4fv(color.ptr()); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color.ptr()); Model *buildingModel= building->getFirstStOfClass(scStop)->getAnimation(); if(gui->getSelectedFacing() != CardinalDir::NORTH) { float rotateAmount = gui->getSelectedFacing() * 90.f; if(rotateAmount > 0) { glRotatef(rotateAmount, 0.f, 1.f, 0.f); } } buildingModel->updateInterpolationData(0.f, false); modelRenderer->render(buildingModel); glDisable(GL_COLOR_MATERIAL); modelRenderer->end(); } else { //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) { 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) { 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::renderConsoleLine(int lineIndex, int xPosition, int yPosition, int lineHeight, const Font2D* font, string stringToHightlight, const ConsoleLineInfo *lineInfo) { Vec4f fontColor; const Metrics &metrics= Metrics::getInstance(); const 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 + ": "; if(fontMetrics == NULL) { throw 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 + ": "; if(fontMetrics == NULL) { throw 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,const bool showFullConsole, const bool showMenuConsole, int overrideMaxConsoleLines){ if(console == NULL) { throw runtime_error("console == NULL"); } glPushAttrib(GL_ENABLE_BIT); glEnable(GL_BLEND); if(showFullConsole) { for(int i = 0; i < console->getStoredLineCount(); ++i) { const ConsoleLineInfo &lineInfo = console->getStoredLineItem(i); renderConsoleLine(i, console->getXPos(), console->getYPos(), console->getLineHeight(), console->getFont(), console->getStringToHighlight(), &lineInfo); } } else if(showMenuConsole) { int allowedMaxLines = (overrideMaxConsoleLines >= 0 ? overrideMaxConsoleLines : maxConsoleLines); for(int i = 0; i < console->getStoredLineCount() && i < allowedMaxLines; ++i) { const ConsoleLineInfo &lineInfo = console->getStoredLineItem(i); renderConsoleLine(i, console->getXPos(), console->getYPos(), console->getLineHeight(), console->getFont(), console->getStringToHighlight(), &lineInfo); } } else { for(int i = 0; i < console->getLineCount(); ++i) { const ConsoleLineInfo &lineInfo = console->getLineItem(i); renderConsoleLine(i, console->getXPos(), console->getYPos(), console->getLineHeight(), console->getFont(), console->getStringToHighlight(), &lineInfo); } } glPopAttrib(); } void Renderer::renderChatManager(const ChatManager *chatManager) { Vec4f fontColor; Lang &lang= Lang::getInstance(); if(chatManager->getEditEnabled()) { string text=""; if(chatManager->getInMenu()){ text += lang.get("Chat"); } else if(chatManager->getTeamMode()) { text += lang.get("Team"); } else { text += lang.get("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); } renderTextShadow( text, chatManager->getFont(), fontColor, chatManager->getXPos(), chatManager->getYPos()); //textRenderer->begin(CoreData::getInstance().getConsoleFont()); //textRenderer->render(text, 300, 150); //textRenderer->end(); } else { if (chatManager->getInMenu()) { string text = ">> "+lang.get("PressEnterToChat")+" <<"; fontColor = Vec4f(0.5f, 0.5f, 0.5f, 0.5f); renderTextShadow(text, chatManager->getFont(), fontColor, chatManager->getXPos(), chatManager->getYPos()); } } } void Renderer::renderResourceStatus() { const Metrics &metrics= Metrics::getInstance(); const World *world= game->getWorld(); const Faction *thisFaction= world->getFaction(world->getThisFactionIndex()); const Vec4f fontColor=game->getGui()->getDisplay()->getColor(); assertGl(); glPushAttrib(GL_ENABLE_BIT); int j= 0; for(int i= 0; igetTechTree()->getResourceTypeCount(); ++i){ const ResourceType *rt= world->getTechTree()->getResourceType(i); const Resource *r= thisFaction->getResource(rt); //if any unit produces the resource bool showResource= false; for(int k=0; kgetType()->getUnitTypeCount(); ++k){ const UnitType *ut= thisFaction->getType()->getUnitType(k); if(ut->getCost(rt)!=NULL){ showResource= true; break; } } //draw resource status if(showResource){ string str= intToStr(r->getAmount()); glEnable(GL_TEXTURE_2D); glColor3f(1.f, 1.f, 1.f); renderQuad(j*100+200, metrics.getVirtualH()-30, 16, 16, rt->getImage()); if(rt->getClass() != rcStatic) { str+= "/" + intToStr(thisFaction->getStoreAmount(rt)); } if(rt->getClass()==rcConsumable){ str+= "("; if(r->getBalance()>0){ str+= "+"; } str+= intToStr(r->getBalance()) + ")"; } glDisable(GL_TEXTURE_2D); renderTextShadow( str, CoreData::getInstance().getDisplayFontSmall(), fontColor, j*100+220, metrics.getVirtualH()-30, false); ++j; } } glPopAttrib(); assertGl(); } void Renderer::renderSelectionQuad() { 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, const Font2D *font, int x, int y) { if(font == NULL) { throw runtime_error("font == NULL"); } const Metrics &metrics= Metrics::getInstance(); const FontMetrics *fontMetrics= font->getMetrics(); if(fontMetrics == NULL) { throw runtime_error("fontMetrics == NULL"); } int virtualX = (fontMetrics->getTextWidth(text) > 0 ? static_cast(fontMetrics->getTextWidth(text)/2.f) : 5); int virtualY = (fontMetrics->getHeight() > 0 ? static_cast(fontMetrics->getHeight()/2.f) : 5); Vec2i textPos( x-metrics.toVirtualX(virtualX), y-metrics.toVirtualY(virtualY)); return textPos; } void Renderer::renderText(const string &text, const Font2D *font, float alpha, int x, int y, bool centered){ glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT); glEnable(GL_BLEND); glColor4fv(Vec4f(1.f, 1.f, 1.f, alpha).ptr()); Vec2i pos= centered? computeCenteredPos(text, font, x, y): Vec2i(x, y); textRenderer->begin(font); textRenderer->render(text, pos.x, pos.y); textRenderer->end(); glPopAttrib(); } void Renderer::renderText(const string &text, const Font2D *font, const Vec3f &color, int x, int y, bool centered){ glPushAttrib(GL_CURRENT_BIT); glColor3fv(color.ptr()); Vec2i pos= centered? computeCenteredPos(text, font, x, y): Vec2i(x, y); textRenderer->begin(font); textRenderer->render(text, pos.x, pos.y); textRenderer->end(); glPopAttrib(); } void Renderer::renderText(const string &text, const Font2D *font, const Vec4f &color, int x, int y, bool centered){ glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT); glEnable(GL_BLEND); glColor4fv(color.ptr()); Vec2i pos= centered? computeCenteredPos(text, font, x, y): Vec2i(x, y); textRenderer->begin(font); textRenderer->render(text, pos.x, pos.y); textRenderer->end(); glPopAttrib(); } void Renderer::renderTextShadow(const string &text, const Font2D *font,const Vec4f &color, int x, int y, bool centered){ if(font == NULL) { throw runtime_error("font == NULL"); } glPushAttrib(GL_CURRENT_BIT); Vec2i pos= centered? computeCenteredPos(text, font, x, y): Vec2i(x, y); textRenderer->begin(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(); glPopAttrib(); } // ============= COMPONENTS ============================= void Renderer::renderLabel(const GraphicLabel *label) { Vec3f labelColor=label->getTextColor(); Vec4f colorWithAlpha = Vec4f(labelColor.x,labelColor.y,labelColor.z,GraphicComponent::getFade()); renderLabel(label,&colorWithAlpha); } void Renderer::renderLabel(const GraphicLabel *label,const Vec3f *color) { if(color != NULL) { Vec4f colorWithAlpha = Vec4f(*color); colorWithAlpha.w = GraphicComponent::getFade(); renderLabel(label,&colorWithAlpha); } else { Vec4f *colorWithAlpha = NULL; renderLabel(label,colorWithAlpha); } } void Renderer::renderLabel(const GraphicLabel *label,const Vec4f *color) { if(label->getVisible() == false) { return; } glPushAttrib(GL_ENABLE_BIT); glEnable(GL_BLEND); vector lines; if(label->getWordWrap() == true) { Tokenize(label->getText(),lines,"\n"); } else { lines.push_back(label->getText()); } 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); } if(color != NULL) { renderText(lines[i], label->getFont(), (*color), textPos.x, textPos.y, label->getCentered()); } else { renderText(lines[i], label->getFont(), GraphicComponent::getFade(), textPos.x, textPos.y, label->getCentered()); } } glPopAttrib(); } void Renderer::renderButton(const GraphicButton *button, const Vec4f *fontColorOverride, bool *lightedOverride) { if(button->getVisible() == false) { return; } 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; if(fontColorOverride != NULL) { fontColor= *fontColorOverride; } 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; 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()) { renderText( button->getText(), button->getFont(), color, x+w/2, y+h/2, true); } else { renderText( button->getText(), button->getFont(),disabledTextColor, x+w/2, y+h/2, true); } glPopAttrib(); } void Renderer::renderCheckBox(const GraphicCheckBox *box) { 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(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(sb->getVisible() == false) { return; } int x= sb->getX(); int y= sb->getY(); int h= sb->getH(); int w= sb->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= coreData.getHorizontalLineTexture(); 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(); //////////////////// // selectBlock //////////////////// x= sb->getX(); y= sb->getY(); h= sb->getH(); w= sb->getW(); 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(); glBindTexture(GL_TEXTURE_2D, static_cast(selectTexture)->getHandle()); //button 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(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(const GraphicListBox *listBox) { if(listBox->getVisible() == false) { return; } renderButton(listBox->getButton1()); renderButton(listBox->getButton2()); glPushAttrib(GL_ENABLE_BIT); glEnable(GL_BLEND); GraphicLabel label; label.init(listBox->getX(), listBox->getY(), listBox->getW(), listBox->getH(), true,listBox->getTextColor()); label.setText(listBox->getText()); label.setFont(listBox->getFont()); 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::renderMessageBox(const GraphicMessageBox *messageBox) { if(messageBox->getVisible() == 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(messageBox->getX(), messageBox->getY()+9*messageBox->getH()/10); glVertex2i(messageBox->getX(), messageBox->getY()); glVertex2i(messageBox->getX() + messageBox->getW(), messageBox->getY() + 9*messageBox->getH()/10); 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()+9*messageBox->getH()/10); glVertex2i(messageBox->getX() + messageBox->getW(), messageBox->getY() + messageBox->getH()); glVertex2i(messageBox->getX() + messageBox->getW(), messageBox->getY()+9*messageBox->getH()/10); 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() + 90*messageBox->getH()/100); glColor4f(0.5f, 0.5f, 0.5f, 0.25f) ; glVertex2i(messageBox->getX()+ messageBox->getW(), messageBox->getY() + 90*messageBox->getH()/100); glEnd(); glPopAttrib(); //buttons renderButton(messageBox->getButton1()); if(messageBox->getButtonCount()==2){ renderButton(messageBox->getButton2()); } 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); //} //text renderTextShadow( messageBox->getText(), messageBox->getFont(), fontColor, messageBox->getX()+15, messageBox->getY()+7*messageBox->getH()/10, false ); renderTextShadow( messageBox->getHeader(), messageBox->getFont(),fontColor, messageBox->getX()+15, messageBox->getY()+93*messageBox->getH()/100, false ); } // ==================== 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, &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 ); glBindBuffer(GL_ARRAY_BUFFER_ARB, 0); assertGl(); // Generate And Bind The Texture Coordinate Buffer glGenBuffersARB( 1, &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 ); glBindBuffer(GL_ARRAY_BUFFER_ARB, 0); assertGl(); // Generate And Bind The Texture Coordinate Buffer glGenBuffersARB( 1, &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 ); glBindBuffer(GL_ARRAY_BUFFER_ARB, 0); assertGl(); // Generate And Bind The Normal Buffer glGenBuffersARB( 1, &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 ); glBindBuffer(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, &item.m_nVBOVertices ); // Get A Valid Name glDeleteBuffersARB( 1, &item.m_nVBOFowTexCoords ); // Get A Valid Name glDeleteBuffersARB( 1, &item.m_nVBOSurfaceTexCoords ); // Get A Valid Name glDeleteBuffersARB( 1, &item.m_nVBONormals ); // Get A Valid Name //glDeleteBuffersARB( 1, &item.m_nVBOIndexes ); // Get A Valid Name } } mapSurfaceVBOCache.clear(); } void Renderer::renderSurface(const int renderFps) { IF_DEBUG_EDITION( if (getDebugRenderer().willRenderSurface()) { getDebugRenderer().renderSurface(visibleQuad / Map::cellScale); } else { ) int lastTex=-1; int currTex=-1; const World *world= game->getWorld(); const Map *map= world->getMap(); const Rect2i mapBounds(0, 0, map->getSurfaceW()-1, map->getSurfaceH()-1); float coordStep= world->getTileset()->getSurfaceAtlas()->getCoordStep(); assertGl(); const Texture2D *fowTex= world->getMinimap()->getFowTexture(); 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(); } } glActiveTexture(baseTexUnit); VisibleQuadContainerCache &qCache = getQuadCache(); if(qCache.visibleScaledCellList.size() > 0) { 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); for(int visibleIndex = 0; visibleIndex < 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 runtime_error("tc00 == NULL"); } if(tc10 == NULL) { throw runtime_error("tc10 == NULL"); } if(tc01 == NULL) { throw runtime_error("tc01 == NULL"); } if(tc11 == NULL) { throw runtime_error("tc11 == NULL"); } triangleCount+= 2; pointCount+= 4; //set texture if(tc00->getSurfaceTexture() == NULL) { throw runtime_error("tc00->getSurfaceTexture() == NULL"); } 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); 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 { int lastSurfaceDataIndex = -1; 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()); for(int visibleIndex = 0; visibleIndex < 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 runtime_error("tc00 == NULL"); } if(tc10 == NULL) { throw runtime_error("tc10 == NULL"); } if(tc01 == NULL) { throw runtime_error("tc01 == NULL"); } if(tc11 == NULL) { throw runtime_error("tc11 == NULL"); } triangleCount+= 2; pointCount+= 4; //set texture if(tc00->getSurfaceTexture() == NULL) { throw 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 = 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++; } /* if(useSurfaceCache == true) { std::pair > &surfaceCacheEntity = mapSurfaceData[snapshotOfvisibleQuad.getString()]; surfaceCacheEntity.first.start(); } */ } //printf("\nsurface.size() = %d vs qCache.visibleScaledCellList.size() = %d snapshotOfvisibleQuad [%s]\n",surface.size(),qCache.visibleScaledCellList.size(),snapshotOfvisibleQuad.getString().c_str()); std::vector *surface = &surfaceData; if(useSurfaceCache == true) { std::pair > &surfaceCacheEntity = mapSurfaceData[snapshotOfvisibleQuad.getString()]; surface = &surfaceCacheEntity.second; //printf("Surface Cache Size for Rendering using VA's = %lu\n",mapSurfaceData.size()); } glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); for(int i = 0; i < 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); glPopAttrib(); //assert glGetError(); //remove when first mtex problem solved 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) { const World *world= game->getWorld(); const Map *map= world->getMap(); assertGl(); const Texture2D *fowTex= NULL; Vec3f baseFogColor; bool modelRenderStarted = false; VisibleQuadContainerCache &qCache = getQuadCache(); for(int visibleIndex = 0; visibleIndex < qCache.visibleObjectList.size(); ++visibleIndex) { Object *o = qCache.visibleObjectList[visibleIndex]; Model *objModel= o->getModelPtr(); const Vec3f &v= o->getConstPos(); if(modelRenderStarted == false) { modelRenderStarted = true; fowTex= world->getMinimap()->getFowTexture(); baseFogColor= world->getTileset()->getFogColor() * computeLightColor(world->getTimeFlow()->getTime()); glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_FOG_BIT | GL_LIGHTING_BIT | GL_TEXTURE_BIT); if(!shadowsOffDueToMinRender && 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); } //ambient and diffuse color is taken from cell color const Pixmap2D *fowTexPixmap = fowTex->getPixmapConst(); 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); objModel->updateInterpolationData(0.f, 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() { bool closed= false; const World *world= game->getWorld(); const Map *map= world->getMap(); 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); if(textures3D){ Texture3D *waterTex= world->getTileset()->getWaterTex(); if(waterTex == NULL) { throw 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(); 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); int thisTeamIndex= world->getThisTeamIndex(); bool cellExplored = world->showWorldForPlayer(world->getThisFactionIndex()); if(cellExplored == false) { cellExplored = (tc0->isExplored(thisTeamIndex) || tc1->isExplored(thisTeamIndex)); } if(tc0->getNearSubmerged() && cellExplored == true) { 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){ 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::renderUnits(const int renderFps) { 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(); //} } bool modelRenderStarted = false; VisibleQuadContainerCache &qCache = getQuadCache(); if(qCache.visibleQuadUnitList.size() > 0) { for(int visibleUnitIndex = 0; visibleUnitIndex < qCache.visibleQuadUnitList.size(); ++visibleUnitIndex) { Unit *unit = qCache.visibleQuadUnitList[visibleUnitIndex]; 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, &meshCallbackTeamColor); } glMatrixMode(GL_MODELVIEW); glPushMatrix(); //translate Vec3f currVec= unit->getCurrVectorFlat(); glTranslatef(currVec.x, currVec.y, currVec.z); //rotate glRotatef(unit->getRotation(), 0.f, 1.f, 0.f); glRotatef(unit->getVerticalRotation(), 1.f, 0.f, 0.f); //dead alpha float alpha= 1.0f; const SkillType *st= unit->getCurrSkill(); if(st->getClass() == scDie && static_cast(st)->getFade()) { alpha= 1.0f-unit->getAnimProgress(); 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); glAlphaFunc(GL_GREATER, 0.4f); } //render Model *model= unit->getCurrentModelPtr(); model->updateInterpolationData(unit->getAnimProgress(), unit->isAlive()); 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(unit->getCurrVectorFlat())); unit->setScreenPos(computeScreenPosition(unit->getCurrVector())); visibleFrameUnitList.push_back(unit); visibleFrameUnitListCameraKey = game->getGameCamera()->getCameraMovementKey(); } //if(allowRenderUnitTitles == true) { // Add to the pending render unit title list //renderUnitTitleList.push_back(std::pair(unit,computeScreenPosition(unit->getCurrVectorFlat())) ); //} } if(modelRenderStarted == true) { modelRenderer->end(); glPopAttrib(); } } //restore static_cast(modelRenderer)->setDuplicateTexCoords(true); // reset alpha glAlphaFunc(GL_GREATER, 0.0f); //assert assertGl(); } void Renderer::renderSelectionEffects() { 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); //translate Vec3f currVec= unit->getCurrVectorFlat(); currVec.y+= 0.3f; //selection circle 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(unit->getHpRatio(), unit->getHpRatio(), unit->getHpRatio(), 0.3f); } else { glColor4f(0, unit->getHpRatio(), 0, 0.3f); } } else if ( world->getThisTeamIndex() == unit->getTeam()) { glColor4f(unit->getHpRatio(), unit->getHpRatio(), 0, 0.3f); } else{ glColor4f(unit->getHpRatio(), 0, 0, 0.3f); } renderSelectionCircle(currVec, unit->getType()->getSize(), selectionCircleRadius); if( showDebugUI == true && (showDebugUILevel & debugui_unit_titles) == debugui_unit_titles) { const UnitPathInterface *path= unit->getPath(); if(path != NULL && dynamic_cast(path)) { vector pathList = dynamic_cast(path)->getLastPathCacheQueue(); Vec2i lastPosValue; for(int i = 0; i < 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); //renderSelectionCircle(currVec2, unit->getType()->getSize(), selectionCircleRadius); //SurfaceCell *cell= map->getSurfaceCell(currVec2.x, currVec2.y); //currVec2.z = cell->getHeight() + 2.0; //renderSelectionCircle(currVec2, unit->getType()->getSize(), selectionCircleRadius); } } } //magic circle if(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); } } if(selectedResourceObject!=NULL) { 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); //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); } //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); } } //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); } } //render selection hightlights 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(), selectionCircleRadius); } } } glPopAttrib(); } void Renderer::renderWaterEffects(){ const World *world= game->getWorld(); const WaterEffects *we= world->getWaterEffects(); const Map *map= world->getMap(); const 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::renderMinimap(){ const World *world= game->getWorld(); const Minimap *minimap= world->getMinimap(); 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(); // CoreData &coreData= CoreData::getInstance(); // Texture2D *backTexture =coreData.getButtonBigTexture(); // 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(mx-8, my-8); // // glTexCoord2f(0.f, 1.f); // glVertex2f(mx-8, my+mh+8); // // glTexCoord2f(1.f, 0.f); // glVertex2f(mx+mw+8, my-8); // // glTexCoord2f(1.f, 1.f); // glVertex2f(mx+mw+8, my+mh+8); // glEnd(); // // glDisable(GL_TEXTURE_2D); // 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(); // Vec4f col= game->getGui()->getDisplay()->getColor(); // glBegin(GL_QUADS); // glColor4f(col.x*0.5f,col.y*0.5f,col.z*0.5f,1.0 ); // glVertex2i(mx-4, my-4); // glVertex2i(mx-4, my+mh+4); // glVertex2i(mx+mw+4, my+mh+4); // glVertex2i(mx+mw+4, my-4); // // 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()); /* Vec2f texCoords[4]; Vec2f texCoords2[4]; Vec2i vertices[4]; texCoords[0] = Vec2f(0.0f, 1.0f); texCoords2[0] = Vec2f(0.0f, 1.0f); vertices[0] = Vec2i(mx, my); texCoords[1] = Vec2f(0.0f, 0.0f); texCoords2[1] = Vec2f(0.0f, 0.0f); vertices[1] = Vec2i(mx, my+mh); texCoords[2] = Vec2f(1.0f, 1.0f); texCoords2[2] = Vec2f(1.0f, 1.0f); vertices[2] = Vec2i(mx+mw, my); texCoords[3] = Vec2f(1.0f, 0.0f); texCoords2[3] = Vec2f(1.0f, 0.0f); vertices[3] = Vec2i(mx+mw, my+mh); glClientActiveTexture(baseTexUnit); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0,&texCoords[0]); glClientActiveTexture(fowTexUnit); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0,&texCoords2[0]); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_INT, 0, &vertices[0]); glColor4f(0.5f, 0.5f, 0.5f, 0.1f); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisableClientState(GL_VERTEX_ARRAY); glClientActiveTexture(baseTexUnit); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTexture(fowTexUnit); glDisableClientState(GL_TEXTURE_COORD_ARRAY); */ //glColor4f(0.3f, 0.3f, 0.3f, 0.90f); 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(); if(qCache.visibleUnitList.size() > 0) { uint32 unitIdx=0; vector unit_vertices; unit_vertices.resize(qCache.visibleUnitList.size()*4); vector unit_colors; unit_colors.resize(qCache.visibleUnitList.size()*4); for(int visibleIndex = 0; visibleIndex < qCache.visibleUnitList.size(); ++visibleIndex) { Unit *unit = qCache.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++; /* glColor3fv(color.ptr()); glBegin(GL_QUADS); glVertex2f(mx + pos.x*zoom.x, my + mh - (pos.y*zoom.y)); glVertex2f(mx + (pos.x+1)*zoom.x+size, my + mh - (pos.y*zoom.y)); glVertex2f(mx + (pos.x+1)*zoom.x+size, my + mh - ((pos.y+size)*zoom.y)); glVertex2f(mx + pos.x*zoom.x, my + mh - ((pos.y+size)*zoom.y)); glEnd(); */ } 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); } } //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 = 0; int y1 = 0; #ifdef USE_STREFLOP x1 = mx + x + static_cast(20*streflop::sin(ang-pi/5)); y1 = my + mh - (y-static_cast(20*streflop::cos(ang-pi/5))); #else x1 = mx + x + static_cast(20*sin(ang-pi/5)); y1 = my + mh - (y-static_cast(20*cos(ang-pi/5))); #endif int x2 = 0; int y2 = 0; #ifdef USE_STREFLOP x2 = mx + x + static_cast(20*streflop::sin(ang+pi/5)); y2 = my + mh - (y-static_cast(20*streflop::cos(ang+pi/5))); #else x2 = mx + x + static_cast(20*sin(ang+pi/5)); y2 = my + mh - (y-static_cast(20*cos(ang+pi/5))); #endif 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::renderDisplay(){ CoreData &coreData= CoreData::getInstance(); const Metrics &metrics= Metrics::getInstance(); const Display *display= game->getGui()->getDisplay(); glPushAttrib(GL_ENABLE_BIT); //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){ if(display->getDownLighted(i)){ glColor3f(1.f, 1.f, 1.f); } else{ glColor3f(0.3f, 0.3f, 0.3f); } 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){ 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); 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()); modelRenderer->begin(true, true, false); for(int i=0; i < MenuBackground::characterCount; ++i) { glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glTranslatef(i*2.f-4.f, -1.4f, -7.5f); 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(); } // ==================== computing ==================== bool Renderer::computePosition(const Vec2i &screenPos, Vec2i &worldPos){ 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 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) { //declarations GLuint selectBuffer[Gui::maxSelBuff]; const Metrics &metrics= Metrics::getInstance(); //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<1) w=1; if(h<1) h=1; //setup matrices glSelectBuffer(Gui::maxSelBuff, selectBuffer); glMatrixMode(GL_PROJECTION); glPushMatrix(); GLint view[]= {0, 0, metrics.getVirtualW(), metrics.getVirtualH()}; glRenderMode(GL_SELECT); glLoadIdentity(); gluPickMatrix(x, y, w, h, view); gluPerspective(perspFov, metrics.getAspectRatio(), perspNearPlane, perspFarPlane); loadGameCameraMatrix(); //render units to find which ones should be selected renderUnitsFast(); if(withObjectSelection){ renderObjectsFast(false,true); } //pop matrices glMatrixMode(GL_PROJECTION); glPopMatrix(); //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 && object) { obj=object; if(withObjectSelection) { break; } } } else { Unit *unit = qCache.visibleQuadUnitList[index]; if(unit != NULL && unit->isAlive()) { units.push_back(unit); } } } } } // ==================== shadows ==================== void Renderer::renderShadowsToTexture(const int renderFps){ 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-shadowAlpha; 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(); infoStr+= lang.get("OpenGlInfo")+":\n"; infoStr+= " "+lang.get("OpenGlVersion")+": "; infoStr+= string((getGlVersion() != NULL ? getGlVersion() : "?"))+"\n"; infoStr+= " "+lang.get("OpenGlRenderer")+": "; infoStr+= string((getGlVersion() != NULL ? getGlVersion() : "?"))+"\n"; infoStr+= " "+lang.get("OpenGlVendor")+": "; infoStr+= string((getGlVendor() != NULL ? getGlVendor() : "?"))+"\n"; infoStr+= " "+lang.get("OpenGlMaxLights")+": "; infoStr+= intToStr(getGlMaxLights())+"\n"; infoStr+= " "+lang.get("OpenGlMaxTextureSize")+": "; infoStr+= intToStr(getGlMaxTextureSize())+"\n"; infoStr+= " "+lang.get("OpenGlMaxTextureUnits")+": "; infoStr+= intToStr(getGlMaxTextureUnits())+"\n"; infoStr+= " "+lang.get("OpenGlModelviewStack")+": "; infoStr+= intToStr(getGlModelviewMatrixStackDepth())+"\n"; infoStr+= " "+lang.get("OpenGlProjectionStack")+": "; infoStr+= intToStr(getGlProjectionMatrixStackDepth())+"\n"; return infoStr; } string Renderer::getGlMoreInfo(){ string infoStr; Lang &lang= Lang::getInstance(); //gl extensions infoStr+= lang.get("OpenGlExtensions")+":\n "; string extensions= getGlExtensions(); int charCount= 0; for(int i=0; i120 && extensions[i]==' '){ infoStr+= "\n "; charCount= 0; } ++charCount; } //platform extensions infoStr+= "\n\n"; infoStr+= lang.get("OpenGlPlatformExtensions")+":\n "; charCount= 0; string platformExtensions= getGlPlatformExtensions(); for(int i=0; i120 && platformExtensions[i]==' '){ infoStr+= "\n "; charCount= 0; } ++charCount; } return infoStr; } void Renderer::autoConfig(){ 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"); //load shadows shadows= strToShadows(config.getString("Shadows")); if(shadows==sProjected || shadows==sShadowMapping){ shadowTextureSize= config.getInt("ShadowTextureSize"); shadowFrameSkip= config.getInt("ShadowFrameSkip"); shadowAlpha= config.getFloat("ShadowAlpha"); } //load filter settings Texture2D::Filter textureFilter= strToTextureFilter(config.getString("Filter")); int maxAnisotropy= config.getInt("FilterMaxAnisotropy"); 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",__FILE__,__FUNCTION__,__LINE__); Config &config= Config::getInstance(); Texture2D::Filter textureFilter = strToTextureFilter(config.getString("Filter")); int maxAnisotropy = config.getInt("FilterMaxAnisotropy"); Texture2D *texture = GraphicsInterface::getInstance().getFactory()->newTexture2D(); texture->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",__FILE__,__FUNCTION__,__LINE__); //glFinish(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); glReadPixels(x, y, pixmapScreenShot->getW(), pixmapScreenShot->getH(), GL_RGB, GL_UNSIGNED_BYTE, pixmapScreenShot->getPixels()); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); return texture; } void Renderer::saveScreen(const string &path) { const Metrics &sm= Metrics::getInstance(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__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",__FILE__,__FUNCTION__,__LINE__); glFinish(); glPixelStorei(GL_PACK_ALIGNMENT, 1); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); glReadPixels(0, 0, 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",__FILE__,__FUNCTION__,__LINE__); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Signal the threads queue to add a screenshot save request MutexSafeWrapper safeMutex(&saveScreenShotThreadAccessor,string(__FILE__) + "_" + 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",__FILE__,__FUNCTION__,__LINE__); } unsigned int Renderer::getSaveScreenQueueSize() { MutexSafeWrapper safeMutex(&saveScreenShotThreadAccessor,string(__FILE__) + "_" + intToStr(__LINE__)); int queueSize = 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(timegetWorld()->getTileset(); Vec3f color; const float transition= 2; const float dayStart= TimeFlow::dawn; const float dayEnd= TimeFlow::dusk-transition; const float nightStart= TimeFlow::dusk; const float nightEnd= TimeFlow::dawn-transition; if(time>dayStart && timegetSunLightColor(); } else if(time>nightStart || timegetMoonLightColor(); } else if(time>=dayEnd && time<=nightStart) { color= tileset->getSunLightColor().lerp((time-dayEnd)/transition, tileset->getMoonLightColor()); } else if(time>=nightEnd && time<=dayStart) { color= tileset->getMoonLightColor().lerp((time-nightEnd)/transition, tileset->getSunLightColor()); } else { assert(false); color= tileset->getSunLightColor(); } return color; } Vec4f Renderer::computeWaterColor(float waterLevel, float cellHeight) { const float waterFactor= 1.5f; return Vec4f(1.f, 1.f, 1.f, clamp((waterLevel-cellHeight)*waterFactor, 0.f, 1.f)); } // ==================== fast render ==================== //render units for selection purposes void Renderer::renderUnitsFast(bool renderingShadows) { assert(game != NULL); const World *world= game->getWorld(); assert(world != NULL); assertGl(); bool modelRenderStarted = false; VisibleQuadContainerCache &qCache = getQuadCache(); if(qCache.visibleQuadUnitList.size() > 0) { for(int visibleUnitIndex = 0; visibleUnitIndex < qCache.visibleQuadUnitList.size(); ++visibleUnitIndex) { Unit *unit = qCache.visibleQuadUnitList[visibleUnitIndex]; if(modelRenderStarted == false) { modelRenderStarted = true; //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); glInitNames(); } glPushName(visibleUnitIndex); 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(); model->updateInterpolationVertices(unit->getAnimProgress(), unit->isAlive()); modelRenderer->render(model); glPopMatrix(); glPopName(); } if(modelRenderStarted == true) { modelRenderer->end(); glPopAttrib(); } } assertGl(); } //render objects for selection purposes void Renderer::renderObjectsFast(bool renderingShadows, bool resourceOnly) { const World *world= game->getWorld(); const Map *map= world->getMap(); assertGl(); bool modelRenderStarted = false; VisibleQuadContainerCache &qCache = getQuadCache(); if(qCache.visibleObjectList.size() > 0) { for(int visibleIndex = 0; visibleIndex < qCache.visibleObjectList.size(); ++visibleIndex) { Object *o = qCache.visibleObjectList[visibleIndex]; if(modelRenderStarted == false) { modelRenderStarted = true; 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); glInitNames(); } if(!resourceOnly || o->getResource()!= NULL){ Model *objModel= o->getModelPtr(); const Vec3f &v= o->getConstPos(); 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); modelRenderer->render(objModel); glPopMatrix(); glPopName(); } } if(modelRenderStarted == true) { modelRenderer->end(); glPopAttrib(); } } assertGl(); } // ==================== gl caps ==================== void Renderer::checkGlCaps() { //opengl 1.3 if(!isGlVersionSupported(1, 3, 0)) { string message; message += "Your system supports OpenGL version \""; message += getGlVersion() + string("\"\n"); message += "MegaGlest needs at least version 1.3 to work\n"; message += "You may solve this problem by installing your latest video card drivers"; throw runtime_error(message.c_str()); } //opengl 1.4 or extension if(!isGlVersionSupported(1, 4, 0)){ checkExtension("GL_ARB_texture_env_crossbar", "MegaGlest"); } } void Renderer::checkGlOptionalCaps() { //shadows if(shadows == sProjected || shadows == sShadowMapping) { if(getGlMaxTextureUnits() < 3) { throw runtime_error("Your system doesn't support 3 texture units, required for shadows"); } } //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"); } } void Renderer::checkExtension(const string &extension, const string &msg) { if(!isGlExtensionSupported(extension.c_str())) { string str= "OpenGL extension not supported: " + extension + ", required for " + msg; throw runtime_error(str); } } // ==================== init 3d lists ==================== void Renderer::init3dList() { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); const Metrics &metrics= Metrics::getInstance(); assertGl(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); list3d= glGenLists(1); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); glNewList(list3d, GL_COMPILE_AND_EXECUTE); //need to execute, because if not gluPerspective takes no effect and gluLoadMatrix is wrong if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__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",__FILE__,__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",__FILE__,__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); //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",__FILE__,__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",__FILE__,__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",__FILE__,__FUNCTION__,__LINE__); tileset = game->getWorld()->getTileset(); } if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); if(tileset != NULL && tileset->getFog()) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__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",__FILE__,__FUNCTION__,__LINE__); glEndList(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); //assert assertGl(); } void Renderer::init2dList() { const Metrics &metrics= Metrics::getInstance(); //this list sets the state for the 2d rendering list2d= glGenLists(1); glNewList(list2d, GL_COMPILE); //projection glViewport(0, 0, metrics.getScreenW(), metrics.getScreenH()); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, metrics.getVirtualW(), 0, metrics.getVirtualH(), 0, 1); //modelview glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //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); glActiveTexture(baseTexUnit); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glDisable(GL_TEXTURE_2D); //blend func glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //color glColor4f(1.f, 1.f, 1.f, 1.f); glEndList(); assertGl(); } void Renderer::init3dListMenu(const MainMenu *mm) { assertGl(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); const Metrics &metrics= Metrics::getInstance(); const MenuBackground *mb= mm->getConstMenuBackground(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); list3dMenu= glGenLists(1); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); glNewList(list3dMenu, GL_COMPILE); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__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",__FILE__,__FUNCTION__,__LINE__); //fog if(mb != NULL && mb->getFog()){ if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__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",__FILE__,__FUNCTION__,__LINE__); glEndList(); if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); //assert assertGl(); } // ==================== misc ==================== void Renderer::loadProjectionMatrix() { 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() { 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::renderSelectionCircle(Vec3f v, int size, float radius) { 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-0.2f), radius*size, 0.2f, 30, 1); gluDeleteQuadric(disc); glPopMatrix(); } void Renderer::renderArrow(const Vec3f &pos1, const Vec3f &pos2, const Vec3f &color, float width) { 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::renderProgressBar(int size, int x, int y, Font2D *font, int customWidth, string prefixLabel,bool centeredText) { 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); if(centeredText == true) { textRenderer->render(renderText.c_str(), x + maxSize / 2, y, centeredText); } else { textRenderer->render(renderText.c_str(), x, y, centeredText); } textRenderer->end(); } void Renderer::renderTile(const Vec2i &pos) { 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) { /* Revert back to 3.4.0 render logic due to issues on some ATI cards * if(w < 0) { w = texture->getPixmapConst()->getW(); } if(h < 0) { h = texture->getPixmapConst()->getH(); } if(texture != NULL) { glBindTexture(GL_TEXTURE_2D, static_cast(texture)->getHandle()); } Vec2i texCoords[4]; Vec2i vertices[4]; texCoords[0] = Vec2i(0, 1); vertices[0] = Vec2i(x, y+h); texCoords[1] = Vec2i(0, 0); vertices[1] = Vec2i(x, y); texCoords[2] = Vec2i(1, 1); vertices[2] = Vec2i(x+w, y+h); texCoords[3] = Vec2i(1, 0); vertices[3] = Vec2i(x+w, y); //glClientActiveTexture(GL_TEXTURE0); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_INT, 0,&texCoords[0]); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_INT, 0, &vertices[0]); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisableClientState(GL_VERTEX_ARRAY); //glClientActiveTexture(GL_TEXTURE0); glDisableClientState(GL_TEXTURE_COORD_ARRAY); */ 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 "Disabled"; 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 runtime_error("Error converting from string to FilterType, found: "+s); } void Renderer::setAllowRenderUnitTitles(bool value) { allowRenderUnitTitles = value; //if(allowRenderUnitTitles == false) { //renderUnitTitleList.clear(); //} } // This method renders titles for units void Renderer::renderUnitTitles(Font2D *font, Vec3f color) { std::map unitRenderedList; if(visibleFrameUnitList.size() > 0) { for(int idx = 0; idx < visibleFrameUnitList.size(); idx++) { const Unit *unit = visibleFrameUnitList[idx]; if(unit != NULL && unit->getCurrentUnitTitle() != "") { //get the screen coordinates Vec3f screenPos = unit->getScreenPos(); #ifdef USE_STREFLOP renderText(unit->getCurrentUnitTitle(), font, color, streflop::fabs(screenPos.x) + 5, streflop::fabs(screenPos.y) + 5, false); #else renderText(unit->getCurrentUnitTitle(), font, color, fabs(screenPos.x) + 5, fabs(screenPos.y) + 5, false); #endif unitRenderedList[unit->getId()] = true; } else { string str = unit->getFullName() + " - " + intToStr(unit->getId()) + " [" + unit->getPos().getString() + "]"; Vec3f screenPos = unit->getScreenPos(); #ifdef USE_STREFLOP renderText(str, font, color, streflop::fabs(screenPos.x) + 5, streflop::fabs(screenPos.y) + 5, false); #else renderText(str, font, color, fabs(screenPos.x) + 5, fabs(screenPos.y) + 5, false); #endif } } visibleFrameUnitList.clear(); } /* if(renderUnitTitleList.size() > 0) { 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",__FILE__,__FUNCTION__,__LINE__,screenPos.x,screenPos.y,screenPos.z); } } renderUnitTitleList.clear(); } */ } void Renderer::removeObjectFromQuadCache(const Object *o) { VisibleQuadContainerCache &qCache = getQuadCache(); for(int visibleIndex = 0; visibleIndex < 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 < 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 < 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(); //} // 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 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); } } } if(forceNew == true || visibleQuad != quadCache.lastVisibleQuad) { // Object calculations const Map *map= world->getMap(); // clear visibility of old objects for(int visibleIndex = 0; visibleIndex < quadCache.visibleObjectList.size(); ++visibleIndex){ quadCache.visibleObjectList[visibleIndex]->setVisible(false); } quadCache.clearNonVolatileCacheData(); PosQuadIterator pqi(map,visibleQuad, Map::cellScale); while(pqi.next()) { const Vec2i &pos= pqi.getPos(); if(map->isInside(pos)) { const Vec2i &mapPos = Map::toSurfCoords(pos); //quadCache.visibleCellList.push_back(mapPos); SurfaceCell *sc = map->getSurfaceCell(mapPos); Object *o = sc->getObject(); 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); } } } 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)) { quadCache.visibleScaledCellList.push_back(pos); } } } quadCache.cacheFrame = world->getFrameCount(); quadCache.lastVisibleQuad = visibleQuad; } } return quadCache; } void Renderer::renderMapPreview( const MapPreview *map, bool renderAll, int screenPosX, int screenPosY, Texture2D **renderToTexture) { static bool supportFBOs = Texture2DGl().supports_FBO_RBO(); //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) { 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) { 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) { 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) { glLineWidth(14); playerCrossSize = 24; } else { // force playerCrossSize to be at least of size 4 if(cellSize < 4) { playerCrossSize = 4; } else { playerCrossSize = cellSize; } } assertGl(); for (int i = 0; i < map->getMaxFactions(); i++) { switch (i) { case 0: glColor3f(1.f, 0.f, 0.f); break; case 1: glColor3f(0.f, 0.f, 1.f); break; case 2: glColor3f(0.f, 1.f, 0.f); break; case 3: glColor3f(1.f, 1.f, 0.f); break; case 4: glColor3f(1.f, 1.f, 1.f); break; case 5: glColor3f(0.f, 1.f, 0.8f); break; case 6: glColor3f(1.f, 0.5f, 0.f); break; case 7: glColor3f(1.f, 0.5f, 1.f); break; } glBegin(GL_LINES); glVertex2f((map->getStartLocationX(i) - 1) * cellSize, clientH - (map->getStartLocationY(i) - 1) * cellSize); glVertex2f((map->getStartLocationX(i) + 1) * cellSize + playerCrossSize, clientH - (map->getStartLocationY(i) + 1) * cellSize - playerCrossSize); glVertex2f((map->getStartLocationX(i) - 1) * cellSize, clientH - (map->getStartLocationY(i) + 1) * cellSize - playerCrossSize); glVertex2f((map->getStartLocationX(i) + 1) * cellSize + playerCrossSize, clientH - (map->getStartLocationY(i) - 1) * cellSize); glEnd(); } assertGl(); glLineWidth(1); glPopMatrix(); glPopAttrib(); glMatrixMode(GL_PROJECTION); glPopMatrix(); if(supportFBOs == true && renderToTexture != NULL) { Texture2DGl *texture = static_cast(*renderToTexture); if(texture != NULL) { texture->dettachFrameBufferFromTexture(); } glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); assertGl(); } 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; } } uint64 Renderer::getCurrentPixelByteCount(ResourceScope rs) const { uint64 result = 0; for(int i = (rs == rsCount ? 0 : rs); i < rsCount; ++i) { const Shared::Graphics::TextureContainer &textures = textureManager[i]->getTextures(); for(int j = 0; j < 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",__FILE__,__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",__FILE__,__FUNCTION__,__LINE__,logoFilename.c_str()); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] load texture from cache [%s]\n",__FILE__,__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",__FILE__,__FUNCTION__,__LINE__,logoFilename.c_str()); Renderer &renderer= Renderer::getInstance(); result = renderer.newTexture2D(rsGlobal); 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",__FILE__,__FUNCTION__,__LINE__,logoFilename.c_str()); crcFactionPreviewTextureCache[logoFilename] = result; } } return result; } Texture2D * Renderer::findFactionLogoTexture(string logoFilename) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] logoFilename [%s]\n",__FILE__,__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() { if((showDebugUILevel & debugui_fps) != debugui_fps || (showDebugUILevel & debugui_unit_titles) != debugui_unit_titles) { showDebugUILevel |= debugui_fps; showDebugUILevel |= debugui_unit_titles; } else { showDebugUILevel = debugui_fps; } } }}//end namespace