00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "light.h"
00025 #ifdef _WIN32
00026 #ifdef _TTIMOBUILD
00027 #include "pakstuff.h"
00028 #else
00029 #include "../libs/pakstuff.h"
00030 #endif
00031 #endif
00032
00033
00034 #define EXTRASCALE 2
00035
00036 typedef struct {
00037 float plane[4];
00038 vec3_t origin;
00039 vec3_t vectors[2];
00040 shaderInfo_t *si;
00041 } filter_t;
00042
00043 #define MAX_FILTERS 1024
00044 filter_t filters[MAX_FILTERS];
00045 int numFilters;
00046
00047 extern char source[1024];
00048
00049 qboolean notrace;
00050 qboolean patchshadows;
00051 qboolean dump;
00052 qboolean extra;
00053 qboolean extraWide;
00054 qboolean lightmapBorder;
00055
00056 qboolean noSurfaces;
00057
00058 int samplesize = 16;
00059 int novertexlighting = 0;
00060 int nogridlighting = 0;
00061
00062
00063 float areaScale = 0.25;
00064
00065
00066 float pointScale = 7500;
00067
00068 qboolean exactPointToPolygon = qtrue;
00069
00070 float formFactorValueScale = 3;
00071
00072 float linearScale = 1.0 / 8000;
00073
00074 light_t *lights;
00075 int numPointLights;
00076 int numAreaLights;
00077
00078 FILE *dumpFile;
00079
00080 int c_visible, c_occluded;
00081
00082
00083 int defaultLightSubdivide = 999;
00084
00085 vec3_t ambientColor;
00086
00087 vec3_t surfaceOrigin[ MAX_MAP_DRAW_SURFS ];
00088 int entitySurface[ MAX_MAP_DRAW_SURFS ];
00089
00090
00091
00092
00093
00094
00095
00096 vec3_t sunDirection = { 0.45, 0.3, 0.9 };
00097 vec3_t sunLight = { 100, 100, 50 };
00098
00099
00100
00101 typedef struct {
00102 dbrush_t *b;
00103 vec3_t bounds[2];
00104 } skyBrush_t;
00105
00106 int numSkyBrushes;
00107 skyBrush_t skyBrushes[MAX_MAP_BRUSHES];
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 #define MAX_FACE_POINTS 128
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 void SubdivideAreaLight( shaderInfo_t *ls, winding_t *w, vec3_t normal,
00138 float areaSubdivide, qboolean backsplash ) {
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
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
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
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
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 }
00218
00219
00220
00221
00222
00223
00224
00225 void CountLightmaps( void ) {
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
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 }
00249
00250
00251
00252
00253
00254
00255
00256
00257 void CreateSurfaceLights( void ) {
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
00275 ds = &drawSurfaces[i];
00276
00277 ls = ShaderInfoForShader( dshaders[ ds->shaderNum].shader );
00278 if ( ls->value == 0 ) {
00279 continue;
00280 }
00281
00282
00283 if ( ls->lightSubdivide ) {
00284 lightSubdivide = ls->lightSubdivide;
00285 } else {
00286 lightSubdivide = defaultLightSubdivide;
00287 }
00288
00289 c_lightSurfaces++;
00290
00291
00292
00293 if ( ls->autosprite ) {
00294
00295 if ( surfaceTest[i] ) {
00296
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
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
00336 for ( side = 0 ; side <= ls->twoSided ; side++ ) {
00337
00338 if ( surfaceTest[i] ) {
00339
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
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 }
00381
00382
00383
00384
00385
00386
00387
00388
00389 void FindSkyBrushes( void ) {
00390 int i, j;
00391 dbrush_t *b;
00392 skyBrush_t *sb;
00393 shaderInfo_t *si;
00394 dbrushside_t *s;
00395
00396
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
00417 VectorNormalize( sunDirection, sunDirection );
00418
00419
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 }
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443 entity_t *FindTargetEntity( const char *target ) {
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 }
00456
00457
00458
00459
00460
00461
00462
00463
00464 void CreateEntityLights (void)
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
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
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 }
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560 void SetEntityOrigins( void ) {
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
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
00589 for ( j = 0 ; j < dm->numSurfaces ; j++ ) {
00590 VectorCopy( origin, surfaceOrigin[ dm->firstSurface + j ] );
00591 }
00592 }
00593 }
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603 #define MAX_POINTS_ON_WINDINGS 64
00604
00605
00606
00607
00608
00609
00610 float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const winding_t *w ) {
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
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
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;
00659
00660 return total;
00661 }
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671 void FilterTrace( const vec3_t start, const vec3_t end, vec3_t filter ) {
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
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
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
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
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 }
00756
00757
00758
00759
00760
00761
00762
00763
00764 int c_sunHit, c_sunMiss;
00765 void SunToPoint( const vec3_t origin, traceWork_t *tw, vec3_t addLight ) {
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
00781 for ( i = 0 ; i < numSkyBrushes ; i++) {
00782 b = &skyBrushes[ i ];
00783
00784
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
00796 TraceLine( origin, trace.hit, &trace, qtrue, tw );
00797
00798
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 }
00815
00816
00817
00818
00819
00820
00821 void SunToPlane( const vec3_t origin, const vec3_t normal, vec3_t color, traceWork_t *tw ) {
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;
00832 }
00833
00834 SunToPoint( origin, tw, sunColor );
00835 VectorMA( color, angle, sunColor, color );
00836 }
00837
00838
00839
00840
00841
00842
00843 void LightingAtSample( vec3_t origin, vec3_t normal, vec3_t color,
00844 qboolean testOcclusion, qboolean forceSunLight, traceWork_t *tw ) {
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
00855 for ( light = lights ; light ; light = light->next ) {
00856
00857
00858 if ( DotProduct(light->origin, normal) - DotProduct(normal, origin) < 0 )
00859 continue;
00860
00861 if ( exactPointToPolygon && light->type == emit_area ) {
00862 float factor;
00863 float d;
00864 vec3_t pushedOrigin;
00865
00866
00867 d = DotProduct( origin, light->normal ) - light->dist;
00868 if ( !light->twosided ) {
00869 if ( d < -1 ) {
00870 continue;
00871 }
00872 }
00873
00874
00875
00876 if ( !notrace && testOcclusion ) {
00877 TraceLine( origin, light->origin, &trace, qfalse, tw );
00878
00879
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
00890
00891 if ( d > -8 && d < 8 ) {
00892 VectorMA( origin, (8-d), light->normal, pushedOrigin );
00893 } else {
00894 VectorCopy( origin, pushedOrigin );
00895 }
00896
00897
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
00914 if ( light->type == emit_point ) {
00915 VectorSubtract( light->origin, origin, dir );
00916 dist = VectorNormalize( dir, dir );
00917
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;
00952 }
00953 if ( sampleRadius <= radiusAtDist - 32 ) {
00954 coneScale = 1.0;
00955 } else {
00956 coneScale = ( radiusAtDist - sampleRadius ) / 32.0;
00957 }
00958
00959 dist = VectorNormalize( dir, dir );
00960
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
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
00998 if ( !notrace && testOcclusion ) {
00999 TraceLine( origin, light->origin, &trace, qfalse, tw );
01000
01001
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
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
01019
01020 if ( testOcclusion || forceSunLight ) {
01021 SunToPlane( origin, normal, color, tw );
01022 }
01023 }
01024
01025
01026
01027
01028
01029
01030
01031
01032 void PrintOccluded( byte occluded[LIGHTMAP_WIDTH*EXTRASCALE][LIGHTMAP_HEIGHT*EXTRASCALE],
01033 int width, int height ) {
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 }
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055 void VertexLighting( dsurface_t *ds, qboolean testOcclusion, qboolean forceSunLight, float scale, traceWork_t *tw ) {
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
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
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
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
01100
01101
01102 }
01103 }
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114 mesh_t *LinearSubdivideMesh( mesh_t *in ) {
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 }
01161
01162
01163
01164
01165
01166
01167 void ColorToBytes( const float *color, byte *colorBytes ) {
01168 float max;
01169 vec3_t sample;
01170
01171 VectorCopy( color, sample );
01172
01173
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 }
01188
01189
01190
01191
01192
01193
01194
01195
01196 void TraceLtm( int num ) {
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
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;
01228 }
01229
01230 if (!novertexlighting) {
01231
01232 VertexLighting( ds, si->vertexShadows, si->forceSunLight, si->vertexScale, &tw );
01233 }
01234
01235 if ( ds->lightmapNum < 0 ) {
01236 return;
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
01269 mp = 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
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
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
01313
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
01328
01329 for ( position = 0 ; position < numPositions ; position++ ) {
01330
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
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
01367 for ( i = 0 ; i < sampleWidth ; i++ ) {
01368 for ( j = 0 ; j < sampleHeight ; j++ ) {
01369 if ( !occluded[i][j] ) {
01370 continue;
01371 }
01372
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