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