1 /***************************************************************************
2                             fog.cpp  -  Fog of war
3                              -------------------
4     begin                : Sat May 3 2003
5     copyright            : (C) 2003 by Gabor Torok
6     email                : cctorok@yahoo.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include "../common/constants.h"
19 #include "fog.h"
20 #include "glshape.h"
21 #include "frustum.h"
22 #include "map.h"
23 #include "location.h"
24 #include "mapadapter.h"
25 #include "renderedcreature.h"
26 
27 // FIXME: remove this later
28 #include "../scourge.h"
29 
30 using namespace std;
31 
32 //#define DEBUG_FOG 1
33 
34 // how many map spaces in a fog chunk
35 #define FOG_CHUNK_SIZE 4
36 
37 #define FOG_WIDTH ( MAP_WIDTH / FOG_CHUNK_SIZE )
38 #define FOG_DEPTH ( MAP_DEPTH / FOG_CHUNK_SIZE )
39 
40 // color of transparent fog
41 //#define ER 118
42 //#define EG 110
43 //#define EB 130
44 
45 #define ER 192
46 #define EG 192
47 #define EB 210
48 #define EA 128
49 
50 //#define DARK_R 0.05f
51 //#define DARK_G 0.04f
52 //#define DARK_B 0.055f
53 
54 #define DARK_R 0.0f
55 #define DARK_G 0.0f
56 #define DARK_B 0.0f
57 
58 // inverse color of dark shade
59 #define SR static_cast<int>( 255.0f * DARK_R )
60 #define SG static_cast<int>( 255.0f * DARK_G )
61 #define SB static_cast<int>( 255.0f * DARK_B )
62 
63 //#define LAMP_RADIUS_SQUARED 36.0f
64 //#define LAMP_RADIUS_SQUARED 64.0f
65 
Fog(Map * map,float lampRadiusSquared)66 Fog::Fog( Map *map, float lampRadiusSquared ) {
67 	this->lampRadiusSquared = lampRadiusSquared;
68 	players = new std::set<RenderedCreature *> [MAP_WIDTH * MAP_DEPTH];
69 	this->map = map;
70 	createOverlayTexture();
71 	createShadeTexture();
72 	reset();
73 }
74 
~Fog()75 Fog::~Fog() {
76 	glDeleteTextures( 1, &overlay_tex );
77 	glDeleteTextures( 1, &shade_tex );
78 	delete [] players;
79 }
80 
reset()81 void Fog::reset() {
82 	for ( int x = 0; x < FOG_WIDTH; x++ ) {
83 		for ( int y = 0; y < FOG_DEPTH; y++ ) {
84 			fog[x][y] = FOG_UNVISITED;
85 			players[x + ( y * MAP_WIDTH )].clear();
86 		}
87 	}
88 }
89 
getValue(int mapx,int mapy)90 int Fog::getValue( int mapx, int mapy ) {
91 	return fog[mapx / FOG_CHUNK_SIZE][mapy / FOG_CHUNK_SIZE];
92 }
93 
visit(RenderedCreature * player)94 void Fog::visit( RenderedCreature *player ) {
95 	for ( int x = 0; x < FOG_WIDTH; x++ ) {
96 		for ( int y = 0; y < FOG_DEPTH; y++ ) {
97 
98 			int fx = toint( player->getX() / FOG_CHUNK_SIZE );
99 			int fy = toint( player->getY() / FOG_CHUNK_SIZE );
100 
101 			double d = static_cast<double>( ( fx - x ) * ( fx - x ) ) + static_cast<double>( ( fy - y ) * ( fy - y ) );
102 			if ( d <= lampRadiusSquared ) {
103 				fog[x][y] = FOG_CLEAR;
104 				players[x + ( y * MAP_WIDTH )].insert( player );
105 			} else if ( fog[x][y] == FOG_CLEAR ) {
106 				players[x + ( y * MAP_WIDTH )].erase( player );
107 				if ( players[x + ( y * MAP_WIDTH )].empty() ) {
108 					fog[x][y] = FOG_VISITED;
109 				}
110 			}
111 		}
112 	}
113 }
114 
hideDeadParty()115 void Fog::hideDeadParty() {
116 	for ( int i = 0; i < map->getAdapter()->getPartySize(); i++ ) {
117 		if ( map->getAdapter()->getParty( i )->getStateMod( StateMod::dead ) ) {
118 			for ( int x = 0; x < FOG_WIDTH; x++ ) {
119 				for ( int y = 0; y < FOG_DEPTH; y++ ) {
120 					if ( fog[x][y] == FOG_CLEAR ) {
121 						players[x + ( y * MAP_WIDTH )].erase( map->getAdapter()->getParty( i ) );
122 						if ( players[x + ( y * MAP_WIDTH )].empty() ) {
123 							fog[x][y] = FOG_VISITED;
124 						}
125 					}
126 				}
127 			}
128 		}
129 	}
130 }
131 
getVisibility(int xp,int yp,Shape * shape)132 int Fog::getVisibility( int xp, int yp, Shape *shape ) {
133 	int v = FOG_UNVISITED;
134 	for ( int x = 0; x < shape->getWidth(); x++ ) {
135 		for ( int y = 0; y < shape->getDepth(); y++ ) {
136 			int vv = getValue( xp + x, yp - y );
137 			if ( vv == FOG_CLEAR ) return FOG_CLEAR;
138 			else if ( vv == FOG_VISITED ) v = vv;
139 		}
140 	}
141 	return v;
142 }
143 
draw(int sx,int sy,int w,int h,CFrustum * frustum)144 void Fog::draw( int sx, int sy, int w, int h, CFrustum *frustum ) {
145 	int fx = sx / FOG_CHUNK_SIZE;
146 	int fy = sy / FOG_CHUNK_SIZE;
147 	int fw = w / FOG_CHUNK_SIZE;
148 	int fh = h / FOG_CHUNK_SIZE;
149 	float nn = FOG_CHUNK_SIZE * MUL;
150 	int ox = sx % FOG_CHUNK_SIZE;
151 	int oy = sy % FOG_CHUNK_SIZE;
152 
153 	GLfloat minLightX, minLightY, maxLightX, maxLightY;
154 	minLightX = minLightY = 2000;
155 	maxLightX = maxLightY = 0;
156 	bool e[1000];
157 	int f[1000];
158 	GLfloat p[1000][4];
159 	int pCount = 0;
160 	for ( int x = 0; x < fw; x ++ ) {
161 		for ( int y = 0; y < fh; y ++ ) {
162 			int v = fog[ fx + x ][ fy + y ];
163 			if ( v == FOG_VISITED ) continue;
164 
165 			float xp = static_cast<float>( x * FOG_CHUNK_SIZE - ox ) * MUL;
166 			float yp = static_cast<float>( y * FOG_CHUNK_SIZE - oy ) * MUL;
167 			int z = getHighestZ( ( fx + x ) * FOG_CHUNK_SIZE, ( fy + y ) * FOG_CHUNK_SIZE, FOG_CHUNK_SIZE, FOG_CHUNK_SIZE );
168 			float zp = static_cast<float>( z ) * MUL;
169 
170 			// FIXME: we should check 2d inclusion in screen rect instead
171 			if ( !frustum->CubeInFrustum( xp, yp, 0.0f, nn ) )
172 				continue;
173 
174 			// get all screen points of the bounding box; draw bounding rectangle on screen
175 			float obj[20][3] = {
176 				{ xp, yp, zp },
177 				{ xp, yp + nn, zp },
178 				{ xp + nn, yp + nn, zp },
179 				{ xp + nn, yp, zp },
180 
181 				{ xp, yp, zp },
182 				{ xp, yp, 0 },
183 				{ xp + nn, yp, 0 },
184 				{ xp + nn, yp, zp },
185 
186 				{ xp, yp + nn, zp },
187 				{ xp, yp + nn, 0 },
188 				{ xp + nn, yp + nn, 0 },
189 				{ xp + nn, yp + nn, zp },
190 
191 				{ xp, yp, zp },
192 				{ xp, yp, 0 },
193 				{ xp, yp + nn, 0 },
194 				{ xp, yp + nn, zp },
195 
196 				{ xp + nn, yp, zp },
197 				{ xp + nn, yp, 0 },
198 				{ xp + nn, yp + nn, 0 },
199 				{ xp + nn, yp + nn, zp }
200 			};
201 			GLfloat maxScX, maxScY;
202 			GLfloat minScX, minScY;
203 
204 			maxScX = maxScY = 0;
205 			minScX = minScY = 2000;
206 			for ( int i = 0; i < 20; i++ ) {
207 				GLdouble scx, scy;
208 				getScreenXY( ( GLdouble )obj[i][0], ( GLdouble )obj[i][1], ( GLdouble )obj[i][2], &scx, &scy );
209 
210 				// only show light area for current player
211 				if ( v == FOG_CLEAR &&
212 				        players[x + fx + ( ( y + fy ) * MAP_WIDTH )].find( map->getAdapter()->getPlayer() ) != players[x + fx + ( ( y + fy ) * MAP_WIDTH )].end() ) {
213 					if ( scx < minLightX ) minLightX = ( GLfloat )scx;
214 					if ( scx > maxLightX ) maxLightX = ( GLfloat )scx;
215 					if ( scy < minLightY ) minLightY = ( GLfloat )scy;
216 					if ( scy > maxLightY ) maxLightY = ( GLfloat )scy;
217 				} else {
218 					if ( scx < minScX ) minScX = ( GLfloat )scx;
219 					if ( scx > maxScX ) maxScX = ( GLfloat )scx;
220 					if ( scy < minScY ) minScY = ( GLfloat )scy;
221 					if ( scy > maxScY ) maxScY = ( GLfloat )scy;
222 				}
223 			}
224 
225 			if ( v == FOG_CLEAR )
226 				continue;
227 
228 			f[pCount] = v;
229 			p[pCount][0] = minScX;
230 			p[pCount][1] = minScY;
231 			p[pCount][2] = maxScX - minScX;
232 			p[pCount][3] = maxScY - minScY;
233 
234 			e[pCount] = false;
235 			if ( ( fy + y > 0 && v != fog[ fx + x ][ fy + y - 1 ] )
236 			        || ( fx + x > 0 && v != fog[ fx + x - 1 ][ fy + y ] )
237 			        || ( fx + x < FOG_WIDTH - 1 && v != fog[ fx + x + 1 ][ fy + y ] )
238 			        || ( fy + y < FOG_DEPTH - 1 &&  v != fog[ fx + x ][ fy + y + 1 ] ) ) {
239 				e[pCount] = true;
240 			}
241 
242 			pCount++;
243 			if ( pCount >= 1000 ) break;
244 		}
245 	}
246 
247 
248 
249 	// ***************************
250 	// DRAW IT!
251 
252 	glDisable( GL_TEXTURE_2D );
253 	glDisable( GL_CULL_FACE );
254 	glDisable( GL_DEPTH_TEST );
255 
256 	//glBindTexture( GL_TEXTURE_2D, texture );
257 
258 	glEnable( GL_BLEND );
259 	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
260 	glColor4f( ER / 255.0f, EG / 255.0f, EB / 255.0f, EA / 255.0f );
261 	//glBlendFunc(GL_DST_COLOR, GL_ZERO);
262 	//glColor4f( ER / 255.0f, EG / 255.0f, EB / 255.0f, 0.5f);
263 
264 
265 	glPushMatrix();
266 	glLoadIdentity();
267 
268 	// draw a gray rect.
269 	if ( map->getAdapter()->
270 	        intersects( 0, 0,
271 	                    map->getAdapter()->getScreenWidth(),
272 	                    map->getAdapter()->getScreenHeight(),
273 	                    static_cast<int>( minLightX ), static_cast<int>( minLightY ),
274 	                    static_cast<int>( maxLightX - minLightX ),
275 	                    static_cast<int>( maxLightY - minLightY ) ) ) {
276 
277 
278 		glBegin( GL_QUADS );
279 
280 		glVertex2f( 0, 0 );
281 		glVertex2f( 0, minLightY );
282 		glVertex2f( map->getAdapter()->getScreenWidth(), minLightY );
283 		glVertex2f( map->getAdapter()->getScreenWidth(), 0 );
284 
285 		glVertex2f( 0, maxLightY );
286 		glVertex2f( 0, map->getAdapter()->getScreenHeight() );
287 		glVertex2f( map->getAdapter()->getScreenWidth(), map->getAdapter()->getScreenHeight() );
288 		glVertex2f( map->getAdapter()->getScreenWidth(), maxLightY );
289 
290 		glVertex2f( 0, minLightY );
291 		glVertex2f( 0, maxLightY );
292 		glVertex2f( minLightX, maxLightY );
293 		glVertex2f( minLightX, minLightY );
294 
295 		glVertex2f( maxLightX, minLightY );
296 		glVertex2f( maxLightX, maxLightY );
297 		glVertex2f( map->getAdapter()->getScreenWidth(), maxLightY );
298 		glVertex2f( map->getAdapter()->getScreenWidth(), minLightY );
299 
300 		glEnd();
301 
302 
303 		// draw the light circle
304 		glEnable( GL_TEXTURE_2D );
305 		glLoadIdentity();
306 		glColor4f( 1, 1, 1, 1 );
307 
308 		glBindTexture( GL_TEXTURE_2D, overlay_tex );
309 		glBegin( GL_TRIANGLE_STRIP );
310 
311 		glTexCoord2f( 0.0f, 0.0f );
312 		glVertex2f( minLightX, minLightY );
313 		glTexCoord2f( 1.0f, 0.0f );
314 		glVertex2f( maxLightX, minLightY );
315 		glTexCoord2f( 0.0f, 1.0f );
316 		glVertex2f( minLightX, maxLightY );
317 		glTexCoord2f( 1.0f, 1.0f );
318 		glVertex2f( maxLightX, maxLightY );
319 		glEnd();
320 		glDisable( GL_TEXTURE_2D );
321 	} else {
322 		glBegin( GL_TRIANGLE_STRIP );
323 		glVertex2f( 0, 0 );
324 		glVertex2f( map->getAdapter()->getScreenWidth(), 0 );
325 		glVertex2f( 0, map->getAdapter()->getScreenHeight() );
326 		glVertex2f( map->getAdapter()->getScreenWidth(),
327 		            map->getAdapter()->getScreenHeight() );
328 		glEnd();
329 	}
330 
331 	// draw the dark (unvisited) fog
332 	glLoadIdentity();
333 	glDisable( GL_BLEND );
334 	//glColor4f( 0.08f, 0.03f, 0.07f, 0.5f);
335 	glColor3f( DARK_R, DARK_G, DARK_B );
336 	for ( int i = 0; i < pCount; i++ ) {
337 		GLfloat x = p[i][0];
338 		GLfloat y = p[i][1];
339 		GLfloat w = p[i][2];
340 		GLfloat h = p[i][3];
341 
342 		if ( e[i] ) {
343 
344 			glEnable( GL_TEXTURE_2D );
345 			glEnable( GL_BLEND );
346 			glBlendFunc( GL_DST_COLOR, GL_ZERO );
347 			glColor4f( 1, 1, 1, 0.5f );
348 			glBindTexture( GL_TEXTURE_2D, shade_tex );
349 			glBegin( GL_TRIANGLE_STRIP );
350 			glTexCoord2f( 0, 0 );
351 			glVertex2f( x - ( w / 2 ), y - ( h / 2 ) );
352 			//glVertex2f( x, y );
353 			glTexCoord2f( 1, 0 );
354 			glVertex2f( x + w + ( w / 2 ), y - ( h / 2 ) );
355 			//glVertex2f( x + w, y );
356 			glTexCoord2f( 0, 1 );
357 			glVertex2f( x - ( w / 2 ), y + h + ( h / 2 ) );
358 			//glVertex2f( x, y + h );
359 			glTexCoord2f( 1, 1 );
360 			glVertex2f( x + w + ( w / 2 ), y + h + ( h / 2 ) );
361 			//glVertex2f( x + w, y + h );
362 			glEnd();
363 			glDisable( GL_BLEND );
364 			glDisable( GL_TEXTURE_2D );
365 			glColor3f( DARK_R, DARK_G, DARK_B );
366 		} else {
367 			glBegin( GL_TRIANGLE_STRIP );
368 			glVertex2f( x, y );
369 			glVertex2f( x + w, y );
370 			glVertex2f( x, y + h );
371 			glVertex2f( x + w, y + h );
372 			glEnd();
373 		}
374 	}
375 	glPopMatrix();
376 
377 #ifdef DEBUG_FOG
378 	glLoadIdentity();
379 	glDisable( GL_BLEND );
380 	glColor3f( 1, 1, 1 );
381 	for ( int i = 0; i < pCount; i++ ) {
382 		glBegin( GL_LINE_LOOP );
383 		glVertex2f( p[i][0], p[i][1] );
384 		glVertex2f( p[i][0], p[i][1] + p[i][3] );
385 		glVertex2f( p[i][0] + p[i][2], p[i][1] + p[i][3] );
386 		glVertex2f( p[i][0] + p[i][2], p[i][1] );
387 		glEnd();
388 	}
389 	glEnable( GL_BLEND );
390 #endif
391 
392 	glEnable( GL_BLEND );
393 	glEnable( GL_TEXTURE_2D );
394 	glEnable( GL_DEPTH_TEST );
395 }
396 
397 // FIXME: highest static point can be stored in the fog[][] struct
getHighestZ(int sx,int sy,int w,int h)398 int Fog::getHighestZ( int sx, int sy, int w, int h ) {
399 	int z = 0;
400 	for ( int x = sx; x < sx + w; x++ ) {
401 		for ( int y = sy; y < sy + h; y++ ) {
402 			Location *pos = map->getLocation( x, y, 0 );
403 			if ( pos && pos->shape ) {
404 				int zz = pos->z + pos->shape->getHeight();
405 				if ( zz > z ) z = zz;
406 			}
407 		}
408 	}
409 	return z;
410 }
411 
getScreenXY(GLdouble mapx,GLdouble mapy,GLdouble mapz,GLdouble * screenx,GLdouble * screeny)412 void Fog::getScreenXY( GLdouble mapx, GLdouble mapy, GLdouble mapz,
413                        GLdouble *screenx, GLdouble *screeny ) {
414 	GLdouble screenz;
415 
416 	double projection[16];
417 	double modelview[16];
418 	GLint viewport[4];
419 
420 	glGetDoublev( GL_PROJECTION_MATRIX, projection );
421 	glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
422 	glGetIntegerv( GL_VIEWPORT, viewport );
423 
424 	int res = gluProject( mapx, mapy, mapz,
425 	                      modelview,
426 	                      projection,
427 	                      viewport,
428 	                      screenx, screeny, &screenz );
429 	*screeny = ( map->getAdapter()->getScreenHeight() - *screeny );
430 	if ( !res ) {
431 		*screenx = *screeny = 2000;
432 	}
433 }
434 
createOverlayTexture()435 void Fog::createOverlayTexture() {
436 
437 	float half = ( static_cast<float>( OVERLAY_SIZE ) - 0.5f ) / 2.0f;
438 	int maxP = 90;
439 	int minP = 75;
440 
441 	// create the dark texture
442 	glGenTextures( 1, &overlay_tex );
443 	for ( unsigned int i = 0; i < OVERLAY_SIZE; i++ ) {
444 		for ( unsigned int j = 0; j < OVERLAY_SIZE; j++ ) {
445 
446 			float id = static_cast<float>( i ) - half;
447 			float jd = static_cast<float>( j ) - half;
448 
449 			// the distance
450 			float dist = sqrt( id * id + jd * jd );
451 
452 			// the distance as a percent of the max distance
453 			float percent = dist / ( sqrt( half * half ) / 100.0f );
454 
455 			int r, g, b, a;
456 			r = ER;
457 			g = EG;
458 			b = EB;
459 			if ( percent < minP ) {
460 				a = 0;
461 			} else if ( percent >= maxP ) {
462 				a = EA;
463 			} else {
464 				a = static_cast<int>( static_cast<float>( percent - minP ) *
465 				                      ( static_cast<float>( EA ) / static_cast<float>( maxP - minP ) ) );
466 			}
467 			overlay_data[i * OVERLAY_SIZE * 4 + j * 4 + 0] = ( unsigned char )r;
468 			overlay_data[i * OVERLAY_SIZE * 4 + j * 4 + 1] = ( unsigned char )g;
469 			overlay_data[i * OVERLAY_SIZE * 4 + j * 4 + 2] = ( unsigned char )b;
470 			overlay_data[i * OVERLAY_SIZE * 4 + j * 4 + 3] = ( unsigned char )a;
471 		}
472 	}
473 	glBindTexture( GL_TEXTURE_2D, overlay_tex );
474 	glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
475 	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
476 	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
477 	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
478 	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
479 	glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
480 	glTexImage2D( GL_TEXTURE_2D, 0, ( map->getPreferences()->getBpp() > 16 ? GL_RGBA : GL_RGBA4 ), OVERLAY_SIZE, OVERLAY_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, overlay_data );
481 	gluBuild2DMipmaps( GL_TEXTURE_2D, ( map->getPreferences()->getBpp() > 16 ? GL_RGBA : GL_RGBA4 ), OVERLAY_SIZE, OVERLAY_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, overlay_data );
482 }
483 
createShadeTexture()484 void Fog::createShadeTexture() {
485 
486 	float half = ( static_cast<float>( OVERLAY_SIZE ) - 0.5f ) / 2.0f;
487 	int maxP = 90;
488 	int minP = 70;
489 
490 	// create the dark texture
491 	glGenTextures( 1, &shade_tex );
492 	for ( unsigned int i = 0; i < OVERLAY_SIZE; i++ ) {
493 		for ( unsigned int j = 0; j < OVERLAY_SIZE; j++ ) {
494 
495 			float id = static_cast<float>( i ) - half;
496 			float jd = static_cast<float>( j ) - half;
497 
498 			// the distance
499 			float dist = sqrt( id * id + jd * jd );
500 
501 			// the distance as a percent of the max distance
502 			float percent = dist / ( sqrt( half * half ) / 100.0f );
503 
504 			int r, g, b;
505 			if ( percent < minP ) {
506 				r = SR;
507 				g = SG;
508 				b = SB;
509 			} else if ( percent >= maxP ) {
510 				r = 0xff;
511 				g = 0xff;
512 				b = 0xff;
513 			} else {
514 				r = SR + static_cast<int>( static_cast<float>( percent - minP ) * ( static_cast<float>( 0xff - SR ) / static_cast<float>( maxP - minP ) ) );
515 				if ( r > 0xff )
516 					r = 0xff;
517 				g = SG + static_cast<int>( static_cast<float>( percent - minP ) * ( static_cast<float>( 0xff - SG ) / static_cast<float>( maxP - minP ) ) );
518 				if ( g > 0xff )
519 					g = 0xff;
520 				b = SB + static_cast<int>( static_cast<float>( percent - minP ) * ( static_cast<float>( 0xff - SB ) / static_cast<float>( maxP - minP ) ) );
521 				if ( b > 0xff )
522 					b = 0xff;
523 			}
524 			shade_data[i * OVERLAY_SIZE * 3 + j * 3 + 0] = ( unsigned char )r;
525 			shade_data[i * OVERLAY_SIZE * 3 + j * 3 + 1] = ( unsigned char )g;
526 			shade_data[i * OVERLAY_SIZE * 3 + j * 3 + 2] = ( unsigned char )b;
527 		}
528 	}
529 	glBindTexture( GL_TEXTURE_2D, shade_tex );
530 	glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
531 	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
532 	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
533 	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
534 	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
535 	glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
536 	glTexImage2D( GL_TEXTURE_2D, 0, ( map->getPreferences()->getBpp() > 16 ? GL_RGB : GL_RGB5 ), OVERLAY_SIZE, OVERLAY_SIZE, 0, GL_RGB, GL_UNSIGNED_BYTE, shade_data );
537 	gluBuild2DMipmaps( GL_TEXTURE_2D, ( map->getPreferences()->getBpp() > 16 ? GL_RGB : GL_RGB5 ), OVERLAY_SIZE, OVERLAY_SIZE, GL_RGB, GL_UNSIGNED_BYTE, shade_data );
538 }
539 
load(FogInfo * fogInfo)540 void Fog::load( FogInfo *fogInfo ) {
541 	for ( int x = 0; x < MAP_WIDTH; x++ ) {
542 		for ( int y = 0; y < MAP_DEPTH; y++ ) {
543 			fog[x][y] = fogInfo->fog[x][y];
544 		}
545 	}
546 }
547 
save(FogInfo * fogInfo)548 void Fog::save( FogInfo *fogInfo ) {
549 	for ( int x = 0; x < MAP_WIDTH; x++ ) {
550 		for ( int y = 0; y < MAP_DEPTH; y++ ) {
551 			fogInfo->fog[x][y] = fog[x][y];
552 		}
553 	}
554 }
555