Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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. */
  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. #ifdef QUAKE2
  120.                                 {
  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
  127.                                         {
  128.                                                 if (blocklights[i] > temp)
  129.                                                         blocklights[i] -= temp;
  130.                                                 else
  131.                                                         blocklights[i] = 0;
  132.                                         }
  133.                                 }
  134. #else
  135.                                         blocklights[t*smax + s] += (rad - dist)*256;
  136. #endif
  137.                         }
  138.                 }
  139.         }
  140. }
  141.  
  142. /*
  143. ===============
  144. R_BuildLightMap
  145.  
  146. Combine and scale multiple lightmaps into the 8.8 format in blocklights
  147. ===============
  148. */
  149. void R_BuildLightMap (void)
  150. {
  151.         int                     smax, tmax;
  152.         int                     t;
  153.         int                     i, size;
  154.         byte            *lightmap;
  155.         unsigned        scale;
  156.         int                     maps;
  157.         msurface_t      *surf;
  158.  
  159.         surf = r_drawsurf.surf;
  160.  
  161.         smax = (surf->extents[0]>>4)+1;
  162.         tmax = (surf->extents[1]>>4)+1;
  163.         size = smax*tmax;
  164.         lightmap = surf->samples;
  165.  
  166.         if (r_fullbright.value || !cl.worldmodel->lightdata)
  167.         {
  168.                 for (i=0 ; i<size ; i++)
  169.                         blocklights[i] = 0;
  170.                 return;
  171.         }
  172.  
  173. // clear to ambient
  174.         for (i=0 ; i<size ; i++)
  175.                 blocklights[i] = r_refdef.ambientlight<<8;
  176.  
  177.  
  178. // add all the lightmaps
  179.         if (lightmap)
  180.                 for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
  181.                          maps++)
  182.                 {
  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
  187.                 }
  188.  
  189. // add all the dynamic lights
  190.         if (surf->dlightframe == r_framecount)
  191.                 R_AddDynamicLights ();
  192.  
  193. // bound, invert, and shift
  194.         for (i=0 ; i<size ; i++)
  195.         {
  196.                 t = (255*256 - (int)blocklights[i]) >> (8 - VID_CBITS);
  197.  
  198.                 if (t < (1 << 6))
  199.                         t = (1 << 6);
  200.  
  201.                 blocklights[i] = t;
  202.         }
  203. }
  204.  
  205.  
  206. /*
  207. ===============
  208. R_TextureAnimation
  209.  
  210. Returns the proper texture for a given time and base texture
  211. ===============
  212. */
  213. texture_t *R_TextureAnimation (texture_t *base)
  214. {
  215.         int             reletive;
  216.         int             count;
  217.  
  218.         if (currententity->frame)
  219.         {
  220.                 if (base->alternate_anims)
  221.                         base = base->alternate_anims;
  222.         }
  223.        
  224.         if (!base->anim_total)
  225.                 return base;
  226.  
  227.         reletive = (int)(cl.time*10) % base->anim_total;
  228.  
  229.         count = 0;     
  230.         while (base->anim_min > reletive || base->anim_max <= reletive)
  231.         {
  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");
  237.         }
  238.  
  239.         return base;
  240. }
  241.  
  242.  
  243. /*
  244. ===============
  245. R_DrawSurface
  246. ===============
  247. */
  248. void R_DrawSurface (void)
  249. {
  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;
  258.  
  259. // calculate the lightings
  260.         R_BuildLightMap ();
  261.        
  262.         surfrowbytes = r_drawsurf.rowbytes;
  263.  
  264.         mt = r_drawsurf.texture;
  265.        
  266.         r_source = (byte *)mt + mt->offsets[r_drawsurf.surfmip];
  267.        
  268. // the fractional light values should range from 0 to (VID_GRADES - 1) << 16
  269. // from a source range of 0 - 255
  270.        
  271.         texwidth = mt->width >> r_drawsurf.surfmip;
  272.  
  273.         blocksize = 16 >> r_drawsurf.surfmip;
  274.         blockdivshift = 4 - r_drawsurf.surfmip;
  275.         blockdivmask = (1 << blockdivshift) - 1;
  276.        
  277.         r_lightwidth = (r_drawsurf.surf->extents[0]>>4)+1;
  278.  
  279.         r_numhblocks = r_drawsurf.surfwidth >> blockdivshift;
  280.         r_numvblocks = r_drawsurf.surfheight >> blockdivshift;
  281.  
  282. //==============================
  283.  
  284.         if (r_pixbytes == 1)
  285.         {
  286.                 pblockdrawer = surfmiptable[r_drawsurf.surfmip];
  287.         // TODO: only needs to be set when there is a display settings change
  288.                 horzblockstep = blocksize;
  289.         }
  290.         else
  291.         {
  292.                 pblockdrawer = R_DrawSurfaceBlock16;
  293.         // TODO: only needs to be set when there is a display settings change
  294.                 horzblockstep = blocksize << 1;
  295.         }
  296.  
  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;
  302.  
  303.         r_sourcemax = r_source + (tmax * smax);
  304.  
  305.         soffset = r_drawsurf.surf->texturemins[0];
  306.         basetoffset = r_drawsurf.surf->texturemins[1];
  307.  
  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)];
  312.  
  313.         pcolumndest = r_drawsurf.surfdat;
  314.  
  315.         for (u=0 ; u<r_numhblocks; u++)
  316.         {
  317.                 r_lightptr = blocklights + u;
  318.  
  319.                 prowdestbase = pcolumndest;
  320.  
  321.                 pbasesource = basetptr + soffset;
  322.  
  323.                 (*pblockdrawer)();
  324.  
  325.                 soffset = soffset + blocksize;
  326.                 if (soffset >= smax)
  327.                         soffset = 0;
  328.  
  329.                 pcolumndest += horzblockstep;
  330.         }
  331. }
  332.  
  333.  
  334. //=============================================================================
  335.  
  336. #if     !id386
  337.  
  338. /*
  339. ================
  340. R_DrawSurfaceBlock8_mip0
  341. ================
  342. */
  343. void R_DrawSurfaceBlock8_mip0 (void)
  344. {
  345.         int                             v, i, b, lightstep, lighttemp, light;
  346.         unsigned char   pix, *psource, *prowdest;
  347.  
  348.         psource = pbasesource;
  349.         prowdest = prowdestbase;
  350.  
  351.         for (v=0 ; v<r_numvblocks ; v++)
  352.         {
  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;
  360.  
  361.                 for (i=0 ; i<16 ; i++)
  362.                 {
  363.                         lighttemp = lightleft - lightright;
  364.                         lightstep = lighttemp >> 4;
  365.  
  366.                         light = lightright;
  367.  
  368.                         for (b=15; b>=0; b--)
  369.                         {
  370.                                 pix = psource[b];
  371.                                 prowdest[b] = ((unsigned char *)vid.colormap)
  372.                                                 [(light & 0xFF00) + pix];
  373.                                 light += lightstep;
  374.                         }
  375.        
  376.                         psource += sourcetstep;
  377.                         lightright += lightrightstep;
  378.                         lightleft += lightleftstep;
  379.                         prowdest += surfrowbytes;
  380.                 }
  381.  
  382.                 if (psource >= r_sourcemax)
  383.                         psource -= r_stepback;
  384.         }
  385. }
  386.  
  387.  
  388. /*
  389. ================
  390. R_DrawSurfaceBlock8_mip1
  391. ================
  392. */
  393. void R_DrawSurfaceBlock8_mip1 (void)
  394. {
  395.         int                             v, i, b, lightstep, lighttemp, light;
  396.         unsigned char   pix, *psource, *prowdest;
  397.  
  398.         psource = pbasesource;
  399.         prowdest = prowdestbase;
  400.  
  401.         for (v=0 ; v<r_numvblocks ; v++)
  402.         {
  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;
  410.  
  411.                 for (i=0 ; i<8 ; i++)
  412.                 {
  413.                         lighttemp = lightleft - lightright;
  414.                         lightstep = lighttemp >> 3;
  415.  
  416.                         light = lightright;
  417.  
  418.                         for (b=7; b>=0; b--)
  419.                         {
  420.                                 pix = psource[b];
  421.                                 prowdest[b] = ((unsigned char *)vid.colormap)
  422.                                                 [(light & 0xFF00) + pix];
  423.                                 light += lightstep;
  424.                         }
  425.        
  426.                         psource += sourcetstep;
  427.                         lightright += lightrightstep;
  428.                         lightleft += lightleftstep;
  429.                         prowdest += surfrowbytes;
  430.                 }
  431.  
  432.                 if (psource >= r_sourcemax)
  433.                         psource -= r_stepback;
  434.         }
  435. }
  436.  
  437.  
  438. /*
  439. ================
  440. R_DrawSurfaceBlock8_mip2
  441. ================
  442. */
  443. void R_DrawSurfaceBlock8_mip2 (void)
  444. {
  445.         int                             v, i, b, lightstep, lighttemp, light;
  446.         unsigned char   pix, *psource, *prowdest;
  447.  
  448.         psource = pbasesource;
  449.         prowdest = prowdestbase;
  450.  
  451.         for (v=0 ; v<r_numvblocks ; v++)
  452.         {
  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;
  460.  
  461.                 for (i=0 ; i<4 ; i++)
  462.                 {
  463.                         lighttemp = lightleft - lightright;
  464.                         lightstep = lighttemp >> 2;
  465.  
  466.                         light = lightright;
  467.  
  468.                         for (b=3; b>=0; b--)
  469.                         {
  470.                                 pix = psource[b];
  471.                                 prowdest[b] = ((unsigned char *)vid.colormap)
  472.                                                 [(light & 0xFF00) + pix];
  473.                                 light += lightstep;
  474.                         }
  475.        
  476.                         psource += sourcetstep;
  477.                         lightright += lightrightstep;
  478.                         lightleft += lightleftstep;
  479.                         prowdest += surfrowbytes;
  480.                 }
  481.  
  482.                 if (psource >= r_sourcemax)
  483.                         psource -= r_stepback;
  484.         }
  485. }
  486.  
  487.  
  488. /*
  489. ================
  490. R_DrawSurfaceBlock8_mip3
  491. ================
  492. */
  493. void R_DrawSurfaceBlock8_mip3 (void)
  494. {
  495.         int                             v, i, b, lightstep, lighttemp, light;
  496.         unsigned char   pix, *psource, *prowdest;
  497.  
  498.         psource = pbasesource;
  499.         prowdest = prowdestbase;
  500.  
  501.         for (v=0 ; v<r_numvblocks ; v++)
  502.         {
  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;
  510.  
  511.                 for (i=0 ; i<2 ; i++)
  512.                 {
  513.                         lighttemp = lightleft - lightright;
  514.                         lightstep = lighttemp >> 1;
  515.  
  516.                         light = lightright;
  517.  
  518.                         for (b=1; b>=0; b--)
  519.                         {
  520.                                 pix = psource[b];
  521.                                 prowdest[b] = ((unsigned char *)vid.colormap)
  522.                                                 [(light & 0xFF00) + pix];
  523.                                 light += lightstep;
  524.                         }
  525.        
  526.                         psource += sourcetstep;
  527.                         lightright += lightrightstep;
  528.                         lightleft += lightleftstep;
  529.                         prowdest += surfrowbytes;
  530.                 }
  531.  
  532.                 if (psource >= r_sourcemax)
  533.                         psource -= r_stepback;
  534.         }
  535. }
  536.  
  537.  
  538. /*
  539. ================
  540. R_DrawSurfaceBlock16
  541.  
  542. FIXME: make this work
  543. ================
  544. */
  545. void R_DrawSurfaceBlock16 (void)
  546. {
  547.         int                             k;
  548.         unsigned char   *psource;
  549.         int                             lighttemp, lightstep, light;
  550.         unsigned short  *prowdest;
  551.  
  552.         prowdest = (unsigned short *)prowdestbase;
  553.  
  554.         for (k=0 ; k<blocksize ; k++)
  555.         {
  556.                 unsigned short  *pdest;
  557.                 unsigned char   pix;
  558.                 int                             b;
  559.  
  560.                 psource = pbasesource;
  561.                 lighttemp = lightright - lightleft;
  562.                 lightstep = lighttemp >> blockdivshift;
  563.  
  564.                 light = lightleft;
  565.                 pdest = prowdest;
  566.  
  567.                 for (b=0; b<blocksize; b++)
  568.                 {
  569.                         pix = *psource;
  570.                         *pdest = vid.colormap16[(light & 0xFF00) + pix];
  571.                         psource += sourcesstep;
  572.                         pdest++;
  573.                         light += lightstep;
  574.                 }
  575.  
  576.                 pbasesource += sourcetstep;
  577.                 lightright += lightrightstep;
  578.                 lightleft += lightleftstep;
  579.                 prowdest = (unsigned short *)((long)prowdest + surfrowbytes);
  580.         }
  581.  
  582.         prowdestbase = prowdest;
  583. }
  584.  
  585. #endif
  586.  
  587.  
  588. //============================================================================
  589.  
  590. /*
  591. ================
  592. R_GenTurbTile
  593. ================
  594. */
  595. void R_GenTurbTile (pixel_t *pbasetex, void *pdest)
  596. {
  597.         int             *turb;
  598.         int             i, j, s, t;
  599.         byte    *pd;
  600.        
  601.         turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
  602.         pd = (byte *)pdest;
  603.  
  604.         for (i=0 ; i<TILE_SIZE ; i++)
  605.         {
  606.                 for (j=0 ; j<TILE_SIZE ; j++)
  607.                 {      
  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);
  611.                 }
  612.         }
  613. }
  614.  
  615.  
  616. /*
  617. ================
  618. R_GenTurbTile16
  619. ================
  620. */
  621. void R_GenTurbTile16 (pixel_t *pbasetex, void *pdest)
  622. {
  623.         int                             *turb;
  624.         int                             i, j, s, t;
  625.         unsigned short  *pd;
  626.  
  627.         turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
  628.         pd = (unsigned short *)pdest;
  629.  
  630.         for (i=0 ; i<TILE_SIZE ; i++)
  631.         {
  632.                 for (j=0 ; j<TILE_SIZE ; j++)
  633.                 {      
  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)];
  637.                 }
  638.         }
  639. }
  640.  
  641.  
  642. /*
  643. ================
  644. R_GenTile
  645. ================
  646. */
  647. void R_GenTile (msurface_t *psurf, void *pdest)
  648. {
  649.         if (psurf->flags & SURF_DRAWTURB)
  650.         {
  651.                 if (r_pixbytes == 1)
  652.                 {
  653.                         R_GenTurbTile ((pixel_t *)
  654.                                 ((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest);
  655.                 }
  656.                 else
  657.                 {
  658.                         R_GenTurbTile16 ((pixel_t *)
  659.                                 ((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest);
  660.                 }
  661.         }
  662.         else if (psurf->flags & SURF_DRAWSKY)
  663.         {
  664.                 if (r_pixbytes == 1)
  665.                 {
  666.                         R_GenSkyTile (pdest);
  667.                 }
  668.                 else
  669.                 {
  670.                         R_GenSkyTile16 (pdest);
  671.                 }
  672.         }
  673.         else
  674.         {
  675.                 Sys_Error ("Unknown tile type");
  676.         }
  677. }
  678.  
  679.