2 //**************************************************************************
4 //** r_segs.c : Heretic 2 : Raven Software, Corp.
11 //** This version has the tall-sector-crossing-precision-bug fixed.
13 //**************************************************************************
18 // OPTIMIZE: closed two sided lines as single sided
20 boolean segtextured; // true if any of the segs textures might be vis
21 boolean markfloor; // false if the back side is the same plane
23 boolean maskedtexture;
24 int toptexture, bottomtexture, midtexture;
27 angle_t rw_normalangle;
28 int rw_angle1; // angle to line origin
35 angle_t rw_centerangle;
40 fixed_t rw_midtexturemid;
41 fixed_t rw_toptexturemid;
42 fixed_t rw_bottomtexturemid;
44 int worldtop, worldbottom, worldhigh, worldlow;
46 fixed_t pixhigh, pixlow;
47 fixed_t pixhighstep, pixlowstep;
48 fixed_t topfrac, topstep;
49 fixed_t bottomfrac, bottomstep;
52 lighttable_t **walllights;
54 short *maskedtexturecol;
58 void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) {}
59 void R_RenderSegLoop (void) {}
60 void R_StoreWallRange (int start, int stop) {}
66 = R_RenderMaskedSegRange
71 void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
79 // calculate light table
80 // use different light tables for horizontal / vertical / diagonal
81 // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
82 curline = ds->curline;
83 frontsector = curline->frontsector;
84 backsector = curline->backsector;
85 texnum = texturetranslation[curline->sidedef->midtexture];
87 lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight;
88 //if (curline->v1->y == curline->v2->y)
90 //else if (curline->v1->x == curline->v2->x)
93 // walllights = scalelight[0];
94 if (lightnum >= LIGHTLEVELS)
95 walllights = scalelight[LIGHTLEVELS-1];
97 walllights = scalelight[lightnum];
99 maskedtexturecol = ds->maskedtexturecol;
101 rw_scalestep = ds->scalestep;
102 spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
103 mfloorclip = ds->sprbottomclip;
104 mceilingclip = ds->sprtopclip;
109 if (curline->linedef->flags & ML_DONTPEGBOTTOM)
111 dc_texturemid = frontsector->floorheight > backsector->floorheight
112 ? frontsector->floorheight : backsector->floorheight;
113 dc_texturemid = dc_texturemid + textureheight[texnum] - viewz;
117 dc_texturemid =frontsector->ceilingheight<backsector->ceilingheight
118 ? frontsector->ceilingheight : backsector->ceilingheight;
119 dc_texturemid = dc_texturemid - viewz;
121 dc_texturemid += curline->sidedef->rowoffset;
124 dc_colormap = fixedcolormap;
128 for (dc_x = x1 ; dc_x <= x2 ; dc_x++)
130 // calculate lighting
131 if (maskedtexturecol[dc_x] != MAXSHORT)
135 index = spryscale>>LIGHTSCALESHIFT;
136 if (index >= MAXLIGHTSCALE )
137 index = MAXLIGHTSCALE-1;
138 dc_colormap = walllights[index];
141 sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
142 dc_iscale = 0xffffffffu / (unsigned)spryscale;
148 (byte *)R_GetColumn(texnum,maskedtexturecol[dc_x]) -3);
150 R_DrawMaskedColumn (col, -1);
151 maskedtexturecol[dc_x] = MAXSHORT;
153 spryscale += rw_scalestep;
162 = Draws zero, one, or two textures (and possibly a masked texture) for walls
163 = Can draw or mark the starting pixel of floor and ceiling textures
165 = CALLED: CORE LOOPING ROUTINE
169 #define HEIGHTBITS 12
170 #define HEIGHTUNIT (1<<HEIGHTBITS)
172 void R_RenderSegLoop (void)
177 fixed_t texturecolumn;
180 /* jim put this back in again */
181 texturecolumn = 0; // shut up compiler warning
183 for ( ; rw_x < rw_stopx ; rw_x++)
186 // mark floor / ceiling areas
188 yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;
189 if (yl < ceilingclip[rw_x]+1)
190 yl = ceilingclip[rw_x]+1; // no space above wall
193 top = ceilingclip[rw_x]+1;
195 if (bottom >= floorclip[rw_x])
196 bottom = floorclip[rw_x]-1;
199 ceilingplane->top[rw_x] = top;
200 ceilingplane->bottom[rw_x] = bottom;
204 yh = bottomfrac>>HEIGHTBITS;
205 if (yh >= floorclip[rw_x])
206 yh = floorclip[rw_x]-1;
210 bottom = floorclip[rw_x]-1;
211 if (top <= ceilingclip[rw_x])
212 top = ceilingclip[rw_x]+1;
215 floorplane->top[rw_x] = top;
216 floorplane->bottom[rw_x] = bottom;
221 // texturecolumn and lighting are independent of wall tiers
225 // calculate texture offset
226 angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT;
227 texturecolumn = rw_offset-FixedMul(finetangent[angle],rw_distance);
228 texturecolumn >>= FRACBITS;
229 // calculate lighting
230 index = rw_scale>>LIGHTSCALESHIFT;
231 if (index >= MAXLIGHTSCALE )
232 index = MAXLIGHTSCALE-1;
233 dc_colormap = walllights[index];
235 dc_iscale = 0xffffffffu / (unsigned)rw_scale;
239 // draw the wall tiers
242 { // single sided line
245 dc_texturemid = rw_midtexturemid;
246 dc_source = R_GetColumn(midtexture,texturecolumn);
248 ceilingclip[rw_x] = viewheight;
249 floorclip[rw_x] = -1;
255 mid = pixhigh>>HEIGHTBITS;
256 pixhigh += pixhighstep;
257 if (mid >= floorclip[rw_x])
258 mid = floorclip[rw_x]-1;
263 dc_texturemid = rw_toptexturemid;
264 dc_source = R_GetColumn(toptexture,texturecolumn);
266 ceilingclip[rw_x] = mid;
269 ceilingclip[rw_x] = yl-1;
274 ceilingclip[rw_x] = yl-1;
279 mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS;
280 pixlow += pixlowstep;
281 if (mid <= ceilingclip[rw_x])
282 mid = ceilingclip[rw_x]+1; // no space above wall
287 dc_texturemid = rw_bottomtexturemid;
288 dc_source = R_GetColumn(bottomtexture,
291 floorclip[rw_x] = mid;
294 floorclip[rw_x] = yh+1;
299 floorclip[rw_x] = yh+1;
303 { // save texturecol for backdrawing of masked mid texture
304 maskedtexturecol[rw_x] = texturecolumn;
308 rw_scale += rw_scalestep;
310 bottomfrac += bottomstep;
317 =====================
321 = A wall segment will be drawn between start and stop pixels (inclusive)
323 ======================
326 void R_StoreWallRange (int start, int stop)
330 angle_t distangle, offsetangle;
334 if (ds_p == &drawsegs[MAXDRAWSEGS])
335 return; // don't overflow and crash
338 if (start >=viewwidth || start > stop)
339 I_Error ("Bad R_RenderWallRange: %i to %i", start , stop);
342 RD_DrawLine (curline);
345 sidedef = curline->sidedef;
346 linedef = curline->linedef;
348 // mark the segment as visible for auto map
349 linedef->flags |= ML_MAPPED;
352 // calculate rw_distance for scale calculation
354 rw_normalangle = curline->angle + ANG90;
355 offsetangle = abs(rw_normalangle-rw_angle1);
356 if (offsetangle > ANG90)
358 distangle = ANG90 - offsetangle;
359 hyp = R_PointToDist (curline->v1->x, curline->v1->y);
360 sineval = finesine[distangle>>ANGLETOFINESHIFT];
361 rw_distance = FixedMul (hyp, sineval);
364 ds_p->x1 = rw_x = start;
366 ds_p->curline = curline;
370 // calculate scale at both ends and step
372 ds_p->scale1 = rw_scale =
373 R_ScaleFromGlobalAngle (viewangle + xtoviewangle[start]);
376 ds_p->scale2 = R_ScaleFromGlobalAngle (viewangle + xtoviewangle[stop]);
377 ds_p->scalestep = rw_scalestep =
378 (ds_p->scale2 - rw_scale) / (stop-start);
383 // try to fix the stretched line bug
386 if (rw_distance < FRACUNIT/2)
391 trx = curline->v1->x - viewx;
392 try = curline->v1->y - viewy;
394 gxt = FixedMul(trx,viewcos);
395 gyt = -FixedMul(try,viewsin);
396 ds_p->scale1 = FixedDiv(projection, gxt-gyt);
399 ds_p->scale2 = ds_p->scale1;
404 // calculate texture boundaries and decide if floor / ceiling marks
407 worldtop = frontsector->ceilingheight - viewz;
408 worldbottom = frontsector->floorheight - viewz;
410 midtexture = toptexture = bottomtexture = maskedtexture = 0;
411 ds_p->maskedtexturecol = NULL;
418 midtexture = texturetranslation[sidedef->midtexture];
419 // a single sided line is terminal, so it must mark ends
420 markfloor = markceiling = true;
421 if (linedef->flags & ML_DONTPEGBOTTOM)
423 vtop = frontsector->floorheight +
424 textureheight[sidedef->midtexture];
425 rw_midtexturemid = vtop - viewz; // bottom of texture at bottom
428 rw_midtexturemid = worldtop; // top of texture at top
429 rw_midtexturemid += sidedef->rowoffset;
430 ds_p->silhouette = SIL_BOTH;
431 ds_p->sprtopclip = screenheightarray;
432 ds_p->sprbottomclip = negonearray;
433 ds_p->bsilheight = MAXINT;
434 ds_p->tsilheight = MININT;
441 ds_p->sprtopclip = ds_p->sprbottomclip = NULL;
442 ds_p->silhouette = 0;
443 if (frontsector->floorheight > backsector->floorheight)
445 ds_p->silhouette = SIL_BOTTOM;
446 ds_p->bsilheight = frontsector->floorheight;
448 else if (backsector->floorheight > viewz)
450 ds_p->silhouette = SIL_BOTTOM;
451 ds_p->bsilheight = MAXINT;
452 // ds_p->sprbottomclip = negonearray;
454 if (frontsector->ceilingheight < backsector->ceilingheight)
456 ds_p->silhouette |= SIL_TOP;
457 ds_p->tsilheight = frontsector->ceilingheight;
459 else if (backsector->ceilingheight < viewz)
461 ds_p->silhouette |= SIL_TOP;
462 ds_p->tsilheight = MININT;
463 // ds_p->sprtopclip = screenheightarray;
466 if (backsector->ceilingheight <= frontsector->floorheight)
468 ds_p->sprbottomclip = negonearray;
469 ds_p->bsilheight = MAXINT;
470 ds_p->silhouette |= SIL_BOTTOM;
472 if (backsector->floorheight >= frontsector->ceilingheight)
474 ds_p->sprtopclip = screenheightarray;
475 ds_p->tsilheight = MININT;
476 ds_p->silhouette |= SIL_TOP;
478 worldhigh = backsector->ceilingheight - viewz;
479 worldlow = backsector->floorheight - viewz;
481 // hack to allow height changes in outdoor areas
482 if (frontsector->ceilingpic == skyflatnum
483 && backsector->ceilingpic == skyflatnum)
484 worldtop = worldhigh;
486 if (worldlow != worldbottom
487 || backsector->floorpic != frontsector->floorpic
488 || backsector->lightlevel != frontsector->lightlevel
489 || backsector->special != frontsector->special)
492 markfloor = false; // same plane on both sides
494 if (worldhigh != worldtop
495 || backsector->ceilingpic != frontsector->ceilingpic
496 || backsector->lightlevel != frontsector->lightlevel)
499 markceiling = false; // same plane on both sides
501 if (backsector->ceilingheight <= frontsector->floorheight
502 || backsector->floorheight >= frontsector->ceilingheight)
503 markceiling = markfloor = true; // closed door
505 if (worldhigh < worldtop)
507 toptexture = texturetranslation[sidedef->toptexture];
508 if (linedef->flags & ML_DONTPEGTOP)
509 rw_toptexturemid = worldtop; // top of texture at top
512 vtop = backsector->ceilingheight +
513 textureheight[sidedef->toptexture];
514 rw_toptexturemid = vtop - viewz; // bottom of texture
517 if (worldlow > worldbottom)
519 bottomtexture = texturetranslation[sidedef->bottomtexture];
520 if (linedef->flags & ML_DONTPEGBOTTOM )
521 { // bottom of texture at bottom
522 rw_bottomtexturemid = worldtop;// top of texture at top
524 else // top of texture at top
525 rw_bottomtexturemid = worldlow;
527 rw_toptexturemid += sidedef->rowoffset;
528 rw_bottomtexturemid += sidedef->rowoffset;
531 // allocate space for masked texture tables
533 if (sidedef->midtexture)
534 { // masked midtexture
535 maskedtexture = true;
536 ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x;
537 lastopening += rw_stopx - rw_x;
542 // calculate rw_offset (only needed for textured lines)
544 segtextured = midtexture | toptexture | bottomtexture | maskedtexture;
548 offsetangle = rw_normalangle-rw_angle1;
549 if (offsetangle > ANG180)
550 offsetangle = -offsetangle;
551 if (offsetangle > ANG90)
553 sineval = finesine[offsetangle >>ANGLETOFINESHIFT];
554 rw_offset = FixedMul (hyp, sineval);
555 if (rw_normalangle-rw_angle1 < ANG180)
556 rw_offset = -rw_offset;
557 rw_offset += sidedef->textureoffset + curline->offset;
558 rw_centerangle = ANG90 + viewangle - rw_normalangle;
561 // calculate light table
562 // use different light tables for horizontal / vertical / diagonal
563 // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
566 lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight;
567 //if (curline->v1->y == curline->v2->y)
569 //else if (curline->v1->x == curline->v2->x)
572 // walllights = scalelight[0];
573 if (lightnum >= LIGHTLEVELS)
574 walllights = scalelight[LIGHTLEVELS-1];
576 walllights = scalelight[lightnum];
582 // if a floor / ceiling plane is on the wrong side of the view plane
583 // it is definately invisible and doesn't need to be marked
585 if (frontsector->floorheight >= viewz)
586 markfloor = false; // above view plane
587 if (frontsector->ceilingheight <= viewz
588 && frontsector->ceilingpic != skyflatnum)
589 markceiling = false; // below view plane
592 // calculate incremental stepping values for texture edges
597 topstep = -FixedMul (rw_scalestep, worldtop);
598 topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale);
600 bottomstep = -FixedMul (rw_scalestep,worldbottom);
601 bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale);
608 if (worldhigh < worldtop)
610 pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale);
611 pixhighstep = -FixedMul (rw_scalestep,worldhigh);
613 if (worldlow > worldbottom)
615 pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale);
616 pixlowstep = -FixedMul (rw_scalestep,worldlow);
624 ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1);
626 floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1);
631 // save sprite clipping info
633 if ( ((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip)
635 memcpy (lastopening, ceilingclip+start, 2*(rw_stopx-start));
636 ds_p->sprtopclip = lastopening - start;
637 lastopening += rw_stopx - start;
639 if ( ((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && !ds_p->sprbottomclip)
641 memcpy (lastopening, floorclip+start, 2*(rw_stopx-start));
642 ds_p->sprbottomclip = lastopening - start;
643 lastopening += rw_stopx - start;
645 if (maskedtexture && !(ds_p->silhouette&SIL_TOP))
647 ds_p->silhouette |= SIL_TOP;
648 ds_p->tsilheight = MININT;
650 if (maskedtexture && !(ds_p->silhouette&SIL_BOTTOM))
652 ds_p->silhouette |= SIL_BOTTOM;
653 ds_p->bsilheight = MAXINT;