diff --git a/tools/quake3/q3map2/q3map2.h b/tools/quake3/q3map2/q3map2.h index 20299941..07aa5422 100644 --- a/tools/quake3/q3map2/q3map2.h +++ b/tools/quake3/q3map2/q3map2.h @@ -974,6 +974,7 @@ struct metaTriangle_t Plane3f plane; Vector3 lightmapAxis; int indexes[ 3 ]; + float min, max; }; @@ -1710,7 +1711,6 @@ void Foliage( mapDrawSurface_t *src ); /* ydnar: surface_meta.c */ void ClearMetaTriangles( void ); -int FindMetaTriangle( metaTriangle_t *src, bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *c, int planeNum ); void MakeEntityMetaTriangles( entity_t *e ); void FixMetaTJunctions( void ); void SmoothMetaTriangles( void ); diff --git a/tools/quake3/q3map2/surface_meta.cpp b/tools/quake3/q3map2/surface_meta.cpp index e41e332b..3449ea01 100644 --- a/tools/quake3/q3map2/surface_meta.cpp +++ b/tools/quake3/q3map2/surface_meta.cpp @@ -119,7 +119,7 @@ static int AddMetaTriangle( void ){ otherwise adds it and returns the index to the metatriangle */ -int FindMetaTriangle( metaTriangle_t *src, bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *c, int planeNum ){ +static int FindMetaTriangle( metaTriangle_t *src, bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *c, int planeNum ){ int triIndex; /* detect degenerate triangles fixme: do something proper here */ @@ -1330,15 +1330,6 @@ static int AddMetaTriangleToSurface( mapDrawSurface_t *ds, metaTriangle_t *tri, /* test the triangle */ - if ( ds->entityNum != tri->entityNum ) { /* ydnar: added 2002-07-06 */ - return 0; - } - if ( ds->castShadows != tri->castShadows || ds->recvShadows != tri->recvShadows ) { - return 0; - } - if ( ds->shaderInfo != tri->si || ds->fogNum != tri->fogNum || ds->sampleSize != tri->sampleSize ) { - return 0; - } #if 0 if ( !( ds->shaderInfo->compileFlags & C_VERTEXLIT ) && //% !VectorCompare( ds->lightmapAxis, tri->lightmapAxis ) ) @@ -1532,21 +1523,13 @@ static int AddMetaTriangleToSurface( mapDrawSurface_t *ds, metaTriangle_t *tri, creates map drawsurface(s) from the list of possibles */ -static void MetaTrianglesToSurface( int numPossibles, metaTriangle_t *possibles, int *fOld, int *numAdded ){ - int i, j, f, best, score, bestScore; - metaTriangle_t *seed, *test; - mapDrawSurface_t *ds; - bspDrawVert_t *verts; - int *indexes; - bool added; - - +static void MetaTrianglesToSurface( metaTriangle_t *begin, metaTriangle_t *end, int *fOld, int *numAdded ){ /* allocate arrays */ - verts = safe_malloc( sizeof( *verts ) * maxSurfaceVerts ); - indexes = safe_malloc( sizeof( *indexes ) * maxSurfaceIndexes ); + bspDrawVert_t *verts = safe_malloc( sizeof( *verts ) * maxSurfaceVerts ); + int *indexes = safe_malloc( sizeof( *indexes ) * maxSurfaceIndexes ); /* walk the list of triangles */ - for ( i = 0, seed = possibles; i < numPossibles; i++, seed++ ) + for ( metaTriangle_t *seed = begin; seed != end; ++seed ) { /* skip this triangle if it has already been merged */ if ( seed->si == NULL ) { @@ -1558,7 +1541,7 @@ static void MetaTrianglesToSurface( int numPossibles, metaTriangle_t *possibles, ----------------------------------------------------------------- */ /* start a new drawsurface */ - ds = AllocDrawSurface( ESurfaceType::Meta ); + mapDrawSurface_t *ds = AllocDrawSurface( ESurfaceType::Meta ); ds->entityNum = seed->entityNum; ds->surfaceNum = seed->surfaceNum; ds->castShadows = seed->castShadows; @@ -1590,23 +1573,21 @@ static void MetaTrianglesToSurface( int numPossibles, metaTriangle_t *possibles, ----------------------------------------------------------------- */ /* progressively walk the list until no more triangles can be added */ - added = true; - while ( added ) + for( bool added = true; added; ) { /* print pacifier */ - f = 10 * *numAdded / numMetaTriangles; - if ( f > *fOld ) { + if ( const int f = 10 * *numAdded / numMetaTriangles; f > *fOld ) { *fOld = f; Sys_FPrintf( SYS_VRB, "%d...", f ); } /* reset best score */ - best = -1; - bestScore = 0; + metaTriangle_t *best = nullptr; + int bestScore = 0; added = false; /* walk the list of possible candidates for merging */ - for ( j = i + 1, test = &possibles[ j ]; j < numPossibles; j++, test++ ) + for ( metaTriangle_t *test = seed + 1; test != end; ++test ) { /* skip this triangle if it has already been merged */ if ( test->si == NULL ) { @@ -1614,19 +1595,19 @@ static void MetaTrianglesToSurface( int numPossibles, metaTriangle_t *possibles, } /* score this triangle */ - score = AddMetaTriangleToSurface( ds, test, texMinMax, sorted_indices, true ); + const int score = AddMetaTriangleToSurface( ds, test, texMinMax, sorted_indices, true ); if ( score > bestScore ) { - best = j; + best = test; bestScore = score; /* if we have a score over a certain threshold, just use it */ if ( bestScore >= GOOD_SCORE ) { - if ( AddMetaTriangleToSurface( ds, &possibles[ best ], texMinMax, sorted_indices, false ) ) { + if ( AddMetaTriangleToSurface( ds, best, texMinMax, sorted_indices, false ) ) { ( *numAdded )++; } /* reset */ - best = -1; + best = nullptr; bestScore = 0; added = true; } @@ -1634,8 +1615,8 @@ static void MetaTrianglesToSurface( int numPossibles, metaTriangle_t *possibles, } /* add best candidate */ - if ( best >= 0 && bestScore > ADEQUATE_SCORE ) { - if ( AddMetaTriangleToSurface( ds, &possibles[ best ], texMinMax, sorted_indices, false ) ) { + if ( best != nullptr && bestScore > ADEQUATE_SCORE ) { + if ( AddMetaTriangleToSurface( ds, best, texMinMax, sorted_indices, false ) ) { ( *numAdded )++; } @@ -1669,83 +1650,121 @@ static void MetaTrianglesToSurface( int numPossibles, metaTriangle_t *possibles, compare functor for std::sort() */ +template struct CompareMetaTriangles { bool operator()( const metaTriangle_t& a, const metaTriangle_t& b ) const { /* shader first */ if ( a.si < b.si ) { - return false; + return true; } else if ( a.si > b.si ) { - return true; + return false; } /* then fog */ else if ( a.fogNum < b.fogNum ) { - return false; + return true; } else if ( a.fogNum > b.fogNum ) { + return false; + } + + else if ( a.entityNum < b.entityNum ) { /* ydnar: added 2002-07-06 */ return true; } + else if ( a.entityNum > b.entityNum ) { + return false; + } + + else if ( a.castShadows < b.castShadows ) { + return true; + } + else if ( a.castShadows > b.castShadows ) { + return false; + } + + else if ( a.recvShadows < b.recvShadows ) { + return true; + } + else if ( a.recvShadows > b.recvShadows ) { + return false; + } + + else if ( a.sampleSize < b.sampleSize ) { + return true; + } + else if ( a.sampleSize > b.sampleSize ) { + return false; + } /* then plane */ #if 0 else if ( npDegrees == 0.0f && !a.si->nonplanar && a.planeNum >= 0 && a.planeNum >= 0 ) { if ( a.plane.dist() < b.plane.dist() ) { - return false; + return true; } else if ( a.plane.dist() > b.plane.dist() ) { - return true; + return false; } else if ( a.plane.normal()[ 0 ] < b.plane.normal()[ 0 ] ) { - return false; + return true; } else if ( a.plane.normal()[ 0 ] > b.plane.normal()[ 0 ] ) { - return true; + return false; } else if ( a.plane.normal()[ 1 ] < b.plane.normal()[ 1 ] ) { - return false; + return true; } else if ( a.plane.normal()[ 1 ] > b.plane.normal()[ 1 ] ) { - return true; - } - else if ( a.plane.normal()[ 2 ] < b.plane.normal()[ 2 ] ) { return false; } - else if ( a.plane.normal()[ 2 ] > b.plane.normal()[ 2 ] ) { + else if ( a.plane.normal()[ 2 ] < b.plane.normal()[ 2 ] ) { return true; } + else if ( a.plane.normal()[ 2 ] > b.plane.normal()[ 2 ] ) { + return false; + } } #endif /* then position in world */ - - /* find mins */ - Vector3 aMins( 999999 ); - Vector3 bMins( 999999 ); - for ( int i = 0; i < 3; i++ ) - { - const int av = a.indexes[ i ]; - const int bv = b.indexes[ i ]; - for ( int j = 0; j < 3; j++ ) - { - value_minimize( aMins[ j ], metaVerts[ av ].xyz[ j ] ); - value_minimize( bMins[ j ], metaVerts[ bv ].xyz[ j ] ); - } - } - - /* test it */ - for ( int i = 0; i < 3; i++ ) - { - if ( aMins[ i ] < bMins[ i ] ) { - return false; - } - else if ( aMins[ i ] > bMins[ i ] ) { + if constexpr ( sort_spatially ){ +#if 0 + if ( a.min < b.min ) { return true; } - } + else if ( a.min > b.min ) { + return false; + } +#else + /* find mins */ + Vector3 aMins( 999999 ); + Vector3 bMins( 999999 ); + for ( int i = 0; i < 3; i++ ) + { + const int av = a.indexes[ i ]; + const int bv = b.indexes[ i ]; + for ( int j = 0; j < 3; j++ ) + { + value_minimize( aMins[ j ], metaVerts[ av ].xyz[ j ] ); + value_minimize( bMins[ j ], metaVerts[ bv ].xyz[ j ] ); + } + } + /* test it */ + for ( int i = 0; i < 3; i++ ) + { + if ( aMins[ i ] < bMins[ i ] ) { + return true; + } + else if ( aMins[ i ] > bMins[ i ] ) { + return false; + } + } +#endif + } /* functionally equivalent */ return false; } @@ -1759,10 +1778,6 @@ struct CompareMetaTriangles */ void MergeMetaTriangles( void ){ - int i, j, fOld, start, numAdded; - metaTriangle_t *head, *end; - - /* only do this if there are meta triangles */ if ( numMetaTriangles <= 0 ) { return; @@ -1772,47 +1787,36 @@ void MergeMetaTriangles( void ){ Sys_FPrintf( SYS_VRB, "--- MergeMetaTriangles ---\n" ); /* sort the triangles by shader major, fognum minor */ - std::sort( metaTriangles, metaTriangles + numMetaTriangles, CompareMetaTriangles() ); + metaTriangle_t *metaTrianglesEnd = metaTriangles + numMetaTriangles; + for( metaTriangle_t *it = metaTriangles; it != metaTrianglesEnd; ++it ){ + it->min = std::numeric_limits::max(); + it->max = std::numeric_limits::lowest(); + for( int i = 0; i < 3; ++i ){ + const float dist = plane3_distance_to_point( c_spatial_sort_plane, metaVerts[it->indexes[i]].xyz ); + value_minimize( it->min, dist ); + value_maximize( it->max, dist ); + } + } + std::sort( metaTriangles, metaTrianglesEnd, CompareMetaTriangles() ); /* init pacifier */ - fOld = -1; - start = I_FloatTime(); - numAdded = 0; + int fOld = -1; + int start = I_FloatTime(); + int numAdded = 0; /* merge */ - for ( i = 0, j = 0; i < numMetaTriangles; i = j ) - { - /* get head of list */ - head = &metaTriangles[ i ]; - - /* skip this triangle if it has already been merged */ - if ( head->si == NULL ) { - continue; - } - - /* find end */ - if ( j <= i ) { - for ( j = i + 1; j < numMetaTriangles; j++ ) - { - /* get end of list */ - end = &metaTriangles[ j ]; - if ( head->si != end->si || head->fogNum != end->fogNum ) { - break; - } - } - } - + metaTriangle_t *begin, *end = metaTriangles; + while( end != metaTrianglesEnd ){ + std::tie( begin, end ) = std::equal_range( end, metaTrianglesEnd, *end, CompareMetaTriangles() ); /* try to merge this list of possible merge candidates */ - MetaTrianglesToSurface( ( j - i ), head, &fOld, &numAdded ); + MetaTrianglesToSurface( begin, end, &fOld, &numAdded ); } /* clear meta triangle list */ ClearMetaTriangles(); /* print time */ - if ( i ) { - Sys_FPrintf( SYS_VRB, " (%d)\n", (int) ( I_FloatTime() - start ) ); - } + Sys_FPrintf( SYS_VRB, " (%d)\n", (int) ( I_FloatTime() - start ) ); /* emit some stats */ Sys_FPrintf( SYS_VRB, "%9d surfaces merged\n", numMergedSurfaces );