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_light.c
  21.  
  22. #include "quakedef.h"
  23.  
  24. int     r_dlightframecount;
  25.  
  26.  
  27. /*
  28. ==================
  29. R_AnimateLight
  30. ==================
  31. */
  32. void R_AnimateLight (void)
  33. {
  34.         int                     i,j,k;
  35.        
  36. //
  37. // light animations
  38. // 'm' is normal light, 'a' is no light, 'z' is double bright
  39.         i = (int)(cl.time*10);
  40.         for (j=0 ; j<MAX_LIGHTSTYLES ; j++)
  41.         {
  42.                 if (!cl_lightstyle[j].length)
  43.                 {
  44.                         d_lightstylevalue[j] = 256;
  45.                         continue;
  46.                 }
  47.                 k = i % cl_lightstyle[j].length;
  48.                 k = cl_lightstyle[j].map[k] - 'a';
  49.                 k = k*22;
  50.                 d_lightstylevalue[j] = k;
  51.         }      
  52. }
  53.  
  54. /*
  55. =============================================================================
  56.  
  57. DYNAMIC LIGHTS BLEND RENDERING
  58.  
  59. =============================================================================
  60. */
  61.  
  62. void AddLightBlend (float r, float g, float b, float a2)
  63. {
  64.         float   a;
  65.  
  66.         v_blend[3] = a = v_blend[3] + a2*(1-v_blend[3]);
  67.  
  68.         a2 = a2/a;
  69.  
  70.         v_blend[0] = v_blend[1]*(1-a2) + r*a2;
  71.         v_blend[1] = v_blend[1]*(1-a2) + g*a2;
  72.         v_blend[2] = v_blend[2]*(1-a2) + b*a2;
  73. }
  74.  
  75. void R_RenderDlight (dlight_t *light)
  76. {
  77.         int             i, j;
  78.         float   a;
  79.         vec3_t  v;
  80.         float   rad;
  81.  
  82.         rad = light->radius * 0.35;
  83.  
  84.         VectorSubtract (light->origin, r_origin, v);
  85.         if (Length (v) < rad)
  86.         {       // view is inside the dlight
  87.                 AddLightBlend (1, 0.5, 0, light->radius * 0.0003);
  88.                 return;
  89.         }
  90.  
  91.         glBegin (GL_TRIANGLE_FAN);
  92.         glColor3f (0.2,0.1,0.0);
  93.         for (i=0 ; i<3 ; i++)
  94.                 v[i] = light->origin[i] - vpn[i]*rad;
  95.         glVertex3fv (v);
  96.         glColor3f (0,0,0);
  97.         for (i=16 ; i>=0 ; i--)
  98.         {
  99.                 a = i/16.0 * M_PI*2;
  100.                 for (j=0 ; j<3 ; j++)
  101.                         v[j] = light->origin[j] + vright[j]*cos(a)*rad
  102.                                 + vup[j]*sin(a)*rad;
  103.                 glVertex3fv (v);
  104.         }
  105.         glEnd ();
  106. }
  107.  
  108. /*
  109. =============
  110. R_RenderDlights
  111. =============
  112. */
  113. void R_RenderDlights (void)
  114. {
  115.         int             i;
  116.         dlight_t        *l;
  117.  
  118.         if (!gl_flashblend.value)
  119.                 return;
  120.  
  121.         r_dlightframecount = r_framecount + 1;  // because the count hasn't
  122.                                                                                         //  advanced yet for this frame
  123.         glDepthMask (0);
  124.         glDisable (GL_TEXTURE_2D);
  125.         glShadeModel (GL_SMOOTH);
  126.         glEnable (GL_BLEND);
  127.         glBlendFunc (GL_ONE, GL_ONE);
  128.  
  129.         l = cl_dlights;
  130.         for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
  131.         {
  132.                 if (l->die < cl.time || !l->radius)
  133.                         continue;
  134.                 R_RenderDlight (l);
  135.         }
  136.  
  137.         glColor3f (1,1,1);
  138.         glDisable (GL_BLEND);
  139.         glEnable (GL_TEXTURE_2D);
  140.         glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  141.         glDepthMask (1);
  142. }
  143.  
  144.  
  145. /*
  146. =============================================================================
  147.  
  148. DYNAMIC LIGHTS
  149.  
  150. =============================================================================
  151. */
  152.  
  153. /*
  154. =============
  155. R_MarkLights
  156. =============
  157. */
  158. void R_MarkLights (dlight_t *light, int bit, mnode_t *node)
  159. {
  160.         mplane_t        *splitplane;
  161.         float           dist;
  162.         msurface_t      *surf;
  163.         int                     i;
  164.        
  165.         if (node->contents < 0)
  166.                 return;
  167.  
  168.         splitplane = node->plane;
  169.         dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
  170.        
  171.         if (dist > light->radius)
  172.         {
  173.                 R_MarkLights (light, bit, node->children[0]);
  174.                 return;
  175.         }
  176.         if (dist < -light->radius)
  177.         {
  178.                 R_MarkLights (light, bit, node->children[1]);
  179.                 return;
  180.         }
  181.                
  182. // mark the polygons
  183.         surf = cl.worldmodel->surfaces + node->firstsurface;
  184.         for (i=0 ; i<node->numsurfaces ; i++, surf++)
  185.         {
  186.                 if (surf->dlightframe != r_dlightframecount)
  187.                 {
  188.                         surf->dlightbits = 0;
  189.                         surf->dlightframe = r_dlightframecount;
  190.                 }
  191.                 surf->dlightbits |= bit;
  192.         }
  193.  
  194.         R_MarkLights (light, bit, node->children[0]);
  195.         R_MarkLights (light, bit, node->children[1]);
  196. }
  197.  
  198.  
  199. /*
  200. =============
  201. R_PushDlights
  202. =============
  203. */
  204. void R_PushDlights (void)
  205. {
  206.         int             i;
  207.         dlight_t        *l;
  208.  
  209.         if (gl_flashblend.value)
  210.                 return;
  211.  
  212.         r_dlightframecount = r_framecount + 1;  // because the count hasn't
  213.                                                                                         //  advanced yet for this frame
  214.         l = cl_dlights;
  215.  
  216.         for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
  217.         {
  218.                 if (l->die < cl.time || !l->radius)
  219.                         continue;
  220.                 R_MarkLights ( l, 1<<i, cl.worldmodel->nodes );
  221.         }
  222. }
  223.  
  224.  
  225. /*
  226. =============================================================================
  227.  
  228. LIGHT SAMPLING
  229.  
  230. =============================================================================
  231. */
  232.  
  233. mplane_t                *lightplane;
  234. vec3_t                  lightspot;
  235.  
  236. int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
  237. {
  238.         int                     r;
  239.         float           front, back, frac;
  240.         int                     side;
  241.         mplane_t        *plane;
  242.         vec3_t          mid;
  243.         msurface_t      *surf;
  244.         int                     s, t, ds, dt;
  245.         int                     i;
  246.         mtexinfo_t      *tex;
  247.         byte            *lightmap;
  248.         unsigned        scale;
  249.         int                     maps;
  250.  
  251.         if (node->contents < 0)
  252.                 return -1;              // didn't hit anything
  253.        
  254. // calculate mid point
  255.  
  256. // FIXME: optimize for axial
  257.         plane = node->plane;
  258.         front = DotProduct (start, plane->normal) - plane->dist;
  259.         back = DotProduct (end, plane->normal) - plane->dist;
  260.         side = front < 0;
  261.        
  262.         if ( (back < 0) == side)
  263.                 return RecursiveLightPoint (node->children[side], start, end);
  264.        
  265.         frac = front / (front-back);
  266.         mid[0] = start[0] + (end[0] - start[0])*frac;
  267.         mid[1] = start[1] + (end[1] - start[1])*frac;
  268.         mid[2] = start[2] + (end[2] - start[2])*frac;
  269.        
  270. // go down front side  
  271.         r = RecursiveLightPoint (node->children[side], start, mid);
  272.         if (r >= 0)
  273.                 return r;               // hit something
  274.                
  275.         if ( (back < 0) == side )
  276.                 return -1;              // didn't hit anuthing
  277.                
  278. // check for impact on this node
  279.         VectorCopy (mid, lightspot);
  280.         lightplane = plane;
  281.  
  282.         surf = cl.worldmodel->surfaces + node->firstsurface;
  283.         for (i=0 ; i<node->numsurfaces ; i++, surf++)
  284.         {
  285.                 if (surf->flags & SURF_DRAWTILED)
  286.                         continue;       // no lightmaps
  287.  
  288.                 tex = surf->texinfo;
  289.                
  290.                 s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3];
  291.                 t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];;
  292.  
  293.                 if (s < surf->texturemins[0] ||
  294.                 t < surf->texturemins[1])
  295.                         continue;
  296.                
  297.                 ds = s - surf->texturemins[0];
  298.                 dt = t - surf->texturemins[1];
  299.                
  300.                 if ( ds > surf->extents[0] || dt > surf->extents[1] )
  301.                         continue;
  302.  
  303.                 if (!surf->samples)
  304.                         return 0;
  305.  
  306.                 ds >>= 4;
  307.                 dt >>= 4;
  308.  
  309.                 lightmap = surf->samples;
  310.                 r = 0;
  311.                 if (lightmap)
  312.                 {
  313.  
  314.                         lightmap += dt * ((surf->extents[0]>>4)+1) + ds;
  315.  
  316.                         for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
  317.                                         maps++)
  318.                         {
  319.                                 scale = d_lightstylevalue[surf->styles[maps]];
  320.                                 r += *lightmap * scale;
  321.                                 lightmap += ((surf->extents[0]>>4)+1) *
  322.                                                 ((surf->extents[1]>>4)+1);
  323.                         }
  324.                        
  325.                         r >>= 8;
  326.                 }
  327.                
  328.                 return r;
  329.         }
  330.  
  331. // go down back side
  332.         return RecursiveLightPoint (node->children[!side], mid, end);
  333. }
  334.  
  335. int R_LightPoint (vec3_t p)
  336. {
  337.         vec3_t          end;
  338.         int                     r;
  339.        
  340.         if (!cl.worldmodel->lightdata)
  341.                 return 255;
  342.        
  343.         end[0] = p[0];
  344.         end[1] = p[1];
  345.         end[2] = p[2] - 2048;
  346.        
  347.         r = RecursiveLightPoint (cl.worldmodel->nodes, p, end);
  348.        
  349.         if (r == -1)
  350.                 r = 0;
  351.  
  352.         return r;
  353. }
  354.  
  355.