• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 */
20 // r_surf.c: surface-related refresh code
21 
22 #include "quakedef.h"
23 #include "r_local.h"
24 
25 drawsurf_t	r_drawsurf;
26 
27 int				lightleft, sourcesstep, blocksize, sourcetstep;
28 int				lightdelta, lightdeltastep;
29 int				lightright, lightleftstep, lightrightstep, blockdivshift;
30 unsigned		blockdivmask;
31 void			*prowdestbase;
32 unsigned char	*pbasesource;
33 int				surfrowbytes;	// used by ASM files
34 unsigned		*r_lightptr;
35 int				r_stepback;
36 int				r_lightwidth;
37 int				r_numhblocks, r_numvblocks;
38 unsigned char	*r_source, *r_sourcemax;
39 
40 void R_DrawSurfaceBlock8_mip0 (void);
41 void R_DrawSurfaceBlock8_mip1 (void);
42 void R_DrawSurfaceBlock8_mip2 (void);
43 void R_DrawSurfaceBlock8_mip3 (void);
44 
45 static void	(*surfmiptable[4])(void) = {
46 	R_DrawSurfaceBlock8_mip0,
47 	R_DrawSurfaceBlock8_mip1,
48 	R_DrawSurfaceBlock8_mip2,
49 	R_DrawSurfaceBlock8_mip3
50 };
51 
52 
53 
54 unsigned		blocklights[18*18];
55 
56 /*
57 ===============
58 R_AddDynamicLights
59 ===============
60 */
R_AddDynamicLights(void)61 void R_AddDynamicLights (void)
62 {
63 	msurface_t *surf;
64 	int			lnum;
65 	int			sd, td;
66 	float		dist, rad, minlight;
67 	vec3_t		impact, local;
68 	int			s, t;
69 	int			i;
70 	int			smax, tmax;
71 	mtexinfo_t	*tex;
72 
73 	surf = r_drawsurf.surf;
74 	smax = (surf->extents[0]>>4)+1;
75 	tmax = (surf->extents[1]>>4)+1;
76 	tex = surf->texinfo;
77 
78 	for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
79 	{
80 		if ( !(surf->dlightbits & (1<<lnum) ) )
81 			continue;		// not lit by this light
82 
83 		rad = cl_dlights[lnum].radius;
84 		dist = DotProduct (cl_dlights[lnum].origin, surf->plane->normal) -
85 				surf->plane->dist;
86 		rad -= fabs(dist);
87 		minlight = cl_dlights[lnum].minlight;
88 		if (rad < minlight)
89 			continue;
90 		minlight = rad - minlight;
91 
92 		for (i=0 ; i<3 ; i++)
93 		{
94 			impact[i] = cl_dlights[lnum].origin[i] -
95 					surf->plane->normal[i]*dist;
96 		}
97 
98 		local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
99 		local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
100 
101 		local[0] -= surf->texturemins[0];
102 		local[1] -= surf->texturemins[1];
103 
104 		for (t = 0 ; t<tmax ; t++)
105 		{
106 			td = local[1] - t*16;
107 			if (td < 0)
108 				td = -td;
109 			for (s=0 ; s<smax ; s++)
110 			{
111 				sd = local[0] - s*16;
112 				if (sd < 0)
113 					sd = -sd;
114 				if (sd > td)
115 					dist = sd + (td>>1);
116 				else
117 					dist = td + (sd>>1);
118 				if (dist < minlight)
119 					blocklights[t*smax + s] += (rad - dist)*256;
120 			}
121 		}
122 	}
123 }
124 
125 /*
126 ===============
127 R_BuildLightMap
128 
129 Combine and scale multiple lightmaps into the 8.8 format in blocklights
130 ===============
131 */
R_BuildLightMap(void)132 void R_BuildLightMap (void)
133 {
134 	int			smax, tmax;
135 	int			t;
136 	int			i, size;
137 	byte		*lightmap;
138 	unsigned	scale;
139 	int			maps;
140 	msurface_t	*surf;
141 
142 	surf = r_drawsurf.surf;
143 
144 	smax = (surf->extents[0]>>4)+1;
145 	tmax = (surf->extents[1]>>4)+1;
146 	size = smax*tmax;
147 	lightmap = surf->samples;
148 
149 	if (/* r_fullbright.value || */ !cl.worldmodel->lightdata)
150 	{
151 		for (i=0 ; i<size ; i++)
152 			blocklights[i] = 0;
153 		return;
154 	}
155 
156 // clear to ambient
157 	for (i=0 ; i<size ; i++)
158 		blocklights[i] = r_refdef.ambientlight<<8;
159 
160 
161 // add all the lightmaps
162 	if (lightmap)
163 		for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
164 			 maps++)
165 		{
166 			scale = r_drawsurf.lightadj[maps];	// 8.8 fraction
167 			for (i=0 ; i<size ; i++)
168 				blocklights[i] += lightmap[i] * scale;
169 			lightmap += size;	// skip to next lightmap
170 		}
171 
172 // add all the dynamic lights
173 	if (surf->dlightframe == r_framecount)
174 		R_AddDynamicLights ();
175 
176 // bound, invert, and shift
177 	for (i=0 ; i<size ; i++)
178 	{
179 		t = (255*256 - (int)blocklights[i]) >> (8 - VID_CBITS);
180 
181 		if (t < (1 << 6))
182 			t = (1 << 6);
183 
184 		blocklights[i] = t;
185 	}
186 }
187 
188 
189 /*
190 ===============
191 R_TextureAnimation
192 
193 Returns the proper texture for a given time and base texture
194 ===============
195 */
R_TextureAnimation(texture_t * base)196 texture_t *R_TextureAnimation (texture_t *base)
197 {
198 	int		reletive;
199 	int		count;
200 
201 	if (currententity->frame)
202 	{
203 		if (base->alternate_anims)
204 			base = base->alternate_anims;
205 	}
206 
207 	if (!base->anim_total)
208 		return base;
209 
210 	reletive = (int)(cl.time*10) % base->anim_total;
211 
212 	count = 0;
213 	while (base->anim_min > reletive || base->anim_max <= reletive)
214 	{
215 		base = base->anim_next;
216 		if (!base)
217 			Sys_Error ("R_TextureAnimation: broken cycle");
218 		if (++count > 100)
219 			Sys_Error ("R_TextureAnimation: infinite cycle");
220 	}
221 
222 	return base;
223 }
224 
225 
226 /*
227 ===============
228 R_DrawSurface
229 ===============
230 */
R_DrawSurface(void)231 void R_DrawSurface (void)
232 {
233 	unsigned char	*basetptr;
234 	int				smax, tmax, twidth;
235 	int				u;
236 	int				soffset, basetoffset, texwidth;
237 	int				horzblockstep;
238 	unsigned char	*pcolumndest;
239 	void			(*pblockdrawer)(void);
240 	texture_t		*mt;
241 
242 // calculate the lightings
243 	R_BuildLightMap ();
244 
245 	surfrowbytes = r_drawsurf.rowbytes;
246 
247 	mt = r_drawsurf.texture;
248 
249 	r_source = (byte *)mt + mt->offsets[r_drawsurf.surfmip];
250 
251 // the fractional light values should range from 0 to (VID_GRADES - 1) << 16
252 // from a source range of 0 - 255
253 
254 	texwidth = mt->width >> r_drawsurf.surfmip;
255 
256 	blocksize = 16 >> r_drawsurf.surfmip;
257 	blockdivshift = 4 - r_drawsurf.surfmip;
258 	blockdivmask = (1 << blockdivshift) - 1;
259 
260 	r_lightwidth = (r_drawsurf.surf->extents[0]>>4)+1;
261 
262 	r_numhblocks = r_drawsurf.surfwidth >> blockdivshift;
263 	r_numvblocks = r_drawsurf.surfheight >> blockdivshift;
264 
265 //==============================
266 
267 	if (r_pixbytes == 1)
268 	{
269 		pblockdrawer = surfmiptable[r_drawsurf.surfmip];
270 	// TODO: only needs to be set when there is a display settings change
271 		horzblockstep = blocksize;
272 	}
273 	else
274 	{
275 		pblockdrawer = R_DrawSurfaceBlock16;
276 	// TODO: only needs to be set when there is a display settings change
277 		horzblockstep = blocksize << 1;
278 	}
279 
280 	smax = mt->width >> r_drawsurf.surfmip;
281 	twidth = texwidth;
282 	tmax = mt->height >> r_drawsurf.surfmip;
283 	sourcetstep = texwidth;
284 	r_stepback = tmax * twidth;
285 
286 	r_sourcemax = r_source + (tmax * smax);
287 
288 	soffset = r_drawsurf.surf->texturemins[0];
289 	basetoffset = r_drawsurf.surf->texturemins[1];
290 
291 // << 16 components are to guarantee positive values for %
292 	soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax;
293 	basetptr = &r_source[((((basetoffset >> r_drawsurf.surfmip)
294 		+ (tmax << 16)) % tmax) * twidth)];
295 
296 	pcolumndest = r_drawsurf.surfdat;
297 
298 	for (u=0 ; u<r_numhblocks; u++)
299 	{
300 		r_lightptr = blocklights + u;
301 
302 		prowdestbase = pcolumndest;
303 
304 		pbasesource = basetptr + soffset;
305 
306 		(*pblockdrawer)();
307 
308 		soffset = soffset + blocksize;
309 		if (soffset >= smax)
310 			soffset = 0;
311 
312 		pcolumndest += horzblockstep;
313 	}
314 }
315 
316 
317 //=============================================================================
318 
319 #if	!id386
320 
321 /*
322 ================
323 R_DrawSurfaceBlock8_mip0
324 ================
325 */
R_DrawSurfaceBlock8_mip0(void)326 void R_DrawSurfaceBlock8_mip0 (void)
327 {
328 	int				v, i, b, lightstep, lighttemp, light;
329 	unsigned char	pix, *psource, *prowdest;
330 
331 	psource = pbasesource;
332 	prowdest = prowdestbase;
333 
334 	for (v=0 ; v<r_numvblocks ; v++)
335 	{
336 	// FIXME: make these locals?
337 	// FIXME: use delta rather than both right and left, like ASM?
338 		lightleft = r_lightptr[0];
339 		lightright = r_lightptr[1];
340 		r_lightptr += r_lightwidth;
341 		lightleftstep = (r_lightptr[0] - lightleft) >> 4;
342 		lightrightstep = (r_lightptr[1] - lightright) >> 4;
343 
344 		for (i=0 ; i<16 ; i++)
345 		{
346 			lighttemp = lightleft - lightright;
347 			lightstep = lighttemp >> 4;
348 
349 			light = lightright;
350 
351 			for (b=15; b>=0; b--)
352 			{
353 				pix = psource[b];
354 				prowdest[b] = ((unsigned char *)vid.colormap)
355 						[(light & 0xFF00) + pix];
356 				light += lightstep;
357 			}
358 
359 			psource += sourcetstep;
360 			lightright += lightrightstep;
361 			lightleft += lightleftstep;
362 			prowdest += surfrowbytes;
363 		}
364 
365 		if (psource >= r_sourcemax)
366 			psource -= r_stepback;
367 	}
368 }
369 
370 
371 /*
372 ================
373 R_DrawSurfaceBlock8_mip1
374 ================
375 */
R_DrawSurfaceBlock8_mip1(void)376 void R_DrawSurfaceBlock8_mip1 (void)
377 {
378 	int				v, i, b, lightstep, lighttemp, light;
379 	unsigned char	pix, *psource, *prowdest;
380 
381 	psource = pbasesource;
382 	prowdest = prowdestbase;
383 
384 	for (v=0 ; v<r_numvblocks ; v++)
385 	{
386 	// FIXME: make these locals?
387 	// FIXME: use delta rather than both right and left, like ASM?
388 		lightleft = r_lightptr[0];
389 		lightright = r_lightptr[1];
390 		r_lightptr += r_lightwidth;
391 		lightleftstep = (r_lightptr[0] - lightleft) >> 3;
392 		lightrightstep = (r_lightptr[1] - lightright) >> 3;
393 
394 		for (i=0 ; i<8 ; i++)
395 		{
396 			lighttemp = lightleft - lightright;
397 			lightstep = lighttemp >> 3;
398 
399 			light = lightright;
400 
401 			for (b=7; b>=0; b--)
402 			{
403 				pix = psource[b];
404 				prowdest[b] = ((unsigned char *)vid.colormap)
405 						[(light & 0xFF00) + pix];
406 				light += lightstep;
407 			}
408 
409 			psource += sourcetstep;
410 			lightright += lightrightstep;
411 			lightleft += lightleftstep;
412 			prowdest += surfrowbytes;
413 		}
414 
415 		if (psource >= r_sourcemax)
416 			psource -= r_stepback;
417 	}
418 }
419 
420 
421 /*
422 ================
423 R_DrawSurfaceBlock8_mip2
424 ================
425 */
R_DrawSurfaceBlock8_mip2(void)426 void R_DrawSurfaceBlock8_mip2 (void)
427 {
428 	int				v, i, b, lightstep, lighttemp, light;
429 	unsigned char	pix, *psource, *prowdest;
430 
431 	psource = pbasesource;
432 	prowdest = prowdestbase;
433 
434 	for (v=0 ; v<r_numvblocks ; v++)
435 	{
436 	// FIXME: make these locals?
437 	// FIXME: use delta rather than both right and left, like ASM?
438 		lightleft = r_lightptr[0];
439 		lightright = r_lightptr[1];
440 		r_lightptr += r_lightwidth;
441 		lightleftstep = (r_lightptr[0] - lightleft) >> 2;
442 		lightrightstep = (r_lightptr[1] - lightright) >> 2;
443 
444 		for (i=0 ; i<4 ; i++)
445 		{
446 			lighttemp = lightleft - lightright;
447 			lightstep = lighttemp >> 2;
448 
449 			light = lightright;
450 
451 			for (b=3; b>=0; b--)
452 			{
453 				pix = psource[b];
454 				prowdest[b] = ((unsigned char *)vid.colormap)
455 						[(light & 0xFF00) + pix];
456 				light += lightstep;
457 			}
458 
459 			psource += sourcetstep;
460 			lightright += lightrightstep;
461 			lightleft += lightleftstep;
462 			prowdest += surfrowbytes;
463 		}
464 
465 		if (psource >= r_sourcemax)
466 			psource -= r_stepback;
467 	}
468 }
469 
470 
471 /*
472 ================
473 R_DrawSurfaceBlock8_mip3
474 ================
475 */
R_DrawSurfaceBlock8_mip3(void)476 void R_DrawSurfaceBlock8_mip3 (void)
477 {
478 	int				v, i, b, lightstep, lighttemp, light;
479 	unsigned char	pix, *psource, *prowdest;
480 
481 	psource = pbasesource;
482 	prowdest = prowdestbase;
483 
484 	for (v=0 ; v<r_numvblocks ; v++)
485 	{
486 	// FIXME: make these locals?
487 	// FIXME: use delta rather than both right and left, like ASM?
488 		lightleft = r_lightptr[0];
489 		lightright = r_lightptr[1];
490 		r_lightptr += r_lightwidth;
491 		lightleftstep = (r_lightptr[0] - lightleft) >> 1;
492 		lightrightstep = (r_lightptr[1] - lightright) >> 1;
493 
494 		for (i=0 ; i<2 ; i++)
495 		{
496 			lighttemp = lightleft - lightright;
497 			lightstep = lighttemp >> 1;
498 
499 			light = lightright;
500 
501 			for (b=1; b>=0; b--)
502 			{
503 				pix = psource[b];
504 				prowdest[b] = ((unsigned char *)vid.colormap)
505 						[(light & 0xFF00) + pix];
506 				light += lightstep;
507 			}
508 
509 			psource += sourcetstep;
510 			lightright += lightrightstep;
511 			lightleft += lightleftstep;
512 			prowdest += surfrowbytes;
513 		}
514 
515 		if (psource >= r_sourcemax)
516 			psource -= r_stepback;
517 	}
518 }
519 
520 
521 /*
522 ================
523 R_DrawSurfaceBlock16
524 
525 FIXME: make this work
526 ================
527 */
R_DrawSurfaceBlock16(void)528 void R_DrawSurfaceBlock16 (void)
529 {
530 	int				k;
531 	unsigned char	*psource;
532 	int				lighttemp, lightstep, light;
533 	unsigned short	*prowdest;
534 
535 	prowdest = (unsigned short *)prowdestbase;
536 
537 	for (k=0 ; k<blocksize ; k++)
538 	{
539 		unsigned short	*pdest;
540 		unsigned char	pix;
541 		int				b;
542 
543 		psource = pbasesource;
544 		lighttemp = lightright - lightleft;
545 		lightstep = lighttemp >> blockdivshift;
546 
547 		light = lightleft;
548 		pdest = prowdest;
549 
550 		for (b=0; b<blocksize; b++)
551 		{
552 			pix = *psource;
553 			*pdest = vid.colormap16[(light & 0xFF00) + pix];
554 			psource += sourcesstep;
555 			pdest++;
556 			light += lightstep;
557 		}
558 
559 		pbasesource += sourcetstep;
560 		lightright += lightrightstep;
561 		lightleft += lightleftstep;
562 		prowdest = (unsigned short *)((long)prowdest + surfrowbytes);
563 	}
564 
565 	prowdestbase = prowdest;
566 }
567 
568 #endif
569 
570 
571 //============================================================================
572 
573 /*
574 ================
575 R_GenTurbTile
576 ================
577 */
R_GenTurbTile(pixel_t * pbasetex,void * pdest)578 void R_GenTurbTile (pixel_t *pbasetex, void *pdest)
579 {
580 	int		*turb;
581 	int		i, j, s, t;
582 	byte	*pd;
583 
584 	turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
585 	pd = (byte *)pdest;
586 
587 	for (i=0 ; i<TILE_SIZE ; i++)
588 	{
589 		for (j=0 ; j<TILE_SIZE ; j++)
590 		{
591 			s = (((j << 16) + turb[i & (CYCLE-1)]) >> 16) & 63;
592 			t = (((i << 16) + turb[j & (CYCLE-1)]) >> 16) & 63;
593 			*pd++ = *(pbasetex + (t<<6) + s);
594 		}
595 	}
596 }
597 
598 
599 /*
600 ================
601 R_GenTurbTile16
602 ================
603 */
R_GenTurbTile16(pixel_t * pbasetex,void * pdest)604 void R_GenTurbTile16 (pixel_t *pbasetex, void *pdest)
605 {
606 	int				*turb;
607 	int				i, j, s, t;
608 	unsigned short	*pd;
609 
610 	turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
611 	pd = (unsigned short *)pdest;
612 
613 	for (i=0 ; i<TILE_SIZE ; i++)
614 	{
615 		for (j=0 ; j<TILE_SIZE ; j++)
616 		{
617 			s = (((j << 16) + turb[i & (CYCLE-1)]) >> 16) & 63;
618 			t = (((i << 16) + turb[j & (CYCLE-1)]) >> 16) & 63;
619 			*pd++ = d_8to16table[*(pbasetex + (t<<6) + s)];
620 		}
621 	}
622 }
623 
624 
625 /*
626 ================
627 R_GenTile
628 ================
629 */
R_GenTile(msurface_t * psurf,void * pdest)630 void R_GenTile (msurface_t *psurf, void *pdest)
631 {
632 	if (psurf->flags & SURF_DRAWTURB)
633 	{
634 		if (r_pixbytes == 1)
635 		{
636 			R_GenTurbTile ((pixel_t *)
637 				((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest);
638 		}
639 		else
640 		{
641 			R_GenTurbTile16 ((pixel_t *)
642 				((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest);
643 		}
644 	}
645 	else if (psurf->flags & SURF_DRAWSKY)
646 	{
647 		if (r_pixbytes == 1)
648 		{
649 			R_GenSkyTile (pdest);
650 		}
651 		else
652 		{
653 			R_GenSkyTile16 (pdest);
654 		}
655 	}
656 	else
657 	{
658 		Sys_Error ("Unknown tile type");
659 	}
660 }
661 
662