# Correct the needed linklibs in curl-config also.
[AROS-Contrib.git] / Games / Doom / r_segs.c
blobf439465f2c4ea51ebeff460f6b3fa87a172ee69c
1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id$
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 //
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
15 // for more details.
17 // $Log$
18 // Revision 1.1 2000/02/29 18:21:05 stegerg
19 // Doom port based on ADoomPPC. Read README.AROS!
22 // DESCRIPTION:
23 // All the clipping: columns, horizontal spans, sky columns.
25 //-----------------------------------------------------------------------------
28 static const char
29 rcsid[] = "$Id$";
35 #include <stdlib.h>
37 #include "i_system.h"
39 #include "doomdef.h"
40 #include "doomstat.h"
42 #include "r_local.h"
43 #include "r_sky.h"
46 // OPTIMIZE: closed two sided lines as single sided
48 // True if any of the segs textures might be visible.
49 boolean segtextured;
51 // False if the back side is the same plane.
52 boolean markfloor;
53 boolean markceiling;
55 boolean maskedtexture;
56 int toptexture;
57 int bottomtexture;
58 int midtexture;
61 angle_t rw_normalangle;
62 // angle to line origin
63 int rw_angle1;
66 // regular wall
68 int rw_x;
69 int rw_stopx;
70 angle_t rw_centerangle;
71 fixed_t rw_offset;
72 fixed_t rw_distance;
73 fixed_t rw_scale;
74 fixed_t rw_scalestep;
75 fixed_t rw_midtexturemid;
76 fixed_t rw_toptexturemid;
77 fixed_t rw_bottomtexturemid;
79 int worldtop;
80 int worldbottom;
81 int worldhigh;
82 int worldlow;
84 fixed_t pixhigh;
85 fixed_t pixlow;
86 fixed_t pixhighstep;
87 fixed_t pixlowstep;
89 fixed_t topfrac;
90 fixed_t topstep;
92 fixed_t bottomfrac;
93 fixed_t bottomstep;
96 lighttable_t** walllights;
98 short* maskedtexturecol;
103 // R_RenderMaskedSegRange
105 void
106 R_RenderMaskedSegRange
107 ( drawseg_t* ds,
108 int x1,
109 int x2 )
111 unsigned index;
112 column_t* col;
113 int lightnum;
114 int texnum;
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)
128 lightnum--;
129 else if (curline->v1->x == curline->v2->x)
130 lightnum++;
132 if (lightnum < 0)
133 walllights = scalelight[0];
134 else if (lightnum >= LIGHTLEVELS)
135 walllights = scalelight[LIGHTLEVELS-1];
136 else
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;
146 // find positioning
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;
153 else
155 dc_texturemid =frontsector->ceilingheight<backsector->ceilingheight
156 ? frontsector->ceilingheight : backsector->ceilingheight;
157 dc_texturemid = dc_texturemid - viewz;
159 dc_texturemid += curline->sidedef->rowoffset;
161 if (fixedcolormap)
162 dc_colormap = fixedcolormap;
164 // draw the columns
165 for (dc_x = x1 ; dc_x <= x2 ; dc_x++)
167 // calculate lighting
168 if (maskedtexturecol[dc_x] != MAXSHORT)
170 if (!fixedcolormap)
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;
183 // draw the texture
184 col = (column_t *)(
185 (byte *)R_GetColumn(texnum,maskedtexturecol[dc_x]) -3);
187 R_DrawMaskedColumn (col);
189 maskedtexturecol[dc_x] = MAXSHORT;
191 spryscale += rw_scalestep;
199 //#define DO_STATS
201 #ifdef DO_STATS
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]++
204 #else
205 #define STATS(x)
206 #endif
210 // R_RenderSegLoop
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
214 // textures.
215 // CALLED: CORE LOOPING ROUTINE.
217 #define HEIGHTBITS 12
218 #define HEIGHTUNIT (1<<HEIGHTBITS)
220 void R_RenderSegLoop (void)
222 angle_t angle;
223 unsigned index;
224 int yl;
225 int yh;
226 int mid;
227 fixed_t texturecolumn = 0;
228 int top;
229 int bottom;
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;
246 if (markceiling)
248 STATS(3); /* 1291140 */
249 top = ceilingclip[rw_x]+1;
250 bottom = yl-1;
252 if (bottom >= floorclip[rw_x]) {
253 STATS(4); /* 50179 */
254 bottom = floorclip[rw_x]-1;
256 if (top <= bottom)
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;
270 if (markfloor)
272 STATS(7); /* 1298743 */
273 top = yh+1;
274 bottom = floorclip[rw_x]-1;
275 if (top <= ceilingclip[rw_x]) {
276 STATS(8); /* 49048 */
277 top = ceilingclip[rw_x]+1;
279 if (top <= bottom)
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
288 if (segtextured)
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];
303 dc_x = rw_x;
304 dc_iscale = 0xffffffffu / (unsigned)rw_scale;
307 // draw the wall tiers
308 if (midtexture)
310 STATS(12); /* 560607 */
311 // single sided line
312 dc_yl = yl;
313 dc_yh = yh;
314 dc_texturemid = rw_midtexturemid;
315 dc_source = R_GetColumn(midtexture,texturecolumn);
316 colfunc ();
317 ceilingclip[rw_x] = viewheight;
318 floorclip[rw_x] = -1;
320 else
322 STATS(13); /* 1043126 */
323 // two sided line
324 if (toptexture)
326 STATS(14); /* 314333 */
327 // top wall
328 mid = pixhigh>>HEIGHTBITS;
329 pixhigh += pixhighstep;
331 if (mid >= floorclip[rw_x]) {
332 STATS(15); /* 45511 */
333 mid = floorclip[rw_x]-1;
335 if (mid >= yl)
337 STATS(16); /* 139708 */
338 dc_yl = yl;
339 dc_yh = mid;
340 dc_texturemid = rw_toptexturemid;
341 dc_source = R_GetColumn(toptexture,texturecolumn);
342 colfunc ();
343 ceilingclip[rw_x] = mid;
345 else {
346 STATS(17); /* 174625 */
347 ceilingclip[rw_x] = yl-1;
350 else
352 STATS(18); /* 728793 */
353 // no top wall
354 if (markceiling) {
355 STATS(19); /* 439926 */
356 ceilingclip[rw_x] = yl-1;
360 if (bottomtexture)
362 STATS(20); /* 446785 */
363 // bottom wall
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;
372 if (mid <= yh)
374 STATS(22); /* 366880 */
375 dc_yl = mid;
376 dc_yh = yh;
377 dc_texturemid = rw_bottomtexturemid;
378 dc_source = R_GetColumn(bottomtexture,
379 texturecolumn);
380 colfunc ();
381 floorclip[rw_x] = mid;
383 else {
384 STATS(23); /* 79905 */
385 floorclip[rw_x] = yh+1;
388 else
390 STATS(24); /* 596341 */
391 // no bottom wall
392 if (markfloor)
393 floorclip[rw_x] = yh+1;
396 if (maskedtexture)
398 STATS(25); /* 0 */
399 // save texturecol
400 // for backdrawing of masked mid texture
401 maskedtexturecol[rw_x] = texturecolumn;
405 rw_scale += rw_scalestep;
406 topfrac += topstep;
407 bottomfrac += bottomstep;
412 #ifdef DO_STATS
413 void _STDdo_stats (void)
415 int i;
417 for (i = 0; i < 26; i++)
418 printf ("stats[%2d] = %u\n", i, stats[i]);
420 #endif
426 // R_StoreWallRange
427 // A wall segment will be drawn
428 // between start and stop pixels (inclusive).
430 void
431 R_StoreWallRange
432 ( int start,
433 int stop )
435 fixed_t hyp;
436 fixed_t sineval;
437 angle_t distangle, offsetangle;
438 fixed_t vtop;
439 int lightnum;
441 // don't overflow and crash
442 if (ds_p == &drawsegs[MAXDRAWSEGS])
443 return;
445 #ifdef RANGECHECK
446 if (start >=viewwidth || start > stop)
447 I_Error ("Bad R_RenderWallRange: %i to %i", start , stop);
448 #endif
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)
461 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;
470 ds_p->x2 = stop;
471 ds_p->curline = curline;
472 rw_stopx = stop+1;
474 // calculate scale at both ends and step
475 ds_p->scale1 = rw_scale =
476 R_ScaleFromGlobalAngle (viewangle + xtoviewangle[start]);
478 if (stop > start )
480 ds_p->scale2 = R_ScaleFromGlobalAngle (viewangle + xtoviewangle[stop]);
481 ds_p->scalestep = rw_scalestep =
482 (ds_p->scale2 - rw_scale) / (stop-start);
484 else
486 // UNUSED: try to fix the stretched line bug
487 #if 0
488 if (rw_distance < FRACUNIT/2)
490 fixed_t trx,try;
491 fixed_t gxt,gyt;
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;
500 #endif
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;
512 if (!backsector)
514 // single sided line
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;
525 else
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;
538 else
540 // two sided line
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)
597 markfloor = true;
599 else
601 // same plane on both sides
602 markfloor = false;
606 if (worldhigh != worldtop
607 || backsector->ceilingpic != frontsector->ceilingpic
608 || backsector->lightlevel != frontsector->lightlevel)
610 markceiling = true;
612 else
614 // same plane on both sides
615 markceiling = false;
618 if (backsector->ceilingheight <= frontsector->floorheight
619 || backsector->floorheight >= frontsector->ceilingheight)
621 // closed door
622 markceiling = markfloor = true;
626 if (worldhigh < worldtop)
628 // top texture
629 toptexture = texturetranslation[sidedef->toptexture];
630 if (linedef->flags & ML_DONTPEGTOP)
632 // top of texture at top
633 rw_toptexturemid = worldtop;
635 else
637 vtop =
638 backsector->ceilingheight
639 + textureheight[sidedef->toptexture];
641 // bottom of texture
642 rw_toptexturemid = vtop - viewz;
645 if (worldlow > worldbottom)
647 // bottom texture
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)
665 // masked 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;
675 if (segtextured)
677 offsetangle = rw_normalangle-rw_angle1;
679 if (offsetangle > ANG180)
680 offsetangle = -offsetangle;
682 if (offsetangle > ANG90)
683 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
698 if (!fixedcolormap)
700 lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight;
702 if (curline->v1->y == curline->v2->y)
703 lightnum--;
704 else if (curline->v1->x == curline->v2->x)
705 lightnum++;
707 if (lightnum < 0)
708 walllights = scalelight[0];
709 else if (lightnum >= LIGHTLEVELS)
710 walllights = scalelight[LIGHTLEVELS-1];
711 else
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)
723 // above view plane
724 markfloor = false;
727 if (frontsector->ceilingheight <= viewz
728 && frontsector->ceilingpic != skyflatnum)
730 // below view plane
731 markceiling = false;
735 // calculate incremental stepping values for texture edges
736 worldtop >>= 4;
737 worldbottom >>= 4;
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);
746 if (backsector)
748 worldhigh >>= 4;
749 worldlow >>= 4;
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);
764 // render it
765 if (markceiling)
766 ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1);
768 if (markfloor)
769 floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1);
771 R_RenderSegLoop ();
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;
801 ds_p++;