123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855 |
- /* Emacs style mode select -*- C++ -*-
- *-----------------------------------------------------------------------------
- *
- *
- * PrBoom: a Doom port merged with LxDoom and LSDLDoom
- * based on BOOM, a modified and improved DOOM engine
- * Copyright (C) 1999 by
- * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
- * Copyright (C) 1999-2004 by
- * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
- * Copyright 2005, 2006 by
- * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * DESCRIPTION:
- * All the clipping: columns, horizontal spans, sky columns.
- *
- *-----------------------------------------------------------------------------*/
- //
- // 4/25/98, 5/2/98 killough: reformatted, beautified
- #include "doomstat.h"
- #include "r_main.h"
- #include "r_bsp.h"
- #include "r_segs.h"
- #include "r_plane.h"
- #include "r_things.h"
- #include "r_draw.h"
- #include "w_wad.h"
- #include "v_video.h"
- #include "lprintf.h"
- // OPTIMIZE: closed two sided lines as single sided
- // killough 1/6/98: replaced globals with statics where appropriate
- // 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 int toptexture;
- static int bottomtexture;
- static int midtexture;
- static fixed_t toptexheight, midtexheight, bottomtexheight; // cph
- angle_t rw_normalangle; // angle to line origin
- int rw_angle1;
- fixed_t rw_distance;
- //
- // regular wall
- //
- static int rw_x;
- static int rw_stopx;
- static angle_t rw_centerangle;
- static fixed_t rw_offset;
- static fixed_t rw_scale;
- static fixed_t rw_scalestep;
- static fixed_t rw_midtexturemid;
- static fixed_t rw_toptexturemid;
- static fixed_t rw_bottomtexturemid;
- static int rw_lightlevel;
- static int worldtop;
- static int worldbottom;
- static int worldhigh;
- static int worldlow;
- static fixed_t pixhigh;
- static fixed_t pixlow;
- static fixed_t pixhighstep;
- static fixed_t pixlowstep;
- static fixed_t topfrac;
- static fixed_t topstep;
- static fixed_t bottomfrac;
- static fixed_t bottomstep;
- static int *maskedtexturecol; // dropoff overflow
- //
- // R_ScaleFromGlobalAngle
- // Returns the texture mapping scale
- // for the current line (horizontal span)
- // at the given angle.
- // rw_distance must be calculated first.
- //
- // killough 5/2/98: reformatted, cleaned up
- // CPhipps - moved here from r_main.c
- static fixed_t R_ScaleFromGlobalAngle(angle_t visangle)
- {
- int anglea = ANG90 + (visangle-viewangle);
- int angleb = ANG90 + (visangle-rw_normalangle);
- int den = FixedMul(rw_distance, finesine[anglea>>ANGLETOFINESHIFT]);
- // proff 11/06/98: Changed for high-res
- fixed_t num = FixedMul(projectiony, finesine[angleb>>ANGLETOFINESHIFT]);
- return den > num>>16 ? (num = FixedDiv(num, den)) > 64*FRACUNIT ?
- 64*FRACUNIT : num < 256 ? 256 : num : 64*FRACUNIT;
- }
- //
- // R_RenderMaskedSegRange
- //
- void R_RenderMaskedSegRange(drawseg_t *ds, int x1, int x2)
- {
- int texnum;
- sector_t tempsec; // killough 4/13/98
- const rpatch_t *patch;
- R_DrawColumn_f colfunc;
- draw_column_vars_t dcvars;
- angle_t angle;
- R_SetDefaultDrawColumnVars(&dcvars);
- // Calculate light table.
- // Use different light tables
- // for horizontal / vertical / diagonal. Diagonal?
- curline = ds->curline; // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
- // killough 4/11/98: draw translucent 2s normal textures
- colfunc = R_GetDrawColumnFunc(RDC_PIPELINE_STANDARD, drawvars.filterwall, drawvars.filterz);
- if (curline->linedef->tranlump >= 0 && general_translucency)
- {
- colfunc = R_GetDrawColumnFunc(RDC_PIPELINE_TRANSLUCENT, drawvars.filterwall, drawvars.filterz);
- tranmap = main_tranmap;
- if (curline->linedef->tranlump > 0)
- tranmap = W_CacheLumpNum(curline->linedef->tranlump-1);
- }
- // killough 4/11/98: end translucent 2s normal code
- frontsector = curline->frontsector;
- backsector = curline->backsector;
- // cph 2001/11/25 - middle textures did not animate in v1.2
- texnum = curline->sidedef->midtexture;
- if (!comp[comp_maskedanim])
- texnum = texturetranslation[texnum];
- // killough 4/13/98: get correct lightlevel for 2s normal textures
- rw_lightlevel = R_FakeFlat(frontsector, &tempsec, NULL, NULL, false) ->lightlevel;
- maskedtexturecol = ds->maskedtexturecol;
- rw_scalestep = ds->scalestep;
- spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
- mfloorclip = ds->sprbottomclip;
- mceilingclip = ds->sprtopclip;
- // find positioning
- if (curline->linedef->flags & ML_DONTPEGBOTTOM)
- {
- dcvars.texturemid = frontsector->floorheight > backsector->floorheight
- ? frontsector->floorheight : backsector->floorheight;
- dcvars.texturemid = dcvars.texturemid + textureheight[texnum] - viewz;
- }
- else
- {
- dcvars.texturemid =frontsector->ceilingheight<backsector->ceilingheight
- ? frontsector->ceilingheight : backsector->ceilingheight;
- dcvars.texturemid = dcvars.texturemid - viewz;
- }
- dcvars.texturemid += curline->sidedef->rowoffset;
- if (fixedcolormap) {
- dcvars.colormap = fixedcolormap;
- dcvars.nextcolormap = dcvars.colormap; // for filtering -- POPE
- }
- patch = R_CacheTextureCompositePatchNum(texnum);
- // draw the columns
- for (dcvars.x = x1 ; dcvars.x <= x2 ; dcvars.x++, spryscale += rw_scalestep)
- if (maskedtexturecol[dcvars.x] != INT_MAX) // dropoff overflow
- {
- // calculate texture offset - POPE
- angle = (ds->rw_centerangle + xtoviewangle[dcvars.x]) >> ANGLETOFINESHIFT;
- dcvars.texu = ds->rw_offset - FixedMul(finetangent[angle], ds->rw_distance);
- if (drawvars.filterwall == RDRAW_FILTER_LINEAR)
- dcvars.texu -= (FRACUNIT>>1);
- if (!fixedcolormap)
- dcvars.z = spryscale; // for filtering -- POPE
- dcvars.colormap = R_ColourMap(rw_lightlevel,spryscale);
- dcvars.nextcolormap = R_ColourMap(rw_lightlevel+1,spryscale); // for filtering -- POPE
- // killough 3/2/98:
- //
- // This calculation used to overflow and cause crashes in Doom:
- //
- // sprtopscreen = centeryfrac - FixedMul(dcvars.texturemid, spryscale);
- //
- // This code fixes it, by using double-precision intermediate
- // arithmetic and by skipping the drawing of 2s normals whose
- // mapping to screen coordinates is totally out of range:
- {
- int_64_t t = ((int_64_t) centeryfrac << FRACBITS) -
- (int_64_t) dcvars.texturemid * spryscale;
- if (t + (int_64_t) textureheight[texnum] * spryscale < 0 ||
- t > (int_64_t) MAX_SCREENHEIGHT << FRACBITS*2)
- continue; // skip if the texture is out of screen's range
- sprtopscreen = (long)(t >> FRACBITS);
- }
- dcvars.iscale = 0xffffffffu / (unsigned) spryscale;
- // killough 1/25/98: here's where Medusa came in, because
- // it implicitly assumed that the column was all one patch.
- // Originally, Doom did not construct complete columns for
- // multipatched textures, so there were no header or trailer
- // bytes in the column referred to below, which explains
- // the Medusa effect. The fix is to construct true columns
- // when forming multipatched textures (see r_data.c).
- // draw the texture
- R_DrawMaskedColumn(
- patch,
- colfunc,
- &dcvars,
- R_GetPatchColumnWrapped(patch, maskedtexturecol[dcvars.x]),
- R_GetPatchColumnWrapped(patch, maskedtexturecol[dcvars.x]-1),
- R_GetPatchColumnWrapped(patch, maskedtexturecol[dcvars.x]+1)
- );
- maskedtexturecol[dcvars.x] = INT_MAX; // dropoff overflow
- }
- // Except for main_tranmap, mark others purgable at this point
- if (curline->linedef->tranlump > 0 && general_translucency)
- W_UnlockLumpNum(curline->linedef->tranlump-1); // cph - unlock it
- R_UnlockTextureCompositePatchNum(texnum);
- curline = NULL; /* cph 2001/11/18 - must clear curline now we're done with it, so R_ColourMap doesn't try using it for other things */
- }
- //
- // 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)
- static int didsolidcol; /* True if at least one column was marked solid */
- static void R_RenderSegLoop (void)
- {
- const rpatch_t *tex_patch;
- R_DrawColumn_f colfunc = R_GetDrawColumnFunc(RDC_PIPELINE_STANDARD, drawvars.filterwall, drawvars.filterz);
- draw_column_vars_t dcvars;
- fixed_t texturecolumn = 0; // shut up compiler warning
- R_SetDefaultDrawColumnVars(&dcvars);
- rendered_segs++;
- for ( ; rw_x < rw_stopx ; rw_x++)
- {
- // mark floor / ceiling areas
- int yh = bottomfrac>>HEIGHTBITS;
- int yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;
- // no space above wall?
- int bottom,top = ceilingclip[rw_x]+1;
- if (yl < top)
- yl = top;
- if (markceiling)
- {
- bottom = yl-1;
- if (bottom >= floorclip[rw_x])
- bottom = floorclip[rw_x]-1;
- if (top <= bottom)
- {
- ceilingplane->top[rw_x] = top;
- ceilingplane->bottom[rw_x] = bottom;
- }
- // SoM: this should be set here
- ceilingclip[rw_x] = 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->top[rw_x] = top;
- floorplane->bottom[rw_x] = bottom;
- }
- // SoM: This should be set here to prevent overdraw
- floorclip[rw_x] = top;
- }
- // texturecolumn and lighting are independent of wall tiers
- if (segtextured)
- {
- // calculate texture offset
- angle_t angle =(rw_centerangle+xtoviewangle[rw_x])>>ANGLETOFINESHIFT;
- texturecolumn = rw_offset-FixedMul(finetangent[angle],rw_distance);
- if (drawvars.filterwall == RDRAW_FILTER_LINEAR)
- texturecolumn -= (FRACUNIT>>1);
- dcvars.texu = texturecolumn; // for filtering -- POPE
- texturecolumn >>= FRACBITS;
- dcvars.colormap = R_ColourMap(rw_lightlevel,rw_scale);
- dcvars.nextcolormap = R_ColourMap(rw_lightlevel+1,rw_scale); // for filtering -- POPE
- dcvars.z = rw_scale; // for filtering -- POPE
- dcvars.x = rw_x;
- dcvars.iscale = 0xffffffffu / (unsigned)rw_scale;
- }
- // draw the wall tiers
- if (midtexture)
- {
- dcvars.yl = yl; // single sided line
- dcvars.yh = yh;
- dcvars.texturemid = rw_midtexturemid;
- tex_patch = R_CacheTextureCompositePatchNum(midtexture);
- dcvars.source = R_GetTextureColumn(tex_patch, texturecolumn);
- dcvars.prevsource = R_GetTextureColumn(tex_patch, texturecolumn-1);
- dcvars.nextsource = R_GetTextureColumn(tex_patch, texturecolumn+1);
- dcvars.texheight = midtexheight;
- colfunc (&dcvars);
- R_UnlockTextureCompositePatchNum(midtexture);
- tex_patch = NULL;
- ceilingclip[rw_x] = viewheight;
- floorclip[rw_x] = -1;
- }
- else
- {
- // two sided line
- if (toptexture)
- {
- // top wall
- int mid = pixhigh>>HEIGHTBITS;
- pixhigh += pixhighstep;
- if (mid >= floorclip[rw_x])
- mid = floorclip[rw_x]-1;
- if (mid >= yl)
- {
- dcvars.yl = yl;
- dcvars.yh = mid;
- dcvars.texturemid = rw_toptexturemid;
- tex_patch = R_CacheTextureCompositePatchNum(toptexture);
- dcvars.source = R_GetTextureColumn(tex_patch,texturecolumn);
- dcvars.prevsource = R_GetTextureColumn(tex_patch,texturecolumn-1);
- dcvars.nextsource = R_GetTextureColumn(tex_patch,texturecolumn+1);
- dcvars.texheight = toptexheight;
- colfunc (&dcvars);
- R_UnlockTextureCompositePatchNum(toptexture);
- tex_patch = NULL;
- ceilingclip[rw_x] = mid;
- }
- else
- ceilingclip[rw_x] = yl-1;
- }
- else // no top wall
- {
- if (markceiling)
- ceilingclip[rw_x] = yl-1;
- }
- if (bottomtexture) // bottom wall
- {
- int mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS;
- pixlow += pixlowstep;
- // no space above wall?
- if (mid <= ceilingclip[rw_x])
- mid = ceilingclip[rw_x]+1;
- if (mid <= yh)
- {
- dcvars.yl = mid;
- dcvars.yh = yh;
- dcvars.texturemid = rw_bottomtexturemid;
- tex_patch = R_CacheTextureCompositePatchNum(bottomtexture);
- dcvars.source = R_GetTextureColumn(tex_patch, texturecolumn);
- dcvars.prevsource = R_GetTextureColumn(tex_patch, texturecolumn-1);
- dcvars.nextsource = R_GetTextureColumn(tex_patch, texturecolumn+1);
- dcvars.texheight = bottomtexheight;
- colfunc (&dcvars);
- R_UnlockTextureCompositePatchNum(bottomtexture);
- tex_patch = NULL;
- floorclip[rw_x] = mid;
- }
- else
- floorclip[rw_x] = yh+1;
- }
- else // no bottom wall
- {
- if (markfloor)
- floorclip[rw_x] = yh+1;
- }
- // cph - if we completely blocked further sight through this column,
- // add this info to the solid columns array for r_bsp.c
- if ((markceiling || markfloor) &&
- (floorclip[rw_x] <= ceilingclip[rw_x] + 1)) {
- solidcol[rw_x] = 1; didsolidcol = 1;
- }
- // save texturecol for backdrawing of masked mid texture
- if (maskedtexture)
- maskedtexturecol[rw_x] = texturecolumn;
- }
- rw_scale += rw_scalestep;
- topfrac += topstep;
- bottomfrac += bottomstep;
- }
- }
- // killough 5/2/98: move from r_main.c, made static, simplified
- static fixed_t R_PointToDist(fixed_t x, fixed_t y)
- {
- fixed_t dx = D_abs(x - viewx);
- fixed_t dy = D_abs(y - viewy);
- if (dy > dx)
- {
- fixed_t t = dx;
- dx = dy;
- dy = t;
- }
- return FixedDiv(dx, finesine[(tantoangle[FixedDiv(dy,dx) >> DBITS]
- + ANG90) >> ANGLETOFINESHIFT]);
- }
- //
- // R_StoreWallRange
- // A wall segment will be drawn
- // between start and stop pixels (inclusive).
- //
- void R_StoreWallRange(const int start, const int stop)
- {
- fixed_t hyp;
- angle_t offsetangle;
- if (ds_p == drawsegs+maxdrawsegs) // killough 1/98 -- fix 2s line HOM
- {
- unsigned pos = ds_p - drawsegs; // jff 8/9/98 fix from ZDOOM1.14a
- unsigned newmax = maxdrawsegs ? maxdrawsegs*2 : 128; // killough
- drawsegs = realloc(drawsegs,newmax*sizeof(*drawsegs));
- ds_p = drawsegs + pos; // jff 8/9/98 fix from ZDOOM1.14a
- maxdrawsegs = newmax;
- }
- if(curline->miniseg == false) // figgi -- skip minisegs
- curline->linedef->flags |= ML_MAPPED;
- #ifdef GL_DOOM
- if (V_GetMode() == VID_MODEGL)
- {
- // proff 11/99: the rest of the calculations is not needed for OpenGL
- ds_p++->curline = curline;
- gld_AddWall(curline);
- return;
- }
- #endif
- #ifdef RANGECHECK
- if (start >=viewwidth || start > stop)
- I_Error ("Bad R_RenderWallRange: %i to %i", start , stop);
- #endif
- sidedef = curline->sidedef;
- linedef = curline->linedef;
- // mark the segment as visible for auto map
- linedef->flags |= ML_MAPPED;
- // calculate rw_distance for scale calculation
- rw_normalangle = curline->angle + ANG90;
- offsetangle = rw_normalangle-rw_angle1;
- if (D_abs(offsetangle) > ANG90)
- offsetangle = ANG90;
- hyp = (viewx==curline->v1->x && viewy==curline->v1->y)?
- 0 : R_PointToDist (curline->v1->x, curline->v1->y);
- rw_distance = FixedMul(hyp, finecosine[offsetangle>>ANGLETOFINESHIFT]);
- ds_p->x1 = rw_x = start;
- ds_p->x2 = stop;
- ds_p->curline = curline;
- rw_stopx = stop+1;
- { // killough 1/6/98, 2/1/98: remove limit on openings
- extern int *openings; // dropoff overflow
- extern size_t maxopenings;
- size_t pos = lastopening - openings;
- size_t need = (rw_stopx - start)*4 + pos;
- if (need > maxopenings)
- {
- drawseg_t *ds; //jff 8/9/98 needed for fix from ZDoom
- int *oldopenings = openings; // dropoff overflow
- int *oldlast = lastopening; // dropoff overflow
- do
- maxopenings = maxopenings ? maxopenings*2 : 16384;
- while (need > maxopenings);
- openings = realloc(openings, maxopenings * sizeof(*openings));
- lastopening = openings + pos;
- // jff 8/9/98 borrowed fix for openings from ZDOOM1.14
- // [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);
- }
- #undef ADJUST
- }
- } // killough: 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]);
- ds_p->scalestep = rw_scalestep = (ds_p->scale2-rw_scale) / (stop-start);
- }
- else
- ds_p->scale2 = ds_p->scale1;
- // calculate texture boundaries
- // and decide if floor / ceiling marks are needed
- worldtop = frontsector->ceilingheight - viewz;
- worldbottom = frontsector->floorheight - viewz;
- midtexture = toptexture = bottomtexture = maskedtexture = 0;
- ds_p->maskedtexturecol = NULL;
- if (!backsector)
- {
- // single sided line
- midtexture = texturetranslation[sidedef->midtexture];
- midtexheight = (linedef->r_flags & RF_MID_TILE) ? 0 : textureheight[midtexture] >> FRACBITS;
- // a single sided line is terminal, so it must mark ends
- markfloor = markceiling = true;
- if (linedef->flags & ML_DONTPEGBOTTOM)
- { // bottom of texture at bottom
- fixed_t vtop = frontsector->floorheight +
- textureheight[sidedef->midtexture];
- rw_midtexturemid = vtop - viewz;
- }
- else // top of texture at top
- rw_midtexturemid = worldtop;
- rw_midtexturemid += FixedMod(sidedef->rowoffset, textureheight[midtexture]);
- ds_p->silhouette = SIL_BOTH;
- ds_p->sprtopclip = screenheightarray;
- ds_p->sprbottomclip = negonearray;
- ds_p->bsilheight = INT_MAX;
- ds_p->tsilheight = INT_MIN;
- }
- else // two sided line
- {
- ds_p->sprtopclip = ds_p->sprbottomclip = NULL;
- ds_p->silhouette = 0;
- if (linedef->r_flags & RF_CLOSED) { /* cph - closed 2S line e.g. door */
- // cph - killough's (outdated) comment follows - this deals with both
- // "automap fixes", his and mine
- // killough 1/17/98: this test is required if the fix
- // for the automap bug (r_bsp.c) is used, or else some
- // sprites will be displayed behind closed doors. That
- // fix prevents lines behind closed doors with dropoffs
- // from being displayed on the automap.
- ds_p->silhouette = SIL_BOTH;
- ds_p->sprbottomclip = negonearray;
- ds_p->bsilheight = INT_MAX;
- ds_p->sprtopclip = screenheightarray;
- ds_p->tsilheight = INT_MIN;
- } else { /* not solid - old code */
- if (frontsector->floorheight > backsector->floorheight)
- {
- ds_p->silhouette = SIL_BOTTOM;
- ds_p->bsilheight = frontsector->floorheight;
- }
- else
- if (backsector->floorheight > viewz)
- {
- ds_p->silhouette = SIL_BOTTOM;
- ds_p->bsilheight = INT_MAX;
- }
- if (frontsector->ceilingheight < backsector->ceilingheight)
- {
- ds_p->silhouette |= SIL_TOP;
- ds_p->tsilheight = frontsector->ceilingheight;
- }
- else
- if (backsector->ceilingheight < viewz)
- {
- ds_p->silhouette |= SIL_TOP;
- ds_p->tsilheight = INT_MIN;
- }
- }
- worldhigh = backsector->ceilingheight - viewz;
- worldlow = backsector->floorheight - viewz;
- // hack to allow height changes in outdoor areas
- if (frontsector->ceilingpic == skyflatnum
- && backsector->ceilingpic == skyflatnum)
- worldtop = worldhigh;
- markfloor = worldlow != worldbottom
- || backsector->floorpic != frontsector->floorpic
- || backsector->lightlevel != frontsector->lightlevel
- // killough 3/7/98: Add checks for (x,y) offsets
- || backsector->floor_xoffs != frontsector->floor_xoffs
- || backsector->floor_yoffs != frontsector->floor_yoffs
- // killough 4/15/98: prevent 2s normals
- // from bleeding through deep water
- || frontsector->heightsec != -1
- // killough 4/17/98: draw floors if different light levels
- || backsector->floorlightsec != frontsector->floorlightsec
- ;
- markceiling = worldhigh != worldtop
- || backsector->ceilingpic != frontsector->ceilingpic
- || backsector->lightlevel != frontsector->lightlevel
- // killough 3/7/98: Add checks for (x,y) offsets
- || backsector->ceiling_xoffs != frontsector->ceiling_xoffs
- || backsector->ceiling_yoffs != frontsector->ceiling_yoffs
- // killough 4/15/98: prevent 2s normals
- // from bleeding through fake ceilings
- || (frontsector->heightsec != -1 &&
- frontsector->ceilingpic!=skyflatnum)
- // killough 4/17/98: draw ceilings if different light levels
- || backsector->ceilinglightsec != frontsector->ceilinglightsec
- ;
- if (backsector->ceilingheight <= frontsector->floorheight
- || backsector->floorheight >= frontsector->ceilingheight)
- markceiling = markfloor = true; // closed door
- if (worldhigh < worldtop) // top texture
- {
- toptexture = texturetranslation[sidedef->toptexture];
- toptexheight = (linedef->r_flags & RF_TOP_TILE) ? 0 : textureheight[toptexture] >> FRACBITS;
- rw_toptexturemid = linedef->flags & ML_DONTPEGTOP ? worldtop :
- backsector->ceilingheight+textureheight[sidedef->toptexture]-viewz;
- rw_toptexturemid += FixedMod(sidedef->rowoffset, textureheight[toptexture]);
- }
- if (worldlow > worldbottom) // bottom texture
- {
- bottomtexture = texturetranslation[sidedef->bottomtexture];
- bottomtexheight = (linedef->r_flags & RF_BOT_TILE) ? 0 : textureheight[bottomtexture] >> FRACBITS;
- rw_bottomtexturemid = linedef->flags & ML_DONTPEGBOTTOM ? worldtop :
- worldlow;
- rw_bottomtexturemid += FixedMod(sidedef->rowoffset, textureheight[bottomtexture]);
- }
- // allocate space for masked texture tables
- if (sidedef->midtexture) // masked midtexture
- {
- maskedtexture = true;
- ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x;
- lastopening += rw_stopx - rw_x;
- }
- }
- // calculate rw_offset (only needed for textured lines)
- segtextured = midtexture | toptexture | bottomtexture | maskedtexture;
- if (segtextured)
- {
- rw_offset = FixedMul (hyp, -finesine[offsetangle >>ANGLETOFINESHIFT]);
- rw_offset += sidedef->textureoffset + curline->offset;
- rw_centerangle = ANG90 + viewangle - rw_normalangle;
- rw_lightlevel = frontsector->lightlevel;
- }
- // Remember the vars used to determine fractional U texture
- // coords for later - POPE
- ds_p->rw_offset = rw_offset;
- ds_p->rw_distance = rw_distance;
- ds_p->rw_centerangle = rw_centerangle;
-
- // 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.
- // killough 3/7/98: add deep water check
- if (frontsector->heightsec == -1)
- {
- if (frontsector->floorheight >= viewz) // above view plane
- markfloor = false;
- if (frontsector->ceilingheight <= viewz &&
- frontsector->ceilingpic != skyflatnum) // below view plane
- markceiling = false;
- }
- // calculate incremental stepping values for texture edges
- worldtop >>= 4;
- worldbottom >>= 4;
- topstep = -FixedMul (rw_scalestep, worldtop);
- topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale);
- bottomstep = -FixedMul (rw_scalestep,worldbottom);
- bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale);
- if (backsector)
- {
- worldhigh >>= 4;
- worldlow >>= 4;
- if (worldhigh < worldtop)
- {
- pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale);
- pixhighstep = -FixedMul (rw_scalestep,worldhigh);
- }
- if (worldlow > worldbottom)
- {
- pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale);
- pixlowstep = -FixedMul (rw_scalestep,worldlow);
- }
- }
- // render it
- if (markceiling) {
- if (ceilingplane) // killough 4/11/98: add NULL ptr checks
- ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1);
- else
- markceiling = 0;
- }
- if (markfloor) {
- if (floorplane) // killough 4/11/98: add NULL ptr checks
- /* cph 2003/04/18 - ceilingplane and floorplane might be the same
- * visplane (e.g. if both skies); R_CheckPlane doesn't know about
- * modifications to the plane that might happen in parallel with the check
- * being made, so we have to override it and split them anyway if that is
- * a possibility, otherwise the floor marking would overwrite the ceiling
- * marking, resulting in HOM. */
- if (markceiling && ceilingplane == floorplane)
- floorplane = R_DupPlane (floorplane, rw_x, rw_stopx-1);
- else
- floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1);
- else
- markfloor = 0;
- }
- didsolidcol = 0;
- R_RenderSegLoop();
- /* cph - if a column was made solid by this wall, we _must_ save full clipping info */
- if (backsector && didsolidcol) {
- if (!(ds_p->silhouette & SIL_BOTTOM)) {
- ds_p->silhouette |= SIL_BOTTOM;
- ds_p->bsilheight = backsector->floorheight;
- }
- if (!(ds_p->silhouette & SIL_TOP)) {
- ds_p->silhouette |= SIL_TOP;
- ds_p->tsilheight = backsector->ceilingheight;
- }
- }
- // save sprite clipping info
- if ((ds_p->silhouette & SIL_TOP || maskedtexture) && !ds_p->sprtopclip)
- {
- memcpy (lastopening, ceilingclip+start, sizeof(int)*(rw_stopx-start)); // dropoff overflow
- ds_p->sprtopclip = lastopening - start;
- lastopening += rw_stopx - start;
- }
- if ((ds_p->silhouette & SIL_BOTTOM || maskedtexture) && !ds_p->sprbottomclip)
- {
- memcpy (lastopening, floorclip+start, sizeof(int)*(rw_stopx-start)); // dropoff overflow
- ds_p->sprbottomclip = lastopening - start;
- lastopening += rw_stopx - start;
- }
- if (maskedtexture && !(ds_p->silhouette & SIL_TOP))
- {
- ds_p->silhouette |= SIL_TOP;
- ds_p->tsilheight = INT_MIN;
- }
- if (maskedtexture && !(ds_p->silhouette & SIL_BOTTOM))
- {
- ds_p->silhouette |= SIL_BOTTOM;
- ds_p->bsilheight = INT_MAX;
- }
- ds_p++;
- }
|