aboutsummaryrefslogtreecommitdiff
path: root/src/r_segs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/r_segs.c')
-rw-r--r--src/r_segs.c854
1 files changed, 854 insertions, 0 deletions
diff --git a/src/r_segs.c b/src/r_segs.c
new file mode 100644
index 0000000..cb30b75
--- /dev/null
+++ b/src/r_segs.c
@@ -0,0 +1,854 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom: a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2004 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 * Copyright 2005, 2006 by
12 * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 * 02111-1307, USA.
28 *
29 * DESCRIPTION:
30 * All the clipping: columns, horizontal spans, sky columns.
31 *
32 *-----------------------------------------------------------------------------*/
33//
34// 4/25/98, 5/2/98 killough: reformatted, beautified
35
36#include "doomstat.h"
37#include "r_main.h"
38#include "r_bsp.h"
39#include "r_segs.h"
40#include "r_plane.h"
41#include "r_things.h"
42#include "r_draw.h"
43#include "w_wad.h"
44#include "v_video.h"
45#include "lprintf.h"
46
47// OPTIMIZE: closed two sided lines as single sided
48
49// killough 1/6/98: replaced globals with statics where appropriate
50
51// True if any of the segs textures might be visible.
52static boolean segtextured;
53static boolean markfloor; // False if the back side is the same plane.
54static boolean markceiling;
55static boolean maskedtexture;
56static int toptexture;
57static int bottomtexture;
58static int midtexture;
59
60static fixed_t toptexheight, midtexheight, bottomtexheight; // cph
61
62angle_t rw_normalangle; // angle to line origin
63int rw_angle1;
64fixed_t rw_distance;
65
66//
67// regular wall
68//
69static int rw_x;
70static int rw_stopx;
71static angle_t rw_centerangle;
72static fixed_t rw_offset;
73static fixed_t rw_scale;
74static fixed_t rw_scalestep;
75static fixed_t rw_midtexturemid;
76static fixed_t rw_toptexturemid;
77static fixed_t rw_bottomtexturemid;
78static int rw_lightlevel;
79static int worldtop;
80static int worldbottom;
81static int worldhigh;
82static int worldlow;
83static fixed_t pixhigh;
84static fixed_t pixlow;
85static fixed_t pixhighstep;
86static fixed_t pixlowstep;
87static fixed_t topfrac;
88static fixed_t topstep;
89static fixed_t bottomfrac;
90static fixed_t bottomstep;
91static int *maskedtexturecol; // dropoff overflow
92
93//
94// R_ScaleFromGlobalAngle
95// Returns the texture mapping scale
96// for the current line (horizontal span)
97// at the given angle.
98// rw_distance must be calculated first.
99//
100// killough 5/2/98: reformatted, cleaned up
101// CPhipps - moved here from r_main.c
102
103static fixed_t R_ScaleFromGlobalAngle(angle_t visangle)
104{
105 int anglea = ANG90 + (visangle-viewangle);
106 int angleb = ANG90 + (visangle-rw_normalangle);
107 int den = FixedMul(rw_distance, finesine[anglea>>ANGLETOFINESHIFT]);
108// proff 11/06/98: Changed for high-res
109 fixed_t num = FixedMul(projectiony, finesine[angleb>>ANGLETOFINESHIFT]);
110 return den > num>>16 ? (num = FixedDiv(num, den)) > 64*FRACUNIT ?
111 64*FRACUNIT : num < 256 ? 256 : num : 64*FRACUNIT;
112}
113
114//
115// R_RenderMaskedSegRange
116//
117
118void R_RenderMaskedSegRange(drawseg_t *ds, int x1, int x2)
119{
120 int texnum;
121 sector_t tempsec; // killough 4/13/98
122 const rpatch_t *patch;
123 R_DrawColumn_f colfunc;
124 draw_column_vars_t dcvars;
125 angle_t angle;
126
127 R_SetDefaultDrawColumnVars(&dcvars);
128
129 // Calculate light table.
130 // Use different light tables
131 // for horizontal / vertical / diagonal. Diagonal?
132
133 curline = ds->curline; // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
134
135 // killough 4/11/98: draw translucent 2s normal textures
136
137 colfunc = R_GetDrawColumnFunc(RDC_PIPELINE_STANDARD, drawvars.filterwall, drawvars.filterz);
138 if (curline->linedef->tranlump >= 0 && general_translucency)
139 {
140 colfunc = R_GetDrawColumnFunc(RDC_PIPELINE_TRANSLUCENT, drawvars.filterwall, drawvars.filterz);
141 tranmap = main_tranmap;
142 if (curline->linedef->tranlump > 0)
143 tranmap = W_CacheLumpNum(curline->linedef->tranlump-1);
144 }
145 // killough 4/11/98: end translucent 2s normal code
146
147 frontsector = curline->frontsector;
148 backsector = curline->backsector;
149
150 // cph 2001/11/25 - middle textures did not animate in v1.2
151 texnum = curline->sidedef->midtexture;
152 if (!comp[comp_maskedanim])
153 texnum = texturetranslation[texnum];
154
155 // killough 4/13/98: get correct lightlevel for 2s normal textures
156 rw_lightlevel = R_FakeFlat(frontsector, &tempsec, NULL, NULL, false) ->lightlevel;
157
158 maskedtexturecol = ds->maskedtexturecol;
159
160 rw_scalestep = ds->scalestep;
161 spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
162 mfloorclip = ds->sprbottomclip;
163 mceilingclip = ds->sprtopclip;
164
165 // find positioning
166 if (curline->linedef->flags & ML_DONTPEGBOTTOM)
167 {
168 dcvars.texturemid = frontsector->floorheight > backsector->floorheight
169 ? frontsector->floorheight : backsector->floorheight;
170 dcvars.texturemid = dcvars.texturemid + textureheight[texnum] - viewz;
171 }
172 else
173 {
174 dcvars.texturemid =frontsector->ceilingheight<backsector->ceilingheight
175 ? frontsector->ceilingheight : backsector->ceilingheight;
176 dcvars.texturemid = dcvars.texturemid - viewz;
177 }
178
179 dcvars.texturemid += curline->sidedef->rowoffset;
180
181 if (fixedcolormap) {
182 dcvars.colormap = fixedcolormap;
183 dcvars.nextcolormap = dcvars.colormap; // for filtering -- POPE
184 }
185
186 patch = R_CacheTextureCompositePatchNum(texnum);
187
188 // draw the columns
189 for (dcvars.x = x1 ; dcvars.x <= x2 ; dcvars.x++, spryscale += rw_scalestep)
190 if (maskedtexturecol[dcvars.x] != INT_MAX) // dropoff overflow
191 {
192 // calculate texture offset - POPE
193 angle = (ds->rw_centerangle + xtoviewangle[dcvars.x]) >> ANGLETOFINESHIFT;
194 dcvars.texu = ds->rw_offset - FixedMul(finetangent[angle], ds->rw_distance);
195 if (drawvars.filterwall == RDRAW_FILTER_LINEAR)
196 dcvars.texu -= (FRACUNIT>>1);
197
198 if (!fixedcolormap)
199 dcvars.z = spryscale; // for filtering -- POPE
200 dcvars.colormap = R_ColourMap(rw_lightlevel,spryscale);
201 dcvars.nextcolormap = R_ColourMap(rw_lightlevel+1,spryscale); // for filtering -- POPE
202
203 // killough 3/2/98:
204 //
205 // This calculation used to overflow and cause crashes in Doom:
206 //
207 // sprtopscreen = centeryfrac - FixedMul(dcvars.texturemid, spryscale);
208 //
209 // This code fixes it, by using double-precision intermediate
210 // arithmetic and by skipping the drawing of 2s normals whose
211 // mapping to screen coordinates is totally out of range:
212
213 {
214 int_64_t t = ((int_64_t) centeryfrac << FRACBITS) -
215 (int_64_t) dcvars.texturemid * spryscale;
216 if (t + (int_64_t) textureheight[texnum] * spryscale < 0 ||
217 t > (int_64_t) MAX_SCREENHEIGHT << FRACBITS*2)
218 continue; // skip if the texture is out of screen's range
219 sprtopscreen = (long)(t >> FRACBITS);
220 }
221
222 dcvars.iscale = 0xffffffffu / (unsigned) spryscale;
223
224 // killough 1/25/98: here's where Medusa came in, because
225 // it implicitly assumed that the column was all one patch.
226 // Originally, Doom did not construct complete columns for
227 // multipatched textures, so there were no header or trailer
228 // bytes in the column referred to below, which explains
229 // the Medusa effect. The fix is to construct true columns
230 // when forming multipatched textures (see r_data.c).
231
232 // draw the texture
233 R_DrawMaskedColumn(
234 patch,
235 colfunc,
236 &dcvars,
237 R_GetPatchColumnWrapped(patch, maskedtexturecol[dcvars.x]),
238 R_GetPatchColumnWrapped(patch, maskedtexturecol[dcvars.x]-1),
239 R_GetPatchColumnWrapped(patch, maskedtexturecol[dcvars.x]+1)
240 );
241
242 maskedtexturecol[dcvars.x] = INT_MAX; // dropoff overflow
243 }
244
245 // Except for main_tranmap, mark others purgable at this point
246 if (curline->linedef->tranlump > 0 && general_translucency)
247 W_UnlockLumpNum(curline->linedef->tranlump-1); // cph - unlock it
248
249 R_UnlockTextureCompositePatchNum(texnum);
250
251 curline = NULL; /* cph 2001/11/18 - must clear curline now we're done with it, so R_ColourMap doesn't try using it for other things */
252}
253
254//
255// R_RenderSegLoop
256// Draws zero, one, or two textures (and possibly a masked texture) for walls.
257// Can draw or mark the starting pixel of floor and ceiling textures.
258// CALLED: CORE LOOPING ROUTINE.
259//
260
261#define HEIGHTBITS 12
262#define HEIGHTUNIT (1<<HEIGHTBITS)
263static int didsolidcol; /* True if at least one column was marked solid */
264
265static void R_RenderSegLoop (void)
266{
267 const rpatch_t *tex_patch;
268 R_DrawColumn_f colfunc = R_GetDrawColumnFunc(RDC_PIPELINE_STANDARD, drawvars.filterwall, drawvars.filterz);
269 draw_column_vars_t dcvars;
270 fixed_t texturecolumn = 0; // shut up compiler warning
271
272 R_SetDefaultDrawColumnVars(&dcvars);
273
274 rendered_segs++;
275 for ( ; rw_x < rw_stopx ; rw_x++)
276 {
277
278 // mark floor / ceiling areas
279
280 int yh = bottomfrac>>HEIGHTBITS;
281 int yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;
282
283 // no space above wall?
284 int bottom,top = ceilingclip[rw_x]+1;
285
286 if (yl < top)
287 yl = top;
288
289 if (markceiling)
290 {
291 bottom = yl-1;
292
293 if (bottom >= floorclip[rw_x])
294 bottom = floorclip[rw_x]-1;
295
296 if (top <= bottom)
297 {
298 ceilingplane->top[rw_x] = top;
299 ceilingplane->bottom[rw_x] = bottom;
300 }
301 // SoM: this should be set here
302 ceilingclip[rw_x] = bottom;
303 }
304
305// yh = bottomfrac>>HEIGHTBITS;
306
307 bottom = floorclip[rw_x]-1;
308 if (yh > bottom)
309 yh = bottom;
310
311 if (markfloor)
312 {
313
314 top = yh < ceilingclip[rw_x] ? ceilingclip[rw_x] : yh;
315
316 if (++top <= bottom)
317 {
318 floorplane->top[rw_x] = top;
319 floorplane->bottom[rw_x] = bottom;
320 }
321 // SoM: This should be set here to prevent overdraw
322 floorclip[rw_x] = top;
323 }
324
325 // texturecolumn and lighting are independent of wall tiers
326 if (segtextured)
327 {
328 // calculate texture offset
329 angle_t angle =(rw_centerangle+xtoviewangle[rw_x])>>ANGLETOFINESHIFT;
330
331 texturecolumn = rw_offset-FixedMul(finetangent[angle],rw_distance);
332 if (drawvars.filterwall == RDRAW_FILTER_LINEAR)
333 texturecolumn -= (FRACUNIT>>1);
334 dcvars.texu = texturecolumn; // for filtering -- POPE
335 texturecolumn >>= FRACBITS;
336
337 dcvars.colormap = R_ColourMap(rw_lightlevel,rw_scale);
338 dcvars.nextcolormap = R_ColourMap(rw_lightlevel+1,rw_scale); // for filtering -- POPE
339 dcvars.z = rw_scale; // for filtering -- POPE
340
341 dcvars.x = rw_x;
342 dcvars.iscale = 0xffffffffu / (unsigned)rw_scale;
343 }
344
345 // draw the wall tiers
346 if (midtexture)
347 {
348
349 dcvars.yl = yl; // single sided line
350 dcvars.yh = yh;
351 dcvars.texturemid = rw_midtexturemid;
352 tex_patch = R_CacheTextureCompositePatchNum(midtexture);
353 dcvars.source = R_GetTextureColumn(tex_patch, texturecolumn);
354 dcvars.prevsource = R_GetTextureColumn(tex_patch, texturecolumn-1);
355 dcvars.nextsource = R_GetTextureColumn(tex_patch, texturecolumn+1);
356 dcvars.texheight = midtexheight;
357 colfunc (&dcvars);
358 R_UnlockTextureCompositePatchNum(midtexture);
359 tex_patch = NULL;
360 ceilingclip[rw_x] = viewheight;
361 floorclip[rw_x] = -1;
362 }
363 else
364 {
365
366 // two sided line
367 if (toptexture)
368 {
369 // top wall
370 int mid = pixhigh>>HEIGHTBITS;
371 pixhigh += pixhighstep;
372
373 if (mid >= floorclip[rw_x])
374 mid = floorclip[rw_x]-1;
375
376 if (mid >= yl)
377 {
378 dcvars.yl = yl;
379 dcvars.yh = mid;
380 dcvars.texturemid = rw_toptexturemid;
381 tex_patch = R_CacheTextureCompositePatchNum(toptexture);
382 dcvars.source = R_GetTextureColumn(tex_patch,texturecolumn);
383 dcvars.prevsource = R_GetTextureColumn(tex_patch,texturecolumn-1);
384 dcvars.nextsource = R_GetTextureColumn(tex_patch,texturecolumn+1);
385 dcvars.texheight = toptexheight;
386 colfunc (&dcvars);
387 R_UnlockTextureCompositePatchNum(toptexture);
388 tex_patch = NULL;
389 ceilingclip[rw_x] = mid;
390 }
391 else
392 ceilingclip[rw_x] = yl-1;
393 }
394 else // no top wall
395 {
396
397 if (markceiling)
398 ceilingclip[rw_x] = yl-1;
399 }
400
401 if (bottomtexture) // bottom wall
402 {
403 int mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS;
404 pixlow += pixlowstep;
405
406 // no space above wall?
407 if (mid <= ceilingclip[rw_x])
408 mid = ceilingclip[rw_x]+1;
409
410 if (mid <= yh)
411 {
412 dcvars.yl = mid;
413 dcvars.yh = yh;
414 dcvars.texturemid = rw_bottomtexturemid;
415 tex_patch = R_CacheTextureCompositePatchNum(bottomtexture);
416 dcvars.source = R_GetTextureColumn(tex_patch, texturecolumn);
417 dcvars.prevsource = R_GetTextureColumn(tex_patch, texturecolumn-1);
418 dcvars.nextsource = R_GetTextureColumn(tex_patch, texturecolumn+1);
419 dcvars.texheight = bottomtexheight;
420 colfunc (&dcvars);
421 R_UnlockTextureCompositePatchNum(bottomtexture);
422 tex_patch = NULL;
423 floorclip[rw_x] = mid;
424 }
425 else
426 floorclip[rw_x] = yh+1;
427 }
428 else // no bottom wall
429 {
430 if (markfloor)
431 floorclip[rw_x] = yh+1;
432 }
433
434 // cph - if we completely blocked further sight through this column,
435 // add this info to the solid columns array for r_bsp.c
436 if ((markceiling || markfloor) &&
437 (floorclip[rw_x] <= ceilingclip[rw_x] + 1)) {
438 solidcol[rw_x] = 1; didsolidcol = 1;
439 }
440
441 // save texturecol for backdrawing of masked mid texture
442 if (maskedtexture)
443 maskedtexturecol[rw_x] = texturecolumn;
444 }
445
446 rw_scale += rw_scalestep;
447 topfrac += topstep;
448 bottomfrac += bottomstep;
449 }
450}
451
452// killough 5/2/98: move from r_main.c, made static, simplified
453
454static fixed_t R_PointToDist(fixed_t x, fixed_t y)
455{
456 fixed_t dx = D_abs(x - viewx);
457 fixed_t dy = D_abs(y - viewy);
458
459 if (dy > dx)
460 {
461 fixed_t t = dx;
462 dx = dy;
463 dy = t;
464 }
465
466 return FixedDiv(dx, finesine[(tantoangle[FixedDiv(dy,dx) >> DBITS]
467 + ANG90) >> ANGLETOFINESHIFT]);
468}
469
470//
471// R_StoreWallRange
472// A wall segment will be drawn
473// between start and stop pixels (inclusive).
474//
475void R_StoreWallRange(const int start, const int stop)
476{
477 fixed_t hyp;
478 angle_t offsetangle;
479
480 if (ds_p == drawsegs+maxdrawsegs) // killough 1/98 -- fix 2s line HOM
481 {
482 unsigned pos = ds_p - drawsegs; // jff 8/9/98 fix from ZDOOM1.14a
483 unsigned newmax = maxdrawsegs ? maxdrawsegs*2 : 128; // killough
484 drawsegs = realloc(drawsegs,newmax*sizeof(*drawsegs));
485 ds_p = drawsegs + pos; // jff 8/9/98 fix from ZDOOM1.14a
486 maxdrawsegs = newmax;
487 }
488
489 if(curline->miniseg == false) // figgi -- skip minisegs
490 curline->linedef->flags |= ML_MAPPED;
491
492#ifdef GL_DOOM
493 if (V_GetMode() == VID_MODEGL)
494 {
495 // proff 11/99: the rest of the calculations is not needed for OpenGL
496 ds_p++->curline = curline;
497 gld_AddWall(curline);
498
499 return;
500 }
501#endif
502
503
504#ifdef RANGECHECK
505 if (start >=viewwidth || start > stop)
506 I_Error ("Bad R_RenderWallRange: %i to %i", start , stop);
507#endif
508
509 sidedef = curline->sidedef;
510 linedef = curline->linedef;
511
512 // mark the segment as visible for auto map
513 linedef->flags |= ML_MAPPED;
514
515 // calculate rw_distance for scale calculation
516 rw_normalangle = curline->angle + ANG90;
517
518 offsetangle = rw_normalangle-rw_angle1;
519
520 if (D_abs(offsetangle) > ANG90)
521 offsetangle = ANG90;
522
523 hyp = (viewx==curline->v1->x && viewy==curline->v1->y)?
524 0 : R_PointToDist (curline->v1->x, curline->v1->y);
525 rw_distance = FixedMul(hyp, finecosine[offsetangle>>ANGLETOFINESHIFT]);
526
527 ds_p->x1 = rw_x = start;
528 ds_p->x2 = stop;
529 ds_p->curline = curline;
530 rw_stopx = stop+1;
531
532 { // killough 1/6/98, 2/1/98: remove limit on openings
533 extern int *openings; // dropoff overflow
534 extern size_t maxopenings;
535 size_t pos = lastopening - openings;
536 size_t need = (rw_stopx - start)*4 + pos;
537 if (need > maxopenings)
538 {
539 drawseg_t *ds; //jff 8/9/98 needed for fix from ZDoom
540 int *oldopenings = openings; // dropoff overflow
541 int *oldlast = lastopening; // dropoff overflow
542
543 do
544 maxopenings = maxopenings ? maxopenings*2 : 16384;
545 while (need > maxopenings);
546 openings = realloc(openings, maxopenings * sizeof(*openings));
547 lastopening = openings + pos;
548
549 // jff 8/9/98 borrowed fix for openings from ZDOOM1.14
550 // [RH] We also need to adjust the openings pointers that
551 // were already stored in drawsegs.
552 for (ds = drawsegs; ds < ds_p; ds++)
553 {
554#define ADJUST(p) if (ds->p + ds->x1 >= oldopenings && ds->p + ds->x1 <= oldlast)\
555 ds->p = ds->p - oldopenings + openings;
556 ADJUST (maskedtexturecol);
557 ADJUST (sprtopclip);
558 ADJUST (sprbottomclip);
559 }
560#undef ADJUST
561 }
562 } // killough: end of code to remove limits on openings
563
564 // calculate scale at both ends and step
565
566 ds_p->scale1 = rw_scale =
567 R_ScaleFromGlobalAngle (viewangle + xtoviewangle[start]);
568
569 if (stop > start)
570 {
571 ds_p->scale2 = R_ScaleFromGlobalAngle (viewangle + xtoviewangle[stop]);
572 ds_p->scalestep = rw_scalestep = (ds_p->scale2-rw_scale) / (stop-start);
573 }
574 else
575 ds_p->scale2 = ds_p->scale1;
576
577 // calculate texture boundaries
578 // and decide if floor / ceiling marks are needed
579
580 worldtop = frontsector->ceilingheight - viewz;
581 worldbottom = frontsector->floorheight - viewz;
582
583 midtexture = toptexture = bottomtexture = maskedtexture = 0;
584 ds_p->maskedtexturecol = NULL;
585
586 if (!backsector)
587 {
588 // single sided line
589 midtexture = texturetranslation[sidedef->midtexture];
590 midtexheight = (linedef->r_flags & RF_MID_TILE) ? 0 : textureheight[midtexture] >> FRACBITS;
591
592 // a single sided line is terminal, so it must mark ends
593 markfloor = markceiling = true;
594
595 if (linedef->flags & ML_DONTPEGBOTTOM)
596 { // bottom of texture at bottom
597 fixed_t vtop = frontsector->floorheight +
598 textureheight[sidedef->midtexture];
599 rw_midtexturemid = vtop - viewz;
600 }
601 else // top of texture at top
602 rw_midtexturemid = worldtop;
603
604 rw_midtexturemid += FixedMod(sidedef->rowoffset, textureheight[midtexture]);
605
606 ds_p->silhouette = SIL_BOTH;
607 ds_p->sprtopclip = screenheightarray;
608 ds_p->sprbottomclip = negonearray;
609 ds_p->bsilheight = INT_MAX;
610 ds_p->tsilheight = INT_MIN;
611 }
612 else // two sided line
613 {
614 ds_p->sprtopclip = ds_p->sprbottomclip = NULL;
615 ds_p->silhouette = 0;
616
617 if (linedef->r_flags & RF_CLOSED) { /* cph - closed 2S line e.g. door */
618 // cph - killough's (outdated) comment follows - this deals with both
619 // "automap fixes", his and mine
620 // killough 1/17/98: this test is required if the fix
621 // for the automap bug (r_bsp.c) is used, or else some
622 // sprites will be displayed behind closed doors. That
623 // fix prevents lines behind closed doors with dropoffs
624 // from being displayed on the automap.
625
626 ds_p->silhouette = SIL_BOTH;
627 ds_p->sprbottomclip = negonearray;
628 ds_p->bsilheight = INT_MAX;
629 ds_p->sprtopclip = screenheightarray;
630 ds_p->tsilheight = INT_MIN;
631
632 } else { /* not solid - old code */
633
634 if (frontsector->floorheight > backsector->floorheight)
635 {
636 ds_p->silhouette = SIL_BOTTOM;
637 ds_p->bsilheight = frontsector->floorheight;
638 }
639 else
640 if (backsector->floorheight > viewz)
641 {
642 ds_p->silhouette = SIL_BOTTOM;
643 ds_p->bsilheight = INT_MAX;
644 }
645
646 if (frontsector->ceilingheight < backsector->ceilingheight)
647 {
648 ds_p->silhouette |= SIL_TOP;
649 ds_p->tsilheight = frontsector->ceilingheight;
650 }
651 else
652 if (backsector->ceilingheight < viewz)
653 {
654 ds_p->silhouette |= SIL_TOP;
655 ds_p->tsilheight = INT_MIN;
656 }
657 }
658
659 worldhigh = backsector->ceilingheight - viewz;
660 worldlow = backsector->floorheight - viewz;
661
662 // hack to allow height changes in outdoor areas
663 if (frontsector->ceilingpic == skyflatnum
664 && backsector->ceilingpic == skyflatnum)
665 worldtop = worldhigh;
666
667 markfloor = worldlow != worldbottom
668 || backsector->floorpic != frontsector->floorpic
669 || backsector->lightlevel != frontsector->lightlevel
670
671 // killough 3/7/98: Add checks for (x,y) offsets
672 || backsector->floor_xoffs != frontsector->floor_xoffs
673 || backsector->floor_yoffs != frontsector->floor_yoffs
674
675 // killough 4/15/98: prevent 2s normals
676 // from bleeding through deep water
677 || frontsector->heightsec != -1
678
679 // killough 4/17/98: draw floors if different light levels
680 || backsector->floorlightsec != frontsector->floorlightsec
681 ;
682
683 markceiling = worldhigh != worldtop
684 || backsector->ceilingpic != frontsector->ceilingpic
685 || backsector->lightlevel != frontsector->lightlevel
686
687 // killough 3/7/98: Add checks for (x,y) offsets
688 || backsector->ceiling_xoffs != frontsector->ceiling_xoffs
689 || backsector->ceiling_yoffs != frontsector->ceiling_yoffs
690
691 // killough 4/15/98: prevent 2s normals
692 // from bleeding through fake ceilings
693 || (frontsector->heightsec != -1 &&
694 frontsector->ceilingpic!=skyflatnum)
695
696 // killough 4/17/98: draw ceilings if different light levels
697 || backsector->ceilinglightsec != frontsector->ceilinglightsec
698 ;
699
700 if (backsector->ceilingheight <= frontsector->floorheight
701 || backsector->floorheight >= frontsector->ceilingheight)
702 markceiling = markfloor = true; // closed door
703
704 if (worldhigh < worldtop) // top texture
705 {
706 toptexture = texturetranslation[sidedef->toptexture];
707 toptexheight = (linedef->r_flags & RF_TOP_TILE) ? 0 : textureheight[toptexture] >> FRACBITS;
708 rw_toptexturemid = linedef->flags & ML_DONTPEGTOP ? worldtop :
709 backsector->ceilingheight+textureheight[sidedef->toptexture]-viewz;
710 rw_toptexturemid += FixedMod(sidedef->rowoffset, textureheight[toptexture]);
711 }
712
713 if (worldlow > worldbottom) // bottom texture
714 {
715 bottomtexture = texturetranslation[sidedef->bottomtexture];
716 bottomtexheight = (linedef->r_flags & RF_BOT_TILE) ? 0 : textureheight[bottomtexture] >> FRACBITS;
717 rw_bottomtexturemid = linedef->flags & ML_DONTPEGBOTTOM ? worldtop :
718 worldlow;
719 rw_bottomtexturemid += FixedMod(sidedef->rowoffset, textureheight[bottomtexture]);
720 }
721
722 // allocate space for masked texture tables
723 if (sidedef->midtexture) // masked midtexture
724 {
725 maskedtexture = true;
726 ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x;
727 lastopening += rw_stopx - rw_x;
728 }
729 }
730
731 // calculate rw_offset (only needed for textured lines)
732 segtextured = midtexture | toptexture | bottomtexture | maskedtexture;
733
734 if (segtextured)
735 {
736 rw_offset = FixedMul (hyp, -finesine[offsetangle >>ANGLETOFINESHIFT]);
737
738 rw_offset += sidedef->textureoffset + curline->offset;
739
740 rw_centerangle = ANG90 + viewangle - rw_normalangle;
741
742 rw_lightlevel = frontsector->lightlevel;
743 }
744
745 // Remember the vars used to determine fractional U texture
746 // coords for later - POPE
747 ds_p->rw_offset = rw_offset;
748 ds_p->rw_distance = rw_distance;
749 ds_p->rw_centerangle = rw_centerangle;
750
751 // if a floor / ceiling plane is on the wrong side of the view
752 // plane, it is definitely invisible and doesn't need to be marked.
753
754 // killough 3/7/98: add deep water check
755 if (frontsector->heightsec == -1)
756 {
757 if (frontsector->floorheight >= viewz) // above view plane
758 markfloor = false;
759 if (frontsector->ceilingheight <= viewz &&
760 frontsector->ceilingpic != skyflatnum) // below view plane
761 markceiling = false;
762 }
763
764 // calculate incremental stepping values for texture edges
765 worldtop >>= 4;
766 worldbottom >>= 4;
767
768 topstep = -FixedMul (rw_scalestep, worldtop);
769 topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale);
770
771 bottomstep = -FixedMul (rw_scalestep,worldbottom);
772 bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale);
773
774 if (backsector)
775 {
776 worldhigh >>= 4;
777 worldlow >>= 4;
778
779 if (worldhigh < worldtop)
780 {
781 pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale);
782 pixhighstep = -FixedMul (rw_scalestep,worldhigh);
783 }
784 if (worldlow > worldbottom)
785 {
786 pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale);
787 pixlowstep = -FixedMul (rw_scalestep,worldlow);
788 }
789 }
790
791 // render it
792 if (markceiling) {
793 if (ceilingplane) // killough 4/11/98: add NULL ptr checks
794 ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1);
795 else
796 markceiling = 0;
797 }
798
799 if (markfloor) {
800 if (floorplane) // killough 4/11/98: add NULL ptr checks
801 /* cph 2003/04/18 - ceilingplane and floorplane might be the same
802 * visplane (e.g. if both skies); R_CheckPlane doesn't know about
803 * modifications to the plane that might happen in parallel with the check
804 * being made, so we have to override it and split them anyway if that is
805 * a possibility, otherwise the floor marking would overwrite the ceiling
806 * marking, resulting in HOM. */
807 if (markceiling && ceilingplane == floorplane)
808 floorplane = R_DupPlane (floorplane, rw_x, rw_stopx-1);
809 else
810 floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1);
811 else
812 markfloor = 0;
813 }
814
815 didsolidcol = 0;
816 R_RenderSegLoop();
817
818 /* cph - if a column was made solid by this wall, we _must_ save full clipping info */
819 if (backsector && didsolidcol) {
820 if (!(ds_p->silhouette & SIL_BOTTOM)) {
821 ds_p->silhouette |= SIL_BOTTOM;
822 ds_p->bsilheight = backsector->floorheight;
823 }
824 if (!(ds_p->silhouette & SIL_TOP)) {
825 ds_p->silhouette |= SIL_TOP;
826 ds_p->tsilheight = backsector->ceilingheight;
827 }
828 }
829
830 // save sprite clipping info
831 if ((ds_p->silhouette & SIL_TOP || maskedtexture) && !ds_p->sprtopclip)
832 {
833 memcpy (lastopening, ceilingclip+start, sizeof(int)*(rw_stopx-start)); // dropoff overflow
834 ds_p->sprtopclip = lastopening - start;
835 lastopening += rw_stopx - start;
836 }
837 if ((ds_p->silhouette & SIL_BOTTOM || maskedtexture) && !ds_p->sprbottomclip)
838 {
839 memcpy (lastopening, floorclip+start, sizeof(int)*(rw_stopx-start)); // dropoff overflow
840 ds_p->sprbottomclip = lastopening - start;
841 lastopening += rw_stopx - start;
842 }
843 if (maskedtexture && !(ds_p->silhouette & SIL_TOP))
844 {
845 ds_p->silhouette |= SIL_TOP;
846 ds_p->tsilheight = INT_MIN;
847 }
848 if (maskedtexture && !(ds_p->silhouette & SIL_BOTTOM))
849 {
850 ds_p->silhouette |= SIL_BOTTOM;
851 ds_p->bsilheight = INT_MAX;
852 }
853 ds_p++;
854}