RingRacers/src/r_segs.c
Sryder d4080e94f7 Better fake contrast.
Fake contrast for the segs are calculated at map load.
OpenGL only has the options "Standard" and "Smooth" now. Standard is default and replicates software. Smooth changes the contrast more smoothly depending on angle.
2020-05-21 16:32:34 +01:00

3187 lines
96 KiB
C

// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2018 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file r_segs.c
/// \brief All the clipping: columns, horizontal spans, sky columns
#include "doomdef.h"
#include "r_local.h"
#include "r_sky.h"
#include "r_splats.h"
#include "w_wad.h"
#include "z_zone.h"
#include "d_netcmd.h"
#include "m_misc.h"
#include "p_local.h" // Camera...
#include "p_slopes.h"
#include "console.h" // con_clipviewtop
// OPTIMIZE: closed two sided lines as single sided
// True if any of the segs textures might be visible.
static boolean segtextured;
static boolean markfloor; // False if the back side is the same plane.
static boolean markceiling;
static boolean maskedtexture;
static INT32 toptexture, bottomtexture, midtexture;
static INT32 numthicksides, numbackffloors;
angle_t rw_normalangle;
// angle to line origin
angle_t rw_angle1;
fixed_t rw_distance;
//
// regular wall
//
static INT32 rw_x, rw_stopx;
static angle_t rw_centerangle;
static fixed_t rw_offset;
static fixed_t rw_offset2; // for splats
static fixed_t rw_scale, rw_scalestep;
static fixed_t rw_midtexturemid, rw_toptexturemid, rw_bottomtexturemid;
static INT32 worldtop, worldbottom, worldhigh, worldlow;
#ifdef ESLOPE
static INT32 worldtopslope, worldbottomslope, worldhighslope, worldlowslope; // worldtop/bottom at end of slope
static fixed_t rw_toptextureslide, rw_midtextureslide, rw_bottomtextureslide; // Defines how to adjust Y offsets along the wall for slopes
static fixed_t rw_midtextureback, rw_midtexturebackslide; // Values for masked midtexture height calculation
#endif
static fixed_t pixhigh, pixlow, pixhighstep, pixlowstep;
static fixed_t topfrac, topstep;
static fixed_t bottomfrac, bottomstep;
static lighttable_t **walllights;
static INT16 *maskedtexturecol;
#ifdef ESLOPE
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)
{
INT32 topscreen, bottomscreen;
fixed_t basetexturemid;
INT32 topdelta, prevdelta = -1;
basetexturemid = dc_texturemid;
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;
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);
// Drawn by R_DrawColumn.
colfunc();
}
column = (column_t *)((UINT8 *)column + column->length + 4);
}
dc_texturemid = basetexturemid;
}
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;
splat = (wallsplat_t *)linedef->splats;
I_Assert(splat != NULL);
seg = ds_p->curline;
// 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 (x1 >= x2)
continue; // does not cross a pixel
// splat is not in this seg range
if (x2 < ds_p->x1 || x1 > ds_p->x2)
continue;
if (x1 < ds_p->x1)
x1 = ds_p->x1;
if (x2 > ds_p->x2)
x2 = ds_p->x2;
if (x2 <= x1)
continue;
// 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);
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 = basecolfunc;
break;
case SPLATDRAWMODE_TRANS:
if (!cv_translucency.value)
colfunc = basecolfunc;
else
{
dc_transmap = transtables + ((tr_trans50 - 1)<<FF_TRANSSHIFT);
colfunc = fuzzcolfunc;
}
break;
case SPLATDRAWMODE_SHADE:
colfunc = shadecolfunc;
break;
}
dc_texheight = 0;
// draw the columns
for (dc_x = x1; dc_x <= x2; dc_x++, spryscale += rw_scalestep)
{
pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE - 1;
dc_colormap = walllights[pindex];
if (encoremap && !(seg->linedef->flags & ML_TFERLINE))
dc_colormap += (256*32);
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
colfunc = basecolfunc;
}
#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)
{
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)
{
dc_yl = ((windowtop + FRACUNIT)>>FRACBITS);
dc_yh = (windowbottom - 1)>>FRACBITS;
}
if (dc_yh >= mfloorclip[dc_x])
dc_yh = mfloorclip[dc_x] - 1;
if (dc_yl <= mceilingclip[dc_x])
dc_yl = mceilingclip[dc_x] + 1;
if (dc_yl >= vid.height || dc_yh < 0)
return;
if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0)
{
dc_source = (UINT8 *)column + 3;
if (colfunc == wallcolfunc)
twosmultipatchfunc();
else if (colfunc == fuzzcolfunc)
twosmultipatchtransfunc();
else
colfunc();
}
}
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
// 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 = fuzzcolfunc;
break;
case 909:
colfunc = R_DrawFogColumn_8;
windowtop = frontsector->ceilingheight;
windowbottom = frontsector->floorheight;
break;
default:
colfunc = wallcolfunc;
break;
}
if (curline->polyseg && curline->polyseg->translucency > 0)
{
if (curline->polyseg->translucency >= NUMTRANSMAPS)
return;
dc_transmap = transtables + ((curline->polyseg->translucency-1)<<FF_TRANSSHIFT);
colfunc = fuzzcolfunc;
}
#ifdef ESLOPE
range = max(ds->x2-ds->x1, 1);
#endif
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)
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;
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
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 (rlight->flags & FF_FOG || (rlight->extra_colormap && rlight->extra_colormap->fog))
lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT);
else if (colfunc == fuzzcolfunc)
lightnum = LIGHTLEVELS - 1;
else
lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT);
if (rlight->extra_colormap && rlight->extra_colormap->fog)
;
else
lightnum += curline->lightOffset;
rlight->lightnum = lightnum;
}
}
else
{
if (colfunc == fuzzcolfunc)
{
if (frontsector->extra_colormap && frontsector->extra_colormap->fog)
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
else
lightnum = LIGHTLEVELS - 1;
}
else
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
if (colfunc == R_DrawFogColumn_8
|| (frontsector->extra_colormap && frontsector->extra_colormap->fog))
;
else
lightnum += curline->lightOffset;
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 = &sectors[frontsector->heightsec];
else
front = frontsector;
if (backsector->heightsec != -1)
back = &sectors[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)
{
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;
}
}
}
#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;
if (curline->linedef->flags & ML_DONTPEGBOTTOM)
dc_texturemid += (textureheight[texnum])*times;
else
dc_texturemid -= (textureheight[texnum])*times;
#endif
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];
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;
}
if (dc_numlights)
{
lighttable_t **xwalllights;
sprbotscreen = INT32_MAX;
sprtopscreen = windowtop = (centeryfrac - FixedMul(dc_texturemid, spryscale));
realbot = windowbottom = FixedMul(textureheight[texnum], spryscale) + sprtopscreen;
dc_iscale = 0xffffffffu / (unsigned)spryscale;
// draw the texture
col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3);
for (i = 0; i < dc_numlights; i++)
{
rlight = &dc_lightlist[i];
if ((rlight->flags & FF_NOSHADE))
continue;
if (rlight->lightnum < 0)
xwalllights = scalelight[0];
else if (rlight->lightnum >= LIGHTLEVELS)
xwalllights = scalelight[LIGHTLEVELS-1];
else
xwalllights = scalelight[rlight->lightnum];
pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE - 1;
if (rlight->extra_colormap)
rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps);
else
rlight->rcolormap = xwalllights[pindex];
height = rlight->height;
rlight->height += rlight->heightstep;
if (height <= windowtop)
{
dc_colormap = rlight->rcolormap;
if (encoremap && !(ldef->flags & ML_TFERLINE))
dc_colormap += (256*32);
continue;
}
windowbottom = height;
if (windowbottom >= realbot)
{
windowbottom = realbot;
colfunc_2s(col);
for (i++; i < dc_numlights; i++)
{
rlight = &dc_lightlist[i];
rlight->height += rlight->heightstep;
}
continue;
}
colfunc_2s(col);
windowtop = windowbottom + 1;
dc_colormap = rlight->rcolormap;
if (encoremap && !(ldef->flags & ML_TFERLINE))
dc_colormap += (256*32);
}
windowbottom = realbot;
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 (encoremap && !(ldef->flags & ML_TFERLINE))
dc_colormap += (256*32);
if (frontsector->extra_colormap)
dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
dc_iscale = 0xffffffffu / (unsigned)spryscale;
// draw the texture
col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3);
//#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;
my_topscreen = sprtopscreen + spryscale*col->topdelta;
my_bottomscreen = sprbotscreen == INT32_MAX ? my_topscreen + spryscale*col->length
: sprbotscreen + spryscale*col->length;
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;
for (i = 0; i < numffloors; i++)
{
if (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg)
continue;
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
colfunc_2s(col);
}
spryscale += rw_scalestep;
}
}
colfunc = wallcolfunc;
}
// 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;
}
}
//
// 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;
#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 = wallcolfunc;
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);
}
if (pfloor->flags & FF_TRANSLUCENT)
{
boolean fuzzy = true;
// 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 = fuzzcolfunc;
}
else if (pfloor->flags & FF_FOG)
colfunc = R_DrawFogColumn_8;
#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)
{
dc_maxlights = dc_numlights;
dc_lightlist = Z_Realloc(dc_lightlist, sizeof (*dc_lightlist) * dc_maxlights, PU_STATIC, NULL);
}
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)
if (leftheight < pfloorleft && rightheight < pfloorright)
continue;
SLOPEPARAMS(*pfloor->t_slope, pfloorleft, pfloorright, *pfloor->topheight)
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;
}
leftheight -= viewz;
rightheight -= viewz;
#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;
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
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->flags & FF_CUTLEVEL)
{
#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;
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
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;
// 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);
if (pfloor->flags & FF_FOG || rlight->flags & FF_FOG || (rlight->extra_colormap && rlight->extra_colormap->fog))
;
else
rlight->lightnum += curline->lightOffset;
p++;
}
dc_numlights = p;
}
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 == fuzzcolfunc)
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
lightnum += curline->lightOffset;
if (lightnum < 0)
walllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
walllights = scalelight[LIGHTLEVELS-1];
else
walllights = scalelight[lightnum];
}
maskedtexturecol = ds->thicksidecol;
mfloorclip = ds->sprbottomclip;
mceilingclip = ds->sprtopclip;
dc_texheight = textureheight[texnum]>>FRACBITS;
#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;
if (slopeskew)
dc_texturemid = left_top;
else
#endif
dc_texturemid = *pfloor->topheight - viewz;
if (newline)
{
offsetvalue = sides[newline->sidenum[0]].rowoffset;
if (newline->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;
}
}
else
{
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;
}
}
#ifdef ESLOPE
if (slopeskew)
{
angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y);
if (skewslope)
ffloortextureslide = FixedMul(skewslope->zdelta, FINECOSINE((lineangle-skewslope->xydirection)>>ANGLETOFINESHIFT));
}
#endif
dc_texturemid += offsetvalue;
// 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)
colfunc_2s = R_DrawRepeatMaskedColumn; //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;
}
#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;
// 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);
top_step = (top_step-top_frac)/(range);
bottom_step = (bottom_step-bottom_frac)/(range);
top_frac += top_step * (x1 - ds->x1);
bottom_frac += bottom_step * (x1 - ds->x1);
}
#endif
// draw the columns
for (dc_x = x1; dc_x <= x2; dc_x++)
{
if (maskedtexturecol[dc_x] != INT16_MAX)
{
#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 (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
// 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;
}
dc_iscale = 0xffffffffu / (unsigned)spryscale;
// Get data for the column
col = (column_t *)((UINT8 *)R_GetColumn(texnum,maskedtexturecol[dc_x]) - 3);
// 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;
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 (lightnum < 0)
xwalllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
xwalllights = scalelight[LIGHTLEVELS-1];
else
xwalllights = scalelight[lightnum];
pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE-1;
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 (encoremap && !(curline->linedef->flags & ML_TFERLINE))
dc_colormap += (256*32);
}
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;
if (encoremap && !(curline->linedef->flags & ML_TFERLINE))
dc_colormap += (256*32);
}
}
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 (encoremap && !(curline->linedef->flags & ML_TFERLINE))
dc_colormap += (256*32);
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;
}
}
colfunc = wallcolfunc;
#undef CLAMPMAX
#undef CLAMPMIN
}
//
// 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)
//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 ---------------------------------------------------------
static void R_RenderSegLoop (void)
{
angle_t angle;
size_t pindex;
INT32 yl;
INT32 yh;
INT32 mid;
fixed_t texturecolumn = 0;
#ifdef ESLOPE
fixed_t oldtexturecolumn = -1;
#endif
INT32 top;
INT32 bottom;
INT32 i;
for (; rw_x < rw_stopx; rw_x++)
{
// mark floor / ceiling areas
yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;
// no space above wall?
top = ceilingclip[rw_x]+1;
// no space above wall?
if (yl < top)
yl = top;
if (markceiling)
{
bottom = yl-1;
if (bottom >= floorclip[rw_x])
bottom = floorclip[rw_x]-1;
if (top <= bottom && ceilingplane)
{
ceilingplane->top[rw_x] = (INT16)top;
ceilingplane->bottom[rw_x] = (INT16)bottom;
}
}
yh = bottomfrac>>HEIGHTBITS;
bottom = floorclip[rw_x]-1;
if (yh > bottom)
yh = bottom;
if (markfloor)
{
top = yh < ceilingclip[rw_x] ? ceilingclip[rw_x] : yh;
if (++top <= bottom && floorplane)
{
floorplane->top[rw_x] = (INT16)top;
floorplane->bottom[rw_x] = (INT16)bottom;
}
}
if (numffloors)
{
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++)
{
#ifdef POLYOBJECTS_PLANES
if (ffloor[i].polyobj && (!curline->polyseg || ffloor[i].polyobj != curline->polyseg))
continue;
// 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) {
if (ffloor[i].plane->minx > rw_x)
ffloor[i].plane->minx = rw_x;
else if (ffloor[i].plane->maxx < rw_x)
ffloor[i].plane->maxx = rw_x;
}
#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 POLYOBJECTS_PLANES
// Polyobject-specific hack to fix plane leaking -Red
if (curline->polyseg && ffloor[i].polyobj && ffloor[i].polyobj == curline->polyseg && top_w >= bottom_w) {
ffloor[i].plane->top[rw_x] = ffloor[i].plane->bottom[rw_x] = 0xFFFF;
} else
#endif
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);
if (top_w < top)
top_w = top;
if (bottom_w > bottom)
bottom_w = bottom;
#ifdef POLYOBJECTS_PLANES
// Polyobject-specific hack to fix plane leaking -Red
if (curline->polyseg && ffloor[i].polyobj && ffloor[i].polyobj == curline->polyseg && top_w >= bottom_w) {
ffloor[i].plane->top[rw_x] = ffloor[i].plane->bottom[rw_x] = 0xFFFF;
} else
#endif
if (top_w <= bottom_w)
{
ffloor[i].plane->top[rw_x] = (INT16)top_w;
ffloor[i].plane->bottom[rw_x] = (INT16)bottom_w;
}
}
}
}
//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);
#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
texturecolumn >>= FRACBITS;
// texturecolumn and lighting are independent of wall tiers
if (segtextured)
{
// calculate lighting
pindex = FixedMul(rw_scale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE-1;
dc_colormap = walllights[pindex];
if (encoremap && !(curline->linedef->flags & ML_TFERLINE))
dc_colormap += (256*32);
dc_x = rw_x;
dc_iscale = 0xffffffffu / (unsigned)rw_scale;
if (frontsector->extra_colormap)
dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
}
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
lightnum += curline->lightOffset;
if (lightnum < 0)
xwalllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
xwalllights = scalelight[LIGHTLEVELS-1];
else
xwalllights = scalelight[lightnum];
pindex = FixedMul(rw_scale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE-1;
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];
colfunc = R_DrawColumnShadowed_8;
}
}
frontscale[rw_x] = rw_scale;
// 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;
//profile stuff ---------------------------------------------------------
#ifdef TIMING
ProfZeroTimer();
#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);
#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;
}
}
else
{
// two sided line
if (toptexture)
{
// top wall
mid = pixhigh>>HEIGHTBITS;
pixhigh += pixhighstep;
if (mid >= floorclip[rw_x])
mid = floorclip[rw_x]-1;
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 (bottomtexture)
{
// bottom wall
mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS;
pixlow += pixlowstep;
// no space above wall?
if (mid <= ceilingclip[rw_x])
mid = ceilingclip[rw_x]+1;
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;
}
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));
}
#endif
}
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;
}
}
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;
}
}
// Uses precalculated seg->length
static INT64 R_CalcSegDist(seg_t* seg, INT64 x2, INT64 y2)
{
if (!seg->linedef->dy)
return llabs(y2 - seg->v1->y);
else if (!seg->linedef->dx)
return 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);
return ((dy*vdx)-(dx*vdy))/(seg->length);
}
}
//
// 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;
#endif
INT32 lightnum;
INT32 i, p;
lightlist_t *light;
r_lightlist_t *rlight;
INT32 range;
#ifdef ESLOPE
vertex_t segleft, segright;
fixed_t ceilingfrontslide, floorfrontslide, ceilingbackslide, floorbackslide;
#endif
static size_t maxdrawsegs = 0;
#ifdef ESLOPE
maskedtextureheight = NULL;
//initialize segleft and segright
memset(&segleft, 0x00, sizeof(segleft));
memset(&segright, 0x00, sizeof(segright));
#endif
if (ds_p == drawsegs+maxdrawsegs)
{
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;
if (firstseg)
firstseg = drawsegs + (size_t)firstseg;
}
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;
distangle = ANGLE_90 - offsetangle;
sineval = FINESINE(distangle>>ANGLETOFINESHIFT);
hyp = R_PointToDist(curline->v1->x, curline->v1->y);
rw_distance = FixedMul(hyp, sineval);
longboi = (hyp >= INT32_MAX);
// big room fix
if (longboi)
rw_distance = (fixed_t)R_CalcSegDist(curline,viewx,viewy);
ds_p->x1 = rw_x = start;
ds_p->x2 = stop;
ds_p->curline = curline;
rw_stopx = stop+1;
//SoM: Code to remove limits on openings.
{
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;
do
maxopenings = maxopenings ? maxopenings*2 : 16384;
while (need > maxopenings);
openings = Z_Realloc(openings, maxopenings * sizeof (*openings), PU_STATIC, NULL);
lastopening = openings + pos;
// 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
}
}
} // end of code to remove limits on openings
// calculate scale at both ends and step
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
{
// 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");
tr_x = curline->v1->x - viewx;
tr_y = curline->v1->y - viewy;
gxt = FixedMul(tr_x, viewcos);
gyt = -FixedMul(tr_y, viewsin);
ds_p->scale1 = FixedDiv(projection, gxt - gyt);
}
#endif
ds_p->scale2 = ds_p->scale1;
range = 1;
}
ds_p->scalestep = rw_scalestep = (ds_p->scale2 - rw_scale) / (range);
// calculate texture boundaries
// and decide if floor / ceiling marks are needed
#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;
// left
temp = xtoviewangle[start]+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
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);
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);
det = a1*b2 - a2*b1;
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);
}
// 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
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);
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);
det = a1*b2 - a2*b1;
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);
}
}
if (frontsector->c_slope) {
worldtop = P_GetZAt(frontsector->c_slope, segleft.x, segleft.y) - viewz;
worldtopslope = P_GetZAt(frontsector->c_slope, segright.x, segright.y) - viewz;
} else {
worldtopslope =
#else
{
#endif
worldtop = frontsector->ceilingheight - viewz;
}
#ifdef ESLOPE
if (frontsector->f_slope) {
worldbottom = P_GetZAt(frontsector->f_slope, segleft.x, segleft.y) - viewz;
worldbottomslope = P_GetZAt(frontsector->f_slope, segright.x, segright.y) - viewz;
} else {
worldbottomslope =
#else
{
#endif
worldbottom = frontsector->floorheight - viewz;
}
midtexture = toptexture = bottomtexture = maskedtexture = 0;
ds_p->maskedtexturecol = NULL;
ds_p->numthicksides = numthicksides = 0;
ds_p->thicksidecol = NULL;
ds_p->tsilheight = 0;
numbackffloors = 0;
for (i = 0; i < MAXFFLOORS; i++)
ds_p->thicksides[i] = NULL;
if (numffloors)
{
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
#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;
}
}
#ifdef ESLOPE
// Set up texture Y offset slides for sloped walls
rw_toptextureslide = rw_midtextureslide = rw_bottomtextureslide = 0;
ceilingfrontslide = floorfrontslide = ceilingbackslide = floorbackslide = 0;
{
angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y);
if (frontsector->f_slope)
floorfrontslide = FixedMul(frontsector->f_slope->zdelta, FINECOSINE((lineangle-frontsector->f_slope->xydirection)>>ANGLETOFINESHIFT));
if (frontsector->c_slope)
ceilingfrontslide = FixedMul(frontsector->c_slope->zdelta, FINECOSINE((lineangle-frontsector->c_slope->xydirection)>>ANGLETOFINESHIFT));
if (backsector && backsector->f_slope)
floorbackslide = FixedMul(backsector->f_slope->zdelta, FINECOSINE((lineangle-backsector->f_slope->xydirection)>>ANGLETOFINESHIFT));
if (backsector && backsector->c_slope)
ceilingbackslide = FixedMul(backsector->c_slope->zdelta, FINECOSINE((lineangle-backsector->c_slope->xydirection)>>ANGLETOFINESHIFT));
}
#endif
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;
ds_p->silhouette = SIL_BOTH;
ds_p->sprtopclip = screenheightarray;
ds_p->sprbottomclip = negonearray;
ds_p->bsilheight = INT32_MAX;
ds_p->tsilheight = INT32_MIN;
}
else
{
// two sided line
#ifdef ESLOPE
if (backsector->c_slope) {
worldhigh = P_GetZAt(backsector->c_slope, segleft.x, segleft.y) - viewz;
worldhighslope = P_GetZAt(backsector->c_slope, segright.x, segright.y) - viewz;
} else {
worldhighslope =
#else
{
#endif
worldhigh = backsector->ceilingheight - viewz;
}
#ifdef ESLOPE
if (backsector->f_slope) {
worldlow = P_GetZAt(backsector->f_slope, segleft.x, segleft.y) - viewz;
worldlowslope = P_GetZAt(backsector->f_slope, segright.x, segright.y) - viewz;
} else {
worldlowslope =
#else
{
#endif
worldlow = backsector->floorheight - viewz;
}
// hack to allow height changes in outdoor areas
if (frontsector->ceilingpic == skyflatnum
&& backsector->ceilingpic == skyflatnum)
{
#ifdef ESLOPE
worldtopslope = worldhighslope =
#endif
worldtop = worldhigh;
}
ds_p->sprtopclip = ds_p->sprbottomclip = NULL;
ds_p->silhouette = 0;
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;
}
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
}
#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;
}
if (viewsector != frontsector && viewsector != backsector)
{
#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;
}
#ifdef ESLOPE
if (worldlow >= worldtop && worldlowslope >= worldtopslope)
#else
if (worldlow >= worldtop)
#endif
{
ds_p->sprtopclip = screenheightarray;
ds_p->tsilheight = INT32_MIN;
ds_p->silhouette |= SIL_TOP;
}
//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.
{
#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;
}
}
}
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
|| 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;
}
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;
}
if (backsector->ceilingheight <= frontsector->floorheight ||
backsector->floorheight >= frontsector->ceilingheight)
{
// closed door
markceiling = markfloor = true;
}
// check TOP TEXTURE
if (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
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
}
}
// check BOTTOM TEXTURE
if (worldlow > worldbottom
#ifdef ESLOPE
|| worldlowslope > worldbottomslope
#endif
) //seulement si VISIBLE!!!
{
// bottom texture
bottomtexture = R_GetTextureNum(sidedef->bottomtexture);
#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
}
}
rw_toptexturemid += sidedef->rowoffset;
rw_bottomtexturemid += sidedef->rowoffset;
// 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;
// Used for height comparisons and etc across FOFs and slopes
fixed_t high1, highslope1, low1, lowslope1, high2, highslope2, low2, lowslope2;
#endif
//markceiling = markfloor = true;
maskedtexture = true;
ds_p->thicksidecol = maskedtexturecol = lastopening - rw_x;
lastopening += rw_stopx - rw_x;
lowcut = max(worldbottom, worldlow) + viewz;
highcut = min(worldtop, worldhigh) + viewz;
#ifdef ESLOPE
lowcutslope = max(worldbottomslope, worldlowslope) + viewz;
highcutslope = min(worldtopslope, worldhighslope) + viewz;
#endif
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;
if (rover->norender == leveltime)
continue;
#ifdef ESLOPE
if (*rover->t_slope) {
high1 = P_GetZAt(*rover->t_slope, segleft.x, segleft.y);
highslope1 = P_GetZAt(*rover->t_slope, segright.x, segright.y);
} else
high1 = highslope1 = *rover->topheight;
if (*rover->b_slope) {
low1 = P_GetZAt(*rover->b_slope, segleft.x, segleft.y);
lowslope1 = P_GetZAt(*rover->b_slope, segright.x, segright.y);
} else
low1 = lowslope1 = *rover->bottomheight;
if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope))
continue;
#else
if (*rover->topheight < lowcut || *rover->bottomheight > highcut)
continue;
#endif
for (r2 = frontsector->ffloors; r2; r2 = r2->next)
{
if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES))
continue;
if (r2->norender == leveltime)
continue;
if (rover->flags & FF_EXTRA)
{
if (!(r2->flags & FF_CUTEXTRA))
continue;
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;
}
#ifdef ESLOPE
if (*r2->t_slope) {
high2 = P_GetZAt(*r2->t_slope, segleft.x, segleft.y);
highslope2 = P_GetZAt(*r2->t_slope, segright.x, segright.y);
} else
high2 = highslope2 = *r2->topheight;
if (*r2->b_slope) {
low2 = P_GetZAt(*r2->b_slope, segleft.x, segleft.y);
lowslope2 = P_GetZAt(*r2->b_slope, segright.x, segright.y);
} else
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
break;
}
if (r2)
continue;
ds_p->thicksides[i] = rover;
i++;
}
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 (rover->norender == leveltime)
continue;
#ifdef ESLOPE
if (*rover->t_slope) {
high1 = P_GetZAt(*rover->t_slope, segleft.x, segleft.y);
highslope1 = P_GetZAt(*rover->t_slope, segright.x, segright.y);
} else
high1 = highslope1 = *rover->topheight;
if (*rover->b_slope) {
low1 = P_GetZAt(*rover->b_slope, segleft.x, segleft.y);
lowslope1 = P_GetZAt(*rover->b_slope, segright.x, segright.y);
} else
low1 = lowslope1 = *rover->bottomheight;
if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope))
continue;
#else
if (*rover->topheight < lowcut || *rover->bottomheight > highcut)
continue;
#endif
for (r2 = backsector->ffloors; r2; r2 = r2->next)
{
if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES))
continue;
if (r2->norender == leveltime)
continue;
if (rover->flags & FF_EXTRA)
{
if (!(r2->flags & FF_CUTEXTRA))
continue;
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;
}
#ifdef ESLOPE
if (*r2->t_slope) {
high2 = P_GetZAt(*r2->t_slope, segleft.x, segleft.y);
highslope2 = P_GetZAt(*r2->t_slope, segright.x, segright.y);
} else
high2 = highslope2 = *r2->topheight;
if (*r2->b_slope) {
low2 = P_GetZAt(*r2->b_slope, segleft.x, segleft.y);
lowslope2 = P_GetZAt(*r2->b_slope, segright.x, segright.y);
} else
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
break;
}
if (r2)
continue;
ds_p->thicksides[i] = rover;
i++;
}
}
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;
#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
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 (( (*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
ds_p->thicksides[i] = rover;
i++;
}
}
ds_p->numthicksides = numthicksides = i;
}
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
ds_p->maskedtexturecol = ds_p->thicksidecol;
#ifdef ESLOPE
maskedtextureheight = ds_p->maskedtextureheight; // note to red, this == &(ds_p->maskedtextureheight[0])
#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;
} 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;
}
}
// calculate rw_offset (only needed for textured lines)
segtextured = midtexture || toptexture || bottomtexture || maskedtexture || (numthicksides > 0);
if (segtextured)
{
offsetangle = rw_normalangle-rw_angle1;
if (offsetangle > ANGLE_180)
offsetangle = -(signed)offsetangle;
if (offsetangle > ANGLE_90)
offsetangle = ANGLE_90;
sineval = FINESINE(offsetangle>>ANGLETOFINESHIFT);
rw_offset = FixedMul(hyp, sineval);
// 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 (rw_normalangle-rw_angle1 < ANGLE_180)
rw_offset = -rw_offset;
/// 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;
// calculate light table
// use different light tables
// for horizontal / vertical / diagonal
// OPTIMIZE: get rid of LIGHTSEGSHIFT globally
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
lightnum += curline->lightOffset;
if (lightnum < 0)
walllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
walllights = scalelight[LIGHTLEVELS - 1];
else
walllights = scalelight[lightnum];
}
// 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 ((
#ifdef ESLOPE
frontsector->f_slope ? P_GetZAt(frontsector->f_slope, viewx, viewy) :
#endif
frontsector->floorheight) >= viewz)
{
// above view plane
markfloor = false;
}
if ((
#ifdef ESLOPE
frontsector->c_slope ? P_GetZAt(frontsector->c_slope, viewx, viewy) :
#endif
frontsector->ceilingheight) <= viewz &&
frontsector->ceilingpic != skyflatnum)
{
// below view plane
markceiling = false;
}
}
// calculate incremental stepping values for texture edges
worldtop >>= 4;
worldbottom >>= 4;
#ifdef ESLOPE
worldtopslope >>= 4;
worldbottomslope >>= 4;
#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);
#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
}
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 = p = 0; i < dc_numlights; i++)
{
#ifdef ESLOPE
fixed_t leftheight, rightheight;
#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;
leftheight -= viewz;
rightheight -= viewz;
leftheight >>= 4;
rightheight >>= 4;
#endif
if (i != 0)
{
#ifdef ESLOPE
if (leftheight < worldbottom && rightheight < worldbottomslope)
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;
if (light->height > frontsector->ceilingheight && i+1 < dc_numlights && frontsector->lightlist[i+1].height > frontsector->ceilingheight)
continue;
#endif
}
#ifdef ESLOPE
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 (light->caster && light->caster->flags & FF_CUTSOLIDS)
{
#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;
leftheight -= viewz;
rightheight -= viewz;
leftheight >>= 4;
rightheight >>= 4;
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;
}
if (numffloors)
{
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.
{
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
}
}
}
if (backsector)
{
worldhigh >>= 4;
worldlow >>= 4;
#ifdef ESLOPE
worldhighslope >>= 4;
worldlowslope >>= 4;
#endif
if (toptexture)
{
pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale);
pixhighstep = -FixedMul (rw_scalestep,worldhigh);
#ifdef ESLOPE
if (backsector->c_slope) {
fixed_t topfracend = (centeryfrac>>4) - FixedMul (worldhighslope, ds_p->scale2);
pixhighstep = (topfracend-pixhigh)/(range);
}
#endif
}
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
}
{
ffloor_t * rover;
#ifdef ESLOPE
fixed_t roverleft, roverright;
fixed_t planevistest;
#endif
i = 0;
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;
#ifdef ESLOPE
// Let the renderer know this sector is sloped.
if (*rover->b_slope || *rover->t_slope)
backsector->hasslope = true;
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++;
}
if (i >= MAXFFLOORS)
break;
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 ((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 (i >= MAXFFLOORS)
break;
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)
continue;
#ifdef ESLOPE
// Let the renderer know this sector is sloped.
if (*rover->b_slope || *rover->t_slope)
frontsector->hasslope = true;
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++;
}
if (i >= MAXFFLOORS)
break;
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 ((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
}
}
#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;
if (ffloor[i].plane->maxx < ds_p->x2)
ffloor[i].plane->maxx = ds_p->x2;
#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 (ffloor[i].plane->maxx < ds_p->x2)
ffloor[i].plane->maxx = ds_p->x2;
#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
numbackffloors = i;
}
}
// 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;
// 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;
}
// get a new or use the same visplane
if (markfloor)
{
if (floorplane) //SoM: 3/29/2000: Check for null planes
floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-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);
}
firstseg = ds_p;
}
else
{
for (i = 0; i < numffloors; i++)
R_ExpandPlane(ffloor[i].plane, rw_x, rw_stopx - 1);
}
}
#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 = wallcolfunc;
if (portalline) // if curline is a portal, set portalrender for drawseg
ds_p->portalpass = portalrender+1;
else
ds_p->portalpass = 0;
// 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;
}
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 (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;
}
ds_p++;
}