diff options
| author | Simon Robertshaw <simon@hardwired.org.uk> | 2012-01-08 17:39:03 (GMT) |
|---|---|---|
| committer | Simon Robertshaw <simon@hardwired.org.uk> | 2012-01-08 17:39:03 (GMT) |
| commit | b0ea52690ba56a0d0602ad8674b7e5ab2ba3e778 (patch) | |
| tree | 7d72e0509f4d2643d3be837a337d088ca5949c73 /src/Graphics.cpp | |
| download | powder-b0ea52690ba56a0d0602ad8674b7e5ab2ba3e778.zip powder-b0ea52690ba56a0d0602ad8674b7e5ab2ba3e778.tar.gz | |
Initial
Diffstat (limited to 'src/Graphics.cpp')
| -rw-r--r-- | src/Graphics.cpp | 2359 |
1 files changed, 2359 insertions, 0 deletions
diff --git a/src/Graphics.cpp b/src/Graphics.cpp new file mode 100644 index 0000000..52fa4c9 --- /dev/null +++ b/src/Graphics.cpp @@ -0,0 +1,2359 @@ +#include <math.h> +#include <SDL/SDL.h> +#include <bzlib.h> +#include <string> + +#if defined(OGLR) +#ifdef MACOSX +#include <GL/glew.h> +#include <OpenGL/gl.h> +#include <OpenGL/glu.h> +#elif defined(WIN32) +#include <GL/glew.h> +#include <GL/gl.h> +#include <GL/glu.h> +#else +#include <GL/gl.h> +#include <GL/glu.h> +#endif +#endif + +#include "Config.h" +#include "air.h" +#include "gravity.h" +//#include "powder.h" +#define INCLUDE_PSTRUCT +#include "Simulation.h" +#include "Graphics.h" +#include "ElementGraphics.h" +#define INCLUDE_FONTDATA +#include "font.h" +#include "misc.h" +#include "hmap.h" + +//unsigned cmode = CM_FIRE; +unsigned int *render_modes; +unsigned int render_mode; +unsigned int colour_mode; +unsigned int *display_modes; +unsigned int display_mode; + +//SDL_Surface *sdl_scrn; +int sdl_scale = 1; + +#ifdef OGLR +GLuint zoomTex, vidBuf, airBuf, fireAlpha, glowAlpha, blurAlpha, partsFboTex, partsFbo, partsTFX, partsTFY, airPV, airVY, airVX; +GLuint fireProg, airProg_Pressure, airProg_Velocity, airProg_Cracker, lensProg; +#endif + +/* +int emp_decor = 0; +int sandcolour_r = 0; +int sandcolour_g = 0; +int sandcolour_b = 0; +int sandcolour_frame = 0; + +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]; +pixel *pers_bg; + +char * flm_data; +int flm_data_points = 4; +pixel flm_data_colours[] = {PIXPACK(0xAF9F0F), PIXPACK(0xDFBF6F), PIXPACK(0x60300F), PIXPACK(0x000000)}; +float flm_data_pos[] = {1.0f, 0.9f, 0.5f, 0.0f}; + +char * plasma_data; +int plasma_data_points = 5; +pixel plasma_data_colours[] = {PIXPACK(0xAFFFFF), PIXPACK(0xAFFFFF), PIXPACK(0x301060), PIXPACK(0x301040), PIXPACK(0x000000)}; +float plasma_data_pos[] = {1.0f, 0.9f, 0.5f, 0.25, 0.0f};*/ + +char * Graphics::generate_gradient(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) +{ + int y, x, fxceil, fyceil; + //int i,j,x,y,w,h,r,g,b,c; + pixel *q = NULL; + //TODO: Actual resampling, this is just cheap nearest pixel crap + if(rw == sw && rh == sh){ + //Don't resample + q = (pixel *)malloc(rw*rh*PIXELSIZE); + memcpy(q, src, rw*rh*PIXELSIZE); + } else if(rw > sw && rh > sh){ + 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){ + rw *= 0.7; + rh *= 0.7; + if(rw <= rrw || rh <= rrh){ + rw = rrw; + rh = rrh; + } + 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 = 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; +} + +#ifdef OGLR +void clearScreen(float alpha) +{ + if(alpha > 0.999f) + { + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo); + glClear(GL_COLOR_BUFFER_BIT); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + } + else + { + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + glColor4f(1.0f, 1.0f, 1.0f, alpha); + 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, 0); + glBlendEquation(GL_FUNC_ADD); + } + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); +} + +void clearScreenNP(float alpha) +{ + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); +} + +void ogl_blit(int x, int y, int w, int h, pixel *src, int pitch, int scale) +{ + + //glDrawPixels(w,h,GL_BGRA,GL_UNSIGNED_BYTE,src); //Why does this still think it's ABGR? + glEnable( GL_TEXTURE_2D ); + glBindTexture(GL_TEXTURE_2D, vidBuf); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, XRES+BARSIZE, YRES+MENUSIZE, GL_BGRA, GL_UNSIGNED_BYTE, src); + glBegin(GL_QUADS); + glTexCoord2d(1, 0); + glVertex3f((XRES+BARSIZE)*sdl_scale, (YRES+MENUSIZE)*sdl_scale, 1.0); + glTexCoord2d(0, 0); + glVertex3f(0, (YRES+MENUSIZE)*sdl_scale, 1.0); + glTexCoord2d(0, 1); + glVertex3f(0, 0, 1.0); + glTexCoord2d(1, 1); + glVertex3f((XRES+BARSIZE)*sdl_scale, 0, 1.0); + glEnd(); + + glDisable( GL_TEXTURE_2D ); + glFlush(); + SDL_GL_SwapBuffers (); +} +#endif + +//an easy way to draw a blob +void Graphics::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); +} + +//draws walls and elements for menu +/*int draw_tool_xy(pixel *vid_buf, int x, int y, int b, unsigned pc) +{ + int i, j, c; + pixel gc; + if (x > XRES-26 || x < 0) + return 26; + if ((b&0xFF) == PT_LIFE) + { + for (j=1; j<15; j++) + { + for (i=1; i<27; i++) + { + vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; + } + } + c = PIXB(pc) + 3*PIXG(pc) + 2*PIXR(pc); + if (c<544) + { + c = 255; + } + else + { + c = 0; + } + drawtext(vid_buf, x+14-textwidth((char *)gmenu[(b>>8)&0xFF].name)/2, y+4, (char *)gmenu[(b>>8)&0xFF].name, c, c, c, 255); + } + else if (b>=UI_WALLSTART) + { + int ds = 0; + if (b-UI_WALLSTART>=0 && b-UI_WALLSTART<UI_WALLCOUNT) + { + ds = wtypes[b-UI_WALLSTART].drawstyle; + gc = wtypes[b-UI_WALLSTART].eglow; + } + //x = (2+32*((b-22)/1)); + //y = YRES+2+40; + if (ds==1) + { + for (j=1; j<15; j+=2) + for (i=1+(1&(j>>1)); i<27; i+=2) + vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; + } + else if (ds==2) + { + for (j=1; j<15; j+=2) + for (i=1; i<27; i+=2) + vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; + } + else if (ds==3) + { + for (j=1; j<15; j++) + for (i=1; i<27; i++) + vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; + } + else if (ds==4) + { + for (j=1; j<15; j++) + for (i=1; i<27; i++) + if(i%CELL == j%CELL) + vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; + else if (i%CELL == (j%CELL)+1 || (i%CELL == 0 && j%CELL == CELL-1)) + vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = gc; + else + vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = PIXPACK(0x202020); + } + else + switch (b) + { + case WL_WALLELEC+100: + for (j=1; j<15; j++) + { + for (i=1; i<27; i++) + { + if (!(i%2) && !(j%2)) + { + vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; + } + else + { + vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = PIXPACK(0x808080); + } + } + } + break; + case WL_EWALL+100: + for (j=1; j<15; j++) + { + for (i=1; i<6+j; i++) + { + if (!(i&j&1)) + { + vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; + } + } + for (; i<27; i++) + { + if (i&j&1) + { + vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; + } + } + } + break; + case WL_STREAM+100: + for (j=1; j<15; j++) + { + for (i=1; i<27; i++) + { + vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = i==1||i==26||j==1||j==14 ? PIXPACK(0xA0A0A0) : PIXPACK(0x000000); + drawtext(vid_buf, x+4, y+3, "\x8D", 255, 255, 255, 255); + } + } + for (i=9; i<27; i++) + { + drawpixel(vid_buf, x+i, y+8+(int)(3.9f*cos(i*0.3f)), 255, 255, 255, 255); + } + break; + case WL_SIGN+100: + for (j=1; j<15; j++) + { + for (i=1; i<27; i++) + { + vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = i==1||i==26||j==1||j==14 ? PIXPACK(0xA0A0A0) : PIXPACK(0x000000); + } + } + drawtext(vid_buf, x+9, y+3, "\xA1", 32, 64, 128, 255); + drawtext(vid_buf, x+9, y+3, "\xA0", 255, 255, 255, 255); + break; + case WL_ERASE+100: + for (j=1; j<15; j+=2) + { + for (i=1+(1&(j>>1)); i<13; i+=2) + { + vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; + } + } + for (j=1; j<15; j++) + { + for (i=14; i<27; i++) + { + vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; + } + } + break; + case SPC_AIR: + case SPC_HEAT: + case SPC_COOL: + case SPC_VACUUM: + case SPC_WIND: + case SPC_PGRV: + case SPC_NGRV: + case SPC_PROP: + for (j=1; j<15; j++) + for (i=1; i<27; i++) + vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; + c = PIXR(pc) + 3*PIXG(pc) + 2*PIXB(pc); + if (c<544) + { + c = 255; + } + else + { + c = 0; + } + if (b==SPC_AIR) + drawtext(vid_buf, x+14-textwidth("AIR")/2, y+4, "AIR", c, c, c, 255); + else if (b==SPC_HEAT) + drawtext(vid_buf, x+14-textwidth("HEAT")/2, y+4, "HEAT", c, c, c, 255); + else if (b==SPC_COOL) + drawtext(vid_buf, x+14-textwidth("COOL")/2, y+4, "COOL", c, c, c, 255); + else if (b==SPC_VACUUM) + drawtext(vid_buf, x+14-textwidth("VAC")/2, y+4, "VAC", c, c, c, 255); + else if (b==SPC_WIND) + drawtext(vid_buf, x+14-textwidth("WIND")/2, y+4, "WIND", c, c, c, 255); + else if (b==SPC_PGRV) + drawtext(vid_buf, x+14-textwidth("PGRV")/2, y+4, "PGRV", c, c, c, 255); + else if (b==SPC_NGRV) + drawtext(vid_buf, x+14-textwidth("NGRV")/2, y+4, "NGRV", c, c, c, 255); + else if (b==SPC_PROP) + drawtext(vid_buf, x+14-textwidth("PROP")/2, y+4, "PROP", c, c, c, 255); + break; + default: + for (j=1; j<15; j++) + for (i=1; i<27; i++) + vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; + } + if (b==WL_ERASE+100) + { + for (j=4; j<12; j++) + { + vid_buf[(XRES+BARSIZE)*(y+j)+(x+j+6)] = PIXPACK(0xFF0000); + vid_buf[(XRES+BARSIZE)*(y+j)+(x+j+7)] = PIXPACK(0xFF0000); + vid_buf[(XRES+BARSIZE)*(y+j)+(x-j+21)] = PIXPACK(0xFF0000); + vid_buf[(XRES+BARSIZE)*(y+j)+(x-j+22)] = PIXPACK(0xFF0000); + } + } + } + else + { + //x = 2+32*(b/2); + //y = YRES+2+20*(b%2); + for (j=1; j<15; j++) + { + for (i=1; i<27; i++) + { + vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; + } + } + if (b==0) + { + for (j=4; j<12; j++) + { + vid_buf[(XRES+BARSIZE)*(y+j)+(x+j+6)] = PIXPACK(0xFF0000); + vid_buf[(XRES+BARSIZE)*(y+j)+(x+j+7)] = PIXPACK(0xFF0000); + vid_buf[(XRES+BARSIZE)*(y+j)+(x-j+21)] = PIXPACK(0xFF0000); + vid_buf[(XRES+BARSIZE)*(y+j)+(x-j+22)] = PIXPACK(0xFF0000); + } + } + c = PIXB(ptypes[b].pcolors) + 3*PIXG(ptypes[b].pcolors) + 2*PIXR(ptypes[b].pcolors); + if (c<544) + { + c = 255; + } + else + { + c = 0; + } + drawtext(vid_buf, x+14-textwidth((char *)ptypes[b].name)/2, y+4, (char *)ptypes[b].name, c, c, c, 255); + } + return 26; +}*/ + +/*void draw_menu(pixel *vid_buf, int i, int hover) +{ + if (i==SEC&&SEC!=0) + drawrect(vid_buf, (XRES+BARSIZE)-16, (i*16)+YRES+MENUSIZE-16-(SC_TOTAL*16), 14, 14, 0, 255, 255, 255); + else + drawrect(vid_buf, (XRES+BARSIZE)-16, (i*16)+YRES+MENUSIZE-16-(SC_TOTAL*16), 14, 14, 255, 255, 255, 255); + if (hover==i) + { + fillrect(vid_buf, (XRES+BARSIZE)-16, (i*16)+YRES+MENUSIZE-16-(SC_TOTAL*16), 14, 14, 255, 255, 255, 255); + drawtext(vid_buf, (XRES+BARSIZE)-13, (i*16)+YRES+MENUSIZE-14-(SC_TOTAL*16), msections[i].icon, 0, 0, 0, 255); + } + else + { + drawtext(vid_buf, (XRES+BARSIZE)-13, (i*16)+YRES+MENUSIZE-14-(SC_TOTAL*16), msections[i].icon, 255, 255, 255, 255); + } +}*/ + +/*void draw_color_menu(pixel *vid_buf, int i, int hover) +{ + drawrect(vid_buf, (XRES+BARSIZE)-16, (i*16)+YRES+MENUSIZE-16-(DECO_SECTIONS*16), 14, 14, 255, 255, 255, 255); + if (hover==i) + { + fillrect(vid_buf, (XRES+BARSIZE)-16, (i*16)+YRES+MENUSIZE-16-(DECO_SECTIONS*16), 14, 14, 255, 255, 255, 255); + drawtext(vid_buf, (XRES+BARSIZE)-13, (i*16)+YRES+MENUSIZE-14-(DECO_SECTIONS*16), colorsections[i].icon, 0, 0, 0, 255); + } + else + { + drawtext(vid_buf, (XRES+BARSIZE)-13, (i*16)+YRES+MENUSIZE-14-(DECO_SECTIONS*16), colorsections[i].icon, 255, 255, 255, 255); + } +}*/ + +//draws a pixel, identical to blendpixel(), except blendpixel has OpenGL support +TPT_INLINE void Graphics::drawpixel(int x, int y, int r, int g, int b, int a) +{ +#ifdef PIXALPHA + pixel t; + if (x<0 || y<0 || x>=XRES+BARSIZE || y>=YRES+MENUSIZE) + return; + if (a!=255) + { + t = vid[y*(XRES+BARSIZE)+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); + } + vid[y*(XRES+BARSIZE)+x] = PIXRGBA(r,g,b,a); +#else + pixel t; + if (x<0 || y<0 || x>=XRES+BARSIZE || y>=YRES+MENUSIZE) + return; + if (a!=255) + { + t = vid[y*(XRES+BARSIZE)+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*(XRES+BARSIZE)+x] = PIXRGB(r,g,b); +#endif +} + +inline int Graphics::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; + } + drawpixel(x+i, y+j, r, g, b, ((ba&3)*a)/3); + ba >>= 2; + bn -= 2; + } + return x + w; +} + +inline int Graphics::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; +} + +int Graphics::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); +} + +int Graphics::drawtext(int x, int y, const char *s, int r, int g, int b, int a) +{ + int sx = x; + for (; *s; s++) + { + if (*s == '\n') + { + x = sx; + y += FONT_H+2; + } + else if (*s == '\b') + { + 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; + } + s++; + } + else + x = drawchar(x, y, *(unsigned char *)s, r, g, b, a); + } + return x; +} + +//Draw text with an outline +int Graphics::drawtext_outline(int x, int y, const char *s, int r, int g, int b, int a, int olr, int olg, int olb, int ola) +{ + drawtext(x-1, y-1, s, olr, olg, olb, ola); + drawtext(x+1, y+1, s, olr, olg, olb, ola); + + drawtext(x-1, y+1, s, olr, olg, olb, ola); + drawtext(x+1, y-1, s, olr, olg, olb, ola); + + return drawtext(x, y, s, r, g, b, a); +} +int Graphics::drawtextwrap(int x, int y, int w, const char *s, int r, int g, int b, int a) +{ + int sx = x; + int rh = 12; + int rw = 0; + int cw = x; + int wordlen; + int charspace; + while (*s) + { + wordlen = strcspn(s," .,!?\n"); + charspace = textwidthx((char *)s, w-(x-cw)); + if (charspace<wordlen && wordlen && w-(x-cw)<w/3) + { + x = sx; + rw = 0; + y+=FONT_H+2; + rh+=FONT_H+2; + } + for (; *s && --wordlen>=-1; s++) + { + if (*s == '\n') + { + x = sx; + rw = 0; + y += FONT_H+2; + } + else if (*s == '\b') + { + 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; + } + s++; + } + else + { + + if (x-cw>=w) + { + x = sx; + rw = 0; + y+=FONT_H+2; + rh+=FONT_H+2; + } + x = drawchar(x, y, *(unsigned char *)s, r, g, b, a); + } + } + } + + return rh; +} + +//draws a rectange, (x,y) are the top left coords. +void Graphics::drawrect(int x, int y, int w, int h, int r, int g, int b, int a) +{ + int i; + for (i=0; i<=w; i++) + { + drawpixel(x+i, y, r, g, b, a); + drawpixel(x+i, y+h, r, g, b, a); + } + for (i=1; i<h; i++) + { + drawpixel(x, y+i, r, g, b, a); + drawpixel(x+w, y+i, r, g, b, a); + } +} + +//draws a rectangle and fills it in as well. +void Graphics::fillrect(int x, int y, int w, int h, int r, int g, int b, int a) +{ + int i,j; + for (j=1; j<h; j++) + for (i=1; i<w; i++) + drawpixel(x+i, y+j, r, g, b, a); +} + +void Graphics::clearrect(int x, int y, int w, int h) +{ +#ifdef OGLR + fillrect(x, y, w, h, 0, 0, 0, 255); +#else + int i; + for (i=1; i<h; i++) + memset(vid+(x+1+(XRES+BARSIZE)*(y+i)), 0, PIXELSIZE*(w-1)); +#endif +} +//draws a line of dots, where h is the height. (why is this even here) +void Graphics::drawdots(int x, int y, int h, int r, int g, int b, int a) +{ + int i; + for (i=0; i<=h; i+=2) + drawpixel(x, y+i, r, g, b, a); +} + +int Graphics::textwidth(char *s) +{ + int x = 0; + for (; *s; s++) + x += font_data[font_ptrs[(int)(*(unsigned char *)s)]]; + return x-1; +} + +int Graphics::drawtextmax(int x, int y, int w, char *s, int r, int g, int b, int a) +{ + int i; + w += x-5; + for (; *s; s++) + { + if (x+font_data[font_ptrs[(int)(*(unsigned char *)s)]]>=w && x+textwidth(s)>=w+5) + break; + x = drawchar(x, y, *(unsigned char *)s, r, g, b, a); + } + if (*s) + for (i=0; i<3; i++) + x = drawchar(x, y, '.', r, g, b, a); + return x; +} + +int Graphics::textnwidth(char *s, int n) +{ + int x = 0; + for (; *s; s++) + { + if (!n) + break; + 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++) + { + cw = font_data[font_ptrs[(int)(*(unsigned char *)s)]]; + if (x+(cw/2) >= w) + break; + x += cw; + n++; + } + return n; +} +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') + { + s++; + } + else + { + cw = font_data[font_ptrs[(int)(*(unsigned char *)s)]]; + if (x+cw>=width) + { + x = 0; + height += FONT_H+2; + } + x += cw; + } + } + } + return height; +} + +//the most used function for drawing a pixel, because it has OpenGL support, which is not fully implemented. +TPT_INLINE void Graphics::blendpixel(int x, int y, int r, int g, int b, int a) +{ +#ifdef PIXALPHA + pixel t; + if (x<0 || y<0 || x>=XRES+BARSIZE || y>=YRES+MENUSIZE) + return; + if (a!=255) + { + t = vid[y*(XRES+BARSIZE)+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); + } + vid[y*(XRES+BARSIZE)+x] = PIXRGBA(r,g,b,a); +#else + pixel t; + if (x<0 || y<0 || x>=XRES+BARSIZE || y>=YRES+MENUSIZE) + return; + if (a!=255) + { + t = vid[y*(XRES+BARSIZE)+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*(XRES+BARSIZE)+x] = PIXRGB(r,g,b); +#endif +} + +void Graphics::draw_icon(int x, int y, char ch, int flag) +{ + char t[2]; + t[0] = ch; + t[1] = 0; + if (flag) + { + fillrect(x-1, y-1, 17, 17, 255, 255, 255, 255); + drawtext(x+3, y+2, t, 0, 0, 0, 255); + } + else + { + drawrect(x, y, 15, 15, 255, 255, 255, 255); + drawtext(x+3, y+2, t, 255, 255, 255, 255); + } +} + +void Graphics::draw_line(int x1, int y1, int x2, int y2, int r, int g, int b, int a) //Draws a line +{ + int dx, dy, i, sx, sy, check, e, x, y; + + dx = abs(x1-x2); + dy = abs(y1-y2); + sx = isign(x2-x1); + sy = isign(y2-y1); + x = x1; + y = y1; + check = 0; + + if (dy>dx) + { + dx = dx+dy; + dy = dx-dy; + dx = dx-dy; + check = 1; + } + + e = (dy<<2)-dx; + for (i=0; i<=dx; i++) + { + if (x>=0 && y>=0 && x<a && y<YRES+MENUSIZE) + vid[x+y*a] =PIXRGB(r, g, b); + if (e>=0) + { + if (check==1) + x = x+sx; + else + y = y+sy; + e = e-(dx<<2); + } + if (check==1) + y = y+sy; + else + x = x+sx; + e = e+(dy<<2); + } +} + +//adds color to a pixel, does not overwrite. +void Graphics::addpixel(int x, int y, int r, int g, int b, int a) +{ + pixel t; + if (x<0 || y<0 || x>=XRES+BARSIZE || y>=YRES+MENUSIZE) + return; + t = vid[y*(XRES+BARSIZE)+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*(XRES+BARSIZE)+x] = PIXRGB(r,g,b); +} + +//draws one of two colors, so that it is always clearly visible +void Graphics::xor_pixel(int x, int y) +{ + int c; + if (x<0 || y<0 || x>=XRES || y>=YRES) + return; + c = vid[y*(XRES+BARSIZE)+x]; + c = PIXB(c) + 3*PIXG(c) + 2*PIXR(c); + if (c<512) + vid[y*(XRES+BARSIZE)+x] = PIXPACK(0xC0C0C0); + else + vid[y*(XRES+BARSIZE)+x] = PIXPACK(0x404040); +} + +//same as xor_pixel, but draws a line of it +void Graphics::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; + } + } +} + +//same as blend_pixel, but draws a line of it +void Graphics::blend_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; + } + } +} + +//same as xor_pixel, but draws a rectangle +void Graphics::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); + } +} + + +//New function for drawing particles +#ifdef OGLR +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 + +#ifdef OGLR +void draw_parts_fbo() +{ + 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, 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, 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); + } + + 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); + glTexCoord2d(0, 0); + glVertex3f(0, (YRES+MENUSIZE)*sdl_scale, 1.0); + glTexCoord2d(0, 1); + glVertex3f(0, MENUSIZE*sdl_scale, 1.0); + glTexCoord2d(1, 1); + glVertex3f(XRES*sdl_scale, MENUSIZE*sdl_scale, 1.0); + glEnd(); + + if(display_mode & DISPLAY_WARP) + { + glUseProgram(0); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + glDisable( GL_TEXTURE_2D ); +} +#endif + + +//draws the photon colors in the HUD +void Graphics::draw_wavelengths(int x, int y, int h, int wl) +{ + int i,cr,cg,cb,j; + int tmp; + fillrect(x-1,y-1,30+1,h+1,64,64,64,255); // coords -1 size +1 to work around bug in fillrect - TODO: fix fillrect + for (i=0; i<30; i++) + { + if ((wl>>i)&1) + { + // Need a spread of wavelengths to get a smooth spectrum, 5 bits seems to work reasonably well + if (i>2) tmp = 0x1F << (i-2); + else tmp = 0x1F >> (2-i); + cg = 0; + cb = 0; + cr = 0; + for (j=0; j<12; j++) { + cr += (tmp >> (j+18)) & 1; + cb += (tmp >> j) & 1; + } + for (j=0; j<13; j++) + cg += (tmp >> (j+9)) & 1; + tmp = 624/(cr+cg+cb+1); + cr *= tmp; + cg *= tmp; + cb *= tmp; + for (j=0; j<h; j++) blendpixel(x+29-i,y+j,cr>255?255:cr,cg>255?255:cg,cb>255?255:cb,255); + } + } +} + +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_rgba_image(unsigned char *data, int x, int y, float alpha) +{ + unsigned char w, h; + int i, j; + unsigned char r, g, b, a; + if (!data) return; + w = *(data++)&0xFF; + h = *(data++)&0xFF; + for (j=0; j<h; j++) + { + for (i=0; i<w; i++) + { + r = *(data++)&0xFF; + g = *(data++)&0xFF; + b = *(data++)&0xFF; + a = *(data++)&0xFF; + drawpixel(x+i, y+j, r, g, b, a*alpha); + } + } +} + +void Graphics::draw_image(pixel *img, int x, int y, int w, int h, int a) +{ + int i, j, r, g, b; + if (!img) return; + for (j=0; j<h; j++) + for (i=0; i<w; i++) + { + r = PIXR(*img); + g = PIXG(*img); + b = PIXB(*img); + drawpixel(x+i, y+j, r, g, b, a); + img++; + } +} + +void Graphics::dim_copy(pixel *dst, pixel *src) //old persistent, unused +{ + int i,r,g,b; + for (i=0; i<XRES*YRES; i++) + { + r = PIXR(src[i]); + g = PIXG(src[i]); + b = PIXB(src[i]); + if (r>0) + r--; + if (g>0) + g--; + if (b>0) + b--; + dst[i] = PIXRGB(r,g,b); + } +} + +void Graphics::dim_copy_pers(pixel *dst, pixel *src) //for persistent view, reduces rgb slowly +{ + int i,r,g,b; + for (i=0; i<(XRES+BARSIZE)*YRES; i++) + { + r = PIXR(src[i]); + g = PIXG(src[i]); + b = PIXB(src[i]); + if (r>0) + r--; + if (g>0) + g--; + if (b>0) + b--; + dst[i] = PIXRGB(r,g,b); + } +} + +/*void render_zoom(pixel *img) //draws the zoom box +{ +#ifdef OGLR + 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; + + zcx0 = (zoom_x)*xfactor; + zcx1 = (zoom_x+ZSIZE)*xfactor; + zcy0 = (zoom_y)*yfactor; + zcy1 = ((zoom_y+ZSIZE))*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); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + glBegin(GL_QUADS); + glTexCoord2d(zcx1, zcy1); + glVertex3f((zoom_wx+ZSIZE*ZFACTOR)*sdl_scale, (YRES+MENUSIZE-(zoom_wy+ZSIZE*ZFACTOR))*sdl_scale, 1.0); + glTexCoord2d(zcx0, zcy1); + glVertex3f(zoom_wx*sdl_scale, (YRES+MENUSIZE-(zoom_wy+ZSIZE*ZFACTOR))*sdl_scale, 1.0); + glTexCoord2d(zcx0, zcy0); + glVertex3f(zoom_wx*sdl_scale, (YRES+MENUSIZE-zoom_wy)*sdl_scale, 1.0); + glTexCoord2d(zcx1, zcy0); + glVertex3f((zoom_wx+ZSIZE*ZFACTOR)*sdl_scale, (YRES+MENUSIZE-zoom_wy)*sdl_scale, 1.0); + glEnd(); + glBindTexture(GL_TEXTURE_2D, 0); + glDisable( GL_TEXTURE_2D ); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glLineWidth(sdl_scale); + glEnable(GL_LINE_SMOOTH); + glBegin(GL_LINES); + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + for(i = 0; i < ZSIZE; i++) + { + glVertex2f((zoom_wx+ZSIZE*ZFACTOR)*sdl_scale, (YRES+MENUSIZE-(zoom_wy+ZSIZE*ZFACTOR)+i*ZFACTOR)*sdl_scale); + glVertex2f(zoom_wx*sdl_scale, (YRES+MENUSIZE-(zoom_wy+ZSIZE*ZFACTOR)+i*ZFACTOR)*sdl_scale); + glVertex2f((zoom_wx+i*ZFACTOR)*sdl_scale, (YRES+MENUSIZE-(zoom_wy+ZSIZE*ZFACTOR))*sdl_scale); + glVertex2f((zoom_wx+i*ZFACTOR)*sdl_scale, (YRES+MENUSIZE-zoom_wy)*sdl_scale); + } + glEnd(); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + glBegin(GL_LINE_STRIP); + glVertex3i((zoom_wx-1)*sdl_scale, (YRES+MENUSIZE-zoom_wy)*sdl_scale, 0); + glVertex3i((zoom_wx-1)*sdl_scale, (YRES+MENUSIZE-(zoom_wy+ZSIZE*ZFACTOR))*sdl_scale, 0); + glVertex3i((zoom_wx+ZSIZE*ZFACTOR)*sdl_scale, (YRES+MENUSIZE-(zoom_wy+ZSIZE*ZFACTOR))*sdl_scale, 0); + glVertex3i((zoom_wx+ZSIZE*ZFACTOR)*sdl_scale, (YRES+MENUSIZE-zoom_wy)*sdl_scale, 0); + glVertex3i((zoom_wx-1)*sdl_scale, (YRES+MENUSIZE-zoom_wy)*sdl_scale, 0); + glEnd(); + glDisable(GL_LINE_SMOOTH); + + glDisable(GL_LINE_SMOOTH); + + if(zoom_en) + { + 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); + glVertex3i((zoom_x-1)*sdl_scale, (YRES+MENUSIZE-(zoom_y-1))*sdl_scale, 0); + glVertex3i((zoom_x-1)*sdl_scale, (YRES+MENUSIZE-(zoom_y+ZSIZE))*sdl_scale, 0); + glVertex3i((zoom_x+ZSIZE)*sdl_scale, (YRES+MENUSIZE-(zoom_y+ZSIZE))*sdl_scale, 0); + glVertex3i((zoom_x+ZSIZE)*sdl_scale, (YRES+MENUSIZE-(zoom_y-1))*sdl_scale, 0); + glVertex3i((zoom_x-1)*sdl_scale, (YRES+MENUSIZE-(zoom_y-1))*sdl_scale, 0); + glEnd(); + glDisable(GL_COLOR_LOGIC_OP); + } + glLineWidth(1); + glBlendFunc(origBlendSrc, origBlendDst); +#else + int x, y, i, j; + pixel pix; + drawrect(img, zoom_wx-2, zoom_wy-2, ZSIZE*ZFACTOR+2, ZSIZE*ZFACTOR+2, 192, 192, 192, 255); + drawrect(img, zoom_wx-1, zoom_wy-1, ZSIZE*ZFACTOR, ZSIZE*ZFACTOR, 0, 0, 0, 255); + clearrect(img, zoom_wx, zoom_wy, ZSIZE*ZFACTOR, ZSIZE*ZFACTOR); + for (j=0; j<ZSIZE; j++) + for (i=0; i<ZSIZE; i++) + { + pix = img[(j+zoom_y)*(XRES+BARSIZE)+(i+zoom_x)]; + for (y=0; y<ZFACTOR-1; y++) + for (x=0; x<ZFACTOR-1; x++) + img[(j*ZFACTOR+y+zoom_wy)*(XRES+BARSIZE)+(i*ZFACTOR+x+zoom_wx)] = pix; + } + if (zoom_en) + { + for (j=-1; j<=ZSIZE; j++) + { + xor_pixel(zoom_x+j, zoom_y-1, img); + xor_pixel(zoom_x+j, zoom_y+ZSIZE, img); + } + for (j=0; j<ZSIZE; j++) + { + xor_pixel(zoom_x-1, zoom_y+j, img); + xor_pixel(zoom_x+ZSIZE, zoom_y+j, img); + } + } +#endif +}*/ + +/*int render_thumb(void *thumb, int size, int bzip2, pixel *vid_buf, int px, int py, int scl) +{ + unsigned char *d, *c = (unsigned char *)thumb; + int i,j,x,y,a,t,r,g,b,sx,sy; + + if (bzip2) + { + if (size<16) + return 1; + if (c[3]!=0x74 || c[2]!=0x49 || c[1]!=0x68 || c[0]!=0x53) + return 1; + if (c[4]>PT_NUM) + return 2; + if (c[5]!=CELL || c[6]!=XRES/CELL || c[7]!=YRES/CELL) + return 3; + i = XRES*YRES; + d = (unsigned char *)malloc(i); + if (!d) + return 1; + + if (BZ2_bzBuffToBuffDecompress((char *)d, (unsigned *)&i, (char *)(c+8), size-8, 0, 0)) + return 1; + size = i; + } + else + d = c; + + if (size < XRES*YRES) + { + if (bzip2) + free(d); + return 1; + } + + sy = 0; + for (y=0; y+scl<=YRES; y+=scl) + { + sx = 0; + for (x=0; x+scl<=XRES; x+=scl) + { + a = 0; + r = g = b = 0; + for (j=0; j<scl; j++) + for (i=0; i<scl; i++) + { + t = d[(y+j)*XRES+(x+i)]; + if (t==0xFF) + { + r += 256; + g += 256; + b += 256; + a += 2; + } + else if (t) + { + if (t>=PT_NUM) + goto corrupt; + r += PIXR(ptypes[t].pcolors); + g += PIXG(ptypes[t].pcolors); + b += PIXB(ptypes[t].pcolors); + a ++; + } + } + if (a) + { + a = 256/a; + r = (r*a)>>8; + g = (g*a)>>8; + b = (b*a)>>8; + } + + drawpixel(vid_buf, px+sx, py+sy, r, g, b, 255); + sx++; + } + sy++; + } + + if (bzip2) + free(d); + return 0; + +corrupt: + if (bzip2) + free(d); + return 1; +}*/ + +//draws the cursor +/*void Graphics::render_cursor(pixel *vid, int x, int y, int t, int rx, int ry) +{ +#ifdef OGLR + int i; + if (t<PT_NUM||(t&0xFF)==PT_LIFE||t==SPC_AIR||t==SPC_HEAT||t==SPC_COOL||t==SPC_VACUUM||t==SPC_WIND||t==SPC_PGRV||t==SPC_NGRV) + { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo); + glEnable(GL_COLOR_LOGIC_OP); + glLogicOp(GL_XOR); + glBegin(GL_LINE_LOOP); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + y *= sdl_scale; + x *= sdl_scale; + ry *= sdl_scale; + rx *= sdl_scale; + if (CURRENT_BRUSH==SQUARE_BRUSH) + { + glVertex2f(x-rx+1, (y)-ry+1); + glVertex2f(x+rx+1, (y)-ry+1); + glVertex2f(x+rx+1, (y)+ry+1); + glVertex2f(x-rx+1, (y)+ry+1); + glVertex2f(x-rx+1, (y)-ry+1); + } + else if (CURRENT_BRUSH==CIRCLE_BRUSH) + { + for (i = 0; i < 360; i++) + { + float degInRad = i*(M_PI/180.0f); + glVertex2f((cos(degInRad)*rx)+x, (sin(degInRad)*ry)+y); + } + } + else if (CURRENT_BRUSH==TRI_BRUSH) + { + glVertex2f(x+1, (y)+ry+1); + glVertex2f(x+rx+1, (y)-ry+1); + glVertex2f(x-rx+1, (y)-ry+1); + glVertex2f(x+1, (y)+ry+1); + } + glEnd(); + glDisable(GL_COLOR_LOGIC_OP); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + } +#else + int i,j,c; + if (t<PT_NUM||(t&0xFF)==PT_LIFE||t==SPC_AIR||t==SPC_HEAT||t==SPC_COOL||t==SPC_VACUUM||t==SPC_WIND||t==SPC_PGRV||t==SPC_NGRV) + { + if (rx<=0) + xor_pixel(x, y, vid); + else if (ry<=0) + xor_pixel(x, y, vid); + if (rx+ry<=0) + xor_pixel(x, y, vid); + else if (CURRENT_BRUSH==SQUARE_BRUSH) + { + for (j=0; j<=ry; j++) + for (i=0; i<=rx; i++) + if (i*j<=ry*rx && ((i+1)>rx || (j+1)>ry)) + { + xor_pixel(x+i, y+j, vid); + xor_pixel(x-i, y-j, vid); + if (i&&j)xor_pixel(x+i, y-j, vid); + if (i&&j)xor_pixel(x-i, y+j, vid); + } + } + else if (CURRENT_BRUSH==CIRCLE_BRUSH) + { + for (j=0; j<=ry; j++) + for (i=0; i<=rx; i++) + if (pow(i,2)*pow(ry,2)+pow(j,2)*pow(rx,2)<=pow(rx,2)*pow(ry,2) && + (pow(i+1,2)*pow(ry,2)+pow(j,2)*pow(rx,2)>pow(rx,2)*pow(ry,2) || + pow(i,2)*pow(ry,2)+pow(j+1,2)*pow(rx,2)>pow(rx,2)*pow(ry,2))) + { + xor_pixel(x+i, y+j, vid); + if (j) xor_pixel(x+i, y-j, vid); + if (i) xor_pixel(x-i, y+j, vid); + if (i&&j) xor_pixel(x-i, y-j, vid); + } + } + else if (CURRENT_BRUSH==TRI_BRUSH) + { + for (j=-ry; j<=ry; j++) + for (i=-rx; i<=0; i++) + if ((j <= ry ) && ( j >= (((-2.0*ry)/(rx))*i)-ry ) && (j+1>ry || ( j-1 < (((-2.0*ry)/(rx))*i)-ry )) ) + { + xor_pixel(x+i, y+j, vid); + if (i) xor_pixel(x-i, y+j, vid); + } + } + } + else //wall cursor + { + int tc; + c = (rx/CELL) * CELL; + x = (x/CELL) * CELL; + y = (y/CELL) * CELL; + + tc = !((c%(CELL*2))==0); + + x -= c/2; + y -= c/2; + + x += tc*(CELL/2); + y += tc*(CELL/2); + + for (i=0; i<CELL+c; i++) + { + xor_pixel(x+i, y, vid); + xor_pixel(x+i, y+CELL+c-1, vid); + } + for (i=1; i<CELL+c-1; i++) + { + xor_pixel(x, y+i, vid); + xor_pixel(x+CELL+c-1, y+i, vid); + } + } +#endif +}*/ + +/*int sdl_opened = 0; +int sdl_open(void) +{ + int status; + if (SDL_Init(SDL_INIT_VIDEO)<0) + { + fprintf(stderr, "Initializing SDL: %s\n", SDL_GetError()); + return 0; + } + atexit(SDL_Quit); +#if defined(OGLR) + sdl_scrn=SDL_SetVideoMode(XRES*sdl_scale + BARSIZE*sdl_scale,YRES*sdl_scale + MENUSIZE*sdl_scale,32,SDL_OPENGL); + SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1); + + if(sdl_opened) + { + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + glOrtho(0, (XRES+BARSIZE)*sdl_scale, 0, (YRES+MENUSIZE)*sdl_scale, -1, 1); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + } + else + { +#ifdef WIN32 + status = glewInit(); + if(status != GLEW_OK) + { + fprintf(stderr, "Initializing Glew: %d\n", status); + return 0; + } +#endif + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + glOrtho(0, (XRES+BARSIZE)*sdl_scale, 0, (YRES+MENUSIZE)*sdl_scale, -1, 1); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glRasterPos2i(0, (YRES+MENUSIZE)); + glPixelZoom(1, -1); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + //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 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); + 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, YRES, 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, &partsTFY); + glBindTexture(GL_TEXTURE_2D, partsTFY); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, XRES, YRES, 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 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); + + loadShaders(); + } +#else +#ifdef PIX16 + if (kiosk_enable) + sdl_scrn=SDL_SetVideoMode(XRES*sdl_scale + BARSIZE*sdl_scale,YRES*sdl_scale + MENUSIZE*sdl_scale,16,SDL_FULLSCREEN|SDL_SWSURFACE); + else + sdl_scrn=SDL_SetVideoMode(XRES*sdl_scale + BARSIZE*sdl_scale,YRES*sdl_scale + MENUSIZE*sdl_scale,16,SDL_SWSURFACE); +#else + if (kiosk_enable) + sdl_scrn=SDL_SetVideoMode(XRES*sdl_scale + BARSIZE*sdl_scale,YRES*sdl_scale + MENUSIZE*sdl_scale,32,SDL_FULLSCREEN|SDL_SWSURFACE); + else + sdl_scrn=SDL_SetVideoMode(XRES*sdl_scale + BARSIZE*sdl_scale,YRES*sdl_scale + MENUSIZE*sdl_scale,32,SDL_SWSURFACE); +#endif +#endif + if (!sdl_scrn) + { + fprintf(stderr, "Creating window: %s\n", SDL_GetError()); + return 0; + } + SDL_WM_SetCaption("The Powder Toy", "Powder Toy"); + sdl_seticon(); + SDL_EnableUNICODE(1); + //SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); +#if (defined(LIN32) || defined(LIN64)) && defined(SDL_VIDEO_DRIVER_X11) + SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); + SDL_VERSION(&sdl_wminfo.version); + SDL_GetWMInfo(&sdl_wminfo); + sdl_wminfo.info.x11.lock_func(); + XA_CLIPBOARD = XInternAtom(sdl_wminfo.info.x11.display, "CLIPBOARD", 1); + XA_TARGETS = XInternAtom(sdl_wminfo.info.x11.display, "TARGETS", 1); + sdl_wminfo.info.x11.unlock_func(); +#endif + sdl_opened = 1; + return 1; +} +#ifdef OGLR +void checkShader(GLuint shader, char * shname) +{ + GLuint 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 checkProgram(GLuint program, char * progname) +{ + GLuint 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 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 +int draw_debug_info(pixel* vid, Simulation * sim, int lm, int lx, int ly, int cx, int cy, int line_x, int line_y) +{ + Particle * parts = sim->parts; + char infobuf[256]; + if(debug_flags & DEBUG_PERFORMANCE_FRAME || debug_flags & DEBUG_PERFORMANCE_CALC) + { + int t1, t2, x = 0, i = debug_perf_istart; + float partiavg = 0, frameavg = 0; + while(i != debug_perf_iend) + { + partiavg += abs(debug_perf_partitime[i]/100000); + frameavg += abs(debug_perf_frametime[i]/100000); + if(debug_flags & DEBUG_PERFORMANCE_CALC) + t1 = abs(debug_perf_partitime[i]/100000); + else + t1 = 0; + + if(debug_flags & DEBUG_PERFORMANCE_FRAME) + t2 = abs(debug_perf_frametime[i]/100000); + else + t2 = 0; + + if(t1 > YRES) + t1 = YRES; + if(t1+t2 > YRES) + t2 = YRES-t1; + + if(t1>0) + draw_line(vid, x, YRES, x, YRES-t1, 0, 255, 120, XRES+BARSIZE); + if(t2>0) + draw_line(vid, x, YRES-t1, x, YRES-(t1+t2), 255, 120, 0, XRES+BARSIZE); + + i++; + x++; + i %= DEBUG_PERF_FRAMECOUNT; + } + + if(debug_flags & DEBUG_PERFORMANCE_CALC) + t1 = abs(partiavg / x); + else + t1 = 0; + + if(debug_flags & DEBUG_PERFORMANCE_FRAME) + t2 = abs(frameavg / x); + else + t2 = 0; + + if(t1 > YRES) + t1 = YRES; + if(t1+t2 > YRES) + t2 = YRES-t1; + + if(t1>0) + fillrect(vid, x, YRES-t1-1, 5, t1+2, 0, 255, 0, 255); + if(t2>0) + fillrect(vid, x, (YRES-t1)-t2-1, 5, t2+1, 255, 0, 0, 255); + } + if(debug_flags & DEBUG_DRAWTOOL) + { + if(lm == 1) //Line tool + { + blend_line(vid, 0, line_y, XRES, line_y, 255, 255, 255, 120); + blend_line(vid, line_x, 0, line_x, YRES, 255, 255, 255, 120); + + blend_line(vid, 0, ly, XRES, ly, 255, 255, 255, 120); + blend_line(vid, lx, 0, lx, YRES, 255, 255, 255, 120); + + sprintf(infobuf, "%d x %d", lx, ly); + drawtext_outline(vid, lx+(lx>line_x?3:-textwidth(infobuf)-3), ly+(ly<line_y?-10:3), infobuf, 255, 255, 255, 200, 0, 0, 0, 120); + + sprintf(infobuf, "%d x %d", line_x, line_y); + drawtext_outline(vid, line_x+(lx<line_x?3:-textwidth(infobuf)-2), line_y+(ly>line_y?-10:3), infobuf, 255, 255, 255, 200, 0, 0, 0, 120); + + sprintf(infobuf, "%d", abs(line_x-lx)); + drawtext_outline(vid, (line_x+lx)/2-textwidth(infobuf)/2, line_y+(ly>line_y?-10:3), infobuf, 255, 255, 255, 200, 0, 0, 0, 120); + + sprintf(infobuf, "%d", abs(line_y-ly)); + drawtext_outline(vid, line_x+(lx<line_x?3:-textwidth(infobuf)-2), (line_y+ly)/2-3, infobuf, 255, 255, 255, 200, 0, 0, 0, 120); + } + } + if(debug_flags & DEBUG_PARTS) + { + int i = 0, x = 0, y = 0, lpx = 0, lpy = 0; + sprintf(infobuf, "%d/%d (%.2f%%)", sim->parts_lastActiveIndex, NPART, (((float)sim->parts_lastActiveIndex)/((float)NPART))*100.0f); + for(i = 0; i < NPART; i++){ + if(parts[i].type){ + drawpixel(vid, x, y, 255, 255, 255, 180); + } else { + drawpixel(vid, x, y, 0, 0, 0, 180); + } + if(i == sim->parts_lastActiveIndex) + { + lpx = x; + lpy = y; + } + x++; + if(x>=XRES){ + y++; + x = 0; + } + } + draw_line(vid, 0, lpy, XRES, lpy, 0, 255, 120, XRES+BARSIZE); + draw_line(vid, lpx, 0, lpx, YRES, 0, 255, 120, XRES+BARSIZE); + drawpixel(vid, lpx, lpy, 255, 50, 50, 220); + + drawpixel(vid, lpx+1, lpy, 255, 50, 50, 120); + drawpixel(vid, lpx-1, lpy, 255, 50, 50, 120); + drawpixel(vid, lpx, lpy+1, 255, 50, 50, 120); + drawpixel(vid, lpx, lpy-1, 255, 50, 50, 120); + + fillrect(vid, 7, YRES-26, textwidth(infobuf)+5, 14, 0, 0, 0, 180); + drawtext(vid, 10, YRES-22, infobuf, 255, 255, 255, 255); + } +}*/ + +void Graphics::Clear() +{ + memset(vid, 0, PIXELSIZE * ((XRES+BARSIZE) * (YRES+MENUSIZE))); +} + +void Graphics::AttachSDLSurface(SDL_Surface * surface) +{ + sdl_scrn = surface; +} + +void Graphics::Blit() +{ + pixel * dst; + pixel * src = vid; + int j, x = 0, y = 0, w = XRES+BARSIZE, h = YRES+MENUSIZE, pitch = XRES+BARSIZE; + if (SDL_MUSTLOCK(sdl_scrn)) + if (SDL_LockSurface(sdl_scrn)<0) + return; + dst=(pixel *)sdl_scrn->pixels+y*sdl_scrn->pitch/PIXELSIZE+x; + for (j=0; j<h; j++) + { + memcpy(dst, src, w*PIXELSIZE); + dst+=sdl_scrn->pitch/PIXELSIZE; + src+=pitch; + } + if (SDL_MUSTLOCK(sdl_scrn)) + SDL_UnlockSurface(sdl_scrn); + SDL_UpdateRect(sdl_scrn,0,0,0,0); +} + +Graphics::Graphics() +{ + vid = (pixel *)malloc(PIXELSIZE * ((XRES+BARSIZE) * (YRES+MENUSIZE))); +} |
