]> icculus.org git repositories - theoddone33/hhexen.git/blob - base/r_segs.c
Remove obnoxious documentation files
[theoddone33/hhexen.git] / base / r_segs.c
1
2 //**************************************************************************
3 //**
4 //** r_segs.c : Heretic 2 : Raven Software, Corp.
5 //**
6 //** $RCSfile$
7 //** $Revision$
8 //** $Date$
9 //** $Author$
10 //**
11 //** This version has the tall-sector-crossing-precision-bug fixed.
12 //**
13 //**************************************************************************
14
15 #include "h2def.h"
16 #include "r_local.h"
17
18 // OPTIMIZE: closed two sided lines as single sided
19
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
22 boolean         markceiling;
23 boolean         maskedtexture;
24 int                     toptexture, bottomtexture, midtexture;
25
26
27 angle_t         rw_normalangle;
28 int                     rw_angle1;              // angle to line origin
29
30 //
31 // wall
32 //
33 int                     rw_x;
34 int                     rw_stopx;
35 angle_t         rw_centerangle;
36 fixed_t         rw_offset;
37 fixed_t         rw_distance;
38 fixed_t         rw_scale;
39 fixed_t         rw_scalestep;
40 fixed_t         rw_midtexturemid;
41 fixed_t         rw_toptexturemid;
42 fixed_t         rw_bottomtexturemid;
43
44 int                     worldtop, worldbottom, worldhigh, worldlow;
45
46 fixed_t         pixhigh, pixlow;
47 fixed_t         pixhighstep, pixlowstep;
48 fixed_t         topfrac, topstep;
49 fixed_t         bottomfrac, bottomstep;
50
51
52 lighttable_t    **walllights;
53
54 short           *maskedtexturecol;
55
56
57 #ifdef RENDER3D
58 void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) {}
59 void R_RenderSegLoop (void) {}
60 void R_StoreWallRange (int start, int stop) {}
61 #else
62
63 /*
64 ================
65 =
66 = R_RenderMaskedSegRange
67 =
68 ================
69 */
70
71 void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
72 {
73         unsigned        index;
74         column_t        *col;
75         int                     lightnum;
76         int                     texnum;
77
78 //
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];
86
87         lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight;
88         //if (curline->v1->y == curline->v2->y)
89         //      lightnum--;
90         //else if (curline->v1->x == curline->v2->x)
91         //      lightnum++;
92         //if (lightnum < 0)
93         //      walllights = scalelight[0];
94         if (lightnum >= LIGHTLEVELS)
95                 walllights = scalelight[LIGHTLEVELS-1];
96         else
97                 walllights = scalelight[lightnum];
98
99         maskedtexturecol = ds->maskedtexturecol;
100
101         rw_scalestep = ds->scalestep;
102         spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
103         mfloorclip = ds->sprbottomclip;
104         mceilingclip = ds->sprtopclip;
105
106 //
107 // find positioning
108 //
109         if (curline->linedef->flags & ML_DONTPEGBOTTOM)
110         {
111                 dc_texturemid = frontsector->floorheight > backsector->floorheight
112                 ? frontsector->floorheight : backsector->floorheight;
113                 dc_texturemid = dc_texturemid + textureheight[texnum] - viewz;
114         }
115         else
116         {
117                 dc_texturemid =frontsector->ceilingheight<backsector->ceilingheight
118                 ? frontsector->ceilingheight : backsector->ceilingheight;
119                 dc_texturemid = dc_texturemid - viewz;
120         }
121         dc_texturemid += curline->sidedef->rowoffset;
122
123         if (fixedcolormap)
124                 dc_colormap = fixedcolormap;
125 //
126 // draw the columns
127 //
128         for (dc_x = x1 ; dc_x <= x2 ; dc_x++)
129         {
130         // calculate lighting
131                 if (maskedtexturecol[dc_x] != MAXSHORT)
132                 {
133                         if (!fixedcolormap)
134                         {
135                                 index = spryscale>>LIGHTSCALESHIFT;
136                                 if (index >=  MAXLIGHTSCALE )
137                                         index = MAXLIGHTSCALE-1;
138                                 dc_colormap = walllights[index];
139                         }
140
141                         sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
142                         dc_iscale = 0xffffffffu / (unsigned)spryscale;
143
144         //
145         // draw the texture
146         //
147                         col = (column_t *)(
148                                 (byte *)R_GetColumn(texnum,maskedtexturecol[dc_x]) -3);
149
150                         R_DrawMaskedColumn (col, -1);
151                         maskedtexturecol[dc_x] = MAXSHORT;
152                 }
153                 spryscale += rw_scalestep;
154         }
155 }
156
157 /*
158 ================
159 =
160 = R_RenderSegLoop
161 =
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
164 =
165 = CALLED: CORE LOOPING ROUTINE
166 ================
167 */
168
169 #define HEIGHTBITS      12
170 #define HEIGHTUNIT      (1<<HEIGHTBITS)
171
172 void R_RenderSegLoop (void)
173 {
174         angle_t         angle;
175         unsigned        index;
176         int                     yl, yh, mid;
177         fixed_t         texturecolumn;
178         int                     top, bottom;
179
180         /* jim put this back in again */
181       texturecolumn = 0;                              // shut up compiler warning
182
183         for ( ; rw_x < rw_stopx ; rw_x++)
184         {
185 //
186 // mark floor / ceiling areas
187 //
188                 yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;
189                 if (yl < ceilingclip[rw_x]+1)
190                         yl = ceilingclip[rw_x]+1;       // no space above wall
191                 if (markceiling)
192                 {
193                         top = ceilingclip[rw_x]+1;
194                         bottom = yl-1;
195                         if (bottom >= floorclip[rw_x])
196                                 bottom = floorclip[rw_x]-1;
197                         if (top <= bottom)
198                         {
199                                 ceilingplane->top[rw_x] = top;
200                                 ceilingplane->bottom[rw_x] = bottom;
201                         }
202                 }
203
204                 yh = bottomfrac>>HEIGHTBITS;
205                 if (yh >= floorclip[rw_x])
206                         yh = floorclip[rw_x]-1;
207                 if (markfloor)
208                 {
209                         top = yh+1;
210                         bottom = floorclip[rw_x]-1;
211                         if (top <= ceilingclip[rw_x])
212                                 top = ceilingclip[rw_x]+1;
213                         if (top <= bottom)
214                         {
215                                 floorplane->top[rw_x] = top;
216                                 floorplane->bottom[rw_x] = bottom;
217                         }
218                 }
219
220 //
221 // texturecolumn and lighting are independent of wall tiers
222 //
223                 if (segtextured)
224                 {
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];
234                         dc_x = rw_x;
235                         dc_iscale = 0xffffffffu / (unsigned)rw_scale;
236                 }
237
238 //
239 // draw the wall tiers
240 //
241                 if (midtexture)
242                 {       // single sided line
243                         dc_yl = yl;
244                         dc_yh = yh;
245                         dc_texturemid = rw_midtexturemid;
246                         dc_source = R_GetColumn(midtexture,texturecolumn);
247                         colfunc ();
248                         ceilingclip[rw_x] = viewheight;
249                         floorclip[rw_x] = -1;
250                 }
251                 else
252                 {       // two sided line
253                         if (toptexture)
254                         {       // top wall
255                                 mid = pixhigh>>HEIGHTBITS;
256                                 pixhigh += pixhighstep;
257                                 if (mid >= floorclip[rw_x])
258                                         mid = floorclip[rw_x]-1;
259                                 if (mid >= yl)
260                                 {
261                                         dc_yl = yl;
262                                         dc_yh = mid;
263                                         dc_texturemid = rw_toptexturemid;
264                                         dc_source = R_GetColumn(toptexture,texturecolumn);
265                                         colfunc ();
266                                         ceilingclip[rw_x] = mid;
267                                 }
268                                 else
269                                         ceilingclip[rw_x] = yl-1;
270                         }
271                         else
272                         {       // no top wall
273                                 if (markceiling)
274                                         ceilingclip[rw_x] = yl-1;
275                         }
276
277                         if (bottomtexture)
278                         {       // bottom wall
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
283                                 if (mid <= yh)
284                                 {
285                                         dc_yl = mid;
286                                         dc_yh = yh;
287                                         dc_texturemid = rw_bottomtexturemid;
288                                         dc_source = R_GetColumn(bottomtexture,
289                                                  texturecolumn);
290                                         colfunc ();
291                                         floorclip[rw_x] = mid;
292                                 }
293                                 else
294                                         floorclip[rw_x] = yh+1;
295                         }
296                         else
297                         {       // no bottom wall
298                                 if (markfloor)
299                                         floorclip[rw_x] = yh+1;
300                         }
301
302                         if (maskedtexture)
303                         {       // save texturecol for backdrawing of masked mid texture
304                                 maskedtexturecol[rw_x] = texturecolumn;
305                         }
306                 }
307
308                 rw_scale += rw_scalestep;
309                 topfrac += topstep;
310                 bottomfrac += bottomstep;
311         }
312 }
313
314
315
316 /*
317 =====================
318 =
319 = R_StoreWallRange
320 =
321 = A wall segment will be drawn between start and stop pixels (inclusive)
322 =
323 ======================
324 */
325
326 void R_StoreWallRange (int start, int stop)
327 {
328         fixed_t         hyp;
329         fixed_t         sineval;
330         angle_t         distangle, offsetangle;
331         fixed_t         vtop;
332         int                     lightnum;
333
334         if (ds_p == &drawsegs[MAXDRAWSEGS])
335                 return;         // don't overflow and crash
336
337 #ifdef RANGECHECK
338         if (start >=viewwidth || start > stop)
339                 I_Error ("Bad R_RenderWallRange: %i to %i", start , stop);
340 #endif
341 #ifdef __NeXT__
342         RD_DrawLine (curline);
343 #endif
344
345         sidedef = curline->sidedef;
346         linedef = curline->linedef;
347
348 // mark the segment as visible for auto map
349         linedef->flags |= ML_MAPPED;
350
351 //
352 // calculate rw_distance for scale calculation
353 //
354         rw_normalangle = curline->angle + ANG90;
355         offsetangle = abs(rw_normalangle-rw_angle1);
356         if (offsetangle > ANG90)
357                 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);
362
363
364         ds_p->x1 = rw_x = start;
365         ds_p->x2 = stop;
366         ds_p->curline = curline;
367         rw_stopx = stop+1;
368
369 //
370 // calculate scale at both ends and step
371 //
372         ds_p->scale1 = rw_scale =
373                 R_ScaleFromGlobalAngle (viewangle + xtoviewangle[start]);
374         if (stop > start )
375         {
376                 ds_p->scale2 = R_ScaleFromGlobalAngle (viewangle + xtoviewangle[stop]);
377                 ds_p->scalestep = rw_scalestep =
378                         (ds_p->scale2 - rw_scale) / (stop-start);
379         }
380         else
381         {
382         //
383         // try to fix the stretched line bug
384         //
385 #if 0
386                 if (rw_distance < FRACUNIT/2)
387                 {
388                         fixed_t         trx,try;
389                         fixed_t         gxt,gyt;
390
391                         trx = curline->v1->x - viewx;
392                         try = curline->v1->y - viewy;
393
394                         gxt = FixedMul(trx,viewcos);
395                         gyt = -FixedMul(try,viewsin);
396                         ds_p->scale1 = FixedDiv(projection, gxt-gyt);
397                 }
398 #endif
399                 ds_p->scale2 = ds_p->scale1;
400         }
401
402
403 //
404 // calculate texture boundaries and decide if floor / ceiling marks
405 // are needed
406 //
407         worldtop = frontsector->ceilingheight - viewz;
408         worldbottom = frontsector->floorheight - viewz;
409
410         midtexture = toptexture = bottomtexture = maskedtexture = 0;
411         ds_p->maskedtexturecol = NULL;
412
413         if (!backsector)
414         {
415 //
416 // single sided line
417 //
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)
422                 {
423                         vtop = frontsector->floorheight +
424                          textureheight[sidedef->midtexture];
425                         rw_midtexturemid = vtop - viewz;        // bottom of texture at bottom
426                 }
427                 else
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;
435         }
436         else
437         {
438 //
439 // two sided line
440 //
441                 ds_p->sprtopclip = ds_p->sprbottomclip = NULL;
442                 ds_p->silhouette = 0;
443                 if (frontsector->floorheight > backsector->floorheight)
444                 {
445                         ds_p->silhouette = SIL_BOTTOM;
446                         ds_p->bsilheight = frontsector->floorheight;
447                 }
448                 else if (backsector->floorheight > viewz)
449                 {
450                         ds_p->silhouette = SIL_BOTTOM;
451                         ds_p->bsilheight = MAXINT;
452 //                      ds_p->sprbottomclip = negonearray;
453                 }
454                 if (frontsector->ceilingheight < backsector->ceilingheight)
455                 {
456                         ds_p->silhouette |= SIL_TOP;
457                         ds_p->tsilheight = frontsector->ceilingheight;
458                 }
459                 else if (backsector->ceilingheight < viewz)
460                 {
461                         ds_p->silhouette |= SIL_TOP;
462                         ds_p->tsilheight = MININT;
463 //                      ds_p->sprtopclip = screenheightarray;
464                 }
465
466                 if (backsector->ceilingheight <= frontsector->floorheight)
467                 {
468                         ds_p->sprbottomclip = negonearray;
469                         ds_p->bsilheight = MAXINT;
470                         ds_p->silhouette |= SIL_BOTTOM;
471                 }
472                 if (backsector->floorheight >= frontsector->ceilingheight)
473                 {
474                         ds_p->sprtopclip = screenheightarray;
475                         ds_p->tsilheight = MININT;
476                         ds_p->silhouette |= SIL_TOP;
477                 }
478                 worldhigh = backsector->ceilingheight - viewz;
479                 worldlow = backsector->floorheight - viewz;
480
481                 // hack to allow height changes in outdoor areas
482                 if (frontsector->ceilingpic == skyflatnum
483                 && backsector->ceilingpic == skyflatnum)
484                         worldtop = worldhigh;
485
486                 if (worldlow != worldbottom
487                 || backsector->floorpic != frontsector->floorpic
488                 || backsector->lightlevel != frontsector->lightlevel
489                 || backsector->special != frontsector->special)
490                         markfloor = true;
491                 else
492                         markfloor = false;                              // same plane on both sides
493
494                 if (worldhigh != worldtop
495                 || backsector->ceilingpic != frontsector->ceilingpic
496                 || backsector->lightlevel != frontsector->lightlevel)
497                         markceiling = true;
498                 else
499                         markceiling = false;                    // same plane on both sides
500
501                 if (backsector->ceilingheight <= frontsector->floorheight
502                 || backsector->floorheight >= frontsector->ceilingheight)
503                         markceiling = markfloor = true;         // closed door
504
505                 if (worldhigh < worldtop)
506                 {       // top texture
507                         toptexture = texturetranslation[sidedef->toptexture];
508                         if (linedef->flags & ML_DONTPEGTOP)
509                                 rw_toptexturemid = worldtop;            // top of texture at top
510                         else
511                         {
512                                 vtop = backsector->ceilingheight +
513                                         textureheight[sidedef->toptexture];
514                                 rw_toptexturemid = vtop - viewz;        // bottom of texture
515                         }
516                 }
517                 if (worldlow > worldbottom)
518                 {       // bottom texture
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
523                         }
524                         else    // top of texture at top
525                                 rw_bottomtexturemid = worldlow;
526                 }
527                 rw_toptexturemid += sidedef->rowoffset;
528                 rw_bottomtexturemid += sidedef->rowoffset;
529
530                 //
531                 // allocate space for masked texture tables
532                 //
533                 if (sidedef->midtexture)
534                 {       // masked midtexture
535                         maskedtexture = true;
536                         ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x;
537                         lastopening += rw_stopx - rw_x;
538                 }
539         }
540
541 //
542 // calculate rw_offset (only needed for textured lines)
543 //
544         segtextured = midtexture | toptexture | bottomtexture | maskedtexture;
545
546         if (segtextured)
547         {
548                 offsetangle = rw_normalangle-rw_angle1;
549                 if (offsetangle > ANG180)
550                         offsetangle = -offsetangle;
551                 if (offsetangle > ANG90)
552                         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;
559
560         //
561         // calculate light table
562         // use different light tables for horizontal / vertical / diagonal
563         // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
564                 if (!fixedcolormap)
565                 {
566                         lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight;
567                         //if (curline->v1->y == curline->v2->y)
568                         //      lightnum--;
569                         //else if (curline->v1->x == curline->v2->x)
570                         //      lightnum++;
571                         //if (lightnum < 0)
572                         //      walllights = scalelight[0];
573                         if (lightnum >= LIGHTLEVELS)
574                                 walllights = scalelight[LIGHTLEVELS-1];
575                         else
576                                 walllights = scalelight[lightnum];
577                 }
578         }
579
580
581 //
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
584 //
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
590
591 //
592 // calculate incremental stepping values for texture edges
593 //
594         worldtop >>= 4;
595         worldbottom >>= 4;
596
597         topstep = -FixedMul (rw_scalestep, worldtop);
598         topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale);
599
600         bottomstep = -FixedMul (rw_scalestep,worldbottom);
601         bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale);
602
603         if (backsector)
604         {
605                 worldhigh >>= 4;
606                 worldlow >>= 4;
607
608                 if (worldhigh < worldtop)
609                 {
610                         pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale);
611                         pixhighstep = -FixedMul (rw_scalestep,worldhigh);
612                 }
613                 if (worldlow > worldbottom)
614                 {
615                         pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale);
616                         pixlowstep = -FixedMul (rw_scalestep,worldlow);
617                 }
618         }
619
620 //
621 // render it
622 //
623         if (markceiling)
624                 ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1);
625         if (markfloor)
626                 floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1);
627
628         R_RenderSegLoop ();
629
630 //
631 // save sprite clipping info
632 //
633         if ( ((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip)
634         {
635                 memcpy (lastopening, ceilingclip+start, 2*(rw_stopx-start));
636                 ds_p->sprtopclip = lastopening - start;
637                 lastopening += rw_stopx - start;
638         }
639         if ( ((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && !ds_p->sprbottomclip)
640         {
641                 memcpy (lastopening, floorclip+start, 2*(rw_stopx-start));
642                 ds_p->sprbottomclip = lastopening - start;
643                 lastopening += rw_stopx - start;
644         }
645         if (maskedtexture && !(ds_p->silhouette&SIL_TOP))
646         {
647                 ds_p->silhouette |= SIL_TOP;
648                 ds_p->tsilheight = MININT;
649         }
650         if (maskedtexture && !(ds_p->silhouette&SIL_BOTTOM))
651         {
652                 ds_p->silhouette |= SIL_BOTTOM;
653                 ds_p->bsilheight = MAXINT;
654         }
655         ds_p++;
656 }
657
658 #endif
659