MegaGlest/source/glest_game/graphics/renderer.cpp

10117 lines
319 KiB
C++

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