yet another rewrite of the dlight engine, this time FAST
[xonotic/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 rlight_init()
27 {
28         Cvar_RegisterVariable(&r_lightmodels);
29 }
30
31 int     r_dlightframecount;
32
33 /*
34 ==================
35 R_AnimateLight
36 ==================
37 */
38 void R_AnimateLight (void)
39 {
40         int                     i,j,k;
41         
42 //
43 // light animations
44 // 'm' is normal light, 'a' is no light, 'z' is double bright
45         i = (int)(cl.time*10);
46         for (j=0 ; j<MAX_LIGHTSTYLES ; j++)
47         {
48                 if (!cl_lightstyle[j].length)
49                 {
50                         d_lightstylevalue[j] = 256;
51                         continue;
52                 }
53                 k = i % cl_lightstyle[j].length;
54                 k = cl_lightstyle[j].map[k] - 'a';
55                 k = k*22;
56                 d_lightstylevalue[j] = k;
57         }       
58 }
59
60 /*
61 =============================================================================
62
63 DYNAMIC LIGHTS
64
65 =============================================================================
66 */
67
68 /*
69 =============
70 R_MarkLights
71 =============
72 */
73 void R_OldMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex, mnode_t *node)
74 {
75         float           dist;
76         msurface_t      *surf;
77         int                     i;
78
79 loc0:
80         if (node->contents < 0)
81                 return;
82
83         dist = PlaneDiff(lightorigin, node->plane);
84         
85         if (dist > light->radius)
86         {
87                 if (node->children[0]->contents >= 0) // LordHavoc: save some time by not pushing another stack frame
88                 {
89                         node = node->children[0];
90                         goto loc0;
91                 }
92                 return;
93         }
94         if (dist < -light->radius)
95         {
96                 if (node->children[1]->contents >= 0) // LordHavoc: save some time by not pushing another stack frame
97                 {
98                         node = node->children[1];
99                         goto loc0;
100                 }
101                 return;
102         }
103
104         if (node->dlightframe != r_dlightframecount) // not dynamic until now
105         {
106                 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;
107                 node->dlightframe = r_dlightframecount;
108         }
109         node->dlightbits[bitindex] |= bit;
110
111 // mark the polygons
112         surf = cl.worldmodel->surfaces + node->firstsurface;
113         for (i=0 ; i<node->numsurfaces ; i++, surf++)
114         {
115                 if (surf->dlightframe != r_dlightframecount) // not dynamic until now
116                 {
117                         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;
118                         surf->dlightframe = r_dlightframecount;
119                 }
120                 surf->dlightbits[bitindex] |= bit;
121         }
122
123         if (node->children[0]->contents >= 0)
124         {
125                 if (node->children[1]->contents >= 0)
126                 {
127                         R_OldMarkLights (lightorigin, light, bit, bitindex, node->children[0]);
128                         node = node->children[1];
129                         goto loc0;
130                 }
131                 else
132                 {
133                         node = node->children[0];
134                         goto loc0;
135                 }
136         }
137         else if (node->children[1]->contents >= 0)
138         {
139                 node = node->children[1];
140                 goto loc0;
141         }
142 }
143
144 void R_NoVisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex, model_t *model)
145 {
146         R_OldMarkLights(lightorigin, light, bit, bitindex, model->nodes + model->hulls[0].firstclipnode);
147 }
148
149 void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex, model_t *model)
150 {
151         mleaf_t *pvsleaf = Mod_PointInLeaf (lightorigin, model);
152
153         if (!pvsleaf->compressed_vis)
154         {       // no vis info, so make all visible
155                 R_OldMarkLights(lightorigin, light, bit, bitindex, model->nodes + model->hulls[0].firstclipnode);
156                 return;
157         }
158         else
159         {
160                 int             i, k, l, m, c;
161                 msurface_t *surf, **mark;
162                 mleaf_t *leaf;
163                 static int lightframe = 0;
164                 byte    *in = pvsleaf->compressed_vis;
165                 int             row = (model->numleafs+7)>>3;
166                 float   low[3], high[3], radius;
167
168                 radius = light->radius * 4.0f;
169                 low[0] = lightorigin[0] - radius;low[1] = lightorigin[1] - radius;low[2] = lightorigin[2] - radius;
170                 high[0] = lightorigin[0] + radius;high[1] = lightorigin[1] + radius;high[2] = lightorigin[2] + radius;
171
172                 lightframe++;
173                 k = 0;
174                 while (k < row)
175                 {
176                         c = *in++;
177                         if (c)
178                         {
179                                 l = model->numleafs - (k << 3);
180                                 if (l > 8)
181                                         l = 8;
182                                 for (i=0 ; i<l ; i++)
183                                 {
184                                         if (c & (1<<i))
185                                         {
186                                                 leaf = &model->leafs[(k << 3)+i+1];
187                                                 leaf->lightframe = lightframe;
188                                                 if (leaf->visframe != r_visframecount)
189                                                         continue;
190                                                 if (leaf->contents == CONTENTS_SOLID)
191                                                         continue;
192                                                 // if out of the light radius, skip
193                                                 if (leaf->minmaxs[0] > high[0] || leaf->minmaxs[3] < low[0]
194                                                  || leaf->minmaxs[1] > high[1] || leaf->minmaxs[4] < low[1]
195                                                  || leaf->minmaxs[2] > high[2] || leaf->minmaxs[5] < low[2])
196                                                         continue;
197                                                 if (leaf->dlightframe != r_dlightframecount) // not dynamic until now
198                                                 {
199                                                         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;
200                                                         leaf->dlightframe = r_dlightframecount;
201                                                 }
202                                                 leaf->dlightbits[bitindex] |= bit;
203                                                 if ((m = leaf->nummarksurfaces))
204                                                 {
205                                                         mark = leaf->firstmarksurface;
206                                                         do
207                                                         {
208                                                                 surf = *mark++;
209                                                                 if (surf->visframe != r_framecount || surf->lightframe == lightframe)
210                                                                         continue;
211                                                                 surf->lightframe = lightframe;
212                                                                 if (((surf->flags & SURF_PLANEBACK) == 0) == ((PlaneDiff(lightorigin, surf->plane)) >= 0))
213                                                                 {
214                                                                         if (surf->dlightframe != r_dlightframecount) // not dynamic until now
215                                                                         {
216                                                                                 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;
217                                                                                 surf->dlightframe = r_dlightframecount;
218                                                                         }
219                                                                         surf->dlightbits[bitindex] |= bit;
220                                                                 }
221                                                         }
222                                                         while (--m);
223                                                 }
224                                         }
225                                 }
226                                 k++;
227                                 continue;
228                         }
229                 
230                         k += *in++;
231                 }
232         }
233 }
234
235
236 /*
237 =============
238 R_PushDlights
239 =============
240 */
241 void R_PushDlights (void)
242 {
243         int             i;
244         dlight_t        *l;
245
246         r_dlightframecount = r_framecount + 1;  // because the count hasn't advanced yet for this frame
247
248         if (!r_dynamic.value)
249                 return;
250
251         l = cl_dlights;
252
253         for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
254         {
255                 if (l->die < cl.time || !l->radius)
256                         continue;
257 //              R_MarkLights (l->origin, l, 1<<(i&31), i >> 5, cl.worldmodel->nodes );
258                 R_VisMarkLights (l->origin, l, 1<<(i&31), i >> 5, cl.worldmodel);
259         }
260 }
261
262
263 /*
264 =============================================================================
265
266 LIGHT SAMPLING
267
268 =============================================================================
269 */
270
271 mplane_t                *lightplane;
272 vec3_t                  lightspot;
273
274 extern cvar_t r_ambient;
275
276 int RecursiveLightPoint (vec3_t color, mnode_t *node, vec3_t start, vec3_t end)
277 {
278         float           front, back, frac;
279         vec3_t          mid;
280
281 loc0:
282         if (node->contents < 0)
283                 return false;           // didn't hit anything
284         
285 // calculate mid point
286         front = PlaneDiff (start, node->plane);
287         back = PlaneDiff (end, node->plane);
288
289         // LordHavoc: optimized recursion
290         if ((back < 0) == (front < 0))
291 //              return RecursiveLightPoint (color, node->children[front < 0], start, end);
292         {
293                 node = node->children[front < 0];
294                 goto loc0;
295         }
296         
297         frac = front / (front-back);
298         mid[0] = start[0] + (end[0] - start[0])*frac;
299         mid[1] = start[1] + (end[1] - start[1])*frac;
300         mid[2] = start[2] + (end[2] - start[2])*frac;
301         
302 // go down front side
303         if (RecursiveLightPoint (color, node->children[front < 0], start, mid))
304                 return true;    // hit something
305         else
306         {
307                 int i, ds, dt;
308                 msurface_t *surf;
309         // check for impact on this node
310                 VectorCopy (mid, lightspot);
311                 lightplane = node->plane;
312
313                 surf = cl.worldmodel->surfaces + node->firstsurface;
314                 for (i = 0;i < node->numsurfaces;i++, surf++)
315                 {
316                         if (surf->flags & SURF_DRAWTILED)
317                                 continue;       // no lightmaps
318
319                         ds = (int) ((float) DotProduct (mid, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]);
320                         dt = (int) ((float) DotProduct (mid, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]);
321
322                         if (ds < surf->texturemins[0] || dt < surf->texturemins[1])
323                                 continue;
324                         
325                         ds -= surf->texturemins[0];
326                         dt -= surf->texturemins[1];
327                         
328                         if (ds > surf->extents[0] || dt > surf->extents[1])
329                                 continue;
330
331                         if (surf->samples)
332                         {
333                                 byte *lightmap;
334                                 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;
335                                 float scale;
336                                 line3 = ((surf->extents[0]>>4)+1)*3;
337
338                                 lightmap = surf->samples + ((dt>>4) * ((surf->extents[0]>>4)+1) + (ds>>4))*3; // LordHavoc: *3 for color
339
340                                 for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++)
341                                 {
342                                         scale = (float) d_lightstylevalue[surf->styles[maps]] * 1.0 / 256.0;
343                                         r00 += (float) lightmap[      0] * scale;g00 += (float) lightmap[      1] * scale;b00 += (float) lightmap[2] * scale;
344                                         r01 += (float) lightmap[      3] * scale;g01 += (float) lightmap[      4] * scale;b01 += (float) lightmap[5] * scale;
345                                         r10 += (float) lightmap[line3+0] * scale;g10 += (float) lightmap[line3+1] * scale;b10 += (float) lightmap[line3+2] * scale;
346                                         r11 += (float) lightmap[line3+3] * scale;g11 += (float) lightmap[line3+4] * scale;b11 += (float) lightmap[line3+5] * scale;
347                                         lightmap += ((surf->extents[0]>>4)+1) * ((surf->extents[1]>>4)+1)*3; // LordHavoc: *3 for colored lighting
348                                 }
349
350                                 color[0] += (float) ((int) ((((((((r11-r10) * dsfrac) >> 4) + r10)-((((r01-r00) * dsfrac) >> 4) + r00)) * dtfrac) >> 4) + ((((r01-r00) * dsfrac) >> 4) + r00)));
351                                 color[1] += (float) ((int) ((((((((g11-g10) * dsfrac) >> 4) + g10)-((((g01-g00) * dsfrac) >> 4) + g00)) * dtfrac) >> 4) + ((((g01-g00) * dsfrac) >> 4) + g00)));
352                                 color[2] += (float) ((int) ((((((((b11-b10) * dsfrac) >> 4) + b10)-((((b01-b00) * dsfrac) >> 4) + b00)) * dtfrac) >> 4) + ((((b01-b00) * dsfrac) >> 4) + b00)));
353                         }
354                         return true; // success
355                 }
356
357         // go down back side
358                 return RecursiveLightPoint (color, node->children[front >= 0], mid, end);
359         }
360 }
361
362 void R_LightPoint (vec3_t color, vec3_t p)
363 {
364         vec3_t          end;
365         
366         if (r_fullbright.value || !cl.worldmodel->lightdata)
367         {
368                 color[0] = color[1] = color[2] = 255;
369                 return;
370         }
371         
372         end[0] = p[0];
373         end[1] = p[1];
374         end[2] = p[2] - 2048;
375
376         color[0] = color[1] = color[2] = r_ambient.value * 2.0f;
377         RecursiveLightPoint (color, cl.worldmodel->nodes, p, end);
378 }
379
380 // LordHavoc: R_DynamicLightPoint - acumulates the dynamic lighting
381 void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits)
382 {
383         int             i, j, k;
384         vec3_t  dist;
385         float   brightness, r, f;
386
387         if (!r_dynamic.value || (!dlightbits[0] && !dlightbits[1] && !dlightbits[2] && !dlightbits[3] && !dlightbits[4] && !dlightbits[5] && !dlightbits[6] && !dlightbits[7]))
388                 return;
389
390         for (j = 0;j < (MAX_DLIGHTS >> 5);j++)
391         {
392                 if (dlightbits[j])
393                 {
394                         for (i=0 ; i<32 ; i++)
395                         {
396                                 if ((!((1 << (i&31)) & dlightbits[i>>5])) || cl_dlights[i].die < cl.time || !cl_dlights[i].radius)
397                                         continue;
398                                 k = (j<<5)+i;
399                                 VectorSubtract (org, cl_dlights[k].origin, dist);
400                                 f = DotProduct(dist, dist) + 65536.0f;
401                                 r = cl_dlights[k].radius*cl_dlights[k].radius*16.0f;
402                                 if (f < r)
403                                 {
404                                         brightness = r * 16.0f / f;
405                                         color[0] += brightness * cl_dlights[k].color[0];
406                                         color[1] += brightness * cl_dlights[k].color[1];
407                                         color[2] += brightness * cl_dlights[k].color[2];
408                                 }
409                         }
410                 }
411         }
412 }
413
414 // same as above but no bitmask to check
415 void R_DynamicLightPointNoMask(vec3_t color, vec3_t org)
416 {
417         int             i;
418         vec3_t  dist;
419         float   brightness, r, f;
420
421         if (!r_dynamic.value)
422                 return;
423
424         for (i=0 ; i<MAX_DLIGHTS ; i++)
425         {
426                 if (cl_dlights[i].die < cl.time || !cl_dlights[i].radius)
427                         continue;
428                 VectorSubtract (org, cl_dlights[i].origin, dist);
429                 f = DotProduct(dist, dist) + 65536.0f;
430                 r = cl_dlights[i].radius*cl_dlights[i].radius*16.0f;
431                 if (f < r)
432                 {
433                         brightness = r * 16.0f / f;
434                         if (cl_dlights[i].dark)
435                                 brightness = -brightness;
436                         color[0] += brightness * cl_dlights[i].color[0];
437                         color[1] += brightness * cl_dlights[i].color[1];
438                         color[2] += brightness * cl_dlights[i].color[2];
439                 }
440         }
441 }
442
443 void R_CompleteLightPoint (vec3_t color, vec3_t p)
444 {
445         R_LightPoint(color, p);
446         R_DynamicLightPointNoMask(color, p);
447 }
448
449 extern float *aliasvert;
450 extern float *aliasvertnorm;
451 extern byte *aliasvertcolor;
452 extern vec_t shadecolor[];
453 extern float modelalpha;
454 extern qboolean lighthalf;
455 extern int modeldlightbits[8];
456 void R_LightModel(int numverts, vec3_t center)
457 {
458         int i, j, nearlights = 0;
459         vec3_t dist;
460         float t, t1, t2, t3, *avn;
461         byte r,g,b,a, *avc;
462         struct
463         {
464                 vec3_t color;
465                 vec3_t origin;
466         } nearlight[MAX_DLIGHTS];
467         if (!lighthalf)
468         {
469                 shadecolor[0] *= 2.0f;
470                 shadecolor[1] *= 2.0f;
471                 shadecolor[2] *= 2.0f;
472         }
473         avc = aliasvertcolor;
474         avn = aliasvertnorm;
475         a = (byte) bound((int) 0, (int) (modelalpha * 255.0f), (int) 255);
476         if (currententity->effects & EF_FULLBRIGHT)
477         {
478                 if (lighthalf)
479                 {
480                         r = (byte) ((float) (128.0f * currententity->colormod[0]));
481                         g = (byte) ((float) (128.0f * currententity->colormod[1]));
482                         b = (byte) ((float) (128.0f * currententity->colormod[2]));
483                 }
484                 else
485                 {
486                         r = (byte) ((float) (255.0f * currententity->colormod[0]));
487                         g = (byte) ((float) (255.0f * currententity->colormod[1]));
488                         b = (byte) ((float) (255.0f * currententity->colormod[2]));
489                 }
490                 for (i = 0;i < numverts;i++)
491                 {
492                         *avc++ = r;
493                         *avc++ = g;
494                         *avc++ = b;
495                         *avc++ = a;
496                 }
497                 return;
498         }
499         if (r_lightmodels.value)
500         {
501                 for (i = 0;i < MAX_DLIGHTS;i++)
502                 {
503                         if (!modeldlightbits[i >> 5])
504                         {
505                                 i |= 31;
506                                 continue;
507                         }
508                         if (!(modeldlightbits[i >> 5] & (1 << (i & 31))))
509                                 continue;
510 //                      if (cl_dlights[i].die < cl.time || !cl_dlights[i].radius)
511 //                              continue;
512                         VectorSubtract (center, cl_dlights[i].origin, dist);
513                         t1 = cl_dlights[i].radius*cl_dlights[i].radius*16.0f;
514                         t2 = DotProduct(dist,dist) + 65536.0f;
515                         if (t2 < t1)
516                         {
517                                 VectorCopy(cl_dlights[i].origin, nearlight[nearlights].origin);
518                                 nearlight[nearlights].color[0] = cl_dlights[i].color[0] * cl_dlights[i].radius * cl_dlights[i].radius * 0.5f;
519                                 nearlight[nearlights].color[1] = cl_dlights[i].color[1] * cl_dlights[i].radius * cl_dlights[i].radius * 0.5f;
520                                 nearlight[nearlights].color[2] = cl_dlights[i].color[2] * cl_dlights[i].radius * cl_dlights[i].radius * 0.5f;
521                                 if (lighthalf)
522                                 {
523                                         nearlight[nearlights].color[0] *= 0.5f;
524                                         nearlight[nearlights].color[1] *= 0.5f;
525                                         nearlight[nearlights].color[2] *= 0.5f;
526                                 }
527                                 t1 = 0.5f / t2;
528                                 shadecolor[0] += nearlight[nearlights].color[0] * t1;
529                                 shadecolor[1] += nearlight[nearlights].color[1] * t1;
530                                 shadecolor[2] += nearlight[nearlights].color[2] * t1;
531                                 nearlight[nearlights].color[0] *= currententity->colormod[0];
532                                 nearlight[nearlights].color[1] *= currententity->colormod[1];
533                                 nearlight[nearlights].color[2] *= currententity->colormod[2];
534                                 nearlights++;
535                         }
536                 }
537         }
538         else
539         {
540                 for (i = 0;i < MAX_DLIGHTS;i++)
541                 {
542                         if (!modeldlightbits[i >> 5])
543                         {
544                                 i |= 31;
545                                 continue;
546                         }
547                         if (!(modeldlightbits[i >> 5] & (1 << (i & 31))))
548                                 continue;
549 //                      if (cl_dlights[i].die < cl.time || !cl_dlights[i].radius)
550 //                              continue;
551                         VectorSubtract (center, cl_dlights[i].origin, dist);
552                         t2 = DotProduct(dist,dist) + 65536.0f;
553                         t1 = cl_dlights[i].radius*cl_dlights[i].radius*16.0f;
554                         if (t2 < t1)
555                         {
556                                 dist[0] = cl_dlights[i].color[0] * cl_dlights[i].radius * cl_dlights[i].radius * 0.5f;
557                                 dist[1] = cl_dlights[i].color[1] * cl_dlights[i].radius * cl_dlights[i].radius * 0.5f;
558                                 dist[2] = cl_dlights[i].color[2] * cl_dlights[i].radius * cl_dlights[i].radius * 0.5f;
559                                 if (lighthalf)
560                                 {
561                                         dist[0] *= 0.5f;
562                                         dist[1] *= 0.5f;
563                                         dist[2] *= 0.5f;
564                                 }
565                                 t1 = 0.75f / t2;
566                                 shadecolor[0] += dist[0] * t1;
567                                 shadecolor[1] += dist[1] * t1;
568                                 shadecolor[2] += dist[2] * t1;
569                         }
570                 }
571         }
572         shadecolor[0] *= currententity->colormod[0];
573         shadecolor[1] *= currententity->colormod[1];
574         shadecolor[2] *= currententity->colormod[2];
575         t1 = bound(0, shadecolor[0], 255);r = (byte) t1;
576         t1 = bound(0, shadecolor[1], 255);g = (byte) t1;
577         t1 = bound(0, shadecolor[2], 255);b = (byte) t1;
578         if (nearlights)
579         {
580                 int temp;
581                 vec3_t v;
582                 float *av;
583                 av = aliasvert;
584                 if (nearlights == 1)
585                 {
586                         for (i = 0;i < numverts;i++)
587                         {
588                                 VectorSubtract(nearlight[0].origin, av, v);
589                                 t = DotProduct(avn,v);
590                                 if (t > 0)
591                                 {
592                                         t /= DotProduct(v,v);
593                                         temp = (int) ((float) (shadecolor[0] + nearlight[0].color[0] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;*avc++ = temp;
594                                         temp = (int) ((float) (shadecolor[1] + nearlight[0].color[1] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;*avc++ = temp;
595                                         temp = (int) ((float) (shadecolor[2] + nearlight[0].color[2] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;*avc++ = temp;
596                                 }
597                                 else
598                                 {
599                                         *avc++ = r;
600                                         *avc++ = g;
601                                         *avc++ = b;
602                                 }
603                                 *avc++ = a;
604                                 av+=3;
605                                 avn+=3;
606                         }
607                 }
608                 else
609                 {
610                         int i1, i2, i3;
611                         for (i = 0;i < numverts;i++)
612                         {
613                                 t1 = shadecolor[0];
614                                 t2 = shadecolor[1];
615                                 t3 = shadecolor[2];
616                                 for (j = 0;j < nearlights;j++)
617                                 {
618                                         VectorSubtract(nearlight[j].origin, av, v);
619                                         t = DotProduct(avn,v);
620                                         if (t > 0)
621                                         {
622                                                 t /= DotProduct(v,v);
623                                                 t1 += nearlight[j].color[0] * t;
624                                                 t2 += nearlight[j].color[1] * t;
625                                                 t3 += nearlight[j].color[2] * t;
626                                         }
627                                 }
628                                 i1 = t1;if (i1 < 0) i1 = 0;else if (i1 > 255) i1 = 255;
629                                 i2 = t2;if (i2 < 0) i2 = 0;else if (i2 > 255) i2 = 255;
630                                 i3 = t3;if (i3 < 0) i3 = 0;else if (i3 > 255) i3 = 255;
631                                 *avc++ = i1;
632                                 *avc++ = i2;
633                                 *avc++ = i3;
634                                 *avc++ = a;
635                         }
636                 }
637         }
638         else
639         {
640                 for (i = 0;i < numverts;i++)
641                 {
642                         *avc++ = r;
643                         *avc++ = g;
644                         *avc++ = b;
645                         *avc++ = a;
646                 }
647         }
648 }