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