1 /*-------------------------------------------------------------------------------
2 
3 	BARONY
4 	File: opengl.cpp
5 	Desc: contains all drawing functions for opengl
6 
7 	Copyright 2013-2016 (c) Turning Wheel LLC, all rights reserved.
8 	See LICENSE for details.
9 
10 -------------------------------------------------------------------------------*/
11 
12 #include "main.hpp"
13 #include "draw.hpp"
14 #include "entity.hpp"
15 #include "files.hpp"
16 
17 #ifdef WINDOWS
18 PFNGLGENBUFFERSPROC SDL_glGenBuffers;
19 PFNGLBINDBUFFERPROC SDL_glBindBuffer;
20 PFNGLBUFFERDATAPROC SDL_glBufferData;
21 PFNGLDELETEBUFFERSPROC SDL_glDeleteBuffers;
22 PFNGLGENVERTEXARRAYSPROC SDL_glGenVertexArrays;
23 PFNGLBINDVERTEXARRAYPROC SDL_glBindVertexArray;
24 PFNGLDELETEVERTEXARRAYSPROC SDL_glDeleteVertexArrays;
25 PFNGLENABLEVERTEXATTRIBARRAYPROC SDL_glEnableVertexAttribArray;
26 PFNGLVERTEXATTRIBPOINTERPROC SDL_glVertexAttribPointer;
27 #endif
28 
29 /*-------------------------------------------------------------------------------
30 
31 	getLightForEntity
32 
33 	Returns a shade factor (0.0-1.0) to shade an entity with, based on
34 	its surroundings
35 
36 -------------------------------------------------------------------------------*/
37 
getLightForEntity(real_t x,real_t y)38 real_t getLightForEntity(real_t x, real_t y)
39 {
40 	if ( x < 0 || y < 0 || x >= map.width || y >= map.height )
41 	{
42 		return 1.f;
43 	}
44 	int u = x;
45 	int v = y;
46 	return std::min(std::max(0, lightmapSmoothed[v + u * map.height]), 255) / 255.0;
47 }
48 
49 /*-------------------------------------------------------------------------------
50 
51 	glDrawVoxel
52 
53 	Draws a voxel model at the given world coordinates
54 
55 -------------------------------------------------------------------------------*/
56 
57 bool wholevoxels = false;
glDrawVoxel(view_t * camera,Entity * entity,int mode)58 void glDrawVoxel(view_t* camera, Entity* entity, int mode)
59 {
60 	real_t dx, dy, dz;
61 	int voxX, voxY, voxZ;
62 	real_t s = 1;
63 	//int x = 0;
64 	//int y = 0;
65 	Sint32 index;
66 	Sint32 indexdown[3];
67 	voxel_t* model;
68 	int modelindex = 0;
69 	GLfloat rotx, roty, rotz;
70 	//GLuint uidcolor;
71 
72 	if (!entity)
73 	{
74 		return;
75 	}
76 
77 	// assign model
78 	if ( entity->sprite >= 0 && entity->sprite < nummodels )
79 	{
80 		if ( models[entity->sprite] != NULL )
81 		{
82 			model = models[entity->sprite];
83 		}
84 		else
85 		{
86 			model = models[0];
87 		}
88 		modelindex = entity->sprite;
89 	}
90 	else
91 	{
92 		model = models[0];
93 		modelindex = 0;
94 	}
95 
96 	if ( model == models[0] )
97 	{
98 		return; // don't draw green balls
99 	}
100 
101 	// model array indexes
102 	indexdown[0] = model->sizez * model->sizey;
103 	indexdown[1] = model->sizez;
104 	indexdown[2] = 1;
105 
106 	glBindTexture(GL_TEXTURE_2D, 0);
107 
108 	// setup projection
109 	glMatrixMode( GL_PROJECTION );
110 	glLoadIdentity();
111 	glViewport(camera->winx, yres - camera->winh - camera->winy, camera->winw, camera->winh);
112 	gluPerspective(fov, (real_t)camera->winw / (real_t)camera->winh, CLIPNEAR, CLIPFAR * 2);
113 	glEnable( GL_DEPTH_TEST );
114 	if ( !entity->flags[OVERDRAW] )
115 	{
116 		rotx = camera->vang * 180 / PI; // get x rotation
117 		roty = (camera->ang - 3 * PI / 2) * 180 / PI; // get y rotation
118 		rotz = 0; // get z rotation
119 		glRotatef(rotx, 1, 0, 0); // rotate pitch
120 		glRotatef(roty, 0, 1, 0); // rotate yaw
121 		glRotatef(rotz, 0, 0, 1); // rotate roll
122 		glTranslatef(-camera->x * 32, camera->z, -camera->y * 32); // translates the scene based on camera position
123 	}
124 	else
125 	{
126 		glRotatef(90, 0, 1, 0);
127 	}
128 
129 	// setup model matrix
130 	glMatrixMode( GL_MODELVIEW );
131 	glLoadIdentity();
132 	glPushMatrix();
133 	rotx = entity->roll * 180 / PI; // get x rotation
134 	roty = 360 - entity->yaw * 180 / PI; // get y rotation
135 	rotz = 360 - entity->pitch * 180 / PI; // get z rotation
136 	glTranslatef(entity->x * 2, -entity->z * 2 - 1, entity->y * 2);
137 	glRotatef(roty, 0, 1, 0); // rotate yaw
138 	glRotatef(rotz, 0, 0, 1); // rotate pitch
139 	glRotatef(rotx, 1, 0, 0); // rotate roll
140 	glTranslatef(entity->focalx * 2, -entity->focalz * 2, entity->focaly * 2);
141 	glScalef(entity->scalex, entity->scalez, entity->scaley);
142 	if ( mode == REALCOLORS )
143 	{
144 		glEnable(GL_BLEND);
145 	}
146 	else
147 	{
148 		glDisable(GL_BLEND);
149 	}
150 
151 	if ( entity->flags[OVERDRAW] || entity->monsterEntityRenderAsTelepath == 1 )
152 	{
153 		glDepthRange(0, 0.1);
154 	}
155 
156 	// get shade factor
157 	if (!entity->flags[BRIGHT])
158 	{
159 		if ( !entity->flags[OVERDRAW] )
160 		{
161 			if ( entity->monsterEntityRenderAsTelepath == 1 )
162 			{
163 				if ( globalLightModifierActive )
164 				{
165 					s = globalLightTelepathyModifier;
166 				}
167 			}
168 			else
169 			{
170 				s = getLightForEntity(entity->x / 16, entity->y / 16);
171 			}
172 		}
173 		else
174 		{
175 			s = getLightForEntity(camera->x, camera->y);
176 		}
177 	}
178 
179 	if ( globalLightModifierActive && entity->monsterEntityRenderAsTelepath == 0 )
180 	{
181 		s *= globalLightModifier;
182 	}
183 
184 	// Moved glBeign / glEnd outside the loops, to limit the number of calls (helps gl4es on Pandora)
185 	if ( wholevoxels )
186 	{
187 		glBegin( GL_QUADS );
188 		for ( index = 0, voxX = 0; voxX < model->sizex; voxX++ )
189 		{
190 			for ( voxY = 0; voxY < model->sizey; voxY++ )
191 			{
192 				for ( voxZ = 0; voxZ < model->sizez; voxZ++, index++ )
193 				{
194 					// get the bit color
195 					if ( model->data[index] == 255 || model->data[index] == 0 )
196 					{
197 						continue;
198 					}
199 					if ( mode == REALCOLORS )
200 					{
201 						glColor3f((model->palette[model->data[index]][0] / 255.0)*s, (model->palette[model->data[index]][1] / 255.0)*s, (model->palette[model->data[index]][2] / 255.0)*s );
202 					}
203 					else
204 					{
205 						Uint32 uid = entity->getUID();
206 						glColor4ub((Uint8)(uid), (Uint8)(uid >> 8), (Uint8)(uid >> 16), (Uint8)(uid >> 24));
207 					}
208 
209 					// calculate model offsets
210 					dx = (real_t)voxX - ((real_t)model->sizex) / 2.f;
211 					dy = (real_t)voxY - ((real_t)model->sizey) / 2.f;
212 					dz = ((real_t)model->sizez) / 2.f - (real_t)voxZ;
213 
214 					// draw front of cube
215 					bool drawFront = false;
216 					if ( voxX == model->sizex - 1 )
217 					{
218 						drawFront = true;
219 					}
220 					else if ( model->data[index + indexdown[0]] == 255 )
221 					{
222 						drawFront = true;
223 					}
224 					if ( drawFront )
225 					{
226 						//glBegin( GL_QUADS );
227 						glVertex3f(dx + 1, dz + 0, dy + 1);
228 						glVertex3f(dx + 1, dz + 0, dy + 0);
229 						glVertex3f(dx + 1, dz + 1, dy + 0);
230 						glVertex3f(dx + 1, dz + 1, dy + 1);
231 						//glEnd();
232 					}
233 
234 					// draw back of cube
235 					bool drawBack = false;
236 					if ( voxX == 0 )
237 					{
238 						drawBack = true;
239 					}
240 					else if ( model->data[index - indexdown[0]] == 255 )
241 					{
242 						drawBack = true;
243 					}
244 					if ( drawBack )
245 					{
246 						//glBegin( GL_QUADS );
247 						glVertex3f(dx + 0, dz + 0, dy + 1);
248 						glVertex3f(dx + 0, dz + 1, dy + 1);
249 						glVertex3f(dx + 0, dz + 1, dy + 0);
250 						glVertex3f(dx + 0, dz + 0, dy + 0);
251 						//glEnd();
252 					}
253 
254 					// draw right side of cube
255 					bool drawRight = false;
256 					if ( voxY == model->sizey - 1 )
257 					{
258 						drawRight = true;
259 					}
260 					else if ( model->data[index + indexdown[1]] == 255 )
261 					{
262 						drawRight = true;
263 					}
264 					if ( drawRight )
265 					{
266 						//glBegin( GL_QUADS );
267 						glVertex3f(dx + 0, dz + 0, dy + 1);
268 						glVertex3f(dx + 1, dz + 0, dy + 1);
269 						glVertex3f(dx + 1, dz + 1, dy + 1);
270 						glVertex3f(dx + 0, dz + 1, dy + 1);
271 						//glEnd();
272 					}
273 
274 					// draw left side of cube
275 					bool drawLeft = false;
276 					if ( voxY == 0 )
277 					{
278 						drawLeft = true;
279 					}
280 					else if ( model->data[index - indexdown[1]] == 255 )
281 					{
282 						drawLeft = true;
283 					}
284 					if ( drawLeft )
285 					{
286 						//glBegin( GL_QUADS );
287 						glVertex3f(dx + 0, dz + 0, dy + 0);
288 						glVertex3f(dx + 0, dz + 1, dy + 0);
289 						glVertex3f(dx + 1, dz + 1, dy + 0);
290 						glVertex3f(dx + 1, dz + 0, dy + 0);
291 						//glEnd();
292 					}
293 
294 					// draw bottom of cube
295 					bool drawBottom = false;
296 					if ( voxZ == model->sizez - 1 )
297 					{
298 						drawBottom = true;
299 					}
300 					else if ( model->data[index + indexdown[2]] == 255 )
301 					{
302 						drawBottom = true;
303 					}
304 					if ( drawBottom )
305 					{
306 						//glBegin( GL_QUADS );
307 						glVertex3f(dx + 0, dz + 0, dy + 0);
308 						glVertex3f(dx + 1, dz + 0, dy + 0);
309 						glVertex3f(dx + 1, dz + 0, dy + 1);
310 						glVertex3f(dx + 0, dz + 0, dy + 1);
311 						//glEnd();
312 					}
313 
314 					// draw top of cube
315 					bool drawTop = false;
316 					if ( voxZ == 0 )
317 					{
318 						drawTop = true;
319 					}
320 					else if ( model->data[index - indexdown[2]] == 255 )
321 					{
322 						drawTop = true;
323 					}
324 					if ( drawTop )
325 					{
326 						//glBegin( GL_QUADS );
327 						glVertex3f(dx + 0, dz + 1, dy + 0);
328 						glVertex3f(dx + 0, dz + 1, dy + 1);
329 						glVertex3f(dx + 1, dz + 1, dy + 1);
330 						glVertex3f(dx + 1, dz + 1, dy + 0);
331 						//glEnd();
332 					}
333 				}
334 			}
335 		}
336 		glEnd();
337 	}
338 	else
339 	{
340 		if ( disablevbos )
341 		{
342 			glBegin( GL_TRIANGLES ); //moved outside
343 			for ( index = 0; index < polymodels[modelindex].numfaces; index++ )
344 			{
345 				if ( mode == REALCOLORS )
346 				{
347 					if ( entity->flags[USERFLAG2] )
348 					{
349 						if ( entity->behavior == &actMonster
350 							&& (entity->isPlayerHeadSprite() || entity->sprite == 467 || !monsterChangesColorWhenAlly(nullptr, entity)) )
351 						{
352 							// dont invert human heads, or automaton heads.
353 							glColor3f((polymodels[modelindex].faces[index].r / 255.f)*s, (polymodels[modelindex].faces[index].g / 255.f)*s, (polymodels[modelindex].faces[index].b / 255.f)*s );
354 						}
355 						else
356 						{
357 							glColor3f((polymodels[modelindex].faces[index].b / 255.f)*s, (polymodels[modelindex].faces[index].r / 255.f)*s, (polymodels[modelindex].faces[index].g / 255.f)*s);
358 						}
359 					}
360 					else
361 					{
362 						glColor3f((polymodels[modelindex].faces[index].b / 255.f)*s, (polymodels[modelindex].faces[index].r / 255.f)*s, (polymodels[modelindex].faces[index].g / 255.f)*s );
363 					}
364 				}
365 				else
366 				{
367 					Uint32 uid = entity->getUID();
368 					glColor4ub((Uint8)(uid), (Uint8)(uid >> 8), (Uint8)(uid >> 16), (Uint8)(uid >> 24));
369 				}
370 
371 				polytriangle_t* face = &polymodels[modelindex].faces[index];
372 
373 				//glBegin( GL_TRIANGLES );
374 				glVertex3f(face->vertex[0].x, -face->vertex[0].z, face->vertex[0].y);
375 				glVertex3f(face->vertex[1].x, -face->vertex[1].z, face->vertex[1].y);
376 				glVertex3f(face->vertex[2].x, -face->vertex[2].z, face->vertex[2].y);
377 				//glEnd();
378 			}
379 			glEnd();
380 		}
381 		else
382 		{
383 			SDL_glBindVertexArray(polymodels[modelindex].va);
384 			SDL_glBindBuffer(GL_ARRAY_BUFFER, polymodels[modelindex].vbo);
385 			glVertexPointer( 3, GL_FLOAT, 0, (char*) NULL );  // Set The Vertex Pointer To The Vertex Buffer
386 			glEnableClientState(GL_VERTEX_ARRAY); // enable the vertex array on the client side
387 			if ( mode == REALCOLORS )
388 			{
389 				glEnableClientState(GL_COLOR_ARRAY); // enable the color array on the client side
390 				if ( entity->flags[USERFLAG2] )
391 				{
392 					if ( entity->behavior == &actMonster && (entity->isPlayerHeadSprite()
393 						|| entity->sprite == 467 || !monsterChangesColorWhenAlly(nullptr, entity)) )
394 					{
395 						SDL_glBindBuffer(GL_ARRAY_BUFFER, polymodels[modelindex].colors);
396 					}
397 					else
398 					{
399 						SDL_glBindBuffer(GL_ARRAY_BUFFER, polymodels[modelindex].colors_shifted);
400 					}
401 				}
402 				else
403 				{
404 					SDL_glBindBuffer(GL_ARRAY_BUFFER, polymodels[modelindex].colors);
405 				}
406 				glColorPointer(3, GL_FLOAT, 0, 0);
407 				GLfloat params_col[4] = {static_cast<GLfloat>(s), static_cast<GLfloat>(s), static_cast<GLfloat>(s), 1.f};
408 				glEnable(GL_LIGHTING);
409 				glEnable(GL_COLOR_MATERIAL);
410 				glLightModelfv(GL_LIGHT_MODEL_AMBIENT, params_col);
411 			}
412 			else
413 			{
414 				GLfloat uidcolors[4];
415 				Uint32 uid = entity->getUID();
416 				uidcolors[0] = ((Uint8)(uid)) / 255.f;
417 				uidcolors[1] = ((Uint8)(uid >> 8)) / 255.f;
418 				uidcolors[2] = ((Uint8)(uid >> 16)) / 255.f;
419 				uidcolors[3] = ((Uint8)(uid >> 24)) / 255.f;
420 				glColor4f(uidcolors[0], uidcolors[1], uidcolors[2], uidcolors[3]);
421 			}
422 			glDrawArrays(GL_TRIANGLES, 0, 3 * polymodels[modelindex].numfaces);
423 			if ( mode == REALCOLORS )
424 			{
425 				glDisable(GL_COLOR_MATERIAL);
426 				glDisable(GL_LIGHTING);
427 				glDisableClientState(GL_COLOR_ARRAY); // disable the color array on the client side
428 			}
429 			glDisableClientState(GL_VERTEX_ARRAY); // disable the vertex array on the client side
430 		}
431 	}
432 	glDepthRange(0, 1);
433 	glPopMatrix();
434 }
435 
436 /*-------------------------------------------------------------------------------
437 
438 	glDrawSprite
439 
440 	Draws a 2D sprite to represent an object in 3D
441 
442 -------------------------------------------------------------------------------*/
443 
glDrawSprite(view_t * camera,Entity * entity,int mode)444 void glDrawSprite(view_t* camera, Entity* entity, int mode)
445 {
446 	SDL_Surface* sprite;
447 	//int x, y;
448 	real_t s = 1;
449 
450 	// setup projection
451 	glMatrixMode( GL_PROJECTION );
452 	glLoadIdentity();
453 	glViewport(camera->winx, yres - camera->winh - camera->winy, camera->winw, camera->winh);
454 	gluPerspective(fov, (real_t)camera->winw / (real_t)camera->winh, CLIPNEAR, CLIPFAR * 2);
455 	glEnable( GL_DEPTH_TEST );
456 	if (!entity->flags[OVERDRAW])
457 	{
458 		GLfloat rotx = camera->vang * 180 / PI; // get x rotation
459 		GLfloat roty = (camera->ang - 3 * PI / 2) * 180 / PI; // get y rotation
460 		GLfloat rotz = 0; // get z rotation
461 		glRotatef(rotx, 1, 0, 0); // rotate pitch
462 		glRotatef(roty, 0, 1, 0); // rotate yaw
463 		glRotatef(rotz, 0, 0, 1); // rotate roll
464 		glTranslatef(-camera->x * 32, camera->z, -camera->y * 32); // translates the scene based on camera position
465 	}
466 	else
467 	{
468 		glRotatef(90, 0, 1, 0);
469 
470 	}
471 
472 	// setup model matrix
473 	glMatrixMode( GL_MODELVIEW );
474 	glLoadIdentity();
475 	glPushMatrix();
476 	if ( mode == REALCOLORS )
477 	{
478 		glEnable(GL_BLEND);
479 	}
480 	else
481 	{
482 		glDisable(GL_BLEND);
483 	}
484 
485 	// assign texture
486 	if ( entity->sprite >= 0 && entity->sprite < numsprites )
487 	{
488 		if ( sprites[entity->sprite] != NULL )
489 		{
490 			sprite = sprites[entity->sprite];
491 		}
492 		else
493 		{
494 			sprite = sprites[0];
495 		}
496 	}
497 	else
498 	{
499 		sprite = sprites[0];
500 	}
501 	if ( mode == REALCOLORS )
502 	{
503 		glBindTexture(GL_TEXTURE_2D, texid[sprite->refcount]);
504 	}
505 	else
506 	{
507 		glBindTexture(GL_TEXTURE_2D, 0);
508 	}
509 
510 	// translate sprite and rotate towards camera
511 	//double tangent = atan2( entity->y-camera->y*16, camera->x*16-entity->x ) * (180/PI);
512 	glTranslatef(entity->x * 2, -entity->z * 2 - 1, entity->y * 2);
513 	if (!entity->flags[OVERDRAW])
514 	{
515 		real_t tangent = 180 - camera->ang * (180 / PI);
516 		glRotatef(tangent, 0, 1, 0);
517 	}
518 	else
519 	{
520 		real_t tangent = 180;
521 		glRotatef(tangent, 0, 1, 0);
522 	}
523 	glScalef(entity->scalex, entity->scalez, entity->scaley);
524 
525 	if ( entity->flags[OVERDRAW] )
526 	{
527 		glDepthRange(0, 0.1);
528 	}
529 
530 	// get shade factor
531 	if ( mode == REALCOLORS )
532 	{
533 		if (!entity->flags[BRIGHT])
534 		{
535 			if (!entity->flags[OVERDRAW])
536 			{
537 				s = getLightForEntity(entity->x / 16, entity->y / 16);
538 			}
539 			else
540 			{
541 				s = getLightForEntity(camera->x, camera->y);
542 			}
543 
544 			if ( globalLightModifierActive )
545 			{
546 				s *= globalLightModifier;
547 			}
548 
549 			glColor4f(s, s, s, 1);
550 		}
551 		else
552 		{
553 			if ( globalLightModifierActive )
554 			{
555 				glColor4f(globalLightModifier, globalLightModifier, globalLightModifier, 1);
556 			}
557 			else
558 			{
559 				glColor4f(1.f, 1.f, 1.f, 1);
560 			}
561 		}
562 	}
563 	else
564 	{
565 		Uint32 uid = entity->getUID();
566 		glColor4ub((Uint8)(uid), (Uint8)(uid >> 8), (Uint8)(uid >> 16), (Uint8)(uid >> 24));
567 	}
568 
569 	// draw quad
570 	glBegin(GL_QUADS);
571 	glTexCoord2f(0, 0);
572 	glVertex3f(0, sprite->h / 2, sprite->w / 2);
573 	glTexCoord2f(0, 1);
574 	glVertex3f(0, -sprite->h / 2, sprite->w / 2);
575 	glTexCoord2f(1, 1);
576 	glVertex3f(0, -sprite->h / 2, -sprite->w / 2);
577 	glTexCoord2f(1, 0);
578 	glVertex3f(0, sprite->h / 2, -sprite->w / 2);
579 	glEnd();
580 	glDepthRange(0, 1);
581 	glPopMatrix();
582 }
583 
glDrawSpriteFromImage(view_t * camera,Entity * entity,std::string text,int mode)584 void glDrawSpriteFromImage(view_t* camera, Entity* entity, std::string text, int mode)
585 {
586 	//int x, y;
587 	real_t s = 1;
588 	SDL_Surface* image = sprites[0];
589 	GLuint textureId = texid[sprites[0]->refcount];
590 	char textToRetrieve[128];
591 
592 	if ( text.compare("") == 0 )
593 	{
594 		return;
595 	}
596 
597 	// strncpy() does not copy N bytes if a terminating null is encountered first
598 	// see http://www.cplusplus.com/reference/cstring/strncpy/
599 	// see https://en.cppreference.com/w/c/string/byte/strncpy
600 	// GCC throws a warning (intended) when the length argument to strncpy()
601 	// in any way depends on strlen(src) to discourage this (and related) construct(s).
602 	strncpy(textToRetrieve, text.c_str(), 22);
603 	textToRetrieve[std::min(static_cast<int>(strlen(text.c_str())), 22)] = '\0';
604 	if ( (image = ttfTextHashRetrieve(ttfTextHash, textToRetrieve, ttf12, true)) != NULL )
605 	{
606 		textureId = texid[image->refcount];
607 	}
608 	else
609 	{
610 		// create the text outline surface
611 		TTF_SetFontOutline(ttf12, 2);
612 		SDL_Color sdlColorBlack = { 0, 0, 0, 255 };
613 		image = TTF_RenderUTF8_Blended(ttf12, textToRetrieve, sdlColorBlack);
614 
615 		// create the text surface
616 		TTF_SetFontOutline(ttf12, 0);
617 		SDL_Color sdlColorWhite = { 255, 255, 255, 255 };
618 		SDL_Surface* textSurf = TTF_RenderUTF8_Blended(ttf12, textToRetrieve, sdlColorWhite);
619 
620 		// combine the surfaces
621 		SDL_Rect pos;
622 		pos.x = 2;
623 		pos.y = 2;
624 		pos.h = 0;
625 		pos.w = 0;
626 
627 		SDL_BlitSurface(textSurf, NULL, image, &pos);
628 		// load the text outline surface as a GL texture
629 		allsurfaces[imgref] = image;
630 		allsurfaces[imgref]->refcount = imgref;
631 		glLoadTexture(allsurfaces[imgref], imgref);
632 		imgref++;
633 		// store the surface in the text surface cache
634 		if ( !ttfTextHashStore(ttfTextHash, textToRetrieve, ttf12, true, image) )
635 		{
636 			printlog("warning: failed to store text outline surface with imgref %d\n", imgref - 1);
637 		}
638 		textureId = texid[image->refcount];
639 	}
640 	// setup projection
641 	glMatrixMode(GL_PROJECTION);
642 	glLoadIdentity();
643 	glViewport(camera->winx, yres - camera->winh - camera->winy, camera->winw, camera->winh);
644 	gluPerspective(fov, (real_t)camera->winw / (real_t)camera->winh, CLIPNEAR, CLIPFAR * 2);
645 	glEnable(GL_DEPTH_TEST);
646 	if ( !entity->flags[OVERDRAW] )
647 	{
648 		GLfloat rotx = camera->vang * 180 / PI; // get x rotation
649 		GLfloat roty = (camera->ang - 3 * PI / 2) * 180 / PI; // get y rotation
650 		GLfloat rotz = 0; // get z rotation
651 		glRotatef(rotx, 1, 0, 0); // rotate pitch
652 		glRotatef(roty, 0, 1, 0); // rotate yaw
653 		glRotatef(rotz, 0, 0, 1); // rotate roll
654 		glTranslatef(-camera->x * 32, camera->z, -camera->y * 32); // translates the scene based on camera position
655 	}
656 	else
657 	{
658 		glRotatef(90, 0, 1, 0);
659 	}
660 
661 
662 	// setup model matrix
663 	glMatrixMode(GL_MODELVIEW);
664 	glLoadIdentity();
665 	glPushMatrix();
666 	if ( mode == REALCOLORS )
667 	{
668 		glEnable(GL_BLEND);
669 	}
670 	else
671 	{
672 		glDisable(GL_BLEND);
673 	}
674 
675 	// assign texture
676 	if ( mode == REALCOLORS )
677 	{
678 		glBindTexture(GL_TEXTURE_2D, textureId);
679 	}
680 	else
681 	{
682 		glBindTexture(GL_TEXTURE_2D, 0);
683 	}
684 
685 	// translate sprite and rotate towards camera
686 	//double tangent = atan2( entity->y-camera->y*16, camera->x*16-entity->x ) * (180/PI);
687 	glTranslatef(entity->x * 2, -entity->z * 2 - 1, entity->y * 2);
688 	if ( !entity->flags[OVERDRAW] )
689 	{
690 		real_t tangent = 180 - camera->ang * (180 / PI);
691 		glRotatef(tangent, 0, 1, 0);
692 	}
693 	else
694 	{
695 		real_t tangent = 180;
696 		glRotatef(tangent, 0, 1, 0);
697 	}
698 	glScalef(entity->scalex, entity->scalez, entity->scaley);
699 
700 	if ( entity->flags[OVERDRAW] )
701 	{
702 		glDepthRange(0, 0.1);
703 	}
704 
705 	// get shade factor
706 	if ( mode == REALCOLORS )
707 	{
708 		if ( !entity->flags[BRIGHT] )
709 		{
710 			if ( !entity->flags[OVERDRAW] )
711 			{
712 				s = getLightForEntity(entity->x / 16, entity->y / 16);
713 			}
714 			else
715 			{
716 				s = getLightForEntity(camera->x, camera->y);
717 			}
718 			glColor4f(s, s, s, 1);
719 		}
720 		else
721 		{
722 			glColor4f(1.f, 1.f, 1.f, 1);
723 		}
724 	}
725 	else
726 	{
727 		Uint32 uid = entity->getUID();
728 		glColor4ub((Uint8)(uid), (Uint8)(uid >> 8), (Uint8)(uid >> 16), (Uint8)(uid >> 24));
729 	}
730 
731 	// draw quad
732 	glBegin(GL_QUADS);
733 	glTexCoord2f(0, 0);
734 	glVertex3f(0, image->h / 2, image->w / 2);
735 	glTexCoord2f(0, 1);
736 	glVertex3f(0, -image->h / 2, image->w / 2);
737 	glTexCoord2f(1, 1);
738 	glVertex3f(0, -image->h / 2, -image->w / 2);
739 	glTexCoord2f(1, 0);
740 	glVertex3f(0, image->h / 2, -image->w / 2);
741 	glEnd();
742 	glDepthRange(0, 1);
743 	glPopMatrix();
744 }
745 
746 /*-------------------------------------------------------------------------------
747 
748 	getLightAt
749 
750 	returns the light shade factor for the vertex at the given x/y point
751 
752 -------------------------------------------------------------------------------*/
753 
getLightAt(int x,int y)754 real_t getLightAt(int x, int y)
755 {
756 	real_t l = 0;
757 	int u, v;
758 
759 	for ( u = x - 1; u < x + 1; u++ )
760 	{
761 		for ( v = y - 1; v < y + 1; v++ )
762 		{
763 			if ( u >= 0 && u < map.width && v >= 0 && v < map.height )
764 			{
765 				l += std::min(std::max(0, lightmapSmoothed[v + u * map.height]), 255) / 255.0;
766 			}
767 		}
768 	}
769 
770 	if ( globalLightModifierActive )
771 	{
772 		l *= globalLightModifier;
773 	}
774 
775 	return l / 4.f;
776 }
777 
778 /*-------------------------------------------------------------------------------
779 
780 	glDrawWorld
781 
782 	Draws the current map from the given camera point
783 
784 -------------------------------------------------------------------------------*/
785 
glDrawWorld(view_t * camera,int mode)786 void glDrawWorld(view_t* camera, int mode)
787 {
788 	int x, y, z;
789 	int index;
790 	real_t s;
791 	bool clouds = false;
792 	int cloudtile = 0;
793 	int mapceilingtile = 50;
794 
795 	if ( softwaremode == true )
796 	{
797 		return;
798 	}
799 
800 	if ( (!strncmp(map.name, "Hell", 4) || map.skybox != 0) && smoothlighting )
801 	{
802 		clouds = true;
803 		if ( !strncmp(map.name, "Hell", 4) )
804 		{
805 			cloudtile = 77;
806 		}
807 		else
808 		{
809 			cloudtile = map.skybox;
810 		}
811 	}
812 
813 	for ( int v = 0; v < map.height; v++ )
814 	{
815 		for ( int u = 0; u < map.width; u++ )
816 		{
817 			int smoothingRate = globalLightSmoothingRate;
818 			int difference = abs(lightmapSmoothed[v + u * map.height] - lightmap[v + u * map.height]);
819 			if ( difference > 64 )
820 			{
821 				smoothingRate *= 4;
822 			}
823 			else if ( difference > 32 )
824 			{
825 				smoothingRate *= 2;
826 			}
827 			if ( lightmapSmoothed[v + u * map.height] < lightmap[v + u * map.height] )
828 			{
829 				lightmapSmoothed[v + u * map.height] = std::min(lightmap[v + u * map.height], lightmapSmoothed[v + u * map.height] + smoothingRate);
830 			}
831 			else if ( lightmapSmoothed[v + u * map.height] > lightmap[v + u * map.height] )
832 			{
833 				lightmapSmoothed[v + u * map.height] = std::max(lightmap[v + u * map.height], lightmapSmoothed[v + u * map.height] - smoothingRate);
834 			}
835 		}
836 	}
837 
838 	if ( map.flags[MAP_FLAG_CEILINGTILE] != 0 && map.flags[MAP_FLAG_CEILINGTILE] < numtiles )
839 	{
840 		mapceilingtile = map.flags[MAP_FLAG_CEILINGTILE];
841 	}
842 
843 	glEnable(GL_SCISSOR_TEST);
844 	glScissor(camera->winx, yres - camera->winh - camera->winy, camera->winw, camera->winh);
845 
846 	if ( clouds && mode == REALCOLORS )
847 	{
848 		// draw sky "box"
849 		glMatrixMode( GL_PROJECTION );
850 		glLoadIdentity();
851 		glViewport(camera->winx, yres - camera->winh - camera->winy, camera->winw, camera->winh);
852 		gluPerspective(fov, (real_t)camera->winw / (real_t)camera->winh, CLIPNEAR, CLIPFAR * 16);
853 		GLfloat rotx = camera->vang * 180 / PI; // get x rotation
854 		GLfloat roty = (camera->ang - 3 * PI / 2) * 180 / PI; // get y rotation
855 		GLfloat rotz = 0; // get z rotation
856 		glRotatef(rotx, 1, 0, 0); // rotate pitch
857 		glRotatef(roty, 0, 1, 0); // rotate yaw
858 		glRotatef(rotz, 0, 0, 1); // rotate roll
859 		glMatrixMode( GL_MODELVIEW );
860 		glLoadIdentity();
861 		glEnable( GL_DEPTH_TEST );
862 		glDepthMask(GL_FALSE);
863 		glEnable(GL_BLEND);
864 
865 		// first (higher) sky layer
866 		glColor4f(1.f, 1.f, 1.f, .5);
867 		glBindTexture(GL_TEXTURE_2D, texid[tiles[cloudtile]->refcount]); // sky tile
868 		glBegin( GL_QUADS );
869 		glTexCoord2f((real_t)(ticks % 60) / 60, (real_t)(ticks % 60) / 60);
870 		glVertex3f(-CLIPFAR * 16, 64, -CLIPFAR * 16);
871 
872 		glTexCoord2f((CLIPFAR) / 2 + (real_t)(ticks % 60) / 60, (real_t)(ticks % 60) / 60);
873 		glVertex3f(CLIPFAR * 16, 64, -CLIPFAR * 16);
874 
875 		glTexCoord2f((CLIPFAR) / 2 + (real_t)(ticks % 60) / 60, (CLIPFAR) / 2 + (real_t)(ticks % 60) / 60);
876 		glVertex3f(CLIPFAR * 16, 64, CLIPFAR * 16);
877 
878 		glTexCoord2f((real_t)(ticks % 60) / 60, (CLIPFAR) / 2 + (real_t)(ticks % 60) / 60);
879 		glVertex3f(-CLIPFAR * 16, 64, CLIPFAR * 16);
880 		glEnd();
881 
882 		// second (closer) sky layer
883 		glColor4f(1.f, 1.f, 1.f, .5);
884 		glBindTexture(GL_TEXTURE_2D, texid[tiles[cloudtile]->refcount]); // sky tile
885 		glBegin( GL_QUADS );
886 		glTexCoord2f((real_t)(ticks % 240) / 240, (real_t)(ticks % 240) / 240);
887 		glVertex3f(-CLIPFAR * 16, 32, -CLIPFAR * 16);
888 
889 		glTexCoord2f((CLIPFAR) / 2 + (real_t)(ticks % 240) / 240, (real_t)(ticks % 240) / 240);
890 		glVertex3f(CLIPFAR * 16, 32, -CLIPFAR * 16);
891 
892 		glTexCoord2f((CLIPFAR) / 2 + (real_t)(ticks % 240) / 240, (CLIPFAR) / 2 + (real_t)(ticks % 240) / 240);
893 		glVertex3f(CLIPFAR * 16, 32, CLIPFAR * 16);
894 
895 		glTexCoord2f((real_t)(ticks % 240) / 240, (CLIPFAR) / 2 + (real_t)(ticks % 240) / 240);
896 		glVertex3f(-CLIPFAR * 16, 32, CLIPFAR * 16);
897 		glEnd();
898 	}
899 
900 	// setup projection
901 	glMatrixMode( GL_PROJECTION );
902 	glLoadIdentity();
903 	glViewport(camera->winx, yres - camera->winh - camera->winy, camera->winw, camera->winh);
904 	gluPerspective(fov, (real_t)camera->winw / (real_t)camera->winh, CLIPNEAR, CLIPFAR * 2);
905 	GLfloat rotx = camera->vang * 180 / PI; // get x rotation
906 	GLfloat roty = (camera->ang - 3 * PI / 2) * 180 / PI; // get y rotation
907 	GLfloat rotz = 0; // get z rotation
908 	glRotatef(rotx, 1, 0, 0); // rotate pitch
909 	glRotatef(roty, 0, 1, 0); // rotate yaw
910 	glRotatef(rotz, 0, 0, 1); // rotate roll
911 	glTranslatef(-camera->x * 32, camera->z, -camera->y * 32); // translates the scene based on camera position
912 	glMatrixMode( GL_MODELVIEW );
913 	glLoadIdentity();
914 	glEnable( GL_DEPTH_TEST );
915 	glDepthMask(GL_TRUE);
916 	if ( mode == REALCOLORS )
917 	{
918 		glEnable(GL_BLEND);
919 	}
920 	else
921 	{
922 		glDisable(GL_BLEND);
923 	}
924 
925 	// glBegin / glEnd are also moved outside,
926 	// but needs to track the texture used to "flush" current drawing before switching
927 	GLuint cur_tex = 0, new_tex = 0;
928 	glBindTexture(GL_TEXTURE_2D, 0);
929 	glBegin(GL_QUADS);
930 	for ( x = 0; x < map.width; x++ )
931 	{
932 		for ( y = 0; y < map.height; y++ )
933 		{
934 			if ( x >= (int)camera->x - 3 && x <= (int)camera->x + 3 && y >= (int)camera->y - 3 && y <= (int)camera->y + 3 )
935 			{
936 				vismap[y + x * map.height] = true;
937 			}
938 			if ( vismap[y + x * map.height] )
939 			{
940 				for ( z = 0; z < MAPLAYERS + 1; z++ )
941 				{
942 					index = z + y * MAPLAYERS + x * MAPLAYERS * map.height;
943 
944 					if ( z >= 0 && z < MAPLAYERS )
945 					{
946 						// skip "air" tiles
947 						if ( map.tiles[index] == 0 )
948 						{
949 							continue;
950 						}
951 
952 						// bind texture
953 						if ( mode == REALCOLORS )
954 						{
955 							if ( map.tiles[index] < 0 || map.tiles[index] >= numtiles )
956 							{
957 								new_tex = texid[sprites[0]->refcount];
958 								//glBindTexture(GL_TEXTURE_2D, texid[sprites[0]->refcount]);
959 							}
960 							else
961 							{
962 								new_tex = texid[tiles[map.tiles[index]]->refcount];
963 								//glBindTexture(GL_TEXTURE_2D, texid[tiles[map.tiles[index]]->refcount]);
964 							}
965 						}
966 						else
967 						{
968 							new_tex = 0;
969 							//glBindTexture(GL_TEXTURE_2D, 0);
970 						}
971 						// check if the texture has changed (flushing drawing if it's the case)
972 						if(new_tex != cur_tex)
973 						{
974 							glEnd();
975 							glBindTexture(GL_TEXTURE_2D, new_tex);
976 							cur_tex=new_tex;
977 							glBegin(GL_QUADS);
978 						}
979 
980 						// draw east wall
981 						if ( x == map.width - 1 || !map.tiles[index + MAPLAYERS * map.height] )
982 						{
983 							if ( smoothlighting && mode == REALCOLORS )
984 							{
985 								//glBegin( GL_QUADS );
986 								if ( z )
987 								{
988 									s = getLightAt(x + 1, y + 1);
989 									glColor3f(s, s, s);
990 									glTexCoord2f(0, 0);
991 									glVertex3f(x * 32 + 32, z * 32 - 16, y * 32 + 32);
992 									glTexCoord2f(0, 1);
993 									glVertex3f(x * 32 + 32, z * 32 - 48, y * 32 + 32);
994 									s = getLightAt(x + 1, y);
995 									glColor3f(s, s, s);
996 									glTexCoord2f(1, 1);
997 									glVertex3f(x * 32 + 32, z * 32 - 48, y * 32 + 0);
998 									glTexCoord2f(1, 0);
999 									glVertex3f(x * 32 + 32, z * 32 - 16, y * 32 + 0);
1000 								}
1001 								else
1002 								{
1003 									s = getLightAt(x + 1, y + 1);
1004 									glColor3f(s, s, s);
1005 									glTexCoord2f(0, 0);
1006 									glVertex3f(x * 32 + 32, z * 32 - 16, y * 32 + 32);
1007 									glColor3f(0, 0, 0);
1008 									glTexCoord2f(0, 2);
1009 									glVertex3f(x * 32 + 32, z * 32 - 48 - 32, y * 32 + 32);
1010 									s = getLightAt(x + 1, y);
1011 									glColor3f(0, 0, 0);
1012 									glTexCoord2f(1, 2);
1013 									glVertex3f(x * 32 + 32, z * 32 - 48 - 32, y * 32 + 0);
1014 									glColor3f(s, s, s);
1015 									glTexCoord2f(1, 0);
1016 									glVertex3f(x * 32 + 32, z * 32 - 16, y * 32 + 0);
1017 								}
1018 								//glEnd();
1019 							}
1020 							else
1021 							{
1022 								if ( mode == REALCOLORS )
1023 								{
1024 									if ( x < map.width - 1 )
1025 									{
1026 										s = std::min(std::max(0, lightmapSmoothed[y + (x + 1) * map.height]), 255) / 255.0;
1027 										if ( globalLightModifierActive )
1028 										{
1029 											s *= globalLightModifier;
1030 										}
1031 									}
1032 									else
1033 									{
1034 										s = .5;
1035 									}
1036 									glColor3f(s, s, s);
1037 								}
1038 								else
1039 								{
1040 									glColor4ub(0, 0, 0, 0);
1041 								}
1042 								if ( x == map.width - 1 || !map.tiles[z + y * MAPLAYERS + (x + 1)*MAPLAYERS * map.height] )
1043 								{
1044 									//glBegin( GL_QUADS );
1045 									glTexCoord2f(0, 0);
1046 									glVertex3f(x * 32 + 32, z * 32 - 16, y * 32 + 32);
1047 									glTexCoord2f(0, 1);
1048 									glVertex3f(x * 32 + 32, z * 32 - 48, y * 32 + 32);
1049 									glTexCoord2f(1, 1);
1050 									glVertex3f(x * 32 + 32, z * 32 - 48, y * 32 + 0);
1051 									glTexCoord2f(1, 0);
1052 									glVertex3f(x * 32 + 32, z * 32 - 16, y * 32 + 0);
1053 									//glEnd();
1054 								}
1055 							}
1056 						}
1057 
1058 						// draw south wall
1059 						if ( y == map.height - 1 || !map.tiles[index + MAPLAYERS] )
1060 						{
1061 							if ( smoothlighting && mode == REALCOLORS )
1062 							{
1063 								//glBegin( GL_QUADS );
1064 								if ( z )
1065 								{
1066 									s = getLightAt(x, y + 1);
1067 									glColor3f(s, s, s);
1068 									glTexCoord2f(0, 0);
1069 									glVertex3f(x * 32 + 0, z * 32 - 16, y * 32 + 32);
1070 									glTexCoord2f(0, 1);
1071 									glVertex3f(x * 32 + 0, z * 32 - 48, y * 32 + 32);
1072 									s = getLightAt(x + 1, y + 1);
1073 									glColor3f(s, s, s);
1074 									glTexCoord2f(1, 1);
1075 									glVertex3f(x * 32 + 32, z * 32 - 48, y * 32 + 32);
1076 									glTexCoord2f(1, 0);
1077 									glVertex3f(x * 32 + 32, z * 32 - 16, y * 32 + 32);
1078 								}
1079 								else
1080 								{
1081 									s = getLightAt(x, y + 1);
1082 									glColor3f(s, s, s);
1083 									glTexCoord2f(0, 0);
1084 									glVertex3f(x * 32 + 0, z * 32 - 16, y * 32 + 32);
1085 									glColor3f(0, 0, 0);
1086 									glTexCoord2f(0, 2);
1087 									glVertex3f(x * 32 + 0, z * 32 - 48 - 32, y * 32 + 32);
1088 									s = getLightAt(x + 1, y + 1);
1089 									glColor3f(0, 0, 0);
1090 									glTexCoord2f(1, 2);
1091 									glVertex3f(x * 32 + 32, z * 32 - 48 - 32, y * 32 + 32);
1092 									glColor3f(s, s, s);
1093 									glTexCoord2f(1, 0);
1094 									glVertex3f(x * 32 + 32, z * 32 - 16, y * 32 + 32);
1095 								}
1096 								//glEnd();
1097 							}
1098 							else
1099 							{
1100 								if ( mode == REALCOLORS )
1101 								{
1102 									if ( y < map.height - 1 )
1103 									{
1104 										s = std::min(std::max(0, lightmapSmoothed[(y + 1) + x * map.height]), 255) / 255.0;
1105 										if ( globalLightModifierActive )
1106 										{
1107 											s *= globalLightModifier;
1108 										}
1109 									}
1110 									else
1111 									{
1112 										s = .5;
1113 									}
1114 									glColor3f(s, s, s);
1115 								}
1116 								if ( y == map.height - 1 || !map.tiles[z + (y + 1)*MAPLAYERS + x * MAPLAYERS * map.height] )
1117 								{
1118 									//glBegin( GL_QUADS );
1119 									glTexCoord2f(0, 0);
1120 									glVertex3f(x * 32 + 0, z * 32 - 16, y * 32 + 32);
1121 									glTexCoord2f(0, 1);
1122 									glVertex3f(x * 32 + 0, z * 32 - 48, y * 32 + 32);
1123 									glTexCoord2f(1, 1);
1124 									glVertex3f(x * 32 + 32, z * 32 - 48, y * 32 + 32);
1125 									glTexCoord2f(1, 0);
1126 									glVertex3f(x * 32 + 32, z * 32 - 16, y * 32 + 32);
1127 									//glEnd();
1128 								}
1129 							}
1130 						}
1131 
1132 						// draw west wall
1133 						if ( x == 0 || !map.tiles[index - MAPLAYERS * map.height] )
1134 						{
1135 							if ( smoothlighting && mode == REALCOLORS )
1136 							{
1137 								//glBegin( GL_QUADS );
1138 								if ( z )
1139 								{
1140 									s = getLightAt(x, y);
1141 									glColor3f(s, s, s);
1142 									glTexCoord2f(0, 0);
1143 									glVertex3f(x * 32 + 0, z * 32 - 16, y * 32 + 0);
1144 									glTexCoord2f(0, 1);
1145 									glVertex3f(x * 32 + 0, z * 32 - 48, y * 32 + 0);
1146 									s = getLightAt(x, y + 1);
1147 									glColor3f(s, s, s);
1148 									glTexCoord2f(1, 1);
1149 									glVertex3f(x * 32 + 0, z * 32 - 48, y * 32 + 32);
1150 									glTexCoord2f(1, 0);
1151 									glVertex3f(x * 32 + 0, z * 32 - 16, y * 32 + 32);
1152 								}
1153 								else
1154 								{
1155 									s = getLightAt(x, y);
1156 									glColor3f(s, s, s);
1157 									glTexCoord2f(0, 0);
1158 									glVertex3f(x * 32 + 0, z * 32 - 16, y * 32 + 0);
1159 									glColor3f(0, 0, 0);
1160 									glTexCoord2f(0, 2);
1161 									glVertex3f(x * 32 + 0, z * 32 - 48 - 32, y * 32 + 0);
1162 									s = getLightAt(x, y + 1);
1163 									glColor3f(0, 0, 0);
1164 									glTexCoord2f(1, 2);
1165 									glVertex3f(x * 32 + 0, z * 32 - 48 - 32, y * 32 + 32);
1166 									glColor3f(s, s, s);
1167 									glTexCoord2f(1, 0);
1168 									glVertex3f(x * 32 + 0, z * 32 - 16, y * 32 + 32);
1169 								}
1170 								//glEnd();
1171 							}
1172 							else
1173 							{
1174 								if ( mode == REALCOLORS )
1175 								{
1176 									if ( x > 0 )
1177 									{
1178 										s = std::min(std::max(0, lightmapSmoothed[y + (x - 1) * map.height]), 255) / 255.0;
1179 										if ( globalLightModifierActive )
1180 										{
1181 											s *= globalLightModifier;
1182 										}
1183 									}
1184 									else
1185 									{
1186 										s = .5;
1187 									}
1188 									glColor3f(s, s, s);
1189 								}
1190 								if ( x == 0 || !map.tiles[z + y * MAPLAYERS + (x - 1)*MAPLAYERS * map.height] )
1191 								{
1192 									//glBegin( GL_QUADS );
1193 									glTexCoord2f(0, 0);
1194 									glVertex3f(x * 32 + 0, z * 32 - 16, y * 32 + 0);
1195 									glTexCoord2f(0, 1);
1196 									glVertex3f(x * 32 + 0, z * 32 - 48, y * 32 + 0);
1197 									glTexCoord2f(1, 1);
1198 									glVertex3f(x * 32 + 0, z * 32 - 48, y * 32 + 32);
1199 									glTexCoord2f(1, 0);
1200 									glVertex3f(x * 32 + 0, z * 32 - 16, y * 32 + 32);
1201 									//glEnd();
1202 								}
1203 							}
1204 						}
1205 
1206 						// draw north wall
1207 						if ( y == 0 || !map.tiles[index - MAPLAYERS] )
1208 						{
1209 							if ( smoothlighting && mode == REALCOLORS )
1210 							{
1211 								//glBegin( GL_QUADS );
1212 								if ( z )
1213 								{
1214 									s = getLightAt(x + 1, y);
1215 									glColor3f(s, s, s);
1216 									glTexCoord2f(0, 0);
1217 									glVertex3f(x * 32 + 32, z * 32 - 16, y * 32 + 0);
1218 									glTexCoord2f(0, 1);
1219 									glVertex3f(x * 32 + 32, z * 32 - 48, y * 32 + 0);
1220 									s = getLightAt(x, y);
1221 									glColor3f(s, s, s);
1222 									glTexCoord2f(1, 1);
1223 									glVertex3f(x * 32 + 0, z * 32 - 48, y * 32 + 0);
1224 									glTexCoord2f(1, 0);
1225 									glVertex3f(x * 32 + 0, z * 32 - 16, y * 32 + 0);
1226 								}
1227 								else
1228 								{
1229 									s = getLightAt(x + 1, y);
1230 									glColor3f(s, s, s);
1231 									glTexCoord2f(0, 0);
1232 									glVertex3f(x * 32 + 32, z * 32 - 16, y * 32 + 0);
1233 									glColor3f(0, 0, 0);
1234 									glTexCoord2f(0, 2);
1235 									glVertex3f(x * 32 + 32, z * 32 - 48 - 32, y * 32 + 0);
1236 									s = getLightAt(x, y);
1237 									glColor3f(0, 0, 0);
1238 									glTexCoord2f(1, 2);
1239 									glVertex3f(x * 32 + 0, z * 32 - 48 - 32, y * 32 + 0);
1240 									glColor3f(s, s, s);
1241 									glTexCoord2f(1, 0);
1242 									glVertex3f(x * 32 + 0, z * 32 - 16, y * 32 + 0);
1243 								}
1244 								//glEnd();
1245 							}
1246 							else
1247 							{
1248 								if ( mode == REALCOLORS )
1249 								{
1250 									if ( y > 0 )
1251 									{
1252 										s = std::min(std::max(0, lightmapSmoothed[(y - 1) + x * map.height]), 255) / 255.0;
1253 										if ( globalLightModifierActive )
1254 										{
1255 											s *= globalLightModifier;
1256 										}
1257 									}
1258 									else
1259 									{
1260 										s = .5;
1261 									}
1262 									glColor3f(s, s, s);
1263 								}
1264 								if ( y == 0 || !map.tiles[z + (y - 1)*MAPLAYERS + x * MAPLAYERS * map.height] )
1265 								{
1266 									//glBegin( GL_QUADS );
1267 									glTexCoord2f(0, 0);
1268 									glVertex3f(x * 32 + 32, z * 32 - 16, y * 32 + 0);
1269 									glTexCoord2f(0, 1);
1270 									glVertex3f(x * 32 + 32, z * 32 - 48, y * 32 + 0);
1271 									glTexCoord2f(1, 1);
1272 									glVertex3f(x * 32 + 0, z * 32 - 48, y * 32 + 0);
1273 									glTexCoord2f(1, 0);
1274 									glVertex3f(x * 32 + 0, z * 32 - 16, y * 32 + 0);
1275 									//glEnd();
1276 								}
1277 							}
1278 						}
1279 					}
1280 					else
1281 					{
1282 						// bind texture
1283 						if ( mode == REALCOLORS )
1284 						{
1285 							new_tex = texid[tiles[mapceilingtile]->refcount];
1286 							//glBindTexture(GL_TEXTURE_2D, texid[tiles[50]->refcount]); // rock tile
1287 							if (cur_tex!=new_tex)
1288 							{
1289 								glEnd();
1290 								cur_tex = new_tex;
1291 								glBindTexture(GL_TEXTURE_2D, new_tex);
1292 								glBegin(GL_QUADS);
1293 							}
1294 						}
1295 						else
1296 						{
1297 							continue;
1298 						}
1299 					}
1300 
1301 					if ( smoothlighting && mode == REALCOLORS )
1302 					{
1303 						// draw floor
1304 						if ( z < OBSTACLELAYER )
1305 						{
1306 							if ( !map.tiles[index + 1] )
1307 							{
1308 								//glBegin( GL_QUADS );
1309 								s = getLightAt(x, y);
1310 								glColor3f(s, s, s);
1311 								glTexCoord2f(0, 0);
1312 								glVertex3f(x * 32 + 0, -16 - 32 * abs(z), y * 32 + 0);
1313 								s = getLightAt(x, y + 1);
1314 								glColor3f(s, s, s);
1315 								glTexCoord2f(0, 1);
1316 								glVertex3f(x * 32 + 0, -16 - 32 * abs(z), y * 32 + 32);
1317 								s = getLightAt(x + 1, y + 1);
1318 								glColor3f(s, s, s);
1319 								glTexCoord2f(1, 1);
1320 								glVertex3f(x * 32 + 32, -16 - 32 * abs(z), y * 32 + 32);
1321 								s = getLightAt(x + 1, y);
1322 								glColor3f(s, s, s);
1323 								glTexCoord2f(1, 0);
1324 								glVertex3f(x * 32 + 32, -16 - 32 * abs(z), y * 32 + 0);
1325 								//glEnd();
1326 							}
1327 						}
1328 
1329 						// draw ceiling
1330 						else if ( z > OBSTACLELAYER && (!clouds || z < MAPLAYERS) )
1331 						{
1332 							if ( !map.tiles[index - 1] )
1333 							{
1334 								//glBegin( GL_QUADS );
1335 								s = getLightAt(x, y);
1336 								glColor3f(s, s, s);
1337 								glTexCoord2f(0, 0);
1338 								glVertex3f(x * 32 + 0, 16 + 32 * abs(z - 2), y * 32 + 0);
1339 								s = getLightAt(x + 1, y);
1340 								glColor3f(s, s, s);
1341 								glTexCoord2f(1, 0);
1342 								glVertex3f(x * 32 + 32, 16 + 32 * abs(z - 2), y * 32 + 0);
1343 								s = getLightAt(x + 1, y + 1);
1344 								glColor3f(s, s, s);
1345 								glTexCoord2f(1, 1);
1346 								glVertex3f(x * 32 + 32, 16 + 32 * abs(z - 2), y * 32 + 32);
1347 								s = getLightAt(x, y + 1);
1348 								glColor3f(s, s, s);
1349 								glTexCoord2f(0, 1);
1350 								glVertex3f(x * 32 + 0, 16 + 32 * abs(z - 2), y * 32 + 32);
1351 								//glEnd();
1352 							}
1353 						}
1354 					}
1355 					else
1356 					{
1357 						// unsmooth lighting
1358 						if ( mode == REALCOLORS )
1359 						{
1360 							s = std::min(std::max(0, lightmapSmoothed[y + x * map.height]), 255) / 255.0;
1361 							glColor3f(s, s, s);
1362 						}
1363 
1364 						// draw floor
1365 						if ( z < OBSTACLELAYER )
1366 						{
1367 							if ( !map.tiles[index + 1] )
1368 							{
1369 								//glBegin( GL_QUADS );
1370 								glTexCoord2f(0, 0);
1371 								glVertex3f(x * 32 + 0, -16 - 32 * abs(z), y * 32 + 0);
1372 								glTexCoord2f(0, 1);
1373 								glVertex3f(x * 32 + 0, -16 - 32 * abs(z), y * 32 + 32);
1374 								glTexCoord2f(1, 1);
1375 								glVertex3f(x * 32 + 32, -16 - 32 * abs(z), y * 32 + 32);
1376 								glTexCoord2f(1, 0);
1377 								glVertex3f(x * 32 + 32, -16 - 32 * abs(z), y * 32 + 0);
1378 								//glEnd();
1379 							}
1380 						}
1381 
1382 						// draw ceiling
1383 						else if ( z > OBSTACLELAYER )
1384 						{
1385 							if ( !map.tiles[index - 1] )
1386 							{
1387 								//glBegin( GL_QUADS );
1388 								glTexCoord2f(0, 0);
1389 								glVertex3f(x * 32 + 0, 16 + 32 * abs(z - 2), y * 32 + 0);
1390 								glTexCoord2f(1, 0);
1391 								glVertex3f(x * 32 + 32, 16 + 32 * abs(z - 2), y * 32 + 0);
1392 								glTexCoord2f(1, 1);
1393 								glVertex3f(x * 32 + 32, 16 + 32 * abs(z - 2), y * 32 + 32);
1394 								glTexCoord2f(0, 1);
1395 								glVertex3f(x * 32 + 0, 16 + 32 * abs(z - 2), y * 32 + 32);
1396 								//glEnd();
1397 							}
1398 						}
1399 					}
1400 				}
1401 			}
1402 		}
1403 	}
1404 	glEnd();
1405 
1406 	glDisable(GL_SCISSOR_TEST);
1407 	glScissor(0, 0, xres, yres);
1408 }
1409 
1410 /*GLuint create_shader(const char* filename, GLenum type)
1411 {
1412 	FILE* input = fopen(filename, "rb");
1413 	if( !input ) {
1414 		printlog("Couldn't open shader file \"%s\"", filename);
1415 		return 0;
1416 		//TODO: Error.
1417 	}
1418 	fclose(input);
1419 	const GLchar* source=NULL;
1420 	if (source == NULL) {
1421 		printlog("Error opening %s: ", filename); perror("");
1422 		return 0;
1423 	}
1424 	GLuint res = glCreateShader(type);
1425 	const GLchar* sources[2] = {
1426 #ifdef GL_ES_VERSION_2_0
1427 	"#version 100\n"
1428 	"#define GLES2\n",
1429 #else
1430 	"#version 120\n",
1431 #endif
1432 	source };
1433 	glShaderSource(res, 2, sources, NULL);
1434 	free((void*)source);
1435 
1436 	glCompileShader(res);
1437 	GLint compile_ok = GL_FALSE;
1438 	glGetShaderiv(res, GL_COMPILE_STATUS, &compile_ok);
1439 	if (compile_ok == GL_FALSE) {
1440 		printlog("%s:", filename);
1441 		glDeleteShader(res);
1442 		return 0;
1443 	}
1444 
1445 	return res;
1446 }
1447 */
1448 
1449 static int dirty = 1;
1450 static int oldx = 0, oldy = 0;
1451 static unsigned int oldpix = 0;
1452 
GO_GetPixelU32(int x,int y,view_t & camera)1453 unsigned int GO_GetPixelU32(int x, int y, view_t& camera)
1454 {
1455 	if(!dirty && (oldx==x) && (oldy==y))
1456 		return oldpix;
1457 
1458 	if(dirty) {
1459 #ifdef PANDORA
1460 		// Pandora fbo
1461 		if((xres==800) && (yres==480)) {
1462 			glBindFramebuffer(GL_FRAMEBUFFER, fbo_fbo);
1463 		}
1464 #endif
1465 		// generate object buffer
1466 		glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
1467 		glDrawWorld(&camera, ENTITYUIDS);
1468 		drawEntities3D(&camera, ENTITYUIDS);
1469 	}
1470 
1471 	GLubyte pixel[4];
1472 	glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)pixel);
1473 	oldpix = pixel[0] + (((Uint32)pixel[1]) << 8) + (((Uint32)pixel[2]) << 16) + (((Uint32)pixel[3]) << 24);
1474 #ifdef PANDORA
1475 	if((dirty) && (xres==800) && (yres==480)) {
1476 		glBindFramebuffer(GL_FRAMEBUFFER, 0);
1477 	}
1478 #endif
1479 	dirty = 0;
1480 	return oldpix;
1481 }
1482 
GO_SwapBuffers(SDL_Window * screen)1483 void GO_SwapBuffers(SDL_Window* screen)
1484 {
1485 	dirty = 1;
1486 #ifdef PANDORA
1487 	bool bBlit = !(xres==800 && yres==480);
1488 
1489 	int vp_old[4];
1490 	if(bBlit) {
1491 		glBindFramebuffer(GL_FRAMEBUFFER, 0);
1492 		glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
1493 		glGetIntegerv(GL_VIEWPORT, vp_old);
1494 		glViewport(0, 0, 800, 480);
1495 		glMatrixMode( GL_PROJECTION );
1496 		glLoadIdentity();
1497 		glOrtho(0, 800, 480, 0, 1, -1);
1498 		glMatrixMode( GL_MODELVIEW );
1499 		glLoadIdentity();
1500 
1501 		glDisable(GL_BLEND);
1502 		glDisable(GL_ALPHA_TEST);
1503 		glDisable(GL_DEPTH_TEST);
1504 		glDisable(GL_LIGHTING);
1505 
1506 		glBindTexture(GL_TEXTURE_2D, fbo_tex);
1507 		glColor4f(1,1,1,1);
1508 
1509 		glBegin(GL_QUADS);
1510 		 glTexCoord2f(0,yres/1024.0f); glVertex2f(0,0);
1511 		 glTexCoord2f(0, 0); glVertex2f(0,480);
1512 		 glTexCoord2f(xres/1024.0f, 0); glVertex2f(800,480);
1513 		 glTexCoord2f(xres/1024.0f, yres/1024.0f); glVertex2f(800,0);
1514 		glEnd();
1515 
1516 		glBindTexture(GL_TEXTURE_2D, 0);
1517 	}
1518 #endif
1519 #ifdef APPLE
1520 	SDL_RenderPresent(renderer);
1521 #else
1522 	SDL_GL_SwapWindow(screen);
1523 #endif
1524 #ifdef PANDORA
1525 	if(bBlit) {
1526 		glBindFramebuffer(GL_FRAMEBUFFER, fbo_fbo);
1527 		glViewport(vp_old[0], vp_old[1], vp_old[2], vp_old[3]);
1528 	}
1529 #endif
1530 }
1531