wrap winding_next logic

prevent crash in AddWindingToConvexHull()
This commit is contained in:
Garux 2021-08-11 18:18:38 +03:00
parent f492ab27eb
commit aa5de2fee9
5 changed files with 35 additions and 33 deletions

View File

@ -55,14 +55,13 @@ winding_t AllocWinding( int points ){
============ ============
*/ */
void RemoveColinearPoints( winding_t& w ){ void RemoveColinearPoints( winding_t& w ){
winding_t p; winding_t p = AllocWinding( w.size() );
p.reserve( w.size() );
for ( size_t i = 0 ; i < w.size() ; i++ ) for ( size_t i = 0; i < w.size(); i++ )
{ {
const size_t j = ( i + 1 ) % w.size(); const size_t j = winding_next( w, i );
const size_t k = ( i + w.size() - 1 ) % w.size(); const size_t k = winding_next( w, j );
if ( vector3_dot( VectorNormalized( w[j] - w[i] ), VectorNormalized( w[j] - w[k] ) ) < 0.999 ) { if ( vector3_dot( VectorNormalized( w[k] - w[j] ), VectorNormalized( w[k] - w[i] ) ) < 0.999 ) {
p.push_back( w[i] ); p.push_back( w[i] );
} }
} }
@ -377,7 +376,7 @@ std::pair<winding_t, winding_t> ClipWindingEpsilonStrict( const winding_t& in
} }
// generate a split point // generate a split point
const Vector3& p2 = in[( i + 1 ) % in.size()]; const Vector3& p2 = in[winding_next( in, i )];
const double dot = dists[i] / ( dists[i] - dists[i + 1] ); const double dot = dists[i] / ( dists[i] - dists[i + 1] );
Vector3 mid; Vector3 mid;
for ( j = 0; j < 3; j++ ) for ( j = 0; j < 3; j++ )
@ -586,8 +585,7 @@ void ChopWindingInPlace( winding_t& inout, const Plane3f& plane, float epsilon )
} }
winding_t f; winding_t f = AllocWinding( in.size() + 4 ); // cant use counts[0]+2 because of fp grouping errors
f.reserve( in.size() + 4 ); // cant use counts[0]+2 because of fp grouping errors
for ( i = 0; i < in.size(); i++ ) for ( i = 0; i < in.size(); i++ )
{ {
@ -607,7 +605,7 @@ void ChopWindingInPlace( winding_t& inout, const Plane3f& plane, float epsilon )
} }
// generate a split point // generate a split point
const Vector3& p2 = in[( i + 1 ) % in.size()]; const Vector3& p2 = in[winding_next( in, i )];
const double dot = dists[i] / ( dists[i] - dists[i + 1] ); const double dot = dists[i] / ( dists[i] - dists[i + 1] );
Vector3 mid; Vector3 mid;
@ -668,7 +666,7 @@ void CheckWinding( const winding_t& w ){
} }
// check the edge isnt degenerate // check the edge isnt degenerate
const Vector3& p2 = w[( i + 1 == w.size() )? 0 : i + 1]; const Vector3& p2 = w[winding_next( w, i )];
const Vector3 dir = p2 - p1; const Vector3 dir = p2 - p1;
if ( vector3_length( dir ) < ON_EPSILON ) { if ( vector3_length( dir ) < ON_EPSILON ) {
@ -750,16 +748,19 @@ void AddWindingToConvexHull( const winding_t& w, winding_t& hull, const Vecto
hull = w; hull = w;
return; return;
} }
if( hull.size() > MAX_HULL_POINTS )
Error( "MAX_HULL_POINTS" );
numHullPoints = hull.size(); numHullPoints = hull.size();
memcpy( hullPoints, hull.data(), numHullPoints * sizeof( Vector3 ) ); memcpy( hullPoints, hull.data(), numHullPoints * sizeof( *hullPoints ) );
for ( const Vector3 &p : w ) { for ( const Vector3 &p : w ) {
const auto wrap = [numHullPoints]( int id ){
return id >= numHullPoints? id - numHullPoints : id;
};
// calculate hull side vectors // calculate hull side vectors
for ( j = 0; j < numHullPoints; j++ ) { for ( j = 0; j < numHullPoints; j++ ) {
k = ( j + 1 ) % numHullPoints; hullDirs[j] = vector3_cross( normal, VectorNormalized( hullPoints[wrap( j + 1 )] - hullPoints[j] ) );
hullDirs[j] = vector3_cross( normal, VectorNormalized( hullPoints[k] - hullPoints[j] ) );
} }
outside = false; outside = false;
@ -778,7 +779,7 @@ void AddWindingToConvexHull( const winding_t& w, winding_t& hull, const Vecto
// find the back side to front side transition // find the back side to front side transition
for ( j = 0; j < numHullPoints; j++ ) { for ( j = 0; j < numHullPoints; j++ ) {
if ( !hullSide[ j % numHullPoints ] && hullSide[ ( j + 1 ) % numHullPoints ] ) { if ( !hullSide[ j ] && hullSide[ wrap( j + 1 ) ] ) {
break; break;
} }
} }
@ -791,17 +792,17 @@ void AddWindingToConvexHull( const winding_t& w, winding_t& hull, const Vecto
numNew = 1; numNew = 1;
// copy over all points that aren't double fronts // copy over all points that aren't double fronts
j = ( j + 1 ) % numHullPoints; j = wrap( j + 1 );
for ( k = 0; k < numHullPoints; k++ ) { for ( k = 0; k < numHullPoints; k++ ) {
if ( hullSide[ ( j + k ) % numHullPoints ] && hullSide[ ( j + k + 1 ) % numHullPoints ] ) { if ( hullSide[ wrap( j + k ) ] && hullSide[ wrap( j + k + 1 ) ] ) {
continue; continue;
} }
newHullPoints[numNew] = hullPoints[ ( j + k + 1 ) % numHullPoints ]; newHullPoints[numNew] = hullPoints[ wrap( j + k + 1 ) ];
numNew++; numNew++;
} }
numHullPoints = numNew; numHullPoints = numNew;
memcpy( hullPoints, newHullPoints, numHullPoints * sizeof( Vector3 ) ); memcpy( hullPoints, newHullPoints, numHullPoints * sizeof( *hullPoints ) );
} }
hull = winding_t( hullPoints, hullPoints + numHullPoints ); hull = winding_t( hullPoints, hullPoints + numHullPoints );

View File

@ -25,6 +25,15 @@
using winding_t = std::vector<Vector3>; using winding_t = std::vector<Vector3>;
// index < w.size()
inline size_t winding_next( const winding_t& w, size_t index ){
return ++index == w.size()? 0 : index;
}
// it < w.end()
inline winding_t::iterator winding_next( winding_t& w, winding_t::iterator it ){
return ++it == w.end()? w.begin() : it;
}
#define MAX_POINTS_ON_WINDING 512 #define MAX_POINTS_ON_WINDING 512
// you can define on_epsilon in the makefile as tighter // you can define on_epsilon in the makefile as tighter

View File

@ -191,7 +191,7 @@ bool FixWinding( winding_t& w ){
/* check all verts */ /* check all verts */
for ( winding_t::iterator i = w.begin(); i != w.end(); ) for ( winding_t::iterator i = w.begin(); i != w.end(); )
{ {
winding_t::iterator j = ( std::next( i ) == w.end() )? w.begin() : std::next( i ); winding_t::iterator j = winding_next( w, i );
/* don't remove points if winding is a triangle */ /* don't remove points if winding is a triangle */
if ( w.size() == 3 ) { if ( w.size() == 3 ) {
return valid; return valid;
@ -566,10 +566,8 @@ void FilterStructuralBrushesIntoTree( entity_t *e, tree_t& tree ) {
#define EDGE_LENGTH 0.2 #define EDGE_LENGTH 0.2
bool WindingIsTiny( const winding_t& w ){ bool WindingIsTiny( const winding_t& w ){
/* /*
if (WindingArea (w) < 1) return WindingArea( w ) < 1;
return true; */
return false;
*/
int edges = 0; int edges = 0;
for ( size_t i = w.size() - 1, j = 0; j < w.size(); i = j, ++j ) for ( size_t i = w.size() - 1, j = 0; j < w.size(); i = j, ++j )

View File

@ -664,7 +664,7 @@ void AddBrushBevels( void ){
// test the non-axial plane edges // test the non-axial plane edges
for ( size_t i = 6; i < sides.size(); ++i ) { for ( size_t i = 6; i < sides.size(); ++i ) {
for ( size_t j = 0; j < sides[i].winding.size(); j++ ) { for ( size_t j = 0; j < sides[i].winding.size(); j++ ) {
Vector3 vec = sides[i].winding[j] - sides[i].winding[( ( j + 1 ) == sides[i].winding.size() )? 0 : ( j + 1 )]; Vector3 vec = sides[i].winding[j] - sides[i].winding[winding_next( sides[i].winding, j )];
if ( VectorNormalize( vec ) < 0.5f ) { if ( VectorNormalize( vec ) < 0.5f ) {
continue; continue;
} }

View File

@ -1558,14 +1558,8 @@ void CullSides( entity_t *e ){
} }
/* find second common point (regardless of winding order) */ /* find second common point (regardless of winding order) */
second = -1; second = ( ( first + 1 ) < numPoints )? ( first + 1 ) : 0;
dir = 0; dir = 0;
if ( ( first + 1 ) < numPoints ) {
second = first + 1;
}
else{
second = 0;
}
if ( vector3_equal_epsilon( w1[ 1 ], w2[ second ], CULL_EPSILON ) ) { if ( vector3_equal_epsilon( w1[ 1 ], w2[ second ], CULL_EPSILON ) ) {
dir = 1; dir = 1;
} }