gtkradiant/tools/urt/tools/quake3/q3map2/patch.patch

1891 lines
55 KiB
Diff

Index: tools/quake3/q3map2/writebsp.c
===================================================================
--- tools/quake3/q3map2/writebsp.c (revision 158)
+++ tools/quake3/q3map2/writebsp.c (working copy)
@@ -136,7 +136,6 @@
bspLeaf_t *leaf_p;
brush_t *b;
drawSurfRef_t *dsr;
- int i = 0;
/* check limits */
Index: tools/quake3/q3map2/facebsp.c
===================================================================
--- tools/quake3/q3map2/facebsp.c (revision 158)
+++ tools/quake3/q3map2/facebsp.c (working copy)
@@ -180,7 +180,7 @@
c = 0;
- for( list; list != NULL; list = list->next )
+ for( ; list != NULL; list = list->next )
c++;
return c;
}
Index: tools/quake3/q3map2/light_ydnar.c
===================================================================
--- tools/quake3/q3map2/light_ydnar.c (revision 158)
+++ tools/quake3/q3map2/light_ydnar.c (working copy)
@@ -49,6 +49,7 @@
int i;
float max, gamma;
vec3_t sample;
+ float inv, dif;
/* ydnar: scaling necessary for simulating r_overbrightBits on external lightmaps */
@@ -72,16 +73,51 @@
/* gamma */
sample[ i ] = pow( sample[ i ] / 255.0f, gamma ) * 255.0f;
}
+
+ if (lightmapExposure == 1)
+ {
+ /* 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 );
+ }
+ else
+ {
+ if (lightmapExposure==0)
+ {
+ lightmapExposure=1.0f;
+ }
+ 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;
+ }
+ }
+
- /* 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 );
-
/* compensate for ingame overbrighting/bitshifting */
VectorScale( sample, (1.0f / lightmapCompensate), sample );
@@ -384,7 +420,7 @@
#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;
@@ -392,6 +428,12 @@
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 ] =
{
@@ -485,6 +527,51 @@
/* non axial lightmap projection (explicit xyz) */
else
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 )
@@ -516,8 +603,13 @@
else
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;
@@ -533,14 +625,14 @@
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;
/* get pvs cluster */
pointCluster = ClusterForPointExtFilter( nudged, LUXEL_EPSILON, numClusters, clusters ); //% + 0.625 );
- if( pointCluster >= 0 )
- VectorCopy( nudged, origin );
+ //if( pointCluster >= 0 )
+ // VectorCopy( nudged, origin );
luxel[ 1 ] += 1.0f;
}
}
@@ -550,8 +642,8 @@
{
VectorMA( dv->xyz, lightmapSampleOffset, dv->normal, nudged );
pointCluster = ClusterForPointExtFilter( nudged, LUXEL_EPSILON, numClusters, clusters );
- if( pointCluster >= 0 )
- VectorCopy( nudged, origin );
+ //if( pointCluster >= 0 )
+ // VectorCopy( nudged, origin );
luxel[ 1 ] += 1.0f;
}
@@ -597,7 +689,7 @@
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;
@@ -645,7 +737,7 @@
/* 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 );
@@ -653,12 +745,12 @@
/* 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 );
}
@@ -674,6 +766,7 @@
int i;
vec4_t plane;
vec3_t *stv, *ttv, stvStatic[ 3 ], ttvStatic[ 3 ];
+ vec3_t worldverts[ 3 ];
/* get plane if possible */
@@ -699,16 +792,20 @@
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;
}
@@ -730,7 +827,7 @@
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 );
}
}
@@ -792,8 +889,8 @@
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 )
@@ -878,10 +975,10 @@
}
/* 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 );
@@ -1173,7 +1270,7 @@
continue;
/* map the fake vert */
- MapSingleLuxel( lm, NULL, &fake, lm->plane, pass, NULL, NULL );
+ MapSingleLuxel( lm, NULL, &fake, lm->plane, pass, NULL, NULL, NULL );
}
}
}
@@ -1767,6 +1864,8 @@
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 */
@@ -1963,22 +2062,32 @@
deluxel = SUPER_DELUXEL( x, y );
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 )
@@ -2223,6 +2332,78 @@
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
----------------------------------------------------------------- */
@@ -3112,7 +3293,7 @@
int i, x, y, z, x1, y1, z1;
light_t *light, *light2, **owner;
bspLeaf_t *leaf;
- vec3_t origin, dir, mins, maxs, nullVector = { 0, 0, 0 };
+ vec3_t origin, dir, mins, maxs;
float radius, intensity;
light_t *buckets[ 256 ];
@@ -3587,7 +3768,320 @@
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;
+}
+
Index: tools/quake3/q3map2/light.c
===================================================================
--- tools/quake3/q3map2/light.c (revision 158)
+++ tools/quake3/q3map2/light.c (working copy)
@@ -1378,6 +1378,56 @@
break;
}
+ /////// 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 );
@@ -1420,6 +1470,9 @@
/* ambient light will be at 1/4 the value of directed light */
/* (ydnar: nuke this in favor of more dramatic lighting?) */
+ /* (PM: how about actually making it work? d=1 when it got here for single lights/sun :P */
+// d = 0.25f;
+ /* (Hobbes: always setting it to .25 is hardly any better) */
d = 0.25f * (1.0f - d);
VectorMA( gp->ambient[ j ], d, contributions[ i ].color, gp->ambient[ j ] );
}
@@ -1661,6 +1714,12 @@
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 );
@@ -1836,6 +1895,14 @@
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 ] );
@@ -2191,6 +2258,21 @@
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" ) )
@@ -2279,6 +2361,7 @@
/* ydnar: set up optimization */
SetupBrushes();
SetupDirt();
+ SetupFloodLight();
SetupSurfaceLightmaps();
/* initialize the surface facet tracing */
Index: tools/quake3/q3map2/game_etut.h
===================================================================
--- tools/quake3/q3map2/game_etut.h (revision 158)
+++ tools/quake3/q3map2/game_etut.h (working copy)
@@ -148,6 +148,7 @@
qfalse, /* wolf lighting model? */
128, /* lightmap width/height */
2.2f, /* lightmap gamma */
+ 1.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
"IBSP", /* bsp file prefix */
47, /* bsp file version */
Index: tools/quake3/q3map2/brush.c
===================================================================
--- tools/quake3/q3map2/brush.c (revision 158)
+++ tools/quake3/q3map2/brush.c (working copy)
@@ -78,7 +78,7 @@
/* count brushes */
- for( brushes; brushes != NULL; brushes = brushes->next )
+ for( ; brushes != NULL; brushes = brushes->next )
c++;
return c;
}
@@ -122,7 +122,7 @@
/* error check */
- if( *((int*) b) == 0xFEFEFEFE )
+ if( *((unsigned int*) b) == 0xFEFEFEFE )
{
Sys_FPrintf( SYS_VRB, "WARNING: Attempt to free an already freed brush!\n" );
return;
@@ -135,7 +135,7 @@
/* ydnar: overwrite it */
memset( b, 0xFE, (int) &(((brush_t*) 0)->sides[ b->numsides ]) );
- *((int*) b) = 0xFEFEFEFE;
+ *((unsigned int*) b) = 0xFEFEFEFE;
/* free it */
free( b );
@@ -156,7 +156,7 @@
/* walk brush list */
- for( brushes; brushes != NULL; brushes = next )
+ for( ; brushes != NULL; brushes = next )
{
next = brushes->next;
FreeBrush( brushes );
Index: tools/quake3/q3map2/game_jk2.h
===================================================================
--- tools/quake3/q3map2/game_jk2.h (revision 158)
+++ tools/quake3/q3map2/game_jk2.h (working copy)
@@ -64,6 +64,7 @@
qfalse, /* wolf lighting model? */
128, /* lightmap width/height */
1.0f, /* lightmap gamma */
+ 1.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
"RBSP", /* bsp file prefix */
1, /* bsp file version */
Index: tools/quake3/q3map2/lightmaps_ydnar.c
===================================================================
--- tools/quake3/q3map2/lightmaps_ydnar.c (revision 158)
+++ tools/quake3/q3map2/lightmaps_ydnar.c (working copy)
@@ -414,6 +414,12 @@
lm->superNormals = safe_malloc( size );
memset( lm->superNormals, 0, size );
+ /* allocate floodlight map storage */
+ size = lm->sw * lm->sh * SUPER_FLOODLIGHT_SIZE * sizeof( float );
+ if( lm->superFloodLight == NULL )
+ lm->superFloodLight = safe_malloc( size );
+ memset( lm->superFloodLight, 0, size );
+
/* allocate cluster map storage */
size = lm->sw * lm->sh * sizeof( int );
if( lm->superClusters == NULL )
Index: tools/quake3/q3map2/game_ja.h
===================================================================
--- tools/quake3/q3map2/game_ja.h (revision 158)
+++ tools/quake3/q3map2/game_ja.h (working copy)
@@ -67,6 +67,7 @@
qfalse, /* wolf lighting model? */
128, /* lightmap width/height */
1.0f, /* lightmap gamma */
+ 1.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
"RBSP", /* bsp file prefix */
1, /* bsp file version */
Index: tools/quake3/q3map2/game_tremulous.h
===================================================================
--- tools/quake3/q3map2/game_tremulous.h (revision 158)
+++ tools/quake3/q3map2/game_tremulous.h (working copy)
@@ -70,6 +70,7 @@
qfalse, /* wolf lighting model? */
128, /* lightmap width/height */
1.0f, /* lightmap gamma */
+ 1.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
"IBSP", /* bsp file prefix */
46, /* bsp file version */
Index: tools/quake3/q3map2/game_wolfet.h
===================================================================
--- tools/quake3/q3map2/game_wolfet.h (revision 158)
+++ tools/quake3/q3map2/game_wolfet.h (working copy)
@@ -66,6 +66,7 @@
qtrue, /* wolf lighting model? */
128, /* lightmap width/height */
1.0f, /* lightmap gamma */
+ 1.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
"IBSP", /* bsp file prefix */
47, /* bsp file version */
Index: tools/quake3/q3map2/model.c
===================================================================
--- tools/quake3/q3map2/model.c (revision 158)
+++ tools/quake3/q3map2/model.c (working copy)
@@ -266,7 +266,7 @@
continue;
/* fix the surface's normals */
- PicoFixSurfaceNormals( surface );
+ //PicoFixSurfaceNormals( surface );
/* allocate a surface (ydnar: gs mods) */
ds = AllocDrawSurface( SURFACE_TRIANGLES );
@@ -521,7 +521,15 @@
else
free( buildBrush );
}
+ else
+ {
+ Sys_Printf( "WARNING: Model %s unable to generate brush - Case 1.\n", name );
+ }
}
+ else
+ {
+ Sys_Printf( "WARNING: Model %s unable to generate brush - Case 2.\n", name );
+ }
}
}
}
Index: tools/quake3/q3map2/light_bounce.c
===================================================================
--- tools/quake3/q3map2/light_bounce.c (revision 158)
+++ tools/quake3/q3map2/light_bounce.c (working copy)
@@ -510,7 +510,7 @@
break;
case MST_TRIANGLE_SOUP:
- numTriangleDiffuseLights;
+ numTriangleDiffuseLights++;
break;
case MST_PATCH:
Index: tools/quake3/q3map2/game_wolf.h
===================================================================
--- tools/quake3/q3map2/game_wolf.h (revision 158)
+++ tools/quake3/q3map2/game_wolf.h (working copy)
@@ -129,6 +129,7 @@
qtrue, /* wolf lighting model? */
128, /* lightmap width/height */
1.0f, /* lightmap gamma */
+ 1.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
"IBSP", /* bsp file prefix */
47, /* bsp file version */
Index: tools/quake3/q3map2/game_sof2.h
===================================================================
--- tools/quake3/q3map2/game_sof2.h (revision 158)
+++ tools/quake3/q3map2/game_sof2.h (working copy)
@@ -139,6 +139,7 @@
qfalse, /* wolf lighting model? */
128, /* lightmap width/height */
1.0f, /* lightmap gamma */
+ 1.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
"RBSP", /* bsp file prefix */
1, /* bsp file version */
Index: tools/quake3/q3map2/q3map2.h
===================================================================
--- tools/quake3/q3map2/q3map2.h (revision 158)
+++ tools/quake3/q3map2/q3map2.h (working copy)
@@ -35,8 +35,8 @@
/* version */
-#define Q3MAP_VERSION "2.5.17"
-#define Q3MAP_MOTD "Last one turns the lights off"
+#define Q3MAP_VERSION "2.5.17 base - FS_20g"
+#define Q3MAP_MOTD "Sorry, it doesn't match my furniture."
@@ -267,6 +267,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))
@@ -279,6 +280,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) )
@@ -543,6 +545,7 @@
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 */
char *bspIdent; /* 4-letter bsp file prefix */
int bspVersion; /* bsp version to use */
@@ -1392,6 +1395,7 @@
float *superDeluxels; /* average light direction */
float *bspDeluxels;
+ float *superFloodLight;
}
rawLightmap_t;
@@ -1704,6 +1708,10 @@
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 );
@@ -2098,6 +2106,13 @@
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 );
@@ -2117,6 +2132,7 @@
/* ydnar: lightmap gamma/compensation */
Q_EXTERN float lightmapGamma Q_ASSIGN( 1.0f );
+Q_EXTERN float lightmapExposure Q_ASSIGN( 1.0f );
Q_EXTERN float lightmapCompensate Q_ASSIGN( 1.0f );
/* ydnar: for runtime tweaking of falloff tolerance */
Index: tools/quake3/q3map2/path_init.c
===================================================================
--- tools/quake3/q3map2/path_init.c (revision 158)
+++ tools/quake3/q3map2/path_init.c (working copy)
@@ -383,7 +383,7 @@
/* remove processed arguments */
for( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
{
- for( j; j < *argc && argv[ j ] == NULL; j++ );
+ for( ; j < *argc && argv[ j ] == NULL; j++ );
argv[ i ] = argv[ j ];
if( argv[ i ] != NULL )
k++;
Index: tools/quake3/q3map2/game_qfusion.h
===================================================================
--- tools/quake3/q3map2/game_qfusion.h (revision 158)
+++ tools/quake3/q3map2/game_qfusion.h (working copy)
@@ -115,6 +115,7 @@
qfalse, /* wolf lighting model? */
512, /* lightmap width/height */
1.0f, /* lightmap gamma */
+ 1.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
"FBSP", /* bsp file prefix */
1, /* bsp file version */
Index: tools/quake3/q3map2/game_tenebrae.h
===================================================================
--- tools/quake3/q3map2/game_tenebrae.h (revision 158)
+++ tools/quake3/q3map2/game_tenebrae.h (working copy)
@@ -112,6 +112,7 @@
qfalse, /* wolf lighting model? */
512, /* lightmap width/height */
2.0f, /* lightmap gamma */
+ 1.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
"IBSP", /* bsp file prefix */
46, /* bsp file version */
Index: tools/quake3/q3map2/q3map2.vcproj
===================================================================
--- tools/quake3/q3map2/q3map2.vcproj (revision 158)
+++ tools/quake3/q3map2/q3map2.vcproj (working copy)
@@ -180,7 +180,7 @@
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="glib-2.0.lib wsock32.lib libxml2.lib libpng.lib libmhash.lib"
- OutputFile=".\Release/q3map2.exe"
+ OutputFile=".\Release/q3map2_fs_20g.exe"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="&quot;..\..\..\..\mhash-0.9\win32\libmhash\Release&quot;;&quot;..\..\..\..\libxml2-2.6\lib&quot;;&quot;..\..\..\..\gtk2-2.10\lib&quot;"
Index: tools/quake3/q3map2/game_quake3.h
===================================================================
--- tools/quake3/q3map2/game_quake3.h (revision 158)
+++ tools/quake3/q3map2/game_quake3.h (working copy)
@@ -112,6 +112,7 @@
qfalse, /* wolf lighting model? */
128, /* lightmap width/height */
1.0f, /* lightmap gamma */
+ 1.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
"IBSP", /* bsp file prefix */
46, /* bsp file version */
Index: tools/quake3/q3map2/game_ef.h
===================================================================
--- tools/quake3/q3map2/game_ef.h (revision 158)
+++ tools/quake3/q3map2/game_ef.h (working copy)
@@ -113,6 +113,7 @@
qfalse, /* wolf lighting model? */
128, /* lightmap width/height */
1.0f, /* lightmap gamma */
+ 1.0f, /* lightmap exposure */
1.0f, /* lightmap compensate */
"IBSP", /* bsp file prefix */
46, /* bsp file version */
Index: tools/quake3/q3map2/surface.c
===================================================================
--- tools/quake3/q3map2/surface.c (revision 158)
+++ tools/quake3/q3map2/surface.c (working copy)
@@ -304,7 +304,7 @@
out = &mapDrawSurfs[ i ];
/* walk the surface list again until a proper surface is found */
- for( j; j < numMapDrawSurfs; j++ )
+ for( ; j < numMapDrawSurfs; j++ )
{
/* get in surface */
in = &mapDrawSurfs[ j ];
@@ -484,7 +484,7 @@
/* walk the list of surfaces */
- for( numSurfs; numSurfs > 0; numSurfs--, ds++ )
+ for( ; numSurfs > 0; numSurfs--, ds++ )
{
/* ignore bogus (or flare) surfaces */
if( ds->type == SURFACE_BAD || ds->numVerts <= 0 )
Index: tools/quake3/q3map2/shaders.c
===================================================================
--- tools/quake3/q3map2/shaders.c (revision 158)
+++ tools/quake3/q3map2/shaders.c (working copy)
@@ -793,8 +793,14 @@
}
if( VectorLength( si->color ) <= 0.0f )
+ {
ColorNormalize( color, si->color );
- VectorScale( color, (1.0f / count), si->averageColor );
+ VectorScale( color, (1.0f / count), si->averageColor );
+ }
+ else
+ {
+ VectorCopy( si->color, si->averageColor );
+ }
}
@@ -1896,12 +1902,14 @@
si->styleMarker = 2;
/* ydnar: default to searching for q3map_<surfaceparm> */
- else
+#if 0
+ else
{
- //% Sys_FPrintf( SYS_VRB, "Attempting to match %s with a known surfaceparm\n", token );
+ Sys_FPrintf( SYS_VRB, "Attempting to match %s with a known surfaceparm\n", token );
if( ApplySurfaceParm( &token[ 6 ], &si->contentFlags, &si->surfaceFlags, &si->compileFlags ) == qfalse )
- ;//% Sys_Printf( "WARNING: Unknown q3map_* directive \"%s\"\n", token );
+ Sys_Printf( "WARNING: Unknown q3map_* directive \"%s\"\n", token );
}
+#endif
}
Index: tools/quake3/q3map2/mesh.c
===================================================================
--- tools/quake3/q3map2/mesh.c (revision 158)
+++ tools/quake3/q3map2/mesh.c (working copy)
@@ -563,7 +563,7 @@
}
/* keep chopping */
- for( iterations; iterations > 0; iterations-- )
+ for( ; iterations > 0; iterations-- )
{
/* horizontal subdivisions */
for( j = 0; j + 2 < out.width; j += 4 )
Index: libs/picomodel/pm_ase.c
===================================================================
--- libs/picomodel/pm_ase.c (revision 158)
+++ libs/picomodel/pm_ase.c (working copy)
@@ -32,6 +32,7 @@
----------------------------------------------------------------------------- */
+void Sys_Printf (const char *format, ...);
/* marker */
#define PM_ASE_C
@@ -253,7 +254,6 @@
struct aseVertex_s
{
picoVec3_t xyz;
- picoVec3_t normal;
picoIndex_t id;
};
@@ -276,6 +276,8 @@
picoIndex_t smoothingGroup;
picoIndex_t materialId;
picoIndex_t subMaterialId;
+ picoVec3_t facenormal;
+ picoVec3_t vertexnormal[3];
};
typedef aseFace_t* aseFacesIter_t;
@@ -455,33 +457,157 @@
#endif
+static int VectorCompareExtn( picoVec3_t n1, picoVec3_t n2, float epsilon )
+{
+ int i;
+
+
+ /* test */
+ for( i= 0; i < 3; i++ )
+ if( fabs( n1[ i ] - n2[ i ]) > epsilon )
+ return -1;
+ return 1;
+}
+
+#define CrossProductTemp(a,b,c) ((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
+
static void _ase_submit_triangles( picoModel_t* model , aseMaterial_t* materials , aseVertex_t* vertices, aseTexCoord_t* texcoords, aseColor_t* colors, aseFace_t* faces, int numFaces )
{
- aseFacesIter_t i = faces, end = faces + numFaces;
- for(; i != end; ++i)
+
+ picoVec3_t accum;
+ int index;
+ int counter;
+ aseFacesIter_t i = faces, end = faces + numFaces;
+ counter=0;
+
+ //rebuild normals
+ for(i=faces; i != end; ++i)
+ {
+
+ //&(*i).facenormal
+ //vec3_t v1, v2;
+ //VectorSubtract(va, vb, v1);
+ //VectorSubtract(vc, vb, v2);
+ //CrossProduct(v1, v2, out);
+
+ picoVec3_t a,b,c;
+ picoVec3_t v1,v2,v3;
+ int j;
+ counter++;
+ for (j=0;j<3;j++)
+ {
+ a[j] = vertices[(*i).indices[0]].xyz[j];
+ b[j] = vertices[(*i).indices[1]].xyz[j];
+ c[j] = vertices[(*i).indices[2]].xyz[j];
+ }
+ for (j=0;j<3;j++)
+ {
+ v1[j]=a[j]-b[j];
+ v2[j]=c[j]-b[j];
+ }
+
+ CrossProductTemp(v1,v2,v3);
+ _pico_normalize_vec(v3);
+ (*i).facenormal[0]=v3[0];
+ (*i).facenormal[1]=v3[1];
+ (*i).facenormal[2]=v3[2];
+
+
+ }
+
+
+ //if (counter>0) Sys_Printf( "Rebuilding %d Normals\n", counter * 3 );
+ for(i=faces; i != end; ++i)
{
- /* look up the shader for the material/submaterial pair */
+ /* look up the shader for the material/submaterial pair */
aseSubMaterial_t* subMtl = _ase_get_submaterial_or_default( materials, (*i).materialId, (*i).subMaterialId );
- if( subMtl == NULL )
+
+ if( subMtl == NULL )
{
return;
}
{
picoVec3_t* xyz[3];
+ picoVec3_t *a[3];
picoVec3_t* normal[3];
picoVec2_t* st[3];
picoColor_t* color[3];
picoIndex_t smooth[3];
- int j;
- /* we pull the data from the vertex, color and texcoord arrays using the face index data */
- for ( j = 0 ; j < 3 ; j ++ )
+
+ int j,z;
+
+
+
+ /* we pull the data from the vertex, color and texcoord arrays using the face index data */
+ for ( j = 0 ; j < 3 ; j ++ )
{
- xyz[j] = &vertices[(*i).indices[j]].xyz;
- normal[j] = &vertices[(*i).indices[j]].normal;
+ aseFacesIter_t q = faces;
+ aseFacesIter_t qend = faces + numFaces;
+
+ xyz[j] = &vertices[(*i).indices[j]].xyz;
+
+ // Use Face normal
+ normal[j] = &(*i).facenormal;
+
+
+ //Oooor we can use the smoothing group
+
+ //Slow method, but testing
+ //Find All faces that use this vertex, average their facenormals.
+ // skip where smoothgroups both equal 0, or don't have any shared bits (x & y)
+ index=(*i).indices[j];
+
+// accum[0]=0;
+ // accum[1]=0;
+ // accum[2]=0;
+ accum[0]=(*i).facenormal[0];
+ accum[1]=(*i).facenormal[1];
+ accum[2]=(*i).facenormal[2];
+ counter=1;
+
+
+ z=0;
+ for(; q != qend; ++q)
+ {
+ z++;
+ if (q==i)
+ continue;
+ // if ( (*q).indices[0]==index || (*q).indices[1]==index || (*q).indices[2]==index)
+ a[0]= &vertices[(*q).indices[0] ].xyz;
+ a[1]= &vertices[(*q).indices[1] ].xyz;
+ a[2]= &vertices[(*q).indices[2] ].xyz;
+
+ if ( VectorCompareExtn(*a[0],*xyz[j],0.01f)>0 ||
+ VectorCompareExtn(*a[1],*xyz[j],0.01f)>0 ||
+ VectorCompareExtn(*a[2],*xyz[j],0.01f)>0
+ )
+ {
+ if ( (*i).smoothingGroup==0 && (*q).smoothingGroup ==0 )
+ continue;
+
+ if ( (*i).smoothingGroup & (*q).smoothingGroup )
+ {
+ accum[0]+=(*q).facenormal[0];
+ accum[1]+=(*q).facenormal[1];
+ accum[2]+=(*q).facenormal[2];
+
+ counter++;
+
+ }
+ }
+ }
+ _pico_normalize_vec(accum);
+
+ (*i).vertexnormal[j][0]=accum[0];
+ (*i).vertexnormal[j][1]=accum[1];
+ (*i).vertexnormal[j][2]=accum[2];
+ normal[j]=&(*i).vertexnormal[j];
+
+
st[j] = &texcoords[(*i).indices[j + 3]].texcoord;
-
- if( colors != NULL && (*i).indices[j + 6] >= 0 )
+
+ if( colors != NULL && (*i).indices[j + 6] >= 0 )
{
color[j] = &colors[(*i).indices[j + 6]].color;
}
@@ -490,30 +616,18 @@
color[j] = &white;
}
- smooth[j] = (vertices[(*i).indices[j]].id * (1 << 16)) + (*i).smoothingGroup; /* don't merge vertices */
+ smooth[j] = 0;// (vertices[(*i).indices[j]].id * (1 << 16)) + (*i).smoothingGroup; /* don't merge vertices */
}
/* submit the triangle to the model */
PicoAddTriangleToModel ( model , xyz , normal , 1 , st , 1 , color , subMtl->shader, smooth );
}
+
}
}
-static void shadername_convert(char* shaderName)
-{
- /* unix-style path separators */
- char* s = shaderName;
- for(; *s != '\0'; ++s)
- {
- if(*s == '\\')
- {
- *s = '/';
- }
- }
-}
-
/* _ase_load:
* loads a 3dsmax ase model file.
*/
@@ -534,6 +648,9 @@
int numColorVertices = 0;
int numColorVertexFaces = 0;
int vertexId = 0;
+ int currentVertexFace=0;
+ int currentVertexIndex=0;
+ int counter=0;
aseMaterial_t* materials = NULL;
@@ -610,10 +727,11 @@
}
else if (!_pico_stricmp(p->token,"*mesh_numvertex"))
{
- if (!_pico_parse_int( p, &numVertices) )
+ if (!_pico_parse_int( p, &numVertices) )
_ase_error_return("Missing MESH_NUMVERTEX value");
vertices = _pico_calloc(numVertices, sizeof(aseVertex_t));
+ currentVertexIndex=0;
}
else if (!_pico_stricmp(p->token,"*mesh_numfaces"))
{
@@ -621,6 +739,7 @@
_ase_error_return("Missing MESH_NUMFACES value");
faces = _pico_calloc(numFaces, sizeof(aseFace_t));
+
}
else if (!_pico_stricmp(p->token,"*mesh_numtvertex"))
{
@@ -685,7 +804,20 @@
vertices[index].id = vertexId++;
}
- /* model mesh vertex normal */
+ else if (!_pico_stricmp(p->token,"*mesh_facenormal"))
+ {
+ //Grab the faceindex for the next vertex normals.
+ if( numVertices == 0 )
+ _ase_error_return("Vertex parse error (facenormals)");
+
+ if (!_pico_parse_int( p,&currentVertexFace ))
+ _ase_error_return("Vertex parse error");
+
+ if (!_pico_parse_vec( p,faces[currentVertexFace].facenormal ))
+ _ase_error_return("Vertex parse error");
+
+ }
+ /* model mesh vertex normal */
else if (!_pico_stricmp(p->token,"*mesh_vertexnormal"))
{
int index;
@@ -696,10 +828,25 @@
/* get vertex data (orig: index +y -x +z) */
if (!_pico_parse_int( p,&index ))
_ase_error_return("Vertex parse error");
- if (!_pico_parse_vec( p,vertices[index].normal ))
+
+ //^^ Index is 'wrong' in .ase models. they reference the same vert index with multiple normals..
+ // I've tried, this is a lost cause. Use the SG's
+ //
+ /*
+
+ if (!_pico_parse_vec( p,vertices[counter].normal ))
_ase_error_return("Vertex parse error");
+ vertices[counter].faceid=index;
+ counter++;
+ */
}
/* model mesh face */
+ else if (!_pico_stricmp(p->token,"*mesh_normals"))
+ {
+ // counter=0; //part of the above vertex normals fix
+ }
+
+ /* model mesh face */
else if (!_pico_stricmp(p->token,"*mesh_face"))
{
picoIndex_t indexes[3];
@@ -736,8 +883,35 @@
}
if (!_pico_stricmp (p->token,"*MESH_SMOOTHING" ))
{
- _pico_parse_int ( p , &faces[index].smoothingGroup );
- }
+ int total=0;
+ char* point;
+ char* start;
+ _pico_parse(p,0);
+
+ point=p->token;
+ start=point;
+ faces[index].smoothingGroup=0;
+
+ //Super dodgy comma delimited string parse
+ while (*point<'A')
+ {
+ if (*point<=32 || *point==',')
+ {
+ total=atoi(start);
+ if (total!=0)
+ {
+ faces[index].smoothingGroup+=1<<total;
+ }
+ start=point+1;
+ }
+
+ point++;
+ }
+
+
+
+
+ }
if (!_pico_stricmp (p->token,"*MESH_MTLID" ))
{
_pico_parse_int ( p , &faces[index].subMaterialId );
@@ -755,19 +929,19 @@
int index;
if( numVertices == 0 )
- _ase_error_return("Texture Vertex parse error");
+ _ase_error_return("Vertex parse error");
/* get uv vertex index */
- if (!_pico_parse_int( p,&index ) || index >= numTextureVertices)
- _ase_error_return("Texture vertex parse error");
+ if (!_pico_parse_int( p,&index ))
+ _ase_error_return("UV vertex parse error");
/* get uv vertex s */
if (!_pico_parse_float( p,&texcoords[index].texcoord[0] ))
- _ase_error_return("Texture vertex parse error");
+ _ase_error_return("UV vertex parse error");
/* get uv vertex t */
if (!_pico_parse_float( p,&texcoords[index].texcoord[1] ))
- _ase_error_return("Texture vertex parse error");
+ _ase_error_return("UV vertex parse error");
/* ydnar: invert t */
texcoords[index].texcoord[ 1 ] = 1.0f - texcoords[index].texcoord[ 1 ];
@@ -831,6 +1005,13 @@
/* leave alpha alone since we don't get any data from the ASE format */
colors[index].color[3] = 255;
+
+ /* 27 hack, red as alpha */
+ colors[index].color[3]=colors[index].color[0];
+ colors[index].color[0]=255;
+ colors[index].color[1]=255;
+ colors[index].color[2]=255;
+
}
/* model color face */
else if (!_pico_stricmp(p->token,"*mesh_cface"))
@@ -900,7 +1081,6 @@
{
/* set material name */
_pico_first_token( materialName );
- shadername_convert(materialName);
PicoSetShaderName( shader, materialName);
/* set shader's transparency */
@@ -1085,7 +1265,6 @@
}
/* set material name */
- shadername_convert(materialName);
PicoSetShaderName( shader,materialName );
/* set shader's transparency */
@@ -1115,8 +1294,18 @@
char* p = mapname;
/* convert to shader-name format */
- shadername_convert(mapname);
{
+ /* unix-style path separators */
+ char* s = mapname;
+ for(; *s != '\0'; ++s)
+ {
+ if(*s == '\\')
+ {
+ *s = '/';
+ }
+ }
+ }
+ {
/* remove extension */
char* last_period = strrchr(p, '.');
if(last_period != NULL)
@@ -1125,14 +1314,32 @@
}
}
- /* find shader path */
+ /* find game root */
for(; *p != '\0'; ++p)
{
- if(_pico_strnicmp(p, "models/", 7) == 0 || _pico_strnicmp(p, "textures/", 9) == 0)
+ if(_pico_strnicmp(p, "quake", 5) == 0 || _pico_strnicmp(p, "doom", 4) == 0)
{
break;
}
}
+ /* root-relative */
+ for(; *p != '\0'; ++p)
+ {
+ if(*p == '/')
+ {
+ ++p;
+ break;
+ }
+ }
+ /* game-relative */
+ for(; *p != '\0'; ++p)
+ {
+ if(*p == '/')
+ {
+ ++p;
+ break;
+ }
+ }
if(*p != '\0')
{
Index: libs/picomodel/picomodel.c
===================================================================
--- libs/picomodel/picomodel.c (revision 158)
+++ libs/picomodel/picomodel.c (working copy)
@@ -295,10 +295,7 @@
model = PicoModuleLoadModel(module, fileName, buffer, bufSize, frameNum);
}
- if(model != 0)
- {
- _pico_free(buffer);
- }
+ _pico_free(buffer);
/* return */
return model;
@@ -1573,6 +1570,7 @@
{
int i, j;
+// Sys_Printf(" %f %f %f\n", normal[0] , normal[1] , normal[2] );
/* dummy check */
if( surface == NULL || surface->numVertexes <= 0 )
@@ -1861,13 +1859,10 @@
typedef picoVec3_t* picoNormalIter_t;
typedef picoIndex_t* picoIndexIter_t;
-#define THE_CROSSPRODUCTS_OF_ANY_PAIR_OF_EDGES_OF_A_GIVEN_TRIANGLE_ARE_EQUAL 1
-
void _pico_triangles_generate_weighted_normals(picoIndexIter_t first, picoIndexIter_t end, picoVec3_t* xyz, picoVec3_t* normals)
{
for(; first != end; first += 3)
{
-#if (THE_CROSSPRODUCTS_OF_ANY_PAIR_OF_EDGES_OF_A_GIVEN_TRIANGLE_ARE_EQUAL)
picoVec3_t weightedNormal;
{
float* a = xyz[*(first + 0)];
@@ -1878,24 +1873,11 @@
_pico_subtract_vec( c, a, ca );
_pico_cross_vec( ca, ba, weightedNormal );
}
-#endif
{
int j = 0;
for(; j < 3; ++j)
{
float* normal = normals[*(first + j)];
-#if (!THE_CROSSPRODUCTS_OF_ANY_PAIR_OF_EDGES_OF_A_GIVEN_TRIANGLE_ARE_EQUAL)
- picoVec3_t weightedNormal;
- {
- float* a = xyz[*(first + ((j + 0) % 3))];
- float* b = xyz[*(first + ((j + 1) % 3))];
- float* c = xyz[*(first + ((j + 2) % 3))];
- picoVec3_t ba, ca;
- _pico_subtract_vec( b, a, ba );
- _pico_subtract_vec( c, a, ca );
- _pico_cross_vec( ca, ba, weightedNormal );
- }
-#endif
_pico_add_vec(weightedNormal, normal, normal);
}
}
@@ -1941,7 +1923,8 @@
{
for(; first != last; ++first, ++generated)
{
- if(!_pico_normal_is_unit_length(*first) || !_pico_normal_within_tolerance(*first, *generated))
+ //27 - fix for badly generated normals thing.
+ // if(!_pico_normal_is_unit_length(*first) || !_pico_normal_within_tolerance(*first, *generated))
{
_pico_copy_vec(*generated, *first);
}
@@ -1954,10 +1937,11 @@
_pico_normals_zero(normals, normals + surface->numVertexes);
+ //Just build standard no sg normals for now
_pico_triangles_generate_weighted_normals(surface->index, surface->index + surface->numIndexes, surface->xyz, normals);
_pico_vertices_combine_shared_normals(surface->xyz, surface->smoothingGroup, normals, surface->numVertexes);
- _pico_normals_normalize(normals, normals + surface->numVertexes);
+ _pico_normals_normalize(normals, normals + surface->numVertexes);
_pico_normals_assign_generated_normals(surface->normal, surface->normal + surface->numVertexes, normals);
@@ -2261,7 +2245,7 @@
int newVertIndex = PicoGetSurfaceNumIndexes ( workSurface );
/* get the index of the vertex that we're going to store at newVertIndex */
- vertDataIndex = PicoFindSurfaceVertexNum ( workSurface , *xyz[i] , *normals[i] , numSTs , st[i] , numColors , colors[i], smoothingGroup[i]);
+ vertDataIndex = -1;// PicoFindSurfaceVertexNum ( workSurface , *xyz[i] , *normals[i] , numSTs , st[i] , numColors , colors[i], smoothingGroup[i]);
/* the vertex wasn't found, so create a new vertex in the pool from the data we have */
if ( vertDataIndex == -1 )
@@ -2290,3 +2274,5 @@
PicoSetSurfaceIndex ( workSurface , newVertIndex , vertDataIndex );
}
}
+
+