Merge pull request #605 from illwieckz/oldfork

lightmap floodlight and exposure [netradiant's q3map2 pivot commit]
This commit is contained in:
Timothee "TTimo" Besset 2018-03-24 17:42:40 -04:00 committed by GitHub
commit 7be91fd84e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 776 additions and 114 deletions

View File

@ -852,7 +852,9 @@ int BSPMain( int argc, char **argv ){
deepBSP = qtrue;
}
else if( !strcmp( argv[ i ], "-bsp" ) )
{
Sys_Printf( "-bsp argument unnecessary\n" );
}
else
{
Sys_Printf( "WARNING: Unknown option \"%s\"\n", argv[ i ] );

View File

@ -63,6 +63,7 @@
qfalse, /* wolf lighting model? */
0, /* lightmap width/height */
0, /* lightmap gamma */
0, /* lightmap exposure */
0, /* lightmap compensate */
0, /* minimap size */
0, /* minimap sharpener */

View File

@ -113,6 +113,7 @@
qfalse, /* wolf lighting model? */
128, /* lightmap width/height */
1.0f, /* lightmap gamma */
0.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
512, /* minimap size */
1.0f, /* minimap sharpener */

View File

@ -148,6 +148,7 @@
qfalse, /* wolf lighting model? */
128, /* lightmap width/height */
2.2f, /* lightmap gamma */
0.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
512, /* minimap size */
1.0f, /* minimap sharpener */

View File

@ -67,6 +67,7 @@
qfalse, /* wolf lighting model? */
128, /* lightmap width/height */
1.0f, /* lightmap gamma */
0.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
512, /* minimap size */
1.0f, /* minimap sharpener */

View File

@ -64,6 +64,7 @@
qfalse, /* wolf lighting model? */
128, /* lightmap width/height */
1.0f, /* lightmap gamma */
0.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
512, /* minimap size */
1.0f, /* minimap sharpener */

View File

@ -63,6 +63,7 @@
qfalse, /* wolf lighting model? */
128, /* lightmap width/height */
1.0f, /* lightmap gamma */
0.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
512, /* minimap size */
1.0f, /* minimap sharpener */

View File

@ -112,6 +112,7 @@
qfalse, /* wolf lighting model? */
512, /* lightmap width/height */
1.0f, /* lightmap gamma */
0.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
256, /* minimap size */
1.0f, /* minimap sharpener */

View File

@ -112,6 +112,7 @@
qfalse, /* wolf lighting model? */
128, /* lightmap width/height */
1.0f, /* lightmap gamma */
0.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
512, /* minimap size */
1.0f, /* minimap sharpener */

View File

@ -76,6 +76,7 @@
qfalse, /* wolf lighting model? */
128, /* lightmap width/height */
1.0f, /* lightmap gamma */
0.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
512, /* minimap size */
1.0f, /* minimap sharpener */

View File

@ -84,6 +84,7 @@
qfalse, /* wolf lighting model? */
128, /* lightmap width/height */
1.0f, /* lightmap gamma */
0.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
512, /* minimap size */
1.0f, /* minimap sharpener */

View File

@ -139,6 +139,7 @@
qfalse, /* wolf lighting model? */
128, /* lightmap width/height */
1.0f, /* lightmap gamma */
0.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
512, /* minimap size */
1.0f, /* minimap sharpener */

View File

@ -112,6 +112,7 @@
qfalse, /* wolf lighting model? */
512, /* lightmap width/height */
2.0f, /* lightmap gamma */
0.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
512, /* minimap size */
1.0f, /* minimap sharpener */

View File

@ -70,6 +70,7 @@
qfalse, /* wolf lighting model? */
128, /* lightmap width/height */
1.0f, /* lightmap gamma */
0.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
512, /* minimap size */
1.0f, /* minimap sharpener */

View File

@ -72,6 +72,7 @@ game_t struct
qfalse, /* wolf lighting model? */
128, /* lightmap width/height */
1.0f, /* lightmap gamma */
1.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
512, /* minimap size */
1.0f, /* minimap sharpener */

View File

@ -129,6 +129,7 @@
qtrue, /* wolf lighting model? */
128, /* lightmap width/height */
1.0f, /* lightmap gamma */
0.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
512, /* minimap size */
1.0f, /* minimap sharpener */

View File

@ -66,6 +66,7 @@
qtrue, /* wolf lighting model? */
128, /* lightmap width/height */
1.0f, /* lightmap gamma */
0.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
512, /* minimap size */
1.0f, /* minimap sharpener */

View File

@ -1442,6 +1442,54 @@ void TraceGrid( int num ){
}
}
/////// Floodlighting for point //////////////////
//do our floodlight ambient occlusion loop, and add a single contribution based on the brightest dir
if ( floodlighty ) {
int q;
float addSize,f;
vec3_t col,dir;
col[0] = col[1] = col[2] = floodlightIntensity;
dir[0] = dir[1] = 0;
dir[2] = 1;
trace.testOcclusion = qtrue;
trace.forceSunlight = qfalse;
trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
trace.testAll = qtrue;
for ( q = 0; q < 2; q++ )
{
if ( q == 0 ) { //upper hemisphere
trace.normal[0] = 0;
trace.normal[1] = 0;
trace.normal[2] = 1;
}
else //lower hemisphere
{
trace.normal[0] = 0;
trace.normal[1] = 0;
trace.normal[2] = -1;
}
f = FloodLightForSample( &trace );
contributions[ numCon ].color[0] = col[0] * f;
contributions[ numCon ].color[1] = col[1] * f;
contributions[ numCon ].color[2] = col[2] * f;
contributions[ numCon ].dir[0] = dir[0];
contributions[ numCon ].dir[1] = dir[1];
contributions[ numCon ].dir[2] = dir[2];
contributions[ numCon ].style = 0;
numCon++;
/* push average direction around */
addSize = VectorLength( col );
VectorMA( gp->dir, addSize, dir, gp->dir );
}
}
/////////////////////
/* normalize to get primary light direction */
VectorNormalize( gp->dir, gp->dir );
@ -1725,6 +1773,11 @@ void LightWorld( void ){
RunThreadsOnIndividual( numRawLightmaps, qtrue, DirtyRawLightmap );
}
/* floodlight them up */
if ( floodlighty ) {
Sys_Printf( "--- FloodlightRawLightmap ---\n" );
RunThreadsOnIndividual( numRawLightmaps, qtrue, FloodLightRawLightmap );
}
/* ydnar: set up light envelopes */
SetupEnvelopes( qfalse, fast );
@ -1767,6 +1820,7 @@ void LightWorld( void ){
/* flag bouncing */
bouncing = qtrue;
VectorClear( ambientColor );
floodlighty = qfalse;
/* generate diffuse lights */
RadFreeLights();
@ -1894,6 +1948,13 @@ int LightMain( int argc, char **argv ){
i++;
}
else if ( !strcmp( argv[ i ], "-exposure" ) ) {
f = atof( argv[ i + 1 ] );
lightmapExposure = f;
Sys_Printf( "Lighting exposure set to %f\n", lightmapExposure );
i++;
}
else if ( !strcmp( argv[ i ], "-compensate" ) ) {
f = atof( argv[ i + 1 ] );
if ( f <= 0.0f ) {
@ -2204,6 +2265,18 @@ int LightMain( int argc, char **argv ){
cpmaHack = qtrue;
Sys_Printf( "Enabling Challenge Pro Mode Asstacular Vertex Lighting Mode (tm)\n" );
}
else if ( !strcmp( argv[ i ], "-floodlight" ) ) {
floodlighty = qtrue;
Sys_Printf( "FloodLighting enabled\n" );
}
else if ( !strcmp( argv[ i ], "-debugnormals" ) ) {
debugnormals = qtrue;
Sys_Printf( "DebugNormals enabled\n" );
}
else if ( !strcmp( argv[ i ], "-lowquality" ) ) {
floodlight_lowquality = qtrue;
Sys_Printf( "Low Quality FloodLighting enabled\n" );
}
/* r7: dirtmapping */
else if ( !strcmp( argv[ i ], "-dirty" ) ) {
@ -2294,6 +2367,7 @@ int LightMain( int argc, char **argv ){
/* ydnar: set up optimization */
SetupBrushes();
SetupDirt();
SetupFloodLight();
SetupSurfaceLightmaps();
/* initialize the surface facet tracing */

View File

@ -48,6 +48,7 @@ void ColorToBytes( const float *color, byte *colorBytes, float scale ){
int i;
float max, gamma;
vec3_t sample;
float inv, dif;
/* ydnar: scaling necessary for simulating r_overbrightBits on external lightmaps */
@ -72,16 +73,46 @@ void ColorToBytes( const float *color, byte *colorBytes, float scale ){
sample[ i ] = pow( sample[ i ] / 255.0f, gamma ) * 255.0f;
}
/* clamp with color normalization */
max = sample[ 0 ];
if ( sample[ 1 ] > max ) {
max = sample[ 1 ];
if ( lightmapExposure == 0 ) {
/* clamp with color normalization */
max = sample[ 0 ];
if ( sample[ 1 ] > max ) {
max = sample[ 1 ];
}
if ( sample[ 2 ] > max ) {
max = sample[ 2 ];
}
if ( max > 255.0f ) {
VectorScale( sample, ( 255.0f / max ), sample );
}
}
if ( sample[ 2 ] > max ) {
max = sample[ 2 ];
}
if ( max > 255.0f ) {
VectorScale( sample, ( 255.0f / max ), sample );
else
{
inv = 1.f / lightmapExposure;
//Exposure
max = sample[ 0 ];
if ( sample[ 1 ] > max ) {
max = sample[ 1 ];
}
if ( sample[ 2 ] > max ) {
max = sample[ 2 ];
}
dif = ( 1 - exp( -max * inv ) ) * 255;
if ( max > 0 ) {
dif = dif / max;
}
else
{
dif = 0;
}
for ( i = 0; i < 3; i++ )
{
sample[i] *= dif;
}
}
/* compensate for ingame overbrighting/bitshifting */
@ -390,13 +421,19 @@ static void PerturbNormal( bspDrawVert_t *dv, shaderInfo_t *si, vec3_t pNormal,
#define NUDGE 0.5f
#define BOGUS_NUDGE -99999.0f
static int MapSingleLuxel( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv, vec4_t plane, float pass, vec3_t stv[ 3 ], vec3_t ttv[ 3 ] ){
static int MapSingleLuxel( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv, vec4_t plane, float pass, vec3_t stv[ 3 ], vec3_t ttv[ 3 ], vec3_t worldverts[ 3 ] ){
int i, x, y, numClusters, *clusters, pointCluster, *cluster;
float *luxel, *origin, *normal, d, lightmapSampleOffset;
shaderInfo_t *si;
vec3_t pNormal;
vec3_t vecs[ 3 ];
vec3_t nudged;
vec3_t cverts[ 3 ];
vec3_t temp;
vec4_t sideplane, hostplane;
vec3_t origintwo;
int j, next;
float e;
float *nudge;
static float nudges[][ 2 ] =
{
@ -497,6 +534,49 @@ static int MapSingleLuxel( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t
VectorCopy( dv->xyz, origin );
}
//////////////////////
//27's test to make sure samples stay within the triangle boundaries
//1) Test the sample origin to see if it lays on the wrong side of any edge (x/y)
//2) if it does, nudge it onto the correct side.
if ( worldverts != NULL ) {
for ( j = 0; j < 3; j++ )
{
VectorCopy( worldverts[j],cverts[j] );
}
PlaneFromPoints( hostplane,cverts[0],cverts[1],cverts[2] );
for ( j = 0; j < 3; j++ )
{
for ( i = 0; i < 3; i++ )
{
//build plane using 2 edges and a normal
next = ( i + 1 ) % 3;
VectorCopy( cverts[next],temp );
VectorAdd( temp,hostplane,temp );
PlaneFromPoints( sideplane,cverts[i],cverts[ next ], temp );
//planetest sample point
e = DotProduct( origin,sideplane );
e = e - sideplane[3];
if ( e > 0 ) {
//we're bad.
//VectorClear(origin);
//Move the sample point back inside triangle bounds
origin[0] -= sideplane[0] * ( e + 1 );
origin[1] -= sideplane[1] * ( e + 1 );
origin[2] -= sideplane[2] * ( e + 1 );
#ifdef DEBUG_27_1
VectorClear( origin );
#endif
}
}
}
}
////////////////////////
/* planar surfaces have precalculated lightmap vectors for nudging */
if ( lm->plane != NULL ) {
VectorCopy( lm->vecs[ 0 ], vecs[ 0 ] );
@ -533,8 +613,12 @@ static int MapSingleLuxel( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t
origin[ lm->axisNum ] += lightmapSampleOffset;
}
VectorCopy( origin,origintwo );
origintwo[0] += vecs[2][0];
origintwo[1] += vecs[2][1];
origintwo[2] += vecs[2][2];
/* get cluster */
pointCluster = ClusterForPointExtFilter( origin, LUXEL_EPSILON, numClusters, clusters );
pointCluster = ClusterForPointExtFilter( origintwo, LUXEL_EPSILON, numClusters, clusters );
/* another retarded hack, storing nudge count in luxel[ 1 ] */
luxel[ 1 ] = 0.0f;
@ -549,7 +633,7 @@ static int MapSingleLuxel( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t
for ( i = 0; i < 3; i++ )
{
/* set nudged point*/
nudged[ i ] = origin[ i ] + ( nudge[ 0 ] * vecs[ 0 ][ i ] ) + ( nudge[ 1 ] * vecs[ 1 ][ i ] );
nudged[ i ] = origintwo[ i ] + ( nudge[ 0 ] * vecs[ 0 ][ i ] ) + ( nudge[ 1 ] * vecs[ 1 ][ i ] );
}
nudge += 2;
@ -615,7 +699,7 @@ static int MapSingleLuxel( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t
than the distance between two luxels (thanks jc :)
*/
static void MapTriangle_r( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv[ 3 ], vec4_t plane, vec3_t stv[ 3 ], vec3_t ttv[ 3 ] ){
static void MapTriangle_r( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv[ 3 ], vec4_t plane, vec3_t stv[ 3 ], vec3_t ttv[ 3 ], vec3_t worldverts[ 3 ] ){
bspDrawVert_t mid, *dv2[ 3 ];
int max;
@ -662,7 +746,7 @@ static void MapTriangle_r( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t
/* split the longest edge and map it */
LerpDrawVert( dv[ max ], dv[ ( max + 1 ) % 3 ], &mid );
MapSingleLuxel( lm, info, &mid, plane, 1, stv, ttv );
MapSingleLuxel( lm, info, &mid, plane, 1, stv, ttv, worldverts );
/* push the point up a little bit to account for fp creep (fixme: revisit this) */
//% VectorMA( mid.xyz, 2.0f, mid.normal, mid.xyz );
@ -670,12 +754,12 @@ static void MapTriangle_r( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t
/* recurse to first triangle */
VectorCopy( dv, dv2 );
dv2[ max ] = &mid;
MapTriangle_r( lm, info, dv2, plane, stv, ttv );
MapTriangle_r( lm, info, dv2, plane, stv, ttv, worldverts );
/* recurse to second triangle */
VectorCopy( dv, dv2 );
dv2[ ( max + 1 ) % 3 ] = &mid;
MapTriangle_r( lm, info, dv2, plane, stv, ttv );
MapTriangle_r( lm, info, dv2, plane, stv, ttv, worldverts );
}
@ -690,6 +774,7 @@ static qboolean MapTriangle( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert
int i;
vec4_t plane;
vec3_t *stv, *ttv, stvStatic[ 3 ], ttvStatic[ 3 ];
vec3_t worldverts[ 3 ];
/* get plane if possible */
@ -714,15 +799,18 @@ static qboolean MapTriangle( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert
ttv = NULL;
}
VectorCopy( dv[ 0 ]->xyz, worldverts[ 0 ] );
VectorCopy( dv[ 1 ]->xyz, worldverts[ 1 ] );
VectorCopy( dv[ 2 ]->xyz, worldverts[ 2 ] );
/* map the vertexes */
MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv );
MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv );
MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv );
MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv, worldverts );
MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv, worldverts );
MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv, worldverts );
/* 2002-11-20: prefer axial triangle edges */
if ( mapNonAxial ) {
/* subdivide the triangle */
MapTriangle_r( lm, info, dv, plane, stv, ttv );
MapTriangle_r( lm, info, dv, plane, stv, ttv, worldverts );
return qtrue;
}
@ -743,7 +831,7 @@ static qboolean MapTriangle( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert
dv2[ 2 ] = dv[ ( i + 1 ) % 3 ];
/* map the degenerate triangle */
MapTriangle_r( lm, info, dv2, plane, stv, ttv );
MapTriangle_r( lm, info, dv2, plane, stv, ttv, worldverts );
}
}
@ -804,8 +892,8 @@ static void MapQuad_r( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv
LerpDrawVert( dv[ max + 2 ], dv[ ( max + 3 ) % 4 ], &mid[ 1 ] );
/* map the vertexes */
MapSingleLuxel( lm, info, &mid[ 0 ], plane, 1, stv, ttv );
MapSingleLuxel( lm, info, &mid[ 1 ], plane, 1, stv, ttv );
MapSingleLuxel( lm, info, &mid[ 0 ], plane, 1, stv, ttv, NULL );
MapSingleLuxel( lm, info, &mid[ 1 ], plane, 1, stv, ttv, NULL );
/* 0 and 2 */
if ( max == 0 ) {
@ -888,10 +976,10 @@ static qboolean MapQuad( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *
}
/* map the vertexes */
MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv );
MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv );
MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv );
MapSingleLuxel( lm, info, dv[ 3 ], plane, 1, stv, ttv );
MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv, NULL );
MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv, NULL );
MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv, NULL );
MapSingleLuxel( lm, info, dv[ 3 ], plane, 1, stv, ttv, NULL );
/* subdivide the quad */
MapQuad_r( lm, info, dv, plane, stv, ttv );
@ -1196,7 +1284,7 @@ void MapRawLightmap( int rawLightmapNum ){
}
/* map the fake vert */
MapSingleLuxel( lm, NULL, &fake, lm->plane, pass, NULL, NULL );
MapSingleLuxel( lm, NULL, &fake, lm->plane, pass, NULL, NULL, NULL );
}
}
}
@ -1784,6 +1872,8 @@ void IlluminateRawLightmap( int rawLightmapNum ){
float tests[ 4 ][ 2 ] = { { 0.0f, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } };
trace_t trace;
float stackLightLuxels[ STACK_LL_SIZE ];
vec3_t flood;
float *floodlight;
/* bail if this number exceeds the number of raw lightmaps */
@ -1987,22 +2077,31 @@ void IlluminateRawLightmap( int rawLightmapNum ){
origin = SUPER_ORIGIN( x, y );
normal = SUPER_NORMAL( x, y );
/* set contribution count */
lightLuxel[ 3 ] = 1.0f;
/* setup trace */
trace.cluster = *cluster;
VectorCopy( origin, trace.origin );
VectorCopy( normal, trace.normal );
/* get light for this sample */
LightContributionToSample( &trace );
VectorCopy( trace.color, lightLuxel );
/* add to count */
if ( trace.color[ 0 ] || trace.color[ 1 ] || trace.color[ 2 ] ) {
////////// 27's temp hack for testing edge clipping ////
if ( origin[0] == 0 && origin[1] == 0 && origin[2] == 0 ) {
lightLuxel[ 1 ] = 255;
lightLuxel[ 3 ] = 1.0f;
totalLighted++;
}
else
{
/* set contribution count */
lightLuxel[ 3 ] = 1.0f;
/* setup trace */
trace.cluster = *cluster;
VectorCopy( origin, trace.origin );
VectorCopy( normal, trace.normal );
/* get light for this sample */
LightContributionToSample( &trace );
VectorCopy( trace.color, lightLuxel );
/* add to count */
if ( trace.color[ 0 ] || trace.color[ 1 ] || trace.color[ 2 ] ) {
totalLighted++;
}
}
/* add to light direction map (fixme: use luxel normal as starting point for deluxel?) */
if ( deluxemap ) {
@ -2255,6 +2354,80 @@ void IlluminateRawLightmap( int rawLightmapNum ){
/* free light list */
FreeTraceLights( &trace );
/* -----------------------------------------------------------------
floodlight pass
----------------------------------------------------------------- */
if ( floodlighty ) {
/* walk lightmaps */
for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
{
/* early out */
if ( lm->superLuxels[ lightmapNum ] == NULL ) {
continue;
}
/* apply floodlight to each luxel */
for ( y = 0; y < lm->sh; y++ )
{
for ( x = 0; x < lm->sw; x++ )
{
/* get cluster */
cluster = SUPER_CLUSTER( x, y );
//% if( *cluster < 0 )
//% continue;
/* get particulars */
luxel = SUPER_LUXEL( lightmapNum, x, y );
floodlight = SUPER_FLOODLIGHT( x, y );
flood[0] = floodlightRGB[0] * floodlightIntensity;
flood[1] = floodlightRGB[1] * floodlightIntensity;
flood[2] = floodlightRGB[2] * floodlightIntensity;
/* scale light value */
VectorScale( flood, *floodlight, flood );
luxel[0] += flood[0];
luxel[1] += flood[1];
luxel[2] += flood[2];
if ( luxel[3] == 0 ) {
luxel[3] = 1;
}
}
}
}
}
if ( debugnormals ) {
for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
{
/* early out */
if ( lm->superLuxels[ lightmapNum ] == NULL ) {
continue;
}
for ( y = 0; y < lm->sh; y++ )
{
for ( x = 0; x < lm->sw; x++ )
{
/* get cluster */
cluster = SUPER_CLUSTER( x, y );
//% if( *cluster < 0 )
//% continue;
/* get particulars */
luxel = SUPER_LUXEL( lightmapNum, x, y );
normal = SUPER_NORMAL( x, y );
luxel[0] = ( normal[0] * 127 ) + 127;
luxel[1] = ( normal[1] * 127 ) + 127;
luxel[2] = ( normal[2] * 127 ) + 127;
}
}
}
}
/* -----------------------------------------------------------------
dirt pass
----------------------------------------------------------------- */
@ -2775,8 +2948,7 @@ void IlluminateVertexes( int num ){
determines opaque brushes in the world and find sky shaders for sunlight calculations
*/
void SetupBrushesFlags( unsigned int mask_any, unsigned int test_any, unsigned int mask_all, unsigned int test_all )
{
void SetupBrushesFlags( unsigned int mask_any, unsigned int test_any, unsigned int mask_all, unsigned int test_all ){
int i, j, b;
unsigned int compileFlags, allCompileFlags;
qboolean inside;
@ -3659,3 +3831,328 @@ void CreateTraceLightsForSurface( int num, trace_t *trace ){
/* create the lights for the bounding box */
CreateTraceLightsForBounds( mins, maxs, normal, info->numSurfaceClusters, &surfaceClusters[ info->firstSurfaceCluster ], LIGHT_SURFACES, trace );
}
/////////////////////////////////////////////////////////////
#define FLOODLIGHT_CONE_ANGLE 88 /* degrees */
#define FLOODLIGHT_NUM_ANGLE_STEPS 16
#define FLOODLIGHT_NUM_ELEVATION_STEPS 4
#define FLOODLIGHT_NUM_VECTORS ( FLOODLIGHT_NUM_ANGLE_STEPS * FLOODLIGHT_NUM_ELEVATION_STEPS )
static vec3_t floodVectors[ FLOODLIGHT_NUM_VECTORS ];
static int numFloodVectors = 0;
void SetupFloodLight( void ){
int i, j;
float angle, elevation, angleStep, elevationStep;
const char *value;
double v1,v2,v3,v4,v5;
/* note it */
Sys_FPrintf( SYS_VRB, "--- SetupFloodLight ---\n" );
/* calculate angular steps */
angleStep = DEG2RAD( 360.0f / FLOODLIGHT_NUM_ANGLE_STEPS );
elevationStep = DEG2RAD( FLOODLIGHT_CONE_ANGLE / FLOODLIGHT_NUM_ELEVATION_STEPS );
/* iterate angle */
angle = 0.0f;
for ( i = 0, angle = 0.0f; i < FLOODLIGHT_NUM_ANGLE_STEPS; i++, angle += angleStep )
{
/* iterate elevation */
for ( j = 0, elevation = elevationStep * 0.5f; j < FLOODLIGHT_NUM_ELEVATION_STEPS; j++, elevation += elevationStep )
{
floodVectors[ numFloodVectors ][ 0 ] = sin( elevation ) * cos( angle );
floodVectors[ numFloodVectors ][ 1 ] = sin( elevation ) * sin( angle );
floodVectors[ numFloodVectors ][ 2 ] = cos( elevation );
numFloodVectors++;
}
}
/* emit some statistics */
Sys_FPrintf( SYS_VRB, "%9d numFloodVectors\n", numFloodVectors );
/* floodlight */
value = ValueForKey( &entities[ 0 ], "_floodlight" );
if ( value[ 0 ] != '\0' ) {
v1 = v2 = v3 = 0;
v4 = floodlightDistance;
v5 = floodlightIntensity;
sscanf( value, "%lf %lf %lf %lf %lf", &v1, &v2, &v3, &v4, &v5 );
floodlightRGB[0] = v1;
floodlightRGB[1] = v2;
floodlightRGB[2] = v3;
if ( VectorLength( floodlightRGB ) == 0 ) {
VectorSet( floodlightRGB,240,240,255 );
}
if ( v4 < 1 ) {
v4 = 1024;
}
if ( v5 < 1 ) {
v5 = 128;
}
floodlightDistance = v4;
floodlightIntensity = v5;
floodlighty = qtrue;
Sys_Printf( "FloodLighting enabled via worldspawn _floodlight key.\n" );
}
else
{
VectorSet( floodlightRGB,240,240,255 );
//floodlighty = qtrue;
//Sys_Printf( "FloodLighting enabled via worldspawn _floodlight key.\n" );
}
VectorNormalize( floodlightRGB,floodlightRGB );
}
//27 - lighttracer style ambient occlusion light hack.
//Kudos to the dirtmapping author for most of this source.
void FloodLightRawLightmap( int rawLightmapNum ){
int i, x, y, sx, sy, *cluster;
float *origin, *normal, *floodlight, *floodlight2, average, samples;
rawLightmap_t *lm;
surfaceInfo_t *info;
trace_t trace;
/* bail if this number exceeds the number of raw lightmaps */
if ( rawLightmapNum >= numRawLightmaps ) {
return;
}
/* get lightmap */
lm = &rawLightmaps[ rawLightmapNum ];
memset( &trace,0,sizeof( trace_t ) );
/* setup trace */
trace.testOcclusion = qtrue;
trace.forceSunlight = qfalse;
trace.twoSided = qtrue;
trace.recvShadows = lm->recvShadows;
trace.numSurfaces = lm->numLightSurfaces;
trace.surfaces = &lightSurfaces[ lm->firstLightSurface ];
trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
trace.testAll = qfalse;
trace.distance = 1024;
/* twosided lighting (may or may not be a good idea for lightmapped stuff) */
//trace.twoSided = qfalse;
for ( i = 0; i < trace.numSurfaces; i++ )
{
/* get surface */
info = &surfaceInfos[ trace.surfaces[ i ] ];
/* check twosidedness */
if ( info->si->twoSided ) {
trace.twoSided = qtrue;
break;
}
}
/* gather dirt */
for ( y = 0; y < lm->sh; y++ )
{
for ( x = 0; x < lm->sw; x++ )
{
/* get luxel */
cluster = SUPER_CLUSTER( x, y );
origin = SUPER_ORIGIN( x, y );
normal = SUPER_NORMAL( x, y );
floodlight = SUPER_FLOODLIGHT( x, y );
/* set default dirt */
*floodlight = 0.0f;
/* only look at mapped luxels */
if ( *cluster < 0 ) {
continue;
}
/* copy to trace */
trace.cluster = *cluster;
VectorCopy( origin, trace.origin );
VectorCopy( normal, trace.normal );
/* get dirt */
*floodlight = FloodLightForSample( &trace );
}
}
/* testing no filtering */
return;
/* filter "dirt" */
for ( y = 0; y < lm->sh; y++ )
{
for ( x = 0; x < lm->sw; x++ )
{
/* get luxel */
cluster = SUPER_CLUSTER( x, y );
floodlight = SUPER_FLOODLIGHT( x, y );
/* filter dirt by adjacency to unmapped luxels */
average = *floodlight;
samples = 1.0f;
for ( sy = ( y - 1 ); sy <= ( y + 1 ); sy++ )
{
if ( sy < 0 || sy >= lm->sh ) {
continue;
}
for ( sx = ( x - 1 ); sx <= ( x + 1 ); sx++ )
{
if ( sx < 0 || sx >= lm->sw || ( sx == x && sy == y ) ) {
continue;
}
/* get neighboring luxel */
cluster = SUPER_CLUSTER( sx, sy );
floodlight2 = SUPER_FLOODLIGHT( sx, sy );
if ( *cluster < 0 || *floodlight2 <= 0.0f ) {
continue;
}
/* add it */
average += *floodlight2;
samples += 1.0f;
}
/* bail */
if ( samples <= 0.0f ) {
break;
}
}
/* bail */
if ( samples <= 0.0f ) {
continue;
}
/* scale dirt */
*floodlight = average / samples;
}
}
}
/*
FloodLightForSample()
calculates floodlight value for a given sample
once again, kudos to the dirtmapping coder
*/
float FloodLightForSample( trace_t *trace ){
int i;
float d;
float contribution;
int sub = 0;
float gatherLight, outLight;
vec3_t normal, worldUp, myUp, myRt, direction, displacement;
float dd;
int vecs = 0;
gatherLight = 0;
/* dummy check */
//if( !dirty )
// return 1.0f;
if ( trace == NULL || trace->cluster < 0 ) {
return 0.0f;
}
/* setup */
dd = floodlightDistance;
VectorCopy( trace->normal, normal );
/* check if the normal is aligned to the world-up */
if ( normal[ 0 ] == 0.0f && normal[ 1 ] == 0.0f ) {
if ( normal[ 2 ] == 1.0f ) {
VectorSet( myRt, 1.0f, 0.0f, 0.0f );
VectorSet( myUp, 0.0f, 1.0f, 0.0f );
}
else if ( normal[ 2 ] == -1.0f ) {
VectorSet( myRt, -1.0f, 0.0f, 0.0f );
VectorSet( myUp, 0.0f, 1.0f, 0.0f );
}
}
else
{
VectorSet( worldUp, 0.0f, 0.0f, 1.0f );
CrossProduct( normal, worldUp, myRt );
VectorNormalize( myRt, myRt );
CrossProduct( myRt, normal, myUp );
VectorNormalize( myUp, myUp );
}
/* iterate through ordered vectors */
for ( i = 0; i < numFloodVectors; i++ )
{
if ( floodlight_lowquality == qtrue ) {
if ( rand() % 10 != 0 ) {
continue;
}
}
vecs++;
/* transform vector into tangent space */
direction[ 0 ] = myRt[ 0 ] * floodVectors[ i ][ 0 ] + myUp[ 0 ] * floodVectors[ i ][ 1 ] + normal[ 0 ] * floodVectors[ i ][ 2 ];
direction[ 1 ] = myRt[ 1 ] * floodVectors[ i ][ 0 ] + myUp[ 1 ] * floodVectors[ i ][ 1 ] + normal[ 1 ] * floodVectors[ i ][ 2 ];
direction[ 2 ] = myRt[ 2 ] * floodVectors[ i ][ 0 ] + myUp[ 2 ] * floodVectors[ i ][ 1 ] + normal[ 2 ] * floodVectors[ i ][ 2 ];
/* set endpoint */
VectorMA( trace->origin, dd, direction, trace->end );
//VectorMA( trace->origin, 1, direction, trace->origin );
SetupTrace( trace );
/* trace */
TraceLine( trace );
contribution = 1;
if ( trace->compileFlags & C_SKY ) {
contribution = 1.0f;
}
else if ( trace->opaque ) {
VectorSubtract( trace->hit, trace->origin, displacement );
d = VectorLength( displacement );
// d=trace->distance;
//if (d>256) gatherDirt+=1;
contribution = d / dd;
if ( contribution > 1 ) {
contribution = 1.0f;
}
//gatherDirt += 1.0f - ooDepth * VectorLength( displacement );
}
gatherLight += contribution;
}
/* early out */
if ( gatherLight <= 0.0f ) {
return 0.0f;
}
sub = vecs;
if ( sub < 1 ) {
sub = 1;
}
gatherLight /= ( sub );
outLight = gatherLight;
if ( outLight > 1.0f ) {
outLight = 1.0f;
}
/* return to sender */
return outLight;
}

View File

@ -410,6 +410,13 @@ void FinishRawLightmap( rawLightmap_t *lm ){
}
memset( lm->superNormals, 0, size );
/* allocate cluster 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 ) {
@ -1210,7 +1217,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, *luxels[ MAX_STITCH_LUXELS ];
/* disabled for now */
@ -2111,8 +2118,7 @@ static void FindOutLightmaps( rawLightmap_t *lm ){
/* allocate two new output lightmaps */
numOutLightmaps += 2;
olm = safe_malloc( numOutLightmaps * sizeof( outLightmap_t ) );
if ( !olm )
{
if ( !olm ) {
Error( "FindOutLightmaps: Failed to allocate memory.\n" );
}

View File

@ -239,7 +239,7 @@ qboolean SnapNormal( vec3_t normal ){
snaps a plane to normal/distance epsilons
*/
void SnapPlane( vec3_t normal, vec_t *dist ){
void SnapPlane( vec3_t normal, vec_t *dist, vec3_t center ){
// SnapPlane disabled by LordHavoc because it often messes up collision
// brushes made from triangles of embedded models, and it has little effect
// on anything else (axial planes are usually derived from snapped points)
@ -315,7 +315,7 @@ void SnapPlaneImproved( vec3_t normal, vec_t *dist, int numPoints, const vec3_t
must be within an epsilon distance of the plane
*/
int FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points )
int FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points ) // NOTE: this has a side effect on the normal. Good or bad?
#ifdef USE_HASHING
@ -324,7 +324,6 @@ int FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points )
plane_t *p;
vec_t d;
#if Q3MAP2_EXPERIMENTAL_SNAP_PLANE_FIX
SnapPlaneImproved( normal, &dist, numPoints, (const vec3_t *) points );
#else

View File

@ -225,6 +225,8 @@ void InsertModel( char *name, int frame, m4x4_t transform, remap_t *remap, shade
byte *color;
picoIndex_t *indexes;
remap_t *rm, *glob;
double normalEpsilon_save;
double distanceEpsilon_save;
/* get model */
@ -415,9 +417,8 @@ void InsertModel( char *name, int frame, m4x4_t transform, remap_t *remap, shade
/* ydnar: giant hack land: generate clipping brushes for model triangles */
if ( si->clipModel || ( spawnFlags & 2 ) ) { /* 2nd bit */
vec3_t points[ 3 ], backs[ 3 ];
vec3_t points[ 4 ], backs[ 3 ];
vec4_t plane, reverse, pa, pb, pc;
vec3_t nadir;
/* temp hack */
@ -458,8 +459,8 @@ void InsertModel( char *name, int frame, m4x4_t transform, remap_t *remap, shade
/* note: this doesn't work as well as simply using the plane of the triangle, below */
for ( k = 0; k < 3; k++ )
{
if ( fabs( dv->normal[ k ] ) > fabs( dv->normal[ ( k + 1 ) % 3 ] ) &&
fabs( dv->normal[ k ] ) > fabs( dv->normal[ ( k + 2 ) % 3 ] ) ) {
if ( fabs( dv->normal[ k ] ) >= fabs( dv->normal[ ( k + 1 ) % 3 ] ) &&
fabs( dv->normal[ k ] ) >= fabs( dv->normal[ ( k + 2 ) % 3 ] ) ) {
backs[ j ][ k ] += dv->normal[ k ] < 0.0f ? 64.0f : -64.0f;
break;
}
@ -467,85 +468,136 @@ void InsertModel( char *name, int frame, m4x4_t transform, remap_t *remap, shade
#endif
}
VectorCopy( points[0], points[3] ); // for cyclic usage
/* make plane for triangle */
// div0: add some extra spawnflags:
// 0: snap normals to axial planes for extrusion
// 8: extrude with the original normals
// 16: extrude only with up/down normals (ideal for terrain)
// 24: extrude by distance zero (may need engine changes)
if ( PlaneFromPoints( plane, points[ 0 ], points[ 1 ], points[ 2 ] ) ) {
vec3_t bestNormal;
float backPlaneDistance = 2;
if ( spawnFlags & 8 ) { // use a DOWN normal
if ( spawnFlags & 16 ) {
// 24: normal as is, and zero width (broken)
VectorCopy( plane, bestNormal );
}
else
{
// 8: normal as is
VectorCopy( plane, bestNormal );
}
}
else
{
if ( spawnFlags & 16 ) {
// 16: UP/DOWN normal
VectorSet( bestNormal, 0, 0, ( plane[2] >= 0 ? 1 : -1 ) );
}
else
{
// 0: axial normal
if ( fabs( plane[0] ) > fabs( plane[1] ) ) { // x>y
if ( fabs( plane[1] ) > fabs( plane[2] ) ) { // x>y, y>z
VectorSet( bestNormal, ( plane[0] >= 0 ? 1 : -1 ), 0, 0 );
}
else // x>y, z>=y
if ( fabs( plane[0] ) > fabs( plane[2] ) ) { // x>z, z>=y
VectorSet( bestNormal, ( plane[0] >= 0 ? 1 : -1 ), 0, 0 );
}
else{ // z>=x, x>y
VectorSet( bestNormal, 0, 0, ( plane[2] >= 0 ? 1 : -1 ) );
}
}
else // y>=x
if ( fabs( plane[1] ) > fabs( plane[2] ) ) { // y>z, y>=x
VectorSet( bestNormal, 0, ( plane[1] >= 0 ? 1 : -1 ), 0 );
}
else{ // z>=y, y>=x
VectorSet( bestNormal, 0, 0, ( plane[2] >= 0 ? 1 : -1 ) );
}
}
}
/* build a brush */
buildBrush = AllocBrush( 48 );
buildBrush->entityNum = mapEntityNum;
buildBrush->original = buildBrush;
buildBrush->contentShader = si;
buildBrush->compileFlags = si->compileFlags;
buildBrush->contentFlags = si->contentFlags;
normalEpsilon_save = normalEpsilon;
distanceEpsilon_save = distanceEpsilon;
if ( si->compileFlags & C_STRUCTURAL ) { // allow forced structural brushes here
buildBrush->detail = qfalse;
// only allow EXACT matches when snapping for these (this is mostly for caulk brushes inside a model)
if ( normalEpsilon > 0 ) {
normalEpsilon = 0;
}
if ( distanceEpsilon > 0 ) {
distanceEpsilon = 0;
}
}
else{
buildBrush->detail = qtrue;
}
/* regenerate back points */
for ( j = 0; j < 3; j++ )
{
/* get vertex */
dv = &ds->verts[ ds->indexes[ i + j ] ];
/* copy xyz */
VectorCopy( dv->xyz, backs[ j ] );
/* find nearest axial to plane normal and push back points opposite */
for ( k = 0; k < 3; k++ )
{
#if Q3MAP2_EXPERIMENTAL_MODEL_CLIPPING_FIX
if ( fabs( plane[ k ] ) >= fabs( plane[ ( k + 1 ) % 3 ] ) &&
fabs( plane[ k ] ) >= fabs( plane[ ( k + 2 ) % 3 ] ) )
#else
// This code is broken for 45 degree angles where there
// is no clear winner.
if ( fabs( plane[ k ] ) > fabs( plane[ ( k + 1 ) % 3 ] ) &&
fabs( plane[ k ] ) > fabs( plane[ ( k + 2 ) % 3 ] ) )
#endif
{
backs[ j ][ k ] += plane[ k ] < 0.0f ? 64.0f : -64.0f;
break;
}
}
// shift by some units
VectorMA( dv->xyz, -64.0f, bestNormal, backs[j] ); // 64 prevents roundoff errors a bit
}
/* make back plane */
VectorScale( plane, -1.0f, reverse );
reverse[ 3 ] = -( plane[ 3 ] - 1 );
/* make back pyramid point */
VectorCopy( points[ 0 ], nadir );
VectorAdd( nadir, points[ 1 ], nadir );
VectorAdd( nadir, points[ 2 ], nadir );
VectorScale( nadir, 0.3333333333333f, nadir );
VectorMA( nadir, -2.0f, plane, nadir );
/* make 3 more planes */
//% if( PlaneFromPoints( pa, points[ 2 ], points[ 1 ], nadir ) &&
//% PlaneFromPoints( pb, points[ 1 ], points[ 0 ], nadir ) &&
//% PlaneFromPoints( pc, points[ 0 ], points[ 2 ], nadir ) )
reverse[ 3 ] = -plane[ 3 ];
if ( ( spawnFlags & 24 ) != 24 ) {
reverse[3] += DotProduct( bestNormal, plane ) * backPlaneDistance;
}
// that's at least sqrt(1/3) backPlaneDistance, unless in DOWN mode; in DOWN mode, we are screwed anyway if we encounter a plane that's perpendicular to the xy plane)
if ( PlaneFromPoints( pa, points[ 2 ], points[ 1 ], backs[ 1 ] ) &&
PlaneFromPoints( pb, points[ 1 ], points[ 0 ], backs[ 0 ] ) &&
PlaneFromPoints( pc, points[ 0 ], points[ 2 ], backs[ 2 ] ) ) {
/* build a brush */
buildBrush = AllocBrush( 48 );
buildBrush->entityNum = mapEntityNum;
buildBrush->original = buildBrush;
buildBrush->contentShader = si;
buildBrush->compileFlags = si->compileFlags;
buildBrush->contentFlags = si->contentFlags;
buildBrush->detail = qtrue;
/* set up brush sides */
buildBrush->numsides = 5;
for ( j = 0; j < buildBrush->numsides; j++ )
buildBrush->sides[ j ].shaderInfo = si;
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( pa, pa[ 3 ], 1, &points[ 2 ] );
buildBrush->sides[ 2 ].planenum = FindFloatPlane( pb, pb[ 3 ], 1, &points[ 1 ] );
buildBrush->sides[ 3 ].planenum = FindFloatPlane( pc, pc[ 3 ], 1, &points[ 0 ] );
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 3, points );
/* add to entity */
if ( CreateBrushWindings( buildBrush ) ) {
AddBrushBevels();
//% EmitBrushes( buildBrush, NULL, NULL );
buildBrush->next = entities[ mapEntityNum ].brushes;
entities[ mapEntityNum ].brushes = buildBrush;
entities[ mapEntityNum ].numBrushes++;
}
else{
free( buildBrush );
}
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points );
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( pa, pa[ 3 ], 2, &points[ 1 ] ); // pa contains points[1] and points[2]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( pb, pb[ 3 ], 2, &points[ 0 ] ); // pb contains points[0] and points[1]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( pc, pc[ 3 ], 2, &points[ 2 ] ); // pc contains points[2] and points[0] (copied to points[3]
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 3, backs );
}
else
{
free( buildBrush );
continue;
}
normalEpsilon = normalEpsilon_save;
distanceEpsilon = distanceEpsilon_save;
/* add to entity */
if ( CreateBrushWindings( buildBrush ) ) {
AddBrushBevels();
//% EmitBrushes( buildBrush, NULL, NULL );
buildBrush->next = entities[ mapEntityNum ].brushes;
entities[ mapEntityNum ].brushes = buildBrush;
entities[ mapEntityNum ].numBrushes++;
}
else{
free( buildBrush );
}
}
}

View File

@ -276,6 +276,7 @@
#define SUPER_NORMAL_SIZE 4
#define SUPER_DELUXEL_SIZE 3
#define BSP_DELUXEL_SIZE 3
#define SUPER_FLOODLIGHT_SIZE 1
#define VERTEX_LUXEL( s, v ) ( vertexLuxels[ s ] + ( ( v ) * VERTEX_LUXEL_SIZE ) )
#define RAD_VERTEX_LUXEL( s, v )( radVertexLuxels[ s ] + ( ( v ) * VERTEX_LUXEL_SIZE ) )
@ -288,6 +289,7 @@
#define SUPER_ORIGIN( x, y ) ( lm->superOrigins + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_ORIGIN_SIZE ) )
#define SUPER_NORMAL( x, y ) ( lm->superNormals + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_NORMAL_SIZE ) )
#define SUPER_DIRT( x, y ) ( lm->superNormals + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_NORMAL_SIZE ) + 3 ) /* stash dirtyness in normal[ 3 ] */
#define SUPER_FLOODLIGHT( x, y ) ( lm->superFloodLight + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_FLOODLIGHT_SIZE ) )
@ -572,6 +574,7 @@ typedef struct game_s
qboolean wolfLight; /* when true, lights work like wolf q3map */
int lightmapSize; /* bsp lightmap width/height */
float lightmapGamma; /* default lightmap gamma */
float lightmapExposure; /* default lightmap exposure */
float lightmapCompensate; /* default lightmap compensate value */
int miniMapSize; /* minimap size */
float miniMapSharpen; /* minimap sharpening coefficient */
@ -1430,6 +1433,7 @@ typedef struct rawLightmap_s
float *superDeluxels; /* average light direction */
float *bspDeluxels;
float *superFloodLight;
}
rawLightmap_t;
@ -1498,7 +1502,7 @@ int BSPInfoMain( int argc, char **argv );
int ScaleBSPMain( int argc, char **argv );
/* minimap.c */
int MiniMapBSPMain( int argc, char **argv );
int MiniMapBSPMain( int argc, char **argv );
/* convert_bsp.c */
int ConvertBSPMain( int argc, char **argv );
@ -1763,6 +1767,10 @@ void SetupDirt();
float DirtForSample( trace_t *trace );
void DirtyRawLightmap( int num );
void SetupFloodLight();
float FloodLightForSample( trace_t *trace );
void FloodLightRawLightmap( int num );
void IlluminateRawLightmap( int num );
void IlluminateVertexes( int num );
@ -2198,6 +2206,13 @@ Q_EXTERN float dirtDepth Q_ASSIGN( 128.0f );
Q_EXTERN float dirtScale Q_ASSIGN( 1.0f );
Q_EXTERN float dirtGain Q_ASSIGN( 1.0f );
Q_EXTERN qboolean debugnormals Q_ASSIGN( qfalse );
Q_EXTERN qboolean floodlighty Q_ASSIGN( qfalse );
Q_EXTERN qboolean floodlight_lowquality Q_ASSIGN( qfalse );
Q_EXTERN vec3_t floodlightRGB;
Q_EXTERN float floodlightIntensity Q_ASSIGN( 512 );
Q_EXTERN float floodlightDistance Q_ASSIGN( 1024 );
Q_EXTERN qboolean dump Q_ASSIGN( qfalse );
Q_EXTERN qboolean debug Q_ASSIGN( qfalse );
Q_EXTERN qboolean debugUnused Q_ASSIGN( qfalse );
@ -2217,6 +2232,7 @@ Q_EXTERN float bounceScale Q_ASSIGN( 0.25f );
/* ydnar: lightmap gamma/compensation */
Q_EXTERN float lightmapGamma Q_ASSIGN( 1.0f );
Q_EXTERN float lightmapExposure Q_ASSIGN( 0.0f );
Q_EXTERN float lightmapCompensate Q_ASSIGN( 1.0f );
/* ydnar: for runtime tweaking of falloff tolerance */