r_light.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // r_light.c
  16. #include "quakedef.h"
  17. #include "r_local.h"
  18. int r_dlightframecount;
  19. /*
  20. ==================
  21. R_AnimateLight
  22. ==================
  23. */
  24. void R_AnimateLight (void)
  25. {
  26. int i,j,k;
  27. //
  28. // light animations
  29. // 'm' is normal light, 'a' is no light, 'z' is double bright
  30. i = (int)(cl.time*10);
  31. for (j=0 ; j<MAX_LIGHTSTYLES ; j++)
  32. {
  33. if (!cl_lightstyle[j].length)
  34. {
  35. d_lightstylevalue[j] = 256;
  36. continue;
  37. }
  38. k = i % cl_lightstyle[j].length;
  39. k = cl_lightstyle[j].map[k] - 'a';
  40. k = k*22;
  41. d_lightstylevalue[j] = k;
  42. }
  43. }
  44. /*
  45. =============================================================================
  46. DYNAMIC LIGHTS
  47. =============================================================================
  48. */
  49. /*
  50. =============
  51. R_MarkLights
  52. =============
  53. */
  54. void R_MarkLights (dlight_t *light, int bit, mnode_t *node)
  55. {
  56. mplane_t *splitplane;
  57. float dist;
  58. msurface_t *surf;
  59. int i;
  60. if (node->contents < 0)
  61. return;
  62. splitplane = node->plane;
  63. dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
  64. if (dist > light->radius)
  65. {
  66. R_MarkLights (light, bit, node->children[0]);
  67. return;
  68. }
  69. if (dist < -light->radius)
  70. {
  71. R_MarkLights (light, bit, node->children[1]);
  72. return;
  73. }
  74. // mark the polygons
  75. surf = cl.worldmodel->surfaces + node->firstsurface;
  76. for (i=0 ; i<node->numsurfaces ; i++, surf++)
  77. {
  78. if (surf->dlightframe != r_dlightframecount)
  79. {
  80. surf->dlightbits = 0;
  81. surf->dlightframe = r_dlightframecount;
  82. }
  83. surf->dlightbits |= bit;
  84. }
  85. R_MarkLights (light, bit, node->children[0]);
  86. R_MarkLights (light, bit, node->children[1]);
  87. }
  88. /*
  89. =============
  90. R_PushDlights
  91. =============
  92. */
  93. void R_PushDlights (void)
  94. {
  95. int i;
  96. dlight_t *l;
  97. r_dlightframecount = r_framecount + 1; // because the count hasn't
  98. // advanced yet for this frame
  99. l = cl_dlights;
  100. for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
  101. {
  102. if (l->die < cl.time || !l->radius)
  103. continue;
  104. R_MarkLights ( l, 1<<i, cl.worldmodel->nodes );
  105. }
  106. }
  107. /*
  108. =============================================================================
  109. LIGHT SAMPLING
  110. =============================================================================
  111. */
  112. int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
  113. {
  114. int r;
  115. float front, back, frac;
  116. int side;
  117. mplane_t *plane;
  118. vec3_t mid;
  119. msurface_t *surf;
  120. int s, t, ds, dt;
  121. int i;
  122. mtexinfo_t *tex;
  123. byte *lightmap;
  124. unsigned scale;
  125. int maps;
  126. if (node->contents < 0)
  127. return -1; // didn't hit anything
  128. // calculate mid point
  129. // FIXME: optimize for axial
  130. plane = node->plane;
  131. front = DotProduct (start, plane->normal) - plane->dist;
  132. back = DotProduct (end, plane->normal) - plane->dist;
  133. side = front < 0;
  134. if ( (back < 0) == side)
  135. return RecursiveLightPoint (node->children[side], start, end);
  136. frac = front / (front-back);
  137. mid[0] = start[0] + (end[0] - start[0])*frac;
  138. mid[1] = start[1] + (end[1] - start[1])*frac;
  139. mid[2] = start[2] + (end[2] - start[2])*frac;
  140. // go down front side
  141. r = RecursiveLightPoint (node->children[side], start, mid);
  142. if (r >= 0)
  143. return r; // hit something
  144. if ( (back < 0) == side )
  145. return -1; // didn't hit anuthing
  146. // check for impact on this node
  147. surf = cl.worldmodel->surfaces + node->firstsurface;
  148. for (i=0 ; i<node->numsurfaces ; i++, surf++)
  149. {
  150. if (surf->flags & SURF_DRAWTILED)
  151. continue; // no lightmaps
  152. tex = surf->texinfo;
  153. s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3];
  154. t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];;
  155. if (s < surf->texturemins[0] ||
  156. t < surf->texturemins[1])
  157. continue;
  158. ds = s - surf->texturemins[0];
  159. dt = t - surf->texturemins[1];
  160. if ( ds > surf->extents[0] || dt > surf->extents[1] )
  161. continue;
  162. if (!surf->samples)
  163. return 0;
  164. ds >>= 4;
  165. dt >>= 4;
  166. lightmap = surf->samples;
  167. r = 0;
  168. if (lightmap)
  169. {
  170. lightmap += dt * ((surf->extents[0]>>4)+1) + ds;
  171. for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
  172. maps++)
  173. {
  174. scale = d_lightstylevalue[surf->styles[maps]];
  175. r += *lightmap * scale;
  176. lightmap += ((surf->extents[0]>>4)+1) *
  177. ((surf->extents[1]>>4)+1);
  178. }
  179. r >>= 8;
  180. }
  181. return r;
  182. }
  183. // go down back side
  184. return RecursiveLightPoint (node->children[!side], mid, end);
  185. }
  186. int R_LightPoint (vec3_t p)
  187. {
  188. vec3_t end;
  189. int r;
  190. if (!cl.worldmodel->lightdata)
  191. return 255;
  192. end[0] = p[0];
  193. end[1] = p[1];
  194. end[2] = p[2] - 2048;
  195. r = RecursiveLightPoint (cl.worldmodel->nodes, p, end);
  196. if (r == -1)
  197. r = 0;
  198. if (r < r_refdef.ambientlight)
  199. r = r_refdef.ambientlight;
  200. return r;
  201. }