Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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