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