2 //**************************************************************************
6 //** This version has the tall-sector-crossing-precision-bug fixed.
8 //**************************************************************************
14 // OPTIMIZE: closed two sided lines as single sided
16 boolean segtextured; // true if any of the segs textures might be vis
17 boolean markfloor; // false if the back side is the same plane
19 boolean maskedtexture;
20 int toptexture, bottomtexture, midtexture;
23 angle_t rw_normalangle;
24 int rw_angle1; // angle to line origin
31 angle_t rw_centerangle;
36 fixed_t rw_midtexturemid;
37 fixed_t rw_toptexturemid;
38 fixed_t rw_bottomtexturemid;
40 int worldtop, worldbottom, worldhigh, worldlow;
42 fixed_t pixhigh, pixlow;
43 fixed_t pixhighstep, pixlowstep;
44 fixed_t topfrac, topstep;
45 fixed_t bottomfrac, bottomstep;
48 lighttable_t **walllights;
50 short *maskedtexturecol;
53 void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) {}
54 void R_RenderSegLoop (void) {}
55 void R_StoreWallRange (int start, int stop) {}
61 = R_RenderMaskedSegRange
66 void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
74 // calculate light table
75 // use different light tables for horizontal / vertical / diagonal
76 // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
77 curline = ds->curline;
78 frontsector = curline->frontsector;
79 backsector = curline->backsector;
80 texnum = texturetranslation[curline->sidedef->midtexture];
82 lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight;
83 if (curline->v1->y == curline->v2->y)
85 else if (curline->v1->x == curline->v2->x)
88 walllights = scalelight[0];
89 else if (lightnum >= LIGHTLEVELS)
90 walllights = scalelight[LIGHTLEVELS-1];
92 walllights = scalelight[lightnum];
94 maskedtexturecol = ds->maskedtexturecol;
96 rw_scalestep = ds->scalestep;
97 spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
98 mfloorclip = ds->sprbottomclip;
99 mceilingclip = ds->sprtopclip;
104 if (curline->linedef->flags & ML_DONTPEGBOTTOM)
106 dc_texturemid = frontsector->floorheight > backsector->floorheight
107 ? frontsector->floorheight : backsector->floorheight;
108 dc_texturemid = dc_texturemid + textureheight[texnum] - viewz;
112 dc_texturemid =frontsector->ceilingheight<backsector->ceilingheight
113 ? frontsector->ceilingheight : backsector->ceilingheight;
114 dc_texturemid = dc_texturemid - viewz;
116 dc_texturemid += curline->sidedef->rowoffset;
119 dc_colormap = fixedcolormap;
123 for (dc_x = x1 ; dc_x <= x2 ; dc_x++)
125 // calculate lighting
126 if (maskedtexturecol[dc_x] != MAXSHORT)
130 index = spryscale>>LIGHTSCALESHIFT;
131 if (index >= MAXLIGHTSCALE )
132 index = MAXLIGHTSCALE-1;
133 dc_colormap = walllights[index];
136 sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
137 dc_iscale = 0xffffffffu / (unsigned)spryscale;
143 (byte *)R_GetColumn(texnum,maskedtexturecol[dc_x]) -3);
145 R_DrawMaskedColumn (col, -1);
146 maskedtexturecol[dc_x] = MAXSHORT;
148 spryscale += rw_scalestep;
158 = Draws zero, one, or two textures (and possibly a masked texture) for walls
159 = Can draw or mark the starting pixel of floor and ceiling textures
161 = CALLED: CORE LOOPING ROUTINE
165 #define HEIGHTBITS 12
166 #define HEIGHTUNIT (1<<HEIGHTBITS)
168 void R_RenderSegLoop (void)
173 fixed_t texturecolumn=0;
176 // texturecolumn = 0; // shut up compiler warning
178 for ( ; rw_x < rw_stopx ; rw_x++)
181 // mark floor / ceiling areas
183 yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;
184 if (yl < ceilingclip[rw_x]+1)
185 yl = ceilingclip[rw_x]+1; // no space above wall
188 top = ceilingclip[rw_x]+1;
190 if (bottom >= floorclip[rw_x])
191 bottom = floorclip[rw_x]-1;
194 ceilingplane->top[rw_x] = top;
195 ceilingplane->bottom[rw_x] = bottom;
199 yh = bottomfrac>>HEIGHTBITS;
200 if (yh >= floorclip[rw_x])
201 yh = floorclip[rw_x]-1;
205 bottom = floorclip[rw_x]-1;
206 if (top <= ceilingclip[rw_x])
207 top = ceilingclip[rw_x]+1;
210 floorplane->top[rw_x] = top;
211 floorplane->bottom[rw_x] = bottom;
216 // texturecolumn and lighting are independent of wall tiers
220 // calculate texture offset
221 angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT;
222 texturecolumn = rw_offset-FixedMul(finetangent[angle],rw_distance);
223 texturecolumn >>= FRACBITS;
224 // calculate lighting
225 index = rw_scale>>LIGHTSCALESHIFT;
226 if (index >= MAXLIGHTSCALE )
227 index = MAXLIGHTSCALE-1;
228 dc_colormap = walllights[index];
230 dc_iscale = 0xffffffffu / (unsigned)rw_scale;
234 // draw the wall tiers
237 { // single sided line
240 dc_texturemid = rw_midtexturemid;
241 dc_source = R_GetColumn(midtexture,texturecolumn);
243 ceilingclip[rw_x] = viewheight;
244 floorclip[rw_x] = -1;
250 mid = pixhigh>>HEIGHTBITS;
251 pixhigh += pixhighstep;
252 if (mid >= floorclip[rw_x])
253 mid = floorclip[rw_x]-1;
258 dc_texturemid = rw_toptexturemid;
259 dc_source = R_GetColumn(toptexture,texturecolumn);
261 ceilingclip[rw_x] = mid;
264 ceilingclip[rw_x] = yl-1;
269 ceilingclip[rw_x] = yl-1;
274 mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS;
275 pixlow += pixlowstep;
276 if (mid <= ceilingclip[rw_x])
277 mid = ceilingclip[rw_x]+1; // no space above wall
282 dc_texturemid = rw_bottomtexturemid;
283 dc_source = R_GetColumn(bottomtexture,
286 floorclip[rw_x] = mid;
289 floorclip[rw_x] = yh+1;
294 floorclip[rw_x] = yh+1;
298 { // save texturecol for backdrawing of masked mid texture
299 maskedtexturecol[rw_x] = texturecolumn;
303 rw_scale += rw_scalestep;
305 bottomfrac += bottomstep;
313 =====================
317 = A wall segment will be drawn between start and stop pixels (inclusive)
319 ======================
322 void R_StoreWallRange (int start, int stop)
326 angle_t distangle, offsetangle;
330 if (ds_p == &drawsegs[MAXDRAWSEGS])
331 return; // don't overflow and crash
334 if (start >=viewwidth || start > stop)
335 I_Error ("Bad R_RenderWallRange: %i to %i", start , stop);
338 RD_DrawLine (curline);
341 sidedef = curline->sidedef;
342 linedef = curline->linedef;
344 // mark the segment as visible for auto map
345 linedef->flags |= ML_MAPPED;
348 // calculate rw_distance for scale calculation
350 rw_normalangle = curline->angle + ANG90;
351 offsetangle = abs(rw_normalangle-rw_angle1);
352 if (offsetangle > ANG90)
354 distangle = ANG90 - offsetangle;
355 hyp = R_PointToDist (curline->v1->x, curline->v1->y);
356 sineval = finesine[distangle>>ANGLETOFINESHIFT];
357 rw_distance = FixedMul (hyp, sineval);
360 ds_p->x1 = rw_x = start;
362 ds_p->curline = curline;
366 // calculate scale at both ends and step
368 ds_p->scale1 = rw_scale =
369 R_ScaleFromGlobalAngle (viewangle + xtoviewangle[start]);
372 ds_p->scale2 = R_ScaleFromGlobalAngle (viewangle + xtoviewangle[stop]);
373 ds_p->scalestep = rw_scalestep =
374 (ds_p->scale2 - rw_scale) / (stop-start);
379 // try to fix the stretched line bug
382 if (rw_distance < FRACUNIT/2)
387 trx = curline->v1->x - viewx;
388 try = curline->v1->y - viewy;
390 gxt = FixedMul(trx,viewcos);
391 gyt = -FixedMul(try,viewsin);
392 ds_p->scale1 = FixedDiv(projection, gxt-gyt);
395 ds_p->scale2 = ds_p->scale1;
400 // calculate texture boundaries and decide if floor / ceiling marks
403 worldtop = frontsector->ceilingheight - viewz;
404 worldbottom = frontsector->floorheight - viewz;
406 midtexture = toptexture = bottomtexture = maskedtexture = 0;
407 ds_p->maskedtexturecol = NULL;
414 midtexture = texturetranslation[sidedef->midtexture];
415 // a single sided line is terminal, so it must mark ends
416 markfloor = markceiling = true;
417 if (linedef->flags & ML_DONTPEGBOTTOM)
419 vtop = frontsector->floorheight +
420 textureheight[sidedef->midtexture];
421 rw_midtexturemid = vtop - viewz; // bottom of texture at bottom
424 rw_midtexturemid = worldtop; // top of texture at top
425 rw_midtexturemid += sidedef->rowoffset;
426 ds_p->silhouette = SIL_BOTH;
427 ds_p->sprtopclip = screenheightarray;
428 ds_p->sprbottomclip = negonearray;
429 ds_p->bsilheight = MAXINT;
430 ds_p->tsilheight = MININT;
437 ds_p->sprtopclip = ds_p->sprbottomclip = NULL;
438 ds_p->silhouette = 0;
439 if (frontsector->floorheight > backsector->floorheight)
441 ds_p->silhouette = SIL_BOTTOM;
442 ds_p->bsilheight = frontsector->floorheight;
444 else if (backsector->floorheight > viewz)
446 ds_p->silhouette = SIL_BOTTOM;
447 ds_p->bsilheight = MAXINT;
448 // ds_p->sprbottomclip = negonearray;
450 if (frontsector->ceilingheight < backsector->ceilingheight)
452 ds_p->silhouette |= SIL_TOP;
453 ds_p->tsilheight = frontsector->ceilingheight;
455 else if (backsector->ceilingheight < viewz)
457 ds_p->silhouette |= SIL_TOP;
458 ds_p->tsilheight = MININT;
459 // ds_p->sprtopclip = screenheightarray;
462 if (backsector->ceilingheight <= frontsector->floorheight)
464 ds_p->sprbottomclip = negonearray;
465 ds_p->bsilheight = MAXINT;
466 ds_p->silhouette |= SIL_BOTTOM;
468 if (backsector->floorheight >= frontsector->ceilingheight)
470 ds_p->sprtopclip = screenheightarray;
471 ds_p->tsilheight = MININT;
472 ds_p->silhouette |= SIL_TOP;
474 worldhigh = backsector->ceilingheight - viewz;
475 worldlow = backsector->floorheight - viewz;
477 // hack to allow height changes in outdoor areas
478 if (frontsector->ceilingpic == skyflatnum
479 && backsector->ceilingpic == skyflatnum)
480 worldtop = worldhigh;
482 if (worldlow != worldbottom
483 || backsector->floorpic != frontsector->floorpic
484 || backsector->lightlevel != frontsector->lightlevel)
487 markfloor = false; // same plane on both sides
489 if (worldhigh != worldtop
490 || backsector->ceilingpic != frontsector->ceilingpic
491 || backsector->lightlevel != frontsector->lightlevel)
494 markceiling = false; // same plane on both sides
496 if (backsector->ceilingheight <= frontsector->floorheight
497 || backsector->floorheight >= frontsector->ceilingheight)
498 markceiling = markfloor = true; // closed door
500 if (worldhigh < worldtop)
502 toptexture = texturetranslation[sidedef->toptexture];
503 if (linedef->flags & ML_DONTPEGTOP)
504 rw_toptexturemid = worldtop; // top of texture at top
507 vtop = backsector->ceilingheight +
508 textureheight[sidedef->toptexture];
509 rw_toptexturemid = vtop - viewz; // bottom of texture
512 if (worldlow > worldbottom)
514 bottomtexture = texturetranslation[sidedef->bottomtexture];
515 if (linedef->flags & ML_DONTPEGBOTTOM )
516 { // bottom of texture at bottom
517 rw_bottomtexturemid = worldtop;// top of texture at top
519 else // top of texture at top
520 rw_bottomtexturemid = worldlow;
522 rw_toptexturemid += sidedef->rowoffset;
523 rw_bottomtexturemid += sidedef->rowoffset;
526 // allocate space for masked texture tables
528 if (sidedef->midtexture)
529 { // masked midtexture
530 maskedtexture = true;
531 ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x;
532 lastopening += rw_stopx - rw_x;
537 // calculate rw_offset (only needed for textured lines)
539 segtextured = midtexture | toptexture | bottomtexture | maskedtexture;
543 offsetangle = rw_normalangle-rw_angle1;
544 if (offsetangle > ANG180)
545 offsetangle = -offsetangle;
546 if (offsetangle > ANG90)
548 sineval = finesine[offsetangle >>ANGLETOFINESHIFT];
549 rw_offset = FixedMul (hyp, sineval);
550 if (rw_normalangle-rw_angle1 < ANG180)
551 rw_offset = -rw_offset;
552 rw_offset += sidedef->textureoffset + curline->offset;
553 rw_centerangle = ANG90 + viewangle - rw_normalangle;
556 // calculate light table
557 // use different light tables for horizontal / vertical / diagonal
558 // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
561 lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight;
562 if (curline->v1->y == curline->v2->y)
564 else if (curline->v1->x == curline->v2->x)
567 walllights = scalelight[0];
568 else if (lightnum >= LIGHTLEVELS)
569 walllights = scalelight[LIGHTLEVELS-1];
571 walllights = scalelight[lightnum];
577 // if a floor / ceiling plane is on the wrong side of the view plane
578 // it is definately invisible and doesn't need to be marked
580 if (frontsector->floorheight >= viewz)
581 markfloor = false; // above view plane
582 if (frontsector->ceilingheight <= viewz
583 && frontsector->ceilingpic != skyflatnum)
584 markceiling = false; // below view plane
587 // calculate incremental stepping values for texture edges
592 topstep = -FixedMul (rw_scalestep, worldtop);
593 topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale);
595 bottomstep = -FixedMul (rw_scalestep,worldbottom);
596 bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale);
603 if (worldhigh < worldtop)
605 pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale);
606 pixhighstep = -FixedMul (rw_scalestep,worldhigh);
608 if (worldlow > worldbottom)
610 pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale);
611 pixlowstep = -FixedMul (rw_scalestep,worldlow);
619 ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1);
621 floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1);
626 // save sprite clipping info
628 if ( ((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip)
630 memcpy (lastopening, ceilingclip+start, 2*(rw_stopx-start));
631 ds_p->sprtopclip = lastopening - start;
632 lastopening += rw_stopx - start;
634 if ( ((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && !ds_p->sprbottomclip)
636 memcpy (lastopening, floorclip+start, 2*(rw_stopx-start));
637 ds_p->sprbottomclip = lastopening - start;
638 lastopening += rw_stopx - start;
640 if (maskedtexture && !(ds_p->silhouette&SIL_TOP))
642 ds_p->silhouette |= SIL_TOP;
643 ds_p->tsilheight = MININT;
645 if (maskedtexture && !(ds_p->silhouette&SIL_BOTTOM))
647 ds_p->silhouette |= SIL_BOTTOM;
648 ds_p->bsilheight = MAXINT;