1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
6 // Copyright (C) 1993-1996 by id Software, Inc.
8 // This source is available for distribution and/or modification
9 // only under the terms of the DOOM Source Code License as
10 // published by id Software. All rights reserved.
12 // The source is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
18 // Revision 1.1 2000/02/29 18:21:05 stegerg
19 // Doom port based on ADoomPPC. Read README.AROS!
23 // All the clipping: columns, horizontal spans, sky columns.
25 //-----------------------------------------------------------------------------
46 // OPTIMIZE: closed two sided lines as single sided
48 // True if any of the segs textures might be visible.
51 // False if the back side is the same plane.
55 boolean maskedtexture
;
61 angle_t rw_normalangle
;
62 // angle to line origin
70 angle_t rw_centerangle
;
75 fixed_t rw_midtexturemid
;
76 fixed_t rw_toptexturemid
;
77 fixed_t rw_bottomtexturemid
;
96 lighttable_t
** walllights
;
98 short* maskedtexturecol
;
103 // R_RenderMaskedSegRange
106 R_RenderMaskedSegRange
116 // Calculate light table.
117 // Use different light tables
118 // for horizontal / vertical / diagonal. Diagonal?
119 // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
120 curline
= ds
->curline
;
121 frontsector
= curline
->frontsector
;
122 backsector
= curline
->backsector
;
123 texnum
= texturetranslation
[curline
->sidedef
->midtexture
];
125 lightnum
= (frontsector
->lightlevel
>> LIGHTSEGSHIFT
)+extralight
;
127 if (curline
->v1
->y
== curline
->v2
->y
)
129 else if (curline
->v1
->x
== curline
->v2
->x
)
133 walllights
= scalelight
[0];
134 else if (lightnum
>= LIGHTLEVELS
)
135 walllights
= scalelight
[LIGHTLEVELS
-1];
137 walllights
= scalelight
[lightnum
];
139 maskedtexturecol
= ds
->maskedtexturecol
;
141 rw_scalestep
= ds
->scalestep
;
142 spryscale
= ds
->scale1
+ (x1
- ds
->x1
)*rw_scalestep
;
143 mfloorclip
= ds
->sprbottomclip
;
144 mceilingclip
= ds
->sprtopclip
;
147 if (curline
->linedef
->flags
& ML_DONTPEGBOTTOM
)
149 dc_texturemid
= frontsector
->floorheight
> backsector
->floorheight
150 ? frontsector
->floorheight
: backsector
->floorheight
;
151 dc_texturemid
= dc_texturemid
+ textureheight
[texnum
] - viewz
;
155 dc_texturemid
=frontsector
->ceilingheight
<backsector
->ceilingheight
156 ? frontsector
->ceilingheight
: backsector
->ceilingheight
;
157 dc_texturemid
= dc_texturemid
- viewz
;
159 dc_texturemid
+= curline
->sidedef
->rowoffset
;
162 dc_colormap
= fixedcolormap
;
165 for (dc_x
= x1
; dc_x
<= x2
; dc_x
++)
167 // calculate lighting
168 if (maskedtexturecol
[dc_x
] != MAXSHORT
)
172 index
= spryscale
>>LIGHTSCALESHIFT
;
174 if (index
>= MAXLIGHTSCALE
)
175 index
= MAXLIGHTSCALE
-1;
177 dc_colormap
= walllights
[index
];
180 sprtopscreen
= centeryfrac
- FixedMul(dc_texturemid
, spryscale
);
181 dc_iscale
= 0xffffffffu
/ (unsigned)spryscale
;
185 (byte
*)R_GetColumn(texnum
,maskedtexturecol
[dc_x
]) -3);
187 R_DrawMaskedColumn (col
);
189 maskedtexturecol
[dc_x
] = MAXSHORT
;
191 spryscale
+= rw_scalestep
;
202 unsigned int stats
[26] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
203 #define STATS(x) stats[x]++
211 // Draws zero, one, or two textures (and possibly a masked
212 // texture) for walls.
213 // Can draw or mark the starting pixel of floor and ceiling
215 // CALLED: CORE LOOPING ROUTINE.
217 #define HEIGHTBITS 12
218 #define HEIGHTUNIT (1<<HEIGHTBITS)
220 void R_RenderSegLoop (void)
227 fixed_t texturecolumn
= 0;
231 //texturecolumn = 0; // shut up compiler warning
233 STATS(0); /* 45443 */
234 for ( ; rw_x
< rw_stopx
; rw_x
++)
236 STATS(1); /* 1603733 */
237 // mark floor / ceiling areas
238 yl
= (topfrac
+HEIGHTUNIT
-1)>>HEIGHTBITS
;
240 // no space above wall?
241 if (yl
< ceilingclip
[rw_x
]+1) {
242 STATS(2); /* 1016131 */
243 yl
= ceilingclip
[rw_x
]+1;
248 STATS(3); /* 1291140 */
249 top
= ceilingclip
[rw_x
]+1;
252 if (bottom
>= floorclip
[rw_x
]) {
253 STATS(4); /* 50179 */
254 bottom
= floorclip
[rw_x
]-1;
258 STATS(5); /* 439559 */
259 ceilingplane
->top
[rw_x
] = top
;
260 ceilingplane
->bottom
[rw_x
] = bottom
;
264 yh
= bottomfrac
>>HEIGHTBITS
;
266 if (yh
>= floorclip
[rw_x
]) {
267 STATS(6); /* 670449 */
268 yh
= floorclip
[rw_x
]-1;
272 STATS(7); /* 1298743 */
274 bottom
= floorclip
[rw_x
]-1;
275 if (top
<= ceilingclip
[rw_x
]) {
276 STATS(8); /* 49048 */
277 top
= ceilingclip
[rw_x
]+1;
281 STATS(9); /* 726501 */
282 floorplane
->top
[rw_x
] = top
;
283 floorplane
->bottom
[rw_x
] = bottom
;
287 // texturecolumn and lighting are independent of wall tiers
290 STATS(10); /* 1261482 */
291 // calculate texture offset
292 angle
= (rw_centerangle
+ xtoviewangle
[rw_x
])>>ANGLETOFINESHIFT
;
293 texturecolumn
= rw_offset
-FixedMul(finetangent
[angle
],rw_distance
);
294 texturecolumn
>>= FRACBITS
;
295 // calculate lighting
296 index
= rw_scale
>>LIGHTSCALESHIFT
;
298 if (index
>= MAXLIGHTSCALE
) {
299 STATS(11); /* 169980 */
300 index
= MAXLIGHTSCALE
-1;
302 dc_colormap
= walllights
[index
];
304 dc_iscale
= 0xffffffffu
/ (unsigned)rw_scale
;
307 // draw the wall tiers
310 STATS(12); /* 560607 */
314 dc_texturemid
= rw_midtexturemid
;
315 dc_source
= R_GetColumn(midtexture
,texturecolumn
);
317 ceilingclip
[rw_x
] = viewheight
;
318 floorclip
[rw_x
] = -1;
322 STATS(13); /* 1043126 */
326 STATS(14); /* 314333 */
328 mid
= pixhigh
>>HEIGHTBITS
;
329 pixhigh
+= pixhighstep
;
331 if (mid
>= floorclip
[rw_x
]) {
332 STATS(15); /* 45511 */
333 mid
= floorclip
[rw_x
]-1;
337 STATS(16); /* 139708 */
340 dc_texturemid
= rw_toptexturemid
;
341 dc_source
= R_GetColumn(toptexture
,texturecolumn
);
343 ceilingclip
[rw_x
] = mid
;
346 STATS(17); /* 174625 */
347 ceilingclip
[rw_x
] = yl
-1;
352 STATS(18); /* 728793 */
355 STATS(19); /* 439926 */
356 ceilingclip
[rw_x
] = yl
-1;
362 STATS(20); /* 446785 */
364 mid
= (pixlow
+HEIGHTUNIT
-1)>>HEIGHTBITS
;
365 pixlow
+= pixlowstep
;
367 // no space above wall?
368 if (mid
<= ceilingclip
[rw_x
]) {
369 STATS(21); /* 67461 */
370 mid
= ceilingclip
[rw_x
]+1;
374 STATS(22); /* 366880 */
377 dc_texturemid
= rw_bottomtexturemid
;
378 dc_source
= R_GetColumn(bottomtexture
,
381 floorclip
[rw_x
] = mid
;
384 STATS(23); /* 79905 */
385 floorclip
[rw_x
] = yh
+1;
390 STATS(24); /* 596341 */
393 floorclip
[rw_x
] = yh
+1;
400 // for backdrawing of masked mid texture
401 maskedtexturecol
[rw_x
] = texturecolumn
;
405 rw_scale
+= rw_scalestep
;
407 bottomfrac
+= bottomstep
;
413 void _STDdo_stats (void)
417 for (i
= 0; i
< 26; i
++)
418 printf ("stats[%2d] = %u\n", i
, stats
[i
]);
427 // A wall segment will be drawn
428 // between start and stop pixels (inclusive).
437 angle_t distangle
, offsetangle
;
441 // don't overflow and crash
442 if (ds_p
== &drawsegs
[MAXDRAWSEGS
])
446 if (start
>=viewwidth
|| start
> stop
)
447 I_Error ("Bad R_RenderWallRange: %i to %i", start
, stop
);
450 sidedef
= curline
->sidedef
;
451 linedef
= curline
->linedef
;
453 // mark the segment as visible for auto map
454 linedef
->flags
|= ML_MAPPED
;
456 // calculate rw_distance for scale calculation
457 rw_normalangle
= curline
->angle
+ ANG90
;
458 offsetangle
= iabs(rw_normalangle
-rw_angle1
);
460 if (offsetangle
> ANG90
)
463 distangle
= ANG90
- offsetangle
;
464 hyp
= R_PointToDist (curline
->v1
->x
, curline
->v1
->y
);
465 sineval
= finesine
[distangle
>>ANGLETOFINESHIFT
];
466 rw_distance
= FixedMul (hyp
, sineval
);
469 ds_p
->x1
= rw_x
= start
;
471 ds_p
->curline
= curline
;
474 // calculate scale at both ends and step
475 ds_p
->scale1
= rw_scale
=
476 R_ScaleFromGlobalAngle (viewangle
+ xtoviewangle
[start
]);
480 ds_p
->scale2
= R_ScaleFromGlobalAngle (viewangle
+ xtoviewangle
[stop
]);
481 ds_p
->scalestep
= rw_scalestep
=
482 (ds_p
->scale2
- rw_scale
) / (stop
-start
);
486 // UNUSED: try to fix the stretched line bug
488 if (rw_distance
< FRACUNIT
/2)
493 trx
= curline
->v1
->x
- viewx
;
494 try = curline
->v1
->y
- viewy
;
496 gxt
= FixedMul(trx
,viewcos
);
497 gyt
= -FixedMul(try,viewsin
);
498 ds_p
->scale1
= FixedDiv(projection
, gxt
-gyt
)<<detailshift
;
501 ds_p
->scale2
= ds_p
->scale1
;
504 // calculate texture boundaries
505 // and decide if floor / ceiling marks are needed
506 worldtop
= frontsector
->ceilingheight
- viewz
;
507 worldbottom
= frontsector
->floorheight
- viewz
;
509 midtexture
= toptexture
= bottomtexture
= maskedtexture
= 0;
510 ds_p
->maskedtexturecol
= NULL
;
515 midtexture
= texturetranslation
[sidedef
->midtexture
];
516 // a single sided line is terminal, so it must mark ends
517 markfloor
= markceiling
= true;
518 if (linedef
->flags
& ML_DONTPEGBOTTOM
)
520 vtop
= frontsector
->floorheight
+
521 textureheight
[sidedef
->midtexture
];
522 // bottom of texture at bottom
523 rw_midtexturemid
= vtop
- viewz
;
527 // top of texture at top
528 rw_midtexturemid
= worldtop
;
530 rw_midtexturemid
+= sidedef
->rowoffset
;
532 ds_p
->silhouette
= SIL_BOTH
;
533 ds_p
->sprtopclip
= screenheightarray
;
534 ds_p
->sprbottomclip
= negonearray
;
535 ds_p
->bsilheight
= MAXINT
;
536 ds_p
->tsilheight
= MININT
;
541 ds_p
->sprtopclip
= ds_p
->sprbottomclip
= NULL
;
542 ds_p
->silhouette
= 0;
544 if (frontsector
->floorheight
> backsector
->floorheight
)
546 ds_p
->silhouette
= SIL_BOTTOM
;
547 ds_p
->bsilheight
= frontsector
->floorheight
;
549 else if (backsector
->floorheight
> viewz
)
551 ds_p
->silhouette
= SIL_BOTTOM
;
552 ds_p
->bsilheight
= MAXINT
;
553 // ds_p->sprbottomclip = negonearray;
556 if (frontsector
->ceilingheight
< backsector
->ceilingheight
)
558 ds_p
->silhouette
|= SIL_TOP
;
559 ds_p
->tsilheight
= frontsector
->ceilingheight
;
561 else if (backsector
->ceilingheight
< viewz
)
563 ds_p
->silhouette
|= SIL_TOP
;
564 ds_p
->tsilheight
= MININT
;
565 // ds_p->sprtopclip = screenheightarray;
568 if (backsector
->ceilingheight
<= frontsector
->floorheight
)
570 ds_p
->sprbottomclip
= negonearray
;
571 ds_p
->bsilheight
= MAXINT
;
572 ds_p
->silhouette
|= SIL_BOTTOM
;
575 if (backsector
->floorheight
>= frontsector
->ceilingheight
)
577 ds_p
->sprtopclip
= screenheightarray
;
578 ds_p
->tsilheight
= MININT
;
579 ds_p
->silhouette
|= SIL_TOP
;
582 worldhigh
= backsector
->ceilingheight
- viewz
;
583 worldlow
= backsector
->floorheight
- viewz
;
585 // hack to allow height changes in outdoor areas
586 if (frontsector
->ceilingpic
== skyflatnum
587 && backsector
->ceilingpic
== skyflatnum
)
589 worldtop
= worldhigh
;
593 if (worldlow
!= worldbottom
594 || backsector
->floorpic
!= frontsector
->floorpic
595 || backsector
->lightlevel
!= frontsector
->lightlevel
)
601 // same plane on both sides
606 if (worldhigh
!= worldtop
607 || backsector
->ceilingpic
!= frontsector
->ceilingpic
608 || backsector
->lightlevel
!= frontsector
->lightlevel
)
614 // same plane on both sides
618 if (backsector
->ceilingheight
<= frontsector
->floorheight
619 || backsector
->floorheight
>= frontsector
->ceilingheight
)
622 markceiling
= markfloor
= true;
626 if (worldhigh
< worldtop
)
629 toptexture
= texturetranslation
[sidedef
->toptexture
];
630 if (linedef
->flags
& ML_DONTPEGTOP
)
632 // top of texture at top
633 rw_toptexturemid
= worldtop
;
638 backsector
->ceilingheight
639 + textureheight
[sidedef
->toptexture
];
642 rw_toptexturemid
= vtop
- viewz
;
645 if (worldlow
> worldbottom
)
648 bottomtexture
= texturetranslation
[sidedef
->bottomtexture
];
650 if (linedef
->flags
& ML_DONTPEGBOTTOM
)
652 // bottom of texture at bottom
653 // top of texture at top
654 rw_bottomtexturemid
= worldtop
;
656 else // top of texture at top
657 rw_bottomtexturemid
= worldlow
;
659 rw_toptexturemid
+= sidedef
->rowoffset
;
660 rw_bottomtexturemid
+= sidedef
->rowoffset
;
662 // allocate space for masked texture tables
663 if (sidedef
->midtexture
)
666 maskedtexture
= true;
667 ds_p
->maskedtexturecol
= maskedtexturecol
= lastopening
- rw_x
;
668 lastopening
+= rw_stopx
- rw_x
;
672 // calculate rw_offset (only needed for textured lines)
673 segtextured
= midtexture
| toptexture
| bottomtexture
| maskedtexture
;
677 offsetangle
= rw_normalangle
-rw_angle1
;
679 if (offsetangle
> ANG180
)
680 offsetangle
= -offsetangle
;
682 if (offsetangle
> ANG90
)
685 sineval
= finesine
[offsetangle
>>ANGLETOFINESHIFT
];
686 rw_offset
= FixedMul (hyp
, sineval
);
688 if (rw_normalangle
-rw_angle1
< ANG180
)
689 rw_offset
= -rw_offset
;
691 rw_offset
+= sidedef
->textureoffset
+ curline
->offset
;
692 rw_centerangle
= ANG90
+ viewangle
- rw_normalangle
;
694 // calculate light table
695 // use different light tables
696 // for horizontal / vertical / diagonal
697 // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
700 lightnum
= (frontsector
->lightlevel
>> LIGHTSEGSHIFT
)+extralight
;
702 if (curline
->v1
->y
== curline
->v2
->y
)
704 else if (curline
->v1
->x
== curline
->v2
->x
)
708 walllights
= scalelight
[0];
709 else if (lightnum
>= LIGHTLEVELS
)
710 walllights
= scalelight
[LIGHTLEVELS
-1];
712 walllights
= scalelight
[lightnum
];
716 // if a floor / ceiling plane is on the wrong side
717 // of the view plane, it is definitely invisible
718 // and doesn't need to be marked.
721 if (frontsector
->floorheight
>= viewz
)
727 if (frontsector
->ceilingheight
<= viewz
728 && frontsector
->ceilingpic
!= skyflatnum
)
735 // calculate incremental stepping values for texture edges
739 topstep
= -FixedMul (rw_scalestep
, worldtop
);
740 topfrac
= (centeryfrac
>>4) - FixedMul (worldtop
, rw_scale
);
742 bottomstep
= -FixedMul (rw_scalestep
,worldbottom
);
743 bottomfrac
= (centeryfrac
>>4) - FixedMul (worldbottom
, rw_scale
);
751 if (worldhigh
< worldtop
)
753 pixhigh
= (centeryfrac
>>4) - FixedMul (worldhigh
, rw_scale
);
754 pixhighstep
= -FixedMul (rw_scalestep
,worldhigh
);
757 if (worldlow
> worldbottom
)
759 pixlow
= (centeryfrac
>>4) - FixedMul (worldlow
, rw_scale
);
760 pixlowstep
= -FixedMul (rw_scalestep
,worldlow
);
766 ceilingplane
= R_CheckPlane (ceilingplane
, rw_x
, rw_stopx
-1);
769 floorplane
= R_CheckPlane (floorplane
, rw_x
, rw_stopx
-1);
774 // save sprite clipping info
775 if ( ((ds_p
->silhouette
& SIL_TOP
) || maskedtexture
)
776 && !ds_p
->sprtopclip
)
778 memcpy (lastopening
, ceilingclip
+start
, 2*(rw_stopx
-start
));
779 ds_p
->sprtopclip
= lastopening
- start
;
780 lastopening
+= rw_stopx
- start
;
783 if ( ((ds_p
->silhouette
& SIL_BOTTOM
) || maskedtexture
)
784 && !ds_p
->sprbottomclip
)
786 memcpy (lastopening
, floorclip
+start
, 2*(rw_stopx
-start
));
787 ds_p
->sprbottomclip
= lastopening
- start
;
788 lastopening
+= rw_stopx
- start
;
791 if (maskedtexture
&& !(ds_p
->silhouette
&SIL_TOP
))
793 ds_p
->silhouette
|= SIL_TOP
;
794 ds_p
->tsilheight
= MININT
;
796 if (maskedtexture
&& !(ds_p
->silhouette
&SIL_BOTTOM
))
798 ds_p
->silhouette
|= SIL_BOTTOM
;
799 ds_p
->bsilheight
= MAXINT
;