123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747 |
- // Emacs style mode select -*- C++ -*-
- //-----------------------------------------------------------------------------
- //
- // $Id:$
- //
- // Copyright (C) 1993-1996 by id Software, Inc.
- //
- // This source is available for distribution and/or modification
- // only under the terms of the DOOM Source Code License as
- // published by id Software. All rights reserved.
- //
- // The source is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
- // for more details.
- //
- // $Log:$
- //
- // DESCRIPTION:
- // All the clipping: columns, horizontal spans, sky columns.
- //
- //-----------------------------------------------------------------------------
- static const char
- rcsid[] = "$Id: r_segs.c,v 1.3 1997/01/29 20:10:19 b1 Exp $";
- #include <stdlib.h>
- #include "i_system.h"
- #include "doomdef.h"
- #include "doomstat.h"
- #include "r_local.h"
- #include "r_sky.h"
- // OPTIMIZE: closed two sided lines as single sided
- // True if any of the segs textures might be visible.
- boolean segtextured;
- // False if the back side is the same plane.
- boolean markfloor;
- boolean markceiling;
- boolean maskedtexture;
- int toptexture;
- int bottomtexture;
- int midtexture;
- angle_t rw_normalangle;
- // angle to line origin
- int rw_angle1;
- //
- // regular 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;
- int worldbottom;
- int worldhigh;
- int worldlow;
- fixed_t pixhigh;
- fixed_t pixlow;
- fixed_t pixhighstep;
- fixed_t pixlowstep;
- fixed_t topfrac;
- fixed_t topstep;
- fixed_t bottomfrac;
- fixed_t 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. 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);
- 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;
- int yh;
- int mid;
- fixed_t texturecolumn;
- int top;
- int bottom;
- //texturecolumn = 0; // shut up compiler warning
-
- for ( ; rw_x < rw_stopx ; rw_x++)
- {
- // mark floor / ceiling areas
- yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;
- // no space above wall?
- if (yl < ceilingclip[rw_x]+1)
- yl = ceilingclip[rw_x]+1;
-
- 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;
- // no space above wall?
- if (mid <= ceilingclip[rw_x])
- mid = ceilingclip[rw_x]+1;
-
- 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;
- // don't overflow and crash
- if (ds_p == &drawsegs[MAXDRAWSEGS])
- return;
-
- #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 = 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
- {
- // UNUSED: 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)<<detailshift;
- }
- #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];
- // bottom of texture at bottom
- rw_midtexturemid = vtop - viewz;
- }
- else
- {
- // top of texture at top
- rw_midtexturemid = worldtop;
- }
- 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
- {
- // same plane on both sides
- markfloor = false;
- }
-
-
- if (worldhigh != worldtop
- || backsector->ceilingpic != frontsector->ceilingpic
- || backsector->lightlevel != frontsector->lightlevel)
- {
- markceiling = true;
- }
- else
- {
- // same plane on both sides
- markceiling = false;
- }
-
- if (backsector->ceilingheight <= frontsector->floorheight
- || backsector->floorheight >= frontsector->ceilingheight)
- {
- // closed door
- markceiling = markfloor = true;
- }
-
- if (worldhigh < worldtop)
- {
- // top texture
- toptexture = texturetranslation[sidedef->toptexture];
- if (linedef->flags & ML_DONTPEGTOP)
- {
- // top of texture at top
- rw_toptexturemid = worldtop;
- }
- else
- {
- vtop =
- backsector->ceilingheight
- + textureheight[sidedef->toptexture];
-
- // bottom of texture
- rw_toptexturemid = vtop - viewz;
- }
- }
- if (worldlow > worldbottom)
- {
- // bottom texture
- bottomtexture = texturetranslation[sidedef->bottomtexture];
- if (linedef->flags & ML_DONTPEGBOTTOM )
- {
- // bottom of texture at bottom
- // top of texture at top
- rw_bottomtexturemid = worldtop;
- }
- 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 definitely invisible
- // and doesn't need to be marked.
-
-
- 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)
- 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++;
- }
|