git-svn-id: http://bladebattles.com/kurok/SVN@11 20cd92bb-ff49-0410-b73e-96a06e42c3b9
[kurok.git] / r_surf.c
blobabd03d4b41f1fb0b6a3aabf818e7e978dafb62ff
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
20 // r_surf.c: surface-related refresh code
22 #include "quakedef.h"
23 #include "r_local.h"
25 drawsurf_t r_drawsurf;
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;
40 void R_DrawSurfaceBlock8_mip0 (void);
41 void R_DrawSurfaceBlock8_mip1 (void);
42 void R_DrawSurfaceBlock8_mip2 (void);
43 void R_DrawSurfaceBlock8_mip3 (void);
45 static void (*surfmiptable[4])(void) = {
46 R_DrawSurfaceBlock8_mip0,
47 R_DrawSurfaceBlock8_mip1,
48 R_DrawSurfaceBlock8_mip2,
49 R_DrawSurfaceBlock8_mip3
54 unsigned blocklights[18*18];
57 ===============
58 R_AddDynamicLights
59 ===============
61 void R_AddDynamicLights (void)
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;
73 surf = r_drawsurf.surf;
74 smax = (surf->extents[0]>>4)+1;
75 tmax = (surf->extents[1]>>4)+1;
76 tex = surf->texinfo;
78 for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
80 if ( !(surf->dlightbits & (1<<lnum) ) )
81 continue; // not lit by this light
83 rad = cl_dlights[lnum].radius;
84 dist = DotProduct (cl_dlights[lnum].origin, surf->plane->normal) -
85 surf->plane->dist;
86 rad -= fabsf(dist);
87 minlight = cl_dlights[lnum].minlight;
88 if (rad < minlight)
89 continue;
90 minlight = rad - minlight;
92 for (i=0 ; i<3 ; i++)
94 impact[i] = cl_dlights[lnum].origin[i] -
95 surf->plane->normal[i]*dist;
98 local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
99 local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
101 local[0] -= surf->texturemins[0];
102 local[1] -= surf->texturemins[1];
104 for (t = 0 ; t<tmax ; t++)
106 td = local[1] - t*16;
107 if (td < 0)
108 td = -td;
109 for (s=0 ; s<smax ; s++)
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 #ifdef QUAKE2
121 unsigned temp;
122 temp = (rad - dist)*256;
123 i = t*smax + s;
124 if (!cl_dlights[lnum].dark)
125 blocklights[i] += temp;
126 else
128 if (blocklights[i] > temp)
129 blocklights[i] -= temp;
130 else
131 blocklights[i] = 0;
134 #else
135 blocklights[t*smax + s] += (rad - dist)*256;
136 #endif
143 ===============
144 R_BuildLightMap
146 Combine and scale multiple lightmaps into the 8.8 format in blocklights
147 ===============
149 void R_BuildLightMap (void)
151 int smax, tmax;
152 int t;
153 int i, size;
154 byte *lightmap;
155 unsigned scale;
156 int maps;
157 msurface_t *surf;
159 surf = r_drawsurf.surf;
161 smax = (surf->extents[0]>>4)+1;
162 tmax = (surf->extents[1]>>4)+1;
163 size = smax*tmax;
164 lightmap = surf->samples;
166 if (r_fullbright.value || !cl.worldmodel->lightdata)
168 for (i=0 ; i<size ; i++)
169 blocklights[i] = 0;
170 return;
173 // clear to ambient
174 for (i=0 ; i<size ; i++)
175 blocklights[i] = r_refdef.ambientlight<<8;
178 // add all the lightmaps
179 if (lightmap)
180 for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
181 maps++)
183 scale = r_drawsurf.lightadj[maps]; // 8.8 fraction
184 for (i=0 ; i<size ; i++)
185 blocklights[i] += lightmap[i] * scale;
186 lightmap += size; // skip to next lightmap
189 // add all the dynamic lights
190 if (surf->dlightframe == r_framecount)
191 R_AddDynamicLights ();
193 // bound, invert, and shift
194 for (i=0 ; i<size ; i++)
196 t = (255*256 - (int)blocklights[i]) >> (8 - VID_CBITS);
198 if (t < (1 << 6))
199 t = (1 << 6);
201 blocklights[i] = t;
207 ===============
208 R_TextureAnimation
210 Returns the proper texture for a given time and base texture
211 ===============
213 texture_t *R_TextureAnimation (texture_t *base)
215 int reletive;
216 int count;
218 if (currententity->frame)
220 if (base->alternate_anims)
221 base = base->alternate_anims;
224 if (!base->anim_total)
225 return base;
227 reletive = (int)(cl.time*10) % base->anim_total;
229 count = 0;
230 while (base->anim_min > reletive || base->anim_max <= reletive)
232 base = base->anim_next;
233 if (!base)
234 Sys_Error ("R_TextureAnimation: broken cycle");
235 if (++count > 100)
236 Sys_Error ("R_TextureAnimation: infinite cycle");
239 return base;
244 ===============
245 R_DrawSurface
246 ===============
248 void R_DrawSurface (void)
250 unsigned char *basetptr;
251 int smax, tmax, twidth;
252 int u;
253 int soffset, basetoffset, texwidth;
254 int horzblockstep;
255 unsigned char *pcolumndest;
256 void (*pblockdrawer)(void);
257 texture_t *mt;
259 // calculate the lightings
260 R_BuildLightMap ();
262 surfrowbytes = r_drawsurf.rowbytes;
264 mt = r_drawsurf.texture;
266 r_source = (byte *)mt + mt->offsets[r_drawsurf.surfmip];
268 // the fractional light values should range from 0 to (VID_GRADES - 1) << 16
269 // from a source range of 0 - 255
271 texwidth = mt->width >> r_drawsurf.surfmip;
273 blocksize = 16 >> r_drawsurf.surfmip;
274 blockdivshift = 4 - r_drawsurf.surfmip;
275 blockdivmask = (1 << blockdivshift) - 1;
277 r_lightwidth = (r_drawsurf.surf->extents[0]>>4)+1;
279 r_numhblocks = r_drawsurf.surfwidth >> blockdivshift;
280 r_numvblocks = r_drawsurf.surfheight >> blockdivshift;
282 //==============================
284 if (r_pixbytes == 1)
286 pblockdrawer = surfmiptable[r_drawsurf.surfmip];
287 // TODO: only needs to be set when there is a display settings change
288 horzblockstep = blocksize;
290 else
292 pblockdrawer = R_DrawSurfaceBlock16;
293 // TODO: only needs to be set when there is a display settings change
294 horzblockstep = blocksize << 1;
297 smax = mt->width >> r_drawsurf.surfmip;
298 twidth = texwidth;
299 tmax = mt->height >> r_drawsurf.surfmip;
300 sourcetstep = texwidth;
301 r_stepback = tmax * twidth;
303 r_sourcemax = r_source + (tmax * smax);
305 soffset = r_drawsurf.surf->texturemins[0];
306 basetoffset = r_drawsurf.surf->texturemins[1];
308 // << 16 components are to guarantee positive values for %
309 soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax;
310 basetptr = &r_source[((((basetoffset >> r_drawsurf.surfmip)
311 + (tmax << 16)) % tmax) * twidth)];
313 pcolumndest = r_drawsurf.surfdat;
315 for (u=0 ; u<r_numhblocks; u++)
317 r_lightptr = blocklights + u;
319 prowdestbase = pcolumndest;
321 pbasesource = basetptr + soffset;
323 (*pblockdrawer)();
325 soffset = soffset + blocksize;
326 if (soffset >= smax)
327 soffset = 0;
329 pcolumndest += horzblockstep;
334 //=============================================================================
336 #if !id386
339 ================
340 R_DrawSurfaceBlock8_mip0
341 ================
343 void R_DrawSurfaceBlock8_mip0 (void)
345 int v, i, b, lightstep, lighttemp, light;
346 unsigned char pix, *psource, *prowdest;
348 psource = pbasesource;
349 prowdest = prowdestbase;
351 for (v=0 ; v<r_numvblocks ; v++)
353 // FIXME: make these locals?
354 // FIXME: use delta rather than both right and left, like ASM?
355 lightleft = r_lightptr[0];
356 lightright = r_lightptr[1];
357 r_lightptr += r_lightwidth;
358 lightleftstep = (r_lightptr[0] - lightleft) >> 4;
359 lightrightstep = (r_lightptr[1] - lightright) >> 4;
361 for (i=0 ; i<16 ; i++)
363 lighttemp = lightleft - lightright;
364 lightstep = lighttemp >> 4;
366 light = lightright;
368 for (b=15; b>=0; b--)
370 pix = psource[b];
371 prowdest[b] = ((unsigned char *)vid.colormap)
372 [(light & 0xFF00) + pix];
373 light += lightstep;
376 psource += sourcetstep;
377 lightright += lightrightstep;
378 lightleft += lightleftstep;
379 prowdest += surfrowbytes;
382 if (psource >= r_sourcemax)
383 psource -= r_stepback;
389 ================
390 R_DrawSurfaceBlock8_mip1
391 ================
393 void R_DrawSurfaceBlock8_mip1 (void)
395 int v, i, b, lightstep, lighttemp, light;
396 unsigned char pix, *psource, *prowdest;
398 psource = pbasesource;
399 prowdest = prowdestbase;
401 for (v=0 ; v<r_numvblocks ; v++)
403 // FIXME: make these locals?
404 // FIXME: use delta rather than both right and left, like ASM?
405 lightleft = r_lightptr[0];
406 lightright = r_lightptr[1];
407 r_lightptr += r_lightwidth;
408 lightleftstep = (r_lightptr[0] - lightleft) >> 3;
409 lightrightstep = (r_lightptr[1] - lightright) >> 3;
411 for (i=0 ; i<8 ; i++)
413 lighttemp = lightleft - lightright;
414 lightstep = lighttemp >> 3;
416 light = lightright;
418 for (b=7; b>=0; b--)
420 pix = psource[b];
421 prowdest[b] = ((unsigned char *)vid.colormap)
422 [(light & 0xFF00) + pix];
423 light += lightstep;
426 psource += sourcetstep;
427 lightright += lightrightstep;
428 lightleft += lightleftstep;
429 prowdest += surfrowbytes;
432 if (psource >= r_sourcemax)
433 psource -= r_stepback;
439 ================
440 R_DrawSurfaceBlock8_mip2
441 ================
443 void R_DrawSurfaceBlock8_mip2 (void)
445 int v, i, b, lightstep, lighttemp, light;
446 unsigned char pix, *psource, *prowdest;
448 psource = pbasesource;
449 prowdest = prowdestbase;
451 for (v=0 ; v<r_numvblocks ; v++)
453 // FIXME: make these locals?
454 // FIXME: use delta rather than both right and left, like ASM?
455 lightleft = r_lightptr[0];
456 lightright = r_lightptr[1];
457 r_lightptr += r_lightwidth;
458 lightleftstep = (r_lightptr[0] - lightleft) >> 2;
459 lightrightstep = (r_lightptr[1] - lightright) >> 2;
461 for (i=0 ; i<4 ; i++)
463 lighttemp = lightleft - lightright;
464 lightstep = lighttemp >> 2;
466 light = lightright;
468 for (b=3; b>=0; b--)
470 pix = psource[b];
471 prowdest[b] = ((unsigned char *)vid.colormap)
472 [(light & 0xFF00) + pix];
473 light += lightstep;
476 psource += sourcetstep;
477 lightright += lightrightstep;
478 lightleft += lightleftstep;
479 prowdest += surfrowbytes;
482 if (psource >= r_sourcemax)
483 psource -= r_stepback;
489 ================
490 R_DrawSurfaceBlock8_mip3
491 ================
493 void R_DrawSurfaceBlock8_mip3 (void)
495 int v, i, b, lightstep, lighttemp, light;
496 unsigned char pix, *psource, *prowdest;
498 psource = pbasesource;
499 prowdest = prowdestbase;
501 for (v=0 ; v<r_numvblocks ; v++)
503 // FIXME: make these locals?
504 // FIXME: use delta rather than both right and left, like ASM?
505 lightleft = r_lightptr[0];
506 lightright = r_lightptr[1];
507 r_lightptr += r_lightwidth;
508 lightleftstep = (r_lightptr[0] - lightleft) >> 1;
509 lightrightstep = (r_lightptr[1] - lightright) >> 1;
511 for (i=0 ; i<2 ; i++)
513 lighttemp = lightleft - lightright;
514 lightstep = lighttemp >> 1;
516 light = lightright;
518 for (b=1; b>=0; b--)
520 pix = psource[b];
521 prowdest[b] = ((unsigned char *)vid.colormap)
522 [(light & 0xFF00) + pix];
523 light += lightstep;
526 psource += sourcetstep;
527 lightright += lightrightstep;
528 lightleft += lightleftstep;
529 prowdest += surfrowbytes;
532 if (psource >= r_sourcemax)
533 psource -= r_stepback;
539 ================
540 R_DrawSurfaceBlock16
542 FIXME: make this work
543 ================
545 void R_DrawSurfaceBlock16 (void)
547 int k;
548 unsigned char *psource;
549 int lighttemp, lightstep, light;
550 unsigned short *prowdest;
552 prowdest = (unsigned short *)prowdestbase;
554 for (k=0 ; k<blocksize ; k++)
556 unsigned short *pdest;
557 unsigned char pix;
558 int b;
560 psource = pbasesource;
561 lighttemp = lightright - lightleft;
562 lightstep = lighttemp >> blockdivshift;
564 light = lightleft;
565 pdest = prowdest;
567 for (b=0; b<blocksize; b++)
569 pix = *psource;
570 *pdest = vid.colormap16[(light & 0xFF00) + pix];
571 psource += sourcesstep;
572 pdest++;
573 light += lightstep;
576 pbasesource += sourcetstep;
577 lightright += lightrightstep;
578 lightleft += lightleftstep;
579 prowdest = (unsigned short *)((long)prowdest + surfrowbytes);
582 prowdestbase = prowdest;
585 #endif
588 //============================================================================
591 ================
592 R_GenTurbTile
593 ================
595 void R_GenTurbTile (pixel_t *pbasetex, void *pdest)
597 int *turb;
598 int i, j, s, t;
599 byte *pd;
601 turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
602 pd = (byte *)pdest;
604 for (i=0 ; i<TILE_SIZE ; i++)
606 for (j=0 ; j<TILE_SIZE ; j++)
608 s = (((j << 16) + turb[i & (CYCLE-1)]) >> 16) & 63;
609 t = (((i << 16) + turb[j & (CYCLE-1)]) >> 16) & 63;
610 *pd++ = *(pbasetex + (t<<6) + s);
617 ================
618 R_GenTurbTile16
619 ================
621 void R_GenTurbTile16 (pixel_t *pbasetex, void *pdest)
623 int *turb;
624 int i, j, s, t;
625 unsigned short *pd;
627 turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
628 pd = (unsigned short *)pdest;
630 for (i=0 ; i<TILE_SIZE ; i++)
632 for (j=0 ; j<TILE_SIZE ; j++)
634 s = (((j << 16) + turb[i & (CYCLE-1)]) >> 16) & 63;
635 t = (((i << 16) + turb[j & (CYCLE-1)]) >> 16) & 63;
636 *pd++ = d_8to16table[*(pbasetex + (t<<6) + s)];
643 ================
644 R_GenTile
645 ================
647 void R_GenTile (msurface_t *psurf, void *pdest)
649 if (psurf->flags & SURF_DRAWTURB)
651 if (r_pixbytes == 1)
653 R_GenTurbTile ((pixel_t *)
654 ((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest);
656 else
658 R_GenTurbTile16 ((pixel_t *)
659 ((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest);
662 else if (psurf->flags & SURF_DRAWSKY)
664 if (r_pixbytes == 1)
666 R_GenSkyTile (pdest);
668 else
670 R_GenSkyTile16 (pdest);
673 else
675 Sys_Error ("Unknown tile type");