From d4fa608be5e197db31ea52956da56306f311dbf7 Mon Sep 17 00:00:00 2001
From: Thomas Debesse <dev@illwieckz.net>
Date: Sat, 6 Feb 2016 06:35:14 +0100
Subject: [PATCH] lightmap allocation speed-up, add -fastallocate

- Allocate large lightmaps first to speed up the allocation process
- Add `-fastallocate` option to trade lightmap size against allocation time (useful with hi res lightmaps on large maps: reduce allocation time from days to minutes for only some extra bytes:
- If fast allocation, skip lightmap files that are more than 90% complete
- If fast allocation, do not test allocation on every pixels, especially for large lightmaps

Thanks to Kangz (Corentin Wallez) for his precious help and his kind availability.
---
 tools/quake3/q3map2/help.c            |  1 +
 tools/quake3/q3map2/light.c           | 14 +++++++---
 tools/quake3/q3map2/lightmaps_ydnar.c | 40 +++++++++++++++++++--------
 tools/quake3/q3map2/q3map2.h          |  2 +-
 4 files changed, 41 insertions(+), 16 deletions(-)

diff --git a/tools/quake3/q3map2/help.c b/tools/quake3/q3map2/help.c
index a06e44a0..641aed59 100644
--- a/tools/quake3/q3map2/help.c
+++ b/tools/quake3/q3map2/help.c
@@ -194,6 +194,7 @@ void HelpLight()
 		{"-extravisnudge", "Broken feature to nudge the luxel origin to a better vis cluster"},
 		{"-extrawide", "Deprecated alias for `-super 2 -filter`"},
 		{"-extra", "Deprecated alias for `-super 2`"},
+		{"-fastallocate", "Use `-fastallocate` to trade lightmap size against allocation time (useful with hi res lightmaps on large maps: reduce allocation time from days to minutes for only some extra bytes)"},
 		{"-fastbounce", "Use `-fast` style lighting for radiosity"},
 		{"-faster", "Use a faster falloff curve for lighting; also implies `-fast`"},
 		{"-fastgrid", "Use `-fast` style lighting for the light grid"},
diff --git a/tools/quake3/q3map2/light.c b/tools/quake3/q3map2/light.c
index 0e8d1602..a408e35a 100644
--- a/tools/quake3/q3map2/light.c
+++ b/tools/quake3/q3map2/light.c
@@ -1890,7 +1890,7 @@ void SetupGrid( void ){
    does what it says...
  */
 
-void LightWorld( const char *BSPFilePath ){
+void LightWorld( const char *BSPFilePath, qboolean fastAllocate ){
 	vec3_t color;
 	float f;
 	int b, bt;
@@ -2033,7 +2033,7 @@ void LightWorld( const char *BSPFilePath ){
 	while ( bounce > 0 )
 	{
 		/* store off the bsp between bounces */
-		StoreSurfaceLightmaps();
+		StoreSurfaceLightmaps( fastAllocate );
 		UnparseEntities();
 		Sys_Printf( "Writing %s\n", BSPFilePath );
 		WriteBSPFile( BSPFilePath );
@@ -2116,6 +2116,7 @@ int LightMain( int argc, char **argv ){
 	const char  *value;
 	int lightmapMergeSize = 0;
 	qboolean lightSamplesInsist = qfalse;
+	qboolean fastAllocate = qfalse;
 
 
 	/* note it */
@@ -2636,6 +2637,11 @@ int LightMain( int argc, char **argv ){
 			Sys_Printf( "Faster mode enabled\n" );
 		}
 
+		else if ( !strcmp( argv[ i ], "-fastallocate" ) ) {
+			fastAllocate = qtrue;
+			Sys_Printf( "Fast allocation mode enabled\n" );
+		}
+
 		else if ( !strcmp( argv[ i ], "-fastgrid" ) ) {
 			fastgrid = qtrue;
 			Sys_Printf( "Fast grid lighting enabled\n" );
@@ -2984,10 +2990,10 @@ int LightMain( int argc, char **argv ){
 	SetupTraceNodes();
 
 	/* light the world */
-	LightWorld( BSPFilePath );
+	LightWorld( BSPFilePath, fastAllocate );
 
 	/* ydnar: store off lightmaps */
-	StoreSurfaceLightmaps();
+	StoreSurfaceLightmaps( fastAllocate );
 
 	/* write out the bsp */
 	UnparseEntities();
diff --git a/tools/quake3/q3map2/lightmaps_ydnar.c b/tools/quake3/q3map2/lightmaps_ydnar.c
index 3db1a7f0..19791c4a 100644
--- a/tools/quake3/q3map2/lightmaps_ydnar.c
+++ b/tools/quake3/q3map2/lightmaps_ydnar.c
@@ -1976,7 +1976,7 @@ static void SetupOutLightmap( rawLightmap_t *lm, outLightmap_t *olm ){
  */
 
 #define LIGHTMAP_RESERVE_COUNT 1
-static void FindOutLightmaps( rawLightmap_t *lm ){
+static void FindOutLightmaps( rawLightmap_t *lm, qboolean fastAllocate ){
 	int i, j, k, lightmapNum, xMax, yMax, x = -1, y = -1, sx, sy, ox, oy, offset;
 	outLightmap_t       *olm;
 	surfaceInfo_t       *info;
@@ -1984,6 +1984,7 @@ static void FindOutLightmaps( rawLightmap_t *lm ){
 	vec3_t color, direction;
 	byte                *pixel;
 	qboolean ok;
+	int xIncrement, yIncrement;
 
 
 	/* set default lightmap number (-3 = LIGHTMAP_BY_VERTEX) */
@@ -2094,6 +2095,13 @@ static void FindOutLightmaps( rawLightmap_t *lm ){
 					continue;
 				}
 
+				/* if fast allocation, skip lightmap files that are more than 90% complete */
+				if ( fastAllocate == qtrue ) {
+					if (olm->freeLuxels < (olm->customWidth * olm->customHeight) / 10) {
+						continue;
+					}
+				}
+
 				/* don't store non-custom raw lightmaps on custom bsp lightmaps */
 				if ( olm->customWidth != lm->customWidth ||
 					 olm->customHeight != lm->customHeight ) {
@@ -2111,10 +2119,20 @@ static void FindOutLightmaps( rawLightmap_t *lm ){
 					yMax = ( olm->customHeight - lm->h ) + 1;
 				}
 
+				/* if fast allocation, do not test allocation on every pixels, especially for large lightmaps */
+				if ( fastAllocate == qtrue ) {
+					xIncrement = MAX(1, lm->w / 15);
+					yIncrement = MAX(1, lm->h / 15);
+				}
+				else {
+					xIncrement = 1;
+					yIncrement = 1;
+				}
+
 				/* walk the origin around the lightmap */
-				for ( y = 0; y < yMax; y++ )
+				for ( y = 0; y < yMax; y += yIncrement )
 				{
-					for ( x = 0; x < xMax; x++ )
+					for ( x = 0; x < xMax; x += xIncrement )
 					{
 						/* find a fine tract of lauhnd */
 						ok = TestOutLightmapStamp( lm, lightmapNum, olm, x, y );
@@ -2292,6 +2310,12 @@ static int CompareRawLightmap( const void *a, const void *b ){
 	/* get min number of surfaces */
 	min = ( alm->numLightSurfaces < blm->numLightSurfaces ? alm->numLightSurfaces : blm->numLightSurfaces );
 
+	/* compare size, allocate bigger first */
+	diff = ( blm->w * blm->h ) - ( alm->w * alm->h );
+	if ( diff != 0 ) {
+		return diff;
+	}
+
 	/* iterate */
 	for ( i = 0; i < min; i++ )
 	{
@@ -2314,12 +2338,6 @@ static int CompareRawLightmap( const void *a, const void *b ){
 		return diff;
 	}
 
-	/* compare size */
-	diff = ( blm->w * blm->h ) - ( alm->w * alm->h );
-	if ( diff != 0 ) {
-		return diff;
-	}
-
 	/* must be equivalent */
 	return 0;
 }
@@ -2441,7 +2459,7 @@ void FillOutLightmap( outLightmap_t *olm ){
    stores the surface lightmaps into the bsp as byte rgb triplets
  */
 
-void StoreSurfaceLightmaps( void ){
+void StoreSurfaceLightmaps( qboolean fastAllocate ){
 	int i, j, k, x, y, lx, ly, sx, sy, *cluster, mappedSamples;
 	int style, size, lightmapNum, lightmapNum2;
 	float               *normal, *luxel, *bspLuxel, *bspLuxel2, *radLuxel, samples, occludedSamples;
@@ -3059,7 +3077,7 @@ void StoreSurfaceLightmaps( void ){
 	for ( i = 0; i < numRawLightmaps; i++ )
 	{
 		lm = &rawLightmaps[ sortLightmaps[ i ] ];
-		FindOutLightmaps( lm );
+		FindOutLightmaps( lm, fastAllocate );
 	}
 
 	/* set output numbers in twinned lightmaps */
diff --git a/tools/quake3/q3map2/q3map2.h b/tools/quake3/q3map2/q3map2.h
index 0100048d..695568b3 100644
--- a/tools/quake3/q3map2/q3map2.h
+++ b/tools/quake3/q3map2/q3map2.h
@@ -1848,7 +1848,7 @@ int                         ImportLightmapsMain( int argc, char **argv );
 
 void                        SetupSurfaceLightmaps( void );
 void                        StitchSurfaceLightmaps( void );
-void                        StoreSurfaceLightmaps( void );
+void                        StoreSurfaceLightmaps( qboolean fastAllocate );
 
 
 /* image.c */
-- 
2.39.5