]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/doom/r_plane.c
games/doom: display correct message on medkit pickup when health low (thanks qu7uux)
[plan9front.git] / sys / src / games / doom / r_plane.c
1 // Emacs style mode select   -*- C++ -*- 
2 //-----------------------------------------------------------------------------
3 //
4 // $Id:$
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 //
8 // This source is available for distribution and/or modification
9 // only under the terms of the DOOM Source Code License as
10 // published by id Software. All rights reserved.
11 //
12 // The source is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
15 // for more details.
16 //
17 // $Log:$
18 //
19 // DESCRIPTION:
20 //      Here is a core component: drawing the floors and ceilings,
21 //       while maintaining a per column clipping list only.
22 //      Moreover, the sky areas have to be determined.
23 //
24 //-----------------------------------------------------------------------------
25
26
27 static const char
28 rcsid[] = "$Id: r_plane.c,v 1.4 1997/02/03 16:47:55 b1 Exp $";
29
30 #include "i_system.h"
31 #include "z_zone.h"
32 #include "w_wad.h"
33
34 #include "doomdef.h"
35 #include "doomstat.h"
36
37 #include "r_local.h"
38 #include "r_sky.h"
39
40
41
42 planefunction_t         floorfunc;
43 planefunction_t         ceilingfunc;
44
45 //
46 // opening
47 //
48
49 // Here comes the obnoxious "visplane".
50 #define MAXVISPLANES    128
51 visplane_t              visplanes[MAXVISPLANES];
52 visplane_t*             lastvisplane;
53 visplane_t*             floorplane;
54 visplane_t*             ceilingplane;
55
56 // ?
57 #define MAXOPENINGS     SCREENWIDTH*64
58 short                   openings[MAXOPENINGS];
59 short*                  lastopening;
60
61
62 //
63 // Clip values are the solid pixel bounding the range.
64 //  floorclip starts out SCREENHEIGHT
65 //  ceilingclip starts out -1
66 //
67 short                   floorclip[SCREENWIDTH];
68 short                   ceilingclip[SCREENWIDTH];
69
70 //
71 // spanstart holds the start of a plane span
72 // initialized to 0 at start
73 //
74 int                     spanstart[SCREENHEIGHT];
75 int                     spanstop[SCREENHEIGHT];
76
77 //
78 // texture mapping
79 //
80 lighttable_t**          planezlight;
81 fixed_t                 planeheight;
82
83 fixed_t                 yslope[SCREENHEIGHT];
84 fixed_t                 distscale[SCREENWIDTH];
85 fixed_t                 basexscale;
86 fixed_t                 baseyscale;
87
88 fixed_t                 cachedheight[SCREENHEIGHT];
89 fixed_t                 cacheddistance[SCREENHEIGHT];
90 fixed_t                 cachedxstep[SCREENHEIGHT];
91 fixed_t                 cachedystep[SCREENHEIGHT];
92
93
94
95 //
96 // R_InitPlanes
97 // Only at game startup.
98 //
99 void R_InitPlanes (void)
100 {
101   // Doh!
102 }
103
104
105 //
106 // R_MapPlane
107 //
108 // Uses global vars:
109 //  planeheight
110 //  ds_source
111 //  basexscale
112 //  baseyscale
113 //  viewx
114 //  viewy
115 //
116 // BASIC PRIMITIVE
117 //
118 void
119 R_MapPlane
120 ( int           y,
121   int           x1,
122   int           x2 )
123 {
124     angle_t     angle;
125     fixed_t     distance;
126     fixed_t     length;
127     unsigned    index;
128         
129 #ifdef RANGECHECK
130     if (x2 < x1
131         || x1<0
132         || x2>=viewwidth
133         || (unsigned)y>viewheight)
134     {
135         I_Error ("R_MapPlane: %i, %i at %i",x1,x2,y);
136     }
137 #endif
138
139     if (planeheight != cachedheight[y])
140     {
141         cachedheight[y] = planeheight;
142         distance = cacheddistance[y] = FixedMul (planeheight, yslope[y]);
143         ds_xstep = cachedxstep[y] = FixedMul (distance,basexscale);
144         ds_ystep = cachedystep[y] = FixedMul (distance,baseyscale);
145     }
146     else
147     {
148         distance = cacheddistance[y];
149         ds_xstep = cachedxstep[y];
150         ds_ystep = cachedystep[y];
151     }
152         
153     length = FixedMul (distance,distscale[x1]);
154     angle = (viewangle + xtoviewangle[x1])>>ANGLETOFINESHIFT;
155     ds_xfrac = viewx + FixedMul(finecosine[angle], length);
156     ds_yfrac = -viewy - FixedMul(finesine[angle], length);
157
158     if (fixedcolormap)
159         ds_colormap = fixedcolormap;
160     else
161     {
162         index = distance >> LIGHTZSHIFT;
163         
164         if (index >= MAXLIGHTZ )
165             index = MAXLIGHTZ-1;
166
167         ds_colormap = planezlight[index];
168     }
169         
170     ds_y = y;
171     ds_x1 = x1;
172     ds_x2 = x2;
173
174     // high or low detail
175     spanfunc ();        
176 }
177
178
179 //
180 // R_ClearPlanes
181 // At begining of frame.
182 //
183 void R_ClearPlanes (void)
184 {
185     int         i;
186     angle_t     angle;
187     
188     // opening / clipping determination
189     for (i=0 ; i<viewwidth ; i++)
190     {
191         floorclip[i] = viewheight;
192         ceilingclip[i] = -1;
193     }
194
195     lastvisplane = visplanes;
196     lastopening = openings;
197     
198     // texture calculation
199     memset (cachedheight, 0, sizeof(cachedheight));
200
201     // left to right mapping
202     angle = (viewangle-ANG90)>>ANGLETOFINESHIFT;
203         
204     // scale will be unit scale at SCREENWIDTH/2 distance
205     basexscale = FixedDiv (finecosine[angle],centerxfrac);
206     baseyscale = -FixedDiv (finesine[angle],centerxfrac);
207 }
208
209
210
211
212 //
213 // R_FindPlane
214 //
215 visplane_t*
216 R_FindPlane
217 ( fixed_t       height,
218   int           picnum,
219   int           lightlevel )
220 {
221     visplane_t* check;
222         
223     if (picnum == skyflatnum)
224     {
225         height = 0;                     // all skys map together
226         lightlevel = 0;
227     }
228         
229     for (check=visplanes; check<lastvisplane; check++)
230     {
231         if (height == check->height
232             && picnum == check->picnum
233             && lightlevel == check->lightlevel)
234         {
235             break;
236         }
237     }
238     
239                         
240     if (check < lastvisplane)
241         return check;
242                 
243     if (lastvisplane - visplanes == MAXVISPLANES)
244         I_Error ("R_FindPlane: no more visplanes");
245                 
246     lastvisplane++;
247
248     check->height = height;
249     check->picnum = picnum;
250     check->lightlevel = lightlevel;
251     check->minx = SCREENWIDTH;
252     check->maxx = -1;
253     
254     memset (check->top,0xff,sizeof(check->top));
255                 
256     return check;
257 }
258
259
260 //
261 // R_CheckPlane
262 //
263 visplane_t*
264 R_CheckPlane
265 ( visplane_t*   pl,
266   int           start,
267   int           stop )
268 {
269     int         intrl;
270     int         intrh;
271     int         unionl;
272     int         unionh;
273     int         x;
274         
275     if (start < pl->minx)
276     {
277         intrl = pl->minx;
278         unionl = start;
279     }
280     else
281     {
282         unionl = pl->minx;
283         intrl = start;
284     }
285         
286     if (stop > pl->maxx)
287     {
288         intrh = pl->maxx;
289         unionh = stop;
290     }
291     else
292     {
293         unionh = pl->maxx;
294         intrh = stop;
295     }
296
297     for (x=intrl ; x<= intrh ; x++)
298         if (pl->top[x] != 0xff)
299             break;
300
301     if (x > intrh)
302     {
303         pl->minx = unionl;
304         pl->maxx = unionh;
305
306         // use the same one
307         return pl;              
308     }
309         
310     // make a new visplane
311     lastvisplane->height = pl->height;
312     lastvisplane->picnum = pl->picnum;
313     lastvisplane->lightlevel = pl->lightlevel;
314     
315     pl = lastvisplane++;
316     pl->minx = start;
317     pl->maxx = stop;
318
319     memset (pl->top,0xff,sizeof(pl->top));
320                 
321     return pl;
322 }
323
324
325 //
326 // R_MakeSpans
327 //
328 void
329 R_MakeSpans
330 ( int           x,
331   int           t1,
332   int           b1,
333   int           t2,
334   int           b2 )
335 {
336     while (t1 < t2 && t1<=b1)
337     {
338         R_MapPlane (t1,spanstart[t1],x-1);
339         t1++;
340     }
341     while (b1 > b2 && b1>=t1)
342     {
343         R_MapPlane (b1,spanstart[b1],x-1);
344         b1--;
345     }
346         
347     while (t2 < t1 && t2<=b2)
348     {
349         spanstart[t2] = x;
350         t2++;
351     }
352     while (b2 > b1 && b2>=t2)
353     {
354         spanstart[b2] = x;
355         b2--;
356     }
357 }
358
359
360
361 //
362 // R_DrawPlanes
363 // At the end of each frame.
364 //
365 void R_DrawPlanes (void)
366 {
367     visplane_t*         pl;
368     int                 light;
369     int                 x;
370     int                 stop;
371     int                 angle;
372                                 
373 #ifdef RANGECHECK
374     if (ds_p - drawsegs > MAXDRAWSEGS)
375         I_Error ("R_DrawPlanes: drawsegs overflow (%i)",
376                  ds_p - drawsegs);
377     
378     if (lastvisplane - visplanes > MAXVISPLANES)
379         I_Error ("R_DrawPlanes: visplane overflow (%i)",
380                  lastvisplane - visplanes);
381     
382     if (lastopening - openings > MAXOPENINGS)
383         I_Error ("R_DrawPlanes: opening overflow (%i)",
384                  lastopening - openings);
385 #endif
386
387     for (pl = visplanes ; pl < lastvisplane ; pl++)
388     {
389         if (pl->minx > pl->maxx)
390             continue;
391
392         
393         // sky flat
394         if (pl->picnum == skyflatnum)
395         {
396             dc_iscale = pspriteiscale>>detailshift;
397             
398             // Sky is allways drawn full bright,
399             //  i.e. colormaps[0] is used.
400             // Because of this hack, sky is not affected
401             //  by INVUL inverse mapping.
402             dc_colormap = colormaps;
403             dc_texturemid = skytexturemid;
404             for (x=pl->minx ; x <= pl->maxx ; x++)
405             {
406                 dc_yl = pl->top[x];
407                 dc_yh = pl->bottom[x];
408
409                 if (dc_yl <= dc_yh)
410                 {
411                     angle = (viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT;
412                     dc_x = x;
413                     dc_source = R_GetColumn(skytexture, angle);
414                     colfunc ();
415                 }
416             }
417             continue;
418         }
419         
420         // regular flat
421         ds_source = W_CacheLumpNum(firstflat +
422                                    flattranslation[pl->picnum],
423                                    PU_STATIC);
424         
425         planeheight = abs(pl->height-viewz);
426         light = (pl->lightlevel >> LIGHTSEGSHIFT)+extralight;
427
428         if (light >= LIGHTLEVELS)
429             light = LIGHTLEVELS-1;
430
431         if (light < 0)
432             light = 0;
433
434         planezlight = zlight[light];
435
436         pl->top[pl->maxx+1] = 0xff;
437         pl->top[pl->minx-1] = 0xff;
438                 
439         stop = pl->maxx + 1;
440
441         for (x=pl->minx ; x<= stop ; x++)
442         {
443             R_MakeSpans(x,pl->top[x-1],
444                         pl->bottom[x-1],
445                         pl->top[x],
446                         pl->bottom[x]);
447         }
448         
449         Z_ChangeTag (ds_source, PU_CACHE);
450     }
451 }