Lensing effect for gravity, adds 3 new gravity maps (full resolution, linear interpolation for faux accuracy), old ones should be removed in time.

This commit is contained in:
Simon Robertshaw 2011-07-18 23:58:08 +01:00
parent 0fbe6e2d3f
commit 68404608f6
5 changed files with 133 additions and 15 deletions

View File

@ -5,12 +5,20 @@
extern float gravmap[YRES/CELL][XRES/CELL]; //Maps to be used by the main thread extern float gravmap[YRES/CELL][XRES/CELL]; //Maps to be used by the main thread
extern float gravx[YRES/CELL][XRES/CELL]; extern float gravx[YRES/CELL][XRES/CELL];
extern float gravy[YRES/CELL][XRES/CELL]; extern float gravy[YRES/CELL][XRES/CELL];
extern float gravp[YRES/CELL][XRES/CELL];
extern float *gravpf;
extern float *gravxf;
extern float *gravyf;
extern unsigned gravmask[YRES/CELL][XRES/CELL]; extern unsigned gravmask[YRES/CELL][XRES/CELL];
extern float th_ogravmap[YRES/CELL][XRES/CELL]; // Maps to be processed by the gravity thread extern float th_ogravmap[YRES/CELL][XRES/CELL]; // Maps to be processed by the gravity thread
extern float th_gravmap[YRES/CELL][XRES/CELL]; extern float th_gravmap[YRES/CELL][XRES/CELL];
extern float th_gravx[YRES/CELL][XRES/CELL]; extern float th_gravx[YRES/CELL][XRES/CELL];
extern float th_gravy[YRES/CELL][XRES/CELL]; extern float th_gravy[YRES/CELL][XRES/CELL];
extern float *th_gravpf;
extern float *th_gravxf;
extern float *th_gravyf;
extern float th_gravp[YRES/CELL][XRES/CELL];
extern float vx[YRES/CELL][XRES/CELL], ovx[YRES/CELL][XRES/CELL]; extern float vx[YRES/CELL][XRES/CELL], ovx[YRES/CELL][XRES/CELL];
extern float vy[YRES/CELL][XRES/CELL], ovy[YRES/CELL][XRES/CELL]; extern float vy[YRES/CELL][XRES/CELL], ovy[YRES/CELL][XRES/CELL];

View File

@ -60,6 +60,8 @@ pixel *resample_img(pixel *src, int sw, int sh, int rw, int rh);
pixel *rescale_img(pixel *src, int sw, int sh, int *qw, int *qh, int f); pixel *rescale_img(pixel *src, int sw, int sh, int *qw, int *qh, int f);
void render_gravlensing(pixel *src, pixel * dst);
void sdl_blit_1(int x, int y, int w, int h, pixel *src, int pitch); void sdl_blit_1(int x, int y, int w, int h, pixel *src, int pitch);
void sdl_blit_2(int x, int y, int w, int h, pixel *src, int pitch); void sdl_blit_2(int x, int y, int w, int h, pixel *src, int pitch);

View File

@ -7,12 +7,20 @@ float kernel[9];
float gravmap[YRES/CELL][XRES/CELL]; //Maps to be used by the main thread float gravmap[YRES/CELL][XRES/CELL]; //Maps to be used by the main thread
float gravx[YRES/CELL][XRES/CELL]; float gravx[YRES/CELL][XRES/CELL];
float gravy[YRES/CELL][XRES/CELL]; float gravy[YRES/CELL][XRES/CELL];
float gravp[YRES/CELL][XRES/CELL];
float *gravpf;
float *gravyf;
float *gravxf;
unsigned gravmask[YRES/CELL][XRES/CELL]; unsigned gravmask[YRES/CELL][XRES/CELL];
float th_ogravmap[YRES/CELL][XRES/CELL]; // Maps to be processed by the gravity thread float th_ogravmap[YRES/CELL][XRES/CELL]; // Maps to be processed by the gravity thread
float th_gravmap[YRES/CELL][XRES/CELL]; float th_gravmap[YRES/CELL][XRES/CELL];
float th_gravx[YRES/CELL][XRES/CELL]; float th_gravx[YRES/CELL][XRES/CELL];
float th_gravy[YRES/CELL][XRES/CELL]; float th_gravy[YRES/CELL][XRES/CELL];
float th_gravp[YRES/CELL][XRES/CELL];
float *th_gravpf;
float *th_gravyf;
float *th_gravxf;
float vx[YRES/CELL][XRES/CELL], ovx[YRES/CELL][XRES/CELL]; float vx[YRES/CELL][XRES/CELL], ovx[YRES/CELL][XRES/CELL];
float vy[YRES/CELL][XRES/CELL], ovy[YRES/CELL][XRES/CELL]; float vy[YRES/CELL][XRES/CELL], ovy[YRES/CELL][XRES/CELL];
@ -119,6 +127,31 @@ void update_airh(void)
} }
memcpy(hv, ohv, sizeof(hv)); memcpy(hv, ohv, sizeof(hv));
} }
void bilinear_interpolation(float *src, float *dst, int sw, int sh, int rw, int rh)
{
int y, x, fxceil, fyceil;
float fx, fy, fyc, fxc;
double intp;
float tr, tl, br, bl;
//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)];
dst[rw*y+x] = ((tl*(1.0f-fxc))+(tr*(fxc)))*(1.0f-fyc) + ((bl*(1.0f-fxc))+(br*(fxc)))*(fyc);
}
}
void update_grav(void) void update_grav(void)
{ {
@ -164,11 +197,15 @@ void update_grav(void)
#endif #endif
th_gravx[y][x] += M_GRAV * val * (j - x) / pow(distance, 3); th_gravx[y][x] += M_GRAV * val * (j - x) / pow(distance, 3);
th_gravy[y][x] += M_GRAV * val * (i - y) / pow(distance, 3); th_gravy[y][x] += M_GRAV * val * (i - y) / pow(distance, 3);
th_gravp[y][x] += M_GRAV * val / pow(distance, 2);
} }
} }
} }
} }
} }
bilinear_interpolation(th_gravy, th_gravyf, XRES/CELL, YRES/CELL, XRES, YRES);
bilinear_interpolation(th_gravx, th_gravxf, XRES/CELL, YRES/CELL, XRES, YRES);
bilinear_interpolation(th_gravp, th_gravpf, XRES/CELL, YRES/CELL, XRES, YRES);
fin: fin:
memcpy(th_ogravmap, th_gravmap, sizeof(th_gravmap)); memcpy(th_ogravmap, th_gravmap, sizeof(th_gravmap));
memset(th_gravmap, 0, sizeof(th_gravmap)); memset(th_gravmap, 0, sizeof(th_gravmap));

View File

@ -3355,7 +3355,6 @@ void draw_parts(pixel *vid)
#ifdef OpenGL #ifdef OpenGL
glFlush (); glFlush ();
#endif #endif
} }
void draw_walls(pixel *vid) void draw_walls(pixel *vid)
{ {
@ -3747,9 +3746,40 @@ void render_signs(pixel *vid_buf)
} }
} }
void render_fire(pixel *dst) void render_gravlensing(pixel *src, pixel * dst)
{ {
int i,j,x,y,r,g,b; int nx, ny, rx, ry, gx, gy, bx, by;
for(nx = 0; nx < XRES; nx++)
{
for(ny = 0; ny < YRES; ny++)
{
rx = nx-(gravxf[(ny*XRES)+nx]*0.5f);
ry = ny-(gravyf[(ny*XRES)+nx]*0.5f);
gx = nx-(gravxf[(ny*XRES)+nx]*0.75f);
gy = ny-(gravyf[(ny*XRES)+nx]*0.75f);
bx = nx-(gravxf[(ny*XRES)+nx]);
by = ny-(gravyf[(ny*XRES)+nx]);
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)
addpixel(dst, nx, ny, PIXR(src[ry*(XRES+BARSIZE)+rx]), PIXG(src[gy*(XRES+BARSIZE)+gx]), PIXB(src[by*(XRES+BARSIZE)+bx]), 255);
/*rx = nx+(gravxf[(ny*XRES)+nx]*0.5f);
ry = ny+(gravyf[(ny*XRES)+nx]*0.5f);
gx = nx+(gravxf[(ny*XRES)+nx]*0.75f);
gy = ny+(gravyf[(ny*XRES)+nx]*0.75f);
bx = nx+(gravxf[(ny*XRES)+nx]);
by = ny+(gravyf[(ny*XRES)+nx]);
if(rx > 0 && rx < XRES && ry > 0 && ry < YRES && gravp[ny/CELL][nx/CELL]*0.5f > -8.0f)
addpixel(dst, rx, ry, PIXR(src[ry*(XRES+BARSIZE)+rx]), 0, 0, 255);
if(gx > 0 && gx < XRES && gy > 0 && gy < YRES && gravp[ny/CELL][nx/CELL]*0.75f > -8.0f)
addpixel(dst, gx, gy, 0, PIXG(src[ry*(XRES+BARSIZE)+rx]), 0, 255);
if(bx > 0 && bx < XRES && by > 0 && by < YRES && gravp[ny/CELL][nx/CELL] > -8.0f)
addpixel(dst, bx, by, 0, 0, PIXB(src[ry*(XRES+BARSIZE)+rx]), 255);*/
}
}
}
void render_fire(pixel *vid)
{
int i,j,x,y,r,g,b,nx,ny;
for (j=0; j<YRES/CELL; j++) for (j=0; j<YRES/CELL; j++)
for (i=0; i<XRES/CELL; i++) for (i=0; i<XRES/CELL; i++)
{ {
@ -3759,7 +3789,7 @@ void render_fire(pixel *dst)
if (r || g || b) if (r || g || b)
for (y=-CELL+1; y<2*CELL; y++) for (y=-CELL+1; y<2*CELL; y++)
for (x=-CELL+1; x<2*CELL; x++) for (x=-CELL+1; x<2*CELL; x++)
addpixel(dst, i*CELL+x, j*CELL+y, r, g, b, fire_alpha[y+CELL][x+CELL]); addpixel(vid, i*CELL+x, j*CELL+y, r, g, b, fire_alpha[y+CELL][x+CELL]);
for (y=-1; y<2; y++) for (y=-1; y<2; y++)
for (x=-1; x<2; x++) for (x=-1; x<2; x++)
if (i+x>=0 && j+y>=0 && i+x<XRES/CELL && j+y<YRES/CELL && (x || y)) if (i+x>=0 && j+y>=0 && i+x<XRES/CELL && j+y<YRES/CELL && (x || y))

View File

@ -1543,6 +1543,8 @@ int main(int argc, char *argv[])
#else #else
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
pixel *part_vbuf; //Extra video buffer
pixel *part_vbuf_store;
int hud_enable = 1; int hud_enable = 1;
int active_menu = 0; int active_menu = 0;
#ifdef BETA #ifdef BETA
@ -1580,7 +1582,18 @@ int main(int argc, char *argv[])
pthread_win32_thread_attach_np(); pthread_win32_thread_attach_np();
#endif #endif
vid_buf = calloc((XRES+BARSIZE)*(YRES+MENUSIZE), PIXELSIZE); vid_buf = calloc((XRES+BARSIZE)*(YRES+MENUSIZE), PIXELSIZE);
part_vbuf = calloc((XRES+BARSIZE)*(YRES+MENUSIZE), PIXELSIZE); //Extra video buffer
part_vbuf_store = part_vbuf;
pers_bg = calloc((XRES+BARSIZE)*YRES, PIXELSIZE); pers_bg = calloc((XRES+BARSIZE)*YRES, PIXELSIZE);
//Allocate full size Gravmaps
th_gravyf = calloc(XRES*YRES, sizeof(float));
th_gravxf = calloc(XRES*YRES, sizeof(float));
th_gravpf = calloc(XRES*YRES, sizeof(float));
gravyf = calloc(XRES*YRES, sizeof(float));
gravxf = calloc(XRES*YRES, sizeof(float));
gravpf = calloc(XRES*YRES, sizeof(float));
GSPEED = 1; GSPEED = 1;
/* Set 16-bit stereo audio at 22Khz */ /* Set 16-bit stereo audio at 22Khz */
@ -1784,6 +1797,15 @@ int main(int argc, char *argv[])
#ifdef OpenGL #ifdef OpenGL
ClearScreen(); ClearScreen();
#else #else
if(cmode==CM_FANCY)
{
part_vbuf = part_vbuf_store;
memset(vid_buf, 0, (XRES+BARSIZE)*YRES*PIXELSIZE);
} else {
part_vbuf = vid_buf;
}
if(gravwl_timeout) if(gravwl_timeout)
{ {
if(gravwl_timeout==1) if(gravwl_timeout==1)
@ -1792,16 +1814,16 @@ int main(int argc, char *argv[])
} }
if (cmode==CM_VEL || cmode==CM_PRESS || cmode==CM_CRACK || (cmode==CM_HEAT && aheat_enable))//air only gets drawn in these modes if (cmode==CM_VEL || cmode==CM_PRESS || cmode==CM_CRACK || (cmode==CM_HEAT && aheat_enable))//air only gets drawn in these modes
{ {
draw_air(vid_buf); draw_air(part_vbuf);
} }
else if (cmode==CM_PERS)//save background for persistent, then clear else if (cmode==CM_PERS)//save background for persistent, then clear
{ {
memcpy(vid_buf, pers_bg, (XRES+BARSIZE)*YRES*PIXELSIZE); memcpy(part_vbuf, pers_bg, (XRES+BARSIZE)*YRES*PIXELSIZE);
memset(vid_buf+((XRES+BARSIZE)*YRES), 0, ((XRES+BARSIZE)*YRES*PIXELSIZE)-((XRES+BARSIZE)*YRES*PIXELSIZE)); memset(part_vbuf+((XRES+BARSIZE)*YRES), 0, ((XRES+BARSIZE)*YRES*PIXELSIZE)-((XRES+BARSIZE)*YRES*PIXELSIZE));
} }
else //clear screen every frame else //clear screen every frame
{ {
memset(vid_buf, 0, (XRES+BARSIZE)*YRES*PIXELSIZE); memset(part_vbuf, 0, (XRES+BARSIZE)*YRES*PIXELSIZE);
} }
#endif #endif
@ -1817,11 +1839,11 @@ int main(int argc, char *argv[])
if(ngrav_enable && drawgrav_enable) if(ngrav_enable && drawgrav_enable)
draw_grav(vid_buf); draw_grav(vid_buf);
draw_walls(vid_buf); draw_walls(part_vbuf);
update_particles(vid_buf); //update everything update_particles(part_vbuf); //update everything
draw_parts(vid_buf); //draw particles draw_parts(part_vbuf); //draw particles
if(sl == WL_GRAV+100 || sr == WL_GRAV+100) if(sl == WL_GRAV+100 || sr == WL_GRAV+100)
draw_grav_zones(vid_buf); draw_grav_zones(part_vbuf);
if(ngrav_enable){ if(ngrav_enable){
pthread_mutex_lock(&gravmutex); pthread_mutex_lock(&gravmutex);
@ -1831,6 +1853,22 @@ int main(int argc, char *argv[])
memcpy(th_gravmap, gravmap, sizeof(gravmap)); //Move our current gravmap to be processed other thread memcpy(th_gravmap, gravmap, sizeof(gravmap)); //Move our current gravmap to be processed other thread
memcpy(gravy, th_gravy, sizeof(gravy)); //Hmm, Gravy memcpy(gravy, th_gravy, sizeof(gravy)); //Hmm, Gravy
memcpy(gravx, th_gravx, sizeof(gravx)); //Move the processed velocity maps to be used memcpy(gravx, th_gravx, sizeof(gravx)); //Move the processed velocity maps to be used
memcpy(gravp, th_gravp, sizeof(gravp));
//Switch the full size gravmaps, we don't really need the two above any more
float *tmpf;
tmpf = gravyf;
gravyf = th_gravyf;
th_gravyf = tmpf;
tmpf = gravxf;
gravxf = th_gravxf;
th_gravxf = tmpf;
tmpf = gravpf;
gravpf = th_gravpf;
th_gravpf = tmpf;
if (!sys_pause||framerender){ //Only update if not paused if (!sys_pause||framerender){ //Only update if not paused
grav_ready = 0; //Tell the other thread that we're ready for it to continue grav_ready = 0; //Tell the other thread that we're ready for it to continue
pthread_cond_signal(&gravcv); pthread_cond_signal(&gravcv);
@ -1863,9 +1901,12 @@ int main(int argc, char *argv[])
fire_fc = (fire_fc+1) % 3; fire_fc = (fire_fc+1) % 3;
} }
if (cmode==CM_FIRE||cmode==CM_BLOB||cmode==CM_FANCY) if (cmode==CM_FIRE||cmode==CM_BLOB||cmode==CM_FANCY)
render_fire(vid_buf); render_fire(part_vbuf);
render_signs(vid_buf); render_signs(part_vbuf);
if(cmode==CM_FANCY)
render_gravlensing(part_vbuf, vid_buf);
memset(vid_buf+((XRES+BARSIZE)*YRES), 0, (PIXELSIZE*(XRES+BARSIZE))*MENUSIZE);//clear menu areas memset(vid_buf+((XRES+BARSIZE)*YRES), 0, (PIXELSIZE*(XRES+BARSIZE))*MENUSIZE);//clear menu areas
clearrect(vid_buf, XRES-1, 0, BARSIZE+1, YRES); clearrect(vid_buf, XRES-1, 0, BARSIZE+1, YRES);