X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fnetradiant.git;a=blobdiff_plain;f=tools%2Fquake3%2Fq3map2%2Fsurface.c;h=c8c6e4f433fe2d067615dea3bac49fba8963c341;hp=5415ae105d8f89e65f935b386bb5bc3fd8780626;hb=81ab1fe02f887ccf43e1755ed44811ff4fd693c3;hpb=107765f0e4b543dfc346851ee5b4605cc17eb1c6 diff --git a/tools/quake3/q3map2/surface.c b/tools/quake3/q3map2/surface.c index 5415ae10..c8c6e4f4 100644 --- a/tools/quake3/q3map2/surface.c +++ b/tools/quake3/q3map2/surface.c @@ -1,30 +1,30 @@ /* ------------------------------------------------------------------------------- -Copyright (C) 1999-2007 id Software, Inc. and contributors. -For a list of contributors, see the accompanying CONTRIBUTORS file. + Copyright (C) 1999-2007 id Software, Inc. and contributors. + For a list of contributors, see the accompanying CONTRIBUTORS file. -This file is part of GtkRadiant. + This file is part of GtkRadiant. -GtkRadiant is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + GtkRadiant is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -GtkRadiant is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + GtkRadiant is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with GtkRadiant; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + You should have received a copy of the GNU General Public License + along with GtkRadiant; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ----------------------------------------------------------------------------------- + ---------------------------------------------------------------------------------- -This code has been altered significantly from its original form, to support -several games based on the Quake III Arena engine, in the form of "Q3Map2." + This code has been altered significantly from its original form, to support + several games based on the Quake III Arena engine, in the form of "Q3Map2." -------------------------------------------------------------------------------- */ + ------------------------------------------------------------------------------- */ @@ -39,67 +39,70 @@ several games based on the Quake III Arena engine, in the form of "Q3Map2." /* -AllocDrawSurface() -ydnar: gs mods: changed to force an explicit type when allocating -*/ - -mapDrawSurface_t *AllocDrawSurface( surfaceType_t type ) -{ - mapDrawSurface_t *ds; - - + AllocDrawSurface() + ydnar: gs mods: changed to force an explicit type when allocating + */ + +mapDrawSurface_t *AllocDrawSurface( surfaceType_t type ){ + mapDrawSurface_t *ds; + + /* ydnar: gs mods: only allocate valid types */ - if( type <= SURFACE_BAD || type >= NUM_SURFACE_TYPES ) + if ( type <= SURFACE_BAD || type >= NUM_SURFACE_TYPES ) { Error( "AllocDrawSurface: Invalid surface type %d specified", type ); - + } + /* bounds check */ - if( numMapDrawSurfs >= MAX_MAP_DRAW_SURFS ) + if ( numMapDrawSurfs >= MAX_MAP_DRAW_SURFS ) { Error( "MAX_MAP_DRAW_SURFS (%d) exceeded", MAX_MAP_DRAW_SURFS ); + } ds = &mapDrawSurfs[ numMapDrawSurfs ]; numMapDrawSurfs++; - + /* ydnar: do initial surface setup */ memset( ds, 0, sizeof( mapDrawSurface_t ) ); ds->type = type; ds->planeNum = -1; - ds->fogNum = defaultFogNum; /* ydnar 2003-02-12 */ - ds->outputNum = -1; /* ydnar 2002-08-13 */ - ds->surfaceNum = numMapDrawSurfs - 1; /* ydnar 2003-02-16 */ - + ds->fogNum = defaultFogNum; /* ydnar 2003-02-12 */ + ds->outputNum = -1; /* ydnar 2002-08-13 */ + ds->surfaceNum = numMapDrawSurfs - 1; /* ydnar 2003-02-16 */ + return ds; } /* -FinishSurface() -ydnar: general surface finish pass -*/ - -void FinishSurface( mapDrawSurface_t *ds ) -{ - mapDrawSurface_t *ds2; - - + FinishSurface() + ydnar: general surface finish pass + */ + +void FinishSurface( mapDrawSurface_t *ds ){ + mapDrawSurface_t *ds2; + + /* dummy check */ - if( ds->type <= SURFACE_BAD || ds->type >= NUM_SURFACE_TYPES || ds == NULL || ds->shaderInfo == NULL ) + if ( ds->type <= SURFACE_BAD || ds->type >= NUM_SURFACE_TYPES || ds == NULL || ds->shaderInfo == NULL ) { return; - + } + /* ydnar: rocking tek-fu celshading */ - if( ds->celShader != NULL ) + if ( ds->celShader != NULL ) { MakeCelSurface( ds, ds->celShader ); - + } + /* backsides stop here */ - if( ds->backSide ) + if ( ds->backSide ) { return; - + } + /* ydnar: rocking surface cloning (fur baby yeah!) */ - if( ds->shaderInfo->cloneShader != NULL && ds->shaderInfo->cloneShader[ 0 ] != '\0' ) + if ( ds->shaderInfo->cloneShader != NULL && ds->shaderInfo->cloneShader[ 0 ] != '\0' ) { CloneSurface( ds, ShaderInfoForShader( ds->shaderInfo->cloneShader ) ); - + } + /* ydnar: q3map_backShader support */ - if( ds->shaderInfo->backShader != NULL && ds->shaderInfo->backShader[ 0 ] != '\0' ) - { + if ( ds->shaderInfo->backShader != NULL && ds->shaderInfo->backShader[ 0 ] != '\0' ) { ds2 = CloneSurface( ds, ShaderInfoForShader( ds->shaderInfo->backShader ) ); ds2->backSide = qtrue; } @@ -108,46 +111,47 @@ void FinishSurface( mapDrawSurface_t *ds ) /* -CloneSurface() -clones a map drawsurface, using the specified shader -*/ - -mapDrawSurface_t *CloneSurface( mapDrawSurface_t *src, shaderInfo_t *si ) -{ - mapDrawSurface_t *ds; - - + CloneSurface() + clones a map drawsurface, using the specified shader + */ + +mapDrawSurface_t *CloneSurface( mapDrawSurface_t *src, shaderInfo_t *si ){ + mapDrawSurface_t *ds; + + /* dummy check */ - if( src == NULL || si == NULL ) + if ( src == NULL || si == NULL ) { return NULL; - + } + /* allocate a new surface */ ds = AllocDrawSurface( src->type ); - if( ds == NULL ) + if ( ds == NULL ) { return NULL; - + } + /* copy it */ memcpy( ds, src, sizeof( *ds ) ); - + /* destroy side reference */ ds->sideRef = NULL; - + /* set shader */ ds->shaderInfo = si; - + /* copy verts */ - if( ds->numVerts > 0 ) - { + if ( ds->numVerts > 0 ) { ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) ); memcpy( ds->verts, src->verts, ds->numVerts * sizeof( *ds->verts ) ); } - + /* copy indexes */ - if( ds->numIndexes <= 0 ) + if ( ds->numIndexes <= 0 ) { return ds; + } ds->indexes = safe_malloc( ds->numIndexes * sizeof( *ds->indexes ) ); memcpy( ds->indexes, src->indexes, ds->numIndexes * sizeof( *ds->indexes ) ); - + /* return the surface */ return ds; } @@ -155,33 +159,36 @@ mapDrawSurface_t *CloneSurface( mapDrawSurface_t *src, shaderInfo_t *si ) /* -MakeCelSurface() - ydnar -makes a copy of a surface, but specific to cel shading -*/ - -mapDrawSurface_t *MakeCelSurface( mapDrawSurface_t *src, shaderInfo_t *si ) -{ - mapDrawSurface_t *ds; - - + MakeCelSurface() - ydnar + makes a copy of a surface, but specific to cel shading + */ + +mapDrawSurface_t *MakeCelSurface( mapDrawSurface_t *src, shaderInfo_t *si ){ + mapDrawSurface_t *ds; + + /* dummy check */ - if( src == NULL || si == NULL ) + if ( src == NULL || si == NULL ) { return NULL; - + } + /* don't create cel surfaces for certain types of shaders */ - if( (src->shaderInfo->compileFlags & C_TRANSLUCENT) || - (src->shaderInfo->compileFlags & C_SKY) ) + if ( ( src->shaderInfo->compileFlags & C_TRANSLUCENT ) || + ( src->shaderInfo->compileFlags & C_SKY ) ) { return NULL; - + } + /* make a copy */ ds = CloneSurface( src, si ); - if( ds == NULL ) + if ( ds == NULL ) { return NULL; - + } + /* do some fixups for celshading */ ds->planar = qfalse; ds->planeNum = -1; - + ds->celShader = NULL; /* don't cel shade cels :P */ + /* return the surface */ return ds; } @@ -189,41 +196,42 @@ mapDrawSurface_t *MakeCelSurface( mapDrawSurface_t *src, shaderInfo_t *si ) /* -MakeSkyboxSurface() - ydnar -generates a skybox surface, viewable from everywhere there is sky -*/ - -mapDrawSurface_t *MakeSkyboxSurface( mapDrawSurface_t *src ) -{ - int i; - mapDrawSurface_t *ds; - - + MakeSkyboxSurface() - ydnar + generates a skybox surface, viewable from everywhere there is sky + */ + +mapDrawSurface_t *MakeSkyboxSurface( mapDrawSurface_t *src ){ + int i; + mapDrawSurface_t *ds; + + /* dummy check */ - if( src == NULL ) + if ( src == NULL ) { return NULL; - + } + /* make a copy */ ds = CloneSurface( src, src->shaderInfo ); - if( ds == NULL ) + if ( ds == NULL ) { return NULL; - + } + /* set parent */ ds->parent = src; - + /* scale the surface vertexes */ - for( i = 0; i < ds->numVerts; i++ ) + for ( i = 0; i < ds->numVerts; i++ ) { m4x4_transform_point( skyboxTransform, ds->verts[ i ].xyz ); - + /* debug code */ //% bspDrawVerts[ bspDrawSurfaces[ ds->outputNum ].firstVert + i ].color[ 0 ][ 1 ] = 0; //% bspDrawVerts[ bspDrawSurfaces[ ds->outputNum ].firstVert + i ].color[ 0 ][ 2 ] = 0; } - + /* so backface culling creep doesn't bork the surface */ VectorClear( ds->lightmapVecs[ 2 ] ); - + /* return the surface */ return ds; } @@ -231,28 +239,28 @@ mapDrawSurface_t *MakeSkyboxSurface( mapDrawSurface_t *src ) /* -IsTriangleDegenerate -returns qtrue if all three points are colinear, backwards, or the triangle is just plain bogus -*/ - -#define TINY_AREA 1.0f - -qboolean IsTriangleDegenerate( bspDrawVert_t *points, int a, int b, int c ) -{ - vec3_t v1, v2, v3; - float d; - - + IsTriangleDegenerate + returns qtrue if all three points are colinear, backwards, or the triangle is just plain bogus + */ + +#define TINY_AREA 1.0f + +qboolean IsTriangleDegenerate( bspDrawVert_t *points, int a, int b, int c ){ + vec3_t v1, v2, v3; + float d; + + /* calcuate the area of the triangle */ VectorSubtract( points[ b ].xyz, points[ a ].xyz, v1 ); VectorSubtract( points[ c ].xyz, points[ a ].xyz, v2 ); CrossProduct( v1, v2, v3 ); d = VectorLength( v3 ); - + /* assume all very small or backwards triangles will cause problems */ - if( d < TINY_AREA ) + if ( d < TINY_AREA ) { return qtrue; - + } + /* must be a good triangle */ return qfalse; } @@ -260,22 +268,23 @@ qboolean IsTriangleDegenerate( bspDrawVert_t *points, int a, int b, int c ) /* -ClearSurface() - ydnar -clears a surface and frees any allocated memory -*/ + ClearSurface() - ydnar + clears a surface and frees any allocated memory + */ -void ClearSurface( mapDrawSurface_t *ds ) -{ +void ClearSurface( mapDrawSurface_t *ds ){ ds->type = SURFACE_BAD; ds->planar = qfalse; ds->planeNum = -1; ds->numVerts = 0; - if( ds->verts != NULL ) + if ( ds->verts != NULL ) { free( ds->verts ); + } ds->verts = NULL; ds->numIndexes = 0; - if( ds->indexes != NULL ) + if ( ds->indexes != NULL ) { free( ds->indexes ); + } ds->indexes = NULL; numClearedSurfaces++; } @@ -283,50 +292,51 @@ void ClearSurface( mapDrawSurface_t *ds ) /* -TidyEntitySurfaces() - ydnar -deletes all empty or bad surfaces from the surface list -*/ - -void TidyEntitySurfaces( entity_t *e ) -{ - int i, j, deleted; - mapDrawSurface_t *out, *in; - - + TidyEntitySurfaces() - ydnar + deletes all empty or bad surfaces from the surface list + */ + +void TidyEntitySurfaces( entity_t *e ){ + int i, j, deleted; + mapDrawSurface_t *out, *in = NULL; + + /* note it */ Sys_FPrintf( SYS_VRB, "--- TidyEntitySurfaces ---\n" ); - + /* walk the surface list */ deleted = 0; - for( i = e->firstDrawSurf, j = e->firstDrawSurf; j < numMapDrawSurfs; i++, j++ ) + for ( i = e->firstDrawSurf, j = e->firstDrawSurf; j < numMapDrawSurfs; i++, j++ ) { /* get out surface */ out = &mapDrawSurfs[ i ]; - + /* walk the surface list again until a proper surface is found */ - for( ; j < numMapDrawSurfs; j++ ) + for ( ; j < numMapDrawSurfs; j++ ) { /* get in surface */ in = &mapDrawSurfs[ j ]; - + /* this surface ok? */ - if( in->type == SURFACE_FLARE || in->type == SURFACE_SHADER || - (in->type != SURFACE_BAD && in->numVerts > 0) ) + if ( in->type == SURFACE_FLARE || in->type == SURFACE_SHADER || + ( in->type != SURFACE_BAD && in->numVerts > 0 ) ) { break; - + } + /* nuke it */ ClearSurface( in ); deleted++; } - + /* copy if necessary */ - if( i != j ) + if ( i != j ) { memcpy( out, in, sizeof( mapDrawSurface_t ) ); + } } - + /* set the new number of drawsurfs */ numMapDrawSurfs = i; - + /* emit some stats */ Sys_FPrintf( SYS_VRB, "%9d empty or malformed surfaces deleted\n", deleted ); } @@ -334,40 +344,42 @@ void TidyEntitySurfaces( entity_t *e ) /* -CalcSurfaceTextureRange() - ydnar -calculates the clamped texture range for a given surface, returns qtrue if it's within [-texRange,texRange] -*/ - -qboolean CalcSurfaceTextureRange( mapDrawSurface_t *ds ) -{ - int i, j, v, size[ 2 ]; - float mins[ 2 ], maxs[ 2 ]; - - + CalcSurfaceTextureRange() - ydnar + calculates the clamped texture range for a given surface, returns qtrue if it's within [-texRange,texRange] + */ + +qboolean CalcSurfaceTextureRange( mapDrawSurface_t *ds ){ + int i, j, v, size[ 2 ]; + float mins[ 2 ], maxs[ 2 ]; + + /* try to early out */ - if( ds->numVerts <= 0 ) + if ( ds->numVerts <= 0 ) { return qtrue; - + } + /* walk the verts and determine min/max st values */ mins[ 0 ] = 999999; mins[ 1 ] = 999999; maxs[ 0 ] = -999999; maxs[ 1 ] = -999999; - for( i = 0; i < ds->numVerts; i++ ) + for ( i = 0; i < ds->numVerts; i++ ) { - for( j = 0; j < 2; j++ ) + for ( j = 0; j < 2; j++ ) { - if( ds->verts[ i ].st[ j ] < mins[ j ] ) + if ( ds->verts[ i ].st[ j ] < mins[ j ] ) { mins[ j ] = ds->verts[ i ].st[ j ]; - if( ds->verts[ i ].st[ j ] > maxs[ j ] ) + } + if ( ds->verts[ i ].st[ j ] > maxs[ j ] ) { maxs[ j ] = ds->verts[ i ].st[ j ]; + } } } - + /* clamp to integer range and calculate surface bias values */ - for( j = 0; j < 2; j++ ) - ds->bias[ j ] = -floor( 0.5f * (mins[ j ] + maxs[ j ]) ); - + for ( j = 0; j < 2; j++ ) + ds->bias[ j ] = -floor( 0.5f * ( mins[ j ] + maxs[ j ] ) ); + /* find biased texture coordinate mins/maxs */ size[ 0 ] = ds->shaderInfo->shaderWidth; size[ 1 ] = ds->shaderInfo->shaderHeight; @@ -375,33 +387,37 @@ qboolean CalcSurfaceTextureRange( mapDrawSurface_t *ds ) ds->texMins[ 1 ] = 999999; ds->texMaxs[ 0 ] = -999999; ds->texMaxs[ 1 ] = -999999; - for( i = 0; i < ds->numVerts; i++ ) + for ( i = 0; i < ds->numVerts; i++ ) { - for( j = 0; j < 2; j++ ) + for ( j = 0; j < 2; j++ ) { - v = ((float) ds->verts[ i ].st[ j ] + ds->bias[ j ]) * size[ j ]; - if( v < ds->texMins[ j ] ) + v = ( (float) ds->verts[ i ].st[ j ] + ds->bias[ j ] ) * size[ j ]; + if ( v < ds->texMins[ j ] ) { ds->texMins[ j ] = v; - if( v > ds->texMaxs[ j ] ) + } + if ( v > ds->texMaxs[ j ] ) { ds->texMaxs[ j ] = v; + } } } - + /* calc ranges */ - for( j = 0; j < 2; j++ ) - ds->texRange[ j ] = (ds->texMaxs[ j ] - ds->texMins[ j ]); - + for ( j = 0; j < 2; j++ ) + ds->texRange[ j ] = ( ds->texMaxs[ j ] - ds->texMins[ j ] ); + /* if range is zero, then assume unlimited precision */ - if( texRange == 0 ) + if ( texRange == 0 ) { return qtrue; - + } + /* within range? */ - for( j = 0; j < 2; j++ ) + for ( j = 0; j < 2; j++ ) { - if( ds->texMins[ j ] < -texRange || ds->texMaxs[ j ] > texRange ) + if ( ds->texMins[ j ] < -texRange || ds->texMaxs[ j ] > texRange ) { return qfalse; + } } - + /* within range */ return qtrue; } @@ -409,50 +425,52 @@ qboolean CalcSurfaceTextureRange( mapDrawSurface_t *ds ) /* -CalcLightmapAxis() - ydnar -gives closed lightmap axis for a plane normal -*/ - -qboolean CalcLightmapAxis( vec3_t normal, vec3_t axis ) -{ - vec3_t absolute; - - + CalcLightmapAxis() - ydnar + gives closed lightmap axis for a plane normal + */ + +qboolean CalcLightmapAxis( vec3_t normal, vec3_t axis ){ + vec3_t absolute; + + /* test */ - if( normal[ 0 ] == 0.0f && normal[ 1 ] == 0.0f && normal[ 2 ] == 0.0f ) - { + if ( normal[ 0 ] == 0.0f && normal[ 1 ] == 0.0f && normal[ 2 ] == 0.0f ) { VectorClear( axis ); return qfalse; } - + /* get absolute normal */ absolute[ 0 ] = fabs( normal[ 0 ] ); absolute[ 1 ] = fabs( normal[ 1 ] ); absolute[ 2 ] = fabs( normal[ 2 ] ); - + /* test and set */ - if( absolute[ 2 ] > absolute[ 0 ] - 0.0001f && absolute[ 2 ] > absolute[ 1 ] - 0.0001f ) - { - if( normal[ 2 ] > 0.0f ) + if ( absolute[ 2 ] > absolute[ 0 ] - 0.0001f && absolute[ 2 ] > absolute[ 1 ] - 0.0001f ) { + if ( normal[ 2 ] > 0.0f ) { VectorSet( axis, 0.0f, 0.0f, 1.0f ); - else + } + else{ VectorSet( axis, 0.0f, 0.0f, -1.0f ); + } } - else if( absolute[ 0 ] > absolute[ 1 ] - 0.0001f && absolute[ 0 ] > absolute[ 2 ] - 0.0001f ) - { - if( normal[ 0 ] > 0.0f ) + else if ( absolute[ 0 ] > absolute[ 1 ] - 0.0001f && absolute[ 0 ] > absolute[ 2 ] - 0.0001f ) { + if ( normal[ 0 ] > 0.0f ) { VectorSet( axis, 1.0f, 0.0f, 0.0f ); - else + } + else{ VectorSet( axis, -1.0f, 0.0f, 0.0f ); + } } else { - if( normal[ 1 ] > 0.0f ) + if ( normal[ 1 ] > 0.0f ) { VectorSet( axis, 0.0f, 1.0f, 0.0f ); - else + } + else{ VectorSet( axis, 0.0f, -1.0f, 0.0f ); + } } - + /* return ok */ return qtrue; } @@ -460,84 +478,81 @@ qboolean CalcLightmapAxis( vec3_t normal, vec3_t axis ) /* -ClassifySurfaces() - ydnar -fills out a bunch of info in the surfaces, including planar status, lightmap projection, and bounding box -*/ - -#define PLANAR_EPSILON 0.5f //% 0.126f 0.25f - -void ClassifySurfaces( int numSurfs, mapDrawSurface_t *ds ) -{ - int i, bestAxis; - float dist; - vec4_t plane; - shaderInfo_t *si; - static vec3_t axii[ 6 ] = - { - { 0, 0, -1 }, - { 0, 0, 1 }, - { -1, 0, 0 }, - { 1, 0, 0 }, - { 0, -1, 0 }, - { 0, 1, 0 } - }; - - + ClassifySurfaces() - ydnar + fills out a bunch of info in the surfaces, including planar status, lightmap projection, and bounding box + */ + +#define PLANAR_EPSILON 0.5f //% 0.126f 0.25f + +void ClassifySurfaces( int numSurfs, mapDrawSurface_t *ds ){ + int i, bestAxis; + float dist; + vec4_t plane; + shaderInfo_t *si; + static vec3_t axii[ 6 ] = + { + { 0, 0, -1 }, + { 0, 0, 1 }, + { -1, 0, 0 }, + { 1, 0, 0 }, + { 0, -1, 0 }, + { 0, 1, 0 } + }; + + /* walk the list of surfaces */ - for( ; numSurfs > 0; numSurfs--, ds++ ) + for ( ; numSurfs > 0; numSurfs--, ds++ ) { /* ignore bogus (or flare) surfaces */ - if( ds->type == SURFACE_BAD || ds->numVerts <= 0 ) + if ( ds->type == SURFACE_BAD || ds->numVerts <= 0 ) { continue; - + } + /* get shader */ si = ds->shaderInfo; - + /* ----------------------------------------------------------------- force meta if vertex count is too high or shader requires it ----------------------------------------------------------------- */ - - if( ds->type != SURFACE_PATCH && ds->type != SURFACE_FACE ) - { - if( ds->numVerts > SHADER_MAX_VERTEXES ) + + if ( ds->type != SURFACE_PATCH && ds->type != SURFACE_FACE ) { + if ( ds->numVerts > SHADER_MAX_VERTEXES ) { ds->type = SURFACE_FORCED_META; + } } - + /* ----------------------------------------------------------------- - plane and bounding box classification + plane and bounding box classification ----------------------------------------------------------------- */ - + /* set surface bounding box */ ClearBounds( ds->mins, ds->maxs ); - for( i = 0; i < ds->numVerts; i++ ) + for ( i = 0; i < ds->numVerts; i++ ) AddPointToBounds( ds->verts[ i ].xyz, ds->mins, ds->maxs ); - + /* try to get an existing plane */ - if( ds->planeNum >= 0 ) - { + if ( ds->planeNum >= 0 ) { VectorCopy( mapplanes[ ds->planeNum ].normal, plane ); plane[ 3 ] = mapplanes[ ds->planeNum ].dist; } - + /* construct one from the first vert with a valid normal */ else { VectorClear( plane ); plane[ 3 ] = 0.0f; - for( i = 0; i < ds->numVerts; i++ ) + for ( i = 0; i < ds->numVerts; i++ ) { - if( ds->verts[ i ].normal[ 0 ] != 0.0f && ds->verts[ i ].normal[ 1 ] != 0.0f && ds->verts[ i ].normal[ 2 ] != 0.0f ) - { + if ( ds->verts[ i ].normal[ 0 ] != 0.0f && ds->verts[ i ].normal[ 1 ] != 0.0f && ds->verts[ i ].normal[ 2 ] != 0.0f ) { VectorCopy( ds->verts[ i ].normal, plane ); plane[ 3 ] = DotProduct( ds->verts[ i ].xyz, plane ); break; } } } - + /* test for bogus plane */ - if( VectorLength( plane ) <= 0.0f ) - { + if ( VectorLength( plane ) <= 0.0f ) { ds->planar = qfalse; ds->planeNum = -1; } @@ -545,17 +560,16 @@ void ClassifySurfaces( int numSurfs, mapDrawSurface_t *ds ) { /* determine if surface is planar */ ds->planar = qtrue; - + /* test each vert */ - for( i = 0; i < ds->numVerts; i++ ) + for ( i = 0; i < ds->numVerts; i++ ) { /* point-plane test */ dist = DotProduct( ds->verts[ i ].xyz, plane ) - plane[ 3 ]; - if( fabs( dist ) > PLANAR_EPSILON ) - { + if ( fabs( dist ) > PLANAR_EPSILON ) { //% if( ds->planeNum >= 0 ) //% { - //% Sys_Printf( "WARNING: Planar surface marked unplanar (%f > %f)\n", fabs( dist ), PLANAR_EPSILON ); + //% Sys_FPrintf( SYS_WRN, "WARNING: Planar surface marked unplanar (%f > %f)\n", fabs( dist ), PLANAR_EPSILON ); //% ds->verts[ i ].color[ 0 ][ 0 ] = ds->verts[ i ].color[ 0 ][ 2 ] = 0; //% } ds->planar = qfalse; @@ -563,12 +577,12 @@ void ClassifySurfaces( int numSurfs, mapDrawSurface_t *ds ) } } } - + /* find map plane if necessary */ - if( ds->planar ) - { - if( ds->planeNum < 0 ) + if ( ds->planar ) { + if ( ds->planeNum < 0 ) { ds->planeNum = FindFloatPlane( plane, plane[ 3 ], 1, &ds->verts[ 0 ].xyz ); + } VectorCopy( plane, ds->lightmapVecs[ 2 ] ); } else @@ -576,72 +590,86 @@ void ClassifySurfaces( int numSurfs, mapDrawSurface_t *ds ) ds->planeNum = -1; VectorClear( ds->lightmapVecs[ 2 ] ); //% if( ds->type == SURF_META || ds->type == SURF_FACE ) - //% Sys_Printf( "WARNING: Non-planar face (%d): %s\n", ds->planeNum, ds->shaderInfo->shader ); + //% Sys_FPrintf( SYS_WRN, "WARNING: Non-planar face (%d): %s\n", ds->planeNum, ds->shaderInfo->shader ); } - + /* ----------------------------------------------------------------- lightmap bounds and axis projection ----------------------------------------------------------------- */ - + /* vertex lit surfaces don't need this information */ - if( si->compileFlags & C_VERTEXLIT || ds->type == SURFACE_TRIANGLES ) - { + if ( si->compileFlags & C_VERTEXLIT || ds->type == SURFACE_TRIANGLES ) { VectorClear( ds->lightmapAxis ); //% VectorClear( ds->lightmapVecs[ 2 ] ); ds->sampleSize = 0; continue; } - + /* the shader can specify an explicit lightmap axis */ - if( si->lightmapAxis[ 0 ] || si->lightmapAxis[ 1 ] || si->lightmapAxis[ 2 ] ) + if ( si->lightmapAxis[ 0 ] || si->lightmapAxis[ 1 ] || si->lightmapAxis[ 2 ] ) { VectorCopy( si->lightmapAxis, ds->lightmapAxis ); - else if( ds->type == SURFACE_FORCED_META ) + } + else if ( ds->type == SURFACE_FORCED_META ) { VectorClear( ds->lightmapAxis ); - else if( ds->planar ) + } + else if ( ds->planar ) { CalcLightmapAxis( plane, ds->lightmapAxis ); + } else { /* find best lightmap axis */ - for( bestAxis = 0; bestAxis < 6; bestAxis++ ) + for ( bestAxis = 0; bestAxis < 6; bestAxis++ ) { - for( i = 0; i < ds->numVerts && bestAxis < 6; i++ ) + for ( i = 0; i < ds->numVerts && bestAxis < 6; i++ ) { //% Sys_Printf( "Comparing %1.3f %1.3f %1.3f to %1.3f %1.3f %1.3f\n", - //% ds->verts[ i ].normal[ 0 ], ds->verts[ i ].normal[ 1 ], ds->verts[ i ].normal[ 2 ], - //% axii[ bestAxis ][ 0 ], axii[ bestAxis ][ 1 ], axii[ bestAxis ][ 2 ] ); - if( DotProduct( ds->verts[ i ].normal, axii[ bestAxis ] ) < 0.25f ) /* fixme: adjust this tolerance to taste */ + //% ds->verts[ i ].normal[ 0 ], ds->verts[ i ].normal[ 1 ], ds->verts[ i ].normal[ 2 ], + //% axii[ bestAxis ][ 0 ], axii[ bestAxis ][ 1 ], axii[ bestAxis ][ 2 ] ); + if ( DotProduct( ds->verts[ i ].normal, axii[ bestAxis ] ) < 0.25f ) { /* fixme: adjust this tolerance to taste */ break; + } } - - if( i == ds->numVerts ) + + if ( i == ds->numVerts ) { break; + } } - + /* set axis if possible */ - if( bestAxis < 6 ) - { + if ( bestAxis < 6 ) { //% if( ds->type == SURFACE_PATCH ) - //% Sys_Printf( "Mapped axis %d onto patch\n", bestAxis ); + //% Sys_Printf( "Mapped axis %d onto patch\n", bestAxis ); VectorCopy( axii[ bestAxis ], ds->lightmapAxis ); } - + /* debug code */ //% if( ds->type == SURFACE_PATCH ) - //% Sys_Printf( "Failed to map axis %d onto patch\n", bestAxis ); + //% Sys_Printf( "Failed to map axis %d onto patch\n", bestAxis ); } - - /* get lightmap sample size */ - if( ds->sampleSize <= 0 ) - { - ds->sampleSize = sampleSize; - if( ds->shaderInfo->lightmapSampleSize ) - ds->sampleSize = ds->shaderInfo->lightmapSampleSize; - if( ds->lightmapScale > 0 ) - ds->sampleSize *= ds->lightmapScale; - if( ds->sampleSize <= 0 ) - ds->sampleSize = 1; - else if( ds->sampleSize > 16384 ) /* powers of 2 are preferred */ - ds->sampleSize = 16384; + + /* calculate lightmap sample size */ + if ( ds->shaderInfo->lightmapSampleSize > 0 ) { /* shader value overrides every other */ + ds->sampleSize = ds->shaderInfo->lightmapSampleSize; + } + else if ( ds->sampleSize <= 0 ) { /* may contain the entity asigned value */ + ds->sampleSize = sampleSize; /* otherwise use global default */ + + } + if ( ds->lightmapScale > 0.0f ) { /* apply surface lightmap scaling factor */ + ds->sampleSize = ds->lightmapScale * (float)ds->sampleSize; + ds->lightmapScale = 0; /* applied */ + } + + if ( ds->sampleSize < minSampleSize ) { + ds->sampleSize = minSampleSize; + } + + if ( ds->sampleSize < 1 ) { + ds->sampleSize = 1; + } + + if ( ds->sampleSize > 16384 ) { /* powers of 2 are preferred */ + ds->sampleSize = 16384; } } } @@ -649,25 +677,24 @@ void ClassifySurfaces( int numSurfs, mapDrawSurface_t *ds ) /* -ClassifyEntitySurfaces() - ydnar -classifies all surfaces in an entity -*/ - -void ClassifyEntitySurfaces( entity_t *e ) -{ - int i; - - + ClassifyEntitySurfaces() - ydnar + classifies all surfaces in an entity + */ + +void ClassifyEntitySurfaces( entity_t *e ){ + int i; + + /* note it */ Sys_FPrintf( SYS_VRB, "--- ClassifyEntitySurfaces ---\n" ); - + /* walk the surface list */ - for( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ ) + for ( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ ) { FinishSurface( &mapDrawSurfs[ i ] ); ClassifySurfaces( 1, &mapDrawSurfs[ i ] ); } - + /* tidy things up */ TidyEntitySurfaces( e ); } @@ -675,72 +702,80 @@ void ClassifyEntitySurfaces( entity_t *e ) /* -GetShaderIndexForPoint() - ydnar -for shader-indexed surfaces (terrain), find a matching index from the indexmap -*/ - -byte GetShaderIndexForPoint( indexMap_t *im, vec3_t eMins, vec3_t eMaxs, vec3_t point ) -{ - int i, x, y; - float s, t; - vec3_t mins, maxs, size; - - + GetShaderIndexForPoint() - ydnar + for shader-indexed surfaces (terrain), find a matching index from the indexmap + */ + +byte GetShaderIndexForPoint( indexMap_t *im, vec3_t eMins, vec3_t eMaxs, vec3_t point ){ + int i, x, y; + float s, t; + vec3_t mins, maxs, size; + + /* early out if no indexmap */ - if( im == NULL ) + if ( im == NULL ) { return 0; - + } + /* this code is really broken */ #if 0 - /* legacy precision fudges for terrain */ - for( i = 0; i < 3; i++ ) - { - mins[ i ] = floor( eMins[ i ] + 0.1 ); - maxs[ i ] = floor( eMaxs[ i ] + 0.1 ); - size[ i ] = maxs[ i ] - mins[ i ]; - } - - /* find st (fixme: support more than just z-axis projection) */ - s = floor( point[ 0 ] + 0.1f - mins[ 0 ] ) / size[ 0 ]; - t = floor( maxs[ 1 ] - point[ 1 ] + 0.1f ) / size[ 1 ]; - if( s < 0.0f ) - s = 0.0f; - else if( s > 1.0f ) - s = 1.0f; - if( t < 0.0f ) - t = 0.0f; - else if( t > 1.0f ) - t = 1.0f; - - /* make xy */ - x = (im->w - 1) * s; - y = (im->h - 1) * t; + /* legacy precision fudges for terrain */ + for ( i = 0; i < 3; i++ ) + { + mins[ i ] = floor( eMins[ i ] + 0.1 ); + maxs[ i ] = floor( eMaxs[ i ] + 0.1 ); + size[ i ] = maxs[ i ] - mins[ i ]; + } + + /* find st (fixme: support more than just z-axis projection) */ + s = floor( point[ 0 ] + 0.1f - mins[ 0 ] ) / size[ 0 ]; + t = floor( maxs[ 1 ] - point[ 1 ] + 0.1f ) / size[ 1 ]; + if ( s < 0.0f ) { + s = 0.0f; + } + else if ( s > 1.0f ) { + s = 1.0f; + } + if ( t < 0.0f ) { + t = 0.0f; + } + else if ( t > 1.0f ) { + t = 1.0f; + } + + /* make xy */ + x = ( im->w - 1 ) * s; + y = ( im->h - 1 ) * t; #else - /* get size */ - for( i = 0; i < 3; i++ ) - { - mins[ i ] = eMins[ i ]; - maxs[ i ] = eMaxs[ i ]; - size[ i ] = maxs[ i ] - mins[ i ]; - } - - /* calc st */ - s = (point[ 0 ] - mins[ 0 ]) / size[ 0 ]; - t = (maxs[ 1 ] - point[ 1 ]) / size[ 1 ]; - - /* calc xy */ - x = s * im->w; - y = t * im->h; - if( x < 0 ) - x = 0; - else if( x > (im->w - 1) ) - x = (im->w - 1); - if( y < 0 ) - y = 0; - else if( y > (im->h - 1) ) - y = (im->h - 1); + /* get size */ + for ( i = 0; i < 3; i++ ) + { + mins[ i ] = eMins[ i ]; + maxs[ i ] = eMaxs[ i ]; + size[ i ] = maxs[ i ] - mins[ i ]; + } + + /* calc st */ + s = ( point[ 0 ] - mins[ 0 ] ) / size[ 0 ]; + t = ( maxs[ 1 ] - point[ 1 ] ) / size[ 1 ]; + + /* calc xy */ + x = s * im->w; + y = t * im->h; + if ( x < 0 ) { + x = 0; + } + else if ( x > ( im->w - 1 ) ) { + x = ( im->w - 1 ); + } + if ( y < 0 ) { + y = 0; + } + else if ( y > ( im->h - 1 ) ) { + y = ( im->h - 1 ); + } #endif - + /* return index */ return im->pixels[ y * im->w + x ]; } @@ -748,75 +783,83 @@ byte GetShaderIndexForPoint( indexMap_t *im, vec3_t eMins, vec3_t eMaxs, vec3_t /* -GetIndexedShader() - ydnar -for a given set of indexes and an indexmap, get a shader and set the vertex alpha in-place -this combines a couple different functions from terrain.c -*/ - -shaderInfo_t *GetIndexedShader( shaderInfo_t *parent, indexMap_t *im, int numPoints, byte *shaderIndexes ) -{ - int i; - byte minShaderIndex, maxShaderIndex; - char shader[ MAX_QPATH ]; - shaderInfo_t *si; - - + GetIndexedShader() - ydnar + for a given set of indexes and an indexmap, get a shader and set the vertex alpha in-place + this combines a couple different functions from terrain.c + */ + +shaderInfo_t *GetIndexedShader( shaderInfo_t *parent, indexMap_t *im, int numPoints, byte *shaderIndexes ){ + int i; + byte minShaderIndex, maxShaderIndex; + char shader[ MAX_QPATH ]; + shaderInfo_t *si; + + /* early out if bad data */ - if( im == NULL || numPoints <= 0 || shaderIndexes == NULL ) + if ( im == NULL || numPoints <= 0 || shaderIndexes == NULL ) { return ShaderInfoForShader( "default" ); - + } + /* determine min/max index */ minShaderIndex = 255; maxShaderIndex = 0; - for( i = 0; i < numPoints; i++ ) + for ( i = 0; i < numPoints; i++ ) { - if( shaderIndexes[ i ] < minShaderIndex ) + if ( shaderIndexes[ i ] < minShaderIndex ) { minShaderIndex = shaderIndexes[ i ]; - if( shaderIndexes[ i ] > maxShaderIndex ) + } + if ( shaderIndexes[ i ] > maxShaderIndex ) { maxShaderIndex = shaderIndexes[ i ]; + } } - + /* set alpha inline */ - for( i = 0; i < numPoints; i++ ) + for ( i = 0; i < numPoints; i++ ) { /* straight rip from terrain.c */ - if( shaderIndexes[ i ] < maxShaderIndex ) + if ( shaderIndexes[ i ] < maxShaderIndex ) { shaderIndexes[ i ] = 0; - else + } + else{ shaderIndexes[ i ] = 255; + } } - + /* make a shader name */ - if( minShaderIndex == maxShaderIndex ) + if ( minShaderIndex == maxShaderIndex ) { sprintf( shader, "textures/%s_%d", im->shader, maxShaderIndex ); - else + } + else{ sprintf( shader, "textures/%s_%dto%d", im->shader, minShaderIndex, maxShaderIndex ); - + } + /* get the shader */ si = ShaderInfoForShader( shader ); - + /* inherit a few things from parent shader */ - if( parent->globalTexture ) + if ( parent->globalTexture ) { si->globalTexture = qtrue; - if( parent->forceMeta ) + } + if ( parent->forceMeta ) { si->forceMeta = qtrue; - if( parent->nonplanar ) + } + if ( parent->nonplanar ) { si->nonplanar = qtrue; - if( si->shadeAngleDegrees == 0.0 ) + } + if ( si->shadeAngleDegrees == 0.0 ) { si->shadeAngleDegrees = parent->shadeAngleDegrees; - if( parent->tcGen && si->tcGen == qfalse ) - { + } + if ( parent->tcGen && si->tcGen == qfalse ) { /* set xy texture projection */ si->tcGen = qtrue; VectorCopy( parent->vecs[ 0 ], si->vecs[ 0 ] ); VectorCopy( parent->vecs[ 1 ], si->vecs[ 1 ] ); } - if( VectorLength( parent->lightmapAxis ) > 0.0f && VectorLength( si->lightmapAxis ) <= 0.0f ) - { + if ( VectorLength( parent->lightmapAxis ) > 0.0f && VectorLength( si->lightmapAxis ) <= 0.0f ) { /* set lightmap projection axis */ VectorCopy( parent->lightmapAxis, si->lightmapAxis ); } - + /* return the shader */ return si; } @@ -825,63 +868,63 @@ shaderInfo_t *GetIndexedShader( shaderInfo_t *parent, indexMap_t *im, int numPoi /* -DrawSurfaceForSide() -creates a SURF_FACE drawsurface from a given brush side and winding -*/ - -#define SNAP_FLOAT_TO_INT 8 -#define SNAP_INT_TO_FLOAT (1.0 / SNAP_FLOAT_TO_INT) - -mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, winding_t *w ) -{ - int i, j, k; - mapDrawSurface_t *ds; - shaderInfo_t *si, *parent; - bspDrawVert_t *dv; - vec3_t texX, texY; - vec_t x, y; - vec3_t vTranslated; - qboolean indexed; - byte shaderIndexes[ 256 ]; - float offsets[ 256 ]; - char tempShader[ MAX_QPATH ]; - - + DrawSurfaceForSide() + creates a SURF_FACE drawsurface from a given brush side and winding + */ + +#define SNAP_FLOAT_TO_INT 8 +#define SNAP_INT_TO_FLOAT ( 1.0 / SNAP_FLOAT_TO_INT ) + +mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, winding_t *w ){ + int i, j, k; + mapDrawSurface_t *ds; + shaderInfo_t *si, *parent; + bspDrawVert_t *dv; + vec3_t texX, texY; + vec_t x, y; + vec3_t vTranslated; + qboolean indexed; + byte shaderIndexes[ 256 ]; + float offsets[ 256 ]; + char tempShader[ MAX_QPATH ]; + + /* ydnar: don't make a drawsurf for culled sides */ - if( s->culled ) + if ( s->culled ) { return NULL; - + } + /* range check */ - if( w->numpoints > MAX_POINTS_ON_WINDING ) + if ( w->numpoints > MAX_POINTS_ON_WINDING ) { Error( "DrawSurfaceForSide: w->numpoints = %d (> %d)", w->numpoints, MAX_POINTS_ON_WINDING ); - + } + /* get shader */ si = s->shaderInfo; - + /* ydnar: gs mods: check for indexed shader */ - if( si->indexed && b->im != NULL ) - { + if ( si->indexed && b->im != NULL ) { /* indexed */ indexed = qtrue; - + /* get shader indexes for each point */ - for( i = 0; i < w->numpoints; i++ ) + for ( i = 0; i < w->numpoints; i++ ) { shaderIndexes[ i ] = GetShaderIndexForPoint( b->im, b->eMins, b->eMaxs, w->p[ i ] ); offsets[ i ] = b->im->offsets[ shaderIndexes[ i ] ]; //% Sys_Printf( "%f ", offsets[ i ] ); } - + /* get matching shader and set alpha */ parent = si; si = GetIndexedShader( parent, b->im, w->numpoints, shaderIndexes ); } - else + else{ indexed = qfalse; - + } + /* ydnar: sky hack/fix for GL_CLAMP borders on ati cards */ - if( skyFixHack && si->skyParmsImageBase[ 0 ] != '\0' ) - { + if ( skyFixHack && si->skyParmsImageBase[ 0 ] != '\0' ) { //% Sys_FPrintf( SYS_VRB, "Enabling sky hack for shader %s using env %s\n", si->shader, si->skyParmsImageBase ); sprintf( tempShader, "%s_lf", si->skyParmsImageBase ); DrawSurfaceForShader( tempShader ); @@ -896,69 +939,68 @@ mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, windin sprintf( tempShader, "%s_dn", si->skyParmsImageBase ); DrawSurfaceForShader( tempShader ); } - + /* ydnar: gs mods */ ds = AllocDrawSurface( SURFACE_FACE ); ds->entityNum = b->entityNum; ds->castShadows = b->castShadows; ds->recvShadows = b->recvShadows; - + ds->planar = qtrue; ds->planeNum = s->planenum; VectorCopy( mapplanes[ s->planenum ].normal, ds->lightmapVecs[ 2 ] ); - + ds->shaderInfo = si; ds->mapBrush = b; ds->sideRef = AllocSideRef( s, NULL ); ds->fogNum = -1; + ds->sampleSize = b->lightmapSampleSize; ds->lightmapScale = b->lightmapScale; ds->numVerts = w->numpoints; ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) ); memset( ds->verts, 0, ds->numVerts * sizeof( *ds->verts ) ); - + /* compute s/t coordinates from brush primitive texture matrix (compute axis base) */ ComputeAxisBase( mapplanes[ s->planenum ].normal, texX, texY ); - + /* create the vertexes */ - for( j = 0; j < w->numpoints; j++ ) + for ( j = 0; j < w->numpoints; j++ ) { /* get the drawvert */ dv = ds->verts + j; - + /* copy xyz and do potential z offset */ VectorCopy( w->p[ j ], dv->xyz ); - if( indexed ) + if ( indexed ) { dv->xyz[ 2 ] += offsets[ j ]; - + } + /* round the xyz to a given precision and translate by origin */ - for( i = 0 ; i < 3 ; i++ ) + for ( i = 0 ; i < 3 ; i++ ) dv->xyz[ i ] = SNAP_INT_TO_FLOAT * floor( dv->xyz[ i ] * SNAP_FLOAT_TO_INT + 0.5f ); VectorAdd( dv->xyz, e->origin, vTranslated ); - + /* ydnar: tek-fu celshading support for flat shaded shit */ - if( flat ) - { + if ( flat ) { dv->st[ 0 ] = si->stFlat[ 0 ]; dv->st[ 1 ] = si->stFlat[ 1 ]; } - + /* ydnar: gs mods: added support for explicit shader texcoord generation */ - else if( si->tcGen ) - { + else if ( si->tcGen ) { dv->st[ 0 ] = DotProduct( si->vecs[ 0 ], vTranslated ); dv->st[ 1 ] = DotProduct( si->vecs[ 1 ], vTranslated ); } - + /* old quake-style texturing */ - else if( g_bBrushPrimit == BPRIMIT_OLDBRUSHES ) - { + else if ( g_bBrushPrimit == BPRIMIT_OLDBRUSHES ) { /* nearest-axial projection */ dv->st[ 0 ] = s->vecs[ 0 ][ 3 ] + DotProduct( s->vecs[ 0 ], vTranslated ); dv->st[ 1 ] = s->vecs[ 1 ][ 3 ] + DotProduct( s->vecs[ 1 ], vTranslated ); dv->st[ 0 ] /= si->shaderWidth; dv->st[ 1 ] /= si->shaderHeight; } - + /* brush primitive texturing */ else { @@ -968,25 +1010,30 @@ mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, windin dv->st[ 0 ] = s->texMat[ 0 ][ 0 ] * x + s->texMat[ 0 ][ 1 ] * y + s->texMat[ 0 ][ 2 ]; dv->st[ 1 ] = s->texMat[ 1 ][ 0 ] * x + s->texMat[ 1 ][ 1 ] * y + s->texMat[ 1 ][ 2 ]; } - + /* copy normal */ VectorCopy( mapplanes[ s->planenum ].normal, dv->normal ); - + /* ydnar: set color */ - for( k = 0; k < MAX_LIGHTMAPS; k++ ) + for ( k = 0; k < MAX_LIGHTMAPS; k++ ) { dv->color[ k ][ 0 ] = 255; dv->color[ k ][ 1 ] = 255; dv->color[ k ][ 2 ] = 255; - + /* ydnar: gs mods: handle indexed shader blending */ - dv->color[ k ][ 3 ] = (indexed ? shaderIndexes[ j ] : 255); + dv->color[ k ][ 3 ] = ( indexed ? shaderIndexes[ j ] : 255 ); } } - + /* set cel shader */ ds->celShader = b->celShader; - + + /* set shade angle */ + if ( b->shadeAngleDegrees > 0.0f ) { + ds->shadeAngleDegrees = b->shadeAngleDegrees; + } + /* ydnar: gs mods: moved st biasing elsewhere */ return ds; } @@ -994,194 +1041,198 @@ mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, windin /* -DrawSurfaceForMesh() -moved here from patch.c -*/ + DrawSurfaceForMesh() + moved here from patch.c + */ #define YDNAR_NORMAL_EPSILON 0.50f -qboolean VectorCompareExt( vec3_t n1, vec3_t n2, float epsilon ) -{ - int i; - - +qboolean VectorCompareExt( vec3_t n1, vec3_t n2, float epsilon ){ + int i; + + /* test */ - for( i= 0; i < 3; i++ ) - if( fabs( n1[ i ] - n2[ i ]) > epsilon ) + for ( i = 0; i < 3; i++ ) + if ( fabs( n1[ i ] - n2[ i ] ) > epsilon ) { return qfalse; + } return qtrue; } -mapDrawSurface_t *DrawSurfaceForMesh( entity_t *e, parseMesh_t *p, mesh_t *mesh ) -{ - int i, k, numVerts; - vec4_t plane; - qboolean planar; - float dist; - mapDrawSurface_t *ds; - shaderInfo_t *si, *parent; - bspDrawVert_t *dv; - vec3_t vTranslated; - mesh_t *copy; - qboolean indexed; - byte shaderIndexes[ MAX_EXPANDED_AXIS * MAX_EXPANDED_AXIS ]; - float offsets[ MAX_EXPANDED_AXIS * MAX_EXPANDED_AXIS ]; - - +mapDrawSurface_t *DrawSurfaceForMesh( entity_t *e, parseMesh_t *p, mesh_t *mesh ){ + int i, k, numVerts; + vec4_t plane; + qboolean planar; + float dist; + mapDrawSurface_t *ds; + shaderInfo_t *si, *parent; + bspDrawVert_t *dv; + vec3_t vTranslated; + mesh_t *copy; + qboolean indexed; + byte shaderIndexes[ MAX_EXPANDED_AXIS * MAX_EXPANDED_AXIS ]; + float offsets[ MAX_EXPANDED_AXIS * MAX_EXPANDED_AXIS ]; + + /* get mesh and shader shader */ - if( mesh == NULL ) + if ( mesh == NULL ) { mesh = &p->mesh; + } si = p->shaderInfo; - if( mesh == NULL || si == NULL ) + if ( mesh == NULL || si == NULL ) { return NULL; - - /* get vertex count */ + } + + /* get vertex count */ numVerts = mesh->width * mesh->height; - + /* to make valid normals for patches with degenerate edges, we need to make a copy of the mesh and put the aproximating points onto the curve */ - + /* create a copy of the mesh */ copy = CopyMesh( mesh ); - + /* store off the original (potentially bad) normals */ MakeMeshNormals( *copy ); - for( i = 0; i < numVerts; i++ ) + for ( i = 0; i < numVerts; i++ ) VectorCopy( copy->verts[ i ].normal, mesh->verts[ i ].normal ); - + /* put the mesh on the curve */ PutMeshOnCurve( *copy ); /* find new normals (to take into account degenerate/flipped edges */ MakeMeshNormals( *copy ); - for( i = 0; i < numVerts; i++ ) + for ( i = 0; i < numVerts; i++ ) { /* ydnar: only copy normals that are significantly different from the originals */ - if( DotProduct( copy->verts[ i ].normal, mesh->verts[ i ].normal ) < 0.75f ) + if ( DotProduct( copy->verts[ i ].normal, mesh->verts[ i ].normal ) < 0.75f ) { VectorCopy( copy->verts[ i ].normal, mesh->verts[ i ].normal ); + } } - + /* free the old mesh */ FreeMesh( copy ); - + /* ydnar: gs mods: check for indexed shader */ - if( si->indexed && p->im != NULL ) - { + if ( si->indexed && p->im != NULL ) { /* indexed */ indexed = qtrue; /* get shader indexes for each point */ - for( i = 0; i < numVerts; i++ ) + for ( i = 0; i < numVerts; i++ ) { shaderIndexes[ i ] = GetShaderIndexForPoint( p->im, p->eMins, p->eMaxs, mesh->verts[ i ].xyz ); offsets[ i ] = p->im->offsets[ shaderIndexes[ i ] ]; } - + /* get matching shader and set alpha */ parent = si; si = GetIndexedShader( parent, p->im, numVerts, shaderIndexes ); } - else + else{ indexed = qfalse; - - + } + + /* ydnar: gs mods */ ds = AllocDrawSurface( SURFACE_PATCH ); ds->entityNum = p->entityNum; ds->castShadows = p->castShadows; ds->recvShadows = p->recvShadows; - + ds->shaderInfo = si; ds->mapMesh = p; - ds->lightmapScale = p->lightmapScale; /* ydnar */ + ds->sampleSize = p->lightmapSampleSize; + ds->lightmapScale = p->lightmapScale; /* ydnar */ ds->patchWidth = mesh->width; ds->patchHeight = mesh->height; ds->numVerts = ds->patchWidth * ds->patchHeight; ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) ); memcpy( ds->verts, mesh->verts, ds->numVerts * sizeof( *ds->verts ) ); - + ds->fogNum = -1; ds->planeNum = -1; - + ds->longestCurve = p->longestCurve; ds->maxIterations = p->maxIterations; - + /* construct a plane from the first vert */ VectorCopy( mesh->verts[ 0 ].normal, plane ); plane[ 3 ] = DotProduct( mesh->verts[ 0 ].xyz, plane ); planar = qtrue; - + /* spew forth errors */ - if( VectorLength( plane ) < 0.001f ) - Sys_Printf( "BOGUS " ); - + if ( VectorLength( plane ) < 0.001f ) { + Sys_Printf( "DrawSurfaceForMesh: bogus plane\n" ); + } + /* test each vert */ - for( i = 1; i < ds->numVerts && planar; i++ ) + for ( i = 1; i < ds->numVerts && planar; i++ ) { /* normal test */ - if( VectorCompare( plane, mesh->verts[ i ].normal ) == qfalse ) + if ( VectorCompare( plane, mesh->verts[ i ].normal ) == qfalse ) { planar = qfalse; - + } + /* point-plane test */ dist = DotProduct( mesh->verts[ i ].xyz, plane ) - plane[ 3 ]; - if( fabs( dist ) > EQUAL_EPSILON ) + if ( fabs( dist ) > EQUAL_EPSILON ) { planar = qfalse; + } } - + /* add a map plane */ - if( planar ) - { + if ( planar ) { /* make a map plane */ ds->planeNum = FindFloatPlane( plane, plane[ 3 ], 1, &mesh->verts[ 0 ].xyz ); VectorCopy( plane, ds->lightmapVecs[ 2 ] ); - + /* push this normal to all verts (ydnar 2003-02-14: bad idea, small patches get screwed up) */ - for( i = 0; i < ds->numVerts; i++ ) + for ( i = 0; i < ds->numVerts; i++ ) VectorCopy( plane, ds->verts[ i ].normal ); } - + /* walk the verts to do special stuff */ - for( i = 0; i < ds->numVerts; i++ ) + for ( i = 0; i < ds->numVerts; i++ ) { /* get the drawvert */ dv = &ds->verts[ i ]; - + /* ydnar: tek-fu celshading support for flat shaded shit */ - if( flat ) - { + if ( flat ) { dv->st[ 0 ] = si->stFlat[ 0 ]; dv->st[ 1 ] = si->stFlat[ 1 ]; } - + /* ydnar: gs mods: added support for explicit shader texcoord generation */ - else if( si->tcGen ) - { + else if ( si->tcGen ) { /* translate by origin and project the texture */ VectorAdd( dv->xyz, e->origin, vTranslated ); dv->st[ 0 ] = DotProduct( si->vecs[ 0 ], vTranslated ); dv->st[ 1 ] = DotProduct( si->vecs[ 1 ], vTranslated ); } - + /* ydnar: set color */ - for( k = 0; k < MAX_LIGHTMAPS; k++ ) + for ( k = 0; k < MAX_LIGHTMAPS; k++ ) { dv->color[ k ][ 0 ] = 255; dv->color[ k ][ 1 ] = 255; dv->color[ k ][ 2 ] = 255; - + /* ydnar: gs mods: handle indexed shader blending */ - dv->color[ k ][ 3 ] = (indexed ? shaderIndexes[ i ] : 255); + dv->color[ k ][ 3 ] = ( indexed ? shaderIndexes[ i ] : 255 ); } - + /* ydnar: offset */ - if( indexed ) + if ( indexed ) { dv->xyz[ 2 ] += offsets[ i ]; + } } - + /* set cel shader */ ds->celShader = p->celShader; - + /* return the drawsurface */ return ds; } @@ -1189,42 +1240,48 @@ mapDrawSurface_t *DrawSurfaceForMesh( entity_t *e, parseMesh_t *p, mesh_t *mesh /* -DrawSurfaceForFlare() - ydnar -creates a flare draw surface -*/ - -mapDrawSurface_t *DrawSurfaceForFlare( int entNum, vec3_t origin, vec3_t normal, vec3_t color, char *flareShader, int lightStyle ) -{ - mapDrawSurface_t *ds; - - + DrawSurfaceForFlare() - ydnar + creates a flare draw surface + */ + +mapDrawSurface_t *DrawSurfaceForFlare( int entNum, vec3_t origin, vec3_t normal, vec3_t color, const char *flareShader, int lightStyle ){ + mapDrawSurface_t *ds; + + /* emit flares? */ - if( emitFlares == qfalse ) + if ( emitFlares == qfalse ) { return NULL; - + } + /* allocate drawsurface */ ds = AllocDrawSurface( SURFACE_FLARE ); ds->entityNum = entNum; - + /* set it up */ - if( flareShader != NULL && flareShader[ 0 ] != '\0' ) + if ( flareShader != NULL && flareShader[ 0 ] != '\0' ) { ds->shaderInfo = ShaderInfoForShader( flareShader ); - else + } + else{ ds->shaderInfo = ShaderInfoForShader( game->flareShader ); - if( origin != NULL ) + } + if ( origin != NULL ) { VectorCopy( origin, ds->lightmapOrigin ); - if( normal != NULL ) + } + if ( normal != NULL ) { VectorCopy( normal, ds->lightmapVecs[ 2 ] ); - if( color != NULL ) + } + if ( color != NULL ) { VectorCopy( color, ds->lightmapVecs[ 0 ] ); - + } + /* store light style */ ds->lightStyle = lightStyle; - if( ds->lightStyle < 0 || ds->lightStyle >= LS_NONE ) + if ( ds->lightStyle < 0 || ds->lightStyle >= LS_NONE ) { ds->lightStyle = LS_NORMAL; - + } + /* fixme: fog */ - + /* return to sender */ return ds; } @@ -1232,36 +1289,36 @@ mapDrawSurface_t *DrawSurfaceForFlare( int entNum, vec3_t origin, vec3_t normal, /* -DrawSurfaceForShader() - ydnar -creates a bogus surface to forcing the game to load a shader -*/ - -mapDrawSurface_t *DrawSurfaceForShader( char *shader ) -{ - int i; - shaderInfo_t *si; - mapDrawSurface_t *ds; - - + DrawSurfaceForShader() - ydnar + creates a bogus surface to forcing the game to load a shader + */ + +mapDrawSurface_t *DrawSurfaceForShader( char *shader ){ + int i; + shaderInfo_t *si; + mapDrawSurface_t *ds; + + /* get shader */ si = ShaderInfoForShader( shader ); /* find existing surface */ - for( i = 0; i < numMapDrawSurfs; i++ ) + for ( i = 0; i < numMapDrawSurfs; i++ ) { /* get surface */ ds = &mapDrawSurfs[ i ]; - + /* check it */ - if( ds->shaderInfo == si ) + if ( ds->shaderInfo == si ) { return ds; + } } - + /* create a new surface */ ds = AllocDrawSurface( SURFACE_SHADER ); ds->entityNum = 0; ds->shaderInfo = ShaderInfoForShader( shader ); - + /* return to sender */ return ds; } @@ -1269,27 +1326,27 @@ mapDrawSurface_t *DrawSurfaceForShader( char *shader ) /* -AddSurfaceFlare() - ydnar -creates flares (coronas) centered on surfaces -*/ - -static void AddSurfaceFlare( mapDrawSurface_t *ds, vec3_t entityOrigin ) -{ - vec3_t origin; - int i; - - + AddSurfaceFlare() - ydnar + creates flares (coronas) centered on surfaces + */ + +static void AddSurfaceFlare( mapDrawSurface_t *ds, vec3_t entityOrigin ){ + vec3_t origin; + int i; + + /* find centroid */ VectorClear( origin ); for ( i = 0; i < ds->numVerts; i++ ) VectorAdd( origin, ds->verts[ i ].xyz, origin ); - VectorScale( origin, (1.0f / ds->numVerts), origin ); - if( entityOrigin != NULL ) + VectorScale( origin, ( 1.0f / ds->numVerts ), origin ); + if ( entityOrigin != NULL ) { VectorAdd( origin, entityOrigin, origin ); - + } + /* push origin off surface a bit */ VectorMA( origin, 2.0f, ds->lightmapVecs[ 2 ], origin ); - + /* create the drawsurface */ DrawSurfaceForFlare( ds->entityNum, origin, ds->lightmapVecs[ 2 ], ds->shaderInfo->color, ds->shaderInfo->flareShader, ds->shaderInfo->lightStyle ); } @@ -1297,58 +1354,60 @@ static void AddSurfaceFlare( mapDrawSurface_t *ds, vec3_t entityOrigin ) /* -SubdivideFace() -subdivides a face surface until it is smaller than the specified size (subdivisions) -*/ - -static void SubdivideFace_r( entity_t *e, brush_t *brush, side_t *side, winding_t *w, int fogNum, float subdivisions ) -{ - int i; - int axis; - vec3_t bounds[ 2 ]; - const float epsilon = 0.1; - int subFloor, subCeil; - winding_t *frontWinding, *backWinding; - mapDrawSurface_t *ds; - - + SubdivideFace() + subdivides a face surface until it is smaller than the specified size (subdivisions) + */ + +static void SubdivideFace_r( entity_t *e, brush_t *brush, side_t *side, winding_t *w, int fogNum, float subdivisions ){ + int i; + int axis; + vec3_t bounds[ 2 ]; + const float epsilon = 0.1; + int subFloor, subCeil; + winding_t *frontWinding, *backWinding; + mapDrawSurface_t *ds; + + /* dummy check */ - if( w == NULL ) + if ( w == NULL ) { return; - if( w->numpoints < 3 ) + } + if ( w->numpoints < 3 ) { Error( "SubdivideFace_r: Bad w->numpoints (%d < 3)", w->numpoints ); - + } + /* determine surface bounds */ ClearBounds( bounds[ 0 ], bounds[ 1 ] ); - for( i = 0; i < w->numpoints; i++ ) + for ( i = 0; i < w->numpoints; i++ ) AddPointToBounds( w->p[ i ], bounds[ 0 ], bounds[ 1 ] ); - + /* split the face */ - for( axis = 0; axis < 3; axis++ ) + for ( axis = 0; axis < 3; axis++ ) { - vec3_t planePoint = { 0, 0, 0 }; - vec3_t planeNormal = { 0, 0, 0 }; - float d; - - + vec3_t planePoint = { 0, 0, 0 }; + vec3_t planeNormal = { 0, 0, 0 }; + float d; + + /* create an axial clipping plane */ - subFloor = floor( bounds[ 0 ][ axis ] / subdivisions) * subdivisions; - subCeil = ceil( bounds[ 1 ][ axis ] / subdivisions) * subdivisions; + subFloor = floor( bounds[ 0 ][ axis ] / subdivisions ) * subdivisions; + subCeil = ceil( bounds[ 1 ][ axis ] / subdivisions ) * subdivisions; planePoint[ axis ] = subFloor + subdivisions; planeNormal[ axis ] = -1; d = DotProduct( planePoint, planeNormal ); /* subdivide if necessary */ - if( (subCeil - subFloor) > subdivisions ) - { + if ( ( subCeil - subFloor ) > subdivisions ) { /* clip the winding */ - ClipWindingEpsilon( w, planeNormal, d, epsilon, &frontWinding, &backWinding ); + ClipWindingEpsilon( w, planeNormal, d, epsilon, &frontWinding, &backWinding ); /* not strict; we assume we always keep a winding */ /* the clip may not produce two polygons if it was epsilon close */ - if( frontWinding == NULL ) + if ( frontWinding == NULL ) { w = backWinding; - else if( backWinding == NULL ) + } + else if ( backWinding == NULL ) { w = frontWinding; + } else { SubdivideFace_r( e, brush, side, frontWinding, fogNum, subdivisions ); @@ -1357,10 +1416,10 @@ static void SubdivideFace_r( entity_t *e, brush_t *brush, side_t *side, winding_ } } } - + /* create a face surface */ ds = DrawSurfaceForSide( e, brush, side, w ); - + /* set correct fog num */ ds->fogNum = fogNum; } @@ -1368,87 +1427,91 @@ static void SubdivideFace_r( entity_t *e, brush_t *brush, side_t *side, winding_ /* -SubdivideFaceSurfaces() -chop up brush face surfaces that have subdivision attributes -ydnar: and subdivide surfaces that exceed specified texture coordinate range -*/ - -void SubdivideFaceSurfaces( entity_t *e, tree_t *tree ) -{ - int i, j, numBaseDrawSurfs, fogNum; - mapDrawSurface_t *ds; - brush_t *brush; - side_t *side; - shaderInfo_t *si; - winding_t *w; - float range, size, subdivisions, s2; - - + SubdivideFaceSurfaces() + chop up brush face surfaces that have subdivision attributes + ydnar: and subdivide surfaces that exceed specified texture coordinate range + */ + +void SubdivideFaceSurfaces( entity_t *e, tree_t *tree ){ + int i, j, numBaseDrawSurfs, fogNum; + mapDrawSurface_t *ds; + brush_t *brush; + side_t *side; + shaderInfo_t *si; + winding_t *w; + float range, size, subdivisions, s2; + + /* note it */ Sys_FPrintf( SYS_VRB, "--- SubdivideFaceSurfaces ---\n" ); - + /* walk the list of surfaces */ numBaseDrawSurfs = numMapDrawSurfs; - for( i = e->firstDrawSurf; i < numBaseDrawSurfs; i++ ) + for ( i = e->firstDrawSurf; i < numBaseDrawSurfs; i++ ) { /* get surface */ ds = &mapDrawSurfs[ i ]; /* only subdivide brush sides */ - if( ds->type != SURFACE_FACE || ds->mapBrush == NULL || ds->sideRef == NULL || ds->sideRef->side == NULL ) + if ( ds->type != SURFACE_FACE || ds->mapBrush == NULL || ds->sideRef == NULL || ds->sideRef->side == NULL ) { continue; - + } + /* get bits */ brush = ds->mapBrush; side = ds->sideRef->side; - + /* check subdivision for shader */ si = side->shaderInfo; - if( si == NULL ) + if ( si == NULL ) { continue; - + } + /* ydnar: don't subdivide sky surfaces */ - if( si->compileFlags & C_SKY ) + if ( si->compileFlags & C_SKY ) { continue; - + } + /* do texture coordinate range check */ ClassifySurfaces( 1, ds ); - if( CalcSurfaceTextureRange( ds ) == qfalse ) - { + if ( CalcSurfaceTextureRange( ds ) == qfalse ) { /* calculate subdivisions texture range (this code is shit) */ - range = (ds->texRange[ 0 ] > ds->texRange[ 1 ] ? ds->texRange[ 0 ] : ds->texRange[ 1 ]); + range = ( ds->texRange[ 0 ] > ds->texRange[ 1 ] ? ds->texRange[ 0 ] : ds->texRange[ 1 ] ); size = ds->maxs[ 0 ] - ds->mins[ 0 ]; - for( j = 1; j < 3; j++ ) - if( (ds->maxs[ j ] - ds->mins[ j ]) > size ) + for ( j = 1; j < 3; j++ ) + if ( ( ds->maxs[ j ] - ds->mins[ j ] ) > size ) { size = ds->maxs[ j ] - ds->mins[ j ]; - subdivisions = (size / range) * texRange; + } + subdivisions = ( size / range ) * texRange; subdivisions = ceil( subdivisions / 2 ) * 2; - for( j = 1; j < 8; j++ ) + for ( j = 1; j < 8; j++ ) { s2 = ceil( (float) texRange / j ); - if( fabs( subdivisions - s2 ) <= 4.0 ) - { + if ( fabs( subdivisions - s2 ) <= 4.0 ) { subdivisions = s2; break; } } } - else + else{ subdivisions = si->subdivisions; - + } + /* get subdivisions from shader */ - if( si->subdivisions > 0 && si->subdivisions < subdivisions ) + if ( si->subdivisions > 0 && si->subdivisions < subdivisions ) { subdivisions = si->subdivisions; - if( subdivisions < 1.0f ) + } + if ( subdivisions < 1.0f ) { continue; - + } + /* preserve fog num */ fogNum = ds->fogNum; - + /* make a winding and free the surface */ w = WindingFromDrawSurf( ds ); ClearSurface( ds ); - + /* subdivide it */ SubdivideFace_r( e, brush, side, w, fogNum, subdivisions ); } @@ -1457,17 +1520,16 @@ void SubdivideFaceSurfaces( entity_t *e, tree_t *tree ) /* -==================== -ClipSideIntoTree_r + ==================== + ClipSideIntoTree_r -Adds non-opaque leaf fragments to the convex hull -==================== -*/ + Adds non-opaque leaf fragments to the convex hull + ==================== + */ -void ClipSideIntoTree_r( winding_t *w, side_t *side, node_t *node ) -{ - plane_t *plane; - winding_t *front, *back; +void ClipSideIntoTree_r( winding_t *w, side_t *side, node_t *node ){ + plane_t *plane; + winding_t *front, *back; if ( !w ) { return; @@ -1478,14 +1540,19 @@ void ClipSideIntoTree_r( winding_t *w, side_t *side, node_t *node ) ClipSideIntoTree_r( w, side, node->children[0] ); return; } - if ( side->planenum == ( node->planenum ^ 1) ) { + if ( side->planenum == ( node->planenum ^ 1 ) ) { ClipSideIntoTree_r( w, side, node->children[1] ); return; } plane = &mapplanes[ node->planenum ]; - ClipWindingEpsilon ( w, plane->normal, plane->dist, - ON_EPSILON, &front, &back ); + ClipWindingEpsilonStrict( w, plane->normal, plane->dist, + ON_EPSILON, &front, &back ); /* strict, we handle the "winding disappeared" case */ + if ( !front && !back ) { + /* in doubt, register it in both nodes */ + front = CopyWinding( w ); + back = CopyWinding( w ); + } FreeWinding( w ); ClipSideIntoTree_r( front, side, node->children[0] ); @@ -1512,65 +1579,68 @@ static int g_numHiddenFaces, g_numCoinFaces; /* -CullVectorCompare() - ydnar -compares two vectors with an epsilon -*/ + CullVectorCompare() - ydnar + compares two vectors with an epsilon + */ #define CULL_EPSILON 0.1f -qboolean CullVectorCompare( const vec3_t v1, const vec3_t v2 ) -{ - int i; - - - for( i = 0; i < 3; i++ ) - if( fabs( v1[ i ] - v2[ i ] ) > CULL_EPSILON ) +qboolean CullVectorCompare( const vec3_t v1, const vec3_t v2 ){ + int i; + + + for ( i = 0; i < 3; i++ ) + if ( fabs( v1[ i ] - v2[ i ] ) > CULL_EPSILON ) { return qfalse; + } return qtrue; } /* -SideInBrush() - ydnar -determines if a brushside lies inside another brush -*/ - -qboolean SideInBrush( side_t *side, brush_t *b ) -{ - int i, s; - plane_t *plane; - - + SideInBrush() - ydnar + determines if a brushside lies inside another brush + */ + +qboolean SideInBrush( side_t *side, brush_t *b ){ + int i, s; + plane_t *plane; + + /* ignore sides w/o windings or shaders */ - if( side->winding == NULL || side->shaderInfo == NULL ) + if ( side->winding == NULL || side->shaderInfo == NULL ) { return qtrue; + } /* ignore culled sides and translucent brushes */ - if( side->culled == qtrue || (b->compileFlags & C_TRANSLUCENT) ) + if ( side->culled == qtrue || ( b->compileFlags & C_TRANSLUCENT ) ) { return qfalse; + } /* side iterator */ - for( i = 0; i < b->numsides; i++ ) + for ( i = 0; i < b->numsides; i++ ) { /* fail if any sides are caulk */ - if( b->sides[ i ].compileFlags & C_NODRAW ) + if ( b->sides[ i ].compileFlags & C_NODRAW ) { return qfalse; + } /* check if side's winding is on or behind the plane */ plane = &mapplanes[ b->sides[ i ].planenum ]; s = WindingOnPlaneSide( side->winding, plane->normal, plane->dist ); - if( s == SIDE_FRONT || s == SIDE_CROSS ) + if ( s == SIDE_FRONT || s == SIDE_CROSS ) { return qfalse; + } } - + /* don't cull autosprite or polygonoffset surfaces */ - if( side->shaderInfo ) - { - if( side->shaderInfo->autosprite || side->shaderInfo->polygonOffset ) + if ( side->shaderInfo ) { + if ( side->shaderInfo->autosprite || side->shaderInfo->polygonOffset ) { return qfalse; + } } - + /* inside */ side->culled = qtrue; g_numHiddenFaces++; @@ -1579,159 +1649,182 @@ qboolean SideInBrush( side_t *side, brush_t *b ) /* -CullSides() - ydnar -culls obscured or buried brushsides from the map -*/ - -void CullSides( entity_t *e ) -{ - int numPoints; - int i, j, k, l, first, second, dir; - winding_t *w1, *w2; - brush_t *b1, *b2; - side_t *side1, *side2; - - + CullSides() - ydnar + culls obscured or buried brushsides from the map + */ + +void CullSides( entity_t *e ){ + int numPoints; + int i, j, k, l, first, second, dir; + winding_t *w1, *w2; + brush_t *b1, *b2; + side_t *side1, *side2; + + /* note it */ Sys_FPrintf( SYS_VRB, "--- CullSides ---\n" ); - + g_numHiddenFaces = 0; g_numCoinFaces = 0; - + /* brush interator 1 */ - for( b1 = e->brushes; b1; b1 = b1->next ) + for ( b1 = e->brushes; b1; b1 = b1->next ) { /* sides check */ - if( b1->numsides < 1 ) + if ( b1->numsides < 1 ) { continue; + } /* brush iterator 2 */ - for( b2 = b1->next; b2; b2 = b2->next ) + for ( b2 = b1->next; b2; b2 = b2->next ) { /* sides check */ - if( b2->numsides < 1 ) + if ( b2->numsides < 1 ) { continue; - + } + /* original check */ - if( b1->original == b2->original && b1->original != NULL ) + if ( b1->original == b2->original && b1->original != NULL ) { continue; - + } + /* bbox check */ j = 0; - for( i = 0; i < 3; i++ ) - if( b1->mins[ i ] > b2->maxs[ i ] || b1->maxs[ i ] < b2->mins[ i ] ) + for ( i = 0; i < 3; i++ ) + if ( b1->mins[ i ] > b2->maxs[ i ] || b1->maxs[ i ] < b2->mins[ i ] ) { j++; - if( j ) + } + if ( j ) { continue; + } /* cull inside sides */ - for( i = 0; i < b1->numsides; i++ ) + for ( i = 0; i < b1->numsides; i++ ) SideInBrush( &b1->sides[ i ], b2 ); - for( i = 0; i < b2->numsides; i++ ) + for ( i = 0; i < b2->numsides; i++ ) SideInBrush( &b2->sides[ i ], b1 ); - + /* side iterator 1 */ - for( i = 0; i < b1->numsides; i++ ) + for ( i = 0; i < b1->numsides; i++ ) { /* winding check */ side1 = &b1->sides[ i ]; w1 = side1->winding; - if( w1 == NULL ) + if ( w1 == NULL ) { continue; + } numPoints = w1->numpoints; - if( side1->shaderInfo == NULL ) + if ( side1->shaderInfo == NULL ) { continue; - + } + /* side iterator 2 */ - for( j = 0; j < b2->numsides; j++ ) + for ( j = 0; j < b2->numsides; j++ ) { /* winding check */ side2 = &b2->sides[ j ]; w2 = side2->winding; - if( w2 == NULL ) + if ( w2 == NULL ) { continue; - if( side2->shaderInfo == NULL ) + } + if ( side2->shaderInfo == NULL ) { continue; - if( w1->numpoints != w2->numpoints ) + } + if ( w1->numpoints != w2->numpoints ) { continue; - if( side1->culled == qtrue && side2->culled == qtrue ) + } + if ( side1->culled == qtrue && side2->culled == qtrue ) { continue; - + } + /* compare planes */ - if( (side1->planenum & ~0x00000001) != (side2->planenum & ~0x00000001) ) + if ( ( side1->planenum & ~0x00000001 ) != ( side2->planenum & ~0x00000001 ) ) { continue; - + } + /* get autosprite and polygonoffset status */ - if( side1->shaderInfo && - (side1->shaderInfo->autosprite || side1->shaderInfo->polygonOffset) ) + if ( side1->shaderInfo && + ( side1->shaderInfo->autosprite || side1->shaderInfo->polygonOffset ) ) { continue; - if( side2->shaderInfo && - (side2->shaderInfo->autosprite || side2->shaderInfo->polygonOffset) ) + } + if ( side2->shaderInfo && + ( side2->shaderInfo->autosprite || side2->shaderInfo->polygonOffset ) ) { continue; - + } + /* find first common point */ first = -1; - for( k = 0; k < numPoints; k++ ) + for ( k = 0; k < numPoints; k++ ) { - if( VectorCompare( w1->p[ 0 ], w2->p[ k ] ) ) - { + if ( VectorCompare( w1->p[ 0 ], w2->p[ k ] ) ) { first = k; k = numPoints; } } - if( first == -1 ) + if ( first == -1 ) { continue; - + } + /* find second common point (regardless of winding order) */ second = -1; dir = 0; - if( (first + 1) < numPoints ) + if ( ( first + 1 ) < numPoints ) { second = first + 1; - else + } + else{ second = 0; - if( CullVectorCompare( w1->p[ 1 ], w2->p[ second ] ) ) + } + if ( CullVectorCompare( w1->p[ 1 ], w2->p[ second ] ) ) { dir = 1; + } else { - if( first > 0 ) + if ( first > 0 ) { second = first - 1; - else + } + else{ second = numPoints - 1; - if( CullVectorCompare( w1->p[ 1 ], w2->p[ second ] ) ) + } + if ( CullVectorCompare( w1->p[ 1 ], w2->p[ second ] ) ) { dir = -1; + } } - if( dir == 0 ) + if ( dir == 0 ) { continue; - + } + /* compare the rest of the points */ l = first; - for( k = 0; k < numPoints; k++ ) + for ( k = 0; k < numPoints; k++ ) { - if( !CullVectorCompare( w1->p[ k ], w2->p[ l ] ) ) + if ( !CullVectorCompare( w1->p[ k ], w2->p[ l ] ) ) { k = 100000; - + } + l += dir; - if( l < 0 ) + if ( l < 0 ) { l = numPoints - 1; - else if( l >= numPoints ) + } + else if ( l >= numPoints ) { l = 0; + } } - if( k >= 100000 ) + if ( k >= 100000 ) { continue; - + } + /* cull face 1 */ - if( !side2->culled && !(side2->compileFlags & C_TRANSLUCENT) && !(side2->compileFlags & C_NODRAW) ) - { + if ( !side2->culled && !( side2->compileFlags & C_TRANSLUCENT ) && !( side2->compileFlags & C_NODRAW ) ) { side1->culled = qtrue; g_numCoinFaces++; } - - if( side1->planenum == side2->planenum && side1->culled == qtrue ) + + if ( side1->planenum == side2->planenum && side1->culled == qtrue ) { continue; - + } + /* cull face 2 */ - if( !side1->culled && !(side1->compileFlags & C_TRANSLUCENT) && !(side1->compileFlags & C_NODRAW) ) - { + if ( !side1->culled && !( side1->compileFlags & C_TRANSLUCENT ) && !( side1->compileFlags & C_NODRAW ) ) { side2->culled = qtrue; g_numCoinFaces++; } @@ -1739,7 +1832,7 @@ void CullSides( entity_t *e ) } } } - + /* emit some stats */ Sys_FPrintf( SYS_VRB, "%9d hidden faces culled\n", g_numHiddenFaces ); Sys_FPrintf( SYS_VRB, "%9d coincident faces culled\n", g_numCoinFaces ); @@ -1749,79 +1842,84 @@ void CullSides( entity_t *e ) /* -ClipSidesIntoTree() - -creates side->visibleHull for all visible sides - -the drawsurf for a side will consist of the convex hull of -all points in non-opaque clusters, which allows overlaps -to be trimmed off automatically. -*/ - -void ClipSidesIntoTree( entity_t *e, tree_t *tree ) -{ - brush_t *b; - int i; - winding_t *w; - side_t *side, *newSide; - shaderInfo_t *si; - - + ClipSidesIntoTree() + + creates side->visibleHull for all visible sides + + the drawsurf for a side will consist of the convex hull of + all points in non-opaque clusters, which allows overlaps + to be trimmed off automatically. + */ + +void ClipSidesIntoTree( entity_t *e, tree_t *tree ){ + brush_t *b; + int i; + winding_t *w; + side_t *side, *newSide; + shaderInfo_t *si; + + /* ydnar: cull brush sides */ CullSides( e ); - + /* note it */ Sys_FPrintf( SYS_VRB, "--- ClipSidesIntoTree ---\n" ); - + /* walk the brush list */ - for( b = e->brushes; b; b = b->next ) + for ( b = e->brushes; b; b = b->next ) { /* walk the brush sides */ - for( i = 0; i < b->numsides; i++ ) + for ( i = 0; i < b->numsides; i++ ) { /* get side */ side = &b->sides[ i ]; - if( side->winding == NULL ) + if ( side->winding == NULL ) { continue; - + } + /* copy the winding */ w = CopyWinding( side->winding ); side->visibleHull = NULL; ClipSideIntoTree_r( w, side, tree->headnode ); - + /* anything left? */ w = side->visibleHull; - if( w == NULL ) + if ( w == NULL ) { continue; - + } + /* shader? */ si = side->shaderInfo; - if( si == NULL ) + if ( si == NULL ) { continue; - + } + /* don't create faces for non-visible sides */ /* ydnar: except indexed shaders, like common/terrain and nodraw fog surfaces */ - if( (si->compileFlags & C_NODRAW) && si->indexed == qfalse && !(si->compileFlags & C_FOG) ) + if ( ( si->compileFlags & C_NODRAW ) && si->indexed == qfalse && !( si->compileFlags & C_FOG ) ) { continue; - + } + /* always use the original winding for autosprites and noclip faces */ - if( si->autosprite || si->noClip ) + if ( si->autosprite || si->noClip ) { w = side->winding; - + } + /* save this winding as a visible surface */ DrawSurfaceForSide( e, b, side, w ); /* make a back side for fog */ - if( !(si->compileFlags & C_FOG) ) + if ( !( si->compileFlags & C_FOG ) ) { continue; - + } + /* duplicate the up-facing side */ w = ReverseWinding( w ); newSide = safe_malloc( sizeof( *side ) ); *newSide = *side; newSide->visibleHull = w; newSide->planenum ^= 1; - + /* save this winding as a visible surface */ DrawSurfaceForSide( e, b, newSide, w ); } @@ -1832,44 +1930,47 @@ void ClipSidesIntoTree( entity_t *e, tree_t *tree ) /* -this section deals with filtering drawsurfaces into the bsp tree, -adding references to each leaf a surface touches + this section deals with filtering drawsurfaces into the bsp tree, + adding references to each leaf a surface touches -*/ + */ /* -AddReferenceToLeaf() - ydnar -adds a reference to surface ds in the bsp leaf node -*/ - -int AddReferenceToLeaf( mapDrawSurface_t *ds, node_t *node ) -{ - drawSurfRef_t *dsr; - - + AddReferenceToLeaf() - ydnar + adds a reference to surface ds in the bsp leaf node + */ + +int AddReferenceToLeaf( mapDrawSurface_t *ds, node_t *node ){ + drawSurfRef_t *dsr; + + /* dummy check */ - if( node->planenum != PLANENUM_LEAF || node->opaque ) + if ( node->planenum != PLANENUM_LEAF || node->opaque ) { return 0; - + } + /* try to find an existing reference */ - for( dsr = node->drawSurfReferences; dsr; dsr = dsr->nextRef ) + for ( dsr = node->drawSurfReferences; dsr; dsr = dsr->nextRef ) { - if( dsr->outputNum == numBSPDrawSurfaces ) + if ( dsr->outputNum == numBSPDrawSurfaces ) { return 0; + } } - + /* add a new reference */ dsr = safe_malloc( sizeof( *dsr ) ); dsr->outputNum = numBSPDrawSurfaces; dsr->nextRef = node->drawSurfReferences; node->drawSurfReferences = dsr; - + /* ydnar: sky/skybox surfaces */ - if( node->skybox ) + if ( node->skybox ) { ds->skybox = qtrue; - if( ds->shaderInfo->compileFlags & C_SKY ) + } + if ( ds->shaderInfo->compileFlags & C_SKY ) { node->sky = qtrue; - + } + /* return */ return 1; } @@ -1877,40 +1978,39 @@ int AddReferenceToLeaf( mapDrawSurface_t *ds, node_t *node ) /* -AddReferenceToTree_r() - ydnar -adds a reference to the specified drawsurface to every leaf in the tree -*/ - -int AddReferenceToTree_r( mapDrawSurface_t *ds, node_t *node, qboolean skybox ) -{ - int i, refs = 0; - - + AddReferenceToTree_r() - ydnar + adds a reference to the specified drawsurface to every leaf in the tree + */ + +int AddReferenceToTree_r( mapDrawSurface_t *ds, node_t *node, qboolean skybox ){ + int i, refs = 0; + + /* dummy check */ - if( node == NULL ) + if ( node == NULL ) { return 0; - + } + /* is this a decision node? */ - if( node->planenum != PLANENUM_LEAF ) - { + if ( node->planenum != PLANENUM_LEAF ) { /* add to child nodes and return */ refs += AddReferenceToTree_r( ds, node->children[ 0 ], skybox ); refs += AddReferenceToTree_r( ds, node->children[ 1 ], skybox ); return refs; } - + /* ydnar */ - if( skybox ) - { + if ( skybox ) { /* skybox surfaces only get added to sky leaves */ - if( !node->sky ) + if ( !node->sky ) { return 0; - + } + /* increase the leaf bounds */ - for( i = 0; i < ds->numVerts; i++ ) + for ( i = 0; i < ds->numVerts; i++ ) AddPointToBounds( ds->verts[ i ].xyz, node->mins, node->maxs ); } - + /* add a reference */ return AddReferenceToLeaf( ds, node ); } @@ -1918,129 +2018,208 @@ int AddReferenceToTree_r( mapDrawSurface_t *ds, node_t *node, qboolean skybox ) /* -FilterPointIntoTree_r() - ydnar -filters a single point from a surface into the tree -*/ - -int FilterPointIntoTree_r( vec3_t point, mapDrawSurface_t *ds, node_t *node ) -{ - float d; - plane_t *plane; - int refs = 0; - - + FilterPointIntoTree_r() - ydnar + filters a single point from a surface into the tree + */ + +int FilterPointIntoTree_r( vec3_t point, mapDrawSurface_t *ds, node_t *node ){ + float d; + plane_t *plane; + int refs = 0; + + /* is this a decision node? */ - if( node->planenum != PLANENUM_LEAF ) - { + if ( node->planenum != PLANENUM_LEAF ) { /* classify the point in relation to the plane */ plane = &mapplanes[ node->planenum ]; d = DotProduct( point, plane->normal ) - plane->dist; - + /* filter by this plane */ refs = 0; - if( d >= -ON_EPSILON ) + if ( d >= -ON_EPSILON ) { refs += FilterPointIntoTree_r( point, ds, node->children[ 0 ] ); - if( d <= ON_EPSILON ) + } + if ( d <= ON_EPSILON ) { refs += FilterPointIntoTree_r( point, ds, node->children[ 1 ] ); - + } + /* return */ return refs; } - + /* add a reference */ return AddReferenceToLeaf( ds, node ); } +/* + FilterPointConvexHullIntoTree_r() - ydnar + filters the convex hull of multiple points from a surface into the tree + */ +int FilterPointConvexHullIntoTree_r( vec3_t **points, int npoints, mapDrawSurface_t *ds, node_t *node ){ + float d, dmin, dmax; + plane_t *plane; + int refs = 0; + int i; -/* -FilterWindingIntoTree_r() - ydnar -filters a winding from a drawsurface into the tree -*/ - -int FilterWindingIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node ) -{ - int i, refs = 0; - plane_t *p1, *p2; - vec4_t plane1, plane2, reverse; - winding_t *fat, *front, *back; - shaderInfo_t *si; - - - /* get shaderinfo */ - si = ds->shaderInfo; - - /* ydnar: is this the head node? */ - if( node->parent == NULL && si != NULL && - (si->mins[ 0 ] != 0.0f || si->maxs[ 0 ] != 0.0f || - si->mins[ 1 ] != 0.0f || si->maxs[ 1 ] != 0.0f || - si->mins[ 2 ] != 0.0f || si->maxs[ 2 ] != 0.0f) ) - { - /* 'fatten' the winding by the shader mins/maxs (parsed from vertexDeform move) */ - /* note this winding is completely invalid (concave, nonplanar, etc) */ - fat = AllocWinding( w->numpoints * 3 ); - fat->numpoints = w->numpoints * 3; - for( i = 0; i < w->numpoints; i++ ) - { - VectorCopy( w->p[ i ], fat->p[ i ] ); - VectorAdd( w->p[ i ], si->mins, fat->p[ i * 2 ] ); - VectorAdd( w->p[ i ], si->maxs, fat->p[ i * 3 ] ); - } - - FreeWinding( w ); - w = fat; + if ( !points ) { + return 0; } - + /* is this a decision node? */ - if( node->planenum != PLANENUM_LEAF ) - { - /* get node plane */ - p1 = &mapplanes[ node->planenum ]; - VectorCopy( p1->normal, plane1 ); - plane1[ 3 ] = p1->dist; - - /* check if surface is planar */ - if( ds->planeNum >= 0 ) + if ( node->planenum != PLANENUM_LEAF ) { + /* classify the point in relation to the plane */ + plane = &mapplanes[ node->planenum ]; + + dmin = dmax = DotProduct( *( points[0] ), plane->normal ) - plane->dist; + for ( i = 1; i < npoints; ++i ) { - /* get surface plane */ - p2 = &mapplanes[ ds->planeNum ]; - VectorCopy( p2->normal, plane2 ); - plane2[ 3 ] = p2->dist; - - #if 1 - /* invert surface plane */ - VectorSubtract( vec3_origin, plane2, reverse ); - reverse[ 3 ] = -plane2[ 3 ]; - - /* compare planes */ - if( DotProduct( plane1, plane2 ) > 0.999f && fabs( plane1[ 3 ] - plane2[ 3 ] ) < 0.001f ) - return FilterWindingIntoTree_r( w, ds, node->children[ 0 ] ); - if( DotProduct( plane1, reverse ) > 0.999f && fabs( plane1[ 3 ] - reverse[ 3 ] ) < 0.001f ) - return FilterWindingIntoTree_r( w, ds, node->children[ 1 ] ); - #else - /* the drawsurf might have an associated plane, if so, force a filter here */ - if( ds->planeNum == node->planenum ) - return FilterWindingIntoTree_r( w, ds, node->children[ 0 ] ); - if( ds->planeNum == (node->planenum ^ 1) ) - return FilterWindingIntoTree_r( w, ds, node->children[ 1 ] ); - #endif + d = DotProduct( *( points[i] ), plane->normal ) - plane->dist; + if ( d > dmax ) { + dmax = d; + } + if ( d < dmin ) { + dmin = d; + } } - - /* clip the winding by this plane */ - ClipWindingEpsilon( w, plane1, plane1[ 3 ], ON_EPSILON, &front, &back ); - + + /* filter by this plane */ + refs = 0; + if ( dmax >= -ON_EPSILON ) { + refs += FilterPointConvexHullIntoTree_r( points, npoints, ds, node->children[ 0 ] ); + } + if ( dmin <= ON_EPSILON ) { + refs += FilterPointConvexHullIntoTree_r( points, npoints, ds, node->children[ 1 ] ); + } + + /* return */ + return refs; + } + + /* add a reference */ + return AddReferenceToLeaf( ds, node ); +} + + +/* + FilterWindingIntoTree_r() - ydnar + filters a winding from a drawsurface into the tree + */ + +int FilterWindingIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node ){ + int i, refs = 0; + plane_t *p1, *p2; + vec4_t plane1, plane2; + winding_t *fat, *front, *back; + shaderInfo_t *si; + + + /* get shaderinfo */ + si = ds->shaderInfo; + + /* ydnar: is this the head node? */ + if ( node->parent == NULL && si != NULL && + ( si->mins[ 0 ] != 0.0f || si->maxs[ 0 ] != 0.0f || + si->mins[ 1 ] != 0.0f || si->maxs[ 1 ] != 0.0f || + si->mins[ 2 ] != 0.0f || si->maxs[ 2 ] != 0.0f ) ) { + static qboolean warned = qfalse; + if ( !warned ) { + Sys_FPrintf( SYS_WRN, "WARNING: this map uses the deformVertexes move hack\n" ); + warned = qtrue; + } + + /* 'fatten' the winding by the shader mins/maxs (parsed from vertexDeform move) */ + /* note this winding is completely invalid (concave, nonplanar, etc) */ + fat = AllocWinding( w->numpoints * 3 + 3 ); + fat->numpoints = w->numpoints * 3 + 3; + for ( i = 0; i < w->numpoints; i++ ) + { + VectorCopy( w->p[ i ], fat->p[ i ] ); + VectorAdd( w->p[ i ], si->mins, fat->p[ i + ( w->numpoints + 1 ) ] ); + VectorAdd( w->p[ i ], si->maxs, fat->p[ i + ( w->numpoints + 1 ) * 2 ] ); + } + VectorCopy( w->p[ 0 ], fat->p[ i ] ); + VectorAdd( w->p[ 0 ], si->mins, fat->p[ i + w->numpoints ] ); + VectorAdd( w->p[ 0 ], si->maxs, fat->p[ i + w->numpoints * 2 ] ); + + /* + * note: this winding is STILL not suitable for ClipWindingEpsilon, and + * also does not really fulfill the intention as it only contains + * origin, +mins, +maxs, but thanks to the "closing" points I just + * added to the three sub-windings, the fattening at least doesn't make + * it worse + */ + + FreeWinding( w ); + w = fat; + } + + /* is this a decision node? */ + if ( node->planenum != PLANENUM_LEAF ) { + /* get node plane */ + p1 = &mapplanes[ node->planenum ]; + VectorCopy( p1->normal, plane1 ); + plane1[ 3 ] = p1->dist; + + /* check if surface is planar */ + if ( ds->planeNum >= 0 ) { + /* get surface plane */ + p2 = &mapplanes[ ds->planeNum ]; + VectorCopy( p2->normal, plane2 ); + plane2[ 3 ] = p2->dist; + + #if 0 + /* div0: this is the plague (inaccurate) */ + vec4_t reverse; + + /* invert surface plane */ + VectorSubtract( vec3_origin, plane2, reverse ); + reverse[ 3 ] = -plane2[ 3 ]; + + /* compare planes */ + if ( DotProduct( plane1, plane2 ) > 0.999f && fabs( plane1[ 3 ] - plane2[ 3 ] ) < 0.001f ) { + return FilterWindingIntoTree_r( w, ds, node->children[ 0 ] ); + } + if ( DotProduct( plane1, reverse ) > 0.999f && fabs( plane1[ 3 ] - reverse[ 3 ] ) < 0.001f ) { + return FilterWindingIntoTree_r( w, ds, node->children[ 1 ] ); + } + #else + (void) plane2; + /* div0: this is the cholera (doesn't hit enough) */ + + /* the drawsurf might have an associated plane, if so, force a filter here */ + if ( ds->planeNum == node->planenum ) { + return FilterWindingIntoTree_r( w, ds, node->children[ 0 ] ); + } + if ( ds->planeNum == ( node->planenum ^ 1 ) ) { + return FilterWindingIntoTree_r( w, ds, node->children[ 1 ] ); + } + #endif + } + + /* clip the winding by this plane */ + ClipWindingEpsilonStrict( w, plane1, plane1[ 3 ], ON_EPSILON, &front, &back ); /* strict; we handle the "winding disappeared" case */ + /* filter by this plane */ refs = 0; - if( front != NULL ) + if ( front == NULL && back == NULL ) { + /* same plane, this is an ugly hack */ + /* but better too many than too few refs */ + refs += FilterWindingIntoTree_r( CopyWinding( w ), ds, node->children[ 0 ] ); + refs += FilterWindingIntoTree_r( CopyWinding( w ), ds, node->children[ 1 ] ); + } + if ( front != NULL ) { refs += FilterWindingIntoTree_r( front, ds, node->children[ 0 ] ); - if( back != NULL ) + } + if ( back != NULL ) { refs += FilterWindingIntoTree_r( back, ds, node->children[ 1 ] ); + } FreeWinding( w ); - + /* return */ return refs; } - + /* add a reference */ return AddReferenceToLeaf( ds, node ); } @@ -2048,20 +2227,19 @@ int FilterWindingIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node ) /* -FilterFaceIntoTree() -filters a planar winding face drawsurface into the bsp tree -*/ - -int FilterFaceIntoTree( mapDrawSurface_t *ds, tree_t *tree ) -{ - winding_t *w; - int refs = 0; - - + FilterFaceIntoTree() + filters a planar winding face drawsurface into the bsp tree + */ + +int FilterFaceIntoTree( mapDrawSurface_t *ds, tree_t *tree ){ + winding_t *w; + int refs = 0; + + /* make a winding and filter it into the tree */ w = WindingFromDrawSurf( ds ); refs = FilterWindingIntoTree_r( w, ds, tree->headnode ); - + /* return */ return refs; } @@ -2069,82 +2247,57 @@ int FilterFaceIntoTree( mapDrawSurface_t *ds, tree_t *tree ) /* -FilterPatchIntoTree() -subdivides a patch into an approximate curve and filters it into the tree -*/ - -#define FILTER_SUBDIVISION 8 - -static int FilterPatchIntoTree( mapDrawSurface_t *ds, tree_t *tree ) -{ - int i, x, y, refs; - mesh_t src, *mesh; - winding_t *w; - - - /* subdivide the surface */ - src.width = ds->patchWidth; - src.height = ds->patchHeight; - src.verts = ds->verts; - mesh = SubdivideMesh( src, FILTER_SUBDIVISION, 32 ); - - - /* filter each quad into the tree (fixme: use new patch x-triangulation code?) */ - refs = 0; - for( y = 0; y < (mesh->height - 1); y++ ) - { - for( x = 0; x < (mesh->width - 1); x++ ) + FilterPatchIntoTree() + subdivides a patch into an approximate curve and filters it into the tree + */ + +#define FILTER_SUBDIVISION 8 + +static int FilterPatchIntoTree( mapDrawSurface_t *ds, tree_t *tree ){ + int x, y, refs = 0; + + for ( y = 0; y + 2 < ds->patchHeight; y += 2 ) + for ( x = 0; x + 2 < ds->patchWidth; x += 2 ) { - /* triangle 1 */ - w = AllocWinding( 3 ); - w->numpoints = 3; - VectorCopy( mesh->verts[ y * mesh->width + x ].xyz, w->p[ 0 ] ); - VectorCopy( mesh->verts[ y * mesh->width + x + 1 ].xyz, w->p[ 1 ] ); - VectorCopy( mesh->verts[ (y + 1) * mesh->width + x ].xyz, w->p[ 2 ] ); - refs += FilterWindingIntoTree_r( w, ds, tree->headnode ); - - /* triangle 2 */ - w = AllocWinding( 3 ); - w->numpoints = 3; - VectorCopy( mesh->verts[ y * mesh->width + x + 1 ].xyz, w->p[ 0 ] ); - VectorCopy( mesh->verts[ (y + 1 ) * mesh->width + x + 1 ].xyz, w->p[ 1 ] ); - VectorCopy( mesh->verts[ (y + 1 ) * mesh->width + x ].xyz, w->p[ 2 ] ); - refs += FilterWindingIntoTree_r( w, ds, tree->headnode ); + vec3_t *points[9]; + points[0] = &ds->verts[( y + 0 ) * ds->patchWidth + ( x + 0 )].xyz; + points[1] = &ds->verts[( y + 0 ) * ds->patchWidth + ( x + 1 )].xyz; + points[2] = &ds->verts[( y + 0 ) * ds->patchWidth + ( x + 2 )].xyz; + points[3] = &ds->verts[( y + 1 ) * ds->patchWidth + ( x + 0 )].xyz; + points[4] = &ds->verts[( y + 1 ) * ds->patchWidth + ( x + 1 )].xyz; + points[5] = &ds->verts[( y + 1 ) * ds->patchWidth + ( x + 2 )].xyz; + points[6] = &ds->verts[( y + 2 ) * ds->patchWidth + ( x + 0 )].xyz; + points[7] = &ds->verts[( y + 2 ) * ds->patchWidth + ( x + 1 )].xyz; + points[8] = &ds->verts[( y + 2 ) * ds->patchWidth + ( x + 2 )].xyz; + refs += FilterPointConvexHullIntoTree_r( points, 9, ds, tree->headnode ); } - } - - /* use point filtering as well */ - for( i = 0; i < (mesh->width * mesh->height); i++ ) - refs += FilterPointIntoTree_r( mesh->verts[ i ].xyz, ds, tree->headnode ); - - /* free the subdivided mesh and return */ - FreeMesh( mesh ); + return refs; } /* -FilterTrianglesIntoTree() -filters a triangle surface (meta, model) into the bsp -*/ - -static int FilterTrianglesIntoTree( mapDrawSurface_t *ds, tree_t *tree ) -{ - int i, refs; - winding_t *w; - - + FilterTrianglesIntoTree() + filters a triangle surface (meta, model) into the bsp + */ + +static int FilterTrianglesIntoTree( mapDrawSurface_t *ds, tree_t *tree ){ + int i, refs; + winding_t *w; + + /* ydnar: gs mods: this was creating bogus triangles before */ refs = 0; - for( i = 0; i < ds->numIndexes; i += 3 ) + for ( i = 0; i < ds->numIndexes; i += 3 ) { /* error check */ - if( ds->indexes[ i ] >= ds->numVerts || - ds->indexes[ i + 1 ] >= ds->numVerts || - ds->indexes[ i + 2 ] >= ds->numVerts ) + if ( ds->indexes[ i ] >= ds->numVerts || + ds->indexes[ i + 1 ] >= ds->numVerts || + ds->indexes[ i + 2 ] >= ds->numVerts ) { Error( "Index %d greater than vertex count %d", ds->indexes[ i ], ds->numVerts ); - + } + /* make a triangle winding and filter it into the tree */ w = AllocWinding( 3 ); w->numpoints = 3; @@ -2153,9 +2306,9 @@ static int FilterTrianglesIntoTree( mapDrawSurface_t *ds, tree_t *tree ) VectorCopy( ds->verts[ ds->indexes[ i + 2 ] ].xyz, w->p[ 2 ] ); refs += FilterWindingIntoTree_r( w, ds, tree->headnode ); } - + /* use point filtering as well */ - for( i = 0; i < ds->numVerts; i++ ) + for ( i = 0; i < ds->numVerts; i++ ) refs += FilterPointIntoTree_r( ds->verts[ i ].xyz, ds, tree->headnode ); return refs; @@ -2164,34 +2317,34 @@ static int FilterTrianglesIntoTree( mapDrawSurface_t *ds, tree_t *tree ) /* -FilterFoliageIntoTree() -filters a foliage surface (wolf et/splash damage) -*/ - -static int FilterFoliageIntoTree( mapDrawSurface_t *ds, tree_t *tree ) -{ - int f, i, refs; - bspDrawVert_t *instance; - vec3_t xyz; - winding_t *w; - - + FilterFoliageIntoTree() + filters a foliage surface (wolf et/splash damage) + */ + +static int FilterFoliageIntoTree( mapDrawSurface_t *ds, tree_t *tree ){ + int f, i, refs; + bspDrawVert_t *instance; + vec3_t xyz; + winding_t *w; + + /* walk origin list */ refs = 0; - for( f = 0; f < ds->numFoliageInstances; f++ ) + for ( f = 0; f < ds->numFoliageInstances; f++ ) { /* get instance */ instance = ds->verts + ds->patchHeight + f; - + /* walk triangle list */ - for( i = 0; i < ds->numIndexes; i += 3 ) + for ( i = 0; i < ds->numIndexes; i += 3 ) { /* error check */ - if( ds->indexes[ i ] >= ds->numVerts || - ds->indexes[ i + 1 ] >= ds->numVerts || - ds->indexes[ i + 2 ] >= ds->numVerts ) + if ( ds->indexes[ i ] >= ds->numVerts || + ds->indexes[ i + 1 ] >= ds->numVerts || + ds->indexes[ i + 2 ] >= ds->numVerts ) { Error( "Index %d greater than vertex count %d", ds->indexes[ i ], ds->numVerts ); - + } + /* make a triangle winding and filter it into the tree */ w = AllocWinding( 3 ); w->numpoints = 3; @@ -2200,77 +2353,74 @@ static int FilterFoliageIntoTree( mapDrawSurface_t *ds, tree_t *tree ) VectorAdd( instance->xyz, ds->verts[ ds->indexes[ i + 2 ] ].xyz, w->p[ 2 ] ); refs += FilterWindingIntoTree_r( w, ds, tree->headnode ); } - + /* use point filtering as well */ - for( i = 0; i < (ds->numVerts - ds->numFoliageInstances); i++ ) + for ( i = 0; i < ( ds->numVerts - ds->numFoliageInstances ); i++ ) { VectorAdd( instance->xyz, ds->verts[ i ].xyz, xyz ); refs += FilterPointIntoTree_r( xyz, ds, tree->headnode ); } } - + return refs; } /* -FilterFlareIntoTree() -simple point filtering for flare surfaces -*/ -static int FilterFlareSurfIntoTree( mapDrawSurface_t *ds, tree_t *tree ) -{ + FilterFlareIntoTree() + simple point filtering for flare surfaces + */ +static int FilterFlareSurfIntoTree( mapDrawSurface_t *ds, tree_t *tree ){ return FilterPointIntoTree_r( ds->lightmapOrigin, ds, tree->headnode ); } /* -EmitDrawVerts() - ydnar -emits bsp drawverts from a map drawsurface -*/ - -void EmitDrawVerts( mapDrawSurface_t *ds, bspDrawSurface_t *out ) -{ - int i, k; - bspDrawVert_t *dv; - shaderInfo_t *si; - float offset; - - + EmitDrawVerts() - ydnar + emits bsp drawverts from a map drawsurface + */ + +void EmitDrawVerts( mapDrawSurface_t *ds, bspDrawSurface_t *out ){ + int i, k; + bspDrawVert_t *dv; + shaderInfo_t *si; + float offset; + + /* get stuff */ si = ds->shaderInfo; offset = si->offset; - + /* copy the verts */ out->firstVert = numBSPDrawVerts; out->numVerts = ds->numVerts; - for( i = 0; i < ds->numVerts; i++ ) + for ( i = 0; i < ds->numVerts; i++ ) { /* allocate a new vert */ - if( numBSPDrawVerts == MAX_MAP_DRAW_VERTS ) - Error( "MAX_MAP_DRAW_VERTS" ); IncDrawVerts(); dv = &bspDrawVerts[ numBSPDrawVerts - 1 ]; - + /* copy it */ memcpy( dv, &ds->verts[ i ], sizeof( *dv ) ); - + /* offset? */ - if( offset != 0.0f ) + if ( offset != 0.0f ) { VectorMA( dv->xyz, offset, dv->normal, dv->xyz ); - + } + /* expand model bounds necessary because of misc_model surfaces on entities note: does not happen on worldspawn as its bounds is only used for determining lightgrid bounds */ - if( numBSPModels > 0 ) + if ( numBSPModels > 0 ) { AddPointToBounds( dv->xyz, bspModels[ numBSPModels ].mins, bspModels[ numBSPModels ].maxs ); - + } + /* debug color? */ - if( debugSurfaces ) - { - for( k = 0; k < MAX_LIGHTMAPS; k++ ) - VectorCopy( debugColors[ (ds - mapDrawSurfs) % 12 ], dv->color[ k ] ); + if ( debugSurfaces ) { + for ( k = 0; k < MAX_LIGHTMAPS; k++ ) + VectorCopy( debugColors[ ( ds - mapDrawSurfs ) % 12 ], dv->color[ k ] ); } } } @@ -2278,71 +2428,69 @@ void EmitDrawVerts( mapDrawSurface_t *ds, bspDrawSurface_t *out ) /* -FindDrawIndexes() - ydnar -this attempts to find a run of indexes in the bsp that match the given indexes -this tends to reduce the size of the bsp index pool by 1/3 or more -returns numIndexes + 1 if the search failed -*/ - -int FindDrawIndexes( int numIndexes, int *indexes ) -{ - int i, j, numTestIndexes; - - + FindDrawIndexes() - ydnar + this attempts to find a run of indexes in the bsp that match the given indexes + this tends to reduce the size of the bsp index pool by 1/3 or more + returns numIndexes + 1 if the search failed + */ + +int FindDrawIndexes( int numIndexes, int *indexes ){ + int i, j, numTestIndexes; + + /* dummy check */ - if( numIndexes < 3 || numBSPDrawIndexes < numIndexes || indexes == NULL ) + if ( numIndexes < 3 || numBSPDrawIndexes < numIndexes || indexes == NULL ) { return numBSPDrawIndexes; - + } + /* set limit */ numTestIndexes = 1 + numBSPDrawIndexes - numIndexes; - + /* handle 3 indexes as a special case for performance */ - if( numIndexes == 3 ) - { + if ( numIndexes == 3 ) { /* run through all indexes */ - for( i = 0; i < numTestIndexes; i++ ) + for ( i = 0; i < numTestIndexes; i++ ) { /* test 3 indexes */ - if( indexes[ 0 ] == bspDrawIndexes[ i ] && - indexes[ 1 ] == bspDrawIndexes[ i + 1 ] && - indexes[ 2 ] == bspDrawIndexes[ i + 2 ] ) - { + if ( indexes[ 0 ] == bspDrawIndexes[ i ] && + indexes[ 1 ] == bspDrawIndexes[ i + 1 ] && + indexes[ 2 ] == bspDrawIndexes[ i + 2 ] ) { numRedundantIndexes += numIndexes; return i; } } - + /* failed */ return numBSPDrawIndexes; } - + /* handle 4 or more indexes */ - for( i = 0; i < numTestIndexes; i++ ) + for ( i = 0; i < numTestIndexes; i++ ) { /* test first 4 indexes */ - if( indexes[ 0 ] == bspDrawIndexes[ i ] && - indexes[ 1 ] == bspDrawIndexes[ i + 1 ] && - indexes[ 2 ] == bspDrawIndexes[ i + 2 ] && - indexes[ 3 ] == bspDrawIndexes[ i + 3 ] ) - { + if ( indexes[ 0 ] == bspDrawIndexes[ i ] && + indexes[ 1 ] == bspDrawIndexes[ i + 1 ] && + indexes[ 2 ] == bspDrawIndexes[ i + 2 ] && + indexes[ 3 ] == bspDrawIndexes[ i + 3 ] ) { /* handle 4 indexes */ - if( numIndexes == 4 ) + if ( numIndexes == 4 ) { return i; - + } + /* test the remainder */ - for( j = 4; j < numIndexes; j++ ) + for ( j = 4; j < numIndexes; j++ ) { - if( indexes[ j ] != bspDrawIndexes[ i + j ] ) + if ( indexes[ j ] != bspDrawIndexes[ i + j ] ) { break; - else if( j == (numIndexes - 1) ) - { + } + else if ( j == ( numIndexes - 1 ) ) { numRedundantIndexes += numIndexes; return i; } } } } - + /* failed */ return numBSPDrawIndexes; } @@ -2350,41 +2498,36 @@ int FindDrawIndexes( int numIndexes, int *indexes ) /* -EmitDrawIndexes() - ydnar -attempts to find an existing run of drawindexes before adding new ones -*/ - -void EmitDrawIndexes( mapDrawSurface_t *ds, bspDrawSurface_t *out ) -{ - int i; - - + EmitDrawIndexes() - ydnar + attempts to find an existing run of drawindexes before adding new ones + */ + +void EmitDrawIndexes( mapDrawSurface_t *ds, bspDrawSurface_t *out ){ + int i; + + /* attempt to use redundant indexing */ out->firstIndex = FindDrawIndexes( ds->numIndexes, ds->indexes ); out->numIndexes = ds->numIndexes; - if( out->firstIndex == numBSPDrawIndexes ) - { + if ( out->firstIndex == numBSPDrawIndexes ) { /* copy new unique indexes */ - for( i = 0; i < ds->numIndexes; i++ ) + for ( i = 0; i < ds->numIndexes; i++ ) { - if( numBSPDrawIndexes == MAX_MAP_DRAW_INDEXES ) - Error( "MAX_MAP_DRAW_INDEXES" ); + AUTOEXPAND_BY_REALLOC_BSP( DrawIndexes, 1024 ); bspDrawIndexes[ numBSPDrawIndexes ] = ds->indexes[ i ]; /* validate the index */ - if( ds->type != SURFACE_PATCH ) - { - if( bspDrawIndexes[ numBSPDrawIndexes ] < 0 || bspDrawIndexes[ numBSPDrawIndexes ] >= ds->numVerts ) - { - Sys_Printf( "WARNING: %d %s has invalid index %d (%d)\n", - numBSPDrawSurfaces, - ds->shaderInfo->shader, - bspDrawIndexes[ numBSPDrawIndexes ], - i ); + if ( ds->type != SURFACE_PATCH ) { + if ( bspDrawIndexes[ numBSPDrawIndexes ] < 0 || bspDrawIndexes[ numBSPDrawIndexes ] >= ds->numVerts ) { + Sys_FPrintf( SYS_WRN, "WARNING: %d %s has invalid index %d (%d)\n", + numBSPDrawSurfaces, + ds->shaderInfo->shader, + bspDrawIndexes[ numBSPDrawIndexes ], + i ); bspDrawIndexes[ numBSPDrawIndexes ] = 0; } } - + /* increment index count */ numBSPDrawIndexes++; } @@ -2395,39 +2538,41 @@ void EmitDrawIndexes( mapDrawSurface_t *ds, bspDrawSurface_t *out ) /* -EmitFlareSurface() -emits a bsp flare drawsurface -*/ - -void EmitFlareSurface( mapDrawSurface_t *ds ) -{ - int i; - bspDrawSurface_t *out; - - + EmitFlareSurface() + emits a bsp flare drawsurface + */ + +void EmitFlareSurface( mapDrawSurface_t *ds ){ + int i; + bspDrawSurface_t *out; + + /* ydnar: nuking useless flare drawsurfaces */ - if( emitFlares == qfalse && ds->type != SURFACE_SHADER ) + if ( emitFlares == qfalse && ds->type != SURFACE_SHADER ) { return; - + } + /* limit check */ - if( numBSPDrawSurfaces == MAX_MAP_DRAW_SURFS ) + if ( numBSPDrawSurfaces == MAX_MAP_DRAW_SURFS ) { Error( "MAX_MAP_DRAW_SURFS" ); - + } + /* allocate a new surface */ - if( numBSPDrawSurfaces == MAX_MAP_DRAW_SURFS ) + if ( numBSPDrawSurfaces == MAX_MAP_DRAW_SURFS ) { Error( "MAX_MAP_DRAW_SURFS" ); + } out = &bspDrawSurfaces[ numBSPDrawSurfaces ]; ds->outputNum = numBSPDrawSurfaces; numBSPDrawSurfaces++; memset( out, 0, sizeof( *out ) ); - + /* set it up */ out->surfaceType = MST_FLARE; out->shaderNum = EmitShader( ds->shaderInfo->shader, &ds->shaderInfo->contentFlags, &ds->shaderInfo->surfaceFlags ); out->fogNum = ds->fogNum; - + /* RBSP */ - for( i = 0; i < MAX_LIGHTMAPS; i++ ) + for ( i = 0; i < MAX_LIGHTMAPS; i++ ) { out->lightmapNum[ i ] = -3; out->lightmapStyles[ i ] = LS_NONE; @@ -2435,77 +2580,79 @@ void EmitFlareSurface( mapDrawSurface_t *ds ) } out->lightmapStyles[ 0 ] = ds->lightStyle; out->vertexStyles[ 0 ] = ds->lightStyle; - - VectorCopy( ds->lightmapOrigin, out->lightmapOrigin ); /* origin */ - VectorCopy( ds->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] ); /* color */ + + VectorCopy( ds->lightmapOrigin, out->lightmapOrigin ); /* origin */ + VectorCopy( ds->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] ); /* color */ VectorCopy( ds->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] ); - VectorCopy( ds->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] ); /* normal */ - + VectorCopy( ds->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] ); /* normal */ + /* add to count */ numSurfacesByType[ ds->type ]++; } +/* + EmitPatchSurface() + emits a bsp patch drawsurface + */ + +void EmitPatchSurface( entity_t *e, mapDrawSurface_t *ds ){ + int i, j; + bspDrawSurface_t *out; + int surfaceFlags, contentFlags; + int forcePatchMeta; + /* vortex: _patchMeta support */ + forcePatchMeta = IntForKey( e, "_patchMeta" ); + if ( !forcePatchMeta ) { + forcePatchMeta = IntForKey( e, "patchMeta" ); + } -/* -EmitPatchSurface() -emits a bsp patch drawsurface -*/ - -void EmitPatchSurface( mapDrawSurface_t *ds ) -{ - int i, j; - bspDrawSurface_t *out; - int surfaceFlags, contentFlags; - - /* invert the surface if necessary */ - if( ds->backSide || ds->shaderInfo->invert ) - { - bspDrawVert_t *dv1, *dv2, temp; - + if ( ds->backSide || ds->shaderInfo->invert ) { + bspDrawVert_t *dv1, *dv2, temp; /* walk the verts, flip the normal */ - for( i = 0; i < ds->numVerts; i++ ) + for ( i = 0; i < ds->numVerts; i++ ) VectorScale( ds->verts[ i ].normal, -1.0f, ds->verts[ i ].normal ); - + /* walk the verts again, but this time reverse their order */ - for( j = 0; j < ds->patchHeight; j++ ) + for ( j = 0; j < ds->patchHeight; j++ ) { - for( i = 0; i < (ds->patchWidth / 2); i++ ) + for ( i = 0; i < ( ds->patchWidth / 2 ); i++ ) { dv1 = &ds->verts[ j * ds->patchWidth + i ]; - dv2 = &ds->verts[ j * ds->patchWidth + (ds->patchWidth - i - 1) ]; + dv2 = &ds->verts[ j * ds->patchWidth + ( ds->patchWidth - i - 1 ) ]; memcpy( &temp, dv1, sizeof( bspDrawVert_t ) ); memcpy( dv1, dv2, sizeof( bspDrawVert_t ) ); memcpy( dv2, &temp, sizeof( bspDrawVert_t ) ); } } - + /* invert facing */ VectorScale( ds->lightmapVecs[ 2 ], -1.0f, ds->lightmapVecs[ 2 ] ); } - + /* allocate a new surface */ - if( numBSPDrawSurfaces == MAX_MAP_DRAW_SURFS ) + if ( numBSPDrawSurfaces == MAX_MAP_DRAW_SURFS ) { Error( "MAX_MAP_DRAW_SURFS" ); + } out = &bspDrawSurfaces[ numBSPDrawSurfaces ]; ds->outputNum = numBSPDrawSurfaces; numBSPDrawSurfaces++; memset( out, 0, sizeof( *out ) ); - + /* set it up */ out->surfaceType = MST_PATCH; - if( debugSurfaces ) + if ( debugSurfaces ) { out->shaderNum = EmitShader( "debugsurfaces", NULL, NULL ); - else if( patchMeta ) - { + } + else if ( patchMeta || forcePatchMeta ) { /* patch meta requires that we have nodraw patches for collision */ surfaceFlags = ds->shaderInfo->surfaceFlags; contentFlags = ds->shaderInfo->contentFlags; ApplySurfaceParm( "nodraw", &contentFlags, &surfaceFlags, NULL ); ApplySurfaceParm( "pointlight", &contentFlags, &surfaceFlags, NULL ); - + /* we don't want this patch getting lightmapped */ VectorClear( ds->lightmapVecs[ 2 ] ); VectorClear( ds->lightmapAxis ); @@ -2514,14 +2661,15 @@ void EmitPatchSurface( mapDrawSurface_t *ds ) /* emit the new fake shader */ out->shaderNum = EmitShader( ds->shaderInfo->shader, &contentFlags, &surfaceFlags ); } - else + else{ out->shaderNum = EmitShader( ds->shaderInfo->shader, &ds->shaderInfo->contentFlags, &ds->shaderInfo->surfaceFlags ); + } out->patchWidth = ds->patchWidth; out->patchHeight = ds->patchHeight; out->fogNum = ds->fogNum; - + /* RBSP */ - for( i = 0; i < MAX_LIGHTMAPS; i++ ) + for ( i = 0; i < MAX_LIGHTMAPS; i++ ) { out->lightmapNum[ i ] = -3; out->lightmapStyles[ i ] = LS_NONE; @@ -2529,130 +2677,130 @@ void EmitPatchSurface( mapDrawSurface_t *ds ) } out->lightmapStyles[ 0 ] = LS_NORMAL; out->vertexStyles[ 0 ] = LS_NORMAL; - + /* ydnar: gs mods: previously, the lod bounds were stored in lightmapVecs[ 0 ] and [ 1 ], moved to bounds[ 0 ] and [ 1 ] */ VectorCopy( ds->lightmapOrigin, out->lightmapOrigin ); VectorCopy( ds->bounds[ 0 ], out->lightmapVecs[ 0 ] ); VectorCopy( ds->bounds[ 1 ], out->lightmapVecs[ 1 ] ); VectorCopy( ds->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] ); - + /* ydnar: gs mods: clear out the plane normal */ - if( ds->planar == qfalse ) + if ( ds->planar == qfalse ) { VectorClear( out->lightmapVecs[ 2 ] ); - + } + /* emit the verts and indexes */ EmitDrawVerts( ds, out ); EmitDrawIndexes( ds, out ); - + /* add to count */ numSurfacesByType[ ds->type ]++; } +/* + OptimizeTriangleSurface() - ydnar + optimizes the vertex/index data in a triangle surface + */ + +#define VERTEX_CACHE_SIZE 16 + +static void OptimizeTriangleSurface( mapDrawSurface_t *ds ){ + int i, j, k, temp, first, best, bestScore, score; + int vertexCache[ VERTEX_CACHE_SIZE + 1 ]; /* one more for optimizing insert */ + int *indexes; -/* -OptimizeTriangleSurface() - ydnar -optimizes the vertex/index data in a triangle surface -*/ - -#define VERTEX_CACHE_SIZE 16 - -static void OptimizeTriangleSurface( mapDrawSurface_t *ds ) -{ - int i, j, k, temp, first, best, bestScore, score; - int vertexCache[ VERTEX_CACHE_SIZE + 1 ]; /* one more for optimizing insert */ - int *indexes; - - /* certain surfaces don't get optimized */ - if( ds->numIndexes <= VERTEX_CACHE_SIZE || - ds->shaderInfo->autosprite ) + if ( ds->numIndexes <= VERTEX_CACHE_SIZE || + ds->shaderInfo->autosprite ) { return; - + } + /* create index scratch pad */ indexes = safe_malloc( ds->numIndexes * sizeof( *indexes ) ); memcpy( indexes, ds->indexes, ds->numIndexes * sizeof( *indexes ) ); - + /* setup */ - for( i = 0; i <= VERTEX_CACHE_SIZE && i < ds->numIndexes; i++ ) + for ( i = 0; i <= VERTEX_CACHE_SIZE && i < ds->numIndexes; i++ ) vertexCache[ i ] = indexes[ i ]; - + /* add triangles in a vertex cache-aware order */ - for( i = 0; i < ds->numIndexes; i += 3 ) + for ( i = 0; i < ds->numIndexes; i += 3 ) { /* find best triangle given the current vertex cache */ first = -1; best = -1; bestScore = -1; - for( j = 0; j < ds->numIndexes; j += 3 ) + for ( j = 0; j < ds->numIndexes; j += 3 ) { /* valid triangle? */ - if( indexes[ j ] != -1 ) - { + if ( indexes[ j ] != -1 ) { /* set first if necessary */ - if( first < 0 ) + if ( first < 0 ) { first = j; - + } + /* score the triangle */ score = 0; - for( k = 0; k < VERTEX_CACHE_SIZE; k++ ) + for ( k = 0; k < VERTEX_CACHE_SIZE; k++ ) { - if( indexes[ j ] == vertexCache[ k ] || indexes[ j + 1 ] == vertexCache[ k ] || indexes[ j + 2 ] == vertexCache[ k ] ) + if ( indexes[ j ] == vertexCache[ k ] || indexes[ j + 1 ] == vertexCache[ k ] || indexes[ j + 2 ] == vertexCache[ k ] ) { score++; + } } - + /* better triangle? */ - if( score > bestScore ) - { + if ( score > bestScore ) { bestScore = score; best = j; } - + /* a perfect score of 3 means this triangle's verts are already present in the vertex cache */ - if( score == 3 ) + if ( score == 3 ) { break; + } } } - + /* check if no decent triangle was found, and use first available */ - if( best < 0 ) + if ( best < 0 ) { best = first; - + } + /* valid triangle? */ - if( best >= 0 ) - { + if ( best >= 0 ) { /* add triangle to vertex cache */ - for( j = 0; j < 3; j++ ) + for ( j = 0; j < 3; j++ ) { - for( k = 0; k < VERTEX_CACHE_SIZE; k++ ) + for ( k = 0; k < VERTEX_CACHE_SIZE; k++ ) { - if( indexes[ best + j ] == vertexCache[ k ] ) + if ( indexes[ best + j ] == vertexCache[ k ] ) { break; + } } - - if( k >= VERTEX_CACHE_SIZE ) - { + + if ( k >= VERTEX_CACHE_SIZE ) { /* pop off top of vertex cache */ - for( k = VERTEX_CACHE_SIZE; k > 0; k-- ) + for ( k = VERTEX_CACHE_SIZE; k > 0; k-- ) vertexCache[ k ] = vertexCache[ k - 1 ]; - + /* add vertex */ vertexCache[ 0 ] = indexes[ best + j ]; } } - + /* add triangle to surface */ ds->indexes[ i ] = indexes[ best ]; ds->indexes[ i + 1 ] = indexes[ best + 1 ]; ds->indexes[ i + 2 ] = indexes[ best + 2 ]; - + /* clear from input pool */ indexes[ best ] = -1; indexes[ best + 1 ] = -1; indexes[ best + 2 ] = -1; - + /* sort triangle windings (312 -> 123) */ - while( ds->indexes[ i ] > ds->indexes[ i + 1 ] || ds->indexes[ i ] > ds->indexes[ i + 2 ] ) + while ( ds->indexes[ i ] > ds->indexes[ i + 1 ] || ds->indexes[ i ] > ds->indexes[ i + 2 ] ) { temp = ds->indexes[ i ]; ds->indexes[ i ] = ds->indexes[ i + 1 ]; @@ -2661,7 +2809,7 @@ static void OptimizeTriangleSurface( mapDrawSurface_t *ds ) } } } - + /* clean up */ free( indexes ); } @@ -2669,90 +2817,92 @@ static void OptimizeTriangleSurface( mapDrawSurface_t *ds ) /* -EmitTriangleSurface() -creates a bsp drawsurface from arbitrary triangle surfaces -*/ - -static void EmitTriangleSurface( mapDrawSurface_t *ds ) -{ - int i, temp; - bspDrawSurface_t *out; - - + EmitTriangleSurface() + creates a bsp drawsurface from arbitrary triangle surfaces + */ + +void EmitTriangleSurface( mapDrawSurface_t *ds ){ + int i, temp; + bspDrawSurface_t *out; + /* invert the surface if necessary */ - if( ds->backSide || ds->shaderInfo->invert ) - { + if ( ds->backSide || ds->shaderInfo->invert ) { /* walk the indexes, reverse the triangle order */ - for( i = 0; i < ds->numIndexes; i += 3 ) + for ( i = 0; i < ds->numIndexes; i += 3 ) { temp = ds->indexes[ i ]; ds->indexes[ i ] = ds->indexes[ i + 1 ]; ds->indexes[ i + 1 ] = temp; } - + /* walk the verts, flip the normal */ - for( i = 0; i < ds->numVerts; i++ ) + for ( i = 0; i < ds->numVerts; i++ ) VectorScale( ds->verts[ i ].normal, -1.0f, ds->verts[ i ].normal ); - + /* invert facing */ VectorScale( ds->lightmapVecs[ 2 ], -1.0f, ds->lightmapVecs[ 2 ] ); } - + /* allocate a new surface */ - if( numBSPDrawSurfaces == MAX_MAP_DRAW_SURFS ) + if ( numBSPDrawSurfaces == MAX_MAP_DRAW_SURFS ) { Error( "MAX_MAP_DRAW_SURFS" ); + } out = &bspDrawSurfaces[ numBSPDrawSurfaces ]; ds->outputNum = numBSPDrawSurfaces; numBSPDrawSurfaces++; memset( out, 0, sizeof( *out ) ); - + /* ydnar/sd: handle wolf et foliage surfaces */ - if( ds->type == SURFACE_FOLIAGE ) + if ( ds->type == SURFACE_FOLIAGE ) { out->surfaceType = MST_FOLIAGE; - + } + /* ydnar: gs mods: handle lightmapped terrain (force to planar type) */ //% else if( VectorLength( ds->lightmapAxis ) <= 0.0f || ds->type == SURFACE_TRIANGLES || ds->type == SURFACE_FOGHULL || debugSurfaces ) - else if( (VectorLength( ds->lightmapAxis ) <= 0.0f && ds->planar == qfalse) || - ds->type == SURFACE_TRIANGLES || - ds->type == SURFACE_FOGHULL || - ds->numVerts > maxLMSurfaceVerts || - debugSurfaces ) + else if ( ( VectorLength( ds->lightmapAxis ) <= 0.0f && ds->planar == qfalse ) || + ds->type == SURFACE_TRIANGLES || + ds->type == SURFACE_FOGHULL || + ds->numVerts > maxLMSurfaceVerts || + debugSurfaces ) { out->surfaceType = MST_TRIANGLE_SOUP; - + } + /* set to a planar face */ - else + else{ out->surfaceType = MST_PLANAR; - + } + /* set it up */ - if( debugSurfaces ) + if ( debugSurfaces ) { out->shaderNum = EmitShader( "debugsurfaces", NULL, NULL ); - else + } + else{ out->shaderNum = EmitShader( ds->shaderInfo->shader, &ds->shaderInfo->contentFlags, &ds->shaderInfo->surfaceFlags ); + } out->patchWidth = ds->patchWidth; out->patchHeight = ds->patchHeight; out->fogNum = ds->fogNum; - + /* debug inset (push each triangle vertex towards the center of each triangle it is on */ - if( debugInset ) - { - bspDrawVert_t *a, *b, *c; - vec3_t cent, dir; + if ( debugInset ) { + bspDrawVert_t *a, *b, *c; + vec3_t cent, dir; + - /* walk triangle list */ - for( i = 0; i < ds->numIndexes; i += 3 ) + for ( i = 0; i < ds->numIndexes; i += 3 ) { /* get verts */ a = &ds->verts[ ds->indexes[ i ] ]; b = &ds->verts[ ds->indexes[ i + 1 ] ]; c = &ds->verts[ ds->indexes[ i + 2 ] ]; - + /* calculate centroid */ VectorCopy( a->xyz, cent ); VectorAdd( cent, b->xyz, cent ); VectorAdd( cent, c->xyz, cent ); VectorScale( cent, 1.0f / 3.0f, cent ); - + /* offset each vertex */ VectorSubtract( cent, a->xyz, dir ); VectorNormalize( dir, dir ); @@ -2765,9 +2915,9 @@ static void EmitTriangleSurface( mapDrawSurface_t *ds ) VectorAdd( c->xyz, dir, c->xyz ); } } - + /* RBSP */ - for( i = 0; i < MAX_LIGHTMAPS; i++ ) + for ( i = 0; i < MAX_LIGHTMAPS; i++ ) { out->lightmapNum[ i ] = -3; out->lightmapStyles[ i ] = LS_NONE; @@ -2775,24 +2925,25 @@ static void EmitTriangleSurface( mapDrawSurface_t *ds ) } out->lightmapStyles[ 0 ] = LS_NORMAL; out->vertexStyles[ 0 ] = LS_NORMAL; - + /* lightmap vectors (lod bounds for patches */ VectorCopy( ds->lightmapOrigin, out->lightmapOrigin ); VectorCopy( ds->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] ); VectorCopy( ds->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] ); VectorCopy( ds->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] ); - + /* ydnar: gs mods: clear out the plane normal */ - if( ds->planar == qfalse ) + if ( ds->planar == qfalse ) { VectorClear( out->lightmapVecs[ 2 ] ); - + } + /* optimize the surface's triangles */ OptimizeTriangleSurface( ds ); - + /* emit the verts and indexes */ EmitDrawVerts( ds, out ); EmitDrawIndexes( ds, out ); - + /* add to count */ numSurfacesByType[ ds->type ]++; } @@ -2800,63 +2951,66 @@ static void EmitTriangleSurface( mapDrawSurface_t *ds ) /* -EmitFaceSurface() -emits a bsp planar winding (brush face) drawsurface -*/ + EmitFaceSurface() + emits a bsp planar winding (brush face) drawsurface + */ -static void EmitFaceSurface( mapDrawSurface_t *ds ) -{ +static void EmitFaceSurface( mapDrawSurface_t *ds ){ /* strip/fan finding was moved elsewhere */ - StripFaceSurface( ds ); + if ( maxAreaFaceSurface ) { + MaxAreaFaceSurface( ds ); + } + else{ + StripFaceSurface( ds ); + } EmitTriangleSurface( ds ); } - /* -MakeDebugPortalSurfs_r() - ydnar -generates drawsurfaces for passable portals in the bsp -*/ - -static void MakeDebugPortalSurfs_r( node_t *node, shaderInfo_t *si ) -{ - int i, k, c, s; - portal_t *p; - winding_t *w; - mapDrawSurface_t *ds; - bspDrawVert_t *dv; - - + MakeDebugPortalSurfs_r() - ydnar + generates drawsurfaces for passable portals in the bsp + */ + +static void MakeDebugPortalSurfs_r( node_t *node, shaderInfo_t *si ){ + int i, k, c, s; + portal_t *p; + winding_t *w; + mapDrawSurface_t *ds; + bspDrawVert_t *dv; + + /* recurse if decision node */ - if( node->planenum != PLANENUM_LEAF) - { + if ( node->planenum != PLANENUM_LEAF ) { MakeDebugPortalSurfs_r( node->children[ 0 ], si ); MakeDebugPortalSurfs_r( node->children[ 1 ], si ); return; } - + /* don't bother with opaque leaves */ - if( node->opaque ) + if ( node->opaque ) { return; - + } + /* walk the list of portals */ - for( c = 0, p = node->portals; p != NULL; c++, p = p->next[ s ] ) + for ( c = 0, p = node->portals; p != NULL; c++, p = p->next[ s ] ) { /* get winding and side even/odd */ w = p->winding; - s = (p->nodes[ 1 ] == node); - + s = ( p->nodes[ 1 ] == node ); + /* is this a valid portal for this leaf? */ - if( w && p->nodes[ 0 ] == node ) - { + if ( w && p->nodes[ 0 ] == node ) { /* is this portal passable? */ - if( PortalPassable( p ) == qfalse ) + if ( PortalPassable( p ) == qfalse ) { continue; - + } + /* check max points */ - if( w->numpoints > 64 ) + if ( w->numpoints > 64 ) { Error( "MakePortalSurfs_r: w->numpoints = %d", w->numpoints ); - + } + /* allocate a drawsurface */ ds = AllocDrawSurface( SURFACE_FACE ); ds->shaderInfo = si; @@ -2868,19 +3022,19 @@ static void MakeDebugPortalSurfs_r( node_t *node, shaderInfo_t *si ) ds->numVerts = w->numpoints; ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) ); memset( ds->verts, 0, ds->numVerts * sizeof( *ds->verts ) ); - + /* walk the winding */ - for( i = 0; i < ds->numVerts; i++ ) + for ( i = 0; i < ds->numVerts; i++ ) { /* get vert */ dv = ds->verts + i; - + /* set it */ VectorCopy( w->p[ i ], dv->xyz ); VectorCopy( p->plane.normal, dv->normal ); dv->st[ 0 ] = 0; dv->st[ 1 ] = 0; - for( k = 0; k < MAX_LIGHTMAPS; k++ ) + for ( k = 0; k < MAX_LIGHTMAPS; k++ ) { VectorCopy( debugColors[ c % 12 ], dv->color[ k ] ); dv->color[ k ][ 3 ] = 32; @@ -2893,21 +3047,20 @@ static void MakeDebugPortalSurfs_r( node_t *node, shaderInfo_t *si ) /* -MakeDebugPortalSurfs() - ydnar -generates drawsurfaces for passable portals in the bsp -*/ - -void MakeDebugPortalSurfs( tree_t *tree ) -{ - shaderInfo_t *si; - - + MakeDebugPortalSurfs() - ydnar + generates drawsurfaces for passable portals in the bsp + */ + +void MakeDebugPortalSurfs( tree_t *tree ){ + shaderInfo_t *si; + + /* note it */ Sys_FPrintf( SYS_VRB, "--- MakeDebugPortalSurfs ---\n" ); - + /* get portal debug shader */ si = ShaderInfoForShader( "debugportals" ); - + /* walk the tree */ MakeDebugPortalSurfs_r( tree->headnode, si ); } @@ -2915,45 +3068,45 @@ void MakeDebugPortalSurfs( tree_t *tree ) /* -MakeFogHullSurfs() -generates drawsurfaces for a foghull (this MUST use a sky shader) -*/ - -void MakeFogHullSurfs( entity_t *e, tree_t *tree, char *shader ) -{ - shaderInfo_t *si; - mapDrawSurface_t *ds; - vec3_t fogMins, fogMaxs; - int i, indexes[] = - { - 0, 1, 2, 0, 2, 3, - 4, 7, 5, 5, 7, 6, - 1, 5, 6, 1, 6, 2, - 0, 4, 5, 0, 5, 1, - 2, 6, 7, 2, 7, 3, - 3, 7, 4, 3, 4, 0 - }; - - + MakeFogHullSurfs() + generates drawsurfaces for a foghull (this MUST use a sky shader) + */ + +void MakeFogHullSurfs( entity_t *e, tree_t *tree, char *shader ){ + shaderInfo_t *si; + mapDrawSurface_t *ds; + vec3_t fogMins, fogMaxs; + int i, indexes[] = + { + 0, 1, 2, 0, 2, 3, + 4, 7, 5, 5, 7, 6, + 1, 5, 6, 1, 6, 2, + 0, 4, 5, 0, 5, 1, + 2, 6, 7, 2, 7, 3, + 3, 7, 4, 3, 4, 0 + }; + + /* dummy check */ - if( shader == NULL || shader[ 0 ] == '\0' ) + if ( shader == NULL || shader[ 0 ] == '\0' ) { return; - + } + /* note it */ Sys_FPrintf( SYS_VRB, "--- MakeFogHullSurfs ---\n" ); - + /* get hull bounds */ VectorCopy( mapMins, fogMins ); VectorCopy( mapMaxs, fogMaxs ); - for( i = 0; i < 3; i++ ) + for ( i = 0; i < 3; i++ ) { fogMins[ i ] -= 128; fogMaxs[ i ] += 128; } - + /* get foghull shader */ si = ShaderInfoForShader( shader ); - + /* allocate a drawsurface */ ds = AllocDrawSurface( SURFACE_FOGHULL ); ds->shaderInfo = si; @@ -2964,18 +3117,18 @@ void MakeFogHullSurfs( entity_t *e, tree_t *tree, char *shader ) ds->numIndexes = 36; ds->indexes = safe_malloc( ds->numIndexes * sizeof( *ds->indexes ) ); memset( ds->indexes, 0, ds->numIndexes * sizeof( *ds->indexes ) ); - + /* set verts */ VectorSet( ds->verts[ 0 ].xyz, fogMins[ 0 ], fogMins[ 1 ], fogMins[ 2 ] ); VectorSet( ds->verts[ 1 ].xyz, fogMins[ 0 ], fogMaxs[ 1 ], fogMins[ 2 ] ); VectorSet( ds->verts[ 2 ].xyz, fogMaxs[ 0 ], fogMaxs[ 1 ], fogMins[ 2 ] ); VectorSet( ds->verts[ 3 ].xyz, fogMaxs[ 0 ], fogMins[ 1 ], fogMins[ 2 ] ); - + VectorSet( ds->verts[ 4 ].xyz, fogMins[ 0 ], fogMins[ 1 ], fogMaxs[ 2 ] ); VectorSet( ds->verts[ 5 ].xyz, fogMins[ 0 ], fogMaxs[ 1 ], fogMaxs[ 2 ] ); VectorSet( ds->verts[ 6 ].xyz, fogMaxs[ 0 ], fogMaxs[ 1 ], fogMaxs[ 2 ] ); VectorSet( ds->verts[ 7 ].xyz, fogMaxs[ 0 ], fogMins[ 1 ], fogMaxs[ 2 ] ); - + /* set indexes */ memcpy( ds->indexes, indexes, ds->numIndexes * sizeof( *ds->indexes ) ); } @@ -2983,24 +3136,24 @@ void MakeFogHullSurfs( entity_t *e, tree_t *tree, char *shader ) /* -BiasSurfaceTextures() -biases a surface's texcoords as close to 0 as possible -*/ - -void BiasSurfaceTextures( mapDrawSurface_t *ds ) -{ - int i; - - + BiasSurfaceTextures() + biases a surface's texcoords as close to 0 as possible + */ + +void BiasSurfaceTextures( mapDrawSurface_t *ds ){ + int i; + + /* calculate the surface texture bias */ CalcSurfaceTextureRange( ds ); - + /* don't bias globaltextured shaders */ - if( ds->shaderInfo->globalTexture ) + if ( ds->shaderInfo->globalTexture ) { return; - + } + /* bias the texture coordinates */ - for( i = 0; i < ds->numVerts; i++ ) + for ( i = 0; i < ds->numVerts; i++ ) { ds->verts[ i ].st[ 0 ] += ds->bias[ 0 ]; ds->verts[ i ].st[ 1 ] += ds->bias[ 1 ]; @@ -3010,150 +3163,150 @@ void BiasSurfaceTextures( mapDrawSurface_t *ds ) /* -AddSurfaceModelsToTriangle_r() -adds models to a specified triangle, returns the number of models added -*/ - -int AddSurfaceModelsToTriangle_r( mapDrawSurface_t *ds, surfaceModel_t *model, bspDrawVert_t **tri ) -{ - bspDrawVert_t mid, *tri2[ 3 ]; - int max, n, localNumSurfaceModels; - - + AddSurfaceModelsToTriangle_r() + adds models to a specified triangle, returns the number of models added + */ + +int AddSurfaceModelsToTriangle_r( mapDrawSurface_t *ds, surfaceModel_t *model, bspDrawVert_t **tri ){ + bspDrawVert_t mid, *tri2[ 3 ]; + int max, n, localNumSurfaceModels; + + /* init */ localNumSurfaceModels = 0; - + /* subdivide calc */ { - int i; - float *a, *b, dx, dy, dz, dist, maxDist; - - + int i; + float *a, *b, dx, dy, dz, dist, maxDist; + + /* find the longest edge and split it */ max = -1; maxDist = 0.0f; - for( i = 0; i < 3; i++ ) + for ( i = 0; i < 3; i++ ) { /* get verts */ a = tri[ i ]->xyz; - b = tri[ (i + 1) % 3 ]->xyz; - + b = tri[ ( i + 1 ) % 3 ]->xyz; + /* get dists */ dx = a[ 0 ] - b[ 0 ]; dy = a[ 1 ] - b[ 1 ]; dz = a[ 2 ] - b[ 2 ]; - dist = (dx * dx) + (dy * dy) + (dz * dz); - + dist = ( dx * dx ) + ( dy * dy ) + ( dz * dz ); + /* longer? */ - if( dist > maxDist ) - { + if ( dist > maxDist ) { maxDist = dist; max = i; } } - + /* is the triangle small enough? */ - if( max < 0 || maxDist <= (model->density * model->density) ) - { - float odds, r, angle; - vec3_t origin, normal, scale, axis[ 3 ], angles; - m4x4_t transform, temp; + if ( max < 0 || maxDist <= ( model->density * model->density ) ) { + float odds, r, angle; + vec3_t origin, normal, scale, axis[ 3 ], angles; + m4x4_t transform, temp; + - /* roll the dice (model's odds scaled by vertex alpha) */ - odds = model->odds * (tri[ 0 ]->color[ 0 ][ 3 ] + tri[ 0 ]->color[ 0 ][ 3 ] + tri[ 0 ]->color[ 0 ][ 3 ]) / 765.0f; + odds = model->odds * ( tri[ 0 ]->color[ 0 ][ 3 ] + tri[ 0 ]->color[ 0 ][ 3 ] + tri[ 0 ]->color[ 0 ][ 3 ] ) / 765.0f; r = Random(); - if( r > model->odds ) + if ( r > odds ) { return 0; - + } + /* calculate scale */ - r = model->minScale + Random() * (model->maxScale - model->minScale); + r = model->minScale + Random() * ( model->maxScale - model->minScale ); VectorSet( scale, r, r, r ); - + /* calculate angle */ - angle = model->minAngle + Random() * (model->maxAngle - model->minAngle); - + angle = model->minAngle + Random() * ( model->maxAngle - model->minAngle ); + /* calculate average origin */ VectorCopy( tri[ 0 ]->xyz, origin ); VectorAdd( origin, tri[ 1 ]->xyz, origin ); VectorAdd( origin, tri[ 2 ]->xyz, origin ); - VectorScale( origin, (1.0f / 3.0f), origin ); - + VectorScale( origin, ( 1.0f / 3.0f ), origin ); + /* clear transform matrix */ m4x4_identity( transform ); /* handle oriented models */ - if( model->oriented ) - { + if ( model->oriented ) { /* set angles */ VectorSet( angles, 0.0f, 0.0f, angle ); - + /* calculate average normal */ VectorCopy( tri[ 0 ]->normal, normal ); VectorAdd( normal, tri[ 1 ]->normal, normal ); VectorAdd( normal, tri[ 2 ]->normal, normal ); - if( VectorNormalize( normal, axis[ 2 ] ) == 0.0f ) + if ( VectorNormalize( normal, axis[ 2 ] ) == 0.0f ) { VectorCopy( tri[ 0 ]->normal, axis[ 2 ] ); - + } + /* make perpendicular vectors */ MakeNormalVectors( axis[ 2 ], axis[ 1 ], axis[ 0 ] ); - + /* copy to matrix */ m4x4_identity( temp ); - temp[ 0 ] = axis[ 0 ][ 0 ]; temp[ 1 ] = axis[ 0 ][ 1 ]; temp[ 2 ] = axis[ 0 ][ 2 ]; - temp[ 4 ] = axis[ 1 ][ 0 ]; temp[ 5 ] = axis[ 1 ][ 1 ]; temp[ 6 ] = axis[ 1 ][ 2 ]; - temp[ 8 ] = axis[ 2 ][ 0 ]; temp[ 9 ] = axis[ 2 ][ 1 ]; temp[ 10 ] = axis[ 2 ][ 2 ]; - + temp[ 0 ] = axis[ 0 ][ 0 ]; temp[ 1 ] = axis[ 0 ][ 1 ]; temp[ 2 ] = axis[ 0 ][ 2 ]; + temp[ 4 ] = axis[ 1 ][ 0 ]; temp[ 5 ] = axis[ 1 ][ 1 ]; temp[ 6 ] = axis[ 1 ][ 2 ]; + temp[ 8 ] = axis[ 2 ][ 0 ]; temp[ 9 ] = axis[ 2 ][ 1 ]; temp[ 10 ] = axis[ 2 ][ 2 ]; + /* scale */ m4x4_scale_by_vec3( temp, scale ); - + /* rotate around z axis */ m4x4_rotate_by_vec3( temp, angles, eXYZ ); - + /* translate */ m4x4_translate_by_vec3( transform, origin ); - + /* tranform into axis space */ m4x4_multiply_by_m4x4( transform, temp ); } - + /* handle z-up models */ else { /* set angles */ VectorSet( angles, 0.0f, 0.0f, angle ); - + /* set matrix */ m4x4_pivoted_transform_by_vec3( transform, origin, angles, eXYZ, scale, vec3_origin ); } - + /* insert the model */ - InsertModel( (char *) model->model, 0, transform, NULL, ds->celShader, ds->entityNum, ds->castShadows, ds->recvShadows, 0, ds->lightmapScale ); - + InsertModel( (char *) model->model, 0, 0, transform, NULL, ds->celShader, ds->entityNum, ds->castShadows, ds->recvShadows, 0, ds->lightmapScale, 0, 0 ); + /* return to sender */ return 1; } } - + /* split the longest edge and map it */ - LerpDrawVert( tri[ max ], tri[ (max + 1) % 3 ], &mid ); - + LerpDrawVert( tri[ max ], tri[ ( max + 1 ) % 3 ], &mid ); + /* recurse to first triangle */ VectorCopy( tri, tri2 ); tri2[ max ] = ∣ n = AddSurfaceModelsToTriangle_r( ds, model, tri2 ); - if( n < 0 ) + if ( n < 0 ) { return n; + } localNumSurfaceModels += n; - + /* recurse to second triangle */ VectorCopy( tri, tri2 ); - tri2[ (max + 1) % 3 ] = ∣ + tri2[ ( max + 1 ) % 3 ] = ∣ n = AddSurfaceModelsToTriangle_r( ds, model, tri2 ); - if( n < 0 ) + if ( n < 0 ) { return n; + } localNumSurfaceModels += n; - + /* return count */ return localNumSurfaceModels; } @@ -3161,158 +3314,163 @@ int AddSurfaceModelsToTriangle_r( mapDrawSurface_t *ds, surfaceModel_t *model, b /* -AddSurfaceModels() -adds a surface's shader models to the surface -*/ - -int AddSurfaceModels( mapDrawSurface_t *ds ) -{ - surfaceModel_t *model; - int i, x, y, n, pw[ 5 ], r, localNumSurfaceModels, iterations; - mesh_t src, *mesh, *subdivided; - bspDrawVert_t centroid, *tri[ 3 ]; - float alpha; - - + AddSurfaceModels() + adds a surface's shader models to the surface + */ + +int AddSurfaceModels( mapDrawSurface_t *ds ){ + surfaceModel_t *model; + int i, x, y, n, pw[ 5 ], r, localNumSurfaceModels, iterations; + mesh_t src, *mesh, *subdivided; + bspDrawVert_t centroid, *tri[ 3 ]; + float alpha; + + /* dummy check */ - if( ds == NULL || ds->shaderInfo == NULL || ds->shaderInfo->surfaceModel == NULL ) + if ( ds == NULL || ds->shaderInfo == NULL || ds->shaderInfo->surfaceModel == NULL ) { return 0; - + } + /* init */ localNumSurfaceModels = 0; - + /* walk the model list */ - for( model = ds->shaderInfo->surfaceModel; model != NULL; model = model->next ) + for ( model = ds->shaderInfo->surfaceModel; model != NULL; model = model->next ) { /* switch on type */ - switch( ds->type ) + switch ( ds->type ) { - /* handle brush faces and decals */ - case SURFACE_FACE: - case SURFACE_DECAL: - /* calculate centroid */ - memset( ¢roid, 0, sizeof( centroid ) ); - alpha = 0.0f; - - /* walk verts */ - for( i = 0; i < ds->numVerts; i++ ) - { - VectorAdd( centroid.xyz, ds->verts[ i ].xyz, centroid.xyz ); - VectorAdd( centroid.normal, ds->verts[ i ].normal, centroid.normal ); - centroid.st[ 0 ] += ds->verts[ i ].st[ 0 ]; - centroid.st[ 1 ] += ds->verts[ i ].st[ 1 ]; - alpha += ds->verts[ i ].color[ 0 ][ 3 ]; + /* handle brush faces and decals */ + case SURFACE_FACE: + case SURFACE_DECAL: + /* calculate centroid */ + memset( ¢roid, 0, sizeof( centroid ) ); + alpha = 0.0f; + + /* walk verts */ + for ( i = 0; i < ds->numVerts; i++ ) + { + VectorAdd( centroid.xyz, ds->verts[ i ].xyz, centroid.xyz ); + VectorAdd( centroid.normal, ds->verts[ i ].normal, centroid.normal ); + centroid.st[ 0 ] += ds->verts[ i ].st[ 0 ]; + centroid.st[ 1 ] += ds->verts[ i ].st[ 1 ]; + alpha += ds->verts[ i ].color[ 0 ][ 3 ]; + } + + /* average */ + centroid.xyz[ 0 ] /= ds->numVerts; + centroid.xyz[ 1 ] /= ds->numVerts; + centroid.xyz[ 2 ] /= ds->numVerts; + if ( VectorNormalize( centroid.normal, centroid.normal ) == 0.0f ) { + VectorCopy( ds->verts[ 0 ].normal, centroid.normal ); + } + centroid.st[ 0 ] /= ds->numVerts; + centroid.st[ 1 ] /= ds->numVerts; + alpha /= ds->numVerts; + centroid.color[ 0 ][ 0 ] = 0xFF; + centroid.color[ 0 ][ 1 ] = 0xFF; + centroid.color[ 0 ][ 2 ] = 0xFF; + centroid.color[ 0 ][ 2 ] = ( alpha > 255.0f ? 0xFF : alpha ); + + /* head vert is centroid */ + tri[ 0 ] = ¢roid; + + /* walk fanned triangles */ + for ( i = 0; i < ds->numVerts; i++ ) + { + /* set triangle */ + tri[ 1 ] = &ds->verts[ i ]; + tri[ 2 ] = &ds->verts[ ( i + 1 ) % ds->numVerts ]; + + /* create models */ + n = AddSurfaceModelsToTriangle_r( ds, model, tri ); + if ( n < 0 ) { + return n; } - - /* average */ - centroid.xyz[ 0 ] /= ds->numVerts; - centroid.xyz[ 1 ] /= ds->numVerts; - centroid.xyz[ 2 ] /= ds->numVerts; - if( VectorNormalize( centroid.normal, centroid.normal ) == 0.0f ) - VectorCopy( ds->verts[ 0 ].normal, centroid.normal ); - centroid.st[ 0 ] /= ds->numVerts; - centroid.st[ 1 ] /= ds->numVerts; - alpha /= ds->numVerts; - centroid.color[ 0 ][ 0 ] = 0xFF; - centroid.color[ 0 ][ 1 ] = 0xFF; - centroid.color[ 0 ][ 2 ] = 0xFF; - centroid.color[ 0 ][ 2 ] = (alpha > 255.0f ? 0xFF : alpha); - - /* head vert is centroid */ - tri[ 0 ] = ¢roid; - - /* walk fanned triangles */ - for( i = 0; i < ds->numVerts; i++ ) + localNumSurfaceModels += n; + } + break; + + /* handle patches */ + case SURFACE_PATCH: + /* subdivide the surface */ + src.width = ds->patchWidth; + src.height = ds->patchHeight; + src.verts = ds->verts; + //% subdivided = SubdivideMesh( src, 8.0f, 512 ); + iterations = IterationsForCurve( ds->longestCurve, patchSubdivisions ); + subdivided = SubdivideMesh2( src, iterations ); + + /* fit it to the curve and remove colinear verts on rows/columns */ + PutMeshOnCurve( *subdivided ); + mesh = RemoveLinearMeshColumnsRows( subdivided ); + FreeMesh( subdivided ); + + /* subdivide each quad to place the models */ + for ( y = 0; y < ( mesh->height - 1 ); y++ ) + { + for ( x = 0; x < ( mesh->width - 1 ); x++ ) { - /* set triangle */ - tri[ 1 ] = &ds->verts[ i ]; - tri[ 2 ] = &ds->verts[ (i + 1) % ds->numVerts ]; - - /* create models */ + /* set indexes */ + pw[ 0 ] = x + ( y * mesh->width ); + pw[ 1 ] = x + ( ( y + 1 ) * mesh->width ); + pw[ 2 ] = x + 1 + ( ( y + 1 ) * mesh->width ); + pw[ 3 ] = x + 1 + ( y * mesh->width ); + pw[ 4 ] = x + ( y * mesh->width ); /* same as pw[ 0 ] */ + + /* set radix */ + r = ( x + y ) & 1; + + /* triangle 1 */ + tri[ 0 ] = &mesh->verts[ pw[ r + 0 ] ]; + tri[ 1 ] = &mesh->verts[ pw[ r + 1 ] ]; + tri[ 2 ] = &mesh->verts[ pw[ r + 2 ] ]; n = AddSurfaceModelsToTriangle_r( ds, model, tri ); - if( n < 0 ) + if ( n < 0 ) { return n; - localNumSurfaceModels += n; - } - break; - - /* handle patches */ - case SURFACE_PATCH: - /* subdivide the surface */ - src.width = ds->patchWidth; - src.height = ds->patchHeight; - src.verts = ds->verts; - //% subdivided = SubdivideMesh( src, 8.0f, 512 ); - iterations = IterationsForCurve( ds->longestCurve, patchSubdivisions ); - subdivided = SubdivideMesh2( src, iterations ); - - /* fit it to the curve and remove colinear verts on rows/columns */ - PutMeshOnCurve( *subdivided ); - mesh = RemoveLinearMeshColumnsRows( subdivided ); - FreeMesh( subdivided ); - - /* subdivide each quad to place the models */ - for( y = 0; y < (mesh->height - 1); y++ ) - { - for( x = 0; x < (mesh->width - 1); x++ ) - { - /* set indexes */ - pw[ 0 ] = x + (y * mesh->width); - pw[ 1 ] = x + ((y + 1) * mesh->width); - pw[ 2 ] = x + 1 + ((y + 1) * mesh->width); - pw[ 3 ] = x + 1 + (y * mesh->width); - pw[ 4 ] = x + (y * mesh->width); /* same as pw[ 0 ] */ - - /* set radix */ - r = (x + y) & 1; - - /* triangle 1 */ - tri[ 0 ] = &mesh->verts[ pw[ r + 0 ] ]; - tri[ 1 ] = &mesh->verts[ pw[ r + 1 ] ]; - tri[ 2 ] = &mesh->verts[ pw[ r + 2 ] ]; - n = AddSurfaceModelsToTriangle_r( ds, model, tri ); - if( n < 0 ) - return n; - localNumSurfaceModels += n; - - /* triangle 2 */ - tri[ 0 ] = &mesh->verts[ pw[ r + 0 ] ]; - tri[ 1 ] = &mesh->verts[ pw[ r + 2 ] ]; - tri[ 2 ] = &mesh->verts[ pw[ r + 3 ] ]; - n = AddSurfaceModelsToTriangle_r( ds, model, tri ); - if( n < 0 ) - return n; - localNumSurfaceModels += n; } - } - - /* free the subdivided mesh */ - FreeMesh( mesh ); - break; - - /* handle triangle surfaces */ - case SURFACE_TRIANGLES: - case SURFACE_FORCED_META: - case SURFACE_META: - /* walk the triangle list */ - for( i = 0; i < ds->numIndexes; i += 3 ) - { - tri[ 0 ] = &ds->verts[ ds->indexes[ i ] ]; - tri[ 1 ] = &ds->verts[ ds->indexes[ i + 1 ] ]; - tri[ 2 ] = &ds->verts[ ds->indexes[ i + 2 ] ]; + localNumSurfaceModels += n; + + /* triangle 2 */ + tri[ 0 ] = &mesh->verts[ pw[ r + 0 ] ]; + tri[ 1 ] = &mesh->verts[ pw[ r + 2 ] ]; + tri[ 2 ] = &mesh->verts[ pw[ r + 3 ] ]; n = AddSurfaceModelsToTriangle_r( ds, model, tri ); - if( n < 0 ) + if ( n < 0 ) { return n; + } localNumSurfaceModels += n; } - break; - - /* no support for flares, foghull, etc */ - default: - break; + } + + /* free the subdivided mesh */ + FreeMesh( mesh ); + break; + + /* handle triangle surfaces */ + case SURFACE_TRIANGLES: + case SURFACE_FORCED_META: + case SURFACE_META: + /* walk the triangle list */ + for ( i = 0; i < ds->numIndexes; i += 3 ) + { + tri[ 0 ] = &ds->verts[ ds->indexes[ i ] ]; + tri[ 1 ] = &ds->verts[ ds->indexes[ i + 1 ] ]; + tri[ 2 ] = &ds->verts[ ds->indexes[ i + 2 ] ]; + n = AddSurfaceModelsToTriangle_r( ds, model, tri ); + if ( n < 0 ) { + return n; + } + localNumSurfaceModels += n; + } + break; + + /* no support for flares, foghull, etc */ + default: + break; } } - + /* return count */ return localNumSurfaceModels; } @@ -3320,71 +3478,74 @@ int AddSurfaceModels( mapDrawSurface_t *ds ) /* -AddEntitySurfaceModels() - ydnar -adds surfacemodels to an entity's surfaces -*/ - -void AddEntitySurfaceModels( entity_t *e ) -{ - int i; - - + AddEntitySurfaceModels() - ydnar + adds surfacemodels to an entity's surfaces + */ + +void AddEntitySurfaceModels( entity_t *e ){ + int i; + + /* note it */ Sys_FPrintf( SYS_VRB, "--- AddEntitySurfaceModels ---\n" ); - + /* walk the surface list */ - for( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ ) + for ( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ ) numSurfaceModels += AddSurfaceModels( &mapDrawSurfs[ i ] ); } /* -VolumeColorMods() - ydnar -applies brush/volumetric color/alpha modulation to vertexes -*/ - -static void VolumeColorMods( entity_t *e, mapDrawSurface_t *ds ) -{ - int i, j; - float d; - brush_t *b; - plane_t *plane; - - + VolumeColorMods() - ydnar + applies brush/volumetric color/alpha modulation to vertexes + */ + +static void VolumeColorMods( entity_t *e, mapDrawSurface_t *ds ){ + int i, j; + float d; + brush_t *b; + plane_t *plane; + + /* early out */ - if( e->colorModBrushes == NULL ) + if ( e->colorModBrushes == NULL ) { return; - + } + /* iterate brushes */ - for( b = e->colorModBrushes; b != NULL; b = b->nextColorModBrush ) + for ( b = e->colorModBrushes; b != NULL; b = b->nextColorModBrush ) { /* worldspawn alpha brushes affect all, grouped ones only affect original entity */ - if( b->entityNum != 0 && b->entityNum != ds->entityNum ) + if ( b->entityNum != 0 && b->entityNum != ds->entityNum ) { continue; - + } + /* test bbox */ - if( b->mins[ 0 ] > ds->maxs[ 0 ] || b->maxs[ 0 ] < ds->mins[ 0 ] || - b->mins[ 1 ] > ds->maxs[ 1 ] || b->maxs[ 1 ] < ds->mins[ 1 ] || - b->mins[ 2 ] > ds->maxs[ 2 ] || b->maxs[ 2 ] < ds->mins[ 2 ] ) + if ( b->mins[ 0 ] > ds->maxs[ 0 ] || b->maxs[ 0 ] < ds->mins[ 0 ] || + b->mins[ 1 ] > ds->maxs[ 1 ] || b->maxs[ 1 ] < ds->mins[ 1 ] || + b->mins[ 2 ] > ds->maxs[ 2 ] || b->maxs[ 2 ] < ds->mins[ 2 ] ) { continue; - + } + /* iterate verts */ - for( i = 0; i < ds->numVerts; i++ ) + for ( i = 0; i < ds->numVerts; i++ ) { /* iterate planes */ - for( j = 0; j < b->numsides; j++ ) + for ( j = 0; j < b->numsides; j++ ) { /* point-plane test */ plane = &mapplanes[ b->sides[ j ].planenum ]; d = DotProduct( ds->verts[ i ].xyz, plane->normal ) - plane->dist; - if( d > 1.0f ) + if ( d > 1.0f ) { break; + } } - + /* apply colormods */ - if( j == b->numsides ) + if ( j == b->numsides ) { ColorMod( b->contentShader->colorMod, 1, &ds->verts[ i ] ); + } } } } @@ -3392,211 +3553,231 @@ static void VolumeColorMods( entity_t *e, mapDrawSurface_t *ds ) /* -FilterDrawsurfsIntoTree() -upon completion, all drawsurfs that actually generate a reference -will have been emited to the bspfile arrays, and the references -will have valid final indexes -*/ - -void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree ) -{ - int i, j; - mapDrawSurface_t *ds; - shaderInfo_t *si; - vec3_t origin, mins, maxs; - int refs; - int numSurfs, numRefs, numSkyboxSurfaces; - - + FilterDrawsurfsIntoTree() + upon completion, all drawsurfs that actually generate a reference + will have been emited to the bspfile arrays, and the references + will have valid final indexes + */ + +void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree ){ + int i, j; + mapDrawSurface_t *ds; + shaderInfo_t *si; + vec3_t origin, mins, maxs; + int refs; + int numSurfs, numRefs, numSkyboxSurfaces; + qboolean sb; + + /* note it */ Sys_FPrintf( SYS_VRB, "--- FilterDrawsurfsIntoTree ---\n" ); - + /* filter surfaces into the tree */ numSurfs = 0; numRefs = 0; numSkyboxSurfaces = 0; - for( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ ) + for ( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ ) { /* get surface and try to early out */ ds = &mapDrawSurfs[ i ]; - if( ds->numVerts == 0 && ds->type != SURFACE_FLARE && ds->type != SURFACE_SHADER ) + if ( ds->numVerts == 0 && ds->type != SURFACE_FLARE && ds->type != SURFACE_SHADER ) { continue; - + } + /* get shader */ si = ds->shaderInfo; - + /* ydnar: skybox surfaces are special */ - if( ds->skybox ) - { + if ( ds->skybox ) { refs = AddReferenceToTree_r( ds, tree->headnode, qtrue ); ds->skybox = qfalse; + sb = qtrue; } else { + sb = qfalse; + /* refs initially zero */ refs = 0; - + /* apply texture coordinate mods */ - for( j = 0; j < ds->numVerts; j++ ) + for ( j = 0; j < ds->numVerts; j++ ) TCMod( si->mod, ds->verts[ j ].st ); - + /* ydnar: apply shader colormod */ ColorMod( ds->shaderInfo->colorMod, ds->numVerts, ds->verts ); - + /* ydnar: apply brush colormod */ VolumeColorMods( e, ds ); - + /* ydnar: make fur surfaces */ - if( si->furNumLayers > 0 ) + if ( si->furNumLayers > 0 ) { Fur( ds ); - + } + /* ydnar/sd: make foliage surfaces */ - if( si->foliage != NULL ) + if ( si->foliage != NULL ) { Foliage( ds ); - + } + /* create a flare surface if necessary */ - if( si->flareShader != NULL && si->flareShader[ 0 ] ) + if ( si->flareShader != NULL && si->flareShader[ 0 ] ) { AddSurfaceFlare( ds, e->origin ); - + } + /* ydnar: don't emit nodraw surfaces (like nodraw fog) */ - if( si != NULL && (si->compileFlags & C_NODRAW) && ds->type != SURFACE_PATCH ) + if ( ( si->compileFlags & C_NODRAW ) && ds->type != SURFACE_PATCH ) { continue; - + } + /* ydnar: bias the surface textures */ BiasSurfaceTextures( ds ); - + /* ydnar: globalizing of fog volume handling (eek a hack) */ - if( e != entities && si->noFog == qfalse ) - { + if ( e != entities && si->noFog == qfalse ) { /* find surface origin and offset by entity origin */ VectorAdd( ds->mins, ds->maxs, origin ); VectorScale( origin, 0.5f, origin ); VectorAdd( origin, e->origin, origin ); - + VectorAdd( ds->mins, e->origin, mins ); VectorAdd( ds->maxs, e->origin, maxs ); - + /* set the fog number for this surface */ - ds->fogNum = FogForBounds( mins, maxs, 1.0f ); //% FogForPoint( origin, 0.0f ); + ds->fogNum = FogForBounds( mins, maxs, 1.0f ); //% FogForPoint( origin, 0.0f ); } } - + /* ydnar: remap shader */ - if( ds->shaderInfo->remapShader && ds->shaderInfo->remapShader[ 0 ] ) + if ( ds->shaderInfo->remapShader && ds->shaderInfo->remapShader[ 0 ] ) { ds->shaderInfo = ShaderInfoForShader( ds->shaderInfo->remapShader ); - + } + /* ydnar: gs mods: handle the various types of surfaces */ - switch( ds->type ) + switch ( ds->type ) { - /* handle brush faces */ - case SURFACE_FACE: - case SURFACE_DECAL: - if( refs == 0 ) - refs = FilterFaceIntoTree( ds, tree ); - if( refs > 0 ) - EmitFaceSurface( ds ); - break; - - /* handle patches */ - case SURFACE_PATCH: - if( refs == 0 ) - refs = FilterPatchIntoTree( ds, tree ); - if( refs > 0 ) - EmitPatchSurface( ds ); - break; - - /* handle triangle surfaces */ - case SURFACE_TRIANGLES: - case SURFACE_FORCED_META: - case SURFACE_META: - //% Sys_FPrintf( SYS_VRB, "Surface %4d: [%1d] %4d verts %s\n", numSurfs, ds->planar, ds->numVerts, si->shader ); - if( refs == 0 ) - refs = FilterTrianglesIntoTree( ds, tree ); - if( refs > 0 ) - EmitTriangleSurface( ds ); - break; - - /* handle foliage surfaces (splash damage/wolf et) */ - case SURFACE_FOLIAGE: - //% Sys_FPrintf( SYS_VRB, "Surface %4d: [%d] %4d verts %s\n", numSurfs, ds->numFoliageInstances, ds->numVerts, si->shader ); - if( refs == 0 ) - refs = FilterFoliageIntoTree( ds, tree ); - if( refs > 0 ) - EmitTriangleSurface( ds ); - break; - - /* handle foghull surfaces */ - case SURFACE_FOGHULL: - if( refs == 0 ) - refs = AddReferenceToTree_r( ds, tree->headnode, qfalse ); - if( refs > 0 ) - EmitTriangleSurface( ds ); - break; - - /* handle flares */ - case SURFACE_FLARE: - if( refs == 0 ) - refs = FilterFlareSurfIntoTree( ds, tree ); - if( refs > 0 ) - EmitFlareSurface( ds ); - break; - - /* handle shader-only surfaces */ - case SURFACE_SHADER: - refs = 1; + /* handle brush faces */ + case SURFACE_FACE: + case SURFACE_DECAL: + if ( refs == 0 ) { + refs = FilterFaceIntoTree( ds, tree ); + } + if ( refs > 0 ) { + EmitFaceSurface( ds ); + } + break; + + /* handle patches */ + case SURFACE_PATCH: + if ( refs == 0 ) { + refs = FilterPatchIntoTree( ds, tree ); + } + if ( refs > 0 ) { + EmitPatchSurface( e, ds ); + } + break; + + /* handle triangle surfaces */ + case SURFACE_TRIANGLES: + case SURFACE_FORCED_META: + case SURFACE_META: + //% Sys_FPrintf( SYS_VRB, "Surface %4d: [%1d] %4d verts %s\n", numSurfs, ds->planar, ds->numVerts, si->shader ); + if ( refs == 0 ) { + refs = FilterTrianglesIntoTree( ds, tree ); + } + if ( refs > 0 ) { + EmitTriangleSurface( ds ); + } + break; + + /* handle foliage surfaces (splash damage/wolf et) */ + case SURFACE_FOLIAGE: + //% Sys_FPrintf( SYS_VRB, "Surface %4d: [%d] %4d verts %s\n", numSurfs, ds->numFoliageInstances, ds->numVerts, si->shader ); + if ( refs == 0 ) { + refs = FilterFoliageIntoTree( ds, tree ); + } + if ( refs > 0 ) { + EmitTriangleSurface( ds ); + } + break; + + /* handle foghull surfaces */ + case SURFACE_FOGHULL: + if ( refs == 0 ) { + refs = AddReferenceToTree_r( ds, tree->headnode, qfalse ); + } + if ( refs > 0 ) { + EmitTriangleSurface( ds ); + } + break; + + /* handle flares */ + case SURFACE_FLARE: + if ( refs == 0 ) { + refs = FilterFlareSurfIntoTree( ds, tree ); + } + if ( refs > 0 ) { EmitFlareSurface( ds ); - break; - - /* no references */ - default: - refs = 0; - break; + } + break; + + /* handle shader-only surfaces */ + case SURFACE_SHADER: + refs = 1; + EmitFlareSurface( ds ); + break; + + /* no references */ + default: + refs = 0; + break; + } + + /* maybe surface got marked as skybox again */ + /* if we keep that flag, it will get scaled up AGAIN */ + if ( sb ) { + ds->skybox = qfalse; } - + /* tot up the references */ - if( refs > 0 ) - { + if ( refs > 0 ) { /* tot up counts */ numSurfs++; numRefs += refs; - + /* emit extra surface data */ SetSurfaceExtra( ds, numBSPDrawSurfaces - 1 ); //% Sys_FPrintf( SYS_VRB, "%d verts %d indexes\n", ds->numVerts, ds->numIndexes ); - + /* one last sanity check */ { - bspDrawSurface_t *out; + bspDrawSurface_t *out; out = &bspDrawSurfaces[ numBSPDrawSurfaces - 1 ]; - if( out->numVerts == 3 && out->numIndexes > 3 ) - { - Sys_Printf( "\nWARNING: Potentially bad %s surface (%d: %d, %d)\n %s\n", - surfaceTypes[ ds->type ], - numBSPDrawSurfaces - 1, out->numVerts, out->numIndexes, si->shader ); + if ( out->numVerts == 3 && out->numIndexes > 3 ) { + Sys_FPrintf( SYS_WRN, "WARNING: Potentially bad %s surface (%d: %d, %d)\n %s\n", + surfaceTypes[ ds->type ], + numBSPDrawSurfaces - 1, out->numVerts, out->numIndexes, si->shader ); } } - + /* ydnar: handle skybox surfaces */ - if( ds->skybox ) - { + if ( ds->skybox ) { MakeSkyboxSurface( ds ); numSkyboxSurfaces++; } } } - + /* emit some statistics */ Sys_FPrintf( SYS_VRB, "%9d references\n", numRefs ); Sys_FPrintf( SYS_VRB, "%9d (%d) emitted drawsurfs\n", numSurfs, numBSPDrawSurfaces ); Sys_FPrintf( SYS_VRB, "%9d stripped face surfaces\n", numStripSurfaces ); Sys_FPrintf( SYS_VRB, "%9d fanned face surfaces\n", numFanSurfaces ); + Sys_FPrintf( SYS_VRB, "%9d maxarea'd face surfaces\n", numMaxAreaSurfaces ); Sys_FPrintf( SYS_VRB, "%9d surface models generated\n", numSurfaceModels ); Sys_FPrintf( SYS_VRB, "%9d skybox surfaces generated\n", numSkyboxSurfaces ); - for( i = 0; i < NUM_SURFACE_TYPES; i++ ) + for ( i = 0; i < NUM_SURFACE_TYPES; i++ ) Sys_FPrintf( SYS_VRB, "%9d %s surfaces\n", numSurfacesByType[ i ], surfaceTypes[ i ] ); - - Sys_FPrintf( SYS_VRB, "%9d redundant indexes supressed, saving %d Kbytes\n", numRedundantIndexes, (numRedundantIndexes * 4 / 1024) ); -} - - + Sys_FPrintf( SYS_VRB, "%9d redundant indexes supressed, saving %d Kbytes\n", numRedundantIndexes, ( numRedundantIndexes * 4 / 1024 ) ); +}