home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quakeworld_src / client / r_light.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  5.7 KB  |  267 lines

  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_light.c
  21.  
  22. #include "quakedef.h"
  23. #include "r_local.h"
  24.  
  25. int r_dlightframecount;
  26.  
  27. #if defined(M68KASM) || defined(PPCASM)
  28. extern int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end);
  29. #endif
  30.  
  31.  
  32. /*
  33. ==================
  34. R_AnimateLight
  35. ==================
  36. */
  37. void R_AnimateLight (void)
  38. {
  39.   int     i,j,k;
  40.   
  41. //
  42. // light animations
  43. // 'm' is normal light, 'a' is no light, 'z' is double bright
  44.   i = (int)(cl.time*10);
  45.   for (j=0 ; j<MAX_LIGHTSTYLES ; j++)
  46.   {
  47.     if (!cl_lightstyle[j].length)
  48.     {
  49.       d_lightstylevalue[j] = 256;
  50.       continue;
  51.     }
  52.     k = i % cl_lightstyle[j].length;
  53.     k = cl_lightstyle[j].map[k] - 'a';
  54.     k = k*22;
  55.     d_lightstylevalue[j] = k;
  56.   } 
  57. }
  58.  
  59.  
  60. /*
  61. =============================================================================
  62.  
  63. DYNAMIC LIGHTS
  64.  
  65. =============================================================================
  66. */
  67.  
  68. /*
  69. =============
  70. R_MarkLights
  71. =============
  72. */
  73. void R_MarkLights (dlight_t *light, int bit, mnode_t *node)
  74. {
  75.   mplane_t  *splitplane;
  76.   float   dist;
  77.   msurface_t  *surf;
  78.   int     i;
  79.   
  80.   if (node->contents < 0)
  81.     return;
  82.  
  83.   splitplane = node->plane;
  84.   dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
  85.   
  86.   if (dist > light->radius)
  87.   {
  88.     R_MarkLights (light, bit, node->children[0]);
  89.     return;
  90.   }
  91.   if (dist < -light->radius)
  92.   {
  93.     R_MarkLights (light, bit, node->children[1]);
  94.     return;
  95.   }
  96.     
  97. // mark the polygons
  98.   surf = cl.worldmodel->surfaces + node->firstsurface;
  99.   for (i=0 ; i<node->numsurfaces ; i++, surf++)
  100.   {
  101.     if (surf->dlightframe != r_dlightframecount)
  102.     {
  103.       surf->dlightbits = 0;
  104.       surf->dlightframe = r_dlightframecount;
  105.     }
  106.     surf->dlightbits |= bit;
  107.   }
  108.  
  109.   R_MarkLights (light, bit, node->children[0]);
  110.   R_MarkLights (light, bit, node->children[1]);
  111. }
  112.  
  113.  
  114. /*
  115. =============
  116. R_PushDlights
  117. =============
  118. */
  119. void R_PushDlights (void)
  120. {
  121.   int   i;
  122.   dlight_t  *l;
  123.  
  124.   r_dlightframecount = r_framecount + 1;  // because the count hasn't
  125.                       //  advanced yet for this frame
  126.   l = cl_dlights;
  127.  
  128.   for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
  129.   {
  130.     if (l->die < cl.time || !l->radius)
  131.       continue;
  132.     R_MarkLights ( l, 1<<i, cl.worldmodel->nodes );
  133.   }
  134. }
  135.  
  136.  
  137. /*
  138. =============================================================================
  139.  
  140. LIGHT SAMPLING
  141.  
  142. =============================================================================
  143. */
  144.  
  145. #if !defined(M68KASM) && !defined(PPCASM)
  146. int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
  147. {
  148.   int     r;
  149.   float   front, back, frac;
  150.   int     side;
  151.   mplane_t  *plane;
  152.   vec3_t    mid;
  153.   msurface_t  *surf;
  154.   int     s, t, ds, dt;
  155.   int     i;
  156.   mtexinfo_t  *tex;
  157.   byte    *lightmap;
  158.   unsigned  scale;
  159.   int     maps;
  160.  
  161.   if (node->contents < 0)
  162.     return -1;    // didn't hit anything
  163.   
  164. // calculate mid point
  165.  
  166. // FIXME: optimize for axial
  167.   plane = node->plane;
  168.   front = DotProduct (start, plane->normal) - plane->dist;
  169.   back = DotProduct (end, plane->normal) - plane->dist;
  170.   side = front < 0;
  171.   
  172.   if ( (back < 0) == side)
  173.     return RecursiveLightPoint (node->children[side], start, end);
  174.   
  175.   frac = front / (front-back);
  176.   mid[0] = start[0] + (end[0] - start[0])*frac;
  177.   mid[1] = start[1] + (end[1] - start[1])*frac;
  178.   mid[2] = start[2] + (end[2] - start[2])*frac;
  179.   
  180. // go down front side 
  181.   r = RecursiveLightPoint (node->children[side], start, mid);
  182.   if (r >= 0)
  183.     return r;   // hit something
  184.     
  185.   if ( (back < 0) == side )
  186.     return -1;    // didn't hit anuthing
  187.     
  188. // check for impact on this node
  189.  
  190.   surf = cl.worldmodel->surfaces + node->firstsurface;
  191.   for (i=0 ; i<node->numsurfaces ; i++, surf++)
  192.   {
  193.     if (surf->flags & SURF_DRAWTILED)
  194.       continue; // no lightmaps
  195.  
  196.     tex = surf->texinfo;
  197.     
  198.     s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3];
  199.     t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];;
  200.  
  201.     if (s < surf->texturemins[0] ||
  202.     t < surf->texturemins[1])
  203.       continue;
  204.     
  205.     ds = s - surf->texturemins[0];
  206.     dt = t - surf->texturemins[1];
  207.     
  208.     if ( ds > surf->extents[0] || dt > surf->extents[1] )
  209.       continue;
  210.  
  211.     if (!surf->samples)
  212.       return 0;
  213.  
  214.     ds >>= 4;
  215.     dt >>= 4;
  216.  
  217.     lightmap = surf->samples;
  218.     r = 0;
  219.     if (lightmap)
  220.     {
  221.  
  222.       lightmap += dt * ((surf->extents[0]>>4)+1) + ds;
  223.  
  224.       for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
  225.           maps++)
  226.       {
  227.         scale = d_lightstylevalue[surf->styles[maps]];
  228.         r += *lightmap * scale;
  229.         lightmap += ((surf->extents[0]>>4)+1) *
  230.             ((surf->extents[1]>>4)+1);
  231.       }
  232.       
  233.       r >>= 8;
  234.     }
  235.     
  236.     return r;
  237.   }
  238.  
  239. // go down back side
  240.   return RecursiveLightPoint (node->children[!side], mid, end);
  241. }
  242. #endif
  243.  
  244. int R_LightPoint (vec3_t p)
  245. {
  246.   vec3_t    end;
  247.   int     r;
  248.   
  249.   if (!cl.worldmodel->lightdata)
  250.     return 255;
  251.   
  252.   end[0] = p[0];
  253.   end[1] = p[1];
  254.   end[2] = p[2] - 2048;
  255.   
  256.   r = RecursiveLightPoint (cl.worldmodel->nodes, p, end);
  257.   
  258.   if (r == -1)
  259.     r = 0;
  260.  
  261.   if (r < r_refdef.ambientlight)
  262.     r = r_refdef.ambientlight;
  263.  
  264.   return r;
  265. }
  266.  
  267.