// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- /// \file r_splats.c /// \brief Floor splats #include "r_draw.h" #include "r_main.h" #include "r_splats.h" #include "r_bsp.h" #include "w_wad.h" #include "z_zone.h" struct rastery_s *prastertab; // for ASM code #ifdef FLOORSPLATS static struct rastery_s rastertab[MAXVIDHEIGHT]; static void prepare_rastertab(void); UINT8 ds_splatclip[MAXVIDWIDTH]; // ========================================================================== // FLOOR SPLATS // ========================================================================== #ifdef USEASM void ASMCALL rasterize_segment_tex_asm(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 tv1, INT32 tv2, INT32 tc, INT32 dir); #endif // Lactozilla static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 tv1, INT32 tv2, INT32 tc, INT32 dir) { #ifdef USEASM if (R_ASM) { rasterize_segment_tex_asm(x1, y1, x2, y2, tv1, tv2, tc, dir); return; } else #endif { fixed_t xs, xe, count; fixed_t dx0, dx1; if (y1 == y2) return; if (y2 > y1) { count = (y2-y1)+1; dx0 = FixedDiv((x2-x1)< ry1) \ step = FixedDiv(x2-x1, y2-ry1+1); \ else if (y2 == ry1) \ step = 0; \ else \ step = FixedDiv(x2-x1, ry1-y2+1); \ if (ry1 < 0) { \ if (step) { \ x1 <<= FRACBITS; \ x1 += (-ry1)*step; \ x1 >>= FRACBITS; \ } \ ry1 = 0; \ } \ if (ry1 >= vid.height) { \ if (step) { \ x1 <<= FRACBITS; \ x1 -= (vid.height-1-ry1)*step; \ x1 >>= FRACBITS; \ } \ ry1 = vid.height - 1; \ } \ if (y2 < 0) { \ if (step) { \ x2 <<= FRACBITS; \ x2 -= (-y2)*step; \ x2 >>= FRACBITS; \ } \ y2 = 0; \ } \ if (y2 >= vid.height) { \ if (step) { \ x2 <<= FRACBITS; \ x2 += (vid.height-1-y2)*step; \ x2 >>= FRACBITS; \ } \ y2 = vid.height - 1; \ } \ rasterize_segment_tex(x1, ry1, x2, y2, tv1, tv2, tc, dir); \ if (ry1 < miny) \ miny = ry1; \ if (ry1 > maxy) \ maxy = ry1; // do segment a -> top of texture RASTERPARAMS(3,2,0,pSplat->width-1,0,0); // do segment b -> right side of texture RASTERPARAMS(2,1,0,pSplat->width-1,pSplat->height-1,0); // do segment c -> bottom of texture RASTERPARAMS(1,0,pSplat->width-1,0,pSplat->height-1,0); // do segment d -> left side of texture RASTERPARAMS(0,3,pSplat->width-1,0,0,1); ds_source = pSplat->pic; ds_flatwidth = pSplat->width; ds_flatheight = pSplat->height; if (R_CheckPowersOfTwo()) R_CheckFlatLength(ds_flatwidth * ds_flatheight); ds_transmap = NULL; if (vis->transmap) { ds_transmap = vis->transmap; spanfunctype = SPANDRAWFUNC_TRANSSPRITE; } if (ds_powersoftwo) spanfunc = spanfuncs[spanfunctype]; else spanfunc = spanfuncs_npo2[spanfunctype]; if (pSplat->angle) { memset(cachedheight, 0, sizeof(cachedheight)); angle = (viewangle + pSplat->angle - ANGLE_90) >> ANGLETOFINESHIFT; basexscale = FixedDiv(FINECOSINE(angle), centerxfrac); baseyscale = -FixedDiv(FINESINE(angle), centerxfrac); } else { angle = (viewangle - ANGLE_90) >> ANGLETOFINESHIFT; basexscale = FixedDiv(FINECOSINE(angle), centerxfrac); baseyscale = -FixedDiv(FINESINE(angle), centerxfrac); } planeheight = abs(pSplat->z - viewz); if (maxy >= vid.height) maxy = vid.height-1; for (y = miny; y <= maxy; y++) { x1 = rastertab[y].minx>>FRACBITS; x2 = rastertab[y].maxx>>FRACBITS; if (x1 > x2) { INT32 swap = x1; x1 = x2; x2 = swap; } if (x1 == INT16_MIN || x2 == INT16_MAX) continue; if (x1 < 0) x1 = 0; if (x2 >= vid.width) x2 = vid.width - 1; angle = (viewangle + pSplat->angle)>>ANGLETOFINESHIFT; planecos = FINECOSINE(angle); planesin = FINESINE(angle); if (planeheight != cachedheight[y]) { cachedheight[y] = planeheight; distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]); xstep = cachedxstep[y] = FixedMul(distance, basexscale); ystep = cachedystep[y] = FixedMul(distance, baseyscale); // don't divide by zero if ((span = abs(centery-y))) { xstep = cachedxstep[y] = FixedMul(planesin, planeheight) / span; ystep = cachedystep[y] = FixedMul(planecos, planeheight) / span; } } else { distance = cacheddistance[y]; xstep = cachedxstep[y]; ystep = cachedystep[y]; } ds_xstep = FixedDiv(xstep, pSplat->xscale); ds_ystep = FixedDiv(ystep, pSplat->yscale); ds_colormap = vis->colormap; ds_translation = R_GetSpriteTranslation(vis); if (ds_translation == NULL) ds_translation = colormaps; if (vis->extra_colormap) { if (!ds_colormap) ds_colormap = vis->extra_colormap->colormap; else ds_colormap = &vis->extra_colormap->colormap[ds_colormap - colormaps]; } if (pSplat->angle) { // Add the view offset, rotated by the plane angle. fixed_t a = -pSplat->verts[0].x + viewx; fixed_t b = -pSplat->verts[0].y + viewy; angle = (pSplat->angle >> ANGLETOFINESHIFT); offsetx = FixedMul(a, FINECOSINE(angle)) - FixedMul(b,FINESINE(angle)); offsety = -FixedMul(a, FINESINE(angle)) - FixedMul(b,FINECOSINE(angle)); } else { offsetx = viewx - pSplat->verts[0].x; offsety = pSplat->verts[0].y - viewy; } if (vis != NULL) { INT32 xclip; mfloorclip = vis->clipbot; mceilingclip = vis->cliptop; R_ClipVisSprite(vis, x1-1, x2+1, drawsegs, NULL); memset(ds_splatclip, 0, sizeof(ds_splatclip)); if (x2 >= x1 && x1 < viewwidth && x1 >= 0) { for (xclip = x1; xclip <= x2; xclip++) { if (y >= mfloorclip[xclip]) ds_splatclip[xclip] = 1; } } while (ds_splatclip[x1]) x1++; i = x2; while (i > x1) { if (ds_splatclip[i]) x2 = i-1; i--; } } ds_xfrac = FixedDiv(offsetx + FixedMul(planecos, distance) + (x1 - centerx) * xstep, pSplat->xscale); ds_yfrac = FixedDiv(offsety - FixedMul(planesin, distance) + (x1 - centerx) * ystep, pSplat->yscale); if (x2 >= x1) { ds_y = y; ds_x1 = x1; ds_x2 = x2; spanfunc(); } rastertab[y].minx = INT32_MAX; rastertab[y].maxx = INT32_MIN; } if (pSplat->angle) { memset(cachedheight, 0, sizeof(cachedheight)); angle = (viewangle - ANGLE_90) >> ANGLETOFINESHIFT; basexscale = FixedDiv(FINECOSINE(angle), centerxfrac); baseyscale = -FixedDiv(FINESINE(angle), centerxfrac); } } static void prepare_rastertab(void) { INT32 i; prastertab = rastertab; for (i = 0; i < vid.height; i++) { rastertab[i].minx = INT32_MAX; rastertab[i].maxx = INT32_MIN; } } #endif // FLOORSPLATS