diff options
Diffstat (limited to 'src/r_segs.c')
-rw-r--r-- | src/r_segs.c | 854 |
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. | ||
52 | static boolean segtextured; | ||
53 | static boolean markfloor; // False if the back side is the same plane. | ||
54 | static boolean markceiling; | ||
55 | static boolean maskedtexture; | ||
56 | static int toptexture; | ||
57 | static int bottomtexture; | ||
58 | static int midtexture; | ||
59 | |||
60 | static fixed_t toptexheight, midtexheight, bottomtexheight; // cph | ||
61 | |||
62 | angle_t rw_normalangle; // angle to line origin | ||
63 | int rw_angle1; | ||
64 | fixed_t rw_distance; | ||
65 | |||
66 | // | ||
67 | // regular wall | ||
68 | // | ||
69 | static int rw_x; | ||
70 | static int rw_stopx; | ||
71 | static angle_t rw_centerangle; | ||
72 | static fixed_t rw_offset; | ||
73 | static fixed_t rw_scale; | ||
74 | static fixed_t rw_scalestep; | ||
75 | static fixed_t rw_midtexturemid; | ||
76 | static fixed_t rw_toptexturemid; | ||
77 | static fixed_t rw_bottomtexturemid; | ||
78 | static int rw_lightlevel; | ||
79 | static int worldtop; | ||
80 | static int worldbottom; | ||
81 | static int worldhigh; | ||
82 | static int worldlow; | ||
83 | static fixed_t pixhigh; | ||
84 | static fixed_t pixlow; | ||
85 | static fixed_t pixhighstep; | ||
86 | static fixed_t pixlowstep; | ||
87 | static fixed_t topfrac; | ||
88 | static fixed_t topstep; | ||
89 | static fixed_t bottomfrac; | ||
90 | static fixed_t bottomstep; | ||
91 | static 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 | |||
103 | static 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 | |||
118 | void 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) | ||
263 | static int didsolidcol; /* True if at least one column was marked solid */ | ||
264 | |||
265 | static 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 | |||
454 | static 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 | // | ||
475 | void 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 | } | ||