summaryrefslogtreecommitdiff
path: root/src/graphics
diff options
context:
space:
mode:
authorSimon Robertshaw <simon@hardwired.org.uk>2012-11-17 19:44:09 (GMT)
committer Simon Robertshaw <simon@hardwired.org.uk>2012-11-17 19:44:09 (GMT)
commit058a2edd75debbd0297f92572316daa704bd379f (patch)
treead303f091f9a08b209b91eb34a9fcad996a3de69 /src/graphics
parente3594aba9e05c6865d396418c028049cda92c2f3 (diff)
parent7a21ae192fe19868539956f3fe28e62b2c7c4429 (diff)
downloadpowder-058a2edd75debbd0297f92572316daa704bd379f.zip
powder-058a2edd75debbd0297f92572316daa704bd379f.tar.gz
Merge branch 'master' of github.com:FacialTurd/PowderToypp
Diffstat (limited to 'src/graphics')
-rw-r--r--src/graphics/DrawMethodsDef.inc17
-rw-r--r--src/graphics/Graphics.cpp1028
-rw-r--r--src/graphics/Graphics.h248
-rw-r--r--src/graphics/OpenGLDrawMethods.inl350
-rw-r--r--src/graphics/OpenGLGraphics.cpp95
-rw-r--r--src/graphics/OpenGLHeaders.h24
-rw-r--r--src/graphics/RasterDrawMethods.inl366
-rw-r--r--src/graphics/RasterGraphics.cpp45
-rw-r--r--src/graphics/Renderer.cpp2719
-rw-r--r--src/graphics/Renderer.h184
10 files changed, 5076 insertions, 0 deletions
diff --git a/src/graphics/DrawMethodsDef.inc b/src/graphics/DrawMethodsDef.inc
new file mode 100644
index 0000000..4aee0c9
--- /dev/null
+++ b/src/graphics/DrawMethodsDef.inc
@@ -0,0 +1,17 @@
+ int drawtext(int x, int y, const char *s, int r, int g, int b, int a);
+ int drawtext(int x, int y, std::string s, int r, int g, int b, int a);
+ int drawchar(int x, int y, int c, int r, int g, int b, int a);
+ int addchar(int x, int y, int c, int r, int g, int b, int a);
+
+ void xor_pixel(int x, int y);
+ void xor_line(int x, int y, int x2, int y2);
+ void xor_rect(int x, int y, int width, int height);
+ void xor_bitmap(unsigned char * bitmap, int x, int y, int w, int h);
+
+ void draw_line(int x, int y, int x2, int y2, int r, int g, int b, int a);
+ void drawrect(int x, int y, int width, int height, int r, int g, int b, int a);
+ void fillrect(int x, int y, int width, int height, int r, int g, int b, int a);
+ void clearrect(int x, int y, int width, int height);
+ void gradientrect(int x, int y, int width, int height, int r, int g, int b, int a, int r2, int g2, int b2, int a2);
+
+ void draw_image(pixel *img, int x, int y, int w, int h, int a); \ No newline at end of file
diff --git a/src/graphics/Graphics.cpp b/src/graphics/Graphics.cpp
new file mode 100644
index 0000000..11dcac3
--- /dev/null
+++ b/src/graphics/Graphics.cpp
@@ -0,0 +1,1028 @@
+#include <cmath>
+#include <iostream>
+#include <bzlib.h>
+#include <string>
+#include "Config.h"
+#include "Misc.h"
+#include "Graphics.h"
+#define INCLUDE_FONTDATA
+#include "font.h"
+
+VideoBuffer::VideoBuffer(int width, int height):
+ Width(width),
+ Height(height)
+{
+ Buffer = new pixel[width*height];
+ std::fill(Buffer, Buffer+(width*height), 0);
+};
+
+VideoBuffer::VideoBuffer(const VideoBuffer & old):
+ Width(old.Width),
+ Height(old.Height)
+{
+ Buffer = new pixel[old.Width*old.Height];
+ std::copy(old.Buffer, old.Buffer+(old.Width*old.Height), Buffer);
+};
+
+VideoBuffer::VideoBuffer(VideoBuffer * old):
+ Width(old->Width),
+ Height(old->Height)
+{
+ Buffer = new pixel[old->Width*old->Height];
+ std::copy(old->Buffer, old->Buffer+(old->Width*old->Height), Buffer);
+};
+
+void VideoBuffer::Resize(float factor, bool resample)
+{
+ int newWidth = ((float)Width)*factor;
+ int newHeight = ((float)Height)*factor;
+ pixel * newBuffer;
+ if(resample)
+ newBuffer = Graphics::resample_img(Buffer, Width, Height, newWidth, newHeight);
+ else
+ newBuffer = Graphics::resample_img_nn(Buffer, Width, Height, newWidth, newHeight);
+
+ if(newBuffer)
+ {
+ delete[] Buffer;
+ Buffer = newBuffer;
+ Width = newWidth;
+ Height = newHeight;
+ }
+}
+
+int VideoBuffer::SetCharacter(int x, int y, int c, int r, int g, int b, int a)
+{
+ int i, j, w, bn = 0, ba = 0;
+ char *rp = font_data + font_ptrs[c];
+ w = *(rp++);
+ for (j=0; j<FONT_H; j++)
+ for (i=0; i<w; i++)
+ {
+ if (!bn)
+ {
+ ba = *(rp++);
+ bn = 8;
+ }
+ SetPixel(x+i, y+j, r, g, b, ((ba&3)*a)/3);
+ ba >>= 2;
+ bn -= 2;
+ }
+ return x + w;
+}
+
+int VideoBuffer::BlendCharacter(int x, int y, int c, int r, int g, int b, int a)
+{
+ int i, j, w, bn = 0, ba = 0;
+ char *rp = font_data + font_ptrs[c];
+ w = *(rp++);
+ for (j=0; j<FONT_H; j++)
+ for (i=0; i<w; i++)
+ {
+ if (!bn)
+ {
+ ba = *(rp++);
+ bn = 8;
+ }
+ BlendPixel(x+i, y+j, r, g, b, ((ba&3)*a)/3);
+ ba >>= 2;
+ bn -= 2;
+ }
+ return x + w;
+}
+
+int VideoBuffer::AddCharacter(int x, int y, int c, int r, int g, int b, int a)
+{
+ int i, j, w, bn = 0, ba = 0;
+ char *rp = font_data + font_ptrs[c];
+ w = *(rp++);
+ for (j=0; j<FONT_H; j++)
+ for (i=0; i<w; i++)
+ {
+ if (!bn)
+ {
+ ba = *(rp++);
+ bn = 8;
+ }
+ AddPixel(x+i, y+j, r, g, b, ((ba&3)*a)/3);
+ ba >>= 2;
+ bn -= 2;
+ }
+ return x + w;
+}
+
+VideoBuffer::~VideoBuffer()
+{
+ delete[] Buffer;
+};
+
+/**
+ * Common graphics functions, mostly static methods that provide
+ * encoding/decoding of different formats and font metrics
+ */
+
+char * Graphics::GenerateGradient(pixel * colours, float * points, int pointcount, int size)
+{
+ int cp, i, j;
+ pixel ptemp;
+ char * newdata = (char*)malloc(size * 3);
+ float poss, pose, temp;
+ memset(newdata, 0, size*3);
+ //Sort the Colours and Points
+ for (i = (pointcount - 1); i > 0; i--)
+ {
+ for (j = 1; j <= i; j++)
+ {
+ if (points[j-1] > points[j])
+ {
+ temp = points[j-1];
+ points[j-1] = points[j];
+ points[j] = temp;
+
+ ptemp = colours[j-1];
+ colours[j-1] = colours[j];
+ colours[j] = ptemp;
+ }
+ }
+ }
+ i = 0;
+ j = 1;
+ poss = points[i];
+ pose = points[j];
+ for (cp = 0; cp < size; cp++)
+ {
+ float cpos = (float)cp / (float)size, ccpos, cccpos;
+ if(cpos > pose && j+1 < pointcount)
+ {
+ poss = points[++i];
+ pose = points[++j];
+ }
+ ccpos = cpos - poss;
+ cccpos = ccpos / (pose - poss);
+ if(cccpos > 1.0f)
+ cccpos = 1.0f;
+ newdata[(cp*3)] = PIXR(colours[i])*(1.0f-cccpos) + PIXR(colours[j])*(cccpos);
+ newdata[(cp*3)+1] = PIXG(colours[i])*(1.0f-cccpos) + PIXG(colours[j])*(cccpos);
+ newdata[(cp*3)+2] = PIXB(colours[i])*(1.0f-cccpos) + PIXB(colours[j])*(cccpos);
+ }
+ return newdata;
+}
+
+void *Graphics::ptif_pack(pixel *src, int w, int h, int *result_size){
+ int i = 0, datalen = (w*h)*3, cx = 0, cy = 0;
+ unsigned char *red_chan = (unsigned char*)calloc(1, w*h);
+ unsigned char *green_chan = (unsigned char*)calloc(1, w*h);
+ unsigned char *blue_chan = (unsigned char*)calloc(1, w*h);
+ unsigned char *data = (unsigned char*)malloc(((w*h)*3)+8);
+ unsigned char *result = (unsigned char*)malloc(((w*h)*3)+8);
+
+ for(cx = 0; cx<w; cx++){
+ for(cy = 0; cy<h; cy++){
+ red_chan[w*(cy)+(cx)] = PIXR(src[w*(cy)+(cx)]);
+ green_chan[w*(cy)+(cx)] = PIXG(src[w*(cy)+(cx)]);
+ blue_chan[w*(cy)+(cx)] = PIXB(src[w*(cy)+(cx)]);
+ }
+ }
+
+ memcpy(data, red_chan, w*h);
+ memcpy(data+(w*h), green_chan, w*h);
+ memcpy(data+((w*h)*2), blue_chan, w*h);
+ free(red_chan);
+ free(green_chan);
+ free(blue_chan);
+
+ result[0] = 'P';
+ result[1] = 'T';
+ result[2] = 'i';
+ result[3] = 1;
+ result[4] = w;
+ result[5] = w>>8;
+ result[6] = h;
+ result[7] = h>>8;
+
+ i -= 8;
+
+ if(BZ2_bzBuffToBuffCompress((char *)(result+8), (unsigned *)&i, (char *)data, datalen, 9, 0, 0) != 0){
+ free(data);
+ free(result);
+ return NULL;
+ }
+
+ *result_size = i+8;
+ free(data);
+ return result;
+}
+
+pixel *Graphics::ptif_unpack(void *datain, int size, int *w, int *h){
+ int width, height, i, cx, cy, resCode;
+ unsigned char *red_chan;
+ unsigned char *green_chan;
+ unsigned char *blue_chan;
+ unsigned char *data = (unsigned char*)datain;
+ unsigned char *undata;
+ pixel *result;
+ if(size<16){
+ printf("Image empty\n");
+ return NULL;
+ }
+ if(!(data[0]=='P' && data[1]=='T' && data[2]=='i')){
+ printf("Image header invalid\n");
+ return NULL;
+ }
+ width = data[4]|(data[5]<<8);
+ height = data[6]|(data[7]<<8);
+
+ i = (width*height)*3;
+ undata = (unsigned char*)calloc(1, (width*height)*3);
+ red_chan = (unsigned char*)calloc(1, width*height);
+ green_chan = (unsigned char*)calloc(1, width*height);
+ blue_chan = (unsigned char *)calloc(1, width*height);
+ result = (pixel *)calloc(width*height, PIXELSIZE);
+
+ resCode = BZ2_bzBuffToBuffDecompress((char *)undata, (unsigned *)&i, (char *)(data+8), size-8, 0, 0);
+ if (resCode){
+ printf("Decompression failure, %d\n", resCode);
+ free(red_chan);
+ free(green_chan);
+ free(blue_chan);
+ free(undata);
+ free(result);
+ return NULL;
+ }
+ if(i != (width*height)*3){
+ printf("Result buffer size mismatch, %d != %d\n", i, (width*height)*3);
+ free(red_chan);
+ free(green_chan);
+ free(blue_chan);
+ free(undata);
+ free(result);
+ return NULL;
+ }
+ memcpy(red_chan, undata, width*height);
+ memcpy(green_chan, undata+(width*height), width*height);
+ memcpy(blue_chan, undata+((width*height)*2), width*height);
+
+ for(cx = 0; cx<width; cx++){
+ for(cy = 0; cy<height; cy++){
+ result[width*(cy)+(cx)] = PIXRGB(red_chan[width*(cy)+(cx)], green_chan[width*(cy)+(cx)], blue_chan[width*(cy)+(cx)]);
+ }
+ }
+
+ *w = width;
+ *h = height;
+ free(red_chan);
+ free(green_chan);
+ free(blue_chan);
+ free(undata);
+ return result;
+}
+
+pixel *Graphics::resample_img_nn(pixel * src, int sw, int sh, int rw, int rh)
+{
+ int y, x;
+ pixel *q = NULL;
+ q = (pixel *)malloc(rw*rh*PIXELSIZE);
+ for (y=0; y<rh; y++)
+ for (x=0; x<rw; x++){
+ q[rw*y+x] = src[sw*(y*sh/rh)+(x*sw/rw)];
+ }
+ return q;
+}
+
+pixel *Graphics::resample_img(pixel *src, int sw, int sh, int rw, int rh)
+{
+#ifdef DEBUG
+ std::cout << "Resampling " << sw << "x" << sh << " to " << rw << "x" << rh << std::endl;
+#endif
+ bool stairstep = false;
+ if(rw < sw || rh < sh)
+ {
+ float fx = (float)(((float)sw)/((float)rw));
+ float fy = (float)(((float)sh)/((float)rh));
+
+ int fxint, fyint;
+ double fxintp_t, fyintp_t;
+
+ float fxf = modf(fx, &fxintp_t), fyf = modf(fy, &fyintp_t);
+ fxint = fxintp_t;
+ fyint = fyintp_t;
+
+ if(((fxint & (fxint-1)) == 0 && fxf < 0.1f) || ((fyint & (fyint-1)) == 0 && fyf < 0.1f))
+ stairstep = true;
+
+#ifdef DEBUG
+ if(stairstep)
+ std::cout << "Downsampling by " << fx << "x" << fy << " using stairstepping" << std::endl;
+ else
+ std::cout << "Downsampling by " << fx << "x" << fy << " without stairstepping" << std::endl;
+#endif
+ }
+
+ int y, x, fxceil, fyceil;
+ //int i,j,x,y,w,h,r,g,b,c;
+ pixel *q = NULL;
+ if(rw == sw && rh == sh){
+ //Don't resample
+ q = (pixel *)malloc(rw*rh*PIXELSIZE);
+ memcpy(q, src, rw*rh*PIXELSIZE);
+ } else if(!stairstep) {
+ float fx, fy, fyc, fxc;
+ double intp;
+ pixel tr, tl, br, bl;
+ q = (pixel *)malloc(rw*rh*PIXELSIZE);
+ //Bilinear interpolation for upscaling
+ for (y=0; y<rh; y++)
+ for (x=0; x<rw; x++)
+ {
+ fx = ((float)x)*((float)sw)/((float)rw);
+ fy = ((float)y)*((float)sh)/((float)rh);
+ fxc = modf(fx, &intp);
+ fyc = modf(fy, &intp);
+ fxceil = (int)ceil(fx);
+ fyceil = (int)ceil(fy);
+ if (fxceil>=sw) fxceil = sw-1;
+ if (fyceil>=sh) fyceil = sh-1;
+ tr = src[sw*(int)floor(fy)+fxceil];
+ tl = src[sw*(int)floor(fy)+(int)floor(fx)];
+ br = src[sw*fyceil+fxceil];
+ bl = src[sw*fyceil+(int)floor(fx)];
+ q[rw*y+x] = PIXRGB(
+ (int)(((((float)PIXR(tl))*(1.0f-fxc))+(((float)PIXR(tr))*(fxc)))*(1.0f-fyc) + ((((float)PIXR(bl))*(1.0f-fxc))+(((float)PIXR(br))*(fxc)))*(fyc)),
+ (int)(((((float)PIXG(tl))*(1.0f-fxc))+(((float)PIXG(tr))*(fxc)))*(1.0f-fyc) + ((((float)PIXG(bl))*(1.0f-fxc))+(((float)PIXG(br))*(fxc)))*(fyc)),
+ (int)(((((float)PIXB(tl))*(1.0f-fxc))+(((float)PIXB(tr))*(fxc)))*(1.0f-fyc) + ((((float)PIXB(bl))*(1.0f-fxc))+(((float)PIXB(br))*(fxc)))*(fyc))
+ );
+ }
+ } else {
+ //Stairstepping
+ float fx, fy, fyc, fxc;
+ double intp;
+ pixel tr, tl, br, bl;
+ int rrw = rw, rrh = rh;
+ pixel * oq;
+ oq = (pixel *)malloc(sw*sh*PIXELSIZE);
+ memcpy(oq, src, sw*sh*PIXELSIZE);
+ rw = sw;
+ rh = sh;
+ while(rrw != rw && rrh != rh){
+ if(rw > rrw)
+ rw *= 0.7;
+ if(rh > rrh)
+ rh *= 0.7;
+ if(rw <= rrw)
+ rw = rrw;
+ if(rh <= rrh)
+ rh = rrh;
+ q = (pixel *)malloc(rw*rh*PIXELSIZE);
+ //Bilinear interpolation
+ for (y=0; y<rh; y++)
+ for (x=0; x<rw; x++)
+ {
+ fx = ((float)x)*((float)sw)/((float)rw);
+ fy = ((float)y)*((float)sh)/((float)rh);
+ fxc = modf(fx, &intp);
+ fyc = modf(fy, &intp);
+ fxceil = (int)ceil(fx);
+ fyceil = (int)ceil(fy);
+ if (fxceil>=sw) fxceil = sw-1;
+ if (fyceil>=sh) fyceil = sh-1;
+ tr = oq[sw*(int)floor(fy)+fxceil];
+ tl = oq[sw*(int)floor(fy)+(int)floor(fx)];
+ br = oq[sw*fyceil+fxceil];
+ bl = oq[sw*fyceil+(int)floor(fx)];
+ q[rw*y+x] = PIXRGB(
+ (int)(((((float)PIXR(tl))*(1.0f-fxc))+(((float)PIXR(tr))*(fxc)))*(1.0f-fyc) + ((((float)PIXR(bl))*(1.0f-fxc))+(((float)PIXR(br))*(fxc)))*(fyc)),
+ (int)(((((float)PIXG(tl))*(1.0f-fxc))+(((float)PIXG(tr))*(fxc)))*(1.0f-fyc) + ((((float)PIXG(bl))*(1.0f-fxc))+(((float)PIXG(br))*(fxc)))*(fyc)),
+ (int)(((((float)PIXB(tl))*(1.0f-fxc))+(((float)PIXB(tr))*(fxc)))*(1.0f-fyc) + ((((float)PIXB(bl))*(1.0f-fxc))+(((float)PIXB(br))*(fxc)))*(fyc))
+ );
+ }
+ free(oq);
+ oq = q;
+ sw = rw;
+ sh = rh;
+ }
+ }
+ return q;
+}
+
+pixel *Graphics::rescale_img(pixel *src, int sw, int sh, int *qw, int *qh, int f)
+{
+ int i,j,x,y,w,h,r,g,b,c;
+ pixel p, *q;
+ w = (sw+f-1)/f;
+ h = (sh+f-1)/f;
+ q = (pixel *)malloc(w*h*PIXELSIZE);
+ for (y=0; y<h; y++)
+ for (x=0; x<w; x++)
+ {
+ r = g = b = c = 0;
+ for (j=0; j<f; j++)
+ for (i=0; i<f; i++)
+ if (x*f+i<sw && y*f+j<sh)
+ {
+ p = src[(y*f+j)*sw + (x*f+i)];
+ if (p)
+ {
+ r += PIXR(p);
+ g += PIXG(p);
+ b += PIXB(p);
+ c ++;
+ }
+ }
+ if (c>1)
+ {
+ r = (r+c/2)/c;
+ g = (g+c/2)/c;
+ b = (b+c/2)/c;
+ }
+ q[y*w+x] = PIXRGB(r, g, b);
+ }
+ *qw = w;
+ *qh = h;
+ return q;
+}
+
+int Graphics::textwidth(const char *s)
+{
+ int x = 0;
+ for (; *s; s++)
+ x += font_data[font_ptrs[(int)(*(unsigned char *)s)]];
+ return x-1;
+}
+
+int Graphics::CharWidth(char c)
+{
+ return font_data[font_ptrs[(int)c]];
+}
+
+int Graphics::textnwidth(char *s, int n)
+{
+ int x = 0;
+ for (; *s; s++)
+ {
+ if (!n)
+ break;
+ if(((char)*s)=='\b')
+ {
+ if(!s[1]) break;
+ s++;
+ continue;
+ } else if(*s == '\x0F') {
+ if(!s[1] || !s[2] || !s[3]) break;
+ s+=3;
+ continue;
+ }
+ x += font_data[font_ptrs[(int)(*(unsigned char *)s)]];
+ n--;
+ }
+ return x-1;
+}
+
+void Graphics::textnpos(char *s, int n, int w, int *cx, int *cy)
+{
+ int x = 0;
+ int y = 0;
+ int wordlen, charspace;
+ while (*s&&n)
+ {
+ wordlen = strcspn(s," .,!?\n");
+ charspace = textwidthx(s, w-x);
+ if (charspace<wordlen && wordlen && w-x<w/3)
+ {
+ x = 0;
+ y += FONT_H+2;
+ }
+ for (; *s && --wordlen>=-1; s++)
+ {
+ if (!n) {
+ break;
+ }
+ x += font_data[font_ptrs[(int)(*(unsigned char *)s)]];
+ if (x>=w)
+ {
+ x = 0;
+ y += FONT_H+2;
+ }
+ n--;
+ }
+ }
+ *cx = x-1;
+ *cy = y;
+}
+
+int Graphics::textwidthx(char *s, int w)
+{
+ int x=0,n=0,cw;
+ for (; *s; s++)
+ {
+ if((char)*s == '\b')
+ {
+ if(!s[1]) break;
+ s++;
+ continue;
+ } else if (*s == '\x0F')
+ {
+ if(!s[1] || !s[2] || !s[3]) break;
+ s+=3;
+ continue;
+ }
+ cw = font_data[font_ptrs[(int)(*(unsigned char *)s)]];
+ if (x+(cw/2) >= w)
+ break;
+ x += cw;
+ n++;
+ }
+ return n;
+}
+
+int Graphics::PositionAtCharIndex(char *s, int charIndex, int & positionX, int & positionY)
+{
+ int x = 0, y = 0, lines = 1;
+ for (; *s; s++)
+ {
+ if (!charIndex)
+ break;
+ if(*s == '\n') {
+ lines++;
+ x = 0;
+ y += FONT_H+2;
+ charIndex--;
+ continue;
+ } else if(*s =='\b') {
+ if(!s[1]) break;
+ s++;
+ charIndex-=2;
+ continue;
+ } else if(*s == '\x0F') {
+ if(!s[1] || !s[2] || !s[3]) break;
+ s+=3;
+ charIndex-=4;
+ continue;
+ }
+ x += font_data[font_ptrs[(int)(*(unsigned char *)s)]];
+ charIndex--;
+ }
+ positionX = x;
+ positionY = y;
+ return lines;
+}
+
+int Graphics::CharIndexAtPosition(char *s, int positionX, int positionY)
+{
+ int x=0, y=0,charIndex=0,cw;
+ for (; *s; s++)
+ {
+ if(*s == '\n') {
+ x = 0;
+ y += FONT_H+2;
+ charIndex++;
+ continue;
+ } else if(*s == '\b') {
+ if(!s[1]) break;
+ s++;
+ charIndex+=2;
+ continue;
+ } else if (*s == '\x0F') {
+ if(!s[1] || !s[2] || !s[3]) break;
+ s+=3;
+ charIndex+=4;
+ continue;
+ }
+ cw = font_data[font_ptrs[(int)(*(unsigned char *)s)]];
+ if ((x+(cw/2) >= positionX && y+FONT_H >= positionY) || y > positionY)
+ break;
+ x += cw;
+ charIndex++;
+ }
+ return charIndex;
+}
+
+
+int Graphics::textposxy(char *s, int width, int w, int h)
+{
+ int x=0,y=0,n=0,cw, wordlen, charspace;
+ while (*s)
+ {
+ wordlen = strcspn(s," .,!?\n");
+ charspace = textwidthx(s, width-x);
+ if (charspace<wordlen && wordlen && width-x<width/3)
+ {
+ x = 0;
+ y += FONT_H+2;
+ }
+ for (; *s && --wordlen>=-1; s++)
+ {
+ cw = font_data[font_ptrs[(int)(*(unsigned char *)s)]];
+ if ((x+(cw/2) >= w && y+6 >= h)||(y+6 >= h+FONT_H+2))
+ return n++;
+ x += cw;
+ if (x>=width) {
+ x = 0;
+ y += FONT_H+2;
+ }
+ n++;
+ }
+ }
+ return n;
+}
+int Graphics::textwrapheight(char *s, int width)
+{
+ int x=0, height=FONT_H+2, cw;
+ int wordlen;
+ int charspace;
+ while (*s)
+ {
+ wordlen = strcspn(s," .,!?\n");
+ charspace = textwidthx(s, width-x);
+ if (charspace<wordlen && wordlen && width-x<width/3)
+ {
+ x = 0;
+ height += FONT_H+2;
+ }
+ for (; *s && --wordlen>=-1; s++)
+ {
+ if (*s == '\n')
+ {
+ x = 0;
+ height += FONT_H+2;
+ }
+ else if (*s == '\b')
+ {
+ if(!s[1]) break;
+ s++;
+ }
+ else if (*s == '\x0F')
+ {
+ if(!s[1] || !s[2] || !s[3]) break;
+ s+=3;
+ }
+ else
+ {
+ cw = font_data[font_ptrs[(int)(*(unsigned char *)s)]];
+ if (x+cw>=width)
+ {
+ x = 0;
+ height += FONT_H+2;
+ }
+ x += cw;
+ }
+ }
+ }
+ return height;
+}
+
+void Graphics::textsize(const char * s, int & width, int & height)
+{
+ if(!strlen(s))
+ {
+ width = 0;
+ height = FONT_H;
+ return;
+ }
+
+ int cHeight = FONT_H, cWidth = 0, lWidth = 0;
+ for (; *s; s++)
+ {
+ if (*s == '\n')
+ {
+ cWidth = 0;
+ cHeight += FONT_H+2;
+ }
+ else if (*s == '\x0F')
+ {
+ if(!s[1] || !s[2] || !s[1]) break;
+ s+=3;
+ }
+ else if (*s == '\b')
+ {
+ if(!s[1]) break;
+ s++;
+ }
+ else
+ {
+ cWidth += font_data[font_ptrs[(int)(*(unsigned char *)s)]];
+ if(cWidth>lWidth)
+ lWidth = cWidth;
+ }
+ }
+ width = lWidth;
+ height = cHeight;
+}
+
+void Graphics::draw_icon(int x, int y, Icon icon, unsigned char alpha, bool invert)
+{
+ y--;
+ switch(icon)
+ {
+ case IconOpen:
+ if(invert)
+ drawchar(x, y, 0x81, 0, 0, 0, alpha);
+ else
+ drawchar(x, y, 0x81, 255, 255, 255, alpha);
+ break;
+ case IconReload:
+ if(invert)
+ drawchar(x, y, 0x91, 0, 0, 0, alpha);
+ else
+ drawchar(x, y, 0x91, 255, 255, 255, alpha);
+ break;
+ case IconSave:
+ if(invert)
+ drawchar(x, y, 0x82, 0, 0, 0, alpha);
+ else
+ drawchar(x, y, 0x82, 255, 255, 255, alpha);
+ break;
+ case IconVoteUp:
+ if(invert)
+ drawchar(x, y, 0xCB, 0, 100, 0, alpha);
+ else
+ drawchar(x, y, 0xCB, 0, 187, 18, alpha);
+ break;
+ case IconVoteDown:
+ if(invert)
+ drawchar(x, y, 0xCA, 100, 10, 0, alpha);
+ else
+ drawchar(x, y, 0xCA, 187, 40, 0, alpha);
+ break;
+ case IconTag:
+ if(invert)
+ drawchar(x, y, 0x83, 0, 0, 0, alpha);
+ else
+ drawchar(x, y, 0x83, 255, 255, 255, alpha);
+ break;
+ case IconNew:
+ if(invert)
+ drawchar(x, y, 0x92, 0, 0, 0, alpha);
+ else
+ drawchar(x, y, 0x92, 255, 255, 255, alpha);
+ break;
+ case IconLogin:
+ if(invert)
+ drawchar(x, y+1, 0x84, 0, 0, 0, alpha);
+ else
+ drawchar(x, y+1, 0x84, 255, 255, 255, alpha);
+ break;
+ case IconSimulationSettings:
+ if(invert)
+ drawchar(x, y+1, 0xCF, 0, 0, 0, alpha);
+ else
+ drawchar(x, y+1, 0xCF, 255, 255, 255, alpha);
+ break;
+ case IconRenderSettings:
+ if(invert)
+ {
+ drawchar(x, y+1, 0xD8, 255, 0, 0, alpha);
+ drawchar(x, y+1, 0xD9, 0, 255, 0, alpha);
+ drawchar(x, y+1, 0xDA, 0, 0, 255, alpha);
+ }
+ else
+ {
+ addchar(x, y+1, 0xD8, 255, 0, 0, alpha);
+ addchar(x, y+1, 0xD9, 0, 255, 0, alpha);
+ addchar(x, y+1, 0xDA, 0, 0, 255, alpha);
+ }
+ break;
+ case IconPause:
+ if(invert)
+ drawchar(x, y, 0x90, 0, 0, 0, alpha);
+ else
+ drawchar(x, y, 0x90, 255, 255, 255, alpha);
+ break;
+ case IconFavourite:
+ if(invert)
+ drawchar(x, y, 0xCC, 100, 80, 32, alpha);
+ else
+ drawchar(x, y, 0xCC, 192, 160, 64, alpha);
+ break;
+ case IconReport:
+ if(invert)
+ drawchar(x, y, 0xE3, 140, 140, 0, alpha);
+ else
+ drawchar(x, y, 0xE3, 255, 255, 0, alpha);
+ break;
+ case IconUsername:
+ if(invert)
+ {
+ drawchar(x, y, 0x8B, 32, 64, 128, alpha);
+ drawchar(x, y, 0x8A, 0, 0, 0, alpha);
+ }
+ else
+ {
+ drawchar(x, y, 0x8B, 32, 64, 128, alpha);
+ drawchar(x, y, 0x8A, 255, 255, 255, alpha);
+ }
+ break;
+ case IconPassword:
+ if(invert)
+ {
+ drawchar(x, y, 0x8C, 160, 144, 32, alpha);
+ drawchar(x, y, 0x84, 0, 0, 0, alpha);
+ }
+ else
+ {
+ drawchar(x, y, 0x8C, 160, 144, 32, alpha);
+ drawchar(x, y, 0x84, 255, 255, 255, alpha);
+ }
+ break;
+ case IconClose:
+ if(invert)
+ drawchar(x, y, 0xAA, 20, 20, 20, alpha);
+ else
+ drawchar(x, y, 0xAA, 230, 230, 230, alpha);
+ break;
+ case IconVoteSort:
+ if (invert)
+ {
+ drawchar(x, y, 0xA9, 44, 48, 32, alpha);
+ drawchar(x, y, 0xA8, 32, 44, 32, alpha);
+ drawchar(x, y, 0xA7, 128, 128, 128, alpha);
+ }
+ else
+ {
+ drawchar(x, y, 0xA9, 144, 48, 32, alpha);
+ drawchar(x, y, 0xA8, 32, 144, 32, alpha);
+ drawchar(x, y, 0xA7, 255, 255, 255, alpha);
+ }
+ break;
+ case IconDateSort:
+ if (invert)
+ {
+ drawchar(x, y, 0xA6, 32, 32, 32, alpha);
+ }
+ else
+ {
+ drawchar(x, y, 0xA6, 255, 255, 255, alpha);
+ }
+ break;
+ case IconMyOwn:
+ if (invert)
+ {
+ drawchar(x, y, 0x94, 192, 160, 64, alpha);
+ drawchar(x, y, 0x93, 32, 32, 32, alpha);
+ }
+ else
+ {
+ drawchar(x, y, 0x94, 192, 160, 64, alpha);
+ drawchar(x, y, 0x93, 255, 255, 255, alpha);
+ }
+ break;
+ case IconSearch:
+ drawchar(x, y, 0x8E, 30, 30, 180, alpha);
+ drawchar(x, y, 0x8F, 255, 255, 255, alpha);
+ break;
+ case IconDelete:
+ if(invert)
+ {
+ drawchar(x, y, 0x86, 159, 47, 31, alpha);
+ drawchar(x, y, 0x85, 0, 0, 0, alpha);
+ }
+ else
+ {
+ drawchar(x, y, 0x86, 159, 47, 31, alpha);
+ drawchar(x, y, 0x85, 255, 255, 255, alpha);
+ }
+ break;
+ case IconAdd:
+ if(invert)
+ {
+ drawchar(x, y, 0x86, 32, 144, 32, alpha);
+ drawchar(x, y, 0x89, 0, 0, 0, alpha);
+ }
+ else
+ {
+ drawchar(x, y, 0x86, 32, 144, 32, alpha);
+ drawchar(x, y, 0x89, 255, 255, 255, alpha);
+ }
+ break;
+ case IconVelocity:
+ drawchar(x+1, y, 0x98, 128, 160, 255, alpha);
+ break;
+ case IconPressure:
+ if(invert)
+ drawchar(x+1, y+1, 0x99, 180, 160, 16, alpha);
+ else
+ drawchar(x+1, y+1, 0x99, 255, 212, 32, alpha);
+ break;
+ case IconPersistant:
+ if(invert)
+ drawchar(x+1, y+1, 0x9A, 20, 20, 20, alpha);
+ else
+ drawchar(x+1, y+1, 0x9A, 212, 212, 212, alpha);
+ break;
+ case IconFire:
+ drawchar(x+1, y+1, 0x9B, 255, 0, 0, alpha);
+ drawchar(x+1, y+1, 0x9C, 255, 255, 64, alpha);
+ break;
+ case IconBlob:
+ if(invert)
+ drawchar(x+1, y, 0xBF, 55, 180, 55, alpha);
+ else
+ drawchar(x+1, y, 0xBF, 55, 255, 55, alpha);
+ break;
+ case IconHeat:
+ drawchar(x+3, y, 0xBE, 255, 0, 0, alpha);
+ if(invert)
+ drawchar(x+3, y, 0xBD, 0, 0, 0, alpha);
+ else
+ drawchar(x+3, y, 0xBD, 255, 255, 255, alpha);
+ break;
+ case IconBlur:
+ if(invert)
+ drawchar(x+1, y, 0xC4, 50, 70, 180, alpha);
+ else
+ drawchar(x+1, y, 0xC4, 100, 150, 255, alpha);
+ break;
+ case IconGradient:
+ if(invert)
+ drawchar(x+1, y+1, 0xD3, 255, 50, 255, alpha);
+ else
+ drawchar(x+1, y+1, 0xD3, 205, 50, 205, alpha);
+ break;
+ case IconLife:
+ if(invert)
+ drawchar(x, y+1, 0xE0, 0, 0, 0, alpha);
+ else
+ drawchar(x, y+1, 0xE0, 255, 255, 255, alpha);
+ break;
+ case IconEffect:
+ drawchar(x+1, y, 0xE1, 255, 255, 160, alpha);
+ break;
+ case IconGlow:
+ drawchar(x+1, y, 0xDF, 200, 255, 255, alpha);
+ break;
+ case IconWarp:
+ drawchar(x+1, y, 0xDE, 255, 255, 255, alpha);
+ break;
+ case IconBasic:
+ if(invert)
+ drawchar(x+1, y+1, 0xDB, 50, 50, 0, alpha);
+ else
+ drawchar(x+1, y+1, 0xDB, 255, 255, 200, alpha);
+ break;
+ case IconAltAir:
+ if(invert) {
+ drawchar(x+1, y+1, 0xD4, 180, 55, 55, alpha);
+ drawchar(x+1, y+1, 0xD5, 55, 180, 55, alpha);
+ } else {
+ drawchar(x+1, y+1, 0xD4, 255, 55, 55, alpha);
+ drawchar(x+1, y+1, 0xD5, 55, 255, 55, alpha);
+ }
+ break;
+ default:
+ if(invert)
+ drawchar(x, y, 't', 0, 0, 0, alpha);
+ else
+ drawchar(x, y, 't', 255, 255, 255, alpha);
+ break;
+ }
+}
+
+pixel *Graphics::render_packed_rgb(void *image, int width, int height, int cmp_size)
+{
+ unsigned char *tmp;
+ pixel *res;
+ int i;
+
+ tmp = (unsigned char *)malloc(width*height*3);
+ if (!tmp)
+ return NULL;
+ res = (pixel *)malloc(width*height*PIXELSIZE);
+ if (!res)
+ {
+ free(tmp);
+ return NULL;
+ }
+
+ i = width*height*3;
+ if (BZ2_bzBuffToBuffDecompress((char *)tmp, (unsigned *)&i, (char *)image, cmp_size, 0, 0))
+ {
+ free(res);
+ free(tmp);
+ return NULL;
+ }
+
+ for (i=0; i<width*height; i++)
+ res[i] = PIXRGB(tmp[3*i], tmp[3*i+1], tmp[3*i+2]);
+
+ free(tmp);
+ return res;
+}
+
+void Graphics::draw_image(const VideoBuffer & vidBuf, int x, int y, int a)
+{
+ draw_image(vidBuf.Buffer, x, y, vidBuf.Width, vidBuf.Height, a);
+}
+
+void Graphics::draw_image(VideoBuffer * vidBuf, int x, int y, int a)
+{
+ draw_image(vidBuf->Buffer, x, y, vidBuf->Width, vidBuf->Height, a);
+}
+
+VideoBuffer Graphics::DumpFrame()
+{
+#ifdef OGLI
+#else
+ VideoBuffer newBuffer(XRES+BARSIZE, YRES+MENUSIZE);
+ std::copy(vid, vid+((XRES+BARSIZE)*(YRES+MENUSIZE)), newBuffer.Buffer);
+ return newBuffer;
+#endif
+} \ No newline at end of file
diff --git a/src/graphics/Graphics.h b/src/graphics/Graphics.h
new file mode 100644
index 0000000..53d3ee7
--- /dev/null
+++ b/src/graphics/Graphics.h
@@ -0,0 +1,248 @@
+#ifndef GRAPHICS_H
+#define GRAPHICS_H
+
+#include <string>
+#include <cstdlib>
+#include <cstring>
+#include <vector>
+#if defined(OGLI)
+#include "OpenGLHeaders.h"
+#endif
+#include "Config.h"
+//#include "powder.h"
+
+#ifdef PIX16
+#define PIXELSIZE 2
+#define PIXPACK(x) ((((x)>>8)&0xF800)|(((x)>>5)&0x07E0)|(((x)>>3)&0x001F))
+#define PIXRGB(r,g,b) ((((r)<<8)&0xF800)|(((g)<<3)&0x07E0)|(((b)>>3)&0x001F))
+#define PIXR(x) (((x)>>8)&0xF8)
+#define PIXG(x) (((x)>>3)&0xFC)
+#define PIXB(x) (((x)<<3)&0xF8)
+#else
+#define PIXELSIZE 4
+#ifdef PIX32BGR
+#define PIXPACK(x) ((((x)>>16)&0x0000FF)|((x)&0x00FF00)|(((x)<<16)&0xFF0000))
+#define PIXRGB(r,g,b) (((b)<<16)|((g)<<8)|((r)))// (((b)<<16)|((g)<<8)|(r))
+#define PIXR(x) ((x)&0xFF)
+#define PIXG(x) (((x)>>8)&0xFF)
+#define PIXB(x) ((x)>>16)
+#else
+#ifdef PIX32BGRA
+#define PIXPACK(x) ((((x)>>8)&0x0000FF00)|(((x)<<8)&0x00FF0000)|(((x)<<24)&0xFF000000))
+#define PIXRGB(r,g,b) (((b)<<24)|((g)<<16)|((r)<<8))
+#define PIXR(x) (((x)>>8)&0xFF)
+#define PIXG(x) (((x)>>16)&0xFF)
+#define PIXB(x) (((x)>>24))
+#elif defined(PIX32OGL)
+#define PIXPACK(x) (0xFF000000|((x)&0xFFFFFF))
+#define PIXRGB(r,g,b) (0xFF000000|((r)<<16)|((g)<<8)|((b)))// (((b)<<16)|((g)<<8)|(r))
+#define PIXRGBA(r,g,b,a) (((a)<<24)|((r)<<16)|((g)<<8)|((b)))// (((b)<<16)|((g)<<8)|(r))
+#define PIXA(x) (((x)>>24)&0xFF)
+#define PIXR(x) (((x)>>16)&0xFF)
+#define PIXG(x) (((x)>>8)&0xFF)
+#define PIXB(x) ((x)&0xFF)
+#else
+#define PIXPACK(x) (x)
+#define PIXRGB(r,g,b) (((r)<<16)|((g)<<8)|(b))
+#define PIXR(x) ((x)>>16)
+#define PIXG(x) (((x)>>8)&0xFF)
+#define PIXB(x) ((x)&0xFF)
+#endif
+#endif
+#endif
+
+#ifdef PIX16
+typedef unsigned short pixel;
+#else
+typedef unsigned int pixel;
+#endif
+
+//Icon names, see Graphics::draw_icon
+enum Icon
+{
+ NoIcon = 0,
+ IconOpen,
+ IconReload,
+ IconSave,
+ IconVoteUp,
+ IconVoteDown,
+ IconTag,
+ IconNew,
+ IconLogin,
+ IconRenderSettings,
+ IconSimulationSettings,
+ IconPause,
+ IconVoteSort,
+ IconDateSort,
+ IconMyOwn,
+ IconFavourite,
+ IconSearch,
+ IconDelete,
+ IconAdd,
+ IconReport,
+ IconUsername,
+ IconPassword,
+ IconClose,
+ IconEffect,
+ IconFire,
+ IconGlow,
+ IconBlur,
+ IconBlob,
+ IconBasic,
+ IconAltAir,
+ IconPressure,
+ IconVelocity,
+ IconWarp,
+ IconPersistant,
+ IconHeat,
+ IconLife,
+ IconGradient
+};
+
+//"Graphics lite" - slightly lower performance due to variable size,
+class VideoBuffer
+{
+public:
+ pixel * Buffer;
+ int Width, Height;
+
+ VideoBuffer(const VideoBuffer & old);
+ VideoBuffer(VideoBuffer * old);
+ VideoBuffer(int width, int height);
+ void Resize(float factor, bool resample = false);
+ TPT_INLINE void BlendPixel(int x, int y, int r, int g, int b, int a)
+ {
+ #ifdef PIX32OGL
+ pixel t;
+ if (x<0 || y<0 || x>=Width || y>=Height)
+ return;
+ if (a!=255)
+ {
+ t = Buffer[y*(Width)+x];
+ r = (a*r + (255-a)*PIXR(t)) >> 8;
+ g = (a*g + (255-a)*PIXG(t)) >> 8;
+ b = (a*b + (255-a)*PIXB(t)) >> 8;
+ a = a > PIXA(t) ? a : PIXA(t);
+ }
+ Buffer[y*(Width)+x] = PIXRGBA(r,g,b,a);
+ #else
+ pixel t;
+ if (x<0 || y<0 || x>=Width || y>=Height)
+ return;
+ if (a!=255)
+ {
+ t = Buffer[y*(Width)+x];
+ r = (a*r + (255-a)*PIXR(t)) >> 8;
+ g = (a*g + (255-a)*PIXG(t)) >> 8;
+ b = (a*b + (255-a)*PIXB(t)) >> 8;
+ }
+ Buffer[y*(Width)+x] = PIXRGB(r,g,b);
+ #endif
+ }
+
+ TPT_INLINE void SetPixel(int x, int y, int r, int g, int b, int a)
+ {
+ if (x<0 || y<0 || x>=Width || y>=Height)
+ return;
+ #ifdef PIX32OGL
+ Buffer[y*(Width)+x] = PIXRGBA(r,g,b,a);
+ #else
+ Buffer[y*(Width)+x] = PIXRGB((r*a)>>8, (g*a)>>8, (b*a)>>8);
+ #endif
+ }
+
+ TPT_INLINE void AddPixel(int x, int y, int r, int g, int b, int a)
+ {
+ pixel t;
+ if (x<0 || y<0 || x>=Width || y>=Height)
+ return;
+ t = Buffer[y*(Width)+x];
+ r = (a*r + 255*PIXR(t)) >> 8;
+ g = (a*g + 255*PIXG(t)) >> 8;
+ b = (a*b + 255*PIXB(t)) >> 8;
+ if (r>255)
+ r = 255;
+ if (g>255)
+ g = 255;
+ if (b>255)
+ b = 255;
+ Buffer[y*(Width)+x] = PIXRGB(r,g,b);
+ }
+ int SetCharacter(int x, int y, int c, int r, int g, int b, int a);
+ int BlendCharacter(int x, int y, int c, int r, int g, int b, int a);
+ int AddCharacter(int x, int y, int c, int r, int g, int b, int a);
+ ~VideoBuffer();
+};
+
+class Graphics
+{
+public:
+ pixel *vid;
+ int sdl_scale;
+#ifdef OGLI
+ //OpenGL specific instance variables
+ GLuint vidBuf, textTexture;
+ void Reset();
+ #endif
+
+ //Common graphics methods in Graphics.cpp
+ static char * GenerateGradient(pixel * colours, float * points, int pointcount, int size);
+
+ //PTIF methods
+ static void *ptif_pack(pixel *src, int w, int h, int *result_size);
+ static pixel *ptif_unpack(void *datain, int size, int *w, int *h);
+ static pixel *resample_img_nn(pixel *src, int sw, int sh, int rw, int rh);
+ static pixel *resample_img(pixel *src, int sw, int sh, int rw, int rh);
+ static pixel *rescale_img(pixel *src, int sw, int sh, int *qw, int *qh, int f);
+ static pixel *render_packed_rgb(void *image, int width, int height, int cmp_size);
+
+ //Font/text metrics
+ static int CharIndexAtPosition(char *s, int positionX, int positionY);
+ static int PositionAtCharIndex(char *s, int charIndex, int & positionX, int & positionY);
+ static int CharWidth(char c);
+ static int textnwidth(char *s, int n);
+ static void textnpos(char *s, int n, int w, int *cx, int *cy);
+ static int textwidthx(char *s, int w);
+ static int textposxy(char *s, int width, int w, int h);
+ static int textwrapheight(char *s, int width);
+ static int textwidth(const char *s);
+ static void textsize(const char * s, int & width, int & height);
+
+ VideoBuffer DumpFrame();
+
+ void Acquire();
+ void Release();
+
+ void blendpixel(int x, int y, int r, int g, int b, int a);
+ void addpixel(int x, int y, int r, int g, int b, int a);
+
+ void draw_icon(int x, int y, Icon icon, unsigned char alpha = 255, bool invert = false);
+
+ void Clear();
+ void Finalise();
+ //
+ int drawtext(int x, int y, const char *s, int r, int g, int b, int a);
+ int drawtext(int x, int y, std::string s, int r, int g, int b, int a);
+ int drawchar(int x, int y, int c, int r, int g, int b, int a);
+ int addchar(int x, int y, int c, int r, int g, int b, int a);
+
+ void xor_pixel(int x, int y);
+ void xor_line(int x, int y, int x2, int y2);
+ void xor_rect(int x, int y, int width, int height);
+ void xor_bitmap(unsigned char * bitmap, int x, int y, int w, int h);
+
+ void draw_line(int x, int y, int x2, int y2, int r, int g, int b, int a);
+ void drawrect(int x, int y, int width, int height, int r, int g, int b, int a);
+ void fillrect(int x, int y, int width, int height, int r, int g, int b, int a);
+ void clearrect(int x, int y, int width, int height);
+ void gradientrect(int x, int y, int width, int height, int r, int g, int b, int a, int r2, int g2, int b2, int a2);
+
+ void draw_image(pixel *img, int x, int y, int w, int h, int a);
+ void draw_image(const VideoBuffer & vidBuf, int w, int h, int a);
+ void draw_image(VideoBuffer * vidBuf, int w, int h, int a);
+
+ Graphics();
+ ~Graphics();
+};
+
+#endif
diff --git a/src/graphics/OpenGLDrawMethods.inl b/src/graphics/OpenGLDrawMethods.inl
new file mode 100644
index 0000000..1ecd6b1
--- /dev/null
+++ b/src/graphics/OpenGLDrawMethods.inl
@@ -0,0 +1,350 @@
+#include "../data/font.h"
+int PIXELMETHODS_CLASS::drawtext(int x, int y, const char *s, int r, int g, int b, int a)
+{
+ bool invert = false;
+ if(!strlen(s))
+ return 0;
+ int oR = r, oG = g, oB = b;
+ int width, height;
+ Graphics::textsize(s, width, height);
+ VideoBuffer texture(width, height);
+ int characterX = 0, characterY = 0;
+ int startX = characterX;
+ for (; *s; s++)
+ {
+ if (*s == '\n')
+ {
+ characterX = startX;
+ characterY += FONT_H+2;
+ }
+ else if (*s == '\x0F')
+ {
+ if(!s[1] || !s[2] || !s[3]) break;
+ oR = r;
+ oG = g;
+ oB = b;
+ r = (unsigned char)s[1];
+ g = (unsigned char)s[2];
+ b = (unsigned char)s[3];
+ s += 3;
+ }
+ else if (*s == '\x0E')
+ {
+ r = oR;
+ g = oG;
+ b = oB;
+ }
+ else if (*s == '\x01')
+ {
+ invert = !invert;
+ r = 255-r;
+ g = 255-g;
+ b = 255-b;
+ }
+ else if (*s == '\b')
+ {
+ if(!s[1]) break;
+ switch (s[1])
+ {
+ case 'w':
+ r = g = b = 255;
+ break;
+ case 'g':
+ r = g = b = 192;
+ break;
+ case 'o':
+ r = 255;
+ g = 216;
+ b = 32;
+ break;
+ case 'r':
+ r = 255;
+ g = b = 0;
+ break;
+ case 'l':
+ r = 255;
+ g = b = 75;
+ break;
+ case 'b':
+ r = g = 0;
+ b = 255;
+ break;
+ case 't':
+ b = 255;
+ g = 170;
+ r = 32;
+ break;
+ }
+ if(invert)
+ {
+ r = 255-r;
+ g = 255-g;
+ b = 255-b;
+ }
+ s++;
+ }
+ else
+ {
+ characterX = texture.SetCharacter(characterX, characterY, *(unsigned char *)s, r, g, b, a);
+ }
+ }
+ glEnable(GL_TEXTURE_2D);
+
+ //Generate texture
+ glBindTexture(GL_TEXTURE_2D, textTexture);
+
+ //Draw texture
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.Width, texture.Height, 0, GL_BGRA, GL_UNSIGNED_BYTE, texture.Buffer);
+
+ //glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture.Width, texture.Height, GL_BGRA, GL_UNSIGNED_BYTE, texture.Buffer);
+ glBegin(GL_QUADS);
+ glTexCoord2d(0, 0);
+ glVertex2f(x, y);
+ glTexCoord2d(1, 0);
+ glVertex2f(x+texture.Width, y);
+ glTexCoord2d(1, 1);
+ glVertex2f(x+texture.Width, y+texture.Height);
+ glTexCoord2d(0, 1);
+ glVertex2f(x, y+texture.Height);
+ glEnd();
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+
+ return x;
+}
+
+int PIXELMETHODS_CLASS::drawtext(int x, int y, std::string s, int r, int g, int b, int a)
+{
+ return drawtext(x, y, s.c_str(), r, g, b, a);
+}
+
+TPT_INLINE int PIXELMETHODS_CLASS::drawchar(int x, int y, int c, int r, int g, int b, int a)
+{
+ int i, j, w, bn = 0, ba = 0;
+ char *rp = font_data + font_ptrs[c];
+ w = *(rp++);
+ VideoBuffer texture(w, 12);
+ texture.SetCharacter(0, 0, c, r, g, b, a);
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, textTexture);
+
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.Width, texture.Height, 0, GL_BGRA, GL_UNSIGNED_BYTE, texture.Buffer);
+ glBegin(GL_QUADS);
+ glTexCoord2d(0, 0);
+ glVertex2f(x, y);
+ glTexCoord2d(1, 0);
+ glVertex2f(x+texture.Width, y);
+ glTexCoord2d(1, 1);
+ glVertex2f(x+texture.Width, y+texture.Height);
+ glTexCoord2d(0, 1);
+ glVertex2f(x, y+texture.Height);
+ glEnd();
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+
+ return x + w;
+}
+
+TPT_NO_INLINE int PIXELMETHODS_CLASS::addchar(int x, int y, int c, int r, int g, int b, int a)
+{
+ int i, j, w, bn = 0, ba = 0;
+ char *rp = font_data + font_ptrs[c];
+ w = *(rp++);
+ VideoBuffer texture(w, 12);
+ texture.AddCharacter(0, 0, c, r, g, b, a);
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, textTexture);
+ glBlendFunc(GL_ONE, GL_ONE);
+
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.Width, texture.Height, 0, GL_BGRA, GL_UNSIGNED_BYTE, texture.Buffer);
+ glBegin(GL_QUADS);
+ glTexCoord2d(0, 0);
+ glVertex2f(x, y);
+ glTexCoord2d(1, 0);
+ glVertex2f(x+texture.Width, y);
+ glTexCoord2d(1, 1);
+ glVertex2f(x+texture.Width, y+texture.Height);
+ glTexCoord2d(0, 1);
+ glVertex2f(x, y+texture.Height);
+ glEnd();
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+
+ return x + w;
+}
+
+TPT_INLINE void PIXELMETHODS_CLASS::xor_pixel(int x, int y)
+{
+ //OpenGL doesn't support single pixel manipulation, there are ways around it, but with poor performance
+}
+
+TPT_INLINE void PIXELMETHODS_CLASS::blendpixel(int x, int y, int r, int g, int b, int a)
+{
+ //OpenGL doesn't support single pixel manipulation, there are ways around it, but with poor performance
+}
+
+TPT_INLINE void PIXELMETHODS_CLASS::addpixel(int x, int y, int r, int g, int b, int a)
+{
+ //OpenGL doesn't support single pixel manipulation, there are ways around it, but with poor performance
+}
+
+void PIXELMETHODS_CLASS::xor_line(int x, int y, int x2, int y2)
+{
+ glEnable(GL_COLOR_LOGIC_OP);
+ //glEnable(GL_LINE_SMOOTH);
+ glLogicOp(GL_XOR);
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ glBegin(GL_LINES);
+ glVertex2i(x, y);
+ glVertex2i(x2, y2);
+ glEnd();
+ glDisable(GL_COLOR_LOGIC_OP);
+}
+
+void PIXELMETHODS_CLASS::xor_rect(int x, int y, int width, int height)
+{
+ glEnable(GL_COLOR_LOGIC_OP);
+ //glEnable(GL_LINE_SMOOTH);
+ glLogicOp(GL_XOR);
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ glBegin(GL_LINE_STRIP);
+ glVertex2i(x, y);
+ glVertex2i(x+width, y);
+ glVertex2i(x+width, y+height);
+ glVertex2i(x, y+height);
+ glVertex2i(x, y);
+ glEnd();
+ glDisable(GL_COLOR_LOGIC_OP);
+}
+
+void PIXELMETHODS_CLASS::xor_bitmap(unsigned char * bitmap, int x, int y, int w, int h)
+{
+ //glEnable(GL_COLOR_LOGIC_OP);
+ //glLogicOp(GL_XOR);
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, textTexture);
+
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap);
+
+ glBegin(GL_QUADS);
+ glTexCoord2d(0, 0);
+ glVertex2f(x, y);
+ glTexCoord2d(1, 0);
+ glVertex2f(x+w, y);
+ glTexCoord2d(1, 1);
+ glVertex2f(x+w, y+h);
+ glTexCoord2d(0, 1);
+ glVertex2f(x, y+h);
+ glEnd();
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+ //glDisable(GL_COLOR_LOGIC_OP);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+}
+
+void PIXELMETHODS_CLASS::draw_line(int x, int y, int x2, int y2, int r, int g, int b, int a)
+{
+ a = 255;
+ glColor4ub(r, g, b, a);
+ glBegin(GL_LINES);
+ glVertex2i(x, y);
+ glVertex2i(x2, y2);
+ glEnd();
+}
+
+void PIXELMETHODS_CLASS::drawrect(int x, int y, int width, int height, int r, int g, int b, int a)
+{
+ float fx = float(x)+0.5f;
+ float fy = float(y)+0.5f;
+ float fwidth = width-1.0f;
+ float fheight = height-1.0f;
+ //x++;
+ //y++;
+ //height-=2;
+ //width-=2;
+ glColor4ub(r, g, b, a);
+ glBegin(GL_LINE_STRIP);
+ glVertex2f(fx, fy);
+ glVertex2f(fx+fwidth, fy);
+ glVertex2f(fx+fwidth, fy+fheight);
+ glVertex2f(fx, fy+fheight); //+1 is a hack to prevent squares from missing their corners, will make smoothed lines look like SHIT
+ glVertex2f(fx, fy);
+ glEnd();
+}
+
+void PIXELMETHODS_CLASS::fillrect(int x, int y, int width, int height, int r, int g, int b, int a)
+{
+ /*x++;
+ y++;
+ width-=1;
+ height-=1;*/
+
+ glColor4ub(r, g, b, a);
+ glBegin(GL_QUADS);
+ glVertex2i(x, y);
+ glVertex2i(x+width, y);
+ glVertex2i(x+width, y+height);
+ glVertex2i(x, y+height);
+ glEnd();
+}
+
+void PIXELMETHODS_CLASS::gradientrect(int x, int y, int width, int height, int r, int g, int b, int a, int r2, int g2, int b2, int a2)
+{
+ glBegin(GL_QUADS);
+ glColor4ub(r, g, b, a);
+ glVertex2i(x, y);
+ glColor4ub(r2, g2, b2, a2);
+ glVertex2i(x+width, y);
+ glColor4ub(r2, g2, b2, a2);
+ glVertex2i(x+width, y+height);
+ glColor4ub(r, g, b, a);
+ glVertex2i(x, y+height);
+ glEnd();
+}
+
+void PIXELMETHODS_CLASS::clearrect(int x, int y, int width, int height)
+{
+ glColor4ub(0, 0, 0, 255);
+ glBegin(GL_QUADS);
+ glVertex2i(x, y);
+ glVertex2i(x+width, y);
+ glVertex2i(x+width, y+height);
+ glVertex2i(x, y+height);
+ glEnd();
+}
+
+void PIXELMETHODS_CLASS::draw_image(pixel *img, int x, int y, int w, int h, int a)
+{
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, textTexture);
+
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, img);
+ glBegin(GL_QUADS);
+ glTexCoord2d(0, 0);
+ glVertex2f(x, y);
+ glTexCoord2d(1, 0);
+ glVertex2f(x+w, y);
+ glTexCoord2d(1, 1);
+ glVertex2f(x+w, y+h);
+ glTexCoord2d(0, 1);
+ glVertex2f(x, y+h);
+ glEnd();
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+}
diff --git a/src/graphics/OpenGLGraphics.cpp b/src/graphics/OpenGLGraphics.cpp
new file mode 100644
index 0000000..4f1d5d4
--- /dev/null
+++ b/src/graphics/OpenGLGraphics.cpp
@@ -0,0 +1,95 @@
+#include "Graphics.h"
+#include "font.h"
+#include <pthread.h>
+#ifdef GetUserName
+#undef GetUserName //God dammit microsoft!
+#endif
+#ifdef OGLI
+
+static pthread_mutex_t gMutex = PTHREAD_MUTEX_INITIALIZER;
+//static pthread_mutex_t TMPMUT = PTHREAD_MUTEX_INITIALIZER;
+Graphics::Graphics():
+ sdl_scale(1)
+{
+// if(gMutex == TMPMUT)
+// pthread_mutex_init (&gMutex, NULL);
+ Reset();
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ //Texture for main UI
+ glEnable(GL_TEXTURE_2D);
+
+ glGenTextures(1, &vidBuf);
+ glBindTexture(GL_TEXTURE_2D, vidBuf);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, XRES+BARSIZE, YRES+MENUSIZE, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glGenTextures(1, &textTexture);
+ glBindTexture(GL_TEXTURE_2D, textTexture);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glDisable(GL_TEXTURE_2D);
+}
+
+void Graphics::Acquire()
+{
+ pthread_mutex_lock(&gMutex);
+}
+
+void Graphics::Release()
+{
+ pthread_mutex_unlock(&gMutex);
+}
+
+Graphics::~Graphics()
+{
+}
+
+void Graphics::Reset()
+{
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ //glOrtho(0, (XRES+BARSIZE)*sdl_scale, 0, (YRES+MENUSIZE)*sdl_scale, -1, 1);
+ glOrtho(0, (XRES+BARSIZE)*sdl_scale, (YRES+MENUSIZE)*sdl_scale, 0, -1, 1);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ //glRasterPos2i(0, (YRES+MENUSIZE));
+ glRasterPos2i(0, 0);
+ glPixelZoom(1, 1);
+}
+
+void Graphics::Clear()
+{
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+void Graphics::Finalise()
+{
+ glFlush();
+}
+
+#define VIDXRES XRES+BARSIZE
+#define VIDYRES YRES+MENUSIZE
+#define PIXELMETHODS_CLASS Graphics
+#include "OpenGLDrawMethods.inl"
+#undef VIDYRES
+#undef VIDXRES
+#undef PIXELMETHODS_CLASS
+
+
+#endif
diff --git a/src/graphics/OpenGLHeaders.h b/src/graphics/OpenGLHeaders.h
new file mode 100644
index 0000000..de692e0
--- /dev/null
+++ b/src/graphics/OpenGLHeaders.h
@@ -0,0 +1,24 @@
+#ifdef MACOSX
+
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
+#include <OpenGL/gl3.h>
+#include <OpenGL/glu.h>
+#else
+//#include <GL/glew.h>
+#include <OpenGL/gl.h>
+#include <OpenGL/glu.h>
+#define GL_RGBA32F 0x8814
+#endif
+
+#elif defined(WIN)
+
+#include <GL/glew.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+#else
+
+#include <GL/glew.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#endif
diff --git a/src/graphics/RasterDrawMethods.inl b/src/graphics/RasterDrawMethods.inl
new file mode 100644
index 0000000..55a64c9
--- /dev/null
+++ b/src/graphics/RasterDrawMethods.inl
@@ -0,0 +1,366 @@
+#include "font.h"
+
+int PIXELMETHODS_CLASS::drawtext(int x, int y, const char *s, int r, int g, int b, int a)
+{
+ if(!strlen(s))
+ return 0;
+ int width, height;
+
+ int invert = 0;
+ int oR = r, oG = g, oB = b;
+ int characterX = x, characterY = y;
+ int startX = characterX;
+ for (; *s; s++)
+ {
+ if (*s == '\n')
+ {
+ characterX = startX;
+ characterY += FONT_H+2;
+ }
+ else if (*s == '\x0F')
+ {
+ if(!s[1] || !s[2] || !s[3]) break;
+ oR = r;
+ oG = g;
+ oB = b;
+ r = (unsigned char)s[1];
+ g = (unsigned char)s[2];
+ b = (unsigned char)s[3];
+ s += 3;
+ }
+ else if (*s == '\x0E')
+ {
+ r = oR;
+ g = oG;
+ b = oB;
+ }
+ else if (*s == '\x01')
+ {
+ invert = !invert;
+ r = 255-r;
+ g = 255-g;
+ b = 255-b;
+ }
+ else if (*s == '\b')
+ {
+ if(!s[1]) break;
+ switch (s[1])
+ {
+ case 'w':
+ r = g = b = 255;
+ break;
+ case 'g':
+ r = g = b = 192;
+ break;
+ case 'o':
+ r = 255;
+ g = 216;
+ b = 32;
+ break;
+ case 'r':
+ r = 255;
+ g = b = 0;
+ break;
+ case 'l':
+ r = 255;
+ g = b = 75;
+ break;
+ case 'b':
+ r = g = 0;
+ b = 255;
+ break;
+ case 't':
+ b = 255;
+ g = 170;
+ r = 32;
+ break;
+ }
+ if(invert)
+ {
+ r = 255-r;
+ g = 255-g;
+ b = 255-b;
+ }
+ s++;
+ }
+ else
+ {
+ characterX = drawchar(characterX, characterY, *(unsigned char *)s, r, g, b, a);
+ }
+ }
+ return x;
+}
+
+int PIXELMETHODS_CLASS::drawtext(int x, int y, std::string s, int r, int g, int b, int a)
+{
+ return drawtext(x, y, s.c_str(), r, g, b, a);
+}
+
+TPT_INLINE int PIXELMETHODS_CLASS::drawchar(int x, int y, int c, int r, int g, int b, int a)
+{
+ int i, j, w, bn = 0, ba = 0;
+ char *rp = font_data + font_ptrs[c];
+ w = *(rp++);
+ for (j=0; j<FONT_H; j++)
+ for (i=0; i<w; i++)
+ {
+ if (!bn)
+ {
+ ba = *(rp++);
+ bn = 8;
+ }
+ blendpixel(x+i, y+j, r, g, b, ((ba&3)*a)/3);
+ ba >>= 2;
+ bn -= 2;
+ }
+ return x + w;
+}
+
+TPT_NO_INLINE int PIXELMETHODS_CLASS::addchar(int x, int y, int c, int r, int g, int b, int a)
+{
+ int i, j, w, bn = 0, ba = 0;
+ char *rp = font_data + font_ptrs[c];
+ w = *(rp++);
+ for (j=0; j<FONT_H; j++)
+ for (i=0; i<w; i++)
+ {
+ if (!bn)
+ {
+ ba = *(rp++);
+ bn = 8;
+ }
+ {
+ addpixel(x+i, y+j, r, g, b, ((ba&3)*a)/3);
+ }
+ ba >>= 2;
+ bn -= 2;
+ }
+ return x + w;
+}
+
+TPT_INLINE void PIXELMETHODS_CLASS::xor_pixel(int x, int y)
+{
+ int c;
+ if (x<0 || y<0 || x>=XRES || y>=YRES)
+ return;
+ c = vid[y*(VIDXRES)+x];
+ c = PIXB(c) + 3*PIXG(c) + 2*PIXR(c);
+ if (c<512)
+ vid[y*(VIDXRES)+x] = PIXPACK(0xC0C0C0);
+ else
+ vid[y*(VIDXRES)+x] = PIXPACK(0x404040);
+}
+
+TPT_INLINE void PIXELMETHODS_CLASS::blendpixel(int x, int y, int r, int g, int b, int a)
+{
+ pixel t;
+ if (x<0 || y<0 || x>=VIDXRES || y>=VIDYRES)
+ return;
+ if (a!=255)
+ {
+ t = vid[y*(VIDXRES)+x];
+ r = (a*r + (255-a)*PIXR(t)) >> 8;
+ g = (a*g + (255-a)*PIXG(t)) >> 8;
+ b = (a*b + (255-a)*PIXB(t)) >> 8;
+ }
+ vid[y*(VIDXRES)+x] = PIXRGB(r,g,b);
+}
+
+TPT_INLINE void PIXELMETHODS_CLASS::addpixel(int x, int y, int r, int g, int b, int a)
+{
+ pixel t;
+ if (x<0 || y<0 || x>=VIDXRES || y>=VIDYRES)
+ return;
+ t = vid[y*(VIDXRES)+x];
+ r = (a*r + 255*PIXR(t)) >> 8;
+ g = (a*g + 255*PIXG(t)) >> 8;
+ b = (a*b + 255*PIXB(t)) >> 8;
+ if (r>255)
+ r = 255;
+ if (g>255)
+ g = 255;
+ if (b>255)
+ b = 255;
+ vid[y*(VIDXRES)+x] = PIXRGB(r,g,b);
+}
+
+void PIXELMETHODS_CLASS::xor_line(int x1, int y1, int x2, int y2)
+{
+ int cp=abs(y2-y1)>abs(x2-x1), x, y, dx, dy, sy;
+ float e, de;
+ if (cp)
+ {
+ y = x1;
+ x1 = y1;
+ y1 = y;
+ y = x2;
+ x2 = y2;
+ y2 = y;
+ }
+ if (x1 > x2)
+ {
+ y = x1;
+ x1 = x2;
+ x2 = y;
+ y = y1;
+ y1 = y2;
+ y2 = y;
+ }
+ dx = x2 - x1;
+ dy = abs(y2 - y1);
+ e = 0.0f;
+ if (dx)
+ de = dy/(float)dx;
+ else
+ de = 0.0f;
+ y = y1;
+ sy = (y1<y2) ? 1 : -1;
+ for (x=x1; x<=x2; x++)
+ {
+ if (cp)
+ xor_pixel(y, x);
+ else
+ xor_pixel(x, y);
+ e += de;
+ if (e >= 0.5f)
+ {
+ y += sy;
+ e -= 1.0f;
+ }
+ }
+}
+
+void PIXELMETHODS_CLASS::xor_rect(int x, int y, int w, int h)
+{
+ int i;
+ for (i=0; i<w; i+=2)
+ {
+ xor_pixel(x+i, y);
+ xor_pixel(x+i, y+h-1);
+ }
+ for (i=2; i<h; i+=2)
+ {
+ xor_pixel(x, y+i);
+ xor_pixel(x+w-1, y+i);
+ }
+}
+
+void PIXELMETHODS_CLASS::xor_bitmap(unsigned char * bitmap, int x, int y, int w, int h)
+{
+ for(int x1 = 0; x1 < w; x1++)
+ {
+ for(int y1 = 0; y1 < h; y1++)
+ {
+ if(bitmap[y1*w+x1])
+ xor_pixel(x+x1, y+y1);
+ }
+ }
+}
+
+void PIXELMETHODS_CLASS::draw_line(int x1, int y1, int x2, int y2, int r, int g, int b, int a)
+{
+ int cp=abs(y2-y1)>abs(x2-x1), x, y, dx, dy, sy;
+ float e, de;
+ if (cp)
+ {
+ y = x1;
+ x1 = y1;
+ y1 = y;
+ y = x2;
+ x2 = y2;
+ y2 = y;
+ }
+ if (x1 > x2)
+ {
+ y = x1;
+ x1 = x2;
+ x2 = y;
+ y = y1;
+ y1 = y2;
+ y2 = y;
+ }
+ dx = x2 - x1;
+ dy = abs(y2 - y1);
+ e = 0.0f;
+ if (dx)
+ de = dy/(float)dx;
+ else
+ de = 0.0f;
+ y = y1;
+ sy = (y1<y2) ? 1 : -1;
+ for (x=x1; x<=x2; x++)
+ {
+ if (cp)
+ blendpixel(y, x, r, g, b, a);
+ else
+ blendpixel(x, y, r, g, b, a);
+ e += de;
+ if (e >= 0.5f)
+ {
+ y += sy;
+ e -= 1.0f;
+ }
+ }
+}
+
+void PIXELMETHODS_CLASS::drawrect(int x, int y, int w, int h, int r, int g, int b, int a)
+{
+ int i;
+ w--;
+ h--;
+ for (i=0; i<=w; i++)
+ {
+ blendpixel(x+i, y, r, g, b, a);
+ blendpixel(x+i, y+h, r, g, b, a);
+ }
+ for (i=1; i<h; i++)
+ {
+ blendpixel(x, y+i, r, g, b, a);
+ blendpixel(x+w, y+i, r, g, b, a);
+ }
+}
+
+void PIXELMETHODS_CLASS::fillrect(int x, int y, int w, int h, int r, int g, int b, int a)
+{
+ int i,j;
+ for (j=0; j<h; j++)
+ for (i=0; i<w; i++)
+ blendpixel(x+i, y+j, r, g, b, a);
+}
+
+void PIXELMETHODS_CLASS::gradientrect(int x, int y, int width, int height, int r, int g, int b, int a, int r2, int g2, int b2, int a2)
+{
+
+}
+
+void PIXELMETHODS_CLASS::clearrect(int x, int y, int w, int h)
+{
+ int i;
+ for (i=1; i<h; i++)
+ memset(vid+(x+1+(VIDXRES)*(y+i)), 0, PIXELSIZE*(w-1));
+}
+
+void PIXELMETHODS_CLASS::draw_image(pixel *img, int x, int y, int w, int h, int a)
+{
+ int i, j, r, g, b;
+ if (!img) return;
+ if(y + h > VIDYRES) h = ((VIDYRES)-y)-1; //Adjust height to prevent drawing off the bottom
+ if(!h || y < 0) return;
+ if(a >= 255)
+ for (j=0; j<h; j++)
+ for (i=0; i<w; i++)
+ {
+ vid[(y+j)*(VIDXRES)+(x+i)] = *img;
+ img++;
+ }
+ else
+ for (j=0; j<h; j++)
+ for (i=0; i<w; i++)
+ {
+ r = PIXR(*img);
+ g = PIXG(*img);
+ b = PIXB(*img);
+ blendpixel(x+i, y+j, r, g, b, a);
+ img++;
+ }
+} \ No newline at end of file
diff --git a/src/graphics/RasterGraphics.cpp b/src/graphics/RasterGraphics.cpp
new file mode 100644
index 0000000..2a485e5
--- /dev/null
+++ b/src/graphics/RasterGraphics.cpp
@@ -0,0 +1,45 @@
+#include "Graphics.h"
+
+#ifndef OGLI
+
+Graphics::Graphics():
+sdl_scale(1)
+{
+ vid = (pixel *)malloc(PIXELSIZE * ((XRES+BARSIZE) * (YRES+MENUSIZE)));
+
+}
+
+void Graphics::Acquire()
+{
+
+}
+
+void Graphics::Release()
+{
+
+}
+
+Graphics::~Graphics()
+{
+ free(vid);
+}
+
+void Graphics::Clear()
+{
+ memset(vid, 0, PIXELSIZE * ((XRES+BARSIZE) * (YRES+MENUSIZE)));
+}
+
+void Graphics::Finalise()
+{
+
+}
+
+#define VIDXRES XRES+BARSIZE
+#define VIDYRES YRES+MENUSIZE
+#define PIXELMETHODS_CLASS Graphics
+#include "RasterDrawMethods.inl"
+#undef VIDYRES
+#undef VIDXRES
+#undef PIXELMETHODS_CLASS
+
+#endif
diff --git a/src/graphics/Renderer.cpp b/src/graphics/Renderer.cpp
new file mode 100644
index 0000000..eaec74c
--- /dev/null
+++ b/src/graphics/Renderer.cpp
@@ -0,0 +1,2719 @@
+/*
+ * Renderer.cpp
+ *
+ * Created on: Jan 7, 2012
+ * Author: Simon
+ */
+#include <cmath>
+#include <iostream>
+#include <vector>
+#include <stdio.h>
+#include <stdlib.h>
+#include "Config.h"
+#include "Renderer.h"
+#include "Graphics.h"
+#include "simulation/Elements.h"
+#include "simulation/ElementGraphics.h"
+#include "simulation/Air.h"
+extern "C"
+{
+#include "hmap.h"
+#ifdef OGLR
+#include "Shaders.h"
+#endif
+}
+
+#ifndef OGLI
+#define VIDXRES (XRES+BARSIZE)
+#define VIDYRES (YRES+MENUSIZE)
+#else
+#define VIDXRES XRES
+#define VIDYRES YRES
+#endif
+
+
+void Renderer::RenderBegin()
+{
+#ifdef OGLI
+#ifdef OGLR
+ draw_air();
+ draw_grav();
+ DrawWalls();
+ render_parts();
+ render_fire();
+ draw_other();
+ draw_grav_zones();
+ DrawSigns();
+
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFbo);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo);
+ glTranslated(0, MENUSIZE, 0);
+#else
+ if(display_mode & DISPLAY_PERS)
+ {
+ std::copy(persistentVid, persistentVid+(VIDXRES*YRES), vid);
+ }
+ pixel * oldVid;
+ if(display_mode & DISPLAY_WARP)
+ {
+ oldVid = vid;
+ vid = warpVid;
+ std::fill(warpVid, warpVid+(VIDXRES*VIDYRES), 0);
+ }
+
+ draw_air();
+ draw_grav();
+ DrawWalls();
+ render_parts();
+
+ if(display_mode & DISPLAY_PERS)
+ {
+ int i,r,g,b;
+ for (i = 0; i < VIDXRES*YRES; i++)
+ {
+ r = PIXR(vid[i]);
+ g = PIXG(vid[i]);
+ b = PIXB(vid[i]);
+ if (r>0)
+ r--;
+ if (g>0)
+ g--;
+ if (b>0)
+ b--;
+ persistentVid[i] = PIXRGB(r,g,b);
+ }
+ }
+
+ render_fire();
+ draw_other();
+ draw_grav_zones();
+ DrawSigns();
+ if(display_mode & DISPLAY_WARP)
+ {
+ vid = oldVid;
+ }
+#endif
+#else
+ if(display_mode & DISPLAY_PERS)
+ {
+ std::copy(persistentVid, persistentVid+(VIDXRES*YRES), vid);
+ }
+ pixel * oldVid;
+ if(display_mode & DISPLAY_WARP)
+ {
+ oldVid = vid;
+ vid = warpVid;
+ std::fill(warpVid, warpVid+(VIDXRES*VIDYRES), 0);
+ }
+
+ draw_air();
+ draw_grav();
+ DrawWalls();
+ render_parts();
+ if(display_mode & DISPLAY_PERS)
+ {
+ int i,r,g,b;
+ for (i = 0; i < VIDXRES*YRES; i++)
+ {
+ r = PIXR(vid[i]);
+ g = PIXG(vid[i]);
+ b = PIXB(vid[i]);
+ if (r>0)
+ r--;
+ if (g>0)
+ g--;
+ if (b>0)
+ b--;
+ persistentVid[i] = PIXRGB(r,g,b);
+ }
+ }
+
+ render_fire();
+ draw_other();
+ draw_grav_zones();
+ DrawSigns();
+
+ if(display_mode & DISPLAY_WARP)
+ {
+ vid = oldVid;
+ }
+
+ FinaliseParts();
+#endif
+}
+
+void Renderer::RenderEnd()
+{
+#ifdef OGLI
+#ifdef OGLR
+ glTranslated(0, -MENUSIZE, 0);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFbo);
+ FinaliseParts();
+ RenderZoom();
+#else
+ RenderZoom();
+ FinaliseParts();
+#endif
+#else
+ RenderZoom();
+#endif
+}
+
+void Renderer::clearScreen(float alpha)
+{
+#ifdef OGLR
+ GLint prevFbo;
+ if(alpha > 0.999f)
+ {
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFbo);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFbo);
+ }
+ else
+ {
+ glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
+ glColor4f(1.0f, 1.0f, 1.0f, alpha);
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFbo);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo);
+ glBegin(GL_QUADS);
+ glVertex2f(0, 0);
+ glVertex2f(XRES, 0);
+ glVertex2f(XRES, YRES);
+ glVertex2f(0, YRES);
+ glEnd();
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFbo);
+ glBlendEquation(GL_FUNC_ADD);
+ }
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+#endif
+#ifdef OGLI
+#ifndef OGLR
+ std::fill(vid, vid+(VIDXRES*VIDYRES), 0);
+#endif
+#else
+ g->Clear();
+#endif
+}
+#ifdef OGLR
+void Renderer::checkShader(GLuint shader, char * shname)
+{
+ GLint status;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
+ if (status == GL_FALSE)
+ {
+ char errorBuf[ GL_INFO_LOG_LENGTH];
+ int errLen;
+ glGetShaderInfoLog(shader, GL_INFO_LOG_LENGTH, &errLen, errorBuf);
+ fprintf(stderr, "Failed to compile %s shader:\n%s\n", shname, errorBuf);
+ exit(1);
+ }
+}
+void Renderer::checkProgram(GLuint program, char * progname)
+{
+ GLint status;
+ glGetProgramiv(program, GL_LINK_STATUS, &status);
+ if (status == GL_FALSE)
+ {
+ char errorBuf[ GL_INFO_LOG_LENGTH];
+ int errLen;
+ glGetShaderInfoLog(program, GL_INFO_LOG_LENGTH, &errLen, errorBuf);
+ fprintf(stderr, "Failed to link %s program:\n%s\n", progname, errorBuf);
+ exit(1);
+ }
+}
+void Renderer::loadShaders()
+{
+ GLuint vertexShader, fragmentShader;
+
+ //Particle texture
+ vertexShader = glCreateShader(GL_VERTEX_SHADER);
+ fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
+
+ glShaderSource( vertexShader, 1, &fireVertex, NULL);
+ glShaderSource( fragmentShader, 1, &fireFragment, NULL);
+
+ glCompileShader( vertexShader );
+ checkShader(vertexShader, "FV");
+ glCompileShader( fragmentShader );
+ checkShader(fragmentShader, "FF");
+
+ fireProg = glCreateProgram();
+ glAttachShader( fireProg, vertexShader );
+ glAttachShader( fireProg, fragmentShader );
+ glLinkProgram( fireProg );
+ checkProgram(fireProg, "F");
+
+ //Lensing
+ vertexShader = glCreateShader(GL_VERTEX_SHADER);
+ fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
+
+ glShaderSource( vertexShader, 1, &lensVertex, NULL);
+ glShaderSource( fragmentShader, 1, &lensFragment, NULL);
+
+ glCompileShader( vertexShader );
+ checkShader(vertexShader, "LV");
+ glCompileShader( fragmentShader );
+ checkShader(fragmentShader, "LF");
+
+ lensProg = glCreateProgram();
+ glAttachShader( lensProg, vertexShader );
+ glAttachShader( lensProg, fragmentShader );
+ glLinkProgram( lensProg );
+ checkProgram(lensProg, "L");
+
+ //Air Velocity
+ vertexShader = glCreateShader(GL_VERTEX_SHADER);
+ fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
+
+ glShaderSource( vertexShader, 1, &airVVertex, NULL);
+ glShaderSource( fragmentShader, 1, &airVFragment, NULL);
+
+ glCompileShader( vertexShader );
+ checkShader(vertexShader, "AVX");
+ glCompileShader( fragmentShader );
+ checkShader(fragmentShader, "AVF");
+
+ airProg_Velocity = glCreateProgram();
+ glAttachShader( airProg_Velocity, vertexShader );
+ glAttachShader( airProg_Velocity, fragmentShader );
+ glLinkProgram( airProg_Velocity );
+ checkProgram(airProg_Velocity, "AV");
+
+ //Air Pressure
+ vertexShader = glCreateShader(GL_VERTEX_SHADER);
+ fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
+
+ glShaderSource( vertexShader, 1, &airPVertex, NULL);
+ glShaderSource( fragmentShader, 1, &airPFragment, NULL);
+
+ glCompileShader( vertexShader );
+ checkShader(vertexShader, "APV");
+ glCompileShader( fragmentShader );
+ checkShader(fragmentShader, "APF");
+
+ airProg_Pressure = glCreateProgram();
+ glAttachShader( airProg_Pressure, vertexShader );
+ glAttachShader( airProg_Pressure, fragmentShader );
+ glLinkProgram( airProg_Pressure );
+ checkProgram(airProg_Pressure, "AP");
+
+ //Air cracker
+ vertexShader = glCreateShader(GL_VERTEX_SHADER);
+ fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
+
+ glShaderSource( vertexShader, 1, &airCVertex, NULL);
+ glShaderSource( fragmentShader, 1, &airCFragment, NULL);
+
+ glCompileShader( vertexShader );
+ checkShader(vertexShader, "ACV");
+ glCompileShader( fragmentShader );
+ checkShader(fragmentShader, "ACF");
+
+ airProg_Cracker = glCreateProgram();
+ glAttachShader( airProg_Cracker, vertexShader );
+ glAttachShader( airProg_Cracker, fragmentShader );
+ glLinkProgram( airProg_Cracker );
+ checkProgram(airProg_Cracker, "AC");
+}
+#endif
+
+void Renderer::FinaliseParts()
+{
+#ifdef OGLR
+ glEnable( GL_TEXTURE_2D );
+ if(display_mode & DISPLAY_WARP)
+ {
+ float xres = XRES, yres = YRES;
+ glUseProgram(lensProg);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, partsFboTex);
+ glUniform1i(glGetUniformLocation(lensProg, "pTex"), 0);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, partsTFX);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, XRES/CELL, YRES/CELL, GL_RED, GL_FLOAT, sim->gravx);
+ glUniform1i(glGetUniformLocation(lensProg, "tfX"), 1);
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D, partsTFY);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, XRES/CELL, YRES/CELL, GL_GREEN, GL_FLOAT, sim->gravy);
+ glUniform1i(glGetUniformLocation(lensProg, "tfY"), 2);
+ glActiveTexture(GL_TEXTURE0);
+ glUniform1fv(glGetUniformLocation(lensProg, "xres"), 1, &xres);
+ glUniform1fv(glGetUniformLocation(lensProg, "yres"), 1, &yres);
+ }
+ else
+ {
+ glBindTexture(GL_TEXTURE_2D, partsFboTex);
+ glBlendFunc(GL_ONE, GL_ONE);
+ }
+
+ int sdl_scale = 1;
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ glBegin(GL_QUADS);
+ glTexCoord2d(1, 0);
+ //glVertex3f(XRES*sdl_scale, (YRES+MENUSIZE)*sdl_scale, 1.0);
+ glVertex3f(XRES*sdl_scale, YRES*sdl_scale, 1.0);
+ glTexCoord2d(0, 0);
+ //glVertex3f(0, (YRES+MENUSIZE)*sdl_scale, 1.0);
+ glVertex3f(0, YRES*sdl_scale, 1.0);
+ glTexCoord2d(0, 1);
+ //glVertex3f(0, MENUSIZE*sdl_scale, 1.0);
+ glVertex3f(0, 0, 1.0);
+ glTexCoord2d(1, 1);
+ //glVertex3f(XRES*sdl_scale, MENUSIZE*sdl_scale, 1.0);
+ glVertex3f(XRES*sdl_scale, 0, 1.0);
+ glEnd();
+
+ if(display_mode & DISPLAY_WARP)
+ {
+ glUseProgram(0);
+
+ }
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable( GL_TEXTURE_2D );
+#endif
+
+#if defined(OGLI) && !defined(OGLR)
+ if(display_mode & DISPLAY_WARP)
+ {
+ render_gravlensing(warpVid);
+ }
+ g->draw_image(vid, 0, 0, VIDXRES, VIDYRES, 255);
+#endif
+
+#if !defined(OGLR) && !defined(OGLI)
+ if(display_mode & DISPLAY_WARP)
+ {
+ render_gravlensing(warpVid);
+ }
+#endif
+}
+
+void Renderer::RenderZoom()
+{
+ if(!zoomEnabled)
+ return;
+ #if defined(OGLR)
+ int sdl_scale = 1;
+ int origBlendSrc, origBlendDst;
+ float zcx1, zcx0, zcy1, zcy0, yfactor, xfactor, i; //X-Factor is shit, btw
+ xfactor = 1.0f/(float)XRES;
+ yfactor = 1.0f/(float)YRES;
+ yfactor*=-1.0f;
+
+ zcx1 = (zoomScopePosition.X)*xfactor;
+ zcx0 = (zoomScopePosition.X+zoomScopeSize)*xfactor;
+ zcy1 = (zoomScopePosition.Y-1)*yfactor;
+ zcy0 = ((zoomScopePosition.Y-1+zoomScopeSize))*yfactor;
+
+ glGetIntegerv(GL_BLEND_SRC, &origBlendSrc);
+ glGetIntegerv(GL_BLEND_DST, &origBlendDst);
+ glBlendFunc(GL_ONE, GL_ZERO);
+
+ glEnable( GL_TEXTURE_2D );
+ //glReadBuffer(GL_AUX0);
+ glBindTexture(GL_TEXTURE_2D, partsFboTex);
+
+ //Draw zoomed texture
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ glBegin(GL_QUADS);
+ glTexCoord2d(zcx1, zcy1);
+ glVertex2i(zoomWindowPosition.X, zoomWindowPosition.Y);
+ glTexCoord2d(zcx0, zcy1);
+ glVertex2i(zoomWindowPosition.X+(zoomScopeSize*ZFACTOR), zoomWindowPosition.Y);
+ glTexCoord2d(zcx0, zcy0);
+ glVertex2i(zoomWindowPosition.X+(zoomScopeSize*ZFACTOR), zoomWindowPosition.Y+(zoomScopeSize*ZFACTOR));
+ glTexCoord2d(zcx1, zcy0);
+ glVertex2i(zoomWindowPosition.X, zoomWindowPosition.Y+(zoomScopeSize*ZFACTOR));
+ glEnd();
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable( GL_TEXTURE_2D );
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ //Lines to make the pixels stand out
+ glLineWidth(sdl_scale);
+ //glEnable(GL_LINE_SMOOTH);
+ glBegin(GL_LINES);
+ glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+ for(i = 0; i < zoomScopeSize; i++)
+ {
+ //Across
+ glVertex2i(zoomWindowPosition.X, zoomWindowPosition.Y+(i*ZFACTOR));
+ glVertex2i(zoomWindowPosition.X+(zoomScopeSize*ZFACTOR), zoomWindowPosition.Y+(i*ZFACTOR));
+
+ //Down
+ glVertex2i(zoomWindowPosition.X+(i*ZFACTOR), zoomWindowPosition.Y);
+ glVertex2i(zoomWindowPosition.X+(i*ZFACTOR), zoomWindowPosition.Y+(zoomScopeSize*ZFACTOR));
+ }
+ glEnd();
+
+ //Draw zoom window border
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ glBegin(GL_LINE_LOOP);
+ glVertex2i(zoomWindowPosition.X, zoomWindowPosition.Y);
+ glVertex2i(zoomWindowPosition.X+(zoomScopeSize*ZFACTOR), zoomWindowPosition.Y);
+ glVertex2i(zoomWindowPosition.X+(zoomScopeSize*ZFACTOR), zoomWindowPosition.Y+(zoomScopeSize*ZFACTOR));
+ glVertex2i(zoomWindowPosition.X, zoomWindowPosition.Y+(zoomScopeSize*ZFACTOR));
+ glEnd();
+ //glDisable(GL_LINE_SMOOTH);
+
+ if(zoomEnabled)
+ {
+ glEnable(GL_COLOR_LOGIC_OP);
+ //glEnable(GL_LINE_SMOOTH);
+ glLogicOp(GL_XOR);
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ glBegin(GL_LINE_LOOP);
+ glVertex2i(zoomScopePosition.X, zoomScopePosition.Y);
+ glVertex2i(zoomScopePosition.X+zoomScopeSize, zoomScopePosition.Y);
+ glVertex2i(zoomScopePosition.X+zoomScopeSize, zoomScopePosition.Y+zoomScopeSize);
+ glVertex2i(zoomScopePosition.X, zoomScopePosition.Y+zoomScopeSize);
+ /*glVertex3i((zoomScopePosition.X-1)*sdl_scale, (YRES+MENUSIZE-(zoomScopePosition.Y-1))*sdl_scale, 0);
+ glVertex3i((zoomScopePosition.X-1)*sdl_scale, (YRES+MENUSIZE-(zoomScopePosition.Y+zoomScopeSize))*sdl_scale, 0);
+ glVertex3i((zoomScopePosition.X+zoomScopeSize)*sdl_scale, (YRES+MENUSIZE-(zoomScopePosition.Y+zoomScopeSize))*sdl_scale, 0);
+ glVertex3i((zoomScopePosition.X+zoomScopeSize)*sdl_scale, (YRES+MENUSIZE-(zoomScopePosition.Y-1))*sdl_scale, 0);
+ glVertex3i((zoomScopePosition.X-1)*sdl_scale, (YRES+MENUSIZE-(zoomScopePosition.Y-1))*sdl_scale, 0);*/
+ glEnd();
+ glDisable(GL_COLOR_LOGIC_OP);
+ }
+ glLineWidth(1);
+ glBlendFunc(origBlendSrc, origBlendDst);
+ #else
+ int x, y, i, j;
+ pixel pix;
+ pixel * img = vid;
+ clearrect(zoomWindowPosition.X-1, zoomWindowPosition.Y-1, zoomScopeSize*ZFACTOR+2, zoomScopeSize*ZFACTOR+2);
+ drawrect(zoomWindowPosition.X-2, zoomWindowPosition.Y-2, zoomScopeSize*ZFACTOR+4, zoomScopeSize*ZFACTOR+4, 192, 192, 192, 255);
+ drawrect(zoomWindowPosition.X-1, zoomWindowPosition.Y-1, zoomScopeSize*ZFACTOR+2, zoomScopeSize*ZFACTOR+2, 0, 0, 0, 255);
+ for (j=0; j<zoomScopeSize; j++)
+ for (i=0; i<zoomScopeSize; i++)
+ {
+ pix = img[(j+zoomScopePosition.Y)*(VIDXRES)+(i+zoomScopePosition.X)];
+ for (y=0; y<ZFACTOR-1; y++)
+ for (x=0; x<ZFACTOR-1; x++)
+ img[(j*ZFACTOR+y+zoomWindowPosition.Y)*(VIDXRES)+(i*ZFACTOR+x+zoomWindowPosition.X)] = pix;
+ }
+ if (zoomEnabled)
+ {
+ for (j=-1; j<=zoomScopeSize; j++)
+ {
+ xor_pixel(zoomScopePosition.X+j, zoomScopePosition.Y-1);
+ xor_pixel(zoomScopePosition.X+j, zoomScopePosition.Y+zoomScopeSize);
+ }
+ for (j=0; j<zoomScopeSize; j++)
+ {
+ xor_pixel(zoomScopePosition.X-1, zoomScopePosition.Y+j);
+ xor_pixel(zoomScopePosition.X+zoomScopeSize, zoomScopePosition.Y+j);
+ }
+ }
+ #endif
+}
+
+int Renderer_wtypesCount;
+wall_type * Renderer_wtypes = LoadWalls(Renderer_wtypesCount);
+
+
+VideoBuffer * Renderer::WallIcon(int wallID, int width, int height)
+{
+ int i, j, cr, cg, cb;
+ int wt = wallID;
+ if (wt<0 || wt>=Renderer_wtypesCount)
+ return 0;
+ wall_type *wtypes = Renderer_wtypes;
+ pixel pc = wtypes[wt].colour;
+ pixel gc = wtypes[wt].eglow;
+ VideoBuffer * newTexture = new VideoBuffer(width, height);
+ if (wtypes[wt].drawstyle==1)
+ {
+ for (j=0; j<height; j+=2)
+ for (i=(j>>1)&1; i<width; i+=2)
+ newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
+ }
+ else if (wtypes[wt].drawstyle==2)
+ {
+ for (j=0; j<height; j+=2)
+ for (i=0; i<width; i+=2)
+ newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
+ }
+ else if (wtypes[wt].drawstyle==3)
+ {
+ for (j=0; j<height; j++)
+ for (i=0; i<width; i++)
+ newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
+ }
+ else if (wtypes[wt].drawstyle==4)
+ {
+ for (j=0; j<height; j++)
+ for (i=0; i<width; i++)
+ if(i%CELL == j%CELL)
+ newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
+ else if (i%CELL == (j%CELL)+1 || (i%CELL == 0 && j%CELL == CELL-1))
+ newTexture->SetPixel(i, j, PIXR(gc), PIXG(gc), PIXB(gc), 255);
+ else
+ newTexture->SetPixel(i, j, 0x20, 0x20, 0x20, 255);
+ }
+
+ // special rendering for some walls
+ if (wt==WL_EWALL)
+ {
+ for (j=0; j<height; j++)
+ {
+ for (i=0; i<(width/4)+j; i++)
+ {
+ if (!(i&j&1))
+ newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
+ }
+ for (; i<width; i++)
+ {
+ if (i&j&1)
+ newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
+ }
+ }
+ }
+ else if (wt==WL_WALLELEC)
+ {
+ for (j=0; j<height; j++)
+ for (i=0; i<width; i++)
+ {
+ if (!(j%2) && !(i%2))
+ newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
+ else
+ newTexture->SetPixel(i, j, 0x80, 0x80, 0x80, 255);
+ }
+ }
+ else if (wt==WL_EHOLE)
+ {
+ for (j=0; j<height; j++)
+ {
+ for (i=0; i<(width/4)+j; i++)
+ {
+ if (i&j&1)
+ newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
+ }
+ for (; i<width; i++)
+ {
+ if (!(i&j&1))
+ newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
+ }
+ }
+ }
+ else if (wt == WL_ERASE)
+ {
+ for (j=0; j<height; j+=2)
+ {
+ for (i=1+(1&(j>>1)); i<width/2; i+=2)
+ {
+ newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
+ }
+ }
+ for (j=0; j<height; j++)
+ {
+ for (i=width/2; i<width; i++)
+ {
+ newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
+ }
+ }
+ for (j=3; j<(width-4)/2; j++)
+ {
+ newTexture->SetPixel(j+6, j, 0xFF, 0, 0, 255);
+ newTexture->SetPixel(j+7, j, 0xFF, 0, 0, 255);
+ newTexture->SetPixel(-j+19, j, 0xFF, 0, 0, 255);
+ newTexture->SetPixel(-j+20, j, 0xFF, 0, 0, 255);
+ }
+ }
+ else if(wt == WL_STREAM)
+ {
+ for (j=0; j<height; j++)
+ {
+ for (i=0; i<width; i++)
+ {
+ pc = i==0||i==width-1||j==0||j==height-1 ? PIXPACK(0xA0A0A0) : PIXPACK(0x000000);
+ newTexture->SetPixel(i, j, PIXR(pc), PIXG(pc), PIXB(pc), 255);
+ }
+ }
+ newTexture->SetCharacter(4, 2, 0x8D, 255, 255, 255, 255);
+ for (i=width/3; i<width; i++)
+ {
+ newTexture->SetPixel(i, 7+(int)(3.9f*cos(i*0.3f)), 255, 255, 255, 255);
+ }
+ }
+ return newTexture;
+}
+
+void Renderer::DrawWalls()
+{
+#ifdef OGLR
+ GLint prevFbo;
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFbo);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo);
+ glTranslated(0, MENUSIZE, 0);
+
+ int x, y, i, j, cr, cg, cb;
+ unsigned char wt;
+ pixel pc;
+ pixel gc;
+ unsigned char (*bmap)[XRES/CELL] = sim->bmap;
+ unsigned char (*emap)[XRES/CELL] = sim->emap;
+ wall_type *wtypes = sim->wtypes;
+ for (y=0; y<YRES/CELL; y++)
+ for (x=0; x<XRES/CELL; x++)
+ if (bmap[y][x])
+ {
+ wt = bmap[y][x];
+ if (wt<0 || wt>=UI_WALLCOUNT)
+ continue;
+ pc = wtypes[wt].colour;
+ gc = wtypes[wt].eglow;
+
+ cr = PIXR(pc);
+ cg = PIXG(pc);
+ cb = PIXB(pc);
+
+ fillrect(x*CELL, y*CELL, CELL, CELL, cr, cg, cb, 255);
+ }
+
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFbo);
+ glTranslated(0, -MENUSIZE, 0);
+#else
+ int x, y, i, j, cr, cg, cb;
+ unsigned char wt;
+ pixel pc;
+ pixel gc;
+ unsigned char (*bmap)[XRES/CELL] = sim->bmap;
+ unsigned char (*emap)[XRES/CELL] = sim->emap;
+ wall_type *wtypes = sim->wtypes;
+ for (y=0; y<YRES/CELL; y++)
+ for (x=0; x<XRES/CELL; x++)
+ if (bmap[y][x])
+ {
+ wt = bmap[y][x];
+ if (wt<0 || wt>=UI_WALLCOUNT)
+ continue;
+ pc = wtypes[wt].colour;
+ gc = wtypes[wt].eglow;
+
+ // standard wall patterns
+ if (wtypes[wt].drawstyle==1)
+ {
+ for (j=0; j<CELL; j+=2)
+ for (i=(j>>1)&1; i<CELL; i+=2)
+ vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = pc;
+ }
+ else if (wtypes[wt].drawstyle==2)
+ {
+ for (j=0; j<CELL; j+=2)
+ for (i=0; i<CELL; i+=2)
+ vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = pc;
+ }
+ else if (wtypes[wt].drawstyle==3)
+ {
+ for (j=0; j<CELL; j++)
+ for (i=0; i<CELL; i++)
+ vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = pc;
+ }
+ else if (wtypes[wt].drawstyle==4)
+ {
+ for (j=0; j<CELL; j++)
+ for (i=0; i<CELL; i++)
+ if(i == j)
+ vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = pc;
+ else if (i == j+1 || (i == 0 && j == CELL-1))
+ vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = gc;
+ else
+ vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = PIXPACK(0x202020);
+ }
+
+ // special rendering for some walls
+ if (wt==WL_EWALL)
+ {
+ if (emap[y][x])
+ {
+ for (j=0; j<CELL; j++)
+ for (i=0; i<CELL; i++)
+ if (i&j&1)
+ vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = pc;
+ }
+ else
+ {
+ for (j=0; j<CELL; j++)
+ for (i=0; i<CELL; i++)
+ if (!(i&j&1))
+ vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = pc;
+ }
+ }
+ else if (wt==WL_WALLELEC)
+ {
+ for (j=0; j<CELL; j++)
+ for (i=0; i<CELL; i++)
+ {
+ if (!((y*CELL+j)%2) && !((x*CELL+i)%2))
+ vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = pc;
+ else
+ vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = PIXPACK(0x808080);
+ }
+ }
+ else if (wt==WL_EHOLE)
+ {
+ if (emap[y][x])
+ {
+ for (j=0; j<CELL; j++)
+ for (i=0; i<CELL; i++)
+ vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = PIXPACK(0x242424);
+ for (j=0; j<CELL; j+=2)
+ for (i=0; i<CELL; i+=2)
+ vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = PIXPACK(0x000000);
+ }
+ else
+ {
+ for (j=0; j<CELL; j+=2)
+ for (i=0; i<CELL; i+=2)
+ vid[(y*CELL+j)*(VIDXRES)+(x*CELL+i)] = PIXPACK(0x242424);
+ }
+ }
+ else if (wt==WL_STREAM)
+ {
+ float lx, ly, nx, ny;
+ lx = x*CELL + CELL*0.5f;
+ ly = y*CELL + CELL*0.5f;
+ for (int t = 0; t < 1024; t++)
+ {
+ nx = (int)(lx+0.5f);
+ ny = (int)(ly+0.5f);
+ if (nx<0 || nx>=XRES || ny<0 || ny>=YRES)
+ break;
+ addpixel(nx, ny, 255, 255, 255, 64);
+ i = nx/CELL;
+ j = ny/CELL;
+ lx += sim->vx[j][i]*0.125f;
+ ly += sim->vy[j][i]*0.125f;
+ if (bmap[j][i]==WL_STREAM && i!=x && j!=y)
+ break;
+ }
+ drawtext(x*CELL, y*CELL-2, "\x8D", 255, 255, 255, 128);
+ }
+ if (wtypes[wt].eglow && emap[y][x])
+ {
+ // glow if electrified
+ pc = wtypes[wt].eglow;
+ cr = fire_r[y][x] + PIXR(pc);
+ if (cr > 255) cr = 255;
+ fire_r[y][x] = cr;
+ cg = fire_g[y][x] + PIXG(pc);
+ if (cg > 255) cg = 255;
+ fire_g[y][x] = cg;
+ cb = fire_b[y][x] + PIXB(pc);
+ if (cb > 255) cb = 255;
+ fire_b[y][x] = cb;
+
+ }
+ }
+#endif
+}
+
+void Renderer::DrawSigns()
+{
+ int i, j, x, y, w, h, dx, dy,mx,my,b=1,bq;
+ std::vector<sign> signs = sim->signs;
+#ifdef OGLR
+ GLint prevFbo;
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFbo);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo);
+ glTranslated(0, MENUSIZE, 0);
+#endif
+ for (i=0; i < signs.size(); i++)
+ if (signs[i].text.length())
+ {
+ char buff[256]; //Buffer
+ sim->signs[i].pos(x, y, w, h);
+ clearrect(x, y, w, h);
+ drawrect(x, y, w, h, 192, 192, 192, 255);
+
+ //Displaying special information
+ if (signs[i].text == "{p}")
+ {
+ float pressure = 0.0f;
+ if (signs[i].x>=0 && signs[i].x<XRES && signs[i].y>=0 && signs[i].y<YRES)
+ pressure = sim->pv[signs[i].y/CELL][signs[i].x/CELL];
+ sprintf(buff, "Pressure: %3.2f", pressure); //...pressure
+ drawtext(x+3, y+3, buff, 255, 255, 255, 255);
+ }
+ else if (signs[i].text == "{t}")
+ {
+ if (signs[i].x>=0 && signs[i].x<XRES && signs[i].y>=0 && signs[i].y<YRES && sim->pmap[signs[i].y][signs[i].x])
+ sprintf(buff, "Temp: %4.2f", sim->parts[sim->pmap[signs[i].y][signs[i].x]>>8].temp-273.15); //...temperature
+ else
+ sprintf(buff, "Temp: 0.00"); //...temperature
+ drawtext(x+3, y+3, buff, 255, 255, 255, 255);
+ }
+ else if (sregexp(signs[i].text.c_str(), "^{[c|t]:[0-9]*|.*}$")==0)
+ {
+ int sldr, startm;
+ memset(buff, 0, sizeof(buff));
+ for (sldr=3; signs[i].text[sldr-1] != '|'; sldr++)
+ startm = sldr + 1;
+ sldr = startm;
+ while (signs[i].text[sldr] != '}')
+ {
+ buff[sldr - startm] = signs[i].text[sldr];
+ sldr++;
+ }
+ drawtext(x+3, y+3, buff, 0, 191, 255, 255);
+ }
+ else
+ {
+ drawtext(x+3, y+3, signs[i].text, 255, 255, 255, 255);
+ }
+
+ x = signs[i].x;
+ y = signs[i].y;
+ dx = 1 - signs[i].ju;
+ dy = (signs[i].y > 18) ? -1 : 1;
+#ifdef OGLR
+ glBegin(GL_LINES);
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ glVertex2i(x, y);
+ glVertex2i(x+(dx*4), y+(dy*4));
+ glEnd();
+#else
+ for (j=0; j<4; j++)
+ {
+ blendpixel(x, y, 192, 192, 192, 255);
+ x+=dx;
+ y+=dy;
+ }
+#endif
+ /*if (MSIGN==i)
+ {
+ bq = b;
+ b = SDL_GetMouseState(&mx, &my);
+ mx /= sdl_scale;
+ my /= sdl_scale;
+ signs[i].x = mx;
+ signs[i].y = my;
+ }*/
+ }
+#ifdef OGLR
+ glTranslated(0, -MENUSIZE, 0);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFbo);
+#endif
+}
+
+void Renderer::render_gravlensing(pixel * source)
+{
+#ifndef OGLR
+ int nx, ny, rx, ry, gx, gy, bx, by, co;
+ int r, g, b;
+ pixel t;
+ pixel *src = source;
+ pixel *dst = vid;
+ for(nx = 0; nx < XRES; nx++)
+ {
+ for(ny = 0; ny < YRES; ny++)
+ {
+ co = (ny/CELL)*(XRES/CELL)+(nx/CELL);
+ rx = (int)(nx-sim->gravx[co]*0.75f+0.5f);
+ ry = (int)(ny-sim->gravy[co]*0.75f+0.5f);
+ gx = (int)(nx-sim->gravx[co]*0.875f+0.5f);
+ gy = (int)(ny-sim->gravy[co]*0.875f+0.5f);
+ bx = (int)(nx-sim->gravx[co]+0.5f);
+ by = (int)(ny-sim->gravy[co]+0.5f);
+ 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)
+ {
+ t = dst[ny*(VIDXRES)+nx];
+ r = PIXR(src[ry*(VIDXRES)+rx]) + PIXR(t);
+ g = PIXG(src[gy*(VIDXRES)+gx]) + PIXG(t);
+ b = PIXB(src[by*(VIDXRES)+bx]) + PIXB(t);
+ if (r>255)
+ r = 255;
+ if (g>255)
+ g = 255;
+ if (b>255)
+ b = 255;
+ dst[ny*(VIDXRES)+nx] = PIXRGB(r,g,b);
+ }
+ }
+ }
+#endif
+}
+
+void Renderer::render_fire()
+{
+#ifndef OGLR
+ if(!(render_mode & FIREMODE))
+ return;
+ int i,j,x,y,r,g,b,nx,ny;
+ for (j=0; j<YRES/CELL; j++)
+ for (i=0; i<XRES/CELL; i++)
+ {
+ r = fire_r[j][i];
+ g = fire_g[j][i];
+ b = fire_b[j][i];
+ if (r || g || b)
+ for (y=-CELL; y<2*CELL; y++)
+ for (x=-CELL; x<2*CELL; x++)
+ addpixel(i*CELL+x, j*CELL+y, r, g, b, fire_alpha[y+CELL][x+CELL]);
+ r *= 8;
+ g *= 8;
+ b *= 8;
+ for (y=-1; y<2; y++)
+ for (x=-1; x<2; x++)
+ if ((x || y) && i+x>=0 && j+y>=0 && i+x<XRES/CELL && j+y<YRES/CELL)
+ {
+ r += fire_r[j+y][i+x];
+ g += fire_g[j+y][i+x];
+ b += fire_b[j+y][i+x];
+ }
+ r /= 16;
+ g /= 16;
+ b /= 16;
+ fire_r[j][i] = r>4 ? r-4 : 0;
+ fire_g[j][i] = g>4 ? g-4 : 0;
+ fire_b[j][i] = b>4 ? b-4 : 0;
+ }
+#endif
+}
+
+float temp[CELL*3][CELL*3];
+float fire_alphaf[CELL*3][CELL*3];
+float glow_alphaf[11][11];
+float blur_alphaf[7][7];
+void Renderer::prepare_alpha(int size, float intensity)
+{
+ //TODO: implement size
+ int x,y,i,j,c;
+ float multiplier = 255.0f*intensity;
+
+ memset(temp, 0, sizeof(temp));
+ for (x=0; x<CELL; x++)
+ for (y=0; y<CELL; y++)
+ for (i=-CELL; i<CELL; i++)
+ for (j=-CELL; j<CELL; j++)
+ temp[y+CELL+j][x+CELL+i] += expf(-0.1f*(i*i+j*j));
+ for (x=0; x<CELL*3; x++)
+ for (y=0; y<CELL*3; y++)
+ fire_alpha[y][x] = (int)(multiplier*temp[y][x]/(CELL*CELL));
+
+#ifdef OGLR
+ memset(fire_alphaf, 0, sizeof(fire_alphaf));
+ for (x=0; x<CELL*3; x++)
+ for (y=0; y<CELL*3; y++)
+ {
+ fire_alphaf[y][x] = intensity*temp[y][x]/((float)(CELL*CELL));
+ }
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, fireAlpha);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, CELL*3, CELL*3, GL_ALPHA, GL_FLOAT, fire_alphaf);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+
+ memset(glow_alphaf, 0, sizeof(glow_alphaf));
+
+ c = 5;
+
+ glow_alphaf[c][c-1] = 0.4f;
+ glow_alphaf[c][c+1] = 0.4f;
+ glow_alphaf[c-1][c] = 0.4f;
+ glow_alphaf[c+1][c] = 0.4f;
+ for (x = 1; x < 6; x++) {
+ glow_alphaf[c][c-x] += 0.02f;
+ glow_alphaf[c][c+x] += 0.02f;
+ glow_alphaf[c-x][c] += 0.02f;
+ glow_alphaf[c+x][c] += 0.02f;
+ for (y = 1; y < 6; y++) {
+ if(x + y > 7)
+ continue;
+ glow_alphaf[c+x][c-y] += 0.02f;
+ glow_alphaf[c-x][c+y] += 0.02f;
+ glow_alphaf[c+x][c+y] += 0.02f;
+ glow_alphaf[c-x][c-y] += 0.02f;
+ }
+ }
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, glowAlpha);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 11, 11, GL_ALPHA, GL_FLOAT, glow_alphaf);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+
+ c = 3;
+
+ for (x=-3; x<4; x++)
+ {
+ for (y=-3; y<4; y++)
+ {
+ if (abs(x)+abs(y) <2 && !(abs(x)==2||abs(y)==2))
+ blur_alphaf[c+x][c-y] = 0.11f;
+ if (abs(x)+abs(y) <=3 && abs(x)+abs(y))
+ blur_alphaf[c+x][c-y] = 0.08f;
+ if (abs(x)+abs(y) == 2)
+ blur_alphaf[c+x][c-y] = 0.04f;
+ }
+ }
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, blurAlpha);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 7, 7, GL_ALPHA, GL_FLOAT, blur_alphaf);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+#endif
+}
+
+void Renderer::render_parts()
+{
+ int deca, decr, decg, decb, cola, colr, colg, colb, firea, firer, fireg, fireb, pixel_mode, q, i, t, nx, ny, x, y, caddress;
+ int orbd[4] = {0, 0, 0, 0}, orbl[4] = {0, 0, 0, 0};
+ float gradv, flicker, fnx, fny;
+ Particle * parts;
+ part_transition *ptransitions;
+ Element *elements;
+ if(!sim)
+ return;
+ parts = sim->parts;
+ elements = sim->elements;
+#ifdef OGLR
+ int cfireV = 0, cfireC = 0, cfire = 0;
+ int csmokeV = 0, csmokeC = 0, csmoke = 0;
+ int cblobV = 0, cblobC = 0, cblob = 0;
+ int cblurV = 0, cblurC = 0, cblur = 0;
+ int cglowV = 0, cglowC = 0, cglow = 0;
+ int cflatV = 0, cflatC = 0, cflat = 0;
+ int caddV = 0, caddC = 0, cadd = 0;
+ int clineV = 0, clineC = 0, cline = 0;
+ GLint origBlendSrc, origBlendDst, prevFbo;
+
+ glGetIntegerv(GL_BLEND_SRC, &origBlendSrc);
+ glGetIntegerv(GL_BLEND_DST, &origBlendDst);
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFbo);
+ //Render to the particle FBO
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo);
+ glTranslated(0, MENUSIZE, 0);
+#else
+ if (gridSize)//draws the grid
+ {
+ for (ny=0; ny<YRES; ny++)
+ for (nx=0; nx<XRES; nx++)
+ {
+ if (ny%(4*gridSize)==0)
+ blendpixel(nx, ny, 100, 100, 100, 80);
+ if (nx%(4*gridSize)==0)
+ blendpixel(nx, ny, 100, 100, 100, 80);
+ }
+ }
+#endif
+ for(i = 0; i<=sim->parts_lastActiveIndex; i++) {
+ if (sim->parts[i].type && sim->parts[i].type >= 0 && sim->parts[i].type < PT_NUM) {
+ t = sim->parts[i].type;
+
+ nx = (int)(sim->parts[i].x+0.5f);
+ ny = (int)(sim->parts[i].y+0.5f);
+ fnx = sim->parts[i].x;
+ fny = sim->parts[i].y;
+
+ if((sim->photons[ny][nx]&0xFF) && !(sim->elements[t].Properties & TYPE_ENERGY) && t!=PT_STKM && t!=PT_STKM2 && t!=PT_FIGH)
+ continue;
+ if(nx >= XRES || nx < 0 || ny >= YRES || ny < 0)
+ continue;
+
+ //Defaults
+ pixel_mode = 0 | PMODE_FLAT;
+ cola = 255;
+ colr = PIXR(elements[t].Colour);
+ colg = PIXG(elements[t].Colour);
+ colb = PIXB(elements[t].Colour);
+ firer = fireg = fireb = firea = 0;
+
+ deca = (sim->parts[i].dcolour>>24)&0xFF;
+ decr = (sim->parts[i].dcolour>>16)&0xFF;
+ decg = (sim->parts[i].dcolour>>8)&0xFF;
+ decb = (sim->parts[i].dcolour)&0xFF;
+
+ if(decorations_enable && blackDecorations)
+ {
+ if(deca < 250 || decr > 5 || decg > 5 || decb > 5)
+ deca = 0;
+ else
+ {
+ deca = 255;
+ decr = decg = decb = 0;
+ }
+ }
+
+ {
+ if (graphicscache[t].isready)
+ {
+ pixel_mode = graphicscache[t].pixel_mode;
+ cola = graphicscache[t].cola;
+ colr = graphicscache[t].colr;
+ colg = graphicscache[t].colg;
+ colb = graphicscache[t].colb;
+ firea = graphicscache[t].firea;
+ firer = graphicscache[t].firer;
+ fireg = graphicscache[t].fireg;
+ fireb = graphicscache[t].fireb;
+ }
+ else if(!(colour_mode & COLOUR_BASC))
+ {
+ if (elements[t].Graphics)
+ {
+ 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
+ {
+ graphicscache[t].isready = 1;
+ graphicscache[t].pixel_mode = pixel_mode;
+ graphicscache[t].cola = cola;
+ graphicscache[t].colr = colr;
+ graphicscache[t].colg = colg;
+ graphicscache[t].colb = colb;
+ graphicscache[t].firea = firea;
+ graphicscache[t].firer = firer;
+ graphicscache[t].fireg = fireg;
+ graphicscache[t].fireb = fireb;
+ }
+ }
+ else
+ {
+ graphicscache[t].isready = 1;
+ graphicscache[t].pixel_mode = pixel_mode;
+ graphicscache[t].cola = cola;
+ graphicscache[t].colr = colr;
+ graphicscache[t].colg = colg;
+ graphicscache[t].colb = colb;
+ graphicscache[t].firea = firea;
+ graphicscache[t].firer = firer;
+ graphicscache[t].fireg = fireg;
+ graphicscache[t].fireb = fireb;
+ }
+ }
+ if((elements[t].Properties & PROP_HOT_GLOW) && sim->parts[i].temp>(elements[t].HighTemperature-800.0f))
+ {
+ gradv = 3.1415/(2*elements[t].HighTemperature-(elements[t].HighTemperature-800.0f));
+ 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);
+ colr += sin(gradv*caddress) * 226;;
+ colg += sin(gradv*caddress*4.55 +3.14) * 34;
+ colb += sin(gradv*caddress*2.22 +3.14) * 64;
+ }
+
+ if((pixel_mode & FIRE_ADD) && !(render_mode & FIRE_ADD))
+ pixel_mode |= PMODE_GLOW;
+ if((pixel_mode & FIRE_BLEND) && !(render_mode & FIRE_BLEND))
+ pixel_mode |= PMODE_BLUR;
+ if((pixel_mode & PMODE_BLUR) && !(render_mode & PMODE_BLUR))
+ pixel_mode |= PMODE_FLAT;
+ if((pixel_mode & PMODE_GLOW) && !(render_mode & PMODE_GLOW))
+ pixel_mode |= PMODE_BLEND;
+ if (render_mode & PMODE_BLOB)
+ pixel_mode |= PMODE_BLOB;
+
+ pixel_mode &= render_mode;
+
+ //Alter colour based on display mode
+ if(colour_mode & COLOUR_HEAT)
+ {
+ 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);
+ firea = 255;
+ firer = colr = (unsigned char)color_data[caddress];
+ fireg = colg = (unsigned char)color_data[caddress+1];
+ fireb = colb = (unsigned char)color_data[caddress+2];
+ cola = 255;
+ if(pixel_mode & (FIREMODE | PMODE_GLOW)) pixel_mode = (pixel_mode & ~(FIREMODE|PMODE_GLOW)) | PMODE_BLUR;
+ }
+ else if(colour_mode & COLOUR_LIFE)
+ {
+ gradv = 0.4f;
+ if (!(sim->parts[i].life<5))
+ q = sqrt((float)sim->parts[i].life);
+ else
+ q = sim->parts[i].life;
+ colr = colg = colb = sin(gradv*q) * 100 + 128;
+ cola = 255;
+ if(pixel_mode & (FIREMODE | PMODE_GLOW)) pixel_mode = (pixel_mode & ~(FIREMODE|PMODE_GLOW)) | PMODE_BLUR;
+ }
+ else if(colour_mode & COLOUR_BASC)
+ {
+ colr = PIXR(elements[t].Colour);
+ colg = PIXG(elements[t].Colour);
+ colb = PIXB(elements[t].Colour);
+ pixel_mode = PMODE_FLAT;
+ }
+
+ //Apply decoration colour
+ if(!(colour_mode & ~COLOUR_GRAD) && decorations_enable && deca)
+ {
+ if(!(pixel_mode & NO_DECO))
+ {
+ colr = (deca*decr + (255-deca)*colr) >> 8;
+ colg = (deca*decg + (255-deca)*colg) >> 8;
+ colb = (deca*decb + (255-deca)*colb) >> 8;
+ }
+
+ if(pixel_mode & DECO_FIRE)
+ {
+ firer = (deca*decr + (255-deca)*firer) >> 8;
+ fireg = (deca*decg + (255-deca)*fireg) >> 8;
+ fireb = (deca*decb + (255-deca)*fireb) >> 8;
+ }
+ }
+
+ if (colour_mode & COLOUR_GRAD)
+ {
+ float frequency = 0.05;
+ int q = sim->parts[i].temp-40;
+ colr = sin(frequency*q) * 16 + colr;
+ colg = sin(frequency*q) * 16 + colg;
+ colb = sin(frequency*q) * 16 + colb;
+ if(pixel_mode & (FIREMODE | PMODE_GLOW)) pixel_mode = (pixel_mode & ~(FIREMODE|PMODE_GLOW)) | PMODE_BLUR;
+ }
+
+ #ifndef OGLR
+ //All colours are now set, check ranges
+ if(colr>255) colr = 255;
+ else if(colr<0) colr = 0;
+ if(colg>255) colg = 255;
+ else if(colg<0) colg = 0;
+ if(colb>255) colb = 255;
+ else if(colb<0) colb = 0;
+ if(cola>255) cola = 255;
+ else if(cola<0) cola = 0;
+
+ if(firer>255) firer = 255;
+ else if(firer<0) firer = 0;
+ if(fireg>255) fireg = 255;
+ else if(fireg<0) fireg = 0;
+ if(fireb>255) fireb = 255;
+ else if(fireb<0) fireb = 0;
+ if(firea>255) firea = 255;
+ else if(firea<0) firea = 0;
+ #endif
+
+ //Pixel rendering
+ if (pixel_mode & EFFECT_LINES)
+ {
+ if (t==PT_SOAP)
+ {
+ if ((parts[i].ctype&7) == 7)
+ draw_line(nx, ny, (int)(parts[parts[i].tmp].x+0.5f), (int)(parts[parts[i].tmp].y+0.5f), colr, colg, colb, cola);
+ }
+ }
+ if(pixel_mode & PSPEC_STICKMAN)
+ {
+ char buff[4]; //Buffer for HP
+ int s;
+ int legr, legg, legb;
+ playerst *cplayer;
+ if(t==PT_STKM)
+ cplayer = &sim->player;
+ else if(t==PT_STKM2)
+ cplayer = &sim->player2;
+ else if(t==PT_FIGH)
+ cplayer = &sim->fighters[(unsigned char)sim->parts[i].tmp];
+ else
+ continue;
+
+ if (mousePosX>(nx-3) && mousePosX<(nx+3) && mousePosY<(ny+3) && mousePosY>(ny-3)) //If mouse is in the head
+ {
+ sprintf(buff, "%3d", sim->parts[i].life); //Show HP
+ drawtext(mousePosX-8-2*(sim->parts[i].life<100)-2*(sim->parts[i].life<10), mousePosY-12, buff, 255, 255, 255, 255);
+ }
+
+ if (colour_mode!=COLOUR_HEAT)
+ {
+ if (cplayer->elem<PT_NUM && cplayer->elem > 0)
+ {
+ colr = PIXR(elements[cplayer->elem].Colour);
+ colg = PIXG(elements[cplayer->elem].Colour);
+ colb = PIXB(elements[cplayer->elem].Colour);
+ }
+ else
+ {
+ colr = 0x80;
+ colg = 0x80;
+ colb = 0xFF;
+ }
+ }
+#ifdef OGLR
+ glColor4f(((float)colr)/255.0f, ((float)colg)/255.0f, ((float)colb)/255.0f, 1.0f);
+ glBegin(GL_LINE_STRIP);
+ if(t==PT_FIGH)
+ {
+ glVertex2f(fnx, fny+2);
+ glVertex2f(fnx+2, fny);
+ glVertex2f(fnx, fny-2);
+ glVertex2f(fnx-2, fny);
+ glVertex2f(fnx, fny+2);
+ }
+ else
+ {
+ glVertex2f(fnx-2, fny-2);
+ glVertex2f(fnx+2, fny-2);
+ glVertex2f(fnx+2, fny+2);
+ glVertex2f(fnx-2, fny+2);
+ glVertex2f(fnx-2, fny-2);
+ }
+ glEnd();
+ glBegin(GL_LINES);
+
+ if (colour_mode!=COLOUR_HEAT)
+ {
+ if (t==PT_STKM2)
+ glColor4f(100.0f/255.0f, 100.0f/255.0f, 1.0f, 1.0f);
+ else
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ }
+
+ glVertex2f(nx, ny+3);
+ glVertex2f(cplayer->legs[0], cplayer->legs[1]);
+
+ glVertex2f(cplayer->legs[0], cplayer->legs[1]);
+ glVertex2f(cplayer->legs[4], cplayer->legs[5]);
+
+ glVertex2f(nx, ny+3);
+ glVertex2f(cplayer->legs[8], cplayer->legs[9]);
+
+ glVertex2f(cplayer->legs[8], cplayer->legs[9]);
+ glVertex2f(cplayer->legs[12], cplayer->legs[13]);
+ glEnd();
+#else
+ if (t==PT_STKM2)
+ {
+ legr = 100;
+ legg = 100;
+ legb = 255;
+ }
+ else
+ {
+ legr = 255;
+ legg = 255;
+ legb = 255;
+ }
+
+ if (colour_mode==COLOUR_HEAT)
+ {
+ legr = colr;
+ legg = colg;
+ legb = colb;
+ }
+
+ //head
+ if(t==PT_FIGH)
+ {
+ draw_line(nx, ny+2, nx+2, ny, colr, colg, colb, 255);
+ draw_line(nx+2, ny, nx, ny-2, colr, colg, colb, 255);
+ draw_line(nx, ny-2, nx-2, ny, colr, colg, colb, 255);
+ draw_line(nx-2, ny, nx, ny+2, colr, colg, colb, 255);
+ }
+ else
+ {
+ draw_line(nx-2, ny+2, nx+2, ny+2, colr, colg, colb, 255);
+ draw_line(nx-2, ny-2, nx+2, ny-2, colr, colg, colb, 255);
+ draw_line(nx-2, ny-2, nx-2, ny+2, colr, colg, colb, 255);
+ draw_line(nx+2, ny-2, nx+2, ny+2, colr, colg, colb, 255);
+ }
+ //legs
+ draw_line(nx, ny+3, cplayer->legs[0], cplayer->legs[1], legr, legg, legb, 255);
+ draw_line(cplayer->legs[0], cplayer->legs[1], cplayer->legs[4], cplayer->legs[5], legr, legg, legb, 255);
+ draw_line(nx, ny+3, cplayer->legs[8], cplayer->legs[9], legr, legg, legb, 255);
+ draw_line(cplayer->legs[8], cplayer->legs[9], cplayer->legs[12], cplayer->legs[13], legr, legg, legb, 255);
+#endif
+ }
+ if(pixel_mode & PMODE_FLAT)
+ {
+#ifdef OGLR
+ flatV[cflatV++] = nx;
+ flatV[cflatV++] = ny;
+ flatC[cflatC++] = ((float)colr)/255.0f;
+ flatC[cflatC++] = ((float)colg)/255.0f;
+ flatC[cflatC++] = ((float)colb)/255.0f;
+ flatC[cflatC++] = 1.0f;
+ cflat++;
+#else
+ vid[ny*(VIDXRES)+nx] = PIXRGB(colr,colg,colb);
+#endif
+ }
+ if(pixel_mode & PMODE_BLEND)
+ {
+#ifdef OGLR
+ flatV[cflatV++] = nx;
+ flatV[cflatV++] = ny;
+ flatC[cflatC++] = ((float)colr)/255.0f;
+ flatC[cflatC++] = ((float)colg)/255.0f;
+ flatC[cflatC++] = ((float)colb)/255.0f;
+ flatC[cflatC++] = ((float)cola)/255.0f;
+ cflat++;
+#else
+ blendpixel(nx, ny, colr, colg, colb, cola);
+#endif
+ }
+ if(pixel_mode & PMODE_ADD)
+ {
+#ifdef OGLR
+ addV[caddV++] = nx;
+ addV[caddV++] = ny;
+ addC[caddC++] = ((float)colr)/255.0f;
+ addC[caddC++] = ((float)colg)/255.0f;
+ addC[caddC++] = ((float)colb)/255.0f;
+ addC[caddC++] = ((float)cola)/255.0f;
+ cadd++;
+#else
+ addpixel(nx, ny, colr, colg, colb, cola);
+#endif
+ }
+ if(pixel_mode & PMODE_BLOB)
+ {
+#ifdef OGLR
+ blobV[cblobV++] = nx;
+ blobV[cblobV++] = ny;
+ blobC[cblobC++] = ((float)colr)/255.0f;
+ blobC[cblobC++] = ((float)colg)/255.0f;
+ blobC[cblobC++] = ((float)colb)/255.0f;
+ blobC[cblobC++] = 1.0f;
+ cblob++;
+#else
+ vid[ny*(VIDXRES)+nx] = PIXRGB(colr,colg,colb);
+
+ blendpixel(nx+1, ny, colr, colg, colb, 223);
+ blendpixel(nx-1, ny, colr, colg, colb, 223);
+ blendpixel(nx, ny+1, colr, colg, colb, 223);
+ blendpixel(nx, ny-1, colr, colg, colb, 223);
+
+ blendpixel(nx+1, ny-1, colr, colg, colb, 112);
+ blendpixel(nx-1, ny-1, colr, colg, colb, 112);
+ blendpixel(nx+1, ny+1, colr, colg, colb, 112);
+ blendpixel(nx-1, ny+1, colr, colg, colb, 112);
+#endif
+ }
+ if(pixel_mode & PMODE_GLOW)
+ {
+ int cola1 = (5*cola)/255;
+#ifdef OGLR
+ glowV[cglowV++] = nx;
+ glowV[cglowV++] = ny;
+ glowC[cglowC++] = ((float)colr)/255.0f;
+ glowC[cglowC++] = ((float)colg)/255.0f;
+ glowC[cglowC++] = ((float)colb)/255.0f;
+ glowC[cglowC++] = 1.0f;
+ cglow++;
+#else
+ addpixel(nx, ny, colr, colg, colb, (192*cola)/255);
+ addpixel(nx+1, ny, colr, colg, colb, (96*cola)/255);
+ addpixel(nx-1, ny, colr, colg, colb, (96*cola)/255);
+ addpixel(nx, ny+1, colr, colg, colb, (96*cola)/255);
+ addpixel(nx, ny-1, colr, colg, colb, (96*cola)/255);
+
+ for (x = 1; x < 6; x++) {
+ addpixel(nx, ny-x, colr, colg, colb, cola1);
+ addpixel(nx, ny+x, colr, colg, colb, cola1);
+ addpixel(nx-x, ny, colr, colg, colb, cola1);
+ addpixel(nx+x, ny, colr, colg, colb, cola1);
+ for (y = 1; y < 6; y++) {
+ if(x + y > 7)
+ continue;
+ addpixel(nx+x, ny-y, colr, colg, colb, cola1);
+ addpixel(nx-x, ny+y, colr, colg, colb, cola1);
+ addpixel(nx+x, ny+y, colr, colg, colb, cola1);
+ addpixel(nx-x, ny-y, colr, colg, colb, cola1);
+ }
+ }
+#endif
+ }
+ if(pixel_mode & PMODE_BLUR)
+ {
+#ifdef OGLR
+ blurV[cblurV++] = nx;
+ blurV[cblurV++] = ny;
+ blurC[cblurC++] = ((float)colr)/255.0f;
+ blurC[cblurC++] = ((float)colg)/255.0f;
+ blurC[cblurC++] = ((float)colb)/255.0f;
+ blurC[cblurC++] = 1.0f;
+ cblur++;
+#else
+ for (x=-3; x<4; x++)
+ {
+ for (y=-3; y<4; y++)
+ {
+ if (abs(x)+abs(y) <2 && !(abs(x)==2||abs(y)==2))
+ blendpixel(x+nx, y+ny, colr, colg, colb, 30);
+ if (abs(x)+abs(y) <=3 && abs(x)+abs(y))
+ blendpixel(x+nx, y+ny, colr, colg, colb, 20);
+ if (abs(x)+abs(y) == 2)
+ blendpixel(x+nx, y+ny, colr, colg, colb, 10);
+ }
+ }
+#endif
+ }
+ if(pixel_mode & PMODE_SPARK)
+ {
+ flicker = rand()%20;
+#ifdef OGLR
+ //Oh god, this is awful
+ lineC[clineC++] = ((float)colr)/255.0f;
+ lineC[clineC++] = ((float)colg)/255.0f;
+ lineC[clineC++] = ((float)colb)/255.0f;
+ lineC[clineC++] = 0.0f;
+ lineV[clineV++] = fnx-5;
+ lineV[clineV++] = fny;
+ cline++;
+
+ lineC[clineC++] = ((float)colr)/255.0f;
+ lineC[clineC++] = ((float)colg)/255.0f;
+ lineC[clineC++] = ((float)colb)/255.0f;
+ lineC[clineC++] = 1.0f - ((float)flicker)/30;
+ lineV[clineV++] = fnx;
+ lineV[clineV++] = fny;
+ cline++;
+
+ lineC[clineC++] = ((float)colr)/255.0f;
+ lineC[clineC++] = ((float)colg)/255.0f;
+ lineC[clineC++] = ((float)colb)/255.0f;
+ lineC[clineC++] = 0.0f;
+ lineV[clineV++] = fnx+5;
+ lineV[clineV++] = fny;
+ cline++;
+
+ lineC[clineC++] = ((float)colr)/255.0f;
+ lineC[clineC++] = ((float)colg)/255.0f;
+ lineC[clineC++] = ((float)colb)/255.0f;
+ lineC[clineC++] = 0.0f;
+ lineV[clineV++] = fnx;
+ lineV[clineV++] = fny-5;
+ cline++;
+
+ lineC[clineC++] = ((float)colr)/255.0f;
+ lineC[clineC++] = ((float)colg)/255.0f;
+ lineC[clineC++] = ((float)colb)/255.0f;
+ lineC[clineC++] = 1.0f - ((float)flicker)/30;
+ lineV[clineV++] = fnx;
+ lineV[clineV++] = fny;
+ cline++;
+
+ lineC[clineC++] = ((float)colr)/255.0f;
+ lineC[clineC++] = ((float)colg)/255.0f;
+ lineC[clineC++] = ((float)colb)/255.0f;
+ lineC[clineC++] = 0.0f;
+ lineV[clineV++] = fnx;
+ lineV[clineV++] = fny+5;
+ cline++;
+#else
+ gradv = 4*sim->parts[i].life + flicker;
+ for (x = 0; gradv>0.5; x++) {
+ addpixel(nx+x, ny, colr, colg, colb, gradv);
+ addpixel(nx-x, ny, colr, colg, colb, gradv);
+
+ addpixel(nx, ny+x, colr, colg, colb, gradv);
+ addpixel(nx, ny-x, colr, colg, colb, gradv);
+ gradv = gradv/1.5f;
+ }
+#endif
+ }
+ if(pixel_mode & PMODE_FLARE)
+ {
+ flicker = rand()%20;
+#ifdef OGLR
+ //Oh god, this is awful
+ lineC[clineC++] = ((float)colr)/255.0f;
+ lineC[clineC++] = ((float)colg)/255.0f;
+ lineC[clineC++] = ((float)colb)/255.0f;
+ lineC[clineC++] = 0.0f;
+ lineV[clineV++] = fnx-10;
+ lineV[clineV++] = fny;
+ cline++;
+
+ lineC[clineC++] = ((float)colr)/255.0f;
+ lineC[clineC++] = ((float)colg)/255.0f;
+ lineC[clineC++] = ((float)colb)/255.0f;
+ lineC[clineC++] = 1.0f - ((float)flicker)/40;
+ lineV[clineV++] = fnx;
+ lineV[clineV++] = fny;
+ cline++;
+
+ lineC[clineC++] = ((float)colr)/255.0f;
+ lineC[clineC++] = ((float)colg)/255.0f;
+ lineC[clineC++] = ((float)colb)/255.0f;
+ lineC[clineC++] = 0.0f;
+ lineV[clineV++] = fnx+10;
+ lineV[clineV++] = fny;
+ cline++;
+
+ lineC[clineC++] = ((float)colr)/255.0f;
+ lineC[clineC++] = ((float)colg)/255.0f;
+ lineC[clineC++] = ((float)colb)/255.0f;
+ lineC[clineC++] = 0.0f;
+ lineV[clineV++] = fnx;
+ lineV[clineV++] = fny-10;
+ cline++;
+
+ lineC[clineC++] = ((float)colr)/255.0f;
+ lineC[clineC++] = ((float)colg)/255.0f;
+ lineC[clineC++] = ((float)colb)/255.0f;
+ lineC[clineC++] = 1.0f - ((float)flicker)/30;
+ lineV[clineV++] = fnx;
+ lineV[clineV++] = fny;
+ cline++;
+
+ lineC[clineC++] = ((float)colr)/255.0f;
+ lineC[clineC++] = ((float)colg)/255.0f;
+ lineC[clineC++] = ((float)colb)/255.0f;
+ lineC[clineC++] = 0.0f;
+ lineV[clineV++] = fnx;
+ lineV[clineV++] = fny+10;
+ cline++;
+#else
+ gradv = flicker + fabs(parts[i].vx)*17 + fabs(sim->parts[i].vy)*17;
+ blendpixel(nx, ny, colr, colg, colb, (gradv*4)>255?255:(gradv*4) );
+ blendpixel(nx+1, ny, colr, colg, colb, (gradv*2)>255?255:(gradv*2) );
+ blendpixel(nx-1, ny, colr, colg, colb, (gradv*2)>255?255:(gradv*2) );
+ blendpixel(nx, ny+1, colr, colg, colb, (gradv*2)>255?255:(gradv*2) );
+ blendpixel(nx, ny-1, colr, colg, colb, (gradv*2)>255?255:(gradv*2) );
+ if (gradv>255) gradv=255;
+ blendpixel(nx+1, ny-1, colr, colg, colb, gradv);
+ blendpixel(nx-1, ny-1, colr, colg, colb, gradv);
+ blendpixel(nx+1, ny+1, colr, colg, colb, gradv);
+ blendpixel(nx-1, ny+1, colr, colg, colb, gradv);
+ for (x = 1; gradv>0.5; x++) {
+ addpixel(nx+x, ny, colr, colg, colb, gradv);
+ addpixel(nx-x, ny, colr, colg, colb, gradv);
+ addpixel(nx, ny+x, colr, colg, colb, gradv);
+ addpixel(nx, ny-x, colr, colg, colb, gradv);
+ gradv = gradv/1.2f;
+ }
+#endif
+ }
+ if(pixel_mode & PMODE_LFLARE)
+ {
+ flicker = rand()%20;
+#ifdef OGLR
+ //Oh god, this is awful
+ lineC[clineC++] = ((float)colr)/255.0f;
+ lineC[clineC++] = ((float)colg)/255.0f;
+ lineC[clineC++] = ((float)colb)/255.0f;
+ lineC[clineC++] = 0.0f;
+ lineV[clineV++] = fnx-70;
+ lineV[clineV++] = fny;
+ cline++;
+
+ lineC[clineC++] = ((float)colr)/255.0f;
+ lineC[clineC++] = ((float)colg)/255.0f;
+ lineC[clineC++] = ((float)colb)/255.0f;
+ lineC[clineC++] = 1.0f - ((float)flicker)/30;
+ lineV[clineV++] = fnx;
+ lineV[clineV++] = fny;
+ cline++;
+
+ lineC[clineC++] = ((float)colr)/255.0f;
+ lineC[clineC++] = ((float)colg)/255.0f;
+ lineC[clineC++] = ((float)colb)/255.0f;
+ lineC[clineC++] = 0.0f;
+ lineV[clineV++] = fnx+70;
+ lineV[clineV++] = fny;
+ cline++;
+
+ lineC[clineC++] = ((float)colr)/255.0f;
+ lineC[clineC++] = ((float)colg)/255.0f;
+ lineC[clineC++] = ((float)colb)/255.0f;
+ lineC[clineC++] = 0.0f;
+ lineV[clineV++] = fnx;
+ lineV[clineV++] = fny-70;
+ cline++;
+
+ lineC[clineC++] = ((float)colr)/255.0f;
+ lineC[clineC++] = ((float)colg)/255.0f;
+ lineC[clineC++] = ((float)colb)/255.0f;
+ lineC[clineC++] = 1.0f - ((float)flicker)/50;
+ lineV[clineV++] = fnx;
+ lineV[clineV++] = fny;
+ cline++;
+
+ lineC[clineC++] = ((float)colr)/255.0f;
+ lineC[clineC++] = ((float)colg)/255.0f;
+ lineC[clineC++] = ((float)colb)/255.0f;
+ lineC[clineC++] = 0.0f;
+ lineV[clineV++] = fnx;
+ lineV[clineV++] = fny+70;
+ cline++;
+#else
+ gradv = flicker + fabs(parts[i].vx)*17 + fabs(parts[i].vy)*17;
+ blendpixel(nx, ny, colr, colg, colb, (gradv*4)>255?255:(gradv*4) );
+ blendpixel(nx+1, ny, colr, colg, colb, (gradv*2)>255?255:(gradv*2) );
+ blendpixel(nx-1, ny, colr, colg, colb, (gradv*2)>255?255:(gradv*2) );
+ blendpixel(nx, ny+1, colr, colg, colb, (gradv*2)>255?255:(gradv*2) );
+ blendpixel(nx, ny-1, colr, colg, colb, (gradv*2)>255?255:(gradv*2) );
+ if (gradv>255) gradv=255;
+ blendpixel(nx+1, ny-1, colr, colg, colb, gradv);
+ blendpixel(nx-1, ny-1, colr, colg, colb, gradv);
+ blendpixel(nx+1, ny+1, colr, colg, colb, gradv);
+ blendpixel(nx-1, ny+1, colr, colg, colb, gradv);
+ for (x = 1; gradv>0.5; x++) {
+ addpixel(nx+x, ny, colr, colg, colb, gradv);
+ addpixel(nx-x, ny, colr, colg, colb, gradv);
+ addpixel(nx, ny+x, colr, colg, colb, gradv);
+ addpixel(nx, ny-x, colr, colg, colb, gradv);
+ gradv = gradv/1.01f;
+ }
+#endif
+ }
+ if (pixel_mode & EFFECT_GRAVIN)
+ {
+ int nxo = 0;
+ int nyo = 0;
+ int r;
+ int fire_rv = 0;
+ float drad = 0.0f;
+ float ddist = 0.0f;
+ sim->orbitalparts_get(parts[i].life, parts[i].ctype, orbd, orbl);
+ for (r = 0; r < 4; r++) {
+ ddist = ((float)orbd[r])/16.0f;
+ drad = (M_PI * ((float)orbl[r]) / 180.0f)*1.41f;
+ nxo = (int)(ddist*cos(drad));
+ nyo = (int)(ddist*sin(drad));
+ if (ny+nyo>0 && ny+nyo<YRES && nx+nxo>0 && nx+nxo<XRES && (sim->pmap[ny+nyo][nx+nxo]&0xFF) != PT_PRTI)
+ addpixel(nx+nxo, ny+nyo, colr, colg, colb, 255-orbd[r]);
+ }
+ }
+ if (pixel_mode & EFFECT_GRAVOUT)
+ {
+ int nxo = 0;
+ int nyo = 0;
+ int r;
+ int fire_bv = 0;
+ float drad = 0.0f;
+ float ddist = 0.0f;
+ sim->orbitalparts_get(parts[i].life, parts[i].ctype, orbd, orbl);
+ for (r = 0; r < 4; r++) {
+ ddist = ((float)orbd[r])/16.0f;
+ drad = (M_PI * ((float)orbl[r]) / 180.0f)*1.41f;
+ nxo = (int)(ddist*cos(drad));
+ nyo = (int)(ddist*sin(drad));
+ if (ny+nyo>0 && ny+nyo<YRES && nx+nxo>0 && nx+nxo<XRES && (sim->pmap[ny+nyo][nx+nxo]&0xFF) != PT_PRTO)
+ addpixel(nx+nxo, ny+nyo, colr, colg, colb, 255-orbd[r]);
+ }
+ }
+ if (pixel_mode & EFFECT_DBGLINES)
+ {
+ if (mousePosX == nx && mousePosY == ny && debugLines)//draw lines connecting wifi/portal channels
+ {
+ int z;
+ int type = parts[i].type;
+ if (type == PT_PRTI)
+ type = PT_PRTO;
+ else if (type == PT_PRTO)
+ type = PT_PRTI;
+ for (z = 0; z<NPART; z++) {
+ if (parts[z].type)
+ {
+ if (parts[z].type==type&&parts[z].tmp==parts[i].tmp)
+ xor_line(nx,ny,(int)(parts[z].x+0.5f),(int)(parts[z].y+0.5f));
+ }
+ }
+ }
+ }
+ //Fire effects
+ if(firea && (pixel_mode & FIRE_BLEND))
+ {
+#ifdef OGLR
+ smokeV[csmokeV++] = nx;
+ smokeV[csmokeV++] = ny;
+ smokeC[csmokeC++] = ((float)firer)/255.0f;
+ smokeC[csmokeC++] = ((float)fireg)/255.0f;
+ smokeC[csmokeC++] = ((float)fireb)/255.0f;
+ smokeC[csmokeC++] = ((float)firea)/255.0f;
+ csmoke++;
+#else
+ firea /= 2;
+ fire_r[ny/CELL][nx/CELL] = (firea*firer + (255-firea)*fire_r[ny/CELL][nx/CELL]) >> 8;
+ fire_g[ny/CELL][nx/CELL] = (firea*fireg + (255-firea)*fire_g[ny/CELL][nx/CELL]) >> 8;
+ fire_b[ny/CELL][nx/CELL] = (firea*fireb + (255-firea)*fire_b[ny/CELL][nx/CELL]) >> 8;
+#endif
+ }
+ if(firea && (pixel_mode & FIRE_ADD))
+ {
+#ifdef OGLR
+ fireV[cfireV++] = nx;
+ fireV[cfireV++] = ny;
+ fireC[cfireC++] = ((float)firer)/255.0f;
+ fireC[cfireC++] = ((float)fireg)/255.0f;
+ fireC[cfireC++] = ((float)fireb)/255.0f;
+ fireC[cfireC++] = ((float)firea)/255.0f;
+ cfire++;
+#else
+ firea /= 8;
+ firer = ((firea*firer) >> 8) + fire_r[ny/CELL][nx/CELL];
+ fireg = ((firea*fireg) >> 8) + fire_g[ny/CELL][nx/CELL];
+ fireb = ((firea*fireb) >> 8) + fire_b[ny/CELL][nx/CELL];
+
+ if(firer>255)
+ firer = 255;
+ if(fireg>255)
+ fireg = 255;
+ if(fireb>255)
+ fireb = 255;
+
+ fire_r[ny/CELL][nx/CELL] = firer;
+ fire_g[ny/CELL][nx/CELL] = fireg;
+ fire_b[ny/CELL][nx/CELL] = fireb;
+#endif
+ }
+ }
+ }
+ }
+#ifdef OGLR
+
+ //Go into array mode
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ if(cflat)
+ {
+ // -- BEGIN FLAT -- //
+ //Set point size (size of fire texture)
+ glPointSize(1.0f);
+
+ glColorPointer(4, GL_FLOAT, 0, &flatC[0]);
+ glVertexPointer(2, GL_INT, 0, &flatV[0]);
+
+ glDrawArrays(GL_POINTS, 0, cflat);
+
+ //Clear some stuff we set
+ // -- END FLAT -- //
+ }
+
+ if(cblob)
+ {
+ // -- BEGIN BLOB -- //
+ glEnable( GL_POINT_SMOOTH ); //Blobs!
+ glPointSize(2.5f);
+
+ glColorPointer(4, GL_FLOAT, 0, &blobC[0]);
+ glVertexPointer(2, GL_INT, 0, &blobV[0]);
+
+ glDrawArrays(GL_POINTS, 0, cblob);
+
+ //Clear some stuff we set
+ glDisable( GL_POINT_SMOOTH );
+ // -- END BLOB -- //
+ }
+
+ if(cglow || cblur)
+ {
+ // -- BEGIN GLOW -- //
+ //Start and prepare fire program
+ glEnable(GL_TEXTURE_2D);
+ glUseProgram(fireProg);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, glowAlpha);
+ glUniform1i(glGetUniformLocation(fireProg, "fireAlpha"), 0);
+
+ glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
+
+ //Make sure we can use texture coords on points
+ glEnable(GL_POINT_SPRITE);
+ glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
+ glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
+
+ //Set point size (size of fire texture)
+ glPointSize(11.0f);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+
+ if(cglow)
+ {
+ glColorPointer(4, GL_FLOAT, 0, &glowC[0]);
+ glVertexPointer(2, GL_INT, 0, &glowV[0]);
+
+ glDrawArrays(GL_POINTS, 0, cglow);
+ }
+
+ glPointSize(7.0f);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ if(cblur)
+ {
+ glBindTexture(GL_TEXTURE_2D, blurAlpha);
+
+ glColorPointer(4, GL_FLOAT, 0, &blurC[0]);
+ glVertexPointer(2, GL_INT, 0, &blurV[0]);
+
+ glDrawArrays(GL_POINTS, 0, cblur);
+ }
+
+ //Clear some stuff we set
+ glDisable(GL_POINT_SPRITE);
+ glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
+ glUseProgram(0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+ // -- END GLOW -- //
+ }
+
+ if(cadd)
+ {
+ // -- BEGIN ADD -- //
+ //Set point size (size of fire texture)
+ glPointSize(1.0f);
+
+ glColorPointer(4, GL_FLOAT, 0, &addC[0]);
+ glVertexPointer(2, GL_INT, 0, &addV[0]);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ glDrawArrays(GL_POINTS, 0, cadd);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ //Clear some stuff we set
+ // -- END ADD -- //
+ }
+
+ if(cline)
+ {
+ // -- BEGIN LINES -- //
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ glEnable( GL_LINE_SMOOTH );
+ glColorPointer(4, GL_FLOAT, 0, &lineC[0]);
+ glVertexPointer(2, GL_FLOAT, 0, &lineV[0]);
+
+ glDrawArrays(GL_LINE_STRIP, 0, cline);
+
+ //Clear some stuff we set
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_LINE_SMOOTH);
+ // -- END LINES -- //
+ }
+
+ if(cfire || csmoke)
+ {
+ // -- BEGIN FIRE -- //
+ //Start and prepare fire program
+ glEnable(GL_TEXTURE_2D);
+ glUseProgram(fireProg);
+ //glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, fireAlpha);
+ glUniform1i(glGetUniformLocation(fireProg, "fireAlpha"), 0);
+
+ //Make sure we can use texture coords on points
+ glEnable(GL_POINT_SPRITE);
+ glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
+ glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
+
+ //Set point size (size of fire texture)
+ glPointSize(CELL*3);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+
+ if(cfire)
+ {
+ glColorPointer(4, GL_FLOAT, 0, &fireC[0]);
+ glVertexPointer(2, GL_INT, 0, &fireV[0]);
+
+ glDrawArrays(GL_POINTS, 0, cfire);
+ }
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ if(csmoke)
+ {
+ glColorPointer(4, GL_FLOAT, 0, &smokeC[0]);
+ glVertexPointer(2, GL_INT, 0, &smokeV[0]);
+
+ glDrawArrays(GL_POINTS, 0, csmoke);
+ }
+
+ //Clear some stuff we set
+ glDisable(GL_POINT_SPRITE);
+ glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
+ glUseProgram(0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+ // -- END FIRE -- //
+ }
+
+ glDisableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ //Reset FBO
+ glTranslated(0, -MENUSIZE, 0);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFbo);
+
+ glBlendFunc(origBlendSrc, origBlendDst);
+#endif
+}
+
+void Renderer::draw_other() // EMP effect
+{
+ int i, j;
+ int emp_decor = sim->emp_decor;
+ if (emp_decor>40) emp_decor = 40;
+ if (emp_decor<0) emp_decor = 0;
+ if (!(render_mode & EFFECT)) // not in nothing mode
+ return;
+ if (emp_decor>0)
+ {
+#ifdef OGLR
+ GLint prevFbo;
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFbo);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo);
+ glTranslated(0, MENUSIZE, 0);
+ float femp_decor = ((float)emp_decor)/255.0f;
+ /*int r=emp_decor*2.5, g=100+emp_decor*1.5, b=255;
+ int a=(1.0*emp_decor/110)*255;
+ if (r>255) r=255;
+ if (g>255) g=255;
+ if (b>255) g=255;
+ if (a>255) a=255;*/
+ glBegin(GL_QUADS);
+ glColor4f(femp_decor*2.5f, 0.4f+femp_decor*1.5f, 1.0f+femp_decor*1.5f, femp_decor/0.44f);
+ glVertex2f(0, MENUSIZE);
+ glVertex2f(XRES, MENUSIZE);
+ glVertex2f(XRES, YRES+MENUSIZE);
+ glVertex2f(0, YRES+MENUSIZE);
+ glEnd();
+ glTranslated(0, -MENUSIZE, 0);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFbo);
+#else
+ int r=emp_decor*2.5, g=100+emp_decor*1.5, b=255;
+ int a=(1.0*emp_decor/110)*255;
+ if (r>255) r=255;
+ if (g>255) g=255;
+ if (b>255) g=255;
+ if (a>255) a=255;
+ for (j=0; j<YRES; j++)
+ for (i=0; i<XRES; i++)
+ {
+ blendpixel(i, j, r, g, b, a);
+ }
+#endif
+ }
+}
+
+void Renderer::draw_grav()
+{
+ int x, y, i, ca;
+ float nx, ny, dist;
+
+ if(!gravityFieldEnabled)
+ return;
+
+ for (y=0; y<YRES/CELL; y++)
+ {
+ for (x=0; x<XRES/CELL; x++)
+ {
+ ca = y*(XRES/CELL)+x;
+ if(fabsf(sim->gravx[ca]) <= 0.001f && fabsf(sim->gravy[ca]) <= 0.001f)
+ continue;
+ nx = x*CELL;
+ ny = y*CELL;
+ dist = fabsf(sim->gravy[ca])+fabsf(sim->gravx[ca]);
+ for(i = 0; i < 4; i++)
+ {
+ nx -= sim->gravx[ca]*0.5f;
+ ny -= sim->gravy[ca]*0.5f;
+ addpixel((int)(nx+0.5f), (int)(ny+0.5f), 255, 255, 255, (int)(dist*20.0f));
+ }
+ }
+ }
+}
+
+void Renderer::draw_air()
+{
+ if(!sim->aheat_enable && (display_mode & DISPLAY_AIRH))
+ return;
+#ifndef OGLR
+ if(!(display_mode & DISPLAY_AIR))
+ return;
+ int x, y, i, j;
+ float (*pv)[XRES/CELL] = sim->air->pv;
+ float (*hv)[XRES/CELL] = sim->air->hv;
+ float (*vx)[XRES/CELL] = sim->air->vx;
+ float (*vy)[XRES/CELL] = sim->air->vy;
+ pixel c;
+ for (y=0; y<YRES/CELL; y++)
+ for (x=0; x<XRES/CELL; x++)
+ {
+ if (display_mode & DISPLAY_AIRP)
+ {
+ if (pv[y][x] > 0.0f)
+ c = PIXRGB(clamp_flt(pv[y][x], 0.0f, 8.0f), 0, 0);//positive pressure is red!
+ else
+ c = PIXRGB(0, 0, clamp_flt(-pv[y][x], 0.0f, 8.0f));//negative pressure is blue!
+ }
+ else if (display_mode & DISPLAY_AIRV)
+ {
+ c = PIXRGB(clamp_flt(fabsf(vx[y][x]), 0.0f, 8.0f),//vx adds red
+ clamp_flt(pv[y][x], 0.0f, 8.0f),//pressure adds green
+ clamp_flt(fabsf(vy[y][x]), 0.0f, 8.0f));//vy adds blue
+ }
+ else if (display_mode & DISPLAY_AIRH)
+ {
+ float ttemp = hv[y][x]+(-MIN_TEMP);
+ 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);
+ c = PIXRGB((int)((unsigned char)color_data[caddress]*0.7f), (int)((unsigned char)color_data[caddress+1]*0.7f), (int)((unsigned char)color_data[caddress+2]*0.7f));
+ //c = PIXRGB(clamp_flt(fabsf(vx[y][x]), 0.0f, 8.0f),//vx adds red
+ // clamp_flt(hv[y][x], 0.0f, 1600.0f),//heat adds green
+ // clamp_flt(fabsf(vy[y][x]), 0.0f, 8.0f));//vy adds blue
+ }
+ else if (display_mode & DISPLAY_AIRC)
+ {
+ int r;
+ int g;
+ int b;
+ // velocity adds grey
+ r = clamp_flt(fabsf(vx[y][x]), 0.0f, 24.0f) + clamp_flt(fabsf(vy[y][x]), 0.0f, 20.0f);
+ g = clamp_flt(fabsf(vx[y][x]), 0.0f, 20.0f) + clamp_flt(fabsf(vy[y][x]), 0.0f, 24.0f);
+ b = clamp_flt(fabsf(vx[y][x]), 0.0f, 24.0f) + clamp_flt(fabsf(vy[y][x]), 0.0f, 20.0f);
+ if (pv[y][x] > 0.0f)
+ {
+ r += clamp_flt(pv[y][x], 0.0f, 16.0f);//pressure adds red!
+ if (r>255)
+ r=255;
+ if (g>255)
+ g=255;
+ if (b>255)
+ b=255;
+ c = PIXRGB(r, g, b);
+ }
+ else
+ {
+ b += clamp_flt(-pv[y][x], 0.0f, 16.0f);//pressure adds blue!
+ if (r>255)
+ r=255;
+ if (g>255)
+ g=255;
+ if (b>255)
+ b=255;
+ c = PIXRGB(r, g, b);
+ }
+ }
+ for (j=0; j<CELL; j++)//draws the colors
+ for (i=0; i<CELL; i++)
+ vid[(x*CELL+i) + (y*CELL+j)*(VIDXRES)] = c;
+ }
+#else
+ int sdl_scale = 1;
+ GLuint airProg;
+ GLint prevFbo;
+ if(display_mode & DISPLAY_AIRC)
+ {
+ airProg = airProg_Cracker;
+ }
+ else if(display_mode & DISPLAY_AIRV)
+ {
+ airProg = airProg_Velocity;
+ }
+ else if(display_mode & DISPLAY_AIRP)
+ {
+ airProg = airProg_Pressure;
+ }
+ else
+ {
+ return;
+ }
+
+ glEnable( GL_TEXTURE_2D );
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFbo);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo);
+ glTranslated(0, MENUSIZE, 0);
+
+ glUseProgram(airProg);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, airVX);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, XRES/CELL, YRES/CELL, GL_RED, GL_FLOAT, sim->air->vx);
+ glUniform1i(glGetUniformLocation(airProg, "airX"), 0);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, airVY);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, XRES/CELL, YRES/CELL, GL_GREEN, GL_FLOAT, sim->air->vy);
+ glUniform1i(glGetUniformLocation(airProg, "airY"), 1);
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D, airPV);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, XRES/CELL, YRES/CELL, GL_BLUE, GL_FLOAT, sim->air->pv);
+ glUniform1i(glGetUniformLocation(airProg, "airP"), 2);
+ glActiveTexture(GL_TEXTURE0);
+
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ glBegin(GL_QUADS);
+ glTexCoord2d(1, 1);
+ glVertex3f(XRES*sdl_scale, YRES*sdl_scale, 1.0);
+ glTexCoord2d(0, 1);
+ glVertex3f(0, YRES*sdl_scale, 1.0);
+ glTexCoord2d(0, 0);
+ glVertex3f(0, 0, 1.0);
+ glTexCoord2d(1, 0);
+ glVertex3f(XRES*sdl_scale, 0, 1.0);
+ glEnd();
+
+ glUseProgram(0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glTranslated(0, -MENUSIZE, 0);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFbo);
+ glDisable( GL_TEXTURE_2D );
+#endif
+}
+
+void Renderer::draw_grav_zones()
+{
+ if(!gravityZonesEnabled)
+ return;
+
+ int x, y, i, j;
+ for (y=0; y<YRES/CELL; y++)
+ {
+ for (x=0; x<XRES/CELL; x++)
+ {
+ if(sim->grav->gravmask[y*(XRES/CELL)+x])
+ {
+ for (j=0; j<CELL; j++)//draws the colors
+ for (i=0; i<CELL; i++)
+ if(i == j)
+ blendpixel(x*CELL+i, y*CELL+j, 255, 200, 0, 120);
+ else
+ blendpixel(x*CELL+i, y*CELL+j, 32, 32, 32, 120);
+ }
+ }
+ }
+}
+
+void Renderer::drawblob(int x, int y, unsigned char cr, unsigned char cg, unsigned char cb)
+{
+ blendpixel(x+1, y, cr, cg, cb, 112);
+ blendpixel(x-1, y, cr, cg, cb, 112);
+ blendpixel(x, y+1, cr, cg, cb, 112);
+ blendpixel(x, y-1, cr, cg, cb, 112);
+
+ blendpixel(x+1, y-1, cr, cg, cb, 64);
+ blendpixel(x-1, y-1, cr, cg, cb, 64);
+ blendpixel(x+1, y+1, cr, cg, cb, 64);
+ blendpixel(x-1, y+1, cr, cg, cb, 64);
+}
+
+pixel Renderer::GetPixel(int x, int y)
+{
+ if (x<0 || y<0 || x>=VIDXRES || y>=VIDYRES)
+ return 0;
+#ifdef OGLR
+ return 0;
+#else
+ return vid[(y*VIDXRES)+x];
+#endif
+}
+
+Renderer::Renderer(Graphics * g, Simulation * sim):
+ sim(NULL),
+ g(NULL),
+ zoomWindowPosition(0, 0),
+ zoomScopePosition(0, 0),
+ zoomScopeSize(32),
+ ZFACTOR(8),
+ zoomEnabled(false),
+ decorations_enable(1),
+ gravityFieldEnabled(false),
+ gravityZonesEnabled(false),
+ mousePosX(-1),
+ mousePosY(-1),
+ display_mode(0),
+ render_mode(0),
+ colour_mode(0),
+ gridSize(0),
+ blackDecorations(false),
+ debugLines(false)
+{
+ this->g = g;
+ this->sim = sim;
+#if !defined(OGLR)
+#if defined(OGLI)
+ vid = new pixel[VIDXRES*VIDYRES];
+#else
+ vid = g->vid;
+#endif
+ persistentVid = new pixel[VIDXRES*YRES];
+ warpVid = new pixel[VIDXRES*VIDYRES];
+#endif
+
+ memset(fire_r, 0, sizeof(fire_r));
+ memset(fire_g, 0, sizeof(fire_g));
+ memset(fire_b, 0, sizeof(fire_b));
+
+ //Set defauly display modes
+ SetColourMode(COLOUR_DEFAULT);
+ AddRenderMode(RENDER_BASC);
+ AddRenderMode(RENDER_FIRE);
+
+ //Render mode presets. Possibly load from config in future?
+ renderModePresets = new RenderPreset[11];
+
+ renderModePresets[0].Name = "Alternative Velocity Display";
+ renderModePresets[0].RenderModes.push_back(RENDER_EFFE);
+ renderModePresets[0].RenderModes.push_back(RENDER_BASC);
+ renderModePresets[0].DisplayModes.push_back(DISPLAY_AIRC);
+
+ renderModePresets[1].Name = "Velocity Display";
+ renderModePresets[1].RenderModes.push_back(RENDER_EFFE);
+ renderModePresets[1].RenderModes.push_back(RENDER_BASC);
+ renderModePresets[1].DisplayModes.push_back(DISPLAY_AIRV);
+
+ renderModePresets[2].Name = "Pressure Display";
+ renderModePresets[2].RenderModes.push_back(RENDER_EFFE);
+ renderModePresets[2].RenderModes.push_back(RENDER_BASC);
+ renderModePresets[2].DisplayModes.push_back(DISPLAY_AIRP);
+
+ renderModePresets[3].Name = "Persistent Display";
+ renderModePresets[3].RenderModes.push_back(RENDER_EFFE);
+ renderModePresets[3].RenderModes.push_back(RENDER_BASC);
+ renderModePresets[3].DisplayModes.push_back(DISPLAY_PERS);
+
+ renderModePresets[4].Name = "Fire Display";
+ renderModePresets[4].RenderModes.push_back(RENDER_FIRE);
+ renderModePresets[4].RenderModes.push_back(RENDER_EFFE);
+ renderModePresets[4].RenderModes.push_back(RENDER_BASC);
+
+ renderModePresets[5].Name = "Blob Display";
+ renderModePresets[5].RenderModes.push_back(RENDER_FIRE);
+ renderModePresets[5].RenderModes.push_back(RENDER_EFFE);
+ renderModePresets[5].RenderModes.push_back(RENDER_BLOB);
+
+ renderModePresets[6].Name = "Heat Display";
+ renderModePresets[6].RenderModes.push_back(RENDER_BASC);
+ renderModePresets[6].DisplayModes.push_back(DISPLAY_AIRH);
+ renderModePresets[6].ColourMode = COLOUR_HEAT;
+
+ renderModePresets[7].Name = "Fancy Display";
+ renderModePresets[7].RenderModes.push_back(RENDER_FIRE);
+ renderModePresets[7].RenderModes.push_back(RENDER_GLOW);
+ renderModePresets[7].RenderModes.push_back(RENDER_BLUR);
+ renderModePresets[7].RenderModes.push_back(RENDER_EFFE);
+ renderModePresets[7].RenderModes.push_back(RENDER_BASC);
+ renderModePresets[7].DisplayModes.push_back(DISPLAY_WARP);
+
+ renderModePresets[8].Name = "Nothing Display";
+ renderModePresets[8].RenderModes.push_back(RENDER_BASC);
+
+ renderModePresets[9].Name = "Heat Gradient Display";
+ renderModePresets[9].RenderModes.push_back(RENDER_BASC);
+ renderModePresets[9].ColourMode = COLOUR_GRAD;
+
+ renderModePresets[10].Name = "Life Gradient Display";
+ renderModePresets[10].RenderModes.push_back(RENDER_BASC);
+ renderModePresets[10].ColourMode = COLOUR_LIFE;
+
+ //Prepare the graphics cache
+ graphicscache = (gcache_item *)malloc(sizeof(gcache_item)*PT_NUM);
+ memset(graphicscache, 0, sizeof(gcache_item)*PT_NUM);
+
+ int fireColoursCount = 4;
+ pixel fireColours[] = {PIXPACK(0xAF9F0F), PIXPACK(0xDFBF6F), PIXPACK(0x60300F), PIXPACK(0x000000)};
+ float fireColoursPoints[] = {1.0f, 0.9f, 0.5f, 0.0f};
+
+ int plasmaColoursCount = 5;
+ pixel plasmaColours[] = {PIXPACK(0xAFFFFF), PIXPACK(0xAFFFFF), PIXPACK(0x301060), PIXPACK(0x301040), PIXPACK(0x000000)};
+ float plasmaColoursPoints[] = {1.0f, 0.9f, 0.5f, 0.25, 0.0f};
+
+ flm_data = Graphics::GenerateGradient(fireColours, fireColoursPoints, fireColoursCount, 200);
+ plasma_data = Graphics::GenerateGradient(plasmaColours, plasmaColoursPoints, plasmaColoursCount, 200);
+
+#ifdef OGLR
+ //FBO Texture
+ glEnable(GL_TEXTURE_2D);
+ glGenTextures(1, &partsFboTex);
+ glBindTexture(GL_TEXTURE_2D, partsFboTex);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, XRES, YRES, 0, GL_RGBA, GL_FLOAT, NULL);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+
+ //FBO
+ glGenFramebuffers(1, &partsFbo);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo);
+ glEnable(GL_BLEND);
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, partsFboTex, 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // Reset framebuffer binding
+ glDisable(GL_TEXTURE_2D);
+
+ //Texture for air to be drawn
+ glEnable(GL_TEXTURE_2D);
+ glGenTextures(1, &airBuf);
+ glBindTexture(GL_TEXTURE_2D, airBuf);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, XRES/CELL, YRES/CELL, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+
+ //Zoom texture
+ glEnable(GL_TEXTURE_2D);
+ glGenTextures(1, &zoomTex);
+ glBindTexture(GL_TEXTURE_2D, zoomTex);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+
+ //Texture for velocity maps for gravity
+ glEnable(GL_TEXTURE_2D);
+ glGenTextures(1, &partsTFX);
+ glBindTexture(GL_TEXTURE_2D, partsTFX);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, XRES/CELL, YRES/CELL, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glGenTextures(1, &partsTFY);
+ glBindTexture(GL_TEXTURE_2D, partsTFY);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, XRES/CELL, YRES/CELL, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+
+ //Texture for velocity maps for air
+ //TODO: Combine all air maps into 3D array or structs
+ glEnable(GL_TEXTURE_2D);
+ glGenTextures(1, &airVX);
+ glBindTexture(GL_TEXTURE_2D, airVX);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, XRES/CELL, YRES/CELL, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glGenTextures(1, &airVY);
+ glBindTexture(GL_TEXTURE_2D, airVY);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, XRES/CELL, YRES/CELL, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glGenTextures(1, &airPV);
+ glBindTexture(GL_TEXTURE_2D, airPV);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, XRES/CELL, YRES/CELL, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+
+ //Fire alpha texture
+ glEnable(GL_TEXTURE_2D);
+ glGenTextures(1, &fireAlpha);
+ glBindTexture(GL_TEXTURE_2D, fireAlpha);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, CELL*3, CELL*3, 0, GL_ALPHA, GL_FLOAT, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+
+ //Glow alpha texture
+ glEnable(GL_TEXTURE_2D);
+ glGenTextures(1, &glowAlpha);
+ glBindTexture(GL_TEXTURE_2D, glowAlpha);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 11, 11, 0, GL_ALPHA, GL_FLOAT, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+
+
+ //Blur Alpha texture
+ glEnable(GL_TEXTURE_2D);
+ glGenTextures(1, &blurAlpha);
+ glBindTexture(GL_TEXTURE_2D, blurAlpha);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 7, 7, 0, GL_ALPHA, GL_FLOAT, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+
+ //Temptexture
+ glEnable(GL_TEXTURE_2D);
+ glGenTextures(1, &textTexture);
+ glBindTexture(GL_TEXTURE_2D, textTexture);
+
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+
+ loadShaders();
+#endif
+ prepare_alpha(CELL, 1.0f);
+}
+
+void Renderer::CompileRenderMode()
+{
+ int old_render_mode = render_mode;
+ render_mode = 0;
+ for(int i = 0; i < render_modes.size(); i++)
+ render_mode |= render_modes[i];
+
+ //If firemode is removed, clear the fire display
+ if(!(render_mode & FIREMODE) && (old_render_mode & FIREMODE))
+ {
+ ClearAccumulation();
+ }
+}
+
+void Renderer::ClearAccumulation()
+{
+ std::fill(fire_r[0]+0, fire_r[(YRES/CELL)-1]+((XRES/CELL)-1), 0);
+ std::fill(fire_g[0]+0, fire_g[(YRES/CELL)-1]+((XRES/CELL)-1), 0);
+ std::fill(fire_b[0]+0, fire_b[(YRES/CELL)-1]+((XRES/CELL)-1), 0);
+#ifndef OGLR
+ std::fill(persistentVid, persistentVid+(VIDXRES*YRES), 0);
+#endif
+}
+
+void Renderer::AddRenderMode(unsigned int mode)
+{
+ for(int i = 0; i < render_modes.size(); i++)
+ {
+ if(render_modes[i] == mode)
+ {
+ return;
+ }
+ }
+ render_modes.push_back(mode);
+ CompileRenderMode();
+}
+
+void Renderer::RemoveRenderMode(unsigned int mode)
+{
+ for(int i = 0; i < render_modes.size(); i++)
+ {
+ if(render_modes[i] == mode)
+ {
+ render_modes.erase(render_modes.begin() + i);
+ i = 0;
+ }
+ }
+ CompileRenderMode();
+}
+
+void Renderer::SetRenderMode(std::vector<unsigned int> render)
+{
+ render_modes = render;
+ CompileRenderMode();
+}
+
+std::vector<unsigned int> Renderer::GetRenderMode()
+{
+ return render_modes;
+}
+
+void Renderer::CompileDisplayMode()
+{
+ display_mode = 0;
+ for(int i = 0; i < display_modes.size(); i++)
+ display_mode |= display_modes[i];
+}
+
+void Renderer::AddDisplayMode(unsigned int mode)
+{
+ for(int i = 0; i < display_modes.size(); i++)
+ {
+ if(display_modes[i] == mode)
+ {
+ return;
+ }
+ if(display_modes[i] & DISPLAY_AIR)
+ {
+ display_modes.erase(display_modes.begin()+i);
+ }
+ }
+ display_modes.push_back(mode);
+ CompileDisplayMode();
+}
+
+void Renderer::RemoveDisplayMode(unsigned int mode)
+{
+ for(int i = 0; i < display_modes.size(); i++)
+ {
+ if(display_modes[i] == mode)
+ {
+ display_modes.erase(display_modes.begin() + i);
+ i = 0;
+ }
+ }
+ CompileDisplayMode();
+}
+
+void Renderer::SetDisplayMode(std::vector<unsigned int> display)
+{
+ display_modes = display;
+ CompileDisplayMode();
+}
+
+std::vector<unsigned int> Renderer::GetDisplayMode()
+{
+ return display_modes;
+}
+
+void Renderer::SetColourMode(unsigned int mode)
+{
+ colour_mode = mode;
+}
+
+unsigned int Renderer::GetColourMode()
+{
+ return colour_mode;
+}
+
+VideoBuffer Renderer::DumpFrame()
+{
+#ifdef OGLR
+#elif defined(OGLI)
+ VideoBuffer newBuffer(XRES, YRES);
+ std::copy(vid, vid+(XRES*YRES), newBuffer.Buffer);
+ return newBuffer;
+#else
+ VideoBuffer newBuffer(XRES, YRES);
+ for(int y = 0; y < YRES; y++)
+ {
+ std::copy(vid+(y*(XRES+BARSIZE)), vid+(y*(XRES+BARSIZE))+XRES, newBuffer.Buffer+(y*XRES));
+ }
+ return newBuffer;
+#endif
+}
+
+Renderer::~Renderer()
+{
+ delete[] renderModePresets;
+
+#if !defined(OGLR)
+#if defined(OGLI)
+ delete[] vid;
+#endif
+ delete[] persistentVid;
+ delete[] warpVid;
+#endif
+ free(graphicscache);
+ free(flm_data);
+ free(plasma_data);
+}
+
+#define PIXELMETHODS_CLASS Renderer
+
+#ifdef OGLR
+#include "OpenGLDrawMethods.inl"
+#else
+#include "RasterDrawMethods.inl"
+#endif
+
+#undef PIXELMETHODS_CLASS
+
diff --git a/src/graphics/Renderer.h b/src/graphics/Renderer.h
new file mode 100644
index 0000000..fa12a8c
--- /dev/null
+++ b/src/graphics/Renderer.h
@@ -0,0 +1,184 @@
+#ifndef RENDERER_H
+#define RENDERER_H
+
+#include <vector>
+#ifdef OGLR
+#include "OpenGLHeaders.h"
+#endif
+
+#include "Config.h"
+#include "client/Client.h"
+#include "Graphics.h"
+#include "interface/Point.h"
+#include "game/RenderPreset.h"
+
+class Simulation;
+
+class Graphics;
+
+struct gcache_item
+{
+ int isready;
+ int pixel_mode;
+ int cola, colr, colg, colb;
+ int firea, firer, fireg, fireb;
+ gcache_item() :
+ isready(0),
+ pixel_mode(0),
+ cola(0),
+ colr(0),
+ colg(0),
+ colb(0),
+ firea(0),
+ firer(0),
+ fireg(0),
+ fireb(0)
+ {
+ }
+};
+typedef struct gcache_item gcache_item;
+
+class Renderer
+{
+public:
+ std::vector<unsigned int> render_modes;
+ unsigned int render_mode;
+ unsigned int colour_mode;
+ std::vector<unsigned int> display_modes;
+ unsigned int display_mode;
+ RenderPreset * renderModePresets;
+ //
+ unsigned char fire_r[YRES/CELL][XRES/CELL];
+ unsigned char fire_g[YRES/CELL][XRES/CELL];
+ unsigned char fire_b[YRES/CELL][XRES/CELL];
+ unsigned int fire_alpha[CELL*3][CELL*3];
+ char * flm_data;
+ char * plasma_data;
+ //
+ bool gravityZonesEnabled;
+ bool gravityFieldEnabled;
+ int decorations_enable;
+ bool blackDecorations;
+ bool debugLines;
+ Simulation * sim;
+ Graphics * g;
+ gcache_item *graphicscache;
+
+ //Mouse position for debug information
+ int mousePosX, mousePosY;
+
+ //Zoom window
+ ui::Point zoomWindowPosition;
+ ui::Point zoomScopePosition;
+ int zoomScopeSize;
+ bool zoomEnabled;
+ int ZFACTOR;
+
+ //Renderers
+ void RenderBegin();
+ void RenderEnd();
+
+ void RenderZoom();
+ void DrawWalls();
+ void DrawSigns();
+ void render_gravlensing(pixel * source);
+ void render_fire();
+ void prepare_alpha(int size, float intensity);
+ void render_parts();
+ void draw_grav_zones();
+ void draw_air();
+ void draw_grav();
+ void draw_other();
+ void FinaliseParts();
+
+ void ClearAccumulation();
+ void clearScreen(float alpha);
+
+ //class SolidsRenderer;
+
+#ifdef OGLR
+ void checkShader(GLuint shader, char * shname);
+ void checkProgram(GLuint program, char * progname);
+ void loadShaders();
+ GLuint vidBuf,textTexture;
+ GLint prevFbo;
+#endif
+ pixel * vid;
+ pixel * persistentVid;
+ pixel * warpVid;
+ void blendpixel(int x, int y, int r, int g, int b, int a);
+ void addpixel(int x, int y, int r, int g, int b, int a);
+
+ void draw_icon(int x, int y, Icon icon);
+
+ int drawtext(int x, int y, const char *s, int r, int g, int b, int a);
+ int drawtext(int x, int y, std::string s, int r, int g, int b, int a);
+ int drawchar(int x, int y, int c, int r, int g, int b, int a);
+ int addchar(int x, int y, int c, int r, int g, int b, int a);
+
+ void xor_pixel(int x, int y);
+ void xor_line(int x, int y, int x2, int y2);
+ void xor_rect(int x, int y, int width, int height);
+ void xor_bitmap(unsigned char * bitmap, int x, int y, int w, int h);
+
+ void draw_line(int x, int y, int x2, int y2, int r, int g, int b, int a);
+ void drawrect(int x, int y, int width, int height, int r, int g, int b, int a);
+ void fillrect(int x, int y, int width, int height, int r, int g, int b, int a);
+ void clearrect(int x, int y, int width, int height);
+ void gradientrect(int x, int y, int width, int height, int r, int g, int b, int a, int r2, int g2, int b2, int a2);
+
+ void draw_image(pixel *img, int x, int y, int w, int h, int a);
+
+ VideoBuffer DumpFrame();
+
+ void drawblob(int x, int y, unsigned char cr, unsigned char cg, unsigned char cb);
+
+ pixel GetPixel(int x, int y);
+ //...
+ //Display mode modifiers
+ void CompileDisplayMode();
+ void CompileRenderMode();
+ void AddRenderMode(unsigned int mode);
+ void SetRenderMode(std::vector<unsigned int> render);
+ std::vector<unsigned int> GetRenderMode();
+ void RemoveRenderMode(unsigned int mode);
+ void AddDisplayMode(unsigned int mode);
+ void RemoveDisplayMode(unsigned int mode);
+ void SetDisplayMode(std::vector<unsigned int> display);
+ std::vector<unsigned int> GetDisplayMode();
+ void SetColourMode(unsigned int mode);
+ unsigned int GetColourMode();
+
+ int GetGridSize() { return gridSize; }
+ void SetGridSize(int value) { gridSize = value; }
+
+ static VideoBuffer * WallIcon(int wallID, int width, int height);
+
+ Renderer(Graphics * g, Simulation * sim);
+ ~Renderer();
+
+private:
+ int gridSize;
+#ifdef OGLR
+ GLuint zoomTex, airBuf, fireAlpha, glowAlpha, blurAlpha, partsFboTex, partsFbo, partsTFX, partsTFY, airPV, airVY, airVX;
+ GLuint fireProg, airProg_Pressure, airProg_Velocity, airProg_Cracker, lensProg;
+ GLuint fireV[(YRES*XRES)*2];
+ GLfloat fireC[(YRES*XRES)*4];
+ GLuint smokeV[(YRES*XRES)*2];
+ GLfloat smokeC[(YRES*XRES)*4];
+ GLuint blobV[(YRES*XRES)*2];
+ GLfloat blobC[(YRES*XRES)*4];
+ GLuint blurV[(YRES*XRES)*2];
+ GLfloat blurC[(YRES*XRES)*4];
+ GLuint glowV[(YRES*XRES)*2];
+ GLfloat glowC[(YRES*XRES)*4];
+ GLuint flatV[(YRES*XRES)*2];
+ GLfloat flatC[(YRES*XRES)*4];
+ GLuint addV[(YRES*XRES)*2];
+ GLfloat addC[(YRES*XRES)*4];
+ GLfloat lineV[(((YRES*XRES)*2)*6)];
+ GLfloat lineC[(((YRES*XRES)*2)*6)];
+#endif
+};
+
+#endif