mirror of
https://github.com/TTimo/GtkRadiant.git
synced 2024-11-10 07:11:54 +00:00
Merge pull request #605 from illwieckz/oldfork
lightmap floodlight and exposure [netradiant's q3map2 pivot commit]
This commit is contained in:
commit
7be91fd84e
23 changed files with 776 additions and 114 deletions
|
@ -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 ] );
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,6 +73,7 @@ void ColorToBytes( const float *color, byte *colorBytes, float scale ){
|
|||
sample[ i ] = pow( sample[ i ] / 255.0f, gamma ) * 255.0f;
|
||||
}
|
||||
|
||||
if ( lightmapExposure == 0 ) {
|
||||
/* clamp with color normalization */
|
||||
max = sample[ 0 ];
|
||||
if ( sample[ 1 ] > max ) {
|
||||
|
@ -83,6 +85,35 @@ void ColorToBytes( const float *color, byte *colorBytes, float scale ){
|
|||
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 */
|
||||
VectorScale( sample, ( 1.0f / lightmapCompensate ), sample );
|
||||
|
@ -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 ] = ∣
|
||||
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 ] = ∣
|
||||
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,6 +2077,14 @@ void IlluminateRawLightmap( int rawLightmapNum ){
|
|||
origin = SUPER_ORIGIN( x, y );
|
||||
normal = SUPER_NORMAL( x, y );
|
||||
|
||||
////////// 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;
|
||||
|
||||
|
@ -2003,6 +2101,7 @@ void IlluminateRawLightmap( int rawLightmapNum ){
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -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 ) {
|
||||
|
@ -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" );
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,73 +468,125 @@ 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 );
|
||||
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 ) ) {
|
||||
|
@ -551,7 +604,6 @@ void InsertModel( char *name, int frame, m4x4_t transform, remap_t *remap, shade
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue