X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fnetradiant.git;a=blobdiff_plain;f=tools%2Fquake3%2Fq3map2%2Flight_bounce.c;h=f72653ab88fb21f849a820b341e1a6808a6e7931;hp=d78c6dee872d9c15cd438099fbd952aa91955cba;hb=e4287c28bb2dafedc81c66e63951d947cfbeb225;hpb=203343b01a7ad87cb3d136689c9936ff5bc23c01 diff --git a/tools/quake3/q3map2/light_bounce.c b/tools/quake3/q3map2/light_bounce.c index d78c6dee..f72653ab 100644 --- a/tools/quake3/q3map2/light_bounce.c +++ b/tools/quake3/q3map2/light_bounce.c @@ -1,30 +1,30 @@ /* ------------------------------------------------------------------------------- -Copyright (C) 1999-2007 id Software, Inc. and contributors. -For a list of contributors, see the accompanying CONTRIBUTORS file. + Copyright (C) 1999-2007 id Software, Inc. and contributors. + For a list of contributors, see the accompanying CONTRIBUTORS file. -This file is part of GtkRadiant. + This file is part of GtkRadiant. -GtkRadiant is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + GtkRadiant is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -GtkRadiant is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + GtkRadiant is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with GtkRadiant; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + You should have received a copy of the GNU General Public License + along with GtkRadiant; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ----------------------------------------------------------------------------------- + ---------------------------------------------------------------------------------- -This code has been altered significantly from its original form, to support -several games based on the Quake III Arena engine, in the form of "Q3Map2." + This code has been altered significantly from its original form, to support + several games based on the Quake III Arena engine, in the form of "Q3Map2." -------------------------------------------------------------------------------- */ + ------------------------------------------------------------------------------- */ @@ -41,21 +41,21 @@ several games based on the Quake III Arena engine, in the form of "Q3Map2." /* functions */ /* -RadFreeLights() -deletes any existing lights, freeing up memory for the next bounce -*/ - -void RadFreeLights( void ) -{ - light_t *light, *next; - - + RadFreeLights() + deletes any existing lights, freeing up memory for the next bounce + */ + +void RadFreeLights( void ){ + light_t *light, *next; + + /* delete lights */ - for( light = lights; light; light = next ) + for ( light = lights; light; light = next ) { next = light->next; - if( light->w != NULL ) + if ( light->w != NULL ) { FreeWinding( light->w ); + } free( light ); } numLights = 0; @@ -65,118 +65,117 @@ void RadFreeLights( void ) /* -RadClipWindingEpsilon() -clips a rad winding by a plane -based off the regular clip winding code -*/ + RadClipWindingEpsilon() + clips a rad winding by a plane + based off the regular clip winding code + */ static void RadClipWindingEpsilon( radWinding_t *in, vec3_t normal, vec_t dist, - vec_t epsilon, radWinding_t *front, radWinding_t *back, clipWork_t *cw ) -{ - vec_t *dists; - int *sides; - int counts[ 3 ]; - vec_t dot; /* ydnar: changed from static b/c of threading */ /* VC 4.2 optimizer bug if not static? */ - int i, j, k; - radVert_t *v1, *v2, mid; - int maxPoints; - - + vec_t epsilon, radWinding_t *front, radWinding_t *back, clipWork_t *cw ){ + vec_t *dists; + int *sides; + int counts[ 3 ]; + vec_t dot; /* ydnar: changed from static b/c of threading */ /* VC 4.2 optimizer bug if not static? */ + int i, j, k; + radVert_t *v1, *v2, mid; + int maxPoints; + + /* crutch */ dists = cw->dists; sides = cw->sides; - + /* clear counts */ counts[ 0 ] = counts[ 1 ] = counts[ 2 ] = 0; /* determine sides for each point */ - for( i = 0; i < in->numVerts; i++ ) + for ( i = 0; i < in->numVerts; i++ ) { dot = DotProduct( in->verts[ i ].xyz, normal ); dot -= dist; dists[ i ] = dot; - if( dot > epsilon ) + if ( dot > epsilon ) { sides[ i ] = SIDE_FRONT; - else if( dot < -epsilon ) + } + else if ( dot < -epsilon ) { sides[ i ] = SIDE_BACK; - else + } + else{ sides[ i ] = SIDE_ON; + } counts[ sides[ i ] ]++; } sides[ i ] = sides[ 0 ]; dists[ i ] = dists[ 0 ]; - + /* clear front and back */ front->numVerts = back->numVerts = 0; - + /* handle all on one side cases */ - if( counts[ 0 ] == 0 ) - { + if ( counts[ 0 ] == 0 ) { memcpy( back, in, sizeof( radWinding_t ) ); return; } - if( counts[ 1 ] == 0 ) - { + if ( counts[ 1 ] == 0 ) { memcpy( front, in, sizeof( radWinding_t ) ); return; } - + /* setup windings */ maxPoints = in->numVerts + 4; - + /* do individual verts */ - for( i = 0; i < in->numVerts; i++ ) + for ( i = 0; i < in->numVerts; i++ ) { /* do simple vertex copies first */ v1 = &in->verts[ i ]; - - if( sides[ i ] == SIDE_ON ) - { + + if ( sides[ i ] == SIDE_ON ) { memcpy( &front->verts[ front->numVerts++ ], v1, sizeof( radVert_t ) ); memcpy( &back->verts[ back->numVerts++ ], v1, sizeof( radVert_t ) ); continue; } - - if( sides[ i ] == SIDE_FRONT ) + + if ( sides[ i ] == SIDE_FRONT ) { memcpy( &front->verts[ front->numVerts++ ], v1, sizeof( radVert_t ) ); - - if( sides[ i ] == SIDE_BACK ) + } + + if ( sides[ i ] == SIDE_BACK ) { memcpy( &back->verts[ back->numVerts++ ], v1, sizeof( radVert_t ) ); - - if( sides[ i + 1 ] == SIDE_ON || sides[ i + 1 ] == sides[ i ] ) + } + + if ( sides[ i + 1 ] == SIDE_ON || sides[ i + 1 ] == sides[ i ] ) { continue; - + } + /* generate a split vertex */ - v2 = &in->verts[ (i + 1) % in->numVerts ]; - - dot = dists[ i ] / (dists[ i ] - dists[ i + 1 ]); + v2 = &in->verts[ ( i + 1 ) % in->numVerts ]; + + dot = dists[ i ] / ( dists[ i ] - dists[ i + 1 ] ); /* average vertex values */ - for( j = 0; j < 4; j++ ) + for ( j = 0; j < 4; j++ ) { /* color */ - if( j < 4 ) - { - for( k = 0; k < MAX_LIGHTMAPS; k++ ) - mid.color[ k ][ j ] = v1->color[ k ][ j ] + dot * (v2->color[ k ][ j ] - v1->color[ k ][ j ]); + if ( j < 4 ) { + for ( k = 0; k < MAX_LIGHTMAPS; k++ ) + mid.color[ k ][ j ] = v1->color[ k ][ j ] + dot * ( v2->color[ k ][ j ] - v1->color[ k ][ j ] ); } - + /* xyz, normal */ - if( j < 3 ) - { - mid.xyz[ j ] = v1->xyz[ j ] + dot * (v2->xyz[ j ] - v1->xyz[ j ]); - mid.normal[ j ] = v1->normal[ j ] + dot * (v2->normal[ j ] - v1->normal[ j ]); + if ( j < 3 ) { + mid.xyz[ j ] = v1->xyz[ j ] + dot * ( v2->xyz[ j ] - v1->xyz[ j ] ); + mid.normal[ j ] = v1->normal[ j ] + dot * ( v2->normal[ j ] - v1->normal[ j ] ); } - + /* st, lightmap */ - if( j < 2 ) - { - mid.st[ j ] = v1->st[ j ] + dot * (v2->st[ j ] - v1->st[ j ]); - for( k = 0; k < MAX_LIGHTMAPS; k++ ) - mid.lightmap[ k ][ j ] = v1->lightmap[ k ][ j ] + dot * (v2->lightmap[ k ][ j ] - v1->lightmap[ k ][ j ]); + if ( j < 2 ) { + mid.st[ j ] = v1->st[ j ] + dot * ( v2->st[ j ] - v1->st[ j ] ); + for ( k = 0; k < MAX_LIGHTMAPS; k++ ) + mid.lightmap[ k ][ j ] = v1->lightmap[ k ][ j ] + dot * ( v2->lightmap[ k ][ j ] - v1->lightmap[ k ][ j ] ); } } - + /* normalize the averaged normal */ VectorNormalize( mid.normal, mid.normal ); @@ -184,12 +183,14 @@ static void RadClipWindingEpsilon( radWinding_t *in, vec3_t normal, vec_t dist, memcpy( &front->verts[ front->numVerts++ ], &mid, sizeof( radVert_t ) ); memcpy( &back->verts[ back->numVerts++ ], &mid, sizeof( radVert_t ) ); } - + /* error check */ - if( front->numVerts > maxPoints || front->numVerts > maxPoints ) + if ( front->numVerts > maxPoints || front->numVerts > maxPoints ) { Error( "RadClipWindingEpsilon: points exceeded estimate" ); - if( front->numVerts > MAX_POINTS_ON_WINDING || front->numVerts > MAX_POINTS_ON_WINDING ) + } + if ( front->numVerts > MAX_POINTS_ON_WINDING || front->numVerts > MAX_POINTS_ON_WINDING ) { Error( "RadClipWindingEpsilon: MAX_POINTS_ON_WINDING" ); + } } @@ -197,48 +198,47 @@ static void RadClipWindingEpsilon( radWinding_t *in, vec3_t normal, vec_t dist, /* -RadSampleImage() -samples a texture image for a given color -returns qfalse if pixels are bad -*/ - -qboolean RadSampleImage( byte *pixels, int width, int height, float st[ 2 ], float color[ 4 ] ) -{ - float sto[ 2 ]; - int x, y; - - + RadSampleImage() + samples a texture image for a given color + returns qfalse if pixels are bad + */ + +qboolean RadSampleImage( byte *pixels, int width, int height, float st[ 2 ], float color[ 4 ] ){ + float sto[ 2 ]; + int x, y; + + /* clear color first */ color[ 0 ] = color[ 1 ] = color[ 2 ] = color[ 3 ] = 255; - + /* dummy check */ - if( pixels == NULL || width < 1 || height < 1 ) + if ( pixels == NULL || width < 1 || height < 1 ) { return qfalse; - + } + /* bias st */ sto[ 0 ] = st[ 0 ]; - while( sto[ 0 ] < 0.0f ) + while ( sto[ 0 ] < 0.0f ) sto[ 0 ] += 1.0f; sto[ 1 ] = st[ 1 ]; - while( sto[ 1 ] < 0.0f ) + while ( sto[ 1 ] < 0.0f ) sto[ 1 ] += 1.0f; /* get offsets */ - x = ((float) width * sto[ 0 ]) + 0.5f; + x = ( (float) width * sto[ 0 ] ) + 0.5f; x %= width; - y = ((float) height * sto[ 1 ]) + 0.5f; + y = ( (float) height * sto[ 1 ] ) + 0.5f; y %= height; - + /* get pixel */ - pixels += (y * width * 4) + (x * 4); + pixels += ( y * width * 4 ) + ( x * 4 ); VectorCopy( pixels, color ); color[ 3 ] = pixels[ 3 ]; - if(texturesRGB) - { - color[0] = Image_LinearFloatFromsRGBFloat(color[0] * (1.0 / 255.0)) * 255.0; - color[1] = Image_LinearFloatFromsRGBFloat(color[1] * (1.0 / 255.0)) * 255.0; - color[2] = Image_LinearFloatFromsRGBFloat(color[2] * (1.0 / 255.0)) * 255.0; + if ( texturesRGB ) { + color[0] = Image_LinearFloatFromsRGBFloat( color[0] * ( 1.0 / 255.0 ) ) * 255.0; + color[1] = Image_LinearFloatFromsRGBFloat( color[1] * ( 1.0 / 255.0 ) ) * 255.0; + color[2] = Image_LinearFloatFromsRGBFloat( color[2] * ( 1.0 / 255.0 ) ) * 255.0; } return qtrue; @@ -247,308 +247,310 @@ qboolean RadSampleImage( byte *pixels, int width, int height, float st[ 2 ], flo /* -RadSample() -samples a fragment's lightmap or vertex color and returns an -average color and a color gradient for the sample -*/ - -#define MAX_SAMPLES 150 -#define SAMPLE_GRANULARITY 6 - -static void RadSample( int lightmapNum, bspDrawSurface_t *ds, rawLightmap_t *lm, shaderInfo_t *si, radWinding_t *rw, vec3_t average, vec3_t gradient, int *style ) -{ - int i, j, k, l, v, x, y, samples; - vec3_t color, mins, maxs; - vec4_t textureColor; - float alpha, alphaI, bf; - vec3_t blend; - float st[ 2 ], lightmap[ 2 ], *radLuxel; - radVert_t *rv[ 3 ]; - - + RadSample() + samples a fragment's lightmap or vertex color and returns an + average color and a color gradient for the sample + */ + +#define MAX_SAMPLES 150 +#define SAMPLE_GRANULARITY 6 + +static void RadSample( int lightmapNum, bspDrawSurface_t *ds, rawLightmap_t *lm, shaderInfo_t *si, radWinding_t *rw, vec3_t average, vec3_t gradient, int *style ){ + int i, j, k, l, v, x, y, samples; + vec3_t color, mins, maxs; + vec4_t textureColor; + float alpha, alphaI, bf; + vec3_t blend; + float st[ 2 ], lightmap[ 2 ], *radLuxel; + radVert_t *rv[ 3 ]; + + /* initial setup */ ClearBounds( mins, maxs ); VectorClear( average ); VectorClear( gradient ); alpha = 0; - + /* dummy check */ - if( rw == NULL || rw->numVerts < 3 ) + if ( rw == NULL || rw->numVerts < 3 ) { return; - + } + /* start sampling */ samples = 0; - + /* sample vertex colors if no lightmap or this is the initial pass */ - if( lm == NULL || lm->radLuxels[ lightmapNum ] == NULL || bouncing == qfalse ) - { - for( samples = 0; samples < rw->numVerts; samples++ ) + if ( lm == NULL || lm->radLuxels[ lightmapNum ] == NULL || bouncing == qfalse ) { + for ( samples = 0; samples < rw->numVerts; samples++ ) { /* multiply by texture color */ - if( !RadSampleImage( si->lightImage->pixels, si->lightImage->width, si->lightImage->height, rw->verts[ samples ].st, textureColor ) ) - { + if ( !RadSampleImage( si->lightImage->pixels, si->lightImage->width, si->lightImage->height, rw->verts[ samples ].st, textureColor ) ) { VectorCopy( si->averageColor, textureColor ); textureColor[ 4 ] = 255.0f; } - for( i = 0; i < 3; i++ ) - color[ i ] = (textureColor[ i ] / 255) * (rw->verts[ samples ].color[ lightmapNum ][ i ] / 255.0f); - + for ( i = 0; i < 3; i++ ) + color[ i ] = ( textureColor[ i ] / 255 ) * ( rw->verts[ samples ].color[ lightmapNum ][ i ] / 255.0f ); + AddPointToBounds( color, mins, maxs ); VectorAdd( average, color, average ); - + /* get alpha */ - alpha += (textureColor[ 3 ] / 255.0f) * (rw->verts[ samples ].color[ lightmapNum ][ 3 ] / 255.0f); + alpha += ( textureColor[ 3 ] / 255.0f ) * ( rw->verts[ samples ].color[ lightmapNum ][ 3 ] / 255.0f ); } - + /* set style */ *style = ds->vertexStyles[ lightmapNum ]; } - + /* sample lightmap */ else { /* fracture the winding into a fan (including degenerate tris) */ - for( v = 1; v < (rw->numVerts - 1) && samples < MAX_SAMPLES; v++ ) + for ( v = 1; v < ( rw->numVerts - 1 ) && samples < MAX_SAMPLES; v++ ) { /* get a triangle */ rv[ 0 ] = &rw->verts[ 0 ]; rv[ 1 ] = &rw->verts[ v ]; rv[ 2 ] = &rw->verts[ v + 1 ]; - + /* this code is embarassing (really should just rasterize the triangle) */ - for( i = 1; i < SAMPLE_GRANULARITY && samples < MAX_SAMPLES; i++ ) + for ( i = 1; i < SAMPLE_GRANULARITY && samples < MAX_SAMPLES; i++ ) { - for( j = 1; j < SAMPLE_GRANULARITY && samples < MAX_SAMPLES; j++ ) + for ( j = 1; j < SAMPLE_GRANULARITY && samples < MAX_SAMPLES; j++ ) { - for( k = 1; k < SAMPLE_GRANULARITY && samples < MAX_SAMPLES; k++ ) + for ( k = 1; k < SAMPLE_GRANULARITY && samples < MAX_SAMPLES; k++ ) { /* create a blend vector (barycentric coordinates) */ blend[ 0 ] = i; blend[ 1 ] = j; blend[ 2 ] = k; - bf = (1.0 / (blend[ 0 ] + blend[ 1 ] + blend[ 2 ])); + bf = ( 1.0 / ( blend[ 0 ] + blend[ 1 ] + blend[ 2 ] ) ); VectorScale( blend, bf, blend ); - + /* create a blended sample */ st[ 0 ] = st[ 1 ] = 0.0f; lightmap[ 0 ] = lightmap[ 1 ] = 0.0f; alphaI = 0.0f; - for( l = 0; l < 3; l++ ) + for ( l = 0; l < 3; l++ ) { - st[ 0 ] += (rv[ l ]->st[ 0 ] * blend[ l ]); - st[ 1 ] += (rv[ l ]->st[ 1 ] * blend[ l ]); - lightmap[ 0 ] += (rv[ l ]->lightmap[ lightmapNum ][ 0 ] * blend[ l ]); - lightmap[ 1 ] += (rv[ l ]->lightmap[ lightmapNum ][ 1 ] * blend[ l ]); - alphaI += (rv[ l ]->color[ lightmapNum ][ 3 ] * blend[ l ]); + st[ 0 ] += ( rv[ l ]->st[ 0 ] * blend[ l ] ); + st[ 1 ] += ( rv[ l ]->st[ 1 ] * blend[ l ] ); + lightmap[ 0 ] += ( rv[ l ]->lightmap[ lightmapNum ][ 0 ] * blend[ l ] ); + lightmap[ 1 ] += ( rv[ l ]->lightmap[ lightmapNum ][ 1 ] * blend[ l ] ); + alphaI += ( rv[ l ]->color[ lightmapNum ][ 3 ] * blend[ l ] ); } - + /* get lightmap xy coords */ x = lightmap[ 0 ] / (float) superSample; y = lightmap[ 1 ] / (float) superSample; - if( x < 0 ) + if ( x < 0 ) { x = 0; - else if ( x >= lm->w ) + } + else if ( x >= lm->w ) { x = lm->w - 1; - if( y < 0 ) + } + if ( y < 0 ) { y = 0; - else if ( y >= lm->h ) + } + else if ( y >= lm->h ) { y = lm->h - 1; - + } + /* get radiosity luxel */ radLuxel = RAD_LUXEL( lightmapNum, x, y ); - + /* ignore unlit/unused luxels */ - if( radLuxel[ 0 ] < 0.0f ) + if ( radLuxel[ 0 ] < 0.0f ) { continue; - + } + /* inc samples */ samples++; - + /* multiply by texture color */ - if( !RadSampleImage( si->lightImage->pixels, si->lightImage->width, si->lightImage->height, st, textureColor ) ) - { + if ( !RadSampleImage( si->lightImage->pixels, si->lightImage->width, si->lightImage->height, st, textureColor ) ) { VectorCopy( si->averageColor, textureColor ); textureColor[ 4 ] = 255; } - for( i = 0; i < 3; i++ ) - color[ i ] = (textureColor[ i ] / 255) * (radLuxel[ i ] / 255); - + for ( i = 0; i < 3; i++ ) + color[ i ] = ( textureColor[ i ] / 255 ) * ( radLuxel[ i ] / 255 ); + AddPointToBounds( color, mins, maxs ); VectorAdd( average, color, average ); - + /* get alpha */ - alpha += (textureColor[ 3 ] / 255) * (alphaI / 255); + alpha += ( textureColor[ 3 ] / 255 ) * ( alphaI / 255 ); } } } } - + /* set style */ *style = ds->lightmapStyles[ lightmapNum ]; } - + /* any samples? */ - if( samples <= 0 ) + if ( samples <= 0 ) { return; - + } + /* average the color */ - VectorScale( average, (1.0 / samples), average ); - + VectorScale( average, ( 1.0 / samples ), average ); + /* 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 ]; + for ( i = 0; i < 3; i++ ) + gradient[ i ] = ( maxs[ i ] - mins[ i ] ) * maxs[ i ]; } /* -RadSubdivideDiffuseLight() -subdivides a radiosity winding until it is smaller than subdivide, then generates an area light -*/ + RadSubdivideDiffuseLight() + subdivides a radiosity winding until it is smaller than subdivide, then generates an area light + */ -#define RADIOSITY_MAX_GRADIENT 0.75f //% 0.25f -#define RADIOSITY_VALUE 500.0f -#define RADIOSITY_MIN 0.0001f -#define RADIOSITY_CLIP_EPSILON 0.125f +#define RADIOSITY_MAX_GRADIENT 0.75f //% 0.25f +#define RADIOSITY_VALUE 500.0f +#define RADIOSITY_MIN 0.0001f +#define RADIOSITY_CLIP_EPSILON 0.125f static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, rawLightmap_t *lm, shaderInfo_t *si, - float scale, float subdivide, qboolean original, radWinding_t *rw, clipWork_t *cw ) -{ - int i, style = 0; - float dist, area, value; - vec3_t mins, maxs, normal, d1, d2, cross, color, gradient; - light_t *light, *splash; - winding_t *w; - - + float scale, float subdivide, qboolean original, radWinding_t *rw, clipWork_t *cw ){ + int i, style = 0; + float dist, area, value; + vec3_t mins, maxs, normal, d1, d2, cross, color, gradient; + light_t *light, *splash; + winding_t *w; + + /* dummy check */ - if( rw == NULL || rw->numVerts < 3 ) + if ( rw == NULL || rw->numVerts < 3 ) { return; - + } + /* get bounds for winding */ ClearBounds( mins, maxs ); - for( i = 0; i < rw->numVerts; i++ ) + for ( i = 0; i < rw->numVerts; i++ ) AddPointToBounds( rw->verts[ i ].xyz, mins, maxs ); - + /* subdivide if necessary */ - for( i = 0; i < 3; i++ ) + for ( i = 0; i < 3; i++ ) { - if( maxs[ i ] - mins[ i ] > subdivide ) - { - radWinding_t front, back; - - + if ( maxs[ i ] - mins[ i ] > subdivide ) { + radWinding_t front, back; + + /* make axial plane */ VectorClear( normal ); normal[ i ] = 1; - dist = (maxs[ i ] + mins[ i ]) * 0.5f; - + dist = ( maxs[ i ] + mins[ i ] ) * 0.5f; + /* clip the winding */ RadClipWindingEpsilon( rw, normal, dist, RADIOSITY_CLIP_EPSILON, &front, &back, cw ); - + /* recurse */ RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, subdivide, qfalse, &front, cw ); RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, subdivide, qfalse, &back, cw ); return; } } - + /* check area */ area = 0.0f; - for( i = 2; i < rw->numVerts; i++ ) + for ( i = 2; i < rw->numVerts; i++ ) { VectorSubtract( rw->verts[ i - 1 ].xyz, rw->verts[ 0 ].xyz, d1 ); VectorSubtract( rw->verts[ i ].xyz, rw->verts[ 0 ].xyz, d2 ); CrossProduct( d1, d2, cross ); area += 0.5f * VectorLength( cross ); } - if( area < 1.0f || area > 20000000.0f ) + if ( area < 1.0f || area > 20000000.0f ) { return; - + } + /* more subdivision may be necessary */ - if( bouncing ) - { + if ( bouncing ) { /* get color sample for the surface fragment */ RadSample( lightmapNum, ds, lm, si, rw, color, gradient, &style ); - + /* if color gradient is too high, subdivide again */ - if( subdivide > minDiffuseSubdivide && - (gradient[ 0 ] > RADIOSITY_MAX_GRADIENT || gradient[ 1 ] > RADIOSITY_MAX_GRADIENT || gradient[ 2 ] > RADIOSITY_MAX_GRADIENT) ) - { - RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, (subdivide / 2.0f), qfalse, rw, cw ); + if ( subdivide > minDiffuseSubdivide && + ( gradient[ 0 ] > RADIOSITY_MAX_GRADIENT || gradient[ 1 ] > RADIOSITY_MAX_GRADIENT || gradient[ 2 ] > RADIOSITY_MAX_GRADIENT ) ) { + RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, ( subdivide / 2.0f ), qfalse, rw, cw ); return; } } - + /* create a regular winding and an average normal */ w = AllocWinding( rw->numVerts ); w->numpoints = rw->numVerts; VectorClear( normal ); - for( i = 0; i < rw->numVerts; i++ ) + for ( i = 0; i < rw->numVerts; i++ ) { VectorCopy( rw->verts[ i ].xyz, w->p[ i ] ); VectorAdd( normal, rw->verts[ i ].normal, normal ); } - VectorScale( normal, (1.0f / rw->numVerts), normal ); - if( VectorNormalize( normal, normal ) == 0.0f ) + VectorScale( normal, ( 1.0f / rw->numVerts ), normal ); + if ( VectorNormalize( normal, normal ) == 0.0f ) { return; - + } + /* early out? */ - if( bouncing && VectorLength( color ) < RADIOSITY_MIN ) + if ( bouncing && VectorLength( color ) < RADIOSITY_MIN ) { return; - + } + /* debug code */ //% Sys_Printf( "Size: %d %d %d\n", (int) (maxs[ 0 ] - mins[ 0 ]), (int) (maxs[ 1 ] - mins[ 1 ]), (int) (maxs[ 2 ] - mins[ 2 ]) ); //% Sys_Printf( "Grad: %f %f %f\n", gradient[ 0 ], gradient[ 1 ], gradient[ 2 ] ); - + /* increment counts */ numDiffuseLights++; - switch( ds->surfaceType ) + switch ( ds->surfaceType ) { - case MST_PLANAR: - numBrushDiffuseLights++; - break; - - case MST_TRIANGLE_SOUP: - numTriangleDiffuseLights++; - break; - - case MST_PATCH: - numPatchDiffuseLights++; - break; - } - + case MST_PLANAR: + numBrushDiffuseLights++; + break; + + case MST_TRIANGLE_SOUP: + numTriangleDiffuseLights++; + break; + + case MST_PATCH: + numPatchDiffuseLights++; + break; + } + /* create a light */ light = safe_malloc( sizeof( *light ) ); memset( light, 0, sizeof( *light ) ); - + /* attach it */ ThreadLock(); light->next = lights; lights = light; ThreadUnlock(); - + /* initialize the light */ light->flags = LIGHT_AREA_DEFAULT; light->type = EMIT_AREA; light->si = si; light->fade = 1.0f; light->w = w; - + /* set falloff threshold */ light->falloffTolerance = falloffTolerance; - + /* bouncing light? */ - if( !bouncing ) - { + if ( !bouncing ) { /* handle first-pass lights in normal q3a style */ value = si->value; light->photons = value * area * areaScale; @@ -556,27 +558,27 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw VectorCopy( si->color, light->color ); VectorScale( light->color, light->add, light->emitColor ); light->style = noStyles ? LS_NORMAL : si->lightStyle; - if( light->style < LS_NORMAL || light->style >= LS_NONE ) + if ( light->style < LS_NORMAL || light->style >= LS_NONE ) { light->style = LS_NORMAL; - + } + /* set origin */ VectorAdd( mins, maxs, light->origin ); VectorScale( light->origin, 0.5f, light->origin ); - + /* nudge it off the plane a bit */ VectorCopy( normal, light->normal ); VectorMA( light->origin, 1.0f, light->normal, light->origin ); light->dist = DotProduct( light->origin, normal ); - + /* optionally create a point splashsplash light for first pass */ - if( original && si->backsplashFraction > 0 ) - { + if ( original && si->backsplashFraction > 0 ) { /* allocate a new point light */ splash = safe_malloc( sizeof( *splash ) ); memset( splash, 0, sizeof( *splash ) ); splash->next = lights; lights = splash; - + /* set it up */ splash->flags = LIGHT_Q3A_DEFAULT; splash->type = EMIT_POINT; @@ -587,7 +589,7 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw VectorCopy( si->color, splash->color ); splash->falloffTolerance = falloffTolerance; splash->style = noStyles ? LS_NORMAL : light->style; - + /* add to counts */ numPointLights++; } @@ -601,22 +603,24 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw VectorCopy( color, light->color ); VectorScale( light->color, light->add, light->emitColor ); light->style = noStyles ? LS_NORMAL : style; - if( light->style < LS_NORMAL || light->style >= LS_NONE ) + if ( light->style < LS_NORMAL || light->style >= LS_NONE ) { light->style = LS_NORMAL; - + } + /* set origin */ WindingCenter( w, light->origin ); - + /* nudge it off the plane a bit */ VectorCopy( normal, light->normal ); VectorMA( light->origin, 1.0f, light->normal, light->origin ); light->dist = DotProduct( light->origin, normal ); } - + /* emit light from both sides? */ - if( si->compileFlags & C_FOG || si->twoSided ) + if ( si->compileFlags & C_FOG || si->twoSided ) { light->flags |= LIGHT_TWOSIDED; - + } + //% Sys_Printf( "\nAL: C: (%6f, %6f, %6f) [%6f] N: (%6f, %6f, %6f) %s\n", //% light->color[ 0 ], light->color[ 1 ], light->color[ 2 ], light->add, //% light->normal[ 0 ], light->normal[ 1 ], light->normal[ 2 ], @@ -626,43 +630,42 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw /* -RadLightForTriangles() -creates unbounced diffuse lights for triangle soup (misc_models, etc) -*/ - -void RadLightForTriangles( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t *si, float scale, float subdivide, clipWork_t *cw ) -{ - int i, j, k, v; - bspDrawSurface_t *ds; - float *radVertexLuxel; - radWinding_t rw; - - + RadLightForTriangles() + creates unbounced diffuse lights for triangle soup (misc_models, etc) + */ + +void RadLightForTriangles( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t *si, float scale, float subdivide, clipWork_t *cw ){ + int i, j, k, v; + bspDrawSurface_t *ds; + float *radVertexLuxel; + radWinding_t rw; + + /* get surface */ ds = &bspDrawSurfaces[ num ]; - + /* each triangle is a potential emitter */ rw.numVerts = 3; - for( i = 0; i < ds->numIndexes; i += 3 ) + for ( i = 0; i < ds->numIndexes; i += 3 ) { /* copy each vert */ - for( j = 0; j < 3; j++ ) + for ( j = 0; j < 3; j++ ) { /* get vertex index and rad vertex luxel */ v = ds->firstVert + bspDrawIndexes[ ds->firstIndex + i + j ]; - + /* get most everything */ memcpy( &rw.verts[ j ], &yDrawVerts[ v ], sizeof( bspDrawVert_t ) ); - + /* fix colors */ - for( k = 0; k < MAX_LIGHTMAPS; k++ ) + for ( k = 0; k < MAX_LIGHTMAPS; k++ ) { radVertexLuxel = RAD_VERTEX_LUXEL( k, ds->firstVert + bspDrawIndexes[ ds->firstIndex + i + j ] ); VectorCopy( radVertexLuxel, rw.verts[ j ].color[ k ] ); rw.verts[ j ].color[ k ][ 3 ] = yDrawVerts[ v ].color[ k ][ 3 ]; } } - + /* subdivide into area lights */ RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, subdivide, qtrue, &rw, cw ); } @@ -671,37 +674,36 @@ void RadLightForTriangles( int num, int lightmapNum, rawLightmap_t *lm, shaderIn /* -RadLightForPatch() -creates unbounced diffuse lights for patches -*/ - -#define PLANAR_EPSILON 0.1f - -void RadLightForPatch( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t *si, float scale, float subdivide, clipWork_t *cw ) -{ - int i, x, y, v, t, pw[ 5 ], r; - bspDrawSurface_t *ds; - surfaceInfo_t *info; - bspDrawVert_t *bogus; - bspDrawVert_t *dv[ 4 ]; - mesh_t src, *subdivided, *mesh; - float *radVertexLuxel; - float dist; - vec4_t plane; - qboolean planar; - radWinding_t rw; - - + RadLightForPatch() + creates unbounced diffuse lights for patches + */ + +#define PLANAR_EPSILON 0.1f + +void RadLightForPatch( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t *si, float scale, float subdivide, clipWork_t *cw ){ + int i, x, y, v, t, pw[ 5 ], r; + bspDrawSurface_t *ds; + surfaceInfo_t *info; + bspDrawVert_t *bogus; + bspDrawVert_t *dv[ 4 ]; + mesh_t src, *subdivided, *mesh; + float *radVertexLuxel; + float dist; + vec4_t plane; + qboolean planar; + radWinding_t rw; + + /* get surface */ ds = &bspDrawSurfaces[ num ]; info = &surfaceInfos[ num ]; - + /* construct a bogus vert list with color index stuffed into color[ 0 ] */ bogus = safe_malloc( ds->numVerts * sizeof( bspDrawVert_t ) ); memcpy( bogus, &yDrawVerts[ ds->firstVert ], ds->numVerts * sizeof( bspDrawVert_t ) ); - for( i = 0; i < ds->numVerts; i++ ) + for ( i = 0; i < ds->numVerts; i++ ) bogus[ i ].color[ 0 ][ 0 ] = i; - + /* build a subdivided mesh identical to shadow facets for this patch */ /* this MUST MATCH FacetsForPatch() identically! */ src.width = ds->patchWidth; @@ -714,100 +716,101 @@ void RadLightForPatch( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t mesh = RemoveLinearMeshColumnsRows( subdivided ); FreeMesh( subdivided ); free( bogus ); - + /* FIXME: build interpolation table into color[ 1 ] */ - + /* fix up color indexes */ - for( i = 0; i < (mesh->width * mesh->height); i++ ) + for ( i = 0; i < ( mesh->width * mesh->height ); i++ ) { dv[ 0 ] = &mesh->verts[ i ]; - if( dv[ 0 ]->color[ 0 ][ 0 ] >= ds->numVerts ) + if ( dv[ 0 ]->color[ 0 ][ 0 ] >= ds->numVerts ) { dv[ 0 ]->color[ 0 ][ 0 ] = ds->numVerts - 1; + } } - + /* iterate through the mesh quads */ - for( y = 0; y < (mesh->height - 1); y++ ) + for ( y = 0; y < ( mesh->height - 1 ); y++ ) { - for( x = 0; x < (mesh->width - 1); x++ ) + for ( x = 0; x < ( mesh->width - 1 ); x++ ) { /* set indexes */ - pw[ 0 ] = x + (y * mesh->width); - pw[ 1 ] = x + ((y + 1) * mesh->width); - pw[ 2 ] = x + 1 + ((y + 1) * mesh->width); - pw[ 3 ] = x + 1 + (y * mesh->width); - pw[ 4 ] = x + (y * mesh->width); /* same as pw[ 0 ] */ - + pw[ 0 ] = x + ( y * mesh->width ); + pw[ 1 ] = x + ( ( y + 1 ) * mesh->width ); + pw[ 2 ] = x + 1 + ( ( y + 1 ) * mesh->width ); + pw[ 3 ] = x + 1 + ( y * mesh->width ); + pw[ 4 ] = x + ( y * mesh->width ); /* same as pw[ 0 ] */ + /* set radix */ - r = (x + y) & 1; - + r = ( x + y ) & 1; + /* get drawverts */ dv[ 0 ] = &mesh->verts[ pw[ r + 0 ] ]; dv[ 1 ] = &mesh->verts[ pw[ r + 1 ] ]; dv[ 2 ] = &mesh->verts[ pw[ r + 2 ] ]; dv[ 3 ] = &mesh->verts[ pw[ r + 3 ] ]; - + /* planar? */ planar = PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ); - if( planar ) - { + if ( planar ) { dist = DotProduct( dv[ 1 ]->xyz, plane ) - plane[ 3 ]; - if( fabs( dist ) > PLANAR_EPSILON ) + if ( fabs( dist ) > PLANAR_EPSILON ) { planar = qfalse; + } } - + /* generate a quad */ - if( planar ) - { + if ( planar ) { rw.numVerts = 4; - for( v = 0; v < 4; v++ ) + for ( v = 0; v < 4; v++ ) { /* get most everything */ memcpy( &rw.verts[ v ], dv[ v ], sizeof( bspDrawVert_t ) ); - + /* fix colors */ - for( i = 0; i < MAX_LIGHTMAPS; i++ ) + for ( i = 0; i < MAX_LIGHTMAPS; i++ ) { radVertexLuxel = RAD_VERTEX_LUXEL( i, ds->firstVert + dv[ v ]->color[ 0 ][ 0 ] ); VectorCopy( radVertexLuxel, rw.verts[ v ].color[ i ] ); rw.verts[ v ].color[ i ][ 3 ] = dv[ v ]->color[ i ][ 3 ]; } } - + /* subdivide into area lights */ RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, subdivide, qtrue, &rw, cw ); } - + /* generate 2 tris */ else { rw.numVerts = 3; - for( t = 0; t < 2; t++ ) + for ( t = 0; t < 2; t++ ) { - for( v = 0; v < 3 + t; v++ ) + for ( v = 0; v < 3 + t; v++ ) { /* get "other" triangle (stupid hacky logic, but whatevah) */ - if( v == 1 && t == 1 ) + if ( v == 1 && t == 1 ) { v++; + } /* get most everything */ memcpy( &rw.verts[ v ], dv[ v ], sizeof( bspDrawVert_t ) ); - + /* fix colors */ - for( i = 0; i < MAX_LIGHTMAPS; i++ ) + for ( i = 0; i < MAX_LIGHTMAPS; i++ ) { radVertexLuxel = RAD_VERTEX_LUXEL( i, ds->firstVert + dv[ v ]->color[ 0 ][ 0 ] ); VectorCopy( radVertexLuxel, rw.verts[ v ].color[ i ] ); rw.verts[ v ].color[ i ][ 3 ] = dv[ v ]->color[ i ][ 3 ]; } } - + /* subdivide into area lights */ RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, subdivide, qtrue, &rw, cw ); } } } } - + /* free the mesh */ FreeMesh( mesh ); } @@ -816,70 +819,71 @@ void RadLightForPatch( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t /* -RadLight() -creates unbounced diffuse lights for a given surface -*/ - -void RadLight( int num ) -{ - int lightmapNum; - float scale, subdivide; - int contentFlags, surfaceFlags, compileFlags; - bspDrawSurface_t *ds; - surfaceInfo_t *info; - rawLightmap_t *lm; - shaderInfo_t *si; - clipWork_t cw; - - + RadLight() + creates unbounced diffuse lights for a given surface + */ + +void RadLight( int num ){ + int lightmapNum; + float scale, subdivide; + int contentFlags, surfaceFlags, compileFlags; + bspDrawSurface_t *ds; + surfaceInfo_t *info; + rawLightmap_t *lm; + shaderInfo_t *si; + clipWork_t cw; + + /* get drawsurface, lightmap, and shader info */ ds = &bspDrawSurfaces[ num ]; info = &surfaceInfos[ num ]; lm = info->lm; si = info->si; scale = si->bounceScale; - + /* find nodraw bit */ contentFlags = surfaceFlags = compileFlags = 0; ApplySurfaceParm( "nodraw", &contentFlags, &surfaceFlags, &compileFlags ); // jal : avoid bouncing on trans surfaces ApplySurfaceParm( "trans", &contentFlags, &surfaceFlags, &compileFlags ); - + /* early outs? */ - if( scale <= 0.0f || (si->compileFlags & C_SKY) || si->autosprite || - (bspShaders[ ds->shaderNum ].contentFlags & contentFlags) || (bspShaders[ ds->shaderNum ].surfaceFlags & surfaceFlags) || - (si->compileFlags & compileFlags) ) + if ( scale <= 0.0f || ( si->compileFlags & C_SKY ) || si->autosprite || + ( bspShaders[ ds->shaderNum ].contentFlags & contentFlags ) || ( bspShaders[ ds->shaderNum ].surfaceFlags & surfaceFlags ) || + ( si->compileFlags & compileFlags ) ) { return; - + } + /* determine how much we need to chop up the surface */ - if( si->lightSubdivide ) + if ( si->lightSubdivide ) { subdivide = si->lightSubdivide; - else + } + else{ subdivide = diffuseSubdivide; - + } + /* inc counts */ numDiffuseSurfaces++; - + /* iterate through styles (this could be more efficient, yes) */ - for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ ) + for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ ) { /* switch on type */ - if( ds->lightmapStyles[ lightmapNum ] != LS_NONE && ds->lightmapStyles[ lightmapNum ] != LS_UNUSED ) - { - switch( ds->surfaceType ) + if ( ds->lightmapStyles[ lightmapNum ] != LS_NONE && ds->lightmapStyles[ lightmapNum ] != LS_UNUSED ) { + switch ( ds->surfaceType ) { - case MST_PLANAR: - case MST_TRIANGLE_SOUP: - RadLightForTriangles( num, lightmapNum, lm, si, scale, subdivide, &cw ); - break; - - case MST_PATCH: - RadLightForPatch( num, lightmapNum, lm, si, scale, subdivide, &cw ); - break; - - default: - break; + case MST_PLANAR: + case MST_TRIANGLE_SOUP: + RadLightForTriangles( num, lightmapNum, lm, si, scale, subdivide, &cw ); + break; + + case MST_PATCH: + RadLightForPatch( num, lightmapNum, lm, si, scale, subdivide, &cw ); + break; + + default: + break; } } } @@ -888,14 +892,13 @@ void RadLight( int num ) /* -RadCreateDiffuseLights() -creates lights for unbounced light on surfaces in the bsp -*/ + RadCreateDiffuseLights() + creates lights for unbounced light on surfaces in the bsp + */ -int iterations = 0; +int iterations = 0; -void RadCreateDiffuseLights( void ) -{ +void RadCreateDiffuseLights( void ){ /* startup */ Sys_FPrintf( SYS_VRB, "--- RadCreateDiffuseLights ---\n" ); numDiffuseSurfaces = 0; @@ -904,52 +907,50 @@ void RadCreateDiffuseLights( void ) numTriangleDiffuseLights = 0; numPatchDiffuseLights = 0; numAreaLights = 0; - + /* hit every surface (threaded) */ RunThreadsOnIndividual( numBSPDrawSurfaces, qtrue, RadLight ); - + /* dump the lights generated to a file */ - if( dump ) - { - char dumpName[ 1024 ], ext[ 64 ]; - FILE *file; - light_t *light; - + if ( dump ) { + char dumpName[ 1024 ], ext[ 64 ]; + FILE *file; + light_t *light; + strcpy( dumpName, source ); StripExtension( dumpName ); sprintf( ext, "_bounce_%03d.map", iterations ); strcat( dumpName, ext ); file = fopen( dumpName, "wb" ); Sys_Printf( "Writing %s...\n", dumpName ); - if( file ) - { - for( light = lights; light; light = light->next ) + if ( file ) { + for ( light = lights; light; light = light->next ) { fprintf( file, - "{\n" - "\"classname\" \"light\"\n" - "\"light\" \"%d\"\n" - "\"origin\" \"%.0f %.0f %.0f\"\n" - "\"_color\" \"%.3f %.3f %.3f\"\n" - "}\n", - - (int) light->add, - - light->origin[ 0 ], - light->origin[ 1 ], - light->origin[ 2 ], - - light->color[ 0 ], - light->color[ 1 ], - light->color[ 2 ] ); + "{\n" + "\"classname\" \"light\"\n" + "\"light\" \"%d\"\n" + "\"origin\" \"%.0f %.0f %.0f\"\n" + "\"_color\" \"%.3f %.3f %.3f\"\n" + "}\n", + + (int) light->add, + + light->origin[ 0 ], + light->origin[ 1 ], + light->origin[ 2 ], + + light->color[ 0 ], + light->color[ 1 ], + light->color[ 2 ] ); } fclose( file ); } } - + /* increment */ iterations++; - + /* print counts */ Sys_Printf( "%8d diffuse surfaces\n", numDiffuseSurfaces ); Sys_FPrintf( SYS_VRB, "%8d total diffuse lights\n", numDiffuseLights ); @@ -957,9 +958,3 @@ void RadCreateDiffuseLights( void ) Sys_FPrintf( SYS_VRB, "%8d patch diffuse lights\n", numPatchDiffuseLights ); Sys_FPrintf( SYS_VRB, "%8d triangle diffuse lights\n", numTriangleDiffuseLights ); } - - - - - -