]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake3/q3map2/lightmaps_ydnar.c
lightmap allocation speed-up, add -fastallocate
[xonotic/netradiant.git] / tools / quake3 / q3map2 / lightmaps_ydnar.c
index b03293499166863dafa64e666bb9dcc9be644b51..19791c4a7118738b539d877e5d2d150c4fc534cd 100644 (file)
@@ -284,8 +284,8 @@ static int CompareLightSurface( const void *a, const void *b ){
 
 
        /* get shaders */
-       asi = surfaceInfos[ *( (int*) a ) ].si;
-       bsi = surfaceInfos[ *( (int*) b ) ].si;
+       asi = surfaceInfos[ *( (const int*) a ) ].si;
+       bsi = surfaceInfos[ *( (const int*) b ) ].si;
 
        /* dummy check */
        if ( asi == NULL ) {
@@ -411,6 +411,13 @@ void FinishRawLightmap( rawLightmap_t *lm ){
        }
        memset( lm->superNormals, 0, size );
 
+       /* allocate floodlight map storage */
+       size = lm->sw * lm->sh * SUPER_FLOODLIGHT_SIZE * sizeof( float );
+       if ( lm->superFloodLight == NULL ) {
+               lm->superFloodLight = safe_malloc( size );
+       }
+       memset( lm->superFloodLight, 0, size );
+
        /* allocate cluster map storage */
        size = lm->sw * lm->sh * sizeof( int );
        if ( lm->superClusters == NULL ) {
@@ -590,10 +597,10 @@ qboolean AddPatchToRawLightmap( int num, rawLightmap_t *lm ){
 
 qboolean AddSurfaceToRawLightmap( int num, rawLightmap_t *lm ){
        bspDrawSurface_t    *ds, *ds2;
-       surfaceInfo_t       *info, *info2;
+       surfaceInfo_t       *info;
        int num2, n, i, axisNum;
        float s, t, d, len, sampleSize;
-       vec3_t mins, maxs, origin, faxis, size, exactSize, delta, normalized, vecs[ 2 ];
+       vec3_t mins, maxs, origin, faxis, size, delta, normalized, vecs[ 2 ];
        vec4_t plane;
        bspDrawVert_t       *verts;
 
@@ -675,18 +682,29 @@ qboolean AddSurfaceToRawLightmap( int num, rawLightmap_t *lm ){
        /* round to the lightmap resolution */
        for ( i = 0; i < 3; i++ )
        {
-               exactSize[ i ] = lm->maxs[ i ] - lm->mins[ i ];
                mins[ i ] = sampleSize * floor( lm->mins[ i ] / sampleSize );
                maxs[ i ] = sampleSize * ceil( lm->maxs[ i ] / sampleSize );
                size[ i ] = ( maxs[ i ] - mins[ i ] ) / sampleSize + 1.0f;
 
                /* hack (god this sucks) */
-               if ( size[ i ] > lm->customWidth || size[ i ] > lm->customHeight ) {
+               if ( size[ i ] > lm->customWidth || size[ i ] > lm->customHeight  || ( lmLimitSize && size[i] > lmLimitSize ) ) {
                        i = -1;
                        sampleSize += 1.0f;
                }
        }
 
+       if ( sampleSize != lm->sampleSize && lmLimitSize == 0 ) {
+               Sys_FPrintf( SYS_VRB,"WARNING: surface at (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) too large for desired samplesize/lightmapsize/lightmapscale combination, increased samplesize from %d to %d\n",
+                                        info->mins[0],
+                                        info->mins[1],
+                                        info->mins[2],
+                                        info->maxs[0],
+                                        info->maxs[1],
+                                        info->maxs[2],
+                                        lm->sampleSize,
+                                        (int) sampleSize );
+       }
+
        /* set actual sample size */
        lm->actualSampleSize = sampleSize;
 
@@ -748,7 +766,6 @@ qboolean AddSurfaceToRawLightmap( int num, rawLightmap_t *lm ){
                /* get surface */
                num2 = lightSurfaces[ lm->firstLightSurface + n ];
                ds2 = &bspDrawSurfaces[ num2 ];
-               info2 = &surfaceInfos[ num2 ];
                verts = &yDrawVerts[ ds2->firstVert ];
 
                /* set the lightmap texture coordinates in yDrawVerts in [0, superSample * lm->customWidth] space */
@@ -770,7 +787,6 @@ qboolean AddSurfaceToRawLightmap( int num, rawLightmap_t *lm ){
        /* get first drawsurface */
        num2 = lightSurfaces[ lm->firstLightSurface ];
        ds2 = &bspDrawSurfaces[ num2 ];
-       info2 = &surfaceInfos[ num2 ];
        verts = &yDrawVerts[ ds2->firstVert ];
 
        /* calculate lightmap origin */
@@ -847,14 +863,14 @@ static int CompareSurfaceInfo( const void *a, const void *b ){
 
 
        /* get surface info */
-       aInfo = &surfaceInfos[ *( (int*) a ) ];
-       bInfo = &surfaceInfos[ *( (int*) b ) ];
+       aInfo = &surfaceInfos[ *( (const int*) a ) ];
+       bInfo = &surfaceInfos[ *( (const int*) b ) ];
 
        /* model first */
-       if ( aInfo->model < bInfo->model ) {
+       if ( aInfo->modelindex < bInfo->modelindex ) {
                return 1;
        }
-       else if ( aInfo->model > bInfo->model ) {
+       else if ( aInfo->modelindex > bInfo->modelindex ) {
                return -1;
        }
 
@@ -866,6 +882,15 @@ static int CompareSurfaceInfo( const void *a, const void *b ){
                return -1;
        }
 
+       /* 27: then shader! */
+       if ( aInfo->si < bInfo->si ) {
+               return 1;
+       }
+       else if ( aInfo->si > bInfo->si ) {
+               return -1;
+       }
+
+
        /* then lightmap sample size */
        if ( aInfo->sampleSize < bInfo->sampleSize ) {
                return 1;
@@ -931,7 +956,7 @@ void SetupSurfaceLightmaps( void ){
        int i, j, k, s,num, num2;
        bspModel_t          *model;
        bspLeaf_t           *leaf;
-       bspDrawSurface_t    *ds, *ds2;
+       bspDrawSurface_t    *ds;
        surfaceInfo_t       *info, *info2;
        rawLightmap_t       *lm;
        qboolean added;
@@ -997,7 +1022,7 @@ void SetupSurfaceLightmaps( void ){
                        }
 
                        /* basic setup */
-                       info->model = model;
+                       info->modelindex = i;
                        info->lm = NULL;
                        info->plane = NULL;
                        info->firstSurfaceCluster = numSurfaceClusters;
@@ -1115,12 +1140,22 @@ void SetupSurfaceLightmaps( void ){
                lm->splotchFix = info->si->splotchFix;
                lm->firstLightSurface = numLightSurfaces;
                lm->numLightSurfaces = 0;
-               lm->sampleSize = info->sampleSize;
-               lm->actualSampleSize = info->sampleSize;
+               /* vortex: multiply lightmap sample size by -samplescale */
+               if ( sampleScale > 0 ) {
+                       lm->sampleSize = info->sampleSize * sampleScale;
+               }
+               else{
+                       lm->sampleSize = info->sampleSize;
+               }
+               lm->actualSampleSize = lm->sampleSize;
                lm->entityNum = info->entityNum;
                lm->recvShadows = info->recvShadows;
                lm->brightness = info->si->lmBrightness;
                lm->filterRadius = info->si->lmFilterRadius;
+               VectorCopy( info->si->floodlightRGB, lm->floodlightRGB );
+               lm->floodlightDistance = info->si->floodlightDistance;
+               lm->floodlightIntensity = info->si->floodlightIntensity;
+               lm->floodlightDirectionScale = info->si->floodlightDirectionScale;
                VectorCopy( info->axis, lm->axis );
                lm->plane = info->plane;
                VectorCopy( info->mins, lm->mins );
@@ -1143,7 +1178,6 @@ void SetupSurfaceLightmaps( void ){
                        {
                                /* get info and attempt early out */
                                num2 = sortSurfaces[ j ];
-                               ds2 = &bspDrawSurfaces[ num2 ];
                                info2 = &surfaceInfos[ num2 ];
                                if ( info2->hasLightmap == qfalse || info2->lm != NULL ) {
                                        continue;
@@ -1203,7 +1237,7 @@ void StitchSurfaceLightmaps( void ){
                numStitched, numCandidates, numLuxels, f, fOld, start;
        rawLightmap_t   *lm, *a, *b, *c[ MAX_STITCH_CANDIDATES ];
        float           *luxel, *luxel2, *origin, *origin2, *normal, *normal2,
-                                        sampleSize, average[ 3 ], totalColor, ootc, *luxels[ MAX_STITCH_LUXELS ];
+                                        sampleSize, average[ 3 ], totalColor, ootc;
 
 
        /* disabled for now */
@@ -1326,7 +1360,6 @@ void StitchSurfaceLightmaps( void ){
 
                                                        /* add luxel */
                                                        //%     VectorSet( luxel2, 255, 0, 255 );
-                                                       luxels[ numLuxels++ ] = luxel2;
                                                        VectorAdd( average, luxel2, average );
                                                        totalColor += luxel2[ 3 ];
                                                }
@@ -1942,14 +1975,16 @@ static void SetupOutLightmap( rawLightmap_t *lm, outLightmap_t *olm ){
    for a given surface lightmap, find output lightmap pages and positions for it
  */
 
-static void FindOutLightmaps( rawLightmap_t *lm ){
-       int i, j, lightmapNum, xMax, yMax, x, y, sx, sy, ox, oy, offset, temp;
+#define LIGHTMAP_RESERVE_COUNT 1
+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;
        float               *luxel, *deluxel;
        vec3_t color, direction;
        byte                *pixel;
        qboolean ok;
+       int xIncrement, yIncrement;
 
 
        /* set default lightmap number (-3 = LIGHTMAP_BY_VERTEX) */
@@ -2044,7 +2079,13 @@ static void FindOutLightmaps( rawLightmap_t *lm ){
                        y = 0;
 
                        /* walk the list of lightmap pages */
-                       for ( i = 0; i < numOutLightmaps; i++ )
+                       if ( lightmapSearchBlockSize <= 0 || numOutLightmaps < LIGHTMAP_RESERVE_COUNT ) {
+                               i = 0;
+                       }
+                       else{
+                               i = ( ( numOutLightmaps - LIGHTMAP_RESERVE_COUNT ) / lightmapSearchBlockSize ) * lightmapSearchBlockSize;
+                       }
+                       for ( ; i < numOutLightmaps; i++ )
                        {
                                /* get the output lightmap */
                                olm = &outLightmaps[ i ];
@@ -2054,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 ) {
@@ -2071,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 );
@@ -2101,21 +2159,21 @@ static void FindOutLightmaps( rawLightmap_t *lm ){
 
                /* no match? */
                if ( ok == qfalse ) {
-                       /* allocate two new output lightmaps */
-                       numOutLightmaps += 2;
+                       /* allocate LIGHTMAP_RESERVE_COUNT new output lightmaps */
+                       numOutLightmaps += LIGHTMAP_RESERVE_COUNT;
                        olm = safe_malloc( numOutLightmaps * sizeof( outLightmap_t ) );
-                       if ( outLightmaps != NULL && numOutLightmaps > 2 ) {
-                               memcpy( olm, outLightmaps, ( numOutLightmaps - 2 ) * sizeof( outLightmap_t ) );
+                       if ( outLightmaps != NULL && numOutLightmaps > LIGHTMAP_RESERVE_COUNT ) {
+                               memcpy( olm, outLightmaps, ( numOutLightmaps - LIGHTMAP_RESERVE_COUNT ) * sizeof( outLightmap_t ) );
                                free( outLightmaps );
                        }
                        outLightmaps = olm;
 
                        /* initialize both out lightmaps */
-                       SetupOutLightmap( lm, &outLightmaps[ numOutLightmaps - 2 ] );
-                       SetupOutLightmap( lm, &outLightmaps[ numOutLightmaps - 1 ] );
+                       for ( k = numOutLightmaps - LIGHTMAP_RESERVE_COUNT; k < numOutLightmaps; ++k )
+                               SetupOutLightmap( lm, &outLightmaps[ k ] );
 
                        /* set out lightmap */
-                       i = numOutLightmaps - 2;
+                       i = numOutLightmaps - LIGHTMAP_RESERVE_COUNT;
                        olm = &outLightmaps[ i ];
 
                        /* set stamp xy origin to the first surface lightmap */
@@ -2220,23 +2278,12 @@ static void FindOutLightmaps( rawLightmap_t *lm ){
                                /* store direction */
                                if ( deluxemap ) {
                                        /* normalize average light direction */
-                                       if ( VectorNormalize( deluxel, direction ) ) {
-                                               /* encode [-1,1] in [0,255] */
-                                               pixel = olm->bspDirBytes + ( ( ( oy * olm->customWidth ) + ox ) * 3 );
-                                               for ( i = 0; i < 3; i++ )
-                                               {
-                                                       temp = ( direction[ i ] + 1.0f ) * 127.5f;
-                                                       if ( temp < 0 ) {
-                                                               pixel[ i ] = 0;
-                                                       }
-                                                       else if ( temp > 255 ) {
-                                                               pixel[ i ] = 255;
-                                                       }
-                                                       else{
-                                                               pixel[ i ] = temp;
-                                                       }
-                                               }
-                                       }
+                                       pixel = olm->bspDirBytes + ( ( ( oy * olm->customWidth ) + ox ) * 3 );
+                                       VectorScale( deluxel, 1000.0f, direction );
+                                       VectorNormalize( direction, direction );
+                                       VectorScale( direction, 127.5f, direction );
+                                       for ( i = 0; i < 3; i++ )
+                                               pixel[ i ] = (byte)( 127.5f + direction[ i ] );
                                }
                        }
                }
@@ -2257,12 +2304,18 @@ static int CompareRawLightmap( const void *a, const void *b ){
 
 
        /* get lightmaps */
-       alm = &rawLightmaps[ *( (int*) a ) ];
-       blm = &rawLightmaps[ *( (int*) b ) ];
+       alm = &rawLightmaps[ *( (const int*) a ) ];
+       blm = &rawLightmaps[ *( (const int*) 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++ )
        {
@@ -2285,24 +2338,128 @@ 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;
 }
 
+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()
    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;
@@ -2320,16 +2477,22 @@ void StoreSurfaceLightmaps( void ){
        char dirname[ 1024 ], filename[ 1024 ];
        shaderInfo_t        *csi;
        char lightmapName[ 128 ];
-       char                *rgbGenValues[ 256 ];
-       char                *alphaGenValues[ 256 ];
+       const char              *rgbGenValues[ 256 ];
+       const char              *alphaGenValues[ 256 ];
 
 
        /* note it */
        Sys_Printf( "--- StoreSurfaceLightmaps ---\n" );
 
        /* setup */
-       strcpy( dirname, source );
-       StripExtension( dirname );
+       if ( lmCustomDir ) {
+               strcpy( dirname, lmCustomDir );
+       }
+       else
+       {
+               strcpy( dirname, source );
+               StripExtension( dirname );
+       }
        memset( rgbGenValues, 0, sizeof( rgbGenValues ) );
        memset( alphaGenValues, 0, sizeof( alphaGenValues ) );
 
@@ -2338,7 +2501,7 @@ void StoreSurfaceLightmaps( void ){
           ----------------------------------------------------------------- */
 
        /* note it */
-       Sys_FPrintf( SYS_VRB, "Subsampling..." );
+       Sys_Printf( "Subsampling..." );
 
        /* walk the list of raw lightmaps */
        numUsed = 0;
@@ -2674,13 +2837,139 @@ void StoreSurfaceLightmaps( void ){
                }
        }
 
+       /* -----------------------------------------------------------------
+          convert modelspace deluxemaps to tangentspace
+          ----------------------------------------------------------------- */
+       /* note it */
+       if ( !bouncing ) {
+               if ( deluxemap && deluxemode == 1 ) {
+                       vec3_t worldUp, myNormal, myTangent, myBinormal;
+                       float dist;
+
+                       Sys_Printf( "converting..." );
+
+                       for ( i = 0; i < numRawLightmaps; i++ )
+                       {
+                               /* get lightmap */
+                               lm = &rawLightmaps[ i ];
+
+                               /* walk lightmap samples */
+                               for ( y = 0; y < lm->sh; y++ )
+                               {
+                                       for ( x = 0; x < lm->sw; x++ )
+                                       {
+                                               /* get normal and deluxel */
+                                               normal = SUPER_NORMAL( x, y );
+                                               cluster = SUPER_CLUSTER( x, y );
+                                               bspDeluxel = BSP_DELUXEL( x, y );
+                                               deluxel = SUPER_DELUXEL( x, y );
+
+                                               /* get normal */
+                                               VectorSet( myNormal, normal[0], normal[1], normal[2] );
+
+                                               /* get tangent vectors */
+                                               if ( myNormal[ 0 ] == 0.0f && myNormal[ 1 ] == 0.0f ) {
+                                                       if ( myNormal[ 2 ] == 1.0f ) {
+                                                               VectorSet( myTangent, 1.0f, 0.0f, 0.0f );
+                                                               VectorSet( myBinormal, 0.0f, 1.0f, 0.0f );
+                                                       }
+                                                       else if ( myNormal[ 2 ] == -1.0f ) {
+                                                               VectorSet( myTangent, -1.0f, 0.0f, 0.0f );
+                                                               VectorSet( myBinormal,  0.0f, 1.0f, 0.0f );
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       VectorSet( worldUp, 0.0f, 0.0f, 1.0f );
+                                                       CrossProduct( myNormal, worldUp, myTangent );
+                                                       VectorNormalize( myTangent, myTangent );
+                                                       CrossProduct( myTangent, myNormal, myBinormal );
+                                                       VectorNormalize( myBinormal, myBinormal );
+                                               }
+
+                                               /* project onto plane */
+                                               dist = -DotProduct( myTangent, myNormal );
+                                               VectorMA( myTangent, dist, myNormal, myTangent );
+                                               dist = -DotProduct( myBinormal, myNormal );
+                                               VectorMA( myBinormal, dist, myNormal, myBinormal );
+
+                                               /* renormalize */
+                                               VectorNormalize( myTangent, myTangent );
+                                               VectorNormalize( myBinormal, myBinormal );
+
+                                               /* convert modelspace deluxel to tangentspace */
+                                               dirSample[0] = bspDeluxel[0];
+                                               dirSample[1] = bspDeluxel[1];
+                                               dirSample[2] = bspDeluxel[2];
+                                               VectorNormalize( dirSample, dirSample );
+
+                                               /* fix tangents to world matrix */
+                                               if ( myNormal[0] > 0 || myNormal[1] < 0 || myNormal[2] < 0 ) {
+                                                       VectorNegate( myTangent, myTangent );
+                                               }
+
+                                               /* build tangentspace vectors */
+                                               bspDeluxel[0] = DotProduct( dirSample, myTangent );
+                                               bspDeluxel[1] = DotProduct( dirSample, myBinormal );
+                                               bspDeluxel[2] = DotProduct( dirSample, myNormal );
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /* -----------------------------------------------------------------
+          blend lightmaps
+          ----------------------------------------------------------------- */
+
+#ifdef sdfsdfwq312323
+       /* note it */
+       Sys_Printf( "blending..." );
+
+       for ( i = 0; i < numRawLightmaps; i++ )
+       {
+               vec3_t myColor;
+               float myBrightness;
+
+               /* get lightmap */
+               lm = &rawLightmaps[ i ];
+
+               /* walk individual lightmaps */
+               for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+               {
+                       /* early outs */
+                       if ( lm->superLuxels[ lightmapNum ] == NULL ) {
+                               continue;
+                       }
+
+                       /* walk lightmap samples */
+                       for ( y = 0; y < lm->sh; y++ )
+                       {
+                               for ( x = 0; x < lm->sw; x++ )
+                               {
+                                       /* get luxel */
+                                       bspLuxel = BSP_LUXEL( lightmapNum, x, y );
+
+                                       /* get color */
+                                       VectorNormalize( bspLuxel, myColor );
+                                       myBrightness = VectorLength( bspLuxel );
+                                       myBrightness *= ( 1 / 127.0f );
+                                       myBrightness = myBrightness * myBrightness;
+                                       myBrightness *= 127.0f;
+                                       VectorScale( myColor, myBrightness, bspLuxel );
+                               }
+                       }
+               }
+       }
+#endif
+
        /* -----------------------------------------------------------------
           collapse non-unique lightmaps
           ----------------------------------------------------------------- */
 
        if ( noCollapse == qfalse && deluxemap == qfalse ) {
                /* note it */
-               Sys_FPrintf( SYS_VRB, "collapsing..." );
+               Sys_Printf( "collapsing..." );
 
                /* set all twin refs to null */
                for ( i = 0; i < numRawLightmaps; i++ )
@@ -2749,7 +3038,7 @@ void StoreSurfaceLightmaps( void ){
           ----------------------------------------------------------------- */
 
        /* note it */
-       Sys_FPrintf( SYS_VRB, "sorting..." );
+       Sys_Printf( "sorting..." );
 
        /* allocate a new sorted list */
        if ( sortLightmaps == NULL ) {
@@ -2766,7 +3055,7 @@ void StoreSurfaceLightmaps( void ){
           ----------------------------------------------------------------- */
 
        /* note it */
-       Sys_FPrintf( SYS_VRB, "allocating..." );
+       Sys_Printf( "allocating..." );
 
        /* kill all existing output lightmaps */
        if ( outLightmaps != NULL ) {
@@ -2788,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 */
@@ -2819,7 +3108,7 @@ void StoreSurfaceLightmaps( void ){
           ----------------------------------------------------------------- */
 
        /* note it */
-       Sys_FPrintf( SYS_VRB, "storing..." );
+       Sys_Printf( "storing..." );
 
        /* count the bsp lightmaps and allocate space */
        if ( bspLightBytes != NULL ) {
@@ -2842,6 +3131,11 @@ 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 ) {
                        /* copy lighting data */
@@ -2884,7 +3178,7 @@ void StoreSurfaceLightmaps( void ){
        }
 
        if ( numExtLightmaps > 0 ) {
-               Sys_FPrintf( SYS_VRB, "\n" );
+               Sys_Printf( "\n" );
        }
 
        /* delete unused external lightmaps */
@@ -2905,7 +3199,7 @@ void StoreSurfaceLightmaps( void ){
           ----------------------------------------------------------------- */
 
        /* note it */
-       Sys_FPrintf( SYS_VRB, "projecting..." );
+       Sys_Printf( "projecting..." );
 
        /* walk the list of surfaces */
        for ( i = 0; i < numBSPDrawSurfaces; i++ )
@@ -3075,7 +3369,7 @@ void StoreSurfaceLightmaps( void ){
                                /* get rgbgen string */
                                if ( rgbGenValues[ style ] == NULL ) {
                                        sprintf( key, "_style%drgbgen", style );
-                                       rgbGenValues[ style ] = (char*) ValueForKey( &entities[ 0 ], key );
+                                       rgbGenValues[ style ] = ValueForKey( &entities[ 0 ], key );
                                        if ( rgbGenValues[ style ][ 0 ] == '\0' ) {
                                                rgbGenValues[ style ] = "wave noise 0.5 1 0 5.37";
                                        }
@@ -3091,7 +3385,7 @@ void StoreSurfaceLightmaps( void ){
                                /* get alphagen string */
                                if ( alphaGenValues[ style ] == NULL ) {
                                        sprintf( key, "_style%dalphagen", style );
-                                       alphaGenValues[ style ] = (char*) ValueForKey( &entities[ 0 ], key );
+                                       alphaGenValues[ style ] = ValueForKey( &entities[ 0 ], key );
                                }
                                if ( alphaGenValues[ style ][ 0 ] != '\0' ) {
                                        sprintf( alphaGen, "\t\talphaGen %s // style %d\n", alphaGenValues[ style ], style );
@@ -3184,7 +3478,7 @@ void StoreSurfaceLightmaps( void ){
        }
 
        /* finish */
-       Sys_FPrintf( SYS_VRB, "done.\n" );
+       Sys_Printf( "done.\n" );
 
        /* calc num stored */
        numStored = numBSPLightBytes / 3;