1 /* R_planes.c */
2
3 #include "doomdef.h"
4 #include "r_local.h"
5
6 planefunction_t floorfunc, ceilingfunc;
7
8 extern int weirdaspect;
9
10 /*
11 * sky mapping
12 */
13 int skyflatnum;
14 int skytexture;
15 int skytexturemid;
16 fixed_t skyiscale;
17
18 /*
19 * opening
20 */
21 visplane_t visplanes[MAXVISPLANES], *lastvisplane;
22 visplane_t *floorplane, *ceilingplane;
23
24 short *openings, *lastopening;
25
26 /*
27 * clip values are the solid pixel bounding the range
28 * floorclip starts out screenheight
29 * ceilingclip starts out -1
30 */
31 short *floorclip;
32 short *ceilingclip;
33
34 /*
35 * spanstart holds the start of a plane span
36 * initialized to 0 at start
37 */
38 int *spanstart;
39 int *spanstop;
40
41 /*
42 * texture mapping
43 */
44 lighttable_t **planezlight;
45 fixed_t planeheight;
46
47 fixed_t *yslope;
48 fixed_t *distscale;
49 fixed_t basexscale, baseyscale;
50
51 fixed_t *cachedheight;
52 fixed_t *cacheddistance;
53 fixed_t *cachedxstep;
54 fixed_t *cachedystep;
55
56
resinit_r_plane_c(void)57 void resinit_r_plane_c(void) { /* called before anything else */
58 int i;
59
60 for (i=0; i<MAXVISPLANES; i++) {
61 unsigned short *blah;
62
63 blah=(unsigned short *)calloc(screenwidth*2+4,sizeof(unsigned short));
64 visplanes[i].top=blah+1;
65 visplanes[i].bottom=blah+screenwidth+3;
66 }
67 openings=(short *)calloc(MAXOPENINGS,sizeof(short));
68 floorclip=(short *)calloc(screenwidth,sizeof(short));
69 ceilingclip=(short *)calloc(screenwidth,sizeof(short));
70 spanstart=(int *)calloc(screenheight,sizeof(int));
71 spanstop=(int *)calloc(screenheight,sizeof(int));
72
73 yslope=(fixed_t *)calloc(screenheight,sizeof(fixed_t));
74 distscale=(fixed_t *)calloc(screenwidth,sizeof(fixed_t));
75 cachedheight=(fixed_t *)calloc(screenheight,sizeof(fixed_t));
76 cacheddistance=(fixed_t *)calloc(screenheight,sizeof(fixed_t));
77 cachedxstep=(fixed_t *)calloc(screenheight,sizeof(fixed_t));
78 cachedystep=(fixed_t *)calloc(screenheight,sizeof(fixed_t));
79 }
80
81
82 /*
83 ================
84 =
85 = R_InitSkyMap
86 =
87 = Called whenever the view size changes
88 =
89 ================
90 */
91
R_InitSkyMap(void)92 void R_InitSkyMap (void)
93 {
94 skyflatnum = R_FlatNumForName ("F_SKY1");
95 skytexturemid = 400*FRACUNIT;
96
97 skyiscale = FRACUNIT/2;
98 }
99
100
101 /*
102 ====================
103 =
104 = R_InitPlanes
105 =
106 = Only at game startup
107 ====================
108 */
109
R_InitPlanes(void)110 void R_InitPlanes (void)
111 {
112 }
113
114
115 /*
116 ================
117 =
118 = R_MapPlane
119 =
120 global vars:
121
122 planeheight
123 ds_source
124 basexscale
125 baseyscale
126 viewx
127 viewy
128
129 BASIC PRIMITIVE
130 ================
131 */
132
R_MapPlane(int y,int x1,int x2)133 void R_MapPlane (int y, int x1, int x2)
134 {
135 angle_t angle;
136 fixed_t distance, length;
137 unsigned index;
138
139 #ifdef RANGECHECK
140 if (x2 < x1
141 || x1<0
142 || x2>=viewwidth
143 || (unsigned)y>viewheight)
144 I_Error ("R_MapPlane: %i, %i at %i",x1,x2,y);
145 #endif
146
147 if (planeheight != cachedheight[y])
148 {
149 cachedheight[y] = planeheight;
150 distance = cacheddistance[y] = FixedMul (planeheight, yslope[y]);
151
152 ds_xstep = cachedxstep[y] = FixedMul (distance,basexscale);
153 ds_ystep = cachedystep[y] = FixedMul (distance,baseyscale);
154 }
155 else
156 {
157 distance = cacheddistance[y];
158 ds_xstep = cachedxstep[y];
159 ds_ystep = cachedystep[y];
160 }
161
162 length = FixedMul (distance,distscale[x1]);
163 angle = (viewangle + xtoviewangle[x1])>>ANGLETOFINESHIFT;
164 ds_xfrac = viewx + FixedMul(finecosine[angle], length);
165 ds_yfrac = -viewy - FixedMul(finesine[angle], length);
166
167 if (fixedcolormap)
168 ds_colormap = fixedcolormap;
169 else
170 {
171 index = distance >> LIGHTZSHIFT;
172 if (index >= MAXLIGHTZ )
173 index = MAXLIGHTZ-1;
174 ds_colormap = planezlight[index];
175 }
176
177 ds_y = y;
178 ds_x1 = x1;
179 ds_x2 = x2;
180
181 spanfunc (); /* high or low detail */
182 }
183
184 /* ============================================================================= */
185
186 /*
187 ====================
188 =
189 = R_ClearPlanes
190 =
191 = At begining of frame
192 ====================
193 */
194
R_ClearPlanes(void)195 void R_ClearPlanes (void)
196 {
197 int i;
198 angle_t angle;
199
200 /*
201 * opening / clipping determination
202 */
203 for (i=0 ; i<viewwidth ; i++)
204 {
205 floorclip[i] = viewheight;
206 ceilingclip[i] = -1;
207 }
208
209 lastvisplane = visplanes;
210 lastopening = openings;
211
212 /*
213 * texture calculation
214 */
215 /* memset (cachedheight, 0, sizeof(cachedheight)); */
216 memset (cachedheight, 0, screenheight*sizeof(fixed_t));
217 angle = (viewangle-ANG90)>>ANGLETOFINESHIFT; /* left to right mapping */
218
219 /* scale will be unit scale at SCREENWIDTH/2 distance */
220 basexscale = FixedDiv (finecosine[angle],centerxfrac);
221 baseyscale = -FixedDiv (finesine[angle],centerxfrac);
222 }
223
224
225
226 /*
227 ===============
228 =
229 = R_FindPlane
230 =
231 ===============
232 */
233
R_FindPlane(fixed_t height,int picnum,int lightlevel,int special)234 visplane_t *R_FindPlane(fixed_t height, int picnum,
235 int lightlevel, int special)
236 {
237 visplane_t *check;
238
239 if(picnum == skyflatnum)
240 {
241 /* all skies map together */
242 height = 0;
243 lightlevel = 0;
244 }
245
246 for(check = visplanes; check < lastvisplane; check++)
247 {
248 if(height == check->height
249 && picnum == check->picnum
250 && lightlevel == check->lightlevel
251 && special == check->special)
252 break;
253 }
254
255 if(check < lastvisplane)
256 {
257 return(check);
258 }
259
260 if(lastvisplane-visplanes == MAXVISPLANES)
261 {
262 I_Error("R_FindPlane: no more visplanes");
263 }
264
265 lastvisplane++;
266 check->height = height;
267 check->picnum = picnum;
268 check->lightlevel = lightlevel;
269 check->special = special;
270 check->minx = screenwidth;
271 check->maxx = -1;
272 /* memset(check->top, 0xff, sizeof(check->top)); */
273 memset(check->top, 0xff, screenwidth*sizeof(unsigned short));
274
275 return(check);
276 }
277
278 /*
279 ===============
280 =
281 = R_CheckPlane
282 =
283 ===============
284 */
285
R_CheckPlane(visplane_t * pl,int start,int stop)286 visplane_t *R_CheckPlane (visplane_t *pl, int start, int stop)
287 {
288 int intrl, intrh;
289 int unionl, unionh;
290 int x;
291
292 if (start < pl->minx)
293 {
294 intrl = pl->minx;
295 unionl = start;
296 }
297 else
298 {
299 unionl = pl->minx;
300 intrl = start;
301 }
302
303 if (stop > pl->maxx)
304 {
305 intrh = pl->maxx;
306 unionh = stop;
307 }
308 else
309 {
310 unionh = pl->maxx;
311 intrh = stop;
312 }
313
314
315 for (x=intrl ; x<= intrh ; x++)
316 /* ANDRE !!! or if (pl->top[x] != 0xffff) ? */
317 if (pl->top[x] != 0xff)
318 break;
319
320 if (x > intrh)
321 {
322 pl->minx = unionl;
323 pl->maxx = unionh;
324 return pl; /* use the same one */
325 }
326
327 /* make a new visplane */
328
329 lastvisplane->height = pl->height;
330 lastvisplane->picnum = pl->picnum;
331 lastvisplane->lightlevel = pl->lightlevel;
332 lastvisplane->special = pl->special;
333 pl = lastvisplane++;
334 pl->minx = start;
335 pl->maxx = stop;
336 /* memset (pl->top, 0xff, sizeof(pl->top)); */
337 memset(pl->top, 0xff, screenwidth*sizeof(unsigned short));
338
339 return pl;
340 }
341
342
343
344 /* ============================================================================= */
345
346 /*
347 ================
348 =
349 = R_MakeSpans
350 =
351 ================
352 */
353
R_MakeSpans(int x,int t1,int b1,int t2,int b2)354 void R_MakeSpans (int x, int t1, int b1, int t2, int b2)
355 {
356 while (t1 < t2 && t1<=b1)
357 {
358 R_MapPlane (t1,spanstart[t1],x-1);
359 t1++;
360 }
361 while (b1 > b2 && b1>=t1)
362 {
363 R_MapPlane (b1,spanstart[b1],x-1);
364 b1--;
365 }
366
367 while (t2 < t1 && t2<=b2)
368 {
369 spanstart[t2] = x;
370 t2++;
371 }
372 while (b2 > b1 && b2>=t2)
373 {
374 spanstart[b2] = x;
375 b2--;
376 }
377 }
378
379
380
381 /*
382 ================
383 =
384 = R_DrawPlanes
385 =
386 = At the end of each frame
387 ================
388 */
389
R_DrawPlanes(void)390 void R_DrawPlanes (void)
391 {
392 visplane_t *pl;
393 int light;
394 int x, stop;
395 int angle;
396 byte *tempSource;
397
398 byte *dest;
399 int count;
400 fixed_t frac, fracstep;
401
402 extern byte *ylookup[MAXSCREENHEIGHT];
403 extern int columnofs[MAXSCREENWIDTH];
404
405 #ifdef RANGECHECK
406 if (ds_p - drawsegs > MAXDRAWSEGS)
407 I_Error ("R_DrawPlanes: drawsegs overflow (%i)", ds_p - drawsegs);
408 if (lastvisplane - visplanes > MAXVISPLANES)
409 I_Error ("R_DrawPlanes: visplane overflow (%i)", lastvisplane - visplanes);
410 if (lastopening - openings > MAXOPENINGS)
411 I_Error ("R_DrawPlanes: opening overflow (%i)", lastopening - openings);
412 #endif
413
414 for (pl = visplanes ; pl < lastvisplane ; pl++)
415 {
416 if (pl->minx > pl->maxx)
417 continue;
418 /*
419 * sky flat
420 */
421 if (pl->picnum == skyflatnum)
422 {/*
423 if ((screenwidth>320) || (screenheight>200)) {
424 dc_iscale = FixedDiv(FRACUNIT, pspriteyscale);
425 }
426 else*/
427 dc_iscale = skyiscale;
428
429 if (!weirdaspect)
430 dc_iscale = FixedMul(dc_iscale, (fixed_t)((200.0/240.0) * (double)FRACUNIT));
431
432 dc_colormap = colormaps; /* sky is allways drawn full bright */
433 dc_texturemid = skytexturemid;
434 for (x=pl->minx ; x <= pl->maxx ; x++)
435 {
436 dc_yl = pl->top[x];
437 dc_yh = pl->bottom[x];
438 if (dc_yl <= dc_yh)
439 {
440 angle = (viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT;
441 dc_x = x;
442 dc_source = R_GetColumn(skytexture, angle);
443
444 if ((screenwidth>320) || (screenheight>200)) {
445 /* Is this correct ? */
446 /* R_DrawSkyColumn(); */
447 colfunc();
448 }
449 else {
450 count = dc_yh - dc_yl;
451 if (count < 0)
452 return;
453
454 #ifdef RANGECHECK
455 if ((unsigned)dc_x >= screenwidth || dc_yl < 0 || dc_yh >= screenheight)
456 I_Error ("R_DrawSpecColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
457 #endif
458
459 dest = ylookup[dc_yl] + columnofs[dc_x];
460
461 fracstep = 1;
462 frac = (dc_texturemid>>FRACBITS) + (dc_yl-centery);
463 do {
464 *dest = dc_source[frac];
465 dest += screenwidth;
466 frac += fracstep;
467 } while (count--);
468 }
469 }
470 }
471 continue;
472 }
473
474 /*
475 * regular flat
476 */
477 tempSource = W_CacheLumpNum(firstflat +
478 flattranslation[pl->picnum], PU_STATIC);
479
480 switch(pl->special)
481 {
482 case 25: case 26: case 27: case 28: case 29: /* Scroll_North */
483 ds_source = tempSource;
484 break;
485 case 20: case 21: case 22: case 23: case 24: /* Scroll_East */
486 ds_source = tempSource+((63-((leveltime>>1)&63))<<
487 (pl->special-20)&63);
488 /* ds_source = tempSource+((leveltime>>1)&63); */
489 break;
490 case 30: case 31: case 32: case 33: case 34: /* Scroll_South */
491 ds_source = tempSource;
492 break;
493 case 35: case 36: case 37: case 38: case 39: /* Scroll_West */
494 ds_source = tempSource;
495 break;
496 case 4: /* Scroll_EastLavaDamage */
497 ds_source = tempSource+(((63-((leveltime>>1)&63))<<3)&63);
498 break;
499 default:
500 ds_source = tempSource;
501 }
502 planeheight = abs(pl->height-viewz);
503 light = (pl->lightlevel >> LIGHTSEGSHIFT)+extralight;
504 if (light >= LIGHTLEVELS)
505 light = LIGHTLEVELS-1;
506 if (light < 0)
507 light = 0;
508 planezlight = zlight[light];
509
510 pl->top[pl->maxx+1] = 0xffff;
511 pl->top[pl->minx-1] = 0xffff;
512
513 stop = pl->maxx + 1;
514 for (x=pl->minx ; x<= stop ; x++)
515 R_MakeSpans (x,pl->top[x-1],pl->bottom[x-1]
516 ,pl->top[x],pl->bottom[x]);
517
518 Z_ChangeTag (tempSource, PU_CACHE);
519 }
520 }
521