diff --git a/src/r_segs.c b/src/r_segs.c index 0066579ac8452d8998b218bc40f5b31f35076007..b132ca9762fb9786f9195c4b337fe59fe46ec9ee 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -78,2908 +78,2904 @@ static INT16 *maskedtexturecol; static fixed_t *maskedtextureheight = NULL; #endif -// ========================================================================== -// R_Splats Wall Splats Drawer -// ========================================================================== - -#ifdef WALLSPLATS -static INT16 last_ceilingclip[MAXVIDWIDTH]; -static INT16 last_floorclip[MAXVIDWIDTH]; - -static void R_DrawSplatColumn(column_t *column) +// R_ExpandPlaneY +// +// A simple function to modify a vsplane's top and bottom for a particular column +// Sort of like R_ExpandPlane in r_plane.c, except this is vertical expansion +static inline void R_ExpandPlaneY(visplane_t *pl, INT32 x, INT16 top, INT16 bottom) { - INT32 topscreen, bottomscreen; - fixed_t basetexturemid; - INT32 topdelta, prevdelta = -1; - - basetexturemid = dc_texturemid; + // Expand the plane, don't shrink it! + // note: top and bottom default to 0xFFFF and 0x0000 respectively, which is totally compatible with this + if (pl->top[x] > top) pl->top[x] = top; + if (pl->bottom[x] < bottom) pl->bottom[x] = bottom; +} - for (; column->topdelta != 0xff ;) - { - // calculate unclipped screen coordinates for post - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - topscreen = sprtopscreen + spryscale*topdelta; - bottomscreen = topscreen + spryscale*column->length; +// +// R_RenderSegLoop +// Draws zero, one, or two textures (and possibly a masked +// texture) for walls. +// Can draw or mark the starting pixel of floor and ceiling +// textures. +// CALLED: CORE LOOPING ROUTINE. +// +#define HEIGHTBITS 12 +#define HEIGHTUNIT (1<<HEIGHTBITS) - dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; - dc_yh = (bottomscreen-1)>>FRACBITS; - if (dc_yh >= last_floorclip[dc_x]) - dc_yh = last_floorclip[dc_x] - 1; - if (dc_yl <= last_ceilingclip[dc_x]) - dc_yl = last_ceilingclip[dc_x] + 1; - if (dc_yl <= dc_yh && dl_yh < vid.height && yh > 0) - { - dc_source = (UINT8 *)column + 3; - dc_texturemid = basetexturemid - (topdelta<<FRACBITS); +//profile stuff --------------------------------------------------------- +//#define TIMING +#ifdef TIMING +#include "p5prof.h" +INT64 mycount; +INT64 mytotal = 0; +UINT32 nombre = 100000; +//static char runtest[10][80]; +#endif +//profile stuff --------------------------------------------------------- - // Drawn by R_DrawColumn. - colfunc(); - } - column = (column_t *)((UINT8 *)column + column->length + 4); - } +static void R_RenderSegLoop (void) +{ + angle_t angle; + size_t pindex = 0; + INT32 yl; + INT32 yh; - dc_texturemid = basetexturemid; -} + INT32 mid; + fixed_t texturecolumn = 0; +#ifdef ESLOPE + fixed_t oldtexturecolumn = -1; +#endif + INT32 top; + INT32 bottom; + INT32 i; -static void R_DrawWallSplats(void) -{ - wallsplat_t *splat; - seg_t *seg; - angle_t angle, angle1, angle2; - INT32 x1, x2; - size_t pindex; - column_t *col; - patch_t *patch; - fixed_t texturecolumn; + // Set the shadowed column drawer for light lists. + if (dc_numlights) + colfunc = colfuncs[COLDRAWFUNC_SHADOWED]; - splat = (wallsplat_t *)linedef->splats; + for (; rw_x < rw_stopx; rw_x++) + { + // mark floor / ceiling areas + yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS; - I_Assert(splat != NULL); + top = ceilingclip[rw_x]+1; - seg = ds_p->curline; + // no space above wall? + if (yl < top) + yl = top; - // draw all splats from the line that touches the range of the seg - for (; splat; splat = splat->next) - { - angle1 = R_PointToAngle(splat->v1.x, splat->v1.y); - angle2 = R_PointToAngle(splat->v2.x, splat->v2.y); - angle1 = (angle1 - viewangle + ANGLE_90)>>ANGLETOFINESHIFT; - angle2 = (angle2 - viewangle + ANGLE_90)>>ANGLETOFINESHIFT; - // out of the viewangletox lut - /// \todo clip it to the screen - if (angle1 > FINEANGLES/2 || angle2 > FINEANGLES/2) - continue; - x1 = viewangletox[angle1]; - x2 = viewangletox[angle2]; + if (markceiling) + { +#if 0 + bottom = yl-1; - if (x1 >= x2) - continue; // does not cross a pixel + if (bottom >= floorclip[rw_x]) + bottom = floorclip[rw_x]-1; - // splat is not in this seg range - if (x2 < ds_p->x1 || x1 > ds_p->x2) - continue; + if (top <= bottom) +#else + bottom = yl > floorclip[rw_x] ? floorclip[rw_x] : yl; - if (x1 < ds_p->x1) - x1 = ds_p->x1; - if (x2 > ds_p->x2) - x2 = ds_p->x2; - if (x2 <= x1) - continue; + if (top <= --bottom && ceilingplane) +#endif + R_ExpandPlaneY(ceilingplane, rw_x, top, bottom); + } - // calculate incremental stepping values for texture edges - rw_scalestep = ds_p->scalestep; - spryscale = ds_p->scale1 + (x1 - ds_p->x1)*rw_scalestep; - mfloorclip = floorclip; - mceilingclip = ceilingclip; - patch = W_CachePatchNum(splat->patch, PU_CACHE); + yh = bottomfrac>>HEIGHTBITS; - dc_texturemid = splat->top + (SHORT(patch->height)<<(FRACBITS-1)) - viewz; - if (splat->yoffset) - dc_texturemid += *splat->yoffset; + bottom = floorclip[rw_x]-1; - sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); + if (yh > bottom) + yh = bottom; - // set drawing mode - switch (splat->flags & SPLATDRAWMODE_MASK) + if (markfloor) { - case SPLATDRAWMODE_OPAQUE: - colfunc = colfuncs[BASEDRAWFUNC]; - break; - case SPLATDRAWMODE_TRANS: - if (!cv_translucency.value) - colfunc = colfuncs[BASEDRAWFUNC]; - else - { - dc_transmap = transtables + ((tr_trans50 - 1)<<FF_TRANSSHIFT); - colfunc = colfuncs[COLDRAWFUNC_FUZZY]; - } + top = yh < ceilingclip[rw_x] ? ceilingclip[rw_x] : yh; - break; - case SPLATDRAWMODE_SHADE: - colfunc = colfuncs[COLDRAWFUNC_SHADE]; - break; + if (++top <= bottom && floorplane) + R_ExpandPlaneY(floorplane, rw_x, top, bottom); } - dc_texheight = 0; - - // draw the columns - for (dc_x = x1; dc_x <= x2; dc_x++, spryscale += rw_scalestep) + if (numffloors) { - pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE - 1; - dc_colormap = walllights[pindex]; + firstseg->frontscale[rw_x] = frontscale[rw_x]; + top = ceilingclip[rw_x]+1; // PRBoom + bottom = floorclip[rw_x]-1; // PRBoom - if (frontsector->extra_colormap) - dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); + for (i = 0; i < numffloors; i++) + { +#ifdef POLYOBJECTS_PLANES + if (ffloor[i].polyobj && (!curline->polyseg || ffloor[i].polyobj != curline->polyseg)) + continue; +#endif - sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); - dc_iscale = 0xffffffffu / (unsigned)spryscale; + if (ffloor[i].height < viewz) + { + INT32 top_w = (ffloor[i].f_frac >> HEIGHTBITS) + 1; + INT32 bottom_w = ffloor[i].f_clip[rw_x]; - // find column of patch, from perspective - angle = (rw_centerangle + xtoviewangle[dc_x])>>ANGLETOFINESHIFT; - texturecolumn = rw_offset2 - splat->offset - - FixedMul(FINETANGENT(angle), rw_distance); + if (top_w < top) + top_w = top; - // FIXME! - texturecolumn >>= FRACBITS; - if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) - continue; + if (bottom_w > bottom) + bottom_w = bottom; - // draw the texture - col = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn])); - R_DrawSplatColumn(col); - } - } // next splat +#ifdef POLYOBJECTS_PLANES + // Polyobject-specific hack to fix plane leaking -Red + if (ffloor[i].polyobj && top_w >= bottom_w) { + ffloor[i].plane->top[rw_x] = 0xFFFF; + ffloor[i].plane->bottom[rw_x] = 0x0000; // fix for sky plane drawing crashes - Monster Iestyn 25/05/18 + } else +#endif - colfunc = colfuncs[BASEDRAWFUNC]; -} + if (top_w <= bottom_w) + { + ffloor[i].plane->top[rw_x] = (INT16)top_w; + ffloor[i].plane->bottom[rw_x] = (INT16)bottom_w; + } + } + else if (ffloor[i].height > viewz) + { + INT32 top_w = ffloor[i].c_clip[rw_x] + 1; + INT32 bottom_w = (ffloor[i].f_frac >> HEIGHTBITS); -#endif //WALLSPLATS + if (top_w < top) + top_w = top; -// ========================================================================== -// R_RenderMaskedSegRange -// ========================================================================== + if (bottom_w > bottom) + bottom_w = bottom; -// If we have a multi-patch texture on a 2sided wall (rare) then we draw -// it using R_DrawColumn, else we draw it using R_DrawMaskedColumn, this -// way we don't have to store extra post_t info with each column for -// multi-patch textures. They are not normally needed as multi-patch -// textures don't have holes in it. At least not for now. -static INT32 column2s_length; // column->length : for multi-patch on 2sided wall = texture->height +#ifdef POLYOBJECTS_PLANES + // Polyobject-specific hack to fix plane leaking -Red + if (ffloor[i].polyobj && top_w >= bottom_w) { + ffloor[i].plane->top[rw_x] = 0xFFFF; + ffloor[i].plane->bottom[rw_x] = 0x0000; // fix for sky plane drawing crashes - Monster Iestyn 25/05/18 + } else +#endif -static void R_Render2sidedMultiPatchColumn(column_t *column) -{ - INT32 topscreen, bottomscreen; + if (top_w <= bottom_w) + { + ffloor[i].plane->top[rw_x] = (INT16)top_w; + ffloor[i].plane->bottom[rw_x] = (INT16)bottom_w; + } + } + } + } - topscreen = sprtopscreen; // + spryscale*column->topdelta; topdelta is 0 for the wall - bottomscreen = topscreen + spryscale * column2s_length; + // Calculate lighting. + // Done for light lists anyway to avoid doing it for every light. + if (segtextured || dc_numlights) + { + pindex = FixedMul(rw_scale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; + if (pindex >= MAXLIGHTSCALE) + pindex = MAXLIGHTSCALE-1; + } - dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS; - dc_yh = (bottomscreen-1)>>FRACBITS; + //SoM: Calculate offsets for Thick fake floors. + // calculate texture offset + angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT; + texturecolumn = rw_offset-FixedMul(FINETANGENT(angle),rw_distance); - if (windowtop != INT32_MAX && windowbottom != INT32_MAX) - { - dc_yl = ((windowtop + FRACUNIT)>>FRACBITS); - dc_yh = (windowbottom - 1)>>FRACBITS; - } +#ifdef ESLOPE + if (oldtexturecolumn != -1) { + rw_bottomtexturemid += FixedMul(rw_bottomtextureslide, oldtexturecolumn-texturecolumn); + rw_midtexturemid += FixedMul(rw_midtextureslide, oldtexturecolumn-texturecolumn); + rw_toptexturemid += FixedMul(rw_toptextureslide, oldtexturecolumn-texturecolumn); + rw_midtextureback += FixedMul(rw_midtexturebackslide, oldtexturecolumn-texturecolumn); + } + oldtexturecolumn = texturecolumn; +#endif - if (dc_yh >= mfloorclip[dc_x]) - dc_yh = mfloorclip[dc_x] - 1; - if (dc_yl <= mceilingclip[dc_x]) - dc_yl = mceilingclip[dc_x] + 1; + texturecolumn >>= FRACBITS; - if (dc_yl >= vid.height || dc_yh < 0) - return; + // texturecolumn and lighting are independent of wall tiers + if (segtextured) + { + dc_colormap = walllights[pindex]; + dc_x = rw_x; + dc_iscale = 0xffffffffu / (unsigned)rw_scale; - if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0) - { - dc_source = (UINT8 *)column + 3; + if (frontsector->extra_colormap) + dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); + } - if (colfunc == colfuncs[BASEDRAWFUNC]) - (colfuncs[COLDRAWFUNC_TWOSMULTIPATCH])(); - else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) - (colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS])(); - else - colfunc(); - } -} + if (dc_numlights) + { + lighttable_t **xwalllights; + for (i = 0; i < dc_numlights; i++) + { + INT32 lightnum; + lightnum = (dc_lightlist[i].lightlevel >> LIGHTSEGSHIFT); -// quick wrapper for R_DrawFlippedMaskedColumn so it can be set as a colfunc_2s value -// uses column2s_length for texture->height as above -static void R_DrawFlippedMaskedSegColumn(column_t *column) -{ - R_DrawFlippedMaskedColumn(column, column2s_length); -} + if (dc_lightlist[i].extra_colormap) + ; + else if (curline->v1->y == curline->v2->y) + lightnum--; + else if (curline->v1->x == curline->v2->x) + lightnum++; -void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) -{ - size_t pindex; - column_t *col; - INT32 lightnum, texnum, i; - fixed_t height, realbot; - lightlist_t *light; - r_lightlist_t *rlight; - void (*colfunc_2s)(column_t *); - line_t *ldef; - sector_t *front, *back; - INT32 times, repeats; - INT64 overflow_test; -#ifdef ESLOPE - INT32 range; -#endif + if (lightnum < 0) + xwalllights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + xwalllights = scalelight[LIGHTLEVELS-1]; + else + xwalllights = scalelight[lightnum]; - // Calculate light table. - // Use different light tables - // for horizontal / vertical / diagonal. Diagonal? - // OPTIMIZE: get rid of LIGHTSEGSHIFT globally - curline = ds->curline; - frontsector = curline->frontsector; - backsector = curline->backsector; - texnum = R_GetTextureNum(curline->sidedef->midtexture); - windowbottom = windowtop = sprbotscreen = INT32_MAX; + if (dc_lightlist[i].extra_colormap) + dc_lightlist[i].rcolormap = dc_lightlist[i].extra_colormap->colormap + (xwalllights[pindex] - colormaps); + else + dc_lightlist[i].rcolormap = xwalllights[pindex]; + } + } - // hack translucent linedef types (900-909 for transtables 1-9) - ldef = curline->linedef; - switch (ldef->special) - { - case 900: - case 901: - case 902: - case 903: - case 904: - case 905: - case 906: - case 907: - case 908: - dc_transmap = transtables + ((ldef->special-900)<<FF_TRANSSHIFT); - colfunc = colfuncs[COLDRAWFUNC_FUZZY]; - break; - case 909: - colfunc = colfuncs[COLDRAWFUNC_FOG]; - windowtop = frontsector->ceilingheight; - windowbottom = frontsector->floorheight; - break; - default: - colfunc = colfuncs[BASEDRAWFUNC]; - break; - } + frontscale[rw_x] = rw_scale; - if (curline->polyseg && curline->polyseg->translucency > 0) - { - if (curline->polyseg->translucency >= NUMTRANSMAPS) - return; + // draw the wall tiers + if (midtexture) + { + // single sided line + if (yl <= yh && yh >= 0 && yl < viewheight) + { + dc_yl = yl; + dc_yh = yh; + dc_texturemid = rw_midtexturemid; + dc_source = R_GetColumn(midtexture,texturecolumn); + dc_texheight = textureheight[midtexture]>>FRACBITS; - dc_transmap = transtables + ((curline->polyseg->translucency-1)<<FF_TRANSSHIFT); - colfunc = colfuncs[COLDRAWFUNC_FUZZY]; - } + //profile stuff --------------------------------------------------------- +#ifdef TIMING + ProfZeroTimer(); +#endif + colfunc(); +#ifdef TIMING + RDMSR(0x10,&mycount); + mytotal += mycount; //64bit add -#ifdef ESLOPE - range = max(ds->x2-ds->x1, 1); + if (nombre--==0) + I_Error("R_DrawColumn CPU Spy reports: 0x%d %d\n", *((INT32 *)&mytotal+1), + (INT32)mytotal); #endif - rw_scalestep = ds->scalestep; - spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; + //profile stuff --------------------------------------------------------- - // Texture must be cached before setting colfunc_2s, - // otherwise texture[texnum]->holes may be false when it shouldn't be - R_CheckTextureCache(texnum); - // handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures - // are not stored per-column with post info in SRB2 - if (textures[texnum]->holes) - { - if (textures[texnum]->flip & 2) // vertically flipped? - { - colfunc_2s = R_DrawFlippedMaskedSegColumn; - column2s_length = textures[texnum]->height; + // dont draw anything more for this column, since + // a midtexture blocks the view + ceilingclip[rw_x] = (INT16)viewheight; + floorclip[rw_x] = -1; + } + else + { + // note: don't use min/max macros, since casting from INT32 to INT16 is involved here + if (markceiling) + ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1; + if (markfloor) + floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight; + } } else - colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture - } - else - { - colfunc_2s = R_Render2sidedMultiPatchColumn; // render multipatch with no holes (no post_t info) - column2s_length = textures[texnum]->height; - } - - // Setup lighting based on the presence/lack-of 3D floors. - dc_numlights = 0; - if (frontsector->numlights) - { - dc_numlights = frontsector->numlights; - if (dc_numlights >= dc_maxlights) - { - dc_maxlights = dc_numlights; - dc_lightlist = Z_Realloc(dc_lightlist, sizeof (*dc_lightlist) * dc_maxlights, PU_STATIC, NULL); - } - - for (i = 0; i < dc_numlights; i++) { -#ifdef ESLOPE - fixed_t leftheight, rightheight; -#endif - light = &frontsector->lightlist[i]; - rlight = &dc_lightlist[i]; -#ifdef ESLOPE - if (light->slope) { - leftheight = P_GetZAt(light->slope, ds->leftpos.x, ds->leftpos.y); - rightheight = P_GetZAt(light->slope, ds->rightpos.x, ds->rightpos.y); - } else - leftheight = rightheight = light->height; + // two sided line + if (toptexture) + { + // top wall + mid = pixhigh>>HEIGHTBITS; + pixhigh += pixhighstep; - leftheight -= viewz; - rightheight -= viewz; + if (mid >= floorclip[rw_x]) + mid = floorclip[rw_x]-1; - rlight->height = (centeryfrac) - FixedMul(leftheight, ds->scale1); - rlight->heightstep = (centeryfrac) - FixedMul(rightheight, ds->scale2); - rlight->heightstep = (rlight->heightstep-rlight->height)/(range); - //if (x1 > ds->x1) - //rlight->height -= (x1 - ds->x1)*rlight->heightstep; -#else - rlight->height = (centeryfrac) - FixedMul((light->height - viewz), spryscale); - rlight->heightstep = -FixedMul(rw_scalestep, (light->height - viewz)); -#endif - rlight->startheight = rlight->height; // keep starting value here to reset for each repeat - rlight->lightlevel = *light->lightlevel; - rlight->extra_colormap = *light->extra_colormap; - rlight->flags = light->flags; + if (mid >= yl) // back ceiling lower than front ceiling ? + { + if (yl >= viewheight) // entirely off bottom of screen + ceilingclip[rw_x] = (INT16)viewheight; + else if (mid >= 0) // safe to draw top texture + { + dc_yl = yl; + dc_yh = mid; + dc_texturemid = rw_toptexturemid; + dc_source = R_GetColumn(toptexture,texturecolumn); + dc_texheight = textureheight[toptexture]>>FRACBITS; + colfunc(); + ceilingclip[rw_x] = (INT16)mid; + } + else // entirely off top of screen + ceilingclip[rw_x] = -1; + } + else + ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1; + } + else if (markceiling) // no top wall + ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1; - if (rlight->flags & FF_FOG || (rlight->extra_colormap && rlight->extra_colormap->fog)) - lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); - else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) - lightnum = LIGHTLEVELS - 1; - else - lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); + if (bottomtexture) + { + // bottom wall + mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS; + pixlow += pixlowstep; - if (rlight->extra_colormap && rlight->extra_colormap->fog) - ; - else if (curline->v1->y == curline->v2->y) - lightnum--; - else if (curline->v1->x == curline->v2->x) - lightnum++; + // no space above wall? + if (mid <= ceilingclip[rw_x]) + mid = ceilingclip[rw_x]+1; - rlight->lightnum = lightnum; + if (mid <= yh) // back floor higher than front floor ? + { + if (yh < 0) // entirely off top of screen + floorclip[rw_x] = -1; + else if (mid < viewheight) // safe to draw bottom texture + { + dc_yl = mid; + dc_yh = yh; + dc_texturemid = rw_bottomtexturemid; + dc_source = R_GetColumn(bottomtexture, + texturecolumn); + dc_texheight = textureheight[bottomtexture]>>FRACBITS; + colfunc(); + floorclip[rw_x] = (INT16)mid; + } + else // entirely off bottom of screen + floorclip[rw_x] = (INT16)viewheight; + } + else + floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight; + } + else if (markfloor) // no bottom wall + floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight; } - } - else - { - if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) + + if (maskedtexture || numthicksides) { - if (frontsector->extra_colormap && frontsector->extra_colormap->fog) - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); - else - lightnum = LIGHTLEVELS - 1; + // save texturecol + // for backdrawing of masked mid texture + maskedtexturecol[rw_x] = (INT16)texturecolumn; + +#ifdef ESLOPE + if (maskedtextureheight != NULL) { + maskedtextureheight[rw_x] = (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3) ? + max(rw_midtexturemid, rw_midtextureback) : + min(rw_midtexturemid, rw_midtextureback)); + } +#endif } - else - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); - if (colfunc == colfuncs[COLDRAWFUNC_FOG] - || (frontsector->extra_colormap && frontsector->extra_colormap->fog)) - ; - else if (curline->v1->y == curline->v2->y) - lightnum--; - else if (curline->v1->x == curline->v2->x) - lightnum++; + if (dc_numlights) + { + for (i = 0; i < dc_numlights; i++) + { + dc_lightlist[i].height += dc_lightlist[i].heightstep; + if (dc_lightlist[i].flags & FF_CUTSOLIDS) + dc_lightlist[i].botheight += dc_lightlist[i].botheightstep; + } + } - if (lightnum < 0) - walllights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - walllights = scalelight[LIGHTLEVELS - 1]; - else - walllights = scalelight[lightnum]; + for (i = 0; i < numffloors; i++) + ffloor[i].f_frac += ffloor[i].f_step; + + for (i = 0; i < numbackffloors; i++) + { + ffloor[i].f_clip[rw_x] = ffloor[i].c_clip[rw_x] = (INT16)((ffloor[i].b_frac >> HEIGHTBITS) & 0xFFFF); + ffloor[i].b_frac += ffloor[i].b_step; + } + + rw_scale += rw_scalestep; + topfrac += topstep; + bottomfrac += bottomstep; } +} - maskedtexturecol = ds->maskedtexturecol; +// Macro for slope bullshit +#define SLOPEPARAMS(slope, end1, end2, normalheight) \ + if (slope) { \ + end1 = P_GetZAt(slope, segleft.x, segleft.y); \ + end2 = P_GetZAt(slope, segright.x, segright.y); \ + } else \ + end1 = end2 = normalheight; - mfloorclip = ds->sprbottomclip; - mceilingclip = ds->sprtopclip; +// +// R_CalculateSegDistance +// Calculate the distance from a seg. +// Uses precalculated seg length. +// +static void R_CalculateSegDistance(seg_t *seg, INT64 x2, INT64 y2, boolean longboi) +{ +#ifdef SOFTWARE_USE_FLOATS + float v1x = FIXED_TO_FLOAT(seg->v1->x); + float v1y = FIXED_TO_FLOAT(seg->v1->y); + float v2x = FIXED_TO_FLOAT(seg->v2->x); + float v2y = FIXED_TO_FLOAT(seg->v2->y); + float dx, dy, vdx, vdy; + float distance = 0.0f; - if (frontsector->heightsec != -1) - front = §ors[frontsector->heightsec]; + // The seg is vertical. + if (!seg->linedef->dy) + distance = fabsf(y2 - v1y); + // The seg is horizontal. + else if (!seg->linedef->dx) + distance = fabsf(x2 - v1x); + // Uses precalculated seg->flength + else if (longboi) + { + dx = v2x-v1x; + dy = v2y-v1y; + vdx = x2-v1x; + vdy = y2-v1y; + distance = ((dy*vdx)-(dx*vdy))/(seg->flength); + } + // Linguica's fix converted to floating-point math else - front = frontsector; + { + fixed_t x, y; + float a, c, ac; - if (backsector->heightsec != -1) - back = §ors[backsector->heightsec]; - else - back = backsector; + v1x -= FIXED_TO_FLOAT(viewx); + v1y -= FIXED_TO_FLOAT(viewy); + v2x -= FIXED_TO_FLOAT(viewx); + v2y -= FIXED_TO_FLOAT(viewy); + dx = v2x - v1x; + dy = v2y - v1y; - if (ds->curline->sidedef->repeatcnt) - repeats = 1 + ds->curline->sidedef->repeatcnt; - else if (ldef->flags & ML_EFFECT5) + a = (v1x*v2y) - (v1y*v2x); + c = (dx*dx) + (dy*dy); + ac = (a/c); + + x = FLOAT_TO_FIXED(ac*(-dy)); + y = FLOAT_TO_FIXED(ac*dx); + + rw_distance = R_PointToDist(viewx + x, viewy + y); + return; + } + + rw_distance = FLOAT_TO_FIXED(distance); +#else + (void)longboi; + if (!seg->linedef->dy) + rw_distance = (fixed_t)(llabs(y2 - seg->v1->y)); + else if (!seg->linedef->dx) + rw_distance = (fixed_t)(llabs(x2 - seg->v1->x)); + else { - fixed_t high, low; + INT64 dx = (seg->v2->x)-(seg->v1->x); + INT64 dy = (seg->v2->y)-(seg->v1->y); + INT64 vdx = x2-(seg->v1->x); + INT64 vdy = y2-(seg->v1->y); + rw_distance = (fixed_t)(((dy*vdx)-(dx*vdy))/(seg->length)); + } +#endif +} - if (front->ceilingheight > back->ceilingheight) - high = back->ceilingheight; - else - high = front->ceilingheight; +// +// R_CalculateWallScale +// Calculate scale at both ends and step. +// +static INT32 R_CalculateWallScale(INT32 start, INT32 stop) +{ + INT32 range = 1; - if (front->floorheight > back->floorheight) - low = front->floorheight; - else - low = back->floorheight; + ds_p->scale1 = rw_scale = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[start]); - repeats = (high - low)/textureheight[texnum]; - if ((high-low)%textureheight[texnum]) - repeats++; // tile an extra time to fill the gap -- Monster Iestyn + if (stop > start) + { + ds_p->scale2 = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[stop]); + range = stop-start; } else - repeats = 1; - - for (times = 0; times < repeats; times++) { - if (times > 0) + // UNUSED: try to fix the stretched line bug +#if 0 + if (rw_distance < FRACUNIT/2) { - rw_scalestep = ds->scalestep; - spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; - if (dc_numlights) - { // reset all lights to their starting heights - for (i = 0; i < dc_numlights; i++) - { - rlight = &dc_lightlist[i]; - rlight->height = rlight->startheight; - } - } - } + fixed_t tr_x,tr_y; + fixed_t gxt,gyt; + CONS_Debug(DBG_RENDER, "TRYING TO FIX THE STRETCHED ETC\n"); -#ifndef ESLOPE - if (curline->linedef->flags & ML_DONTPEGBOTTOM) - { - dc_texturemid = front->floorheight > back->floorheight - ? front->floorheight : back->floorheight; - dc_texturemid = dc_texturemid + textureheight[texnum] - viewz; - } - else - { - dc_texturemid = front->ceilingheight < back->ceilingheight - ? front->ceilingheight : back->ceilingheight; - dc_texturemid = dc_texturemid - viewz; - } - dc_texturemid += curline->sidedef->rowoffset; + tr_x = curline->v1->x - viewx; + tr_y = curline->v1->y - viewy; - if (curline->linedef->flags & ML_DONTPEGBOTTOM) - dc_texturemid += (textureheight[texnum])*times; - else - dc_texturemid -= (textureheight[texnum])*times; + gxt = FixedMul(tr_x, viewcos); + gyt = -FixedMul(tr_y, viewsin); + ds_p->scale1 = FixedDiv(projection, gxt - gyt); + } #endif + ds_p->scale2 = ds_p->scale1; + } - dc_texheight = textureheight[texnum]>>FRACBITS; - - // draw the columns - for (dc_x = x1; dc_x <= x2; dc_x++) - { -#ifdef ESLOPE - dc_texturemid = ds->maskedtextureheight[dc_x]; + ds_p->scalestep = rw_scalestep = (ds_p->scale2 - rw_scale) / (range); - if (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3)) - dc_texturemid += (textureheight[texnum])*times + textureheight[texnum]; - else - dc_texturemid -= (textureheight[texnum])*times; -#endif - // calculate lighting - if (maskedtexturecol[dc_x] != INT16_MAX) - { - // Check for overflows first - overflow_test = (INT64)centeryfrac - (((INT64)dc_texturemid*spryscale)>>FRACBITS); - if (overflow_test < 0) overflow_test = -overflow_test; - if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) - { - // Eh, no, go away, don't waste our time - if (dc_numlights) - { - for (i = 0; i < dc_numlights; i++) - { - rlight = &dc_lightlist[i]; - rlight->height += rlight->heightstep; - } - } - spryscale += rw_scalestep; - continue; - } + return range; +} - if (dc_numlights) - { - lighttable_t **xwalllights; +// +// R_WorldTopAndBottom +// Calculate texture boundaries +// and decide if floor or ceiling marks are needed. +// +static void R_WorldTopAndBottom(INT32 start, INT32 stop) +{ +#ifdef ESLOPE + // Figure out map coordinates of where start and end are mapping to on seg, so we can clip right for slope bullshit + if (frontsector->hasslope || (backsector && backsector->hasslope)) // Commenting this out for FOFslop. -Red + { + angle_t temp; - sprbotscreen = INT32_MAX; - sprtopscreen = windowtop = (centeryfrac - FixedMul(dc_texturemid, spryscale)); + // left + temp = xtoviewangle[start]+viewangle; - realbot = windowbottom = FixedMul(textureheight[texnum], spryscale) + sprtopscreen; - dc_iscale = 0xffffffffu / (unsigned)spryscale; + { + // Both lines can be written in slope-intercept form, so figure out line intersection + float a1, b1, c1, a2, b2, c2, det; // 1 is the seg, 2 is the view angle vector... + ///TODO: convert to FPU - // draw the texture - col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); + a1 = FIXED_TO_FLOAT(curline->v2->y-curline->v1->y); + b1 = FIXED_TO_FLOAT(curline->v1->x-curline->v2->x); + c1 = a1*FIXED_TO_FLOAT(curline->v1->x) + b1*FIXED_TO_FLOAT(curline->v1->y); - for (i = 0; i < dc_numlights; i++) - { - rlight = &dc_lightlist[i]; + a2 = -FIXED_TO_FLOAT(FINESINE(temp>>ANGLETOFINESHIFT)); + b2 = FIXED_TO_FLOAT(FINECOSINE(temp>>ANGLETOFINESHIFT)); + c2 = a2*FIXED_TO_FLOAT(viewx) + b2*FIXED_TO_FLOAT(viewy); - if ((rlight->flags & FF_NOSHADE)) - continue; + det = a1*b2 - a2*b1; - if (rlight->lightnum < 0) - xwalllights = scalelight[0]; - else if (rlight->lightnum >= LIGHTLEVELS) - xwalllights = scalelight[LIGHTLEVELS-1]; - else - xwalllights = scalelight[rlight->lightnum]; + ds_p->leftpos.x = segleft.x = FLOAT_TO_FIXED((b2*c1 - b1*c2)/det); + ds_p->leftpos.y = segleft.y = FLOAT_TO_FIXED((a1*c2 - a2*c1)/det); + } - pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; + // right + temp = xtoviewangle[stop]+viewangle; - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE - 1; + { + // Both lines can be written in slope-intercept form, so figure out line intersection + float a1, b1, c1, a2, b2, c2, det; // 1 is the seg, 2 is the view angle vector... + ///TODO: convert to FPU - if (rlight->extra_colormap) - rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps); - else - rlight->rcolormap = xwalllights[pindex]; + a1 = FIXED_TO_FLOAT(curline->v2->y-curline->v1->y); + b1 = FIXED_TO_FLOAT(curline->v1->x-curline->v2->x); + c1 = a1*FIXED_TO_FLOAT(curline->v1->x) + b1*FIXED_TO_FLOAT(curline->v1->y); - height = rlight->height; - rlight->height += rlight->heightstep; + a2 = -FIXED_TO_FLOAT(FINESINE(temp>>ANGLETOFINESHIFT)); + b2 = FIXED_TO_FLOAT(FINECOSINE(temp>>ANGLETOFINESHIFT)); + c2 = a2*FIXED_TO_FLOAT(viewx) + b2*FIXED_TO_FLOAT(viewy); - if (height <= windowtop) - { - dc_colormap = rlight->rcolormap; - continue; - } + det = a1*b2 - a2*b1; - windowbottom = height; - if (windowbottom >= realbot) - { - windowbottom = realbot; - colfunc_2s(col); - for (i++; i < dc_numlights; i++) - { - rlight = &dc_lightlist[i]; - rlight->height += rlight->heightstep; - } + ds_p->rightpos.x = segright.x = FLOAT_TO_FIXED((b2*c1 - b1*c2)/det); + ds_p->rightpos.y = segright.y = FLOAT_TO_FIXED((a1*c2 - a2*c1)/det); + } + } - continue; - } - colfunc_2s(col); - windowtop = windowbottom + 1; - dc_colormap = rlight->rcolormap; - } - windowbottom = realbot; - if (windowtop < windowbottom) - colfunc_2s(col); + SLOPEPARAMS(frontsector->c_slope, worldtop, worldtopslope, frontsector->ceilingheight) + SLOPEPARAMS(frontsector->f_slope, worldbottom, worldbottomslope, frontsector->floorheight) + // subtract viewz from these to turn them into + // positions relative to the camera's z position + worldtop -= viewz; + worldtopslope -= viewz; + worldbottom -= viewz; + worldbottomslope -= viewz; +#else + worldtop = frontsector->ceilingheight - viewz; + worldbottom = frontsector->floorheight - viewz; +#endif +} - spryscale += rw_scalestep; - continue; - } +// +// R_WorldSegTextured +// Calculate rw_offset. +// Only needed for textured lines. +// +static void R_WorldSegTextured(fixed_t hyp, boolean longboi) +{ + INT32 lightnum; + fixed_t sineval; + angle_t offsetangle = rw_normalangle-rw_angle1; - // calculate lighting - pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; + if (offsetangle > ANGLE_180) + offsetangle = -(signed)offsetangle; + if (offsetangle > ANGLE_90) + offsetangle = ANGLE_90; - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE - 1; + sineval = FINESINE(offsetangle>>ANGLETOFINESHIFT); + rw_offset = FixedMul(hyp, sineval); - dc_colormap = walllights[pindex]; + // big room fix + if (longboi) + { + INT64 dx = (curline->v2->x)-(curline->v1->x); + INT64 dy = (curline->v2->y)-(curline->v1->y); + INT64 vdx = viewx-(curline->v1->x); + INT64 vdy = viewy-(curline->v1->y); + rw_offset = ((dx*vdx-dy*vdy))/(curline->length); + } - if (frontsector->extra_colormap) - dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); + if (rw_normalangle-rw_angle1 < ANGLE_180) + rw_offset = -rw_offset; - sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); - dc_iscale = 0xffffffffu / (unsigned)spryscale; + /// don't use texture offset for splats + rw_offset2 = rw_offset + curline->offset; + rw_offset += sidedef->textureoffset + curline->offset; + rw_centerangle = ANGLE_90 + viewangle - rw_normalangle; - // draw the texture - col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); + // calculate light table + // use different light tables + // for horizontal / vertical / diagonal + // OPTIMIZE: get rid of LIGHTSEGSHIFT globally + lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); -//#ifdef POLYOBJECTS_PLANES -#if 0 // Disabling this allows inside edges to render below the planes, for until the clipping is fixed to work right when POs are near the camera. -Red - if (curline->dontrenderme && curline->polyseg && (curline->polyseg->flags & POF_RENDERPLANES)) - { - fixed_t my_topscreen; - fixed_t my_bottomscreen; - fixed_t my_yl, my_yh; + if (curline->v1->y == curline->v2->y) + lightnum--; + else if (curline->v1->x == curline->v2->x) + lightnum++; - my_topscreen = sprtopscreen + spryscale*col->topdelta; - my_bottomscreen = sprbotscreen == INT32_MAX ? my_topscreen + spryscale*col->length - : sprbotscreen + spryscale*col->length; + if (lightnum < 0) + walllights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + walllights = scalelight[LIGHTLEVELS - 1]; + else + walllights = scalelight[lightnum]; +} - my_yl = (my_topscreen+FRACUNIT-1)>>FRACBITS; - my_yh = (my_bottomscreen-1)>>FRACBITS; - // CONS_Debug(DBG_RENDER, "my_topscreen: %d\nmy_bottomscreen: %d\nmy_yl: %d\nmy_yh: %d\n", my_topscreen, my_bottomscreen, my_yl, my_yh); - - if (numffloors) - { - INT32 top = my_yl; - INT32 bottom = my_yh; +// +// R_CheckMaskedTextures +// Midtexture stuff, presumably. +// +static void R_CheckMaskedTextures(void) +{ + INT32 i = 0; + // allocate space for masked texture tables + if (frontsector && backsector && frontsector->tag != backsector->tag && (backsector->ffloors || frontsector->ffloors)) + { + ffloor_t *rover; + ffloor_t *r2; + fixed_t lowcut, highcut; +#ifdef ESLOPE + fixed_t lowcutslope, highcutslope; - for (i = 0; i < numffloors; i++) - { - if (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg) - continue; + // Used for height comparisons and etc across FOFs and slopes + fixed_t high1, highslope1, low1, lowslope1, high2, highslope2, low2, lowslope2; +#endif - if (ffloor[i].height < viewz) - { - INT32 top_w = ffloor[i].plane->top[dc_x]; + //markceiling = markfloor = true; + maskedtexture = true; - // CONS_Debug(DBG_RENDER, "Leveltime : %d\n", leveltime); - // CONS_Debug(DBG_RENDER, "Top is %d, top_w is %d\n", top, top_w); - if (top_w < top) - { - ffloor[i].plane->top[dc_x] = (INT16)top; - ffloor[i].plane->picnum = 0; - } - // CONS_Debug(DBG_RENDER, "top_w is now %d\n", ffloor[i].plane->top[dc_x]); - } - else if (ffloor[i].height > viewz) - { - INT32 bottom_w = ffloor[i].plane->bottom[dc_x]; + ds_p->thicksidecol = maskedtexturecol = lastopening - rw_x; + lastopening += rw_stopx - rw_x; - if (bottom_w > bottom) - { - ffloor[i].plane->bottom[dc_x] = (INT16)bottom; - ffloor[i].plane->picnum = 0; - } - } - } - } - } - else + lowcut = max(worldbottom, worldlow) + viewz; + highcut = min(worldtop, worldhigh) + viewz; +#ifdef ESLOPE + lowcutslope = max(worldbottomslope, worldlowslope) + viewz; + highcutslope = min(worldtopslope, worldhighslope) + viewz; #endif - colfunc_2s(col); - } - spryscale += rw_scalestep; - } - } - colfunc = colfuncs[BASEDRAWFUNC]; -} -// Loop through R_DrawMaskedColumn calls -static void R_DrawRepeatMaskedColumn(column_t *col) -{ - while (sprtopscreen < sprbotscreen) { - R_DrawMaskedColumn(col); - if ((INT64)sprtopscreen + dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow - sprtopscreen = INT32_MAX; - else - sprtopscreen += dc_texheight*spryscale; - } -} + if (frontsector->ffloors && backsector->ffloors) + { + i = 0; + for (rover = backsector->ffloors; rover && i < MAXFFLOORS; rover = rover->next) + { + if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS)) + continue; + if (rover->flags & FF_INVERTSIDES) + continue; -static void R_DrawRepeatFlippedMaskedColumn(column_t *col) -{ - do { - R_DrawFlippedMaskedColumn(col, column2s_length); - sprtopscreen += dc_texheight*spryscale; - } while (sprtopscreen < sprbotscreen); -} + if (rover->norender == leveltime) + continue; -// -// R_RenderThickSideRange -// Renders all the thick sides in the given range. -void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) -{ - size_t pindex; - column_t * col; - INT32 lightnum; - INT32 texnum; - sector_t tempsec; - INT32 templight; - INT32 i, p; - fixed_t bottombounds = viewheight << FRACBITS; - fixed_t topbounds = (con_clipviewtop - 1) << FRACBITS; - fixed_t offsetvalue = 0; - lightlist_t *light; - r_lightlist_t *rlight; -#ifdef ESLOPE - INT32 range; -#endif -#ifndef ESLOPE - fixed_t lheight; -#endif - line_t *newline = NULL; #ifdef ESLOPE - // Render FOF sides kinda like normal sides, with the frac and step and everything - // NOTE: INT64 instead of fixed_t because overflow concerns - INT64 top_frac, top_step, bottom_frac, bottom_step; - // skew FOF walls with slopes? - boolean slopeskew = false; - fixed_t ffloortextureslide = 0; - INT32 oldx = -1; - fixed_t left_top, left_bottom; // needed here for slope skewing - pslope_t *skewslope = NULL; + SLOPEPARAMS(*rover->t_slope, high1, highslope1, *rover->topheight) + SLOPEPARAMS(*rover->b_slope, low1, lowslope1, *rover->bottomheight) + + if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope)) + continue; +#else + if (*rover->topheight < lowcut || *rover->bottomheight > highcut) + continue; #endif - void (*colfunc_2s) (column_t *); + for (r2 = frontsector->ffloors; r2; r2 = r2->next) + { + if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES)) + continue; - // Calculate light table. - // Use different light tables - // for horizontal / vertical / diagonal. Diagonal? - // OPTIMIZE: get rid of LIGHTSEGSHIFT globally + if (r2->norender == leveltime) + continue; - curline = ds->curline; - backsector = pfloor->target; - frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector; - texnum = R_GetTextureNum(sides[pfloor->master->sidenum[0]].midtexture); + if (rover->flags & FF_EXTRA) + { + if (!(r2->flags & FF_CUTEXTRA)) + continue; - colfunc = colfuncs[BASEDRAWFUNC]; + if (r2->flags & FF_EXTRA && (r2->flags & (FF_TRANSLUCENT|FF_FOG)) != (rover->flags & (FF_TRANSLUCENT|FF_FOG))) + continue; + } + else + { + if (!(r2->flags & FF_CUTSOLIDS)) + continue; + } - if (pfloor->master->flags & ML_TFERLINE) - { - size_t linenum = curline->linedef-backsector->lines[0]; - newline = pfloor->master->frontsector->lines[0] + linenum; - texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture); - } +#ifdef ESLOPE + SLOPEPARAMS(*r2->t_slope, high2, highslope2, *r2->topheight) + SLOPEPARAMS(*r2->b_slope, low2, lowslope2, *r2->bottomheight) - if (pfloor->flags & FF_TRANSLUCENT) - { - boolean fuzzy = true; + if ((high2 < lowcut || highslope2 < lowcutslope) || (low2 > highcut || lowslope2 > highcutslope)) + continue; + if ((high1 > high2 || highslope1 > highslope2) || (low1 < low2 || lowslope1 < lowslope2)) + continue; +#else + if (*r2->topheight < lowcut || *r2->bottomheight > highcut) + continue; + if (*rover->topheight > *r2->topheight || *rover->bottomheight < *r2->bottomheight) + continue; +#endif - // Hacked up support for alpha value in software mode Tails 09-24-2002 - if (pfloor->alpha < 12) - return; // Don't even draw it - else if (pfloor->alpha < 38) - dc_transmap = transtables + ((tr_trans90-1)<<FF_TRANSSHIFT); - else if (pfloor->alpha < 64) - dc_transmap = transtables + ((tr_trans80-1)<<FF_TRANSSHIFT); - else if (pfloor->alpha < 89) - dc_transmap = transtables + ((tr_trans70-1)<<FF_TRANSSHIFT); - else if (pfloor->alpha < 115) - dc_transmap = transtables + ((tr_trans60-1)<<FF_TRANSSHIFT); - else if (pfloor->alpha < 140) - dc_transmap = transtables + ((tr_trans50-1)<<FF_TRANSSHIFT); - else if (pfloor->alpha < 166) - dc_transmap = transtables + ((tr_trans40-1)<<FF_TRANSSHIFT); - else if (pfloor->alpha < 192) - dc_transmap = transtables + ((tr_trans30-1)<<FF_TRANSSHIFT); - else if (pfloor->alpha < 217) - dc_transmap = transtables + ((tr_trans20-1)<<FF_TRANSSHIFT); - else if (pfloor->alpha < 243) - dc_transmap = transtables + ((tr_trans10-1)<<FF_TRANSSHIFT); - else - fuzzy = false; // Opaque + break; + } + if (r2) + continue; - if (fuzzy) - colfunc = colfuncs[COLDRAWFUNC_FUZZY]; - } - else if (pfloor->flags & FF_FOG) - colfunc = colfuncs[COLDRAWFUNC_FOG]; + ds_p->thicksides[i] = rover; + i++; + } -#ifdef ESLOPE - range = max(ds->x2-ds->x1, 1); -#endif - //SoM: Moved these up here so they are available for my lightlist calculations - rw_scalestep = ds->scalestep; - spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; + for (rover = frontsector->ffloors; rover && i < MAXFFLOORS; rover = rover->next) + { + if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS)) + continue; + if (!(rover->flags & FF_ALLSIDES)) + continue; - dc_numlights = 0; - if (frontsector->numlights) - { - dc_numlights = frontsector->numlights; - if (dc_numlights > dc_maxlights) - { - dc_maxlights = dc_numlights; - dc_lightlist = Z_Realloc(dc_lightlist, sizeof (*dc_lightlist) * dc_maxlights, PU_STATIC, NULL); - } + if (rover->norender == leveltime) + continue; - for (i = p = 0; i < dc_numlights; i++) - { #ifdef ESLOPE - fixed_t leftheight, rightheight; - fixed_t pfloorleft, pfloorright; - INT64 overflow_test; -#endif - light = &frontsector->lightlist[i]; - rlight = &dc_lightlist[p]; -#ifdef ESLOPE - -#define SLOPEPARAMS(slope, end1, end2, normalheight) \ - if (slope) { \ - end1 = P_GetZAt(slope, ds->leftpos.x, ds->leftpos.y); \ - end2 = P_GetZAt(slope, ds->rightpos.x, ds->rightpos.y); \ - } else \ - end1 = end2 = normalheight; - - SLOPEPARAMS(light->slope, leftheight, rightheight, light->height) - SLOPEPARAMS(*pfloor->b_slope, pfloorleft, pfloorright, *pfloor->bottomheight) + SLOPEPARAMS(*rover->t_slope, high1, highslope1, *rover->topheight) + SLOPEPARAMS(*rover->b_slope, low1, lowslope1, *rover->bottomheight) - if (leftheight < pfloorleft && rightheight < pfloorright) - continue; + if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope)) + continue; +#else + if (*rover->topheight < lowcut || *rover->bottomheight > highcut) + continue; +#endif - SLOPEPARAMS(*pfloor->t_slope, pfloorleft, pfloorright, *pfloor->topheight) + for (r2 = backsector->ffloors; r2; r2 = r2->next) + { + if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES)) + continue; - if (leftheight > pfloorleft && rightheight > pfloorright && i+1 < dc_numlights) - { - lightlist_t *nextlight = &frontsector->lightlist[i+1]; - if ((nextlight->slope ? P_GetZAt(nextlight->slope, ds->leftpos.x, ds->leftpos.y) : nextlight->height) > pfloorleft - && (nextlight->slope ? P_GetZAt(nextlight->slope, ds->rightpos.x, ds->rightpos.y) : nextlight->height) > pfloorright) - continue; - } + if (r2->norender == leveltime) + continue; - leftheight -= viewz; - rightheight -= viewz; + if (rover->flags & FF_EXTRA) + { + if (!(r2->flags & FF_CUTEXTRA)) + continue; -#define CLAMPMAX INT32_MAX -#define CLAMPMIN (-INT32_MAX) // This is not INT32_MIN on purpose! INT32_MIN makes the drawers freak out. - // Monster Iestyn (25/03/18): do not skip these lights if they fail overflow test, just clamp them instead so they behave. - overflow_test = (INT64)centeryfrac - (((INT64)leftheight*ds->scale1)>>FRACBITS); - if (overflow_test > (INT64)CLAMPMAX) rlight->height = CLAMPMAX; - else if (overflow_test > (INT64)CLAMPMIN) rlight->height = (fixed_t)overflow_test; - else rlight->height = CLAMPMIN; + if (r2->flags & FF_EXTRA && (r2->flags & (FF_TRANSLUCENT|FF_FOG)) != (rover->flags & (FF_TRANSLUCENT|FF_FOG))) + continue; + } + else + { + if (!(r2->flags & FF_CUTSOLIDS)) + continue; + } - overflow_test = (INT64)centeryfrac - (((INT64)rightheight*ds->scale2)>>FRACBITS); - if (overflow_test > (INT64)CLAMPMAX) rlight->heightstep = CLAMPMAX; - else if (overflow_test > (INT64)CLAMPMIN) rlight->heightstep = (fixed_t)overflow_test; - else rlight->heightstep = CLAMPMIN; - rlight->heightstep = (rlight->heightstep-rlight->height)/(range); +#ifdef ESLOPE + SLOPEPARAMS(*r2->t_slope, high2, highslope2, *r2->topheight) + SLOPEPARAMS(*r2->b_slope, low2, lowslope2, *r2->bottomheight) + if ((high2 < lowcut || highslope2 < lowcutslope) || (low2 > highcut || lowslope2 > highcutslope)) + continue; + if ((high1 > high2 || highslope1 > highslope2) || (low1 < low2 || lowslope1 < lowslope2)) + continue; #else - if (light->height < *pfloor->bottomheight) - continue; + if (*r2->topheight < lowcut || *r2->bottomheight > highcut) + continue; + if (*rover->topheight > *r2->topheight || *rover->bottomheight < *r2->bottomheight) + continue; +#endif - if (light->height > *pfloor->topheight && i+1 < dc_numlights && frontsector->lightlist[i+1].height > *pfloor->topheight) - continue; + break; + } + if (r2) + continue; - lheight = light->height;// > *pfloor->topheight ? *pfloor->topheight + FRACUNIT : light->height; - rlight->heightstep = -FixedMul (rw_scalestep, (lheight - viewz)); - rlight->height = (centeryfrac) - FixedMul((lheight - viewz), spryscale); -#endif - rlight->flags = light->flags; - if (light->flags & FF_CUTLEVEL) + ds_p->thicksides[i] = rover; + i++; + } + } + else if (backsector->ffloors) + { + for (rover = backsector->ffloors, i = 0; rover && i < MAXFFLOORS; rover = rover->next) { -#ifdef ESLOPE - SLOPEPARAMS(*light->caster->b_slope, leftheight, rightheight, *light->caster->bottomheight) -#undef SLOPEPARAMS - leftheight -= viewz; - rightheight -= viewz; - - // Monster Iestyn (25/03/18): do not skip these lights if they fail overflow test, just clamp them instead so they behave. - overflow_test = (INT64)centeryfrac - (((INT64)leftheight*ds->scale1)>>FRACBITS); - if (overflow_test > (INT64)CLAMPMAX) rlight->botheight = CLAMPMAX; - else if (overflow_test > (INT64)CLAMPMIN) rlight->botheight = (fixed_t)overflow_test; - else rlight->botheight = CLAMPMIN; + if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS) || rover->flags & FF_INVERTSIDES) + continue; + if (rover->norender == leveltime) + continue; - overflow_test = (INT64)centeryfrac - (((INT64)rightheight*ds->scale2)>>FRACBITS); - if (overflow_test > (INT64)CLAMPMAX) rlight->botheightstep = CLAMPMAX; - else if (overflow_test > (INT64)CLAMPMIN) rlight->botheightstep = (fixed_t)overflow_test; - else rlight->botheightstep = CLAMPMIN; - rlight->botheightstep = (rlight->botheightstep-rlight->botheight)/(range); +#ifdef ESLOPE + // Oy vey. + if (( (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldbottom+viewz + && (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldbottomslope+viewz) + ||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldtop+viewz + && (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldtopslope+viewz)) + continue; #else - lheight = *light->caster->bottomheight;// > *pfloor->topheight ? *pfloor->topheight + FRACUNIT : *light->caster->bottomheight; - rlight->botheightstep = -FixedMul (rw_scalestep, (lheight - viewz)); - rlight->botheight = (centeryfrac) - FixedMul((lheight - viewz), spryscale); + if (*rover->topheight <= frontsector->floorheight || *rover->bottomheight >= frontsector->ceilingheight) + continue; #endif - } - - rlight->lightlevel = *light->lightlevel; - rlight->extra_colormap = *light->extra_colormap; - // Check if the current light effects the colormap/lightlevel - if (pfloor->flags & FF_FOG) - rlight->lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT); - else - rlight->lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); + ds_p->thicksides[i] = rover; + i++; + } + } + else if (frontsector->ffloors) + { + for (rover = frontsector->ffloors, i = 0; rover && i < MAXFFLOORS; rover = rover->next) + { + if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS) || !(rover->flags & FF_ALLSIDES)) + continue; + if (rover->norender == leveltime) + continue; +#ifdef ESLOPE + // Oy vey. + if (( (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldbottom+viewz + && (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldbottomslope+viewz) + ||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldtop+viewz + && (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldtopslope+viewz)) + continue; - if (pfloor->flags & FF_FOG || rlight->flags & FF_FOG || (rlight->extra_colormap && rlight->extra_colormap->fog)) - ; - else if (curline->v1->y == curline->v2->y) - rlight->lightnum--; - else if (curline->v1->x == curline->v2->x) - rlight->lightnum++; + if (( (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldlow+viewz + && (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldlowslope+viewz) + ||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldhigh+viewz + && (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldhighslope+viewz)) + continue; +#else + if (*rover->topheight <= frontsector->floorheight || *rover->bottomheight >= frontsector->ceilingheight) + continue; + if (*rover->topheight <= backsector->floorheight || *rover->bottomheight >= backsector->ceilingheight) + continue; +#endif - p++; + ds_p->thicksides[i] = rover; + i++; + } } - dc_numlights = p; + ds_p->numthicksides = numthicksides = i; } - else - { - // Get correct light level! - if ((frontsector->extra_colormap && frontsector->extra_colormap->fog)) - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); - else if (pfloor->flags & FF_FOG) - lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT); - else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) - lightnum = LIGHTLEVELS-1; - else - lightnum = R_FakeFlat(frontsector, &tempsec, &templight, &templight, false) - ->lightlevel >> LIGHTSEGSHIFT; - - if (pfloor->flags & FF_FOG || (frontsector->extra_colormap && frontsector->extra_colormap->fog)); - else if (curline->v1->y == curline->v2->y) - lightnum--; - else if (curline->v1->x == curline->v2->x) - lightnum++; - if (lightnum < 0) - walllights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - walllights = scalelight[LIGHTLEVELS-1]; + if (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) + { + // masked midtexture + if (!ds_p->thicksidecol) + { + ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x; + lastopening += rw_stopx - rw_x; + } else - walllights = scalelight[lightnum]; - } - - maskedtexturecol = ds->thicksidecol; - - mfloorclip = ds->sprbottomclip; - mceilingclip = ds->sprtopclip; - dc_texheight = textureheight[texnum]>>FRACBITS; + ds_p->maskedtexturecol = ds_p->thicksidecol; #ifdef ESLOPE - // calculate both left ends - if (*pfloor->t_slope) - left_top = P_GetZAt(*pfloor->t_slope, ds->leftpos.x, ds->leftpos.y) - viewz; - else - left_top = *pfloor->topheight - viewz; - - if (*pfloor->b_slope) - left_bottom = P_GetZAt(*pfloor->b_slope, ds->leftpos.x, ds->leftpos.y) - viewz; - else - left_bottom = *pfloor->bottomheight - viewz; - skewslope = *pfloor->t_slope; // skew using top slope by default - if (newline) - { - if (newline->flags & ML_DONTPEGTOP) - slopeskew = true; - } - else if (pfloor->master->flags & ML_DONTPEGTOP) - slopeskew = true; + maskedtextureheight = ds_p->maskedtextureheight; // note to red, this == &(ds_p->maskedtextureheight[0]) - if (slopeskew) - dc_texturemid = left_top; - else +#ifdef POLYOBJECTS + if (curline->polyseg) { // use REAL front and back floors please, so midtexture rendering isn't mucked up + rw_midtextureslide = rw_midtexturebackslide = 0; + if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) + rw_midtexturemid = rw_midtextureback = max(curline->frontsector->floorheight, curline->backsector->floorheight) - viewz; + else + rw_midtexturemid = rw_midtextureback = min(curline->frontsector->ceilingheight, curline->backsector->ceilingheight) - viewz; + } else #endif - dc_texturemid = *pfloor->topheight - viewz; + // Set midtexture starting height + if (linedef->flags & ML_EFFECT2) { // Ignore slopes when texturing + rw_midtextureslide = rw_midtexturebackslide = 0; + if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) + rw_midtexturemid = rw_midtextureback = max(frontsector->floorheight, backsector->floorheight) - viewz; + else + rw_midtexturemid = rw_midtextureback = min(frontsector->ceilingheight, backsector->ceilingheight) - viewz; - if (newline) - { - offsetvalue = sides[newline->sidenum[0]].rowoffset; - if (newline->flags & ML_DONTPEGBOTTOM) - { + } else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) { + rw_midtexturemid = worldbottom; + rw_midtextureslide = floorfrontslide; + rw_midtextureback = worldlow; + rw_midtexturebackslide = floorbackslide; + } else { + rw_midtexturemid = worldtop; + rw_midtextureslide = ceilingfrontslide; + rw_midtextureback = worldhigh; + rw_midtexturebackslide = ceilingbackslide; + } + rw_midtexturemid += sidedef->rowoffset; + rw_midtextureback += sidedef->rowoffset; +#endif + + maskedtexture = true; + } +} + +// +// R_CheckWallTextures +// Self-explanatory, I hope?! +// +static void R_CheckWallTextures(void) +{ + if (!backsector) + { + fixed_t texheight; + // single sided line + midtexture = R_GetTextureNum(sidedef->midtexture); + texheight = textureheight[midtexture]; + // a single sided line is terminal, so it must mark ends + markfloor = markceiling = true; #ifdef ESLOPE - skewslope = *pfloor->b_slope; // skew using bottom slope - if (slopeskew) - dc_texturemid = left_bottom; + if (linedef->flags & ML_EFFECT2) { + if (linedef->flags & ML_DONTPEGBOTTOM) + rw_midtexturemid = frontsector->floorheight + texheight - viewz; else + rw_midtexturemid = frontsector->ceilingheight - viewz; + } + else +#endif + if (linedef->flags & ML_DONTPEGBOTTOM) + { +#ifdef ESLOPE + rw_midtexturemid = worldbottom + texheight; + rw_midtextureslide = floorfrontslide; +#else + vtop = frontsector->floorheight + texheight; + // bottom of texture at bottom + rw_midtexturemid = vtop - viewz; +#endif + } + else + { + // top of texture at top + rw_midtexturemid = worldtop; +#ifdef ESLOPE + rw_midtextureslide = ceilingfrontslide; #endif - offsetvalue -= *pfloor->topheight - *pfloor->bottomheight; } + rw_midtexturemid += sidedef->rowoffset; } else { - offsetvalue = sides[pfloor->master->sidenum[0]].rowoffset; - if (curline->linedef->flags & ML_DONTPEGBOTTOM) + // check TOP TEXTURE + if (!bothceilingssky // never draw the top texture if on + && (worldhigh < worldtop +#ifdef ESLOPE + || worldhighslope < worldtopslope +#endif + )) { + fixed_t texheight; + // top texture + if ((linedef->flags & (ML_DONTPEGTOP) && (linedef->flags & ML_DONTPEGBOTTOM)) + && linedef->sidenum[1] != 0xffff) + { + // Special case... use offsets from 2nd side but only if it has a texture. + side_t *def = &sides[linedef->sidenum[1]]; + toptexture = R_GetTextureNum(def->toptexture); + + if (!toptexture) //Second side has no texture, use the first side's instead. + toptexture = R_GetTextureNum(sidedef->toptexture); + texheight = textureheight[toptexture]; + } + else + { + toptexture = R_GetTextureNum(sidedef->toptexture); + texheight = textureheight[toptexture]; + } #ifdef ESLOPE - skewslope = *pfloor->b_slope; // skew using bottom slope - if (slopeskew) - dc_texturemid = left_bottom; + if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked + if (linedef->flags & ML_DONTPEGTOP) + rw_toptexturemid = frontsector->ceilingheight - viewz; + else + rw_toptexturemid = backsector->ceilingheight - viewz; + } else +#endif + if (linedef->flags & ML_DONTPEGTOP) + { + // top of texture at top + rw_toptexturemid = worldtop; +#ifdef ESLOPE + rw_toptextureslide = ceilingfrontslide; +#endif + } else + { +#ifdef ESLOPE + rw_toptexturemid = worldhigh + texheight; + rw_toptextureslide = ceilingbackslide; +#else + vtop = backsector->ceilingheight + texheight; + // bottom of texture + rw_toptexturemid = vtop - viewz; #endif - offsetvalue -= *pfloor->topheight - *pfloor->bottomheight; + } } - } - + // check BOTTOM TEXTURE + if (!bothfloorssky // never draw the bottom texture if on + && (worldlow > worldbottom #ifdef ESLOPE - if (slopeskew) - { - angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y); + || worldlowslope > worldbottomslope +#endif + )) //seulement si VISIBLE!!! + { + // bottom texture + bottomtexture = R_GetTextureNum(sidedef->bottomtexture); - if (skewslope) - ffloortextureslide = FixedMul(skewslope->zdelta, FINECOSINE((lineangle-skewslope->xydirection)>>ANGLETOFINESHIFT)); - } +#ifdef ESLOPE + if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked + if (linedef->flags & ML_DONTPEGBOTTOM) + rw_bottomtexturemid = frontsector->floorheight - viewz; + else + rw_bottomtexturemid = backsector->floorheight - viewz; + } else #endif + if (linedef->flags & ML_DONTPEGBOTTOM) + { + // bottom of texture at bottom + // top of texture at top + rw_bottomtexturemid = worldbottom; +#ifdef ESLOPE + rw_bottomtextureslide = floorfrontslide; +#endif + } + else { // top of texture at top + rw_bottomtexturemid = worldlow; +#ifdef ESLOPE + rw_bottomtextureslide = floorbackslide; +#endif + } + } - dc_texturemid += offsetvalue; + rw_toptexturemid += sidedef->rowoffset; + rw_bottomtexturemid += sidedef->rowoffset; + } +} - // Texture must be cached before setting colfunc_2s, - // otherwise texture[texnum]->holes may be false when it shouldn't be - R_CheckTextureCache(texnum); - //faB: handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures - // are not stored per-column with post info anymore in Doom Legacy - if (textures[texnum]->holes) +// +// R_StoreWallSilhouette +// Sets the silhouette for the current seg. +// Also checks if any floors or ceilings have to be marked. +// +static void R_StoreWallSilhouette(void) +{ + if (!backsector) { - if (textures[texnum]->flip & 2) // vertically flipped? - { - colfunc_2s = R_DrawRepeatFlippedMaskedColumn; - column2s_length = textures[texnum]->height; - } - else - colfunc_2s = R_DrawRepeatMaskedColumn; // render the usual 2sided single-patch packed texture + ds_p->silhouette = SIL_BOTH; + ds_p->sprtopclip = screenheightarray; + ds_p->sprbottomclip = negonearray; + ds_p->bsilheight = INT32_MAX; + ds_p->tsilheight = INT32_MIN; } else { - colfunc_2s = R_Render2sidedMultiPatchColumn; //render multipatch with no holes (no post_t info) - column2s_length = textures[texnum]->height; - } + // two sided line + bothceilingssky = false; // turned on if both back and front ceilings are sky + bothfloorssky = false; // likewise, but for floors #ifdef ESLOPE - // Set heights according to plane, or slope, whichever - { - fixed_t right_top, right_bottom; - - // calculate right ends now - if (*pfloor->t_slope) - right_top = P_GetZAt(*pfloor->t_slope, ds->rightpos.x, ds->rightpos.y) - viewz; - else - right_top = *pfloor->topheight - viewz; - - if (*pfloor->b_slope) - right_bottom = P_GetZAt(*pfloor->b_slope, ds->rightpos.x, ds->rightpos.y) - viewz; - else - right_bottom = *pfloor->bottomheight - viewz; + SLOPEPARAMS(backsector->c_slope, worldhigh, worldhighslope, backsector->ceilingheight) + SLOPEPARAMS(backsector->f_slope, worldlow, worldlowslope, backsector->floorheight) + worldhigh -= viewz; + worldhighslope -= viewz; + worldlow -= viewz; + worldlowslope -= viewz; +#else + worldhigh = backsector->ceilingheight - viewz; + worldlow = backsector->floorheight - viewz; +#endif - // using INT64 to avoid 32bit overflow - top_frac = (INT64)centeryfrac - (((INT64)left_top * ds->scale1) >> FRACBITS); - bottom_frac = (INT64)centeryfrac - (((INT64)left_bottom * ds->scale1) >> FRACBITS); - top_step = (INT64)centeryfrac - (((INT64)right_top * ds->scale2) >> FRACBITS); - bottom_step = (INT64)centeryfrac - (((INT64)right_bottom * ds->scale2) >> FRACBITS); + // hack to allow height changes in outdoor areas + // This is what gets rid of the upper textures if there should be sky + if (frontsector->ceilingpic == skyflatnum + && backsector->ceilingpic == skyflatnum) + { + bothceilingssky = true; + } - top_step = (top_step-top_frac)/(range); - bottom_step = (bottom_step-bottom_frac)/(range); + // likewise, but for floors and upper textures + if (frontsector->floorpic == skyflatnum + && backsector->floorpic == skyflatnum) + { + bothfloorssky = true; + } - top_frac += top_step * (x1 - ds->x1); - bottom_frac += bottom_step * (x1 - ds->x1); - } -#endif + ds_p->sprtopclip = ds_p->sprbottomclip = NULL; + ds_p->silhouette = 0; - // draw the columns - for (dc_x = x1; dc_x <= x2; dc_x++) - { - if (maskedtexturecol[dc_x] != INT16_MAX) + if (!bothfloorssky) { + if ( #ifdef ESLOPE - if (ffloortextureslide) { // skew FOF walls - if (oldx != -1) - dc_texturemid += FixedMul(ffloortextureslide, (maskedtexturecol[oldx]-maskedtexturecol[dc_x])<<FRACBITS); - oldx = dc_x; + worldbottomslope > worldlowslope || +#endif + worldbottom > worldlow) + { + ds_p->silhouette = SIL_BOTTOM; +#ifdef ESLOPE + if ((backsector->f_slope ? P_GetZAt(backsector->f_slope, viewx, viewy) : backsector->floorheight) > viewz) + ds_p->bsilheight = INT32_MAX; + else + ds_p->bsilheight = (frontsector->f_slope ? INT32_MAX : frontsector->floorheight); +#else + ds_p->bsilheight = frontsector->floorheight; +#endif } +#ifdef ESLOPE + else if ((backsector->f_slope ? P_GetZAt(backsector->f_slope, viewx, viewy) : backsector->floorheight) > viewz) +#else + else if (backsector->floorheight > viewz) #endif - // Calculate bounds - // clamp the values if necessary to avoid overflows and rendering glitches caused by them + { + ds_p->silhouette = SIL_BOTTOM; + ds_p->bsilheight = INT32_MAX; + // ds_p->sprbottomclip = negonearray; + } + } + if (!bothceilingssky) + { + if ( #ifdef ESLOPE - if (top_frac > (INT64)CLAMPMAX) sprtopscreen = windowtop = CLAMPMAX; - else if (top_frac > (INT64)CLAMPMIN) sprtopscreen = windowtop = (fixed_t)top_frac; - else sprtopscreen = windowtop = CLAMPMIN; - if (bottom_frac > (INT64)CLAMPMAX) sprbotscreen = windowbottom = CLAMPMAX; - else if (bottom_frac > (INT64)CLAMPMIN) sprbotscreen = windowbottom = (fixed_t)bottom_frac; - else sprbotscreen = windowbottom = CLAMPMIN; + worldtopslope < worldhighslope || +#endif + worldtop < worldhigh) + { + ds_p->silhouette |= SIL_TOP; +#ifdef ESLOPE + if ((backsector->c_slope ? P_GetZAt(backsector->c_slope, viewx, viewy) : backsector->ceilingheight) < viewz) + ds_p->tsilheight = INT32_MIN; + else + ds_p->tsilheight = (frontsector->c_slope ? INT32_MIN : frontsector->ceilingheight); +#else + ds_p->tsilheight = frontsector->ceilingheight; +#endif + } +#ifdef ESLOPE + else if ((backsector->c_slope ? P_GetZAt(backsector->c_slope, viewx, viewy) : backsector->ceilingheight) < viewz) +#else + else if (backsector->ceilingheight < viewz) +#endif + { + ds_p->silhouette |= SIL_TOP; + ds_p->tsilheight = INT32_MIN; + // ds_p->sprtopclip = screenheightarray; + } + } - top_frac += top_step; - bottom_frac += bottom_step; + if (!bothceilingssky && !bothfloorssky) + { +#ifdef ESLOPE + if (worldhigh <= worldbottom && worldhighslope <= worldbottomslope) #else - sprtopscreen = windowtop = (centeryfrac - FixedMul((dc_texturemid - offsetvalue), spryscale)); - sprbotscreen = windowbottom = FixedMul(*pfloor->topheight - *pfloor->bottomheight, spryscale) + sprtopscreen; + if (worldhigh <= worldbottom) #endif + { + ds_p->sprbottomclip = negonearray; + ds_p->bsilheight = INT32_MAX; + ds_p->silhouette |= SIL_BOTTOM; + } - // SoM: If column is out of range, why bother with it?? - if (windowbottom < topbounds || windowtop > bottombounds) +#ifdef ESLOPE + if (worldlow >= worldtop && worldlowslope >= worldtopslope) +#else + if (worldlow >= worldtop) +#endif { - if (dc_numlights) - { - for (i = 0; i < dc_numlights; i++) - { - rlight = &dc_lightlist[i]; - rlight->height += rlight->heightstep; - if (rlight->flags & FF_CUTLEVEL) - rlight->botheight += rlight->botheightstep; - } - } - spryscale += rw_scalestep; - continue; + ds_p->sprtopclip = screenheightarray; + ds_p->tsilheight = INT32_MIN; + ds_p->silhouette |= SIL_TOP; } + } - dc_iscale = 0xffffffffu / (unsigned)spryscale; + //SoM: 3/25/2000: This code fixes an automap bug that didn't check + // frontsector->ceiling and backsector->floor to see if a door was closed. + // Without the following code, sprites get displayed behind closed doors. + if (!bothceilingssky && !bothfloorssky) + { +#ifdef ESLOPE + if (doorclosed || (worldhigh <= worldbottom && worldhighslope <= worldbottomslope)) +#else + if (doorclosed || backsector->ceilingheight <= frontsector->floorheight) +#endif + { + ds_p->sprbottomclip = negonearray; + ds_p->bsilheight = INT32_MAX; + ds_p->silhouette |= SIL_BOTTOM; + } +#ifdef ESLOPE + if (doorclosed || (worldlow >= worldtop && worldlowslope >= worldtopslope)) +#else + if (doorclosed || backsector->floorheight >= frontsector->ceilingheight) +#endif + { // killough 1/17/98, 2/8/98 + ds_p->sprtopclip = screenheightarray; + ds_p->tsilheight = INT32_MIN; + ds_p->silhouette |= SIL_TOP; + } + } - // Get data for the column - col = (column_t *)((UINT8 *)R_GetColumn(texnum,maskedtexturecol[dc_x]) - 3); + if (bothfloorssky) + { + // see double ceiling skies comment + // this is the same but for upside down thok barriers where the floor is sky and the ceiling is normal + markfloor = false; + } + else if (worldlow != worldbottom +#ifdef ESLOPE + || worldlowslope != worldbottomslope + || backsector->f_slope != frontsector->f_slope +#endif + || backsector->floorpic != frontsector->floorpic + || backsector->lightlevel != frontsector->lightlevel + //SoM: 3/22/2000: Check floor x and y offsets. + || backsector->floor_xoffs != frontsector->floor_xoffs + || backsector->floor_yoffs != frontsector->floor_yoffs + || backsector->floorpic_angle != frontsector->floorpic_angle + //SoM: 3/22/2000: Prevents bleeding. + || (frontsector->heightsec != -1 && frontsector->floorpic != skyflatnum) + || backsector->floorlightsec != frontsector->floorlightsec + //SoM: 4/3/2000: Check for colormaps + || frontsector->extra_colormap != backsector->extra_colormap + || (frontsector->ffloors != backsector->ffloors && frontsector->tag != backsector->tag)) + { + markfloor = true; + } + else + { + // same plane on both sides + markfloor = false; + } - // SoM: New code does not rely on R_DrawColumnShadowed_8 which - // will (hopefully) put less strain on the stack. - if (dc_numlights) - { - lighttable_t **xwalllights; - fixed_t height; - fixed_t bheight = 0; - INT32 solid = 0; - INT32 lighteffect = 0; + if (bothceilingssky) + { + // double ceiling skies are special + // we don't want to lower the ceiling clipping, (no new plane is drawn anyway) + // so we can see the floor of thok barriers always regardless of sector properties + markceiling = false; + } + else if (worldhigh != worldtop +#ifdef ESLOPE + || worldhighslope != worldtopslope + || backsector->c_slope != frontsector->c_slope +#endif + || backsector->ceilingpic != frontsector->ceilingpic + || backsector->lightlevel != frontsector->lightlevel + //SoM: 3/22/2000: Check floor x and y offsets. + || backsector->ceiling_xoffs != frontsector->ceiling_xoffs + || backsector->ceiling_yoffs != frontsector->ceiling_yoffs + || backsector->ceilingpic_angle != frontsector->ceilingpic_angle + //SoM: 3/22/2000: Prevents bleeding. + || (frontsector->heightsec != -1 && frontsector->ceilingpic != skyflatnum) + || backsector->ceilinglightsec != frontsector->ceilinglightsec + //SoM: 4/3/2000: Check for colormaps + || frontsector->extra_colormap != backsector->extra_colormap + || (frontsector->ffloors != backsector->ffloors && frontsector->tag != backsector->tag)) + { + markceiling = true; + } + else + { + // same plane on both sides + markceiling = false; + } - for (i = 0; i < dc_numlights; i++) - { - // Check if the current light effects the colormap/lightlevel - rlight = &dc_lightlist[i]; - lighteffect = !(dc_lightlist[i].flags & FF_NOSHADE); - if (lighteffect) - { - lightnum = rlight->lightnum; + if (!bothceilingssky && !bothfloorssky) + { +#ifdef ESLOPE + if ((worldhigh <= worldbottom && worldhighslope <= worldbottomslope) + || (worldlow >= worldtop && worldlowslope >= worldtopslope)) +#else + if (backsector->ceilingheight <= frontsector->floorheight + || backsector->floorheight >= frontsector->ceilingheight) +#endif + { + // closed door + markceiling = markfloor = true; + } + } + } +} - if (lightnum < 0) - xwalllights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - xwalllights = scalelight[LIGHTLEVELS-1]; - else - xwalllights = scalelight[lightnum]; +// +// R_WorldStep +// Does... stepping... stuff? +// +static void R_WorldStep(INT32 range) +{ + worldtop >>= 4; + worldbottom >>= 4; +#ifdef ESLOPE + worldtopslope >>= 4; + worldbottomslope >>= 4; +#else + (void)range; +#endif - pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; + if (linedef->special == HORIZONSPECIAL) { // HORIZON LINES + topstep = bottomstep = 0; + topfrac = bottomfrac = (centeryfrac>>4); + topfrac++; // Prevent 1px HOM + } else { + topstep = -FixedMul (rw_scalestep, worldtop); + topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale); - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE-1; + bottomstep = -FixedMul (rw_scalestep,worldbottom); + bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale); - if (pfloor->flags & FF_FOG) - { - if (pfloor->master->frontsector->extra_colormap) - rlight->rcolormap = pfloor->master->frontsector->extra_colormap->colormap + (xwalllights[pindex] - colormaps); - else - rlight->rcolormap = xwalllights[pindex]; - } - else - { - if (rlight->extra_colormap) - rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps); - else - rlight->rcolormap = xwalllights[pindex]; - } - } - - solid = 0; // don't carry over solid-cutting flag from the previous light - - // Check if the current light can cut the current 3D floor. - if (rlight->flags & FF_CUTSOLIDS && !(pfloor->flags & FF_EXTRA)) - solid = 1; - else if (rlight->flags & FF_CUTEXTRA && pfloor->flags & FF_EXTRA) - { - if (rlight->flags & FF_EXTRA) - { - // The light is from an extra 3D floor... Check the flags so - // there are no undesired cuts. - if ((rlight->flags & (FF_FOG|FF_SWIMMABLE)) == (pfloor->flags & (FF_FOG|FF_SWIMMABLE))) - solid = 1; - } - else - solid = 1; - } - else - solid = 0; - - height = rlight->height; - rlight->height += rlight->heightstep; - - if (solid) - { - bheight = rlight->botheight - (FRACUNIT >> 1); - rlight->botheight += rlight->botheightstep; - } - - if (height <= windowtop) - { - if (lighteffect) - dc_colormap = rlight->rcolormap; - if (solid && windowtop < bheight) - windowtop = bheight; - continue; - } - - windowbottom = height; - if (windowbottom >= sprbotscreen) - { - windowbottom = sprbotscreen; - // draw the texture - colfunc_2s (col); - for (i++; i < dc_numlights; i++) - { - rlight = &dc_lightlist[i]; - rlight->height += rlight->heightstep; - if (rlight->flags & FF_CUTLEVEL) - rlight->botheight += rlight->botheightstep; - } - continue; - } - // draw the texture - colfunc_2s (col); - if (solid) - windowtop = bheight; - else - windowtop = windowbottom + 1; - if (lighteffect) - dc_colormap = rlight->rcolormap; - } - windowbottom = sprbotscreen; - // draw the texture, if there is any space left - if (windowtop < windowbottom) - colfunc_2s (col); - - spryscale += rw_scalestep; - continue; - } - - // calculate lighting - pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; - - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE - 1; - - dc_colormap = walllights[pindex]; - - if (pfloor->flags & FF_FOG && pfloor->master->frontsector->extra_colormap) - dc_colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc_colormap - colormaps); - else if (frontsector->extra_colormap) - dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); - - // draw the texture - colfunc_2s (col); - spryscale += rw_scalestep; +#ifdef ESLOPE + if (frontsector->c_slope) { + fixed_t topfracend = (centeryfrac>>4) - FixedMul (worldtopslope, ds_p->scale2); + topstep = (topfracend-topfrac)/(range); + } + if (frontsector->f_slope) { + fixed_t bottomfracend = (centeryfrac>>4) - FixedMul (worldbottomslope, ds_p->scale2); + bottomstep = (bottomfracend-bottomfrac)/(range); } +#endif } - colfunc = colfuncs[BASEDRAWFUNC]; - -#undef CLAMPMAX -#undef CLAMPMIN -} - -// R_ExpandPlaneY -// -// A simple function to modify a vsplane's top and bottom for a particular column -// Sort of like R_ExpandPlane in r_plane.c, except this is vertical expansion -static inline void R_ExpandPlaneY(visplane_t *pl, INT32 x, INT16 top, INT16 bottom) -{ - // Expand the plane, don't shrink it! - // note: top and bottom default to 0xFFFF and 0x0000 respectively, which is totally compatible with this - if (pl->top[x] > top) pl->top[x] = top; - if (pl->bottom[x] < bottom) pl->bottom[x] = bottom; } // -// R_RenderSegLoop -// Draws zero, one, or two textures (and possibly a masked -// texture) for walls. -// Can draw or mark the starting pixel of floor and ceiling -// textures. -// CALLED: CORE LOOPING ROUTINE. +// R_WorldBackStep +// Does... stepping... stuff? For backsides?!?!?!?!?!?! // -#define HEIGHTBITS 12 -#define HEIGHTUNIT (1<<HEIGHTBITS) - +static void R_WorldBackStep(INT32 range) +{ + INT32 i; -//profile stuff --------------------------------------------------------- -//#define TIMING -#ifdef TIMING -#include "p5prof.h" -INT64 mycount; -INT64 mytotal = 0; -UINT32 nombre = 100000; -//static char runtest[10][80]; + worldhigh >>= 4; + worldlow >>= 4; +#ifdef ESLOPE + worldhighslope >>= 4; + worldlowslope >>= 4; +#else + (void)range; #endif -//profile stuff --------------------------------------------------------- -static void R_RenderSegLoop (void) -{ - angle_t angle; - size_t pindex = 0; - INT32 yl; - INT32 yh; + if (toptexture) + { + pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale); + pixhighstep = -FixedMul (rw_scalestep,worldhigh); - INT32 mid; - fixed_t texturecolumn = 0; #ifdef ESLOPE - fixed_t oldtexturecolumn = -1; + if (backsector->c_slope) { + fixed_t topfracend = (centeryfrac>>4) - FixedMul (worldhighslope, ds_p->scale2); + pixhighstep = (topfracend-pixhigh)/(range); + } #endif - INT32 top; - INT32 bottom; - INT32 i; - - // Set the shadowed column drawer for light lists. - if (dc_numlights) - colfunc = colfuncs[COLDRAWFUNC_SHADOWED]; + } - for (; rw_x < rw_stopx; rw_x++) + if (bottomtexture) { - // mark floor / ceiling areas - yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS; - - top = ceilingclip[rw_x]+1; + pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale); + pixlowstep = -FixedMul (rw_scalestep,worldlow); +#ifdef ESLOPE + if (backsector->f_slope) { + fixed_t bottomfracend = (centeryfrac>>4) - FixedMul (worldlowslope, ds_p->scale2); + pixlowstep = (bottomfracend-pixlow)/(range); + } +#endif + } - // no space above wall? - if (yl < top) - yl = top; + { + ffloor_t * rover; +#ifdef ESLOPE + fixed_t roverleft, roverright; + fixed_t planevistest; +#endif + i = 0; - if (markceiling) + if (backsector->ffloors) { -#if 0 - bottom = yl-1; - - if (bottom >= floorclip[rw_x]) - bottom = floorclip[rw_x]-1; + for (rover = backsector->ffloors; rover && i < MAXFFLOORS; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES)) + continue; + if (rover->norender == leveltime) + continue; - if (top <= bottom) -#else - bottom = yl > floorclip[rw_x] ? floorclip[rw_x] : yl; +#ifdef ESLOPE + // Let the renderer know this sector is sloped. + if (*rover->b_slope || *rover->t_slope) + backsector->hasslope = true; - if (top <= --bottom && ceilingplane) -#endif - R_ExpandPlaneY(ceilingplane, rw_x, top, bottom); - } + roverleft = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) - viewz; + roverright = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) - viewz; + planevistest = (*rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : *rover->bottomheight); + if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) && + (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) && + ((viewz < planevistest && !(rover->flags & FF_INVERTPLANES)) || + (viewz > planevistest && (rover->flags & FF_BOTHPLANES)))) + { + //ffloor[i].slope = *rover->b_slope; + ffloor[i].b_pos = roverleft; + ffloor[i].b_pos_slope = roverright; + ffloor[i].b_pos >>= 4; + ffloor[i].b_pos_slope >>= 4; + ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); + ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2); + ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range); + i++; + } - yh = bottomfrac>>HEIGHTBITS; + if (i >= MAXFFLOORS) + break; - bottom = floorclip[rw_x]-1; + roverleft = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) - viewz; + roverright = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) - viewz; + planevistest = (*rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : *rover->topheight); - if (yh > bottom) - yh = bottom; + if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) && + (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) && + ((viewz > planevistest && !(rover->flags & FF_INVERTPLANES)) || + (viewz < planevistest && (rover->flags & FF_BOTHPLANES)))) + { + //ffloor[i].slope = *rover->t_slope; + ffloor[i].b_pos = roverleft; + ffloor[i].b_pos_slope = roverright; + ffloor[i].b_pos >>= 4; + ffloor[i].b_pos_slope >>= 4; + ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); + ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2); + ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range); + i++; + } +#else + if (*rover->bottomheight <= backsector->ceilingheight && + *rover->bottomheight >= backsector->floorheight && + ((viewz < *rover->bottomheight && !(rover->flags & FF_INVERTPLANES)) || + (viewz > *rover->bottomheight && (rover->flags & FF_BOTHPLANES)))) + { + ffloor[i].b_pos = *rover->bottomheight; + ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; + ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); + ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); + i++; + } - if (markfloor) - { - top = yh < ceilingclip[rw_x] ? ceilingclip[rw_x] : yh; + if (i >= MAXFFLOORS) + break; - if (++top <= bottom && floorplane) - R_ExpandPlaneY(floorplane, rw_x, top, bottom); + if (*rover->topheight >= backsector->floorheight && + *rover->topheight <= backsector->ceilingheight && + ((viewz > *rover->topheight && !(rover->flags & FF_INVERTPLANES)) || + (viewz < *rover->topheight && (rover->flags & FF_BOTHPLANES)))) + { + ffloor[i].b_pos = *rover->topheight; + ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; + ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); + ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); + i++; + } +#endif + } } - - if (numffloors) + else if (frontsector && frontsector->ffloors) { - firstseg->frontscale[rw_x] = frontscale[rw_x]; - top = ceilingclip[rw_x]+1; // PRBoom - bottom = floorclip[rw_x]-1; // PRBoom - - for (i = 0; i < numffloors; i++) + for (rover = frontsector->ffloors; rover && i < MAXFFLOORS; rover = rover->next) { -#ifdef POLYOBJECTS_PLANES - if (ffloor[i].polyobj && (!curline->polyseg || ffloor[i].polyobj != curline->polyseg)) + if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES)) + continue; + if (rover->norender == leveltime) continue; -#endif - - if (ffloor[i].height < viewz) - { - INT32 top_w = (ffloor[i].f_frac >> HEIGHTBITS) + 1; - INT32 bottom_w = ffloor[i].f_clip[rw_x]; - if (top_w < top) - top_w = top; - if (bottom_w > bottom) - bottom_w = bottom; +#ifdef ESLOPE + // Let the renderer know this sector is sloped. + if (*rover->b_slope || *rover->t_slope) + frontsector->hasslope = true; -#ifdef POLYOBJECTS_PLANES - // Polyobject-specific hack to fix plane leaking -Red - if (ffloor[i].polyobj && top_w >= bottom_w) { - ffloor[i].plane->top[rw_x] = 0xFFFF; - ffloor[i].plane->bottom[rw_x] = 0x0000; // fix for sky plane drawing crashes - Monster Iestyn 25/05/18 - } else -#endif + roverleft = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) - viewz; + roverright = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) - viewz; + planevistest = (*rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : *rover->bottomheight); - if (top_w <= bottom_w) - { - ffloor[i].plane->top[rw_x] = (INT16)top_w; - ffloor[i].plane->bottom[rw_x] = (INT16)bottom_w; - } - } - else if (ffloor[i].height > viewz) + if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) && + (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) && + ((viewz < planevistest && !(rover->flags & FF_INVERTPLANES)) || + (viewz > planevistest && (rover->flags & FF_BOTHPLANES)))) { - INT32 top_w = ffloor[i].c_clip[rw_x] + 1; - INT32 bottom_w = (ffloor[i].f_frac >> HEIGHTBITS); - - if (top_w < top) - top_w = top; + //ffloor[i].slope = *rover->b_slope; + ffloor[i].b_pos = roverleft; + ffloor[i].b_pos_slope = roverright; + ffloor[i].b_pos >>= 4; + ffloor[i].b_pos_slope >>= 4; + ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); + ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2); + ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range); + i++; + } - if (bottom_w > bottom) - bottom_w = bottom; + if (i >= MAXFFLOORS) + break; -#ifdef POLYOBJECTS_PLANES - // Polyobject-specific hack to fix plane leaking -Red - if (ffloor[i].polyobj && top_w >= bottom_w) { - ffloor[i].plane->top[rw_x] = 0xFFFF; - ffloor[i].plane->bottom[rw_x] = 0x0000; // fix for sky plane drawing crashes - Monster Iestyn 25/05/18 - } else -#endif + roverleft = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) - viewz; + roverright = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) - viewz; + planevistest = (*rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : *rover->topheight); - if (top_w <= bottom_w) - { - ffloor[i].plane->top[rw_x] = (INT16)top_w; - ffloor[i].plane->bottom[rw_x] = (INT16)bottom_w; - } + if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) && + (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) && + ((viewz > planevistest && !(rover->flags & FF_INVERTPLANES)) || + (viewz < planevistest && (rover->flags & FF_BOTHPLANES)))) + { + //ffloor[i].slope = *rover->t_slope; + ffloor[i].b_pos = roverleft; + ffloor[i].b_pos_slope = roverright; + ffloor[i].b_pos >>= 4; + ffloor[i].b_pos_slope >>= 4; + ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); + ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2); + ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range); + i++; + } +#else + if (*rover->bottomheight <= frontsector->ceilingheight && + *rover->bottomheight >= frontsector->floorheight && + ((viewz < *rover->bottomheight && !(rover->flags & FF_INVERTPLANES)) || + (viewz > *rover->bottomheight && (rover->flags & FF_BOTHPLANES)))) + { + ffloor[i].b_pos = *rover->bottomheight; + ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; + ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); + ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); + i++; + } + if (i >= MAXFFLOORS) + break; + if (*rover->topheight >= frontsector->floorheight && + *rover->topheight <= frontsector->ceilingheight && + ((viewz > *rover->topheight && !(rover->flags & FF_INVERTPLANES)) || + (viewz < *rover->topheight && (rover->flags & FF_BOTHPLANES)))) + { + ffloor[i].b_pos = *rover->topheight; + ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; + ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); + ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); + i++; } +#endif } } - // Calculate lighting. - // Done for light lists anyway to avoid doing it for every light. - if (segtextured || dc_numlights) +#ifdef POLYOBJECTS_PLANES + if (curline->polyseg && frontsector && (curline->polyseg->flags & POF_RENDERPLANES)) { - pindex = FixedMul(rw_scale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE-1; - } + while (i < numffloors && ffloor[i].polyobj != curline->polyseg) i++; + if (i < numffloors && backsector->floorheight <= frontsector->ceilingheight && + backsector->floorheight >= frontsector->floorheight && + (viewz < backsector->floorheight)) + { + if (ffloor[i].plane->minx > ds_p->x1) + ffloor[i].plane->minx = ds_p->x1; - //SoM: Calculate offsets for Thick fake floors. - // calculate texture offset - angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT; - texturecolumn = rw_offset-FixedMul(FINETANGENT(angle),rw_distance); + if (ffloor[i].plane->maxx < ds_p->x2) + ffloor[i].plane->maxx = ds_p->x2; #ifdef ESLOPE - if (oldtexturecolumn != -1) { - rw_bottomtexturemid += FixedMul(rw_bottomtextureslide, oldtexturecolumn-texturecolumn); - rw_midtexturemid += FixedMul(rw_midtextureslide, oldtexturecolumn-texturecolumn); - rw_toptexturemid += FixedMul(rw_toptextureslide, oldtexturecolumn-texturecolumn); - rw_midtextureback += FixedMul(rw_midtexturebackslide, oldtexturecolumn-texturecolumn); - } - oldtexturecolumn = texturecolumn; + ffloor[i].slope = NULL; #endif + ffloor[i].b_pos = backsector->floorheight; + ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; + ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); + ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); + i++; + } + if (i < numffloors && backsector->ceilingheight >= frontsector->floorheight && + backsector->ceilingheight <= frontsector->ceilingheight && + (viewz > backsector->ceilingheight)) + { + if (ffloor[i].plane->minx > ds_p->x1) + ffloor[i].plane->minx = ds_p->x1; - texturecolumn >>= FRACBITS; - - // texturecolumn and lighting are independent of wall tiers - if (segtextured) - { - dc_colormap = walllights[pindex]; - dc_x = rw_x; - dc_iscale = 0xffffffffu / (unsigned)rw_scale; + if (ffloor[i].plane->maxx < ds_p->x2) + ffloor[i].plane->maxx = ds_p->x2; - if (frontsector->extra_colormap) - dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); +#ifdef ESLOPE + ffloor[i].slope = NULL; +#endif + ffloor[i].b_pos = backsector->ceilingheight; + ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; + ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); + ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); + i++; + } } +#endif - if (dc_numlights) - { - lighttable_t **xwalllights; - for (i = 0; i < dc_numlights; i++) - { - INT32 lightnum; - lightnum = (dc_lightlist[i].lightlevel >> LIGHTSEGSHIFT); - - if (dc_lightlist[i].extra_colormap) - ; - else if (curline->v1->y == curline->v2->y) - lightnum--; - else if (curline->v1->x == curline->v2->x) - lightnum++; + numbackffloors = i; + } +} - if (lightnum < 0) - xwalllights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - xwalllights = scalelight[LIGHTLEVELS-1]; - else - xwalllights = scalelight[lightnum]; - - if (dc_lightlist[i].extra_colormap) - dc_lightlist[i].rcolormap = dc_lightlist[i].extra_colormap->colormap + (xwalllights[pindex] - colormaps); - else - dc_lightlist[i].rcolormap = xwalllights[pindex]; - } - } +// +// R_WorldFFloorStep +// Does... stepping... stuff? For FOFs?! +// +static void R_WorldFFloorStep(INT32 range) +{ + INT32 i; - frontscale[rw_x] = rw_scale; +#ifndef ESLOPE + (void)range; // Not needed! +#endif - // draw the wall tiers - if (midtexture) + for (i = 0; i < numffloors; i++) + { + ffloor[i].f_pos >>= 4; +#ifdef ESLOPE + ffloor[i].f_pos_slope >>= 4; +#endif + if (linedef->special == HORIZONSPECIAL) // Horizon lines extend FOFs in contact with them too. { - // single sided line - if (yl <= yh && yh >= 0 && yl < viewheight) - { - dc_yl = yl; - dc_yh = yh; - dc_texturemid = rw_midtexturemid; - dc_source = R_GetColumn(midtexture,texturecolumn); - dc_texheight = textureheight[midtexture]>>FRACBITS; - - //profile stuff --------------------------------------------------------- -#ifdef TIMING - ProfZeroTimer(); + ffloor[i].f_step = 0; + ffloor[i].f_frac = (centeryfrac>>4); + topfrac++; // Prevent 1px HOM + } + else + { +#ifdef ESLOPE + ffloor[i].f_frac = (centeryfrac>>4) - FixedMul(ffloor[i].f_pos, rw_scale); + ffloor[i].f_step = ((centeryfrac>>4) - FixedMul(ffloor[i].f_pos_slope, ds_p->scale2) - ffloor[i].f_frac)/(range); +#else + ffloor[i].f_step = FixedMul(-rw_scalestep, ffloor[i].f_pos); + ffloor[i].f_frac = (centeryfrac>>4) - FixedMul(ffloor[i].f_pos, rw_scale); #endif - colfunc(); -#ifdef TIMING - RDMSR(0x10,&mycount); - mytotal += mycount; //64bit add + } + } +} - if (nombre--==0) - I_Error("R_DrawColumn CPU Spy reports: 0x%d %d\n", *((INT32 *)&mytotal+1), - (INT32)mytotal); +// +// R_WorldLightLists +// Creates light lists. +// +static void R_WorldLightLists(INT32 range) +{ + INT32 i, p; + lightlist_t *light; + r_lightlist_t *rlight; + +#ifndef ESLOPE + (void)range; // Not needed! #endif - //profile stuff --------------------------------------------------------- - // dont draw anything more for this column, since - // a midtexture blocks the view - ceilingclip[rw_x] = (INT16)viewheight; - floorclip[rw_x] = -1; - } - else - { - // note: don't use min/max macros, since casting from INT32 to INT16 is involved here - if (markceiling) - ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1; - if (markfloor) - floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight; - } + dc_numlights = 0; + + if (frontsector->numlights) + { + dc_numlights = frontsector->numlights; + if (dc_numlights >= dc_maxlights) + { + dc_maxlights = dc_numlights; + dc_lightlist = Z_Realloc(dc_lightlist, sizeof (*dc_lightlist) * dc_maxlights, PU_STATIC, NULL); } - else + + for (i = p = 0; i < dc_numlights; i++) { - // two sided line - if (toptexture) - { - // top wall - mid = pixhigh>>HEIGHTBITS; - pixhigh += pixhighstep; +#ifdef ESLOPE + fixed_t leftheight, rightheight; +#endif - if (mid >= floorclip[rw_x]) - mid = floorclip[rw_x]-1; + light = &frontsector->lightlist[i]; + rlight = &dc_lightlist[p]; - if (mid >= yl) // back ceiling lower than front ceiling ? - { - if (yl >= viewheight) // entirely off bottom of screen - ceilingclip[rw_x] = (INT16)viewheight; - else if (mid >= 0) // safe to draw top texture - { - dc_yl = yl; - dc_yh = mid; - dc_texturemid = rw_toptexturemid; - dc_source = R_GetColumn(toptexture,texturecolumn); - dc_texheight = textureheight[toptexture]>>FRACBITS; - colfunc(); - ceilingclip[rw_x] = (INT16)mid; - } - else // entirely off top of screen - ceilingclip[rw_x] = -1; - } - else - ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1; - } - else if (markceiling) // no top wall - ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1; +#ifdef ESLOPE + if (light->slope) { + leftheight = P_GetZAt(light->slope, segleft.x, segleft.y); + rightheight = P_GetZAt(light->slope, segright.x, segright.y); - if (bottomtexture) + // Flag sector as having slopes + frontsector->hasslope = true; + } else + leftheight = rightheight = light->height; + + leftheight -= viewz; + rightheight -= viewz; + + leftheight >>= 4; + rightheight >>= 4; +#endif + + if (i != 0) { - // bottom wall - mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS; - pixlow += pixlowstep; +#ifdef ESLOPE + if (leftheight < worldbottom && rightheight < worldbottomslope) + continue; - // no space above wall? - if (mid <= ceilingclip[rw_x]) - mid = ceilingclip[rw_x]+1; + if (leftheight > worldtop && rightheight > worldtopslope && i+1 < dc_numlights && frontsector->lightlist[i+1].height > frontsector->ceilingheight) + continue; +#else + if (light->height < frontsector->floorheight) + continue; - if (mid <= yh) // back floor higher than front floor ? - { - if (yh < 0) // entirely off top of screen - floorclip[rw_x] = -1; - else if (mid < viewheight) // safe to draw bottom texture - { - dc_yl = mid; - dc_yh = yh; - dc_texturemid = rw_bottomtexturemid; - dc_source = R_GetColumn(bottomtexture, - texturecolumn); - dc_texheight = textureheight[bottomtexture]>>FRACBITS; - colfunc(); - floorclip[rw_x] = (INT16)mid; - } - else // entirely off bottom of screen - floorclip[rw_x] = (INT16)viewheight; - } - else - floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight; + if (light->height > frontsector->ceilingheight && i+1 < dc_numlights && frontsector->lightlist[i+1].height > frontsector->ceilingheight) + continue; +#endif } - else if (markfloor) // no bottom wall - floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight; - } - - if (maskedtexture || numthicksides) - { - // save texturecol - // for backdrawing of masked mid texture - maskedtexturecol[rw_x] = (INT16)texturecolumn; #ifdef ESLOPE - if (maskedtextureheight != NULL) { - maskedtextureheight[rw_x] = (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3) ? - max(rw_midtexturemid, rw_midtextureback) : - min(rw_midtexturemid, rw_midtextureback)); - } + rlight->height = (centeryfrac>>4) - FixedMul(leftheight, rw_scale); + rlight->heightstep = (centeryfrac>>4) - FixedMul(rightheight, ds_p->scale2); + rlight->heightstep = (rlight->heightstep-rlight->height)/(range); +#else + rlight->height = (centeryfrac>>4) - FixedMul((light->height - viewz) >> 4, rw_scale); + rlight->heightstep = -FixedMul (rw_scalestep, (light->height - viewz) >> 4); #endif - } + rlight->flags = light->flags; - if (dc_numlights) - { - for (i = 0; i < dc_numlights; i++) + if (light->caster && light->caster->flags & FF_CUTSOLIDS) { - dc_lightlist[i].height += dc_lightlist[i].heightstep; - if (dc_lightlist[i].flags & FF_CUTSOLIDS) - dc_lightlist[i].botheight += dc_lightlist[i].botheightstep; - } - } +#ifdef ESLOPE + if (*light->caster->b_slope) { + leftheight = P_GetZAt(*light->caster->b_slope, segleft.x, segleft.y); + rightheight = P_GetZAt(*light->caster->b_slope, segright.x, segright.y); - for (i = 0; i < numffloors; i++) - ffloor[i].f_frac += ffloor[i].f_step; + // Flag sector as having slopes + frontsector->hasslope = true; + } else + leftheight = rightheight = *light->caster->bottomheight; - for (i = 0; i < numbackffloors; i++) - { - ffloor[i].f_clip[rw_x] = ffloor[i].c_clip[rw_x] = (INT16)((ffloor[i].b_frac >> HEIGHTBITS) & 0xFFFF); - ffloor[i].b_frac += ffloor[i].b_step; - } + leftheight -= viewz; + rightheight -= viewz; - rw_scale += rw_scalestep; - topfrac += topstep; - bottomfrac += bottomstep; - } -} + leftheight >>= 4; + rightheight >>= 4; -// Macro for slope bullshit -#define SLOPEPARAMS(slope, end1, end2, normalheight) \ - if (slope) { \ - end1 = P_GetZAt(slope, segleft.x, segleft.y); \ - end2 = P_GetZAt(slope, segright.x, segright.y); \ - } else \ - end1 = end2 = normalheight; + rlight->botheight = (centeryfrac>>4) - FixedMul(leftheight, rw_scale); + rlight->botheightstep = (centeryfrac>>4) - FixedMul(rightheight, ds_p->scale2); + rlight->botheightstep = (rlight->botheightstep-rlight->botheight)/(range); + +#else + rlight->botheight = (centeryfrac >> 4) - FixedMul((*light->caster->bottomheight - viewz) >> 4, rw_scale); + rlight->botheightstep = -FixedMul (rw_scalestep, (*light->caster->bottomheight - viewz) >> 4); +#endif + } + + rlight->lightlevel = *light->lightlevel; + rlight->extra_colormap = *light->extra_colormap; + p++; + } + + dc_numlights = p; + } +} // -// R_CalculateSegDistance -// Calculate the distance from a seg. -// Uses precalculated seg length. +// R_MarkPlanes +// Creates visplanes. // -static void R_CalculateSegDistance(seg_t *seg, INT64 x2, INT64 y2, boolean longboi) +static void R_MarkPlanes(void) { -#ifdef SOFTWARE_USE_FLOATS - float v1x = FIXED_TO_FLOAT(seg->v1->x); - float v1y = FIXED_TO_FLOAT(seg->v1->y); - float v2x = FIXED_TO_FLOAT(seg->v2->x); - float v2y = FIXED_TO_FLOAT(seg->v2->y); - float dx, dy, vdx, vdy; - float distance = 0.0f; + INT32 i; - // The seg is vertical. - if (!seg->linedef->dy) - distance = fabsf(y2 - v1y); - // The seg is horizontal. - else if (!seg->linedef->dx) - distance = fabsf(x2 - v1x); - // Uses precalculated seg->flength - else if (longboi) + // get a new or use the same visplane + if (markceiling) { - dx = v2x-v1x; - dy = v2y-v1y; - vdx = x2-v1x; - vdy = y2-v1y; - distance = ((dy*vdx)-(dx*vdy))/(seg->flength); + if (ceilingplane) //SoM: 3/29/2000: Check for null ceiling planes + ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1); + else + markceiling = false; + + // Don't mark ceiling flat lines for polys unless this line has an upper texture, otherwise we get flat leakage pulling downward + // (If it DOES have an upper texture and we do this, the ceiling won't render at all) + if (curline->polyseg && !curline->sidedef->toptexture) + markceiling = false; } - // Linguica's fix converted to floating-point math - else + + // get a new or use the same visplane + if (markfloor) { - fixed_t x, y; - float a, c, ac; + if (floorplane) //SoM: 3/29/2000: Check for null planes + floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1); + else + markfloor = false; - v1x -= FIXED_TO_FLOAT(viewx); - v1y -= FIXED_TO_FLOAT(viewy); - v2x -= FIXED_TO_FLOAT(viewx); - v2y -= FIXED_TO_FLOAT(viewy); - dx = v2x - v1x; - dy = v2y - v1y; + // Don't mark floor flat lines for polys unless this line has a lower texture, otherwise we get flat leakage pulling upward + // (If it DOES have a lower texture and we do this, the floor won't render at all) + if (curline->polyseg && !curline->sidedef->bottomtexture) + markfloor = false; + } - a = (v1x*v2y) - (v1y*v2x); - c = (dx*dx) + (dy*dy); - ac = (a/c); + ds_p->numffloorplanes = 0; + if (numffloors) + { + if (!firstseg) + { + ds_p->numffloorplanes = numffloors; - x = FLOAT_TO_FIXED(ac*(-dy)); - y = FLOAT_TO_FIXED(ac*dx); + for (i = 0; i < numffloors; i++) + { + ds_p->ffloorplanes[i] = ffloor[i].plane = + R_CheckPlane(ffloor[i].plane, rw_x, rw_stopx - 1); + } - rw_distance = R_PointToDist(viewx + x, viewy + y); - return; - } + firstseg = ds_p; + } + else + { + for (i = 0; i < numffloors; i++) + R_ExpandPlane(ffloor[i].plane, rw_x, rw_stopx - 1); + } +#ifdef POLYOBJECTS_PLANES + // FIXME hack to fix planes disappearing when a seg goes behind the camera. This NEEDS to be changed to be done properly. -Red + if (curline->polyseg) + { + for (i = 0; i < numffloors; i++) + { + if (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg) + continue; + if (ffloor[i].plane->minx > rw_x) + ffloor[i].plane->minx = rw_x; - rw_distance = FLOAT_TO_FIXED(distance); -#else - (void)longboi; - if (!seg->linedef->dy) - rw_distance = (fixed_t)(llabs(y2 - seg->v1->y)); - else if (!seg->linedef->dx) - rw_distance = (fixed_t)(llabs(x2 - seg->v1->x)); - else - { - INT64 dx = (seg->v2->x)-(seg->v1->x); - INT64 dy = (seg->v2->y)-(seg->v1->y); - INT64 vdx = x2-(seg->v1->x); - INT64 vdy = y2-(seg->v1->y); - rw_distance = (fixed_t)(((dy*vdx)-(dx*vdy))/(seg->length)); - } + if (ffloor[i].plane->maxx < rw_stopx - 1) + ffloor[i].plane->maxx = rw_stopx - 1; + } + } #endif + } } // -// R_CalculateWallScale -// Calculate scale at both ends and step. +// R_RemoveOpeningLimits +// Code to remove limits on openings. // -static INT32 R_CalculateWallScale(INT32 start, INT32 stop) +static void R_RemoveOpeningLimits(INT32 start) { - INT32 range = 1; - - ds_p->scale1 = rw_scale = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[start]); - - if (stop > start) - { - ds_p->scale2 = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[stop]); - range = stop-start; - } - else + size_t pos = lastopening - openings; + size_t need = (rw_stopx - start)*4 + pos; + if (need > maxopenings) { - // UNUSED: try to fix the stretched line bug -#if 0 - if (rw_distance < FRACUNIT/2) - { - fixed_t tr_x,tr_y; - fixed_t gxt,gyt; - CONS_Debug(DBG_RENDER, "TRYING TO FIX THE STRETCHED ETC\n"); + drawseg_t *ds; //needed for fix from *cough* zdoom *cough* + INT16 *oldopenings = openings; + INT16 *oldlast = lastopening; - tr_x = curline->v1->x - viewx; - tr_y = curline->v1->y - viewy; + do + maxopenings = maxopenings ? maxopenings*2 : 16384; + while (need > maxopenings); + openings = Z_Realloc(openings, maxopenings * sizeof (*openings), PU_STATIC, NULL); + lastopening = openings + pos; - gxt = FixedMul(tr_x, viewcos); - gyt = -FixedMul(tr_y, viewsin); - ds_p->scale1 = FixedDiv(projection, gxt - gyt); + // borrowed fix from *cough* zdoom *cough* + // [RH] We also need to adjust the openings pointers that + // were already stored in drawsegs. + for (ds = drawsegs; ds < ds_p; ds++) + { +#define ADJUST(p) if (ds->p + ds->x1 >= oldopenings && ds->p + ds->x1 <= oldlast) ds->p = ds->p - oldopenings + openings; + ADJUST(maskedtexturecol); + ADJUST(sprtopclip); + ADJUST(sprbottomclip); + ADJUST(thicksidecol); +#undef ADJUST } -#endif - ds_p->scale2 = ds_p->scale1; } - - ds_p->scalestep = rw_scalestep = (ds_p->scale2 - rw_scale) / (range); - - return range; } // -// R_WorldTopAndBottom -// Calculate texture boundaries -// and decide if floor or ceiling marks are needed. +// R_StoreWallRange +// A wall segment will be drawn +// between start and stop pixels (inclusive). // -static void R_WorldTopAndBottom(INT32 start, INT32 stop) +void R_StoreWallRange(INT32 start, INT32 stop) { + fixed_t hyp; + fixed_t sineval; + angle_t distangle, offsetangle; + boolean longboi; +#ifndef ESLOPE + fixed_t vtop; +#endif + INT32 i; + INT32 range; + static size_t maxdrawsegs = 0; + #ifdef ESLOPE - // Figure out map coordinates of where start and end are mapping to on seg, so we can clip right for slope bullshit - if (frontsector->hasslope || (backsector && backsector->hasslope)) // Commenting this out for FOFslop. -Red - { - angle_t temp; + maskedtextureheight = NULL; + //initialize segleft and segright + memset(&segleft, 0x00, sizeof(segleft)); + memset(&segright, 0x00, sizeof(segright)); +#endif - // left - temp = xtoviewangle[start]+viewangle; + colfunc = colfuncs[BASEDRAWFUNC]; - { - // Both lines can be written in slope-intercept form, so figure out line intersection - float a1, b1, c1, a2, b2, c2, det; // 1 is the seg, 2 is the view angle vector... - ///TODO: convert to FPU + if (ds_p == drawsegs+maxdrawsegs) + { + size_t curpos = curdrawsegs - drawsegs; + size_t pos = ds_p - drawsegs; + size_t newmax = maxdrawsegs ? maxdrawsegs*2 : 128; + if (firstseg) + firstseg = (drawseg_t *)(firstseg - drawsegs); + drawsegs = Z_Realloc(drawsegs, newmax*sizeof (*drawsegs), PU_STATIC, NULL); + ds_p = drawsegs + pos; + maxdrawsegs = newmax; + curdrawsegs = drawsegs + curpos; + if (firstseg) + firstseg = drawsegs + (size_t)firstseg; + } - a1 = FIXED_TO_FLOAT(curline->v2->y-curline->v1->y); - b1 = FIXED_TO_FLOAT(curline->v1->x-curline->v2->x); - c1 = a1*FIXED_TO_FLOAT(curline->v1->x) + b1*FIXED_TO_FLOAT(curline->v1->y); + sidedef = curline->sidedef; + linedef = curline->linedef; - a2 = -FIXED_TO_FLOAT(FINESINE(temp>>ANGLETOFINESHIFT)); - b2 = FIXED_TO_FLOAT(FINECOSINE(temp>>ANGLETOFINESHIFT)); - c2 = a2*FIXED_TO_FLOAT(viewx) + b2*FIXED_TO_FLOAT(viewy); + // calculate rw_distance for scale calculation + rw_normalangle = curline->angle + ANGLE_90; + offsetangle = abs((INT32)(rw_normalangle-rw_angle1)); - det = a1*b2 - a2*b1; + if (offsetangle > ANGLE_90) + offsetangle = ANGLE_90; - ds_p->leftpos.x = segleft.x = FLOAT_TO_FIXED((b2*c1 - b1*c2)/det); - ds_p->leftpos.y = segleft.y = FLOAT_TO_FIXED((a1*c2 - a2*c1)/det); - } + distangle = ANGLE_90 - offsetangle; + sineval = FINESINE(distangle>>ANGLETOFINESHIFT); - // right - temp = xtoviewangle[stop]+viewangle; - - { - // Both lines can be written in slope-intercept form, so figure out line intersection - float a1, b1, c1, a2, b2, c2, det; // 1 is the seg, 2 is the view angle vector... - ///TODO: convert to FPU + hyp = R_PointToDist(curline->v1->x, curline->v1->y); + longboi = (hyp >= INT32_MAX); - a1 = FIXED_TO_FLOAT(curline->v2->y-curline->v1->y); - b1 = FIXED_TO_FLOAT(curline->v1->x-curline->v2->x); - c1 = a1*FIXED_TO_FLOAT(curline->v1->x) + b1*FIXED_TO_FLOAT(curline->v1->y); + // The seg is vertical. + if (curline->v1->y == curline->v2->y) + rw_distance = (fixed_t)(llabs(viewy - curline->v1->y)); + // The seg is horizontal. + else if (curline->v1->x == curline->v2->x) + rw_distance = (fixed_t)(llabs(viewx - curline->v1->x)); + // big room fix +#ifdef SOFTWARE_USE_FLOATS + else if ((curline->length >= 1024<<FRACBITS) || longboi) +#else + else if (longboi) +#endif + R_CalculateSegDistance(curline, viewx, viewy, longboi); + else + rw_distance = FixedMul(hyp, sineval); - a2 = -FIXED_TO_FLOAT(FINESINE(temp>>ANGLETOFINESHIFT)); - b2 = FIXED_TO_FLOAT(FINECOSINE(temp>>ANGLETOFINESHIFT)); - c2 = a2*FIXED_TO_FLOAT(viewx) + b2*FIXED_TO_FLOAT(viewy); + ds_p->x1 = rw_x = start; + ds_p->x2 = stop; + ds_p->curline = curline; + rw_stopx = stop+1; - det = a1*b2 - a2*b1; + //SoM: Code to remove limits on openings. + R_RemoveOpeningLimits(start); - ds_p->rightpos.x = segright.x = FLOAT_TO_FIXED((b2*c1 - b1*c2)/det); - ds_p->rightpos.y = segright.y = FLOAT_TO_FIXED((a1*c2 - a2*c1)/det); - } - } + // calculate scale at both ends and step + range = R_CalculateWallScale(start, stop); - SLOPEPARAMS(frontsector->c_slope, worldtop, worldtopslope, frontsector->ceilingheight) - SLOPEPARAMS(frontsector->f_slope, worldbottom, worldbottomslope, frontsector->floorheight) - // subtract viewz from these to turn them into - // positions relative to the camera's z position - worldtop -= viewz; - worldtopslope -= viewz; - worldbottom -= viewz; - worldbottomslope -= viewz; -#else - worldtop = frontsector->ceilingheight - viewz; - worldbottom = frontsector->floorheight - viewz; -#endif -} + // calculate texture boundaries + // and decide if floor / ceiling marks are needed + R_WorldTopAndBottom(start, stop); -// -// R_WorldSegTextured -// Calculate rw_offset. -// Only needed for textured lines. -// -static void R_WorldSegTextured(fixed_t hyp, boolean longboi) -{ - INT32 lightnum; - fixed_t sineval; - angle_t offsetangle = rw_normalangle-rw_angle1; + midtexture = toptexture = bottomtexture = maskedtexture = 0; + ds_p->maskedtexturecol = NULL; + ds_p->numthicksides = numthicksides = 0; + ds_p->thicksidecol = NULL; + ds_p->tsilheight = 0; - if (offsetangle > ANGLE_180) - offsetangle = -(signed)offsetangle; - if (offsetangle > ANGLE_90) - offsetangle = ANGLE_90; + numbackffloors = 0; - sineval = FINESINE(offsetangle>>ANGLETOFINESHIFT); - rw_offset = FixedMul(hyp, sineval); + for (i = 0; i < MAXFFLOORS; i++) + ds_p->thicksides[i] = NULL; - // big room fix - if (longboi) + if (numffloors) { - INT64 dx = (curline->v2->x)-(curline->v1->x); - INT64 dy = (curline->v2->y)-(curline->v1->y); - INT64 vdx = viewx-(curline->v1->x); - INT64 vdy = viewy-(curline->v1->y); - rw_offset = ((dx*vdx-dy*vdy))/(curline->length); - } + for (i = 0; i < numffloors; i++) + { +#ifdef POLYOBJECTS_PLANES + if (ffloor[i].polyobj && (!ds_p->curline->polyseg || ffloor[i].polyobj != ds_p->curline->polyseg)) + continue; +#endif - if (rw_normalangle-rw_angle1 < ANGLE_180) - rw_offset = -rw_offset; +#ifdef ESLOPE + if (ffloor[i].slope) { + ffloor[i].f_pos = P_GetZAt(ffloor[i].slope, segleft.x, segleft.y) - viewz; + ffloor[i].f_pos_slope = P_GetZAt(ffloor[i].slope, segright.x, segright.y) - viewz; + } else + ffloor[i].f_pos_slope = +#endif + ffloor[i].f_pos = ffloor[i].height - viewz; + } + } - /// don't use texture offset for splats - rw_offset2 = rw_offset + curline->offset; - rw_offset += sidedef->textureoffset + curline->offset; - rw_centerangle = ANGLE_90 + viewangle - rw_normalangle; +#ifdef ESLOPE + // Set up texture Y offset slides for sloped walls + rw_toptextureslide = rw_midtextureslide = rw_bottomtextureslide = 0; + ceilingfrontslide = floorfrontslide = ceilingbackslide = floorbackslide = 0; - // calculate light table - // use different light tables - // for horizontal / vertical / diagonal - // OPTIMIZE: get rid of LIGHTSEGSHIFT globally - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); + { + angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y); - if (curline->v1->y == curline->v2->y) - lightnum--; - else if (curline->v1->x == curline->v2->x) - lightnum++; + if (frontsector->f_slope) + floorfrontslide = FixedMul(frontsector->f_slope->zdelta, FINECOSINE((lineangle-frontsector->f_slope->xydirection)>>ANGLETOFINESHIFT)); - if (lightnum < 0) - walllights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - walllights = scalelight[LIGHTLEVELS - 1]; - else - walllights = scalelight[lightnum]; -} + if (frontsector->c_slope) + ceilingfrontslide = FixedMul(frontsector->c_slope->zdelta, FINECOSINE((lineangle-frontsector->c_slope->xydirection)>>ANGLETOFINESHIFT)); -// -// R_CheckMaskedTextures -// Midtexture stuff, presumably. -// -static void R_CheckMaskedTextures(void) -{ - INT32 i = 0; - // allocate space for masked texture tables - if (frontsector && backsector && frontsector->tag != backsector->tag && (backsector->ffloors || frontsector->ffloors)) - { - ffloor_t *rover; - ffloor_t *r2; - fixed_t lowcut, highcut; -#ifdef ESLOPE - fixed_t lowcutslope, highcutslope; + if (backsector && backsector->f_slope) + floorbackslide = FixedMul(backsector->f_slope->zdelta, FINECOSINE((lineangle-backsector->f_slope->xydirection)>>ANGLETOFINESHIFT)); - // Used for height comparisons and etc across FOFs and slopes - fixed_t high1, highslope1, low1, lowslope1, high2, highslope2, low2, lowslope2; + if (backsector && backsector->c_slope) + ceilingbackslide = FixedMul(backsector->c_slope->zdelta, FINECOSINE((lineangle-backsector->c_slope->xydirection)>>ANGLETOFINESHIFT)); + } #endif - //markceiling = markfloor = true; - maskedtexture = true; + // Check for textures + R_StoreWallSilhouette(); + R_CheckWallTextures(); + if (backsector) + R_CheckMaskedTextures(); - ds_p->thicksidecol = maskedtexturecol = lastopening - rw_x; - lastopening += rw_stopx - rw_x; +#undef SLOPEPARAMS - lowcut = max(worldbottom, worldlow) + viewz; - highcut = min(worldtop, worldhigh) + viewz; + // Calculate rw_offset (only needed for textured lines) + segtextured = midtexture || toptexture || bottomtexture || maskedtexture || (numthicksides > 0); + if (segtextured) + R_WorldSegTextured(hyp, longboi); + + // if a floor / ceiling plane is on the wrong side + // of the view plane, it is definitely invisible + // and doesn't need to be marked. + if (frontsector->heightsec == -1) + { + if (frontsector->floorpic != skyflatnum + && ( #ifdef ESLOPE - lowcutslope = max(worldbottomslope, worldlowslope) + viewz; - highcutslope = min(worldtopslope, worldhighslope) + viewz; + frontsector->f_slope ? P_GetZAt(frontsector->f_slope, viewx, viewy) : #endif - - if (frontsector->ffloors && backsector->ffloors) + frontsector->floorheight) >= viewz) { - i = 0; - for (rover = backsector->ffloors; rover && i < MAXFFLOORS; rover = rover->next) - { - if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS)) - continue; - if (rover->flags & FF_INVERTSIDES) - continue; - - if (rover->norender == leveltime) - continue; + // above view plane + markfloor = false; + } + if (frontsector->ceilingpic != skyflatnum + && ( #ifdef ESLOPE - SLOPEPARAMS(*rover->t_slope, high1, highslope1, *rover->topheight) - SLOPEPARAMS(*rover->b_slope, low1, lowslope1, *rover->bottomheight) - - if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope)) - continue; -#else - if (*rover->topheight < lowcut || *rover->bottomheight > highcut) - continue; + frontsector->c_slope ? P_GetZAt(frontsector->c_slope, viewx, viewy) : #endif + frontsector->ceilingheight) <= viewz) + { + // below view plane + markceiling = false; + } + } - for (r2 = frontsector->ffloors; r2; r2 = r2->next) - { - if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES)) - continue; + // Calculate incremental stepping values for texture edges + R_WorldStep(range); - if (r2->norender == leveltime) - continue; + // Create light lists + R_WorldLightLists(range); - if (rover->flags & FF_EXTRA) - { - if (!(r2->flags & FF_CUTEXTRA)) - continue; + // Step FOFs + if (numffloors) + R_WorldFFloorStep(range); - if (r2->flags & FF_EXTRA && (r2->flags & (FF_TRANSLUCENT|FF_FOG)) != (rover->flags & (FF_TRANSLUCENT|FF_FOG))) - continue; - } - else - { - if (!(r2->flags & FF_CUTSOLIDS)) - continue; - } + // Step world back + if (backsector) + R_WorldBackStep(range); -#ifdef ESLOPE - SLOPEPARAMS(*r2->t_slope, high2, highslope2, *r2->topheight) - SLOPEPARAMS(*r2->b_slope, low2, lowslope2, *r2->bottomheight) + // Mark floor and or ceiling visplanes + R_MarkPlanes(); - if ((high2 < lowcut || highslope2 < lowcutslope) || (low2 > highcut || lowslope2 > highcutslope)) - continue; - if ((high1 > high2 || highslope1 > highslope2) || (low1 < low2 || lowslope1 < lowslope2)) - continue; -#else - if (*r2->topheight < lowcut || *r2->bottomheight > highcut) - continue; - if (*rover->topheight > *r2->topheight || *rover->bottomheight < *r2->bottomheight) - continue; +#ifdef WALLSPLATS + if (linedef->splats && cv_splats.value) + { + // Isn't a bit wasteful to copy the ENTIRE array for every drawseg? + M_Memcpy(last_ceilingclip + ds_p->x1, ceilingclip + ds_p->x1, + sizeof (INT16) * (ds_p->x2 - ds_p->x1 + 1)); + M_Memcpy(last_floorclip + ds_p->x1, floorclip + ds_p->x1, + sizeof (INT16) * (ds_p->x2 - ds_p->x1 + 1)); + R_RenderSegLoop(); + R_DrawWallSplats(); + } + else #endif + R_RenderSegLoop(); + colfunc = colfuncs[BASEDRAWFUNC]; - break; - } - if (r2) - continue; + if (portalline) // if curline is a portal, set portalrender for drawseg + ds_p->portalpass = portalrender+1; + else + ds_p->portalpass = 0; - ds_p->thicksides[i] = rover; - i++; - } + // save sprite clipping info + if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip) + { + M_Memcpy(lastopening, ceilingclip+start, 2*(rw_stopx - start)); + ds_p->sprtopclip = lastopening - start; + lastopening += rw_stopx - start; + } - for (rover = frontsector->ffloors; rover && i < MAXFFLOORS; rover = rover->next) - { - if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS)) - continue; - if (!(rover->flags & FF_ALLSIDES)) - continue; + if (((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && !ds_p->sprbottomclip) + { + M_Memcpy(lastopening, floorclip + start, 2*(rw_stopx-start)); + ds_p->sprbottomclip = lastopening - start; + lastopening += rw_stopx - start; + } - if (rover->norender == leveltime) - continue; + if (maskedtexture && !(ds_p->silhouette & SIL_TOP)) + { + ds_p->silhouette |= SIL_TOP; + ds_p->tsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MIN: INT32_MAX; + } + if (maskedtexture && !(ds_p->silhouette & SIL_BOTTOM)) + { + ds_p->silhouette |= SIL_BOTTOM; + ds_p->bsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MAX: INT32_MIN; + } -#ifdef ESLOPE - SLOPEPARAMS(*rover->t_slope, high1, highslope1, *rover->topheight) - SLOPEPARAMS(*rover->b_slope, low1, lowslope1, *rover->bottomheight) + ds_p++; +} - if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope)) - continue; -#else - if (*rover->topheight < lowcut || *rover->bottomheight > highcut) - continue; -#endif +// ========================================================================== +// R_Splats Wall Splats Drawer +// ========================================================================== - for (r2 = backsector->ffloors; r2; r2 = r2->next) - { - if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES)) - continue; +#ifdef WALLSPLATS +static INT16 last_ceilingclip[MAXVIDWIDTH]; +static INT16 last_floorclip[MAXVIDWIDTH]; - if (r2->norender == leveltime) - continue; +static void R_DrawSplatColumn(column_t *column) +{ + INT32 topscreen, bottomscreen; + fixed_t basetexturemid; + INT32 topdelta, prevdelta = -1; - if (rover->flags & FF_EXTRA) - { - if (!(r2->flags & FF_CUTEXTRA)) - continue; + basetexturemid = dc_texturemid; - if (r2->flags & FF_EXTRA && (r2->flags & (FF_TRANSLUCENT|FF_FOG)) != (rover->flags & (FF_TRANSLUCENT|FF_FOG))) - continue; - } - else - { - if (!(r2->flags & FF_CUTSOLIDS)) - continue; - } + for (; column->topdelta != 0xff ;) + { + // calculate unclipped screen coordinates for post + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + topscreen = sprtopscreen + spryscale*topdelta; + bottomscreen = topscreen + spryscale*column->length; -#ifdef ESLOPE - SLOPEPARAMS(*r2->t_slope, high2, highslope2, *r2->topheight) - SLOPEPARAMS(*r2->b_slope, low2, lowslope2, *r2->bottomheight) - if ((high2 < lowcut || highslope2 < lowcutslope) || (low2 > highcut || lowslope2 > highcutslope)) - continue; - if ((high1 > high2 || highslope1 > highslope2) || (low1 < low2 || lowslope1 < lowslope2)) - continue; -#else - if (*r2->topheight < lowcut || *r2->bottomheight > highcut) - continue; - if (*rover->topheight > *r2->topheight || *rover->bottomheight < *r2->bottomheight) - continue; -#endif + dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; + dc_yh = (bottomscreen-1)>>FRACBITS; - break; - } - if (r2) - continue; + if (dc_yh >= last_floorclip[dc_x]) + dc_yh = last_floorclip[dc_x] - 1; + if (dc_yl <= last_ceilingclip[dc_x]) + dc_yl = last_ceilingclip[dc_x] + 1; + if (dc_yl <= dc_yh && dl_yh < vid.height && yh > 0) + { + dc_source = (UINT8 *)column + 3; + dc_texturemid = basetexturemid - (topdelta<<FRACBITS); - ds_p->thicksides[i] = rover; - i++; - } + // Drawn by R_DrawColumn. + colfunc(); } - else if (backsector->ffloors) - { - for (rover = backsector->ffloors, i = 0; rover && i < MAXFFLOORS; rover = rover->next) - { - if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS) || rover->flags & FF_INVERTSIDES) - continue; - if (rover->norender == leveltime) - continue; + column = (column_t *)((UINT8 *)column + column->length + 4); + } -#ifdef ESLOPE - // Oy vey. - if (( (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldbottom+viewz - && (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldbottomslope+viewz) - ||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldtop+viewz - && (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldtopslope+viewz)) - continue; -#else - if (*rover->topheight <= frontsector->floorheight || *rover->bottomheight >= frontsector->ceilingheight) - continue; -#endif + dc_texturemid = basetexturemid; +} - ds_p->thicksides[i] = rover; - i++; - } - } - else if (frontsector->ffloors) - { - for (rover = frontsector->ffloors, i = 0; rover && i < MAXFFLOORS; rover = rover->next) - { - if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS) || !(rover->flags & FF_ALLSIDES)) - continue; - if (rover->norender == leveltime) - continue; -#ifdef ESLOPE - // Oy vey. - if (( (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldbottom+viewz - && (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldbottomslope+viewz) - ||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldtop+viewz - && (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldtopslope+viewz)) - continue; +static void R_DrawWallSplats(void) +{ + wallsplat_t *splat; + seg_t *seg; + angle_t angle, angle1, angle2; + INT32 x1, x2; + size_t pindex; + column_t *col; + patch_t *patch; + fixed_t texturecolumn; - if (( (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldlow+viewz - && (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldlowslope+viewz) - ||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldhigh+viewz - && (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldhighslope+viewz)) - continue; -#else - if (*rover->topheight <= frontsector->floorheight || *rover->bottomheight >= frontsector->ceilingheight) - continue; - if (*rover->topheight <= backsector->floorheight || *rover->bottomheight >= backsector->ceilingheight) - continue; -#endif + splat = (wallsplat_t *)linedef->splats; - ds_p->thicksides[i] = rover; - i++; - } - } + I_Assert(splat != NULL); - ds_p->numthicksides = numthicksides = i; - } + seg = ds_p->curline; - if (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) + // draw all splats from the line that touches the range of the seg + for (; splat; splat = splat->next) { - // masked midtexture - if (!ds_p->thicksidecol) - { - ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x; - lastopening += rw_stopx - rw_x; - } - else - ds_p->maskedtexturecol = ds_p->thicksidecol; + angle1 = R_PointToAngle(splat->v1.x, splat->v1.y); + angle2 = R_PointToAngle(splat->v2.x, splat->v2.y); + angle1 = (angle1 - viewangle + ANGLE_90)>>ANGLETOFINESHIFT; + angle2 = (angle2 - viewangle + ANGLE_90)>>ANGLETOFINESHIFT; + // out of the viewangletox lut + /// \todo clip it to the screen + if (angle1 > FINEANGLES/2 || angle2 > FINEANGLES/2) + continue; + x1 = viewangletox[angle1]; + x2 = viewangletox[angle2]; -#ifdef ESLOPE - maskedtextureheight = ds_p->maskedtextureheight; // note to red, this == &(ds_p->maskedtextureheight[0]) + if (x1 >= x2) + continue; // does not cross a pixel -#ifdef POLYOBJECTS - if (curline->polyseg) { // use REAL front and back floors please, so midtexture rendering isn't mucked up - rw_midtextureslide = rw_midtexturebackslide = 0; - if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) - rw_midtexturemid = rw_midtextureback = max(curline->frontsector->floorheight, curline->backsector->floorheight) - viewz; - else - rw_midtexturemid = rw_midtextureback = min(curline->frontsector->ceilingheight, curline->backsector->ceilingheight) - viewz; - } else -#endif - // Set midtexture starting height - if (linedef->flags & ML_EFFECT2) { // Ignore slopes when texturing - rw_midtextureslide = rw_midtexturebackslide = 0; - if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) - rw_midtexturemid = rw_midtextureback = max(frontsector->floorheight, backsector->floorheight) - viewz; - else - rw_midtexturemid = rw_midtextureback = min(frontsector->ceilingheight, backsector->ceilingheight) - viewz; + // splat is not in this seg range + if (x2 < ds_p->x1 || x1 > ds_p->x2) + continue; - } else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) { - rw_midtexturemid = worldbottom; - rw_midtextureslide = floorfrontslide; - rw_midtextureback = worldlow; - rw_midtexturebackslide = floorbackslide; - } else { - rw_midtexturemid = worldtop; - rw_midtextureslide = ceilingfrontslide; - rw_midtextureback = worldhigh; - rw_midtexturebackslide = ceilingbackslide; - } - rw_midtexturemid += sidedef->rowoffset; - rw_midtextureback += sidedef->rowoffset; -#endif + if (x1 < ds_p->x1) + x1 = ds_p->x1; + if (x2 > ds_p->x2) + x2 = ds_p->x2; + if (x2 <= x1) + continue; - maskedtexture = true; - } -} + // calculate incremental stepping values for texture edges + rw_scalestep = ds_p->scalestep; + spryscale = ds_p->scale1 + (x1 - ds_p->x1)*rw_scalestep; + mfloorclip = floorclip; + mceilingclip = ceilingclip; -// -// R_CheckWallTextures -// Self-explanatory, I hope?! -// -static void R_CheckWallTextures(void) -{ - if (!backsector) - { - fixed_t texheight; - // single sided line - midtexture = R_GetTextureNum(sidedef->midtexture); - texheight = textureheight[midtexture]; - // a single sided line is terminal, so it must mark ends - markfloor = markceiling = true; -#ifdef ESLOPE - if (linedef->flags & ML_EFFECT2) { - if (linedef->flags & ML_DONTPEGBOTTOM) - rw_midtexturemid = frontsector->floorheight + texheight - viewz; - else - rw_midtexturemid = frontsector->ceilingheight - viewz; - } - else -#endif - if (linedef->flags & ML_DONTPEGBOTTOM) - { -#ifdef ESLOPE - rw_midtexturemid = worldbottom + texheight; - rw_midtextureslide = floorfrontslide; -#else - vtop = frontsector->floorheight + texheight; - // bottom of texture at bottom - rw_midtexturemid = vtop - viewz; -#endif - } - else - { - // top of texture at top - rw_midtexturemid = worldtop; -#ifdef ESLOPE - rw_midtextureslide = ceilingfrontslide; -#endif - } - rw_midtexturemid += sidedef->rowoffset; - } - else - { - // check TOP TEXTURE - if (!bothceilingssky // never draw the top texture if on - && (worldhigh < worldtop -#ifdef ESLOPE - || worldhighslope < worldtopslope -#endif - )) - { - fixed_t texheight; - // top texture - if ((linedef->flags & (ML_DONTPEGTOP) && (linedef->flags & ML_DONTPEGBOTTOM)) - && linedef->sidenum[1] != 0xffff) - { - // Special case... use offsets from 2nd side but only if it has a texture. - side_t *def = &sides[linedef->sidenum[1]]; - toptexture = R_GetTextureNum(def->toptexture); + patch = W_CachePatchNum(splat->patch, PU_CACHE); - if (!toptexture) //Second side has no texture, use the first side's instead. - toptexture = R_GetTextureNum(sidedef->toptexture); - texheight = textureheight[toptexture]; - } - else - { - toptexture = R_GetTextureNum(sidedef->toptexture); - texheight = textureheight[toptexture]; - } -#ifdef ESLOPE - if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked - if (linedef->flags & ML_DONTPEGTOP) - rw_toptexturemid = frontsector->ceilingheight - viewz; + dc_texturemid = splat->top + (SHORT(patch->height)<<(FRACBITS-1)) - viewz; + if (splat->yoffset) + dc_texturemid += *splat->yoffset; + + sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); + + // set drawing mode + switch (splat->flags & SPLATDRAWMODE_MASK) + { + case SPLATDRAWMODE_OPAQUE: + colfunc = colfuncs[BASEDRAWFUNC]; + break; + case SPLATDRAWMODE_TRANS: + if (!cv_translucency.value) + colfunc = colfuncs[BASEDRAWFUNC]; else - rw_toptexturemid = backsector->ceilingheight - viewz; - } else -#endif - if (linedef->flags & ML_DONTPEGTOP) - { - // top of texture at top - rw_toptexturemid = worldtop; -#ifdef ESLOPE - rw_toptextureslide = ceilingfrontslide; -#endif - } - else - { -#ifdef ESLOPE - rw_toptexturemid = worldhigh + texheight; - rw_toptextureslide = ceilingbackslide; -#else - vtop = backsector->ceilingheight + texheight; - // bottom of texture - rw_toptexturemid = vtop - viewz; -#endif - } + { + dc_transmap = transtables + ((tr_trans50 - 1)<<FF_TRANSSHIFT); + colfunc = colfuncs[COLDRAWFUNC_FUZZY]; + } + + break; + case SPLATDRAWMODE_SHADE: + colfunc = colfuncs[COLDRAWFUNC_SHADE]; + break; } - // check BOTTOM TEXTURE - if (!bothfloorssky // never draw the bottom texture if on - && (worldlow > worldbottom -#ifdef ESLOPE - || worldlowslope > worldbottomslope -#endif - )) //seulement si VISIBLE!!! + + dc_texheight = 0; + + // draw the columns + for (dc_x = x1; dc_x <= x2; dc_x++, spryscale += rw_scalestep) { - // bottom texture - bottomtexture = R_GetTextureNum(sidedef->bottomtexture); + pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; + if (pindex >= MAXLIGHTSCALE) + pindex = MAXLIGHTSCALE - 1; + dc_colormap = walllights[pindex]; -#ifdef ESLOPE - if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked - if (linedef->flags & ML_DONTPEGBOTTOM) - rw_bottomtexturemid = frontsector->floorheight - viewz; - else - rw_bottomtexturemid = backsector->floorheight - viewz; - } else -#endif - if (linedef->flags & ML_DONTPEGBOTTOM) - { - // bottom of texture at bottom - // top of texture at top - rw_bottomtexturemid = worldbottom; -#ifdef ESLOPE - rw_bottomtextureslide = floorfrontslide; -#endif - } - else { // top of texture at top - rw_bottomtexturemid = worldlow; -#ifdef ESLOPE - rw_bottomtextureslide = floorbackslide; -#endif - } + if (frontsector->extra_colormap) + dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); + + sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); + dc_iscale = 0xffffffffu / (unsigned)spryscale; + + // find column of patch, from perspective + angle = (rw_centerangle + xtoviewangle[dc_x])>>ANGLETOFINESHIFT; + texturecolumn = rw_offset2 - splat->offset + - FixedMul(FINETANGENT(angle), rw_distance); + + // FIXME! + texturecolumn >>= FRACBITS; + if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) + continue; + + // draw the texture + col = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn])); + R_DrawSplatColumn(col); } + } // next splat - rw_toptexturemid += sidedef->rowoffset; - rw_bottomtexturemid += sidedef->rowoffset; - } + colfunc = colfuncs[BASEDRAWFUNC]; } -// -// R_StoreWallSilhouette -// Sets the silhouette for the current seg. -// Also checks if any floors or ceilings have to be marked. -// -static void R_StoreWallSilhouette(void) +#endif //WALLSPLATS + +// ========================================================================== +// R_RenderMaskedSegRange +// ========================================================================== + +// If we have a multi-patch texture on a 2sided wall (rare) then we draw +// it using R_DrawColumn, else we draw it using R_DrawMaskedColumn, this +// way we don't have to store extra post_t info with each column for +// multi-patch textures. They are not normally needed as multi-patch +// textures don't have holes in it. At least not for now. +static INT32 column2s_length; // column->length : for multi-patch on 2sided wall = texture->height + +static void R_Render2sidedMultiPatchColumn(column_t *column) { - if (!backsector) + INT32 topscreen, bottomscreen; + + topscreen = sprtopscreen; // + spryscale*column->topdelta; topdelta is 0 for the wall + bottomscreen = topscreen + spryscale * column2s_length; + + dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS; + dc_yh = (bottomscreen-1)>>FRACBITS; + + if (windowtop != INT32_MAX && windowbottom != INT32_MAX) { - ds_p->silhouette = SIL_BOTH; - ds_p->sprtopclip = screenheightarray; - ds_p->sprbottomclip = negonearray; - ds_p->bsilheight = INT32_MAX; - ds_p->tsilheight = INT32_MIN; + dc_yl = ((windowtop + FRACUNIT)>>FRACBITS); + dc_yh = (windowbottom - 1)>>FRACBITS; } - else - { - // two sided line - bothceilingssky = false; // turned on if both back and front ceilings are sky - bothfloorssky = false; // likewise, but for floors -#ifdef ESLOPE - SLOPEPARAMS(backsector->c_slope, worldhigh, worldhighslope, backsector->ceilingheight) - SLOPEPARAMS(backsector->f_slope, worldlow, worldlowslope, backsector->floorheight) - worldhigh -= viewz; - worldhighslope -= viewz; - worldlow -= viewz; - worldlowslope -= viewz; -#else - worldhigh = backsector->ceilingheight - viewz; - worldlow = backsector->floorheight - viewz; -#endif + if (dc_yh >= mfloorclip[dc_x]) + dc_yh = mfloorclip[dc_x] - 1; + if (dc_yl <= mceilingclip[dc_x]) + dc_yl = mceilingclip[dc_x] + 1; - // hack to allow height changes in outdoor areas - // This is what gets rid of the upper textures if there should be sky - if (frontsector->ceilingpic == skyflatnum - && backsector->ceilingpic == skyflatnum) - { - bothceilingssky = true; - } + if (dc_yl >= vid.height || dc_yh < 0) + return; - // likewise, but for floors and upper textures - if (frontsector->floorpic == skyflatnum - && backsector->floorpic == skyflatnum) - { - bothfloorssky = true; - } + if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0) + { + dc_source = (UINT8 *)column + 3; - ds_p->sprtopclip = ds_p->sprbottomclip = NULL; - ds_p->silhouette = 0; + if (colfunc == colfuncs[BASEDRAWFUNC]) + (colfuncs[COLDRAWFUNC_TWOSMULTIPATCH])(); + else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) + (colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS])(); + else + colfunc(); + } +} - if (!bothfloorssky) - { - if ( -#ifdef ESLOPE - worldbottomslope > worldlowslope || -#endif - worldbottom > worldlow) - { - ds_p->silhouette = SIL_BOTTOM; -#ifdef ESLOPE - if ((backsector->f_slope ? P_GetZAt(backsector->f_slope, viewx, viewy) : backsector->floorheight) > viewz) - ds_p->bsilheight = INT32_MAX; - else - ds_p->bsilheight = (frontsector->f_slope ? INT32_MAX : frontsector->floorheight); -#else - ds_p->bsilheight = frontsector->floorheight; -#endif - } -#ifdef ESLOPE - else if ((backsector->f_slope ? P_GetZAt(backsector->f_slope, viewx, viewy) : backsector->floorheight) > viewz) -#else - else if (backsector->floorheight > viewz) -#endif - { - ds_p->silhouette = SIL_BOTTOM; - ds_p->bsilheight = INT32_MAX; - // ds_p->sprbottomclip = negonearray; - } - } +// quick wrapper for R_DrawFlippedMaskedColumn so it can be set as a colfunc_2s value +// uses column2s_length for texture->height as above +static void R_DrawFlippedMaskedSegColumn(column_t *column) +{ + R_DrawFlippedMaskedColumn(column, column2s_length); +} - if (!bothceilingssky) - { - if ( -#ifdef ESLOPE - worldtopslope < worldhighslope || -#endif - worldtop < worldhigh) - { - ds_p->silhouette |= SIL_TOP; -#ifdef ESLOPE - if ((backsector->c_slope ? P_GetZAt(backsector->c_slope, viewx, viewy) : backsector->ceilingheight) < viewz) - ds_p->tsilheight = INT32_MIN; - else - ds_p->tsilheight = (frontsector->c_slope ? INT32_MIN : frontsector->ceilingheight); -#else - ds_p->tsilheight = frontsector->ceilingheight; -#endif - } +void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) +{ + size_t pindex; + column_t *col; + INT32 lightnum, texnum, i; + fixed_t height, realbot; + lightlist_t *light; + r_lightlist_t *rlight; + void (*colfunc_2s)(column_t *); + line_t *ldef; + sector_t *front, *back; + INT32 times, repeats; + INT64 overflow_test; #ifdef ESLOPE - else if ((backsector->c_slope ? P_GetZAt(backsector->c_slope, viewx, viewy) : backsector->ceilingheight) < viewz) -#else - else if (backsector->ceilingheight < viewz) + INT32 range; #endif - { - ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = INT32_MIN; - // ds_p->sprtopclip = screenheightarray; - } - } - if (!bothceilingssky && !bothfloorssky) - { -#ifdef ESLOPE - if (worldhigh <= worldbottom && worldhighslope <= worldbottomslope) -#else - if (worldhigh <= worldbottom) -#endif - { - ds_p->sprbottomclip = negonearray; - ds_p->bsilheight = INT32_MAX; - ds_p->silhouette |= SIL_BOTTOM; - } + // Calculate light table. + // Use different light tables + // for horizontal / vertical / diagonal. Diagonal? + // OPTIMIZE: get rid of LIGHTSEGSHIFT globally + curline = ds->curline; + frontsector = curline->frontsector; + backsector = curline->backsector; + texnum = R_GetTextureNum(curline->sidedef->midtexture); + windowbottom = windowtop = sprbotscreen = INT32_MAX; + + // hack translucent linedef types (900-909 for transtables 1-9) + ldef = curline->linedef; + switch (ldef->special) + { + case 900: + case 901: + case 902: + case 903: + case 904: + case 905: + case 906: + case 907: + case 908: + dc_transmap = transtables + ((ldef->special-900)<<FF_TRANSSHIFT); + colfunc = colfuncs[COLDRAWFUNC_FUZZY]; + break; + case 909: + colfunc = colfuncs[COLDRAWFUNC_FOG]; + windowtop = frontsector->ceilingheight; + windowbottom = frontsector->floorheight; + break; + default: + colfunc = colfuncs[BASEDRAWFUNC]; + break; + } + + if (curline->polyseg && curline->polyseg->translucency > 0) + { + if (curline->polyseg->translucency >= NUMTRANSMAPS) + return; + + dc_transmap = transtables + ((curline->polyseg->translucency-1)<<FF_TRANSSHIFT); + colfunc = colfuncs[COLDRAWFUNC_FUZZY]; + } #ifdef ESLOPE - if (worldlow >= worldtop && worldlowslope >= worldtopslope) -#else - if (worldlow >= worldtop) + range = max(ds->x2-ds->x1, 1); #endif - { - ds_p->sprtopclip = screenheightarray; - ds_p->tsilheight = INT32_MIN; - ds_p->silhouette |= SIL_TOP; - } + rw_scalestep = ds->scalestep; + spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; + + // Texture must be cached before setting colfunc_2s, + // otherwise texture[texnum]->holes may be false when it shouldn't be + R_CheckTextureCache(texnum); + // handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures + // are not stored per-column with post info in SRB2 + if (textures[texnum]->holes) + { + if (textures[texnum]->flip & 2) // vertically flipped? + { + colfunc_2s = R_DrawFlippedMaskedSegColumn; + column2s_length = textures[texnum]->height; + } + else + colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture + } + else + { + colfunc_2s = R_Render2sidedMultiPatchColumn; // render multipatch with no holes (no post_t info) + column2s_length = textures[texnum]->height; + } + + // Setup lighting based on the presence/lack-of 3D floors. + dc_numlights = 0; + if (frontsector->numlights) + { + dc_numlights = frontsector->numlights; + if (dc_numlights >= dc_maxlights) + { + dc_maxlights = dc_numlights; + dc_lightlist = Z_Realloc(dc_lightlist, sizeof (*dc_lightlist) * dc_maxlights, PU_STATIC, NULL); } - //SoM: 3/25/2000: This code fixes an automap bug that didn't check - // frontsector->ceiling and backsector->floor to see if a door was closed. - // Without the following code, sprites get displayed behind closed doors. - if (!bothceilingssky && !bothfloorssky) + for (i = 0; i < dc_numlights; i++) { #ifdef ESLOPE - if (doorclosed || (worldhigh <= worldbottom && worldhighslope <= worldbottomslope)) -#else - if (doorclosed || backsector->ceilingheight <= frontsector->floorheight) + fixed_t leftheight, rightheight; #endif - { - ds_p->sprbottomclip = negonearray; - ds_p->bsilheight = INT32_MAX; - ds_p->silhouette |= SIL_BOTTOM; - } + light = &frontsector->lightlist[i]; + rlight = &dc_lightlist[i]; #ifdef ESLOPE - if (doorclosed || (worldlow >= worldtop && worldlowslope >= worldtopslope)) + if (light->slope) { + leftheight = P_GetZAt(light->slope, ds->leftpos.x, ds->leftpos.y); + rightheight = P_GetZAt(light->slope, ds->rightpos.x, ds->rightpos.y); + } else + leftheight = rightheight = light->height; + + leftheight -= viewz; + rightheight -= viewz; + + rlight->height = (centeryfrac) - FixedMul(leftheight, ds->scale1); + rlight->heightstep = (centeryfrac) - FixedMul(rightheight, ds->scale2); + rlight->heightstep = (rlight->heightstep-rlight->height)/(range); + //if (x1 > ds->x1) + //rlight->height -= (x1 - ds->x1)*rlight->heightstep; #else - if (doorclosed || backsector->floorheight >= frontsector->ceilingheight) + rlight->height = (centeryfrac) - FixedMul((light->height - viewz), spryscale); + rlight->heightstep = -FixedMul(rw_scalestep, (light->height - viewz)); #endif - { // killough 1/17/98, 2/8/98 - ds_p->sprtopclip = screenheightarray; - ds_p->tsilheight = INT32_MIN; - ds_p->silhouette |= SIL_TOP; - } - } + rlight->startheight = rlight->height; // keep starting value here to reset for each repeat + rlight->lightlevel = *light->lightlevel; + rlight->extra_colormap = *light->extra_colormap; + rlight->flags = light->flags; - if (bothfloorssky) - { - // see double ceiling skies comment - // this is the same but for upside down thok barriers where the floor is sky and the ceiling is normal - markfloor = false; + if (rlight->flags & FF_FOG || (rlight->extra_colormap && rlight->extra_colormap->fog)) + lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); + else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) + lightnum = LIGHTLEVELS - 1; + else + lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); + + if (rlight->extra_colormap && rlight->extra_colormap->fog) + ; + else if (curline->v1->y == curline->v2->y) + lightnum--; + else if (curline->v1->x == curline->v2->x) + lightnum++; + + rlight->lightnum = lightnum; } - else if (worldlow != worldbottom -#ifdef ESLOPE - || worldlowslope != worldbottomslope - || backsector->f_slope != frontsector->f_slope -#endif - || backsector->floorpic != frontsector->floorpic - || backsector->lightlevel != frontsector->lightlevel - //SoM: 3/22/2000: Check floor x and y offsets. - || backsector->floor_xoffs != frontsector->floor_xoffs - || backsector->floor_yoffs != frontsector->floor_yoffs - || backsector->floorpic_angle != frontsector->floorpic_angle - //SoM: 3/22/2000: Prevents bleeding. - || (frontsector->heightsec != -1 && frontsector->floorpic != skyflatnum) - || backsector->floorlightsec != frontsector->floorlightsec - //SoM: 4/3/2000: Check for colormaps - || frontsector->extra_colormap != backsector->extra_colormap - || (frontsector->ffloors != backsector->ffloors && frontsector->tag != backsector->tag)) + } + else + { + if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) { - markfloor = true; + if (frontsector->extra_colormap && frontsector->extra_colormap->fog) + lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); + else + lightnum = LIGHTLEVELS - 1; } else - { - // same plane on both sides - markfloor = false; - } + lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); - if (bothceilingssky) + if (colfunc == colfuncs[COLDRAWFUNC_FOG] + || (frontsector->extra_colormap && frontsector->extra_colormap->fog)) + ; + else if (curline->v1->y == curline->v2->y) + lightnum--; + else if (curline->v1->x == curline->v2->x) + lightnum++; + + if (lightnum < 0) + walllights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + walllights = scalelight[LIGHTLEVELS - 1]; + else + walllights = scalelight[lightnum]; + } + + maskedtexturecol = ds->maskedtexturecol; + + mfloorclip = ds->sprbottomclip; + mceilingclip = ds->sprtopclip; + + if (frontsector->heightsec != -1) + front = §ors[frontsector->heightsec]; + else + front = frontsector; + + if (backsector->heightsec != -1) + back = §ors[backsector->heightsec]; + else + back = backsector; + + if (ds->curline->sidedef->repeatcnt) + repeats = 1 + ds->curline->sidedef->repeatcnt; + else if (ldef->flags & ML_EFFECT5) + { + fixed_t high, low; + + if (front->ceilingheight > back->ceilingheight) + high = back->ceilingheight; + else + high = front->ceilingheight; + + if (front->floorheight > back->floorheight) + low = front->floorheight; + else + low = back->floorheight; + + repeats = (high - low)/textureheight[texnum]; + if ((high-low)%textureheight[texnum]) + repeats++; // tile an extra time to fill the gap -- Monster Iestyn + } + else + repeats = 1; + + for (times = 0; times < repeats; times++) + { + if (times > 0) { - // double ceiling skies are special - // we don't want to lower the ceiling clipping, (no new plane is drawn anyway) - // so we can see the floor of thok barriers always regardless of sector properties - markceiling = false; + rw_scalestep = ds->scalestep; + spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; + if (dc_numlights) + { // reset all lights to their starting heights + for (i = 0; i < dc_numlights; i++) + { + rlight = &dc_lightlist[i]; + rlight->height = rlight->startheight; + } + } } - else if (worldhigh != worldtop -#ifdef ESLOPE - || worldhighslope != worldtopslope - || backsector->c_slope != frontsector->c_slope -#endif - || backsector->ceilingpic != frontsector->ceilingpic - || backsector->lightlevel != frontsector->lightlevel - //SoM: 3/22/2000: Check floor x and y offsets. - || backsector->ceiling_xoffs != frontsector->ceiling_xoffs - || backsector->ceiling_yoffs != frontsector->ceiling_yoffs - || backsector->ceilingpic_angle != frontsector->ceilingpic_angle - //SoM: 3/22/2000: Prevents bleeding. - || (frontsector->heightsec != -1 && frontsector->ceilingpic != skyflatnum) - || backsector->ceilinglightsec != frontsector->ceilinglightsec - //SoM: 4/3/2000: Check for colormaps - || frontsector->extra_colormap != backsector->extra_colormap - || (frontsector->ffloors != backsector->ffloors && frontsector->tag != backsector->tag)) + +#ifndef ESLOPE + if (curline->linedef->flags & ML_DONTPEGBOTTOM) { - markceiling = true; + dc_texturemid = front->floorheight > back->floorheight + ? front->floorheight : back->floorheight; + dc_texturemid = dc_texturemid + textureheight[texnum] - viewz; } else { - // same plane on both sides - markceiling = false; - } - - if (!bothceilingssky && !bothfloorssky) - { -#ifdef ESLOPE - if ((worldhigh <= worldbottom && worldhighslope <= worldbottomslope) - || (worldlow >= worldtop && worldlowslope >= worldtopslope)) -#else - if (backsector->ceilingheight <= frontsector->floorheight - || backsector->floorheight >= frontsector->ceilingheight) -#endif - { - // closed door - markceiling = markfloor = true; - } + dc_texturemid = front->ceilingheight < back->ceilingheight + ? front->ceilingheight : back->ceilingheight; + dc_texturemid = dc_texturemid - viewz; } - } -} + dc_texturemid += curline->sidedef->rowoffset; -// -// R_WorldStep -// Does... stepping... stuff? -// -static void R_WorldStep(INT32 range) -{ - worldtop >>= 4; - worldbottom >>= 4; -#ifdef ESLOPE - worldtopslope >>= 4; - worldbottomslope >>= 4; -#else - (void)range; + if (curline->linedef->flags & ML_DONTPEGBOTTOM) + dc_texturemid += (textureheight[texnum])*times; + else + dc_texturemid -= (textureheight[texnum])*times; #endif - if (linedef->special == HORIZONSPECIAL) { // HORIZON LINES - topstep = bottomstep = 0; - topfrac = bottomfrac = (centeryfrac>>4); - topfrac++; // Prevent 1px HOM - } else { - topstep = -FixedMul (rw_scalestep, worldtop); - topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale); - - bottomstep = -FixedMul (rw_scalestep,worldbottom); - bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale); + dc_texheight = textureheight[texnum]>>FRACBITS; + // draw the columns + for (dc_x = x1; dc_x <= x2; dc_x++) + { #ifdef ESLOPE - if (frontsector->c_slope) { - fixed_t topfracend = (centeryfrac>>4) - FixedMul (worldtopslope, ds_p->scale2); - topstep = (topfracend-topfrac)/(range); - } - if (frontsector->f_slope) { - fixed_t bottomfracend = (centeryfrac>>4) - FixedMul (worldbottomslope, ds_p->scale2); - bottomstep = (bottomfracend-bottomfrac)/(range); - } + dc_texturemid = ds->maskedtextureheight[dc_x]; + + if (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3)) + dc_texturemid += (textureheight[texnum])*times + textureheight[texnum]; + else + dc_texturemid -= (textureheight[texnum])*times; #endif - } -} + // calculate lighting + if (maskedtexturecol[dc_x] != INT16_MAX) + { + // Check for overflows first + overflow_test = (INT64)centeryfrac - (((INT64)dc_texturemid*spryscale)>>FRACBITS); + if (overflow_test < 0) overflow_test = -overflow_test; + if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) + { + // Eh, no, go away, don't waste our time + if (dc_numlights) + { + for (i = 0; i < dc_numlights; i++) + { + rlight = &dc_lightlist[i]; + rlight->height += rlight->heightstep; + } + } + spryscale += rw_scalestep; + continue; + } -// -// R_WorldBackStep -// Does... stepping... stuff? For backsides?!?!?!?!?!?! -// -static void R_WorldBackStep(INT32 range) -{ - INT32 i; + if (dc_numlights) + { + lighttable_t **xwalllights; - worldhigh >>= 4; - worldlow >>= 4; -#ifdef ESLOPE - worldhighslope >>= 4; - worldlowslope >>= 4; -#else - (void)range; -#endif + sprbotscreen = INT32_MAX; + sprtopscreen = windowtop = (centeryfrac - FixedMul(dc_texturemid, spryscale)); - if (toptexture) - { - pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale); - pixhighstep = -FixedMul (rw_scalestep,worldhigh); + realbot = windowbottom = FixedMul(textureheight[texnum], spryscale) + sprtopscreen; + dc_iscale = 0xffffffffu / (unsigned)spryscale; -#ifdef ESLOPE - if (backsector->c_slope) { - fixed_t topfracend = (centeryfrac>>4) - FixedMul (worldhighslope, ds_p->scale2); - pixhighstep = (topfracend-pixhigh)/(range); - } -#endif - } + // draw the texture + col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); - if (bottomtexture) - { - pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale); - pixlowstep = -FixedMul (rw_scalestep,worldlow); -#ifdef ESLOPE - if (backsector->f_slope) { - fixed_t bottomfracend = (centeryfrac>>4) - FixedMul (worldlowslope, ds_p->scale2); - pixlowstep = (bottomfracend-pixlow)/(range); - } -#endif - } + for (i = 0; i < dc_numlights; i++) + { + rlight = &dc_lightlist[i]; - { - ffloor_t * rover; -#ifdef ESLOPE - fixed_t roverleft, roverright; - fixed_t planevistest; -#endif - i = 0; + if ((rlight->flags & FF_NOSHADE)) + continue; - if (backsector->ffloors) - { - for (rover = backsector->ffloors; rover && i < MAXFFLOORS; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES)) - continue; - if (rover->norender == leveltime) - continue; + if (rlight->lightnum < 0) + xwalllights = scalelight[0]; + else if (rlight->lightnum >= LIGHTLEVELS) + xwalllights = scalelight[LIGHTLEVELS-1]; + else + xwalllights = scalelight[rlight->lightnum]; -#ifdef ESLOPE - // Let the renderer know this sector is sloped. - if (*rover->b_slope || *rover->t_slope) - backsector->hasslope = true; + pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; - roverleft = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) - viewz; - roverright = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) - viewz; - planevistest = (*rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : *rover->bottomheight); + if (pindex >= MAXLIGHTSCALE) + pindex = MAXLIGHTSCALE - 1; - if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) && - (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) && - ((viewz < planevistest && !(rover->flags & FF_INVERTPLANES)) || - (viewz > planevistest && (rover->flags & FF_BOTHPLANES)))) - { - //ffloor[i].slope = *rover->b_slope; - ffloor[i].b_pos = roverleft; - ffloor[i].b_pos_slope = roverright; - ffloor[i].b_pos >>= 4; - ffloor[i].b_pos_slope >>= 4; - ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); - ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2); - ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range); - i++; - } + if (rlight->extra_colormap) + rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps); + else + rlight->rcolormap = xwalllights[pindex]; - if (i >= MAXFFLOORS) - break; + height = rlight->height; + rlight->height += rlight->heightstep; - roverleft = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) - viewz; - roverright = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) - viewz; - planevistest = (*rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : *rover->topheight); + if (height <= windowtop) + { + dc_colormap = rlight->rcolormap; + continue; + } - if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) && - (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) && - ((viewz > planevistest && !(rover->flags & FF_INVERTPLANES)) || - (viewz < planevistest && (rover->flags & FF_BOTHPLANES)))) - { - //ffloor[i].slope = *rover->t_slope; - ffloor[i].b_pos = roverleft; - ffloor[i].b_pos_slope = roverright; - ffloor[i].b_pos >>= 4; - ffloor[i].b_pos_slope >>= 4; - ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); - ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2); - ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range); - i++; - } -#else - if (*rover->bottomheight <= backsector->ceilingheight && - *rover->bottomheight >= backsector->floorheight && - ((viewz < *rover->bottomheight && !(rover->flags & FF_INVERTPLANES)) || - (viewz > *rover->bottomheight && (rover->flags & FF_BOTHPLANES)))) - { - ffloor[i].b_pos = *rover->bottomheight; - ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; - ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); - ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); - i++; - } + windowbottom = height; + if (windowbottom >= realbot) + { + windowbottom = realbot; + colfunc_2s(col); + for (i++; i < dc_numlights; i++) + { + rlight = &dc_lightlist[i]; + rlight->height += rlight->heightstep; + } - if (i >= MAXFFLOORS) - break; + continue; + } + colfunc_2s(col); + windowtop = windowbottom + 1; + dc_colormap = rlight->rcolormap; + } + windowbottom = realbot; + if (windowtop < windowbottom) + colfunc_2s(col); - if (*rover->topheight >= backsector->floorheight && - *rover->topheight <= backsector->ceilingheight && - ((viewz > *rover->topheight && !(rover->flags & FF_INVERTPLANES)) || - (viewz < *rover->topheight && (rover->flags & FF_BOTHPLANES)))) - { - ffloor[i].b_pos = *rover->topheight; - ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; - ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); - ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); - i++; - } -#endif - } - } - else if (frontsector && frontsector->ffloors) - { - for (rover = frontsector->ffloors; rover && i < MAXFFLOORS; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES)) - continue; - if (rover->norender == leveltime) + spryscale += rw_scalestep; continue; + } + // calculate lighting + pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; -#ifdef ESLOPE - // Let the renderer know this sector is sloped. - if (*rover->b_slope || *rover->t_slope) - frontsector->hasslope = true; + if (pindex >= MAXLIGHTSCALE) + pindex = MAXLIGHTSCALE - 1; - roverleft = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) - viewz; - roverright = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) - viewz; - planevistest = (*rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : *rover->bottomheight); + dc_colormap = walllights[pindex]; - if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) && - (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) && - ((viewz < planevistest && !(rover->flags & FF_INVERTPLANES)) || - (viewz > planevistest && (rover->flags & FF_BOTHPLANES)))) - { - //ffloor[i].slope = *rover->b_slope; - ffloor[i].b_pos = roverleft; - ffloor[i].b_pos_slope = roverright; - ffloor[i].b_pos >>= 4; - ffloor[i].b_pos_slope >>= 4; - ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); - ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2); - ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range); - i++; - } + if (frontsector->extra_colormap) + dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); - if (i >= MAXFFLOORS) - break; + sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); + dc_iscale = 0xffffffffu / (unsigned)spryscale; - roverleft = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) - viewz; - roverright = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) - viewz; - planevistest = (*rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : *rover->topheight); + // draw the texture + col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); - if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) && - (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) && - ((viewz > planevistest && !(rover->flags & FF_INVERTPLANES)) || - (viewz < planevistest && (rover->flags & FF_BOTHPLANES)))) - { - //ffloor[i].slope = *rover->t_slope; - ffloor[i].b_pos = roverleft; - ffloor[i].b_pos_slope = roverright; - ffloor[i].b_pos >>= 4; - ffloor[i].b_pos_slope >>= 4; - ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); - ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2); - ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range); - i++; - } -#else - if (*rover->bottomheight <= frontsector->ceilingheight && - *rover->bottomheight >= frontsector->floorheight && - ((viewz < *rover->bottomheight && !(rover->flags & FF_INVERTPLANES)) || - (viewz > *rover->bottomheight && (rover->flags & FF_BOTHPLANES)))) - { - ffloor[i].b_pos = *rover->bottomheight; - ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; - ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); - ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); - i++; - } - if (i >= MAXFFLOORS) - break; - if (*rover->topheight >= frontsector->floorheight && - *rover->topheight <= frontsector->ceilingheight && - ((viewz > *rover->topheight && !(rover->flags & FF_INVERTPLANES)) || - (viewz < *rover->topheight && (rover->flags & FF_BOTHPLANES)))) +//#ifdef POLYOBJECTS_PLANES +#if 0 // Disabling this allows inside edges to render below the planes, for until the clipping is fixed to work right when POs are near the camera. -Red + if (curline->dontrenderme && curline->polyseg && (curline->polyseg->flags & POF_RENDERPLANES)) { - ffloor[i].b_pos = *rover->topheight; - ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; - ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); - ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); - i++; - } -#endif - } - } + fixed_t my_topscreen; + fixed_t my_bottomscreen; + fixed_t my_yl, my_yh; -#ifdef POLYOBJECTS_PLANES - if (curline->polyseg && frontsector && (curline->polyseg->flags & POF_RENDERPLANES)) - { - while (i < numffloors && ffloor[i].polyobj != curline->polyseg) i++; - if (i < numffloors && backsector->floorheight <= frontsector->ceilingheight && - backsector->floorheight >= frontsector->floorheight && - (viewz < backsector->floorheight)) - { - if (ffloor[i].plane->minx > ds_p->x1) - ffloor[i].plane->minx = ds_p->x1; + my_topscreen = sprtopscreen + spryscale*col->topdelta; + my_bottomscreen = sprbotscreen == INT32_MAX ? my_topscreen + spryscale*col->length + : sprbotscreen + spryscale*col->length; - if (ffloor[i].plane->maxx < ds_p->x2) - ffloor[i].plane->maxx = ds_p->x2; + my_yl = (my_topscreen+FRACUNIT-1)>>FRACBITS; + my_yh = (my_bottomscreen-1)>>FRACBITS; + // CONS_Debug(DBG_RENDER, "my_topscreen: %d\nmy_bottomscreen: %d\nmy_yl: %d\nmy_yh: %d\n", my_topscreen, my_bottomscreen, my_yl, my_yh); -#ifdef ESLOPE - ffloor[i].slope = NULL; -#endif - ffloor[i].b_pos = backsector->floorheight; - ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; - ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); - ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); - i++; - } - if (i < numffloors && backsector->ceilingheight >= frontsector->floorheight && - backsector->ceilingheight <= frontsector->ceilingheight && - (viewz > backsector->ceilingheight)) - { - if (ffloor[i].plane->minx > ds_p->x1) - ffloor[i].plane->minx = ds_p->x1; + if (numffloors) + { + INT32 top = my_yl; + INT32 bottom = my_yh; - if (ffloor[i].plane->maxx < ds_p->x2) - ffloor[i].plane->maxx = ds_p->x2; + for (i = 0; i < numffloors; i++) + { + if (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg) + continue; -#ifdef ESLOPE - ffloor[i].slope = NULL; + if (ffloor[i].height < viewz) + { + INT32 top_w = ffloor[i].plane->top[dc_x]; + + // CONS_Debug(DBG_RENDER, "Leveltime : %d\n", leveltime); + // CONS_Debug(DBG_RENDER, "Top is %d, top_w is %d\n", top, top_w); + if (top_w < top) + { + ffloor[i].plane->top[dc_x] = (INT16)top; + ffloor[i].plane->picnum = 0; + } + // CONS_Debug(DBG_RENDER, "top_w is now %d\n", ffloor[i].plane->top[dc_x]); + } + else if (ffloor[i].height > viewz) + { + INT32 bottom_w = ffloor[i].plane->bottom[dc_x]; + + if (bottom_w > bottom) + { + ffloor[i].plane->bottom[dc_x] = (INT16)bottom; + ffloor[i].plane->picnum = 0; + } + } + } + } + } + else #endif - ffloor[i].b_pos = backsector->ceilingheight; - ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; - ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); - ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); - i++; + colfunc_2s(col); } + spryscale += rw_scalestep; } -#endif - - numbackffloors = i; } + colfunc = colfuncs[BASEDRAWFUNC]; } -// -// R_WorldFFloorStep -// Does... stepping... stuff? For FOFs?! -// -static void R_WorldFFloorStep(INT32 range) +// Loop through R_DrawMaskedColumn calls +static void R_DrawRepeatMaskedColumn(column_t *col) { - INT32 i; + while (sprtopscreen < sprbotscreen) { + R_DrawMaskedColumn(col); + if ((INT64)sprtopscreen + dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow + sprtopscreen = INT32_MAX; + else + sprtopscreen += dc_texheight*spryscale; + } +} -#ifndef ESLOPE - (void)range; // Not needed! -#endif +static void R_DrawRepeatFlippedMaskedColumn(column_t *col) +{ + do { + R_DrawFlippedMaskedColumn(col, column2s_length); + sprtopscreen += dc_texheight*spryscale; + } while (sprtopscreen < sprbotscreen); +} - for (i = 0; i < numffloors; i++) - { - ffloor[i].f_pos >>= 4; +// +// R_RenderThickSideRange +// Renders all the thick sides in the given range. +void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) +{ + size_t pindex; + column_t * col; + INT32 lightnum; + INT32 texnum; + sector_t tempsec; + INT32 templight; + INT32 i, p; + fixed_t bottombounds = viewheight << FRACBITS; + fixed_t topbounds = (con_clipviewtop - 1) << FRACBITS; + fixed_t offsetvalue = 0; + lightlist_t *light; + r_lightlist_t *rlight; #ifdef ESLOPE - ffloor[i].f_pos_slope >>= 4; + INT32 range; #endif - if (linedef->special == HORIZONSPECIAL) // Horizon lines extend FOFs in contact with them too. - { - ffloor[i].f_step = 0; - ffloor[i].f_frac = (centeryfrac>>4); - topfrac++; // Prevent 1px HOM - } - else - { +#ifndef ESLOPE + fixed_t lheight; +#endif + line_t *newline = NULL; #ifdef ESLOPE - ffloor[i].f_frac = (centeryfrac>>4) - FixedMul(ffloor[i].f_pos, rw_scale); - ffloor[i].f_step = ((centeryfrac>>4) - FixedMul(ffloor[i].f_pos_slope, ds_p->scale2) - ffloor[i].f_frac)/(range); -#else - ffloor[i].f_step = FixedMul(-rw_scalestep, ffloor[i].f_pos); - ffloor[i].f_frac = (centeryfrac>>4) - FixedMul(ffloor[i].f_pos, rw_scale); + // Render FOF sides kinda like normal sides, with the frac and step and everything + // NOTE: INT64 instead of fixed_t because overflow concerns + INT64 top_frac, top_step, bottom_frac, bottom_step; + // skew FOF walls with slopes? + boolean slopeskew = false; + fixed_t ffloortextureslide = 0; + INT32 oldx = -1; + fixed_t left_top, left_bottom; // needed here for slope skewing + pslope_t *skewslope = NULL; #endif - } + + void (*colfunc_2s) (column_t *); + + // Calculate light table. + // Use different light tables + // for horizontal / vertical / diagonal. Diagonal? + // OPTIMIZE: get rid of LIGHTSEGSHIFT globally + + curline = ds->curline; + backsector = pfloor->target; + frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector; + texnum = R_GetTextureNum(sides[pfloor->master->sidenum[0]].midtexture); + + colfunc = colfuncs[BASEDRAWFUNC]; + + if (pfloor->master->flags & ML_TFERLINE) + { + size_t linenum = curline->linedef-backsector->lines[0]; + newline = pfloor->master->frontsector->lines[0] + linenum; + texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture); } -} -// -// R_WorldLightLists -// Creates light lists. -// -static void R_WorldLightLists(INT32 range) -{ - INT32 i, p; - lightlist_t *light; - r_lightlist_t *rlight; + if (pfloor->flags & FF_TRANSLUCENT) + { + boolean fuzzy = true; -#ifndef ESLOPE - (void)range; // Not needed! + // Hacked up support for alpha value in software mode Tails 09-24-2002 + if (pfloor->alpha < 12) + return; // Don't even draw it + else if (pfloor->alpha < 38) + dc_transmap = transtables + ((tr_trans90-1)<<FF_TRANSSHIFT); + else if (pfloor->alpha < 64) + dc_transmap = transtables + ((tr_trans80-1)<<FF_TRANSSHIFT); + else if (pfloor->alpha < 89) + dc_transmap = transtables + ((tr_trans70-1)<<FF_TRANSSHIFT); + else if (pfloor->alpha < 115) + dc_transmap = transtables + ((tr_trans60-1)<<FF_TRANSSHIFT); + else if (pfloor->alpha < 140) + dc_transmap = transtables + ((tr_trans50-1)<<FF_TRANSSHIFT); + else if (pfloor->alpha < 166) + dc_transmap = transtables + ((tr_trans40-1)<<FF_TRANSSHIFT); + else if (pfloor->alpha < 192) + dc_transmap = transtables + ((tr_trans30-1)<<FF_TRANSSHIFT); + else if (pfloor->alpha < 217) + dc_transmap = transtables + ((tr_trans20-1)<<FF_TRANSSHIFT); + else if (pfloor->alpha < 243) + dc_transmap = transtables + ((tr_trans10-1)<<FF_TRANSSHIFT); + else + fuzzy = false; // Opaque + + if (fuzzy) + colfunc = colfuncs[COLDRAWFUNC_FUZZY]; + } + else if (pfloor->flags & FF_FOG) + colfunc = colfuncs[COLDRAWFUNC_FOG]; + +#ifdef ESLOPE + range = max(ds->x2-ds->x1, 1); #endif + //SoM: Moved these up here so they are available for my lightlist calculations + rw_scalestep = ds->scalestep; + spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; dc_numlights = 0; - if (frontsector->numlights) { dc_numlights = frontsector->numlights; - if (dc_numlights >= dc_maxlights) + if (dc_numlights > dc_maxlights) { dc_maxlights = dc_numlights; dc_lightlist = Z_Realloc(dc_lightlist, sizeof (*dc_lightlist) * dc_maxlights, PU_STATIC, NULL); @@ -2989,448 +2985,452 @@ static void R_WorldLightLists(INT32 range) { #ifdef ESLOPE fixed_t leftheight, rightheight; + fixed_t pfloorleft, pfloorright; + INT64 overflow_test; #endif - light = &frontsector->lightlist[i]; rlight = &dc_lightlist[p]; - #ifdef ESLOPE - if (light->slope) { - leftheight = P_GetZAt(light->slope, segleft.x, segleft.y); - rightheight = P_GetZAt(light->slope, segright.x, segright.y); - // Flag sector as having slopes - frontsector->hasslope = true; - } else - leftheight = rightheight = light->height; +#define SLOPEPARAMS(slope, end1, end2, normalheight) \ + if (slope) { \ + end1 = P_GetZAt(slope, ds->leftpos.x, ds->leftpos.y); \ + end2 = P_GetZAt(slope, ds->rightpos.x, ds->rightpos.y); \ + } else \ + end1 = end2 = normalheight; - leftheight -= viewz; - rightheight -= viewz; + SLOPEPARAMS(light->slope, leftheight, rightheight, light->height) + SLOPEPARAMS(*pfloor->b_slope, pfloorleft, pfloorright, *pfloor->bottomheight) - leftheight >>= 4; - rightheight >>= 4; -#endif + if (leftheight < pfloorleft && rightheight < pfloorright) + continue; - if (i != 0) + SLOPEPARAMS(*pfloor->t_slope, pfloorleft, pfloorright, *pfloor->topheight) + + if (leftheight > pfloorleft && rightheight > pfloorright && i+1 < dc_numlights) { -#ifdef ESLOPE - if (leftheight < worldbottom && rightheight < worldbottomslope) + lightlist_t *nextlight = &frontsector->lightlist[i+1]; + if ((nextlight->slope ? P_GetZAt(nextlight->slope, ds->leftpos.x, ds->leftpos.y) : nextlight->height) > pfloorleft + && (nextlight->slope ? P_GetZAt(nextlight->slope, ds->rightpos.x, ds->rightpos.y) : nextlight->height) > pfloorright) continue; + } - if (leftheight > worldtop && rightheight > worldtopslope && i+1 < dc_numlights && frontsector->lightlist[i+1].height > frontsector->ceilingheight) - continue; -#else - if (light->height < frontsector->floorheight) - continue; + leftheight -= viewz; + rightheight -= viewz; - if (light->height > frontsector->ceilingheight && i+1 < dc_numlights && frontsector->lightlist[i+1].height > frontsector->ceilingheight) - continue; -#endif - } +#define CLAMPMAX INT32_MAX +#define CLAMPMIN (-INT32_MAX) // This is not INT32_MIN on purpose! INT32_MIN makes the drawers freak out. + // Monster Iestyn (25/03/18): do not skip these lights if they fail overflow test, just clamp them instead so they behave. + overflow_test = (INT64)centeryfrac - (((INT64)leftheight*ds->scale1)>>FRACBITS); + if (overflow_test > (INT64)CLAMPMAX) rlight->height = CLAMPMAX; + else if (overflow_test > (INT64)CLAMPMIN) rlight->height = (fixed_t)overflow_test; + else rlight->height = CLAMPMIN; -#ifdef ESLOPE - rlight->height = (centeryfrac>>4) - FixedMul(leftheight, rw_scale); - rlight->heightstep = (centeryfrac>>4) - FixedMul(rightheight, ds_p->scale2); + overflow_test = (INT64)centeryfrac - (((INT64)rightheight*ds->scale2)>>FRACBITS); + if (overflow_test > (INT64)CLAMPMAX) rlight->heightstep = CLAMPMAX; + else if (overflow_test > (INT64)CLAMPMIN) rlight->heightstep = (fixed_t)overflow_test; + else rlight->heightstep = CLAMPMIN; rlight->heightstep = (rlight->heightstep-rlight->height)/(range); #else - rlight->height = (centeryfrac>>4) - FixedMul((light->height - viewz) >> 4, rw_scale); - rlight->heightstep = -FixedMul (rw_scalestep, (light->height - viewz) >> 4); + if (light->height < *pfloor->bottomheight) + continue; + + if (light->height > *pfloor->topheight && i+1 < dc_numlights && frontsector->lightlist[i+1].height > *pfloor->topheight) + continue; + + lheight = light->height;// > *pfloor->topheight ? *pfloor->topheight + FRACUNIT : light->height; + rlight->heightstep = -FixedMul (rw_scalestep, (lheight - viewz)); + rlight->height = (centeryfrac) - FixedMul((lheight - viewz), spryscale); #endif rlight->flags = light->flags; - - if (light->caster && light->caster->flags & FF_CUTSOLIDS) + if (light->flags & FF_CUTLEVEL) { #ifdef ESLOPE - if (*light->caster->b_slope) { - leftheight = P_GetZAt(*light->caster->b_slope, segleft.x, segleft.y); - rightheight = P_GetZAt(*light->caster->b_slope, segright.x, segright.y); - - // Flag sector as having slopes - frontsector->hasslope = true; - } else - leftheight = rightheight = *light->caster->bottomheight; - + SLOPEPARAMS(*light->caster->b_slope, leftheight, rightheight, *light->caster->bottomheight) +#undef SLOPEPARAMS leftheight -= viewz; rightheight -= viewz; - leftheight >>= 4; - rightheight >>= 4; + // Monster Iestyn (25/03/18): do not skip these lights if they fail overflow test, just clamp them instead so they behave. + overflow_test = (INT64)centeryfrac - (((INT64)leftheight*ds->scale1)>>FRACBITS); + if (overflow_test > (INT64)CLAMPMAX) rlight->botheight = CLAMPMAX; + else if (overflow_test > (INT64)CLAMPMIN) rlight->botheight = (fixed_t)overflow_test; + else rlight->botheight = CLAMPMIN; - rlight->botheight = (centeryfrac>>4) - FixedMul(leftheight, rw_scale); - rlight->botheightstep = (centeryfrac>>4) - FixedMul(rightheight, ds_p->scale2); + overflow_test = (INT64)centeryfrac - (((INT64)rightheight*ds->scale2)>>FRACBITS); + if (overflow_test > (INT64)CLAMPMAX) rlight->botheightstep = CLAMPMAX; + else if (overflow_test > (INT64)CLAMPMIN) rlight->botheightstep = (fixed_t)overflow_test; + else rlight->botheightstep = CLAMPMIN; rlight->botheightstep = (rlight->botheightstep-rlight->botheight)/(range); - #else - rlight->botheight = (centeryfrac >> 4) - FixedMul((*light->caster->bottomheight - viewz) >> 4, rw_scale); - rlight->botheightstep = -FixedMul (rw_scalestep, (*light->caster->bottomheight - viewz) >> 4); + lheight = *light->caster->bottomheight;// > *pfloor->topheight ? *pfloor->topheight + FRACUNIT : *light->caster->bottomheight; + rlight->botheightstep = -FixedMul (rw_scalestep, (lheight - viewz)); + rlight->botheight = (centeryfrac) - FixedMul((lheight - viewz), spryscale); #endif } rlight->lightlevel = *light->lightlevel; rlight->extra_colormap = *light->extra_colormap; - p++; - } - dc_numlights = p; - } -} + // Check if the current light effects the colormap/lightlevel + if (pfloor->flags & FF_FOG) + rlight->lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT); + else + rlight->lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); -// -// R_MarkPlanes -// Creates visplanes. -// -static void R_MarkPlanes(void) -{ - INT32 i; + if (pfloor->flags & FF_FOG || rlight->flags & FF_FOG || (rlight->extra_colormap && rlight->extra_colormap->fog)) + ; + else if (curline->v1->y == curline->v2->y) + rlight->lightnum--; + else if (curline->v1->x == curline->v2->x) + rlight->lightnum++; - // get a new or use the same visplane - if (markceiling) - { - if (ceilingplane) //SoM: 3/29/2000: Check for null ceiling planes - ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1); - else - markceiling = false; + p++; + } - // Don't mark ceiling flat lines for polys unless this line has an upper texture, otherwise we get flat leakage pulling downward - // (If it DOES have an upper texture and we do this, the ceiling won't render at all) - if (curline->polyseg && !curline->sidedef->toptexture) - markceiling = false; + dc_numlights = p; } - - // get a new or use the same visplane - if (markfloor) + else { - if (floorplane) //SoM: 3/29/2000: Check for null planes - floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1); + // Get correct light level! + if ((frontsector->extra_colormap && frontsector->extra_colormap->fog)) + lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); + else if (pfloor->flags & FF_FOG) + lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT); + else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) + lightnum = LIGHTLEVELS-1; else - markfloor = false; - - // Don't mark floor flat lines for polys unless this line has a lower texture, otherwise we get flat leakage pulling upward - // (If it DOES have a lower texture and we do this, the floor won't render at all) - if (curline->polyseg && !curline->sidedef->bottomtexture) - markfloor = false; - } - - ds_p->numffloorplanes = 0; - if (numffloors) - { - if (!firstseg) - { - ds_p->numffloorplanes = numffloors; - - for (i = 0; i < numffloors; i++) - { - ds_p->ffloorplanes[i] = ffloor[i].plane = - R_CheckPlane(ffloor[i].plane, rw_x, rw_stopx - 1); - } + lightnum = R_FakeFlat(frontsector, &tempsec, &templight, &templight, false) + ->lightlevel >> LIGHTSEGSHIFT; - firstseg = ds_p; - } - else - { - for (i = 0; i < numffloors; i++) - R_ExpandPlane(ffloor[i].plane, rw_x, rw_stopx - 1); - } -#ifdef POLYOBJECTS_PLANES - // FIXME hack to fix planes disappearing when a seg goes behind the camera. This NEEDS to be changed to be done properly. -Red - if (curline->polyseg) - { - for (i = 0; i < numffloors; i++) - { - if (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg) - continue; - if (ffloor[i].plane->minx > rw_x) - ffloor[i].plane->minx = rw_x; + if (pfloor->flags & FF_FOG || (frontsector->extra_colormap && frontsector->extra_colormap->fog)); + else if (curline->v1->y == curline->v2->y) + lightnum--; + else if (curline->v1->x == curline->v2->x) + lightnum++; - if (ffloor[i].plane->maxx < rw_stopx - 1) - ffloor[i].plane->maxx = rw_stopx - 1; - } - } -#endif + if (lightnum < 0) + walllights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + walllights = scalelight[LIGHTLEVELS-1]; + else + walllights = scalelight[lightnum]; } -} -// -// R_RemoveOpeningLimits -// Code to remove limits on openings. -// -static void R_RemoveOpeningLimits(INT32 start) -{ - size_t pos = lastopening - openings; - size_t need = (rw_stopx - start)*4 + pos; - if (need > maxopenings) - { - drawseg_t *ds; //needed for fix from *cough* zdoom *cough* - INT16 *oldopenings = openings; - INT16 *oldlast = lastopening; + maskedtexturecol = ds->thicksidecol; - do - maxopenings = maxopenings ? maxopenings*2 : 16384; - while (need > maxopenings); - openings = Z_Realloc(openings, maxopenings * sizeof (*openings), PU_STATIC, NULL); - lastopening = openings + pos; + mfloorclip = ds->sprbottomclip; + mceilingclip = ds->sprtopclip; + dc_texheight = textureheight[texnum]>>FRACBITS; - // borrowed fix from *cough* zdoom *cough* - // [RH] We also need to adjust the openings pointers that - // were already stored in drawsegs. - for (ds = drawsegs; ds < ds_p; ds++) - { -#define ADJUST(p) if (ds->p + ds->x1 >= oldopenings && ds->p + ds->x1 <= oldlast) ds->p = ds->p - oldopenings + openings; - ADJUST(maskedtexturecol); - ADJUST(sprtopclip); - ADJUST(sprbottomclip); - ADJUST(thicksidecol); -#undef ADJUST - } +#ifdef ESLOPE + // calculate both left ends + if (*pfloor->t_slope) + left_top = P_GetZAt(*pfloor->t_slope, ds->leftpos.x, ds->leftpos.y) - viewz; + else + left_top = *pfloor->topheight - viewz; + + if (*pfloor->b_slope) + left_bottom = P_GetZAt(*pfloor->b_slope, ds->leftpos.x, ds->leftpos.y) - viewz; + else + left_bottom = *pfloor->bottomheight - viewz; + skewslope = *pfloor->t_slope; // skew using top slope by default + if (newline) + { + if (newline->flags & ML_DONTPEGTOP) + slopeskew = true; } -} + else if (pfloor->master->flags & ML_DONTPEGTOP) + slopeskew = true; -// -// R_StoreWallRange -// A wall segment will be drawn -// between start and stop pixels (inclusive). -// -void R_StoreWallRange(INT32 start, INT32 stop) -{ - fixed_t hyp; - fixed_t sineval; - angle_t distangle, offsetangle; - boolean longboi; -#ifndef ESLOPE - fixed_t vtop; + if (slopeskew) + dc_texturemid = left_top; + else #endif - INT32 i; - INT32 range; - static size_t maxdrawsegs = 0; + dc_texturemid = *pfloor->topheight - viewz; + if (newline) + { + offsetvalue = sides[newline->sidenum[0]].rowoffset; + if (newline->flags & ML_DONTPEGBOTTOM) + { #ifdef ESLOPE - maskedtextureheight = NULL; - //initialize segleft and segright - memset(&segleft, 0x00, sizeof(segleft)); - memset(&segright, 0x00, sizeof(segright)); + skewslope = *pfloor->b_slope; // skew using bottom slope + if (slopeskew) + dc_texturemid = left_bottom; + else #endif - - colfunc = colfuncs[BASEDRAWFUNC]; - - if (ds_p == drawsegs+maxdrawsegs) + offsetvalue -= *pfloor->topheight - *pfloor->bottomheight; + } + } + else { - size_t curpos = curdrawsegs - drawsegs; - size_t pos = ds_p - drawsegs; - size_t newmax = maxdrawsegs ? maxdrawsegs*2 : 128; - if (firstseg) - firstseg = (drawseg_t *)(firstseg - drawsegs); - drawsegs = Z_Realloc(drawsegs, newmax*sizeof (*drawsegs), PU_STATIC, NULL); - ds_p = drawsegs + pos; - maxdrawsegs = newmax; - curdrawsegs = drawsegs + curpos; - if (firstseg) - firstseg = drawsegs + (size_t)firstseg; + offsetvalue = sides[pfloor->master->sidenum[0]].rowoffset; + if (curline->linedef->flags & ML_DONTPEGBOTTOM) + { +#ifdef ESLOPE + skewslope = *pfloor->b_slope; // skew using bottom slope + if (slopeskew) + dc_texturemid = left_bottom; + else +#endif + offsetvalue -= *pfloor->topheight - *pfloor->bottomheight; + } } - sidedef = curline->sidedef; - linedef = curline->linedef; - - // calculate rw_distance for scale calculation - rw_normalangle = curline->angle + ANGLE_90; - offsetangle = abs((INT32)(rw_normalangle-rw_angle1)); - - if (offsetangle > ANGLE_90) - offsetangle = ANGLE_90; +#ifdef ESLOPE + if (slopeskew) + { + angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y); - distangle = ANGLE_90 - offsetangle; - sineval = FINESINE(distangle>>ANGLETOFINESHIFT); + if (skewslope) + ffloortextureslide = FixedMul(skewslope->zdelta, FINECOSINE((lineangle-skewslope->xydirection)>>ANGLETOFINESHIFT)); + } +#endif - hyp = R_PointToDist(curline->v1->x, curline->v1->y); - longboi = (hyp >= INT32_MAX); + dc_texturemid += offsetvalue; - // The seg is vertical. - if (curline->v1->y == curline->v2->y) - rw_distance = (fixed_t)(llabs(viewy - curline->v1->y)); - // The seg is horizontal. - else if (curline->v1->x == curline->v2->x) - rw_distance = (fixed_t)(llabs(viewx - curline->v1->x)); - // big room fix -#ifdef SOFTWARE_USE_FLOATS - else if ((curline->length >= 1024<<FRACBITS) || longboi) -#else - else if (longboi) -#endif - R_CalculateSegDistance(curline, viewx, viewy, longboi); + // Texture must be cached before setting colfunc_2s, + // otherwise texture[texnum]->holes may be false when it shouldn't be + R_CheckTextureCache(texnum); + //faB: handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures + // are not stored per-column with post info anymore in Doom Legacy + if (textures[texnum]->holes) + { + if (textures[texnum]->flip & 2) // vertically flipped? + { + colfunc_2s = R_DrawRepeatFlippedMaskedColumn; + column2s_length = textures[texnum]->height; + } + else + colfunc_2s = R_DrawRepeatMaskedColumn; // render the usual 2sided single-patch packed texture + } else - rw_distance = FixedMul(hyp, sineval); - - ds_p->x1 = rw_x = start; - ds_p->x2 = stop; - ds_p->curline = curline; - rw_stopx = stop+1; + { + colfunc_2s = R_Render2sidedMultiPatchColumn; //render multipatch with no holes (no post_t info) + column2s_length = textures[texnum]->height; + } - //SoM: Code to remove limits on openings. - R_RemoveOpeningLimits(start); +#ifdef ESLOPE + // Set heights according to plane, or slope, whichever + { + fixed_t right_top, right_bottom; - // calculate scale at both ends and step - range = R_CalculateWallScale(start, stop); + // calculate right ends now + if (*pfloor->t_slope) + right_top = P_GetZAt(*pfloor->t_slope, ds->rightpos.x, ds->rightpos.y) - viewz; + else + right_top = *pfloor->topheight - viewz; - // calculate texture boundaries - // and decide if floor / ceiling marks are needed - R_WorldTopAndBottom(start, stop); + if (*pfloor->b_slope) + right_bottom = P_GetZAt(*pfloor->b_slope, ds->rightpos.x, ds->rightpos.y) - viewz; + else + right_bottom = *pfloor->bottomheight - viewz; - midtexture = toptexture = bottomtexture = maskedtexture = 0; - ds_p->maskedtexturecol = NULL; - ds_p->numthicksides = numthicksides = 0; - ds_p->thicksidecol = NULL; - ds_p->tsilheight = 0; + // using INT64 to avoid 32bit overflow + top_frac = (INT64)centeryfrac - (((INT64)left_top * ds->scale1) >> FRACBITS); + bottom_frac = (INT64)centeryfrac - (((INT64)left_bottom * ds->scale1) >> FRACBITS); + top_step = (INT64)centeryfrac - (((INT64)right_top * ds->scale2) >> FRACBITS); + bottom_step = (INT64)centeryfrac - (((INT64)right_bottom * ds->scale2) >> FRACBITS); - numbackffloors = 0; + top_step = (top_step-top_frac)/(range); + bottom_step = (bottom_step-bottom_frac)/(range); - for (i = 0; i < MAXFFLOORS; i++) - ds_p->thicksides[i] = NULL; + top_frac += top_step * (x1 - ds->x1); + bottom_frac += bottom_step * (x1 - ds->x1); + } +#endif - if (numffloors) + // draw the columns + for (dc_x = x1; dc_x <= x2; dc_x++) { - for (i = 0; i < numffloors; i++) + if (maskedtexturecol[dc_x] != INT16_MAX) { -#ifdef POLYOBJECTS_PLANES - if (ffloor[i].polyobj && (!ds_p->curline->polyseg || ffloor[i].polyobj != ds_p->curline->polyseg)) - continue; +#ifdef ESLOPE + if (ffloortextureslide) { // skew FOF walls + if (oldx != -1) + dc_texturemid += FixedMul(ffloortextureslide, (maskedtexturecol[oldx]-maskedtexturecol[dc_x])<<FRACBITS); + oldx = dc_x; + } #endif + // Calculate bounds + // clamp the values if necessary to avoid overflows and rendering glitches caused by them #ifdef ESLOPE - if (ffloor[i].slope) { - ffloor[i].f_pos = P_GetZAt(ffloor[i].slope, segleft.x, segleft.y) - viewz; - ffloor[i].f_pos_slope = P_GetZAt(ffloor[i].slope, segright.x, segright.y) - viewz; - } else - ffloor[i].f_pos_slope = + if (top_frac > (INT64)CLAMPMAX) sprtopscreen = windowtop = CLAMPMAX; + else if (top_frac > (INT64)CLAMPMIN) sprtopscreen = windowtop = (fixed_t)top_frac; + else sprtopscreen = windowtop = CLAMPMIN; + if (bottom_frac > (INT64)CLAMPMAX) sprbotscreen = windowbottom = CLAMPMAX; + else if (bottom_frac > (INT64)CLAMPMIN) sprbotscreen = windowbottom = (fixed_t)bottom_frac; + else sprbotscreen = windowbottom = CLAMPMIN; + + top_frac += top_step; + bottom_frac += bottom_step; +#else + sprtopscreen = windowtop = (centeryfrac - FixedMul((dc_texturemid - offsetvalue), spryscale)); + sprbotscreen = windowbottom = FixedMul(*pfloor->topheight - *pfloor->bottomheight, spryscale) + sprtopscreen; #endif - ffloor[i].f_pos = ffloor[i].height - viewz; - } - } -#ifdef ESLOPE - // Set up texture Y offset slides for sloped walls - rw_toptextureslide = rw_midtextureslide = rw_bottomtextureslide = 0; - ceilingfrontslide = floorfrontslide = ceilingbackslide = floorbackslide = 0; + // SoM: If column is out of range, why bother with it?? + if (windowbottom < topbounds || windowtop > bottombounds) + { + if (dc_numlights) + { + for (i = 0; i < dc_numlights; i++) + { + rlight = &dc_lightlist[i]; + rlight->height += rlight->heightstep; + if (rlight->flags & FF_CUTLEVEL) + rlight->botheight += rlight->botheightstep; + } + } + spryscale += rw_scalestep; + continue; + } - { - angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y); + dc_iscale = 0xffffffffu / (unsigned)spryscale; - if (frontsector->f_slope) - floorfrontslide = FixedMul(frontsector->f_slope->zdelta, FINECOSINE((lineangle-frontsector->f_slope->xydirection)>>ANGLETOFINESHIFT)); + // Get data for the column + col = (column_t *)((UINT8 *)R_GetColumn(texnum,maskedtexturecol[dc_x]) - 3); - if (frontsector->c_slope) - ceilingfrontslide = FixedMul(frontsector->c_slope->zdelta, FINECOSINE((lineangle-frontsector->c_slope->xydirection)>>ANGLETOFINESHIFT)); + // SoM: New code does not rely on R_DrawColumnShadowed_8 which + // will (hopefully) put less strain on the stack. + if (dc_numlights) + { + lighttable_t **xwalllights; + fixed_t height; + fixed_t bheight = 0; + INT32 solid = 0; + INT32 lighteffect = 0; - if (backsector && backsector->f_slope) - floorbackslide = FixedMul(backsector->f_slope->zdelta, FINECOSINE((lineangle-backsector->f_slope->xydirection)>>ANGLETOFINESHIFT)); + for (i = 0; i < dc_numlights; i++) + { + // Check if the current light effects the colormap/lightlevel + rlight = &dc_lightlist[i]; + lighteffect = !(dc_lightlist[i].flags & FF_NOSHADE); + if (lighteffect) + { + lightnum = rlight->lightnum; - if (backsector && backsector->c_slope) - ceilingbackslide = FixedMul(backsector->c_slope->zdelta, FINECOSINE((lineangle-backsector->c_slope->xydirection)>>ANGLETOFINESHIFT)); - } -#endif + if (lightnum < 0) + xwalllights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + xwalllights = scalelight[LIGHTLEVELS-1]; + else + xwalllights = scalelight[lightnum]; - // Check for textures - R_StoreWallSilhouette(); - R_CheckWallTextures(); - if (backsector) - R_CheckMaskedTextures(); + pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; -#undef SLOPEPARAMS + if (pindex >= MAXLIGHTSCALE) + pindex = MAXLIGHTSCALE-1; - // Calculate rw_offset (only needed for textured lines) - segtextured = midtexture || toptexture || bottomtexture || maskedtexture || (numthicksides > 0); - if (segtextured) - R_WorldSegTextured(hyp, longboi); + if (pfloor->flags & FF_FOG) + { + if (pfloor->master->frontsector->extra_colormap) + rlight->rcolormap = pfloor->master->frontsector->extra_colormap->colormap + (xwalllights[pindex] - colormaps); + else + rlight->rcolormap = xwalllights[pindex]; + } + else + { + if (rlight->extra_colormap) + rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps); + else + rlight->rcolormap = xwalllights[pindex]; + } + } - // if a floor / ceiling plane is on the wrong side - // of the view plane, it is definitely invisible - // and doesn't need to be marked. - if (frontsector->heightsec == -1) - { - if (frontsector->floorpic != skyflatnum - && ( -#ifdef ESLOPE - frontsector->f_slope ? P_GetZAt(frontsector->f_slope, viewx, viewy) : -#endif - frontsector->floorheight) >= viewz) - { - // above view plane - markfloor = false; - } + solid = 0; // don't carry over solid-cutting flag from the previous light - if (frontsector->ceilingpic != skyflatnum - && ( -#ifdef ESLOPE - frontsector->c_slope ? P_GetZAt(frontsector->c_slope, viewx, viewy) : -#endif - frontsector->ceilingheight) <= viewz) - { - // below view plane - markceiling = false; - } - } + // Check if the current light can cut the current 3D floor. + if (rlight->flags & FF_CUTSOLIDS && !(pfloor->flags & FF_EXTRA)) + solid = 1; + else if (rlight->flags & FF_CUTEXTRA && pfloor->flags & FF_EXTRA) + { + if (rlight->flags & FF_EXTRA) + { + // The light is from an extra 3D floor... Check the flags so + // there are no undesired cuts. + if ((rlight->flags & (FF_FOG|FF_SWIMMABLE)) == (pfloor->flags & (FF_FOG|FF_SWIMMABLE))) + solid = 1; + } + else + solid = 1; + } + else + solid = 0; - // Calculate incremental stepping values for texture edges - R_WorldStep(range); + height = rlight->height; + rlight->height += rlight->heightstep; - // Create light lists - R_WorldLightLists(range); + if (solid) + { + bheight = rlight->botheight - (FRACUNIT >> 1); + rlight->botheight += rlight->botheightstep; + } - // Step FOFs - if (numffloors) - R_WorldFFloorStep(range); + if (height <= windowtop) + { + if (lighteffect) + dc_colormap = rlight->rcolormap; + if (solid && windowtop < bheight) + windowtop = bheight; + continue; + } - // Step world back - if (backsector) - R_WorldBackStep(range); + windowbottom = height; + if (windowbottom >= sprbotscreen) + { + windowbottom = sprbotscreen; + // draw the texture + colfunc_2s (col); + for (i++; i < dc_numlights; i++) + { + rlight = &dc_lightlist[i]; + rlight->height += rlight->heightstep; + if (rlight->flags & FF_CUTLEVEL) + rlight->botheight += rlight->botheightstep; + } + continue; + } + // draw the texture + colfunc_2s (col); + if (solid) + windowtop = bheight; + else + windowtop = windowbottom + 1; + if (lighteffect) + dc_colormap = rlight->rcolormap; + } + windowbottom = sprbotscreen; + // draw the texture, if there is any space left + if (windowtop < windowbottom) + colfunc_2s (col); - // Mark floor and or ceiling visplanes - R_MarkPlanes(); + spryscale += rw_scalestep; + continue; + } -#ifdef WALLSPLATS - if (linedef->splats && cv_splats.value) - { - // Isn't a bit wasteful to copy the ENTIRE array for every drawseg? - M_Memcpy(last_ceilingclip + ds_p->x1, ceilingclip + ds_p->x1, - sizeof (INT16) * (ds_p->x2 - ds_p->x1 + 1)); - M_Memcpy(last_floorclip + ds_p->x1, floorclip + ds_p->x1, - sizeof (INT16) * (ds_p->x2 - ds_p->x1 + 1)); - R_RenderSegLoop(); - R_DrawWallSplats(); - } - else -#endif - R_RenderSegLoop(); - colfunc = colfuncs[BASEDRAWFUNC]; + // calculate lighting + pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; - if (portalline) // if curline is a portal, set portalrender for drawseg - ds_p->portalpass = portalrender+1; - else - ds_p->portalpass = 0; + if (pindex >= MAXLIGHTSCALE) + pindex = MAXLIGHTSCALE - 1; - // save sprite clipping info - if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip) - { - M_Memcpy(lastopening, ceilingclip+start, 2*(rw_stopx - start)); - ds_p->sprtopclip = lastopening - start; - lastopening += rw_stopx - start; - } + dc_colormap = walllights[pindex]; - if (((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && !ds_p->sprbottomclip) - { - M_Memcpy(lastopening, floorclip + start, 2*(rw_stopx-start)); - ds_p->sprbottomclip = lastopening - start; - lastopening += rw_stopx - start; - } + if (pfloor->flags & FF_FOG && pfloor->master->frontsector->extra_colormap) + dc_colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc_colormap - colormaps); + else if (frontsector->extra_colormap) + dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); - if (maskedtexture && !(ds_p->silhouette & SIL_TOP)) - { - ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MIN: INT32_MAX; - } - if (maskedtexture && !(ds_p->silhouette & SIL_BOTTOM)) - { - ds_p->silhouette |= SIL_BOTTOM; - ds_p->bsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MAX: INT32_MIN; + // draw the texture + colfunc_2s (col); + spryscale += rw_scalestep; + } } + colfunc = colfuncs[BASEDRAWFUNC]; - ds_p++; +#undef CLAMPMAX +#undef CLAMPMIN }