1 // ==============================================================
2 //	This file is part of Glest (www.glest.org)
3 //
4 //	Copyright (C) 2001-2008 Marti�o Figueroa
5 //
6 //	You can redistribute this code and/or modify it under
7 //	the terms of the GNU General Public License as published
8 //	by the Free Software Foundation; either version 2 of the
9 //	License, or (at your option) any later version
10 // ==============================================================
11 
12 #include "renderer.h"
13 
14 #include "texture_gl.h"
15 #include "main_menu.h"
16 #include "config.h"
17 #include "components.h"
18 #include "time_flow.h"
19 #include "graphics_interface.h"
20 #include "object.h"
21 #include "core_data.h"
22 #include "game.h"
23 #include "metrics.h"
24 #include "opengl.h"
25 #include "faction.h"
26 #include "factory_repository.h"
27 #include "leak_dumper.h"
28 
29 using namespace Shared::Graphics;
30 using namespace Shared::Graphics::Gl;
31 using namespace Shared::Util;
32 
33 namespace Glest { namespace Game{
34 
35 // =====================================================
36 // 	class MeshCallbackTeamColor
37 // =====================================================
38 
39 class MeshCallbackTeamColor: public MeshCallback{
40 private:
41 	const Texture *teamTexture;
42 
43 public:
setTeamTexture(const Texture * teamTexture)44 	void setTeamTexture(const Texture *teamTexture)	{this->teamTexture= teamTexture;}
45 	virtual void execute(const Mesh *mesh);
46 };
47 
execute(const Mesh * mesh)48 void MeshCallbackTeamColor::execute(const Mesh *mesh){
49 
50 	//team color
51 	if(mesh->getCustomTexture() && teamTexture!=NULL){
52 		//texture 0
53 		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
54 
55 		//set color to interpolation
56 		glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
57 
58 		glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
59 		glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
60 
61 		glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE1);
62 		glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
63 
64 		glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE);
65 		glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
66 
67 		//set alpha to 1
68 		glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
69 		glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
70 		glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
71 
72 		//texture 1
73 		glActiveTexture(GL_TEXTURE1);
74 		glMultiTexCoord2f(GL_TEXTURE1, 0.f, 0.f);
75 		glEnable(GL_TEXTURE_2D);
76 
77 		glBindTexture(GL_TEXTURE_2D, static_cast<const Texture2DGl*>(teamTexture)->getHandle());
78 		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
79 
80 		glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
81 
82 		glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
83 		glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
84 
85 		glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
86 		glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
87 
88 		//set alpha to 1
89 		glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
90 		glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR);
91 		glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
92 
93 		glActiveTexture(GL_TEXTURE0);
94 	}
95 	else{
96 		glActiveTexture(GL_TEXTURE1);
97 		glDisable(GL_TEXTURE_2D);
98 		glActiveTexture(GL_TEXTURE0);
99 		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
100 	}
101 }
102 
103 // ===========================================================
104 //	class Renderer
105 // ===========================================================
106 
107 // ===================== PUBLIC ========================
108 
109 const int Renderer::maxProgressBar= 100;
110 const Vec4f Renderer::progressBarBack1= Vec4f(0.7f, 0.7f, 0.7f, 0.7f);
111 const Vec4f Renderer::progressBarBack2= Vec4f(0.7f, 0.7f, 0.7f, 1.f);
112 const Vec4f Renderer::progressBarFront1= Vec4f(0.f, 0.5f, 0.f, 1.f);
113 const Vec4f Renderer::progressBarFront2= Vec4f(0.f, 0.1f, 0.f, 1.f);
114 
115 const float Renderer::sunDist= 10e6;
116 const float Renderer::moonDist= 10e6;
117 const float Renderer::lightAmbFactor= 0.4f;
118 
119 const int Renderer::maxMouse2dAnim= 100;
120 
121 const GLenum Renderer::baseTexUnit= GL_TEXTURE0;
122 const GLenum Renderer::fowTexUnit= GL_TEXTURE1;
123 const GLenum Renderer::shadowTexUnit= GL_TEXTURE2;
124 
125 const float Renderer::selectionCircleRadius= 0.7f;
126 const float Renderer::magicCircleRadius= 1.f;
127 
128 //perspective values
129 const float Renderer::perspFov= 60.f;
130 const float Renderer::perspNearPlane= 1.f;
131 const float Renderer::perspFarPlane= 50.f;
132 
133 const float Renderer::ambFactor= 0.7f;
134 const Vec4f Renderer::fowColor= Vec4f(0.0f, 0.0f, 0.0f, 1.0f);
135 const Vec4f Renderer::defSpecularColor= Vec4f(0.8f, 0.8f, 0.8f, 1.f);
136 const Vec4f Renderer::defDiffuseColor= Vec4f(1.f, 1.f, 1.f, 1.f);
137 const Vec4f Renderer::defAmbientColor= Vec4f(1.f * ambFactor, 1.f * ambFactor, 1.f * ambFactor, 1.f);
138 const Vec4f Renderer::defColor= Vec4f(1.f, 1.f, 1.f, 1.f);
139 
140 const float Renderer::maxLightDist= 50.f;
141 
142 // ==================== constructor and destructor ====================
143 
Renderer()144 Renderer::Renderer(){
145 	GraphicsInterface &gi= GraphicsInterface::getInstance();
146 	FactoryRepository &fr= FactoryRepository::getInstance();
147 	Config &config= Config::getInstance();
148 
149 	gi.setFactory(fr.getGraphicsFactory(config.getString("FactoryGraphics")));
150 	GraphicsFactory *graphicsFactory= GraphicsInterface::getInstance().getFactory();
151 
152 	modelRenderer= graphicsFactory->newModelRenderer();
153 	textRenderer= graphicsFactory->newTextRenderer2D();
154 	particleRenderer= graphicsFactory->newParticleRenderer();
155 
156 	//resources
157 	for(int i=0; i<rsCount; ++i){
158 		modelManager[i]= graphicsFactory->newModelManager();
159 		textureManager[i]= graphicsFactory->newTextureManager();
160 		modelManager[i]->setTextureManager(textureManager[i]);
161 		particleManager[i]= graphicsFactory->newParticleManager();
162 		fontManager[i]= graphicsFactory->newFontManager();
163 	}
164 }
165 
~Renderer()166 Renderer::~Renderer(){
167 	delete modelRenderer;
168 	delete textRenderer;
169 	delete particleRenderer;
170 
171 	//resources
172 	for(int i=0; i<rsCount; ++i){
173 		delete modelManager[i];
174 		delete textureManager[i];
175 		delete particleManager[i];
176 		delete fontManager[i];
177 	}
178 }
179 
getInstance()180 Renderer &Renderer::getInstance(){
181 	static Renderer renderer;
182 	return renderer;
183 }
184 
185 
186 // ==================== init ====================
187 
init()188 void Renderer::init(){
189 
190 	Config &config= Config::getInstance();
191 
192 	loadConfig();
193 
194 	if(config.getBool("CheckGlCaps")){
195 		checkGlCaps();
196 	}
197 
198 	if(config.getBool("FirstTime")){
199 		config.setBool("FirstTime", false);
200 		autoConfig();
201 		config.save();
202 	}
203 
204 	modelManager[rsGlobal]->init();
205 	textureManager[rsGlobal]->init();
206 	fontManager[rsGlobal]->init();
207 
208 	init2dList();
209 }
210 
initGame(Game * game)211 void Renderer::initGame(Game *game){
212 	this->game= game;
213 
214 	//check gl caps
215 	checkGlOptionalCaps();
216 
217 	//vars
218 	shadowMapFrame= 0;
219 	waterAnim= 0;
220 
221 	//shadows
222 	if(shadows==sProjected || shadows==sShadowMapping){
223 		static_cast<ModelRendererGl*>(modelRenderer)->setSecondaryTexCoordUnit(2);
224 
225 		glGenTextures(1, &shadowMapHandle);
226 		glBindTexture(GL_TEXTURE_2D, shadowMapHandle);
227 
228 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
229 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
230 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
231 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
232 
233 		if(shadows==sShadowMapping){
234 
235 			//shadow mapping
236 			glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
237 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
238 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
239 			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, 1.0f-shadowAlpha);
240 
241 			glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32,
242 				shadowTextureSize, shadowTextureSize,
243 				0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
244 		}
245 		else{
246 
247 			//projected
248 			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8,
249 				shadowTextureSize, shadowTextureSize,
250 				0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
251 		}
252 
253 		shadowMapFrame= -1;
254 	}
255 
256 	//texture init
257 	modelManager[rsGame]->init();
258 	textureManager[rsGame]->init();
259 	fontManager[rsGame]->init();
260 
261 	init3dList();
262 }
263 
initMenu(MainMenu * mm)264 void Renderer::initMenu(MainMenu *mm){
265 	modelManager[rsMenu]->init();
266 	textureManager[rsMenu]->init();
267 	fontManager[rsMenu]->init();
268 	//modelRenderer->setCustomTexture(CoreData::getInstance().getCustomTexture());
269 
270 	init3dListMenu(mm);
271 }
272 
reset3d()273 void Renderer::reset3d(){
274 	assertGl();
275 	glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
276 	glCallList(list3d);
277 	pointCount= 0;
278 	triangleCount= 0;
279 	assertGl();
280 }
281 
reset2d()282 void Renderer::reset2d(){
283 	assertGl();
284 	glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);
285 	glCallList(list2d);
286 	assertGl();
287 }
288 
reset3dMenu()289 void Renderer::reset3dMenu(){
290 	assertGl();
291 	glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);
292 	glCallList(list3dMenu);
293 	assertGl();
294 }
295 
296 // ==================== end ====================
297 
end()298 void Renderer::end(){
299 
300 	//delete resources
301 	modelManager[rsGlobal]->end();
302 	textureManager[rsGlobal]->end();
303 	fontManager[rsGlobal]->end();
304 	particleManager[rsGlobal]->end();
305 
306 	//delete 2d list
307 	glDeleteLists(list2d, 1);
308 }
309 
endGame()310 void Renderer::endGame(){
311 	game= NULL;
312 
313 	//delete resources
314 	modelManager[rsGame]->end();
315 	textureManager[rsGame]->end();
316 	fontManager[rsGame]->end();
317 	particleManager[rsGame]->end();
318 
319 	if(shadows==sProjected || shadows==sShadowMapping){
320 		glDeleteTextures(1, &shadowMapHandle);
321 	}
322 
323 	glDeleteLists(list3d, 1);
324 }
325 
endMenu()326 void Renderer::endMenu(){
327 	//delete resources
328 	modelManager[rsMenu]->end();
329 	textureManager[rsMenu]->end();
330 	fontManager[rsMenu]->end();
331 	particleManager[rsMenu]->end();
332 
333 	glDeleteLists(list3dMenu, 1);
334 }
335 
reloadResources()336 void Renderer::reloadResources(){
337 	for(int i=0; i<rsCount; ++i){
338 		modelManager[i]->end();
339 		textureManager[i]->end();
340 		fontManager[i]->end();
341 	}
342 	for(int i=0; i<rsCount; ++i){
343 		modelManager[i]->init();
344 		textureManager[i]->init();
345 		fontManager[i]->init();
346 	}
347 }
348 
349 
350 // ==================== engine interface ====================
351 
newModel(ResourceScope rs)352 Model *Renderer::newModel(ResourceScope rs){
353 	return modelManager[rs]->newModel();
354 }
355 
newTexture2D(ResourceScope rs)356 Texture2D *Renderer::newTexture2D(ResourceScope rs){
357 	return textureManager[rs]->newTexture2D();
358 }
359 
newTexture3D(ResourceScope rs)360 Texture3D *Renderer::newTexture3D(ResourceScope rs){
361 	return textureManager[rs]->newTexture3D();
362 }
363 
newFont(ResourceScope rs)364 Font2D *Renderer::newFont(ResourceScope rs){
365 	return fontManager[rs]->newFont2D();
366 }
367 
manageParticleSystem(ParticleSystem * particleSystem,ResourceScope rs)368 void Renderer::manageParticleSystem(ParticleSystem *particleSystem, ResourceScope rs){
369 	particleManager[rs]->manage(particleSystem);
370 }
371 
updateParticleManager(ResourceScope rs)372 void Renderer::updateParticleManager(ResourceScope rs){
373 	particleManager[rs]->update();
374 }
375 
renderParticleManager(ResourceScope rs)376 void Renderer::renderParticleManager(ResourceScope rs){
377 	glPushAttrib(GL_DEPTH_BUFFER_BIT  | GL_STENCIL_BUFFER_BIT);
378 	glDepthFunc(GL_LESS);
379 	particleRenderer->renderManager(particleManager[rs], modelRenderer);
380 	glPopAttrib();
381 }
382 
swapBuffers()383 void Renderer::swapBuffers(){
384 	glFlush();
385 	GraphicsInterface::getInstance().getCurrentContext()->swapBuffers();
386 }
387 
388 // ==================== lighting ====================
389 
390 //places all the opengl lights
setupLighting()391 void Renderer::setupLighting(){
392 
393     int lightCount= 0;
394 	const World *world= game->getWorld();
395 	const GameCamera *gameCamera= game->getGameCamera();
396 	const TimeFlow *timeFlow= world->getTimeFlow();
397 	float time= timeFlow->getTime();
398 
399 	assertGl();
400 
401     //sun/moon light
402 	Vec3f lightColor= computeLightColor(time);
403 	Vec3f fogColor= world->getTileset()->getFogColor();
404 	Vec4f lightPos= timeFlow->isDay()? computeSunPos(time): computeMoonPos(time);
405 	nearestLightPos= lightPos;
406 
407 	glLightfv(GL_LIGHT0, GL_POSITION, lightPos.ptr());
408 	glLightfv(GL_LIGHT0, GL_AMBIENT, Vec4f(lightColor*lightAmbFactor, 1.f).ptr());
409 	glLightfv(GL_LIGHT0, GL_DIFFUSE, Vec4f(lightColor, 1.f).ptr());
410 	glLightfv(GL_LIGHT0, GL_SPECULAR, Vec4f(0.0f, 0.0f, 0.f, 1.f).ptr());
411 
412 	glFogfv(GL_FOG_COLOR, Vec4f(fogColor*lightColor, 1.f).ptr());
413 
414     lightCount++;
415 
416 	//disable all secondary lights
417 	for(int i= 1; i<maxLights; ++i){
418 		glDisable(GL_LIGHT0 + i);
419 	}
420 
421     //unit lights (not projectiles)
422 	if(timeFlow->isTotalNight()){
423         for(int i=0; i<world->getFactionCount() && lightCount<maxLights; ++i){
424             for(int j=0; j<world->getFaction(i)->getUnitCount() && lightCount<maxLights; ++j){
425                 Unit *unit= world->getFaction(i)->getUnit(j);
426 				if(world->toRenderUnit(unit) &&
427 					unit->getCurrVector().dist(gameCamera->getPos())<maxLightDist &&
428                     unit->getType()->getLight() && unit->isOperative()){
429 
430 					Vec4f pos= Vec4f(unit->getCurrVector());
431                     pos.y+=4.f;
432 
433 					GLenum lightEnum= GL_LIGHT0 + lightCount;
434 
435 					glEnable(lightEnum);
436 					glLightfv(lightEnum, GL_POSITION, pos.ptr());
437 					glLightfv(lightEnum, GL_AMBIENT, Vec4f(unit->getType()->getLightColor()).ptr());
438 					glLightfv(lightEnum, GL_DIFFUSE, Vec4f(unit->getType()->getLightColor()).ptr());
439 					glLightfv(lightEnum, GL_SPECULAR, Vec4f(unit->getType()->getLightColor()*0.3f).ptr());
440 					glLightf(lightEnum, GL_QUADRATIC_ATTENUATION, 0.05f);
441 
442                     ++lightCount;
443 
444 					const GameCamera *gameCamera= game->getGameCamera();
445 
446 					if(Vec3f(pos).dist(gameCamera->getPos())<Vec3f(nearestLightPos).dist(gameCamera->getPos())){
447 						nearestLightPos= pos;
448 					}
449                 }
450             }
451         }
452     }
453 
454 	assertGl();
455 }
456 
loadGameCameraMatrix()457 void Renderer::loadGameCameraMatrix(){
458 	const GameCamera *gameCamera= game->getGameCamera();
459 
460 	glMatrixMode(GL_MODELVIEW);
461 	glLoadIdentity();
462 	glRotatef(gameCamera->getVAng(), -1, 0, 0);
463 	glRotatef(gameCamera->getHAng(), 0, 1, 0);
464 	glTranslatef(-gameCamera->getPos().x, -gameCamera->getPos().y, -gameCamera->getPos().z);
465 }
466 
loadCameraMatrix(const Camera * camera)467 void Renderer::loadCameraMatrix(const Camera *camera){
468 	Vec3f position= camera->getPosition();
469 	Quaternion orientation= camera->getOrientation().conjugate();
470 
471 	glMatrixMode(GL_MODELVIEW);
472 	glLoadIdentity();
473 	glMultMatrixf(orientation.toMatrix4().ptr());
474 	glTranslatef(-position.x, -position.y, -position.z);
475 }
476 
computeVisibleQuad()477 void Renderer::computeVisibleQuad(){
478 	const GameCamera *gameCamera= game->getGameCamera();
479 	visibleQuad= gameCamera->computeVisibleQuad();
480 }
481 
482 // =======================================
483 // basic rendering
484 // =======================================
485 
renderMouse2d(int x,int y,int anim,float fade)486 void Renderer::renderMouse2d(int x, int y, int anim, float fade){
487     float color1, color2;
488 
489 	float fadeFactor= fade+1.f;
490 
491 	anim= anim*2-maxMouse2dAnim;
492 
493     color2= (abs(anim*fadeFactor)/static_cast<float>(maxMouse2dAnim))/2.f+0.4f;
494     color1= (abs(anim*fadeFactor)/static_cast<float>(maxMouse2dAnim))/2.f+0.8f;
495 
496     glPushAttrib(GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT | GL_LINE_BIT);
497         glEnable(GL_BLEND);
498 
499 		//inside
500 		glColor4f(0.4f*fadeFactor, 0.2f*fadeFactor, 0.2f*fadeFactor, 0.5f*fadeFactor);
501         glBegin(GL_TRIANGLES);
502             glVertex2i(x, y);
503             glVertex2i(x+20, y-10);
504             glVertex2i(x+10, y-20);
505         glEnd();
506 
507 		//biorder
508         glLineWidth(2);
509         glBegin(GL_LINE_LOOP);
510             glColor4f(1.f, 0.2f, 0, color1);
511             glVertex2i(x, y);
512             glColor4f(1.f, 0.4f, 0, color2);
513             glVertex2i(x+20, y-10);
514             glColor4f(1.f, 0.4f, 0, color2);
515             glVertex2i(x+10, y-20);
516         glEnd();
517     glPopAttrib();
518 }
519 
renderMouse3d()520 void Renderer::renderMouse3d(){
521 
522 	const Gui *gui= game->getGui();
523 	const Mouse3d *mouse3d= gui->getMouse3d();
524 	const Map *map= game->getWorld()->getMap();
525 
526 	GLUquadricObj *cilQuadric;
527 	Vec4f color;
528 
529 	assertGl();
530 
531 	if((mouse3d->isEnabled() || gui->isPlacingBuilding()) && gui->isValidPosObjWorld()){
532 
533 		glMatrixMode(GL_MODELVIEW);
534 		glPushMatrix();
535 		glPushAttrib(GL_CURRENT_BIT | GL_LIGHTING_BIT | GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT);
536 		glEnable(GL_BLEND);
537 		glDisable(GL_STENCIL_TEST);
538 		glDepthFunc(GL_LESS);
539 		glEnable(GL_COLOR_MATERIAL);
540 		glDepthMask(GL_FALSE);
541 
542 		Vec2i pos= gui->getPosObjWorld();
543 		Vec3f pos3f= Vec3f(pos.x, map->getCell(pos)->getHeight(), pos.y);
544 
545 		if(gui->isPlacingBuilding()){
546 
547 			const UnitType *building= gui->getBuilding();
548 
549 			//selection building emplacement
550 			float offset= building->getSize()/2.f-0.5f;
551 			glTranslatef(pos3f.x+offset, pos3f.y, pos3f.z+offset);
552 
553 			//choose color
554 			if(map->isFreeCells(pos, building->getSize(), fLand)){
555 				color= Vec4f(1.f, 1.f, 1.f, 0.5f);
556 			}
557 			else{
558 				color= Vec4f(1.f, 0.f, 0.f, 0.5f);
559 			}
560 
561 			modelRenderer->begin(true, true, false);
562 			glColor4fv(color.ptr());
563 			glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color.ptr());
564 			const Model *buildingModel= building->getFirstStOfClass(scStop)->getAnimation();
565 			buildingModel->updateInterpolationData(0.f, false);
566 			modelRenderer->render(buildingModel);
567 			glDisable(GL_COLOR_MATERIAL);
568 			modelRenderer->end();
569 
570 		}
571 		else{
572 			//standard mouse
573 			glDisable(GL_TEXTURE_2D);
574 			glDisable(GL_CULL_FACE);
575 			color= Vec4f(1.f, 0.f, 0.f, 1.f-mouse3d->getFade());
576 			glColor4fv(color.ptr());
577 			glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color.ptr());
578 
579 			glTranslatef(pos3f.x, pos3f.y+2.f, pos3f.z);
580 			glRotatef(90.f, 1.f, 0.f, 0.f);
581 			glRotatef(static_cast<float>(mouse3d->getRot()), 0.f, 0.f, 1.f);
582 
583 			cilQuadric= gluNewQuadric();
584 			gluQuadricDrawStyle(cilQuadric, GLU_FILL);
585 			gluCylinder(cilQuadric, 0.5f, 0.f, 2.f, 4, 1);
586 			gluCylinder(cilQuadric, 0.5f, 0.f, 0.f, 4, 1);
587 			glTranslatef(0.f, 0.f, 1.f);
588 			gluCylinder(cilQuadric, 0.7f, 0.f, 1.f, 4, 1);
589 			gluCylinder(cilQuadric, 0.7f, 0.f, 0.f, 4, 1);
590 			gluDeleteQuadric(cilQuadric);
591 		}
592 
593 		glPopAttrib();
594 		glPopMatrix();
595 	}
596 
597 }
598 
renderBackground(const Texture2D * texture)599 void Renderer::renderBackground(const Texture2D *texture){
600 
601 	const Metrics &metrics= Metrics::getInstance();
602 
603 	assertGl();
604 
605     glPushAttrib(GL_ENABLE_BIT);
606 
607 	glDisable(GL_LIGHTING);
608 	glEnable(GL_TEXTURE_2D);
609 
610 	renderQuad(0, 0, metrics.getVirtualW(), metrics.getVirtualH(), texture);
611 
612 	glPopAttrib();
613 
614 	assertGl();
615 }
616 
renderTextureQuad(int x,int y,int w,int h,const Texture2D * texture,float alpha)617 void Renderer::renderTextureQuad(int x, int y, int w, int h, const Texture2D *texture, float alpha){
618     assertGl();
619 
620 	glPushAttrib(GL_ENABLE_BIT);
621 
622 	glDisable(GL_LIGHTING);
623 	glEnable(GL_TEXTURE_2D);
624 	glEnable(GL_BLEND);
625 
626 	glColor4f(1.f, 1.f, 1.f, alpha);
627 	renderQuad(x, y, w, h, texture);
628 
629 	glPopAttrib();
630 
631 	assertGl();
632 }
633 
renderConsole(const Console * console)634 void Renderer::renderConsole(const Console *console){
635 	glPushAttrib(GL_ENABLE_BIT);
636 	glEnable(GL_BLEND);
637 
638 	for(int i=0; i<console->getLineCount(); ++i){
639 		renderTextShadow(
640 			console->getLine(i),
641 			CoreData::getInstance().getConsoleFont(),
642 			20, i*20+20);
643 	}
644 
645 	glPopAttrib();
646 }
647 
renderChatManager(const ChatManager * chatManager)648 void Renderer::renderChatManager(const ChatManager *chatManager){
649 	Lang &lang= Lang::getInstance();
650 
651 	if(chatManager->getEditEnabled()){
652 		string text;
653 
654 		if(chatManager->getTeamMode()){
655 			text+= lang.get("Team");
656 		}
657 		else
658 		{
659 			text+= lang.get("All");
660 		}
661 		text+= ": " + chatManager->getText() + "_";
662 
663 		textRenderer->begin(CoreData::getInstance().getConsoleFont());
664 		textRenderer->render(text, 300, 150);
665 		textRenderer->end();
666 	}
667 }
668 
renderResourceStatus()669 void Renderer::renderResourceStatus(){
670 
671 	const Metrics &metrics= Metrics::getInstance();
672 	const World *world= game->getWorld();
673 	const Faction *thisFaction= world->getFaction(world->getThisFactionIndex());
674 
675 	assertGl();
676 
677 	glPushAttrib(GL_ENABLE_BIT);
678 
679 	int j= 0;
680 	for(int i= 0; i<world->getTechTree()->getResourceTypeCount(); ++i){
681 		const ResourceType *rt= world->getTechTree()->getResourceType(i);
682 		const Resource *r= thisFaction->getResource(rt);
683 
684 		//if any unit produces the resource
685 		bool showResource= false;
686 		for(int k=0; k<thisFaction->getType()->getUnitTypeCount(); ++k){
687 			const UnitType *ut= thisFaction->getType()->getUnitType(k);
688 			if(ut->getCost(rt)!=NULL){
689 				showResource= true;
690 				break;
691 			}
692 		}
693 
694 		//draw resource status
695 		if(showResource){
696 
697 			string str= intToStr(r->getAmount());
698 
699 			glEnable(GL_TEXTURE_2D);
700 			renderQuad(j*100+200, metrics.getVirtualH()-30, 16, 16, rt->getImage());
701 
702 			if(rt->getClass()!=rcStatic){
703 				str+= "/" + intToStr(thisFaction->getStoreAmount(rt));
704 			}
705 			if(rt->getClass()==rcConsumable){
706 				str+= "(";
707 				if(r->getBalance()>0){
708 					str+= "+";
709 				}
710 				str+= intToStr(r->getBalance()) + ")";
711 			}
712 
713 			glDisable(GL_TEXTURE_2D);
714 
715 			renderTextShadow(
716 				str, CoreData::getInstance().getMenuFontSmall(),
717 				j*100+220, metrics.getVirtualH()-30, false);
718 			++j;
719 		}
720 
721 	}
722 
723 	glPopAttrib();
724 
725 	assertGl();
726 }
727 
renderSelectionQuad()728 void Renderer::renderSelectionQuad(){
729 
730 	const Gui *gui= game->getGui();
731 	const SelectionQuad *sq= gui->getSelectionQuad();
732 
733     Vec2i down= sq->getPosDown();
734     Vec2i up= sq->getPosUp();
735 
736     if(gui->isSelecting()){
737         glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT);
738             glColor3f(0,1,0);
739             glBegin(GL_LINE_LOOP);
740                 glVertex2i(down.x, down.y);
741                 glVertex2i(up.x, down.y);
742                 glVertex2i(up.x, up.y);
743                 glVertex2i(down.x, up.y);
744             glEnd();
745         glPopAttrib();
746     }
747 }
748 
computeCenteredPos(const string & text,const Font2D * font,int x,int y)749 Vec2i computeCenteredPos(const string &text, const Font2D *font, int x, int y){
750 	Vec2i textPos;
751 
752 	const Metrics &metrics= Metrics::getInstance();
753 	const FontMetrics *fontMetrics= font->getMetrics();
754 
755 	textPos= Vec2i(
756 		x-metrics.toVirtualX(static_cast<int>(fontMetrics->getTextWidth(text)/2.f)),
757 		y-metrics.toVirtualY(static_cast<int>(fontMetrics->getHeight()/2.f)));
758 
759 	return textPos;
760 }
761 
renderText(const string & text,const Font2D * font,float alpha,int x,int y,bool centered)762 void Renderer::renderText(const string &text, const Font2D *font, float alpha, int x, int y, bool centered){
763 	glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT);
764 	glEnable(GL_BLEND);
765 	glColor4fv(Vec4f(1.f, 1.f, 1.f, alpha).ptr());
766 
767 	Vec2i pos= centered? computeCenteredPos(text, font, x, y): Vec2i(x, y);
768 
769 	textRenderer->begin(font);
770 	textRenderer->render(text, pos.x, pos.y);
771 	textRenderer->end();
772 
773 	glPopAttrib();
774 }
775 
renderText(const string & text,const Font2D * font,const Vec3f & color,int x,int y,bool centered)776 void Renderer::renderText(const string &text, const Font2D *font, const Vec3f &color, int x, int y, bool centered){
777 	glPushAttrib(GL_CURRENT_BIT);
778 	glColor3fv(color.ptr());
779 
780 	Vec2i pos= centered? computeCenteredPos(text, font, x, y): Vec2i(x, y);
781 
782 	textRenderer->begin(font);
783 	textRenderer->render(text, pos.x, pos.y);
784 	textRenderer->end();
785 
786 	glPopAttrib();
787 }
788 
renderTextShadow(const string & text,const Font2D * font,int x,int y,bool centered)789 void Renderer::renderTextShadow(const string &text, const Font2D *font, int x, int y, bool centered){
790 	glPushAttrib(GL_CURRENT_BIT);
791 
792 	Vec2i pos= centered? computeCenteredPos(text, font, x, y): Vec2i(x, y);
793 
794 	textRenderer->begin(font);
795 	glColor3f(0.0f, 0.0f, 0.0f);
796 	textRenderer->render(text, pos.x-1.0f, pos.y-1.0f);
797 	glColor3f(1.0f, 1.0f, 1.0f);
798 	textRenderer->render(text, pos.x, pos.y);
799 	textRenderer->end();
800 
801 	glPopAttrib();
802 }
803 
804 // ============= COMPONENTS =============================
805 
renderLabel(const GraphicLabel * label)806 void Renderer::renderLabel(const GraphicLabel *label){
807 
808 	glPushAttrib(GL_ENABLE_BIT);
809 	glEnable(GL_BLEND);
810 
811 	Vec2i textPos;
812 	int x= label->getX();
813     int y= label->getY();
814     int h= label->getH();
815     int w= label->getW();
816 
817 	if(label->getCentered()){
818 		textPos= Vec2i(x+w/2, y+h/2);
819 	}
820 	else{
821 		textPos= Vec2i(x, y+h/4);
822 	}
823 
824 	renderText(label->getText(), label->getFont(), GraphicComponent::getFade(), textPos.x, textPos.y, label->getCentered());
825 
826 	glPopAttrib();
827 }
828 
renderButton(const GraphicButton * button)829 void Renderer::renderButton(const GraphicButton *button){
830 
831     int x= button->getX();
832     int y= button->getY();
833     int h= button->getH();
834     int w= button->getW();
835 
836 	glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT);
837 
838 	//background
839 	CoreData &coreData= CoreData::getInstance();
840 	Texture2D *backTexture= w>3*h/2? coreData.getButtonBigTexture(): coreData.getButtonSmallTexture();
841 
842 	glEnable(GL_TEXTURE_2D);
843 	glEnable(GL_BLEND);
844 
845 	glBindTexture(GL_TEXTURE_2D, static_cast<Texture2DGl*>(backTexture)->getHandle());
846 
847 	//button
848 	Vec4f color= Vec4f(1.f, 1.f, 1.f, GraphicComponent::getFade());
849 	glColor4fv(color.ptr());
850 
851 	glBegin(GL_TRIANGLE_STRIP);
852 		glTexCoord2f(0.f, 0.f);
853 		glVertex2f(x, y);
854 
855 		glTexCoord2f(0.f, 1.f);
856 		glVertex2f(x, y+h);
857 
858 		glTexCoord2f(1.f, 0.f);
859 		glVertex2f(x+w, y);
860 
861 		glTexCoord2f(1.f, 1.f);
862 		glVertex2f(x+w, y+h);
863 
864 	glEnd();
865 
866 	glDisable(GL_TEXTURE_2D);
867 
868 	//lighting
869 	float anim= GraphicComponent::getAnim();
870 	if(anim>0.5f) anim= 1.f-anim;
871 
872 	if(button->getLighted()){
873 		const int lightSize= 0;
874 		const Vec4f color1= Vec4f(1.f, 1.f, 1.f, 0.1f+anim*0.5f);
875 		const Vec4f color2= Vec4f(1.f, 1.f, 1.f, 0.3f+anim);
876 
877 		glBegin(GL_TRIANGLE_FAN);
878 
879 		glColor4fv(color2.ptr());
880 		glVertex2f(x+w/2, y+h/2);
881 
882 		glColor4fv(color1.ptr());
883 		glVertex2f(x-lightSize, y-lightSize);
884 
885 		glColor4fv(color1.ptr());
886 		glVertex2f(x+w+lightSize, y-lightSize);
887 
888 		glColor4fv(color1.ptr());
889 		glVertex2f(x+w+lightSize, y+h+lightSize);
890 
891 		glColor4fv(color1.ptr());
892 		glVertex2f(x+w+lightSize, y+h+lightSize);
893 
894 		glColor4fv(color1.ptr());
895 		glVertex2f(x-lightSize, y+h+lightSize);
896 
897 		glColor4fv(color1.ptr());
898 		glVertex2f(x-lightSize, y-lightSize);
899 
900 		glEnd();
901 	}
902 
903 	Vec2i textPos= Vec2i(x+w/2, y+h/2);
904 
905 	renderText(
906 		button->getText(), button->getFont(), GraphicButton::getFade(),
907 		x+w/2, y+h/2, true);
908 
909     glPopAttrib();
910 }
911 
renderListBox(const GraphicListBox * listBox)912 void Renderer::renderListBox(const GraphicListBox *listBox){
913 
914 	renderButton(listBox->getButton1());
915     renderButton(listBox->getButton2());
916 
917 	glPushAttrib(GL_ENABLE_BIT);
918 	glEnable(GL_BLEND);
919 
920 	GraphicLabel label;
921 	label.init(listBox->getX(), listBox->getY(), listBox->getW(), listBox->getH(), true);
922 	label.setText(listBox->getText());
923 	label.setFont(listBox->getFont());
924 	renderLabel(&label);
925 
926 	glPopAttrib();
927 }
928 
renderMessageBox(const GraphicMessageBox * messageBox)929 void Renderer::renderMessageBox(const GraphicMessageBox *messageBox){
930 
931 	//background
932 	glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT);
933 	glEnable(GL_BLEND);
934 
935 	glColor4f(0.0f, 0.0f, 0.0f, 0.5f) ;
936 	glBegin(GL_TRIANGLE_STRIP);
937 		glVertex2i(messageBox->getX(), messageBox->getY()+9*messageBox->getH()/10);
938 		glVertex2i(messageBox->getX(), messageBox->getY());
939 		glVertex2i(messageBox->getX() + messageBox->getW(), messageBox->getY() + 9*messageBox->getH()/10);
940 		glVertex2i(messageBox->getX() + messageBox->getW(), messageBox->getY());
941 	glEnd();
942 
943 	glColor4f(0.0f, 0.0f, 0.0f, 0.8f) ;
944 	glBegin(GL_TRIANGLE_STRIP);
945 		glVertex2i(messageBox->getX(), messageBox->getY()+messageBox->getH());
946 		glVertex2i(messageBox->getX(), messageBox->getY()+9*messageBox->getH()/10);
947 		glVertex2i(messageBox->getX() + messageBox->getW(), messageBox->getY() + messageBox->getH());
948 		glVertex2i(messageBox->getX() + messageBox->getW(), messageBox->getY()+9*messageBox->getH()/10);
949 	glEnd();
950 
951 	glBegin(GL_LINE_LOOP);
952 		glColor4f(0.5f, 0.5f, 0.5f, 0.25f) ;
953 		glVertex2i(messageBox->getX(), messageBox->getY());
954 
955 		glColor4f(0.0f, 0.0f, 0.0f, 0.25f) ;
956 		glVertex2i(messageBox->getX()+ messageBox->getW(), messageBox->getY());
957 
958 		glColor4f(0.5f, 0.5f, 0.5f, 0.25f) ;
959 		glVertex2i(messageBox->getX()+ messageBox->getW(), messageBox->getY() + messageBox->getH());
960 
961 		glColor4f(0.25f, 0.25f, 0.25f, 0.25f) ;
962 		glVertex2i(messageBox->getX(), messageBox->getY() + messageBox->getH());
963 	glEnd();
964 
965 	glBegin(GL_LINE_STRIP);
966 		glColor4f(1.0f, 1.0f, 1.0f, 0.25f) ;
967 		glVertex2i(messageBox->getX(), messageBox->getY() + 90*messageBox->getH()/100);
968 
969 		glColor4f(0.5f, 0.5f, 0.5f, 0.25f) ;
970 		glVertex2i(messageBox->getX()+ messageBox->getW(), messageBox->getY() + 90*messageBox->getH()/100);
971 	glEnd();
972 
973 	glPopAttrib();
974 
975 	//buttons
976 	renderButton(messageBox->getButton1());
977 	if(messageBox->getButtonCount()==2){
978 		renderButton(messageBox->getButton2());
979 	}
980 
981 	//text
982 	renderText(
983 		messageBox->getText(), messageBox->getFont(), Vec3f(1.0f, 1.0f, 1.0f),
984 		messageBox->getX()+15, messageBox->getY()+7*messageBox->getH()/10,
985 		false );
986 
987 	renderText(
988 		messageBox->getHeader(), messageBox->getFont(),Vec3f(1.0f, 1.0f, 1.0f),
989 		messageBox->getX()+15, messageBox->getY()+93*messageBox->getH()/100,
990 		false );
991 }
992 
993 // ==================== complex rendering ====================
994 
renderSurface()995 void Renderer::renderSurface(){
996 
997 	int lastTex=-1;
998 	int currTex;
999 	const World *world= game->getWorld();
1000 	const Map *map= world->getMap();
1001 	const Rect2i mapBounds(0, 0, map->getSurfaceW()-1, map->getSurfaceH()-1);
1002 	float coordStep= world->getTileset()->getSurfaceAtlas()->getCoordStep();
1003 
1004 	assertGl();
1005 
1006 	const Texture2D *fowTex= world->getMinimap()->getFowTexture();
1007 
1008 	glPushAttrib(GL_LIGHTING_BIT | GL_ENABLE_BIT | GL_FOG_BIT | GL_TEXTURE_BIT);
1009 
1010 	glEnable(GL_BLEND);
1011 	glEnable(GL_COLOR_MATERIAL);
1012 	glDisable(GL_ALPHA_TEST);
1013 
1014 	//fog of war tex unit
1015 	glActiveTexture(fowTexUnit);
1016 	glEnable(GL_TEXTURE_2D);
1017 	glBindTexture(GL_TEXTURE_2D, static_cast<const Texture2DGl*>(fowTex)->getHandle());
1018 	glTexSubImage2D(
1019 		GL_TEXTURE_2D, 0, 0, 0,
1020 		fowTex->getPixmap()->getW(), fowTex->getPixmap()->getH(),
1021 		GL_ALPHA, GL_UNSIGNED_BYTE, fowTex->getPixmap()->getPixels());
1022 
1023 	//shadow texture
1024 	if(shadows==sProjected || shadows==sShadowMapping){
1025 		glActiveTexture(shadowTexUnit);
1026 		glEnable(GL_TEXTURE_2D);
1027 
1028 		glBindTexture(GL_TEXTURE_2D, shadowMapHandle);
1029 
1030 		static_cast<ModelRendererGl*>(modelRenderer)->setDuplicateTexCoords(true);
1031 		enableProjectiveTexturing();
1032 	}
1033 
1034 	glActiveTexture(baseTexUnit);
1035 
1036 	Quad2i scaledQuad= visibleQuad/Map::cellScale;
1037 
1038 	PosQuadIterator pqi(map, scaledQuad);
1039 	while(pqi.next()){
1040 
1041 		const Vec2i &pos= pqi.getPos();
1042 
1043 		if(mapBounds.isInside(pos)){
1044 
1045 			SurfaceCell *tc00= map->getSurfaceCell(pos.x, pos.y);
1046 			SurfaceCell *tc10= map->getSurfaceCell(pos.x+1, pos.y);
1047 			SurfaceCell *tc01= map->getSurfaceCell(pos.x, pos.y+1);
1048 			SurfaceCell *tc11= map->getSurfaceCell(pos.x+1, pos.y+1);
1049 
1050 			triangleCount+= 2;
1051 			pointCount+= 4;
1052 
1053 			//set texture
1054 			currTex= static_cast<const Texture2DGl*>(tc00->getSurfaceTexture())->getHandle();
1055 			if(currTex!=lastTex){
1056 				lastTex=currTex;
1057 				glBindTexture(GL_TEXTURE_2D, lastTex);
1058 			}
1059 
1060 			Vec2f surfCoord= tc00->getSurfTexCoord();
1061 
1062 			glBegin(GL_TRIANGLE_STRIP);
1063 
1064 			//draw quad using immediate mode
1065 			glMultiTexCoord2fv(fowTexUnit, tc01->getFowTexCoord().ptr());
1066 			glMultiTexCoord2f(baseTexUnit, surfCoord.x, surfCoord.y+coordStep);
1067 			glNormal3fv(tc01->getNormal().ptr());
1068 			glVertex3fv(tc01->getVertex().ptr());
1069 
1070 			glMultiTexCoord2fv(fowTexUnit, tc00->getFowTexCoord().ptr());
1071 			glMultiTexCoord2f(baseTexUnit, surfCoord.x, surfCoord.y);
1072 			glNormal3fv(tc00->getNormal().ptr());
1073 			glVertex3fv(tc00->getVertex().ptr());
1074 
1075 			glMultiTexCoord2fv(fowTexUnit, tc11->getFowTexCoord().ptr());
1076 			glMultiTexCoord2f(baseTexUnit, surfCoord.x+coordStep, surfCoord.y+coordStep);
1077 			glNormal3fv(tc11->getNormal().ptr());
1078 			glVertex3fv(tc11->getVertex().ptr());
1079 
1080 			glMultiTexCoord2fv(fowTexUnit, tc10->getFowTexCoord().ptr());
1081 			glMultiTexCoord2f(baseTexUnit, surfCoord.x+coordStep, surfCoord.y);
1082 			glNormal3fv(tc10->getNormal().ptr());
1083 			glVertex3fv(tc10->getVertex().ptr());
1084 
1085 			glEnd();
1086 		}
1087 	}
1088 	glEnd();
1089 
1090 	//Restore
1091 	static_cast<ModelRendererGl*>(modelRenderer)->setDuplicateTexCoords(false);
1092 	glPopAttrib();
1093 
1094 	//assert
1095 	glGetError();	//remove when first mtex problem solved
1096 	assertGl();
1097 }
1098 
renderObjects()1099 void Renderer::renderObjects(){
1100 	const World *world= game->getWorld();
1101 	const Map *map= world->getMap();
1102 
1103     assertGl();
1104 	const Texture2D *fowTex= world->getMinimap()->getFowTexture();
1105 	Vec3f baseFogColor= world->getTileset()->getFogColor()*computeLightColor(world->getTimeFlow()->getTime());
1106 
1107 	glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_FOG_BIT | GL_LIGHTING_BIT | GL_TEXTURE_BIT);
1108 
1109 	if(shadows==sShadowMapping){
1110 		glActiveTexture(shadowTexUnit);
1111 		glEnable(GL_TEXTURE_2D);
1112 
1113 		glBindTexture(GL_TEXTURE_2D, shadowMapHandle);
1114 
1115 		static_cast<ModelRendererGl*>(modelRenderer)->setDuplicateTexCoords(true);
1116 		enableProjectiveTexturing();
1117 	}
1118 
1119 	glActiveTexture(baseTexUnit);
1120 
1121 	glEnable(GL_COLOR_MATERIAL);
1122     glAlphaFunc(GL_GREATER, 0.5f);
1123 
1124 	modelRenderer->begin(true, true, false);
1125 	int thisTeamIndex= world->getThisTeamIndex();
1126 
1127 	PosQuadIterator pqi(map, visibleQuad, Map::cellScale);
1128 	while(pqi.next()){
1129 		const Vec2i pos= pqi.getPos();
1130 
1131 		if(map->isInside(pos)){
1132 
1133 			SurfaceCell *sc= map->getSurfaceCell(Map::toSurfCoords(pos));
1134 			Object *o= sc->getObject();
1135 			if(sc->isExplored(thisTeamIndex) && o!=NULL){
1136 
1137 				const Model *objModel= sc->getObject()->getModel();
1138 				Vec3f v= o->getPos();
1139 
1140 				//ambient and diffuse color is taken from cell color
1141 				float fowFactor= fowTex->getPixmap()->getPixelf(pos.x/Map::cellScale, pos.y/Map::cellScale);
1142 				Vec4f color= Vec4f(Vec3f(fowFactor), 1.f);
1143 				glColor4fv(color.ptr());
1144 				glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (color*ambFactor).ptr());
1145 				glFogfv(GL_FOG_COLOR, (baseFogColor*fowFactor).ptr());
1146 
1147 				glMatrixMode(GL_MODELVIEW);
1148 				glPushMatrix();
1149 				glTranslatef(v.x, v.y, v.z);
1150 				glRotatef(o->getRotation(), 0.f, 1.f, 0.f);
1151 
1152 				objModel->updateInterpolationData(0.f, true);
1153 				modelRenderer->render(objModel);
1154 
1155 				triangleCount+= objModel->getTriangleCount();
1156 				pointCount+= objModel->getVertexCount();
1157 
1158 				glPopMatrix();
1159 
1160 			}
1161 		}
1162 	}
1163 
1164 	modelRenderer->end();
1165 
1166 	//restore
1167 	static_cast<ModelRendererGl*>(modelRenderer)->setDuplicateTexCoords(true);
1168 	glPopAttrib();
1169 }
1170 
renderWater()1171 void Renderer::renderWater(){
1172 
1173 	bool closed= false;
1174 	const World *world= game->getWorld();
1175 	const Map *map= world->getMap();
1176 
1177 	float waterAnim= world->getWaterEffects()->getAmin();
1178 
1179 	//assert
1180     assertGl();
1181 
1182 	glPushAttrib(GL_TEXTURE_BIT | GL_ENABLE_BIT | GL_CURRENT_BIT);
1183 
1184 	//water texture nit
1185     glDisable(GL_TEXTURE_2D);
1186 
1187 	glEnable(GL_BLEND);
1188 	if(textures3D){
1189 		Texture3D *waterTex= world->getTileset()->getWaterTex();
1190 		glEnable(GL_TEXTURE_3D);
1191 		glBindTexture(GL_TEXTURE_3D, static_cast<Texture3DGl*>(waterTex)->getHandle());
1192 	}
1193 	else{
1194 		glEnable(GL_COLOR_MATERIAL);
1195 		glColor4f(0.5f, 0.5f, 1.0f, 0.5f);
1196 		glBindTexture(GL_TEXTURE_3D, 0);
1197 	}
1198 
1199 	assertGl();
1200 
1201 	//fog of War texture Unit
1202 	const Texture2D *fowTex= world->getMinimap()->getFowTexture();
1203 	glActiveTexture(fowTexUnit);
1204 	glEnable(GL_TEXTURE_2D);
1205     glBindTexture(GL_TEXTURE_2D, static_cast<const Texture2DGl*>(fowTex)->getHandle());
1206     glActiveTexture(baseTexUnit);
1207 
1208 	assertGl();
1209 
1210 	Rect2i boundingRect= visibleQuad.computeBoundingRect();
1211 	Rect2i scaledRect= boundingRect/Map::cellScale;
1212 	scaledRect.clamp(0, 0, map->getSurfaceW()-1, map->getSurfaceH()-1);
1213 
1214 	float waterLevel= world->getMap()->getWaterLevel();
1215     for(int j=scaledRect.p[0].y; j<scaledRect.p[1].y; ++j){
1216         glBegin(GL_TRIANGLE_STRIP);
1217 
1218 		for(int i=scaledRect.p[0].x; i<=scaledRect.p[1].x; ++i){
1219 
1220 			SurfaceCell *tc0= map->getSurfaceCell(i, j);
1221             SurfaceCell *tc1= map->getSurfaceCell(i, j+1);
1222 
1223 			int thisTeamIndex= world->getThisTeamIndex();
1224 			if(tc0->getNearSubmerged() && (tc0->isExplored(thisTeamIndex) || tc1->isExplored(thisTeamIndex))){
1225 				glNormal3f(0.f, 1.f, 0.f);
1226                 closed= false;
1227 
1228                 triangleCount+= 2;
1229 				pointCount+= 2;
1230 
1231                 //vertex 1
1232 				glMaterialfv(
1233 					GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,
1234 					computeWaterColor(waterLevel, tc1->getHeight()).ptr());
1235 				glMultiTexCoord2fv(GL_TEXTURE1, tc1->getFowTexCoord().ptr());
1236                 glTexCoord3f(i, 1.f, waterAnim);
1237 				glVertex3f(
1238 					static_cast<float>(i)*Map::mapScale,
1239 					waterLevel,
1240 					static_cast<float>(j+1)*Map::mapScale);
1241 
1242                 //vertex 2
1243 				glMaterialfv(
1244 					GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,
1245 					computeWaterColor(waterLevel, tc0->getHeight()).ptr());
1246 				glMultiTexCoord2fv(GL_TEXTURE1, tc0->getFowTexCoord().ptr());
1247                 glTexCoord3f(i, 0.f, waterAnim);
1248                 glVertex3f(
1249 					static_cast<float>(i)*Map::mapScale,
1250 					waterLevel,
1251 					static_cast<float>(j)*Map::mapScale);
1252 
1253             }
1254             else{
1255 				if(!closed){
1256 
1257 					pointCount+= 2;
1258 
1259 					//vertex 1
1260 					glMaterialfv(
1261 						GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,
1262 						computeWaterColor(waterLevel, tc1->getHeight()).ptr());
1263 					glMultiTexCoord2fv(GL_TEXTURE1, tc1->getFowTexCoord().ptr());
1264 					glTexCoord3f(i, 1.f, waterAnim);
1265 					glVertex3f(
1266 						static_cast<float>(i)*Map::mapScale,
1267 						waterLevel,
1268 						static_cast<float>(j+1)*Map::mapScale);
1269 
1270 					//vertex 2
1271 					glMaterialfv(
1272 						GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,
1273 						computeWaterColor(waterLevel, tc0->getHeight()).ptr());
1274 					glMultiTexCoord2fv(GL_TEXTURE1, tc0->getFowTexCoord().ptr());
1275 					glTexCoord3f(i, 0.f, waterAnim);
1276 					glVertex3f(
1277 						static_cast<float>(i)*Map::mapScale,
1278 						waterLevel,
1279 						static_cast<float>(j)*Map::mapScale);
1280 
1281 					glEnd();
1282 					glBegin(GL_TRIANGLE_STRIP);
1283 					closed= true;
1284 				}
1285            	}
1286         }
1287         glEnd();
1288     }
1289 
1290 	//restore
1291 	glPopAttrib();
1292 
1293 	assertGl();
1294 }
1295 
renderUnits()1296 void Renderer::renderUnits(){
1297 	Unit *unit;
1298 	const World *world= game->getWorld();
1299 	MeshCallbackTeamColor meshCallbackTeamColor;
1300 
1301 	//assert
1302 	assertGl();
1303 
1304 	glPushAttrib(GL_ENABLE_BIT | GL_FOG_BIT | GL_LIGHTING_BIT | GL_TEXTURE_BIT);
1305 	glEnable(GL_COLOR_MATERIAL);
1306 
1307 	if(shadows==sShadowMapping){
1308 		glActiveTexture(shadowTexUnit);
1309 		glEnable(GL_TEXTURE_2D);
1310 
1311 		glBindTexture(GL_TEXTURE_2D, shadowMapHandle);
1312 
1313 		static_cast<ModelRendererGl*>(modelRenderer)->setDuplicateTexCoords(true);
1314 		enableProjectiveTexturing();
1315 	}
1316 	glActiveTexture(baseTexUnit);
1317 
1318 	modelRenderer->begin(true, true, true, &meshCallbackTeamColor);
1319 
1320 	for(int i=0; i<world->getFactionCount(); ++i){
1321 		meshCallbackTeamColor.setTeamTexture(world->getFaction(i)->getTexture());
1322 		for(int j=0; j<world->getFaction(i)->getUnitCount(); ++j){
1323 			unit= world->getFaction(i)->getUnit(j);
1324 			if(world->toRenderUnit(unit, visibleQuad)) {
1325 
1326 				glMatrixMode(GL_MODELVIEW);
1327 				glPushMatrix();
1328 
1329 				//translate
1330 				Vec3f currVec= unit->getCurrVectorFlat();
1331 				glTranslatef(currVec.x, currVec.y, currVec.z);
1332 
1333 				//rotate
1334 				glRotatef(unit->getRotation(), 0.f, 1.f, 0.f);
1335 				glRotatef(unit->getVerticalRotation(), 1.f, 0.f, 0.f);
1336 
1337 				//dead alpha
1338 				float alpha= 1.0f;
1339 				const SkillType *st= unit->getCurrSkill();
1340 				if(st->getClass()==scDie && static_cast<const DieSkillType*>(st)->getFade()){
1341 					alpha= 1.0f-unit->getAnimProgress();
1342 					glDisable(GL_COLOR_MATERIAL);
1343 					glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Vec4f(1.0f, 1.0f, 1.0f, alpha).ptr());
1344 				}
1345 				else{
1346 					glEnable(GL_COLOR_MATERIAL);
1347 				}
1348 
1349 				//render
1350 				const Model *model= unit->getCurrentModel();
1351 				model->updateInterpolationData(unit->getAnimProgress(), unit->isAlive());
1352 				modelRenderer->render(model);
1353 
1354 				triangleCount+= model->getTriangleCount();
1355 				pointCount+= model->getVertexCount();
1356 
1357 				glPopMatrix();
1358 			}
1359 		}
1360 	}
1361 	modelRenderer->end();
1362 
1363 	//restore
1364 	static_cast<ModelRendererGl*>(modelRenderer)->setDuplicateTexCoords(true);
1365 	glPopAttrib();
1366 
1367 	//assert
1368 	assertGl();
1369 }
1370 
renderSelectionEffects()1371 void Renderer::renderSelectionEffects(){
1372 
1373 	const World *world= game->getWorld();
1374 	const Map *map= world->getMap();
1375 	const Selection *selection= game->getGui()->getSelection();
1376 
1377 	glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT);
1378 	glDisable(GL_LIGHTING);
1379 	glDisable(GL_TEXTURE_2D);
1380 	glDepthFunc(GL_ALWAYS);
1381 	glDisable(GL_STENCIL_TEST);
1382 	glDisable(GL_CULL_FACE);
1383 	glEnable(GL_BLEND);
1384 	glLineWidth(2.f);
1385 
1386 	//units
1387 	for(int i=0; i<selection->getCount(); ++i){
1388 
1389 		const Unit *unit= selection->getUnit(i);
1390 
1391 		//translate
1392 		Vec3f currVec= unit->getCurrVectorFlat();
1393 		currVec.y+= 0.3f;
1394 
1395 		//selection circle
1396 		if(world->getThisFactionIndex()==unit->getFactionIndex()){
1397 			glColor4f(0, unit->getHpRatio(), 0, 0.3f);
1398 		}
1399 		else{
1400 			glColor4f(unit->getHpRatio(), 0, 0, 0.3f);
1401 		}
1402 		renderSelectionCircle(currVec, unit->getType()->getSize(), selectionCircleRadius);
1403 
1404 		//magic circle
1405 		if(world->getThisFactionIndex()==unit->getFactionIndex() && unit->getType()->getMaxEp()>0){
1406 			glColor4f(unit->getEpRatio()/2.f, unit->getEpRatio(), unit->getEpRatio(), 0.5f);
1407 			renderSelectionCircle(currVec, unit->getType()->getSize(), magicCircleRadius);
1408 		}
1409 	}
1410 
1411 	//target arrow
1412 	if(selection->getCount()==1){
1413 		const Unit *unit= selection->getUnit(0);
1414 
1415 		//comand arrow
1416 		if(focusArrows && unit->anyCommand()){
1417 			const CommandType *ct= unit->getCurrCommand()->getCommandType();
1418 			if(ct->getClicks()!=cOne){
1419 
1420 				//arrow color
1421 				Vec3f arrowColor;
1422 				switch(ct->getClass()){
1423 				case ccMove:
1424 					arrowColor= Vec3f(0.f, 1.f, 0.f);
1425 					break;
1426 				case ccAttack:
1427 				case ccAttackStopped:
1428 					arrowColor= Vec3f(1.f, 0.f, 0.f);
1429 					break;
1430 				default:
1431 					arrowColor= Vec3f(1.f, 1.f, 0.f);
1432 				}
1433 
1434 				//arrow target
1435 				Vec3f arrowTarget;
1436 				Command *c= unit->getCurrCommand();
1437 				if(c->getUnit()!=NULL){
1438 					arrowTarget= c->getUnit()->getCurrVectorFlat();
1439 				}
1440 				else{
1441 					Vec2i pos= c->getPos();
1442 					arrowTarget= Vec3f(pos.x, map->getCell(pos)->getHeight(), pos.y);
1443 				}
1444 
1445 				renderArrow(unit->getCurrVectorFlat(), arrowTarget, arrowColor, 0.3f);
1446 			}
1447 		}
1448 
1449 		//meeting point arrow
1450 		if(unit->getType()->getMeetingPoint()){
1451 			Vec2i pos= unit->getMeetingPos();
1452 			Vec3f arrowTarget= Vec3f(pos.x, map->getCell(pos)->getHeight(), pos.y);
1453 			renderArrow(unit->getCurrVectorFlat(), arrowTarget, Vec3f(0.f, 0.f, 1.f), 0.3f);
1454 		}
1455 
1456 	}
1457 
1458 	//render selection hightlights
1459 	for(int i=0; i<world->getFactionCount(); ++i){
1460 		for(int j=0; j<world->getFaction(i)->getUnitCount(); ++j){
1461 			const Unit *unit= world->getFaction(i)->getUnit(j);
1462 
1463 			if(unit->isHighlighted()){
1464 				float highlight= unit->getHightlight();
1465 				if(game->getWorld()->getThisFactionIndex()==unit->getFactionIndex()){
1466 					glColor4f(0.f, 1.f, 0.f, highlight);
1467 				}
1468 				else{
1469 					glColor4f(1.f, 0.f, 0.f, highlight);
1470 				}
1471 
1472 				Vec3f v= unit->getCurrVectorFlat();
1473 				v.y+= 0.3f;
1474 				renderSelectionCircle(v, unit->getType()->getSize(), selectionCircleRadius);
1475 			}
1476 		}
1477 	}
1478 
1479 	glPopAttrib();
1480 }
1481 
renderWaterEffects()1482 void Renderer::renderWaterEffects(){
1483 	const World *world= game->getWorld();
1484 	const WaterEffects *we= world->getWaterEffects();
1485 	const Map *map= world->getMap();
1486 	const CoreData &coreData= CoreData::getInstance();
1487 	float height= map->getWaterLevel()+0.001f;
1488 
1489 	assertGl();
1490 
1491 	glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT);
1492 	glEnable(GL_BLEND);
1493 	glDisable(GL_ALPHA_TEST);
1494 	glDepthMask(GL_FALSE);
1495 	glDepthFunc(GL_LEQUAL);
1496 	glEnable(GL_COLOR_MATERIAL);
1497 
1498 	glNormal3f(0.f, 1.f, 0.f);
1499 
1500 	//splashes
1501 	glBindTexture(GL_TEXTURE_2D, static_cast<Texture2DGl*>(coreData.getWaterSplashTexture())->getHandle());
1502 	for(int i=0; i<we->getWaterSplashCount(); ++i){
1503 		const WaterSplash *ws= we->getWaterSplash(i);
1504 
1505 		//render only if enabled
1506 		if(ws->getEnabled()){
1507 
1508 			//render only if visible
1509 			Vec2i intPos= Vec2i(static_cast<int>(ws->getPos().x), static_cast<int>(ws->getPos().y));
1510 			if(map->getSurfaceCell(Map::toSurfCoords(intPos))->isVisible(world->getThisTeamIndex())){
1511 
1512 				float scale= ws->getAnim();
1513 
1514 				glColor4f(1.f, 1.f, 1.f, 1.f-ws->getAnim());
1515 				glBegin(GL_TRIANGLE_STRIP);
1516 					glTexCoord2f(0.f, 1.f);
1517 					glVertex3f(ws->getPos().x-scale, height, ws->getPos().y+scale);
1518 					glTexCoord2f(0.f, 0.f);
1519 					glVertex3f(ws->getPos().x-scale, height, ws->getPos().y-scale);
1520 					glTexCoord2f(1.f, 1.f);
1521 					glVertex3f(ws->getPos().x+scale, height, ws->getPos().y+scale);
1522 					glTexCoord2f(1.f, 0.f);
1523 					glVertex3f(ws->getPos().x+scale, height, ws->getPos().y-scale);
1524 				glEnd();
1525 			}
1526 		}
1527 	}
1528 
1529 	glPopAttrib();
1530 
1531 	assertGl();
1532 }
1533 
renderMinimap()1534 void Renderer::renderMinimap(){
1535     const World *world= game->getWorld();
1536 	const Minimap *minimap= world->getMinimap();
1537 	const GameCamera *gameCamera= game->getGameCamera();
1538 	const Pixmap2D *pixmap= minimap->getTexture()->getPixmap();
1539 	const Metrics &metrics= Metrics::getInstance();
1540 
1541 	int mx= metrics.getMinimapX();
1542 	int my= metrics.getMinimapY();
1543 	int mw= metrics.getMinimapW();
1544 	int mh= metrics.getMinimapH();
1545 
1546 	Vec2f zoom= Vec2f(
1547 		static_cast<float>(mw)/ pixmap->getW(),
1548 		static_cast<float>(mh)/ pixmap->getH());
1549 
1550 	assertGl();
1551 
1552     glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_LINE_BIT | GL_TEXTURE_BIT);
1553 
1554     //draw map
1555 	glEnable(GL_TEXTURE_2D);
1556 	glEnable(GL_BLEND);
1557 
1558 	glActiveTexture(fowTexUnit);
1559 	glEnable(GL_TEXTURE_2D);
1560 	glBindTexture(GL_TEXTURE_2D, static_cast<const Texture2DGl*>(minimap->getFowTexture())->getHandle());
1561 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
1562 
1563 	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
1564 	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
1565 	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
1566 	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE);
1567 
1568 	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_ADD);
1569 	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR);
1570 	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE);
1571 
1572 	glActiveTexture(baseTexUnit);
1573 	glBindTexture(GL_TEXTURE_2D, static_cast<const Texture2DGl*>(minimap->getTexture())->getHandle());
1574 
1575 	glColor4f(0.5f, 0.5f, 0.5f, 0.1f);
1576 	glBegin(GL_TRIANGLE_STRIP);
1577 		glTexCoord2f(0.0f, 1.0f);
1578 		glMultiTexCoord2f(fowTexUnit, 0.0f, 1.0f);
1579 		glVertex2i(mx, my);
1580 		glTexCoord2f(0.0f, 0.0f);
1581 		glMultiTexCoord2f(fowTexUnit, 0.0f, 0.0f);
1582 		glVertex2i(mx, my+mh);
1583 		glTexCoord2f(1.0f, 1.0f);
1584 		glMultiTexCoord2f(fowTexUnit, 1.0f, 1.0f);
1585 		glVertex2i(mx+mw, my);
1586 		glTexCoord2f(1.0f, 0.0f);
1587 		glMultiTexCoord2f(fowTexUnit, 1.0f, 0.0f);
1588 		glVertex2i(mx+mw, my+mh);
1589 	glEnd();
1590 
1591     glDisable(GL_BLEND);
1592 
1593 	glActiveTexture(fowTexUnit);
1594 	glDisable(GL_TEXTURE_2D);
1595 	glActiveTexture(baseTexUnit);
1596 	glDisable(GL_TEXTURE_2D);
1597 
1598 	//draw units
1599 	glBegin(GL_QUADS);
1600 	for(int i=0; i<world->getFactionCount(); ++i){
1601 		for(int j=0; j<world->getFaction(i)->getUnitCount(); ++j){
1602 			Unit *unit= world->getFaction(i)->getUnit(j);
1603 			if(world->toRenderUnit(unit)){
1604 				Vec2i pos= unit->getPos()/Map::cellScale;
1605 				int size= unit->getType()->getSize();
1606 				Vec3f color=  world->getFaction(i)->getTexture()->getPixmap()->getPixel3f(0, 0);
1607 				glColor3fv(color.ptr());
1608 				glVertex2f(mx + pos.x*zoom.x, my + mh - (pos.y*zoom.y));
1609 				glVertex2f(mx + (pos.x+1)*zoom.x+size, my + mh - (pos.y*zoom.y));
1610 				glVertex2f(mx + (pos.x+1)*zoom.x+size, my + mh - ((pos.y+size)*zoom.y));
1611 				glVertex2f(mx + pos.x*zoom.x, my + mh - ((pos.y+size)*zoom.y));
1612 			}
1613 		}
1614 	}
1615 	glEnd();
1616 
1617     //draw camera
1618 	float wRatio= static_cast<float>(metrics.getMinimapW()) / world->getMap()->getW();
1619 	float hRatio= static_cast<float>(metrics.getMinimapH()) / world->getMap()->getH();
1620 
1621     int x= static_cast<int>(gameCamera->getPos().x * wRatio);
1622     int y= static_cast<int>(gameCamera->getPos().z * hRatio);
1623 
1624     float ang= degToRad(gameCamera->getHAng());
1625 
1626     glEnable(GL_BLEND);
1627 
1628 	glBegin(GL_TRIANGLES);
1629     glColor4f(1.f, 1.f, 1.f, 1.f);
1630 	glVertex2i(mx+x, my+mh-y);
1631 
1632 	glColor4f(1.f, 1.f, 1.f, 0.0f);
1633 	glVertex2i(
1634 		mx + x + static_cast<int>(20*sin(ang-pi/5)),
1635 		my + mh - (y-static_cast<int>(20*cos(ang-pi/5))));
1636 
1637 	glColor4f(1.f, 1.f, 1.f, 0.0f);
1638     glVertex2i(
1639 		mx + x + static_cast<int>(20*sin(ang+pi/5)),
1640 		my + mh - (y-static_cast<int>(20*cos(ang+pi/5))));
1641 
1642     glEnd();
1643     glPopAttrib();
1644 
1645 	assertGl();
1646 }
1647 
renderDisplay()1648 void Renderer::renderDisplay(){
1649 
1650 	CoreData &coreData= CoreData::getInstance();
1651 	const Metrics &metrics= Metrics::getInstance();
1652 	const Display *display= game->getGui()->getDisplay();
1653 
1654 	glPushAttrib(GL_ENABLE_BIT);
1655 
1656 	//infoString
1657 	renderTextShadow(
1658 		display->getInfoText().c_str(),
1659 		coreData.getDisplayFont(),
1660 		metrics.getDisplayX(),
1661 		metrics.getDisplayY()+Display::infoStringY);
1662 
1663 	//title
1664 	renderTextShadow(
1665 		display->getTitle().c_str(),
1666 		coreData.getDisplayFont(),
1667 		metrics.getDisplayX()+40,
1668 		metrics.getDisplayY() + metrics.getDisplayH() - 20);
1669 
1670     glColor3f(0.0f, 0.0f, 0.0f);
1671 
1672 	//text
1673 	renderTextShadow(
1674 		display->getText().c_str(),
1675 		coreData.getDisplayFont(),
1676 		metrics.getDisplayX() -1,
1677 		metrics.getDisplayY() + metrics.getDisplayH() - 56);
1678 
1679 	//progress Bar
1680 	if(display->getProgressBar()!=-1){
1681 		renderProgressBar(
1682 			display->getProgressBar(),
1683 			metrics.getDisplayX(),
1684 			metrics.getDisplayY() + metrics.getDisplayH()-50,
1685 			coreData.getMenuFontSmall());
1686 	}
1687 
1688 	//up images
1689 	glEnable(GL_TEXTURE_2D);
1690 
1691 	glColor3f(1.f, 1.f, 1.f);
1692 	for(int i=0; i<Display::upCellCount; ++i){
1693 		if(display->getUpImage(i)!=NULL){
1694 			renderQuad(
1695 				metrics.getDisplayX()+display->computeUpX(i),
1696 				metrics.getDisplayY()+display->computeUpY(i),
1697 				Display::imageSize, Display::imageSize, display->getUpImage(i));
1698 		}
1699 	}
1700 
1701  	//down images
1702 	for(int i=0; i<Display::downCellCount; ++i){
1703 		if(display->getDownImage(i)!=NULL){
1704 			if(display->getDownLighted(i)){
1705                 glColor3f(1.f, 1.f, 1.f);
1706 			}
1707 			else{
1708                 glColor3f(0.3f, 0.3f, 0.3f);
1709 			}
1710 
1711 			int x= metrics.getDisplayX()+display->computeDownX(i);
1712 			int y= metrics.getDisplayY()+display->computeDownY(i);
1713 			int size= Display::imageSize;
1714 
1715 			if(display->getDownSelectedPos()==i){
1716 				x-= 3;
1717 				y-= 3;
1718 				size+= 6;
1719 			}
1720 
1721 			renderQuad(x, y, size, size, display->getDownImage(i));
1722 		}
1723 	}
1724 
1725 	//selection
1726 	int downPos= display->getDownSelectedPos();
1727 	if(downPos!=Display::invalidPos){
1728 		const Texture2D *texture= display->getDownImage(downPos);
1729 		if(texture!=NULL){
1730 			int x= metrics.getDisplayX()+display->computeDownX(downPos)-3;
1731 			int y= metrics.getDisplayY()+display->computeDownY(downPos)-3;
1732 			int size= Display::imageSize+6;
1733 			renderQuad(x, y, size, size, display->getDownImage(downPos));
1734 		}
1735     }
1736 
1737 	glPopAttrib();
1738 }
1739 
renderMenuBackground(const MenuBackground * menuBackground)1740 void Renderer::renderMenuBackground(const MenuBackground *menuBackground){
1741 
1742 	assertGl();
1743 
1744 	Vec3f cameraPosition= menuBackground->getCamera()->getPosition();
1745 
1746 	glPushAttrib(GL_LIGHTING_BIT | GL_ENABLE_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT);
1747 
1748 	//clear
1749 	Vec4f fogColor= Vec4f(0.4f, 0.4f, 0.4f, 1.f) * menuBackground->getFade();
1750 	glClearColor(fogColor.x, fogColor.y, fogColor.z, 1.f);
1751 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1752 	glFogfv(GL_FOG_COLOR, fogColor.ptr());
1753 
1754 	//light
1755 	Vec4f lightPos= Vec4f(10.f, 10.f, 10.f, 1.f)* menuBackground->getFade();
1756 	Vec4f diffLight= Vec4f(0.9f, 0.9f, 0.9f, 1.f)* menuBackground->getFade();
1757 	Vec4f ambLight= Vec4f(0.3f, 0.3f, 0.3f, 1.f)* menuBackground->getFade();
1758 	Vec4f specLight= Vec4f(0.1f, 0.1f, 0.1f, 1.f)* menuBackground->getFade();
1759 
1760 	glEnable(GL_LIGHT0);
1761 	glLightfv(GL_LIGHT0, GL_POSITION, lightPos.ptr());
1762 	glLightfv(GL_LIGHT0, GL_DIFFUSE, diffLight.ptr());
1763 	glLightfv(GL_LIGHT0, GL_AMBIENT, ambLight.ptr());
1764 	glLightfv(GL_LIGHT0, GL_SPECULAR, specLight.ptr());
1765 
1766 	//main model
1767 	glEnable(GL_ALPHA_TEST);
1768 	glAlphaFunc(GL_GREATER, 0.5f);
1769 	modelRenderer->begin(true, true, true);
1770 	modelRenderer->render(menuBackground->getMainModel());
1771 	modelRenderer->end();
1772 	glDisable(GL_ALPHA_TEST);
1773 
1774 	//characters
1775 	float dist= menuBackground->getAboutPosition().dist(cameraPosition);
1776 	float minDist= 3.f;
1777 	if(dist<minDist){
1778 
1779 		glAlphaFunc(GL_GREATER, 0.0f);
1780 		float alpha= clamp((minDist-dist)/minDist, 0.f, 1.f);
1781 		glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Vec4f(1.0f, 1.0f, 1.0f, alpha).ptr());
1782 		modelRenderer->begin(true, true, false);
1783 
1784 		for(int i=0; i<MenuBackground::characterCount; ++i){
1785 			glMatrixMode(GL_MODELVIEW);
1786 			glPushMatrix();
1787 			glLoadIdentity();
1788 			glTranslatef(i*2.f-4.f, -1.4f, -7.5f);
1789 			menuBackground->getCharacterModel(i)->updateInterpolationData(menuBackground->getAnim(), true);
1790 			modelRenderer->render(menuBackground->getCharacterModel(i));
1791 			glPopMatrix();
1792 		}
1793 		modelRenderer->end();
1794 	}
1795 
1796 	//water
1797 	if(menuBackground->getWater()){
1798 
1799 		//water surface
1800 		const int waterTesselation= 10;
1801 		const int waterSize= 250;
1802 		const int waterQuadSize= 2*waterSize/waterTesselation;
1803 		const float waterHeight= menuBackground->getWaterHeight();
1804 
1805 		glEnable(GL_BLEND);
1806 
1807 		glNormal3f(0.f, 1.f, 0.f);
1808 		glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Vec4f(1.f, 1.f, 1.f, 1.f).ptr());
1809 		GLuint waterHandle= static_cast<Texture2DGl*>(menuBackground->getWaterTexture())->getHandle();
1810 		glBindTexture(GL_TEXTURE_2D, waterHandle);
1811 		for(int i=1; i<waterTesselation; ++i){
1812 			glBegin(GL_TRIANGLE_STRIP);
1813 			for(int j=1; j<waterTesselation; ++j){
1814 				glTexCoord2i(1, 2 % j);
1815 				glVertex3f(-waterSize+i*waterQuadSize, waterHeight, -waterSize+j*waterQuadSize);
1816 				glTexCoord2i(0, 2 % j);
1817 				glVertex3f(-waterSize+(i+1)*waterQuadSize, waterHeight, -waterSize+j*waterQuadSize);
1818 			}
1819 			glEnd();
1820 		}
1821 		glDisable(GL_BLEND);
1822 
1823 		//raindrops
1824 		if(menuBackground->getRain()){
1825 			const float maxRaindropAlpha= 0.5f;
1826 
1827 			glEnable(GL_BLEND);
1828 			glDisable(GL_LIGHTING);
1829 			glDisable(GL_ALPHA_TEST);
1830 			glDepthMask(GL_FALSE);
1831 
1832 			//splashes
1833 			CoreData &coreData= CoreData::getInstance();
1834 			glBindTexture(GL_TEXTURE_2D, static_cast<Texture2DGl*>(coreData.getWaterSplashTexture())->getHandle());
1835 			for(int i=0; i<MenuBackground::raindropCount; ++i){
1836 
1837 				Vec2f pos= menuBackground->getRaindropPos(i);
1838 				float scale= menuBackground->getRaindropState(i);
1839 				float alpha= maxRaindropAlpha-scale*maxRaindropAlpha;
1840 
1841 				glMatrixMode(GL_MODELVIEW);
1842 				glPushMatrix();
1843 
1844 				glColor4f(1.f, 1.f, 1.f, alpha);
1845 				glTranslatef(pos.x, waterHeight+0.01f, pos.y);
1846 
1847 				glBegin(GL_TRIANGLE_STRIP);
1848 					glTexCoord2f(0.f, 1.f);
1849 					glVertex3f(-scale, 0, scale);
1850 					glTexCoord2f(0.f, 0.f);
1851 					glVertex3f(-scale, 0, -scale);
1852 					glTexCoord2f(1.f, 1.f);
1853 					glVertex3f(scale, 0, scale);
1854 					glTexCoord2f(1.f, 0.f);
1855 					glVertex3f(scale, 0, -scale);
1856 				glEnd();
1857 
1858 				glPopMatrix();
1859 			}
1860 		}
1861 	}
1862 
1863 	glPopAttrib();
1864 
1865 	assertGl();
1866 }
1867 
1868 // ==================== computing ====================
1869 
computePosition(const Vec2i & screenPos,Vec2i & worldPos)1870 bool Renderer::computePosition(const Vec2i &screenPos, Vec2i &worldPos){
1871 
1872 	assertGl();
1873 	const Map* map= game->getWorld()->getMap();
1874 	const Metrics &metrics= Metrics::getInstance();
1875 	float depth= 0.0f;
1876 	GLdouble modelviewMatrix[16];
1877 	GLdouble projectionMatrix[16];
1878 	GLint viewport[4]= {0, 0, metrics.getScreenW(), metrics.getScreenH()};
1879 	GLdouble worldX;
1880 	GLdouble worldY;
1881 	GLdouble worldZ;
1882 	GLint screenX= (screenPos.x * metrics.getScreenW() / metrics.getVirtualW());
1883 	GLint screenY= (screenPos.y * metrics.getScreenH() / metrics.getVirtualH());
1884 
1885 	//get the depth in the cursor pixel
1886 	glReadPixels(screenX, screenY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
1887 
1888 	//load matrices
1889 	loadProjectionMatrix();
1890     loadGameCameraMatrix();
1891 
1892 	//get matrices
1893 	glGetDoublev(GL_MODELVIEW_MATRIX, modelviewMatrix);
1894 	glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix);
1895 
1896 	//get the world coordinates
1897 	gluUnProject(
1898 		screenX, screenY, depth,
1899 		modelviewMatrix, projectionMatrix, viewport,
1900 		&worldX, &worldY, &worldZ);
1901 
1902 	//conver coords to int
1903 	worldPos= Vec2i(static_cast<int>(worldX+0.5f), static_cast<int>(worldZ+0.5f));
1904 
1905 	//clamp coords to map size
1906 	return map->isInside(worldPos);
1907 }
1908 
computeSelected(Selection::UnitContainer & units,const Vec2i & posDown,const Vec2i & posUp)1909 void Renderer::computeSelected(Selection::UnitContainer &units, const Vec2i &posDown, const Vec2i &posUp){
1910 
1911 	//declarations
1912 	GLuint selectBuffer[Gui::maxSelBuff];
1913 	const Metrics &metrics= Metrics::getInstance();
1914 
1915 	//compute center and dimensions of selection rectangle
1916 	int x= (posDown.x+posUp.x) / 2;
1917 	int y= (posDown.y+posUp.y) / 2;
1918 	int w= abs(posDown.x-posUp.x);
1919 	int h= abs(posDown.y-posUp.y);
1920 	if(w<1) w=1;
1921 	if(h<1) h=1;
1922 
1923 	//setup matrices
1924 	glSelectBuffer(Gui::maxSelBuff, selectBuffer);
1925 	glMatrixMode(GL_PROJECTION);
1926 	glPushMatrix();
1927 	GLint view[]= {0, 0, metrics.getVirtualW(), metrics.getVirtualH()};
1928 	glRenderMode(GL_SELECT);
1929 	glLoadIdentity();
1930 	gluPickMatrix(x, y, w, h, view);
1931 	gluPerspective(perspFov, metrics.getAspectRatio(), perspNearPlane, perspFarPlane);
1932 	loadGameCameraMatrix();
1933 
1934 	//render units
1935 	renderUnitsFast();
1936 
1937 	//pop matrices
1938 	glMatrixMode(GL_PROJECTION);
1939 	glPopMatrix();
1940 
1941 	//select units
1942 	int selCount= glRenderMode(GL_RENDER);
1943 	for(int i=1; i<=selCount; ++i){
1944 		int factionIndex= selectBuffer[i*5-2];
1945 		int unitIndex= selectBuffer[i*5-1];
1946 		const World *world= game->getWorld();
1947 		if(factionIndex<world->getFactionCount() && unitIndex<world->getFaction(factionIndex)->getUnitCount()){
1948 			Unit *unit= world->getFaction(factionIndex)->getUnit(unitIndex);
1949 			if(unit->isAlive()){
1950 				units.push_back(unit);
1951 			}
1952 		}
1953 	}
1954 }
1955 
1956 
1957 // ==================== shadows ====================
1958 
renderShadowsToTexture()1959 void Renderer::renderShadowsToTexture(){
1960 
1961 	if(shadows==sProjected || shadows==sShadowMapping){
1962 
1963 		shadowMapFrame= (shadowMapFrame + 1) % (shadowFrameSkip + 1);
1964 
1965 		if(shadowMapFrame==0){
1966 
1967 			assertGl();
1968 
1969 			glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT | GL_VIEWPORT_BIT | GL_POLYGON_BIT);
1970 
1971 			if(shadows==sShadowMapping){
1972 				glClear(GL_DEPTH_BUFFER_BIT);
1973 			}
1974 			else{
1975 				float color= 1.0f-shadowAlpha;
1976 				glColor3f(color, color, color);
1977 				glClearColor(1.f, 1.f, 1.f, 1.f);
1978 				glDisable(GL_DEPTH_TEST);
1979 				glClear(GL_COLOR_BUFFER_BIT);
1980 			}
1981 
1982 			//clear color buffer
1983 			//
1984 			//set viewport, we leave one texel always in white to avoid problems
1985 			glViewport(1, 1, shadowTextureSize-2, shadowTextureSize-2);
1986 
1987 			if(nearestLightPos.w==0.f){
1988 				//directional light
1989 
1990 				//light pos
1991 				const TimeFlow *tf= game->getWorld()->getTimeFlow();
1992 				float ang= tf->isDay()? computeSunAngle(tf->getTime()): computeMoonAngle(tf->getTime());
1993 				ang= radToDeg(ang);
1994 
1995 				//push and set projection
1996 				glMatrixMode(GL_PROJECTION);
1997 				glPushMatrix();
1998 				glLoadIdentity();
1999 				if(game->getGameCamera()->getState()==GameCamera::sGame){
2000 					glOrtho(-35, 5, -15, 15, -1000, 1000);
2001 				}
2002 				else{
2003 					glOrtho(-30, 30, -20, 20, -1000, 1000);
2004 				}
2005 
2006 				//push and set modelview
2007 				glMatrixMode(GL_MODELVIEW);
2008 				glPushMatrix();
2009 				glLoadIdentity();
2010 
2011 				glRotatef(15, 0, 1, 0);
2012 
2013 				glRotatef(ang, 1, 0, 0);
2014 				glRotatef(90, 0, 1, 0);
2015 				Vec3f pos= game->getGameCamera()->getPos();
2016 
2017 				glTranslatef(static_cast<int>(-pos.x), 0, static_cast<int>(-pos.z));
2018 
2019 			}
2020 			else{
2021 				//non directional light
2022 
2023 				//push projection
2024 				glMatrixMode(GL_PROJECTION);
2025 				glPushMatrix();
2026 				glLoadIdentity();
2027 				gluPerspective(150, 1.f, perspNearPlane, perspFarPlane);
2028 
2029 				//push modelview
2030 				glMatrixMode(GL_MODELVIEW);
2031 				glPushMatrix();
2032 				glLoadIdentity();
2033 				glRotatef(-90, -1, 0, 0);
2034 				glTranslatef(-nearestLightPos.x, -nearestLightPos.y-2, -nearestLightPos.z);
2035 			}
2036 
2037 			if(shadows==sShadowMapping){
2038 				glEnable(GL_POLYGON_OFFSET_FILL);
2039 				glPolygonOffset(1.0f, 0.001f);
2040 			}
2041 
2042 			//render 3d
2043 			renderUnitsFast();
2044 			renderObjectsFast();
2045 
2046 			//read color buffer
2047 			glBindTexture(GL_TEXTURE_2D, shadowMapHandle);
2048 			glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, shadowTextureSize, shadowTextureSize);
2049 
2050 			//get elemental matrices
2051 			Matrix4f matrix1;
2052 			matrix1[0]= 0.5f;	matrix1[4]= 0.f;	matrix1[8]= 0.f;	matrix1[12]= 0.5f;
2053 			matrix1[1]= 0.f;	matrix1[5]= 0.5f;	matrix1[9]= 0.f;	matrix1[13]= 0.5f;
2054 			matrix1[2]= 0.f;	matrix1[6]= 0.f;	matrix1[10]= 0.5f;	matrix1[14]= 0.5f;
2055 			matrix1[3]= 0.f;	matrix1[7]= 0.f;	matrix1[11]= 0.f;	matrix1[15]= 1.f;
2056 
2057 			Matrix4f matrix2;
2058 			glGetFloatv(GL_PROJECTION_MATRIX, matrix2.ptr());
2059 
2060 			Matrix4f matrix3;
2061 			glGetFloatv(GL_MODELVIEW_MATRIX, matrix3.ptr());
2062 
2063 			//pop both matrices
2064 			glPopMatrix();
2065 			glMatrixMode(GL_PROJECTION);
2066 			glPopMatrix();
2067 
2068 			glMatrixMode(GL_PROJECTION);
2069 			glPushMatrix();
2070 
2071 			//compute texture matrix
2072 			glLoadMatrixf(matrix1.ptr());
2073 			glMultMatrixf(matrix2.ptr());
2074 			glMultMatrixf(matrix3.ptr());
2075 			glGetFloatv(GL_TRANSPOSE_PROJECTION_MATRIX_ARB, shadowMapMatrix.ptr());
2076 
2077 			//pop
2078 			glPopMatrix();
2079 
2080 			glPopAttrib();
2081 
2082 			assertGl();
2083 		}
2084 	}
2085 }
2086 
2087 
2088 // ==================== gl wrap ====================
2089 
getGlInfo()2090 string Renderer::getGlInfo(){
2091 	string infoStr;
2092 	Lang &lang= Lang::getInstance();
2093 
2094 	infoStr+= lang.get("OpenGlInfo")+":\n";
2095 	infoStr+= "   "+lang.get("OpenGlVersion")+": ";
2096     infoStr+= string(getGlVersion())+"\n";
2097     infoStr+= "   "+lang.get("OpenGlRenderer")+": ";
2098     infoStr+= string(getGlRenderer())+"\n";
2099     infoStr+= "   "+lang.get("OpenGlVendor")+": ";
2100     infoStr+= string(getGlVendor())+"\n";
2101 	infoStr+= "   "+lang.get("OpenGlMaxLights")+": ";
2102     infoStr+= intToStr(getGlMaxLights())+"\n";
2103 	infoStr+= "   "+lang.get("OpenGlMaxTextureSize")+": ";
2104     infoStr+= intToStr(getGlMaxTextureSize())+"\n";
2105 	infoStr+= "   "+lang.get("OpenGlMaxTextureUnits")+": ";
2106     infoStr+= intToStr(getGlMaxTextureUnits())+"\n";
2107 	infoStr+= "   "+lang.get("OpenGlModelviewStack")+": ";
2108     infoStr+= intToStr(getGlModelviewMatrixStackDepth())+"\n";
2109 	infoStr+= "   "+lang.get("OpenGlProjectionStack")+": ";
2110     infoStr+= intToStr(getGlProjectionMatrixStackDepth())+"\n";
2111 
2112 	return infoStr;
2113 }
2114 
getGlMoreInfo()2115 string Renderer::getGlMoreInfo(){
2116 	string infoStr;
2117 	Lang &lang= Lang::getInstance();
2118 
2119 	//gl extensions
2120 	infoStr+= lang.get("OpenGlExtensions")+":\n   ";
2121 
2122 	string extensions= getGlExtensions();
2123 	int charCount= 0;
2124 	for(int i=0; i<extensions.size(); ++i){
2125 		infoStr+= extensions[i];
2126 		if(charCount>120 && extensions[i]==' '){
2127 			infoStr+= "\n   ";
2128 			charCount= 0;
2129 		}
2130 		++charCount;
2131 	}
2132 
2133 	//platform extensions
2134 	infoStr+= "\n\n";
2135 	infoStr+= lang.get("OpenGlPlatformExtensions")+":\n   ";
2136 
2137 	charCount= 0;
2138 	string platformExtensions= getGlPlatformExtensions();
2139 	for(int i=0; i<platformExtensions.size(); ++i){
2140 		infoStr+= platformExtensions[i];
2141 		if(charCount>120 && platformExtensions[i]==' '){
2142 			infoStr+= "\n   ";
2143 			charCount= 0;
2144 		}
2145 		++charCount;
2146 	}
2147 
2148 	return infoStr;
2149 }
2150 
autoConfig()2151 void Renderer::autoConfig(){
2152 
2153 	Config &config= Config::getInstance();
2154 	bool nvidiaCard= toLower(getGlVendor()).find("nvidia")!=string::npos;
2155 	bool atiCard= toLower(getGlVendor()).find("ati")!=string::npos;
2156 	bool shadowExtensions = isGlExtensionSupported("GL_ARB_shadow") && isGlExtensionSupported("GL_ARB_shadow_ambient");
2157 
2158 	//3D textures
2159 	config.setBool("Textures3D", isGlExtensionSupported("GL_EXT_texture3D"));
2160 
2161 	//shadows
2162 	string shadows;
2163 	if(getGlMaxTextureUnits()>=3){
2164 		if(nvidiaCard && shadowExtensions){
2165 			shadows= shadowsToStr(sShadowMapping);
2166 		}
2167 		else{
2168 			shadows= shadowsToStr(sProjected);
2169 		}
2170 	}
2171 	else{
2172 		shadows=shadowsToStr(sDisabled);
2173 	}
2174 	config.setString("Shadows", shadows);
2175 
2176 	//lights
2177 	config.setInt("MaxLights", atiCard? 1: 4);
2178 
2179 	//filter
2180 	config.setString("Filter", "Bilinear");
2181 }
2182 
clearBuffers()2183 void Renderer::clearBuffers(){
2184 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2185 }
2186 
clearZBuffer()2187 void Renderer::clearZBuffer(){
2188 	glClear(GL_DEPTH_BUFFER_BIT);
2189 }
2190 
loadConfig()2191 void Renderer::loadConfig(){
2192 	Config &config= Config::getInstance();
2193 
2194 	//cache most used config params
2195 	maxLights= config.getInt("MaxLights");
2196 	photoMode= config.getBool("PhotoMode");
2197 	focusArrows= config.getBool("FocusArrows");
2198 	textures3D= config.getBool("Textures3D");
2199 
2200 	//load shadows
2201 	shadows= strToShadows(config.getString("Shadows"));
2202 	if(shadows==sProjected || shadows==sShadowMapping){
2203 		shadowTextureSize= config.getInt("ShadowTextureSize");
2204 		shadowFrameSkip= config.getInt("ShadowFrameSkip");
2205 		shadowAlpha= config.getFloat("ShadowAlpha");
2206 	}
2207 
2208 	//load filter settings
2209 	Texture2D::Filter textureFilter= strToTextureFilter(config.getString("Filter"));
2210 	int maxAnisotropy= config.getInt("FilterMaxAnisotropy");
2211 	for(int i=0; i<rsCount; ++i){
2212 		textureManager[i]->setFilter(textureFilter);
2213 		textureManager[i]->setMaxAnisotropy(maxAnisotropy);
2214 	}
2215 }
2216 
saveScreen(const string & path)2217 void Renderer::saveScreen(const string &path){
2218 
2219 	const Metrics &sm= Metrics::getInstance();
2220 
2221 	Pixmap2D pixmap(sm.getScreenW(), sm.getScreenH(), 3);
2222 
2223 	glReadPixels(0, 0, pixmap.getW(), pixmap.getH(), GL_RGB, GL_UNSIGNED_BYTE, pixmap.getPixels());
2224 	pixmap.saveTga(path);
2225 }
2226 
2227 // ==================== PRIVATE ====================
2228 
computeSunAngle(float time)2229 float Renderer::computeSunAngle(float time){
2230 
2231 	float dayTime= TimeFlow::dusk-TimeFlow::dawn;
2232 	float fTime= (time-TimeFlow::dawn)/dayTime;
2233 	return clamp(fTime*pi, pi/8.f, 7.f*pi/8.f);
2234 }
2235 
computeMoonAngle(float time)2236 float Renderer::computeMoonAngle(float time){
2237 	float nightTime= 24-(TimeFlow::dusk-TimeFlow::dawn);
2238 
2239 	if(time<TimeFlow::dawn){
2240 		time+= 24.f;
2241 	}
2242 
2243 	float fTime= (time-TimeFlow::dusk)/nightTime;
2244 	return clamp((1.0f-fTime)*pi, pi/8.f, 7.f*pi/8.f);
2245 }
2246 
computeSunPos(float time)2247 Vec4f Renderer::computeSunPos(float time){
2248 	float ang= computeSunAngle(time);
2249 	return Vec4f(-cos(ang)*sunDist, sin(ang)*sunDist, 0.f, 0.f);
2250 }
2251 
computeMoonPos(float time)2252 Vec4f Renderer::computeMoonPos(float time){
2253 	float ang= computeMoonAngle(time);
2254 	return Vec4f(-cos(ang)*moonDist, sin(ang)*moonDist, 0.f, 0.f);
2255 }
2256 
computeLightColor(float time)2257 Vec3f Renderer::computeLightColor(float time){
2258 	const Tileset *tileset= game->getWorld()->getTileset();
2259 	Vec3f color;
2260 
2261 	const float transition= 2;
2262 	const float dayStart= TimeFlow::dawn;
2263 	const float dayEnd= TimeFlow::dusk-transition;
2264 	const float nightStart= TimeFlow::dusk;
2265 	const float nightEnd= TimeFlow::dawn-transition;
2266 
2267 	if(time>dayStart && time<dayEnd){
2268 		color= tileset->getSunLightColor();
2269 	}
2270 	else if(time>nightStart || time<nightEnd){
2271 		color= tileset->getMoonLightColor();
2272 	}
2273 	else if(time>=dayEnd && time<=nightStart){
2274 		color= tileset->getSunLightColor().lerp((time-dayEnd)/transition, tileset->getMoonLightColor());
2275 	}
2276 	else if(time>=nightEnd && time<=dayStart){
2277 		color= tileset->getMoonLightColor().lerp((time-nightEnd)/transition, tileset->getSunLightColor());
2278 	}
2279 	else{
2280 		assert(false);
2281 		color= tileset->getSunLightColor();
2282 	}
2283 	return color;
2284 }
2285 
computeWaterColor(float waterLevel,float cellHeight)2286 Vec4f Renderer::computeWaterColor(float waterLevel, float cellHeight){
2287 	const float waterFactor= 1.5f;
2288 	return Vec4f(1.f, 1.f, 1.f, clamp((waterLevel-cellHeight)*waterFactor, 0.f, 1.f));
2289 }
2290 
2291 // ==================== fast render ====================
2292 
2293 //render units for selection purposes
renderUnitsFast()2294 void Renderer::renderUnitsFast(){
2295 	const World *world= game->getWorld();
2296 
2297 	assertGl();
2298 
2299 	glPushAttrib(GL_ENABLE_BIT);
2300 	glDisable(GL_TEXTURE_2D);
2301 	glDisable(GL_LIGHTING);
2302 
2303 	modelRenderer->begin(false, false, false);
2304 	glInitNames();
2305 	for(int i=0; i<world->getFactionCount(); ++i){
2306 		glPushName(i);
2307 		for(int j=0; j<world->getFaction(i)->getUnitCount(); ++j){
2308 			glPushName(j);
2309 			Unit *unit= world->getFaction(i)->getUnit(j);
2310 			if(world->toRenderUnit(unit, visibleQuad)) {
2311 				glMatrixMode(GL_MODELVIEW);
2312 
2313 				//debuxar modelo
2314 				glPushMatrix();
2315 
2316 				//translate
2317 				Vec3f currVec= unit->getCurrVectorFlat();
2318 				glTranslatef(currVec.x, currVec.y, currVec.z);
2319 
2320 				//rotate
2321 				glRotatef(unit->getRotation(), 0.f, 1.f, 0.f);
2322 
2323 				//render
2324 				const Model *model= unit->getCurrentModel();
2325 				model->updateInterpolationVertices(unit->getAnimProgress(), unit->isAlive());
2326 				modelRenderer->render(model);
2327 
2328 				glPopMatrix();
2329 
2330 			}
2331 			glPopName();
2332 		}
2333 		glPopName();
2334 	}
2335 	modelRenderer->end();
2336 
2337 	glPopAttrib();
2338 }
2339 
2340 //render objects for selection purposes
renderObjectsFast()2341 void Renderer::renderObjectsFast(){
2342 	const World *world= game->getWorld();
2343 	const Map *map= world->getMap();
2344 
2345     assertGl();
2346 
2347 	glPushAttrib(GL_ENABLE_BIT| GL_TEXTURE_BIT);
2348 	glDisable(GL_LIGHTING);
2349 
2350     glAlphaFunc(GL_GREATER, 0.5f);
2351 
2352 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
2353 
2354 	//set color to the texture alpha
2355 	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
2356 	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
2357 	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
2358 
2359 	//set alpha to the texture alpha
2360 	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
2361 	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
2362 	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
2363 
2364 	modelRenderer->begin(false, true, false);
2365 	int thisTeamIndex= world->getThisTeamIndex();
2366 
2367 	PosQuadIterator pqi(map, visibleQuad, Map::cellScale);
2368 	while(pqi.next()){
2369 		const Vec2i pos= pqi.getPos();
2370 
2371 		if(map->isInside(pos)){
2372 
2373 			SurfaceCell *sc= map->getSurfaceCell(Map::toSurfCoords(pos));
2374 			Object *o= sc->getObject();
2375 			if(sc->isExplored(thisTeamIndex) && o!=NULL){
2376 
2377 				const Model *objModel= sc->getObject()->getModel();
2378 				Vec3f v= o->getPos();
2379 
2380 				glMatrixMode(GL_MODELVIEW);
2381 				glPushMatrix();
2382 				glTranslatef(v.x, v.y, v.z);
2383 				glRotatef(o->getRotation(), 0.f, 1.f, 0.f);
2384 
2385 				modelRenderer->render(objModel);
2386 
2387 				glPopMatrix();
2388 
2389 			}
2390 		}
2391 	}
2392 
2393 	modelRenderer->end();
2394 
2395 	glPopAttrib();
2396 
2397 	assertGl();
2398 }
2399 
2400 // ==================== gl caps ====================
2401 
checkGlCaps()2402 void Renderer::checkGlCaps(){
2403 
2404 	//opengl 1.3
2405 	if(!isGlVersionSupported(1, 3, 0)){
2406 		string message;
2407 
2408 		message += "Your system supports OpenGL version \"";
2409  		message += getGlVersion() + string("\"\n");
2410  		message += "Glest needs at least version 1.3 to work\n";
2411  		message += "You may solve this problem by installing your latest video card drivers";
2412 
2413  		throw runtime_error(message.c_str());
2414 	}
2415 
2416 	//opengl 1.4 or extension
2417 	if(!isGlVersionSupported(1, 4, 0)){
2418 		checkExtension("GL_ARB_texture_env_crossbar", "Glest");
2419 	}
2420 }
2421 
checkGlOptionalCaps()2422 void Renderer::checkGlOptionalCaps(){
2423 
2424 	//shadows
2425 	if(shadows==sProjected || shadows==sShadowMapping){
2426 		if(getGlMaxTextureUnits()<3){
2427 			throw runtime_error("Your system doesn't support 3 texture units, required for shadows");
2428 		}
2429 	}
2430 
2431 	//shadow mapping
2432 	if(shadows==sShadowMapping){
2433 		checkExtension("GL_ARB_shadow", "Shadow Mapping");
2434 		checkExtension("GL_ARB_shadow_ambient", "Shadow Mapping");
2435 	}
2436 }
2437 
checkExtension(const string & extension,const string & msg)2438 void Renderer::checkExtension(const string &extension, const string &msg){
2439 	if(!isGlExtensionSupported(extension.c_str())){
2440 		string str= "OpenGL extension not supported: " + extension +  ", required for " + msg;
2441 		throw runtime_error(str);
2442 	}
2443 }
2444 
2445 // ==================== init 3d lists ====================
2446 
init3dList()2447 void Renderer::init3dList(){
2448 
2449 	const Metrics &metrics= Metrics::getInstance();
2450 
2451     assertGl();
2452 
2453 	list3d= glGenLists(1);
2454 	glNewList(list3d, GL_COMPILE_AND_EXECUTE);
2455 	//need to execute, because if not gluPerspective takes no effect and gluLoadMatrix is wrong
2456 
2457 		//misc
2458 		glViewport(0, 0, metrics.getScreenW(), metrics.getScreenH());
2459 		glClearColor(fowColor.x, fowColor.y, fowColor.z, fowColor.w);
2460 		glFrontFace(GL_CW);
2461 		glEnable(GL_CULL_FACE);
2462 		loadProjectionMatrix();
2463 
2464 		//texture state
2465 		glActiveTexture(shadowTexUnit);
2466 		glDisable(GL_TEXTURE_2D);
2467 		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2468 
2469 		glActiveTexture(fowTexUnit);
2470 		glDisable(GL_TEXTURE_2D);
2471 		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2472 
2473 		glActiveTexture(baseTexUnit);
2474 		glEnable(GL_TEXTURE_2D);
2475 		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2476 
2477 		//material state
2478 		glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, defSpecularColor.ptr());
2479 		glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, defAmbientColor.ptr());
2480 		glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, defDiffuseColor.ptr());
2481 		glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2482 		glColor4fv(defColor.ptr());
2483 
2484 		//blend state
2485 		glDisable(GL_BLEND);
2486 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2487 
2488 		//alpha test state
2489 		glEnable(GL_ALPHA_TEST);
2490 		glAlphaFunc(GL_GREATER, 0.f);
2491 
2492 		//depth test state
2493 		glEnable(GL_DEPTH_TEST);
2494 		glDepthMask(GL_TRUE);
2495 		glDepthFunc(GL_LESS);
2496 
2497 		//lighting state
2498 		glEnable(GL_LIGHTING);
2499 		glEnable(GL_LIGHT0);
2500 
2501 		//matrix mode
2502 		glMatrixMode(GL_MODELVIEW);
2503 
2504 		//stencil test
2505 		glDisable(GL_STENCIL_TEST);
2506 
2507 		//fog
2508 		const Tileset *tileset= game->getWorld()->getTileset();
2509 		if(tileset->getFog()){
2510 			glEnable(GL_FOG);
2511 			if(tileset->getFogMode()==fmExp){
2512 				glFogi(GL_FOG_MODE, GL_EXP);
2513 			}
2514 			else{
2515 				glFogi(GL_FOG_MODE, GL_EXP2);
2516 			}
2517 
2518 			glFogf(GL_FOG_DENSITY, tileset->getFogDensity());
2519 			glFogfv(GL_FOG_COLOR, tileset->getFogColor().ptr());
2520 		}
2521 
2522 	glEndList();
2523 
2524 	//assert
2525 	assertGl();
2526 
2527 }
2528 
init2dList()2529 void Renderer::init2dList(){
2530 
2531 	const Metrics &metrics= Metrics::getInstance();
2532 
2533 	//this list sets the state for the 2d rendering
2534 	list2d= glGenLists(1);
2535 	glNewList(list2d, GL_COMPILE);
2536 
2537 		//projection
2538 		glViewport(0, 0, metrics.getScreenW(), metrics.getScreenH());
2539 		glMatrixMode(GL_PROJECTION);
2540 		glLoadIdentity();
2541 		glOrtho(0, metrics.getVirtualW(), 0, metrics.getVirtualH(), 0, 1);
2542 
2543 		//modelview
2544 		glMatrixMode(GL_MODELVIEW);
2545 		glLoadIdentity();
2546 
2547 		//disable everything
2548 		glDisable(GL_BLEND);
2549 		glDisable(GL_LIGHTING);
2550 		glDisable(GL_ALPHA_TEST);
2551 		glDisable(GL_DEPTH_TEST);
2552 		glDisable(GL_STENCIL_TEST);
2553 		glDisable(GL_FOG);
2554 		glDisable(GL_CULL_FACE);
2555 		glFrontFace(GL_CCW);
2556 		glActiveTexture(baseTexUnit);
2557 		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2558 		glDisable(GL_TEXTURE_2D);
2559 
2560 		//blend func
2561 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2562 
2563 		//color
2564 		glColor4f(1.f, 1.f, 1.f, 1.f);
2565 
2566 	glEndList();
2567 
2568 	assertGl();
2569 }
2570 
init3dListMenu(MainMenu * mm)2571 void Renderer::init3dListMenu(MainMenu *mm){
2572     assertGl();
2573 
2574 	const Metrics &metrics= Metrics::getInstance();
2575 	const MenuBackground *mb= mm->getMenuBackground();
2576 
2577 	list3dMenu= glGenLists(1);
2578 	glNewList(list3dMenu, GL_COMPILE);
2579 
2580 		//misc
2581 		glViewport(0, 0, metrics.getScreenW(), metrics.getScreenH());
2582 		glClearColor(0.4f, 0.4f, 0.4f, 1.f);
2583 		glFrontFace(GL_CW);
2584 		glEnable(GL_CULL_FACE);
2585 		glMatrixMode(GL_PROJECTION);
2586 		glLoadIdentity();
2587 		gluPerspective(perspFov, metrics.getAspectRatio(), perspNearPlane, 1000);
2588 
2589 		//texture state
2590 		glEnable(GL_TEXTURE_2D);
2591 		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2592 
2593 		//material state
2594 		glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, defSpecularColor.ptr());
2595 		glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, defAmbientColor.ptr());
2596 		glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, defDiffuseColor.ptr());
2597 		glColor4fv(defColor.ptr());
2598 		glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2599 
2600 		//blend state
2601 		glDisable(GL_BLEND);
2602 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2603 
2604 		//alpha test state
2605 		glEnable(GL_ALPHA_TEST);
2606 		glAlphaFunc(GL_GREATER, 0.f);
2607 
2608 		//depth test state
2609 		glEnable(GL_DEPTH_TEST);
2610 		glDepthMask(GL_TRUE);
2611 		glDepthFunc(GL_LESS);
2612 
2613 		//lighting state
2614 		glEnable(GL_LIGHTING);
2615 
2616 		//matrix mode
2617 		glMatrixMode(GL_MODELVIEW);
2618 
2619 		//stencil test
2620 		glDisable(GL_STENCIL_TEST);
2621 
2622 		//fog
2623 		if(mb->getFog()){
2624 			glEnable(GL_FOG);
2625 			glFogi(GL_FOG_MODE, GL_EXP2);
2626 			glFogf(GL_FOG_DENSITY, mb->getFogDensity());
2627 		}
2628 
2629 	glEndList();
2630 
2631 	//assert
2632 	assertGl();
2633 }
2634 
2635 
2636 // ==================== misc ====================
2637 
loadProjectionMatrix()2638 void Renderer::loadProjectionMatrix(){
2639 	GLdouble clipping;
2640 	const Metrics &metrics= Metrics::getInstance();
2641 
2642     assertGl();
2643 
2644 	clipping= photoMode ? perspFarPlane*100 : perspFarPlane;
2645 
2646 	glMatrixMode(GL_PROJECTION);
2647 	glLoadIdentity();
2648 	gluPerspective(perspFov, metrics.getAspectRatio(), perspNearPlane, clipping);
2649 
2650     assertGl();
2651 }
2652 
enableProjectiveTexturing()2653 void Renderer::enableProjectiveTexturing(){
2654 	glTexGenfv(GL_S, GL_EYE_PLANE, &shadowMapMatrix[0]);
2655 	glTexGenfv(GL_T, GL_EYE_PLANE, &shadowMapMatrix[4]);
2656 	glTexGenfv(GL_R, GL_EYE_PLANE, &shadowMapMatrix[8]);
2657 	glTexGenfv(GL_Q, GL_EYE_PLANE, &shadowMapMatrix[12]);
2658 	glEnable(GL_TEXTURE_GEN_S);
2659 	glEnable(GL_TEXTURE_GEN_T);
2660 	glEnable(GL_TEXTURE_GEN_R);
2661 	glEnable(GL_TEXTURE_GEN_Q);
2662 }
2663 
2664 // ==================== private aux drawing ====================
2665 
renderSelectionCircle(Vec3f v,int size,float radius)2666 void Renderer::renderSelectionCircle(Vec3f v, int size, float radius){
2667 	GLUquadricObj *disc;
2668 
2669 	glMatrixMode(GL_MODELVIEW);
2670     glPushMatrix();
2671 
2672 	glTranslatef(v.x, v.y, v.z);
2673 	glRotatef(90.f, 1.f, 0.f, 0.f);
2674 	disc= gluNewQuadric();
2675 	gluQuadricDrawStyle(disc, GLU_FILL);
2676 	gluCylinder(disc, radius*(size-0.2f), radius*size, 0.2f, 30, 1);
2677 	gluDeleteQuadric(disc);
2678 
2679     glPopMatrix();
2680 }
2681 
renderArrow(const Vec3f & pos1,const Vec3f & pos2,const Vec3f & color,float width)2682 void Renderer::renderArrow(const Vec3f &pos1, const Vec3f &pos2, const Vec3f &color, float width){
2683 	const int tesselation= 3;
2684 	const float arrowEndSize= 0.4f;
2685 	const float maxlen= 25;
2686 	const float blendDelay= 5.f;
2687 
2688 	Vec3f dir= Vec3f(pos2-pos1);
2689 	float len= dir.length();
2690 
2691 	if(len>maxlen){
2692 		return;
2693 	}
2694 	float alphaFactor= clamp((maxlen-len)/blendDelay, 0.f, 1.f);
2695 
2696 	dir.normalize();
2697 	Vec3f normal= dir.cross(Vec3f(0, 1, 0));
2698 
2699 	Vec3f pos2Left= pos2 + normal*(width-0.05f) - dir*arrowEndSize*width;
2700 	Vec3f pos2Right= pos2 - normal*(width-0.05f) - dir*arrowEndSize*width;
2701 	Vec3f pos1Left= pos1 + normal*(width+0.05f);
2702 	Vec3f pos1Right= pos1 - normal*(width+0.05f);
2703 
2704 	//arrow body
2705 	glBegin(GL_TRIANGLE_STRIP);
2706 	for(int i=0; i<=tesselation; ++i){
2707 		float t= static_cast<float>(i)/tesselation;
2708 		Vec3f a= pos1Left.lerp(t, pos2Left);
2709 		Vec3f b= pos1Right.lerp(t, pos2Right);
2710 		Vec4f c= Vec4f(color, t*0.25f*alphaFactor);
2711 
2712 		glColor4fv(c.ptr());
2713 		glVertex3fv(a.ptr());
2714 		glVertex3fv(b.ptr());
2715 	}
2716 	glEnd();
2717 
2718 	//arrow end
2719 	glBegin(GL_TRIANGLES);
2720 		glVertex3fv((pos2Left + normal*(arrowEndSize-0.1f)).ptr());
2721 		glVertex3fv((pos2Right - normal*(arrowEndSize-0.1f)).ptr());
2722 		glVertex3fv((pos2 + dir*(arrowEndSize-0.1f)).ptr());
2723 	glEnd();
2724 }
2725 
renderProgressBar(int size,int x,int y,Font2D * font)2726 void Renderer::renderProgressBar(int size, int x, int y, Font2D *font){
2727 
2728 	//bar
2729 	glBegin(GL_QUADS);
2730 		glColor4fv(progressBarFront2.ptr());
2731 		glVertex2i(x, y);
2732 		glVertex2i(x, y+10);
2733 		glColor4fv(progressBarFront1.ptr());
2734 		glVertex2i(x+size, y+10);
2735 		glVertex2i(x+size, y);
2736 	glEnd();
2737 
2738 	//transp bar
2739 	glEnable(GL_BLEND);
2740 	glBegin(GL_QUADS);
2741 		glColor4fv(progressBarBack2.ptr());
2742 		glVertex2i(x+size, y);
2743 		glVertex2i(x+size, y+10);
2744 		glColor4fv(progressBarBack1.ptr());
2745 		glVertex2i(x+maxProgressBar, y+10);
2746 		glVertex2i(x+maxProgressBar, y);
2747 	glEnd();
2748 	glDisable(GL_BLEND);
2749 
2750 	//text
2751 	glColor3fv(defColor.ptr());
2752 	textRenderer->begin(font);
2753 	textRenderer->render(intToStr(static_cast<int>(size))+"%", x+maxProgressBar/2, y, true);
2754 	textRenderer->end();
2755 }
2756 
2757 
renderTile(const Vec2i & pos)2758 void Renderer::renderTile(const Vec2i &pos){
2759 
2760 	const Map *map= game->getWorld()->getMap();
2761 	Vec2i scaledPos= pos * Map::cellScale;
2762 
2763 	glMatrixMode(GL_MODELVIEW);
2764 	glPushMatrix();
2765 	glTranslatef(-0.5f, 0.f, -0.5f);
2766 
2767 	glInitNames();
2768 	for(int i=0; i<Map::cellScale; ++i){
2769 		for(int j=0; j<Map::cellScale; ++j){
2770 
2771 			Vec2i renderPos= scaledPos + Vec2i(i, j);
2772 
2773 			glPushName(renderPos.y);
2774 			glPushName(renderPos.x);
2775 
2776 			glDisable(GL_CULL_FACE);
2777 
2778 			glBegin(GL_TRIANGLE_STRIP);
2779 			glVertex3f(
2780 				static_cast<float>(renderPos.x),
2781 				map->getCell(renderPos.x, renderPos.y)->getHeight(),
2782 				static_cast<float>(renderPos.y));
2783 			glVertex3f(
2784 				static_cast<float>(renderPos.x),
2785 				map->getCell(renderPos.x, renderPos.y+1)->getHeight(),
2786 				static_cast<float>(renderPos.y+1));
2787 			glVertex3f(
2788 				static_cast<float>(renderPos.x+1),
2789 				map->getCell(renderPos.x+1, renderPos.y)->getHeight(),
2790 				static_cast<float>(renderPos.y));
2791 			glVertex3f(
2792 				static_cast<float>(renderPos.x+1),
2793 				map->getCell(renderPos.x+1, renderPos.y+1)->getHeight(),
2794 				static_cast<float>(renderPos.y+1));
2795 			glEnd();
2796 
2797 			glPopName();
2798 			glPopName();
2799 		}
2800 	}
2801 
2802 	glPopMatrix();
2803 }
2804 
renderQuad(int x,int y,int w,int h,const Texture2D * texture)2805 void Renderer::renderQuad(int x, int y, int w, int h, const Texture2D *texture){
2806 	glBindTexture(GL_TEXTURE_2D, static_cast<const Texture2DGl*>(texture)->getHandle());
2807 	glBegin(GL_TRIANGLE_STRIP);
2808 		glTexCoord2i(0, 1);
2809 		glVertex2i(x, y+h);
2810 		glTexCoord2i(0, 0);
2811 		glVertex2i(x, y);
2812 		glTexCoord2i(1, 1);
2813 		glVertex2i(x+w, y+h);
2814 		glTexCoord2i(1, 0);
2815 		glVertex2i(x+w, y);
2816 	glEnd();
2817 }
2818 
strToShadows(const string & s)2819 Renderer::Shadows Renderer::strToShadows(const string &s){
2820 	if(s=="Projected"){
2821 		return sProjected;
2822 	}
2823 	else if(s=="ShadowMapping"){
2824 		return sShadowMapping;
2825 	}
2826 	return sDisabled;
2827 }
2828 
shadowsToStr(Shadows shadows)2829 string Renderer::shadowsToStr(Shadows shadows){
2830 	switch(shadows){
2831 	case sDisabled:
2832 		return "Disabled";
2833 	case sProjected:
2834 		return "Projected";
2835 	case sShadowMapping:
2836 		return "ShadowMapping";
2837 	default:
2838 		assert(false);
2839 		return "";
2840 	}
2841 }
2842 
strToTextureFilter(const string & s)2843 Texture2D::Filter Renderer::strToTextureFilter(const string &s){
2844 	if(s=="Bilinear"){
2845 		return Texture2D::fBilinear;
2846 	}
2847 	else if(s=="Trilinear"){
2848 		return Texture2D::fTrilinear;
2849 	}
2850 
2851 	throw runtime_error("Error converting from string to FilterType, found: "+s);
2852 }
2853 
2854 }}//end namespace
2855