From cf84ba8be24e861ae0f4988c08a6a8a8e304076b Mon Sep 17 00:00:00 2001 From: Rudolf Polzer Date: Sun, 31 Oct 2010 12:38:58 +0100 Subject: [PATCH] new light option -fill to improve lossy compression of lightmaps (should have no other impact) --- tools/quake3/q3map2/light.c | 5 ++ tools/quake3/q3map2/lightmaps_ydnar.c | 109 ++++++++++++++++++++++++++ tools/quake3/q3map2/q3map2.h | 1 + 3 files changed, 115 insertions(+) diff --git a/tools/quake3/q3map2/light.c b/tools/quake3/q3map2/light.c index 99a5a47..a703faa 100644 --- a/tools/quake3/q3map2/light.c +++ b/tools/quake3/q3map2/light.c @@ -2754,6 +2754,11 @@ int LightMain( int argc, char **argv ) { lightmapExtraVisClusterNudge = qtrue; } + else if( !strcmp( argv[ i ], "-fill" ) ) + { + lightmapFill = qtrue; + Sys_Printf( "Filling lightmap colors from surrounding pixels to improve JPEG compression\n" ); + } /* unhandled args */ else { diff --git a/tools/quake3/q3map2/lightmaps_ydnar.c b/tools/quake3/q3map2/lightmaps_ydnar.c index d315a78..080f26e 100644 --- a/tools/quake3/q3map2/lightmaps_ydnar.c +++ b/tools/quake3/q3map2/lightmaps_ydnar.c @@ -2255,7 +2255,112 @@ static int CompareRawLightmap( const void *a, const void *b ) return 0; } +void FillOutLightmap(outLightmap_t *olm) +{ + int x, y; + int ofs; + vec3_t dir_sum, light_sum; + int cnt, filled; + byte *lightBitsNew = NULL; + byte *lightBytesNew = NULL; + byte *dirBytesNew = NULL; + + lightBitsNew = safe_malloc((olm->customWidth * olm->customHeight + 8) / 8); + lightBytesNew = safe_malloc(olm->customWidth * olm->customHeight * 3); + if(deluxemap) + dirBytesNew = safe_malloc(olm->customWidth * olm->customHeight * 3); + + /* + memset(olm->lightBits, 0, (olm->customWidth * olm->customHeight + 8) / 8); + olm->lightBits[0] |= 1; + olm->lightBits[(10 * olm->customWidth + 30) >> 3] |= 1 << ((10 * olm->customWidth + 30) & 7); + memset(olm->bspLightBytes, 0, olm->customWidth * olm->customHeight * 3); + olm->bspLightBytes[0] = 255; + olm->bspLightBytes[(10 * olm->customWidth + 30) * 3 + 2] = 255; + */ + + memcpy(lightBitsNew, olm->lightBits, (olm->customWidth * olm->customHeight + 8) / 8); + memcpy(lightBytesNew, olm->bspLightBytes, olm->customWidth * olm->customHeight * 3); + if(deluxemap) + memcpy(dirBytesNew, olm->bspDirBytes, olm->customWidth * olm->customHeight * 3); + + for(;;) + { + filled = 0; + for(y = 0; y < olm->customHeight; ++y) + { + for(x = 0; x < olm->customWidth; ++x) + { + ofs = y * olm->customWidth + x; + if(olm->lightBits[ofs >> 3] & (1 << (ofs & 7))) /* already filled */ + continue; + cnt = 0; + VectorClear(dir_sum); + VectorClear(light_sum); + + /* try all four neighbors */ + ofs = ((y + olm->customHeight - 1) % olm->customHeight) * olm->customWidth + x; + if(olm->lightBits[ofs >> 3] & (1 << (ofs & 7))) /* already filled */ + { + ++cnt; + VectorAdd(light_sum, olm->bspLightBytes + ofs * 3, light_sum); + if(deluxemap) + VectorAdd(dir_sum, olm->bspDirBytes + ofs * 3, dir_sum); + } + + ofs = ((y + 1) % olm->customHeight) * olm->customWidth + x; + if(olm->lightBits[ofs >> 3] & (1 << (ofs & 7))) /* already filled */ + { + ++cnt; + VectorAdd(light_sum, olm->bspLightBytes + ofs * 3, light_sum); + if(deluxemap) + VectorAdd(dir_sum, olm->bspDirBytes + ofs * 3, dir_sum); + } + + ofs = y * olm->customWidth + (x + olm->customWidth - 1) % olm->customWidth; + if(olm->lightBits[ofs >> 3] & (1 << (ofs & 7))) /* already filled */ + { + ++cnt; + VectorAdd(light_sum, olm->bspLightBytes + ofs * 3, light_sum); + if(deluxemap) + VectorAdd(dir_sum, olm->bspDirBytes + ofs * 3, dir_sum); + } + ofs = y * olm->customWidth + (x + 1) % olm->customWidth; + if(olm->lightBits[ofs >> 3] & (1 << (ofs & 7))) /* already filled */ + { + ++cnt; + VectorAdd(light_sum, olm->bspLightBytes + ofs * 3, light_sum); + if(deluxemap) + VectorAdd(dir_sum, olm->bspDirBytes + ofs * 3, dir_sum); + } + + if(cnt) + { + ++filled; + ofs = y * olm->customWidth + x; + lightBitsNew[ofs >> 3] |= (1 << (ofs & 7)); + VectorScale(light_sum, 1.0/cnt, lightBytesNew + ofs * 3); + if(deluxemap) + VectorScale(dir_sum, 1.0/cnt, dirBytesNew + ofs * 3); + } + } + } + + if(!filled) + break; + + memcpy(olm->lightBits, lightBitsNew, (olm->customWidth * olm->customHeight + 8) / 8); + memcpy(olm->bspLightBytes, lightBytesNew, olm->customWidth * olm->customHeight * 3); + if(deluxemap) + memcpy(olm->bspDirBytes, dirBytesNew, olm->customWidth * olm->customHeight * 3); + } + + free(lightBitsNew); + free(lightBytesNew); + if(deluxemap) + free(dirBytesNew); +} /* StoreSurfaceLightmaps() @@ -2937,6 +3042,10 @@ void StoreSurfaceLightmaps( void ) { /* get output lightmap */ olm = &outLightmaps[ i ]; + + /* fill output lightmap */ + if(lightmapFill) + FillOutLightmap(olm); /* is this a valid bsp lightmap? */ if( olm->lightmapNum >= 0 && !externalLightmaps ) diff --git a/tools/quake3/q3map2/q3map2.h b/tools/quake3/q3map2/q3map2.h index 99a2469..baa29c7 100644 --- a/tools/quake3/q3map2/q3map2.h +++ b/tools/quake3/q3map2/q3map2.h @@ -2022,6 +2022,7 @@ Q_EXTERN qboolean debugInset Q_ASSIGN( qfalse ); Q_EXTERN qboolean debugPortals Q_ASSIGN( qfalse ); Q_EXTERN qboolean lightmapTriangleCheck Q_ASSIGN(qfalse); Q_EXTERN qboolean lightmapExtraVisClusterNudge Q_ASSIGN(qfalse); +Q_EXTERN qboolean lightmapFill Q_ASSIGN(qfalse); Q_EXTERN double normalEpsilon Q_ASSIGN( 0.00001 ); Q_EXTERN double distanceEpsilon Q_ASSIGN( 0.01 ); -- 2.39.2