bmodel rotation physics now work
[divverent/darkplaces.git] / r_light.c
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 cvar_t r_lightmodels = {"r_lightmodels", "1"};
25
26 void r_light_start()
27 {
28 }
29
30 void r_light_shutdown()
31 {
32 }
33
34 void R_Light_Init()
35 {
36         Cvar_RegisterVariable(&r_lightmodels);
37         R_RegisterModule("R_Light", r_light_start, r_light_shutdown);
38 }
39
40 int     r_dlightframecount;
41
42 /*
43 ==================
44 R_AnimateLight
45 ==================
46 */
47 void R_AnimateLight (void)
48 {
49         int                     i,j,k;
50         
51 //
52 // light animations
53 // 'm' is normal light, 'a' is no light, 'z' is double bright
54         i = (int)(cl.time*10);
55         for (j=0 ; j<MAX_LIGHTSTYLES ; j++)
56         {
57                 if (!cl_lightstyle[j].length)
58                 {
59                         d_lightstylevalue[j] = 256;
60                         continue;
61                 }
62                 k = i % cl_lightstyle[j].length;
63                 k = cl_lightstyle[j].map[k] - 'a';
64                 k = k*22;
65                 d_lightstylevalue[j] = k;
66         }       
67 }
68
69 /*
70 =============================================================================
71
72 DYNAMIC LIGHTS
73
74 =============================================================================
75 */
76
77 /*
78 =============
79 R_MarkLights
80 =============
81 */
82 void R_OldMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex, mnode_t *node)
83 {
84         float           dist;
85         msurface_t      *surf;
86         int                     i;
87
88 loc0:
89         if (node->contents < 0)
90                 return;
91
92         dist = PlaneDiff(lightorigin, node->plane);
93         
94         if (dist > light->radius)
95         {
96                 if (node->children[0]->contents >= 0) // LordHavoc: save some time by not pushing another stack frame
97                 {
98                         node = node->children[0];
99                         goto loc0;
100                 }
101                 return;
102         }
103         if (dist < -light->radius)
104         {
105                 if (node->children[1]->contents >= 0) // LordHavoc: save some time by not pushing another stack frame
106                 {
107                         node = node->children[1];
108                         goto loc0;
109                 }
110                 return;
111         }
112
113         if (node->dlightframe != r_dlightframecount) // not dynamic until now
114         {
115                 node->dlightbits[0] = node->dlightbits[1] = node->dlightbits[2] = node->dlightbits[3] = node->dlightbits[4] = node->dlightbits[5] = node->dlightbits[6] = node->dlightbits[7] = 0;
116                 node->dlightframe = r_dlightframecount;
117         }
118         node->dlightbits[bitindex] |= bit;
119
120 // mark the polygons
121         surf = cl.worldmodel->surfaces + node->firstsurface;
122         for (i=0 ; i<node->numsurfaces ; i++, surf++)
123         {
124                 if (((surf->flags & SURF_PLANEBACK) == 0) == ((PlaneDist(lightorigin, surf->plane)) >= surf->plane->dist))
125                 {
126                         if (surf->dlightframe != r_dlightframecount) // not dynamic until now
127                         {
128                                 surf->dlightbits[0] = surf->dlightbits[1] = surf->dlightbits[2] = surf->dlightbits[3] = surf->dlightbits[4] = surf->dlightbits[5] = surf->dlightbits[6] = surf->dlightbits[7] = 0;
129                                 surf->dlightframe = r_dlightframecount;
130                         }
131                         surf->dlightbits[bitindex] |= bit;
132                 }
133         }
134
135         if (node->children[0]->contents >= 0)
136         {
137                 if (node->children[1]->contents >= 0)
138                 {
139                         R_OldMarkLights (lightorigin, light, bit, bitindex, node->children[0]);
140                         node = node->children[1];
141                         goto loc0;
142                 }
143                 else
144                 {
145                         node = node->children[0];
146                         goto loc0;
147                 }
148         }
149         else if (node->children[1]->contents >= 0)
150         {
151                 node = node->children[1];
152                 goto loc0;
153         }
154 }
155
156 void R_NoVisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex, model_t *model)
157 {
158         R_OldMarkLights(lightorigin, light, bit, bitindex, model->nodes + model->hulls[0].firstclipnode);
159 }
160
161 int lightframe = 0;
162 void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex, model_t *model)
163 {
164         mleaf_t *pvsleaf = Mod_PointInLeaf (lightorigin, model);
165
166         if (!pvsleaf->compressed_vis)
167         {       // no vis info, so make all visible
168                 R_OldMarkLights(lightorigin, light, bit, bitindex, model->nodes + model->hulls[0].firstclipnode);
169                 return;
170         }
171         else
172         {
173                 int             i, k, l, m, c;
174                 msurface_t *surf, **mark;
175                 mleaf_t *leaf;
176                 byte    *in = pvsleaf->compressed_vis;
177                 int             row = (model->numleafs+7)>>3;
178                 float   low[3], high[3], radius;
179
180                 radius = light->radius * 4.0f;
181                 low[0] = lightorigin[0] - radius;low[1] = lightorigin[1] - radius;low[2] = lightorigin[2] - radius;
182                 high[0] = lightorigin[0] + radius;high[1] = lightorigin[1] + radius;high[2] = lightorigin[2] + radius;
183
184                 lightframe++;
185                 k = 0;
186                 while (k < row)
187                 {
188                         c = *in++;
189                         if (c)
190                         {
191                                 l = model->numleafs - (k << 3);
192                                 if (l > 8)
193                                         l = 8;
194                                 for (i=0 ; i<l ; i++)
195                                 {
196                                         if (c & (1<<i))
197                                         {
198                                                 leaf = &model->leafs[(k << 3)+i+1];
199                                                 leaf->lightframe = lightframe;
200                                                 if (leaf->visframe != r_visframecount)
201                                                         continue;
202                                                 if (leaf->contents == CONTENTS_SOLID)
203                                                         continue;
204                                                 // if out of the light radius, skip
205                                                 /*
206                                                 if (leaf->minmaxs[0] > high[0] || leaf->minmaxs[3] < low[0]
207                                                  || leaf->minmaxs[1] > high[1] || leaf->minmaxs[4] < low[1]
208                                                  || leaf->minmaxs[2] > high[2] || leaf->minmaxs[5] < low[2])
209                                                         continue;
210                                                 */
211                                                 if (leaf->dlightframe != r_dlightframecount) // not dynamic until now
212                                                 {
213                                                         leaf->dlightbits[0] = leaf->dlightbits[1] = leaf->dlightbits[2] = leaf->dlightbits[3] = leaf->dlightbits[4] = leaf->dlightbits[5] = leaf->dlightbits[6] = leaf->dlightbits[7] = 0;
214                                                         leaf->dlightframe = r_dlightframecount;
215                                                 }
216                                                 leaf->dlightbits[bitindex] |= bit;
217                                                 if ((m = leaf->nummarksurfaces))
218                                                 {
219                                                         mark = leaf->firstmarksurface;
220                                                         do
221                                                         {
222                                                                 surf = *mark++;
223                                                                 if (surf->visframe != r_framecount || surf->lightframe == lightframe)
224                                                                         continue;
225                                                                 surf->lightframe = lightframe;
226                                                                 if (((surf->flags & SURF_PLANEBACK) == 0) == ((PlaneDist(lightorigin, surf->plane)) >= surf->plane->dist))
227                                                                 {
228                                                                         if (surf->dlightframe != r_dlightframecount) // not dynamic until now
229                                                                         {
230                                                                                 surf->dlightbits[0] = surf->dlightbits[1] = surf->dlightbits[2] = surf->dlightbits[3] = surf->dlightbits[4] = surf->dlightbits[5] = surf->dlightbits[6] = surf->dlightbits[7] = 0;
231                                                                                 surf->dlightframe = r_dlightframecount;
232                                                                         }
233                                                                         surf->dlightbits[bitindex] |= bit;
234                                                                 }
235                                                         }
236                                                         while (--m);
237                                                 }
238                                         }
239                                 }
240                                 k++;
241                                 continue;
242                         }
243                 
244                         k += *in++;
245                 }
246         }
247 }
248
249
250 /*
251 =============
252 R_PushDlights
253 =============
254 */
255 void R_PushDlights (void)
256 {
257         int             i;
258         dlight_t        *l;
259
260         r_dlightframecount = r_framecount + 1;  // because the count hasn't advanced yet for this frame
261
262         if (!r_dynamic.value)
263                 return;
264
265         l = cl_dlights;
266
267         for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
268         {
269                 if (l->die < cl.time || !l->radius)
270                         continue;
271 //              R_MarkLights (l->origin, l, 1<<(i&31), i >> 5, cl.worldmodel->nodes );
272                 R_VisMarkLights (l->origin, l, 1<<(i&31), i >> 5, cl.worldmodel);
273         }
274 }
275
276
277 /*
278 =============================================================================
279
280 LIGHT SAMPLING
281
282 =============================================================================
283 */
284
285 mplane_t                *lightplane;
286 vec3_t                  lightspot;
287
288 extern cvar_t r_ambient;
289
290 /*
291 int RecursiveLightPoint (vec3_t color, mnode_t *node, vec3_t start, vec3_t end)
292 {
293         float           front, back, frac;
294         vec3_t          mid;
295
296 loc0:
297         if (node->contents < 0)
298                 return false;           // didn't hit anything
299         
300 // calculate mid point
301         front = PlaneDiff (start, node->plane);
302         back = PlaneDiff (end, node->plane);
303
304         // LordHavoc: optimized recursion
305         if ((back < 0) == (front < 0))
306 //              return RecursiveLightPoint (color, node->children[front < 0], start, end);
307         {
308                 node = node->children[front < 0];
309                 goto loc0;
310         }
311         
312         frac = front / (front-back);
313         mid[0] = start[0] + (end[0] - start[0])*frac;
314         mid[1] = start[1] + (end[1] - start[1])*frac;
315         mid[2] = start[2] + (end[2] - start[2])*frac;
316         
317 // go down front side
318         if (RecursiveLightPoint (color, node->children[front < 0], start, mid))
319                 return true;    // hit something
320         else
321         {
322                 int i, ds, dt;
323                 msurface_t *surf;
324         // check for impact on this node
325                 VectorCopy (mid, lightspot);
326                 lightplane = node->plane;
327
328                 surf = cl.worldmodel->surfaces + node->firstsurface;
329                 for (i = 0;i < node->numsurfaces;i++, surf++)
330                 {
331                         if (surf->flags & SURF_DRAWTILED)
332                                 continue;       // no lightmaps
333
334                         ds = (int) ((float) DotProduct (mid, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]);
335                         dt = (int) ((float) DotProduct (mid, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]);
336
337                         if (ds < surf->texturemins[0] || dt < surf->texturemins[1])
338                                 continue;
339                         
340                         ds -= surf->texturemins[0];
341                         dt -= surf->texturemins[1];
342                         
343                         if (ds > surf->extents[0] || dt > surf->extents[1])
344                                 continue;
345
346                         if (surf->samples)
347                         {
348                                 byte *lightmap;
349                                 int maps, line3, dsfrac = ds & 15, dtfrac = dt & 15, r00 = 0, g00 = 0, b00 = 0, r01 = 0, g01 = 0, b01 = 0, r10 = 0, g10 = 0, b10 = 0, r11 = 0, g11 = 0, b11 = 0;
350                                 float scale;
351                                 line3 = ((surf->extents[0]>>4)+1)*3;
352
353                                 lightmap = surf->samples + ((dt>>4) * ((surf->extents[0]>>4)+1) + (ds>>4))*3; // LordHavoc: *3 for color
354
355                                 for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++)
356                                 {
357                                         scale = (float) d_lightstylevalue[surf->styles[maps]] * 1.0 / 256.0;
358                                         r00 += (float) lightmap[      0] * scale;g00 += (float) lightmap[      1] * scale;b00 += (float) lightmap[2] * scale;
359                                         r01 += (float) lightmap[      3] * scale;g01 += (float) lightmap[      4] * scale;b01 += (float) lightmap[5] * scale;
360                                         r10 += (float) lightmap[line3+0] * scale;g10 += (float) lightmap[line3+1] * scale;b10 += (float) lightmap[line3+2] * scale;
361                                         r11 += (float) lightmap[line3+3] * scale;g11 += (float) lightmap[line3+4] * scale;b11 += (float) lightmap[line3+5] * scale;
362                                         lightmap += ((surf->extents[0]>>4)+1) * ((surf->extents[1]>>4)+1)*3; // LordHavoc: *3 for colored lighting
363                                 }
364
365                                 color[0] += (float) ((int) ((((((((r11-r10) * dsfrac) >> 4) + r10)-((((r01-r00) * dsfrac) >> 4) + r00)) * dtfrac) >> 4) + ((((r01-r00) * dsfrac) >> 4) + r00)));
366                                 color[1] += (float) ((int) ((((((((g11-g10) * dsfrac) >> 4) + g10)-((((g01-g00) * dsfrac) >> 4) + g00)) * dtfrac) >> 4) + ((((g01-g00) * dsfrac) >> 4) + g00)));
367                                 color[2] += (float) ((int) ((((((((b11-b10) * dsfrac) >> 4) + b10)-((((b01-b00) * dsfrac) >> 4) + b00)) * dtfrac) >> 4) + ((((b01-b00) * dsfrac) >> 4) + b00)));
368                         }
369                         return true; // success
370                 }
371
372         // go down back side
373                 return RecursiveLightPoint (color, node->children[front >= 0], mid, end);
374         }
375 }
376
377 void R_LightPoint (vec3_t color, vec3_t p)
378 {
379         vec3_t          end;
380         
381         if (r_fullbright.value || !cl.worldmodel->lightdata)
382         {
383                 color[0] = color[1] = color[2] = 255;
384                 return;
385         }
386
387         end[0] = p[0];
388         end[1] = p[1];
389         end[2] = p[2] - 2048;
390
391         color[0] = color[1] = color[2] = r_ambient.value * 2.0f;
392         RecursiveLightPoint (color, cl.worldmodel->nodes, p, end);
393 }
394
395 void SV_LightPoint (vec3_t color, vec3_t p)
396 {
397         vec3_t          end;
398         
399         if (!sv.worldmodel->lightdata)
400         {
401                 color[0] = color[1] = color[2] = 255;
402                 return;
403         }
404         
405         end[0] = p[0];
406         end[1] = p[1];
407         end[2] = p[2] - 2048;
408
409         color[0] = color[1] = color[2] = 0;
410         RecursiveLightPoint (color, sv.worldmodel->nodes, p, end);
411 }
412 */
413
414 int RecursiveLightPoint (vec3_t color, mnode_t *node, float x, float y, float startz, float endz)
415 {
416         int             side, distz = endz - startz;
417         float   front, back;
418         float   mid;
419
420 loc0:
421         if (node->contents < 0)
422                 return false;           // didn't hit anything
423
424         switch (node->plane->type)
425         {
426         case PLANE_X:
427                 node = node->children[x < node->plane->dist];
428                 goto loc0;
429         case PLANE_Y:
430                 node = node->children[y < node->plane->dist];
431                 goto loc0;
432         case PLANE_Z:
433                 side = startz < node->plane->dist;
434                 if ((endz < node->plane->dist) == side)
435                 {
436                         node = node->children[side];
437                         goto loc0;
438                 }
439                 // found an intersection
440 //              mid = startz + (endz - startz) * (startz - node->plane->dist) / (startz - endz);
441 //              mid = startz + distz * (startz - node->plane->dist) / (-distz);
442 //              mid = startz + (-(startz - node->plane->dist));
443 //              mid = startz - (startz - node->plane->dist);
444 //              mid = startz + node->plane->dist - startz;
445                 mid = node->plane->dist;
446                 break;
447         default:
448                 back = front = x * node->plane->normal[0] + y * node->plane->normal[1];
449                 front += startz * node->plane->normal[2];
450                 back += endz * node->plane->normal[2];
451                 side = front < node->plane->dist;
452                 if ((back < node->plane->dist) == side)
453                 {
454                         node = node->children[side];
455                         goto loc0;
456                 }
457                 // found an intersection
458 //              mid = startz + (endz - startz) * ((front - node->plane->dist) / ((front - node->plane->dist) - (back - node->plane->dist)));
459 //              mid = startz + (endz - startz) * ((front - node->plane->dist) / (front - back));
460                 mid = startz + distz * (front - node->plane->dist) / (front - back);
461                 break;
462         }
463         
464         // go down front side
465         if (node->children[side]->contents >= 0 && RecursiveLightPoint (color, node->children[side], x, y, startz, mid))
466                 return true;    // hit something
467         else
468         {
469                 // check for impact on this node
470                 if (node->numsurfaces)
471                 {
472                         int i, ds, dt;
473                         msurface_t *surf;
474                         lightspot[0] = x;
475                         lightspot[1] = y;
476                         lightspot[2] = mid;
477                         lightplane = node->plane;
478
479                         surf = cl.worldmodel->surfaces + node->firstsurface;
480                         for (i = 0;i < node->numsurfaces;i++, surf++)
481                         {
482                                 if (surf->flags & SURF_DRAWTILED)
483                                         continue;       // no lightmaps
484
485                                 ds = (int) (x * surf->texinfo->vecs[0][0] + y * surf->texinfo->vecs[0][1] + mid * surf->texinfo->vecs[0][2] + surf->texinfo->vecs[0][3]);
486                                 dt = (int) (x * surf->texinfo->vecs[1][0] + y * surf->texinfo->vecs[1][1] + mid * surf->texinfo->vecs[1][2] + surf->texinfo->vecs[1][3]);
487
488                                 if (ds < surf->texturemins[0] || dt < surf->texturemins[1])
489                                         continue;
490                                 
491                                 ds -= surf->texturemins[0];
492                                 dt -= surf->texturemins[1];
493                                 
494                                 if (ds > surf->extents[0] || dt > surf->extents[1])
495                                         continue;
496
497                                 if (surf->samples)
498                                 {
499                                         byte *lightmap;
500                                         int maps, line3, size3, dsfrac = ds & 15, dtfrac = dt & 15, scale = 0, r00 = 0, g00 = 0, b00 = 0, r01 = 0, g01 = 0, b01 = 0, r10 = 0, g10 = 0, b10 = 0, r11 = 0, g11 = 0, b11 = 0;
501                                         line3 = ((surf->extents[0]>>4)+1)*3;
502                                         size3 = ((surf->extents[0]>>4)+1) * ((surf->extents[1]>>4)+1)*3; // LordHavoc: *3 for colored lighting
503
504                                         lightmap = surf->samples + ((dt>>4) * ((surf->extents[0]>>4)+1) + (ds>>4))*3; // LordHavoc: *3 for color
505
506                                         for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++)
507                                         {
508                                                 scale = d_lightstylevalue[surf->styles[maps]];
509                                                 r00 += lightmap[      0] * scale;g00 += lightmap[      1] * scale;b00 += lightmap[      2] * scale;
510                                                 r01 += lightmap[      3] * scale;g01 += lightmap[      4] * scale;b01 += lightmap[      5] * scale;
511                                                 r10 += lightmap[line3+0] * scale;g10 += lightmap[line3+1] * scale;b10 += lightmap[line3+2] * scale;
512                                                 r11 += lightmap[line3+3] * scale;g11 += lightmap[line3+4] * scale;b11 += lightmap[line3+5] * scale;
513                                                 lightmap += size3;
514                                         }
515
516                                         color[0] += (float) ((((((((r11-r10) * dsfrac) >> 4) + r10)-((((r01-r00) * dsfrac) >> 4) + r00)) * dtfrac) >> 4) + ((((r01-r00) * dsfrac) >> 4) + r00)) * (1.0f / 256.0f);
517                                         color[1] += (float) ((((((((g11-g10) * dsfrac) >> 4) + g10)-((((g01-g00) * dsfrac) >> 4) + g00)) * dtfrac) >> 4) + ((((g01-g00) * dsfrac) >> 4) + g00)) * (1.0f / 256.0f);
518                                         color[2] += (float) ((((((((b11-b10) * dsfrac) >> 4) + b10)-((((b01-b00) * dsfrac) >> 4) + b00)) * dtfrac) >> 4) + ((((b01-b00) * dsfrac) >> 4) + b00)) * (1.0f / 256.0f);
519                                 }
520                                 return true; // success
521                         }
522                 }
523
524                 // go down back side
525                 node = node->children[side ^ 1];
526                 startz = mid;
527                 distz = endz - startz;
528                 goto loc0;
529 //              return RecursiveLightPoint (color, node->children[side ^ 1], x, y, mid, endz);
530         }
531 }
532
533 void R_LightPoint (vec3_t color, vec3_t p)
534 {
535         if (r_fullbright.value || !cl.worldmodel->lightdata)
536         {
537                 color[0] = color[1] = color[2] = 255;
538                 return;
539         }
540         
541         color[0] = color[1] = color[2] = r_ambient.value * 2.0f;
542         RecursiveLightPoint (color, cl.worldmodel->nodes, p[0], p[1], p[2], p[2] - 65536);
543 }
544
545 // LordHavoc: added light checking to the server
546 void SV_LightPoint (vec3_t color, vec3_t p)
547 {
548         if (!sv.worldmodel->lightdata)
549         {
550                 color[0] = color[1] = color[2] = 255;
551                 return;
552         }
553         
554         color[0] = color[1] = color[2] = 0;
555         RecursiveLightPoint (color, sv.worldmodel->nodes, p[0], p[1], p[2], p[2] - 65536);
556 }
557
558 // LordHavoc: R_DynamicLightPoint - acumulates the dynamic lighting
559 void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits)
560 {
561         int             i, j, k;
562         vec3_t  dist;
563         float   brightness, r, f;
564
565         if (!r_dynamic.value || (!dlightbits[0] && !dlightbits[1] && !dlightbits[2] && !dlightbits[3] && !dlightbits[4] && !dlightbits[5] && !dlightbits[6] && !dlightbits[7]))
566                 return;
567
568         for (j = 0;j < (MAX_DLIGHTS >> 5);j++)
569         {
570                 if (dlightbits[j])
571                 {
572                         for (i=0 ; i<32 ; i++)
573                         {
574                                 if ((!((1 << (i&31)) & dlightbits[i>>5])) || cl_dlights[i].die < cl.time || !cl_dlights[i].radius)
575                                         continue;
576                                 k = (j<<5)+i;
577                                 VectorSubtract (org, cl_dlights[k].origin, dist);
578                                 f = DotProduct(dist, dist) + LIGHTOFFSET;
579                                 r = cl_dlights[k].radius*cl_dlights[k].radius*LIGHTSCALE;
580                                 if (f < r)
581                                 {
582                                         brightness = r * 16.0f / f;
583                                         color[0] += brightness * cl_dlights[k].color[0];
584                                         color[1] += brightness * cl_dlights[k].color[1];
585                                         color[2] += brightness * cl_dlights[k].color[2];
586                                 }
587                         }
588                 }
589         }
590 }
591
592 // same as above but no bitmask to check
593 void R_DynamicLightPointNoMask(vec3_t color, vec3_t org)
594 {
595         int             i;
596         vec3_t  dist;
597         float   brightness, r, f;
598
599         if (!r_dynamic.value)
600                 return;
601
602         for (i=0 ; i<MAX_DLIGHTS ; i++)
603         {
604                 if (cl_dlights[i].die < cl.time || !cl_dlights[i].radius)
605                         continue;
606                 VectorSubtract (org, cl_dlights[i].origin, dist);
607                 f = DotProduct(dist, dist) + LIGHTOFFSET;
608                 r = cl_dlights[i].radius*cl_dlights[i].radius*LIGHTSCALE;
609                 if (f < r)
610                 {
611                         brightness = r * 16.0f / f;
612                         if (cl_dlights[i].dark)
613                                 brightness = -brightness;
614                         color[0] += brightness * cl_dlights[i].color[0];
615                         color[1] += brightness * cl_dlights[i].color[1];
616                         color[2] += brightness * cl_dlights[i].color[2];
617                 }
618         }
619 }
620
621 void R_CompleteLightPoint (vec3_t color, vec3_t p)
622 {
623         R_LightPoint(color, p);
624         R_DynamicLightPointNoMask(color, p);
625 }
626
627 extern float *aliasvert;
628 extern float *aliasvertnorm;
629 extern byte *aliasvertcolor;
630 extern float modelalpha;
631 extern int modeldlightbits[8];
632 void R_LightModel(int numverts, vec3_t center, vec3_t basecolor)
633 {
634         // LordHavoc: warning: reliance on int being 4 bytes here (of course the d_8to24table relies on that too...)
635         int i, j, nearlights = 0, color;
636         vec3_t dist, mod;
637         float t, t1, t2, t3, *avn;
638         byte r,g,b,a, *avc;
639         struct
640         {
641                 vec3_t color;
642                 vec3_t origin;
643         } nearlight[MAX_DLIGHTS];
644         avc = aliasvertcolor;
645         avn = aliasvertnorm;
646         a = (byte) bound((int) 0, (int) (modelalpha * 255.0f), (int) 255);
647         if (currententity->effects & EF_FULLBRIGHT)
648         {
649                 if (lighthalf)
650                 {
651                         ((byte *)&color)[0] = (byte) ((float) (128.0f * currententity->colormod[0]));
652                         ((byte *)&color)[1] = (byte) ((float) (128.0f * currententity->colormod[1]));
653                         ((byte *)&color)[2] = (byte) ((float) (128.0f * currententity->colormod[2]));
654                 }
655                 else
656                 {
657                         ((byte *)&color)[0] = (byte) ((float) (255.0f * currententity->colormod[0]));
658                         ((byte *)&color)[1] = (byte) ((float) (255.0f * currententity->colormod[1]));
659                         ((byte *)&color)[2] = (byte) ((float) (255.0f * currententity->colormod[2]));
660                 }
661                 ((byte *)&color)[3] = a;
662                 for (i = 0;i < numverts;i++)
663                 {
664                         *((int *)avc) = color;
665                         avc += 4;
666                 }
667                 return;
668         }
669         if (lighthalf)
670         {
671                 mod[0] = currententity->colormod[0] * 0.5f;
672                 mod[1] = currententity->colormod[1] * 0.5f;
673                 mod[2] = currententity->colormod[2] * 0.5f;
674         }
675         else
676         {
677                 mod[0] = currententity->colormod[0];
678                 mod[1] = currententity->colormod[1];
679                 mod[2] = currententity->colormod[2];
680         }
681         basecolor[0] *= mod[0];
682         basecolor[1] *= mod[1];
683         basecolor[2] *= mod[2];
684         if (r_lightmodels.value)
685         {
686                 for (i = 0;i < MAX_DLIGHTS;i++)
687                 {
688                         if (!modeldlightbits[i >> 5])
689                         {
690                                 i |= 31;
691                                 continue;
692                         }
693                         if (!(modeldlightbits[i >> 5] & (1 << (i & 31))))
694                                 continue;
695                         VectorSubtract (center, cl_dlights[i].origin, dist);
696                         t1 = cl_dlights[i].radius*cl_dlights[i].radius*LIGHTSCALE;
697                         t2 = DotProduct(dist,dist) + LIGHTOFFSET;
698                         if (t2 < t1)
699                         {
700                                 VectorCopy(cl_dlights[i].origin, nearlight[nearlights].origin);
701                                 nearlight[nearlights].color[0] = cl_dlights[i].color[0] * cl_dlights[i].radius * cl_dlights[i].radius * mod[0];
702                                 nearlight[nearlights].color[1] = cl_dlights[i].color[1] * cl_dlights[i].radius * cl_dlights[i].radius * mod[1];
703                                 nearlight[nearlights].color[2] = cl_dlights[i].color[2] * cl_dlights[i].radius * cl_dlights[i].radius * mod[2];
704                                 t1 = (128.0f / LIGHTSCALE) / t2;
705                                 basecolor[0] += nearlight[nearlights].color[0] * t1;
706                                 basecolor[1] += nearlight[nearlights].color[1] * t1;
707                                 basecolor[2] += nearlight[nearlights].color[2] * t1;
708                                 nearlights++;
709                         }
710                 }
711         }
712         else
713         {
714                 for (i = 0;i < MAX_DLIGHTS;i++)
715                 {
716                         if (!modeldlightbits[i >> 5])
717                         {
718                                 i |= 31;
719                                 continue;
720                         }
721                         if (!(modeldlightbits[i >> 5] & (1 << (i & 31))))
722                                 continue;
723                         VectorSubtract (center, cl_dlights[i].origin, dist);
724                         t1 = cl_dlights[i].radius*cl_dlights[i].radius*LIGHTSCALE;
725                         t2 = DotProduct(dist,dist) + LIGHTOFFSET;
726                         if (t2 < t1)
727                         {
728                                 dist[0] = cl_dlights[i].color[0] * cl_dlights[i].radius * cl_dlights[i].radius * mod[0];
729                                 dist[1] = cl_dlights[i].color[1] * cl_dlights[i].radius * cl_dlights[i].radius * mod[1];
730                                 dist[2] = cl_dlights[i].color[2] * cl_dlights[i].radius * cl_dlights[i].radius * mod[2];
731                                 t1 = (192.0f / LIGHTSCALE) / t2;
732                                 basecolor[0] += dist[0] * t1;
733                                 basecolor[1] += dist[1] * t1;
734                                 basecolor[2] += dist[2] * t1;
735                         }
736                 }
737         }
738         t1 = bound(0, basecolor[0], 255);r = (byte) t1;
739         t1 = bound(0, basecolor[1], 255);g = (byte) t1;
740         t1 = bound(0, basecolor[2], 255);b = (byte) t1;
741         ((byte *)&color)[0] = r;
742         ((byte *)&color)[1] = g;
743         ((byte *)&color)[2] = b;
744         ((byte *)&color)[3] = a;
745         if (nearlights)
746         {
747                 int temp;
748                 vec3_t v;
749                 float *av;
750                 av = aliasvert;
751                 if (nearlights == 1)
752                 {
753                         for (i = 0;i < numverts;i++)
754                         {
755                                 VectorSubtract(nearlight[0].origin, av, v);
756                                 t = DotProduct(avn,v);
757                                 if (t > 0)
758                                 {
759                                         t /= DotProduct(v,v);
760                                         temp = (int) ((float) (basecolor[0] + nearlight[0].color[0] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;avc[0] = temp;
761                                         temp = (int) ((float) (basecolor[1] + nearlight[0].color[1] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;avc[1] = temp;
762                                         temp = (int) ((float) (basecolor[2] + nearlight[0].color[2] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;avc[2] = temp;
763                                         avc[3] = a;
764                                 }
765                                 else
766                                         *((int *)avc) = color;
767                                 avc += 4;
768                                 av+=3;
769                                 avn+=3;
770                         }
771                 }
772                 else
773                 {
774                         int i1, i2, i3, k;
775                         for (i = 0;i < numverts;i++)
776                         {
777                                 t1 = basecolor[0];
778                                 t2 = basecolor[1];
779                                 t3 = basecolor[2];
780                                 k = false;
781                                 for (j = 0;j < nearlights;j++)
782                                 {
783                                         VectorSubtract(nearlight[j].origin, av, v);
784                                         t = DotProduct(avn,v);
785                                         if (t > 0)
786                                         {
787                                                 t /= DotProduct(v,v);
788                                                 t1 += nearlight[j].color[0] * t;
789                                                 t2 += nearlight[j].color[1] * t;
790                                                 t3 += nearlight[j].color[2] * t;
791                                                 k = true;
792                                         }
793                                 }
794                                 if (k) // dodge the costly float -> int conversions
795                                 {
796                                         i1 = t1;if (i1 < 0) i1 = 0;else if (i1 > 255) i1 = 255;avc[0] = i1;
797                                         i2 = t2;if (i2 < 0) i2 = 0;else if (i2 > 255) i2 = 255;avc[1] = i2;
798                                         i3 = t3;if (i3 < 0) i3 = 0;else if (i3 > 255) i3 = 255;avc[2] = i3;
799                                         avc[3] = a;
800                                 }
801                                 else
802                                         *((int *)avc) = color;
803                                 avc += 4;
804                         }
805                 }
806         }
807         else
808         {
809                 for (i = 0;i < numverts;i++)
810                 {
811                         *((int *)avc) = color;
812                         avc += 4;
813                 }
814         }
815 }