]> icculus.org git repositories - divverent/darkplaces.git/blob - r_light.c
A minor removal of a few pieces of dead code. Nothing major. This is
[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 #include "cl_collision.h"
24
25 rdlight_t r_dlight[MAX_DLIGHTS];
26 int r_numdlights = 0;
27
28 cvar_t r_lightmodels = {CVAR_SAVE, "r_lightmodels", "1"};
29 cvar_t r_vismarklights = {0, "r_vismarklights", "1"};
30
31 static rtexture_t *lightcorona;
32 static rtexturepool_t *lighttexturepool;
33
34 void r_light_start(void)
35 {
36         float dx, dy;
37         int x, y, a;
38         qbyte pixels[32][32][4];
39         lighttexturepool = R_AllocTexturePool();
40         for (y = 0;y < 32;y++)
41         {
42                 dy = (y - 15.5f) * (1.0f / 16.0f);
43                 for (x = 0;x < 32;x++)
44                 {
45                         dx = (x - 15.5f) * (1.0f / 16.0f);
46                         a = ((1.0f / (dx * dx + dy * dy + 0.2f)) - (1.0f / (1.0f + 0.2))) * 64.0f / (1.0f / (1.0f + 0.2));
47                         a = bound(0, a, 255);
48                         pixels[y][x][0] = 255;
49                         pixels[y][x][1] = 255;
50                         pixels[y][x][2] = 255;
51                         pixels[y][x][3] = a;
52                 }
53         }
54         lightcorona = R_LoadTexture (lighttexturepool, "lightcorona", 32, 32, &pixels[0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_ALPHA);
55 }
56
57 void r_light_shutdown(void)
58 {
59         lighttexturepool = NULL;
60         lightcorona = NULL;
61 }
62
63 void r_light_newmap(void)
64 {
65 }
66
67 void R_Light_Init(void)
68 {
69         Cvar_RegisterVariable(&r_lightmodels);
70         Cvar_RegisterVariable(&r_vismarklights);
71         R_RegisterModule("R_Light", r_light_start, r_light_shutdown, r_light_newmap);
72 }
73
74 /*
75 ==================
76 R_AnimateLight
77 ==================
78 */
79 void R_AnimateLight (void)
80 {
81         int i, j, k;
82
83 //
84 // light animations
85 // 'm' is normal light, 'a' is no light, 'z' is double bright
86         i = (int)(cl.time * 10);
87         for (j = 0;j < MAX_LIGHTSTYLES;j++)
88         {
89                 if (!cl_lightstyle[j].length)
90                 {
91                         d_lightstylevalue[j] = 256;
92                         continue;
93                 }
94                 k = i % cl_lightstyle[j].length;
95                 k = cl_lightstyle[j].map[k] - 'a';
96                 k = k*22;
97                 d_lightstylevalue[j] = k;
98         }
99 }
100
101
102 void R_BuildLightList(void)
103 {
104         int                     i;
105         dlight_t        *cd;
106         rdlight_t       *rd;
107
108         r_numdlights = 0;
109         c_dlights = 0;
110
111         if (!r_dynamic.integer)
112                 return;
113
114         for (i = 0;i < MAX_DLIGHTS;i++)
115         {
116                 cd = cl_dlights + i;
117                 if (cd->radius <= 0)
118                         continue;
119                 rd = &r_dlight[r_numdlights++];
120                 VectorCopy(cd->origin, rd->origin);
121                 VectorScale(cd->color, cd->radius * 128.0f, rd->light);
122                 rd->cullradius = (1.0f / 128.0f) * sqrt(DotProduct(rd->light, rd->light));
123                 // clamp radius to avoid overflowing division table in lightmap code
124                 if (rd->cullradius > 2048.0f)
125                         rd->cullradius = 2048.0f;
126                 rd->cullradius2 = rd->cullradius * rd->cullradius;
127                 rd->lightsubtract = 1.0f / rd->cullradius2;
128                 rd->ent = cd->ent;
129                 r_numdlights++;
130                 c_dlights++; // count every dlight in use
131         }
132 }
133
134 static int coronapolyindex[6] = {0, 1, 2, 0, 2, 3};
135
136 void R_DrawCoronas(void)
137 {
138         int i;
139         rmeshinfo_t m;
140         float tvxyz[4][4], tvst[4][2], scale, viewdist, diff[3], dist;
141         rdlight_t *rd;
142         memset(&m, 0, sizeof(m));
143         m.transparent = false;
144         m.blendfunc1 = GL_SRC_ALPHA;
145         m.blendfunc2 = GL_ONE;
146         m.depthdisable = true; // magic
147         m.numtriangles = 2;
148         m.numverts = 4;
149         m.index = coronapolyindex;
150         m.vertex = &tvxyz[0][0];
151         m.vertexstep = sizeof(float[4]);
152         m.tex[0] = R_GetTexture(lightcorona);
153         m.texcoords[0] = &tvst[0][0];
154         m.texcoordstep[0] = sizeof(float[2]);
155         tvst[0][0] = 0;
156         tvst[0][1] = 0;
157         tvst[1][0] = 0;
158         tvst[1][1] = 1;
159         tvst[2][0] = 1;
160         tvst[2][1] = 1;
161         tvst[3][0] = 1;
162         tvst[3][1] = 0;
163         viewdist = DotProduct(r_origin, vpn);
164         for (i = 0;i < r_numdlights;i++)
165         {
166                 rd = r_dlight + i;
167                 dist = (DotProduct(rd->origin, vpn) - viewdist);
168                 if (dist >= 24.0f)
169                 {
170                         // trace to a point just barely closer to the eye
171                         VectorSubtract(rd->origin, vpn, diff);
172                         if (CL_TraceLine(r_origin, diff, NULL, NULL, 0, true) == 1)
173                         {
174                                 scale = 1.0f / 262144.0f;
175                                 m.cr = rd->light[0] * scale;
176                                 m.cg = rd->light[1] * scale;
177                                 m.cb = rd->light[2] * scale;
178                                 m.ca = 1;
179                                 if (fogenabled)
180                                 {
181                                         VectorSubtract(rd->origin, r_origin, diff);
182                                         m.ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
183                                 }
184                                 scale = rd->cullradius * 0.25f;
185                                 tvxyz[0][0] = rd->origin[0] - vright[0] * scale - vup[0] * scale;
186                                 tvxyz[0][1] = rd->origin[1] - vright[1] * scale - vup[1] * scale;
187                                 tvxyz[0][2] = rd->origin[2] - vright[2] * scale - vup[2] * scale;
188                                 tvxyz[1][0] = rd->origin[0] - vright[0] * scale + vup[0] * scale;
189                                 tvxyz[1][1] = rd->origin[1] - vright[1] * scale + vup[1] * scale;
190                                 tvxyz[1][2] = rd->origin[2] - vright[2] * scale + vup[2] * scale;
191                                 tvxyz[2][0] = rd->origin[0] + vright[0] * scale + vup[0] * scale;
192                                 tvxyz[2][1] = rd->origin[1] + vright[1] * scale + vup[1] * scale;
193                                 tvxyz[2][2] = rd->origin[2] + vright[2] * scale + vup[2] * scale;
194                                 tvxyz[3][0] = rd->origin[0] + vright[0] * scale - vup[0] * scale;
195                                 tvxyz[3][1] = rd->origin[1] + vright[1] * scale - vup[1] * scale;
196                                 tvxyz[3][2] = rd->origin[2] + vright[2] * scale - vup[2] * scale;
197                                 R_Mesh_Draw(&m);
198                         }
199                 }
200         }
201 }
202
203 /*
204 =============================================================================
205
206 DYNAMIC LIGHTS
207
208 =============================================================================
209 */
210
211 /*
212 =============
213 R_MarkLights
214 =============
215 */
216 static void R_OldMarkLights (vec3_t lightorigin, rdlight_t *rd, int bit, int bitindex, mnode_t *node)
217 {
218         float           ndist, maxdist;
219         msurface_t      *surf;
220         mleaf_t         *leaf;
221         int                     i;
222
223         if (!r_dynamic.integer)
224                 return;
225
226         // for comparisons to minimum acceptable light
227         maxdist = rd->cullradius2;
228
229 loc0:
230         if (node->contents < 0)
231         {
232                 if (node->contents != CONTENTS_SOLID)
233                 {
234                         leaf = (mleaf_t *)node;
235                         if (leaf->dlightframe != r_framecount) // not dynamic until now
236                         {
237                                 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;
238                                 leaf->dlightframe = r_framecount;
239                         }
240                         leaf->dlightbits[bitindex] |= bit;
241                 }
242                 return;
243         }
244
245         ndist = PlaneDiff(lightorigin, node->plane);
246
247         if (ndist > rd->cullradius)
248         {
249                 node = node->children[0];
250                 goto loc0;
251         }
252         if (ndist < -rd->cullradius)
253         {
254                 node = node->children[1];
255                 goto loc0;
256         }
257
258 // mark the polygons
259         surf = currentrenderentity->model->surfaces + node->firstsurface;
260         for (i=0 ; i<node->numsurfaces ; i++, surf++)
261         {
262                 int d, impacts, impactt;
263                 float dist, dist2, impact[3];
264                 if (surf->visframe != r_framecount)
265                         continue;
266                 dist = ndist;
267                 if (surf->flags & SURF_PLANEBACK)
268                         dist = -dist;
269
270                 if (dist < -0.25f && !(surf->flags & SURF_LIGHTBOTHSIDES))
271                         continue;
272
273                 dist2 = dist * dist;
274                 if (dist2 >= maxdist)
275                         continue;
276
277                 impact[0] = rd->origin[0] - surf->plane->normal[0] * dist;
278                 impact[1] = rd->origin[1] - surf->plane->normal[1] * dist;
279                 impact[2] = rd->origin[2] - surf->plane->normal[2] * dist;
280
281                 impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
282
283                 d = bound(0, impacts, surf->extents[0] + 16) - impacts;
284                 dist2 += d * d;
285                 if (dist2 > maxdist)
286                         continue;
287
288                 impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
289
290                 d = bound(0, impactt, surf->extents[1] + 16) - impactt;
291                 dist2 += d * d;
292                 if (dist2 > maxdist)
293                         continue;
294
295                 if (surf->dlightframe != r_framecount) // not dynamic until now
296                 {
297                         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;
298                         surf->dlightframe = r_framecount;
299                 }
300                 surf->dlightbits[bitindex] |= bit;
301         }
302
303         if (node->children[0]->contents >= 0)
304         {
305                 if (node->children[1]->contents >= 0)
306                 {
307                         R_OldMarkLights (lightorigin, rd, bit, bitindex, node->children[0]);
308                         node = node->children[1];
309                         goto loc0;
310                 }
311                 else
312                 {
313                         node = node->children[0];
314                         goto loc0;
315                 }
316         }
317         else if (node->children[1]->contents >= 0)
318         {
319                 node = node->children[1];
320                 goto loc0;
321         }
322 }
323
324
325 static void R_VisMarkLights (rdlight_t *rd, int bit, int bitindex)
326 {
327         static int lightframe = 0;
328         mleaf_t *pvsleaf;
329         vec3_t lightorigin;
330         model_t *model;
331         int             i, k, m, c, leafnum;
332         msurface_t *surf, **mark;
333         mleaf_t *leaf;
334         qbyte   *in;
335         int             row;
336         float   low[3], high[3], dist, maxdist;
337
338         if (!r_dynamic.integer)
339                 return;
340
341         model = currentrenderentity->model;
342         softwareuntransform(rd->origin, lightorigin);
343
344         if (!r_vismarklights.integer)
345         {
346                 R_OldMarkLights(lightorigin, rd, bit, bitindex, model->nodes + model->hulls[0].firstclipnode);
347                 return;
348         }
349
350         pvsleaf = Mod_PointInLeaf (lightorigin, model);
351         if (pvsleaf == NULL)
352         {
353                 Con_Printf("R_VisMarkLights: NULL leaf??\n");
354                 R_OldMarkLights(lightorigin, rd, bit, bitindex, model->nodes + model->hulls[0].firstclipnode);
355                 return;
356         }
357
358         in = pvsleaf->compressed_vis;
359         if (!in)
360         {
361                 // no vis info, so make all visible
362                 R_OldMarkLights(lightorigin, rd, bit, bitindex, model->nodes + model->hulls[0].firstclipnode);
363                 return;
364         }
365
366         lightframe++;
367
368         low[0] = lightorigin[0] - rd->cullradius;low[1] = lightorigin[1] - rd->cullradius;low[2] = lightorigin[2] - rd->cullradius;
369         high[0] = lightorigin[0] + rd->cullradius;high[1] = lightorigin[1] + rd->cullradius;high[2] = lightorigin[2] + rd->cullradius;
370
371         // for comparisons to minimum acceptable light
372         maxdist = rd->cullradius2;
373
374         row = (model->numleafs+7)>>3;
375
376         k = 0;
377         while (k < row)
378         {
379                 c = *in++;
380                 if (c)
381                 {
382                         for (i = 0;i < 8;i++)
383                         {
384                                 if (c & (1<<i))
385                                 {
386                                         // warning to the clumsy: numleafs is one less than it should be, it only counts leafs with vis bits (skips leaf 0)
387                                         leafnum = (k << 3)+i+1;
388                                         if (leafnum > model->numleafs)
389                                                 return;
390                                         leaf = &model->leafs[leafnum];
391                                         if (leaf->visframe != r_framecount
392                                          || leaf->contents == CONTENTS_SOLID
393                                          || leaf->mins[0] > high[0] || leaf->maxs[0] < low[0]
394                                          || leaf->mins[1] > high[1] || leaf->maxs[1] < low[1]
395                                          || leaf->mins[2] > high[2] || leaf->maxs[2] < low[2])
396                                                 continue;
397                                         if (leaf->dlightframe != r_framecount)
398                                         {
399                                                 // not dynamic until now
400                                                 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;
401                                                 leaf->dlightframe = r_framecount;
402                                         }
403                                         leaf->dlightbits[bitindex] |= bit;
404                                         if ((m = leaf->nummarksurfaces))
405                                         {
406                                                 mark = leaf->firstmarksurface;
407                                                 do
408                                                 {
409                                                         surf = *mark++;
410                                                         // if not visible in current frame, or already marked because it was in another leaf we passed, skip
411                                                         if (surf->lightframe == lightframe)
412                                                                 continue;
413                                                         surf->lightframe = lightframe;
414                                                         if (surf->visframe != r_framecount)
415                                                                 continue;
416                                                         dist = PlaneDiff(lightorigin, surf->plane);
417                                                         if (surf->flags & SURF_PLANEBACK)
418                                                                 dist = -dist;
419                                                         // LordHavoc: make sure it is infront of the surface and not too far away
420                                                         if (dist < rd->cullradius && (dist > -0.25f || ((surf->flags & SURF_LIGHTBOTHSIDES) && dist > -rd->cullradius)))
421                                                         {
422                                                                 int d;
423                                                                 int impacts, impactt;
424                                                                 float dist2, impact[3];
425
426                                                                 dist2 = dist * dist;
427
428                                                                 impact[0] = rd->origin[0] - surf->plane->normal[0] * dist;
429                                                                 impact[1] = rd->origin[1] - surf->plane->normal[1] * dist;
430                                                                 impact[2] = rd->origin[2] - surf->plane->normal[2] * dist;
431
432                                                                 impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
433                                                                 d = bound(0, impacts, surf->extents[0] + 16) - impacts;
434                                                                 dist2 += d * d;
435                                                                 if (dist2 > maxdist)
436                                                                         continue;
437
438                                                                 impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
439                                                                 d = bound(0, impactt, surf->extents[1] + 16) - impactt;
440                                                                 dist2 += d * d;
441                                                                 if (dist2 > maxdist)
442                                                                         continue;
443
444                                                                 if (surf->dlightframe != r_framecount) // not dynamic until now
445                                                                 {
446                                                                         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;
447                                                                         surf->dlightframe = r_framecount;
448                                                                 }
449                                                                 surf->dlightbits[bitindex] |= bit;
450                                                         }
451                                                 }
452                                                 while (--m);
453                                         }
454                                 }
455                         }
456                         k++;
457                         continue;
458                 }
459
460                 k += *in++;
461         }
462 }
463
464 void R_MarkLights(void)
465 {
466         int i;
467         for (i = 0;i < r_numdlights;i++)
468                 R_VisMarkLights (r_dlight + i, 1 << (i & 31), i >> 5);
469 }
470
471 /*
472 =============================================================================
473
474 LIGHT SAMPLING
475
476 =============================================================================
477 */
478
479 static int RecursiveLightPoint (vec3_t color, mnode_t *node, float x, float y, float startz, float endz)
480 {
481         int             side, distz = endz - startz;
482         float   front, back;
483         float   mid;
484
485 loc0:
486         if (node->contents < 0)
487                 return false;           // didn't hit anything
488
489         switch (node->plane->type)
490         {
491         case PLANE_X:
492                 node = node->children[x < node->plane->dist];
493                 goto loc0;
494         case PLANE_Y:
495                 node = node->children[y < node->plane->dist];
496                 goto loc0;
497         case PLANE_Z:
498                 side = startz < node->plane->dist;
499                 if ((endz < node->plane->dist) == side)
500                 {
501                         node = node->children[side];
502                         goto loc0;
503                 }
504                 // found an intersection
505                 mid = node->plane->dist;
506                 break;
507         default:
508                 back = front = x * node->plane->normal[0] + y * node->plane->normal[1];
509                 front += startz * node->plane->normal[2];
510                 back += endz * node->plane->normal[2];
511                 side = front < node->plane->dist;
512                 if ((back < node->plane->dist) == side)
513                 {
514                         node = node->children[side];
515                         goto loc0;
516                 }
517                 // found an intersection
518                 mid = startz + distz * (front - node->plane->dist) / (front - back);
519                 break;
520         }
521
522         // go down front side
523         if (node->children[side]->contents >= 0 && RecursiveLightPoint (color, node->children[side], x, y, startz, mid))
524                 return true;    // hit something
525         else
526         {
527                 // check for impact on this node
528                 if (node->numsurfaces)
529                 {
530                         int i, ds, dt;
531                         msurface_t *surf;
532
533                         surf = cl.worldmodel->surfaces + node->firstsurface;
534                         for (i = 0;i < node->numsurfaces;i++, surf++)
535                         {
536                                 if (!(surf->flags & SURF_LIGHTMAP))
537                                         continue;       // no lightmaps
538
539                                 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]);
540                                 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]);
541
542                                 if (ds < surf->texturemins[0] || dt < surf->texturemins[1])
543                                         continue;
544
545                                 ds -= surf->texturemins[0];
546                                 dt -= surf->texturemins[1];
547
548                                 if (ds > surf->extents[0] || dt > surf->extents[1])
549                                         continue;
550
551                                 if (surf->samples)
552                                 {
553                                         qbyte *lightmap;
554                                         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;
555                                         line3 = ((surf->extents[0]>>4)+1)*3;
556                                         size3 = ((surf->extents[0]>>4)+1) * ((surf->extents[1]>>4)+1)*3; // LordHavoc: *3 for colored lighting
557
558                                         lightmap = surf->samples + ((dt>>4) * ((surf->extents[0]>>4)+1) + (ds>>4))*3; // LordHavoc: *3 for color
559
560                                         for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++)
561                                         {
562                                                 scale = d_lightstylevalue[surf->styles[maps]];
563                                                 r00 += lightmap[      0] * scale;g00 += lightmap[      1] * scale;b00 += lightmap[      2] * scale;
564                                                 r01 += lightmap[      3] * scale;g01 += lightmap[      4] * scale;b01 += lightmap[      5] * scale;
565                                                 r10 += lightmap[line3+0] * scale;g10 += lightmap[line3+1] * scale;b10 += lightmap[line3+2] * scale;
566                                                 r11 += lightmap[line3+3] * scale;g11 += lightmap[line3+4] * scale;b11 += lightmap[line3+5] * scale;
567                                                 lightmap += size3;
568                                         }
569
570 /*
571 LordHavoc: here's the readable version of the interpolation
572 code, not quite as easy for the compiler to optimize...
573
574 dsfrac is the X position in the lightmap pixel, * 16
575 dtfrac is the Y position in the lightmap pixel, * 16
576 r00 is top left corner, r01 is top right corner
577 r10 is bottom left corner, r11 is bottom right corner
578 g and b are the same layout.
579 r0 and r1 are the top and bottom intermediate results
580
581 first we interpolate the top two points, to get the top
582 edge sample
583
584         r0 = (((r01-r00) * dsfrac) >> 4) + r00;
585         g0 = (((g01-g00) * dsfrac) >> 4) + g00;
586         b0 = (((b01-b00) * dsfrac) >> 4) + b00;
587
588 then we interpolate the bottom two points, to get the
589 bottom edge sample
590
591         r1 = (((r11-r10) * dsfrac) >> 4) + r10;
592         g1 = (((g11-g10) * dsfrac) >> 4) + g10;
593         b1 = (((b11-b10) * dsfrac) >> 4) + b10;
594
595 then we interpolate the top and bottom samples to get the
596 middle sample (the one which was requested)
597
598         r = (((r1-r0) * dtfrac) >> 4) + r0;
599         g = (((g1-g0) * dtfrac) >> 4) + g0;
600         b = (((b1-b0) * dtfrac) >> 4) + b0;
601 */
602
603                                         color[0] += (float) ((((((((r11-r10) * dsfrac) >> 4) + r10)-((((r01-r00) * dsfrac) >> 4) + r00)) * dtfrac) >> 4) + ((((r01-r00) * dsfrac) >> 4) + r00)) * (1.0f / 32768.0f);
604                                         color[1] += (float) ((((((((g11-g10) * dsfrac) >> 4) + g10)-((((g01-g00) * dsfrac) >> 4) + g00)) * dtfrac) >> 4) + ((((g01-g00) * dsfrac) >> 4) + g00)) * (1.0f / 32768.0f);
605                                         color[2] += (float) ((((((((b11-b10) * dsfrac) >> 4) + b10)-((((b01-b00) * dsfrac) >> 4) + b00)) * dtfrac) >> 4) + ((((b01-b00) * dsfrac) >> 4) + b00)) * (1.0f / 32768.0f);
606                                 }
607                                 return true; // success
608                         }
609                 }
610
611                 // go down back side
612                 node = node->children[side ^ 1];
613                 startz = mid;
614                 distz = endz - startz;
615                 goto loc0;
616         }
617 }
618
619 void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic, mleaf_t *leaf)
620 {
621         int      i, *dlightbits;
622         vec3_t dist;
623         float f;
624         rdlight_t *rd;
625         mlight_t *sl;
626         if (leaf == NULL)
627                 leaf = Mod_PointInLeaf(p, cl.worldmodel);
628
629         if (leaf->contents == CONTENTS_SOLID)
630         {
631                 color[0] = color[1] = color[2] = 0;
632                 return;
633         }
634
635         if (r_fullbright.integer || !cl.worldmodel->lightdata)
636         {
637                 color[0] = color[1] = color[2] = 2;
638                 return;
639         }
640
641         color[0] = color[1] = color[2] = r_ambient.value * (2.0f / 128.0f);
642         if (cl.worldmodel->numlights)
643         {
644                 for (i = 0;i < cl.worldmodel->numlights;i++)
645                 {
646                         sl = cl.worldmodel->lights + i;
647                         if (d_lightstylevalue[sl->style] > 0)
648                         {
649                                 VectorSubtract (p, sl->origin, dist);
650                                 f = DotProduct(dist, dist) + sl->distbias;
651                                 f = (1.0f / f) - sl->subtract;
652                                 if (f > 0)
653                                 {
654                                         if (CL_TraceLine(p, sl->origin, NULL, NULL, 0, false) == 1)
655                                         {
656                                                 f *= d_lightstylevalue[sl->style] * (1.0f / 32768.0f);
657                                                 VectorMA(color, f, sl->light, color);
658                                         }
659                                 }
660                         }
661
662                 }
663         }
664         else
665                 RecursiveLightPoint (color, cl.worldmodel->nodes, p[0], p[1], p[2], p[2] - 65536);
666
667         if (dynamic && leaf->dlightframe == r_framecount)
668         {
669                 dlightbits = leaf->dlightbits;
670                 for (i = 0;i < r_numdlights;i++)
671                 {
672                         if (!(dlightbits[i >> 5] & (1 << (i & 31))))
673                                 continue;
674                         rd = r_dlight + i;
675                         VectorSubtract (p, rd->origin, dist);
676                         f = DotProduct(dist, dist) + LIGHTOFFSET;
677                         if (f < rd->cullradius2)
678                         {
679                                 f = (1.0f / f) - rd->lightsubtract;
680                                 if (f > 0)
681                                         VectorMA(color, f, rd->light, color);
682                         }
683                 }
684         }
685 }
686
687 void R_ModelLightPoint (vec3_t color, vec3_t p, int *dlightbits)
688 {
689         mleaf_t *leaf;
690         leaf = Mod_PointInLeaf(p, cl.worldmodel);
691         if (leaf->contents == CONTENTS_SOLID)
692         {
693                 color[0] = color[1] = color[2] = 0;
694                 dlightbits[0] = dlightbits[1] = dlightbits[2] = dlightbits[3] = dlightbits[4] = dlightbits[5] = dlightbits[6] = dlightbits[7] = 0;
695                 return;
696         }
697
698         if (r_fullbright.integer || !cl.worldmodel->lightdata)
699         {
700                 color[0] = color[1] = color[2] = 2;
701                 dlightbits[0] = dlightbits[1] = dlightbits[2] = dlightbits[3] = dlightbits[4] = dlightbits[5] = dlightbits[6] = dlightbits[7] = 0;
702                 return;
703         }
704
705         color[0] = color[1] = color[2] = r_ambient.value * (2.0f / 128.0f);
706         if (!cl.worldmodel->numlights)
707                 RecursiveLightPoint (color, cl.worldmodel->nodes, p[0], p[1], p[2], p[2] - 65536);
708
709         if (leaf->dlightframe == r_framecount)
710         {
711                 dlightbits[0] = leaf->dlightbits[0];
712                 dlightbits[1] = leaf->dlightbits[1];
713                 dlightbits[2] = leaf->dlightbits[2];
714                 dlightbits[3] = leaf->dlightbits[3];
715                 dlightbits[4] = leaf->dlightbits[4];
716                 dlightbits[5] = leaf->dlightbits[5];
717                 dlightbits[6] = leaf->dlightbits[6];
718                 dlightbits[7] = leaf->dlightbits[7];
719         }
720         else
721                 dlightbits[0] = dlightbits[1] = dlightbits[2] = dlightbits[3] = dlightbits[4] = dlightbits[5] = dlightbits[6] = dlightbits[7] = 0;
722 }
723
724 void R_LightModel(int numverts, float colorr, float colorg, float colorb, int worldcoords)
725 {
726         int i, j, nearlights = 0;
727         float color[3], basecolor[3], v[3], t, *av, *avn, *avc, a, number, f, dist2;
728         struct
729         {
730                 vec3_t origin;
731                 vec_t cullradius2;
732                 vec3_t light;
733                 vec_t lightsubtract;
734                 vec_t falloff;
735                 vec_t offset;
736         }
737         nearlight[MAX_DLIGHTS], *nl;
738         int modeldlightbits[8];
739         mlight_t *sl;
740         a = currentrenderentity->alpha;
741         if (currentrenderentity->effects & EF_FULLBRIGHT)
742         {
743                 basecolor[0] = colorr;
744                 basecolor[1] = colorg;
745                 basecolor[2] = colorb;
746         }
747         else
748         {
749                 if (r_lightmodels.integer)
750                 {
751                         R_ModelLightPoint(basecolor, currentrenderentity->origin, modeldlightbits);
752
753                         nl = &nearlight[0];
754                         for (i = 0, sl = cl.worldmodel->lights;i < cl.worldmodel->numlights && nearlights < MAX_DLIGHTS;i++, sl++)
755                         {
756                                 if (CL_TraceLine(currentrenderentity->origin, sl->origin, NULL, NULL, 0, false) == 1)
757                                 {
758                                         nl->falloff = sl->falloff;
759                                         // transform the light into the model's coordinate system
760                                         if (worldcoords)
761                                                 VectorCopy(sl->origin, nl->origin);
762                                         else
763                                                 softwareuntransform(sl->origin, nl->origin);
764                                         f = d_lightstylevalue[sl->style] * (1.0f / 32768.0f);
765                                         VectorScale(sl->light, f, nl->light);
766                                         nl->cullradius2 = 99999999;
767                                         nl->lightsubtract = sl->subtract;
768                                         nl->offset = sl->distbias;
769                                         nl++;
770                                         nearlights++;
771                                 }
772                         }
773                         for (i = 0;i < r_numdlights && nearlights < MAX_DLIGHTS;i++)
774                         {
775                                 if (!(modeldlightbits[i >> 5] & (1 << (i & 31))))
776                                         continue;
777                                 if (currentrenderentity == r_dlight[i].ent)
778                                 {
779                                         f = (1.0f / LIGHTOFFSET) - nl->lightsubtract;
780                                         if (f > 0)
781                                                 VectorMA(basecolor, f, r_dlight[i].light, basecolor);
782                                 }
783                                 else
784                                 {
785                                         // transform the light into the model's coordinate system
786                                         if (worldcoords)
787                                                 VectorCopy(r_dlight[i].origin, nl->origin);
788                                         else
789                                                 softwareuntransform(r_dlight[i].origin, nl->origin);
790                                         nl->cullradius2 = r_dlight[i].cullradius2;
791                                         nl->light[0] = r_dlight[i].light[0] * colorr;
792                                         nl->light[1] = r_dlight[i].light[1] * colorg;
793                                         nl->light[2] = r_dlight[i].light[2] * colorb;
794                                         nl->lightsubtract = r_dlight[i].lightsubtract;
795                                         nl->offset = LIGHTOFFSET;
796                                         nl++;
797                                         nearlights++;
798                                 }
799                         }
800                 }
801                 else
802                         R_CompleteLightPoint (basecolor, currentrenderentity->origin, true, NULL);
803         }
804         basecolor[0] *= colorr;
805         basecolor[1] *= colorg;
806         basecolor[2] *= colorb;
807         avc = aliasvertcolor;
808         if (nearlights)
809         {
810                 av = aliasvert;
811                 avn = aliasvertnorm;
812                 for (i = 0;i < numverts;i++)
813                 {
814                         VectorCopy(basecolor, color);
815                         for (j = 0, nl = &nearlight[0];j < nearlights;j++, nl++)
816                         {
817                                 // distance attenuation
818                                 VectorSubtract(nl->origin, av, v);
819                                 dist2 = DotProduct(v,v);
820                                 if (dist2 < nl->cullradius2)
821                                 {
822                                         f = (1.0f / (dist2 + nl->offset)) - nl->lightsubtract;
823                                         if (f > 0)
824                                         {
825                                                 // directional shading
826 #if SLOWMATH
827                                                 t = 1.0f / sqrt(dist2);
828 #else
829                                                 number = DotProduct(v, v);
830                                                 *((int *)&t) = 0x5f3759df - ((* (int *) &number) >> 1);
831                                                 t = t * (1.5f - (number * 0.5f * t * t));
832 #endif
833                                                 // DotProduct(avn,v) * t is dotproduct with a normalized v,
834                                                 // the hardness variables are for backlighting/shinyness
835                                                 f *= DotProduct(avn,v) * t;// * hardness + hardnessoffset;
836                                                 if (f > 0)
837                                                         VectorMA(color, f, nl->light, color);
838                                         }
839                                 }
840                         }
841
842                         VectorCopy(color, avc);
843                         avc[3] = a;
844                         avc += 4;
845                         av += 4;
846                         avn += 3;
847                 }
848         }
849         else
850         {
851                 for (i = 0;i < numverts;i++)
852                 {
853                         VectorCopy(basecolor, avc);
854                         avc[3] = a;
855                         avc += 4;
856                 }
857         }
858 }
859