1 #include "Renderer.h"
2 
3 #include <cmath>
4 #include <iostream>
5 #include <iomanip>
6 #include <vector>
7 #include <cstdio>
8 #include <cstdlib>
9 #include "Config.h"
10 #include "Misc.h"
11 
12 #include "common/tpt-rand.h"
13 #include "common/tpt-compat.h"
14 
15 #include "gui/game/RenderPreset.h"
16 
17 #include "simulation/Simulation.h"
18 #include "simulation/ElementGraphics.h"
19 #include "simulation/Air.h"
20 #include "simulation/Gravity.h"
21 #include "simulation/ElementClasses.h"
22 
23 #ifdef LUACONSOLE
24 #include "lua/LuaScriptInterface.h"
25 #include "lua/LuaScriptHelper.h"
26 #include "lua/LuaSmartRef.h"
27 #endif
28 #include "hmap.h"
29 #ifdef OGLR
30 #include "Shaders.h"
31 #endif
32 
33 #ifndef OGLI
34 #define VIDXRES WINDOWW
35 #define VIDYRES WINDOWH
36 #else
37 #define VIDXRES XRES
38 #define VIDYRES YRES
39 #endif
40 
41 
RenderBegin()42 void Renderer::RenderBegin()
43 {
44 #ifdef OGLI
45 #ifdef OGLR
46 	draw_air();
47 	draw_grav();
48 	DrawWalls();
49 	render_parts();
50 	render_fire();
51 	draw_other();
52 	draw_grav_zones();
53 	DrawSigns();
54 
55 	glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFbo);
56 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo);
57 	glTranslated(0, MENUSIZE, 0);
58 #else
59 	if(display_mode & DISPLAY_PERS)
60 	{
61 		std::copy(persistentVid, persistentVid+(VIDXRES*YRES), vid);
62 	}
63 	pixel * oldVid;
64 	if(display_mode & DISPLAY_WARP)
65 	{
66 		oldVid = vid;
67 		vid = warpVid;
68 		std::fill(warpVid, warpVid+(VIDXRES*VIDYRES), 0);
69 	}
70 
71 	draw_air();
72 	draw_grav();
73 	DrawWalls();
74 	render_parts();
75 	if(display_mode & DISPLAY_PERS)
76 	{
77 		int i,r,g,b;
78 		for (i = 0; i < VIDXRES*YRES; i++)
79 		{
80 			r = PIXR(vid[i]);
81 			g = PIXG(vid[i]);
82 			b = PIXB(vid[i]);
83 			if (r>0)
84 				r--;
85 			if (g>0)
86 				g--;
87 			if (b>0)
88 				b--;
89 			persistentVid[i] = PIXRGB(r,g,b);
90 		}
91 	}
92 
93 	render_fire();
94 	draw_other();
95 	draw_grav_zones();
96 	DrawSigns();
97 	if(display_mode & DISPLAY_WARP)
98 	{
99 		vid = oldVid;
100 	}
101 #endif
102 #else
103 	if(display_mode & DISPLAY_PERS)
104 	{
105 		std::copy(persistentVid, persistentVid+(VIDXRES*YRES), vid);
106 	}
107 	pixel * oldVid = NULL;
108 	if(display_mode & DISPLAY_WARP)
109 	{
110 		oldVid = vid;
111 		vid = warpVid;
112 		std::fill(warpVid, warpVid+(VIDXRES*VIDYRES), 0);
113 	}
114 
115 	draw_air();
116 	draw_grav();
117 	DrawWalls();
118 	render_parts();
119 	if(display_mode & DISPLAY_PERS)
120 	{
121 		int i,r,g,b;
122 		for (i = 0; i < VIDXRES*YRES; i++)
123 		{
124 			r = PIXR(vid[i]);
125 			g = PIXG(vid[i]);
126 			b = PIXB(vid[i]);
127 			if (r>0)
128 				r--;
129 			if (g>0)
130 				g--;
131 			if (b>0)
132 				b--;
133 			persistentVid[i] = PIXRGB(r,g,b);
134 		}
135 	}
136 
137 	render_fire();
138 	draw_other();
139 	draw_grav_zones();
140 	DrawSigns();
141 
142 	if(display_mode & DISPLAY_WARP)
143 	{
144 		vid = oldVid;
145 	}
146 
147 	FinaliseParts();
148 #endif
149 }
150 
RenderEnd()151 void Renderer::RenderEnd()
152 {
153 #ifdef OGLI
154 #ifdef OGLR
155 	glTranslated(0, -MENUSIZE, 0);
156 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFbo);
157 	FinaliseParts();
158 	RenderZoom();
159 #else
160 	RenderZoom();
161 	FinaliseParts();
162 #endif
163 #else
164 	RenderZoom();
165 #endif
166 }
167 
SetSample(int x,int y)168 void Renderer::SetSample(int x, int y)
169 {
170 	sampleColor = GetPixel(x, y);
171 }
172 
clearScreen(float alpha)173 void Renderer::clearScreen(float alpha)
174 {
175 #ifdef OGLR
176 	GLint prevFbo;
177 	if(alpha > 0.999f)
178 	{
179 		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
180 		glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFbo);
181 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo);
182 		glClear(GL_COLOR_BUFFER_BIT);
183 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFbo);
184 	}
185 	else
186 	{
187 		glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
188 		glColor4f(1.0f, 1.0f, 1.0f, alpha);
189 		glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFbo);
190 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo);
191 		glBegin(GL_QUADS);
192 		glVertex2f(0, 0);
193 		glVertex2f(XRES, 0);
194 		glVertex2f(XRES, YRES);
195 		glVertex2f(0, YRES);
196 		glEnd();
197 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFbo);
198 		glBlendEquation(GL_FUNC_ADD);
199 	}
200 	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
201 	glClear(GL_COLOR_BUFFER_BIT);
202 #endif
203 #ifdef OGLI
204 #ifndef OGLR
205 	std::fill(vid, vid+(VIDXRES*VIDYRES), 0);
206 #endif
207 #else
208 	g->Clear();
209 #endif
210 }
211 #ifdef OGLR
checkShader(GLuint shader,const char * shname)212 void Renderer::checkShader(GLuint shader, const char * shname)
213 {
214 	GLint status;
215 	glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
216 	if (status == GL_FALSE)
217 	{
218 		char errorBuf[ GL_INFO_LOG_LENGTH];
219 		int errLen;
220 		glGetShaderInfoLog(shader, GL_INFO_LOG_LENGTH, &errLen, errorBuf);
221 		fprintf(stderr, "Failed to compile %s shader:\n%s\n", shname, errorBuf);
222 		exit(1);
223 	}
224 }
checkProgram(GLuint program,const char * progname)225 void Renderer::checkProgram(GLuint program, const char * progname)
226 {
227 	GLint status;
228 	glGetProgramiv(program, GL_LINK_STATUS, &status);
229 	if (status == GL_FALSE)
230 	{
231 		char errorBuf[ GL_INFO_LOG_LENGTH];
232 		int errLen;
233 		glGetShaderInfoLog(program, GL_INFO_LOG_LENGTH, &errLen, errorBuf);
234 		fprintf(stderr, "Failed to link %s program:\n%s\n", progname, errorBuf);
235 		exit(1);
236 	}
237 }
loadShaders()238 void Renderer::loadShaders()
239 {
240 	GLuint vertexShader, fragmentShader;
241 
242 	//Particle texture
243 	vertexShader = glCreateShader(GL_VERTEX_SHADER);
244 	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
245 
246 	glShaderSource( vertexShader, 1, &fireVertex, NULL);
247 	glShaderSource( fragmentShader, 1, &fireFragment, NULL);
248 
249 	glCompileShader( vertexShader );
250 	checkShader(vertexShader, "FV");
251 	glCompileShader( fragmentShader );
252 	checkShader(fragmentShader, "FF");
253 
254 	fireProg = glCreateProgram();
255 	glAttachShader( fireProg, vertexShader );
256 	glAttachShader( fireProg, fragmentShader );
257 	glLinkProgram( fireProg );
258 	checkProgram(fireProg, "F");
259 
260 	//Lensing
261 	vertexShader = glCreateShader(GL_VERTEX_SHADER);
262 	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
263 
264 	glShaderSource( vertexShader, 1, &lensVertex, NULL);
265 	glShaderSource( fragmentShader, 1, &lensFragment, NULL);
266 
267 	glCompileShader( vertexShader );
268 	checkShader(vertexShader, "LV");
269 	glCompileShader( fragmentShader );
270 	checkShader(fragmentShader, "LF");
271 
272 	lensProg = glCreateProgram();
273 	glAttachShader( lensProg, vertexShader );
274 	glAttachShader( lensProg, fragmentShader );
275 	glLinkProgram( lensProg );
276 	checkProgram(lensProg, "L");
277 
278 	//Air Velocity
279 	vertexShader = glCreateShader(GL_VERTEX_SHADER);
280 	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
281 
282 	glShaderSource( vertexShader, 1, &airVVertex, NULL);
283 	glShaderSource( fragmentShader, 1, &airVFragment, NULL);
284 
285 	glCompileShader( vertexShader );
286 	checkShader(vertexShader, "AVX");
287 	glCompileShader( fragmentShader );
288 	checkShader(fragmentShader, "AVF");
289 
290 	airProg_Velocity = glCreateProgram();
291 	glAttachShader( airProg_Velocity, vertexShader );
292 	glAttachShader( airProg_Velocity, fragmentShader );
293 	glLinkProgram( airProg_Velocity );
294 	checkProgram(airProg_Velocity, "AV");
295 
296 	//Air Pressure
297 	vertexShader = glCreateShader(GL_VERTEX_SHADER);
298 	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
299 
300 	glShaderSource( vertexShader, 1, &airPVertex, NULL);
301 	glShaderSource( fragmentShader, 1, &airPFragment, NULL);
302 
303 	glCompileShader( vertexShader );
304 	checkShader(vertexShader, "APV");
305 	glCompileShader( fragmentShader );
306 	checkShader(fragmentShader, "APF");
307 
308 	airProg_Pressure = glCreateProgram();
309 	glAttachShader( airProg_Pressure, vertexShader );
310 	glAttachShader( airProg_Pressure, fragmentShader );
311 	glLinkProgram( airProg_Pressure );
312 	checkProgram(airProg_Pressure, "AP");
313 
314 	//Air cracker
315 	vertexShader = glCreateShader(GL_VERTEX_SHADER);
316 	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
317 
318 	glShaderSource( vertexShader, 1, &airCVertex, NULL);
319 	glShaderSource( fragmentShader, 1, &airCFragment, NULL);
320 
321 	glCompileShader( vertexShader );
322 	checkShader(vertexShader, "ACV");
323 	glCompileShader( fragmentShader );
324 	checkShader(fragmentShader, "ACF");
325 
326 	airProg_Cracker = glCreateProgram();
327 	glAttachShader( airProg_Cracker, vertexShader );
328 	glAttachShader( airProg_Cracker, fragmentShader );
329 	glLinkProgram( airProg_Cracker );
330 	checkProgram(airProg_Cracker, "AC");
331 }
332 #endif
333 
FinaliseParts()334 void Renderer::FinaliseParts()
335 {
336 #ifdef OGLR
337 	glEnable( GL_TEXTURE_2D );
338 	if(display_mode & DISPLAY_WARP)
339 	{
340 		float xres = XRES, yres = YRES;
341 		glUseProgram(lensProg);
342 		glActiveTexture(GL_TEXTURE0);
343 		glBindTexture(GL_TEXTURE_2D, partsFboTex);
344 		glUniform1i(glGetUniformLocation(lensProg, "pTex"), 0);
345 		glActiveTexture(GL_TEXTURE1);
346 		glBindTexture(GL_TEXTURE_2D, partsTFX);
347 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, XRES/CELL, YRES/CELL, GL_RED, GL_FLOAT, sim->gravx);
348 		glUniform1i(glGetUniformLocation(lensProg, "tfX"), 1);
349 		glActiveTexture(GL_TEXTURE2);
350 		glBindTexture(GL_TEXTURE_2D, partsTFY);
351 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, XRES/CELL, YRES/CELL, GL_GREEN, GL_FLOAT, sim->gravy);
352 		glUniform1i(glGetUniformLocation(lensProg, "tfY"), 2);
353 		glActiveTexture(GL_TEXTURE0);
354 		glUniform1fv(glGetUniformLocation(lensProg, "xres"), 1, &xres);
355 		glUniform1fv(glGetUniformLocation(lensProg, "yres"), 1, &yres);
356 	}
357 	else
358 	{
359 		glBindTexture(GL_TEXTURE_2D, partsFboTex);
360 		glBlendFunc(GL_ONE, GL_ONE);
361 	}
362 
363 	int sdl_scale = 1;
364 	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
365 	glBegin(GL_QUADS);
366 	glTexCoord2d(1, 0);
367 	//glVertex3f(XRES*sdl_scale, WINDOWH*sdl_scale, 1.0);
368 	glVertex3f(XRES*sdl_scale, YRES*sdl_scale, 1.0);
369 	glTexCoord2d(0, 0);
370 	//glVertex3f(0, WINDOWH*sdl_scale, 1.0);
371 	glVertex3f(0, YRES*sdl_scale, 1.0);
372 	glTexCoord2d(0, 1);
373 	//glVertex3f(0, MENUSIZE*sdl_scale, 1.0);
374 	glVertex3f(0, 0, 1.0);
375 	glTexCoord2d(1, 1);
376 	//glVertex3f(XRES*sdl_scale, MENUSIZE*sdl_scale, 1.0);
377 	glVertex3f(XRES*sdl_scale, 0, 1.0);
378 	glEnd();
379 
380 	if(display_mode & DISPLAY_WARP)
381 	{
382 		glUseProgram(0);
383 
384 	}
385 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
386 	glDisable( GL_TEXTURE_2D );
387 #endif
388 
389 #if defined(OGLI) && !defined(OGLR)
390 	if(display_mode & DISPLAY_WARP)
391 	{
392 		render_gravlensing(warpVid);
393 	}
394 	g->draw_image(vid, 0, 0, VIDXRES, VIDYRES, 255);
395 #endif
396 
397 #if !defined(OGLR) && !defined(OGLI)
398 	if(display_mode & DISPLAY_WARP)
399 	{
400 		render_gravlensing(warpVid);
401 	}
402 #endif
403 }
404 
RenderZoom()405 void Renderer::RenderZoom()
406 {
407 	if(!zoomEnabled)
408 		return;
409 	#if defined(OGLR)
410 		int sdl_scale = 1;
411 		int origBlendSrc, origBlendDst;
412 		float zcx1, zcx0, zcy1, zcy0, yfactor, xfactor, i; //X-Factor is shit, btw
413 		xfactor = 1.0f/(float)XRES;
414 		yfactor = 1.0f/(float)YRES;
415 		yfactor*=-1.0f;
416 
417 		zcx1 = (zoomScopePosition.X)*xfactor;
418 		zcx0 = (zoomScopePosition.X+zoomScopeSize)*xfactor;
419 		zcy1 = (zoomScopePosition.Y-1)*yfactor;
420 		zcy0 = ((zoomScopePosition.Y-1+zoomScopeSize))*yfactor;
421 
422 		glGetIntegerv(GL_BLEND_SRC, &origBlendSrc);
423 		glGetIntegerv(GL_BLEND_DST, &origBlendDst);
424 		glBlendFunc(GL_ONE, GL_ZERO);
425 
426 		glEnable( GL_TEXTURE_2D );
427 		//glReadBuffer(GL_AUX0);
428 		glBindTexture(GL_TEXTURE_2D, partsFboTex);
429 
430 		//Draw zoomed texture
431 		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
432 		glBegin(GL_QUADS);
433 		glTexCoord2d(zcx1, zcy1);
434 		glVertex2i(zoomWindowPosition.X, zoomWindowPosition.Y);
435 		glTexCoord2d(zcx0, zcy1);
436 		glVertex2i(zoomWindowPosition.X+(zoomScopeSize*ZFACTOR), zoomWindowPosition.Y);
437 		glTexCoord2d(zcx0, zcy0);
438 		glVertex2i(zoomWindowPosition.X+(zoomScopeSize*ZFACTOR), zoomWindowPosition.Y+(zoomScopeSize*ZFACTOR));
439 		glTexCoord2d(zcx1, zcy0);
440 		glVertex2i(zoomWindowPosition.X, zoomWindowPosition.Y+(zoomScopeSize*ZFACTOR));
441 		glEnd();
442 		glBindTexture(GL_TEXTURE_2D, 0);
443 		glDisable( GL_TEXTURE_2D );
444 
445 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
446 
447 		//Lines to make the pixels stand out
448 		glLineWidth(sdl_scale);
449 		//glEnable(GL_LINE_SMOOTH);
450 		glBegin(GL_LINES);
451 		glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
452 		for(i = 0; i < zoomScopeSize; i++)
453 		{
454 			//Across
455 			glVertex2i(zoomWindowPosition.X, zoomWindowPosition.Y+(i*ZFACTOR));
456 			glVertex2i(zoomWindowPosition.X+(zoomScopeSize*ZFACTOR), zoomWindowPosition.Y+(i*ZFACTOR));
457 
458 			//Down
459 			glVertex2i(zoomWindowPosition.X+(i*ZFACTOR), zoomWindowPosition.Y);
460 			glVertex2i(zoomWindowPosition.X+(i*ZFACTOR), zoomWindowPosition.Y+(zoomScopeSize*ZFACTOR));
461 		}
462 		glEnd();
463 
464 		//Draw zoom window border
465 		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
466 		glBegin(GL_LINE_LOOP);
467 		glVertex2i(zoomWindowPosition.X, zoomWindowPosition.Y);
468 		glVertex2i(zoomWindowPosition.X+(zoomScopeSize*ZFACTOR), zoomWindowPosition.Y);
469 		glVertex2i(zoomWindowPosition.X+(zoomScopeSize*ZFACTOR), zoomWindowPosition.Y+(zoomScopeSize*ZFACTOR));
470 		glVertex2i(zoomWindowPosition.X, zoomWindowPosition.Y+(zoomScopeSize*ZFACTOR));
471 		glEnd();
472 		//glDisable(GL_LINE_SMOOTH);
473 
474 		if(zoomEnabled)
475 		{
476 			glEnable(GL_COLOR_LOGIC_OP);
477 			//glEnable(GL_LINE_SMOOTH);
478 			glLogicOp(GL_XOR);
479 			glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
480 			glBegin(GL_LINE_LOOP);
481 			glVertex2i(zoomScopePosition.X, zoomScopePosition.Y);
482 			glVertex2i(zoomScopePosition.X+zoomScopeSize, zoomScopePosition.Y);
483 			glVertex2i(zoomScopePosition.X+zoomScopeSize, zoomScopePosition.Y+zoomScopeSize);
484 			glVertex2i(zoomScopePosition.X, zoomScopePosition.Y+zoomScopeSize);
485 			/*glVertex3i((zoomScopePosition.X-1)*sdl_scale, (WINDOWH-(zoomScopePosition.Y-1))*sdl_scale, 0);
486 			glVertex3i((zoomScopePosition.X-1)*sdl_scale, (WINDOWH-(zoomScopePosition.Y+zoomScopeSize))*sdl_scale, 0);
487 			glVertex3i((zoomScopePosition.X+zoomScopeSize)*sdl_scale, (WINDOWH-(zoomScopePosition.Y+zoomScopeSize))*sdl_scale, 0);
488 			glVertex3i((zoomScopePosition.X+zoomScopeSize)*sdl_scale, (WINDOWH-(zoomScopePosition.Y-1))*sdl_scale, 0);
489 			glVertex3i((zoomScopePosition.X-1)*sdl_scale, (WINDOWH-(zoomScopePosition.Y-1))*sdl_scale, 0);*/
490 			glEnd();
491 			glDisable(GL_COLOR_LOGIC_OP);
492 		}
493 		glLineWidth(1);
494 		glBlendFunc(origBlendSrc, origBlendDst);
495 	#else
496 		int x, y, i, j;
497 		pixel pix;
498 		pixel * img = vid;
499 		clearrect(zoomWindowPosition.X-1, zoomWindowPosition.Y-1, zoomScopeSize*ZFACTOR+1, zoomScopeSize*ZFACTOR+1);
500 		drawrect(zoomWindowPosition.X-2, zoomWindowPosition.Y-2, zoomScopeSize*ZFACTOR+3, zoomScopeSize*ZFACTOR+3, 192, 192, 192, 255);
501 		drawrect(zoomWindowPosition.X-1, zoomWindowPosition.Y-1, zoomScopeSize*ZFACTOR+1, zoomScopeSize*ZFACTOR+1, 0, 0, 0, 255);
502 		for (j=0; j<zoomScopeSize; j++)
503 			for (i=0; i<zoomScopeSize; i++)
504 			{
505 				pix = img[(j+zoomScopePosition.Y)*(VIDXRES)+(i+zoomScopePosition.X)];
506 				for (y=0; y<ZFACTOR-1; y++)
507 					for (x=0; x<ZFACTOR-1; x++)
508 						img[(j*ZFACTOR+y+zoomWindowPosition.Y)*(VIDXRES)+(i*ZFACTOR+x+zoomWindowPosition.X)] = pix;
509 			}
510 		if (zoomEnabled)
511 		{
512 			for (j=-1; j<=zoomScopeSize; j++)
513 			{
514 				xor_pixel(zoomScopePosition.X+j, zoomScopePosition.Y-1);
515 				xor_pixel(zoomScopePosition.X+j, zoomScopePosition.Y+zoomScopeSize);
516 			}
517 			for (j=0; j<zoomScopeSize; j++)
518 			{
519 				xor_pixel(zoomScopePosition.X-1, zoomScopePosition.Y+j);
520 				xor_pixel(zoomScopePosition.X+zoomScopeSize, zoomScopePosition.Y+j);
521 			}
522 		}
523 	#endif
524 }
525 
526 std::vector<wall_type> Renderer_wtypes = LoadWalls();
527 
528 
WallIcon(int wallID,int width,int height)529 VideoBuffer * Renderer::WallIcon(int wallID, int width, int height)
530 {
531 	int i, j;
532 	int wt = wallID;
533 	if (wt<0 || wt>=(int)Renderer_wtypes.size())
534 		return 0;
535 	wall_type *wtypes = Renderer_wtypes.data();
536 	pixel pc = wtypes[wt].colour;
537 	pixel gc = wtypes[wt].eglow;
538 	VideoBuffer * newTexture = new VideoBuffer(width, height);
539 	if (wtypes[wt].drawstyle==1)
540 	{
541 		for (j=0; j<height; j+=2)
542 			for (i=(j>>1)&1; i<width; i+=2)
543 				newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
544 	}
545 	else if (wtypes[wt].drawstyle==2)
546 	{
547 		for (j=0; j<height; j+=2)
548 			for (i=0; i<width; i+=2)
549 				newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
550 	}
551 	else if (wtypes[wt].drawstyle==3)
552 	{
553 		for (j=0; j<height; j++)
554 			for (i=0; i<width; i++)
555 				newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
556 	}
557 	else if (wtypes[wt].drawstyle==4)
558 	{
559 		for (j=0; j<height; j++)
560 			for (i=0; i<width; i++)
561 				if(i%CELL == j%CELL)
562 					newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
563 				else if  (i%CELL == (j%CELL)+1 || (i%CELL == 0 && j%CELL == CELL-1))
564 					newTexture->SetPixel(i, j, PIXR(gc), PIXG(gc), PIXB(gc), 255);
565 				else
566 					newTexture->SetPixel(i, j, 0x20, 0x20, 0x20, 255);
567 	}
568 
569 	// special rendering for some walls
570 	if (wt==WL_EWALL)
571 	{
572 		for (j=0; j<height; j++)
573 		{
574 			for (i=0; i<(width/4)+j; i++)
575 			{
576 				if (!(i&j&1))
577 					newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
578 			}
579 			for (; i<width; i++)
580 			{
581 				if (i&j&1)
582 					newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
583 			}
584 		}
585 	}
586 	else if (wt==WL_WALLELEC)
587 	{
588 		for (j=0; j<height; j++)
589 			for (i=0; i<width; i++)
590 			{
591 				if (!(j%2) && !(i%2))
592 					newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
593 				else
594 					newTexture->SetPixel(i, j, 0x80, 0x80, 0x80, 255);
595 			}
596 	}
597 	else if (wt==WL_EHOLE || wt==WL_STASIS)
598 	{
599 		for (j=0; j<height; j++)
600 		{
601 			for (i=0; i<(width/4)+j; i++)
602 			{
603 				if (i&j&1)
604 					newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
605 			}
606 			for (; i<width; i++)
607 			{
608 				if (!(i&j&1))
609 					newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
610 			}
611 		}
612 	}
613 	else if (wt == WL_ERASE)
614 	{
615 		for (j=0; j<height; j+=2)
616 		{
617 			for (i=1+(1&(j>>1)); i<width/2; i+=2)
618 			{
619 				newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
620 			}
621 		}
622 		for (j=0; j<height; j++)
623 		{
624 			for (i=width/2; i<width; i++)
625 			{
626 				newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
627 			}
628 		}
629 		for (j=3; j<(width-4)/2; j++)
630 		{
631 			newTexture->SetPixel(j+6, j, 0xFF, 0, 0, 255);
632 			newTexture->SetPixel(j+7, j, 0xFF, 0, 0, 255);
633 			newTexture->SetPixel(-j+19, j, 0xFF, 0, 0, 255);
634 			newTexture->SetPixel(-j+20, j, 0xFF, 0, 0, 255);
635 		}
636 	}
637 	else if (wt == WL_ERASEALL)
638 	{
639 		for (int j = 0; j < height; j++)
640 		{
641 			int r = 100, g = 150, b = 50;
642 			int rd = 1, gd = -1, bd = -1;
643 			for (int i = 0; i < width; i++)
644 			{
645 				r += 15*rd;
646 				g += 15*gd;
647 				b += 15*bd;
648 				if (r > 200) rd = -1;
649 				if (g > 200) gd = -1;
650 				if (b > 200) bd = -1;
651 				if (r < 15) rd = 1;
652 				if (g < 15) gd = 1;
653 				if (b < 15) bd = 1;
654 				int rc = std::min(150, std::max(0, r));
655 				int gc = std::min(200, std::max(0, g));
656 				int bc = std::min(200, std::max(0, b));
657 				newTexture->SetPixel(i, j, rc, gc, bc, 255);
658 			}
659 		}
660 		for (int j = 3; j < (width-4)/2; j++)
661 		{
662 			newTexture->SetPixel(j+0, j, 0xFF, 0, 0, 255);
663 			newTexture->SetPixel(j+1, j, 0xFF, 0, 0, 255);
664 			newTexture->SetPixel(-j+13, j, 0xFF, 0, 0, 255);
665 			newTexture->SetPixel(-j+14, j, 0xFF, 0, 0, 255);
666 
667 			newTexture->SetPixel(j+11, j, 0xFF, 0, 0, 255);
668 			newTexture->SetPixel(j+12, j, 0xFF, 0, 0, 255);
669 			newTexture->SetPixel(-j+24, j, 0xFF, 0, 0, 255);
670 			newTexture->SetPixel(-j+25, j, 0xFF, 0, 0, 255);
671 		}
672 	}
673 	else if(wt == WL_STREAM)
674 	{
675 		for (j=0; j<height; j++)
676 		{
677 			for (i=0; i<width; i++)
678 			{
679 				pc =  i==0||i==width-1||j==0||j==height-1 ? PIXPACK(0xA0A0A0) : PIXPACK(0x000000);
680 				newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
681 			}
682 		}
683 		newTexture->AddCharacter(4, 2, 0xE00D, 255, 255, 255, 255);
684 		for (i=width/3; i<width; i++)
685 		{
686 			newTexture->SetPixel(i, 7+(int)(3.9f*cos(i*0.3f)), 255, 255, 255, 255);
687 		}
688 	}
689 	return newTexture;
690 }
691 
DrawBlob(int x,int y,unsigned char cr,unsigned char cg,unsigned char cb)692 void Renderer::DrawBlob(int x, int y, unsigned char cr, unsigned char cg, unsigned char cb)
693 {
694 	blendpixel(x+1, y, cr, cg, cb, 112);
695 	blendpixel(x-1, y, cr, cg, cb, 112);
696 	blendpixel(x, y+1, cr, cg, cb, 112);
697 	blendpixel(x, y-1, cr, cg, cb, 112);
698 
699 	blendpixel(x+1, y-1, cr, cg, cb, 64);
700 	blendpixel(x-1, y-1, cr, cg, cb, 64);
701 	blendpixel(x+1, y+1, cr, cg, cb, 64);
702 	blendpixel(x-1, y+1, cr, cg, cb, 64);
703 }
704 
DrawWalls()705 void Renderer::DrawWalls()
706 {
707 #ifdef OGLR
708 	// terrible OpenGL "support"
709 	GLint prevFbo;
710 	glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFbo);
711 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo);
712 	glTranslated(0, MENUSIZE, 0);
713 
714 	for (int y = 0; y < YRES/CELL; y++)
715 		for (int x = 0; x < XRES/CELL; x++)
716 			if (sim->bmap[y][x])
717 			{
718 				unsigned char wt = sim->bmap[y][x];
719 				if (wt >= UI_WALLCOUNT)
720 					continue;
721 				pixel pc = sim->wtypes[wt].colour;
722 				pixel gc = sim->wtypes[wt].eglow;
723 
724 				int cr = PIXR(pc);
725 				int cg = PIXG(pc);
726 				int cb = PIXB(pc);
727 
728 				fillrect(x*CELL, y*CELL, CELL, CELL, cr, cg, cb, 255);
729 			}
730 
731 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFbo);
732 	glTranslated(0, -MENUSIZE, 0);
733 #else
734 	for (int y = 0; y < YRES/CELL; y++)
735 		for (int x =0; x < XRES/CELL; x++)
736 			if (sim->bmap[y][x])
737 			{
738 				unsigned char wt = sim->bmap[y][x];
739 				if (wt >= UI_WALLCOUNT)
740 					continue;
741 				unsigned char powered = sim->emap[y][x];
742 				pixel pc = PIXPACK(sim->wtypes[wt].colour);
743 				pixel gc = PIXPACK(sim->wtypes[wt].eglow);
744 
745 				if (findingElement)
746 				{
747 					pc = PIXRGB(PIXR(pc)/10,PIXG(pc)/10,PIXB(pc)/10);
748 					gc = PIXRGB(PIXR(gc)/10,PIXG(gc)/10,PIXB(gc)/10);
749 				}
750 
751 				switch (sim->wtypes[wt].drawstyle)
752 				{
753 				case 0:
754 					if (wt == WL_EWALL || wt == WL_STASIS)
755 					{
756 						bool reverse = wt == WL_STASIS;
757 						if ((powered > 0) ^ reverse)
758 						{
759 							for (int j = 0; j < CELL; j++)
760 								for (int i =0; i < CELL; i++)
761 									if (i&j&1)
762 										vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = pc;
763 						}
764 						else
765 						{
766 							for (int j = 0; j < CELL; j++)
767 								for (int i = 0; i < CELL; i++)
768 									if (!(i&j&1))
769 										vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = pc;
770 						}
771 					}
772 					else if (wt == WL_WALLELEC)
773 					{
774 						for (int j = 0; j < CELL; j++)
775 							for (int i = 0; i < CELL; i++)
776 							{
777 								if (!((y*CELL+j)%2) && !((x*CELL+i)%2))
778 									vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = pc;
779 								else
780 									vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = PIXPACK(0x808080);
781 							}
782 					}
783 					else if (wt == WL_EHOLE)
784 					{
785 						if (powered)
786 						{
787 							for (int j = 0; j < CELL; j++)
788 								for (int i = 0; i < CELL; i++)
789 									vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = PIXPACK(0x242424);
790 							for (int j = 0; j < CELL; j += 2)
791 								for (int i = 0; i < CELL; i += 2)
792 									vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = PIXPACK(0x000000);
793 						}
794 						else
795 						{
796 							for (int j = 0; j < CELL; j += 2)
797 								for (int i =0; i < CELL; i += 2)
798 									vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = PIXPACK(0x242424);
799 						}
800 					}
801 					else if (wt == WL_STREAM)
802 					{
803 						float xf = x*CELL + CELL*0.5f;
804 						float yf = y*CELL + CELL*0.5f;
805 						int oldX = (int)(xf+0.5f), oldY = (int)(yf+0.5f);
806 						int newX, newY;
807 						float xVel = sim->vx[y][x]*0.125f, yVel = sim->vy[y][x]*0.125f;
808 						// there is no velocity here, draw a streamline and continue
809 						if (!xVel && !yVel)
810 						{
811 							drawtext(x*CELL, y*CELL-2, 0xE00D, 255, 255, 255, 128);
812 							addpixel(oldX, oldY, 255, 255, 255, 255);
813 							continue;
814 						}
815 						bool changed = false;
816 						for (int t = 0; t < 1024; t++)
817 						{
818 							newX = (int)(xf+0.5f);
819 							newY = (int)(yf+0.5f);
820 							if (newX != oldX || newY != oldY)
821 							{
822 								changed = true;
823 								oldX = newX;
824 								oldY = newY;
825 							}
826 							if (changed && (newX<0 || newX>=XRES || newY<0 || newY>=YRES))
827 								break;
828 							addpixel(newX, newY, 255, 255, 255, 64);
829 							// cache velocity and other checks so we aren't running them constantly
830 							if (changed)
831 							{
832 								int wallX = newX/CELL;
833 								int wallY = newY/CELL;
834 								xVel = sim->vx[wallY][wallX]*0.125f;
835 								yVel = sim->vy[wallY][wallX]*0.125f;
836 								if (wallX != x && wallY != y && sim->bmap[wallY][wallX] == WL_STREAM)
837 									break;
838 							}
839 							xf += xVel;
840 							yf += yVel;
841 						}
842 						drawtext(x*CELL, y*CELL-2, 0xE00D, 255, 255, 255, 128);
843 					}
844 					break;
845 				case 1:
846 					for (int j = 0; j < CELL; j += 2)
847 						for (int i = (j>>1)&1; i < CELL; i += 2)
848 							vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = pc;
849 					break;
850 				case 2:
851 					for (int j = 0; j < CELL; j += 2)
852 						for (int i = 0; i < CELL; i += 2)
853 							vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = pc;
854 					break;
855 				case 3:
856 					for (int j = 0; j < CELL; j++)
857 						for (int i = 0; i < CELL; i++)
858 							vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = pc;
859 					break;
860 				case 4:
861 					for (int j = 0; j < CELL; j++)
862 						for (int i = 0; i < CELL; i++)
863 							if (i == j)
864 								vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = pc;
865 							else if (i == j+1 || (i == 0 && j == CELL-1))
866 								vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = gc;
867 							else
868 								vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = PIXPACK(0x202020);
869 					break;
870 				}
871 
872 				// when in blob view, draw some blobs...
873 				if (render_mode & PMODE_BLOB)
874 				{
875 					switch (sim->wtypes[wt].drawstyle)
876 					{
877 					case 0:
878 						if (wt == WL_EWALL || wt == WL_STASIS)
879 						{
880 							bool reverse = wt == WL_STASIS;
881 							if ((powered>0) ^ reverse)
882 							{
883 								for (int j = 0; j < CELL; j++)
884 									for (int i =0; i < CELL; i++)
885 										if (i&j&1)
886 											drawblob((x*CELL+i), (y*CELL+j), PIXR(pc), PIXG(pc), PIXB(pc));
887 							}
888 							else
889 							{
890 								for (int j = 0; j < CELL; j++)
891 									for (int i = 0; i < CELL; i++)
892 										if (!(i&j&1))
893 											drawblob((x*CELL+i), (y*CELL+j), PIXR(pc), PIXG(pc), PIXB(pc));
894 							}
895 						}
896 						else if (wt == WL_WALLELEC)
897 						{
898 							for (int j = 0; j < CELL; j++)
899 								for (int i =0; i < CELL; i++)
900 								{
901 									if (!((y*CELL+j)%2) && !((x*CELL+i)%2))
902 										drawblob((x*CELL+i), (y*CELL+j), PIXR(pc), PIXG(pc), PIXB(pc));
903 									else
904 										drawblob((x*CELL+i), (y*CELL+j), 0x80, 0x80, 0x80);
905 								}
906 						}
907 						else if (wt == WL_EHOLE)
908 						{
909 							if (powered)
910 							{
911 								for (int j = 0; j < CELL; j++)
912 									for (int i = 0; i < CELL; i++)
913 										drawblob((x*CELL+i), (y*CELL+j), 0x24, 0x24, 0x24);
914 								for (int j = 0; j < CELL; j += 2)
915 									for (int i = 0; i < CELL; i += 2)
916 										// looks bad if drawing black blobs
917 										vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = PIXPACK(0x000000);
918 							}
919 							else
920 							{
921 								for (int j = 0; j < CELL; j += 2)
922 									for (int i = 0; i < CELL; i += 2)
923 										drawblob((x*CELL+i), (y*CELL+j), 0x24, 0x24, 0x24);
924 							}
925 						}
926 						break;
927 					case 1:
928 						for (int j = 0; j < CELL; j += 2)
929 							for (int i = (j>>1)&1; i < CELL; i += 2)
930 								drawblob((x*CELL+i), (y*CELL+j), PIXR(pc), PIXG(pc), PIXB(pc));
931 						break;
932 					case 2:
933 						for (int j = 0; j < CELL; j += 2)
934 							for (int i = 0; i < CELL; i+=2)
935 								drawblob((x*CELL+i), (y*CELL+j), PIXR(pc), PIXG(pc), PIXB(pc));
936 						break;
937 					case 3:
938 						for (int j = 0; j < CELL; j++)
939 							for (int i = 0; i < CELL; i++)
940 								drawblob((x*CELL+i), (y*CELL+j), PIXR(pc), PIXG(pc), PIXB(pc));
941 						break;
942 					case 4:
943 						for (int j = 0; j < CELL; j++)
944 							for (int i = 0; i < CELL; i++)
945 								if (i == j)
946 									drawblob((x*CELL+i), (y*CELL+j), PIXR(pc), PIXG(pc), PIXB(pc));
947 								else if (i == j+1 || (i == 0 && j == CELL-1))
948 									vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = gc;
949 								else
950 									// looks bad if drawing black blobs
951 									vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = PIXPACK(0x202020);
952 						break;
953 					}
954 				}
955 
956 				if (sim->wtypes[wt].eglow && powered)
957 				{
958 					// glow if electrified
959 					pixel glow = sim->wtypes[wt].eglow;
960 					int alpha = 255;
961 					int cr = (alpha*PIXR(glow) + (255-alpha)*fire_r[y/CELL][x/CELL]) >> 8;
962 					int cg = (alpha*PIXG(glow) + (255-alpha)*fire_g[y/CELL][x/CELL]) >> 8;
963 					int cb = (alpha*PIXB(glow) + (255-alpha)*fire_b[y/CELL][x/CELL]) >> 8;
964 
965 					if (cr > 255)
966 						cr = 255;
967 					if (cg > 255)
968 						cg = 255;
969 					if (cb > 255)
970 						cb = 255;
971 					fire_r[y][x] = cr;
972 					fire_g[y][x] = cg;
973 					fire_b[y][x] = cb;
974 				}
975 			}
976 #endif
977 }
978 
DrawSigns()979 void Renderer::DrawSigns()
980 {
981 	int x, y, w, h;
982 	std::vector<sign> signs = sim->signs;
983 #ifdef OGLR
984 	GLint prevFbo;
985 	glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFbo);
986 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo);
987 	glTranslated(0, MENUSIZE, 0);
988 #endif
989 	for (auto &currentSign : signs)
990 	{
991 		if (currentSign.text.length())
992 		{
993 			String text = currentSign.getDisplayText(sim, x, y, w, h);
994 			clearrect(x, y, w+1, h);
995 			drawrect(x, y, w+1, h, 192, 192, 192, 255);
996 			drawtext(x+3, y+3, text, 255, 255, 255, 255);
997 
998 			if (currentSign.ju != sign::None)
999 			{
1000 				int x = currentSign.x;
1001 				int y = currentSign.y;
1002 				int dx = 1 - currentSign.ju;
1003 				int dy = (currentSign.y > 18) ? -1 : 1;
1004 #ifdef OGLR
1005 				glBegin(GL_LINES);
1006 				glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1007 				glVertex2i(x, y);
1008 				glVertex2i(x+(dx*4), y+(dy*4));
1009 				glEnd();
1010 #else
1011 				for (int j = 0; j < 4; j++)
1012 				{
1013 					blendpixel(x, y, 192, 192, 192, 255);
1014 					x += dx;
1015 					y += dy;
1016 				}
1017 #endif
1018 			}
1019 		}
1020 	}
1021 #ifdef OGLR
1022 	glTranslated(0, -MENUSIZE, 0);
1023 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFbo);
1024 #endif
1025 }
1026 
render_gravlensing(pixel * source)1027 void Renderer::render_gravlensing(pixel * source)
1028 {
1029 #ifndef OGLR
1030 	int nx, ny, rx, ry, gx, gy, bx, by, co;
1031 	int r, g, b;
1032 	pixel t;
1033 	pixel *src = source;
1034 	pixel *dst = vid;
1035 	if (!dst)
1036 		return;
1037 	for(nx = 0; nx < XRES; nx++)
1038 	{
1039 		for(ny = 0; ny < YRES; ny++)
1040 		{
1041 			co = (ny/CELL)*(XRES/CELL)+(nx/CELL);
1042 			rx = (int)(nx-sim->gravx[co]*0.75f+0.5f);
1043 			ry = (int)(ny-sim->gravy[co]*0.75f+0.5f);
1044 			gx = (int)(nx-sim->gravx[co]*0.875f+0.5f);
1045 			gy = (int)(ny-sim->gravy[co]*0.875f+0.5f);
1046 			bx = (int)(nx-sim->gravx[co]+0.5f);
1047 			by = (int)(ny-sim->gravy[co]+0.5f);
1048 			if(rx >= 0 && rx < XRES && ry >= 0 && ry < YRES && gx >= 0 && gx < XRES && gy >= 0 && gy < YRES && bx >= 0 && bx < XRES && by >= 0 && by < YRES)
1049 			{
1050 				t = dst[ny*(VIDXRES)+nx];
1051 				r = PIXR(src[ry*(VIDXRES)+rx]) + PIXR(t);
1052 				g = PIXG(src[gy*(VIDXRES)+gx]) + PIXG(t);
1053 				b = PIXB(src[by*(VIDXRES)+bx]) + PIXB(t);
1054 				if (r>255)
1055 					r = 255;
1056 				if (g>255)
1057 					g = 255;
1058 				if (b>255)
1059 					b = 255;
1060 				dst[ny*(VIDXRES)+nx] = PIXRGB(r,g,b);
1061 			}
1062 		}
1063 	}
1064 #endif
1065 }
1066 
render_fire()1067 void Renderer::render_fire()
1068 {
1069 #ifndef OGLR
1070 	if(!(render_mode & FIREMODE))
1071 		return;
1072 	int i,j,x,y,r,g,b,a;
1073 	for (j=0; j<YRES/CELL; j++)
1074 		for (i=0; i<XRES/CELL; i++)
1075 		{
1076 			r = fire_r[j][i];
1077 			g = fire_g[j][i];
1078 			b = fire_b[j][i];
1079 			if (r || g || b)
1080 				for (y=-CELL; y<2*CELL; y++)
1081 					for (x=-CELL; x<2*CELL; x++)
1082 					{
1083 						a = fire_alpha[y+CELL][x+CELL];
1084 						if (findingElement)
1085 							a /= 2;
1086 						addpixel(i*CELL+x, j*CELL+y, r, g, b, a);
1087 					}
1088 			r *= 8;
1089 			g *= 8;
1090 			b *= 8;
1091 			for (y=-1; y<2; y++)
1092 				for (x=-1; x<2; x++)
1093 					if ((x || y) && i+x>=0 && j+y>=0 && i+x<XRES/CELL && j+y<YRES/CELL)
1094 					{
1095 						r += fire_r[j+y][i+x];
1096 						g += fire_g[j+y][i+x];
1097 						b += fire_b[j+y][i+x];
1098 					}
1099 			r /= 16;
1100 			g /= 16;
1101 			b /= 16;
1102 			fire_r[j][i] = r>4 ? r-4 : 0;
1103 			fire_g[j][i] = g>4 ? g-4 : 0;
1104 			fire_b[j][i] = b>4 ? b-4 : 0;
1105 		}
1106 #endif
1107 }
1108 
1109 float temp[CELL*3][CELL*3];
1110 float fire_alphaf[CELL*3][CELL*3];
1111 float glow_alphaf[11][11];
1112 float blur_alphaf[7][7];
prepare_alpha(int size,float intensity)1113 void Renderer::prepare_alpha(int size, float intensity)
1114 {
1115 	//TODO: implement size
1116 	int x,y,i,j;
1117 	float multiplier = 255.0f*intensity;
1118 
1119 	memset(temp, 0, sizeof(temp));
1120 	for (x=0; x<CELL; x++)
1121 		for (y=0; y<CELL; y++)
1122 			for (i=-CELL; i<CELL; i++)
1123 				for (j=-CELL; j<CELL; j++)
1124 					temp[y+CELL+j][x+CELL+i] += expf(-0.1f*(i*i+j*j));
1125 	for (x=0; x<CELL*3; x++)
1126 		for (y=0; y<CELL*3; y++)
1127 			fire_alpha[y][x] = (int)(multiplier*temp[y][x]/(CELL*CELL));
1128 
1129 #ifdef OGLR
1130 	memset(fire_alphaf, 0, sizeof(fire_alphaf));
1131 	for (x=0; x<CELL*3; x++)
1132 		for (y=0; y<CELL*3; y++)
1133 		{
1134 			fire_alphaf[y][x] = intensity*temp[y][x]/((float)(CELL*CELL));
1135 		}
1136 	glEnable(GL_TEXTURE_2D);
1137 	glBindTexture(GL_TEXTURE_2D, fireAlpha);
1138 	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, CELL*3, CELL*3, GL_ALPHA, GL_FLOAT, fire_alphaf);
1139 	glBindTexture(GL_TEXTURE_2D, 0);
1140 	glDisable(GL_TEXTURE_2D);
1141 
1142 	memset(glow_alphaf, 0, sizeof(glow_alphaf));
1143 
1144 	int c = 5;
1145 
1146 	glow_alphaf[c][c-1] = 0.4f;
1147 	glow_alphaf[c][c+1] = 0.4f;
1148 	glow_alphaf[c-1][c] = 0.4f;
1149 	glow_alphaf[c+1][c] = 0.4f;
1150 	for (x = 1; x < 6; x++) {
1151 		glow_alphaf[c][c-x] += 0.02f;
1152 		glow_alphaf[c][c+x] += 0.02f;
1153 		glow_alphaf[c-x][c] += 0.02f;
1154 		glow_alphaf[c+x][c] += 0.02f;
1155 		for (y = 1; y < 6; y++) {
1156 			if(x + y > 7)
1157 				continue;
1158 			glow_alphaf[c+x][c-y] += 0.02f;
1159 			glow_alphaf[c-x][c+y] += 0.02f;
1160 			glow_alphaf[c+x][c+y] += 0.02f;
1161 			glow_alphaf[c-x][c-y] += 0.02f;
1162 		}
1163 	}
1164 
1165 	glEnable(GL_TEXTURE_2D);
1166 	glBindTexture(GL_TEXTURE_2D, glowAlpha);
1167 	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 11, 11, GL_ALPHA, GL_FLOAT, glow_alphaf);
1168 	glBindTexture(GL_TEXTURE_2D, 0);
1169 	glDisable(GL_TEXTURE_2D);
1170 
1171 	c = 3;
1172 
1173 	for (x=-3; x<4; x++)
1174 	{
1175 		for (y=-3; y<4; y++)
1176 		{
1177 			if (abs(x)+abs(y) <2 && !(abs(x)==2||abs(y)==2))
1178 				blur_alphaf[c+x][c-y] = 0.11f;
1179 			if (abs(x)+abs(y) <=3 && abs(x)+abs(y))
1180 				blur_alphaf[c+x][c-y] = 0.08f;
1181 			if (abs(x)+abs(y) == 2)
1182 				blur_alphaf[c+x][c-y] = 0.04f;
1183 		}
1184 	}
1185 
1186 	glEnable(GL_TEXTURE_2D);
1187 	glBindTexture(GL_TEXTURE_2D, blurAlpha);
1188 	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 7, 7, GL_ALPHA, GL_FLOAT, blur_alphaf);
1189 	glBindTexture(GL_TEXTURE_2D, 0);
1190 	glDisable(GL_TEXTURE_2D);
1191 #endif
1192 }
1193 
render_parts()1194 void Renderer::render_parts()
1195 {
1196 	int deca, decr, decg, decb, cola, colr, colg, colb, firea, firer, fireg, fireb, pixel_mode, q, i, t, nx, ny, x, y, caddress;
1197 	int orbd[4] = {0, 0, 0, 0}, orbl[4] = {0, 0, 0, 0};
1198 	float gradv, flicker;
1199 	Particle * parts;
1200 	Element *elements;
1201 	if(!sim)
1202 		return;
1203 	parts = sim->parts;
1204 	elements = sim->elements.data();
1205 #ifdef OGLR
1206 	float fnx, fny;
1207 	int cfireV = 0, cfireC = 0, cfire = 0;
1208 	int csmokeV = 0, csmokeC = 0, csmoke = 0;
1209 	int cblobV = 0, cblobC = 0, cblob = 0;
1210 	int cblurV = 0, cblurC = 0, cblur = 0;
1211 	int cglowV = 0, cglowC = 0, cglow = 0;
1212 	int cflatV = 0, cflatC = 0, cflat = 0;
1213 	int caddV = 0, caddC = 0, cadd = 0;
1214 	int clineV = 0, clineC = 0, cline = 0;
1215 	GLint origBlendSrc, origBlendDst, prevFbo;
1216 
1217 	glGetIntegerv(GL_BLEND_SRC, &origBlendSrc);
1218 	glGetIntegerv(GL_BLEND_DST, &origBlendDst);
1219 	glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFbo);
1220 	//Render to the particle FBO
1221 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo);
1222 	glTranslated(0, MENUSIZE, 0);
1223 #else
1224 	if (gridSize)//draws the grid
1225 	{
1226 		for (ny=0; ny<YRES; ny++)
1227 			for (nx=0; nx<XRES; nx++)
1228 			{
1229 				if (ny%(4*gridSize) == 0)
1230 					blendpixel(nx, ny, 100, 100, 100, 80);
1231 				if (nx%(4*gridSize) == 0 && ny%(4*gridSize) != 0)
1232 					blendpixel(nx, ny, 100, 100, 100, 80);
1233 			}
1234 	}
1235 #endif
1236 	foundElements = 0;
1237 	for(i = 0; i<=sim->parts_lastActiveIndex; i++) {
1238 		if (sim->parts[i].type && sim->parts[i].type >= 0 && sim->parts[i].type < PT_NUM) {
1239 			t = sim->parts[i].type;
1240 
1241 			nx = (int)(sim->parts[i].x+0.5f);
1242 			ny = (int)(sim->parts[i].y+0.5f);
1243 #ifdef OGLR
1244 			fnx = sim->parts[i].x;
1245 			fny = sim->parts[i].y;
1246 #endif
1247 
1248 			if(nx >= XRES || nx < 0 || ny >= YRES || ny < 0)
1249 				continue;
1250 			if(TYP(sim->photons[ny][nx]) && !(sim->elements[t].Properties & TYPE_ENERGY) && t!=PT_STKM && t!=PT_STKM2 && t!=PT_FIGH)
1251 				continue;
1252 
1253 			//Defaults
1254 			pixel_mode = 0 | PMODE_FLAT;
1255 			cola = 255;
1256 			colr = PIXR(elements[t].Colour);
1257 			colg = PIXG(elements[t].Colour);
1258 			colb = PIXB(elements[t].Colour);
1259 			firer = fireg = fireb = firea = 0;
1260 
1261 			deca = (sim->parts[i].dcolour>>24)&0xFF;
1262 			decr = (sim->parts[i].dcolour>>16)&0xFF;
1263 			decg = (sim->parts[i].dcolour>>8)&0xFF;
1264 			decb = (sim->parts[i].dcolour)&0xFF;
1265 
1266 			if(decorations_enable && blackDecorations)
1267 			{
1268 				if(deca < 250 || decr > 5 || decg > 5 || decb > 5)
1269 					deca = 0;
1270 				else
1271 				{
1272 					deca = 255;
1273 					decr = decg = decb = 0;
1274 				}
1275 			}
1276 
1277 			{
1278 				if (graphicscache[t].isready)
1279 				{
1280 					pixel_mode = graphicscache[t].pixel_mode;
1281 					cola = graphicscache[t].cola;
1282 					colr = graphicscache[t].colr;
1283 					colg = graphicscache[t].colg;
1284 					colb = graphicscache[t].colb;
1285 					firea = graphicscache[t].firea;
1286 					firer = graphicscache[t].firer;
1287 					fireg = graphicscache[t].fireg;
1288 					fireb = graphicscache[t].fireb;
1289 				}
1290 				else if(!(colour_mode & COLOUR_BASC))
1291 				{
1292 					if (elements[t].Graphics)
1293 					{
1294 #if !defined(RENDERER) && defined(LUACONSOLE)
1295 						if (lua_gr_func[t])
1296 						{
1297 							if (luacon_graphicsReplacement(this, &(sim->parts[i]), nx, ny, &pixel_mode, &cola, &colr, &colg, &colb, &firea, &firer, &fireg, &fireb, i))
1298 							{
1299 								graphicscache[t].isready = 1;
1300 								graphicscache[t].pixel_mode = pixel_mode;
1301 								graphicscache[t].cola = cola;
1302 								graphicscache[t].colr = colr;
1303 								graphicscache[t].colg = colg;
1304 								graphicscache[t].colb = colb;
1305 								graphicscache[t].firea = firea;
1306 								graphicscache[t].firer = firer;
1307 								graphicscache[t].fireg = fireg;
1308 								graphicscache[t].fireb = fireb;
1309 							}
1310 						}
1311 						else if ((*(elements[t].Graphics))(this, &(sim->parts[i]), nx, ny, &pixel_mode, &cola, &colr, &colg, &colb, &firea, &firer, &fireg, &fireb)) //That's a lot of args, a struct might be better
1312 #else
1313 						if ((*(elements[t].Graphics))(this, &(sim->parts[i]), nx, ny, &pixel_mode, &cola, &colr, &colg, &colb, &firea, &firer, &fireg, &fireb)) //That's a lot of args, a struct might be better
1314 #endif
1315 						{
1316 							graphicscache[t].isready = 1;
1317 							graphicscache[t].pixel_mode = pixel_mode;
1318 							graphicscache[t].cola = cola;
1319 							graphicscache[t].colr = colr;
1320 							graphicscache[t].colg = colg;
1321 							graphicscache[t].colb = colb;
1322 							graphicscache[t].firea = firea;
1323 							graphicscache[t].firer = firer;
1324 							graphicscache[t].fireg = fireg;
1325 							graphicscache[t].fireb = fireb;
1326 						}
1327 					}
1328 					else
1329 					{
1330 						graphicscache[t].isready = 1;
1331 						graphicscache[t].pixel_mode = pixel_mode;
1332 						graphicscache[t].cola = cola;
1333 						graphicscache[t].colr = colr;
1334 						graphicscache[t].colg = colg;
1335 						graphicscache[t].colb = colb;
1336 						graphicscache[t].firea = firea;
1337 						graphicscache[t].firer = firer;
1338 						graphicscache[t].fireg = fireg;
1339 						graphicscache[t].fireb = fireb;
1340 					}
1341 				}
1342 				if((elements[t].Properties & PROP_HOT_GLOW) && sim->parts[i].temp>(elements[t].HighTemperature-800.0f))
1343 				{
1344 					gradv = 3.1415/(2*elements[t].HighTemperature-(elements[t].HighTemperature-800.0f));
1345 					caddress = (sim->parts[i].temp>elements[t].HighTemperature)?elements[t].HighTemperature-(elements[t].HighTemperature-800.0f):sim->parts[i].temp-(elements[t].HighTemperature-800.0f);
1346 					colr += sin(gradv*caddress) * 226;;
1347 					colg += sin(gradv*caddress*4.55 +3.14) * 34;
1348 					colb += sin(gradv*caddress*2.22 +3.14) * 64;
1349 				}
1350 
1351 				if((pixel_mode & FIRE_ADD) && !(render_mode & FIRE_ADD))
1352 					pixel_mode |= PMODE_GLOW;
1353 				if((pixel_mode & FIRE_BLEND) && !(render_mode & FIRE_BLEND))
1354 					pixel_mode |= PMODE_BLUR;
1355 				if((pixel_mode & PMODE_BLUR) && !(render_mode & PMODE_BLUR))
1356 					pixel_mode |= PMODE_FLAT;
1357 				if((pixel_mode & PMODE_GLOW) && !(render_mode & PMODE_GLOW))
1358 					pixel_mode |= PMODE_BLEND;
1359 				if (render_mode & PMODE_BLOB)
1360 					pixel_mode |= PMODE_BLOB;
1361 
1362 				pixel_mode &= render_mode;
1363 
1364 				//Alter colour based on display mode
1365 				if(colour_mode & COLOUR_HEAT)
1366 				{
1367 					caddress = restrict_flt((int)( restrict_flt((float)(sim->parts[i].temp+(-MIN_TEMP)), 0.0f, MAX_TEMP+(-MIN_TEMP)) / ((MAX_TEMP+(-MIN_TEMP))/1024) ) *3, 0.0f, (1024.0f*3)-3);
1368 					firea = 255;
1369 					firer = colr = color_data[caddress];
1370 					fireg = colg = color_data[caddress+1];
1371 					fireb = colb = color_data[caddress+2];
1372 					cola = 255;
1373 					if(pixel_mode & (FIREMODE | PMODE_GLOW))
1374 						pixel_mode = (pixel_mode & ~(FIREMODE|PMODE_GLOW)) | PMODE_BLUR;
1375 					else if ((pixel_mode & (PMODE_BLEND | PMODE_ADD)) == (PMODE_BLEND | PMODE_ADD))
1376 						pixel_mode = (pixel_mode & ~(PMODE_BLEND|PMODE_ADD)) | PMODE_FLAT;
1377 					else if (!pixel_mode)
1378 						pixel_mode |= PMODE_FLAT;
1379 				}
1380 				else if(colour_mode & COLOUR_LIFE)
1381 				{
1382 					gradv = 0.4f;
1383 					if (!(sim->parts[i].life<5))
1384 						q = sqrt((float)sim->parts[i].life);
1385 					else
1386 						q = sim->parts[i].life;
1387 					colr = colg = colb = sin(gradv*q) * 100 + 128;
1388 					cola = 255;
1389 					if(pixel_mode & (FIREMODE | PMODE_GLOW))
1390 						pixel_mode = (pixel_mode & ~(FIREMODE|PMODE_GLOW)) | PMODE_BLUR;
1391 					else if ((pixel_mode & (PMODE_BLEND | PMODE_ADD)) == (PMODE_BLEND | PMODE_ADD))
1392 						pixel_mode = (pixel_mode & ~(PMODE_BLEND|PMODE_ADD)) | PMODE_FLAT;
1393 					else if (!pixel_mode)
1394 						pixel_mode |= PMODE_FLAT;
1395 				}
1396 				else if(colour_mode & COLOUR_BASC)
1397 				{
1398 					colr = PIXR(elements[t].Colour);
1399 					colg = PIXG(elements[t].Colour);
1400 					colb = PIXB(elements[t].Colour);
1401 					pixel_mode = PMODE_FLAT;
1402 				}
1403 
1404 				//Apply decoration colour
1405 				if(!(colour_mode & ~COLOUR_GRAD) && decorations_enable && deca)
1406 				{
1407 					deca++;
1408 					if(!(pixel_mode & NO_DECO))
1409 					{
1410 						colr = (deca*decr + (256-deca)*colr) >> 8;
1411 						colg = (deca*decg + (256-deca)*colg) >> 8;
1412 						colb = (deca*decb + (256-deca)*colb) >> 8;
1413 					}
1414 
1415 					if(pixel_mode & DECO_FIRE)
1416 					{
1417 						firer = (deca*decr + (256-deca)*firer) >> 8;
1418 						fireg = (deca*decg + (256-deca)*fireg) >> 8;
1419 						fireb = (deca*decb + (256-deca)*fireb) >> 8;
1420 					}
1421 				}
1422 
1423 				if (findingElement)
1424 				{
1425 					if (TYP(findingElement) == parts[i].type &&
1426 							(parts[i].type != PT_LIFE || (ID(findingElement) == parts[i].ctype)))
1427 					{
1428 						colr = firer = 255;
1429 						colg = fireg = colb = fireb = 0;
1430 						foundElements++;
1431 					}
1432 					else
1433 					{
1434 						colr /= 10;
1435 						colg /= 10;
1436 						colb /= 10;
1437 						firer /= 5;
1438 						fireg /= 5;
1439 						fireb /= 5;
1440 					}
1441 				}
1442 
1443 				if (colour_mode & COLOUR_GRAD)
1444 				{
1445 					float frequency = 0.05;
1446 					int q = sim->parts[i].temp-40;
1447 					colr = sin(frequency*q) * 16 + colr;
1448 					colg = sin(frequency*q) * 16 + colg;
1449 					colb = sin(frequency*q) * 16 + colb;
1450 					if(pixel_mode & (FIREMODE | PMODE_GLOW)) pixel_mode = (pixel_mode & ~(FIREMODE|PMODE_GLOW)) | PMODE_BLUR;
1451 				}
1452 
1453 	#ifndef OGLR
1454 				//All colours are now set, check ranges
1455 				if(colr>255) colr = 255;
1456 				else if(colr<0) colr = 0;
1457 				if(colg>255) colg = 255;
1458 				else if(colg<0) colg = 0;
1459 				if(colb>255) colb = 255;
1460 				else if(colb<0) colb = 0;
1461 				if(cola>255) cola = 255;
1462 				else if(cola<0) cola = 0;
1463 
1464 				if(firer>255) firer = 255;
1465 				else if(firer<0) firer = 0;
1466 				if(fireg>255) fireg = 255;
1467 				else if(fireg<0) fireg = 0;
1468 				if(fireb>255) fireb = 255;
1469 				else if(fireb<0) fireb = 0;
1470 				if(firea>255) firea = 255;
1471 				else if(firea<0) firea = 0;
1472 	#endif
1473 
1474 				//Pixel rendering
1475 				if (pixel_mode & EFFECT_LINES)
1476 				{
1477 					if (t==PT_SOAP)
1478 					{
1479 						if ((parts[i].ctype&3) == 3 && parts[i].tmp >= 0 && parts[i].tmp < NPART)
1480 							draw_line(nx, ny, (int)(parts[parts[i].tmp].x+0.5f), (int)(parts[parts[i].tmp].y+0.5f), colr, colg, colb, cola);
1481 					}
1482 				}
1483 				if(pixel_mode & PSPEC_STICKMAN)
1484 				{
1485 					int legr, legg, legb;
1486 					playerst *cplayer;
1487 					if(t==PT_STKM)
1488 						cplayer = &sim->player;
1489 					else if(t==PT_STKM2)
1490 						cplayer = &sim->player2;
1491 					else if (t==PT_FIGH && sim->parts[i].tmp >= 0 && sim->parts[i].tmp < MAX_FIGHTERS)
1492 						cplayer = &sim->fighters[(unsigned char)sim->parts[i].tmp];
1493 					else
1494 						continue;
1495 
1496 					if (mousePos.X>(nx-3) && mousePos.X<(nx+3) && mousePos.Y<(ny+3) && mousePos.Y>(ny-3)) //If mouse is in the head
1497 					{
1498 						String hp = String::Build(Format::Width(sim->parts[i].life, 3));
1499 						drawtext(mousePos.X-8-2*(sim->parts[i].life<100)-2*(sim->parts[i].life<10), mousePos.Y-12, hp, 255, 255, 255, 255);
1500 					}
1501 
1502 					if (findingElement == t)
1503 					{
1504 						colr = 255;
1505 						colg = colb = 0;
1506 					}
1507 					else if (colour_mode != COLOUR_HEAT)
1508 					{
1509 						if (cplayer->fan)
1510 						{
1511 							colr = PIXR(0x8080FF);
1512 							colg = PIXG(0x8080FF);
1513 							colb = PIXB(0x8080FF);
1514 						}
1515 						else if (cplayer->elem < PT_NUM && cplayer->elem > 0)
1516 						{
1517 							colr = PIXR(elements[cplayer->elem].Colour);
1518 							colg = PIXG(elements[cplayer->elem].Colour);
1519 							colb = PIXB(elements[cplayer->elem].Colour);
1520 						}
1521 						else
1522 						{
1523 							colr = 0x80;
1524 							colg = 0x80;
1525 							colb = 0xFF;
1526 						}
1527 					}
1528 
1529 #ifdef OGLR
1530 					glColor4f(((float)colr)/255.0f, ((float)colg)/255.0f, ((float)colb)/255.0f, 1.0f);
1531 					glBegin(GL_LINE_STRIP);
1532 					if(t==PT_FIGH)
1533 					{
1534 						glVertex2f(fnx, fny+2);
1535 						glVertex2f(fnx+2, fny);
1536 						glVertex2f(fnx, fny-2);
1537 						glVertex2f(fnx-2, fny);
1538 						glVertex2f(fnx, fny+2);
1539 					}
1540 					else
1541 					{
1542 						glVertex2f(fnx-2, fny-2);
1543 						glVertex2f(fnx+2, fny-2);
1544 						glVertex2f(fnx+2, fny+2);
1545 						glVertex2f(fnx-2, fny+2);
1546 						glVertex2f(fnx-2, fny-2);
1547 					}
1548 					glEnd();
1549 					glBegin(GL_LINES);
1550 
1551 					if (colour_mode!=COLOUR_HEAT)
1552 					{
1553 						if (t==PT_STKM2)
1554 							glColor4f(100.0f/255.0f, 100.0f/255.0f, 1.0f, 1.0f);
1555 						else
1556 							glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1557 					}
1558 
1559 					glVertex2f(nx, ny+3);
1560 					glVertex2f(cplayer->legs[0], cplayer->legs[1]);
1561 
1562 					glVertex2f(cplayer->legs[0], cplayer->legs[1]);
1563 					glVertex2f(cplayer->legs[4], cplayer->legs[5]);
1564 
1565 					glVertex2f(nx, ny+3);
1566 					glVertex2f(cplayer->legs[8], cplayer->legs[9]);
1567 
1568 					glVertex2f(cplayer->legs[8], cplayer->legs[9]);
1569 					glVertex2f(cplayer->legs[12], cplayer->legs[13]);
1570 					glEnd();
1571 #else
1572 					if (findingElement && findingElement == t)
1573 					{
1574 						legr = 255;
1575 						legg = legb = 0;
1576 					}
1577 					else if (colour_mode==COLOUR_HEAT)
1578 					{
1579 						legr = colr;
1580 						legg = colg;
1581 						legb = colb;
1582 					}
1583 					else if (t==PT_STKM2)
1584 					{
1585 						legr = 100;
1586 						legg = 100;
1587 						legb = 255;
1588 					}
1589 					else
1590 					{
1591 						legr = 255;
1592 						legg = 255;
1593 						legb = 255;
1594 					}
1595 
1596 					if (findingElement && findingElement != t)
1597 					{
1598 						colr /= 10;
1599 						colg /= 10;
1600 						colb /= 10;
1601 						legr /= 10;
1602 						legg /= 10;
1603 						legb /= 10;
1604 					}
1605 
1606 					//head
1607 					if(t==PT_FIGH)
1608 					{
1609 						draw_line(nx, ny+2, nx+2, ny, colr, colg, colb, 255);
1610 						draw_line(nx+2, ny, nx, ny-2, colr, colg, colb, 255);
1611 						draw_line(nx, ny-2, nx-2, ny, colr, colg, colb, 255);
1612 						draw_line(nx-2, ny, nx, ny+2, colr, colg, colb, 255);
1613 					}
1614 					else
1615 					{
1616 						draw_line(nx-2, ny+2, nx+2, ny+2, colr, colg, colb, 255);
1617 						draw_line(nx-2, ny-2, nx+2, ny-2, colr, colg, colb, 255);
1618 						draw_line(nx-2, ny-2, nx-2, ny+2, colr, colg, colb, 255);
1619 						draw_line(nx+2, ny-2, nx+2, ny+2, colr, colg, colb, 255);
1620 					}
1621 					//legs
1622 					draw_line(nx, ny+3, cplayer->legs[0], cplayer->legs[1], legr, legg, legb, 255);
1623 					draw_line(cplayer->legs[0], cplayer->legs[1], cplayer->legs[4], cplayer->legs[5], legr, legg, legb, 255);
1624 					draw_line(nx, ny+3, cplayer->legs[8], cplayer->legs[9], legr, legg, legb, 255);
1625 					draw_line(cplayer->legs[8], cplayer->legs[9], cplayer->legs[12], cplayer->legs[13], legr, legg, legb, 255);
1626 					if (cplayer->rocketBoots)
1627 					{
1628 						for (int leg=0; leg<2; leg++)
1629 						{
1630 							int nx = cplayer->legs[leg*8+4], ny = cplayer->legs[leg*8+5];
1631 							int colr = 255, colg = 0, colb = 255;
1632 							if (((int)(cplayer->comm)&0x04) == 0x04 || (((int)(cplayer->comm)&0x01) == 0x01 && leg==0) || (((int)(cplayer->comm)&0x02) == 0x02 && leg==1))
1633 								blendpixel(nx, ny, 0, 255, 0, 255);
1634 							else
1635 								blendpixel(nx, ny, 255, 0, 0, 255);
1636 							blendpixel(nx+1, ny, colr, colg, colb, 223);
1637 							blendpixel(nx-1, ny, colr, colg, colb, 223);
1638 							blendpixel(nx, ny+1, colr, colg, colb, 223);
1639 							blendpixel(nx, ny-1, colr, colg, colb, 223);
1640 
1641 							blendpixel(nx+1, ny-1, colr, colg, colb, 112);
1642 							blendpixel(nx-1, ny-1, colr, colg, colb, 112);
1643 							blendpixel(nx+1, ny+1, colr, colg, colb, 112);
1644 							blendpixel(nx-1, ny+1, colr, colg, colb, 112);
1645 						}
1646 					}
1647 #endif
1648 				}
1649 				if(pixel_mode & PMODE_FLAT)
1650 				{
1651 #ifdef OGLR
1652 					flatV[cflatV++] = nx;
1653 					flatV[cflatV++] = ny;
1654 					flatC[cflatC++] = ((float)colr)/255.0f;
1655 					flatC[cflatC++] = ((float)colg)/255.0f;
1656 					flatC[cflatC++] = ((float)colb)/255.0f;
1657 					flatC[cflatC++] = 1.0f;
1658 					cflat++;
1659 #else
1660 					vid[ny*(VIDXRES)+nx] = PIXRGB(colr,colg,colb);
1661 #endif
1662 				}
1663 				if(pixel_mode & PMODE_BLEND)
1664 				{
1665 #ifdef OGLR
1666 					flatV[cflatV++] = nx;
1667 					flatV[cflatV++] = ny;
1668 					flatC[cflatC++] = ((float)colr)/255.0f;
1669 					flatC[cflatC++] = ((float)colg)/255.0f;
1670 					flatC[cflatC++] = ((float)colb)/255.0f;
1671 					flatC[cflatC++] = ((float)cola)/255.0f;
1672 					cflat++;
1673 #else
1674 					blendpixel(nx, ny, colr, colg, colb, cola);
1675 #endif
1676 				}
1677 				if(pixel_mode & PMODE_ADD)
1678 				{
1679 #ifdef OGLR
1680 					addV[caddV++] = nx;
1681 					addV[caddV++] = ny;
1682 					addC[caddC++] = ((float)colr)/255.0f;
1683 					addC[caddC++] = ((float)colg)/255.0f;
1684 					addC[caddC++] = ((float)colb)/255.0f;
1685 					addC[caddC++] = ((float)cola)/255.0f;
1686 					cadd++;
1687 #else
1688 					addpixel(nx, ny, colr, colg, colb, cola);
1689 #endif
1690 				}
1691 				if(pixel_mode & PMODE_BLOB)
1692 				{
1693 #ifdef OGLR
1694 					blobV[cblobV++] = nx;
1695 					blobV[cblobV++] = ny;
1696 					blobC[cblobC++] = ((float)colr)/255.0f;
1697 					blobC[cblobC++] = ((float)colg)/255.0f;
1698 					blobC[cblobC++] = ((float)colb)/255.0f;
1699 					blobC[cblobC++] = 1.0f;
1700 					cblob++;
1701 #else
1702 					vid[ny*(VIDXRES)+nx] = PIXRGB(colr,colg,colb);
1703 
1704 					blendpixel(nx+1, ny, colr, colg, colb, 223);
1705 					blendpixel(nx-1, ny, colr, colg, colb, 223);
1706 					blendpixel(nx, ny+1, colr, colg, colb, 223);
1707 					blendpixel(nx, ny-1, colr, colg, colb, 223);
1708 
1709 					blendpixel(nx+1, ny-1, colr, colg, colb, 112);
1710 					blendpixel(nx-1, ny-1, colr, colg, colb, 112);
1711 					blendpixel(nx+1, ny+1, colr, colg, colb, 112);
1712 					blendpixel(nx-1, ny+1, colr, colg, colb, 112);
1713 #endif
1714 				}
1715 				if(pixel_mode & PMODE_GLOW)
1716 				{
1717 					int cola1 = (5*cola)/255;
1718 #ifdef OGLR
1719 					glowV[cglowV++] = nx;
1720 					glowV[cglowV++] = ny;
1721 					glowC[cglowC++] = ((float)colr)/255.0f;
1722 					glowC[cglowC++] = ((float)colg)/255.0f;
1723 					glowC[cglowC++] = ((float)colb)/255.0f;
1724 					glowC[cglowC++] = 1.0f;
1725 					cglow++;
1726 #else
1727 					addpixel(nx, ny, colr, colg, colb, (192*cola)/255);
1728 					addpixel(nx+1, ny, colr, colg, colb, (96*cola)/255);
1729 					addpixel(nx-1, ny, colr, colg, colb, (96*cola)/255);
1730 					addpixel(nx, ny+1, colr, colg, colb, (96*cola)/255);
1731 					addpixel(nx, ny-1, colr, colg, colb, (96*cola)/255);
1732 
1733 					for (x = 1; x < 6; x++) {
1734 						addpixel(nx, ny-x, colr, colg, colb, cola1);
1735 						addpixel(nx, ny+x, colr, colg, colb, cola1);
1736 						addpixel(nx-x, ny, colr, colg, colb, cola1);
1737 						addpixel(nx+x, ny, colr, colg, colb, cola1);
1738 						for (y = 1; y < 6; y++) {
1739 							if(x + y > 7)
1740 								continue;
1741 							addpixel(nx+x, ny-y, colr, colg, colb, cola1);
1742 							addpixel(nx-x, ny+y, colr, colg, colb, cola1);
1743 							addpixel(nx+x, ny+y, colr, colg, colb, cola1);
1744 							addpixel(nx-x, ny-y, colr, colg, colb, cola1);
1745 						}
1746 					}
1747 #endif
1748 				}
1749 				if(pixel_mode & PMODE_BLUR)
1750 				{
1751 #ifdef OGLR
1752 					blurV[cblurV++] = nx;
1753 					blurV[cblurV++] = ny;
1754 					blurC[cblurC++] = ((float)colr)/255.0f;
1755 					blurC[cblurC++] = ((float)colg)/255.0f;
1756 					blurC[cblurC++] = ((float)colb)/255.0f;
1757 					blurC[cblurC++] = 1.0f;
1758 					cblur++;
1759 #else
1760 					for (x=-3; x<4; x++)
1761 					{
1762 						for (y=-3; y<4; y++)
1763 						{
1764 							if (abs(x)+abs(y) <2 && !(abs(x)==2||abs(y)==2))
1765 								blendpixel(x+nx, y+ny, colr, colg, colb, 30);
1766 							if (abs(x)+abs(y) <=3 && abs(x)+abs(y))
1767 								blendpixel(x+nx, y+ny, colr, colg, colb, 20);
1768 							if (abs(x)+abs(y) == 2)
1769 								blendpixel(x+nx, y+ny, colr, colg, colb, 10);
1770 						}
1771 					}
1772 #endif
1773 				}
1774 				if(pixel_mode & PMODE_SPARK)
1775 				{
1776 					flicker = random_gen()%20;
1777 #ifdef OGLR
1778 					//Oh god, this is awful
1779 					lineC[clineC++] = ((float)colr)/255.0f;
1780 					lineC[clineC++] = ((float)colg)/255.0f;
1781 					lineC[clineC++] = ((float)colb)/255.0f;
1782 					lineC[clineC++] = 0.0f;
1783 					lineV[clineV++] = fnx-5;
1784 					lineV[clineV++] = fny;
1785 					cline++;
1786 
1787 					lineC[clineC++] = ((float)colr)/255.0f;
1788 					lineC[clineC++] = ((float)colg)/255.0f;
1789 					lineC[clineC++] = ((float)colb)/255.0f;
1790 					lineC[clineC++] = 1.0f - ((float)flicker)/30;
1791 					lineV[clineV++] = fnx;
1792 					lineV[clineV++] = fny;
1793 					cline++;
1794 
1795 					lineC[clineC++] = ((float)colr)/255.0f;
1796 					lineC[clineC++] = ((float)colg)/255.0f;
1797 					lineC[clineC++] = ((float)colb)/255.0f;
1798 					lineC[clineC++] = 0.0f;
1799 					lineV[clineV++] = fnx+5;
1800 					lineV[clineV++] = fny;
1801 					cline++;
1802 
1803 					lineC[clineC++] = ((float)colr)/255.0f;
1804 					lineC[clineC++] = ((float)colg)/255.0f;
1805 					lineC[clineC++] = ((float)colb)/255.0f;
1806 					lineC[clineC++] = 0.0f;
1807 					lineV[clineV++] = fnx;
1808 					lineV[clineV++] = fny-5;
1809 					cline++;
1810 
1811 					lineC[clineC++] = ((float)colr)/255.0f;
1812 					lineC[clineC++] = ((float)colg)/255.0f;
1813 					lineC[clineC++] = ((float)colb)/255.0f;
1814 					lineC[clineC++] = 1.0f - ((float)flicker)/30;
1815 					lineV[clineV++] = fnx;
1816 					lineV[clineV++] = fny;
1817 					cline++;
1818 
1819 					lineC[clineC++] = ((float)colr)/255.0f;
1820 					lineC[clineC++] = ((float)colg)/255.0f;
1821 					lineC[clineC++] = ((float)colb)/255.0f;
1822 					lineC[clineC++] = 0.0f;
1823 					lineV[clineV++] = fnx;
1824 					lineV[clineV++] = fny+5;
1825 					cline++;
1826 #else
1827 					gradv = 4*sim->parts[i].life + flicker;
1828 					for (x = 0; gradv>0.5; x++) {
1829 						addpixel(nx+x, ny, colr, colg, colb, gradv);
1830 						addpixel(nx-x, ny, colr, colg, colb, gradv);
1831 
1832 						addpixel(nx, ny+x, colr, colg, colb, gradv);
1833 						addpixel(nx, ny-x, colr, colg, colb, gradv);
1834 						gradv = gradv/1.5f;
1835 					}
1836 #endif
1837 				}
1838 				if(pixel_mode & PMODE_FLARE)
1839 				{
1840 					flicker = random_gen()%20;
1841 #ifdef OGLR
1842 					//Oh god, this is awful
1843 					lineC[clineC++] = ((float)colr)/255.0f;
1844 					lineC[clineC++] = ((float)colg)/255.0f;
1845 					lineC[clineC++] = ((float)colb)/255.0f;
1846 					lineC[clineC++] = 0.0f;
1847 					lineV[clineV++] = fnx-10;
1848 					lineV[clineV++] = fny;
1849 					cline++;
1850 
1851 					lineC[clineC++] = ((float)colr)/255.0f;
1852 					lineC[clineC++] = ((float)colg)/255.0f;
1853 					lineC[clineC++] = ((float)colb)/255.0f;
1854 					lineC[clineC++] = 1.0f - ((float)flicker)/40;
1855 					lineV[clineV++] = fnx;
1856 					lineV[clineV++] = fny;
1857 					cline++;
1858 
1859 					lineC[clineC++] = ((float)colr)/255.0f;
1860 					lineC[clineC++] = ((float)colg)/255.0f;
1861 					lineC[clineC++] = ((float)colb)/255.0f;
1862 					lineC[clineC++] = 0.0f;
1863 					lineV[clineV++] = fnx+10;
1864 					lineV[clineV++] = fny;
1865 					cline++;
1866 
1867 					lineC[clineC++] = ((float)colr)/255.0f;
1868 					lineC[clineC++] = ((float)colg)/255.0f;
1869 					lineC[clineC++] = ((float)colb)/255.0f;
1870 					lineC[clineC++] = 0.0f;
1871 					lineV[clineV++] = fnx;
1872 					lineV[clineV++] = fny-10;
1873 					cline++;
1874 
1875 					lineC[clineC++] = ((float)colr)/255.0f;
1876 					lineC[clineC++] = ((float)colg)/255.0f;
1877 					lineC[clineC++] = ((float)colb)/255.0f;
1878 					lineC[clineC++] = 1.0f - ((float)flicker)/30;
1879 					lineV[clineV++] = fnx;
1880 					lineV[clineV++] = fny;
1881 					cline++;
1882 
1883 					lineC[clineC++] = ((float)colr)/255.0f;
1884 					lineC[clineC++] = ((float)colg)/255.0f;
1885 					lineC[clineC++] = ((float)colb)/255.0f;
1886 					lineC[clineC++] = 0.0f;
1887 					lineV[clineV++] = fnx;
1888 					lineV[clineV++] = fny+10;
1889 					cline++;
1890 #else
1891 					gradv = flicker + fabs(parts[i].vx)*17 + fabs(sim->parts[i].vy)*17;
1892 					blendpixel(nx, ny, colr, colg, colb, (gradv*4)>255?255:(gradv*4) );
1893 					blendpixel(nx+1, ny, colr, colg, colb, (gradv*2)>255?255:(gradv*2) );
1894 					blendpixel(nx-1, ny, colr, colg, colb, (gradv*2)>255?255:(gradv*2) );
1895 					blendpixel(nx, ny+1, colr, colg, colb, (gradv*2)>255?255:(gradv*2) );
1896 					blendpixel(nx, ny-1, colr, colg, colb, (gradv*2)>255?255:(gradv*2) );
1897 					if (gradv>255) gradv=255;
1898 					blendpixel(nx+1, ny-1, colr, colg, colb, gradv);
1899 					blendpixel(nx-1, ny-1, colr, colg, colb, gradv);
1900 					blendpixel(nx+1, ny+1, colr, colg, colb, gradv);
1901 					blendpixel(nx-1, ny+1, colr, colg, colb, gradv);
1902 					for (x = 1; gradv>0.5; x++) {
1903 						addpixel(nx+x, ny, colr, colg, colb, gradv);
1904 						addpixel(nx-x, ny, colr, colg, colb, gradv);
1905 						addpixel(nx, ny+x, colr, colg, colb, gradv);
1906 						addpixel(nx, ny-x, colr, colg, colb, gradv);
1907 						gradv = gradv/1.2f;
1908 					}
1909 #endif
1910 				}
1911 				if(pixel_mode & PMODE_LFLARE)
1912 				{
1913 					flicker = random_gen()%20;
1914 #ifdef OGLR
1915 					//Oh god, this is awful
1916 					lineC[clineC++] = ((float)colr)/255.0f;
1917 					lineC[clineC++] = ((float)colg)/255.0f;
1918 					lineC[clineC++] = ((float)colb)/255.0f;
1919 					lineC[clineC++] = 0.0f;
1920 					lineV[clineV++] = fnx-70;
1921 					lineV[clineV++] = fny;
1922 					cline++;
1923 
1924 					lineC[clineC++] = ((float)colr)/255.0f;
1925 					lineC[clineC++] = ((float)colg)/255.0f;
1926 					lineC[clineC++] = ((float)colb)/255.0f;
1927 					lineC[clineC++] = 1.0f - ((float)flicker)/30;
1928 					lineV[clineV++] = fnx;
1929 					lineV[clineV++] = fny;
1930 					cline++;
1931 
1932 					lineC[clineC++] = ((float)colr)/255.0f;
1933 					lineC[clineC++] = ((float)colg)/255.0f;
1934 					lineC[clineC++] = ((float)colb)/255.0f;
1935 					lineC[clineC++] = 0.0f;
1936 					lineV[clineV++] = fnx+70;
1937 					lineV[clineV++] = fny;
1938 					cline++;
1939 
1940 					lineC[clineC++] = ((float)colr)/255.0f;
1941 					lineC[clineC++] = ((float)colg)/255.0f;
1942 					lineC[clineC++] = ((float)colb)/255.0f;
1943 					lineC[clineC++] = 0.0f;
1944 					lineV[clineV++] = fnx;
1945 					lineV[clineV++] = fny-70;
1946 					cline++;
1947 
1948 					lineC[clineC++] = ((float)colr)/255.0f;
1949 					lineC[clineC++] = ((float)colg)/255.0f;
1950 					lineC[clineC++] = ((float)colb)/255.0f;
1951 					lineC[clineC++] = 1.0f - ((float)flicker)/50;
1952 					lineV[clineV++] = fnx;
1953 					lineV[clineV++] = fny;
1954 					cline++;
1955 
1956 					lineC[clineC++] = ((float)colr)/255.0f;
1957 					lineC[clineC++] = ((float)colg)/255.0f;
1958 					lineC[clineC++] = ((float)colb)/255.0f;
1959 					lineC[clineC++] = 0.0f;
1960 					lineV[clineV++] = fnx;
1961 					lineV[clineV++] = fny+70;
1962 					cline++;
1963 #else
1964 					gradv = flicker + fabs(parts[i].vx)*17 + fabs(parts[i].vy)*17;
1965 					blendpixel(nx, ny, colr, colg, colb, (gradv*4)>255?255:(gradv*4) );
1966 					blendpixel(nx+1, ny, colr, colg, colb, (gradv*2)>255?255:(gradv*2) );
1967 					blendpixel(nx-1, ny, colr, colg, colb, (gradv*2)>255?255:(gradv*2) );
1968 					blendpixel(nx, ny+1, colr, colg, colb, (gradv*2)>255?255:(gradv*2) );
1969 					blendpixel(nx, ny-1, colr, colg, colb, (gradv*2)>255?255:(gradv*2) );
1970 					if (gradv>255) gradv=255;
1971 					blendpixel(nx+1, ny-1, colr, colg, colb, gradv);
1972 					blendpixel(nx-1, ny-1, colr, colg, colb, gradv);
1973 					blendpixel(nx+1, ny+1, colr, colg, colb, gradv);
1974 					blendpixel(nx-1, ny+1, colr, colg, colb, gradv);
1975 					for (x = 1; gradv>0.5; x++) {
1976 						addpixel(nx+x, ny, colr, colg, colb, gradv);
1977 						addpixel(nx-x, ny, colr, colg, colb, gradv);
1978 						addpixel(nx, ny+x, colr, colg, colb, gradv);
1979 						addpixel(nx, ny-x, colr, colg, colb, gradv);
1980 						gradv = gradv/1.01f;
1981 					}
1982 #endif
1983 				}
1984 				if (pixel_mode & EFFECT_GRAVIN)
1985 				{
1986 					int nxo = 0;
1987 					int nyo = 0;
1988 					int r;
1989 					float drad = 0.0f;
1990 					float ddist = 0.0f;
1991 					sim->orbitalparts_get(parts[i].life, parts[i].ctype, orbd, orbl);
1992 					for (r = 0; r < 4; r++) {
1993 						ddist = ((float)orbd[r])/16.0f;
1994 						drad = (M_PI * ((float)orbl[r]) / 180.0f)*1.41f;
1995 						nxo = (int)(ddist*cos(drad));
1996 						nyo = (int)(ddist*sin(drad));
1997 						if (ny+nyo>0 && ny+nyo<YRES && nx+nxo>0 && nx+nxo<XRES && TYP(sim->pmap[ny+nyo][nx+nxo]) != PT_PRTI)
1998 							addpixel(nx+nxo, ny+nyo, colr, colg, colb, 255-orbd[r]);
1999 					}
2000 				}
2001 				if (pixel_mode & EFFECT_GRAVOUT)
2002 				{
2003 					int nxo = 0;
2004 					int nyo = 0;
2005 					int r;
2006 					float drad = 0.0f;
2007 					float ddist = 0.0f;
2008 					sim->orbitalparts_get(parts[i].life, parts[i].ctype, orbd, orbl);
2009 					for (r = 0; r < 4; r++) {
2010 						ddist = ((float)orbd[r])/16.0f;
2011 						drad = (M_PI * ((float)orbl[r]) / 180.0f)*1.41f;
2012 						nxo = (int)(ddist*cos(drad));
2013 						nyo = (int)(ddist*sin(drad));
2014 						if (ny+nyo>0 && ny+nyo<YRES && nx+nxo>0 && nx+nxo<XRES && TYP(sim->pmap[ny+nyo][nx+nxo]) != PT_PRTO)
2015 							addpixel(nx+nxo, ny+nyo, colr, colg, colb, 255-orbd[r]);
2016 					}
2017 				}
2018 				if (pixel_mode & EFFECT_DBGLINES && !(display_mode&DISPLAY_PERS))
2019 				{
2020 					// draw lines connecting wifi/portal channels
2021 					if (mousePos.X == nx && mousePos.Y == ny && i == ID(sim->pmap[ny][nx]) && debugLines)
2022 					{
2023 						int type = parts[i].type, tmp = (int)((parts[i].temp-73.15f)/100+1), othertmp;
2024 						if (type == PT_PRTI)
2025 							type = PT_PRTO;
2026 						else if (type == PT_PRTO)
2027 							type = PT_PRTI;
2028 						for (int z = 0; z <= sim->parts_lastActiveIndex; z++)
2029 						{
2030 							if (parts[z].type == type)
2031 							{
2032 								othertmp = (int)((parts[z].temp-73.15f)/100+1);
2033 								if (tmp == othertmp)
2034 									xor_line(nx,ny,(int)(parts[z].x+0.5f),(int)(parts[z].y+0.5f));
2035 							}
2036 						}
2037 					}
2038 				}
2039 				//Fire effects
2040 				if(firea && (pixel_mode & FIRE_BLEND))
2041 				{
2042 #ifdef OGLR
2043 					smokeV[csmokeV++] = nx;
2044 					smokeV[csmokeV++] = ny;
2045 					smokeC[csmokeC++] = ((float)firer)/255.0f;
2046 					smokeC[csmokeC++] = ((float)fireg)/255.0f;
2047 					smokeC[csmokeC++] = ((float)fireb)/255.0f;
2048 					smokeC[csmokeC++] = ((float)firea)/255.0f;
2049 					csmoke++;
2050 #else
2051 					firea /= 2;
2052 					fire_r[ny/CELL][nx/CELL] = (firea*firer + (255-firea)*fire_r[ny/CELL][nx/CELL]) >> 8;
2053 					fire_g[ny/CELL][nx/CELL] = (firea*fireg + (255-firea)*fire_g[ny/CELL][nx/CELL]) >> 8;
2054 					fire_b[ny/CELL][nx/CELL] = (firea*fireb + (255-firea)*fire_b[ny/CELL][nx/CELL]) >> 8;
2055 #endif
2056 				}
2057 				if(firea && (pixel_mode & FIRE_ADD))
2058 				{
2059 #ifdef OGLR
2060 					fireV[cfireV++] = nx;
2061 					fireV[cfireV++] = ny;
2062 					fireC[cfireC++] = ((float)firer)/255.0f;
2063 					fireC[cfireC++] = ((float)fireg)/255.0f;
2064 					fireC[cfireC++] = ((float)fireb)/255.0f;
2065 					fireC[cfireC++] = ((float)firea)/255.0f;
2066 					cfire++;
2067 #else
2068 					firea /= 8;
2069 					firer = ((firea*firer) >> 8) + fire_r[ny/CELL][nx/CELL];
2070 					fireg = ((firea*fireg) >> 8) + fire_g[ny/CELL][nx/CELL];
2071 					fireb = ((firea*fireb) >> 8) + fire_b[ny/CELL][nx/CELL];
2072 
2073 					if(firer>255)
2074 						firer = 255;
2075 					if(fireg>255)
2076 						fireg = 255;
2077 					if(fireb>255)
2078 						fireb = 255;
2079 
2080 					fire_r[ny/CELL][nx/CELL] = firer;
2081 					fire_g[ny/CELL][nx/CELL] = fireg;
2082 					fire_b[ny/CELL][nx/CELL] = fireb;
2083 #endif
2084 				}
2085 				if(firea && (pixel_mode & FIRE_SPARK))
2086 				{
2087 #ifdef OGLR
2088 					smokeV[csmokeV++] = nx;
2089 					smokeV[csmokeV++] = ny;
2090 					smokeC[csmokeC++] = ((float)firer)/255.0f;
2091 					smokeC[csmokeC++] = ((float)fireg)/255.0f;
2092 					smokeC[csmokeC++] = ((float)fireb)/255.0f;
2093 					smokeC[csmokeC++] = ((float)firea)/255.0f;
2094 					csmoke++;
2095 #else
2096 					firea /= 4;
2097 					fire_r[ny/CELL][nx/CELL] = (firea*firer + (255-firea)*fire_r[ny/CELL][nx/CELL]) >> 8;
2098 					fire_g[ny/CELL][nx/CELL] = (firea*fireg + (255-firea)*fire_g[ny/CELL][nx/CELL]) >> 8;
2099 					fire_b[ny/CELL][nx/CELL] = (firea*fireb + (255-firea)*fire_b[ny/CELL][nx/CELL]) >> 8;
2100 #endif
2101 				}
2102 			}
2103 		}
2104 	}
2105 #ifdef OGLR
2106 
2107 		//Go into array mode
2108 		glEnableClientState(GL_COLOR_ARRAY);
2109 		glEnableClientState(GL_VERTEX_ARRAY);
2110 
2111 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2112 
2113 		if(cflat)
2114 		{
2115 			// -- BEGIN FLAT -- //
2116 			//Set point size (size of fire texture)
2117 			glPointSize(1.0f);
2118 
2119 			glColorPointer(4, GL_FLOAT, 0, &flatC[0]);
2120 			glVertexPointer(2, GL_INT, 0, &flatV[0]);
2121 
2122 			glDrawArrays(GL_POINTS, 0, cflat);
2123 
2124 			//Clear some stuff we set
2125 			// -- END FLAT -- //
2126 		}
2127 
2128 		if(cblob)
2129 		{
2130 			// -- BEGIN BLOB -- //
2131 			glEnable( GL_POINT_SMOOTH ); //Blobs!
2132 			glPointSize(2.5f);
2133 
2134 			glColorPointer(4, GL_FLOAT, 0, &blobC[0]);
2135 			glVertexPointer(2, GL_INT, 0, &blobV[0]);
2136 
2137 			glDrawArrays(GL_POINTS, 0, cblob);
2138 
2139 			//Clear some stuff we set
2140 			glDisable( GL_POINT_SMOOTH );
2141 			// -- END BLOB -- //
2142 		}
2143 
2144 		if(cglow || cblur)
2145 		{
2146 			// -- BEGIN GLOW -- //
2147 			//Start and prepare fire program
2148 			glEnable(GL_TEXTURE_2D);
2149 			glUseProgram(fireProg);
2150 			glActiveTexture(GL_TEXTURE0);
2151 			glBindTexture(GL_TEXTURE_2D, glowAlpha);
2152 			glUniform1i(glGetUniformLocation(fireProg, "fireAlpha"), 0);
2153 
2154 			glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2155 
2156 			//Make sure we can use texture coords on points
2157 			glEnable(GL_POINT_SPRITE);
2158 			glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2159 			glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
2160 
2161 			//Set point size (size of fire texture)
2162 			glPointSize(11.0f);
2163 
2164 			glBlendFunc(GL_SRC_ALPHA, GL_ONE);
2165 
2166 			if(cglow)
2167 			{
2168 				glColorPointer(4, GL_FLOAT, 0, &glowC[0]);
2169 				glVertexPointer(2, GL_INT, 0, &glowV[0]);
2170 
2171 				glDrawArrays(GL_POINTS, 0, cglow);
2172 			}
2173 
2174 			glPointSize(7.0f);
2175 
2176 			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2177 
2178 			if(cblur)
2179 			{
2180 				glBindTexture(GL_TEXTURE_2D, blurAlpha);
2181 
2182 				glColorPointer(4, GL_FLOAT, 0, &blurC[0]);
2183 				glVertexPointer(2, GL_INT, 0, &blurV[0]);
2184 
2185 				glDrawArrays(GL_POINTS, 0, cblur);
2186 			}
2187 
2188 			//Clear some stuff we set
2189 			glDisable(GL_POINT_SPRITE);
2190 			glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
2191 			glUseProgram(0);
2192 			glBindTexture(GL_TEXTURE_2D, 0);
2193 			glDisable(GL_TEXTURE_2D);
2194 			// -- END GLOW -- //
2195 		}
2196 
2197 		if(cadd)
2198 		{
2199 			// -- BEGIN ADD -- //
2200 			//Set point size (size of fire texture)
2201 			glPointSize(1.0f);
2202 
2203 			glColorPointer(4, GL_FLOAT, 0, &addC[0]);
2204 			glVertexPointer(2, GL_INT, 0, &addV[0]);
2205 
2206 			glBlendFunc(GL_SRC_ALPHA, GL_ONE);
2207 			glDrawArrays(GL_POINTS, 0, cadd);
2208 			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2209 			//Clear some stuff we set
2210 			// -- END ADD -- //
2211 		}
2212 
2213 		if(cline)
2214 		{
2215 			// -- BEGIN LINES -- //
2216 			glBlendFunc(GL_SRC_ALPHA, GL_ONE);
2217 			glEnable( GL_LINE_SMOOTH );
2218 			glColorPointer(4, GL_FLOAT, 0, &lineC[0]);
2219 			glVertexPointer(2, GL_FLOAT, 0, &lineV[0]);
2220 
2221 			glDrawArrays(GL_LINE_STRIP, 0, cline);
2222 
2223 			//Clear some stuff we set
2224 			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2225 			glDisable(GL_LINE_SMOOTH);
2226 			// -- END LINES -- //
2227 		}
2228 
2229 		if(cfire || csmoke)
2230 		{
2231 			// -- BEGIN FIRE -- //
2232 			//Start and prepare fire program
2233 			glEnable(GL_TEXTURE_2D);
2234 			glUseProgram(fireProg);
2235 			//glActiveTexture(GL_TEXTURE0);
2236 			glBindTexture(GL_TEXTURE_2D, fireAlpha);
2237 			glUniform1i(glGetUniformLocation(fireProg, "fireAlpha"), 0);
2238 
2239 			//Make sure we can use texture coords on points
2240 			glEnable(GL_POINT_SPRITE);
2241 			glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2242 			glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
2243 
2244 			//Set point size (size of fire texture)
2245 			glPointSize(CELL*3);
2246 
2247 			glBlendFunc(GL_SRC_ALPHA, GL_ONE);
2248 
2249 			if(cfire)
2250 			{
2251 				glColorPointer(4, GL_FLOAT, 0, &fireC[0]);
2252 				glVertexPointer(2, GL_INT, 0, &fireV[0]);
2253 
2254 				glDrawArrays(GL_POINTS, 0, cfire);
2255 			}
2256 
2257 			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2258 
2259 			if(csmoke)
2260 			{
2261 				glColorPointer(4, GL_FLOAT, 0, &smokeC[0]);
2262 				glVertexPointer(2, GL_INT, 0, &smokeV[0]);
2263 
2264 				glDrawArrays(GL_POINTS, 0, csmoke);
2265 			}
2266 
2267 			//Clear some stuff we set
2268 			glDisable(GL_POINT_SPRITE);
2269 			glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
2270 			glUseProgram(0);
2271 			glBindTexture(GL_TEXTURE_2D, 0);
2272 			glDisable(GL_TEXTURE_2D);
2273 			// -- END FIRE -- //
2274 		}
2275 
2276 		glDisableClientState(GL_COLOR_ARRAY);
2277 		glDisableClientState(GL_VERTEX_ARRAY);
2278 
2279 		//Reset FBO
2280 		glTranslated(0, -MENUSIZE, 0);
2281 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFbo);
2282 
2283 		glBlendFunc(origBlendSrc, origBlendDst);
2284 #endif
2285 }
2286 
draw_other()2287 void Renderer::draw_other() // EMP effect
2288 {
2289 	int i, j;
2290 	int emp_decor = sim->emp_decor;
2291 	if (emp_decor>40) emp_decor = 40;
2292 	if (emp_decor<0) emp_decor = 0;
2293 	if (!(render_mode & EFFECT)) // not in nothing mode
2294 		return;
2295 	if (emp_decor>0)
2296 	{
2297 #ifdef OGLR
2298 		GLint prevFbo;
2299 		glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFbo);
2300 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo);
2301 		glTranslated(0, MENUSIZE, 0);
2302 		float femp_decor = ((float)emp_decor)/255.0f;
2303 		/*int r=emp_decor*2.5, g=100+emp_decor*1.5, b=255;
2304 		int a=(1.0*emp_decor/110)*255;
2305 		if (r>255) r=255;
2306 		if (g>255) g=255;
2307 		if (b>255) g=255;
2308 		if (a>255) a=255;*/
2309 		glBegin(GL_QUADS);
2310 		glColor4f(femp_decor*2.5f, 0.4f+femp_decor*1.5f, 1.0f+femp_decor*1.5f, femp_decor/0.44f);
2311 		glVertex2f(0, MENUSIZE);
2312 		glVertex2f(XRES, MENUSIZE);
2313 		glVertex2f(XRES, WINDOWH);
2314 		glVertex2f(0, WINDOWH);
2315 		glEnd();
2316 		glTranslated(0, -MENUSIZE, 0);
2317 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFbo);
2318 #else
2319 		int r=emp_decor*2.5, g=100+emp_decor*1.5, b=255;
2320 		int a=(1.0*emp_decor/110)*255;
2321 		if (r>255) r=255;
2322 		if (g>255) g=255;
2323 		if (b>255) g=255;
2324 		if (a>255) a=255;
2325 		for (j=0; j<YRES; j++)
2326 			for (i=0; i<XRES; i++)
2327 			{
2328 				blendpixel(i, j, r, g, b, a);
2329 			}
2330 #endif
2331 	}
2332 }
2333 
draw_grav()2334 void Renderer::draw_grav()
2335 {
2336 	int x, y, i, ca;
2337 	float nx, ny, dist;
2338 
2339 	if(!gravityFieldEnabled)
2340 		return;
2341 
2342 	for (y=0; y<YRES/CELL; y++)
2343 	{
2344 		for (x=0; x<XRES/CELL; x++)
2345 		{
2346 			ca = y*(XRES/CELL)+x;
2347 			if(fabsf(sim->gravx[ca]) <= 0.001f && fabsf(sim->gravy[ca]) <= 0.001f)
2348 				continue;
2349 			nx = x*CELL;
2350 			ny = y*CELL;
2351 			dist = fabsf(sim->gravy[ca])+fabsf(sim->gravx[ca]);
2352 			for(i = 0; i < 4; i++)
2353 			{
2354 				nx -= sim->gravx[ca]*0.5f;
2355 				ny -= sim->gravy[ca]*0.5f;
2356 				addpixel((int)(nx+0.5f), (int)(ny+0.5f), 255, 255, 255, (int)(dist*20.0f));
2357 			}
2358 		}
2359 	}
2360 }
2361 
draw_air()2362 void Renderer::draw_air()
2363 {
2364 	if(!sim->aheat_enable && (display_mode & DISPLAY_AIRH))
2365 		return;
2366 #ifndef OGLR
2367 	if(!(display_mode & DISPLAY_AIR))
2368 		return;
2369 	int x, y, i, j;
2370 	float (*pv)[XRES/CELL] = sim->air->pv;
2371 	float (*hv)[XRES/CELL] = sim->air->hv;
2372 	float (*vx)[XRES/CELL] = sim->air->vx;
2373 	float (*vy)[XRES/CELL] = sim->air->vy;
2374 	pixel c = 0;
2375 	for (y=0; y<YRES/CELL; y++)
2376 		for (x=0; x<XRES/CELL; x++)
2377 		{
2378 			if (display_mode & DISPLAY_AIRP)
2379 			{
2380 				if (pv[y][x] > 0.0f)
2381 					c  = PIXRGB(clamp_flt(pv[y][x], 0.0f, 8.0f), 0, 0);//positive pressure is red!
2382 				else
2383 					c  = PIXRGB(0, 0, clamp_flt(-pv[y][x], 0.0f, 8.0f));//negative pressure is blue!
2384 			}
2385 			else if (display_mode & DISPLAY_AIRV)
2386 			{
2387 				c  = PIXRGB(clamp_flt(fabsf(vx[y][x]), 0.0f, 8.0f),//vx adds red
2388 					clamp_flt(pv[y][x], 0.0f, 8.0f),//pressure adds green
2389 					clamp_flt(fabsf(vy[y][x]), 0.0f, 8.0f));//vy adds blue
2390 			}
2391 			else if (display_mode & DISPLAY_AIRH)
2392 			{
2393 				float ttemp = hv[y][x]+(-MIN_TEMP);
2394 				int caddress = restrict_flt((int)( restrict_flt(ttemp, 0.0f, MAX_TEMP+(-MIN_TEMP)) / ((MAX_TEMP+(-MIN_TEMP))/1024) ) *3, 0.0f, (1024.0f*3)-3);
2395 				c = PIXRGB((int)(color_data[caddress]*0.7f), (int)(color_data[caddress+1]*0.7f), (int)(color_data[caddress+2]*0.7f));
2396 				//c  = PIXRGB(clamp_flt(fabsf(vx[y][x]), 0.0f, 8.0f),//vx adds red
2397 				//	clamp_flt(hv[y][x], 0.0f, 1600.0f),//heat adds green
2398 				//	clamp_flt(fabsf(vy[y][x]), 0.0f, 8.0f));//vy adds blue
2399 			}
2400 			else if (display_mode & DISPLAY_AIRC)
2401 			{
2402 				int r;
2403 				int g;
2404 				int b;
2405 				// velocity adds grey
2406 				r = clamp_flt(fabsf(vx[y][x]), 0.0f, 24.0f) + clamp_flt(fabsf(vy[y][x]), 0.0f, 20.0f);
2407 				g = clamp_flt(fabsf(vx[y][x]), 0.0f, 20.0f) + clamp_flt(fabsf(vy[y][x]), 0.0f, 24.0f);
2408 				b = clamp_flt(fabsf(vx[y][x]), 0.0f, 24.0f) + clamp_flt(fabsf(vy[y][x]), 0.0f, 20.0f);
2409 				if (pv[y][x] > 0.0f)
2410 				{
2411 					r += clamp_flt(pv[y][x], 0.0f, 16.0f);//pressure adds red!
2412 					if (r>255)
2413 						r=255;
2414 					if (g>255)
2415 						g=255;
2416 					if (b>255)
2417 						b=255;
2418 					c  = PIXRGB(r, g, b);
2419 				}
2420 				else
2421 				{
2422 					b += clamp_flt(-pv[y][x], 0.0f, 16.0f);//pressure adds blue!
2423 					if (r>255)
2424 						r=255;
2425 					if (g>255)
2426 						g=255;
2427 					if (b>255)
2428 						b=255;
2429 					c  = PIXRGB(r, g, b);
2430 				}
2431 			}
2432 			if (findingElement)
2433 				c = PIXRGB(PIXR(c)/10,PIXG(c)/10,PIXB(c)/10);
2434 			for (j=0; j<CELL; j++)//draws the colors
2435 				for (i=0; i<CELL; i++)
2436 					vid[(x*CELL+i) + (y*CELL+j)*(VIDXRES)] = c;
2437 		}
2438 #else
2439 	int sdl_scale = 1;
2440 	GLuint airProg;
2441 	GLint prevFbo;
2442 	if(display_mode & DISPLAY_AIRC)
2443 	{
2444 		airProg = airProg_Cracker;
2445 	}
2446 	else if(display_mode & DISPLAY_AIRV)
2447 	{
2448 		airProg = airProg_Velocity;
2449 	}
2450 	else if(display_mode & DISPLAY_AIRP)
2451 	{
2452 		airProg = airProg_Pressure;
2453 	}
2454 	else
2455 	{
2456 		return;
2457 	}
2458 
2459 	glEnable( GL_TEXTURE_2D );
2460 	glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFbo);
2461 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo);
2462 	glTranslated(0, MENUSIZE, 0);
2463 
2464 	glUseProgram(airProg);
2465 
2466 	glActiveTexture(GL_TEXTURE0);
2467 	glBindTexture(GL_TEXTURE_2D, airVX);
2468 	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, XRES/CELL, YRES/CELL, GL_RED, GL_FLOAT, sim->air->vx);
2469 	glUniform1i(glGetUniformLocation(airProg, "airX"), 0);
2470 	glActiveTexture(GL_TEXTURE1);
2471 	glBindTexture(GL_TEXTURE_2D, airVY);
2472 	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, XRES/CELL, YRES/CELL, GL_GREEN, GL_FLOAT, sim->air->vy);
2473 	glUniform1i(glGetUniformLocation(airProg, "airY"), 1);
2474 	glActiveTexture(GL_TEXTURE2);
2475 	glBindTexture(GL_TEXTURE_2D, airPV);
2476 	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, XRES/CELL, YRES/CELL, GL_BLUE, GL_FLOAT, sim->air->pv);
2477 	glUniform1i(glGetUniformLocation(airProg, "airP"), 2);
2478 	glActiveTexture(GL_TEXTURE0);
2479 
2480 	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
2481 	glBegin(GL_QUADS);
2482 	glTexCoord2d(1, 1);
2483 	glVertex3f(XRES*sdl_scale, YRES*sdl_scale, 1.0);
2484 	glTexCoord2d(0, 1);
2485 	glVertex3f(0, YRES*sdl_scale, 1.0);
2486 	glTexCoord2d(0, 0);
2487 	glVertex3f(0, 0, 1.0);
2488 	glTexCoord2d(1, 0);
2489 	glVertex3f(XRES*sdl_scale, 0, 1.0);
2490 	glEnd();
2491 
2492 	glUseProgram(0);
2493 	glBindTexture(GL_TEXTURE_2D, 0);
2494 	glTranslated(0, -MENUSIZE, 0);
2495 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFbo);
2496 	glDisable( GL_TEXTURE_2D );
2497 #endif
2498 }
2499 
draw_grav_zones()2500 void Renderer::draw_grav_zones()
2501 {
2502 	if(!gravityZonesEnabled)
2503 		return;
2504 
2505 	int x, y, i, j;
2506 	for (y=0; y<YRES/CELL; y++)
2507 	{
2508 		for (x=0; x<XRES/CELL; x++)
2509 		{
2510 			if(sim->grav->gravmask[y*(XRES/CELL)+x])
2511 			{
2512 				for (j=0; j<CELL; j++)//draws the colors
2513 					for (i=0; i<CELL; i++)
2514 						if(i == j)
2515 							blendpixel(x*CELL+i, y*CELL+j, 255, 200, 0, 120);
2516 						else
2517 							blendpixel(x*CELL+i, y*CELL+j, 32, 32, 32, 120);
2518 			}
2519 		}
2520 	}
2521 }
2522 
drawblob(int x,int y,unsigned char cr,unsigned char cg,unsigned char cb)2523 void Renderer::drawblob(int x, int y, unsigned char cr, unsigned char cg, unsigned char cb)
2524 {
2525 	blendpixel(x+1, y, cr, cg, cb, 112);
2526 	blendpixel(x-1, y, cr, cg, cb, 112);
2527 	blendpixel(x, y+1, cr, cg, cb, 112);
2528 	blendpixel(x, y-1, cr, cg, cb, 112);
2529 
2530 	blendpixel(x+1, y-1, cr, cg, cb, 64);
2531 	blendpixel(x-1, y-1, cr, cg, cb, 64);
2532 	blendpixel(x+1, y+1, cr, cg, cb, 64);
2533 	blendpixel(x-1, y+1, cr, cg, cb, 64);
2534 }
2535 
GetPixel(int x,int y)2536 pixel Renderer::GetPixel(int x, int y)
2537 {
2538 	if (x<0 || y<0 || x>=VIDXRES || y>=VIDYRES)
2539 		return 0;
2540 #ifdef OGLR
2541 	return 0;
2542 #else
2543 	return vid[(y*VIDXRES)+x];
2544 #endif
2545 }
2546 
Renderer(Graphics * g,Simulation * sim)2547 Renderer::Renderer(Graphics * g, Simulation * sim):
2548 	sim(NULL),
2549 	g(NULL),
2550 	render_mode(0),
2551 	colour_mode(0),
2552 	display_mode(0),
2553 	gravityZonesEnabled(false),
2554 	gravityFieldEnabled(false),
2555 	decorations_enable(1),
2556 	blackDecorations(false),
2557 	debugLines(false),
2558 	sampleColor(0xFFFFFFFF),
2559 	findingElement(0),
2560     foundElements(0),
2561 	mousePos(0, 0),
2562 	zoomWindowPosition(0, 0),
2563 	zoomScopePosition(0, 0),
2564 	zoomScopeSize(32),
2565 	zoomEnabled(false),
2566 	ZFACTOR(8),
2567 	gridSize(0)
2568 {
2569 	this->g = g;
2570 	this->sim = sim;
2571 #if !defined(OGLR)
2572 #if defined(OGLI)
2573 	vid = new pixel[VIDXRES*VIDYRES];
2574 #else
2575 	vid = g->vid;
2576 #endif
2577 	persistentVid = new pixel[VIDXRES*YRES];
2578 	warpVid = new pixel[VIDXRES*VIDYRES];
2579 #endif
2580 
2581 	memset(fire_r, 0, sizeof(fire_r));
2582 	memset(fire_g, 0, sizeof(fire_g));
2583 	memset(fire_b, 0, sizeof(fire_b));
2584 
2585 	//Set defauly display modes
2586 	ResetModes();
2587 
2588 	//Render mode presets. Possibly load from config in future?
2589 	renderModePresets.push_back({
2590 		"Alternative Velocity Display",
2591 		{ RENDER_EFFE, RENDER_BASC },
2592 		{ DISPLAY_AIRC },
2593 		0
2594 	});
2595 	renderModePresets.push_back({
2596 		"Velocity Display",
2597 		{ RENDER_EFFE, RENDER_BASC },
2598 		{ DISPLAY_AIRV },
2599 		0
2600 	});
2601 	renderModePresets.push_back({
2602 		"Pressure Display",
2603 		{ RENDER_EFFE, RENDER_BASC },
2604 		{ DISPLAY_AIRP },
2605 		0
2606 	});
2607 	renderModePresets.push_back({
2608 		"Persistent Display",
2609 		{ RENDER_EFFE, RENDER_BASC },
2610 		{ DISPLAY_PERS },
2611 		0
2612 	});
2613 	renderModePresets.push_back({
2614 		"Fire Display",
2615 		{ RENDER_FIRE, RENDER_SPRK, RENDER_EFFE, RENDER_BASC },
2616 		{ },
2617 		0
2618 	});
2619 	renderModePresets.push_back({
2620 		"Blob Display",
2621 		{ RENDER_FIRE, RENDER_SPRK, RENDER_EFFE, RENDER_BLOB },
2622 		{ },
2623 		0
2624 	});
2625 	renderModePresets.push_back({
2626 		"Heat Display",
2627 		{ RENDER_BASC },
2628 		{ DISPLAY_AIRH },
2629 		COLOUR_HEAT
2630 	});
2631 	renderModePresets.push_back({
2632 		"Fancy Display",
2633 		{ RENDER_FIRE, RENDER_SPRK, RENDER_GLOW, RENDER_BLUR, RENDER_EFFE, RENDER_BASC },
2634 		{ DISPLAY_WARP },
2635 		0
2636 	});
2637 	renderModePresets.push_back({
2638 		"Nothing Display",
2639 		{ RENDER_BASC },
2640 		{ },
2641 		0
2642 	});
2643 	renderModePresets.push_back({
2644 		"Heat Gradient Display",
2645 		{ RENDER_BASC },
2646 		{ },
2647 		COLOUR_GRAD
2648 	});
2649 	renderModePresets.push_back({
2650 		"Life Gradient Display",
2651 		{ RENDER_BASC },
2652 		{ },
2653 		COLOUR_LIFE
2654 	});
2655 
2656 	//Prepare the graphics cache
2657 	graphicscache = new gcache_item[PT_NUM];
2658 	std::fill(&graphicscache[0], &graphicscache[PT_NUM], gcache_item());
2659 
2660 	int fireColoursCount = 4;
2661 	pixel fireColours[] = {PIXPACK(0xAF9F0F), PIXPACK(0xDFBF6F), PIXPACK(0x60300F), PIXPACK(0x000000)};
2662 	float fireColoursPoints[] = {1.0f, 0.9f, 0.5f, 0.0f};
2663 
2664 	int plasmaColoursCount = 5;
2665 	pixel plasmaColours[] = {PIXPACK(0xAFFFFF), PIXPACK(0xAFFFFF), PIXPACK(0x301060), PIXPACK(0x301040), PIXPACK(0x000000)};
2666 	float plasmaColoursPoints[] = {1.0f, 0.9f, 0.5f, 0.25, 0.0f};
2667 
2668 	flm_data = Graphics::GenerateGradient(fireColours, fireColoursPoints, fireColoursCount, 200);
2669 	plasma_data = Graphics::GenerateGradient(plasmaColours, plasmaColoursPoints, plasmaColoursCount, 200);
2670 
2671 #ifdef OGLR
2672 	//FBO Texture
2673 	glEnable(GL_TEXTURE_2D);
2674 	glGenTextures(1, &partsFboTex);
2675 	glBindTexture(GL_TEXTURE_2D, partsFboTex);
2676 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, XRES, YRES, 0, GL_RGBA, GL_FLOAT, NULL);
2677 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
2678 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
2679 
2680 	//FBO
2681 	glGenFramebuffers(1, &partsFbo);
2682 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo);
2683 	glEnable(GL_BLEND);
2684 	glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, partsFboTex, 0);
2685 	glBindTexture(GL_TEXTURE_2D, 0);
2686 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // Reset framebuffer binding
2687 	glDisable(GL_TEXTURE_2D);
2688 
2689 	//Texture for air to be drawn
2690 	glEnable(GL_TEXTURE_2D);
2691 	glGenTextures(1, &airBuf);
2692 	glBindTexture(GL_TEXTURE_2D, airBuf);
2693 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, XRES/CELL, YRES/CELL, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
2694 
2695 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
2696 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
2697 
2698 	glBindTexture(GL_TEXTURE_2D, 0);
2699 	glDisable(GL_TEXTURE_2D);
2700 
2701 	//Zoom texture
2702 	glEnable(GL_TEXTURE_2D);
2703 	glGenTextures(1, &zoomTex);
2704 	glBindTexture(GL_TEXTURE_2D, zoomTex);
2705 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
2706 
2707 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
2708 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
2709 
2710 	glBindTexture(GL_TEXTURE_2D, 0);
2711 	glDisable(GL_TEXTURE_2D);
2712 
2713 	//Texture for velocity maps for gravity
2714 	glEnable(GL_TEXTURE_2D);
2715 	glGenTextures(1, &partsTFX);
2716 	glBindTexture(GL_TEXTURE_2D, partsTFX);
2717 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, XRES/CELL, YRES/CELL, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
2718 
2719 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
2720 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
2721 
2722 	glBindTexture(GL_TEXTURE_2D, 0);
2723 	glGenTextures(1, &partsTFY);
2724 	glBindTexture(GL_TEXTURE_2D, partsTFY);
2725 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, XRES/CELL, YRES/CELL, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
2726 
2727 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
2728 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
2729 
2730 	glBindTexture(GL_TEXTURE_2D, 0);
2731 	glDisable(GL_TEXTURE_2D);
2732 
2733 	//Texture for velocity maps for air
2734 	//TODO: Combine all air maps into 3D array or structs
2735 	glEnable(GL_TEXTURE_2D);
2736 	glGenTextures(1, &airVX);
2737 	glBindTexture(GL_TEXTURE_2D, airVX);
2738 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, XRES/CELL, YRES/CELL, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
2739 
2740 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
2741 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
2742 
2743 	glBindTexture(GL_TEXTURE_2D, 0);
2744 	glGenTextures(1, &airVY);
2745 	glBindTexture(GL_TEXTURE_2D, airVY);
2746 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, XRES/CELL, YRES/CELL, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
2747 
2748 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
2749 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
2750 
2751 	glBindTexture(GL_TEXTURE_2D, 0);
2752 	glGenTextures(1, &airPV);
2753 	glBindTexture(GL_TEXTURE_2D, airPV);
2754 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, XRES/CELL, YRES/CELL, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
2755 
2756 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
2757 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
2758 
2759 	glBindTexture(GL_TEXTURE_2D, 0);
2760 	glDisable(GL_TEXTURE_2D);
2761 
2762 	//Fire alpha texture
2763 	glEnable(GL_TEXTURE_2D);
2764 	glGenTextures(1, &fireAlpha);
2765 	glBindTexture(GL_TEXTURE_2D, fireAlpha);
2766 	glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, CELL*3, CELL*3, 0, GL_ALPHA, GL_FLOAT, NULL);
2767 
2768 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
2769 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
2770 
2771 	glBindTexture(GL_TEXTURE_2D, 0);
2772 	glDisable(GL_TEXTURE_2D);
2773 
2774 	//Glow alpha texture
2775 	glEnable(GL_TEXTURE_2D);
2776 	glGenTextures(1, &glowAlpha);
2777 	glBindTexture(GL_TEXTURE_2D, glowAlpha);
2778 	glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 11, 11, 0, GL_ALPHA, GL_FLOAT, NULL);
2779 
2780 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
2781 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
2782 
2783 	glBindTexture(GL_TEXTURE_2D, 0);
2784 	glDisable(GL_TEXTURE_2D);
2785 
2786 
2787 	//Blur Alpha texture
2788 	glEnable(GL_TEXTURE_2D);
2789 	glGenTextures(1, &blurAlpha);
2790 	glBindTexture(GL_TEXTURE_2D, blurAlpha);
2791 	glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 7, 7, 0, GL_ALPHA, GL_FLOAT, NULL);
2792 
2793 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
2794 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
2795 
2796 	glBindTexture(GL_TEXTURE_2D, 0);
2797 	glDisable(GL_TEXTURE_2D);
2798 
2799 	//Temptexture
2800 	glEnable(GL_TEXTURE_2D);
2801 	glGenTextures(1, &textTexture);
2802 	glBindTexture(GL_TEXTURE_2D, textTexture);
2803 
2804 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
2805 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
2806 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2807 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2808 
2809 	glBindTexture(GL_TEXTURE_2D, 0);
2810 	glDisable(GL_TEXTURE_2D);
2811 
2812 	loadShaders();
2813 #endif
2814 	prepare_alpha(CELL, 1.0f);
2815 }
2816 
CompileRenderMode()2817 void Renderer::CompileRenderMode()
2818 {
2819 	int old_render_mode = render_mode;
2820 	render_mode = 0;
2821 	for (size_t i = 0; i < render_modes.size(); i++)
2822 		render_mode |= render_modes[i];
2823 
2824 	//If firemode is removed, clear the fire display
2825 	if(!(render_mode & FIREMODE) && (old_render_mode & FIREMODE))
2826 	{
2827 		ClearAccumulation();
2828 	}
2829 }
2830 
ClearAccumulation()2831 void Renderer::ClearAccumulation()
2832 {
2833 	std::fill(fire_r[0]+0, fire_r[(YRES/CELL)-1]+((XRES/CELL)-1), 0);
2834 	std::fill(fire_g[0]+0, fire_g[(YRES/CELL)-1]+((XRES/CELL)-1), 0);
2835 	std::fill(fire_b[0]+0, fire_b[(YRES/CELL)-1]+((XRES/CELL)-1), 0);
2836 #ifndef OGLR
2837 	std::fill(persistentVid, persistentVid+(VIDXRES*YRES), 0);
2838 #endif
2839 }
2840 
AddRenderMode(unsigned int mode)2841 void Renderer::AddRenderMode(unsigned int mode)
2842 {
2843 	for (size_t i = 0; i < render_modes.size(); i++)
2844 	{
2845 		if(render_modes[i] == mode)
2846 		{
2847 			return;
2848 		}
2849 	}
2850 	render_modes.push_back(mode);
2851 	CompileRenderMode();
2852 }
2853 
RemoveRenderMode(unsigned int mode)2854 void Renderer::RemoveRenderMode(unsigned int mode)
2855 {
2856 	for (size_t i = 0; i < render_modes.size(); i++)
2857 	{
2858 		if(render_modes[i] == mode)
2859 		{
2860 			render_modes.erase(render_modes.begin() + i);
2861 			i = 0;
2862 		}
2863 	}
2864 	CompileRenderMode();
2865 }
2866 
SetRenderMode(std::vector<unsigned int> render)2867 void Renderer::SetRenderMode(std::vector<unsigned int> render)
2868 {
2869 	render_modes = render;
2870 	CompileRenderMode();
2871 }
2872 
GetRenderMode()2873 std::vector<unsigned int> Renderer::GetRenderMode()
2874 {
2875 	return render_modes;
2876 }
2877 
CompileDisplayMode()2878 void Renderer::CompileDisplayMode()
2879 {
2880 	int old_display_mode = display_mode;
2881 	display_mode = 0;
2882 	for (size_t i = 0; i < display_modes.size(); i++)
2883 		display_mode |= display_modes[i];
2884 	if (!(display_mode & DISPLAY_PERS) && (old_display_mode & DISPLAY_PERS))
2885 	{
2886 		ClearAccumulation();
2887 	}
2888 }
2889 
AddDisplayMode(unsigned int mode)2890 void Renderer::AddDisplayMode(unsigned int mode)
2891 {
2892 	for (size_t i = 0; i < display_modes.size(); i++)
2893 	{
2894 		if (display_modes[i] == mode)
2895 		{
2896 			return;
2897 		}
2898 		if (display_modes[i] & DISPLAY_AIR)
2899 		{
2900 			display_modes.erase(display_modes.begin()+i);
2901 		}
2902 	}
2903 	display_modes.push_back(mode);
2904 	CompileDisplayMode();
2905 }
2906 
RemoveDisplayMode(unsigned int mode)2907 void Renderer::RemoveDisplayMode(unsigned int mode)
2908 {
2909 	for (size_t i = 0; i < display_modes.size(); i++)
2910 	{
2911 		if (display_modes[i] == mode)
2912 		{
2913 			display_modes.erase(display_modes.begin() + i);
2914 			i = 0;
2915 		}
2916 	}
2917 	CompileDisplayMode();
2918 }
2919 
SetDisplayMode(std::vector<unsigned int> display)2920 void Renderer::SetDisplayMode(std::vector<unsigned int> display)
2921 {
2922 	display_modes = display;
2923 	CompileDisplayMode();
2924 }
2925 
GetDisplayMode()2926 std::vector<unsigned int> Renderer::GetDisplayMode()
2927 {
2928 	return display_modes;
2929 }
2930 
SetColourMode(unsigned int mode)2931 void Renderer::SetColourMode(unsigned int mode)
2932 {
2933 	colour_mode = mode;
2934 }
2935 
GetColourMode()2936 unsigned int Renderer::GetColourMode()
2937 {
2938 	return colour_mode;
2939 }
2940 
ResetModes()2941 void Renderer::ResetModes()
2942 {
2943 	SetRenderMode({ RENDER_BASC, RENDER_FIRE, RENDER_SPRK });
2944 	SetDisplayMode({ });
2945 	SetColourMode(COLOUR_DEFAULT);
2946 }
2947 
DumpFrame()2948 VideoBuffer Renderer::DumpFrame()
2949 {
2950 #ifdef OGLR
2951 #elif defined(OGLI)
2952 	VideoBuffer newBuffer(XRES, YRES);
2953 	std::copy(vid, vid+(XRES*YRES), newBuffer.Buffer);
2954 	return newBuffer;
2955 #else
2956 	VideoBuffer newBuffer(XRES, YRES);
2957 	for(int y = 0; y < YRES; y++)
2958 	{
2959 		std::copy(vid+(y*WINDOWW), vid+(y*WINDOWW)+XRES, newBuffer.Buffer+(y*XRES));
2960 	}
2961 	return newBuffer;
2962 #endif
2963 }
2964 
~Renderer()2965 Renderer::~Renderer()
2966 {
2967 #if !defined(OGLR)
2968 #if defined(OGLI)
2969 	delete[] vid;
2970 #endif
2971 	delete[] persistentVid;
2972 	delete[] warpVid;
2973 #endif
2974 	delete[] graphicscache;
2975 	free(flm_data);
2976 	free(plasma_data);
2977 }
2978 
2979 #define PIXELMETHODS_CLASS Renderer
2980 
2981 #ifdef OGLR
2982 #include "OpenGLDrawMethods.inl"
2983 #else
2984 #include "RasterDrawMethods.inl"
2985 #endif
2986 
2987 #undef PIXELMETHODS_CLASS
2988