From dbfb22e27376c6de3ca36fe77cc1c274460ab325 Mon Sep 17 00:00:00 2001 From: Garux Date: Fri, 30 Jul 2021 12:20:56 +0300 Subject: [PATCH] using winding_accu_t = std::vector; --- tools/quake3/common/polylib.cpp | 136 +++++++------------------------- tools/quake3/common/polylib.h | 13 +-- tools/quake3/q3map2/brush.cpp | 46 +++-------- 3 files changed, 45 insertions(+), 150 deletions(-) diff --git a/tools/quake3/common/polylib.cpp b/tools/quake3/common/polylib.cpp index 87a9bb3e..2d509a0e 100644 --- a/tools/quake3/common/polylib.cpp +++ b/tools/quake3/common/polylib.cpp @@ -48,18 +48,6 @@ winding_t *AllocWinding( int points ){ return safe_calloc( offsetof_array( winding_t, p, points ) ); } -/* - ============= - AllocWindingAccu - ============= - */ -winding_accu_t *AllocWindingAccu( int points ){ - if ( points >= MAX_POINTS_ON_WINDING ) { - Error( "AllocWindingAccu failed: MAX_POINTS_ON_WINDING exceeded" ); - } - return safe_calloc( offsetof_array( winding_accu_t, p, points ) ); -} - /* ============= FreeWinding @@ -78,24 +66,6 @@ void FreeWinding( winding_t *w ){ free( w ); } -/* - ============= - FreeWindingAccu - ============= - */ -void FreeWindingAccu( winding_accu_t *w ){ - if ( !w ) { - Error( "FreeWindingAccu: winding is NULL" ); - } - - if ( *( (unsigned *) w ) == 0xdeaddead ) { - Error( "FreeWindingAccu: freed a freed winding" ); - } - *( (unsigned *) w ) = 0xdeaddead; - - free( w ); -} - /* ============ RemoveColinearPoints @@ -177,7 +147,7 @@ Vector3 WindingCenter( const winding_t *w ){ BaseWindingForPlaneAccu ================= */ -winding_accu_t *BaseWindingForPlaneAccu( const Plane3& plane ){ +winding_accu_t BaseWindingForPlaneAccu( const Plane3& plane ){ // The goal in this function is to replicate the behavior of the original BaseWindingForPlane() // function (see below) but at the same time increasing accuracy substantially. @@ -194,7 +164,6 @@ winding_accu_t *BaseWindingForPlaneAccu( const Plane3& plane ){ int x, i; float max, v; DoubleVector3 vright, vup, org; - winding_accu_t *w; // One of the components of normal must have a magnitiude greater than this value, // otherwise normal is not a unit vector. This is a little bit of inexpensive @@ -265,16 +234,12 @@ winding_accu_t *BaseWindingForPlaneAccu( const Plane3& plane ){ // outside the world. sqrt(262144^2 + 262144^2)/2 = 185363, which is greater than // 113512. - w = AllocWindingAccu( 4 ); - - w->p[0] = org - vright + vup; - w->p[1] = org + vright + vup; - w->p[2] = org + vright - vup; - w->p[3] = org - vright - vup; - - w->numpoints = 4; - - return w; + return winding_accu_t{ + org - vright + vup, + org + vright + vup, + org + vright - vup, + org - vright - vup + }; } /* @@ -364,39 +329,17 @@ winding_t *CopyWinding( const winding_t *w ){ return void_ptr( memcpy( AllocWinding( w->numpoints ), w, offsetof_array( winding_t, p, w->numpoints ) ) ); } -/* - ================== - CopyWindingAccuIncreaseSizeAndFreeOld - ================== - */ -winding_accu_t *CopyWindingAccuIncreaseSizeAndFreeOld( winding_accu_t *w ){ - if ( !w ) { - Error( "CopyWindingAccuIncreaseSizeAndFreeOld: winding is NULL" ); - } - - winding_accu_t *c = void_ptr( memcpy( AllocWindingAccu( w->numpoints + 1 ), w, offsetof_array( winding_accu_t, p, w->numpoints ) ) ); - FreeWindingAccu( w ); - return c; -} - /* ================== CopyWindingAccuToRegular ================== */ -winding_t *CopyWindingAccuToRegular( const winding_accu_t *w ){ - int i; - winding_t *c; - - if ( !w ) { - Error( "CopyWindingAccuToRegular: winding is NULL" ); - } - - c = AllocWinding( w->numpoints ); - c->numpoints = w->numpoints; - for ( i = 0; i < c->numpoints; i++ ) +winding_t *CopyWindingAccuToRegular( const winding_accu_t& w ){ + winding_t *c = AllocWinding( w.size() ); + c->numpoints = w.size(); + for ( int i = 0; i < c->numpoints; i++ ) { - c->p[i] = w->p[i]; + c->p[i] = w[i]; } return c; } @@ -553,15 +496,11 @@ void ClipWindingEpsilon( winding_t *in, const Plane3f& plane, ChopWindingInPlaceAccu ============= */ -void ChopWindingInPlaceAccu( winding_accu_t **inout, const Plane3& plane, float crudeEpsilon ){ - winding_accu_t *in; - int counts[3]; - int i, j; +void ChopWindingInPlaceAccu( winding_accu_t& inout, const Plane3& plane, float crudeEpsilon ){ + size_t counts[3] = { 0 }; + size_t i, j; double dists[MAX_POINTS_ON_WINDING + 1]; EPlaneSide sides[MAX_POINTS_ON_WINDING + 1]; - int maxpts; - winding_accu_t *f; - double w; // We require at least a very small epsilon. It's a good idea for several reasons. // First, we will be dividing by a potentially very small distance below. We don't @@ -598,12 +537,9 @@ void ChopWindingInPlaceAccu( winding_accu_t **inout, const Plane3& plane, float static const double smallestEpsilonAllowed = ( (double) VEC_SMALLEST_EPSILON_AROUND_ONE ) * 0.5; const double fineEpsilon = std::max( smallestEpsilonAllowed, (double) crudeEpsilon ); - in = *inout; - counts[0] = counts[1] = counts[2] = 0; - - for ( i = 0; i < in->numpoints; i++ ) + for ( i = 0; i < inout.size(); i++ ) { - dists[i] = plane3_distance_to_point( plane, in->p[i] ); + dists[i] = plane3_distance_to_point( plane, inout[i] ); if ( dists[i] > fineEpsilon ) { sides[i] = eSideFront; } @@ -622,8 +558,7 @@ void ChopWindingInPlaceAccu( winding_accu_t **inout, const Plane3& plane, float // that we never get a case where two nearly equal planes result in 2 NULL windings // due to the 'if' statement below. TODO: Investigate this. if ( !counts[eSideFront] ) { - FreeWindingAccu( in ); - *inout = NULL; + inout.clear(); return; } if ( !counts[eSideBack] ) { @@ -633,24 +568,18 @@ void ChopWindingInPlaceAccu( winding_accu_t **inout, const Plane3& plane, float // NOTE: The least number of points that a winding can have at this point is 2. // In that case, one point is SIDE_FRONT and the other is SIDE_BACK. - maxpts = counts[eSideFront] + 2; // We dynamically expand if this is too small. - f = AllocWindingAccu( maxpts ); + winding_accu_t f; + f.reserve( counts[eSideFront] + 2 ); - for ( i = 0; i < in->numpoints; i++ ) + for ( i = 0; i < inout.size(); i++ ) { - const DoubleVector3& p1 = in->p[i]; + const DoubleVector3& p1 = inout[i]; if ( sides[i] == eSideOn || sides[i] == eSideFront ) { - if ( f->numpoints >= MAX_POINTS_ON_WINDING ) { + if ( f.size() >= MAX_POINTS_ON_WINDING ) { Error( "ChopWindingInPlaceAccu: MAX_POINTS_ON_WINDING" ); } - if ( f->numpoints >= maxpts ) { // This will probably never happen. - Sys_FPrintf( SYS_WRN | SYS_VRBflag, "WARNING: estimate on chopped winding size incorrect (no problem)\n" ); - f = CopyWindingAccuIncreaseSizeAndFreeOld( f ); - maxpts++; - } - f->p[f->numpoints] = p1; - f->numpoints++; + f.push_back( p1 ); if ( sides[i] == eSideOn ) { continue; } @@ -660,11 +589,11 @@ void ChopWindingInPlaceAccu( winding_accu_t **inout, const Plane3& plane, float } // Generate a split point. - const DoubleVector3& p2 = in->p[( ( i + 1 ) == in->numpoints ) ? 0 : ( i + 1 )]; + const DoubleVector3& p2 = inout[( ( i + 1 ) == inout.size() ) ? 0 : ( i + 1 )]; // The divisor's absolute value is greater than the dividend's absolute value. // w is in the range (0,1). - w = dists[i] / ( dists[i] - dists[i + 1] ); + const double w = dists[i] / ( dists[i] - dists[i + 1] ); DoubleVector3 mid; for ( j = 0; j < 3; j++ ) { @@ -679,20 +608,13 @@ void ChopWindingInPlaceAccu( winding_accu_t **inout, const Plane3& plane, float mid[j] = p1[j] + ( w * ( p2[j] - p1[j] ) ); } } - if ( f->numpoints >= MAX_POINTS_ON_WINDING ) { + if ( f.size() >= MAX_POINTS_ON_WINDING ) { Error( "ChopWindingInPlaceAccu: MAX_POINTS_ON_WINDING" ); } - if ( f->numpoints >= maxpts ) { // This will probably never happen. - Sys_FPrintf( SYS_WRN | SYS_VRBflag, "WARNING: estimate on chopped winding size incorrect (no problem)\n" ); - f = CopyWindingAccuIncreaseSizeAndFreeOld( f ); - maxpts++; - } - f->p[f->numpoints] = mid; - f->numpoints++; + f.push_back( mid ); } - FreeWindingAccu( in ); - *inout = f; + inout.swap( f ); } /* diff --git a/tools/quake3/common/polylib.h b/tools/quake3/common/polylib.h index ff36fbe0..28093abd 100644 --- a/tools/quake3/common/polylib.h +++ b/tools/quake3/common/polylib.h @@ -75,13 +75,8 @@ void pw( winding_t *w ); // in q3map2 brush processing. /////////////////////////////////////////////////////////////////////////////////////// -struct winding_accu_t -{ - int numpoints; - DoubleVector3 p[]; -}; +using winding_accu_t = std::vector; -winding_accu_t *BaseWindingForPlaneAccu( const Plane3& plane ); -void ChopWindingInPlaceAccu( winding_accu_t **w, const Plane3& plane, float epsilon ); -winding_t *CopyWindingAccuToRegular( const winding_accu_t *w ); -void FreeWindingAccu( winding_accu_t *w ); +winding_accu_t BaseWindingForPlaneAccu( const Plane3& plane ); +void ChopWindingInPlaceAccu( winding_accu_t& w, const Plane3& plane, float epsilon ); +winding_t *CopyWindingAccuToRegular( const winding_accu_t& w ); diff --git a/tools/quake3/q3map2/brush.cpp b/tools/quake3/q3map2/brush.cpp index c670ca74..5793625b 100644 --- a/tools/quake3/q3map2/brush.cpp +++ b/tools/quake3/q3map2/brush.cpp @@ -353,33 +353,25 @@ bool FixWinding( winding_t *w ){ if the some of the winding's points are close together. ================== */ -bool FixWindingAccu( winding_accu_t *w ){ - if ( w == NULL ) { - Error( "FixWindingAccu: NULL argument" ); - } - +bool FixWindingAccu( winding_accu_t& w ){ bool altered = false; while ( true ) { - if ( w->numpoints < 2 ) { + if ( w.size() < 2 ) { break; // Don't remove the only remaining point. } bool done = true; - for ( int i = w->numpoints - 1, j = 0; j < w->numpoints; i = j, ++j ) + for ( winding_accu_t::iterator i = w.end() - 1, j = w.begin(); j != w.end(); i = j, ++j ) { - if ( vector3_length( w->p[i] - w->p[j] ) < DEGENERATE_EPSILON ) { + if ( vector3_length( *i - *j ) < DEGENERATE_EPSILON ) { // TODO: I think the "snap weld vector" was written before // some of the math precision fixes, and its purpose was // probably to address math accuracy issues. We can think // about changing the logic here. Maybe once plane distance // gets 64 bits, we can look at it then. - w->p[i] = SnapWeldVectorAccu( w->p[i], w->p[j] ); - for ( int k = j + 1; k < w->numpoints; k++ ) - { - w->p[k - 1] = w->p[k]; - } - w->numpoints--; + *i = SnapWeldVectorAccu( *i, *j ); + w.erase( j ); altered = true; // The only way to finish off fixing the winding consistently and // accurately is by fixing the winding all over again. For example, @@ -407,11 +399,6 @@ bool FixWindingAccu( winding_accu_t *w ){ */ bool CreateBrushWindings( brush_t *brush ){ -#if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES - winding_accu_t *w; -#else - winding_t *w; -#endif /* walk the list of brush sides */ for ( int i = 0; i < brush->numsides; i++ ) { @@ -421,13 +408,13 @@ bool CreateBrushWindings( brush_t *brush ){ /* make huge winding */ #if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES - w = BaseWindingForPlaneAccu( ( side.plane.normal() != g_vector3_identity )? side.plane : Plane3( plane.plane ) ); + winding_accu_t w = BaseWindingForPlaneAccu( ( side.plane.normal() != g_vector3_identity )? side.plane : Plane3( plane.plane ) ); #else - w = BaseWindingForPlane( plane.plane ); + winding_t *w = BaseWindingForPlane( plane.plane ); #endif /* walk the list of brush sides */ - for ( int j = 0; j < brush->numsides && w != NULL; j++ ) + for ( int j = 0; j < brush->numsides && !w.empty(); j++ ) { const side_t& cside = brush->sides[ j ]; const plane_t& cplane = mapplanes[ cside.planenum ^ 1 ]; @@ -437,7 +424,7 @@ bool CreateBrushWindings( brush_t *brush ){ continue; } #if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES - ChopWindingInPlaceAccu( &w, ( cside.plane.normal() != g_vector3_identity )? plane3_flipped( cside.plane ) : Plane3( cplane.plane ), 0 ); + ChopWindingInPlaceAccu( w, ( cside.plane.normal() != g_vector3_identity )? plane3_flipped( cside.plane ) : Plane3( cplane.plane ), 0 ); #else ChopWindingInPlace( &w, cplane.plane, 0 ); // CLIP_EPSILON ); #endif @@ -455,17 +442,8 @@ bool CreateBrushWindings( brush_t *brush ){ /* set side winding */ #if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES - if ( w != NULL ) { - FixWindingAccu( w ); - if ( w->numpoints < 3 ) { - FreeWindingAccu( w ); - w = NULL; - } - } - side.winding = ( w ? CopyWindingAccuToRegular( w ) : NULL ); - if ( w ) { - FreeWindingAccu( w ); - } + FixWindingAccu( w ); + side.winding = ( w.size() >= 3 ? CopyWindingAccuToRegular( w ) : NULL ); #else side.winding = w; #endif