/* create a light */
numSunLights++;
- light = safe_malloc( sizeof( *light ) );
- memset( light, 0, sizeof( *light ) );
+ light = safe_malloc0( sizeof( *light ) );
light->next = lights;
lights = light;
/* create a light */
numPointLights++;
- light = safe_malloc( sizeof( *light ) );
- memset( light, 0, sizeof( *light ) );
+ light = safe_malloc0( sizeof( *light ) );
light->next = lights;
lights = light;
/* get target */
e2 = FindTargetEntity( target );
if ( e2 == NULL ) {
- Sys_Printf( "WARNING: light at (%i %i %i) has missing target\n",
+ Sys_FPrintf( SYS_WRN, "WARNING: light at (%i %i %i) has missing target\n",
(int) light->origin[ 0 ], (int) light->origin[ 1 ], (int) light->origin[ 2 ] );
light->photons *= pointScale;
}
VectorScale( origin, 0.5f, origin );
/* create a light */
- light = safe_malloc( sizeof( *light ) );
- memset( light, 0, sizeof( *light ) );
+ light = safe_malloc0( sizeof( *light ) );
light->next = lights;
lights = light;
/* return to sender */
return 1;
}
- else{
+ else {
Error( "Light of undefined type!" );
}
}
/* vortex: apply gridscale and gridambientscale here */
- ColorToBytes( color, bgp->ambient[ i ], gridScale * gridAmbientScale );
+ if (gp->directed[i][0] || gp->directed[i][1] || gp->directed[i][2]) {
+ /*
+ * HACK: if there's a non-zero directed component, this
+ * lightgrid cell is useful. However, ioq3 skips grid
+ * cells with zero ambient. So let's force ambient to be
+ * nonzero unless directed is zero too.
+ */
+ ColorToBytesNonZero(color, bgp->ambient[i], gridScale * gridAmbientScale);
+ } else {
+ ColorToBytes(color, bgp->ambient[i], gridScale * gridAmbientScale);
+ }
ColorToBytes( gp->directed[ i ], bgp->directed[ i ], gridScale );
}
numBSPGridPoints = numRawGridPoints;
/* allocate lightgrid */
- rawGridPoints = safe_malloc( numRawGridPoints * sizeof( *rawGridPoints ) );
- memset( rawGridPoints, 0, numRawGridPoints * sizeof( *rawGridPoints ) );
+ rawGridPoints = safe_malloc0( numRawGridPoints * sizeof( *rawGridPoints ) );
if ( bspGridPoints != NULL ) {
free( bspGridPoints );
}
- bspGridPoints = safe_malloc( numBSPGridPoints * sizeof( *bspGridPoints ) );
- memset( bspGridPoints, 0, numBSPGridPoints * sizeof( *bspGridPoints ) );
+ bspGridPoints = safe_malloc0( numBSPGridPoints * sizeof( *bspGridPoints ) );
/* clear lightgrid */
for ( i = 0; i < numRawGridPoints; i++ )
does what it says...
*/
-void LightWorld( void ){
+void LightWorld( const char *BSPFilePath, qboolean fastLightmapSearch, qboolean noBounceStore ){
vec3_t color;
float f;
int b, bt;
qboolean minVertex, minGrid;
const char *value;
-
/* ydnar: smooth normals */
if ( shade ) {
Sys_Printf( "--- SmoothNormals ---\n" );
/* find the optional minimum lighting values */
GetVectorForKey( &entities[ 0 ], "_color", color );
+ if ( VectorLength( color ) == 0.0f ) {
+ VectorSet( color, 1.0, 1.0, 1.0 );
+ }
+
if ( colorsRGB ) {
color[0] = Image_LinearFloatFromsRGBFloat( color[0] );
color[1] = Image_LinearFloatFromsRGBFloat( color[1] );
color[2] = Image_LinearFloatFromsRGBFloat( color[2] );
}
- if ( VectorLength( color ) == 0.0f ) {
- VectorSet( color, 1.0, 1.0, 1.0 );
- }
/* ambient */
f = FloatForKey( &entities[ 0 ], "_ambient" );
/* radiosity */
b = 1;
bt = bounce;
+
while ( bounce > 0 )
{
+ qboolean storeForReal = !noBounceStore;
+
/* store off the bsp between bounces */
- StoreSurfaceLightmaps();
+ StoreSurfaceLightmaps( fastLightmapSearch, storeForReal );
UnparseEntities();
- Sys_Printf( "Writing %s\n", source );
- WriteBSPFile( source );
+
+ if ( storeForReal ) {
+ Sys_Printf( "Writing %s\n", BSPFilePath );
+ WriteBSPFile( BSPFilePath );
+ }
/* note it */
Sys_Printf( "\n--- Radiosity (bounce %d of %d) ---\n", b, bt );
SetupEnvelopes( qfalse, fastbounce );
if ( numLights == 0 ) {
Sys_Printf( "No diffuse light to calculate, ending radiosity.\n" );
- break;
+ if ( noBounceStore ) {
+ break;
+ }
+ return;
}
/* add to lightgrid */
bounce--;
b++;
}
+
+ /* ydnar: store off lightmaps */
+ StoreSurfaceLightmaps( fastLightmapSearch, qtrue );
+}
+
+
+
+/*
+ LoadSurfaceFlags()
+ added by spoon to get back the changed surfaceflags
+ from tex file
+*/
+
+void LoadSurfaceFlags( char *filename ) {
+ int i;
+
+ for( i = 0; i < numBSPShaders; i++ ) {
+ shaderInfo_t *si;
+
+ si = ShaderInfoForShader( bspShaders[i].shader );
+
+ bspShaders[ i ].surfaceFlags = si->surfaceFlags;
+ }
}
int LightMain( int argc, char **argv ){
int i;
float f;
- char mapSource[ 1024 ];
+ char BSPFilePath[ 1024 ];
+ char surfaceFilePath[ 1024 ];
+ BSPFilePath[0] = 0;
+ surfaceFilePath[0] = 0;
const char *value;
int lightmapMergeSize = 0;
qboolean lightSamplesInsist = qfalse;
-
+ qboolean fastLightmapSearch = qfalse;
+ qboolean noBounceStore = qfalse;
/* note it */
Sys_Printf( "--- Light ---\n" );
}
i++;
}
+
else if ( !strcmp( argv[ i ], "-deluxe" ) || !strcmp( argv[ i ], "-deluxemap" ) ) {
deluxemap = qtrue;
Sys_Printf( "Generating deluxemaps for average light direction\n" );
/* must be a power of 2 and greater than 2 */
if ( ( ( lmCustomSize - 1 ) & lmCustomSize ) || lmCustomSize < 2 ) {
- Sys_Printf( "WARNING: Lightmap size must be a power of 2, greater or equal to 2 pixels.\n" );
+ Sys_FPrintf( SYS_WRN, "WARNING: Lightmap size must be a power of 2, greater or equal to 2 pixels.\n" );
lmCustomSize = game->lightmapSize;
}
i++;
else if ( !strcmp( argv[ i ], "-lightmapdir" ) ) {
lmCustomDir = argv[i + 1];
+ argv[ i ] = NULL;
i++;
+ argv[ i ] = NULL;
Sys_Printf( "Lightmap directory set to %s\n", lmCustomDir );
externalLightmaps = qtrue;
Sys_Printf( "Storing all lightmaps externally\n" );
Sys_Printf( "Storing bounced light (radiosity) only\n" );
}
+ else if ( !strcmp( argv[ i ], "-nobouncestore" ) ) {
+ noBounceStore = qtrue;
+ Sys_Printf( "Do not store BSP, lightmap and shader files between bounces\n" );
+ }
+
else if ( !strcmp( argv[ i ], "-nocollapse" ) ) {
noCollapse = qtrue;
Sys_Printf( "Identical lightmap collapsing disabled\n" );
Sys_Printf( "Faster mode enabled\n" );
}
+ else if ( !strcmp( argv[ i ], "-fastlightmapsearch" ) || !strcmp( argv[ i ], "-fastallocate") ) {
+ fastLightmapSearch = qtrue;
+
+ if ( !strcmp( argv[ i ], "-fastallocate" ) ) {
+ Sys_Printf( "The -fastallocate argument is deprecated, use \"-fastlightmapsearch\" instead\n" );
+ }
+ else {
+ Sys_Printf( "Fast lightmap search enabled\n" );
+ }
+ }
+
else if ( !strcmp( argv[ i ], "-fastgrid" ) ) {
fastgrid = qtrue;
Sys_Printf( "Fast grid lighting enabled\n" );
loMem = qtrue;
Sys_Printf( "Enabling low-memory (potentially slower) lighting mode\n" );
}
+ else if ( !strcmp( argv[ i ], "-lightsubdiv" ) ) {
+ defaultLightSubdivide = atoi( argv[ i + 1 ] );
+ if ( defaultLightSubdivide < 1 ) {
+ defaultLightSubdivide = 1;
+ }
+ i++;
+ Sys_Printf( "Default light subdivision set to %d\n", defaultLightSubdivide );
+ }
else if ( !strcmp( argv[ i ], "-lightanglehl" ) ) {
if ( ( atoi( argv[ i + 1 ] ) != 0 ) != lightAngleHL ) {
lightAngleHL = ( atoi( argv[ i + 1 ] ) != 0 );
Sys_Printf( "Disabling half lambert light angle attenuation\n" );
}
}
+ i++;
}
else if ( !strcmp( argv[ i ], "-nostyle" ) || !strcmp( argv[ i ], "-nostyles" ) ) {
noStyles = qtrue;
lightmapFill = qtrue;
Sys_Printf( "Filling lightmap colors from surrounding pixels to improve JPEG compression\n" );
}
+ else if ( !strcmp( argv[ i ], "-bspfile" ) )
+ {
+ strcpy( BSPFilePath, argv[i + 1] );
+ argv[ i ] = NULL;
+ i++;
+ argv[ i ] = NULL;
+ Sys_Printf( "Use %s as bsp file\n", BSPFilePath );
+ }
+ else if ( !strcmp( argv[ i ], "-srffile" ) )
+ {
+ strcpy( surfaceFilePath, argv[i + 1] );
+ argv[ i ] = NULL;
+ i++;
+ argv[ i ] = NULL;
+ Sys_Printf( "Use %s as surface file\n", surfaceFilePath );
+ }
/* unhandled args */
else
{
- Sys_Printf( "WARNING: Unknown argument \"%s\"\n", argv[ i ] );
+ Sys_FPrintf( SYS_WRN, "WARNING: Unknown argument \"%s\"\n", argv[ i ] );
}
}
Sys_Printf( "Restricted lightmap searching enabled - block size adjusted to %d\n", lightmapSearchBlockSize );
}
- /* clean up map name */
+ /* arg checking */
+ if ( i != ( argc - 1 ) ) {
+ Error( "usage: q3map -light [options] <bspfile>" );
+ }
+
strcpy( source, ExpandArg( argv[ i ] ) );
StripExtension( source );
- DefaultExtension( source, ".bsp" );
- strcpy( mapSource, ExpandArg( argv[ i ] ) );
- StripExtension( mapSource );
- DefaultExtension( mapSource, ".map" );
+ DefaultExtension( source, ".map" );
+
+ if (!BSPFilePath[0]) {
+ strcpy( BSPFilePath, ExpandArg( argv[ i ] ) );
+ StripExtension( BSPFilePath );
+ DefaultExtension( BSPFilePath, ".bsp" );
+ }
+
+ if (!surfaceFilePath[0]) {
+ strcpy( surfaceFilePath, ExpandArg( argv[ i ] ) );
+ StripExtension( surfaceFilePath );
+ DefaultExtension( surfaceFilePath, ".srf" );
+ }
/* ydnar: set default sample size */
SetDefaultSampleSize( sampleSize );
/* ydnar: handle shaders */
- BeginMapShaderFile( source );
+ BeginMapShaderFile( BSPFilePath );
LoadShaderInfo();
/* note loading */
Sys_Printf( "Loading %s\n", source );
/* ydnar: load surface file */
- LoadSurfaceExtraFile( source );
+ LoadSurfaceExtraFile( surfaceFilePath );
/* load bsp file */
- LoadBSPFile( source );
+ LoadBSPFile( BSPFilePath );
/* parse bsp entities */
ParseEntities();
/* load map file */
value = ValueForKey( &entities[ 0 ], "_keepLights" );
if ( value[ 0 ] != '1' ) {
- LoadMapFile( mapSource, qtrue, qfalse );
+ LoadMapFile( source, qtrue, qfalse );
}
/* set the entity/model origins and init yDrawVerts */
SetupTraceNodes();
/* light the world */
- LightWorld();
-
- /* ydnar: store off lightmaps */
- StoreSurfaceLightmaps();
+ LightWorld( BSPFilePath, fastLightmapSearch, noBounceStore );
/* write out the bsp */
UnparseEntities();
- Sys_Printf( "Writing %s\n", source );
- WriteBSPFile( source );
+ Sys_Printf( "Writing %s\n", BSPFilePath );
+ WriteBSPFile( BSPFilePath );
/* ydnar: export lightmaps */
if ( exportLightmaps && !externalLightmaps ) {