1 Index: tools/quake3/q3map2/light_ydnar.c
2 ===================================================================
3 --- tools/quake3/q3map2/light_ydnar.c (revision 191)
4 +++ tools/quake3/q3map2/light_ydnar.c (working copy)
6 float tests[ 4 ][ 2 ] = { { 0.0f, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } };
8 float stackLightLuxels[ STACK_LL_SIZE ];
13 /* bail if this number exceeds the number of raw lightmaps */
14 @@ -2223,6 +2332,78 @@
15 FreeTraceLights( &trace );
17 /* -----------------------------------------------------------------
19 + ----------------------------------------------------------------- */
23 + /* walk lightmaps */
24 + for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
27 + if( lm->superLuxels[ lightmapNum ] == NULL )
30 + /* apply floodlight to each luxel */
31 + for( y = 0; y < lm->sh; y++ )
33 + for( x = 0; x < lm->sw; x++ )
36 + cluster = SUPER_CLUSTER( x, y );
37 + //% if( *cluster < 0 )
40 + /* get particulars */
41 + luxel = SUPER_LUXEL( lightmapNum, x, y );
42 + floodlight = SUPER_FLOODLIGHT( x, y );
44 + flood[0]=floodlightRGB[0]*floodlightIntensity;
45 + flood[1]=floodlightRGB[1]*floodlightIntensity;
46 + flood[2]=floodlightRGB[2]*floodlightIntensity;
48 + /* scale light value */
49 + VectorScale( flood, *floodlight, flood );
54 + if (luxel[3]==0) luxel[3]=1;
62 + for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
65 + if( lm->superLuxels[ lightmapNum ] == NULL )
68 + for( y = 0; y < lm->sh; y++ )
70 + for( x = 0; x < lm->sw; x++ )
73 + cluster = SUPER_CLUSTER( x, y );
74 + //% if( *cluster < 0 )
77 + /* get particulars */
78 + luxel = SUPER_LUXEL( lightmapNum, x, y );
79 + normal = SUPER_NORMAL ( x, y );
81 + luxel[0]=(normal[0]*127)+127;
82 + luxel[1]=(normal[1]*127)+127;
83 + luxel[2]=(normal[2]*127)+127;
89 + /* -----------------------------------------------------------------
91 ----------------------------------------------------------------- */
93 @@ -3587,7 +3768,320 @@
94 CreateTraceLightsForBounds( mins, maxs, normal, info->numSurfaceClusters, &surfaceClusters[ info->firstSurfaceCluster ], LIGHT_SURFACES, trace );
97 +/////////////////////////////////////////////////////////////
99 +#define FLOODLIGHT_CONE_ANGLE 88 /* degrees */
100 +#define FLOODLIGHT_NUM_ANGLE_STEPS 16
101 +#define FLOODLIGHT_NUM_ELEVATION_STEPS 4
102 +#define FLOODLIGHT_NUM_VECTORS (FLOODLIGHT_NUM_ANGLE_STEPS * FLOODLIGHT_NUM_ELEVATION_STEPS)
104 +static vec3_t floodVectors[ FLOODLIGHT_NUM_VECTORS ];
105 +static int numFloodVectors = 0;
107 +void SetupFloodLight( void )
110 + float angle, elevation, angleStep, elevationStep;
112 + double v1,v2,v3,v4,v5;
115 + Sys_FPrintf( SYS_VRB, "--- SetupFloodLight ---\n" );
117 + /* calculate angular steps */
118 + angleStep = DEG2RAD( 360.0f / FLOODLIGHT_NUM_ANGLE_STEPS );
119 + elevationStep = DEG2RAD( FLOODLIGHT_CONE_ANGLE / FLOODLIGHT_NUM_ELEVATION_STEPS );
121 + /* iterate angle */
123 + for( i = 0, angle = 0.0f; i < FLOODLIGHT_NUM_ANGLE_STEPS; i++, angle += angleStep )
125 + /* iterate elevation */
126 + for( j = 0, elevation = elevationStep * 0.5f; j < FLOODLIGHT_NUM_ELEVATION_STEPS; j++, elevation += elevationStep )
128 + floodVectors[ numFloodVectors ][ 0 ] = sin( elevation ) * cos( angle );
129 + floodVectors[ numFloodVectors ][ 1 ] = sin( elevation ) * sin( angle );
130 + floodVectors[ numFloodVectors ][ 2 ] = cos( elevation );
135 + /* emit some statistics */
136 + Sys_FPrintf( SYS_VRB, "%9d numFloodVectors\n", numFloodVectors );
139 + value = ValueForKey( &entities[ 0 ], "_floodlight" );
141 + if( value[ 0 ] != '\0' )
144 + v4=floodlightDistance;
145 + v5=floodlightIntensity;
147 + sscanf( value, "%lf %lf %lf %lf %lf", &v1, &v2, &v3, &v4, &v5);
149 + floodlightRGB[0]=v1;
150 + floodlightRGB[1]=v2;
151 + floodlightRGB[2]=v3;
153 + if (VectorLength(floodlightRGB)==0)
155 + VectorSet(floodlightRGB,240,240,255);
161 + floodlightDistance=v4;
162 + floodlightIntensity=v5;
164 + floodlighty = qtrue;
165 + Sys_Printf( "FloodLighting enabled via worldspawn _floodlight key.\n" );
169 + VectorSet(floodlightRGB,240,240,255);
170 + //floodlighty = qtrue;
171 + //Sys_Printf( "FloodLighting enabled via worldspawn _floodlight key.\n" );
173 + VectorNormalize(floodlightRGB,floodlightRGB);
176 +//27 - lighttracer style ambient occlusion light hack.
177 +//Kudos to the dirtmapping author for most of this source.
178 +void FloodLightRawLightmap( int rawLightmapNum )
180 + int i, x, y, sx, sy, *cluster;
181 + float *origin, *normal, *floodlight, *floodlight2, average, samples;
183 + surfaceInfo_t *info;
186 + /* bail if this number exceeds the number of raw lightmaps */
187 + if( rawLightmapNum >= numRawLightmaps )
191 + lm = &rawLightmaps[ rawLightmapNum ];
193 + memset(&trace,0,sizeof(trace_t));
195 + trace.testOcclusion = qtrue;
196 + trace.forceSunlight = qfalse;
197 + trace.twoSided = qtrue;
198 + trace.recvShadows = lm->recvShadows;
199 + trace.numSurfaces = lm->numLightSurfaces;
200 + trace.surfaces = &lightSurfaces[ lm->firstLightSurface ];
201 + trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
202 + trace.testAll = qfalse;
203 + trace.distance = 1024;
205 + /* twosided lighting (may or may not be a good idea for lightmapped stuff) */
206 + //trace.twoSided = qfalse;
207 + for( i = 0; i < trace.numSurfaces; i++ )
210 + info = &surfaceInfos[ trace.surfaces[ i ] ];
212 + /* check twosidedness */
213 + if( info->si->twoSided )
215 + trace.twoSided = qtrue;
221 + for( y = 0; y < lm->sh; y++ )
223 + for( x = 0; x < lm->sw; x++ )
226 + cluster = SUPER_CLUSTER( x, y );
227 + origin = SUPER_ORIGIN( x, y );
228 + normal = SUPER_NORMAL( x, y );
229 + floodlight = SUPER_FLOODLIGHT( x, y );
231 + /* set default dirt */
232 + *floodlight = 0.0f;
234 + /* only look at mapped luxels */
238 + /* copy to trace */
239 + trace.cluster = *cluster;
240 + VectorCopy( origin, trace.origin );
241 + VectorCopy( normal, trace.normal );
246 + *floodlight = FloodLightForSample( &trace );
250 + /* testing no filtering */
253 + /* filter "dirt" */
254 + for( y = 0; y < lm->sh; y++ )
256 + for( x = 0; x < lm->sw; x++ )
259 + cluster = SUPER_CLUSTER( x, y );
260 + floodlight = SUPER_FLOODLIGHT( x, y );
262 + /* filter dirt by adjacency to unmapped luxels */
263 + average = *floodlight;
265 + for( sy = (y - 1); sy <= (y + 1); sy++ )
267 + if( sy < 0 || sy >= lm->sh )
270 + for( sx = (x - 1); sx <= (x + 1); sx++ )
272 + if( sx < 0 || sx >= lm->sw || (sx == x && sy == y) )
275 + /* get neighboring luxel */
276 + cluster = SUPER_CLUSTER( sx, sy );
277 + floodlight2 = SUPER_FLOODLIGHT( sx, sy );
278 + if( *cluster < 0 || *floodlight2 <= 0.0f )
282 + average += *floodlight2;
287 + if( samples <= 0.0f )
292 + if( samples <= 0.0f )
296 + *floodlight = average / samples;
302 +FloodLightForSample()
303 +calculates floodlight value for a given sample
304 +once again, kudos to the dirtmapping coder
306 +float FloodLightForSample( trace_t *trace )
310 + float contribution;
312 + float gatherLight, outLight;
313 + vec3_t normal, worldUp, myUp, myRt, direction, displacement;
321 + if( trace == NULL || trace->cluster < 0 )
326 + dd = floodlightDistance;
327 + VectorCopy( trace->normal, normal );
329 + /* check if the normal is aligned to the world-up */
330 + if( normal[ 0 ] == 0.0f && normal[ 1 ] == 0.0f )
332 + if( normal[ 2 ] == 1.0f )
334 + VectorSet( myRt, 1.0f, 0.0f, 0.0f );
335 + VectorSet( myUp, 0.0f, 1.0f, 0.0f );
337 + else if( normal[ 2 ] == -1.0f )
339 + VectorSet( myRt, -1.0f, 0.0f, 0.0f );
340 + VectorSet( myUp, 0.0f, 1.0f, 0.0f );
345 + VectorSet( worldUp, 0.0f, 0.0f, 1.0f );
346 + CrossProduct( normal, worldUp, myRt );
347 + VectorNormalize( myRt, myRt );
348 + CrossProduct( myRt, normal, myUp );
349 + VectorNormalize( myUp, myUp );
352 + /* iterate through ordered vectors */
353 + for( i = 0; i < numFloodVectors; i++ )
355 + if (floodlight_lowquality==qtrue)
357 + if (rand()%10 != 0 ) continue;
362 + /* transform vector into tangent space */
363 + direction[ 0 ] = myRt[ 0 ] * floodVectors[ i ][ 0 ] + myUp[ 0 ] * floodVectors[ i ][ 1 ] + normal[ 0 ] * floodVectors[ i ][ 2 ];
364 + direction[ 1 ] = myRt[ 1 ] * floodVectors[ i ][ 0 ] + myUp[ 1 ] * floodVectors[ i ][ 1 ] + normal[ 1 ] * floodVectors[ i ][ 2 ];
365 + direction[ 2 ] = myRt[ 2 ] * floodVectors[ i ][ 0 ] + myUp[ 2 ] * floodVectors[ i ][ 1 ] + normal[ 2 ] * floodVectors[ i ][ 2 ];
368 + VectorMA( trace->origin, dd, direction, trace->end );
370 + //VectorMA( trace->origin, 1, direction, trace->origin );
372 + SetupTrace( trace );
374 + TraceLine( trace );
377 + if (trace->compileFlags & C_SKY )
381 + else if ( trace->opaque )
383 + VectorSubtract( trace->hit, trace->origin, displacement );
384 + d=VectorLength( displacement );
386 + // d=trace->distance;
387 + //if (d>256) gatherDirt+=1;
389 + if (contribution>1) contribution=1.0f;
391 + //gatherDirt += 1.0f - ooDepth * VectorLength( displacement );
394 + gatherLight+=contribution;
398 + if( gatherLight <= 0.0f )
404 + gatherLight/=(sub);
406 + outLight=gatherLight;
407 + if( outLight > 1.0f )
410 + /* return to sender */
414 Index: tools/quake3/q3map2/light.c
415 ===================================================================
416 --- tools/quake3/q3map2/light.c (revision 191)
417 +++ tools/quake3/q3map2/light.c (working copy)
418 @@ -1378,6 +1378,56 @@
422 + /////// Floodlighting for point //////////////////
423 + //do our floodlight ambient occlusion loop, and add a single contribution based on the brightest dir
429 + col[0]=col[1]=col[2]=floodlightIntensity;
433 + trace.testOcclusion = qtrue;
434 + trace.forceSunlight = qfalse;
435 + trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
436 + trace.testAll = qtrue;
440 + if (q==0) //upper hemisphere
446 + else //lower hemisphere
450 + trace.normal[2]=-1;
453 + f = FloodLightForSample(&trace);
455 + contributions[ numCon ].color[0]=col[0]*f;
456 + contributions[ numCon ].color[1]=col[1]*f;
457 + contributions[ numCon ].color[2]=col[2]*f;
459 + contributions[ numCon ].dir[0]=dir[0];
460 + contributions[ numCon ].dir[1]=dir[1];
461 + contributions[ numCon ].dir[2]=dir[2];
463 + contributions[ numCon ].style = 0;
465 + /* push average direction around */
466 + addSize = VectorLength( col );
467 + VectorMA( gp->dir, addSize, dir, gp->dir );
470 + /////////////////////
472 /* normalize to get primary light direction */
473 VectorNormalize( gp->dir, gp->dir );
475 @@ -1661,6 +1711,12 @@
476 RunThreadsOnIndividual( numRawLightmaps, qtrue, DirtyRawLightmap );
479 + /* floodlight them up */
482 + Sys_Printf( "--- FloodlightRawLightmap ---\n" );
483 + RunThreadsOnIndividual( numRawLightmaps, qtrue, FloodLightRawLightmap );
486 /* ydnar: set up light envelopes */
487 SetupEnvelopes( qfalse, fast );
488 @@ -1703,6 +1759,7 @@
491 VectorClear( ambientColor );
492 + floodlighty = false;
494 /* generate diffuse lights */
496 @@ -2191,6 +2256,21 @@
498 Sys_Printf( "Enabling Challenge Pro Mode Asstacular Vertex Lighting Mode (tm)\n" );
500 + else if( !strcmp( argv[ i ], "-floodlight" ) )
502 + floodlighty = qtrue;
503 + Sys_Printf( "FloodLighting enabled\n" );
505 + else if( !strcmp( argv[ i ], "-debugnormals" ) )
507 + debugnormals = qtrue;
508 + Sys_Printf( "DebugNormals enabled\n" );
510 + else if( !strcmp( argv[ i ], "-lowquality" ) )
512 + floodlight_lowquality = qtrue;
513 + Sys_Printf( "Low Quality FloodLighting enabled\n" );
516 /* r7: dirtmapping */
517 else if( !strcmp( argv[ i ], "-dirty" ) )
518 @@ -2279,6 +2359,7 @@
519 /* ydnar: set up optimization */
523 SetupSurfaceLightmaps();
525 /* initialize the surface facet tracing */
526 Index: tools/quake3/q3map2/lightmaps_ydnar.c
527 ===================================================================
528 --- tools/quake3/q3map2/lightmaps_ydnar.c (revision 191)
529 +++ tools/quake3/q3map2/lightmaps_ydnar.c (working copy)
531 lm->superNormals = safe_malloc( size );
532 memset( lm->superNormals, 0, size );
534 + /* allocate floodlight map storage */
535 + size = lm->sw * lm->sh * SUPER_FLOODLIGHT_SIZE * sizeof( float );
536 + if( lm->superFloodLight == NULL )
537 + lm->superFloodLight = safe_malloc( size );
538 + memset( lm->superFloodLight, 0, size );
540 /* allocate cluster map storage */
541 size = lm->sw * lm->sh * sizeof( int );
542 if( lm->superClusters == NULL )
543 Index: tools/quake3/q3map2/q3map2.h
544 ===================================================================
545 --- tools/quake3/q3map2/q3map2.h (revision 191)
546 +++ tools/quake3/q3map2/q3map2.h (working copy)
548 #define SUPER_NORMAL_SIZE 4
549 #define SUPER_DELUXEL_SIZE 3
550 #define BSP_DELUXEL_SIZE 3
551 +#define SUPER_FLOODLIGHT_SIZE 1
553 #define VERTEX_LUXEL( s, v ) (vertexLuxels[ s ] + ((v) * VERTEX_LUXEL_SIZE))
554 #define RAD_VERTEX_LUXEL( s, v )(radVertexLuxels[ s ] + ((v) * VERTEX_LUXEL_SIZE))
556 #define SUPER_ORIGIN( x, y ) (lm->superOrigins + ((((y) * lm->sw) + (x)) * SUPER_ORIGIN_SIZE))
557 #define SUPER_NORMAL( x, y ) (lm->superNormals + ((((y) * lm->sw) + (x)) * SUPER_NORMAL_SIZE))
558 #define SUPER_DIRT( x, y ) (lm->superNormals + ((((y) * lm->sw) + (x)) * SUPER_NORMAL_SIZE) + 3) /* stash dirtyness in normal[ 3 ] */
559 +#define SUPER_FLOODLIGHT( x, y ) (lm->superFloodLight + ((((y) * lm->sw) + (x)) * SUPER_FLOODLIGHT_SIZE) )
563 @@ -1392,6 +1395,7 @@
565 float *superDeluxels; /* average light direction */
567 + float *superFloodLight;
571 @@ -1704,6 +1708,10 @@
572 float DirtForSample( trace_t *trace );
573 void DirtyRawLightmap( int num );
575 +void SetupFloodLight();
576 +float FloodLightForSample( trace_t *trace );
577 +void FloodLightRawLightmap( int num );
579 void IlluminateRawLightmap( int num );
580 void IlluminateVertexes( int num );
582 @@ -2098,6 +2106,13 @@
583 Q_EXTERN float dirtScale Q_ASSIGN( 1.0f );
584 Q_EXTERN float dirtGain Q_ASSIGN( 1.0f );
586 +Q_EXTERN qboolean debugnormals Q_ASSIGN( qfalse );
587 +Q_EXTERN qboolean floodlighty Q_ASSIGN( qfalse );
588 +Q_EXTERN qboolean floodlight_lowquality Q_ASSIGN( qfalse );
589 +Q_EXTERN vec3_t floodlightRGB;
590 +Q_EXTERN float floodlightIntensity Q_ASSIGN( 512 );
591 +Q_EXTERN float floodlightDistance Q_ASSIGN( 1024 );
593 Q_EXTERN qboolean dump Q_ASSIGN( qfalse );
594 Q_EXTERN qboolean debug Q_ASSIGN( qfalse );
595 Q_EXTERN qboolean debugUnused Q_ASSIGN( qfalse );