use spatially sorted indices during search of coincident vertices in AddMetaVertToSurface

This commit is contained in:
Garux 2021-08-28 10:56:50 +03:00
parent e780b45696
commit 0ad3d89d4a

View File

@ -30,8 +30,12 @@
/* dependencies */ /* dependencies */
#include "q3map2.h" #include "q3map2.h"
#include <set>
const Plane3f c_spatial_sort_plane( 0.786868, 0.316861, 0.529564, 0 );
const float c_spatial_EQUAL_EPSILON = EQUAL_EPSILON * 2;
#define VERTS_EXCEEDED -1000 #define VERTS_EXCEEDED -1000
@ -1237,28 +1241,38 @@ void SmoothMetaTriangles( void ){
struct SpatialIndex
{
const float m_dist;
const int m_index; // index of bspDrawVert_t in mapDrawSurface_t::verts array
SpatialIndex( const Vector3& point, int index ) : m_dist( plane3_distance_to_point( c_spatial_sort_plane, point ) ), m_index( index ){}
bool operator<( const SpatialIndex& other ) const {
return m_dist < other.m_dist - c_spatial_EQUAL_EPSILON;
}
};
using Sorted_indices = std::multiset<SpatialIndex>;
/* /*
AddMetaVertToSurface() AddMetaVertToSurface()
adds a drawvert to a surface unless an existing vert matching already exists adds a drawvert to a surface unless an existing vert matching already exists
returns the index of that vert (or < 0 on failure) returns the index of that vert (or < 0 on failure)
*/ */
int AddMetaVertToSurface( mapDrawSurface_t *ds, bspDrawVert_t *dv1, int *coincident ){ int AddMetaVertToSurface( mapDrawSurface_t *ds, const bspDrawVert_t& dv1, const Sorted_indices& sorted_indices, int *coincident ){
int i;
bspDrawVert_t *dv2;
/* go through the verts and find a suitable candidate */ /* go through the verts and find a suitable candidate */
for ( i = 0; i < ds->numVerts; i++ ) const auto [begin, end] = sorted_indices.equal_range( SpatialIndex( dv1.xyz, 0 ) );
{ for( auto it = begin; it != end; ++it ){
/* get test vert */ /* get test vert */
dv2 = &ds->verts[ i ]; const bspDrawVert_t& dv2 = ds->verts[ it->m_index ];
/* compare xyz and normal */ /* compare xyz and normal */
if ( !VectorCompare( dv1->xyz, dv2->xyz ) ) { if ( !VectorCompare( dv1.xyz, dv2.xyz ) ) {
continue; continue;
} }
if ( !VectorCompare( dv1->normal, dv2->normal ) ) { if ( !VectorCompare( dv1.normal, dv2.normal ) ) {
continue; continue;
} }
@ -1266,16 +1280,16 @@ int AddMetaVertToSurface( mapDrawSurface_t *ds, bspDrawVert_t *dv1, int *coincid
( *coincident )++; ( *coincident )++;
/* compare texture coordinates and color */ /* compare texture coordinates and color */
if ( dv1->st[ 0 ] != dv2->st[ 0 ] || dv1->st[ 1 ] != dv2->st[ 1 ] ) { if ( dv1.st[ 0 ] != dv2.st[ 0 ] || dv1.st[ 1 ] != dv2.st[ 1 ] ) {
continue; continue;
} }
if ( dv1->color[ 0 ].alpha() != dv2->color[ 0 ].alpha() ) { if ( dv1.color[ 0 ].alpha() != dv2.color[ 0 ].alpha() ) {
continue; continue;
} }
/* found a winner */ /* found a winner */
numMergedVerts++; numMergedVerts++;
return i; return it->m_index;
} }
/* overflow check */ /* overflow check */
@ -1284,8 +1298,7 @@ int AddMetaVertToSurface( mapDrawSurface_t *ds, bspDrawVert_t *dv1, int *coincid
} }
/* made it this far, add the vert and return */ /* made it this far, add the vert and return */
dv2 = &ds->verts[ ds->numVerts++ ]; ds->verts[ ds->numVerts++ ] = dv1;
*dv2 = *dv1;
return ( ds->numVerts - 1 ); return ( ds->numVerts - 1 );
} }
@ -1312,7 +1325,7 @@ int AddMetaVertToSurface( mapDrawSurface_t *ds, bspDrawVert_t *dv1, int *coincid
#define ADEQUATE_SCORE ( metaAdequateScore >= 0 ? metaAdequateScore : DEFAULT_ADEQUATE_SCORE ) #define ADEQUATE_SCORE ( metaAdequateScore >= 0 ? metaAdequateScore : DEFAULT_ADEQUATE_SCORE )
#define GOOD_SCORE ( metaGoodScore >= 0 ? metaGoodScore : DEFAULT_GOOD_SCORE ) #define GOOD_SCORE ( metaGoodScore >= 0 ? metaGoodScore : DEFAULT_GOOD_SCORE )
static int AddMetaTriangleToSurface( mapDrawSurface_t *ds, metaTriangle_t *tri, MinMax& texMinMax, bool testAdd ){ static int AddMetaTriangleToSurface( mapDrawSurface_t *ds, metaTriangle_t *tri, MinMax& texMinMax, Sorted_indices& sorted_indices, bool testAdd ){
int i, score, coincident, ai, bi, ci; int i, score, coincident, ai, bi, ci;
@ -1368,10 +1381,11 @@ static int AddMetaTriangleToSurface( mapDrawSurface_t *ds, metaTriangle_t *tri,
mapDrawSurface_t old( *ds ); mapDrawSurface_t old( *ds );
/* attempt to add the verts */ /* attempt to add the verts */
const int numVerts_original = ds->numVerts;
coincident = 0; coincident = 0;
ai = AddMetaVertToSurface( ds, &metaVerts[ tri->indexes[ 0 ] ], &coincident ); ai = AddMetaVertToSurface( ds, metaVerts[ tri->indexes[ 0 ] ], sorted_indices, &coincident );
bi = AddMetaVertToSurface( ds, &metaVerts[ tri->indexes[ 1 ] ], &coincident ); bi = AddMetaVertToSurface( ds, metaVerts[ tri->indexes[ 1 ] ], sorted_indices, &coincident );
ci = AddMetaVertToSurface( ds, &metaVerts[ tri->indexes[ 2 ] ], &coincident ); ci = AddMetaVertToSurface( ds, metaVerts[ tri->indexes[ 2 ] ], sorted_indices, &coincident );
/* check vertex underflow */ /* check vertex underflow */
if ( ai < 0 || bi < 0 || ci < 0 ) { if ( ai < 0 || bi < 0 || ci < 0 ) {
@ -1500,6 +1514,11 @@ static int AddMetaTriangleToSurface( mapDrawSurface_t *ds, metaTriangle_t *tri,
/* add a side reference */ /* add a side reference */
ds->sideRef = AllocSideRef( tri->side, ds->sideRef ); ds->sideRef = AllocSideRef( tri->side, ds->sideRef );
for( const auto id : { ai, bi, ci } ){
if( id >= numVerts_original )
sorted_indices.insert( SpatialIndex( ds->verts[id].xyz, id ) );
}
} }
/* return to sender */ /* return to sender */
@ -1559,8 +1578,10 @@ static void MetaTrianglesToSurface( int numPossibles, metaTriangle_t *possibles,
MinMax texMinMax; MinMax texMinMax;
Sorted_indices sorted_indices;
/* add the first triangle */ /* add the first triangle */
if ( AddMetaTriangleToSurface( ds, seed, texMinMax, false ) ) { if ( AddMetaTriangleToSurface( ds, seed, texMinMax, sorted_indices, false ) ) {
( *numAdded )++; ( *numAdded )++;
} }
@ -1593,14 +1614,14 @@ static void MetaTrianglesToSurface( int numPossibles, metaTriangle_t *possibles,
} }
/* score this triangle */ /* score this triangle */
score = AddMetaTriangleToSurface( ds, test, texMinMax, true ); score = AddMetaTriangleToSurface( ds, test, texMinMax, sorted_indices, true );
if ( score > bestScore ) { if ( score > bestScore ) {
best = j; best = j;
bestScore = score; bestScore = score;
/* if we have a score over a certain threshold, just use it */ /* if we have a score over a certain threshold, just use it */
if ( bestScore >= GOOD_SCORE ) { if ( bestScore >= GOOD_SCORE ) {
if ( AddMetaTriangleToSurface( ds, &possibles[ best ], texMinMax, false ) ) { if ( AddMetaTriangleToSurface( ds, &possibles[ best ], texMinMax, sorted_indices, false ) ) {
( *numAdded )++; ( *numAdded )++;
} }
@ -1614,7 +1635,7 @@ static void MetaTrianglesToSurface( int numPossibles, metaTriangle_t *possibles,
/* add best candidate */ /* add best candidate */
if ( best >= 0 && bestScore > ADEQUATE_SCORE ) { if ( best >= 0 && bestScore > ADEQUATE_SCORE ) {
if ( AddMetaTriangleToSurface( ds, &possibles[ best ], texMinMax, false ) ) { if ( AddMetaTriangleToSurface( ds, &possibles[ best ], texMinMax, sorted_indices, false ) ) {
( *numAdded )++; ( *numAdded )++;
} }