Index: tools/quake3/q3map2/image.c =================================================================== --- tools/quake3/q3map2/image.c (revision 486) +++ tools/quake3/q3map2/image.c (working copy) @@ -177,10 +177,12 @@ pb.size = size; pb.offset = 0; png_set_read_fn( png, &pb, PNGReadData ); +#if 0 png->io_ptr = &pb; /* hack! */ - +#endif + /* set error longjmp */ - if( setjmp( png->jmpbuf ) ) + if( setjmp( png_jmpbuf(png) ) ) { Sys_Printf( "WARNING: An error occurred reading PNG image\n" ); png_destroy_read_struct( &png, &info, &end ); Index: tools/quake3/q3map2/light.c =================================================================== --- tools/quake3/q3map2/light.c (revision 486) +++ tools/quake3/q3map2/light.c (working copy) @@ -2234,7 +2234,13 @@ dirtGain = 1.0f; Sys_Printf( "Dirtmapping gain set to %.1f\n", dirtGain ); } - + else if( !strcmp( argv[ i ], "-exporthdr" ) ) + { + exporthdr = qtrue; + // FIXME: this tolerance allows for 256x brightness at most + falloffTolerance = 1.0f / 256.0f; + Sys_Printf( "Exporting hdr lightmaps\n" ); + } /* unhandled args */ else Sys_Printf( "WARNING: Unknown argument \"%s\"\n", argv[ i ] ); Index: tools/quake3/q3map2/light_bounce.c =================================================================== --- tools/quake3/q3map2/light_bounce.c (revision 486) +++ tools/quake3/q3map2/light_bounce.c (working copy) @@ -389,14 +389,19 @@ /* create the color gradient */ //% VectorSubtract( maxs, mins, delta ); - /* new: color gradient will always be 0-1.0, expressed as the range of light relative to overall light */ - //% gradient[ 0 ] = maxs[ 0 ] > 0.0f ? (maxs[ 0 ] - mins[ 0 ]) / maxs[ 0 ] : 0.0f; - //% gradient[ 1 ] = maxs[ 1 ] > 0.0f ? (maxs[ 1 ] - mins[ 1 ]) / maxs[ 1 ] : 0.0f; - //% gradient[ 2 ] = maxs[ 2 ] > 0.0f ? (maxs[ 2 ] - mins[ 2 ]) / maxs[ 2 ] : 0.0f; - - /* newer: another contrast function */ - for( i = 0; i < 3; i++ ) - gradient[ i ] = (maxs[ i ] - mins[ i ]) * maxs[ i ]; + if (exporthdr) + { + /* new: color gradient will always be 0-1.0, expressed as the range of light relative to overall light */ + gradient[ 0 ] = maxs[ 0 ] > 0.0f ? (maxs[ 0 ] - mins[ 0 ]) / maxs[ 0 ] : 0.0f; + gradient[ 1 ] = maxs[ 1 ] > 0.0f ? (maxs[ 1 ] - mins[ 1 ]) / maxs[ 1 ] : 0.0f; + gradient[ 2 ] = maxs[ 2 ] > 0.0f ? (maxs[ 2 ] - mins[ 2 ]) / maxs[ 2 ] : 0.0f; + } + else + { + /* newer: another contrast function */ + for( i = 0; i < 3; i++ ) + gradient[ i ] = (maxs[ i ] - mins[ i ]) * maxs[ i ]; + } } Index: tools/quake3/q3map2/light_ydnar.c =================================================================== --- tools/quake3/q3map2/light_ydnar.c (revision 486) +++ tools/quake3/q3map2/light_ydnar.c (working copy) @@ -93,6 +93,54 @@ +/* +ColorToRGBE() +Tr3B: standard conversion from float pixels to rgbe pixels +*/ + +void ColorToRGBE(const float *color, unsigned char rgbe[4]) +{ + vec3_t sample; + float maxComponent; + int e; + + VectorCopy(color, sample); + + maxComponent = sample[0]; + if(sample[1] > maxComponent) + maxComponent = sample[1]; + if(sample[2] > maxComponent) + maxComponent = sample[2]; + + if(maxComponent < 1e-32) + { + rgbe[0] = 0; + rgbe[1] = 0; + rgbe[2] = 0; + rgbe[3] = 0; + } + else + { +#if 1 + maxComponent = frexp(maxComponent, &e) * 255.0 / maxComponent; + rgbe[0] = (unsigned char) (sample[0] * maxComponent); + rgbe[1] = (unsigned char) (sample[1] * maxComponent); + rgbe[2] = (unsigned char) (sample[2] * maxComponent); + rgbe[3] = (unsigned char) (e + 128); +#else + e = ceil(log2(maxComponent)); + VectorScale(sample, 1.0 / exp2(e), sample); + + rgbe[0] = (unsigned char) (sample[0] * 255); + rgbe[1] = (unsigned char) (sample[1] * 255); + rgbe[2] = (unsigned char) (sample[2] * 255); + rgbe[3] = (unsigned char) (e + 128); +#endif + } +} + + + /* ------------------------------------------------------------------------------- this section deals with phong shading (normal interpolation across brush faces) Index: tools/quake3/q3map2/lightmaps_ydnar.c =================================================================== --- tools/quake3/q3map2/lightmaps_ydnar.c (revision 486) +++ tools/quake3/q3map2/lightmaps_ydnar.c (working copy) @@ -108,6 +108,63 @@ /* +WriteRGBE() +*/ + +void WriteRGBE(char *filename, float * data, int width, int height) +{ + int i, c; + FILE *file; + unsigned char rgbe[4]; + float rgb[3]; + + file = fopen(filename, "wb"); + if(file == NULL) + Error("Unable to open %s for writing", filename); + + + // write header + if(fprintf(file,"#?RGBE\n") < 0) + Error("RGBE write error: %s", filename); + + if(fprintf(file,"# Generated by ETXMap \n") < 0) + Error("RGBE write error: %s", filename); + + if(fprintf(file, "FORMAT=32-bit_rle_rgbe\n\n") < 0) + Error("RGBE write error: %s", filename); + + if(fprintf(file, "-Y %d +X %d\n", height, width) < 0) + Error("RGBE write error: %s", filename); + + c = (width * height * 3); + for(i = 0; i < c; i += 3) + { +#if 0 + // FIXME XMap2's output is 255 times too high + rgb[0] = data[i + 0] / 255.0f; + rgb[1] = data[i + 1] / 255.0f; + rgb[2] = data[i + 2] / 255.0f; + + ColorToRGBE(rgb, rgbe); + if(fwrite(rgbe, sizeof(rgbe), 1, file) < 1) + Error("RGBE write error: %s", filename); +#else + rgb[0] = data[i + 0]; + rgb[1] = data[i + 1]; + rgb[2] = data[i + 2]; + + if(fwrite(rgb, sizeof(rgb), 1, file) < 1) + Error("RGBE write error: %s", filename); +#endif + } + + // close the file + fclose(file); +} + + + +/* ExportLightmaps() exports the lightmaps as a list of numbered tga images */ @@ -1868,8 +1925,20 @@ /* allocate buffers */ olm->lightBits = safe_malloc( (olm->customWidth * olm->customHeight / 8) + 8 ); memset( olm->lightBits, 0, (olm->customWidth * olm->customHeight / 8) + 8 ); + olm->bspLightBytes = safe_malloc( olm->customWidth * olm->customHeight * 3 ); memset( olm->bspLightBytes, 0, olm->customWidth * olm->customHeight * 3 ); + + if(exporthdr) + { + olm->bspLightFloats = safe_malloc(olm->customWidth * olm->customHeight * 3 * sizeof(float)); + memset(olm->bspLightFloats, 0, olm->customWidth * olm->customHeight * 3 * sizeof(float)); + } + else + { + olm->bspLightFloats = NULL; + } + if( deluxemap ) { olm->bspDirBytes = safe_malloc( olm->customWidth * olm->customHeight * 3 ); @@ -2149,6 +2218,16 @@ /* store color */ pixel = olm->bspLightBytes + (((oy * olm->customWidth) + ox) * 3); ColorToBytes( color, pixel, lm->brightness ); + + if(exporthdr) + { + float *hdrPixel; + + hdrPixel = olm->bspLightFloats + (((oy * olm->customWidth) + ox) * 3); + + // FIXME gamma + VectorScale(color, lm->brightness <= 0.0f ? 1.0f : lm->brightness, hdrPixel); + } /* store direction */ if( deluxemap ) @@ -2705,6 +2784,7 @@ { free( outLightmaps[ i ].lightBits ); free( outLightmaps[ i ].bspLightBytes ); + free( outLightmaps[ i ].bspLightFloats ); } free( outLightmaps ); outLightmaps = NULL; @@ -2747,7 +2827,21 @@ /* ----------------------------------------------------------------- store output lightmaps ----------------------------------------------------------------- */ - + + /* delete old conflicting external lightmaps */ + // FIXME scan for all lightmaps + for(i = 0; i < (numOutLightmaps * 2); i++) + { + /* determine if file exists */ + sprintf(filename, "%s/" EXTERNAL_LIGHTMAP, dirname, i); + if(FileExists(filename)) + remove(filename); + + sprintf(filename, "%s/" EXTERNAL_HDRLIGHTMAP, dirname, i); + if(FileExists(filename)) + remove(filename); + } + /* note it */ Sys_FPrintf( SYS_VRB, "storing..." ); @@ -2800,6 +2894,12 @@ sprintf( filename, "%s/" EXTERNAL_LIGHTMAP, dirname, numExtLightmaps ); Sys_FPrintf( SYS_VRB, "\nwriting %s", filename ); WriteTGA24( filename, olm->bspLightBytes, olm->customWidth, olm->customHeight, qtrue ); + if(exporthdr) + { + sprintf(filename, "%s/" EXTERNAL_HDRLIGHTMAP, dirname, numExtLightmaps); + Sys_FPrintf(SYS_VRB, "\nwriting %s", filename); + WriteRGBE(filename, olm->bspLightFloats, olm->customWidth, olm->customHeight); + } numExtLightmaps++; /* write deluxemap */ @@ -2814,6 +2914,17 @@ olm->extLightmapNum++; } } + + /* HDR lightmaps are always exported */ + if (exporthdr && !externalLightmaps && olm->lightmapNum >= 0) + { + /* make a directory for the lightmaps */ + Q_mkdir( dirname ); + + sprintf(filename, "%s/" EXTERNAL_HDRLIGHTMAP, dirname, olm->lightmapNum); + Sys_FPrintf(SYS_VRB, "\nwriting %s", filename); + WriteRGBE(filename, olm->bspLightFloats, olm->customWidth, olm->customHeight); + } } if( numExtLightmaps > 0 ) @@ -2823,12 +2934,15 @@ for( i = numExtLightmaps; i; i++ ) { /* determine if file exists */ - sprintf( filename, "%s/" EXTERNAL_LIGHTMAP, dirname, i ); - if( !FileExists( filename ) ) - break; - - /* delete it */ - remove( filename ); + sprintf(filename, "%s/" EXTERNAL_HDRLIGHTMAP, dirname, i); + if(FileExists(filename)) + remove(filename); + + sprintf(filename, "%s/" EXTERNAL_LIGHTMAP, dirname, i); + if(FileExists(filename)) + remove( filename ); + else + break; } /* ----------------------------------------------------------------- Index: tools/quake3/q3map2/q3map2.h =================================================================== --- tools/quake3/q3map2/q3map2.h (revision 486) +++ tools/quake3/q3map2/q3map2.h (working copy) @@ -295,6 +295,7 @@ ------------------------------------------------------------------------------- */ #define EXTERNAL_LIGHTMAP "lm_%04d.tga" +#define EXTERNAL_HDRLIGHTMAP "lm_%04d.hdr" #define MAX_LIGHTMAPS 4 /* RBSP */ #define MAX_LIGHT_STYLES 64 @@ -1366,6 +1367,7 @@ shaderInfo_t *shaders[ MAX_LIGHTMAP_SHADERS ]; byte *lightBits; byte *bspLightBytes; + float *bspLightFloats; byte *bspDirBytes; } outLightmap_t; @@ -2109,6 +2111,8 @@ Q_EXTERN qboolean deluxemap Q_ASSIGN( qfalse ); Q_EXTERN qboolean debugDeluxemap Q_ASSIGN( qfalse ); +Q_EXTERN qboolean exporthdr Q_ASSIGN( qfalse ); + Q_EXTERN qboolean fast Q_ASSIGN( qfalse ); Q_EXTERN qboolean faster Q_ASSIGN( qfalse ); Q_EXTERN qboolean fastgrid Q_ASSIGN( qfalse );