123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646 |
- //**************************************************************************
- //**
- //** R_SEGS.C
- //**
- //** This version has the tall-sector-crossing-precision-bug fixed.
- //**
- //**************************************************************************
- #include "DoomDef.h"
- #include "R_local.h"
- // OPTIMIZE: closed two sided lines as single sided
- boolean segtextured; // true if any of the segs textures might be vis
- boolean markfloor; // false if the back side is the same plane
- boolean markceiling;
- boolean maskedtexture;
- int toptexture, bottomtexture, midtexture;
- angle_t rw_normalangle;
- int rw_angle1; // angle to line origin
- //
- // wall
- //
- int rw_x;
- int rw_stopx;
- angle_t rw_centerangle;
- fixed_t rw_offset;
- fixed_t rw_distance;
- fixed_t rw_scale;
- fixed_t rw_scalestep;
- fixed_t rw_midtexturemid;
- fixed_t rw_toptexturemid;
- fixed_t rw_bottomtexturemid;
- int worldtop, worldbottom, worldhigh, worldlow;
- fixed_t pixhigh, pixlow;
- fixed_t pixhighstep, pixlowstep;
- fixed_t topfrac, topstep;
- fixed_t bottomfrac, bottomstep;
- lighttable_t **walllights;
- short *maskedtexturecol;
- /*
- ================
- =
- = R_RenderMaskedSegRange
- =
- ================
- */
- void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
- {
- unsigned index;
- column_t *col;
- int lightnum;
- int texnum;
- //
- // calculate light table
- // use different light tables for horizontal / vertical / diagonal
- // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
- curline = ds->curline;
- frontsector = curline->frontsector;
- backsector = curline->backsector;
- texnum = texturetranslation[curline->sidedef->midtexture];
- lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight;
- if (curline->v1->y == curline->v2->y)
- lightnum--;
- else if (curline->v1->x == curline->v2->x)
- lightnum++;
- if (lightnum < 0)
- walllights = scalelight[0];
- else if (lightnum >= LIGHTLEVELS)
- walllights = scalelight[LIGHTLEVELS-1];
- else
- walllights = scalelight[lightnum];
- maskedtexturecol = ds->maskedtexturecol;
- 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)
- {
- dc_texturemid = frontsector->floorheight > backsector->floorheight
- ? frontsector->floorheight : backsector->floorheight;
- dc_texturemid = dc_texturemid + textureheight[texnum] - viewz;
- }
- else
- {
- dc_texturemid =frontsector->ceilingheight<backsector->ceilingheight
- ? frontsector->ceilingheight : backsector->ceilingheight;
- dc_texturemid = dc_texturemid - viewz;
- }
- dc_texturemid += curline->sidedef->rowoffset;
- if (fixedcolormap)
- dc_colormap = fixedcolormap;
- //
- // draw the columns
- //
- for (dc_x = x1 ; dc_x <= x2 ; dc_x++)
- {
- // calculate lighting
- if (maskedtexturecol[dc_x] != MAXSHORT)
- {
- if (!fixedcolormap)
- {
- index = spryscale>>LIGHTSCALESHIFT;
- if (index >= MAXLIGHTSCALE )
- index = MAXLIGHTSCALE-1;
- dc_colormap = walllights[index];
- }
- sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
- dc_iscale = 0xffffffffu / (unsigned)spryscale;
- //
- // draw the texture
- //
- col = (column_t *)(
- (byte *)R_GetColumn(texnum,maskedtexturecol[dc_x]) -3);
- R_DrawMaskedColumn (col, -1);
- maskedtexturecol[dc_x] = MAXSHORT;
- }
- spryscale += rw_scalestep;
- }
- }
- /*
- ================
- =
- = 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)
- void R_RenderSegLoop (void)
- {
- angle_t angle;
- unsigned index;
- int yl, yh, mid;
- fixed_t texturecolumn;
- int top, bottom;
- // texturecolumn = 0; // shut up compiler warning
- for ( ; rw_x < rw_stopx ; rw_x++)
- {
- //
- // mark floor / ceiling areas
- //
- yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;
- if (yl < ceilingclip[rw_x]+1)
- yl = ceilingclip[rw_x]+1; // no space above wall
- if (markceiling)
- {
- top = ceilingclip[rw_x]+1;
- 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;
- }
- }
- yh = bottomfrac>>HEIGHTBITS;
- if (yh >= floorclip[rw_x])
- yh = floorclip[rw_x]-1;
- if (markfloor)
- {
- top = yh+1;
- bottom = floorclip[rw_x]-1;
- if (top <= ceilingclip[rw_x])
- top = ceilingclip[rw_x]+1;
- if (top <= bottom)
- {
- floorplane->top[rw_x] = top;
- floorplane->bottom[rw_x] = bottom;
- }
- }
- //
- // texturecolumn and lighting are independent of wall tiers
- //
- if (segtextured)
- {
- // calculate texture offset
- angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT;
- texturecolumn = rw_offset-FixedMul(finetangent[angle],rw_distance);
- texturecolumn >>= FRACBITS;
- // calculate lighting
- index = rw_scale>>LIGHTSCALESHIFT;
- if (index >= MAXLIGHTSCALE )
- index = MAXLIGHTSCALE-1;
- dc_colormap = walllights[index];
- dc_x = rw_x;
- dc_iscale = 0xffffffffu / (unsigned)rw_scale;
- }
- //
- // draw the wall tiers
- //
- if (midtexture)
- { // single sided line
- dc_yl = yl;
- dc_yh = yh;
- dc_texturemid = rw_midtexturemid;
- dc_source = R_GetColumn(midtexture,texturecolumn);
- colfunc ();
- ceilingclip[rw_x] = viewheight;
- floorclip[rw_x] = -1;
- }
- 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)
- {
- dc_yl = yl;
- dc_yh = mid;
- dc_texturemid = rw_toptexturemid;
- dc_source = R_GetColumn(toptexture,texturecolumn);
- colfunc ();
- 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
- mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS;
- pixlow += pixlowstep;
- if (mid <= ceilingclip[rw_x])
- mid = ceilingclip[rw_x]+1; // no space above wall
- if (mid <= yh)
- {
- dc_yl = mid;
- dc_yh = yh;
- dc_texturemid = rw_bottomtexturemid;
- dc_source = R_GetColumn(bottomtexture,
- texturecolumn);
- colfunc ();
- floorclip[rw_x] = mid;
- }
- else
- floorclip[rw_x] = yh+1;
- }
- else
- { // no bottom wall
- if (markfloor)
- floorclip[rw_x] = yh+1;
- }
- if (maskedtexture)
- { // save texturecol for backdrawing of masked mid texture
- maskedtexturecol[rw_x] = texturecolumn;
- }
- }
- rw_scale += rw_scalestep;
- topfrac += topstep;
- bottomfrac += bottomstep;
- }
- }
- /*
- =====================
- =
- = R_StoreWallRange
- =
- = A wall segment will be drawn between start and stop pixels (inclusive)
- =
- ======================
- */
- void R_StoreWallRange (int start, int stop)
- {
- fixed_t hyp;
- fixed_t sineval;
- angle_t distangle, offsetangle;
- fixed_t vtop;
- int lightnum;
- if (ds_p == &drawsegs[MAXDRAWSEGS])
- return; // don't overflow and crash
- #ifdef RANGECHECK
- if (start >=viewwidth || start > stop)
- I_Error ("Bad R_RenderWallRange: %i to %i", start , stop);
- #endif
- #ifdef __NeXT__
- RD_DrawLine (curline);
- #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 = abs(rw_normalangle-rw_angle1);
- if (offsetangle > ANG90)
- offsetangle = ANG90;
- distangle = ANG90 - offsetangle;
- hyp = R_PointToDist (curline->v1->x, curline->v1->y);
- sineval = finesine[distangle>>ANGLETOFINESHIFT];
- rw_distance = FixedMul (hyp, sineval);
- ds_p->x1 = rw_x = start;
- ds_p->x2 = stop;
- ds_p->curline = curline;
- rw_stopx = stop+1;
- //
- // 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
- {
- //
- // try to fix the stretched line bug
- //
- #if 0
- if (rw_distance < FRACUNIT/2)
- {
- fixed_t trx,try;
- fixed_t gxt,gyt;
- trx = curline->v1->x - viewx;
- try = curline->v1->y - viewy;
- gxt = FixedMul(trx,viewcos);
- gyt = -FixedMul(try,viewsin);
- ds_p->scale1 = FixedDiv(projection, gxt-gyt);
- }
- #endif
- 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];
- // a single sided line is terminal, so it must mark ends
- markfloor = markceiling = true;
- if (linedef->flags & ML_DONTPEGBOTTOM)
- {
- vtop = frontsector->floorheight +
- textureheight[sidedef->midtexture];
- rw_midtexturemid = vtop - viewz; // bottom of texture at bottom
- }
- else
- rw_midtexturemid = worldtop; // top of texture at top
- rw_midtexturemid += sidedef->rowoffset;
- ds_p->silhouette = SIL_BOTH;
- ds_p->sprtopclip = screenheightarray;
- ds_p->sprbottomclip = negonearray;
- ds_p->bsilheight = MAXINT;
- ds_p->tsilheight = MININT;
- }
- else
- {
- //
- // two sided line
- //
- ds_p->sprtopclip = ds_p->sprbottomclip = NULL;
- ds_p->silhouette = 0;
- 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 = MAXINT;
- // ds_p->sprbottomclip = negonearray;
- }
- 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 = MININT;
- // ds_p->sprtopclip = screenheightarray;
- }
- if (backsector->ceilingheight <= frontsector->floorheight)
- {
- ds_p->sprbottomclip = negonearray;
- ds_p->bsilheight = MAXINT;
- ds_p->silhouette |= SIL_BOTTOM;
- }
- if (backsector->floorheight >= frontsector->ceilingheight)
- {
- ds_p->sprtopclip = screenheightarray;
- ds_p->tsilheight = MININT;
- ds_p->silhouette |= SIL_TOP;
- }
- 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;
- if (worldlow != worldbottom
- || backsector->floorpic != frontsector->floorpic
- || backsector->lightlevel != frontsector->lightlevel)
- markfloor = true;
- else
- markfloor = false; // same plane on both sides
- if (worldhigh != worldtop
- || backsector->ceilingpic != frontsector->ceilingpic
- || backsector->lightlevel != frontsector->lightlevel)
- markceiling = true;
- else
- markceiling = false; // same plane on both sides
- if (backsector->ceilingheight <= frontsector->floorheight
- || backsector->floorheight >= frontsector->ceilingheight)
- markceiling = markfloor = true; // closed door
- if (worldhigh < worldtop)
- { // top texture
- toptexture = texturetranslation[sidedef->toptexture];
- if (linedef->flags & ML_DONTPEGTOP)
- rw_toptexturemid = worldtop; // top of texture at top
- else
- {
- vtop = backsector->ceilingheight +
- textureheight[sidedef->toptexture];
- rw_toptexturemid = vtop - viewz; // bottom of texture
- }
- }
- if (worldlow > worldbottom)
- { // bottom texture
- bottomtexture = texturetranslation[sidedef->bottomtexture];
- if (linedef->flags & ML_DONTPEGBOTTOM )
- { // bottom of texture at bottom
- rw_bottomtexturemid = worldtop;// top of texture at top
- }
- else // top of texture at top
- rw_bottomtexturemid = worldlow;
- }
- rw_toptexturemid += sidedef->rowoffset;
- rw_bottomtexturemid += sidedef->rowoffset;
- //
- // 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)
- {
- offsetangle = rw_normalangle-rw_angle1;
- if (offsetangle > ANG180)
- offsetangle = -offsetangle;
- if (offsetangle > ANG90)
- offsetangle = ANG90;
- sineval = finesine[offsetangle >>ANGLETOFINESHIFT];
- rw_offset = FixedMul (hyp, sineval);
- if (rw_normalangle-rw_angle1 < ANG180)
- rw_offset = -rw_offset;
- rw_offset += sidedef->textureoffset + curline->offset;
- rw_centerangle = ANG90 + viewangle - rw_normalangle;
- //
- // calculate light table
- // use different light tables for horizontal / vertical / diagonal
- // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
- if (!fixedcolormap)
- {
- lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight;
- if (curline->v1->y == curline->v2->y)
- lightnum--;
- else if (curline->v1->x == curline->v2->x)
- lightnum++;
- if (lightnum < 0)
- walllights = scalelight[0];
- else if (lightnum >= LIGHTLEVELS)
- walllights = scalelight[LIGHTLEVELS-1];
- else
- walllights = scalelight[lightnum];
- }
- }
- //
- // if a floor / ceiling plane is on the wrong side of the view plane
- // it is definately invisible and doesn't need to be marked
- //
- if (frontsector->floorheight >= viewz)
- markfloor = false; // above view plane
- if (frontsector->ceilingheight <= viewz
- && frontsector->ceilingpic != skyflatnum)
- markceiling = false; // below view plane
- //
- // 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)
- ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1);
- if (markfloor)
- floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1);
- R_RenderSegLoop ();
- //
- // save sprite clipping info
- //
- if ( ((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip)
- {
- 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)
- {
- 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 = MININT;
- }
- if (maskedtexture && !(ds_p->silhouette&SIL_BOTTOM))
- {
- ds_p->silhouette |= SIL_BOTTOM;
- ds_p->bsilheight = MAXINT;
- }
- ds_p++;
- }
|