2 //**************************************************************************
6 //** This version has the tall-sector-crossing-precision-bug fixed.
8 //**************************************************************************
13 // OPTIMIZE: closed two sided lines as single sided
15 boolean segtextured; // true if any of the segs textures might be vis
16 boolean markfloor; // false if the back side is the same plane
18 boolean maskedtexture;
19 int toptexture, bottomtexture, midtexture;
22 angle_t rw_normalangle;
23 int rw_angle1; // angle to line origin
30 angle_t rw_centerangle;
35 fixed_t rw_midtexturemid;
36 fixed_t rw_toptexturemid;
37 fixed_t rw_bottomtexturemid;
39 int worldtop, worldbottom, worldhigh, worldlow;
41 fixed_t pixhigh, pixlow;
42 fixed_t pixhighstep, pixlowstep;
43 fixed_t topfrac, topstep;
44 fixed_t bottomfrac, bottomstep;
47 lighttable_t **walllights;
49 short *maskedtexturecol;
52 void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) {}
53 void R_RenderSegLoop (void) {}
54 void R_StoreWallRange (int start, int stop) {}
60 = R_RenderMaskedSegRange
65 void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
73 // calculate light table
74 // use different light tables for horizontal / vertical / diagonal
75 // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
76 curline = ds->curline;
77 frontsector = curline->frontsector;
78 backsector = curline->backsector;
79 texnum = texturetranslation[curline->sidedef->midtexture];
81 lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight;
82 if (curline->v1->y == curline->v2->y)
84 else if (curline->v1->x == curline->v2->x)
87 walllights = scalelight[0];
88 else if (lightnum >= LIGHTLEVELS)
89 walllights = scalelight[LIGHTLEVELS-1];
91 walllights = scalelight[lightnum];
93 maskedtexturecol = ds->maskedtexturecol;
95 rw_scalestep = ds->scalestep;
96 spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
97 mfloorclip = ds->sprbottomclip;
98 mceilingclip = ds->sprtopclip;
103 if (curline->linedef->flags & ML_DONTPEGBOTTOM)
105 dc_texturemid = frontsector->floorheight > backsector->floorheight
106 ? frontsector->floorheight : backsector->floorheight;
107 dc_texturemid = dc_texturemid + textureheight[texnum] - viewz;
111 dc_texturemid =frontsector->ceilingheight<backsector->ceilingheight
112 ? frontsector->ceilingheight : backsector->ceilingheight;
113 dc_texturemid = dc_texturemid - viewz;
115 dc_texturemid += curline->sidedef->rowoffset;
118 dc_colormap = fixedcolormap;
122 for (dc_x = x1 ; dc_x <= x2 ; dc_x++)
124 // calculate lighting
125 if (maskedtexturecol[dc_x] != MAXSHORT)
129 index = spryscale>>LIGHTSCALESHIFT;
130 if (index >= MAXLIGHTSCALE )
131 index = MAXLIGHTSCALE-1;
132 dc_colormap = walllights[index];
135 sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
136 dc_iscale = 0xffffffffu / (unsigned)spryscale;
142 (byte *)R_GetColumn(texnum,maskedtexturecol[dc_x]) -3);
144 R_DrawMaskedColumn (col, -1);
145 maskedtexturecol[dc_x] = MAXSHORT;
147 spryscale += rw_scalestep;
157 = Draws zero, one, or two textures (and possibly a masked texture) for walls
158 = Can draw or mark the starting pixel of floor and ceiling textures
160 = CALLED: CORE LOOPING ROUTINE
164 #define HEIGHTBITS 12
165 #define HEIGHTUNIT (1<<HEIGHTBITS)
167 void R_RenderSegLoop (void)
172 fixed_t texturecolumn=0;
175 // texturecolumn = 0; // shut up compiler warning
177 for ( ; rw_x < rw_stopx ; rw_x++)
180 // mark floor / ceiling areas
182 yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;
183 if (yl < ceilingclip[rw_x]+1)
184 yl = ceilingclip[rw_x]+1; // no space above wall
187 top = ceilingclip[rw_x]+1;
189 if (bottom >= floorclip[rw_x])
190 bottom = floorclip[rw_x]-1;
193 ceilingplane->top[rw_x] = top;
194 ceilingplane->bottom[rw_x] = bottom;
198 yh = bottomfrac>>HEIGHTBITS;
199 if (yh >= floorclip[rw_x])
200 yh = floorclip[rw_x]-1;
204 bottom = floorclip[rw_x]-1;
205 if (top <= ceilingclip[rw_x])
206 top = ceilingclip[rw_x]+1;
209 floorplane->top[rw_x] = top;
210 floorplane->bottom[rw_x] = bottom;
215 // texturecolumn and lighting are independent of wall tiers
219 // calculate texture offset
220 angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT;
221 texturecolumn = rw_offset-FixedMul(finetangent[angle],rw_distance);
222 texturecolumn >>= FRACBITS;
223 // calculate lighting
224 index = rw_scale>>LIGHTSCALESHIFT;
225 if (index >= MAXLIGHTSCALE )
226 index = MAXLIGHTSCALE-1;
227 dc_colormap = walllights[index];
229 dc_iscale = 0xffffffffu / (unsigned)rw_scale;
233 // draw the wall tiers
236 { // single sided line
239 dc_texturemid = rw_midtexturemid;
240 dc_source = R_GetColumn(midtexture,texturecolumn);
242 ceilingclip[rw_x] = viewheight;
243 floorclip[rw_x] = -1;
249 mid = pixhigh>>HEIGHTBITS;
250 pixhigh += pixhighstep;
251 if (mid >= floorclip[rw_x])
252 mid = floorclip[rw_x]-1;
257 dc_texturemid = rw_toptexturemid;
258 dc_source = R_GetColumn(toptexture,texturecolumn);
260 ceilingclip[rw_x] = mid;
263 ceilingclip[rw_x] = yl-1;
268 ceilingclip[rw_x] = yl-1;
273 mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS;
274 pixlow += pixlowstep;
275 if (mid <= ceilingclip[rw_x])
276 mid = ceilingclip[rw_x]+1; // no space above wall
281 dc_texturemid = rw_bottomtexturemid;
282 dc_source = R_GetColumn(bottomtexture,
285 floorclip[rw_x] = mid;
288 floorclip[rw_x] = yh+1;
293 floorclip[rw_x] = yh+1;
297 { // save texturecol for backdrawing of masked mid texture
298 maskedtexturecol[rw_x] = texturecolumn;
302 rw_scale += rw_scalestep;
304 bottomfrac += bottomstep;
312 =====================
316 = A wall segment will be drawn between start and stop pixels (inclusive)
318 ======================
321 void R_StoreWallRange (int start, int stop)
325 angle_t distangle, offsetangle;
329 if (ds_p == &drawsegs[MAXDRAWSEGS])
330 return; // don't overflow and crash
333 if (start >=viewwidth || start > stop)
334 I_Error ("Bad R_RenderWallRange: %i to %i", start , stop);
337 RD_DrawLine (curline);
340 sidedef = curline->sidedef;
341 linedef = curline->linedef;
343 // mark the segment as visible for auto map
344 linedef->flags |= ML_MAPPED;
347 // calculate rw_distance for scale calculation
349 rw_normalangle = curline->angle + ANG90;
350 offsetangle = abs(rw_normalangle-rw_angle1);
351 if (offsetangle > ANG90)
353 distangle = ANG90 - offsetangle;
354 hyp = R_PointToDist (curline->v1->x, curline->v1->y);
355 sineval = finesine[distangle>>ANGLETOFINESHIFT];
356 rw_distance = FixedMul (hyp, sineval);
359 ds_p->x1 = rw_x = start;
361 ds_p->curline = curline;
365 // calculate scale at both ends and step
367 ds_p->scale1 = rw_scale =
368 R_ScaleFromGlobalAngle (viewangle + xtoviewangle[start]);
371 ds_p->scale2 = R_ScaleFromGlobalAngle (viewangle + xtoviewangle[stop]);
372 ds_p->scalestep = rw_scalestep =
373 (ds_p->scale2 - rw_scale) / (stop-start);
378 // try to fix the stretched line bug
381 if (rw_distance < FRACUNIT/2)
386 trx = curline->v1->x - viewx;
387 try = curline->v1->y - viewy;
389 gxt = FixedMul(trx,viewcos);
390 gyt = -FixedMul(try,viewsin);
391 ds_p->scale1 = FixedDiv(projection, gxt-gyt);
394 ds_p->scale2 = ds_p->scale1;
399 // calculate texture boundaries and decide if floor / ceiling marks
402 worldtop = frontsector->ceilingheight - viewz;
403 worldbottom = frontsector->floorheight - viewz;
405 midtexture = toptexture = bottomtexture = maskedtexture = 0;
406 ds_p->maskedtexturecol = NULL;
413 midtexture = texturetranslation[sidedef->midtexture];
414 // a single sided line is terminal, so it must mark ends
415 markfloor = markceiling = true;
416 if (linedef->flags & ML_DONTPEGBOTTOM)
418 vtop = frontsector->floorheight +
419 textureheight[sidedef->midtexture];
420 rw_midtexturemid = vtop - viewz; // bottom of texture at bottom
423 rw_midtexturemid = worldtop; // top of texture at top
424 rw_midtexturemid += sidedef->rowoffset;
425 ds_p->silhouette = SIL_BOTH;
426 ds_p->sprtopclip = screenheightarray;
427 ds_p->sprbottomclip = negonearray;
428 ds_p->bsilheight = MAXINT;
429 ds_p->tsilheight = MININT;
436 ds_p->sprtopclip = ds_p->sprbottomclip = NULL;
437 ds_p->silhouette = 0;
438 if (frontsector->floorheight > backsector->floorheight)
440 ds_p->silhouette = SIL_BOTTOM;
441 ds_p->bsilheight = frontsector->floorheight;
443 else if (backsector->floorheight > viewz)
445 ds_p->silhouette = SIL_BOTTOM;
446 ds_p->bsilheight = MAXINT;
447 // ds_p->sprbottomclip = negonearray;
449 if (frontsector->ceilingheight < backsector->ceilingheight)
451 ds_p->silhouette |= SIL_TOP;
452 ds_p->tsilheight = frontsector->ceilingheight;
454 else if (backsector->ceilingheight < viewz)
456 ds_p->silhouette |= SIL_TOP;
457 ds_p->tsilheight = MININT;
458 // ds_p->sprtopclip = screenheightarray;
461 if (backsector->ceilingheight <= frontsector->floorheight)
463 ds_p->sprbottomclip = negonearray;
464 ds_p->bsilheight = MAXINT;
465 ds_p->silhouette |= SIL_BOTTOM;
467 if (backsector->floorheight >= frontsector->ceilingheight)
469 ds_p->sprtopclip = screenheightarray;
470 ds_p->tsilheight = MININT;
471 ds_p->silhouette |= SIL_TOP;
473 worldhigh = backsector->ceilingheight - viewz;
474 worldlow = backsector->floorheight - viewz;
476 // hack to allow height changes in outdoor areas
477 if (frontsector->ceilingpic == skyflatnum
478 && backsector->ceilingpic == skyflatnum)
479 worldtop = worldhigh;
481 if (worldlow != worldbottom
482 || backsector->floorpic != frontsector->floorpic
483 || backsector->lightlevel != frontsector->lightlevel)
486 markfloor = false; // same plane on both sides
488 if (worldhigh != worldtop
489 || backsector->ceilingpic != frontsector->ceilingpic
490 || backsector->lightlevel != frontsector->lightlevel)
493 markceiling = false; // same plane on both sides
495 if (backsector->ceilingheight <= frontsector->floorheight
496 || backsector->floorheight >= frontsector->ceilingheight)
497 markceiling = markfloor = true; // closed door
499 if (worldhigh < worldtop)
501 toptexture = texturetranslation[sidedef->toptexture];
502 if (linedef->flags & ML_DONTPEGTOP)
503 rw_toptexturemid = worldtop; // top of texture at top
506 vtop = backsector->ceilingheight +
507 textureheight[sidedef->toptexture];
508 rw_toptexturemid = vtop - viewz; // bottom of texture
511 if (worldlow > worldbottom)
513 bottomtexture = texturetranslation[sidedef->bottomtexture];
514 if (linedef->flags & ML_DONTPEGBOTTOM )
515 { // bottom of texture at bottom
516 rw_bottomtexturemid = worldtop;// top of texture at top
518 else // top of texture at top
519 rw_bottomtexturemid = worldlow;
521 rw_toptexturemid += sidedef->rowoffset;
522 rw_bottomtexturemid += sidedef->rowoffset;
525 // allocate space for masked texture tables
527 if (sidedef->midtexture)
528 { // masked midtexture
529 maskedtexture = true;
530 ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x;
531 lastopening += rw_stopx - rw_x;
536 // calculate rw_offset (only needed for textured lines)
538 segtextured = midtexture | toptexture | bottomtexture | maskedtexture;
542 offsetangle = rw_normalangle-rw_angle1;
543 if (offsetangle > ANG180)
544 offsetangle = -offsetangle;
545 if (offsetangle > ANG90)
547 sineval = finesine[offsetangle >>ANGLETOFINESHIFT];
548 rw_offset = FixedMul (hyp, sineval);
549 if (rw_normalangle-rw_angle1 < ANG180)
550 rw_offset = -rw_offset;
551 rw_offset += sidedef->textureoffset + curline->offset;
552 rw_centerangle = ANG90 + viewangle - rw_normalangle;
555 // calculate light table
556 // use different light tables for horizontal / vertical / diagonal
557 // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
560 lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight;
561 if (curline->v1->y == curline->v2->y)
563 else if (curline->v1->x == curline->v2->x)
566 walllights = scalelight[0];
567 else if (lightnum >= LIGHTLEVELS)
568 walllights = scalelight[LIGHTLEVELS-1];
570 walllights = scalelight[lightnum];
576 // if a floor / ceiling plane is on the wrong side of the view plane
577 // it is definately invisible and doesn't need to be marked
579 if (frontsector->floorheight >= viewz)
580 markfloor = false; // above view plane
581 if (frontsector->ceilingheight <= viewz
582 && frontsector->ceilingpic != skyflatnum)
583 markceiling = false; // below view plane
586 // calculate incremental stepping values for texture edges
591 topstep = -FixedMul (rw_scalestep, worldtop);
592 topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale);
594 bottomstep = -FixedMul (rw_scalestep,worldbottom);
595 bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale);
602 if (worldhigh < worldtop)
604 pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale);
605 pixhighstep = -FixedMul (rw_scalestep,worldhigh);
607 if (worldlow > worldbottom)
609 pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale);
610 pixlowstep = -FixedMul (rw_scalestep,worldlow);
618 ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1);
620 floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1);
625 // save sprite clipping info
627 if ( ((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip)
629 memcpy (lastopening, ceilingclip+start, 2*(rw_stopx-start));
630 ds_p->sprtopclip = lastopening - start;
631 lastopening += rw_stopx - start;
633 if ( ((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && !ds_p->sprbottomclip)
635 memcpy (lastopening, floorclip+start, 2*(rw_stopx-start));
636 ds_p->sprbottomclip = lastopening - start;
637 lastopening += rw_stopx - start;
639 if (maskedtexture && !(ds_p->silhouette&SIL_TOP))
641 ds_p->silhouette |= SIL_TOP;
642 ds_p->tsilheight = MININT;
644 if (maskedtexture && !(ds_p->silhouette&SIL_BOTTOM))
646 ds_p->silhouette |= SIL_BOTTOM;
647 ds_p->bsilheight = MAXINT;