Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

light.c File Reference

#include "light.h"

Include dependency graph for light.c:

Include dependency graph

Go to the source code of this file.

Data Structures

struct  contribution_t
struct  filter_t
struct  skyBrush_t

Defines

#define EXTRASCALE   2
#define MAX_CONTRIBUTIONS   1024
#define MAX_FACE_POINTS   128
#define MAX_FILTERS   1024
#define MAX_POINTS_ON_WINDINGS   64
#define PLANAR_PATCH_EPSILON   0.1

Functions

void ColorToBytes (const float *color, byte *colorBytes)
void CountLightmaps (void)
void CreateEntityLights (void)
void CreateFilters (void)
void CreateSurfaceLights (void)
void FilterTrace (const vec3_t start, const vec3_t end, vec3_t filter)
void FindSkyBrushes (void)
entity_tFindTargetEntity (const char *target)
void GridAndVertexLighting (void)
qboolean LightContributionToPoint (const light_t *light, const vec3_t origin, vec3_t color, traceWork_t *tw)
void LightingAtSample (vec3_t origin, vec3_t normal, vec3_t color, qboolean testOcclusion, qboolean forceSunLight, traceWork_t *tw)
int LightMain (int argc, char **argv)
void LightWorld (void)
mesh_tLinearSubdivideMesh (mesh_t *in)
float PointToPolygonFormFactor (const vec3_t point, const vec3_t normal, const winding_t *w)
void PrintOccluded (byte occluded[LIGHTMAP_WIDTH *EXTRASCALE][LIGHTMAP_HEIGHT *EXTRASCALE], int width, int height)
void RemoveLightsInSolid (void)
void SetEntityOrigins (void)
void SetupGrid (void)
void SubdivideAreaLight (shaderInfo_t *ls, winding_t *w, vec3_t normal, float areaSubdivide, qboolean backsplash)
void SunToPlane (const vec3_t origin, const vec3_t normal, vec3_t color, traceWork_t *tw)
void SunToPoint (const vec3_t origin, traceWork_t *tw, vec3_t addLight)
void TraceGrid (int num)
void TraceLtm (int num)
void TriSoupLightingThread (int num)
void VertexLighting (dsurface_t *ds, qboolean testOcclusion, qboolean forceSunLight, float scale, traceWork_t *tw)
void VertexLightingThread (int num)

Variables

vec3_t ambientColor
float areaScale = 0.25
int c_occluded
int c_sunHit
int c_sunMiss
int c_visible
int defaultLightSubdivide = 999
qboolean dump
FILEdumpFile
int entitySurface [MAX_MAP_DRAW_SURFS]
qboolean exactPointToPolygon = qtrue
qboolean extra
qboolean extraWide
filter_t filters [MAX_FILTERS]
float formFactorValueScale = 3
int gridBounds [3]
vec3_t gridMins
vec3_t gridSize = { 64, 64, 128 }
qboolean lightmapBorder
light_tlights
float linearScale = 1.0 / 8000
int nogridlighting = 0
qboolean noSurfaces
qboolean notrace
int novertexlighting = 0
int numAreaLights
int numFilters
int numPointLights
int numSkyBrushes
qboolean patchshadows
float pointScale = 7500
int samplesize = 16
skyBrush_t skyBrushes [MAX_MAP_BRUSHES]
char source [1024]
vec3_t sunDirection = { 0.45, 0.3, 0.9 }
vec3_t sunLight = { 100, 100, 50 }
vec3_t surfaceOrigin [MAX_MAP_DRAW_SURFS]


Define Documentation

#define EXTRASCALE   2
 

Definition at line 34 of file light.c.

#define MAX_CONTRIBUTIONS   1024
 

Definition at line 1590 of file light.c.

Referenced by TraceGrid().

#define MAX_FACE_POINTS   128
 

Definition at line 127 of file light.c.

#define MAX_FILTERS   1024
 

Definition at line 43 of file light.c.

#define MAX_POINTS_ON_WINDINGS   64
 

Definition at line 603 of file light.c.

#define PLANAR_PATCH_EPSILON   0.1
 

Definition at line 1844 of file light.c.


Function Documentation

void ColorToBytes const float *  color,
byte colorBytes
 

Definition at line 1167 of file light.c.

References byte, max, vec3_t, VectorCopy, and VectorScale.

Referenced by TraceGrid(), TraceLtm(), VL_StoreLightmap(), and VS_StoreLightmap().

01167                                                           {
01168     float   max;
01169     vec3_t  sample;
01170 
01171     VectorCopy( color, sample );
01172 
01173     // clamp with color normalization
01174     max = sample[0];
01175     if ( sample[1] > max ) {
01176         max = sample[1];
01177     }
01178     if ( sample[2] > max ) {
01179         max = sample[2];
01180     }
01181     if ( max > 255 ) {
01182         VectorScale( sample, 255/max, sample );
01183     }
01184     colorBytes[ 0 ] = sample[0];
01185     colorBytes[ 1 ] = sample[1];
01186     colorBytes[ 2 ] = sample[2];
01187 }

void CountLightmaps void   ) 
 

Definition at line 225 of file light.c.

References count, drawSurfaces, Error(), i, LIGHTMAP_HEIGHT, LIGHTMAP_WIDTH, dsurface_t::lightmapNum, numDrawSurfaces, numLightBytes, and qprintf().

Referenced by LightMain(), VLightMain(), and VSoundMain().

00225                             {
00226     int         count;
00227     int         i;
00228     dsurface_t  *ds;
00229 
00230     qprintf ("--- CountLightmaps ---\n");
00231     count = 0;
00232     for ( i = 0 ; i < numDrawSurfaces ; i++ ) {
00233         // see if this surface is light emiting
00234         ds = &drawSurfaces[i];
00235         if ( ds->lightmapNum > count ) {
00236             count = ds->lightmapNum;
00237         }
00238     }
00239 
00240     count++;
00241     numLightBytes = count * LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 3;
00242     if ( numLightBytes > MAX_MAP_LIGHTING ) {
00243         Error("MAX_MAP_LIGHTING exceeded");
00244     }
00245 
00246     qprintf( "%5i drawSurfaces\n", numDrawSurfaces );
00247     qprintf( "%5i lightmaps\n", count );
00248 }

Here is the call graph for this function:

void CreateEntityLights void   ) 
 

Definition at line 464 of file light.c.

References _printf(), light_s::color, ColorNormalize(), e, entities, FindTargetEntity(), FloatForKey(), GetVectorForKey(), i, light_t, lights, light_s::linearLight, malloc(), memset(), name, light_s::next, numPointLights, entity_t::origin, light_s::photons, sscanf(), strncmp(), light_s::style, light_s::type, ValueForKey(), vec3_t, VectorNormalize(), and VectorSubtract.

Referenced by GridAndVertexLighting(), and LightWorld().

00465 {
00466     int     i;
00467     light_t *dl;
00468     entity_t    *e, *e2;
00469     const char  *name;
00470     const char  *target;
00471     vec3_t  dest;
00472     const char  *_color;
00473     float   intensity;
00474     int     spawnflags;
00475 
00476     //
00477     // entities
00478     //
00479     for ( i = 0 ; i < num_entities ; i++ ) {
00480         e = &entities[i];
00481         name = ValueForKey (e, "classname");
00482         if (strncmp (name, "light", 5))
00483             continue;
00484 
00485         numPointLights++;
00486         dl = malloc(sizeof(*dl));
00487         memset (dl, 0, sizeof(*dl));
00488         dl->next = lights;
00489         lights = dl;
00490 
00491         spawnflags = FloatForKey (e, "spawnflags");
00492         if ( spawnflags & 1 ) {
00493             dl->linearLight = qtrue;
00494         }
00495 
00496         GetVectorForKey (e, "origin", dl->origin);
00497         dl->style = FloatForKey (e, "_style");
00498         if (!dl->style)
00499             dl->style = FloatForKey (e, "style");
00500         if (dl->style < 0)
00501             dl->style = 0;
00502 
00503         intensity = FloatForKey (e, "light");
00504         if (!intensity)
00505             intensity = FloatForKey (e, "_light");
00506         if (!intensity)
00507             intensity = 300;
00508         _color = ValueForKey (e, "_color");
00509         if (_color && _color[0])
00510         {
00511             sscanf (_color, "%f %f %f", &dl->color[0],&dl->color[1],&dl->color[2]);
00512             ColorNormalize (dl->color, dl->color);
00513         }
00514         else
00515             dl->color[0] = dl->color[1] = dl->color[2] = 1.0;
00516 
00517         intensity = intensity * pointScale;
00518         dl->photons = intensity;
00519 
00520         dl->type = emit_point;
00521 
00522         // lights with a target will be spotlights
00523         target = ValueForKey (e, "target");
00524 
00525         if ( target[0] ) {
00526             float   radius;
00527             float   dist;
00528 
00529             e2 = FindTargetEntity (target);
00530             if (!e2) {
00531                 _printf ("WARNING: light at (%i %i %i) has missing target\n",
00532                 (int)dl->origin[0], (int)dl->origin[1], (int)dl->origin[2]);
00533             } else {
00534                 GetVectorForKey (e2, "origin", dest);
00535                 VectorSubtract (dest, dl->origin, dl->normal);
00536                 dist = VectorNormalize (dl->normal, dl->normal);
00537                 radius = FloatForKey (e, "radius");
00538                 if ( !radius ) {
00539                     radius = 64;
00540                 }
00541                 if ( !dist ) {
00542                     dist = 64;
00543                 }
00544                 dl->radiusByDist = (radius + 16) / dist;
00545                 dl->type = emit_spotlight;
00546             }
00547         }
00548     }
00549 }

Here is the call graph for this function:

void CreateFilters void   ) 
 

Definition at line 1845 of file light.c.

References _printf(), CrossProduct(), d, DotProduct, drawSurfaces, drawVerts, dshaders, Error(), f, fabs(), filters, dsurface_t::firstVert, i, numFilters, dsurface_t::numVerts, filter_t::origin, dsurface_t::patchHeight, dsurface_t::patchWidth, filter_t::plane, shaderInfo_t, ShaderInfoForShader(), dsurface_t::shaderNum, filter_t::si, v1, v2, vec3_t, VectorNormalize(), filter_t::vectors, VectorSubtract, and drawVert_t::xyz.

Referenced by GridAndVertexLighting(), and LightMain().

01845                            {
01846     int             i;
01847     filter_t        *f;
01848     dsurface_t      *ds;
01849     shaderInfo_t    *si;
01850     drawVert_t      *v1, *v2, *v3;
01851     vec3_t          d1, d2;
01852     int             vertNum;
01853 
01854     numFilters = 0;
01855 
01856     return;
01857 
01858     for ( i = 0 ; i < numDrawSurfaces ; i++ ) {
01859         ds = &drawSurfaces[i];
01860         if ( !ds->patchWidth ) {
01861             continue;
01862         }
01863         si = ShaderInfoForShader( dshaders[ ds->shaderNum ].shader );
01864 /*
01865         if ( !(si->surfaceFlags & SURF_LIGHTFILTER) ) {
01866             continue;
01867         }
01868 */
01869 
01870         // we have a filter patch
01871         v1 = &drawVerts[ ds->firstVert ];
01872 
01873         if ( ds->patchWidth != 3 || ds->patchHeight != 3 ) {
01874             _printf("WARNING: patch at %i %i %i has SURF_LIGHTFILTER but isn't a 3 by 3\n",
01875                 v1->xyz[0], v1->xyz[1], v1->xyz[2] );
01876             continue;
01877         }
01878 
01879         if ( numFilters == MAX_FILTERS ) {
01880             Error( "MAX_FILTERS" );
01881         }
01882         f = &filters[ numFilters ];
01883         numFilters++;
01884 
01885         v2 = &drawVerts[ ds->firstVert + 2 ];
01886         v3 = &drawVerts[ ds->firstVert + 6 ];
01887 
01888         VectorSubtract( v2->xyz, v1->xyz, d1 );
01889         VectorSubtract( v3->xyz, v1->xyz, d2 );
01890         VectorNormalize( d1, d1 );
01891         VectorNormalize( d2, d2 );
01892         CrossProduct( d1, d2, f->plane );
01893         f->plane[3] = DotProduct( v1->xyz, f->plane );
01894 
01895         // make sure all the control points are on the plane
01896         for ( vertNum = 0 ; vertNum < ds->numVerts ; vertNum++ ) {
01897             float   d;
01898 
01899             d = DotProduct( drawVerts[ ds->firstVert + vertNum ].xyz, f->plane ) - f->plane[3];
01900             if ( fabs( d ) > PLANAR_PATCH_EPSILON ) {
01901                 break;
01902             }
01903         }
01904         if ( vertNum != ds->numVerts ) {
01905             numFilters--;
01906             _printf("WARNING: patch at %i %i %i has SURF_LIGHTFILTER but isn't flat\n",
01907                 v1->xyz[0], v1->xyz[1], v1->xyz[2] );
01908             continue;
01909         }
01910     }
01911 
01912     f = &filters[0];
01913     numFilters = 1;
01914 
01915     f->plane[0] = 1;
01916     f->plane[1] = 0;
01917     f->plane[2] = 0;
01918     f->plane[3] = 448;
01919 
01920     f->origin[0] = 448;
01921     f->origin[1] = 192;
01922     f->origin[2] = 0;
01923 
01924     f->vectors[0][0] = 0;
01925     f->vectors[0][1] = -1.0 / 128;
01926     f->vectors[0][2] = 0;
01927 
01928     f->vectors[1][0] = 0;
01929     f->vectors[1][1] = 0;
01930     f->vectors[1][2] = 1.0 / 128;
01931 
01932     f->si = ShaderInfoForShader( "textures/hell/blocks11ct" );
01933 }

Here is the call graph for this function:

void CreateSurfaceLights void   ) 
 

Definition at line 257 of file light.c.

References _printf(), AllocWinding(), shaderInfo_s::autosprite, cFacet_t, shaderInfo_s::color, drawSurfaces, drawVerts, dshaders, f, surfaceTest_t::facets, dsurface_t::firstVert, FreeWinding(), i, j, light_t, dsurface_t::lightmapVecs, lights, shaderInfo_s::lightSubdivide, malloc(), memcpy(), memset(), light_s::next, cFacet_s::numBoundaries, surfaceTest_t::numFacets, numPointLights, winding_t::numpoints, dsurface_t::numVerts, winding_t::p, light_s::photons, cFacet_s::points, qprintf(), qtrue, ReverseWinding(), shaderInfo_t, ShaderInfoForShader(), dsurface_t::shaderNum, SubdivideAreaLight(), cFacet_s::surface, surfaceTest, t, shaderInfo_s::twoSided, shaderInfo_s::value, vec3_origin, vec3_t, VectorAdd, VectorCopy, VectorScale, VectorSubtract, w, and drawVert_t::xyz.

Referenced by GridAndVertexLighting(), and LightMain().

00257                                  {
00258     int             i, j, side;
00259     dsurface_t      *ds;
00260     shaderInfo_t    *ls;
00261     winding_t       *w;
00262     cFacet_t        *f;
00263     light_t         *dl;
00264     vec3_t          origin;
00265     drawVert_t      *dv;
00266     int             c_lightSurfaces;
00267     float           lightSubdivide;
00268     vec3_t          normal;
00269 
00270     qprintf ("--- CreateSurfaceLights ---\n");
00271     c_lightSurfaces = 0;
00272 
00273     for ( i = 0 ; i < numDrawSurfaces ; i++ ) {
00274         // see if this surface is light emiting
00275         ds = &drawSurfaces[i];
00276 
00277         ls = ShaderInfoForShader( dshaders[ ds->shaderNum].shader );
00278         if ( ls->value == 0 ) {
00279             continue;
00280         }
00281 
00282         // determine how much we need to chop up the surface
00283         if ( ls->lightSubdivide ) {
00284             lightSubdivide = ls->lightSubdivide;
00285         } else {
00286             lightSubdivide = defaultLightSubdivide;
00287         }
00288 
00289         c_lightSurfaces++;
00290 
00291         // an autosprite shader will become
00292         // a point light instead of an area light
00293         if ( ls->autosprite ) {
00294             // autosprite geometry should only have four vertexes
00295             if ( surfaceTest[i] ) {
00296                 // curve or misc_model
00297                 f = surfaceTest[i]->facets;
00298                 if ( surfaceTest[i]->numFacets != 1 || f->numBoundaries != 4 ) {
00299                     _printf( "WARNING: surface at (%i %i %i) has autosprite shader but isn't a quad\n",
00300                         (int)f->points[0], (int)f->points[1], (int)f->points[2] );
00301                 }
00302                 VectorAdd( f->points[0], f->points[1], origin );
00303                 VectorAdd( f->points[2], origin, origin );
00304                 VectorAdd( f->points[3], origin, origin );
00305                 VectorScale( origin, 0.25, origin );
00306             } else {
00307                 // normal polygon
00308                 dv = &drawVerts[ ds->firstVert ];
00309                 if ( ds->numVerts != 4 ) {
00310                     _printf( "WARNING: surface at (%i %i %i) has autosprite shader but %i verts\n",
00311                         (int)dv->xyz[0], (int)dv->xyz[1], (int)dv->xyz[2] );
00312                     continue;
00313                 }
00314 
00315                 VectorAdd( dv[0].xyz, dv[1].xyz, origin );
00316                 VectorAdd( dv[2].xyz, origin, origin );
00317                 VectorAdd( dv[3].xyz, origin, origin );
00318                 VectorScale( origin, 0.25, origin );
00319             }
00320 
00321 
00322             numPointLights++;
00323             dl = malloc(sizeof(*dl));
00324             memset (dl, 0, sizeof(*dl));
00325             dl->next = lights;
00326             lights = dl;
00327 
00328             VectorCopy( origin, dl->origin );
00329             VectorCopy( ls->color, dl->color );
00330             dl->photons = ls->value * pointScale;
00331             dl->type = emit_point;
00332             continue;
00333         }
00334 
00335         // possibly create for both sides of the polygon
00336         for ( side = 0 ; side <= ls->twoSided ; side++ ) {
00337             // create area lights
00338             if ( surfaceTest[i] ) {
00339                 // curve or misc_model
00340                 for ( j = 0 ; j < surfaceTest[i]->numFacets ; j++ ) {
00341                     f = surfaceTest[i]->facets + j;
00342                     w = AllocWinding( f->numBoundaries );
00343                     w->numpoints = f->numBoundaries;
00344                     memcpy( w->p, f->points, f->numBoundaries * 12 );
00345 
00346                     VectorCopy( f->surface, normal );
00347                     if ( side ) {
00348                         winding_t   *t;
00349 
00350                         t = w;
00351                         w = ReverseWinding( t );
00352                         FreeWinding( t );
00353                         VectorSubtract( vec3_origin, normal, normal );
00354                     }
00355                     SubdivideAreaLight( ls, w, normal, lightSubdivide, qtrue );
00356                 }
00357             } else {
00358                 // normal polygon
00359 
00360                 w = AllocWinding( ds->numVerts );
00361                 w->numpoints = ds->numVerts;
00362                 for ( j = 0 ; j < ds->numVerts ; j++ ) {
00363                     VectorCopy( drawVerts[ds->firstVert+j].xyz, w->p[j] );
00364                 }
00365                 VectorCopy( ds->lightmapVecs[2], normal );
00366                 if ( side ) {
00367                     winding_t   *t;
00368 
00369                     t = w;
00370                     w = ReverseWinding( t );
00371                     FreeWinding( t );
00372                     VectorSubtract( vec3_origin, normal, normal );
00373                 }
00374                 SubdivideAreaLight( ls, w, normal, lightSubdivide, qtrue );
00375             }
00376         }
00377     }
00378 
00379     _printf( "%5i light emitting surfaces\n", c_lightSurfaces );
00380 }

Here is the call graph for this function:

void FilterTrace const vec3_t  start,
const vec3_t  end,
vec3_t  filter
 

Definition at line 671 of file light.c.

References byte, DotProduct, f, filters, shaderInfo_s::height, i, filter_t::origin, shaderInfo_s::pixels, filter_t::plane, point, s, filter_t::si, t, v, vec3_t, VectorClear, VectorLength(), filter_t::vectors, VectorSubtract, shaderInfo_s::width, x, and y.

00671                                                                            {
00672     float       d1, d2;
00673     filter_t    *f;
00674     int         filterNum;
00675     vec3_t      point;
00676     float       frac;
00677     int         i;
00678     float       s, t;
00679     int         u, v;
00680     int         x, y;
00681     byte        *pixel;
00682     float       radius;
00683     float       len;
00684     vec3_t      total;
00685 
00686     filter[0] = 1.0;
00687     filter[1] = 1.0;
00688     filter[2] = 1.0;
00689 
00690     for ( filterNum = 0 ; filterNum < numFilters ; filterNum++ ) {
00691         f = &filters[ filterNum ];
00692 
00693         // see if the plane is crossed
00694         d1 = DotProduct( start, f->plane ) - f->plane[3];
00695         d2 = DotProduct( end, f->plane ) - f->plane[3];
00696 
00697         if ( ( d1 < 0 ) == ( d2 < 0 ) ) {
00698             continue;
00699         }
00700 
00701         // calculate the crossing point
00702         frac = d1 / ( d1 - d2 );
00703 
00704         for ( i = 0 ; i < 3 ; i++ ) {
00705             point[i] = start[i] + frac * ( end[i] - start[i] );
00706         }
00707 
00708         VectorSubtract( point, f->origin, point );
00709 
00710         s = DotProduct( point, f->vectors[0] );
00711         t = 1.0 - DotProduct( point, f->vectors[1] );
00712         if ( s < 0 || s >= 1.0 || t < 0 || t >= 1.0 ) {
00713             continue;
00714         }
00715 
00716         // decide the filter size
00717         radius = 10 * frac;
00718         len = VectorLength( f->vectors[0] );
00719         if ( !len ) {
00720             continue;
00721         }
00722         radius = radius * len * f->si->width;
00723 
00724         // look up the filter, taking multiple samples
00725         VectorClear( total );
00726         for ( u = -1 ; u <= 1 ; u++ ) {
00727             for ( v = -1 ; v <=1 ; v++ ) {
00728                 x = s * f->si->width + u * radius;
00729                 if ( x < 0 ) {
00730                     x = 0;
00731                 }
00732                 if ( x >= f->si->width ) {
00733                     x = f->si->width - 1;
00734                 }
00735                 y = t * f->si->height + v * radius;
00736                 if ( y < 0 ) {
00737                     y = 0;
00738                 }
00739                 if ( y >= f->si->height ) {
00740                     y = f->si->height - 1;
00741                 }
00742 
00743                 pixel = f->si->pixels + ( y * f->si->width + x ) * 4;
00744                 total[0] += pixel[0];
00745                 total[1] += pixel[1];
00746                 total[2] += pixel[2];
00747             }
00748         }
00749 
00750         filter[0] *= total[0]/(255.0*9);
00751         filter[1] *= total[1]/(255.0*9);
00752         filter[2] *= total[2]/(255.0*9);
00753     }
00754 
00755 }

Here is the call graph for this function:

void FindSkyBrushes void   ) 
 

Definition at line 389 of file light.c.

References skyBrush_t::b, b, skyBrush_t::bounds, dbrushes, dbrushsides, dplane_t::dist, dplanes, drawSurfaces, dshaders, dbrush_t::firstSide, i, j, dbrush_t::numSides, numSkyBrushes, dbrushside_t::planeNum, s, shaderInfo_t, ShaderInfoForShader(), dbrushside_t::shaderNum, skyBrushes, shaderInfo_s::sunDirection, sunDirection, sunLight, shaderInfo_s::sunLight, shaderInfo_s::surfaceFlags, dshader_t::surfaceFlags, VectorCopy, and VectorNormalize().

Referenced by GridAndVertexLighting(), and LightMain().

00389                             {
00390     int             i, j;
00391     dbrush_t        *b;
00392     skyBrush_t      *sb;
00393     shaderInfo_t    *si;
00394     dbrushside_t    *s;
00395 
00396     // find the brushes
00397     for ( i = 0 ; i < numbrushes ; i++ ) {
00398         b = &dbrushes[i];
00399         for ( j = 0 ; j < b->numSides ; j++ ) {
00400             s = &dbrushsides[ b->firstSide + j ];
00401             if ( dshaders[ s->shaderNum ].surfaceFlags & SURF_SKY ) {
00402                 sb = &skyBrushes[ numSkyBrushes ];
00403                 sb->b = b;
00404                 sb->bounds[0][0] = -dplanes[ dbrushsides[ b->firstSide + 0 ].planeNum ].dist - 1;
00405                 sb->bounds[1][0] = dplanes[ dbrushsides[ b->firstSide + 1 ].planeNum ].dist + 1;
00406                 sb->bounds[0][1] = -dplanes[ dbrushsides[ b->firstSide + 2 ].planeNum ].dist - 1;
00407                 sb->bounds[1][1] = dplanes[ dbrushsides[ b->firstSide + 3 ].planeNum ].dist + 1;
00408                 sb->bounds[0][2] = -dplanes[ dbrushsides[ b->firstSide + 4 ].planeNum ].dist - 1;
00409                 sb->bounds[1][2] = dplanes[ dbrushsides[ b->firstSide + 5 ].planeNum ].dist + 1;
00410                 numSkyBrushes++;
00411                 break;
00412             }
00413         }
00414     }
00415 
00416     // default
00417     VectorNormalize( sunDirection, sunDirection );
00418 
00419     // find the sky shader
00420     for ( i = 0 ; i < numDrawSurfaces ; i++ ) {
00421         si = ShaderInfoForShader( dshaders[ drawSurfaces[i].shaderNum ].shader );
00422         if ( si->surfaceFlags & SURF_SKY ) {
00423             VectorCopy( si->sunLight, sunLight );
00424             VectorCopy( si->sunDirection, sunDirection );
00425             break;
00426         }
00427     }
00428 }

Here is the call graph for this function:

entity_t* FindTargetEntity const char *  target  ) 
 

Definition at line 443 of file light.c.

References entities, i, n, strcmp(), and ValueForKey().

Referenced by CreateEntityLights(), VL_CreateEntityLights(), and VS_CreateEntitySpeakers().

00443                                                  {
00444     int         i;
00445     const char  *n;
00446 
00447     for ( i = 0 ; i < num_entities ; i++ ) {
00448         n = ValueForKey (&entities[i], "targetname");
00449         if ( !strcmp (n, target) ) {
00450             return &entities[i];
00451         }
00452     }
00453 
00454     return NULL;
00455 }

Here is the call graph for this function:

void GridAndVertexLighting void   ) 
 

Definition at line 1989 of file light.c.

References _printf(), CreateEntityLights(), CreateFilters(), CreateSurfaceLights(), FindSkyBrushes(), InitTrace(), numDrawSurfaces, numGridPoints, qtrue, RunThreadsOnIndividual(), SetupGrid(), TraceGrid(), TriSoupLightingThread(), and VertexLightingThread().

Referenced by VLightMain(), and VSoundMain().

01989                                  {
01990     SetupGrid();
01991 
01992     FindSkyBrushes();
01993     CreateFilters();
01994     InitTrace();
01995     CreateEntityLights ();
01996     CreateSurfaceLights();
01997 
01998     if (!nogridlighting) {
01999         _printf ("--- TraceGrid ---\n");
02000         RunThreadsOnIndividual( numGridPoints, qtrue, TraceGrid );
02001     }
02002 
02003     if (!novertexlighting) {
02004         _printf ("--- Vertex Lighting ---\n");
02005         RunThreadsOnIndividual( numDrawSurfaces, qtrue, VertexLightingThread );
02006     }
02007 
02008     _printf("--- Model Lighting ---\n");
02009     RunThreadsOnIndividual( numDrawSurfaces, qtrue, TriSoupLightingThread );
02010 }

Here is the call graph for this function:

qboolean LightContributionToPoint const light_t light,
const vec3_t  origin,
vec3_t  color,
traceWork_t tw
 

Definition at line 1487 of file light.c.

References add, light_s::color, d, light_s::dist, DotProduct, emit_point, light_s::emitColor, exactPointToPolygon, light_t, light_s::linearLight, linearScale, light_s::normal, light_s::origin, trace_t::passSolid, light_s::photons, PointToPolygonFormFactor(), qboolean, qfalse, TraceLine(), light_s::twosided, light_s::type, vec3_t, VectorClear, VectorLength(), VectorNormalize(), VectorScale, VectorSubtract, and light_s::w.

Referenced by TraceGrid().

01488                                                                   {
01489     trace_t     trace;
01490     float       add;
01491 
01492     add = 0;
01493 
01494     VectorClear( color );
01495 
01496     // testing exact PTPFF
01497     if ( exactPointToPolygon && light->type == emit_area ) {
01498         float       factor;
01499         float       d;
01500         vec3_t      normal;
01501 
01502         // see if the point is behind the light
01503         d = DotProduct( origin, light->normal ) - light->dist;
01504         if ( !light->twosided ) {
01505             if ( d < 1 ) {
01506                 return qfalse;      // point is behind light
01507             }
01508         }
01509 
01510         // test occlusion
01511         // clip the line, tracing from the surface towards the light
01512         TraceLine( origin, light->origin, &trace, qfalse, tw );
01513         if ( trace.passSolid ) {
01514             return qfalse;
01515         }
01516 
01517         // calculate the contribution
01518         VectorSubtract( light->origin, origin, normal );
01519         if ( VectorNormalize( normal, normal ) == 0 ) {
01520             return qfalse;
01521         }
01522         factor = PointToPolygonFormFactor( origin, normal, light->w );
01523         if ( factor <= 0 ) {
01524             if ( light->twosided ) {
01525                 factor = -factor;
01526             } else {
01527                 return qfalse;
01528             }
01529         }
01530         VectorScale( light->emitColor, factor, color );
01531         return qtrue;
01532     }
01533 
01534     // calculate the amount of light at this sample
01535     if ( light->type == emit_point || light->type == emit_spotlight ) {
01536         vec3_t      dir;
01537         float       dist;
01538 
01539         VectorSubtract( light->origin, origin, dir );
01540         dist = VectorLength( dir );
01541         // clamp the distance to prevent super hot spots
01542         if ( dist < 16 ) {
01543             dist = 16;
01544         }
01545         if ( light->linearLight ) {
01546             add = light->photons * linearScale - dist;
01547             if ( add < 0 ) {
01548                 add = 0;
01549             }
01550         } else {
01551             add = light->photons / ( dist * dist );
01552         }
01553     } else {
01554         return qfalse;
01555     }
01556 
01557     if ( add <= 1.0 ) {
01558         return qfalse;
01559     }
01560 
01561     // clip the line, tracing from the surface towards the light
01562     TraceLine( origin, light->origin, &trace, qfalse, tw );
01563 
01564     // other light rays must not hit anything
01565     if ( trace.passSolid ) {
01566         return qfalse;
01567     }
01568 
01569     // add the result
01570     color[0] = add * light->color[0];
01571     color[1] = add * light->color[1];
01572     color[2] = add * light->color[2];
01573 
01574     return qtrue;
01575 }

Here is the call graph for this function:

void LightingAtSample vec3_t  origin,
vec3_t  normal,
vec3_t  color,
qboolean  testOcclusion,
qboolean  forceSunLight,
traceWork_t tw
 

Definition at line 843 of file light.c.

References add, ambientColor, light_s::color, d, light_s::dist, DotProduct, light_s::emitColor, exactPointToPolygon, trace_t::filter, light_t, light_s::linearLight, linearScale, light_s::next, light_s::normal, notrace, light_s::origin, trace_t::passSolid, light_s::photons, PointToPolygonFormFactor(), qfalse, light_s::radiusByDist, SunToPlane(), TraceLine(), light_s::twosided, light_s::type, vec3_t, VectorCopy, VectorLength(), VectorMA, VectorNormalize(), VectorSubtract, and light_s::w.

Referenced by TraceLtm(), and VertexLighting().

00844                                                                                         {
00845     light_t     *light;
00846     trace_t     trace;
00847     float       angle;
00848     float       add;
00849     float       dist;
00850     vec3_t      dir;
00851 
00852     VectorCopy( ambientColor, color );
00853 
00854     // trace to all the lights
00855     for ( light = lights ; light ; light = light->next ) {
00856 
00857         //MrE: if the light is behind the surface
00858         if ( DotProduct(light->origin, normal) - DotProduct(normal, origin) < 0 )
00859             continue;
00860         // testing exact PTPFF
00861         if ( exactPointToPolygon && light->type == emit_area ) {
00862             float       factor;
00863             float       d;
00864             vec3_t      pushedOrigin;
00865 
00866             // see if the point is behind the light
00867             d = DotProduct( origin, light->normal ) - light->dist;
00868             if ( !light->twosided ) {
00869                 if ( d < -1 ) {
00870                     continue;       // point is behind light
00871                 }
00872             }
00873 
00874             // test occlusion and find light filters
00875             // clip the line, tracing from the surface towards the light
00876             if ( !notrace && testOcclusion ) {
00877                 TraceLine( origin, light->origin, &trace, qfalse, tw );
00878 
00879                 // other light rays must not hit anything
00880                 if ( trace.passSolid ) {
00881                     continue;
00882                 }
00883             } else {
00884                 trace.filter[0] = 1.0;
00885                 trace.filter[1] = 1.0;
00886                 trace.filter[2] = 1.0;
00887             }
00888 
00889             // nudge the point so that it is clearly forward of the light
00890             // so that surfaces meeting a light emiter don't get black edges
00891             if ( d > -8 && d < 8 ) {
00892                 VectorMA( origin, (8-d), light->normal, pushedOrigin ); 
00893             } else {
00894                 VectorCopy( origin, pushedOrigin );
00895             }
00896 
00897             // calculate the contribution
00898             factor = PointToPolygonFormFactor( pushedOrigin, normal, light->w );
00899             if ( factor <= 0 ) {
00900                 if ( light->twosided ) {
00901                     factor = -factor;
00902                 } else {
00903                     continue;
00904                 }
00905             }
00906             color[0] += factor * light->emitColor[0] * trace.filter[0];
00907             color[1] += factor * light->emitColor[1] * trace.filter[1];
00908             color[2] += factor * light->emitColor[2] * trace.filter[2];
00909 
00910             continue;
00911         }
00912 
00913         // calculate the amount of light at this sample
00914         if ( light->type == emit_point ) {
00915             VectorSubtract( light->origin, origin, dir );
00916             dist = VectorNormalize( dir, dir );
00917             // clamp the distance to prevent super hot spots
00918             if ( dist < 16 ) {
00919                 dist = 16;
00920             }
00921             angle = DotProduct( normal, dir );
00922             if ( light->linearLight ) {
00923                 add = angle * light->photons * linearScale - dist;
00924                 if ( add < 0 ) {
00925                     add = 0;
00926                 }
00927             } else {
00928                 add = light->photons / ( dist * dist ) * angle;
00929             }
00930         } else if ( light->type == emit_spotlight ) {
00931             float   distByNormal;
00932             vec3_t  pointAtDist;
00933             float   radiusAtDist;
00934             float   sampleRadius;
00935             vec3_t  distToSample;
00936             float   coneScale;
00937 
00938             VectorSubtract( light->origin, origin, dir );
00939 
00940             distByNormal = -DotProduct( dir, light->normal );
00941             if ( distByNormal < 0 ) {
00942                 continue;
00943             }
00944             VectorMA( light->origin, distByNormal, light->normal, pointAtDist );
00945             radiusAtDist = light->radiusByDist * distByNormal;
00946 
00947             VectorSubtract( origin, pointAtDist, distToSample );
00948             sampleRadius = VectorLength( distToSample );
00949 
00950             if ( sampleRadius >= radiusAtDist ) {
00951                 continue;       // outside the cone
00952             }
00953             if ( sampleRadius <= radiusAtDist - 32 ) {
00954                 coneScale = 1.0;    // fully inside
00955             } else {
00956                 coneScale = ( radiusAtDist - sampleRadius ) / 32.0;
00957             }
00958             
00959             dist = VectorNormalize( dir, dir );
00960             // clamp the distance to prevent super hot spots
00961             if ( dist < 16 ) {
00962                 dist = 16;
00963             }
00964             angle = DotProduct( normal, dir );
00965             add = light->photons / ( dist * dist ) * angle * coneScale;
00966 
00967         } else if ( light->type == emit_area ) {
00968             VectorSubtract( light->origin, origin, dir );
00969             dist = VectorNormalize( dir, dir );
00970             // clamp the distance to prevent super hot spots
00971             if ( dist < 16 ) {
00972                 dist = 16;
00973             }
00974             angle = DotProduct( normal, dir );
00975             if ( angle <= 0 ) {
00976                 continue;
00977             }
00978             angle *= -DotProduct( light->normal, dir );
00979             if ( angle <= 0 ) {
00980                 continue;
00981             }
00982 
00983             if ( light->linearLight ) {
00984                 add = angle * light->photons * linearScale - dist;
00985                 if ( add < 0 ) {
00986                     add = 0;
00987                 }
00988             } else {
00989                 add = light->photons / ( dist * dist ) * angle;
00990             }
00991         }
00992 
00993         if ( add <= 1.0 ) {
00994             continue;
00995         }
00996 
00997         // clip the line, tracing from the surface towards the light
00998         if ( !notrace && testOcclusion ) {
00999             TraceLine( origin, light->origin, &trace, qfalse, tw );
01000 
01001             // other light rays must not hit anything
01002             if ( trace.passSolid ) {
01003                 continue;
01004             }
01005         } else {
01006             trace.filter[0] = 1;
01007             trace.filter[1] = 1;
01008             trace.filter[2] = 1;
01009         }
01010         
01011         // add the result
01012         color[0] += add * light->color[0] * trace.filter[0];
01013         color[1] += add * light->color[1] * trace.filter[1];
01014         color[2] += add * light->color[2] * trace.filter[2];
01015     }
01016 
01017     //
01018     // trace directly to the sun
01019     //
01020     if ( testOcclusion || forceSunLight ) {
01021         SunToPlane( origin, normal, color, tw );
01022     }
01023 }

Here is the call graph for this function:

int LightMain int  argc,
char **  argv
 

Definition at line 2018 of file light.c.

References _printf(), areaScale, argc, argv, atof(), atoi, CountLightmaps(), CreateFilters(), CreateSurfaceLights(), DefaultExtension(), dump, entities, exit(), ExpandArg(), extra, extraWide, FindSkyBrushes(), gamedir, gridSize, i, I_FloatTime(), InitPakFile(), InitTrace(), lightmapBorder, LightWorld(), LoadBSPFile(), LoadShaderInfo(), nogridlighting, noSurfaces, notrace, novertexlighting, NULL, numthreads, ParseEntities(), patchshadows, pointScale, samplesize, SetEntityOrigins(), SetQdirFromPath(), source, sscanf(), strcmp(), strcpy(), StripExtension(), strlen(), ThreadSetDefault(), value, ValueForKey(), verbose, and WriteBSPFile().

Referenced by main().

02018                                       {
02019     int         i;
02020     double      start, end;
02021     const char  *value;
02022 
02023     _printf ("----- Lighting ----\n");
02024 
02025     verbose = qfalse;
02026 
02027     for (i=1 ; i<argc ; i++) {
02028         if (!strcmp(argv[i],"-tempname"))
02029     {
02030       i++;
02031     } else if (!strcmp(argv[i],"-v")) {
02032             verbose = qtrue;
02033         } else if (!strcmp(argv[i],"-threads")) {
02034             numthreads = atoi (argv[i+1]);
02035             i++;
02036         } else if (!strcmp(argv[i],"-area")) {
02037             areaScale *= atof(argv[i+1]);
02038             _printf ("area light scaling at %f\n", areaScale);
02039             i++;
02040         } else if (!strcmp(argv[i],"-point")) {
02041             pointScale *= atof(argv[i+1]);
02042             _printf ("point light scaling at %f\n", pointScale);
02043             i++;
02044         } else if (!strcmp(argv[i],"-notrace")) {
02045             notrace = qtrue;
02046             _printf ("No occlusion tracing\n");
02047         } else if (!strcmp(argv[i],"-patchshadows")) {
02048             patchshadows = qtrue;
02049             _printf ("Patch shadow casting enabled\n");
02050         } else if (!strcmp(argv[i],"-extra")) {
02051             extra = qtrue;
02052             _printf ("Extra detail tracing\n");
02053         } else if (!strcmp(argv[i],"-extrawide")) {
02054             extra = qtrue;
02055             extraWide = qtrue;
02056             _printf ("Extra wide detail tracing\n");
02057         } else if (!strcmp(argv[i], "-samplesize")) {
02058             samplesize = atoi(argv[i+1]);
02059             if (samplesize < 1) samplesize = 1;
02060             i++;
02061             _printf("lightmap sample size is %dx%d units\n", samplesize, samplesize);
02062         } else if (!strcmp(argv[i], "-novertex")) {
02063             novertexlighting = qtrue;
02064             _printf("no vertex lighting = true\n");
02065         } else if (!strcmp(argv[i], "-nogrid")) {
02066             nogridlighting = qtrue;
02067             _printf("no grid lighting = true\n");
02068         } else if (!strcmp(argv[i],"-border")) {
02069             lightmapBorder = qtrue;
02070             _printf ("Adding debug border to lightmaps\n");
02071         } else if (!strcmp(argv[i],"-nosurf")) {
02072             noSurfaces = qtrue;
02073             _printf ("Not tracing against surfaces\n" );
02074         } else if (!strcmp(argv[i],"-dump")) {
02075             dump = qtrue;
02076             _printf ("Dumping occlusion maps\n");
02077         } else {
02078             break;
02079         }
02080     }
02081 
02082     ThreadSetDefault ();
02083 
02084     if (i != argc - 1) {
02085         _printf("usage: q3map -light [-<switch> [-<switch> ...]] <mapname>\n"
02086                 "\n"
02087                 "Switches:\n"
02088                 "   v              = verbose output\n"
02089                 "   threads <X>    = set number of threads to X\n"
02090                 "   area <V>       = set the area light scale to V\n"
02091                 "   point <W>      = set the point light scale to W\n"
02092                 "   notrace        = don't cast any shadows\n"
02093                 "   extra          = enable super sampling for anti-aliasing\n"
02094                 "   extrawide      = same as extra but smoothen more\n"
02095                 "   nogrid         = don't calculate light grid for dynamic model lighting\n"
02096                 "   novertex       = don't calculate vertex lighting\n"
02097                 "   samplesize <N> = set the lightmap pixel size to NxN units\n");
02098         exit(0);
02099     }
02100 
02101     start = I_FloatTime ();
02102 
02103     SetQdirFromPath (argv[i]);  
02104 
02105 #ifdef _WIN32
02106     InitPakFile(gamedir, NULL);
02107 #endif
02108 
02109     strcpy (source, ExpandArg(argv[i]));
02110     StripExtension (source);
02111     DefaultExtension (source, ".bsp");
02112 
02113     LoadShaderInfo();
02114 
02115     _printf ("reading %s\n", source);
02116 
02117     LoadBSPFile (source);
02118 
02119     FindSkyBrushes();
02120 
02121     ParseEntities();
02122 
02123     value = ValueForKey( &entities[0], "gridsize" );
02124     if (strlen(value)) {
02125         sscanf( value, "%f %f %f", &gridSize[0], &gridSize[1], &gridSize[2] );
02126         _printf("grid size = {%1.1f, %1.1f, %1.1f}\n", gridSize[0], gridSize[1], gridSize[2]);
02127     }
02128 
02129     CreateFilters();
02130 
02131     InitTrace();
02132 
02133     SetEntityOrigins();
02134 
02135     CountLightmaps();
02136 
02137     CreateSurfaceLights();
02138 
02139     LightWorld();
02140 
02141     _printf ("writing %s\n", source);
02142     WriteBSPFile (source);
02143 
02144     end = I_FloatTime ();
02145     _printf ("%5.0f seconds elapsed\n", end-start);
02146     
02147     return 0;
02148 }

Here is the call graph for this function:

void LightWorld void   ) 
 

Definition at line 1803 of file light.c.

References ambientColor, c_occluded, c_visible, CreateEntityLights(), entities, f, FloatForKey(), GetVectorForKey(), gridBounds, numAreaLights, numDrawSurfaces, numGridPoints, numPointLights, qprintf(), qtrue, RunThreadsOnIndividual(), SetupGrid(), TraceGrid(), TraceLtm(), and VectorScale.

Referenced by LightMain().

01803                        {
01804     float       f;
01805 
01806     // determine the number of grid points
01807     SetupGrid();
01808 
01809     // find the optional world ambient
01810     GetVectorForKey( &entities[0], "_color", ambientColor );
01811     f = FloatForKey( &entities[0], "ambient" );
01812     VectorScale( ambientColor, f, ambientColor );
01813 
01814     // create lights out of patches and lights
01815     qprintf ("--- CreateLights ---\n");
01816     CreateEntityLights ();
01817     qprintf ("%i point lights\n", numPointLights);
01818     qprintf ("%i area lights\n", numAreaLights);
01819 
01820     if (!nogridlighting) {
01821         qprintf ("--- TraceGrid ---\n");
01822         RunThreadsOnIndividual( numGridPoints, qtrue, TraceGrid );
01823         qprintf( "%i x %i x %i = %i grid\n", gridBounds[0], gridBounds[1],
01824             gridBounds[2], numGridPoints);
01825     }
01826 
01827     qprintf ("--- TraceLtm ---\n");
01828     RunThreadsOnIndividual( numDrawSurfaces, qtrue, TraceLtm );
01829     qprintf( "%5i visible samples\n", c_visible );
01830     qprintf( "%5i occluded samples\n", c_occluded );
01831 }

Here is the call graph for this function:

mesh_t* LinearSubdivideMesh mesh_t in  ) 
 

Definition at line 1114 of file light.c.

References FreeMesh(), mesh_t::height, i, in, j, malloc(), drawVert_t::normal, v1, v2, VectorNormalize(), mesh_t::verts, mesh_t::width, and drawVert_t::xyz.

Referenced by TraceLtm().

01114                                           {
01115     int         i, j;
01116     mesh_t      *out;
01117     drawVert_t  *v1, *v2, *vout;
01118 
01119     out = malloc( sizeof( *out ) );
01120 
01121     out->width = in->width * 2;
01122     out->height = in->height;
01123     out->verts = malloc( out->width * out->height * sizeof(*out->verts) );
01124     for ( j = 0 ; j < in->height ; j++ ) {
01125         out->verts[ j * out->width + 0 ] = in->verts[ j * in->width + 0 ];
01126         out->verts[ j * out->width + out->width - 1 ] = in->verts[ j * in->width + in->width - 1 ];
01127         for ( i = 1 ; i < out->width - 1 ; i+= 2 ) {
01128             v1 = in->verts + j * in->width + (i >> 1);
01129             v2 = v1 + 1;
01130             vout = out->verts + j * out->width + i;
01131 
01132             vout->xyz[0] = 0.75 * v1->xyz[0] + 0.25 * v2->xyz[0];
01133             vout->xyz[1] = 0.75 * v1->xyz[1] + 0.25 * v2->xyz[1];
01134             vout->xyz[2] = 0.75 * v1->xyz[2] + 0.25 * v2->xyz[2];
01135 
01136             vout->normal[0] = 0.75 * v1->normal[0] + 0.25 * v2->normal[0];
01137             vout->normal[1] = 0.75 * v1->normal[1] + 0.25 * v2->normal[1];
01138             vout->normal[2] = 0.75 * v1->normal[2] + 0.25 * v2->normal[2];
01139 
01140             VectorNormalize( vout->normal, vout->normal );
01141 
01142             vout++;
01143 
01144             vout->xyz[0] = 0.25 * v1->xyz[0] + 0.75 * v2->xyz[0];
01145             vout->xyz[1] = 0.25 * v1->xyz[1] + 0.75 * v2->xyz[1];
01146             vout->xyz[2] = 0.25 * v1->xyz[2] + 0.75 * v2->xyz[2];
01147 
01148             vout->normal[0] = 0.25 * v1->normal[0] + 0.75 * v2->normal[0];
01149             vout->normal[1] = 0.25 * v1->normal[1] + 0.75 * v2->normal[1];
01150             vout->normal[2] = 0.25 * v1->normal[2] + 0.75 * v2->normal[2];
01151 
01152             VectorNormalize( vout->normal, vout->normal );
01153 
01154         }
01155     }
01156 
01157     FreeMesh( in );
01158 
01159     return out;
01160 }

Here is the call graph for this function:

float PointToPolygonFormFactor const vec3_t  point,
const vec3_t  normal,
const winding_t w
 

Definition at line 610 of file light.c.

References _printf(), acos(), CrossProduct(), dirs, DotProduct, i, j, winding_t::numpoints, winding_t::p, point, printed(), qboolean, vec3_t, VectorCopy, VectorNormalize(), VectorSubtract, and w.

Referenced by LightContributionToPoint(), LightingAtSample(), VL_LightSurfaceWithVolume(), and VS_LightSurfaceWithVolume().

00610                                                                                                 {
00611     vec3_t      triVector, triNormal;
00612     int         i, j;
00613     vec3_t      dirs[MAX_POINTS_ON_WINDING];
00614     float       total;
00615     float       dot, angle, facing;
00616 
00617     for ( i = 0 ; i < w->numpoints ; i++ ) {
00618         VectorSubtract( w->p[i], point, dirs[i] );
00619         VectorNormalize( dirs[i], dirs[i] );
00620     }
00621 
00622     // duplicate first vertex to avoid mod operation
00623     VectorCopy( dirs[0], dirs[i] );
00624 
00625     total = 0;
00626     for ( i = 0 ; i < w->numpoints ; i++ ) {
00627         j = i+1;
00628         dot = DotProduct( dirs[i], dirs[j] );
00629 
00630         // roundoff can cause slight creep, which gives an IND from acos
00631         if ( dot > 1.0 ) {
00632             dot = 1.0;
00633         } else if ( dot < -1.0 ) {
00634             dot = -1.0;
00635         }
00636         
00637         angle = acos( dot );
00638         CrossProduct( dirs[i], dirs[j], triVector );
00639         if ( VectorNormalize( triVector, triNormal ) < 0.0001 ) {
00640             continue;
00641         }
00642         facing = DotProduct( normal, triNormal );
00643         total += facing * angle;
00644 
00645         if ( total > 6.3 || total < -6.3 ) {
00646             static qboolean printed;
00647 
00648             if ( !printed ) {
00649                 printed = qtrue;
00650                 _printf( "WARNING: bad PointToPolygonFormFactor: %f at %1.1f %1.1f %1.1f from %1.1f %1.1f %1.1f\n", total,
00651                     w->p[i][0], w->p[i][1], w->p[i][2], point[0], point[1], point[2]);
00652             }
00653             return 0;
00654         }
00655 
00656     }
00657 
00658     total /= 2*3.141592657;     // now in the range of 0 to 1 over the entire incoming hemisphere
00659 
00660     return total;
00661 }

Here is the call graph for this function:

void PrintOccluded byte  occluded[LIGHTMAP_WIDTH *EXTRASCALE][LIGHTMAP_HEIGHT *EXTRASCALE],
int  width,
int  height
 

Definition at line 1032 of file light.c.

References _printf(), byte, i, and j.

Referenced by TraceLtm().

01033                                            {
01034     int i, j;
01035 
01036     _printf( "\n" );
01037 
01038     for ( i = 0 ; i < height ; i++ ) {
01039         for ( j = 0 ; j < width ; j++ ) {
01040             _printf("%i", (int)occluded[j][i] );
01041         }
01042         _printf( "\n" );
01043     }
01044 }

Here is the call graph for this function:

void RemoveLightsInSolid void   ) 
 

Definition at line 1769 of file light.c.

References _printf(), free(), FreeWinding(), light_t, lights, light_s::next, light_s::origin, PointInSolid(), and light_s::w.

01770 {
01771     light_t *light, *prev;
01772     int numsolid = 0;
01773 
01774     prev = NULL;
01775     for ( light = lights ; light ;  ) {
01776         if (PointInSolid(light->origin))
01777         {
01778             if (prev) prev->next = light->next;
01779             else lights = light->next;
01780             if (light->w)
01781                 FreeWinding(light->w);
01782             free(light);
01783             numsolid++;
01784             if (prev)
01785                 light = prev->next;
01786             else
01787                 light = lights;
01788         }
01789         else
01790         {
01791             prev = light;
01792             light = light->next;
01793         }
01794     }
01795     _printf (" %7i lights in solid\n", numsolid);
01796 }

Here is the call graph for this function:

void SetEntityOrigins void   ) 
 

Definition at line 560 of file light.c.

References atoi, dmodels, e, entities, entitySurface, dmodel_t::firstSurface, GetVectorForKey(), i, j, dmodel_t::numSurfaces, surfaceOrigin, ValueForKey(), vec3_t, and VectorCopy.

Referenced by LightMain(), VLightMain(), and VSoundMain().

00560                               {
00561     int         i, j;
00562     entity_t    *e;
00563     vec3_t      origin;
00564     const char  *key;
00565     int         modelnum;
00566     dmodel_t    *dm;
00567 
00568     for ( i=0 ; i < num_entities ; i++ ) {
00569         e = &entities[i];
00570         key = ValueForKey (e, "model");
00571         if ( key[0] != '*' ) {
00572             continue;
00573         }
00574         modelnum = atoi( key + 1 );
00575         dm = &dmodels[ modelnum ];
00576 
00577         // set entity surface to true for all surfaces for this model
00578         for ( j = 0 ; j < dm->numSurfaces ; j++ ) {
00579             entitySurface[ dm->firstSurface + j ] = qtrue;
00580         }
00581 
00582         key = ValueForKey (e, "origin");
00583         if ( !key[0] ) {
00584             continue;
00585         }
00586         GetVectorForKey ( e, "origin", origin );
00587 
00588         // set origin for all surfaces for this model
00589         for ( j = 0 ; j < dm->numSurfaces ; j++ ) {
00590             VectorCopy( origin, surfaceOrigin[ dm->firstSurface + j ] );
00591         }
00592     }
00593 }

Here is the call graph for this function:

void SetupGrid void   ) 
 

Definition at line 1746 of file light.c.

References ceil(), dmodels, Error(), floor(), gridBounds, gridMins, gridSize, i, numGridPoints, qprintf(), and vec3_t.

Referenced by GridAndVertexLighting(), and LightWorld().

01746                        {
01747     int     i;
01748     vec3_t  maxs;
01749 
01750     for ( i = 0 ; i < 3 ; i++ ) {
01751         gridMins[i] = gridSize[i] * ceil( dmodels[0].mins[i] / gridSize[i] );
01752         maxs[i] = gridSize[i] * floor( dmodels[0].maxs[i] / gridSize[i] );
01753         gridBounds[i] = (maxs[i] - gridMins[i])/gridSize[i] + 1;
01754     }
01755 
01756     numGridPoints = gridBounds[0] * gridBounds[1] * gridBounds[2];
01757     if (numGridPoints * 8 >= MAX_MAP_LIGHTGRID)
01758         Error("MAX_MAP_LIGHTGRID");
01759     qprintf( "%5i gridPoints\n", numGridPoints );
01760 }

Here is the call graph for this function:

void SubdivideAreaLight shaderInfo_t ls,
winding_t w,
vec3_t  normal,
float  areaSubdivide,
qboolean  backsplash
 

Definition at line 137 of file light.c.

References areaScale, shaderInfo_s::backsplashDistance, shaderInfo_s::backsplashFraction, ClipWindingEpsilon(), shaderInfo_s::color, shaderInfo_s::contents, DotProduct, formFactorValueScale, FreeWinding(), light_t, lights, malloc(), memset(), light_s::next, numAreaLights, ON_EPSILON, light_s::photons, qfalse, shaderInfo_t, light_s::type, shaderInfo_s::value, value, vec3_t, VectorAdd, VectorClear, VectorCopy, VectorMA, VectorScale, light_s::w, w, WindingArea(), WindingBounds(), and WindingCenter().

Referenced by CreateSurfaceLights().

00138                                                                    {
00139     float           area, value, intensity;
00140     light_t         *dl, *dl2;
00141     vec3_t          mins, maxs;
00142     int             axis;
00143     winding_t       *front, *back;
00144     vec3_t          planeNormal;
00145     float           planeDist;
00146 
00147     if ( !w ) {
00148         return;
00149     }
00150 
00151     WindingBounds( w, mins, maxs );
00152 
00153     // check for subdivision
00154     for ( axis = 0 ; axis < 3 ; axis++ ) {
00155         if ( maxs[axis] - mins[axis] > areaSubdivide ) {
00156             VectorClear( planeNormal );
00157             planeNormal[axis] = 1;
00158             planeDist = ( maxs[axis] + mins[axis] ) * 0.5;
00159             ClipWindingEpsilon ( w, planeNormal, planeDist, ON_EPSILON, &front, &back );
00160             SubdivideAreaLight( ls, front, normal, areaSubdivide, qfalse );
00161             SubdivideAreaLight( ls, back, normal, areaSubdivide, qfalse );
00162             FreeWinding( w );
00163             return;
00164         }
00165     }
00166 
00167     // create a light from this
00168     area = WindingArea (w);
00169     if ( area <= 0 || area > 20000000 ) {
00170         return;
00171     }
00172 
00173     numAreaLights++;
00174     dl = malloc(sizeof(*dl));
00175     memset (dl, 0, sizeof(*dl));
00176     dl->next = lights;
00177     lights = dl;
00178     dl->type = emit_area;
00179 
00180     WindingCenter( w, dl->origin );
00181     dl->w = w;
00182     VectorCopy ( normal, dl->normal);
00183     dl->dist = DotProduct( dl->origin, normal );
00184 
00185     value = ls->value;
00186     intensity = value * area * areaScale;
00187     VectorAdd( dl->origin, dl->normal, dl->origin );
00188 
00189     VectorCopy( ls->color, dl->color );
00190 
00191     dl->photons = intensity;
00192 
00193     // emitColor is irrespective of the area
00194     VectorScale( ls->color, value*formFactorValueScale*areaScale, dl->emitColor );
00195 
00196     dl->si = ls;
00197 
00198     if ( ls->contents & CONTENTS_FOG ) {
00199         dl->twosided = qtrue;
00200     }
00201 
00202     // optionally create a point backsplash light
00203     if ( backsplash && ls->backsplashFraction > 0 ) {
00204         dl2 = malloc(sizeof(*dl));
00205         memset (dl2, 0, sizeof(*dl2));
00206         dl2->next = lights;
00207         lights = dl2;
00208         dl2->type = emit_point;
00209 
00210         VectorMA( dl->origin, ls->backsplashDistance, normal, dl2->origin );
00211 
00212         VectorCopy( ls->color, dl2->color );
00213 
00214         dl2->photons = dl->photons * ls->backsplashFraction;
00215         dl2->si = ls;
00216     }
00217 }

Here is the call graph for this function:

void SunToPlane const vec3_t  origin,
const vec3_t  normal,
vec3_t  color,
traceWork_t tw
 

Definition at line 821 of file light.c.

References DotProduct, sunDirection, SunToPoint(), vec3_t, and VectorMA.

Referenced by LightingAtSample().

00821                                                                                            {
00822     float       angle;
00823     vec3_t      sunColor;
00824 
00825     if ( !numSkyBrushes ) {
00826         return;
00827     }
00828 
00829     angle = DotProduct( normal, sunDirection );
00830     if ( angle <= 0 ) {
00831         return;     // facing away
00832     }
00833 
00834     SunToPoint( origin, tw, sunColor );
00835     VectorMA( color, angle, sunColor, color );
00836 }

Here is the call graph for this function:

void SunToPoint const vec3_t  origin,
traceWork_t tw,
vec3_t  addLight
 

Definition at line 765 of file light.c.

References b, skyBrush_t::bounds, c_sunHit, c_sunMiss, trace_t::filter, trace_t::hit, i, MAX_WORLD_COORD, numthreads, qtrue, skyBrushes, sunDirection, sunLight, TraceLine(), vec3_t, VectorClear, and VectorMA.

Referenced by SunToPlane(), and TraceGrid().

00765                                                                          {
00766     int         i;
00767     trace_t     trace;
00768     skyBrush_t  *b;
00769     vec3_t      end;
00770 
00771     if ( !numSkyBrushes ) {
00772         VectorClear( addLight );
00773         return;
00774     }
00775 
00776     VectorMA( origin, MAX_WORLD_COORD * 2, sunDirection, end );
00777 
00778     TraceLine( origin, end, &trace, qtrue, tw );
00779 
00780     // see if trace.hit is inside a sky brush
00781     for ( i = 0 ; i < numSkyBrushes ; i++) {
00782         b = &skyBrushes[ i ];
00783 
00784         // this assumes that sky brushes are axial...
00785         if (   trace.hit[0] < b->bounds[0][0] 
00786             || trace.hit[0] > b->bounds[1][0]
00787             || trace.hit[1] < b->bounds[0][1]
00788             || trace.hit[1] > b->bounds[1][1]
00789             || trace.hit[2] < b->bounds[0][2]
00790             || trace.hit[2] > b->bounds[1][2] ) {
00791             continue;
00792         }
00793 
00794 
00795         // trace again to get intermediate filters
00796         TraceLine( origin, trace.hit, &trace, qtrue, tw );
00797 
00798         // we hit the sky, so add sunlight
00799         if ( numthreads == 1 ) {
00800             c_sunHit++;
00801         }
00802         addLight[0] = trace.filter[0] * sunLight[0];
00803         addLight[1] = trace.filter[1] * sunLight[1];
00804         addLight[2] = trace.filter[2] * sunLight[2];
00805 
00806         return;
00807     }
00808 
00809     if ( numthreads == 1 ) {
00810         c_sunMiss++;
00811     }
00812 
00813     VectorClear( addLight );
00814 }

Here is the call graph for this function:

void TraceGrid int  num  ) 
 

Definition at line 1591 of file light.c.

References add, ambientColor, ColorToBytes(), d, DotProduct, gridBounds, gridData, gridMins, gridSize, i, light_t, LightContributionToPoint(), MAX_CONTRIBUTIONS, light_s::next, NormalToLatLong(), light_s::origin, PointInSolid(), sunDirection, SunToPoint(), vec3_t, VectorClear, VectorCopy, VectorLength(), VectorMA, VectorNormalize(), VectorSubtract, x, y, and z.

Referenced by GridAndVertexLighting(), and LightWorld().

01591                           {
01592     int         x, y, z;
01593     vec3_t      origin;
01594     light_t     *light;
01595     vec3_t      color;
01596     int         mod;
01597     vec3_t      directedColor;
01598     vec3_t      summedDir;
01599     contribution_t  contributions[MAX_CONTRIBUTIONS];
01600     int         numCon;
01601     int         i;
01602     traceWork_t tw;
01603     float       addSize;
01604 
01605     mod = num;
01606     z = mod / ( gridBounds[0] * gridBounds[1] );
01607     mod -= z * ( gridBounds[0] * gridBounds[1] );
01608 
01609     y = mod / gridBounds[0];
01610     mod -= y * gridBounds[0];
01611 
01612     x = mod;
01613 
01614     origin[0] = gridMins[0] + x * gridSize[0];
01615     origin[1] = gridMins[1] + y * gridSize[1];
01616     origin[2] = gridMins[2] + z * gridSize[2];
01617 
01618     if ( PointInSolid( origin ) ) {
01619         vec3_t  baseOrigin;
01620         int     step;
01621 
01622         VectorCopy( origin, baseOrigin );
01623 
01624         // try to nudge the origin around to find a valid point
01625         for ( step = 9 ; step <= 18 ; step += 9 ) {
01626             for ( i = 0 ; i < 8 ; i++ ) {
01627                 VectorCopy( baseOrigin, origin );
01628                 if ( i & 1 ) {
01629                     origin[0] += step;
01630                 } else {
01631                     origin[0] -= step;
01632                 }
01633                 if ( i & 2 ) {
01634                     origin[1] += step;
01635                 } else {
01636                     origin[1] -= step;
01637                 }
01638                 if ( i & 4 ) {
01639                     origin[2] += step;
01640                 } else {
01641                     origin[2] -= step;
01642                 }
01643 
01644                 if ( !PointInSolid( origin ) ) {
01645                     break;
01646                 }
01647             }
01648             if ( i != 8 ) {
01649                 break;
01650             }
01651         }
01652         if ( step > 18 ) {
01653             // can't find a valid point at all
01654             for ( i = 0 ; i < 8 ; i++ ) {
01655                 gridData[ num*8 + i ] = 0;
01656             }
01657             return;
01658         }
01659     }
01660 
01661     VectorClear( summedDir );
01662 
01663     // trace to all the lights
01664 
01665     // find the major light direction, and divide the
01666     // total light between that along the direction and
01667     // the remaining in the ambient 
01668     numCon = 0;
01669     for ( light = lights ; light ; light = light->next ) {
01670         vec3_t      add;
01671         vec3_t      dir;
01672         float       addSize;
01673 
01674         if ( !LightContributionToPoint( light, origin, add, &tw ) ) {
01675             continue;
01676         }
01677 
01678         VectorSubtract( light->origin, origin, dir );
01679         VectorNormalize( dir, dir );
01680 
01681         VectorCopy( add, contributions[numCon].color );
01682         VectorCopy( dir, contributions[numCon].dir );
01683         numCon++;
01684 
01685         addSize = VectorLength( add );
01686         VectorMA( summedDir, addSize, dir, summedDir );
01687 
01688         if ( numCon == MAX_CONTRIBUTIONS-1 ) {
01689             break;
01690         }
01691     }
01692 
01693     //
01694     // trace directly to the sun
01695     //
01696     SunToPoint( origin, &tw, color );
01697     addSize = VectorLength( color );
01698     if ( addSize > 0 ) {
01699         VectorCopy( color, contributions[numCon].color );
01700         VectorCopy( sunDirection, contributions[numCon].dir );
01701         VectorMA( summedDir, addSize, sunDirection, summedDir );
01702         numCon++;
01703     }
01704 
01705 
01706     // now that we have identified the primary light direction,
01707     // go back and seperate all the light into directed and ambient
01708     VectorNormalize( summedDir, summedDir );
01709     VectorCopy( ambientColor, color );
01710     VectorClear( directedColor );
01711 
01712     for ( i = 0 ; i < numCon ; i++ ) {
01713         float   d;
01714 
01715         d = DotProduct( contributions[i].dir, summedDir );
01716         if ( d < 0 ) {
01717             d = 0;
01718         }
01719 
01720         VectorMA( directedColor, d, contributions[i].color, directedColor );
01721 
01722         // the ambient light will be at 1/4 the value of directed light
01723         d = 0.25 * ( 1.0 - d );
01724         VectorMA( color, d, contributions[i].color, color );
01725     }
01726 
01727     // now do some fudging to keep the ambient from being too low
01728     VectorMA( color, 0.25, directedColor, color );
01729 
01730     //
01731     // save the resulting value out
01732     //
01733     ColorToBytes( color, gridData + num*8 );
01734     ColorToBytes( directedColor, gridData + num*8 + 3 );
01735 
01736     VectorNormalize( summedDir, summedDir );
01737     NormalToLatLong( summedDir, gridData + num*8 + 6);
01738 }

Here is the call graph for this function:

void TraceLtm int  num  ) 
 

Definition at line 1196 of file light.c.

References byte, c_occluded, c_visible, ColorToBytes(), count, drawSurfaces, drawVerts, dshaders, Error(), dsurface_t::firstVert, shaderInfo_s::forceSunLight, FreeMesh(), mesh_t::height, i, j, k, lightBytes, LightingAtSample(), LIGHTMAP_HEIGHT, LIGHTMAP_WIDTH, dsurface_t::lightmapHeight, dsurface_t::lightmapNum, dsurface_t::lightmapOrigin, shaderInfo_s::lightmapSampleSize, dsurface_t::lightmapVecs, dsurface_t::lightmapWidth, dsurface_t::lightmapX, dsurface_t::lightmapY, LinearSubdivideMesh(), MakeMeshNormals(), MakeNormalVectors(), memset(), shaderInfo_s::noVertexShadows, numthreads, dsurface_t::patchHeight, shaderInfo_s::patchShadows, traceWork_t::patchshadows, dsurface_t::patchWidth, PointInSolid(), PrintOccluded(), PutMeshOnCurve(), qfalse, qtrue, RemoveLinearMeshColumnsRows(), shaderInfo_t, ShaderInfoForShader(), dsurface_t::shaderNum, SubdivideMesh(), SubdivideMeshQuads(), surfaceOrigin, dsurface_t::surfaceType, TransposeMesh(), value, vec3_t, VectorAdd, VectorClear, VectorCopy, VectorMA, VectorScale, VertexLighting(), shaderInfo_s::vertexScale, shaderInfo_s::vertexShadows, mesh_t::verts, mesh_t::width, x, and y.

Referenced by LightWorld(), VL_DoForcedTraceLight(), and VS_DoForcedTraceLight().

01196                          {
01197     dsurface_t  *ds;
01198     int         i, j, k;
01199     int         x, y;
01200     int         position, numPositions;
01201     vec3_t      base, origin, normal;
01202     byte        occluded[LIGHTMAP_WIDTH*EXTRASCALE][LIGHTMAP_HEIGHT*EXTRASCALE];
01203     vec3_t      color[LIGHTMAP_WIDTH*EXTRASCALE][LIGHTMAP_HEIGHT*EXTRASCALE];
01204     traceWork_t tw;
01205     vec3_t      average;
01206     int         count;
01207     mesh_t      srcMesh, *mesh, *subdivided;
01208     shaderInfo_t    *si;
01209     static float    nudge[2][9] = {
01210         { 0, -1, 0, 1, -1, 1, -1, 0, 1 },
01211         { 0, -1, -1, -1, 0, 0, 1, 1, 1 }
01212     };
01213     int         sampleWidth, sampleHeight, ssize;
01214     vec3_t      lightmapOrigin, lightmapVecs[2];
01215     int widthtable[LIGHTMAP_WIDTH], heighttable[LIGHTMAP_WIDTH];
01216 
01217     ds = &drawSurfaces[num];
01218     si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader );
01219 
01220     // vertex-lit triangle model
01221     if ( ds->surfaceType == MST_TRIANGLE_SOUP ) {
01222         VertexLighting( ds, !si->noVertexShadows, si->forceSunLight, 1.0, &tw );
01223         return;
01224     }
01225     
01226     if ( ds->lightmapNum == -1 ) {
01227         return;     // doesn't need lighting at all
01228     }
01229 
01230     if (!novertexlighting) {
01231         // calculate the vertex lighting for gouraud shade mode
01232         VertexLighting( ds, si->vertexShadows, si->forceSunLight, si->vertexScale, &tw );
01233     }
01234 
01235     if ( ds->lightmapNum < 0 ) {
01236         return;     // doesn't need lightmap lighting
01237     }
01238 
01239     si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader );
01240     ssize = samplesize;
01241     if (si->lightmapSampleSize)
01242         ssize = si->lightmapSampleSize;
01243 
01244     if (si->patchShadows)
01245         tw.patchshadows = qtrue;
01246     else
01247         tw.patchshadows = patchshadows;
01248 
01249     if ( ds->surfaceType == MST_PATCH ) {
01250         srcMesh.width = ds->patchWidth;
01251         srcMesh.height = ds->patchHeight;
01252         srcMesh.verts = drawVerts + ds->firstVert;
01253         mesh = SubdivideMesh( srcMesh, 8, 999 );
01254         PutMeshOnCurve( *mesh );
01255         MakeMeshNormals( *mesh );
01256 
01257         subdivided = RemoveLinearMeshColumnsRows( mesh );
01258         FreeMesh(mesh);
01259 
01260         mesh = SubdivideMeshQuads( subdivided, ssize, LIGHTMAP_WIDTH, widthtable, heighttable);
01261         if ( mesh->width != ds->lightmapWidth || mesh->height != ds->lightmapHeight ) {
01262             Error( "Mesh lightmap miscount");
01263         }
01264 
01265         if ( extra ) {
01266             mesh_t  *mp;
01267 
01268             // chop it up for more light samples (leaking memory...)
01269             mp = mesh;//CopyMesh( mesh );
01270             mp = LinearSubdivideMesh( mp );
01271             mp = TransposeMesh( mp );
01272             mp = LinearSubdivideMesh( mp );
01273             mp = TransposeMesh( mp );
01274 
01275             mesh = mp;
01276         }
01277     } else {
01278         VectorCopy( ds->lightmapVecs[2], normal );
01279 
01280         if ( !extra ) {
01281             VectorCopy( ds->lightmapOrigin, lightmapOrigin );
01282             VectorCopy( ds->lightmapVecs[0], lightmapVecs[0] );
01283             VectorCopy( ds->lightmapVecs[1], lightmapVecs[1] );
01284         } else {
01285             // sample at a closer spacing for antialiasing
01286             VectorCopy( ds->lightmapOrigin, lightmapOrigin );
01287             VectorScale( ds->lightmapVecs[0], 0.5, lightmapVecs[0] );
01288             VectorScale( ds->lightmapVecs[1], 0.5, lightmapVecs[1] );
01289             VectorMA( lightmapOrigin, -0.5, lightmapVecs[0], lightmapOrigin );
01290             VectorMA( lightmapOrigin, -0.5, lightmapVecs[1], lightmapOrigin );
01291         }
01292     }
01293 
01294     if ( extra ) {
01295         sampleWidth = ds->lightmapWidth * 2;
01296         sampleHeight = ds->lightmapHeight * 2;
01297     } else {
01298         sampleWidth = ds->lightmapWidth;
01299         sampleHeight = ds->lightmapHeight;
01300     }
01301 
01302     memset ( color, 0, sizeof( color ) );
01303 
01304     // determine which samples are occluded
01305     memset ( occluded, 0, sizeof( occluded ) );
01306     for ( i = 0 ; i < sampleWidth ; i++ ) {
01307         for ( j = 0 ; j < sampleHeight ; j++ ) {
01308 
01309             if ( ds->patchWidth ) {
01310                 numPositions = 9;
01311                 VectorCopy( mesh->verts[j*mesh->width+i].normal, normal );
01312                 // VectorNormalize( normal, normal );
01313                 // push off of the curve a bit
01314                 VectorMA( mesh->verts[j*mesh->width+i].xyz, 1, normal, base );
01315 
01316                 MakeNormalVectors( normal, lightmapVecs[0], lightmapVecs[1] );
01317             } else {
01318                 numPositions = 9;
01319                 for ( k = 0 ; k < 3 ; k++ ) {
01320                     base[k] = lightmapOrigin[k] + normal[k]
01321                         + i * lightmapVecs[0][k] 
01322                         + j * lightmapVecs[1][k];
01323                 }
01324             }
01325             VectorAdd( base, surfaceOrigin[ num ], base );
01326 
01327             // we may need to slightly nudge the sample point
01328             // if directly on a wall
01329             for ( position = 0 ; position < numPositions ; position++ ) {
01330                 // calculate lightmap sample position
01331                 for ( k = 0 ; k < 3 ; k++ ) {
01332                     origin[k] = base[k] + 
01333                         + ( nudge[0][position]/16 ) * lightmapVecs[0][k] 
01334                         + ( nudge[1][position]/16 ) * lightmapVecs[1][k];
01335                 }
01336 
01337                 if ( notrace ) {
01338                     break;
01339                 }
01340                 if ( !PointInSolid( origin ) ) {
01341                     break;
01342                 }
01343             }
01344 
01345             // if none of the nudges worked, this sample is occluded
01346             if ( position == numPositions ) {
01347                 occluded[i][j] = qtrue;
01348                 if ( numthreads == 1 ) {
01349                     c_occluded++;
01350                 }
01351                 continue;
01352             }
01353             
01354             if ( numthreads == 1 ) {
01355                 c_visible++;
01356             }
01357             occluded[i][j] = qfalse;
01358             LightingAtSample( origin, normal, color[i][j], qtrue, qfalse, &tw );
01359         }
01360     }
01361 
01362     if ( dump ) {
01363         PrintOccluded( occluded, sampleWidth, sampleHeight );
01364     }
01365 
01366     // calculate average values for occluded samples
01367     for ( i = 0 ; i < sampleWidth ; i++ ) {
01368         for ( j = 0 ; j < sampleHeight ; j++ ) {
01369             if ( !occluded[i][j] ) {
01370                 continue;
01371             }
01372             // scan all surrounding samples
01373             count = 0;
01374             VectorClear( average );
01375             for ( x = -1 ; x <= 1; x++ ) {
01376                 for ( y = -1 ; y <= 1 ; y++ ) {
01377                     if ( i + x < 0 || i + x >= sampleWidth ) {
01378                         continue;
01379                     }
01380                     if ( j + y < 0 || j + y >= sampleHeight ) {
01381                         continue;
01382                     }
01383                     if ( occluded[i+x][j+y] ) {
01384                         continue;
01385                     }
01386                     count++;
01387                     VectorAdd( color[i+x][j+y], average, average );
01388                 }
01389             }
01390             if ( count ) {
01391                 VectorScale( average, 1.0/count, color[i][j] );
01392             }
01393         }
01394     }
01395 
01396     // average together the values if we are extra sampling
01397     if ( ds->lightmapWidth != sampleWidth ) {
01398         for ( i = 0 ; i < ds->lightmapWidth ; i++ ) {
01399             for ( j = 0 ; j < ds->lightmapHeight ; j++ ) {
01400                 for ( k = 0 ; k < 3 ; k++ ) {
01401                     float       value, coverage;
01402 
01403                     value = color[i*2][j*2][k] + color[i*2][j*2+1][k] +
01404                         color[i*2+1][j*2][k] + color[i*2+1][j*2+1][k];
01405                     coverage = 4;
01406                     if ( extraWide ) {
01407                         // wider than box filter
01408                         if ( i > 0 ) {
01409                             value += color[i*2-1][j*2][k] + color[i*2-1][j*2+1][k];
01410                             value += color[i*2-2][j*2][k] + color[i*2-2][j*2+1][k];
01411                             coverage += 4;
01412                         }
01413                         if ( i < ds->lightmapWidth - 1 ) {
01414                             value += color[i*2+2][j*2][k] + color[i*2+2][j*2+1][k];
01415                             value += color[i*2+3][j*2][k] + color[i*2+3][j*2+1][k];
01416                             coverage += 4;
01417                         }
01418                         if ( j > 0 ) {
01419                             value += color[i*2][j*2-1][k] + color[i*2+1][j*2-1][k];
01420                             value += color[i*2][j*2-2][k] + color[i*2+1][j*2-2][k];
01421                             coverage += 4;
01422                         }
01423                         if ( j < ds->lightmapHeight - 1 ) {
01424                             value += color[i*2][j*2+2][k] + color[i*2+1][j*2+2][k];
01425                             value += color[i*2][j*2+3][k] + color[i*2+1][j*2+3][k];
01426                             coverage += 2;
01427                         }
01428                     }
01429 
01430                     color[i][j][k] = value / coverage;
01431                 }
01432             }
01433         }
01434     }
01435 
01436     // optionally create a debugging border around the lightmap
01437     if ( lightmapBorder ) {
01438         for ( i = 0 ; i < ds->lightmapWidth ; i++ ) {
01439             color[i][0][0] = 255;
01440             color[i][0][1] = 0;
01441             color[i][0][2] = 0;
01442 
01443             color[i][ds->lightmapHeight-1][0] = 255;
01444             color[i][ds->lightmapHeight-1][1] = 0;
01445             color[i][ds->lightmapHeight-1][2] = 0;
01446         }
01447         for ( i = 0 ; i < ds->lightmapHeight ; i++ ) {
01448             color[0][i][0] = 255;
01449             color[0][i][1] = 0;
01450             color[0][i][2] = 0;
01451 
01452             color[ds->lightmapWidth-1][i][0] = 255;
01453             color[ds->lightmapWidth-1][i][1] = 0;
01454             color[ds->lightmapWidth-1][i][2] = 0;
01455         }
01456     }
01457 
01458     // clamp the colors to bytes and store off
01459     for ( i = 0 ; i < ds->lightmapWidth ; i++ ) {
01460         for ( j = 0 ; j < ds->lightmapHeight ; j++ ) {
01461             k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + j) 
01462                 * LIGHTMAP_WIDTH + ds->lightmapX + i;
01463 
01464             ColorToBytes( color[i][j], lightBytes + k*3 );
01465         }
01466     }
01467 
01468     if (ds->surfaceType == MST_PATCH)
01469     {
01470         FreeMesh(mesh);
01471     }
01472 }

Here is the call graph for this function:

void TriSoupLightingThread int  num  ) 
 

Definition at line 1970 of file light.c.

References drawSurfaces, dshaders, shaderInfo_s::forceSunLight, shaderInfo_s::noVertexShadows, shaderInfo_t, ShaderInfoForShader(), dsurface_t::shaderNum, dsurface_t::surfaceType, and VertexLighting().

Referenced by GridAndVertexLighting().

01970                                     {
01971     dsurface_t  *ds;
01972     traceWork_t tw;
01973     shaderInfo_t *si;
01974 
01975     ds = &drawSurfaces[num];
01976     si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader );
01977 
01978     // vertex-lit triangle model
01979     if ( ds->surfaceType == MST_TRIANGLE_SOUP ) {
01980         VertexLighting( ds, !si->noVertexShadows, si->forceSunLight, 1.0, &tw );
01981     }
01982 }

Here is the call graph for this function:

void VertexLighting dsurface_t ds,
qboolean  testOcclusion,
qboolean  forceSunLight,
float  scale,
traceWork_t tw
 

Definition at line 1055 of file light.c.

References drawVert_t::color, drawVerts, dsurface_t::firstVert, i, j, LightingAtSample(), dsurface_t::lightmapVecs, max, drawVert_t::normal, dsurface_t::numVerts, dsurface_t::patchWidth, dsurface_t::surfaceType, vec3_t, VectorCopy, VectorScale, and drawVert_t::xyz.

Referenced by TraceLtm(), TriSoupLightingThread(), and VertexLightingThread().

01055                                                                                                                     {
01056     int         i, j;
01057     drawVert_t  *dv;
01058     vec3_t      sample, normal;
01059     float       max;
01060 
01061     VectorCopy( ds->lightmapVecs[2], normal );
01062 
01063     // generate vertex lighting
01064     for ( i = 0 ; i < ds->numVerts ; i++ ) {
01065         dv = &drawVerts[ ds->firstVert + i ];
01066 
01067         if ( ds->patchWidth ) {
01068             LightingAtSample( dv->xyz, dv->normal, sample, testOcclusion, forceSunLight, tw );
01069         }
01070         else if (ds->surfaceType == MST_TRIANGLE_SOUP) {
01071             LightingAtSample( dv->xyz, dv->normal, sample, testOcclusion, forceSunLight, tw );
01072         }
01073         else {
01074             LightingAtSample( dv->xyz, normal, sample, testOcclusion, forceSunLight, tw );
01075         }
01076 
01077         if (scale >= 0)
01078             VectorScale(sample, scale, sample);
01079         // clamp with color normalization
01080         max = sample[0];
01081         if ( sample[1] > max ) {
01082             max = sample[1];
01083         }
01084         if ( sample[2] > max ) {
01085             max = sample[2];
01086         }
01087         if ( max > 255 ) {
01088             VectorScale( sample, 255/max, sample );
01089         }
01090 
01091         // save the sample
01092         for ( j = 0 ; j < 3 ; j++ ) {
01093             if ( sample[j] > 255 ) {
01094                 sample[j] = 255;
01095             }
01096             dv->color[j] = sample[j];
01097         }
01098 
01099         // Don't bother writing alpha since it will already be set to 255,
01100         // plus we don't want to write over alpha generated by SetTerrainTextures
01101         //dv->color[3] = 255;
01102     }
01103 }

Here is the call graph for this function:

void VertexLightingThread int  num  ) 
 

Definition at line 1940 of file light.c.

References drawSurfaces, dshaders, shaderInfo_s::forceSunLight, dsurface_t::lightmapNum, shaderInfo_t, ShaderInfoForShader(), dsurface_t::shaderNum, dsurface_t::surfaceType, VertexLighting(), shaderInfo_s::vertexScale, and shaderInfo_s::vertexShadows.

Referenced by GridAndVertexLighting().

01940                                    {
01941     dsurface_t  *ds;
01942     traceWork_t tw;
01943     shaderInfo_t *si;
01944 
01945     ds = &drawSurfaces[num];
01946 
01947     // vertex-lit triangle model
01948     if ( ds->surfaceType == MST_TRIANGLE_SOUP ) {
01949         return;
01950     }
01951 
01952     if (novertexlighting)
01953         return;
01954 
01955     if ( ds->lightmapNum == -1 ) {
01956         return; // doesn't need lighting at all
01957     }
01958 
01959     si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader );
01960 
01961     // calculate the vertex lighting for gouraud shade mode
01962     VertexLighting( ds, si->vertexShadows, si->forceSunLight, si->vertexScale, &tw );
01963 }

Here is the call graph for this function:


Variable Documentation

vec3_t ambientColor
 

Definition at line 85 of file light.c.

Referenced by LightingAtSample(), LightWorld(), and TraceGrid().

float areaScale = 0.25
 

Definition at line 63 of file light.c.

Referenced by LightMain(), and SubdivideAreaLight().

int c_occluded
 

Definition at line 80 of file light.c.

Referenced by LightWorld(), and TraceLtm().

int c_sunHit
 

Definition at line 764 of file light.c.

Referenced by SunToPoint().

int c_sunMiss
 

Definition at line 764 of file light.c.

Referenced by SunToPoint().

int c_visible
 

Definition at line 80 of file light.c.

Referenced by LightWorld(), and TraceLtm().

int defaultLightSubdivide = 999
 

Definition at line 83 of file light.c.

qboolean dump
 

Definition at line 51 of file light.c.

Referenced by LightMain(), S_StartBackgroundTrack(), and Z_LogZoneHeap().

FILE* dumpFile
 

Definition at line 78 of file light.c.

int entitySurface[MAX_MAP_DRAW_SURFS]
 

Definition at line 88 of file light.c.

qboolean exactPointToPolygon = qtrue
 

Definition at line 68 of file light.c.

Referenced by LightContributionToPoint(), and LightingAtSample().

qboolean extra
 

Definition at line 52 of file light.c.

Referenced by LightMain(), and Z_TagMalloc().

qboolean extraWide
 

Definition at line 53 of file light.c.

Referenced by LightMain().

filter_t filters[MAX_FILTERS]
 

Definition at line 44 of file light.c.

Referenced by CreateFilters(), and FilterTrace().

float formFactorValueScale = 3
 

Definition at line 70 of file light.c.

Referenced by SubdivideAreaLight().

int gridBounds[3]
 

Definition at line 1479 of file light.c.

Referenced by LightWorld(), SetupGrid(), and TraceGrid().

vec3_t gridMins
 

Definition at line 1477 of file light.c.

Referenced by SetupGrid(), and TraceGrid().

vec3_t gridSize = { 64, 64, 128 }
 

Definition at line 1478 of file light.c.

Referenced by LightMain(), SetupGrid(), TraceGrid(), VLightMain(), and VSoundMain().

qboolean lightmapBorder
 

Definition at line 54 of file light.c.

Referenced by LightMain().

light_t* lights
 

Definition at line 74 of file light.c.

Referenced by CreateEntityLights(), CreateSurfaceLights(), RemoveLightsInSolid(), and SubdivideAreaLight().

float linearScale = 1.0 / 8000
 

Definition at line 72 of file light.c.

Referenced by LightContributionToPoint(), and LightingAtSample().

int nogridlighting = 0
 

Definition at line 60 of file light.c.

Referenced by LightMain(), and VLightMain().

qboolean noSurfaces
 

Definition at line 56 of file light.c.

Referenced by LightMain().

qboolean notrace
 

Definition at line 49 of file light.c.

Referenced by LightingAtSample(), and LightMain().

int novertexlighting = 0
 

Definition at line 59 of file light.c.

Referenced by LightMain(), and VLightMain().

int numAreaLights
 

Definition at line 76 of file light.c.

Referenced by LightWorld(), and SubdivideAreaLight().

int numFilters
 

Definition at line 45 of file light.c.

Referenced by CreateFilters().

int numPointLights
 

Definition at line 75 of file light.c.

Referenced by CreateEntityLights(), CreateSurfaceLights(), and LightWorld().

int numSkyBrushes
 

Definition at line 106 of file light.c.

Referenced by FindSkyBrushes().

qboolean patchshadows
 

Definition at line 50 of file light.c.

Referenced by LightMain().

float pointScale = 7500
 

Definition at line 66 of file light.c.

Referenced by LightMain().

int samplesize = 16
 

Definition at line 58 of file light.c.

Referenced by LightMain(), main(), VLightMain(), and VSoundMain().

skyBrush_t skyBrushes[MAX_MAP_BRUSHES]
 

Definition at line 107 of file light.c.

Referenced by FindSkyBrushes(), and SunToPoint().

char source[1024]
 

Definition at line 49 of file bspc.c.

vec3_t sunDirection = { 0.45, 0.3, 0.9 }
 

Definition at line 96 of file light.c.

Referenced by FindSkyBrushes(), SunToPlane(), SunToPoint(), and TraceGrid().

vec3_t sunLight = { 100, 100, 50 }
 

Definition at line 97 of file light.c.

Referenced by FindSkyBrushes(), and SunToPoint().

vec3_t surfaceOrigin[MAX_MAP_DRAW_SURFS]
 

Definition at line 87 of file light.c.

Referenced by SetEntityOrigins(), TraceLtm(), VL_GenerateFacetFor3Points(), VL_GenerateFacetFor4Points(), VL_LightmapMatrixFromPoints(), VS_GenerateFacetFor3Points(), VS_GenerateFacetFor4Points(), and VS_LightmapMatrixFromPoints().


Generated on Thu Aug 25 16:47:49 2005 for Quake III Arena by  doxygen 1.3.9.1