more c++ in q3map2

This commit is contained in:
Garux 2021-08-10 22:41:43 +03:00
parent 99f4a4a767
commit f492ab27eb
19 changed files with 1093 additions and 1722 deletions

View File

@ -40,16 +40,7 @@ void pw( const winding_t& w ){
AllocWinding AllocWinding
============= =============
*/ */
winding_t *AllocWinding( int points ){ winding_t AllocWinding( int points ){
if ( points >= MAX_POINTS_ON_WINDING ) {
Error( "AllocWinding failed: MAX_POINTS_ON_WINDING exceeded" );
}
winding_t *w = new winding_t;
w->reserve( points );
return w;
}
winding_t AllocWinding_( int points ){
if ( points >= MAX_POINTS_ON_WINDING ) { if ( points >= MAX_POINTS_ON_WINDING ) {
Error( "AllocWinding failed: MAX_POINTS_ON_WINDING exceeded" ); Error( "AllocWinding failed: MAX_POINTS_ON_WINDING exceeded" );
} }
@ -58,18 +49,6 @@ winding_t AllocWinding_( int points ){
return w; return w;
} }
/*
=============
FreeWinding
=============
*/
void FreeWinding( winding_t *w ){
if ( !w ) {
Error( "FreeWinding: winding is NULL" );
}
delete w;
}
/* /*
============ ============
RemoveColinearPoints RemoveColinearPoints
@ -255,7 +234,7 @@ winding_accu_t BaseWindingForPlaneAccu( const Plane3& plane ){
error, and can lead to all sorts of disappearing triangle problems. error, and can lead to all sorts of disappearing triangle problems.
================= =================
*/ */
winding_t *BaseWindingForPlane( const Plane3f& plane ){ winding_t BaseWindingForPlane( const Plane3f& plane ){
int i, x; int i, x;
float max, v; float max, v;
Vector3 org, vright, vup; Vector3 org, vright, vup;
@ -302,7 +281,7 @@ winding_t *BaseWindingForPlane( const Plane3f& plane ){
vright *= MAX_WORLD_COORD * 2; vright *= MAX_WORLD_COORD * 2;
// project a really big axis aligned box onto the plane // project a really big axis aligned box onto the plane
return new winding_t{ return winding_t{
org - vright + vup, org - vright + vup,
org + vright + vup, org + vright + vup,
org + vright - vup, org + vright - vup,
@ -310,25 +289,13 @@ winding_t *BaseWindingForPlane( const Plane3f& plane ){
}; };
} }
/*
==================
CopyWinding
==================
*/
winding_t *CopyWinding( const winding_t *w ){
if ( !w ) {
Error( "CopyWinding: winding is NULL" );
}
return new winding_t( *w );
}
/* /*
================== ==================
CopyWindingAccuToRegular CopyWindingAccuToRegular
================== ==================
*/ */
winding_t *CopyWindingAccuToRegular( const winding_accu_t& w ){ winding_t CopyWindingAccuToRegular( const winding_accu_t& w ){
return new winding_t( w.begin(), w.end() ); return winding_t( w.begin(), w.end() );
} }
/* /*
@ -336,8 +303,8 @@ winding_t *CopyWindingAccuToRegular( const winding_accu_t& w ){
ReverseWinding ReverseWinding
================== ==================
*/ */
winding_t *ReverseWinding( const winding_t& w ){ winding_t ReverseWinding( const winding_t& w ){
return new winding_t( w.crbegin(), w.crend() ); return winding_t( w.crbegin(), w.crend() );
} }
@ -346,8 +313,7 @@ winding_t *ReverseWinding( const winding_t& w ){
ClipWindingEpsilon ClipWindingEpsilon
============= =============
*/ */
void ClipWindingEpsilonStrict( const winding_t& in, const Plane3f& plane, std::pair<winding_t, winding_t> ClipWindingEpsilonStrict( const winding_t& in, const Plane3f& plane, float epsilon ){
float epsilon, winding_t *&front, winding_t *&back ){
float dists[MAX_POINTS_ON_WINDING + 4]; float dists[MAX_POINTS_ON_WINDING + 4];
EPlaneSide sides[MAX_POINTS_ON_WINDING + 4]; EPlaneSide sides[MAX_POINTS_ON_WINDING + 4];
int counts[3] = { 0 }; int counts[3] = { 0 };
@ -373,41 +339,37 @@ void ClipWindingEpsilonStrict( const winding_t& in, const Plane3f& plane,
sides[i] = sides[0]; sides[i] = sides[0];
dists[i] = dists[0]; dists[i] = dists[0];
front = back = NULL;
if ( !counts[eSideFront] && !counts[eSideBack] ) { if ( !counts[eSideFront] && !counts[eSideBack] ) {
return; return {};
} }
if ( !counts[eSideFront] ) { if ( !counts[eSideFront] ) {
back = CopyWinding( &in ); return { {}, in };
return;
} }
if ( !counts[eSideBack] ) { if ( !counts[eSideBack] ) {
front = CopyWinding( &in ); return { in, {} };
return;
} }
const size_t maxpts = in.size() + 4; // cant use counts[0]+2 because const size_t maxpts = in.size() + 4; // cant use counts[0]+2 because
// of fp grouping errors // of fp grouping errors
front = AllocWinding( maxpts ); winding_t front = AllocWinding( maxpts );
back = AllocWinding( maxpts ); winding_t back = AllocWinding( maxpts );
for ( i = 0 ; i < in.size() ; i++ ) for ( i = 0; i < in.size(); i++ )
{ {
const Vector3& p1 = in[i]; const Vector3& p1 = in[i];
if ( sides[i] == eSideOn ) { if ( sides[i] == eSideOn ) {
front->push_back( p1 ); front.push_back( p1 );
back->push_back( p1 ); back.push_back( p1 );
continue; continue;
} }
if ( sides[i] == eSideFront ) { if ( sides[i] == eSideFront ) {
front->push_back( p1 ); front.push_back( p1 );
} }
if ( sides[i] == eSideBack ) { if ( sides[i] == eSideBack ) {
back->push_back( p1 ); back.push_back( p1 );
} }
if ( sides[i + 1] == eSideOn || sides[i + 1] == sides[i] ) { if ( sides[i + 1] == eSideOn || sides[i + 1] == sides[i] ) {
@ -431,22 +393,24 @@ void ClipWindingEpsilonStrict( const winding_t& in, const Plane3f& plane,
} }
} }
front->push_back( mid ); front.push_back( mid );
back->push_back( mid ); back.push_back( mid );
} }
if ( front->size() > MAX_POINTS_ON_WINDING || back->size() > MAX_POINTS_ON_WINDING ) { if ( front.size() > MAX_POINTS_ON_WINDING || back.size() > MAX_POINTS_ON_WINDING ) {
Error( "ClipWinding: MAX_POINTS_ON_WINDING" ); Error( "ClipWinding: MAX_POINTS_ON_WINDING" );
} }
return { front, back };
} }
void ClipWindingEpsilon( const winding_t& in, const Plane3f& plane, std::pair<winding_t, winding_t> ClipWindingEpsilon( const winding_t& in, const Plane3f& plane, float epsilon ){
float epsilon, winding_t *&front, winding_t *&back ){ auto [front, back] = ClipWindingEpsilonStrict( in, plane, epsilon );
ClipWindingEpsilonStrict( in, plane, epsilon, front, back );
/* apparently most code expects that in the winding-on-plane case, the back winding is the original winding */ /* apparently most code expects that in the winding-on-plane case, the back winding is the original winding */
if ( !front && !back ) { if ( front.empty() && back.empty() ) {
back = CopyWinding( &in ); back = in;
} }
return { front, back };
} }
@ -587,8 +551,8 @@ void ChopWindingInPlaceAccu( winding_accu_t& inout, const Plane3& plane, float c
ChopWindingInPlace ChopWindingInPlace
============= =============
*/ */
void ChopWindingInPlace( winding_t *&inout, const Plane3f& plane, float epsilon ){ void ChopWindingInPlace( winding_t& inout, const Plane3f& plane, float epsilon ){
winding_t& in = *inout; const winding_t& in = inout;
float dists[MAX_POINTS_ON_WINDING + 4]; float dists[MAX_POINTS_ON_WINDING + 4];
EPlaneSide sides[MAX_POINTS_ON_WINDING + 4]; EPlaneSide sides[MAX_POINTS_ON_WINDING + 4];
int counts[3] = { 0 }; int counts[3] = { 0 };
@ -614,8 +578,7 @@ void ChopWindingInPlace( winding_t *&inout, const Plane3f& plane, float epsilon
dists[i] = dists[0]; dists[i] = dists[0];
if ( !counts[eSideFront] ) { if ( !counts[eSideFront] ) {
FreeWinding( inout ); inout.clear();
inout = NULL;
return; return;
} }
if ( !counts[eSideBack] ) { if ( !counts[eSideBack] ) {
@ -668,27 +631,7 @@ void ChopWindingInPlace( winding_t *&inout, const Plane3f& plane, float epsilon
Error( "ClipWinding: MAX_POINTS_ON_WINDING" ); Error( "ClipWinding: MAX_POINTS_ON_WINDING" );
} }
inout->swap( f ); inout.swap( f );
}
/*
=================
ChopWinding
Returns the fragment of in that is on the front side
of the cliping plane. The original is freed.
=================
*/
winding_t *ChopWinding( winding_t *in, const Plane3f& plane ){
winding_t *f, *b;
ClipWindingEpsilon( *in, plane, ON_EPSILON, f, b );
FreeWinding( in );
if ( b ) {
FreeWinding( b );
}
return f;
} }
@ -794,7 +737,7 @@ EPlaneSide WindingOnPlaneSide( const winding_t& w, const Plane3f& plane ){
================= =================
*/ */
#define MAX_HULL_POINTS 128 #define MAX_HULL_POINTS 128
void AddWindingToConvexHull( const winding_t& w, winding_t *&hull, const Vector3& normal ) { void AddWindingToConvexHull( const winding_t& w, winding_t& hull, const Vector3& normal ) {
int j, k; int j, k;
int numHullPoints, numNew; int numHullPoints, numNew;
Vector3 hullPoints[MAX_HULL_POINTS]; Vector3 hullPoints[MAX_HULL_POINTS];
@ -803,13 +746,13 @@ void AddWindingToConvexHull( const winding_t& w, winding_t *&hull, const Vect
bool hullSide[MAX_HULL_POINTS]; bool hullSide[MAX_HULL_POINTS];
bool outside; bool outside;
if ( hull == nullptr ) { if ( hull.empty() ) {
hull = CopyWinding( &w ); hull = w;
return; return;
} }
numHullPoints = hull->size(); numHullPoints = hull.size();
memcpy( hullPoints, hull->data(), numHullPoints * sizeof( Vector3 ) ); memcpy( hullPoints, hull.data(), numHullPoints * sizeof( Vector3 ) );
for ( const Vector3 &p : w ) { for ( const Vector3 &p : w ) {
// calculate hull side vectors // calculate hull side vectors
@ -861,5 +804,5 @@ void AddWindingToConvexHull( const winding_t& w, winding_t *&hull, const Vect
memcpy( hullPoints, newHullPoints, numHullPoints * sizeof( Vector3 ) ); memcpy( hullPoints, newHullPoints, numHullPoints * sizeof( Vector3 ) );
} }
*hull = winding_t( hullPoints, hullPoints + numHullPoints ); hull = winding_t( hullPoints, hullPoints + numHullPoints );
} }

View File

@ -40,28 +40,22 @@ enum EPlaneSide
eSideCross = 3, eSideCross = 3,
}; };
winding_t *AllocWinding( int points ); winding_t AllocWinding( int points );
winding_t AllocWinding_( int points );
float WindingArea( const winding_t& w ); float WindingArea( const winding_t& w );
Vector3 WindingCenter( const winding_t& w ); Vector3 WindingCenter( const winding_t& w );
void ClipWindingEpsilon( const winding_t& in, const Plane3f& plane, std::pair<winding_t, winding_t> ClipWindingEpsilon( const winding_t& in, const Plane3f& plane, float epsilon ); // returns { front, back } windings pair
float epsilon, winding_t *&front, winding_t *&back ); std::pair<winding_t, winding_t> ClipWindingEpsilonStrict( const winding_t& in, const Plane3f& plane, float epsilon ); // returns { front, back } windings pair
void ClipWindingEpsilonStrict( const winding_t& in, const Plane3f& plane, winding_t ReverseWinding( const winding_t& w );
float epsilon, winding_t *&front, winding_t *&back ); winding_t BaseWindingForPlane( const Plane3f& plane );
winding_t *ChopWinding( winding_t *in, const Plane3f& plane );
winding_t *CopyWinding( const winding_t *w );
winding_t *ReverseWinding( const winding_t& w );
winding_t *BaseWindingForPlane( const Plane3f& plane );
void CheckWinding( const winding_t& w ); void CheckWinding( const winding_t& w );
Plane3f WindingPlane( const winding_t& w ); Plane3f WindingPlane( const winding_t& w );
void RemoveColinearPoints( winding_t& w ); void RemoveColinearPoints( winding_t& w );
EPlaneSide WindingOnPlaneSide( const winding_t& w, const Plane3f& plane ); EPlaneSide WindingOnPlaneSide( const winding_t& w, const Plane3f& plane );
void FreeWinding( winding_t *w );
void WindingExtendBounds( const winding_t& w, MinMax& minmax ); void WindingExtendBounds( const winding_t& w, MinMax& minmax );
void AddWindingToConvexHull( const winding_t& w, winding_t *&hull, const Vector3& normal ); void AddWindingToConvexHull( const winding_t& w, winding_t& hull, const Vector3& normal );
void ChopWindingInPlace( winding_t *&w, const Plane3f& plane, float epsilon ); void ChopWindingInPlace( winding_t& w, const Plane3f& plane, float epsilon );
// frees the original if clipped // frees the original if clipped
void pw( const winding_t& w ); void pw( const winding_t& w );
@ -76,4 +70,4 @@ using winding_accu_t = std::vector<DoubleVector3>;
winding_accu_t BaseWindingForPlaneAccu( const Plane3& plane ); winding_accu_t BaseWindingForPlaneAccu( const Plane3& plane );
void ChopWindingInPlaceAccu( winding_accu_t& w, const Plane3& plane, float epsilon ); void ChopWindingInPlaceAccu( winding_accu_t& w, const Plane3& plane, float epsilon );
winding_t *CopyWindingAccuToRegular( const winding_accu_t& w ); winding_t CopyWindingAccuToRegular( const winding_accu_t& w );

View File

@ -44,17 +44,14 @@
allocates and assigns a brush side reference allocates and assigns a brush side reference
*/ */
sideRef_t *AllocSideRef( side_t *side, sideRef_t *next ){ sideRef_t *AllocSideRef( const side_t *side, sideRef_t *next ){
sideRef_t *sideRef;
/* dummy check */ /* dummy check */
if ( side == NULL ) { if ( side == NULL ) {
return next; return next;
} }
/* allocate and return */ /* allocate and return */
sideRef = safe_malloc( sizeof( *sideRef ) ); sideRef_t *sideRef = safe_malloc( sizeof( *sideRef ) );
sideRef->side = side; sideRef->side = side;
sideRef->next = next; sideRef->next = next;
return sideRef; return sideRef;
@ -62,110 +59,6 @@ sideRef_t *AllocSideRef( side_t *side, sideRef_t *next ){
/*
CountBrushList()
counts the number of brushes in a brush linked list
*/
int CountBrushList( brush_t *brushes ){
int c = 0;
/* count brushes */
for ( ; brushes != NULL; brushes = brushes->next )
c++;
return c;
}
/*
AllocBrush()
allocates a new brush
*/
brush_t *AllocBrush( int numSides ){
return safe_calloc( offsetof_array( brush_t, sides, numSides ) );
}
/*
FreeBrush()
frees a single brush and all sides/windings
*/
void FreeBrush( brush_t *b ){
int i;
/* error check */
if ( *( (unsigned int*) b ) == 0xFEFEFEFE ) {
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "WARNING: Attempt to free an already freed brush!\n" );
return;
}
/* free brush sides */
for ( i = 0; i < b->numsides; i++ )
if ( b->sides[i].winding != NULL ) {
FreeWinding( b->sides[ i ].winding );
}
/* ydnar: overwrite it */
memset( b, 0xFE, offsetof_array( brush_t, sides, b->numsides ) );
*( (unsigned int*) b ) = 0xFEFEFEFE;
/* free it */
free( b );
}
/*
FreeBrushList()
frees a linked list of brushes
*/
void FreeBrushList( brush_t *brushes ){
brush_t *next;
/* walk brush list */
for ( ; brushes != NULL; brushes = next )
{
next = brushes->next;
FreeBrush( brushes );
}
}
/*
CopyBrush()
duplicates the brush, sides, and windings
*/
brush_t *CopyBrush( const brush_t *brush ){
/* copy brush */
brush_t *newBrush = AllocBrush( brush->numsides );
memcpy( newBrush, brush, offsetof_array( brush_t, sides, brush->numsides ) );
/* ydnar: nuke linked list */
newBrush->next = NULL;
/* copy sides */
for ( int i = 0; i < brush->numsides; i++ )
{
if ( brush->sides[ i ].winding != NULL ) {
newBrush->sides[ i ].winding = CopyWinding( brush->sides[ i ].winding );
}
}
/* return it */
return newBrush;
}
/* /*
@ -174,17 +67,14 @@ brush_t *CopyBrush( const brush_t *brush ){
returns false if the brush doesn't enclose a valid volume returns false if the brush doesn't enclose a valid volume
*/ */
bool BoundBrush( brush_t *brush ){ bool BoundBrush( brush_t& brush ){
brush->minmax.clear(); brush.minmax.clear();
for ( int i = 0; i < brush->numsides; i++ ) for ( const side_t& side : brush.sides )
{ {
const winding_t *w = brush->sides[ i ].winding; WindingExtendBounds( side.winding, brush.minmax );
if ( w != NULL ) {
WindingExtendBounds( *w, brush->minmax );
}
} }
return brush->minmax.valid() && c_worldMinmax.surrounds( brush->minmax ); return brush.minmax.valid() && c_worldMinmax.surrounds( brush.minmax );
} }
@ -290,19 +180,20 @@ DoubleVector3 SnapWeldVectorAccu( const DoubleVector3& a, const DoubleVector3& b
#define DEGENERATE_EPSILON 0.1 #define DEGENERATE_EPSILON 0.1
bool FixWinding( winding_t *w ){ bool FixWinding( winding_t& w ){
bool valid = true; bool valid = true;
/* dummy check */ /* dummy check */
if ( !w ) { if ( w.empty() ) {
return false; return false;
} }
/* check all verts */ /* check all verts */
for ( winding_t::iterator i = w->end() - 1, j = w->begin(); j != w->end(); i = j, ++j ) for ( winding_t::iterator i = w.begin(); i != w.end(); )
{ {
winding_t::iterator j = ( std::next( i ) == w.end() )? w.begin() : std::next( 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;
} }
@ -312,17 +203,20 @@ bool FixWinding( winding_t *w ){
//Sys_FPrintf( SYS_WRN | SYS_VRBflag, "WARNING: Degenerate winding edge found, fixing...\n" ); //Sys_FPrintf( SYS_WRN | SYS_VRBflag, "WARNING: Degenerate winding edge found, fixing...\n" );
/* create an average point (ydnar 2002-01-26: using nearest-integer weld preference) */ /* create an average point (ydnar 2002-01-26: using nearest-integer weld preference) */
*i = SnapWeldVector( *i, *j ); *j = SnapWeldVector( *i, *j );
//VectorAdd( w->p[ i ], w->p[ j ], vec ); //VectorAdd( w[ i ], w[ j ], vec );
//VectorScale( vec, 0.5, w->p[ i ] ); //VectorScale( vec, 0.5, w[ i ] );
/* move the remaining verts */ /* move the remaining verts */
w->erase( j ); i = w.erase( i );
}
else{
++i;
} }
} }
/* one last check and return */ /* one last check and return */
if ( w->size() < 3 ) { if ( w.size() < 3 ) {
valid = false; valid = false;
} }
return valid; return valid;
@ -387,25 +281,25 @@ bool FixWindingAccu( winding_accu_t& w ){
returns false if the brush doesn't enclose a valid volume returns false if the brush doesn't enclose a valid volume
*/ */
bool CreateBrushWindings( brush_t *brush ){ bool CreateBrushWindings( brush_t& brush ){
/* walk the list of brush sides */ /* walk the list of brush sides */
for ( int i = 0; i < brush->numsides; i++ ) for ( size_t i = 0; i < brush.sides.size(); ++i )
{ {
/* get side and plane */ /* get side and plane */
side_t& side = brush->sides[ i ]; side_t& side = brush.sides[ i ];
const plane_t& plane = mapplanes[ side.planenum ]; const plane_t& plane = mapplanes[ side.planenum ];
/* make huge winding */ /* make huge winding */
#if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES #if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
winding_accu_t 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 #else
winding_t *w = BaseWindingForPlane( plane.plane ); winding_t w = BaseWindingForPlane( plane.plane );
#endif #endif
/* walk the list of brush sides */ /* walk the list of brush sides */
for ( int j = 0; j < brush->numsides && !w.empty(); j++ ) for ( size_t j = 0; j < brush.sides.size() && !w.empty(); ++j )
{ {
const side_t& cside = brush->sides[ j ]; const side_t& cside = brush.sides[ j ];
const plane_t& cplane = mapplanes[ cside.planenum ^ 1 ]; const plane_t& cplane = mapplanes[ cside.planenum ^ 1 ];
if ( i == j if ( i == j
|| cside.planenum == ( side.planenum ^ 1 ) /* back side clipaway */ || cside.planenum == ( side.planenum ^ 1 ) /* back side clipaway */
@ -432,9 +326,12 @@ bool CreateBrushWindings( brush_t *brush ){
/* set side winding */ /* set side winding */
#if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES #if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
FixWindingAccu( w ); FixWindingAccu( w );
side.winding = ( w.size() >= 3 ? CopyWindingAccuToRegular( w ) : NULL ); if( w.size() >= 3 )
side.winding = CopyWindingAccuToRegular( w );
else
side.winding.clear();
#else #else
side.winding = w; side.winding.swap( w );
#endif #endif
} }
@ -452,20 +349,16 @@ bool CreateBrushWindings( brush_t *brush ){
Creates a new axial brush Creates a new axial brush
================== ==================
*/ */
brush_t *BrushFromBounds( const Vector3& mins, const Vector3& maxs ){ brush_t BrushFromBounds( const Vector3& mins, const Vector3& maxs ){
brush_t *b; brush_t b;
int i; b.sides.resize( 6 );
float dist; for ( int i = 0 ; i < 3 ; i++ )
b = AllocBrush( 6 );
b->numsides = 6;
for ( i = 0 ; i < 3 ; i++ )
{ {
dist = maxs[i]; float dist = maxs[i];
b->sides[i].planenum = FindFloatPlane( g_vector3_axes[i], dist, 1, &maxs ); b.sides[i].planenum = FindFloatPlane( g_vector3_axes[i], dist, 1, &maxs );
dist = -mins[i]; dist = -mins[i];
b->sides[3 + i].planenum = FindFloatPlane( -g_vector3_axes[i], dist, 1, &mins ); b.sides[3 + i].planenum = FindFloatPlane( -g_vector3_axes[i], dist, 1, &mins );
} }
CreateBrushWindings( b ); CreateBrushWindings( b );
@ -479,45 +372,25 @@ brush_t *BrushFromBounds( const Vector3& mins, const Vector3& maxs ){
================== ==================
*/ */
float BrushVolume( brush_t *brush ){ float BrushVolume( const brush_t& brush ){
int i; float volume = 0;
const winding_t *w;
Vector3 corner;
float volume;
if ( !brush ) { for ( auto i = brush.sides.cbegin(); i != brush.sides.cend(); ++i ){
return 0; // grab the first valid point as the corner
} if( !i->winding.empty() ){
const Vector3 corner = i->winding[0];
// grab the first valid point as the corner // make tetrahedrons to all other faces
for ( ++i; i != brush.sides.cend(); ++i )
w = NULL; {
for ( i = 0 ; i < brush->numsides ; i++ ) if ( !i->winding.empty() ) {
{ volume += -plane3_distance_to_point( mapplanes[i->planenum].plane, corner ) * WindingArea( i->winding );
w = brush->sides[i].winding; }
if ( w ) { }
break; break;
} }
} }
if ( !w ) {
return 0;
}
corner = ( *w )[0];
// make tetrahedrons to all other faces return volume / 3;
volume = 0;
for ( ; i < brush->numsides ; i++ )
{
w = brush->sides[i].winding;
if ( !w ) {
continue;
}
volume += -plane3_distance_to_point( mapplanes[brush->sides[i].planenum].plane, corner ) * WindingArea( *w );
}
volume /= 3;
return volume;
} }
@ -527,10 +400,7 @@ float BrushVolume( brush_t *brush ){
writes a map with the split bsp brushes writes a map with the split bsp brushes
*/ */
void WriteBSPBrushMap( const char *name, brush_t *list ){ void WriteBSPBrushMap( const char *name, const brushlist_t& list ){
side_t *s;
int i;
/* note it */ /* note it */
Sys_Printf( "Writing %s\n", name ); Sys_Printf( "Writing %s\n", name );
@ -539,22 +409,20 @@ void WriteBSPBrushMap( const char *name, brush_t *list ){
fprintf( f, "{\n\"classname\" \"worldspawn\"\n" ); fprintf( f, "{\n\"classname\" \"worldspawn\"\n" );
for ( ; list; list = list->next ) for ( const brush_t& brush : list )
{ {
fprintf( f, "{\n" ); fprintf( f, "{\n" );
for ( i = 0, s = list->sides; i < list->numsides; i++, s++ ) for ( const side_t& side : brush.sides )
{ {
// TODO: See if we can use a smaller winding to prevent resolution loss. // TODO: See if we can use a smaller winding to prevent resolution loss.
// Is WriteBSPBrushMap() used only to decompile maps? // Is WriteBSPBrushMap() used only to decompile maps?
winding_t *w = BaseWindingForPlane( mapplanes[s->planenum].plane ); const winding_t w = BaseWindingForPlane( mapplanes[side.planenum].plane );
const winding_t& wr = *w;
fprintf( f, "( %i %i %i ) ", (int)wr[0][0], (int)wr[0][1], (int)wr[0][2] ); fprintf( f, "( %i %i %i ) ", (int)w[0][0], (int)w[0][1], (int)w[0][2] );
fprintf( f, "( %i %i %i ) ", (int)wr[1][0], (int)wr[1][1], (int)wr[1][2] ); fprintf( f, "( %i %i %i ) ", (int)w[1][0], (int)w[1][1], (int)w[1][2] );
fprintf( f, "( %i %i %i ) ", (int)wr[2][0], (int)wr[2][1], (int)wr[2][2] ); fprintf( f, "( %i %i %i ) ", (int)w[2][0], (int)w[2][1], (int)w[2][2] );
fprintf( f, "notexture 0 0 0 1 1\n" ); fprintf( f, "notexture 0 0 0 1 1\n" );
FreeWinding( w );
} }
fprintf( f, "}\n" ); fprintf( f, "}\n" );
} }
@ -571,11 +439,7 @@ void WriteBSPBrushMap( const char *name, brush_t *list ){
adds brush reference to any intersecting bsp leafnode adds brush reference to any intersecting bsp leafnode
*/ */
int FilterBrushIntoTree_r( brush_t *b, node_t *node ){ int FilterBrushIntoTree_r( brush_t* b, node_t *node ){
brush_t *front, *back;
int c;
/* dummy check */ /* dummy check */
if ( b == NULL ) { if ( b == NULL ) {
return 0; return 0;
@ -584,8 +448,7 @@ int FilterBrushIntoTree_r( brush_t *b, node_t *node ){
/* add it to the leaf list */ /* add it to the leaf list */
if ( node->planenum == PLANENUM_LEAF ) { if ( node->planenum == PLANENUM_LEAF ) {
/* something somewhere is hammering brushlist */ /* something somewhere is hammering brushlist */
b->next = node->brushlist; node->brushlist.push_front( std::move( *b ) );
node->brushlist = b;
/* classify the leaf by the structural brush */ /* classify the leaf by the structural brush */
if ( !b->detail ) { if ( !b->detail ) {
@ -604,11 +467,10 @@ int FilterBrushIntoTree_r( brush_t *b, node_t *node ){
} }
/* split it by the node plane */ /* split it by the node plane */
c = b->numsides; auto [front, back] = SplitBrush( *b, node->planenum );
SplitBrush( b, node->planenum, &front, &back ); delete b;
FreeBrush( b );
c = 0; int c = 0;
c += FilterBrushIntoTree_r( front, node->children[ 0 ] ); c += FilterBrushIntoTree_r( front, node->children[ 0 ] );
c += FilterBrushIntoTree_r( back, node->children[ 1 ] ); c += FilterBrushIntoTree_r( back, node->children[ 1 ] );
@ -622,11 +484,8 @@ int FilterBrushIntoTree_r( brush_t *b, node_t *node ){
fragment all the detail brushes into the structural leafs fragment all the detail brushes into the structural leafs
*/ */
void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree ){ void FilterDetailBrushesIntoTree( entity_t *e, tree_t& tree ){
brush_t *b, *newb; int c_unique = 0, c_clusters = 0;
int r;
int c_unique, c_clusters;
int i;
/* note it */ /* note it */
@ -635,22 +494,21 @@ void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree ){
/* walk the list of brushes */ /* walk the list of brushes */
c_unique = 0; c_unique = 0;
c_clusters = 0; c_clusters = 0;
for ( b = e->brushes; b; b = b->next ) for ( brush_t& b : e->brushes )
{ {
if ( !b->detail ) { if ( !b.detail ) {
continue; continue;
} }
c_unique++; c_unique++;
newb = CopyBrush( b ); const int r = FilterBrushIntoTree_r( new brush_t( b ), tree.headnode );
r = FilterBrushIntoTree_r( newb, tree->headnode );
c_clusters += r; c_clusters += r;
/* mark all sides as visible so drawsurfs are created */ /* mark all sides as visible so drawsurfs are created */
if ( r ) { if ( r ) {
for ( i = 0; i < b->numsides; i++ ) for ( side_t& side : b.sides )
{ {
if ( b->sides[ i ].winding ) { if ( !side.winding.empty() ) {
b->sides[ i ].visible = true; side.visible = true;
} }
} }
} }
@ -668,30 +526,24 @@ void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree ){
Mark the leafs as opaque and areaportals Mark the leafs as opaque and areaportals
===================== =====================
*/ */
void FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree ) { void FilterStructuralBrushesIntoTree( entity_t *e, tree_t& tree ) {
brush_t *b, *newb; int c_unique = 0, c_clusters = 0;
int r;
int c_unique, c_clusters;
int i;
Sys_FPrintf( SYS_VRB, "--- FilterStructuralBrushesIntoTree ---\n" ); Sys_FPrintf( SYS_VRB, "--- FilterStructuralBrushesIntoTree ---\n" );
c_unique = 0; for ( brush_t& b : e->brushes ) {
c_clusters = 0; if ( b.detail ) {
for ( b = e->brushes ; b ; b = b->next ) {
if ( b->detail ) {
continue; continue;
} }
c_unique++; c_unique++;
newb = CopyBrush( b ); const int r = FilterBrushIntoTree_r( new brush_t( b ), tree.headnode );
r = FilterBrushIntoTree_r( newb, tree->headnode );
c_clusters += r; c_clusters += r;
// mark all sides as visible so drawsurfs are created // mark all sides as visible so drawsurfs are created
if ( r ) { if ( r ) {
for ( i = 0 ; i < b->numsides ; i++ ) { for ( side_t& side : b.sides ) {
if ( b->sides[i].winding ) { if ( !side.winding.empty() ) {
b->sides[i].visible = true; side.visible = true;
} }
} }
} }
@ -703,28 +555,6 @@ void FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree ) {
} }
/*
================
AllocTree
================
*/
tree_t *AllocTree( void ){
tree_t *tree = safe_calloc( sizeof( *tree ) );
tree->minmax.clear();
return tree;
}
/*
================
AllocNode
================
*/
node_t *AllocNode( void ){
return safe_calloc( sizeof( node_t ) );
}
/* /*
================ ================
WindingIsTiny WindingIsTiny
@ -776,24 +606,21 @@ bool WindingIsHuge( const winding_t& w ){
================== ==================
*/ */
int BrushMostlyOnSide( brush_t *brush, plane_t *plane ){ int BrushMostlyOnSide( const brush_t& brush, const Plane3f& plane ){
float max = 0; float max = 0;
int side = PSIDE_FRONT; int side = PSIDE_FRONT;
for ( int i = 0 ; i < brush->numsides ; i++ ) for ( const side_t& s : brush.sides )
{ {
winding_t *w = brush->sides[i].winding; for ( const Vector3& p : s.winding )
if ( w ) { {
for ( const Vector3& p : *w ) const double d = plane3_distance_to_point( plane, p );
{ if ( d > max ) {
const double d = plane3_distance_to_point( plane->plane, p ); max = d;
if ( d > max ) { side = PSIDE_FRONT;
max = d; }
side = PSIDE_FRONT; if ( -d > max ) {
} max = -d;
if ( -d > max ) { side = PSIDE_BACK;
max = -d;
side = PSIDE_BACK;
}
} }
} }
} }
@ -807,30 +634,16 @@ int BrushMostlyOnSide( brush_t *brush, plane_t *plane ){
generates two new brushes, leaving the original unchanged generates two new brushes, leaving the original unchanged
*/ */
void SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back ){ std::pair<brush_t*, brush_t*> SplitBrush( const brush_t& brush, int planenum ){
brush_t *b[2]; const Plane3f& plane = mapplanes[planenum].plane;
int i, j;
winding_t *w, *cw[2], *midwinding;
plane_t *plane, *plane2;
side_t *s, *cs;
float d_front, d_back;
*front = NULL;
*back = NULL;
plane = &mapplanes[planenum];
// check all points // check all points
d_front = d_back = 0; float d_front = 0, d_back = 0;
for ( i = 0 ; i < brush->numsides ; i++ ) for ( const side_t& side : brush.sides )
{ {
w = brush->sides[i].winding; for ( const Vector3& p : side.winding )
if ( !w ) {
continue;
}
for ( const Vector3& p : *w )
{ {
const float d = plane3_distance_to_point( plane->plane, p ); const float d = plane3_distance_to_point( plane, p );
if ( d > 0 ) { if ( d > 0 ) {
value_maximize( d_front, d ); value_maximize( d_front, d );
} }
@ -842,140 +655,117 @@ void SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back )
if ( d_front < 0.1 ) { // PLANESIDE_EPSILON) if ( d_front < 0.1 ) { // PLANESIDE_EPSILON)
// only on back // only on back
*back = CopyBrush( brush ); return { {}, new brush_t( brush ) };
return;
} }
if ( d_back > -0.1 ) { // PLANESIDE_EPSILON) if ( d_back > -0.1 ) { // PLANESIDE_EPSILON)
// only on front // only on front
*front = CopyBrush( brush ); return { new brush_t( brush ), {} };
return;
} }
// create a new winding from the split plane // create a new winding from the split plane
w = BaseWindingForPlane( plane->plane ); winding_t midwinding = BaseWindingForPlane( plane );
for ( i = 0 ; i < brush->numsides && w ; i++ ) for ( const side_t& side : brush.sides )
{ {
plane2 = &mapplanes[brush->sides[i].planenum ^ 1]; ChopWindingInPlace( midwinding, mapplanes[side.planenum ^ 1].plane, 0 ); // PLANESIDE_EPSILON);
ChopWindingInPlace( w, plane2->plane, 0 ); // PLANESIDE_EPSILON); if( midwinding.empty() )
break;
} }
if ( !w || WindingIsTiny( *w ) ) { // the brush isn't really split if ( midwinding.empty() || WindingIsTiny( midwinding ) ) { // the brush isn't really split
int side; const int side = BrushMostlyOnSide( brush, plane );
side = BrushMostlyOnSide( brush, plane );
if ( side == PSIDE_FRONT ) {
*front = CopyBrush( brush );
}
if ( side == PSIDE_BACK ) { if ( side == PSIDE_BACK ) {
*back = CopyBrush( brush ); return { {}, new brush_t( brush ) };
}
else { // side == PSIDE_FRONT
return { new brush_t( brush ), {} };
} }
return;
} }
if ( WindingIsHuge( *w ) ) { if ( WindingIsHuge( midwinding ) ) {
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "WARNING: huge winding\n" ); Sys_FPrintf( SYS_WRN | SYS_VRBflag, "WARNING: huge winding\n" );
} }
midwinding = w;
// split it for real // split it for real
brush_t *b[2];
for ( i = 0 ; i < 2 ; i++ ) for ( int i = 0; i < 2; i++ )
{ {
b[i] = AllocBrush( brush->numsides + 1 ); b[i] = new brush_t( brush );
memcpy( b[i], brush, sizeof( brush_t ) ); b[i]->sides.clear();
b[i]->numsides = 0;
b[i]->next = NULL;
b[i]->original = brush->original;
} }
// split all the current windings // split all the current windings
for ( i = 0 ; i < brush->numsides ; i++ ) for ( const side_t& side : brush.sides )
{ {
s = &brush->sides[i]; if ( !side.winding.empty() ) {
w = s->winding; winding_t cw[2];
if ( !w ) { std::tie( cw[0], cw[1] ) =
continue; ClipWindingEpsilonStrict( side.winding, plane, 0 /*PLANESIDE_EPSILON*/ ); /* strict, in parallel case we get the face back because it also is the midwinding */
} for ( int i = 0; i < 2; i++ )
ClipWindingEpsilonStrict( *w, plane->plane, {
0 /*PLANESIDE_EPSILON*/, cw[0], cw[1] ); /* strict, in parallel case we get the face back because it also is the midwinding */ if ( !cw[i].empty() ) {
for ( j = 0 ; j < 2 ; j++ ) side_t& cs = b[i]->sides.emplace_back( side );
{ cs.winding.swap( cw[i] );
if ( !cw[j] ) { }
continue;
} }
cs = &b[j]->sides[b[j]->numsides];
b[j]->numsides++;
*cs = *s;
cs->winding = cw[j];
} }
} }
// see if we have valid polygons on both sides // see if we have valid polygons on both sides
for ( i = 0 ; i < 2 ; i++ ) for ( int i = 0; i < 2; i++ )
{ {
if ( b[i]->numsides < 3 || !BoundBrush( b[i] ) ) { if ( b[i]->sides.size() < 3 || !BoundBrush( *b[i] ) ) {
if ( b[i]->numsides >= 3 ) { if ( b[i]->sides.size() >= 3 ) {
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "bogus brush after clip\n" ); Sys_FPrintf( SYS_WRN | SYS_VRBflag, "bogus brush after clip\n" );
} }
FreeBrush( b[i] ); delete b[i];
b[i] = NULL; b[i] = NULL;
} }
} }
if ( !( b[0] && b[1] ) ) { if ( b[0] == nullptr || b[1] == nullptr ) {
if ( !b[0] && !b[1] ) { if ( b[0] == nullptr && b[1] == nullptr ) {
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "split removed brush\n" ); Sys_FPrintf( SYS_WRN | SYS_VRBflag, "split removed brush\n" );
} }
else{ else{
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "split not on both sides\n" ); Sys_FPrintf( SYS_WRN | SYS_VRBflag, "split not on both sides\n" );
} }
if ( b[0] ) { if ( b[0] != nullptr ) {
FreeBrush( b[0] ); delete b[0];
*front = CopyBrush( brush ); return { new brush_t( brush ), {} };
} }
if ( b[1] ) { else if ( b[1] != nullptr ) {
FreeBrush( b[1] ); delete b[1];
*back = CopyBrush( brush ); return { {}, new brush_t( brush ) };
} }
return; return{};
} }
// add the midwinding to both sides // add the midwinding to both sides
for ( i = 0 ; i < 2 ; i++ ) for ( int i = 0; i < 2; i++ )
{ {
cs = &b[i]->sides[b[i]->numsides]; side_t& cs = b[i]->sides.emplace_back();
b[i]->numsides++;
cs->planenum = planenum ^ i ^ 1; cs.planenum = planenum ^ i ^ 1;
cs->shaderInfo = NULL; cs.shaderInfo = NULL;
if ( i == 0 ) { if ( i == 0 ) {
cs->winding = CopyWinding( midwinding ); cs.winding = midwinding; // copy
} }
else{ else{
cs->winding = midwinding; cs.winding.swap( midwinding ); // move
} }
} }
for ( int i = 0; i < 2; i++ )
{ {
float v1; if ( BrushVolume( *b[i] ) < 1.0 ) {
int i; delete b[i];
b[i] = NULL;
// Sys_FPrintf( SYS_WRN | SYS_VRBflag, "tiny volume after clip\n" );
for ( i = 0 ; i < 2 ; i++ )
{
v1 = BrushVolume( b[i] );
if ( v1 < 1.0 ) {
FreeBrush( b[i] );
b[i] = NULL;
// Sys_FPrintf( SYS_WRN | SYS_VRBflag, "tiny volume after clip\n" );
}
} }
} }
*front = b[0]; return{ b[0], b[1] };
*back = b[1];
} }

View File

@ -47,11 +47,11 @@ static void autocaulk_write(){
int flava = 8; int flava = 8;
ApplySurfaceParm( "lava", &flava, NULL, NULL ); ApplySurfaceParm( "lava", &flava, NULL, NULL );
for ( brush_t* b = entities[0].brushes; b; b = b->next ) { for ( const brush_t& b : entities[0].brushes ) {
fprintf( file, "%i ", b->brushNum ); fprintf( file, "%i ", b.brushNum );
shaderInfo_t* contentShader = b->contentShader; const shaderInfo_t* contentShader = b.contentShader;
for( int i = 0; i < b->numsides; ++i ){ for( const side_t& side : b.sides ){
if( b->sides[i].visibleHull || ( b->sides[i].compileFlags & C_NODRAW ) ){ if( !side.visibleHull.empty() || ( side.compileFlags & C_NODRAW ) ){
fprintf( file, "-" ); fprintf( file, "-" );
} }
else if( contentShader->compileFlags & C_LIQUID ){ else if( contentShader->compileFlags & C_LIQUID ){
@ -62,7 +62,7 @@ static void autocaulk_write(){
else else
fprintf( file, "w" ); fprintf( file, "w" );
} }
else if( b->compileFlags & C_TRANSLUCENT ){ else if( b.compileFlags & C_TRANSLUCENT ){
if( contentShader->compileFlags & C_SOLID ) if( contentShader->compileFlags & C_SOLID )
fprintf( file, "N" ); fprintf( file, "N" );
else else
@ -170,7 +170,7 @@ static void SetCloneModelNumbers( void ){
for ( std::size_t i = 1; i < entities.size(); ++i ) for ( std::size_t i = 1; i < entities.size(); ++i )
{ {
/* only entities with brushes or patches get a model number */ /* only entities with brushes or patches get a model number */
if ( entities[ i ].brushes == NULL && entities[ i ].patches == NULL ) { if ( entities[ i ].brushes.empty() && entities[ i ].patches == NULL ) {
continue; continue;
} }
@ -190,7 +190,7 @@ static void SetCloneModelNumbers( void ){
for ( std::size_t i = 1; i < entities.size(); ++i ) for ( std::size_t i = 1; i < entities.size(); ++i )
{ {
/* only entities with brushes or patches get a model number */ /* only entities with brushes or patches get a model number */
if ( entities[ i ].brushes == NULL && entities[ i ].patches == NULL ) { if ( entities[ i ].brushes.empty() && entities[ i ].patches == NULL ) {
continue; continue;
} }
@ -220,7 +220,7 @@ static void SetCloneModelNumbers( void ){
entities[ i ].setKeyValue( "model", modelValue ); entities[ i ].setKeyValue( "model", modelValue );
/* nuke the brushes/patches for this entity (fixme: leak!) */ /* nuke the brushes/patches for this entity (fixme: leak!) */
entities[ i ].brushes = NULL; brushlist_t *leak = new brushlist_t( std::move( entities[ i ].brushes ) ); // are brushes referenced elsewhere, so we do not nuke them really?
entities[ i ].patches = NULL; entities[ i ].patches = NULL;
} }
} }
@ -284,8 +284,6 @@ static void FixBrushSides( entity_t *e ){
void ProcessWorldModel( void ){ void ProcessWorldModel( void ){
entity_t *e; entity_t *e;
tree_t *tree;
facelist_t faces;
xmlNodePtr polyline, leaknode; xmlNodePtr polyline, leaknode;
char level[ 2 ]; char level[ 2 ];
const char *value; const char *value;
@ -321,8 +319,8 @@ void ProcessWorldModel( void ){
} }
/* build an initial bsp tree using all of the sides of all of the structural brushes */ /* build an initial bsp tree using all of the sides of all of the structural brushes */
faces = MakeStructuralBSPFaceList( entities[ 0 ].brushes ); facelist_t faces = MakeStructuralBSPFaceList( entities[ 0 ].brushes );
tree = FaceBSP( faces ); tree_t tree = FaceBSP( faces );
MakeTreePortals( tree ); MakeTreePortals( tree );
FilterStructuralBrushesIntoTree( e, tree ); FilterStructuralBrushesIntoTree( e, tree );
@ -353,7 +351,7 @@ void ProcessWorldModel( void ){
if ( leakStatus != EFloodEntities::Empty ) { /* if no entities exist, this would accidentally the whole map, and that IS bad */ if ( leakStatus != EFloodEntities::Empty ) { /* if no entities exist, this would accidentally the whole map, and that IS bad */
/* rebuild a better bsp tree using only the sides that are visible from the inside */ /* rebuild a better bsp tree using only the sides that are visible from the inside */
FillOutside( tree->headnode ); FillOutside( tree.headnode );
/* chop the sides to the convex hull of their visible fragments, giving us the smallest polygons */ /* chop the sides to the convex hull of their visible fragments, giving us the smallest polygons */
ClipSidesIntoTree( e, tree ); ClipSidesIntoTree( e, tree );
@ -372,7 +370,7 @@ void ProcessWorldModel( void ){
/* flood again to discard portals in the void (also required for _skybox) */ /* flood again to discard portals in the void (also required for _skybox) */
FloodEntities( tree ); FloodEntities( tree );
FillOutside( tree->headnode ); FillOutside( tree.headnode );
} }
/* save out information for visibility processing */ /* save out information for visibility processing */
@ -405,7 +403,7 @@ void ProcessWorldModel( void ){
/* subdivide each drawsurf as required by shader tesselation */ /* subdivide each drawsurf as required by shader tesselation */
if ( !nosubdivide ) { if ( !nosubdivide ) {
SubdivideFaceSurfaces( e, tree ); SubdivideFaceSurfaces( e );
} }
/* add in any vertexes required to fix t-junctions */ /* add in any vertexes required to fix t-junctions */
@ -433,7 +431,7 @@ void ProcessWorldModel( void ){
/* ydnar: fog hull */ /* ydnar: fog hull */
if ( entities[ 0 ].read_keyvalue( value, "_foghull" ) ) { if ( entities[ 0 ].read_keyvalue( value, "_foghull" ) ) {
const auto shader = String64()( "textures/", value ); const auto shader = String64()( "textures/", value );
MakeFogHullSurfs( e, tree, shader ); MakeFogHullSurfs( e, shader );
} }
/* ydnar: bug 645: do flares for lights */ /* ydnar: bug 645: do flares for lights */
@ -484,7 +482,7 @@ void ProcessWorldModel( void ){
FixBrushSides( e ); FixBrushSides( e );
/* finish */ /* finish */
EndModel( e, tree->headnode ); EndModel( e, tree.headnode );
FreeTree( tree ); FreeTree( tree );
} }
@ -496,15 +494,9 @@ void ProcessWorldModel( void ){
*/ */
void ProcessSubModel( void ){ void ProcessSubModel( void ){
entity_t *e;
tree_t *tree;
brush_t *b, *bc;
node_t *node;
/* start a brush model */ /* start a brush model */
BeginModel(); BeginModel();
e = &entities[ mapEntityNum ]; entity_t *e = &entities[ mapEntityNum ];
e->firstDrawSurf = numMapDrawSurfs; e->firstDrawSurf = numMapDrawSurfs;
/* ydnar: gs mods */ /* ydnar: gs mods */
@ -514,10 +506,9 @@ void ProcessSubModel( void ){
PatchMapDrawSurfs( e ); PatchMapDrawSurfs( e );
/* allocate a tree */ /* allocate a tree */
node = AllocNode(); tree_t tree{};
node->planenum = PLANENUM_LEAF; tree.headnode = AllocNode();
tree = AllocTree(); tree.headnode->planenum = PLANENUM_LEAF;
tree->headnode = node;
/* add the sides to the tree */ /* add the sides to the tree */
ClipSidesIntoTree( e, tree ); ClipSidesIntoTree( e, tree );
@ -532,16 +523,11 @@ void ProcessSubModel( void ){
EmitBrushes( e->brushes, &e->firstBrush, &e->numBrushes ); EmitBrushes( e->brushes, &e->firstBrush, &e->numBrushes );
/* just put all the brushes in headnode */ /* just put all the brushes in headnode */
for ( b = e->brushes; b; b = b->next ) tree.headnode->brushlist = e->brushes;
{
bc = CopyBrush( b );
bc->next = node->brushlist;
node->brushlist = bc;
}
/* subdivide each drawsurf as required by shader tesselation */ /* subdivide each drawsurf as required by shader tesselation */
if ( !nosubdivide ) { if ( !nosubdivide ) {
SubdivideFaceSurfaces( e, tree ); SubdivideFaceSurfaces( e );
} }
/* add in any vertexes required to fix t-junctions */ /* add in any vertexes required to fix t-junctions */
@ -568,7 +554,7 @@ void ProcessSubModel( void ){
FixBrushSides( e ); FixBrushSides( e );
/* finish */ /* finish */
EndModel( e, node ); EndModel( e, tree.headnode );
FreeTree( tree ); FreeTree( tree );
} }
@ -597,7 +583,7 @@ void ProcessModels( void ){
{ {
/* get entity */ /* get entity */
const entity_t& entity = entities[ mapEntityNum ]; const entity_t& entity = entities[ mapEntityNum ];
if ( entity.brushes == NULL && entity.patches == NULL ) { if ( entity.brushes.empty() && entity.patches == NULL ) {
continue; continue;
} }

View File

@ -726,10 +726,7 @@ void PseudoCompileBSP( bool need_tree ){
char modelValue[16]; char modelValue[16];
entity_t *entity; entity_t *entity;
facelist_t faces; facelist_t faces;
tree_t *tree; tree_t tree{};
node_t *node;
brush_t *brush;
side_t *side;
SetDrawSurfacesBuffer(); SetDrawSurfacesBuffer();
mapDrawSurfs = safe_calloc( sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS ); mapDrawSurfs = safe_calloc( sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
@ -741,7 +738,7 @@ void PseudoCompileBSP( bool need_tree ){
{ {
/* get entity */ /* get entity */
entity = &entities[ mapEntityNum ]; entity = &entities[ mapEntityNum ];
if ( entity->brushes == NULL && entity->patches == NULL ) { if ( entity->brushes.empty() && entity->patches == NULL ) {
continue; continue;
} }
@ -762,33 +759,28 @@ void PseudoCompileBSP( bool need_tree ){
if ( mapEntityNum == 0 && need_tree ) { if ( mapEntityNum == 0 && need_tree ) {
faces = MakeStructuralBSPFaceList( entities[0].brushes ); faces = MakeStructuralBSPFaceList( entities[0].brushes );
tree = FaceBSP( faces ); tree = FaceBSP( faces );
node = tree->headnode;
} }
else else
{ {
node = AllocNode(); tree.headnode = AllocNode();
node->planenum = PLANENUM_LEAF; tree.headnode->planenum = PLANENUM_LEAF;
tree = AllocTree();
tree->headnode = node;
} }
/* a minimized ClipSidesIntoTree */ /* a minimized ClipSidesIntoTree */
for ( brush = entity->brushes; brush; brush = brush->next ) for ( const brush_t& brush : entity->brushes )
{ {
/* walk the brush sides */ /* walk the brush sides */
for ( int j = 0; j < brush->numsides; j++ ) for ( const side_t& side : brush.sides )
{ {
/* get side */ if ( side.winding.empty() ) {
side = &brush->sides[ j ];
if ( side->winding == NULL ) {
continue; continue;
} }
/* shader? */ /* shader? */
if ( side->shaderInfo == NULL ) { if ( side.shaderInfo == NULL ) {
continue; continue;
} }
/* save this winding as a visible surface */ /* save this winding as a visible surface */
DrawSurfaceForSide( entity, brush, side, *side->winding ); DrawSurfaceForSide( entity, brush, side, side.winding );
} }
} }
@ -805,7 +797,7 @@ void PseudoCompileBSP( bool need_tree ){
FilterDetailBrushesIntoTree( entity, tree ); FilterDetailBrushesIntoTree( entity, tree );
EmitBrushes( entity->brushes, &entity->firstBrush, &entity->numBrushes ); EmitBrushes( entity->brushes, &entity->firstBrush, &entity->numBrushes );
EndModel( entity, node ); EndModel( entity, tree.headnode );
} }
EndBSPFile( false ); EndBSPFile( false );
} }

View File

@ -47,14 +47,14 @@ static float Det3x3( float a00, float a01, float a02,
+ a02 * ( a10 * a21 - a11 * a20 ); + a02 * ( a10 * a21 - a11 * a20 );
} }
void GetBestSurfaceTriangleMatchForBrushside( side_t *buildSide, bspDrawVert_t *bestVert[3] ){ void GetBestSurfaceTriangleMatchForBrushside( const side_t& buildSide, bspDrawVert_t *bestVert[3] ){
bspDrawSurface_t *s; bspDrawSurface_t *s;
int i; int i;
int t; int t;
float best = 0; float best = 0;
float thisarea; float thisarea;
bspDrawVert_t *vert[3]; bspDrawVert_t *vert[3];
const plane_t& buildPlane = mapplanes[buildSide->planenum]; const plane_t& buildPlane = mapplanes[buildSide.planenum];
int matches = 0; int matches = 0;
// first, start out with NULLs // first, start out with NULLs
@ -66,7 +66,7 @@ void GetBestSurfaceTriangleMatchForBrushside( side_t *buildSide, bspDrawVert_t *
if ( s->surfaceType != MST_PLANAR && s->surfaceType != MST_TRIANGLE_SOUP ) { if ( s->surfaceType != MST_PLANAR && s->surfaceType != MST_TRIANGLE_SOUP ) {
continue; continue;
} }
if ( !strEqual( buildSide->shaderInfo->shader, bspShaders[s->shaderNum].shader ) ) { if ( !strEqual( buildSide.shaderInfo->shader, bspShaders[s->shaderNum].shader ) ) {
continue; continue;
} }
for ( t = 0; t + 3 <= s->numIndexes; t += 3 ) for ( t = 0; t + 3 <= s->numIndexes; t += 3 )
@ -98,7 +98,7 @@ void GetBestSurfaceTriangleMatchForBrushside( side_t *buildSide, bspDrawVert_t *
continue; continue;
} }
// Okay. Correct surface type, correct shader, correct plane. Let's start with the business... // Okay. Correct surface type, correct shader, correct plane. Let's start with the business...
winding_t *polygon = CopyWinding( buildSide->winding ); winding_t polygon( buildSide.winding );
for ( i = 0; i < 3; ++i ) for ( i = 0; i < 3; ++i )
{ {
// 0: 1, 2 // 0: 1, 2
@ -110,11 +110,11 @@ void GetBestSurfaceTriangleMatchForBrushside( side_t *buildSide, bspDrawVert_t *
Plane3f plane( vector3_cross( v2 - v1, buildPlane.normal() ), 0 ); Plane3f plane( vector3_cross( v2 - v1, buildPlane.normal() ), 0 );
plane.dist() = vector3_dot( v1, plane.normal() ); plane.dist() = vector3_dot( v1, plane.normal() );
ChopWindingInPlace( polygon, plane, distanceEpsilon ); ChopWindingInPlace( polygon, plane, distanceEpsilon );
if ( !polygon ) { if ( polygon.empty() ) {
goto exwinding; goto exwinding;
} }
} }
thisarea = WindingArea( *polygon ); thisarea = WindingArea( polygon );
if ( thisarea > 0 ) { if ( thisarea > 0 ) {
++matches; ++matches;
} }
@ -124,13 +124,12 @@ void GetBestSurfaceTriangleMatchForBrushside( side_t *buildSide, bspDrawVert_t *
bestVert[1] = vert[1]; bestVert[1] = vert[1];
bestVert[2] = vert[2]; bestVert[2] = vert[2];
} }
FreeWinding( polygon );
exwinding: exwinding:
; ;
} }
} }
//if(!striEqualPrefix(buildSide->shaderInfo->shader, "textures/common/")) //if(!striEqualPrefix(buildSide.shaderInfo->shader, "textures/common/"))
// fprintf(stderr, "brushside with %s: %d matches (%f area)\n", buildSide->shaderInfo->shader, matches, best); // fprintf(stderr, "brushside with %s: %d matches (%f area)\n", buildSide.shaderInfo->shader, matches, best);
} }
#define FRAC( x ) ( ( x ) - floor( x ) ) #define FRAC( x ) ( ( x ) - floor( x ) )
@ -195,43 +194,26 @@ static void ConvertOriginBrush( FILE *f, int num, const Vector3& origin, bool br
} }
static void ConvertBrushFast( FILE *f, int num, bspBrush_t *brush, const Vector3& origin, bool brushPrimitives ){ static void ConvertBrushFast( FILE *f, int num, bspBrush_t *brush, const Vector3& origin, bool brushPrimitives ){
int i;
bspBrushSide_t *side;
side_t *buildSide;
bspShader_t *shader;
const char *texture;
plane_t *buildPlane;
Vector3 pts[ 3 ];
/* clear out build brush */ /* clear out build brush */
for ( i = 0; i < buildBrush->numsides; i++ ) buildBrush.sides.clear();
{
buildSide = &buildBrush->sides[ i ];
if ( buildSide->winding != NULL ) {
FreeWinding( buildSide->winding );
buildSide->winding = NULL;
}
}
buildBrush->numsides = 0;
bool modelclip = false; bool modelclip = false;
/* try to guess if thats model clip */ /* try to guess if thats model clip */
if ( force ){ if ( force ){
int notNoShader = 0; int notNoShader = 0;
modelclip = true; modelclip = true;
for ( i = 0; i < brush->numSides; i++ ) for ( int i = 0; i < brush->numSides; i++ )
{ {
/* get side */ /* get side */
side = &bspBrushSides[ brush->firstSide + i ]; const bspBrushSide_t& side = bspBrushSides[ brush->firstSide + i ];
/* get shader */ /* get shader */
if ( side->shaderNum < 0 || side->shaderNum >= numBSPShaders ) { if ( side.shaderNum < 0 || side.shaderNum >= numBSPShaders ) {
continue; continue;
} }
shader = &bspShaders[ side->shaderNum ]; const bspShader_t& shader = bspShaders[ side.shaderNum ];
//"noshader" happens on modelclip and unwanted sides ( usually breaking complex brushes ) //"noshader" happens on modelclip and unwanted sides ( usually breaking complex brushes )
if( !striEqual( shader->shader, "noshader" ) ){ if( !striEqual( shader.shader, "noshader" ) ){
notNoShader++; notNoShader++;
} }
if( notNoShader > 1 ){ if( notNoShader > 1 ){
@ -242,28 +224,26 @@ static void ConvertBrushFast( FILE *f, int num, bspBrush_t *brush, const Vector3
} }
/* iterate through bsp brush sides */ /* iterate through bsp brush sides */
for ( i = 0; i < brush->numSides; i++ ) for ( int i = 0; i < brush->numSides; i++ )
{ {
/* get side */ /* get side */
side = &bspBrushSides[ brush->firstSide + i ]; const bspBrushSide_t& side = bspBrushSides[ brush->firstSide + i ];
/* get shader */ /* get shader */
if ( side->shaderNum < 0 || side->shaderNum >= numBSPShaders ) { if ( side.shaderNum < 0 || side.shaderNum >= numBSPShaders ) {
continue; continue;
} }
shader = &bspShaders[ side->shaderNum ]; const bspShader_t& shader = bspShaders[ side.shaderNum ];
//"noshader" happens on modelclip and unwanted sides ( usually breaking complex brushes ) //"noshader" happens on modelclip and unwanted sides ( usually breaking complex brushes )
if( striEqual( shader->shader, "default" ) || ( striEqual( shader->shader, "noshader" ) && !modelclip ) ) if( striEqual( shader.shader, "default" ) || ( striEqual( shader.shader, "noshader" ) && !modelclip ) )
continue; continue;
/* add build side */ /* add build side */
buildSide = &buildBrush->sides[ buildBrush->numsides ]; buildBrush.sides.emplace_back();
buildBrush->numsides++;
/* tag it */ /* tag it */
buildSide->shaderInfo = ShaderInfoForShader( shader->shader ); buildBrush.sides.back().shaderInfo = ShaderInfoForShader( shader.shader );
buildSide->planenum = side->planeNum; buildBrush.sides.back().planenum = side.planeNum;
buildSide->winding = NULL;
} }
if ( !CreateBrushWindings( buildBrush ) ) { if ( !CreateBrushWindings( buildBrush ) ) {
@ -280,31 +260,26 @@ static void ConvertBrushFast( FILE *f, int num, bspBrush_t *brush, const Vector3
} }
/* iterate through build brush sides */ /* iterate through build brush sides */
for ( i = 0; i < buildBrush->numsides; i++ ) for ( side_t& buildSide : buildBrush.sides )
{ {
/* get build side */
buildSide = &buildBrush->sides[ i ];
/* get plane */ /* get plane */
buildPlane = &mapplanes[ buildSide->planenum ]; const plane_t& buildPlane = mapplanes[ buildSide.planenum ];
/* dummy check */ /* dummy check */
if ( buildSide->shaderInfo == NULL || buildSide->winding == NULL ) { if ( buildSide.shaderInfo == NULL || buildSide.winding.empty() ) {
continue; continue;
} }
/* get texture name */ /* get texture name */
if ( striEqualPrefix( buildSide->shaderInfo->shader, "textures/" ) ) { const char *texture = striEqualPrefix( buildSide.shaderInfo->shader, "textures/" )
texture = buildSide->shaderInfo->shader + 9; ? buildSide.shaderInfo->shader + 9
} : buildSide.shaderInfo->shader;
else{
texture = buildSide->shaderInfo->shader;
}
Vector3 pts[ 3 ];
{ {
Vector3 vecs[ 2 ]; Vector3 vecs[ 2 ];
MakeNormalVectors( buildPlane->normal(), vecs[ 0 ], vecs[ 1 ] ); MakeNormalVectors( buildPlane.normal(), vecs[ 0 ], vecs[ 1 ] );
pts[ 0 ] = buildPlane->normal() * buildPlane->dist() + origin; pts[ 0 ] = buildPlane.normal() * buildPlane.dist() + origin;
pts[ 1 ] = pts[ 0 ] + vecs[ 0 ] * 256.0f; pts[ 1 ] = pts[ 0 ] + vecs[ 0 ] * 256.0f;
pts[ 2 ] = pts[ 0 ] + vecs[ 1 ] * 256.0f; pts[ 2 ] = pts[ 0 ] + vecs[ 1 ] * 256.0f;
} }
@ -343,43 +318,26 @@ static void ConvertBrushFast( FILE *f, int num, bspBrush_t *brush, const Vector3
} }
static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& origin, bool brushPrimitives ){ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& origin, bool brushPrimitives ){
int i, j;
bspBrushSide_t *side;
side_t *buildSide;
bspShader_t *shader;
const char *texture;
Vector3 pts[ 3 ];
bspDrawVert_t *vert[3];
/* clear out build brush */ /* clear out build brush */
for ( i = 0; i < buildBrush->numsides; i++ ) buildBrush.sides.clear();
{
buildSide = &buildBrush->sides[ i ];
if ( buildSide->winding != NULL ) {
FreeWinding( buildSide->winding );
buildSide->winding = NULL;
}
}
buildBrush->numsides = 0;
bool modelclip = false; bool modelclip = false;
/* try to guess if thats model clip */ /* try to guess if thats model clip */
if ( force ){ if ( force ){
int notNoShader = 0; int notNoShader = 0;
modelclip = true; modelclip = true;
for ( i = 0; i < brush->numSides; i++ ) for ( int i = 0; i < brush->numSides; i++ )
{ {
/* get side */ /* get side */
side = &bspBrushSides[ brush->firstSide + i ]; const bspBrushSide_t& side = bspBrushSides[ brush->firstSide + i ];
/* get shader */ /* get shader */
if ( side->shaderNum < 0 || side->shaderNum >= numBSPShaders ) { if ( side.shaderNum < 0 || side.shaderNum >= numBSPShaders ) {
continue; continue;
} }
shader = &bspShaders[ side->shaderNum ]; const bspShader_t& shader = bspShaders[ side.shaderNum ];
//"noshader" happens on modelclip and unwanted sides ( usually breaking complex brushes ) //"noshader" happens on modelclip and unwanted sides ( usually breaking complex brushes )
if( !striEqual( shader->shader, "noshader" ) ){ if( !striEqual( shader.shader, "noshader" ) ){
notNoShader++; notNoShader++;
} }
if( notNoShader > 1 ){ if( notNoShader > 1 ){
@ -390,28 +348,26 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
} }
/* iterate through bsp brush sides */ /* iterate through bsp brush sides */
for ( i = 0; i < brush->numSides; i++ ) for ( int i = 0; i < brush->numSides; i++ )
{ {
/* get side */ /* get side */
side = &bspBrushSides[ brush->firstSide + i ]; const bspBrushSide_t& side = bspBrushSides[ brush->firstSide + i ];
/* get shader */ /* get shader */
if ( side->shaderNum < 0 || side->shaderNum >= numBSPShaders ) { if ( side.shaderNum < 0 || side.shaderNum >= numBSPShaders ) {
continue; continue;
} }
shader = &bspShaders[ side->shaderNum ]; const bspShader_t& shader = bspShaders[ side.shaderNum ];
//"noshader" happens on modelclip and unwanted sides ( usually breaking complex brushes ) //"noshader" happens on modelclip and unwanted sides ( usually breaking complex brushes )
if( striEqual( shader->shader, "default" ) || ( striEqual( shader->shader, "noshader" ) && !modelclip ) ) if( striEqual( shader.shader, "default" ) || ( striEqual( shader.shader, "noshader" ) && !modelclip ) )
continue; continue;
/* add build side */ /* add build side */
buildSide = &buildBrush->sides[ buildBrush->numsides ]; buildBrush.sides.emplace_back();
buildBrush->numsides++;
/* tag it */ /* tag it */
buildSide->shaderInfo = ShaderInfoForShader( shader->shader ); buildBrush.sides.back().shaderInfo = ShaderInfoForShader( shader.shader );
buildSide->planenum = side->planeNum; buildBrush.sides.back().planenum = side.planeNum;
buildSide->winding = NULL;
} }
/* make brush windings */ /* make brush windings */
@ -429,42 +385,38 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
} }
/* iterate through build brush sides */ /* iterate through build brush sides */
for ( i = 0; i < buildBrush->numsides; i++ ) for ( side_t& buildSide : buildBrush.sides )
{ {
/* get build side */
buildSide = &buildBrush->sides[ i ];
/* get plane */ /* get plane */
const plane_t& buildPlane = mapplanes[ buildSide->planenum ]; const plane_t& buildPlane = mapplanes[ buildSide.planenum ];
/* dummy check */ /* dummy check */
if ( buildSide->shaderInfo == NULL || buildSide->winding == NULL ) { if ( buildSide.shaderInfo == NULL || buildSide.winding.empty() ) {
continue; continue;
} }
// st-texcoords -> texMat block // st-texcoords -> texMat block
// start out with dummy // start out with dummy
buildSide->texMat[0] = { 1 / 32.0, 0, 0 }; buildSide.texMat[0] = { 1 / 32.0, 0, 0 };
buildSide->texMat[1] = { 0, 1 / 32.0, 0 }; buildSide.texMat[1] = { 0, 1 / 32.0, 0 };
// find surface for this side (by brute force) // find surface for this side (by brute force)
// surface format: // surface format:
// - meshverts point in pairs of three into verts // - meshverts point in pairs of three into verts
// - (triangles) // - (triangles)
// - find the triangle that has most in common with our side // - find the triangle that has most in common with our
bspDrawVert_t *vert[3];
GetBestSurfaceTriangleMatchForBrushside( buildSide, vert ); GetBestSurfaceTriangleMatchForBrushside( buildSide, vert );
/* get texture name */ /* get texture name */
if ( striEqualPrefix( buildSide->shaderInfo->shader, "textures/" ) ) { const char *texture = striEqualPrefix( buildSide.shaderInfo->shader, "textures/" )
texture = buildSide->shaderInfo->shader + 9; ? buildSide.shaderInfo->shader + 9
} : buildSide.shaderInfo->shader;
else{
texture = buildSide->shaderInfo->shader;
}
Vector3 pts[ 3 ];
/* recheck and fix winding points, fails occur somehow */ /* recheck and fix winding points, fails occur somehow */
int match = 0; int match = 0;
for ( const Vector3& p : ( *buildSide->winding ) ){ for ( const Vector3& p : buildSide.winding ){
if ( fabs( plane3_distance_to_point( buildPlane.plane, p ) ) < distanceEpsilon ) { if ( fabs( plane3_distance_to_point( buildPlane.plane, p ) ) < distanceEpsilon ) {
pts[ match ] = p; pts[ match ] = p;
match++; match++;
@ -476,8 +428,7 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
if( match > 2 ){ if( match > 2 ){
//Sys_Printf( "pointsKK " ); //Sys_Printf( "pointsKK " );
Plane3f testplane; if ( Plane3f testplane; PlaneFromPoints( testplane, pts ) ){
if ( PlaneFromPoints( testplane, pts ) ){
if( !PlaneEqual( buildPlane, testplane ) ){ if( !PlaneEqual( buildPlane, testplane ) ){
//Sys_Printf( "1: %f %f %f %f\n2: %f %f %f %f\n", buildPlane->normal[0], buildPlane->normal[1], buildPlane->normal[2], buildPlane->dist, testplane[0], testplane[1], testplane[2], testplane[3] ); //Sys_Printf( "1: %f %f %f %f\n2: %f %f %f %f\n", buildPlane->normal[0], buildPlane->normal[1], buildPlane->normal[2], buildPlane->dist, testplane[0], testplane[1], testplane[2], testplane[3] );
match--; match--;
@ -493,8 +444,8 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
if( match > 2 ){ if( match > 2 ){
//Sys_Printf( "ok " ); //Sys_Printf( "ok " );
/* offset by origin */ /* offset by origin */
for ( j = 0; j < 3; j++ ) for ( Vector3& pt : pts )
pts[ j ] += origin; pt += origin;
} }
else{ else{
Vector3 vecs[ 2 ]; Vector3 vecs[ 2 ];
@ -552,7 +503,7 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
xyJ[0], xyJ[1], stJ[i], xyJ[0], xyJ[1], stJ[i],
xyK[0], xyK[1], stK[i] xyK[0], xyK[1], stK[i]
); );
buildSide->texMat[i] = { D0 / D, D1 / D, D2 / D }; buildSide.texMat[i] = { D0 / D, D1 / D, D2 / D };
} }
} }
else{ else{
@ -572,8 +523,8 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ], pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ],
pts[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 2 ], pts[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 2 ],
pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ], pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
buildSide->texMat[0][0], buildSide->texMat[0][1], FRAC( buildSide->texMat[0][2] ), buildSide.texMat[0][0], buildSide.texMat[0][1], FRAC( buildSide.texMat[0][2] ),
buildSide->texMat[1][0], buildSide->texMat[1][1], FRAC( buildSide->texMat[1][2] ), buildSide.texMat[1][0], buildSide.texMat[1][1], FRAC( buildSide.texMat[1][2] ),
texture, texture,
0 0
); );
@ -609,12 +560,12 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
tv = 2; tv = 2;
} }
stI[0] = vert[0]->st[0] * buildSide->shaderInfo->shaderWidth; stI[0] = vert[0]->st[0] * buildSide.shaderInfo->shaderWidth;
stI[1] = vert[0]->st[1] * buildSide->shaderInfo->shaderHeight; stI[1] = vert[0]->st[1] * buildSide.shaderInfo->shaderHeight;
stJ[0] = vert[1]->st[0] * buildSide->shaderInfo->shaderWidth; stJ[0] = vert[1]->st[0] * buildSide.shaderInfo->shaderWidth;
stJ[1] = vert[1]->st[1] * buildSide->shaderInfo->shaderHeight; stJ[1] = vert[1]->st[1] * buildSide.shaderInfo->shaderHeight;
stK[0] = vert[2]->st[0] * buildSide->shaderInfo->shaderWidth; stK[0] = vert[2]->st[0] * buildSide.shaderInfo->shaderWidth;
stK[1] = vert[2]->st[1] * buildSide->shaderInfo->shaderHeight; stK[1] = vert[2]->st[1] * buildSide.shaderInfo->shaderHeight;
D = Det3x3( D = Det3x3(
vert[0]->xyz[sv], vert[0]->xyz[tv], 1, vert[0]->xyz[sv], vert[0]->xyz[tv], 1,
@ -664,8 +615,8 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
scale[0] = 1.0 / sqrt( sts[0][0] * sts[0][0] + sts[0][1] * sts[0][1] ); scale[0] = 1.0 / sqrt( sts[0][0] * sts[0][0] + sts[0][1] * sts[0][1] );
scale[1] = 1.0 / sqrt( sts[1][0] * sts[1][0] + sts[1][1] * sts[1][1] ); scale[1] = 1.0 / sqrt( sts[1][0] * sts[1][0] + sts[1][1] * sts[1][1] );
rotate = radians_to_degrees( atan2( sts[0][1] * vecs[0][sv] - sts[1][0] * vecs[1][tv], sts[0][0] * vecs[0][sv] + sts[1][1] * vecs[1][tv] ) ); rotate = radians_to_degrees( atan2( sts[0][1] * vecs[0][sv] - sts[1][0] * vecs[1][tv], sts[0][0] * vecs[0][sv] + sts[1][1] * vecs[1][tv] ) );
shift[0] = buildSide->shaderInfo->shaderWidth * FRAC( sts[0][2] / buildSide->shaderInfo->shaderWidth ); shift[0] = buildSide.shaderInfo->shaderWidth * FRAC( sts[0][2] / buildSide.shaderInfo->shaderWidth );
shift[1] = buildSide->shaderInfo->shaderHeight * FRAC( sts[1][2] / buildSide->shaderInfo->shaderHeight ); shift[1] = buildSide.shaderInfo->shaderHeight * FRAC( sts[1][2] / buildSide.shaderInfo->shaderHeight );
/* print brush side */ /* print brush side */
/* ( 640 24 -224 ) ( 448 24 -224 ) ( 448 -232 -224 ) common/caulk 0 48 0 0.500000 0.500000 0 0 0 */ /* ( 640 24 -224 ) ( 448 24 -224 ) ( 448 -232 -224 ) common/caulk 0 48 0 0.500000 0.500000 0 0 0 */
@ -681,11 +632,11 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
} }
else else
{ {
if ( !striEqualPrefix( buildSide->shaderInfo->shader, "textures/common/" ) if ( !striEqualPrefix( buildSide.shaderInfo->shader, "textures/common/" )
&& !striEqualPrefix( buildSide->shaderInfo->shader, "textures/system/" ) && !striEqualPrefix( buildSide.shaderInfo->shader, "textures/system/" )
&& !strEqual( buildSide->shaderInfo->shader, "noshader" ) && !strEqual( buildSide.shaderInfo->shader, "noshader" )
&& !strEqual( buildSide->shaderInfo->shader, "default" ) ) { && !strEqual( buildSide.shaderInfo->shader, "default" ) ) {
//fprintf( stderr, "no matching triangle for brushside using %s (hopefully nobody can see this side anyway)\n", buildSide->shaderInfo->shader ); //fprintf( stderr, "no matching triangle for brushside using %s (hopefully nobody can see this side anyway)\n", buildSide.shaderInfo->shader );
texture = "common/WTF"; texture = "common/WTF";
} }
@ -882,9 +833,9 @@ static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, const Vector
} }
/* allocate a build brush */ /* allocate a build brush */
buildBrush = AllocBrush( 512 ); buildBrush.sides.reserve( MAX_BUILD_SIDES );
buildBrush->entityNum = 0; buildBrush.entityNum = 0;
buildBrush->original = buildBrush; buildBrush.original = &buildBrush;
if ( origin != g_vector3_identity ) { if ( origin != g_vector3_identity ) {
ConvertOriginBrush( f, -1, origin, brushPrimitives ); ConvertOriginBrush( f, -1, origin, brushPrimitives );
@ -903,9 +854,6 @@ static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, const Vector
} }
} }
/* free the build brush */
free( buildBrush );
/* go through each drawsurf in the model */ /* go through each drawsurf in the model */
for ( i = 0; i < model->numBSPSurfaces; i++ ) for ( i = 0; i < model->numBSPSurfaces; i++ )
{ {

View File

@ -493,33 +493,29 @@ void ProcessDecals( void ){
projects a decal onto a winding projects a decal onto a winding
*/ */
static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds, winding_t *w ){ static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds, winding_t& w ){
int i, j; int i, j;
winding_t *front, *back;
mapDrawSurface_t *ds2; mapDrawSurface_t *ds2;
bspDrawVert_t *dv; bspDrawVert_t *dv;
Plane3f plane; Plane3f plane;
/* dummy check */ /* dummy check */
if ( w->size() < 3 ) { if ( w.size() < 3 ) {
FreeWinding( w );
return; return;
} }
/* offset by entity origin */ /* offset by entity origin */
for ( Vector3& p : *w ) for ( Vector3& p : w )
p += entityOrigin; p += entityOrigin;
/* make a plane from the winding */ /* make a plane from the winding */
if ( !PlaneFromPoints( plane, w->data() ) ) { if ( !PlaneFromPoints( plane, w.data() ) ) {
FreeWinding( w );
return; return;
} }
/* backface check */ /* backface check */
if ( vector3_dot( dp->planes[ 0 ].normal(), plane.normal() ) < -0.0001f ) { if ( vector3_dot( dp->planes[ 0 ].normal(), plane.normal() ) < -0.0001f ) {
FreeWinding( w );
return; return;
} }
@ -527,25 +523,20 @@ static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds,
for ( i = 0; i < dp->numPlanes; i++ ) for ( i = 0; i < dp->numPlanes; i++ )
{ {
/* chop winding by the plane */ /* chop winding by the plane */
ClipWindingEpsilonStrict( *w, dp->planes[ i ], 0.0625f, front, back ); /* strict, if identical plane we don't want to keep it */ auto [front, back] = ClipWindingEpsilonStrict( w, dp->planes[ i ], 0.0625f ); /* strict, if identical plane we don't want to keep it */
FreeWinding( w );
/* lose the front fragment */ /* lose the front fragment */
if ( front != NULL ) {
FreeWinding( front );
}
/* if nothing left in back, then bail */ /* if nothing left in back, then bail */
if ( back == NULL ) { if ( back.empty() ) {
return; return;
} }
/* reset winding */ /* reset winding */
w = back; w.swap( back );
} }
/* nothing left? */ /* nothing left? */
if ( w == NULL || w->size() < 3 ) { if ( w.size() < 3 ) {
return; return;
} }
@ -563,7 +554,7 @@ static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds,
ds2->fogNum = ds->fogNum; /* why was this -1? */ ds2->fogNum = ds->fogNum; /* why was this -1? */
ds2->lightmapScale = ds->lightmapScale; ds2->lightmapScale = ds->lightmapScale;
ds2->shadeAngleDegrees = ds->shadeAngleDegrees; ds2->shadeAngleDegrees = ds->shadeAngleDegrees;
ds2->numVerts = w->size(); ds2->numVerts = w.size();
ds2->verts = safe_calloc( ds2->numVerts * sizeof( *ds2->verts ) ); ds2->verts = safe_calloc( ds2->numVerts * sizeof( *ds2->verts ) );
/* set vertexes */ /* set vertexes */
@ -573,12 +564,12 @@ static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds,
dv = &ds2->verts[ i ]; dv = &ds2->verts[ i ];
/* set alpha */ /* set alpha */
const float d = plane3_distance_to_point( dp->planes[ 0 ], ( *w )[ i ] ); const float d = plane3_distance_to_point( dp->planes[ 0 ], w[ i ] );
const float d2 = plane3_distance_to_point( dp->planes[ 1 ], ( *w )[ i ] ); const float d2 = plane3_distance_to_point( dp->planes[ 1 ], w[ i ] );
const float alpha = 255.0f * d2 / ( d + d2 ); const float alpha = 255.0f * d2 / ( d + d2 );
/* set misc */ /* set misc */
dv->xyz = ( *w )[ i ] - entityOrigin; dv->xyz = w[ i ] - entityOrigin;
dv->normal = plane.normal(); dv->normal = plane.normal();
dv->st[ 0 ] = vector3_dot( dv->xyz, dp->texMat[ 0 ].vec3() ) + dp->texMat[ 0 ][ 3 ]; dv->st[ 0 ] = vector3_dot( dv->xyz, dp->texMat[ 0 ].vec3() ) + dp->texMat[ 0 ][ 3 ];
dv->st[ 1 ] = vector3_dot( dv->xyz, dp->texMat[ 1 ].vec3() ) + dp->texMat[ 1 ][ 3 ]; dv->st[ 1 ] = vector3_dot( dv->xyz, dp->texMat[ 1 ].vec3() ) + dp->texMat[ 1 ][ 3 ];
@ -614,7 +605,7 @@ static void ProjectDecalOntoFace( decalProjector_t *dp, mapDrawSurface_t *ds ){
} }
/* generate decal */ /* generate decal */
winding_t *w = WindingFromDrawSurf( ds ); winding_t w = WindingFromDrawSurf( ds );
ProjectDecalOntoWinding( dp, ds, w ); ProjectDecalOntoWinding( dp, ds, w );
} }
@ -628,7 +619,6 @@ static void ProjectDecalOntoFace( decalProjector_t *dp, mapDrawSurface_t *ds ){
static void ProjectDecalOntoPatch( decalProjector_t *dp, mapDrawSurface_t *ds ){ static void ProjectDecalOntoPatch( decalProjector_t *dp, mapDrawSurface_t *ds ){
int x, y, pw[ 5 ], r, iterations; int x, y, pw[ 5 ], r, iterations;
mesh_t src, *mesh, *subdivided; mesh_t src, *mesh, *subdivided;
winding_t *w;
/* backface check */ /* backface check */
@ -668,18 +658,18 @@ static void ProjectDecalOntoPatch( decalProjector_t *dp, mapDrawSurface_t *ds ){
r = ( x + y ) & 1; r = ( x + y ) & 1;
/* generate decal for first triangle */ /* generate decal for first triangle */
w = AllocWinding( 3 ); winding_t w{
w->push_back( mesh->verts[ pw[ r + 0 ] ].xyz ); mesh->verts[ pw[ r + 0 ] ].xyz,
w->push_back( mesh->verts[ pw[ r + 1 ] ].xyz ); mesh->verts[ pw[ r + 1 ] ].xyz,
w->push_back( mesh->verts[ pw[ r + 2 ] ].xyz ); mesh->verts[ pw[ r + 2 ] ].xyz };
ProjectDecalOntoWinding( dp, ds, w ); ProjectDecalOntoWinding( dp, ds, w );
/* generate decal for second triangle */ /* generate decal for second triangle */
w = AllocWinding( 3 ); winding_t w2{
w->push_back( mesh->verts[ pw[ r + 0 ] ].xyz ); mesh->verts[ pw[ r + 0 ] ].xyz,
w->push_back( mesh->verts[ pw[ r + 2 ] ].xyz ); mesh->verts[ pw[ r + 2 ] ].xyz,
w->push_back( mesh->verts[ pw[ r + 3 ] ].xyz ); mesh->verts[ pw[ r + 3 ] ].xyz };
ProjectDecalOntoWinding( dp, ds, w ); ProjectDecalOntoWinding( dp, ds, w2 );
} }
} }
@ -714,10 +704,10 @@ static void ProjectDecalOntoTriangles( decalProjector_t *dp, mapDrawSurface_t *d
for ( int i = 0; i < ds->numIndexes; i += 3 ) for ( int i = 0; i < ds->numIndexes; i += 3 )
{ {
/* generate decal */ /* generate decal */
winding_t *w = AllocWinding( 3 ); winding_t w{
w->push_back( ds->verts[ ds->indexes[ i ] ].xyz ); ds->verts[ ds->indexes[ i ] ].xyz,
w->push_back( ds->verts[ ds->indexes[ i + 1 ] ].xyz ); ds->verts[ ds->indexes[ i + 1 ] ].xyz,
w->push_back( ds->verts[ ds->indexes[ i + 2 ] ].xyz ); ds->verts[ ds->indexes[ i + 2 ] ].xyz };
ProjectDecalOntoWinding( dp, ds, w ); ProjectDecalOntoWinding( dp, ds, w );
} }
} }

View File

@ -42,7 +42,7 @@ int c_faceLeafs;
finds the best split plane for this node finds the best split plane for this node
*/ */
static void SelectSplitPlaneNum( node_t *node, const facelist_t& list, int *splitPlaneNum, int *compileFlags ){ static void SelectSplitPlaneNum( const node_t *node, const facelist_t& list, int *splitPlaneNum, int *compileFlags ){
//int frontC,backC,splitsC,facingC; //int frontC,backC,splitsC,facingC;
@ -217,21 +217,17 @@ void BuildFaceTree_r( node_t *node, facelist_t& list ){
/* switch on side */ /* switch on side */
if ( side == eSideCross ) { if ( side == eSideCross ) {
winding_t *frontWinding, *backWinding; auto [frontWinding, backWinding] = ClipWindingEpsilonStrict( split.w, plane.plane, CLIP_EPSILON * 2 ); /* strict; if no winding is left, we have a "virtually identical" plane and don't want to split by it */
ClipWindingEpsilonStrict( split.w, plane.plane, CLIP_EPSILON * 2, if ( !frontWinding.empty() ) {
frontWinding, backWinding ); /* strict; if no winding is left, we have a "virtually identical" plane and don't want to split by it */
if ( frontWinding ) {
face_t& newFace = childLists[0].emplace_front(); face_t& newFace = childLists[0].emplace_front();
newFace.w.swap( *frontWinding ); newFace.w.swap( frontWinding );
FreeWinding( frontWinding );
newFace.planenum = split.planenum; newFace.planenum = split.planenum;
newFace.priority = split.priority; newFace.priority = split.priority;
newFace.compileFlags = split.compileFlags; newFace.compileFlags = split.compileFlags;
} }
if ( backWinding ) { if ( !backWinding.empty() ) {
face_t& newFace = childLists[1].emplace_front(); face_t& newFace = childLists[1].emplace_front();
newFace.w.swap( *backWinding ); newFace.w.swap( backWinding );
FreeWinding( backWinding );
newFace.planenum = split.planenum; newFace.planenum = split.planenum;
newFace.priority = split.priority; newFace.priority = split.priority;
newFace.compileFlags = split.compileFlags; newFace.compileFlags = split.compileFlags;
@ -299,15 +295,15 @@ void BuildFaceTree_r( node_t *node, facelist_t& list ){
List will be freed before returning List will be freed before returning
================ ================
*/ */
tree_t *FaceBSP( facelist_t& list ) { tree_t FaceBSP( facelist_t& list ) {
Sys_FPrintf( SYS_VRB, "--- FaceBSP ---\n" ); Sys_FPrintf( SYS_VRB, "--- FaceBSP ---\n" );
tree_t *tree = AllocTree(); tree_t tree{};
int count = 0; int count = 0;
for ( const face_t& face : list ) for ( const face_t& face : list )
{ {
WindingExtendBounds( face.w, tree->minmax ); WindingExtendBounds( face.w, tree.minmax );
count++; count++;
} }
Sys_FPrintf( SYS_VRB, "%9d faces\n", count ); Sys_FPrintf( SYS_VRB, "%9d faces\n", count );
@ -317,11 +313,11 @@ tree_t *FaceBSP( facelist_t& list ) {
plane.counter = 0; plane.counter = 0;
} }
tree->headnode = AllocNode(); tree.headnode = AllocNode();
tree->headnode->minmax = tree->minmax; tree.headnode->minmax = tree.minmax;
c_faceLeafs = 0; c_faceLeafs = 0;
BuildFaceTree_r( tree->headnode, list ); BuildFaceTree_r( tree.headnode, list );
Sys_FPrintf( SYS_VRB, "%9d leafs\n", c_faceLeafs ); Sys_FPrintf( SYS_VRB, "%9d leafs\n", c_faceLeafs );
@ -335,21 +331,20 @@ tree_t *FaceBSP( facelist_t& list ) {
get structural brush faces get structural brush faces
*/ */
facelist_t MakeStructuralBSPFaceList( const brush_t *list ){ facelist_t MakeStructuralBSPFaceList( const brushlist_t& list ){
facelist_t flist; facelist_t flist;
for ( const brush_t *b = list; b != NULL; b = b->next ) for ( const brush_t &b : list )
{ {
if ( !deepBSP && b->detail ) { if ( !deepBSP && b.detail ) {
continue; continue;
} }
for ( int i = 0; i < b->numsides; i++ ) for ( const side_t& s : b.sides )
{ {
/* get side and winding */ /* get winding */
const side_t& s = b->sides[ i ]; const winding_t& w = s.winding;
const winding_t *w = s.winding; if ( w.empty() ) {
if ( w == NULL ) {
continue; continue;
} }
@ -360,10 +355,10 @@ facelist_t MakeStructuralBSPFaceList( const brush_t *list ){
/* allocate a face */ /* allocate a face */
face_t& f = flist.emplace_front(); face_t& f = flist.emplace_front();
f.w = *w; f.w = w;
f.planenum = s.planenum & ~1; f.planenum = s.planenum & ~1;
f.compileFlags = s.compileFlags; /* ydnar */ f.compileFlags = s.compileFlags; /* ydnar */
if ( b->detail ) { if ( b.detail ) {
f.compileFlags |= C_DETAIL; f.compileFlags |= C_DETAIL;
} }
@ -394,21 +389,20 @@ facelist_t MakeStructuralBSPFaceList( const brush_t *list ){
get visible brush faces get visible brush faces
*/ */
facelist_t MakeVisibleBSPFaceList( const brush_t *list ){ facelist_t MakeVisibleBSPFaceList( const brushlist_t& list ){
facelist_t flist; facelist_t flist;
for ( const brush_t *b = list; b != NULL; b = b->next ) for ( const brush_t& b : list )
{ {
if ( !deepBSP && b->detail ) { if ( !deepBSP && b.detail ) {
continue; continue;
} }
for ( int i = 0; i < b->numsides; i++ ) for ( const side_t& s : b.sides )
{ {
/* get side and winding */ /* get winding */
const side_t& s = b->sides[ i ]; const winding_t& w = s.visibleHull;
const winding_t *w = s.visibleHull; if ( w.empty() ) {
if ( w == NULL ) {
continue; continue;
} }
@ -419,10 +413,10 @@ facelist_t MakeVisibleBSPFaceList( const brush_t *list ){
/* allocate a face */ /* allocate a face */
face_t& f = flist.emplace_front(); face_t& f = flist.emplace_front();
f.w = *w; f.w = w;
f.planenum = s.planenum & ~1; f.planenum = s.planenum & ~1;
f.compileFlags = s.compileFlags; /* ydnar */ f.compileFlags = s.compileFlags; /* ydnar */
if ( b->detail ) { if ( b.detail ) {
f.compileFlags |= C_DETAIL; f.compileFlags |= C_DETAIL;
} }

View File

@ -244,9 +244,8 @@ void SplitMeshByPlane( mesh_t *in, const Plane3f& plane, mesh_t **front, mesh_t
chops a patch up by a fog brush chops a patch up by a fog brush
*/ */
bool ChopPatchSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){ bool ChopPatchSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, const brush_t *b ){
int i, j; int i, j;
side_t *s;
mesh_t *outside[MAX_BRUSH_SIDES]; mesh_t *outside[MAX_BRUSH_SIDES];
int numOutside; int numOutside;
mesh_t *m, *front, *back; mesh_t *m, *front, *back;
@ -259,8 +258,7 @@ bool ChopPatchSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){
// some messy patch clipping issues // some messy patch clipping issues
for ( i = 4 ; i <= 5 ; i++ ) { for ( i = 4 ; i <= 5 ; i++ ) {
s = &b->sides[ i ]; const plane_t& plane = mapplanes[ b->sides[ i ].planenum ];
const plane_t& plane = mapplanes[ s->planenum ];
SplitMeshByPlane( m, plane.plane, &front, &back ); SplitMeshByPlane( m, plane.plane, &front, &back );
@ -331,26 +329,23 @@ bool ChopPatchSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){
creates a winding from a surface's verts creates a winding from a surface's verts
*/ */
winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds ){ winding_t WindingFromDrawSurf( const mapDrawSurface_t *ds ){
winding_t *w;
int i;
// we use the first point of the surface, maybe something more clever would be useful // we use the first point of the surface, maybe something more clever would be useful
// (actually send the whole draw surface would be cool?) // (actually send the whole draw surface would be cool?)
if ( ds->numVerts >= MAX_POINTS_ON_WINDING ) { if ( ds->numVerts >= MAX_POINTS_ON_WINDING ) {
const int max = std::min( ds->numVerts, 256 ); const int max = std::min( ds->numVerts, 256 );
Vector3 p[256]; Vector3 p[256];
for ( i = 0; i < max; i++ ) { for ( int i = 0; i < max; i++ ) {
p[i] = ds->verts[i].xyz; p[i] = ds->verts[i].xyz;
} }
xml_Winding( "WindingFromDrawSurf failed: MAX_POINTS_ON_WINDING exceeded", p, max, true ); xml_Winding( "WindingFromDrawSurf failed: MAX_POINTS_ON_WINDING exceeded", p, max, true );
} }
w = AllocWinding( ds->numVerts ); winding_t w = AllocWinding( ds->numVerts );
for ( i = 0; i < ds->numVerts; i++ ) { for ( int i = 0; i < ds->numVerts; i++ ) {
w->push_back( ds->verts[i].xyz ); w.push_back( ds->verts[i].xyz );
} }
return w; return w;
} }
@ -362,13 +357,8 @@ winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds ){
chops up a face drawsurface by a fog brush, with a potential fragment left inside chops up a face drawsurface by a fog brush, with a potential fragment left inside
*/ */
bool ChopFaceSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){ bool ChopFaceSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, const brush_t *b ){
int i, j; std::list<winding_t> outside;
side_t *s;
winding_t *w;
winding_t *front, *back;
winding_t *outside[ MAX_BRUSH_SIDES ];
int numOutside;
mapDrawSurface_t *newds; mapDrawSurface_t *newds;
@ -378,58 +368,51 @@ bool ChopFaceSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){
} }
/* initial setup */ /* initial setup */
w = WindingFromDrawSurf( ds ); winding_t w = WindingFromDrawSurf( ds );
numOutside = 0;
/* chop by each brush side */ /* chop by each brush side */
for ( i = 0; i < b->numsides; i++ ) for ( const side_t& side : b->sides )
{ {
/* get brush side and plane */ /* get brush plane */
s = &b->sides[ i ]; const plane_t& plane = mapplanes[ side.planenum ];
const plane_t& plane = mapplanes[ s->planenum ];
/* handle coplanar outfacing (don't fog) */ /* handle coplanar outfacing (don't fog) */
if ( ds->sideRef->side->planenum == s->planenum ) { if ( ds->sideRef->side->planenum == side.planenum ) {
return false; return false;
} }
/* handle coplanar infacing (keep inside) */ /* handle coplanar infacing (keep inside) */
if ( ( ds->sideRef->side->planenum ^ 1 ) == s->planenum ) { if ( ( ds->sideRef->side->planenum ^ 1 ) == side.planenum ) {
continue; continue;
} }
/* general case */ /* general case */
ClipWindingEpsilonStrict( *w, plane.plane, ON_EPSILON, front, back ); /* strict; if plane is "almost identical" to face, both ways to continue can be wrong, so we better not fog it */ auto [front, back] = ClipWindingEpsilonStrict( w, plane.plane, ON_EPSILON ); /* strict; if plane is "almost identical" to face, both ways to continue can be wrong, so we better not fog it */
FreeWinding( w );
if ( back == NULL ) { if ( back.empty() ) {
/* nothing actually contained inside */ /* nothing actually contained inside */
for ( j = 0; j < numOutside; j++ )
FreeWinding( outside[ j ] );
return false; return false;
} }
if ( front != NULL ) { if ( !front.empty() ) {
if ( numOutside == MAX_BRUSH_SIDES ) { if ( outside.size() == MAX_BRUSH_SIDES ) {
Error( "MAX_BRUSH_SIDES" ); Error( "MAX_BRUSH_SIDES" );
} }
outside[ numOutside ] = front; outside.push_back( std::move( front ) );
numOutside++;
} }
w = back; w.swap( back );
} }
/* fixme: celshaded surface fragment errata */ /* fixme: celshaded surface fragment errata */
/* all of outside fragments become separate drawsurfs */ /* all of outside fragments become separate drawsurfs */
numFogFragments += numOutside; numFogFragments += outside.size();
s = ds->sideRef->side; const side_t *s = ds->sideRef->side;
for ( i = 0; i < numOutside; i++ ) for ( const winding_t& wi : outside )
{ {
newds = DrawSurfaceForSide( e, ds->mapBrush, s, *outside[ i ] ); newds = DrawSurfaceForSide( e, *ds->mapBrush, *s, wi );
newds->fogNum = ds->fogNum; newds->fogNum = ds->fogNum;
FreeWinding( outside[ i ] );
} }
/* ydnar: the old code neglected to snap to 0.125 for the fragment /* ydnar: the old code neglected to snap to 0.125 for the fragment
@ -437,7 +420,7 @@ bool ChopFaceSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){
the right thing and uses the original surface's brush side */ the right thing and uses the original surface's brush side */
/* build a drawsurf for it */ /* build a drawsurf for it */
newds = DrawSurfaceForSide( e, ds->mapBrush, s, *w ); newds = DrawSurfaceForSide( e, *ds->mapBrush, *s, w );
if ( newds == NULL ) { if ( newds == NULL ) {
return false; return false;
} }
@ -562,16 +545,11 @@ void FogDrawSurfaces( entity_t *e ){
*/ */
int FogForPoint( const Vector3& point, float epsilon ){ int FogForPoint( const Vector3& point, float epsilon ){
int fogNum, i, j;
bool inside;
brush_t *brush;
/* start with bogus fog num */ /* start with bogus fog num */
fogNum = defaultFogNum; int fogNum = defaultFogNum;
/* walk the list of fog volumes */ /* walk the list of fog volumes */
for ( i = 0; i < numMapFogs; i++ ) for ( int i = 0; i < numMapFogs; i++ )
{ {
/* sof2: global fog doesn't reference a brush */ /* sof2: global fog doesn't reference a brush */
if ( mapFogs[ i ].brush == NULL ) { if ( mapFogs[ i ].brush == NULL ) {
@ -579,15 +557,13 @@ int FogForPoint( const Vector3& point, float epsilon ){
continue; continue;
} }
/* get fog brush */
brush = mapFogs[ i ].brush;
/* check point against all planes */ /* check point against all planes */
inside = true; bool inside = true;
for ( j = 0; j < brush->numsides && inside; j++ ) for ( const side_t& side : mapFogs[ i ].brush->sides )
{ {
if ( plane3_distance_to_point( mapplanes[ brush->sides[ j ].planenum ].plane, point ) > epsilon ) { if ( plane3_distance_to_point( mapplanes[ side.planenum ].plane, point ) > epsilon ) {
inside = false; inside = false;
break;
} }
} }
@ -628,7 +604,7 @@ int FogForBounds( const MinMax& minmax, float epsilon ){
} }
/* get fog brush */ /* get fog brush */
brush_t *brush = mapFogs[ i ].brush; const brush_t *brush = mapFogs[ i ].brush;
/* get bounds */ /* get bounds */
const MinMax fogMinmax( brush->minmax.mins - Vector3( epsilon ), const MinMax fogMinmax( brush->minmax.mins - Vector3( epsilon ),
@ -663,11 +639,6 @@ int FogForBounds( const MinMax& minmax, float epsilon ){
*/ */
void CreateMapFogs( void ){ void CreateMapFogs( void ){
int j;
brush_t *brush;
fog_t *fog;
/* skip? */ /* skip? */
if ( nofog ) { if ( nofog ) {
return; return;
@ -680,10 +651,10 @@ void CreateMapFogs( void ){
for ( const auto& e : entities ) for ( const auto& e : entities )
{ {
/* walk entity brushes */ /* walk entity brushes */
for ( brush = e.brushes; brush != NULL; brush = brush->next ) for ( const brush_t& brush : e.brushes )
{ {
/* ignore non-fog brushes */ /* ignore non-fog brushes */
if ( !brush->contentShader->fogParms ) { if ( !brush.contentShader->fogParms ) {
continue; continue;
} }
@ -693,21 +664,21 @@ void CreateMapFogs( void ){
} }
/* set up fog */ /* set up fog */
fog = &mapFogs[ numMapFogs++ ]; fog_t& fog = mapFogs[ numMapFogs++ ];
fog->si = brush->contentShader; fog.si = brush.contentShader;
fog->brush = brush; fog.brush = &brush;
fog->visibleSide = -1; fog.visibleSide = -1;
/* if shader specifies an explicit direction, then find a matching brush side with an opposed normal */ /* if shader specifies an explicit direction, then find a matching brush side with an opposed normal */
if ( vector3_length( fog->si->fogDir ) ) { if ( vector3_length( fog.si->fogDir ) ) {
/* flip it */ /* flip it */
const Vector3 invFogDir = -fog->si->fogDir; const Vector3 invFogDir = -fog.si->fogDir;
/* find the brush side */ /* find the brush side */
for ( j = 0; j < brush->numsides; j++ ) for ( size_t j = 0; j < brush.sides.size(); ++j )
{ {
if ( VectorCompare( invFogDir, mapplanes[ brush->sides[ j ].planenum ].normal() ) ) { if ( VectorCompare( invFogDir, mapplanes[ brush.sides[ j ].planenum ].normal() ) ) {
fog->visibleSide = j; fog.visibleSide = j;
//% Sys_Printf( "Brush num: %d Side num: %d\n", fog->brushNum, fog->visibleSide ); //% Sys_Printf( "Brush num: %d Side num: %d\n", fog->brushNum, fog->visibleSide );
break; break;
} }
@ -728,20 +699,20 @@ void CreateMapFogs( void ){
Sys_FPrintf( SYS_VRB, "Map has global fog shader %s\n", globalFog ); Sys_FPrintf( SYS_VRB, "Map has global fog shader %s\n", globalFog );
/* set up fog */ /* set up fog */
fog = &mapFogs[ numMapFogs++ ]; fog_t& fog = mapFogs[ numMapFogs++ ];
fog->si = ShaderInfoForShaderNull( globalFog ); fog.si = ShaderInfoForShaderNull( globalFog );
if ( fog->si == NULL ) { if ( fog.si == NULL ) {
Error( "Invalid shader \"%s\" referenced trying to add global fog", globalFog ); Error( "Invalid shader \"%s\" referenced trying to add global fog", globalFog );
} }
fog->brush = NULL; fog.brush = NULL;
fog->visibleSide = -1; fog.visibleSide = -1;
/* set as default fog */ /* set as default fog */
defaultFogNum = numMapFogs - 1; defaultFogNum = numMapFogs - 1;
/* mark all worldspawn brushes as fogged */ /* mark all worldspawn brushes as fogged */
for ( brush = entities[ 0 ].brushes; brush != NULL; brush = brush->next ) for ( brush_t& brush : entities[ 0 ].brushes )
ApplySurfaceParm( "fog", &brush->contentFlags, NULL, &brush->compileFlags ); ApplySurfaceParm( "fog", &brush.contentFlags, NULL, &brush.compileFlags );
} }
/* emit some stats */ /* emit some stats */

View File

@ -54,14 +54,14 @@
TTimo: builds a polyline xml node TTimo: builds a polyline xml node
============= =============
*/ */
xmlNodePtr LeakFile( tree_t *tree ){ xmlNodePtr LeakFile( const tree_t& tree ){
Vector3 mid; Vector3 mid;
FILE *linefile; FILE *linefile;
node_t *node; const node_t *node;
int count; int count;
xmlNodePtr xml_node, point; xmlNodePtr xml_node, point;
if ( !tree->outside_node.occupied ) { if ( !tree.outside_node.occupied ) {
return NULL; return NULL;
} }
@ -76,12 +76,12 @@ xmlNodePtr LeakFile( tree_t *tree ){
xml_node = xmlNewNode( NULL, (const xmlChar*)"polyline" ); xml_node = xmlNewNode( NULL, (const xmlChar*)"polyline" );
count = 0; count = 0;
node = &tree->outside_node; node = &tree.outside_node;
while ( node->occupied > 1 ) while ( node->occupied > 1 )
{ {
int next; int next;
portal_t *p, *nextportal = NULL; const portal_t *p, *nextportal = NULL;
node_t *nextnode = NULL; const node_t *nextnode = NULL;
int s; int s;
// find the best portal exit // find the best portal exit
@ -97,7 +97,7 @@ xmlNodePtr LeakFile( tree_t *tree ){
} }
} }
node = nextnode; node = nextnode;
mid = WindingCenter( *nextportal->winding ); mid = WindingCenter( nextportal->winding );
fprintf( linefile, "%f %f %f\n", mid[0], mid[1], mid[2] ); fprintf( linefile, "%f %f %f\n", mid[0], mid[1], mid[2] );
point = xml_NodeForVec( mid ); point = xml_NodeForVec( mid );
xmlAddChild( xml_node, point ); xmlAddChild( xml_node, point );

View File

@ -468,7 +468,7 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw
light.si = si; light.si = si;
light.fade = 1.0f; light.fade = 1.0f;
/* create a regular winding */ /* create a regular winding */
light.w = AllocWinding_( rw->numVerts ); light.w = AllocWinding( rw->numVerts );
for ( i = 0; i < rw->numVerts; i++ ) for ( i = 0; i < rw->numVerts; i++ )
{ {
light.w.push_back( rw->verts[ i ].xyz ); light.w.push_back( rw->verts[ i ].xyz );
@ -548,7 +548,7 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw
} }
/* create a regular winding */ /* create a regular winding */
splash.w = AllocWinding_( rw->numVerts ); splash.w = AllocWinding( rw->numVerts );
for ( i = 0; i < rw->numVerts; i++ ) for ( i = 0; i < rw->numVerts; i++ )
splash.w.push_back( rw->verts[rw->numVerts - 1 - i].xyz + normal * si->backsplashDistance ); splash.w.push_back( rw->verts[rw->numVerts - 1 - i].xyz + normal * si->backsplashDistance );

File diff suppressed because it is too large Load Diff

View File

@ -718,13 +718,12 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor
if ( PlaneFromPoints( plane, points ) ) { if ( PlaneFromPoints( plane, points ) ) {
/* build a brush */ /* build a brush */
buildBrush = AllocBrush( 48 ); buildBrush.sides.reserve( MAX_BUILD_SIDES );
buildBrush->entityNum = mapEntityNum; buildBrush.entityNum = mapEntityNum;
buildBrush->original = buildBrush; buildBrush.contentShader = si;
buildBrush->contentShader = si; buildBrush.compileFlags = si->compileFlags;
buildBrush->compileFlags = si->compileFlags; buildBrush.contentFlags = si->contentFlags;
buildBrush->contentFlags = si->contentFlags; buildBrush.detail = true;
buildBrush->detail = true;
//snap points before using them for further calculations //snap points before using them for further calculations
//precision suffers a lot, when two of normal values are under .00025 (often no collision, knocking up effect in ioq3) //precision suffers a lot, when two of normal values are under .00025 (often no collision, knocking up effect in ioq3)
@ -893,24 +892,25 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor
} }
#endif #endif
/* set up brush sides */ /* set up brush sides */
buildBrush->numsides = 4; buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
buildBrush->sides[ 0 ].shaderInfo = si; buildBrush.sides.resize( 4 );
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags; buildBrush.sides[ 0 ].shaderInfo = si;
for ( j = 1; j < buildBrush->numsides; j++ ) { buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < 4; j++ ) {
if ( debugClip ) { if ( debugClip ) {
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" ); buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" ); buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
} }
else { else {
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works buildBrush.sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
} }
} }
points[3] = points[0]; // for cyclic usage points[3] = points[0]; // for cyclic usage
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points ); buildBrush.sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1] buildBrush.sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2] buildBrush.sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3] buildBrush.sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
} }
@ -1033,25 +1033,26 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor
} }
#endif #endif
/* set up brush sides */ /* set up brush sides */
buildBrush->numsides = 5; buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
buildBrush->sides[ 0 ].shaderInfo = si; buildBrush.sides.resize( 5 );
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags; buildBrush.sides[ 0 ].shaderInfo = si;
for ( j = 1; j < buildBrush->numsides; j++ ) { buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < 5; j++ ) {
if ( debugClip ) { if ( debugClip ) {
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" ); buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" ); buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
} }
else { else {
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works buildBrush.sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
} }
} }
points[3] = points[0]; // for cyclic usage points[3] = points[0]; // for cyclic usage
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points ); buildBrush.sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1] buildBrush.sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2] buildBrush.sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3] buildBrush.sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL ); buildBrush.sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
} }
@ -1087,25 +1088,26 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor
reverse.dist() += clipDepth; reverse.dist() += clipDepth;
/* set up brush sides */ /* set up brush sides */
buildBrush->numsides = 5; buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
buildBrush->sides[ 0 ].shaderInfo = si; buildBrush.sides.resize( 5 );
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags; buildBrush.sides[ 0 ].shaderInfo = si;
for ( j = 1; j < buildBrush->numsides; j++ ) { buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < 5; j++ ) {
if ( debugClip ) { if ( debugClip ) {
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" ); buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" ); buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
} }
else { else {
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works buildBrush.sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
} }
} }
points[3] = points[0]; // for cyclic usage points[3] = points[0]; // for cyclic usage
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points ); buildBrush.sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1] buildBrush.sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2] buildBrush.sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3] buildBrush.sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL ); buildBrush.sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
} }
@ -1166,25 +1168,26 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor
reverse.dist() += clipDepth; reverse.dist() += clipDepth;
/* set up brush sides */ /* set up brush sides */
buildBrush->numsides = 5; buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
buildBrush->sides[ 0 ].shaderInfo = si; buildBrush.sides.resize( 5 );
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags; buildBrush.sides[ 0 ].shaderInfo = si;
for ( j = 1; j < buildBrush->numsides; j++ ) { buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < 5; j++ ) {
if ( debugClip ) { if ( debugClip ) {
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" ); buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" ); buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
} }
else { else {
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works buildBrush.sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
} }
} }
points[3] = points[0]; // for cyclic usage points[3] = points[0]; // for cyclic usage
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points ); buildBrush.sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1] buildBrush.sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2] buildBrush.sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3] buildBrush.sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL ); buildBrush.sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
} }
@ -1230,25 +1233,26 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor
} }
#endif #endif
/* set up brush sides */ /* set up brush sides */
buildBrush->numsides = 5; buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
buildBrush->sides[ 0 ].shaderInfo = si; buildBrush.sides.resize( 5 );
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags; buildBrush.sides[ 0 ].shaderInfo = si;
for ( j = 1; j < buildBrush->numsides; j++ ) { buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < 5; j++ ) {
if ( debugClip ) { if ( debugClip ) {
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" ); buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" ); buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
} }
else { else {
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works buildBrush.sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
} }
} }
points[3] = points[0]; // for cyclic usage points[3] = points[0]; // for cyclic usage
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points ); buildBrush.sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1] buildBrush.sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2] buildBrush.sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3] buildBrush.sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL ); buildBrush.sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
} }
@ -1293,30 +1297,30 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor
} }
#endif #endif
/* set up brush sides */ /* set up brush sides */
buildBrush->numsides = 4; buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
buildBrush->sides[ 0 ].shaderInfo = si; buildBrush.sides.resize( 4 );
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags; buildBrush.sides[ 0 ].shaderInfo = si;
for ( j = 1; j < buildBrush->numsides; j++ ) { buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < 4; j++ ) {
if ( debugClip ) { if ( debugClip ) {
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" ); buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" ); buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
} }
else { else {
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works buildBrush.sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
} }
} }
points[3] = points[0]; // for cyclic usage points[3] = points[0]; // for cyclic usage
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points ); buildBrush.sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 1 ] ); // p[0] contains points[1] and points[2] buildBrush.sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 1 ] ); // p[0] contains points[1] and points[2]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 0 ] ); // p[1] contains points[0] and points[1] buildBrush.sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 0 ] ); // p[1] contains points[0] and points[1]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3] buildBrush.sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
} }
else else
{ {
Sys_Warning( "triangle (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) of %s was not autoclipped\n", Sys_Warning( "triangle (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) of %s was not autoclipped\n",
points[0][0], points[0][1], points[0][2], points[1][0], points[1][1], points[1][2], points[2][0], points[2][1], points[2][2], name ); points[0][0], points[0][1], points[0][2], points[1][0], points[1][1], points[1][2], points[2][0], points[2][1], points[2][2], name );
free( buildBrush );
continue; continue;
} }
} }
@ -1359,25 +1363,26 @@ default_CLIPMODEL:
} }
#endif #endif
/* set up brush sides */ /* set up brush sides */
buildBrush->numsides = 5; buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
buildBrush->sides[ 0 ].shaderInfo = si; buildBrush.sides.resize( 5 );
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags; buildBrush.sides[ 0 ].shaderInfo = si;
for ( j = 1; j < buildBrush->numsides; j++ ) { buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < 5; j++ ) {
if ( debugClip ) { if ( debugClip ) {
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" ); buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" ); buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
} }
else { else {
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works buildBrush.sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
} }
} }
points[3] = points[0]; // for cyclic usage points[3] = points[0]; // for cyclic usage
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points ); buildBrush.sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1] buildBrush.sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2] buildBrush.sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3] buildBrush.sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL ); buildBrush.sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
} }
@ -1385,14 +1390,13 @@ default_CLIPMODEL:
if ( CreateBrushWindings( buildBrush ) ) { if ( CreateBrushWindings( buildBrush ) ) {
AddBrushBevels(); AddBrushBevels();
//% EmitBrushes( buildBrush, NULL, NULL ); //% EmitBrushes( buildBrush, NULL, NULL );
buildBrush->next = entities[ mapEntityNum ].brushes; brush_t& newBrush = entities[ mapEntityNum ].brushes.emplace_front( buildBrush );
entities[ mapEntityNum ].brushes = buildBrush; newBrush.original = &newBrush;
entities[ mapEntityNum ].numBrushes++; entities[ mapEntityNum ].numBrushes++;
} }
else{ else{
Sys_Warning( "triangle (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) of %s was not autoclipped\n", Sys_Warning( "triangle (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) of %s was not autoclipped\n",
points[0][0], points[0][1], points[0][2], points[1][0], points[1][1], points[1][2], points[2][0], points[2][1], points[2][2], name ); points[0][0], points[0][1], points[0][2], points[1][0], points[1][1], points[1][2], points[2][0], points[2][1], points[2][2], name );
free( buildBrush );
} }
} }
} }

View File

@ -34,24 +34,7 @@
/* ydnar: to fix broken portal windings */ /* ydnar: to fix broken portal windings */
extern bool FixWinding( winding_t *w ); extern bool FixWinding( winding_t& w );
/*
===========
AllocPortal
===========
*/
portal_t *AllocPortal( void ){
return safe_calloc( sizeof( portal_t ) );
}
void FreePortal( portal_t *p ){
if ( p->winding ) {
FreeWinding( p->winding );
}
free( p );
}
@ -157,7 +140,7 @@ void RemovePortalFromNode( portal_t *portal, node_t *l ){
//============================================================================ //============================================================================
void PrintPortal( const portal_t *p ){ void PrintPortal( const portal_t *p ){
for ( const Vector3& point : ( *p->winding ) ) for ( const Vector3& point : p->winding )
Sys_Printf( "(%5.0f,%5.0f,%5.0f)\n", point[0], point[1], point[2] ); Sys_Printf( "(%5.0f,%5.0f,%5.0f)\n", point[0], point[1], point[2] );
} }
@ -169,59 +152,46 @@ void PrintPortal( const portal_t *p ){
================ ================
*/ */
#define SIDESPACE 8 #define SIDESPACE 8
void MakeHeadnodePortals( tree_t *tree ){ void MakeHeadnodePortals( tree_t& tree ){
int i, j, n; portal_t *portals[6];
portal_t *p, *portals[6];
plane_t bplanes[6];
node_t *node;
node = tree->headnode;
// pad with some space so there will never be null volume leafs // pad with some space so there will never be null volume leafs
const MinMax bounds( tree->minmax.mins - Vector3( SIDESPACE ), const MinMax bounds( tree.minmax.mins - Vector3( SIDESPACE ),
tree->minmax.maxs + Vector3( SIDESPACE ) ); tree.minmax.maxs + Vector3( SIDESPACE ) );
if ( !bounds.valid() ) { if ( !bounds.valid() ) {
Error( "Backwards tree volume" ); Error( "Backwards tree volume" );
} }
tree->outside_node.planenum = PLANENUM_LEAF; tree.outside_node.planenum = PLANENUM_LEAF;
tree->outside_node.brushlist = NULL; tree.outside_node.brushlist.clear();
tree->outside_node.portals = NULL; tree.outside_node.portals = NULL;
tree->outside_node.opaque = false; tree.outside_node.opaque = false;
for ( i = 0 ; i < 3 ; i++ ) for ( int i = 0 ; i < 3 ; i++ )
for ( j = 0 ; j < 2 ; j++ ) for ( int j = 0 ; j < 2 ; j++ )
{ {
n = j * 3 + i; portal_t *p = portals[j * 3 + i] = AllocPortal();
p = AllocPortal();
portals[n] = p;
plane_t *pl = &bplanes[n];
memset( pl, 0, sizeof( *pl ) );
if ( j ) { if ( j ) {
pl->normal()[i] = -1; p->plane.plane = Plane3f( -g_vector3_axes[i], -bounds.maxs[i] );
pl->dist() = -bounds.maxs[i];
} }
else else
{ {
pl->normal()[i] = 1; p->plane.plane = Plane3f( g_vector3_axes[i], bounds.mins[i] );
pl->dist() = bounds.mins[i];
} }
p->plane = *pl; p->winding = BaseWindingForPlane( p->plane.plane );
p->winding = BaseWindingForPlane( pl->plane ); AddPortalToNodes( p, tree.headnode, &tree.outside_node );
AddPortalToNodes( p, node, &tree->outside_node );
} }
// clip the basewindings by all the other planes // clip the basewindings by all the other planes
for ( i = 0 ; i < 6 ; i++ ) for ( int i = 0 ; i < 6 ; i++ )
{ {
for ( j = 0 ; j < 6 ; j++ ) for ( int j = 0 ; j < 6 ; j++ )
{ {
if ( j == i ) { if ( j == i ) {
continue; continue;
} }
ChopWindingInPlace( portals[i]->winding, bplanes[j].plane, ON_EPSILON ); ChopWindingInPlace( portals[i]->winding, portals[j]->plane.plane, ON_EPSILON );
} }
} }
} }
@ -237,14 +207,11 @@ void MakeHeadnodePortals( tree_t *tree ){
#define BASE_WINDING_EPSILON 0.001 #define BASE_WINDING_EPSILON 0.001
#define SPLIT_WINDING_EPSILON 0.001 #define SPLIT_WINDING_EPSILON 0.001
winding_t *BaseWindingForNode( node_t *node ){ winding_t BaseWindingForNode( const node_t *node ){
winding_t *w; winding_t w = BaseWindingForPlane( mapplanes[node->planenum].plane );
node_t *n;
w = BaseWindingForPlane( mapplanes[node->planenum].plane );
// clip by all the parents // clip by all the parents
for ( n = node->parent ; n && w ; ) for ( const node_t *n = node->parent; n && !w.empty(); )
{ {
const plane_t& plane = mapplanes[n->planenum]; const plane_t& plane = mapplanes[n->planenum];
@ -273,14 +240,12 @@ winding_t *BaseWindingForNode( node_t *node ){
================== ==================
*/ */
void MakeNodePortal( node_t *node ){ void MakeNodePortal( node_t *node ){
portal_t *new_portal, *p;
winding_t *w;
int side; int side;
w = BaseWindingForNode( node ); winding_t w = BaseWindingForNode( node );
// clip the portal by all the other portals in the node // clip the portal by all the other portals in the node
for ( p = node->portals ; p && w; p = p->next[side] ) for ( const portal_t *p = node->portals; p && !w.empty(); p = p->next[side] )
{ {
if ( p->nodes[0] == node ) { if ( p->nodes[0] == node ) {
side = 0; side = 0;
@ -296,7 +261,7 @@ void MakeNodePortal( node_t *node ){
} }
if ( !w ) { if ( w.empty() ) {
return; return;
} }
@ -305,21 +270,19 @@ void MakeNodePortal( node_t *node ){
#if 0 #if 0
if ( !FixWinding( w ) ) { if ( !FixWinding( w ) ) {
c_badportals++; c_badportals++;
FreeWinding( w );
return; return;
} }
#endif #endif
if ( WindingIsTiny( *w ) ) { if ( WindingIsTiny( w ) ) {
c_tinyportals++; c_tinyportals++;
FreeWinding( w );
return; return;
} }
new_portal = AllocPortal(); portal_t *new_portal = AllocPortal();
new_portal->plane = mapplanes[node->planenum]; new_portal->plane = mapplanes[node->planenum];
new_portal->onnode = node; new_portal->onnode = node;
new_portal->winding = w; new_portal->winding.swap( w );
new_portal->compileFlags = node->compileFlags; new_portal->compileFlags = node->compileFlags;
AddPortalToNodes( new_portal, node->children[0], node->children[1] ); AddPortalToNodes( new_portal, node->children[0], node->children[1] );
} }
@ -334,17 +297,15 @@ void MakeNodePortal( node_t *node ){
============== ==============
*/ */
void SplitNodePortals( node_t *node ){ void SplitNodePortals( node_t *node ){
portal_t *p, *next_portal, *new_portal;
node_t *f, *b, *other_node; node_t *f, *b, *other_node;
int side;
winding_t *frontwinding, *backwinding;
const plane_t& plane = mapplanes[node->planenum]; const plane_t& plane = mapplanes[node->planenum];
f = node->children[0]; f = node->children[0];
b = node->children[1]; b = node->children[1];
for ( p = node->portals ; p ; p = next_portal ) for ( portal_t *next_portal, *p = node->portals; p; p = next_portal )
{ {
int side;
if ( p->nodes[0] == node ) { if ( p->nodes[0] == node ) {
side = 0; side = 0;
} }
@ -363,45 +324,41 @@ void SplitNodePortals( node_t *node ){
// //
// cut the portal into two portals, one on each side of the cut plane // cut the portal into two portals, one on each side of the cut plane
// //
ClipWindingEpsilon( *p->winding, plane.plane, auto [frontwinding, backwinding] = ClipWindingEpsilon( p->winding, plane.plane, SPLIT_WINDING_EPSILON ); /* not strict, we want to always keep one of them even if coplanar */
SPLIT_WINDING_EPSILON, frontwinding, backwinding ); /* not strict, we want to always keep one of them even if coplanar */
if ( frontwinding && WindingIsTiny( *frontwinding ) ) { if ( !frontwinding.empty() && WindingIsTiny( frontwinding ) ) {
if ( !f->tinyportals ) { if ( !f->tinyportals ) {
f->referencepoint = ( *frontwinding )[0]; f->referencepoint = frontwinding[0];
} }
f->tinyportals++; f->tinyportals++;
if ( !other_node->tinyportals ) { if ( !other_node->tinyportals ) {
other_node->referencepoint = ( *frontwinding )[0]; other_node->referencepoint = frontwinding[0];
} }
other_node->tinyportals++; other_node->tinyportals++;
FreeWinding( frontwinding ); frontwinding.clear();
frontwinding = NULL;
c_tinyportals++; c_tinyportals++;
} }
if ( backwinding && WindingIsTiny( *backwinding ) ) { if ( !backwinding.empty() && WindingIsTiny( backwinding ) ) {
if ( !b->tinyportals ) { if ( !b->tinyportals ) {
b->referencepoint = ( *backwinding )[0]; b->referencepoint = backwinding[0];
} }
b->tinyportals++; b->tinyportals++;
if ( !other_node->tinyportals ) { if ( !other_node->tinyportals ) {
other_node->referencepoint = ( *backwinding )[0]; other_node->referencepoint = backwinding[0];
} }
other_node->tinyportals++; other_node->tinyportals++;
FreeWinding( backwinding ); backwinding.clear();
backwinding = NULL;
c_tinyportals++; c_tinyportals++;
} }
if ( !frontwinding && !backwinding ) { // tiny windings on both sides if ( frontwinding.empty() && backwinding.empty() ) { // tiny windings on both sides
continue; continue;
} }
if ( !frontwinding ) { if ( frontwinding.empty() ) {
FreeWinding( backwinding );
if ( side == 0 ) { if ( side == 0 ) {
AddPortalToNodes( p, b, other_node ); AddPortalToNodes( p, b, other_node );
} }
@ -410,8 +367,7 @@ void SplitNodePortals( node_t *node ){
} }
continue; continue;
} }
if ( !backwinding ) { if ( backwinding.empty() ) {
FreeWinding( frontwinding );
if ( side == 0 ) { if ( side == 0 ) {
AddPortalToNodes( p, f, other_node ); AddPortalToNodes( p, f, other_node );
} }
@ -422,11 +378,10 @@ void SplitNodePortals( node_t *node ){
} }
// the winding is split // the winding is split
new_portal = AllocPortal(); p->winding.clear();
*new_portal = *p; portal_t *new_portal = new portal_t( *p ); // AllocPortal()
new_portal->winding = backwinding; new_portal->winding.swap( backwinding );
FreeWinding( p->winding ); p->winding.swap( frontwinding );
p->winding = frontwinding;
if ( side == 0 ) { if ( side == 0 ) {
AddPortalToNodes( p, f, other_node ); AddPortalToNodes( p, f, other_node );
@ -457,7 +412,7 @@ void CalcNodeBounds( node_t *node ){
for ( p = node->portals; p; p = p->next[s] ) for ( p = node->portals; p; p = p->next[s] )
{ {
s = ( p->nodes[1] == node ); s = ( p->nodes[1] == node );
WindingExtendBounds( *p->winding, node->minmax ); WindingExtendBounds( p->winding, node->minmax );
} }
} }
@ -479,8 +434,8 @@ void MakeTreePortals_r( node_t *node ){
} }
if ( !c_worldMinmax.surrounds( node->minmax ) ) { if ( !c_worldMinmax.surrounds( node->minmax ) ) {
if ( node->portals && node->portals->winding ) { if ( node->portals && !node->portals->winding.empty() ) {
xml_Winding( "WARNING: Node With Unbounded Volume", node->portals->winding->data(), node->portals->winding->size(), false ); xml_Winding( "WARNING: Node With Unbounded Volume", node->portals->winding.data(), node->portals->winding.size(), false );
} }
} }
if ( node->planenum == PLANENUM_LEAF ) { if ( node->planenum == PLANENUM_LEAF ) {
@ -499,10 +454,10 @@ void MakeTreePortals_r( node_t *node ){
MakeTreePortals MakeTreePortals
================== ==================
*/ */
void MakeTreePortals( tree_t *tree ){ void MakeTreePortals( tree_t& tree ){
Sys_FPrintf( SYS_VRB, "--- MakeTreePortals ---\n" ); Sys_FPrintf( SYS_VRB, "--- MakeTreePortals ---\n" );
MakeHeadnodePortals( tree ); MakeHeadnodePortals( tree );
MakeTreePortals_r( tree->headnode ); MakeTreePortals_r( tree.headnode );
Sys_FPrintf( SYS_VRB, "%9d tiny portals\n", c_tinyportals ); Sys_FPrintf( SYS_VRB, "%9d tiny portals\n", c_tinyportals );
Sys_FPrintf( SYS_VRB, "%9d bad portals\n", c_badportals ); /* ydnar */ Sys_FPrintf( SYS_VRB, "%9d bad portals\n", c_badportals ); /* ydnar */
} }
@ -591,16 +546,14 @@ bool PlaceOccupant( node_t *headnode, const Vector3& origin, const entity_t *occ
============= =============
*/ */
EFloodEntities FloodEntities( tree_t *tree ){ EFloodEntities FloodEntities( tree_t& tree ){
bool r, inside, skybox; bool r, inside, skybox;
node_t *headnode;
const char *value; const char *value;
headnode = tree->headnode;
Sys_FPrintf( SYS_VRB, "--- FloodEntities ---\n" ); Sys_FPrintf( SYS_VRB, "--- FloodEntities ---\n" );
inside = false; inside = false;
tree->outside_node.occupied = 0; tree.outside_node.occupied = 0;
c_floodedleafs = 0; c_floodedleafs = 0;
for ( std::size_t i = 1; i < entities.size(); ++i ) for ( std::size_t i = 1; i < entities.size(); ++i )
@ -617,7 +570,7 @@ EFloodEntities FloodEntities( tree_t *tree ){
} }
#endif #endif
/* also allow bmodel entities outside, as they could be on a moving path that will go into the map */ /* also allow bmodel entities outside, as they could be on a moving path that will go into the map */
if ( e.brushes != NULL || e.patches != NULL || e.classname_is( "_decal" ) ) { //_decal primitive is freed at this point if ( !e.brushes.empty() || e.patches != NULL || e.classname_is( "_decal" ) ) { //_decal primitive is freed at this point
continue; continue;
} }
@ -653,7 +606,7 @@ EFloodEntities FloodEntities( tree_t *tree ){
//% origin[ 2 ] += 4096; //% origin[ 2 ] += 4096;
/* find leaf */ /* find leaf */
r = PlaceOccupant( headnode, origin, &e, skybox ); r = PlaceOccupant( tree.headnode, origin, &e, skybox );
if ( r ) { if ( r ) {
inside = true; inside = true;
} }
@ -668,7 +621,7 @@ EFloodEntities FloodEntities( tree_t *tree ){
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "no entities in open -- no filling\n" ); Sys_FPrintf( SYS_WRN | SYS_VRBflag, "no entities in open -- no filling\n" );
return EFloodEntities::Empty; return EFloodEntities::Empty;
} }
if ( tree->outside_node.occupied ) { if ( tree.outside_node.occupied ) {
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "entity reached from outside -- leak detected\n" ); Sys_FPrintf( SYS_WRN | SYS_VRBflag, "entity reached from outside -- leak detected\n" );
return EFloodEntities::Leaked; return EFloodEntities::Leaked;
} }
@ -696,7 +649,6 @@ int c_areas;
void FloodAreas_r( node_t *node ){ void FloodAreas_r( node_t *node ){
int s; int s;
portal_t *p; portal_t *p;
brush_t *b;
if ( node->areaportal ) { if ( node->areaportal ) {
@ -705,7 +657,7 @@ void FloodAreas_r( node_t *node ){
} }
/* this node is part of an area portal brush */ /* this node is part of an area portal brush */
b = node->brushlist->original; brush_t *b = node->brushlist.front().original;
/* if the current area has already touched this portal, we are done */ /* if the current area has already touched this portal, we are done */
if ( b->portalareas[ 0 ] == c_areas || b->portalareas[ 1 ] == c_areas ) { if ( b->portalareas[ 0 ] == c_areas || b->portalareas[ 1 ] == c_areas ) {
@ -786,9 +738,7 @@ void FindAreas_r( node_t *node ){
CheckAreas_r CheckAreas_r
============= =============
*/ */
void CheckAreas_r( node_t *node ){ void CheckAreas_r( const node_t *node ){
brush_t *b;
if ( node->planenum != PLANENUM_LEAF ) { if ( node->planenum != PLANENUM_LEAF ) {
CheckAreas_r( node->children[0] ); CheckAreas_r( node->children[0] );
CheckAreas_r( node->children[1] ); CheckAreas_r( node->children[1] );
@ -805,7 +755,7 @@ void CheckAreas_r( node_t *node ){
} }
} }
if ( node->areaportal ) { if ( node->areaportal ) {
b = node->brushlist->original; const brush_t *b = node->brushlist.front().original;
// check if the areaportal touches two areas // check if the areaportal touches two areas
if ( b->portalareas[0] == -1 || b->portalareas[1] == -1 ) { if ( b->portalareas[0] == -1 || b->portalareas[1] == -1 ) {
@ -846,16 +796,16 @@ void FloodSkyboxArea_r( node_t *node ){
mark each leaf with an area, bounded by C_AREAPORTAL mark each leaf with an area, bounded by C_AREAPORTAL
*/ */
void FloodAreas( tree_t *tree ){ void FloodAreas( tree_t& tree ){
Sys_FPrintf( SYS_VRB, "--- FloodAreas ---\n" ); Sys_FPrintf( SYS_VRB, "--- FloodAreas ---\n" );
FindAreas_r( tree->headnode ); FindAreas_r( tree.headnode );
/* ydnar: flood all skybox nodes */ /* ydnar: flood all skybox nodes */
FloodSkyboxArea_r( tree->headnode ); FloodSkyboxArea_r( tree.headnode );
/* check for areaportal brushes that don't touch two areas */ /* check for areaportal brushes that don't touch two areas */
/* ydnar: fix this rather than just silence the warnings */ /* ydnar: fix this rather than just silence the warnings */
//% CheckAreas_r( tree->headnode ); //% CheckAreas_r( tree.headnode );
Sys_FPrintf( SYS_VRB, "%9d areas\n", c_areas ); Sys_FPrintf( SYS_VRB, "%9d areas\n", c_areas );
} }

View File

@ -59,7 +59,7 @@ void WriteFloat( FILE *f, float v ){
} }
} }
void CountVisportals_r( node_t *node ){ void CountVisportals_r( const node_t *node ){
int s; int s;
// decision node // decision node
@ -75,9 +75,8 @@ void CountVisportals_r( node_t *node ){
for ( const portal_t *p = node->portals; p; p = p->next[s] ) for ( const portal_t *p = node->portals; p; p = p->next[s] )
{ {
const winding_t *w = p->winding;
s = ( p->nodes[1] == node ); s = ( p->nodes[1] == node );
if ( w && p->nodes[0] == node ) { if ( !p->winding.empty() && p->nodes[0] == node ) {
if ( !PortalPassable( p ) ) { if ( !PortalPassable( p ) ) {
continue; continue;
} }
@ -94,7 +93,7 @@ void CountVisportals_r( node_t *node ){
WritePortalFile_r WritePortalFile_r
================= =================
*/ */
void WritePortalFile_r( node_t *node ){ void WritePortalFile_r( const node_t *node ){
int s, flags; int s, flags;
// decision node // decision node
@ -110,9 +109,9 @@ void WritePortalFile_r( node_t *node ){
for (const portal_t *p = node->portals; p; p = p->next[s] ) for (const portal_t *p = node->portals; p; p = p->next[s] )
{ {
const winding_t *w = p->winding; const winding_t& w = p->winding;
s = ( p->nodes[1] == node ); s = ( p->nodes[1] == node );
if ( w && p->nodes[0] == node ) { if ( !w.empty() && p->nodes[0] == node ) {
if ( !PortalPassable( p ) ) { if ( !PortalPassable( p ) ) {
continue; continue;
} }
@ -126,11 +125,11 @@ void WritePortalFile_r( node_t *node ){
// the changeover point between different axis. interpret the // the changeover point between different axis. interpret the
// plane the same way vis will, and flip the side orders if needed // plane the same way vis will, and flip the side orders if needed
// FIXME: is this still relevant? // FIXME: is this still relevant?
if ( vector3_dot( p->plane.normal(), WindingPlane( *w ).normal() ) < 0.99 ) { // backwards... if ( vector3_dot( p->plane.normal(), WindingPlane( w ).normal() ) < 0.99 ) { // backwards...
fprintf( pf, "%zu %i %i ", w->size(), p->nodes[1]->cluster, p->nodes[0]->cluster ); fprintf( pf, "%zu %i %i ", w.size(), p->nodes[1]->cluster, p->nodes[0]->cluster );
} }
else{ else{
fprintf( pf, "%zu %i %i ", w->size(), p->nodes[0]->cluster, p->nodes[1]->cluster ); fprintf( pf, "%zu %i %i ", w.size(), p->nodes[0]->cluster, p->nodes[1]->cluster );
} }
flags = 0; flags = 0;
@ -148,7 +147,7 @@ void WritePortalFile_r( node_t *node ){
fprintf( pf, "%d ", flags ); fprintf( pf, "%d ", flags );
/* write the winding */ /* write the winding */
for ( const Vector3 point : *w ) for ( const Vector3 point : w )
{ {
fprintf( pf, "(" ); fprintf( pf, "(" );
WriteFloat( pf, point.x() ); WriteFloat( pf, point.x() );
@ -162,7 +161,7 @@ void WritePortalFile_r( node_t *node ){
} }
void CountSolidFaces_r( node_t *node ){ void CountSolidFaces_r( const node_t *node ){
int s; int s;
// decision node // decision node
@ -178,9 +177,8 @@ void CountSolidFaces_r( node_t *node ){
for ( const portal_t *p = node->portals; p; p = p->next[s] ) for ( const portal_t *p = node->portals; p; p = p->next[s] )
{ {
const winding_t *w = p->winding;
s = ( p->nodes[1] == node ); s = ( p->nodes[1] == node );
if ( w ) { if ( !p->winding.empty() ) {
if ( PortalPassable( p ) ) { if ( PortalPassable( p ) ) {
continue; continue;
} }
@ -199,7 +197,7 @@ void CountSolidFaces_r( node_t *node ){
WriteFaceFile_r WriteFaceFile_r
================= =================
*/ */
void WriteFaceFile_r( node_t *node ){ void WriteFaceFile_r( const node_t *node ){
int s; int s;
// decision node // decision node
@ -215,9 +213,9 @@ void WriteFaceFile_r( node_t *node ){
for ( const portal_t *p = node->portals; p; p = p->next[s] ) for ( const portal_t *p = node->portals; p; p = p->next[s] )
{ {
const winding_t *w = p->winding; const winding_t& w = p->winding;
s = ( p->nodes[1] == node ); s = ( p->nodes[1] == node );
if ( w ) { if ( !w.empty() ) {
if ( PortalPassable( p ) ) { if ( PortalPassable( p ) ) {
continue; continue;
} }
@ -227,8 +225,8 @@ void WriteFaceFile_r( node_t *node ){
// write out to the file // write out to the file
if ( p->nodes[0] == node ) { if ( p->nodes[0] == node ) {
fprintf( pf, "%zu %i ", w->size(), p->nodes[0]->cluster ); fprintf( pf, "%zu %i ", w.size(), p->nodes[0]->cluster );
for ( const Vector3& point : *w ) for ( const Vector3& point : w )
{ {
fprintf( pf, "(" ); fprintf( pf, "(" );
WriteFloat( pf, point.x() ); WriteFloat( pf, point.x() );
@ -240,8 +238,8 @@ void WriteFaceFile_r( node_t *node ){
} }
else else
{ {
fprintf( pf, "%zu %i ", w->size(), p->nodes[1]->cluster ); fprintf( pf, "%zu %i ", w.size(), p->nodes[1]->cluster );
for ( winding_t::const_reverse_iterator point = w->crbegin(); point != w->crend(); ++point ) for ( winding_t::const_reverse_iterator point = w.crbegin(); point != w.crend(); ++point )
{ {
fprintf( pf, "(" ); fprintf( pf, "(" );
WriteFloat( pf, point->x() ); WriteFloat( pf, point->x() );
@ -332,7 +330,7 @@ void NumberLeafs_r( node_t *node, int c ){
NumberClusters NumberClusters
================ ================
*/ */
void NumberClusters( tree_t *tree ) { void NumberClusters( tree_t& tree ) {
num_visclusters = 0; num_visclusters = 0;
num_visportals = 0; num_visportals = 0;
num_solidfaces = 0; num_solidfaces = 0;
@ -340,9 +338,9 @@ void NumberClusters( tree_t *tree ) {
Sys_FPrintf( SYS_VRB, "--- NumberClusters ---\n" ); Sys_FPrintf( SYS_VRB, "--- NumberClusters ---\n" );
// set the cluster field in every leaf and count the total number of portals // set the cluster field in every leaf and count the total number of portals
NumberLeafs_r( tree->headnode, -1 ); NumberLeafs_r( tree.headnode, -1 );
CountVisportals_r( tree->headnode ); CountVisportals_r( tree.headnode );
CountSolidFaces_r( tree->headnode ); CountSolidFaces_r( tree.headnode );
Sys_FPrintf( SYS_VRB, "%9d visclusters\n", num_visclusters ); Sys_FPrintf( SYS_VRB, "%9d visclusters\n", num_visclusters );
Sys_FPrintf( SYS_VRB, "%9d visportals\n", num_visportals ); Sys_FPrintf( SYS_VRB, "%9d visportals\n", num_visportals );
@ -354,7 +352,7 @@ void NumberClusters( tree_t *tree ) {
WritePortalFile WritePortalFile
================ ================
*/ */
void WritePortalFile( tree_t *tree ){ void WritePortalFile( const tree_t& tree ){
Sys_FPrintf( SYS_VRB, "--- WritePortalFile ---\n" ); Sys_FPrintf( SYS_VRB, "--- WritePortalFile ---\n" );
// write the file // write the file
@ -367,8 +365,8 @@ void WritePortalFile( tree_t *tree ){
fprintf( pf, "%i\n", num_visportals ); fprintf( pf, "%i\n", num_visportals );
fprintf( pf, "%i\n", num_solidfaces ); fprintf( pf, "%i\n", num_solidfaces );
WritePortalFile_r( tree->headnode ); WritePortalFile_r( tree.headnode );
WriteFaceFile_r( tree->headnode ); WriteFaceFile_r( tree.headnode );
fclose( pf ); fclose( pf );
} }

View File

@ -739,9 +739,9 @@ struct side_t
Vector3 texMat[ 2 ]; /* brush primitive texture matrix */ Vector3 texMat[ 2 ]; /* brush primitive texture matrix */
Vector4 vecs[ 2 ]; /* old-style texture coordinate mapping */ Vector4 vecs[ 2 ]; /* old-style texture coordinate mapping */
Plane3 plane; /* optional plane in double precision for building windings */ Plane3 plane{ 0, 0, 0, 0 }; /* optional plane in double precision for building windings */
winding_t *winding; winding_t winding;
winding_t *visibleHull; /* convex hull of all visible fragments */ winding_t visibleHull; /* convex hull of all visible fragments */
shaderInfo_t *shaderInfo; shaderInfo_t *shaderInfo;
@ -759,7 +759,7 @@ struct side_t
struct sideRef_t struct sideRef_t
{ {
sideRef_t *next; sideRef_t *next;
side_t *side; const side_t *side;
}; };
@ -775,8 +775,6 @@ struct indexMap_t
struct brush_t struct brush_t
{ {
brush_t *next;
brush_t *nextColorModBrush; /* ydnar: colorMod volume brushes go here */
brush_t *original; /* chopped up brushes will reference the originals */ brush_t *original; /* chopped up brushes will reference the originals */
int entityNum, brushNum; /* editor numbering */ int entityNum, brushNum; /* editor numbering */
@ -804,16 +802,16 @@ struct brush_t
int portalareas[ 2 ]; int portalareas[ 2 ];
MinMax minmax; MinMax minmax;
int numsides;
side_t sides[]; /* variably sized */ std::vector<side_t> sides;
}; };
using brushlist_t = std::list<brush_t>;
struct fog_t struct fog_t
{ {
shaderInfo_t *si; shaderInfo_t *si;
brush_t *brush; const brush_t *brush;
int visibleSide; /* the brush side that ray tests need to clip against (-1 == none) */ int visibleSide; /* the brush side that ray tests need to clip against (-1 == none) */
}; };
@ -914,7 +912,7 @@ struct mapDrawSurface_t
shaderInfo_t *shaderInfo; shaderInfo_t *shaderInfo;
shaderInfo_t *celShader; shaderInfo_t *celShader;
brush_t *mapBrush; const brush_t *mapBrush;
parseMesh_t *mapMesh; parseMesh_t *mapMesh;
sideRef_t *sideRef; sideRef_t *sideRef;
@ -974,7 +972,7 @@ struct drawSurfRef_t
struct metaTriangle_t struct metaTriangle_t
{ {
shaderInfo_t *si; shaderInfo_t *si;
side_t *side; const side_t *side;
int entityNum, surfaceNum, planeNum, fogNum, sampleSize, castShadows, recvShadows; int entityNum, surfaceNum, planeNum, fogNum, sampleSize, castShadows, recvShadows;
float shadeAngleDegrees; float shadeAngleDegrees;
Plane3f plane; Plane3f plane;
@ -992,7 +990,8 @@ struct epair_t
struct entity_t struct entity_t
{ {
Vector3 origin{ 0 }; Vector3 origin{ 0 };
brush_t *brushes, *lastBrush, *colorModBrushes; brushlist_t brushes;
std::vector<brush_t*> colorModBrushes;
parseMesh_t *patches; parseMesh_t *patches;
int mapEntityNum, firstDrawSurf; int mapEntityNum, firstDrawSurf;
int firstBrush, numBrushes; /* only valid during BSP compile */ int firstBrush, numBrushes; /* only valid during BSP compile */
@ -1059,10 +1058,8 @@ struct node_t
int planenum; /* -1 = leaf node */ int planenum; /* -1 = leaf node */
node_t *parent; node_t *parent;
MinMax minmax; /* valid after portalization */ MinMax minmax; /* valid after portalization */
brush_t *volume; /* one for each leaf/node */
/* nodes only */ /* nodes only */
side_t *side; /* the side that created the node */
node_t *children[ 2 ]; node_t *children[ 2 ];
int compileFlags; /* ydnar: hint, antiportal */ int compileFlags; /* ydnar: hint, antiportal */
int tinyportals; int tinyportals;
@ -1075,7 +1072,7 @@ struct node_t
bool sky; /* ydnar: a sky leaf */ bool sky; /* ydnar: a sky leaf */
int cluster; /* for portalfile writing */ int cluster; /* for portalfile writing */
int area; /* for areaportals */ int area; /* for areaportals */
brush_t *brushlist; /* fragments of all brushes in this leaf */ brushlist_t brushlist; /* fragments of all brushes in this leaf */
drawSurfRef_t *drawSurfReferences; drawSurfRef_t *drawSurfReferences;
int occupied; /* 1 or greater can reach entity */ int occupied; /* 1 or greater can reach entity */
@ -1093,11 +1090,10 @@ struct portal_t
node_t *onnode; /* NULL = outside box */ node_t *onnode; /* NULL = outside box */
node_t *nodes[ 2 ]; /* [ 0 ] = front side of plane */ node_t *nodes[ 2 ]; /* [ 0 ] = front side of plane */
portal_t *next[ 2 ]; portal_t *next[ 2 ];
winding_t *winding; winding_t winding;
bool sidefound; /* false if ->side hasn't been checked */ bool sidefound; /* false if ->side hasn't been checked */
int compileFlags; /* from original face that caused the split */ int compileFlags; /* from original face that caused the split */
side_t *side; /* NULL = non-visible */
}; };
@ -1551,28 +1547,20 @@ int ConvertBSPToOBJ( char *bspName );
/* brush.c */ /* brush.c */
sideRef_t *AllocSideRef( side_t *side, sideRef_t *next ); sideRef_t *AllocSideRef( const side_t *side, sideRef_t *next );
int CountBrushList( brush_t *brushes ); bool BoundBrush( brush_t& brush );
brush_t *AllocBrush( int numsides );
void FreeBrush( brush_t *brushes );
void FreeBrushList( brush_t *brushes );
brush_t *CopyBrush( const brush_t *brush );
bool BoundBrush( brush_t *brush );
Vector3 SnapWeldVector( const Vector3& a, const Vector3& b ); Vector3 SnapWeldVector( const Vector3& a, const Vector3& b );
bool CreateBrushWindings( brush_t *brush ); bool CreateBrushWindings( brush_t& brush );
brush_t *BrushFromBounds( const Vector3& mins, const Vector3& maxs ); brush_t BrushFromBounds( const Vector3& mins, const Vector3& maxs );
float BrushVolume( brush_t *brush ); float BrushVolume( const brush_t& brush );
void WriteBSPBrushMap( const char *name, brush_t *list ); void WriteBSPBrushMap( const char *name, const brushlist_t& list );
void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree ); void FilterDetailBrushesIntoTree( entity_t *e, tree_t& tree );
void FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree ); void FilterStructuralBrushesIntoTree( entity_t *e, tree_t& tree );
bool WindingIsTiny( const winding_t& w ); bool WindingIsTiny( const winding_t& w );
void SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back ); std::pair<brush_t*, brush_t*> SplitBrush( const brush_t& brush, int planenum );
tree_t *AllocTree( void );
node_t *AllocNode( void );
/* mesh.c */ /* mesh.c */
@ -1600,11 +1588,10 @@ inline int FindFloatPlane( const Vector3& normal, float dist, i
} }
bool PlaneEqual( const plane_t& p, const Plane3f& plane ); bool PlaneEqual( const plane_t& p, const Plane3f& plane );
void AddBrushBevels( void ); void AddBrushBevels( void );
brush_t *FinishBrush( bool noCollapseGroups );
/* portals.c */ /* portals.c */
void MakeHeadnodePortals( tree_t *tree ); void MakeHeadnodePortals( tree_t& tree );
void MakeNodePortal( node_t *node ); void MakeNodePortal( node_t *node );
void SplitNodePortals( node_t *node ); void SplitNodePortals( node_t *node );
@ -1616,32 +1603,33 @@ enum class EFloodEntities
Good, Good,
Empty Empty
}; };
EFloodEntities FloodEntities( tree_t *tree ); EFloodEntities FloodEntities( tree_t& tree );
void FillOutside( node_t *headnode ); void FillOutside( node_t *headnode );
void FloodAreas( tree_t *tree ); void FloodAreas( tree_t& tree );
void FreePortal( portal_t *p ); inline portal_t *AllocPortal( void ){ return new portal_t(); }
inline void FreePortal( portal_t *p ){ delete p; }
void MakeTreePortals( tree_t *tree ); void MakeTreePortals( tree_t& tree );
/* leakfile.c */ /* leakfile.c */
xmlNodePtr LeakFile( tree_t *tree ); xmlNodePtr LeakFile( const tree_t& tree );
/* prtfile.c */ /* prtfile.c */
void NumberClusters( tree_t *tree ); void NumberClusters( tree_t& tree );
void WritePortalFile( tree_t *tree ); void WritePortalFile( const tree_t& tree );
/* writebsp.c */ /* writebsp.c */
void SetModelNumbers( void ); void SetModelNumbers( void );
void SetLightStyles( void ); void SetLightStyles( void );
int EmitShader( const char *shader, int *contentFlags, int *surfaceFlags ); int EmitShader( const char *shader, const int *contentFlags, const int *surfaceFlags );
void BeginBSPFile( void ); void BeginBSPFile( void );
void EndBSPFile( bool do_write ); void EndBSPFile( bool do_write );
void EmitBrushes( brush_t *brushes, int *firstBrush, int *numBrushes ); void EmitBrushes( brushlist_t& brushes, int *firstBrush, int *numBrushes );
void EmitFogs( void ); void EmitFogs( void );
void BeginModel( void ); void BeginModel( void );
@ -1649,10 +1637,11 @@ void EndModel( entity_t *e, node_t *headnode );
/* tree.c */ /* tree.c */
void FreeTree( tree_t *tree ); void FreeTree( tree_t& tree );
void FreeTree_r( node_t *node ); void FreeTree_r( node_t *node );
void PrintTree_r( node_t *node, int depth ); void PrintTree_r( const node_t *node, int depth );
void FreeTreePortals_r( node_t *node ); void FreeTreePortals_r( node_t *node );
inline node_t *AllocNode(){ return new node_t(); }
/* patch.c */ /* patch.c */
@ -1667,7 +1656,7 @@ void FixTJunctions( entity_t *e );
/* fog.c */ /* fog.c */
winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds ); winding_t WindingFromDrawSurf( const mapDrawSurface_t *ds );
void FogDrawSurfaces( entity_t *e ); void FogDrawSurfaces( entity_t *e );
int FogForPoint( const Vector3& point, float epsilon ); int FogForPoint( const Vector3& point, float epsilon );
int FogForBounds( const MinMax& minmax, float epsilon ); int FogForBounds( const MinMax& minmax, float epsilon );
@ -1675,9 +1664,9 @@ void CreateMapFogs( void );
/* facebsp.c */ /* facebsp.c */
facelist_t MakeStructuralBSPFaceList( const brush_t *list ); facelist_t MakeStructuralBSPFaceList( const brushlist_t& list );
facelist_t MakeVisibleBSPFaceList( const brush_t *list ); facelist_t MakeVisibleBSPFaceList( const brushlist_t& list );
tree_t *FaceBSP( facelist_t& list ); tree_t FaceBSP( facelist_t& list );
/* model.c */ /* model.c */
@ -1701,17 +1690,17 @@ mapDrawSurface_t *MakeCelSurface( mapDrawSurface_t *src, shaderInfo_t
bool IsTriangleDegenerate( bspDrawVert_t *points, int a, int b, int c ); bool IsTriangleDegenerate( bspDrawVert_t *points, int a, int b, int c );
void ClearSurface( mapDrawSurface_t *ds ); void ClearSurface( mapDrawSurface_t *ds );
void AddEntitySurfaceModels( entity_t *e ); void AddEntitySurfaceModels( entity_t *e );
mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, const winding_t& w ); mapDrawSurface_t *DrawSurfaceForSide( const entity_t *e, const brush_t& b, const side_t& s, const winding_t& w );
mapDrawSurface_t *DrawSurfaceForMesh( entity_t *e, parseMesh_t *p, mesh_t *mesh ); mapDrawSurface_t *DrawSurfaceForMesh( entity_t *e, parseMesh_t *p, mesh_t *mesh );
mapDrawSurface_t *DrawSurfaceForFlare( int entNum, const Vector3& origin, const Vector3& normal, const Vector3& color, const char *flareShader, int lightStyle ); mapDrawSurface_t *DrawSurfaceForFlare( int entNum, const Vector3& origin, const Vector3& normal, const Vector3& color, const char *flareShader, int lightStyle );
mapDrawSurface_t *DrawSurfaceForShader( const char *shader ); mapDrawSurface_t *DrawSurfaceForShader( const char *shader );
void ClipSidesIntoTree( entity_t *e, tree_t *tree ); void ClipSidesIntoTree( entity_t *e, const tree_t& tree );
void MakeDebugPortalSurfs( tree_t *tree ); void MakeDebugPortalSurfs( const tree_t& tree );
void MakeFogHullSurfs( entity_t *e, tree_t *tree, const char *shader ); void MakeFogHullSurfs( entity_t *e, const char *shader );
void SubdivideFaceSurfaces( entity_t *e, tree_t *tree ); void SubdivideFaceSurfaces( entity_t *e );
void AddEntitySurfaceModels( entity_t *e ); void AddEntitySurfaceModels( entity_t *e );
int AddSurfaceModels( mapDrawSurface_t *ds ); int AddSurfaceModels( mapDrawSurface_t *ds );
void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree ); void FilterDrawsurfsIntoTree( entity_t *e, tree_t& tree );
void EmitPatchSurface( entity_t *e, mapDrawSurface_t *ds ); void EmitPatchSurface( entity_t *e, mapDrawSurface_t *ds );
void EmitTriangleSurface( mapDrawSurface_t *ds ); void EmitTriangleSurface( mapDrawSurface_t *ds );
@ -2112,7 +2101,7 @@ Q_EXTERN int numMapFogs Q_ASSIGN( 0 );
Q_EXTERN fog_t mapFogs[ MAX_MAP_FOGS ]; Q_EXTERN fog_t mapFogs[ MAX_MAP_FOGS ];
Q_EXTERN entity_t *mapEnt; Q_EXTERN entity_t *mapEnt;
Q_EXTERN brush_t *buildBrush; Q_EXTERN brush_t buildBrush;
Q_EXTERN EBrushType g_brushType Q_ASSIGN( EBrushType::Undefined ); Q_EXTERN EBrushType g_brushType Q_ASSIGN( EBrushType::Undefined );
Q_EXTERN int numStrippedLights Q_ASSIGN( 0 ); Q_EXTERN int numStrippedLights Q_ASSIGN( 0 );

View File

@ -761,12 +761,13 @@ shaderInfo_t *GetIndexedShader( const shaderInfo_t *parent, const indexMap_t *im
/* /*
DrawSurfaceForSide() DrawSurfaceForSide()
creates a SURF_FACE drawsurface from a given brush side and winding creates a SURF_FACE drawsurface from a given brush side and winding
stores references to given brush and side
*/ */
const double SNAP_FLOAT_TO_INT = 8.0; const double SNAP_FLOAT_TO_INT = 8.0;
const double SNAP_INT_TO_FLOAT = ( 1.0 / SNAP_FLOAT_TO_INT ); const double SNAP_INT_TO_FLOAT = ( 1.0 / SNAP_FLOAT_TO_INT );
mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, const winding_t& w ){ mapDrawSurface_t *DrawSurfaceForSide( const entity_t *e, const brush_t& b, const side_t& s, const winding_t& w ){
mapDrawSurface_t *ds; mapDrawSurface_t *ds;
shaderInfo_t *si, *parent; shaderInfo_t *si, *parent;
bspDrawVert_t *dv; bspDrawVert_t *dv;
@ -779,7 +780,7 @@ mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, const
/* ydnar: don't make a drawsurf for culled sides */ /* ydnar: don't make a drawsurf for culled sides */
if ( s->culled ) { if ( s.culled ) {
return NULL; return NULL;
} }
@ -789,24 +790,24 @@ mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, const
} }
/* get shader */ /* get shader */
si = s->shaderInfo; si = s.shaderInfo;
/* ydnar: gs mods: check for indexed shader */ /* ydnar: gs mods: check for indexed shader */
if ( si->indexed && b->im != NULL ) { if ( si->indexed && b.im != NULL ) {
/* indexed */ /* indexed */
indexed = true; indexed = true;
/* get shader indexes for each point */ /* get shader indexes for each point */
for ( size_t i = 0; i < w.size(); i++ ) for ( size_t i = 0; i < w.size(); i++ )
{ {
shaderIndexes[ i ] = GetShaderIndexForPoint( b->im, b->eMinmax, w[ i ] ); shaderIndexes[ i ] = GetShaderIndexForPoint( b.im, b.eMinmax, w[ i ] );
offsets[ i ] = b->im->offsets[ shaderIndexes[ i ] ]; offsets[ i ] = b.im->offsets[ shaderIndexes[ i ] ];
//% Sys_Printf( "%f ", offsets[ i ] ); //% Sys_Printf( "%f ", offsets[ i ] );
} }
/* get matching shader and set alpha */ /* get matching shader and set alpha */
parent = si; parent = si;
si = GetIndexedShader( parent, b->im, w.size(), shaderIndexes ); si = GetIndexedShader( parent, b.im, w.size(), shaderIndexes );
} }
else{ else{
indexed = false; indexed = false;
@ -821,25 +822,25 @@ mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, const
/* ydnar: gs mods */ /* ydnar: gs mods */
ds = AllocDrawSurface( ESurfaceType::Face ); ds = AllocDrawSurface( ESurfaceType::Face );
ds->entityNum = b->entityNum; ds->entityNum = b.entityNum;
ds->castShadows = b->castShadows; ds->castShadows = b.castShadows;
ds->recvShadows = b->recvShadows; ds->recvShadows = b.recvShadows;
ds->planar = true; ds->planar = true;
ds->planeNum = s->planenum; ds->planeNum = s.planenum;
ds->lightmapVecs[ 2 ] = mapplanes[ s->planenum ].normal(); ds->lightmapVecs[ 2 ] = mapplanes[ s.planenum ].normal();
ds->shaderInfo = si; ds->shaderInfo = si;
ds->mapBrush = b; ds->mapBrush = &b;
ds->sideRef = AllocSideRef( s, NULL ); ds->sideRef = AllocSideRef( &s, NULL );
ds->fogNum = -1; ds->fogNum = -1;
ds->sampleSize = b->lightmapSampleSize; ds->sampleSize = b.lightmapSampleSize;
ds->lightmapScale = b->lightmapScale; ds->lightmapScale = b.lightmapScale;
ds->numVerts = w.size(); ds->numVerts = w.size();
ds->verts = safe_calloc( ds->numVerts * sizeof( *ds->verts ) ); ds->verts = safe_calloc( ds->numVerts * sizeof( *ds->verts ) );
/* compute s/t coordinates from brush primitive texture matrix (compute axis base) */ /* compute s/t coordinates from brush primitive texture matrix (compute axis base) */
ComputeAxisBase( mapplanes[ s->planenum ].normal(), texX, texY ); ComputeAxisBase( mapplanes[ s.planenum ].normal(), texX, texY );
/* create the vertexes */ /* create the vertexes */
for ( size_t j = 0; j < w.size(); j++ ) for ( size_t j = 0; j < w.size(); j++ )
@ -874,21 +875,21 @@ mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, const
/* calculate texture s/t from brush primitive texture matrix */ /* calculate texture s/t from brush primitive texture matrix */
x = vector3_dot( vTranslated, texX ); x = vector3_dot( vTranslated, texX );
y = vector3_dot( vTranslated, texY ); y = vector3_dot( vTranslated, texY );
dv->st[ 0 ] = s->texMat[ 0 ][ 0 ] * x + s->texMat[ 0 ][ 1 ] * y + s->texMat[ 0 ][ 2 ]; 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 ]; dv->st[ 1 ] = s.texMat[ 1 ][ 0 ] * x + s.texMat[ 1 ][ 1 ] * y + s.texMat[ 1 ][ 2 ];
} }
/* old quake-style or valve 220 texturing */ /* old quake-style or valve 220 texturing */
else { else {
/* nearest-axial projection */ /* nearest-axial projection */
dv->st[ 0 ] = s->vecs[ 0 ][ 3 ] + vector3_dot( s->vecs[ 0 ].vec3(), vTranslated ); dv->st[ 0 ] = s.vecs[ 0 ][ 3 ] + vector3_dot( s.vecs[ 0 ].vec3(), vTranslated );
dv->st[ 1 ] = s->vecs[ 1 ][ 3 ] + vector3_dot( s->vecs[ 1 ].vec3(), vTranslated ); dv->st[ 1 ] = s.vecs[ 1 ][ 3 ] + vector3_dot( s.vecs[ 1 ].vec3(), vTranslated );
dv->st[ 0 ] /= si->shaderWidth; dv->st[ 0 ] /= si->shaderWidth;
dv->st[ 1 ] /= si->shaderHeight; dv->st[ 1 ] /= si->shaderHeight;
} }
/* copy normal */ /* copy normal */
dv->normal = mapplanes[ s->planenum ].normal(); dv->normal = mapplanes[ s.planenum ].normal();
/* ydnar: set color */ /* ydnar: set color */
for ( int k = 0; k < MAX_LIGHTMAPS; k++ ) for ( int k = 0; k < MAX_LIGHTMAPS; k++ )
@ -902,11 +903,11 @@ mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, const
} }
/* set cel shader */ /* set cel shader */
ds->celShader = b->celShader; ds->celShader = b.celShader;
/* set shade angle */ /* set shade angle */
if ( b->shadeAngleDegrees > 0.0f ) { if ( b.shadeAngleDegrees > 0.0f ) {
ds->shadeAngleDegrees = b->shadeAngleDegrees; ds->shadeAngleDegrees = b.shadeAngleDegrees;
} }
/* ydnar: gs mods: moved st biasing elsewhere */ /* ydnar: gs mods: moved st biasing elsewhere */
@ -1202,25 +1203,24 @@ static void AddSurfaceFlare( mapDrawSurface_t *ds, const Vector3& entityOrigin )
subdivides a face surface until it is smaller than the specified size (subdivisions) 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, const winding_t *w, int fogNum, float subdivisions ){ static void SubdivideFace_r( entity_t *e, const brush_t& brush, const side_t& side, winding_t& w, int fogNum, float subdivisions ){
int axis; int axis;
MinMax bounds; MinMax bounds;
const float epsilon = 0.1; const float epsilon = 0.1;
int subFloor, subCeil; int subFloor, subCeil;
winding_t *frontWinding, *backWinding;
mapDrawSurface_t *ds; mapDrawSurface_t *ds;
/* dummy check */ /* dummy check */
if ( w == NULL ) { if ( w.empty() ) {
return; return;
} }
if ( w->size() < 3 ) { if ( w.size() < 3 ) {
Error( "SubdivideFace_r: Bad w->numpoints (%zu < 3)", w->size() ); Error( "SubdivideFace_r: Bad w->numpoints (%zu < 3)", w.size() );
} }
/* determine surface bounds */ /* determine surface bounds */
WindingExtendBounds( *w, bounds ); WindingExtendBounds( w, bounds );
/* split the face */ /* split the face */
for ( axis = 0; axis < 3; axis++ ) for ( axis = 0; axis < 3; axis++ )
@ -1239,14 +1239,14 @@ static void SubdivideFace_r( entity_t *e, brush_t *brush, side_t *side, const wi
/* subdivide if necessary */ /* subdivide if necessary */
if ( ( subCeil - subFloor ) > subdivisions ) { if ( ( subCeil - subFloor ) > subdivisions ) {
/* clip the winding */ /* clip the winding */
ClipWindingEpsilon( *w, plane, epsilon, frontWinding, backWinding ); /* not strict; we assume we always keep a winding */ auto [frontWinding, backWinding] = ClipWindingEpsilon( w, plane, epsilon ); /* not strict; we assume we always keep a winding */
/* the clip may not produce two polygons if it was epsilon close */ /* the clip may not produce two polygons if it was epsilon close */
if ( frontWinding == NULL ) { if ( frontWinding.empty() ) {
w = backWinding; w.swap( backWinding );
} }
else if ( backWinding == NULL ) { else if ( backWinding.empty() ) {
w = frontWinding; w.swap( frontWinding );
} }
else else
{ {
@ -1258,7 +1258,7 @@ static void SubdivideFace_r( entity_t *e, brush_t *brush, side_t *side, const wi
} }
/* create a face surface */ /* create a face surface */
ds = DrawSurfaceForSide( e, brush, side, *w ); ds = DrawSurfaceForSide( e, brush, side, w );
/* set correct fog num */ /* set correct fog num */
ds->fogNum = fogNum; ds->fogNum = fogNum;
@ -1272,13 +1272,9 @@ static void SubdivideFace_r( entity_t *e, brush_t *brush, side_t *side, const wi
ydnar: and subdivide surfaces that exceed specified texture coordinate range ydnar: and subdivide surfaces that exceed specified texture coordinate range
*/ */
void SubdivideFaceSurfaces( entity_t *e, tree_t *tree ){ void SubdivideFaceSurfaces( entity_t *e ){
int i, j, numBaseDrawSurfs, fogNum; int i, j, numBaseDrawSurfs, fogNum;
mapDrawSurface_t *ds; mapDrawSurface_t *ds;
brush_t *brush;
side_t *side;
shaderInfo_t *si;
winding_t *w;
float range, size, subdivisions, s2; float range, size, subdivisions, s2;
@ -1298,11 +1294,11 @@ void SubdivideFaceSurfaces( entity_t *e, tree_t *tree ){
} }
/* get bits */ /* get bits */
brush = ds->mapBrush; const brush_t *brush = ds->mapBrush;
side = ds->sideRef->side; const side_t& side = *ds->sideRef->side;
/* check subdivision for shader */ /* check subdivision for shader */
si = side->shaderInfo; const shaderInfo_t *si = side.shaderInfo;
if ( si == NULL ) { if ( si == NULL ) {
continue; continue;
} }
@ -1347,11 +1343,11 @@ void SubdivideFaceSurfaces( entity_t *e, tree_t *tree ){
fogNum = ds->fogNum; fogNum = ds->fogNum;
/* make a winding and free the surface */ /* make a winding and free the surface */
w = WindingFromDrawSurf( ds ); winding_t w = WindingFromDrawSurf( ds );
ClearSurface( ds ); ClearSurface( ds );
/* subdivide it */ /* subdivide it */
SubdivideFace_r( e, brush, side, w, fogNum, subdivisions ); SubdivideFace_r( e, *brush, side, w, fogNum, subdivisions );
} }
} }
@ -1365,46 +1361,40 @@ void SubdivideFaceSurfaces( entity_t *e, tree_t *tree ){
==================== ====================
*/ */
void ClipSideIntoTree_r( winding_t *w, side_t *side, node_t *node ){ void ClipSideIntoTree_r( const winding_t& w, side_t& side, const node_t *node ){
winding_t *front, *back; if ( w.empty() ) {
if ( !w ) {
return; return;
} }
if ( node->planenum != PLANENUM_LEAF ) { if ( node->planenum != PLANENUM_LEAF ) {
if ( side->planenum == node->planenum ) { if ( side.planenum == node->planenum ) {
ClipSideIntoTree_r( w, side, node->children[0] ); ClipSideIntoTree_r( w, side, node->children[0] );
return; return;
} }
if ( side->planenum == ( node->planenum ^ 1 ) ) { if ( side.planenum == ( node->planenum ^ 1 ) ) {
ClipSideIntoTree_r( w, side, node->children[1] ); ClipSideIntoTree_r( w, side, node->children[1] );
return; return;
} }
const Plane3f& plane = mapplanes[ node->planenum ].plane; const Plane3f& plane = mapplanes[ node->planenum ].plane;
ClipWindingEpsilonStrict( *w, plane, auto [front, back] = ClipWindingEpsilonStrict( w, plane, ON_EPSILON ); /* strict, we handle the "winding disappeared" case */
ON_EPSILON, front, back ); /* strict, we handle the "winding disappeared" case */ if ( front.empty() && back.empty() ) {
if ( !front && !back ) {
/* in doubt, register it in both nodes */ /* in doubt, register it in both nodes */
front = CopyWinding( w ); ClipSideIntoTree_r( w, side, node->children[0] );
back = CopyWinding( w ); ClipSideIntoTree_r( w, side, node->children[1] );
}
else{
ClipSideIntoTree_r( front, side, node->children[0] );
ClipSideIntoTree_r( back, side, node->children[1] );
} }
FreeWinding( w );
ClipSideIntoTree_r( front, side, node->children[0] );
ClipSideIntoTree_r( back, side, node->children[1] );
return; return;
} }
// if opaque leaf, don't add // if opaque leaf, don't add
if ( !node->opaque ) { if ( !node->opaque ) {
AddWindingToConvexHull( *w, side->visibleHull, mapplanes[ side->planenum ].normal() ); AddWindingToConvexHull( w, side.visibleHull, mapplanes[ side.planenum ].normal() );
} }
FreeWinding( w );
return;
} }
@ -1422,44 +1412,42 @@ static int g_numHiddenFaces, g_numCoinFaces;
determines if a brushside lies inside another brush determines if a brushside lies inside another brush
*/ */
bool SideInBrush( side_t *side, brush_t *b ){ bool SideInBrush( side_t& side, const brush_t& b ){
/* ignore sides w/o windings or shaders */ /* ignore sides w/o windings or shaders */
if ( side->winding == NULL || side->shaderInfo == NULL ) { if ( side.winding.empty() || side.shaderInfo == NULL ) {
return true; return true;
} }
/* ignore culled sides and translucent brushes */ /* ignore culled sides and translucent brushes */
if ( side->culled || ( b->compileFlags & C_TRANSLUCENT ) ) { if ( side.culled || ( b.compileFlags & C_TRANSLUCENT ) ) {
return false; return false;
} }
/* side iterator */ /* side iterator */
for ( int i = 0; i < b->numsides; i++ ) for ( const side_t& bside : b.sides )
{ {
/* fail if any sides are caulk */ /* fail if any sides are caulk */
if ( b->sides[ i ].compileFlags & C_NODRAW ) { if ( bside.compileFlags & C_NODRAW ) {
return false; return false;
} }
/* check if side's winding is on or behind the plane */ /* check if side's winding is on or behind the plane */
const Plane3f& plane = mapplanes[ b->sides[ i ].planenum ].plane; const Plane3f& plane = mapplanes[ bside.planenum ].plane;
const EPlaneSide s = WindingOnPlaneSide( *side->winding, plane ); const EPlaneSide s = WindingOnPlaneSide( side.winding, plane );
if ( s == eSideFront || s == eSideCross ) { if ( s == eSideFront || s == eSideCross ) {
return false; return false;
} }
if( s == eSideOn && b->sides[ i ].culled && vector3_dot( mapplanes[ side->planenum ].normal(), plane.normal() ) > 0 ) /* don't cull by freshly culled with matching plane */ if( s == eSideOn && bside.culled && vector3_dot( mapplanes[ side.planenum ].normal(), plane.normal() ) > 0 ) /* don't cull by freshly culled with matching plane */
return false; return false;
} }
/* don't cull autosprite or polygonoffset surfaces */ /* don't cull autosprite or polygonoffset surfaces */
if ( side->shaderInfo ) { if ( side.shaderInfo->autosprite || side.shaderInfo->polygonOffset ) {
if ( side->shaderInfo->autosprite || side->shaderInfo->polygonOffset ) { return false;
return false;
}
} }
/* inside */ /* inside */
side->culled = true; side.culled = true;
g_numHiddenFaces++; g_numHiddenFaces++;
return true; return true;
} }
@ -1471,11 +1459,7 @@ bool SideInBrush( side_t *side, brush_t *b ){
*/ */
void CullSides( entity_t *e ){ void CullSides( entity_t *e ){
int numPoints; int k, l, first, second, dir;
int i, j, k, l, first, second, dir;
const winding_t *w1, *w2;
brush_t *b1, *b2;
side_t *side1, *side2;
/* note it */ /* note it */
@ -1485,18 +1469,18 @@ void CullSides( entity_t *e ){
g_numCoinFaces = 0; g_numCoinFaces = 0;
/* brush interator 1 */ /* brush interator 1 */
for ( b1 = e->brushes; b1; b1 = b1->next ) for ( brushlist_t::iterator b1 = e->brushes.begin(); b1 != e->brushes.end(); ++b1 )
{ {
/* sides check */ /* sides check */
if ( b1->numsides < 1 ) { if ( b1->sides.empty() ) {
continue; continue;
} }
/* brush iterator 2 */ /* brush iterator 2 */
for ( b2 = b1->next; b2; b2 = b2->next ) for ( brushlist_t::iterator b2 = std::next( b1 ); b2 != e->brushes.end(); ++b2 )
{ {
/* sides check */ /* sides check */
if ( b2->numsides < 1 ) { if ( b2->sides.empty() ) {
continue; continue;
} }
@ -1511,56 +1495,52 @@ void CullSides( entity_t *e ){
} }
/* cull inside sides */ /* cull inside sides */
for ( i = 0; i < b1->numsides; i++ ) for ( side_t& side : b1->sides )
SideInBrush( &b1->sides[ i ], b2 ); SideInBrush( side, *b2 );
for ( i = 0; i < b2->numsides; i++ ) for ( side_t& side : b2->sides )
SideInBrush( &b2->sides[ i ], b1 ); SideInBrush( side, *b1 );
/* side iterator 1 */ /* side iterator 1 */
for ( i = 0; i < b1->numsides; i++ ) for ( side_t& side1 : b1->sides )
{ {
/* winding check */ /* winding check */
side1 = &b1->sides[ i ]; winding_t& w1 = side1.winding;
w1 = side1->winding; if ( w1.empty() ) {
if ( w1 == NULL ) {
continue; continue;
} }
numPoints = w1->size(); const int numPoints = w1.size();
if ( side1->shaderInfo == NULL ) { if ( side1.shaderInfo == NULL ) {
continue; continue;
} }
/* side iterator 2 */ /* side iterator 2 */
for ( j = 0; j < b2->numsides; j++ ) for ( side_t& side2 : b2->sides )
{ {
/* winding check */ /* winding check */
side2 = &b2->sides[ j ]; winding_t& w2 = side2.winding;
w2 = side2->winding; if ( w2.empty() ) {
if ( w2 == NULL ) {
continue; continue;
} }
if ( side2->shaderInfo == NULL ) { if ( side2.shaderInfo == NULL ) {
continue; continue;
} }
if ( w1->size() != w2->size() ) { if ( w1.size() != w2.size() ) {
continue; continue;
} }
if ( side1->culled && side2->culled ) { if ( side1.culled && side2.culled ) {
continue; continue;
} }
/* compare planes */ /* compare planes */
if ( ( side1->planenum & ~0x00000001 ) != ( side2->planenum & ~0x00000001 ) ) { if ( ( side1.planenum & ~0x00000001 ) != ( side2.planenum & ~0x00000001 ) ) {
continue; continue;
} }
/* get autosprite and polygonoffset status */ /* get autosprite and polygonoffset status */
if ( side1->shaderInfo && if ( side1.shaderInfo->autosprite || side1.shaderInfo->polygonOffset ) {
( side1->shaderInfo->autosprite || side1->shaderInfo->polygonOffset ) ) {
continue; continue;
} }
if ( side2->shaderInfo && if ( side2.shaderInfo->autosprite || side2.shaderInfo->polygonOffset ) {
( side2->shaderInfo->autosprite || side2->shaderInfo->polygonOffset ) ) {
continue; continue;
} }
@ -1568,7 +1548,7 @@ void CullSides( entity_t *e ){
first = -1; first = -1;
for ( k = 0; k < numPoints; k++ ) for ( k = 0; k < numPoints; k++ )
{ {
if ( VectorCompare( ( *w1 )[ 0 ], ( *w2 )[ k ] ) ) { if ( VectorCompare( w1[ 0 ], w2[ k ] ) ) {
first = k; first = k;
break; break;
} }
@ -1586,7 +1566,7 @@ void CullSides( entity_t *e ){
else{ else{
second = 0; 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;
} }
else else
@ -1597,7 +1577,7 @@ void CullSides( entity_t *e ){
else{ else{
second = numPoints - 1; second = numPoints - 1;
} }
if ( vector3_equal_epsilon( ( *w1 )[ 1 ], ( *w2 )[ second ], CULL_EPSILON ) ) { if ( vector3_equal_epsilon( w1[ 1 ], w2[ second ], CULL_EPSILON ) ) {
dir = -1; dir = -1;
} }
} }
@ -1609,7 +1589,7 @@ void CullSides( entity_t *e ){
l = first; l = first;
for ( k = 0; k < numPoints; k++ ) for ( k = 0; k < numPoints; k++ )
{ {
if ( !vector3_equal_epsilon( ( *w1 )[ k ], ( *w2 )[ l ], CULL_EPSILON ) ) { if ( !vector3_equal_epsilon( w1[ k ], w2[ l ], CULL_EPSILON ) ) {
k = 100000; k = 100000;
} }
@ -1626,18 +1606,18 @@ void CullSides( entity_t *e ){
} }
/* cull face 1 */ /* 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 = true; side1.culled = true;
g_numCoinFaces++; g_numCoinFaces++;
} }
if ( side1->planenum == side2->planenum && side1->culled ) { if ( side1.planenum == side2.planenum && side1.culled ) {
continue; continue;
} }
/* cull face 2 */ /* 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 = true; side2.culled = true;
g_numCoinFaces++; g_numCoinFaces++;
} }
@ -1665,14 +1645,7 @@ void CullSides( entity_t *e ){
to be trimmed off automatically. to be trimmed off automatically.
*/ */
void ClipSidesIntoTree( entity_t *e, tree_t *tree ){ void ClipSidesIntoTree( entity_t *e, const tree_t& tree ){
brush_t *b;
int i;
winding_t *w;
side_t *side, *newSide;
shaderInfo_t *si;
/* ydnar: cull brush sides */ /* ydnar: cull brush sides */
CullSides( e ); CullSides( e );
@ -1680,30 +1653,25 @@ void ClipSidesIntoTree( entity_t *e, tree_t *tree ){
Sys_FPrintf( SYS_VRB, "--- ClipSidesIntoTree ---\n" ); Sys_FPrintf( SYS_VRB, "--- ClipSidesIntoTree ---\n" );
/* walk the brush list */ /* walk the brush list */
for ( b = e->brushes; b; b = b->next ) for ( brush_t& b : e->brushes )
{ {
/* walk the brush sides */ /* walk the brush sides */
for ( i = 0; i < b->numsides; i++ ) for ( side_t& side : b.sides )
{ {
/* get side */ if ( side.winding.empty() ) {
side = &b->sides[ i ];
if ( side->winding == NULL ) {
continue; continue;
} }
/* copy the winding */ side.visibleHull.clear();
w = CopyWinding( side->winding ); ClipSideIntoTree_r( side.winding, side, tree.headnode );
side->visibleHull = NULL;
ClipSideIntoTree_r( w, side, tree->headnode );
/* anything left? */ /* anything left? */
w = side->visibleHull; if ( side.visibleHull.empty() ) {
if ( w == NULL ) {
continue; continue;
} }
/* shader? */ /* shader? */
si = side->shaderInfo; const shaderInfo_t *si = side.shaderInfo;
if ( si == NULL ) { if ( si == NULL ) {
continue; continue;
} }
@ -1715,27 +1683,21 @@ void ClipSidesIntoTree( entity_t *e, tree_t *tree ){
} }
/* always use the original winding for autosprites and noclip faces */ /* always use the original winding for autosprites and noclip faces */
if ( si->autosprite || si->noClip ) { const winding_t& w = ( si->autosprite || si->noClip )? side.winding : side.visibleHull;
w = side->winding;
}
/* save this winding as a visible surface */ /* save this winding as a visible surface */
DrawSurfaceForSide( e, b, side, *w ); DrawSurfaceForSide( e, b, side, w );
/* make a back side for fog */ /* make a back side for fog */
if ( !( si->compileFlags & C_FOG ) ) { if ( si->compileFlags & C_FOG ) {
continue; /* duplicate the up-facing side */
side_t& newSide = *new side_t( side );
newSide.visibleHull = ReverseWinding( w );
newSide.planenum ^= 1;
/* save this winding as a visible surface */
DrawSurfaceForSide( e, b, newSide, newSide.visibleHull ); // references new side by sideref, leak!
} }
/* 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 );
} }
} }
} }
@ -1910,14 +1872,11 @@ int FilterPointConvexHullIntoTree_r( Vector3 *points[], const int npoints, mapDr
filters a winding from a drawsurface into the tree filters a winding from a drawsurface into the tree
*/ */
int FilterWindingIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node ){ int FilterWindingIntoTree_r( winding_t& w, mapDrawSurface_t *ds, node_t *node ){
int refs = 0; int refs = 0;
winding_t *fat, *front, *back;
shaderInfo_t *si;
/* get shaderinfo */ /* get shaderinfo */
si = ds->shaderInfo; const shaderInfo_t *si = ds->shaderInfo;
/* ydnar: is this the head node? */ /* ydnar: is this the head node? */
if ( node->parent == NULL && si != NULL && si->minmax.valid() ) { if ( node->parent == NULL && si != NULL && si->minmax.valid() ) {
@ -1929,17 +1888,16 @@ int FilterWindingIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node ){
/* 'fatten' the winding by the shader mins/maxs (parsed from vertexDeform move) */ /* 'fatten' the winding by the shader mins/maxs (parsed from vertexDeform move) */
/* note this winding is completely invalid (concave, nonplanar, etc) */ /* note this winding is completely invalid (concave, nonplanar, etc) */
fat = AllocWinding( w->size() * 3 + 3 ); winding_t fat( w.size() * 3 + 3 );
fat->resize( w->size() * 3 + 3 ); for ( size_t i = 0; i < w.size(); i++ )
for ( size_t i = 0; i < w->size(); i++ )
{ {
( *fat )[ i ] = ( *w )[ i ]; fat[ i ] = w[ i ];
( *fat )[ i + ( w->size() + 1 ) ] = ( *w )[ i ] + si->minmax.mins; fat[ i + ( w.size() + 1 ) ] = w[ i ] + si->minmax.mins;
( *fat )[ i + ( w->size() + 1 ) * 2 ] = ( *w )[ i ] + si->minmax.maxs; fat[ i + ( w.size() + 1 ) * 2 ] = w[ i ] + si->minmax.maxs;
} }
( *fat )[ w->size() ] = ( *w )[ 0 ]; fat[ w.size() ] = w[ 0 ];
( *fat )[ w->size() * 2 ] = ( *w )[ 0 ] + si->minmax.mins; fat[ w.size() * 2 ] = w[ 0 ] + si->minmax.mins;
( *fat )[ w->size() * 3 ] = ( *w )[ 0 ] + si->minmax.maxs; fat[ w.size() * 3 ] = w[ 0 ] + si->minmax.maxs;
/* /*
* note: this winding is STILL not suitable for ClipWindingEpsilon, and * note: this winding is STILL not suitable for ClipWindingEpsilon, and
@ -1949,8 +1907,7 @@ int FilterWindingIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node ){
* it worse * it worse
*/ */
FreeWinding( w ); w.swap( fat );
w = fat;
} }
/* is this a decision node? */ /* is this a decision node? */
@ -1989,23 +1946,23 @@ int FilterWindingIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node ){
} }
/* clip the winding by this plane */ /* clip the winding by this plane */
ClipWindingEpsilonStrict( *w, plane1, ON_EPSILON, front, back ); /* strict; we handle the "winding disappeared" case */ auto [front, back] = ClipWindingEpsilonStrict( w, plane1, ON_EPSILON ); /* strict; we handle the "winding disappeared" case */
/* filter by this plane */ /* filter by this plane */
refs = 0; refs = 0;
if ( front == NULL && back == NULL ) { if ( front.empty() && back.empty() ) {
/* same plane, this is an ugly hack */ /* same plane, this is an ugly hack */
/* but better too many than too few refs */ /* but better too many than too few refs */
refs += FilterWindingIntoTree_r( CopyWinding( w ), ds, node->children[ 0 ] ); winding_t wcopy( w );
refs += FilterWindingIntoTree_r( CopyWinding( w ), ds, node->children[ 1 ] ); refs += FilterWindingIntoTree_r( wcopy, ds, node->children[ 0 ] );
refs += FilterWindingIntoTree_r( w, ds, node->children[ 1 ] );
} }
if ( front != NULL ) { if ( !front.empty() ) {
refs += FilterWindingIntoTree_r( front, ds, node->children[ 0 ] ); refs += FilterWindingIntoTree_r( front, ds, node->children[ 0 ] );
} }
if ( back != NULL ) { if ( !back.empty() ) {
refs += FilterWindingIntoTree_r( back, ds, node->children[ 1 ] ); refs += FilterWindingIntoTree_r( back, ds, node->children[ 1 ] );
} }
FreeWinding( w );
/* return */ /* return */
return refs; return refs;
@ -2022,14 +1979,10 @@ int FilterWindingIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node ){
filters a planar winding face drawsurface into the bsp tree filters a planar winding face drawsurface into the bsp tree
*/ */
int FilterFaceIntoTree( mapDrawSurface_t *ds, tree_t *tree ){ int FilterFaceIntoTree( mapDrawSurface_t *ds, tree_t& tree ){
winding_t *w;
int refs = 0;
/* make a winding and filter it into the tree */ /* make a winding and filter it into the tree */
w = WindingFromDrawSurf( ds ); winding_t w = WindingFromDrawSurf( ds );
refs = FilterWindingIntoTree_r( w, ds, tree->headnode ); int refs = FilterWindingIntoTree_r( w, ds, tree.headnode );
/* return */ /* return */
return refs; return refs;
@ -2044,7 +1997,7 @@ int FilterFaceIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
#define FILTER_SUBDIVISION 8 #define FILTER_SUBDIVISION 8
static int FilterPatchIntoTree( mapDrawSurface_t *ds, tree_t *tree ){ static int FilterPatchIntoTree( mapDrawSurface_t *ds, tree_t& tree ){
int x, y, refs = 0; int x, y, refs = 0;
for ( y = 0; y + 2 < ds->patchHeight; y += 2 ) for ( y = 0; y + 2 < ds->patchHeight; y += 2 )
@ -2060,7 +2013,7 @@ static int FilterPatchIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
points[6] = &ds->verts[( y + 2 ) * ds->patchWidth + ( x + 0 )].xyz; points[6] = &ds->verts[( y + 2 ) * ds->patchWidth + ( x + 0 )].xyz;
points[7] = &ds->verts[( y + 2 ) * ds->patchWidth + ( x + 1 )].xyz; points[7] = &ds->verts[( y + 2 ) * ds->patchWidth + ( x + 1 )].xyz;
points[8] = &ds->verts[( y + 2 ) * ds->patchWidth + ( x + 2 )].xyz; points[8] = &ds->verts[( y + 2 ) * ds->patchWidth + ( x + 2 )].xyz;
refs += FilterPointConvexHullIntoTree_r( points, 9, ds, tree->headnode ); refs += FilterPointConvexHullIntoTree_r( points, 9, ds, tree.headnode );
} }
return refs; return refs;
@ -2073,9 +2026,8 @@ static int FilterPatchIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
filters a triangle surface (meta, model) into the bsp filters a triangle surface (meta, model) into the bsp
*/ */
static int FilterTrianglesIntoTree( mapDrawSurface_t *ds, tree_t *tree ){ static int FilterTrianglesIntoTree( mapDrawSurface_t *ds, tree_t& tree ){
int i, refs; int i, refs;
winding_t *w;
/* ydnar: gs mods: this was creating bogus triangles before */ /* ydnar: gs mods: this was creating bogus triangles before */
@ -2090,16 +2042,16 @@ static int FilterTrianglesIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
} }
/* make a triangle winding and filter it into the tree */ /* make a triangle winding and filter it into the tree */
w = AllocWinding( 3 ); winding_t w{
w->push_back( ds->verts[ ds->indexes[ i ] ].xyz ); ds->verts[ ds->indexes[ i ] ].xyz,
w->push_back( ds->verts[ ds->indexes[ i + 1 ] ].xyz ); ds->verts[ ds->indexes[ i + 1 ] ].xyz,
w->push_back( ds->verts[ ds->indexes[ i + 2 ] ].xyz ); ds->verts[ ds->indexes[ i + 2 ] ].xyz };
refs += FilterWindingIntoTree_r( w, ds, tree->headnode ); refs += FilterWindingIntoTree_r( w, ds, tree.headnode );
} }
/* use point filtering as well */ /* 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 ); refs += FilterPointIntoTree_r( ds->verts[ i ].xyz, ds, tree.headnode );
return refs; return refs;
} }
@ -2111,10 +2063,9 @@ static int FilterTrianglesIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
filters a foliage surface (wolf et/splash damage) filters a foliage surface (wolf et/splash damage)
*/ */
static int FilterFoliageIntoTree( mapDrawSurface_t *ds, tree_t *tree ){ static int FilterFoliageIntoTree( mapDrawSurface_t *ds, tree_t& tree ){
int f, i, refs; int f, i, refs;
bspDrawVert_t *instance; bspDrawVert_t *instance;
winding_t *w;
/* walk origin list */ /* walk origin list */
@ -2135,17 +2086,17 @@ static int FilterFoliageIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
} }
/* make a triangle winding and filter it into the tree */ /* make a triangle winding and filter it into the tree */
w = AllocWinding( 3 ); winding_t w{
w->push_back( instance->xyz + ds->verts[ ds->indexes[ i ] ].xyz ); instance->xyz + ds->verts[ ds->indexes[ i ] ].xyz,
w->push_back( instance->xyz + ds->verts[ ds->indexes[ i + 1 ] ].xyz ); instance->xyz + ds->verts[ ds->indexes[ i + 1 ] ].xyz,
w->push_back( instance->xyz + ds->verts[ ds->indexes[ i + 2 ] ].xyz ); instance->xyz + ds->verts[ ds->indexes[ i + 2 ] ].xyz };
refs += FilterWindingIntoTree_r( w, ds, tree->headnode ); refs += FilterWindingIntoTree_r( w, ds, tree.headnode );
} }
/* use point filtering as well */ /* use point filtering as well */
for ( i = 0; i < ( ds->numVerts - ds->numFoliageInstances ); i++ ) for ( i = 0; i < ( ds->numVerts - ds->numFoliageInstances ); i++ )
{ {
refs += FilterPointIntoTree_r( instance->xyz + ds->verts[ i ].xyz, ds, tree->headnode ); refs += FilterPointIntoTree_r( instance->xyz + ds->verts[ i ].xyz, ds, tree.headnode );
} }
} }
@ -2158,8 +2109,8 @@ static int FilterFoliageIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
FilterFlareIntoTree() FilterFlareIntoTree()
simple point filtering for flare surfaces simple point filtering for flare surfaces
*/ */
static int FilterFlareSurfIntoTree( mapDrawSurface_t *ds, tree_t *tree ){ static int FilterFlareSurfIntoTree( mapDrawSurface_t *ds, tree_t& tree ){
return FilterPointIntoTree_r( ds->lightmapOrigin, ds, tree->headnode ); return FilterPointIntoTree_r( ds->lightmapOrigin, ds, tree.headnode );
} }
@ -2741,10 +2692,9 @@ static void EmitFaceSurface( mapDrawSurface_t *ds ){
generates drawsurfaces for passable portals in the bsp generates drawsurfaces for passable portals in the bsp
*/ */
static void MakeDebugPortalSurfs_r( node_t *node, shaderInfo_t *si ){ static void MakeDebugPortalSurfs_r( const node_t *node, shaderInfo_t *si ){
int i, k, c, s; int i, k, c, s;
portal_t *p; const portal_t *p;
winding_t *w;
mapDrawSurface_t *ds; mapDrawSurface_t *ds;
bspDrawVert_t *dv; bspDrawVert_t *dv;
@ -2765,30 +2715,29 @@ static void MakeDebugPortalSurfs_r( node_t *node, shaderInfo_t *si ){
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 */ /* get winding and side even/odd */
w = p->winding; const winding_t& w = p->winding;
s = ( p->nodes[ 1 ] == node ); s = ( p->nodes[ 1 ] == node );
/* is this a valid portal for this leaf? */ /* is this a valid portal for this leaf? */
if ( w && p->nodes[ 0 ] == node ) { if ( !w.empty() && p->nodes[ 0 ] == node ) {
/* is this portal passable? */ /* is this portal passable? */
if ( !PortalPassable( p ) ) { if ( !PortalPassable( p ) ) {
continue; continue;
} }
/* check max points */ /* check max points */
if ( w->size() > 64 ) { if ( w.size() > 64 ) {
Error( "MakePortalSurfs_r: w->numpoints = %zu", w->size() ); Error( "MakePortalSurfs_r: w->numpoints = %zu", w.size() );
} }
/* allocate a drawsurface */ /* allocate a drawsurface */
ds = AllocDrawSurface( ESurfaceType::Face ); ds = AllocDrawSurface( ESurfaceType::Face );
ds->shaderInfo = si; ds->shaderInfo = si;
ds->planar = true; ds->planar = true;
ds->sideRef = AllocSideRef( p->side, NULL );
ds->planeNum = FindFloatPlane( p->plane.plane, 0, NULL ); ds->planeNum = FindFloatPlane( p->plane.plane, 0, NULL );
ds->lightmapVecs[ 2 ] = p->plane.normal(); ds->lightmapVecs[ 2 ] = p->plane.normal();
ds->fogNum = -1; ds->fogNum = -1;
ds->numVerts = w->size(); ds->numVerts = w.size();
ds->verts = safe_calloc( ds->numVerts * sizeof( *ds->verts ) ); ds->verts = safe_calloc( ds->numVerts * sizeof( *ds->verts ) );
/* walk the winding */ /* walk the winding */
@ -2798,7 +2747,7 @@ static void MakeDebugPortalSurfs_r( node_t *node, shaderInfo_t *si ){
dv = ds->verts + i; dv = ds->verts + i;
/* set it */ /* set it */
dv->xyz = ( *w )[ i ]; dv->xyz = w[ i ];
dv->normal = p->plane.normal(); dv->normal = p->plane.normal();
dv->st = { 0, 0 }; dv->st = { 0, 0 };
for ( k = 0; k < MAX_LIGHTMAPS; k++ ) for ( k = 0; k < MAX_LIGHTMAPS; k++ )
@ -2818,7 +2767,7 @@ static void MakeDebugPortalSurfs_r( node_t *node, shaderInfo_t *si ){
generates drawsurfaces for passable portals in the bsp generates drawsurfaces for passable portals in the bsp
*/ */
void MakeDebugPortalSurfs( tree_t *tree ){ void MakeDebugPortalSurfs( const tree_t& tree ){
shaderInfo_t *si; shaderInfo_t *si;
@ -2829,7 +2778,7 @@ void MakeDebugPortalSurfs( tree_t *tree ){
si = ShaderInfoForShader( "debugportals" ); si = ShaderInfoForShader( "debugportals" );
/* walk the tree */ /* walk the tree */
MakeDebugPortalSurfs_r( tree->headnode, si ); MakeDebugPortalSurfs_r( tree.headnode, si );
} }
@ -2839,7 +2788,7 @@ void MakeDebugPortalSurfs( tree_t *tree ){
generates drawsurfaces for a foghull (this MUST use a sky shader) generates drawsurfaces for a foghull (this MUST use a sky shader)
*/ */
void MakeFogHullSurfs( entity_t *e, tree_t *tree, const char *shader ){ void MakeFogHullSurfs( entity_t *e, const char *shader ){
shaderInfo_t *si; shaderInfo_t *si;
mapDrawSurface_t *ds; mapDrawSurface_t *ds;
int indexes[] = int indexes[] =
@ -3231,17 +3180,8 @@ void AddEntitySurfaceModels( entity_t *e ){
*/ */
static void VolumeColorMods( entity_t *e, mapDrawSurface_t *ds ){ static void VolumeColorMods( entity_t *e, mapDrawSurface_t *ds ){
int i, j;
brush_t *b;
/* early out */
if ( e->colorModBrushes == NULL ) {
return;
}
/* iterate brushes */ /* iterate brushes */
for ( b = e->colorModBrushes; b != NULL; b = b->nextColorModBrush ) for ( const brush_t *b : e->colorModBrushes )
{ {
/* worldspawn alpha brushes affect all, grouped ones only affect original entity */ /* 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 ) {
@ -3254,10 +3194,11 @@ static void VolumeColorMods( entity_t *e, mapDrawSurface_t *ds ){
} }
/* iterate verts */ /* iterate verts */
for ( i = 0; i < ds->numVerts; i++ ) for ( int i = 0; i < ds->numVerts; i++ )
{ {
/* iterate planes */ /* iterate planes */
for ( j = 0; j < b->numsides; j++ ) size_t j;
for ( j = 0; j < b->sides.size(); j++ )
{ {
/* point-plane test */ /* point-plane test */
if ( plane3_distance_to_point( mapplanes[ b->sides[ j ].planenum ].plane, ds->verts[ i ].xyz ) > 1.0f ) { if ( plane3_distance_to_point( mapplanes[ b->sides[ j ].planenum ].plane, ds->verts[ i ].xyz ) > 1.0f ) {
@ -3266,7 +3207,7 @@ static void VolumeColorMods( entity_t *e, mapDrawSurface_t *ds ){
} }
/* apply colormods */ /* apply colormods */
if ( j == b->numsides ) { if ( j == b->sides.size() ) {
ColorMod( b->contentShader->colorMod, 1, &ds->verts[ i ] ); ColorMod( b->contentShader->colorMod, 1, &ds->verts[ i ] );
} }
} }
@ -3282,7 +3223,7 @@ static void VolumeColorMods( entity_t *e, mapDrawSurface_t *ds ){
will have valid final indexes will have valid final indexes
*/ */
void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree ){ void FilterDrawsurfsIntoTree( entity_t *e, tree_t& tree ){
int i, j; int i, j;
mapDrawSurface_t *ds; mapDrawSurface_t *ds;
shaderInfo_t *si; shaderInfo_t *si;
@ -3311,7 +3252,7 @@ void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree ){
/* ydnar: skybox surfaces are special */ /* ydnar: skybox surfaces are special */
if ( ds->skybox ) { if ( ds->skybox ) {
refs = AddReferenceToTree_r( ds, tree->headnode, true ); refs = AddReferenceToTree_r( ds, tree.headnode, true );
ds->skybox = false; ds->skybox = false;
sb = true; sb = true;
} }
@ -3421,7 +3362,7 @@ void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree ){
/* handle foghull surfaces */ /* handle foghull surfaces */
case ESurfaceType::Foghull: case ESurfaceType::Foghull:
if ( refs == 0 ) { if ( refs == 0 ) {
refs = AddReferenceToTree_r( ds, tree->headnode, false ); refs = AddReferenceToTree_r( ds, tree.headnode, false );
} }
if ( refs > 0 ) { if ( refs > 0 ) {
EmitTriangleSurface( ds ); EmitTriangleSurface( ds );

View File

@ -91,15 +91,8 @@ void FreeTree_r( node_t *node ){
FreeTree_r( node->children[1] ); FreeTree_r( node->children[1] );
} }
// free bspbrushes
FreeBrushList( node->brushlist );
// free the node // free the node
if ( node->volume ) { delete node;
FreeBrush( node->volume );
}
free( node );
} }
@ -108,25 +101,24 @@ void FreeTree_r( node_t *node ){
FreeTree FreeTree
============= =============
*/ */
void FreeTree( tree_t *tree ){ void FreeTree( tree_t& tree ){
FreeTreePortals_r( tree->headnode ); FreeTreePortals_r( tree.headnode );
FreeTree_r( tree->headnode ); FreeTree_r( tree.headnode );
free( tree );
} }
//=============================================================== //===============================================================
void PrintTree_r( node_t *node, int depth ){ void PrintTree_r( const node_t *node, int depth ){
for ( int i = 0; i < depth; i++ ) for ( int i = 0; i < depth; i++ )
Sys_Printf( " " ); Sys_Printf( " " );
if ( node->planenum == PLANENUM_LEAF ) { if ( node->planenum == PLANENUM_LEAF ) {
if ( !node->brushlist ) { if ( node->brushlist.empty() ) {
Sys_Printf( "NULL\n" ); Sys_Printf( "NULL\n" );
} }
else else
{ {
for ( const brush_t *bb = node->brushlist; bb; bb = bb->next ) for ( const brush_t& bb : node->brushlist )
Sys_Printf( "%d ", bb->original->brushNum ); Sys_Printf( "%d ", bb.original->brushNum );
Sys_Printf( "\n" ); Sys_Printf( "\n" );
} }
return; return;

View File

@ -38,7 +38,7 @@
emits a bsp shader entry emits a bsp shader entry
*/ */
int EmitShader( const char *shader, int *contentFlags, int *surfaceFlags ){ int EmitShader( const char *shader, const int *contentFlags, const int *surfaceFlags ){
int i; int i;
shaderInfo_t *si; shaderInfo_t *si;
@ -132,7 +132,6 @@ void EmitPlanes( void ){
void EmitLeaf( node_t *node ){ void EmitLeaf( node_t *node ){
bspLeaf_t *leaf_p; bspLeaf_t *leaf_p;
brush_t *b;
drawSurfRef_t *dsr; drawSurfRef_t *dsr;
@ -153,18 +152,18 @@ void EmitLeaf( node_t *node ){
/* emit leaf brushes */ /* emit leaf brushes */
leaf_p->firstBSPLeafBrush = numBSPLeafBrushes; leaf_p->firstBSPLeafBrush = numBSPLeafBrushes;
for ( b = node->brushlist; b; b = b->next ) for ( const brush_t& b : node->brushlist )
{ {
/* something is corrupting brushes */ /* something is corrupting brushes */
if ( (size_t) b < 256 ) { // if ( (size_t) b < 256 ) {
Sys_Warning( "Node brush list corrupted (0x%08X)\n", b ); // Sys_Warning( "Node brush list corrupted (0x%08X)\n", b );
break; // break;
} // }
//% if( b->guard != 0xDEADBEEF ) //% if( b->guard != 0xDEADBEEF )
//% Sys_Printf( "Brush %6d: 0x%08X Guard: 0x%08X Next: 0x%08X Original: 0x%08X Sides: %d\n", b->brushNum, b, b, b->next, b->original, b->numsides ); //% Sys_Printf( "Brush %6d: 0x%08X Guard: 0x%08X Next: 0x%08X Original: 0x%08X Sides: %d\n", b->brushNum, b, b, b->next, b->original, b->numsides );
AUTOEXPAND_BY_REALLOC_BSP( LeafBrushes, 1024 ); AUTOEXPAND_BY_REALLOC_BSP( LeafBrushes, 1024 );
bspLeafBrushes[ numBSPLeafBrushes ] = b->original->outputNum; bspLeafBrushes[ numBSPLeafBrushes ] = b.original->outputNum;
numBSPLeafBrushes++; numBSPLeafBrushes++;
} }
@ -247,12 +246,10 @@ int EmitDrawNode_r( node_t *node ){
============ ============
*/ */
void SetModelNumbers( void ){ void SetModelNumbers( void ){
int models; int models = 1;
char value[16];
models = 1;
for ( std::size_t i = 1; i < entities.size(); ++i ) { for ( std::size_t i = 1; i < entities.size(); ++i ) {
if ( entities[i].brushes || entities[i].patches ) { if ( !entities[i].brushes.empty() || entities[i].patches ) {
char value[16];
sprintf( value, "*%i", models ); sprintf( value, "*%i", models );
models++; models++;
entities[i].setKeyValue( "model", value ); entities[i].setKeyValue( "model", value );
@ -404,9 +401,7 @@ void EndBSPFile( bool do_write ){
writes the brush list to the bsp writes the brush list to the bsp
*/ */
void EmitBrushes( brush_t *brushes, int *firstBrush, int *numBrushes ){ void EmitBrushes( brushlist_t& brushes, int *firstBrush, int *numBrushes ){
int j;
brush_t *b;
bspBrush_t *db; bspBrush_t *db;
bspBrushSide_t *cp; bspBrushSide_t *cp;
@ -420,45 +415,45 @@ void EmitBrushes( brush_t *brushes, int *firstBrush, int *numBrushes ){
} }
/* walk list of brushes */ /* walk list of brushes */
for ( b = brushes; b != NULL; b = b->next ) for ( brush_t& b : brushes )
{ {
/* check limits */ /* check limits */
AUTOEXPAND_BY_REALLOC_BSP( Brushes, 1024 ); AUTOEXPAND_BY_REALLOC_BSP( Brushes, 1024 );
/* get bsp brush */ /* get bsp brush */
b->outputNum = numBSPBrushes; b.outputNum = numBSPBrushes;
db = &bspBrushes[ numBSPBrushes ]; db = &bspBrushes[ numBSPBrushes ];
numBSPBrushes++; numBSPBrushes++;
if ( numBrushes != NULL ) { if ( numBrushes != NULL ) {
( *numBrushes )++; ( *numBrushes )++;
} }
db->shaderNum = EmitShader( b->contentShader->shader, &b->contentShader->contentFlags, &b->contentShader->surfaceFlags ); db->shaderNum = EmitShader( b.contentShader->shader, &b.contentShader->contentFlags, &b.contentShader->surfaceFlags );
db->firstSide = numBSPBrushSides; db->firstSide = numBSPBrushSides;
/* walk sides */ /* walk sides */
db->numSides = 0; db->numSides = 0;
for ( j = 0; j < b->numsides; j++ ) for ( side_t& side : b.sides )
{ {
/* set output number to bogus initially */ /* set output number to bogus initially */
b->sides[ j ].outputNum = -1; side.outputNum = -1;
/* check count */ /* check count */
AUTOEXPAND_BY_REALLOC_BSP( BrushSides, 1024 ); AUTOEXPAND_BY_REALLOC_BSP( BrushSides, 1024 );
/* emit side */ /* emit side */
b->sides[ j ].outputNum = numBSPBrushSides; side.outputNum = numBSPBrushSides;
cp = &bspBrushSides[ numBSPBrushSides ]; cp = &bspBrushSides[ numBSPBrushSides ];
db->numSides++; db->numSides++;
numBSPBrushSides++; numBSPBrushSides++;
cp->planeNum = b->sides[ j ].planenum; cp->planeNum = side.planenum;
/* emit shader */ /* emit shader */
if ( b->sides[ j ].shaderInfo ) { if ( side.shaderInfo ) {
cp->shaderNum = EmitShader( b->sides[ j ].shaderInfo->shader, &b->sides[ j ].shaderInfo->contentFlags, &b->sides[ j ].shaderInfo->surfaceFlags ); cp->shaderNum = EmitShader( side.shaderInfo->shader, &side.shaderInfo->contentFlags, &side.shaderInfo->surfaceFlags );
} }
else if( b->sides[ j ].bevel ) { /* emit surfaceFlags for bevels to get correct physics at walkable brush edges and vertices */ else if( side.bevel ) { /* emit surfaceFlags for bevels to get correct physics at walkable brush edges and vertices */
cp->shaderNum = EmitShader( NULL, NULL, &b->sides[ j ].surfaceFlags ); cp->shaderNum = EmitShader( NULL, NULL, &side.surfaceFlags );
} }
else{ else{
cp->shaderNum = EmitShader( NULL, NULL, NULL ); cp->shaderNum = EmitShader( NULL, NULL, NULL );
@ -507,7 +502,7 @@ void EmitFogs( void ){
/* find visible side */ /* find visible side */
for ( j = 0; j < 6; j++ ) for ( j = 0; j < 6; j++ )
{ {
if ( mapFogs[ i ].brush->sides[ j ].visibleHull != NULL ) { if ( !mapFogs[ i ].brush->sides[ j ].visibleHull.empty() ) {
Sys_Printf( "Fog %d has visible side %d\n", i, j ); Sys_Printf( "Fog %d has visible side %d\n", i, j );
bspFogs[ i ].visibleSide = j; bspFogs[ i ].visibleSide = j;
break; break;
@ -536,17 +531,17 @@ void BeginModel( void ){
const entity_t& e = entities[ mapEntityNum ]; const entity_t& e = entities[ mapEntityNum ];
/* bound the brushes */ /* bound the brushes */
for ( const brush_t *b = e.brushes; b; b = b->next ) for ( const brush_t& b : e.brushes )
{ {
/* ignore non-real brushes (origin, etc) */ /* ignore non-real brushes (origin, etc) */
if ( b->numsides == 0 ) { if ( b.sides.empty() ) {
continue; continue;
} }
minmax.extend( b->minmax ); minmax.extend( b.minmax );
/* ydnar: lightgrid bounds */ /* ydnar: lightgrid bounds */
if ( b->compileFlags & C_LIGHTGRID ) { if ( b.compileFlags & C_LIGHTGRID ) {
lgMinmax.extend( b->minmax ); lgMinmax.extend( b.minmax );
} }
} }