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 ) {
return 0;
}
for ( auto i = brush.sides.cbegin(); i != brush.sides.cend(); ++i ){
// grab the first valid point as the corner // grab the first valid point as the corner
if( !i->winding.empty() ){
w = NULL; const Vector3 corner = i->winding[0];
for ( i = 0 ; i < brush->numsides ; i++ ) // make tetrahedrons to all other faces
for ( ++i; i != brush.sides.cend(); ++i )
{ {
w = brush->sides[i].winding; if ( !i->winding.empty() ) {
if ( w ) { volume += -plane3_distance_to_point( mapplanes[i->planenum].plane, corner ) * WindingArea( i->winding );
}
}
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,16 +606,14 @@ 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->plane, p ); const double d = plane3_distance_to_point( plane, p );
if ( d > max ) { if ( d > max ) {
max = d; max = d;
side = PSIDE_FRONT; side = PSIDE_FRONT;
@ -796,7 +624,6 @@ int BrushMostlyOnSide( brush_t *brush, plane_t *plane ){
} }
} }
} }
}
return side; return side;
} }
@ -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 */
for ( j = 0 ; j < 2 ; j++ )
{ {
if ( !cw[j] ) { if ( !cw[i].empty() ) {
continue; side_t& cs = b[i]->sides.emplace_back( side );
cs.winding.swap( cw[i] );
}
} }
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];
for ( i = 0 ; i < 2 ; i++ )
{
v1 = BrushVolume( b[i] );
if ( v1 < 1.0 ) {
FreeBrush( b[i] );
b[i] = NULL; b[i] = NULL;
// Sys_FPrintf( SYS_WRN | SYS_VRBflag, "tiny volume after clip\n" ); // 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 );

View File

@ -457,25 +457,20 @@ int MapPlaneFromPoints( DoubleVector3 p[3] ){
the content flags and compile flags on all sides of a brush should be the same the content flags and compile flags on all sides of a brush should be the same
*/ */
void SetBrushContents( brush_t *b ){ void SetBrushContents( brush_t& b ){
int contentFlags, compileFlags; if( b.sides.empty() )
side_t *s; return;
int i;
//% bool mixed;
//% bool mixed = false;
/* get initial compile flags from first side */ /* get initial compile flags from first side */
s = &b->sides[ 0 ]; auto s = b.sides.cbegin();
contentFlags = s->contentFlags; int contentFlags = s->contentFlags;
compileFlags = s->compileFlags; int compileFlags = s->compileFlags;
b->contentShader = s->shaderInfo; b.contentShader = s->shaderInfo;
//% mixed = false;
/* get the content/compile flags for every side in the brush */ /* get the content/compile flags for every side in the brush */
//for ( i = 1; i < b->numsides; i++, s++ ) for ( ++s; s != b.sides.cend(); ++s )
for ( i = 1; i < b->numsides; i++ )
{ {
s = &b->sides[ i ];
if ( s->shaderInfo == NULL ) { if ( s->shaderInfo == NULL ) {
continue; continue;
} }
@ -486,36 +481,36 @@ void SetBrushContents( brush_t *b ){
compileFlags |= s->compileFlags; compileFlags |= s->compileFlags;
/* resolve inconsistency, when brush content was determined by 1st face */ /* resolve inconsistency, when brush content was determined by 1st face */
if ( b->contentShader->compileFlags & C_LIQUID ){ if ( b.contentShader->compileFlags & C_LIQUID ){
continue; continue;
} }
else if ( s->compileFlags & C_LIQUID ){ else if ( s->compileFlags & C_LIQUID ){
b->contentShader = s->shaderInfo; b.contentShader = s->shaderInfo;
} }
else if ( b->contentShader->compileFlags & C_FOG ){ else if ( b.contentShader->compileFlags & C_FOG ){
continue; continue;
} }
else if ( s->compileFlags & C_FOG ){ else if ( s->compileFlags & C_FOG ){
b->contentShader = s->shaderInfo; b.contentShader = s->shaderInfo;
} }
//playerclip //playerclip
else if ( b->contentShader->contentFlags & 0x10000 ){ else if ( b.contentShader->contentFlags & 0x10000 ){
continue; continue;
} }
else if ( s->contentFlags & 0x10000 ){ else if ( s->contentFlags & 0x10000 ){
b->contentShader = s->shaderInfo; b.contentShader = s->shaderInfo;
} }
else if (!( b->contentShader->compileFlags & C_SOLID )){ else if (!( b.contentShader->compileFlags & C_SOLID )){
continue; continue;
} }
else if (!( s->compileFlags & C_SOLID )){ else if (!( s->compileFlags & C_SOLID )){
b->contentShader = s->shaderInfo; b.contentShader = s->shaderInfo;
} }
} }
/* ydnar: getting rid of this stupid warning */ /* ydnar: getting rid of this stupid warning */
//% if( mixed ) //% if( mixed )
//% Sys_FPrintf( SYS_WRN | SYS_VRBflag, "Entity %i, Brush %i: mixed face contentFlags\n", b->entitynum, b->brushnum ); //% Sys_FPrintf( SYS_WRN | SYS_VRBflag, "Entity %i, Brush %i: mixed face contentFlags\n", b.entitynum, b.brushnum );
/* check for detail & structural */ /* check for detail & structural */
if ( ( compileFlags & C_DETAIL ) && ( compileFlags & C_STRUCTURAL ) ) { if ( ( compileFlags & C_DETAIL ) && ( compileFlags & C_STRUCTURAL ) ) {
@ -536,20 +531,20 @@ void SetBrushContents( brush_t *b ){
/* detail? */ /* detail? */
if ( compileFlags & C_DETAIL ) { if ( compileFlags & C_DETAIL ) {
c_detail++; c_detail++;
b->detail = true; b.detail = true;
} }
else else
{ {
c_structural++; c_structural++;
b->detail = false; b.detail = false;
} }
/* opaque? */ /* opaque? */
if ( compileFlags & C_TRANSLUCENT ) { if ( compileFlags & C_TRANSLUCENT ) {
b->opaque = false; b.opaque = false;
} }
else{ else{
b->opaque = true; b.opaque = true;
} }
/* areaportal? */ /* areaportal? */
@ -558,8 +553,8 @@ void SetBrushContents( brush_t *b ){
} }
/* set brush flags */ /* set brush flags */
b->contentFlags = contentFlags; b.contentFlags = contentFlags;
b->compileFlags = compileFlags; b.compileFlags = compileFlags;
} }
@ -572,102 +567,89 @@ void SetBrushContents( brush_t *b ){
*/ */
void AddBrushBevels( void ){ void AddBrushBevels( void ){
int axis, dir; const int surfaceFlagsMask = game->brushBevelsSurfaceFlagsMask;
int i, k, order; auto& sides = buildBrush.sides;
side_t sidetemp;
side_t *s, *s2;
const winding_t *w, *w2;
Plane3f plane;
Vector3 vec, vec2;
float d, minBack;
int surfaceFlagsMask = game->brushBevelsSurfaceFlagsMask;
// //
// add the axial planes // add the axial planes
// //
order = 0; size_t order = 0;
for ( axis = 0; axis < 3; axis++ ) { for ( size_t axis = 0; axis < 3; axis++ ) {
for ( dir = -1; dir <= 1; dir += 2, order++ ) { for ( int dir = -1; dir <= 1; dir += 2, order++ ) {
// see if the plane is already present // see if the plane is already present
for ( i = 0, s = buildBrush->sides; i < buildBrush->numsides; i++, s++ ) size_t i = 0;
for ( ; i < sides.size(); ++i )
{ {
/* ydnar: testing disabling of mre code */ /* ydnar: testing disabling of mre code */
#if 0 #if 0
if ( dir > 0 ) { if ( dir > 0 ) {
if ( mapplanes[s->planenum].normal()[axis] >= 0.9999f ) { if ( mapplanes[sides[i].planenum].normal()[axis] >= 0.9999f ) {
break; break;
} }
} }
else { else {
if ( mapplanes[s->planenum].normal()[axis] <= -0.9999f ) { if ( mapplanes[sides[i].planenum].normal()[axis] <= -0.9999f ) {
break; break;
} }
} }
#else #else
if ( ( dir > 0 && mapplanes[ s->planenum ].normal()[ axis ] == 1.0f ) || if ( ( dir > 0 && mapplanes[ sides[i].planenum ].normal()[ axis ] == 1.0f ) ||
( dir < 0 && mapplanes[ s->planenum ].normal()[ axis ] == -1.0f ) ) { ( dir < 0 && mapplanes[ sides[i].planenum ].normal()[ axis ] == -1.0f ) ) {
break; break;
} }
#endif #endif
} }
if ( i == buildBrush->numsides ) { if ( i == sides.size() ) {
// add a new side // add a new side
if ( buildBrush->numsides == MAX_BUILD_SIDES ) { if ( sides.size() == MAX_BUILD_SIDES ) {
xml_Select( "MAX_BUILD_SIDES", buildBrush->entityNum, buildBrush->brushNum, true ); xml_Select( "MAX_BUILD_SIDES", buildBrush.entityNum, buildBrush.brushNum, true );
} }
memset( s, 0, sizeof( *s ) ); side_t& s = sides.emplace_back();
buildBrush->numsides++; Plane3f plane;
plane.normal().set( 0 ); plane.normal().set( 0 );
plane.normal()[axis] = dir; plane.normal()[axis] = dir;
if ( dir == 1 ) { if ( dir == 1 ) {
/* ydnar: adding bevel plane snapping for fewer bsp planes */ /* ydnar: adding bevel plane snapping for fewer bsp planes */
if ( bevelSnap > 0 ) { if ( bevelSnap > 0 ) {
plane.dist() = floor( buildBrush->minmax.maxs[ axis ] / bevelSnap ) * bevelSnap; plane.dist() = floor( buildBrush.minmax.maxs[ axis ] / bevelSnap ) * bevelSnap;
} }
else{ else{
plane.dist() = buildBrush->minmax.maxs[ axis ]; plane.dist() = buildBrush.minmax.maxs[ axis ];
} }
} }
else else
{ {
/* ydnar: adding bevel plane snapping for fewer bsp planes */ /* ydnar: adding bevel plane snapping for fewer bsp planes */
if ( bevelSnap > 0 ) { if ( bevelSnap > 0 ) {
plane.dist() = -ceil( buildBrush->minmax.mins[ axis ] / bevelSnap ) * bevelSnap; plane.dist() = -ceil( buildBrush.minmax.mins[ axis ] / bevelSnap ) * bevelSnap;
} }
else{ else{
plane.dist() = -buildBrush->minmax.mins[ axis ]; plane.dist() = -buildBrush.minmax.mins[ axis ];
} }
} }
s->planenum = FindFloatPlane( plane, 0, NULL ); s.planenum = FindFloatPlane( plane, 0, NULL );
s->contentFlags = buildBrush->sides[ 0 ].contentFlags; s.contentFlags = sides[ 0 ].contentFlags;
/* handle bevel surfaceflags for topmost one only: assuming that only walkable ones are meaningful */ /* handle bevel surfaceflags for topmost one only: assuming that only walkable ones are meaningful */
if( axis == 2 && dir == 1 ){ if( axis == 2 && dir == 1 ){
for ( int j = 0; j < buildBrush->numsides; j++ ) { for ( const side_t& side : sides ) {
s2 = buildBrush->sides + j; for ( const Vector3& point : side.winding ) {
w = s2->winding; if ( fabs( plane.dist() - point[axis] ) < .1f ) {
if ( !w ) { s.surfaceFlags |= ( side.surfaceFlags & surfaceFlagsMask );
continue;
}
for ( const Vector3& po : *w ) {
if ( fabs( plane.dist() - po[axis] ) < .1f ) {
s->surfaceFlags |= ( s2->surfaceFlags & surfaceFlagsMask );
break; break;
} }
} }
} }
} }
s->bevel = true; s.bevel = true;
c_boxbevels++; c_boxbevels++;
} }
// if the plane is not in it canonical order, swap it // if the plane is not in it canonical order, swap it
if ( i != order ) { if ( i != order ) {
sidetemp = buildBrush->sides[order]; std::swap( sides[order], sides[i] );
buildBrush->sides[order] = buildBrush->sides[i];
buildBrush->sides[i] = sidetemp;
} }
} }
} }
@ -675,76 +657,70 @@ void AddBrushBevels( void ){
// //
// add the edge bevels // add the edge bevels
// //
if ( buildBrush->numsides == 6 ) { if ( sides.size() == 6 ) {
return; // pure axial return; // pure axial
} }
// test the non-axial plane edges // test the non-axial plane edges
for ( i = 6; i < buildBrush->numsides; i++ ) { for ( size_t i = 6; i < sides.size(); ++i ) {
s = buildBrush->sides + i; for ( size_t j = 0; j < sides[i].winding.size(); j++ ) {
w = s->winding; Vector3 vec = sides[i].winding[j] - sides[i].winding[( ( j + 1 ) == sides[i].winding.size() )? 0 : ( j + 1 )];
if ( !w ) {
continue;
}
for ( size_t j = 0; j < w->size(); j++ ) {
k = ( j + 1 ) % w->size();
vec = ( *w )[j] - ( *w )[k];
if ( VectorNormalize( vec ) < 0.5f ) { if ( VectorNormalize( vec ) < 0.5f ) {
continue; continue;
} }
SnapNormal( vec ); SnapNormal( vec );
for ( k = 0; k < 3; k++ ) { if ( vec[0] == -1.0f || vec[0] == 1.0f || ( vec[0] == 0.0f && vec[1] == 0.0f )
if ( vec[k] == -1.0f || vec[k] == 1.0f || ( vec[k] == 0.0f && vec[( k + 1 ) % 3] == 0.0f ) ) { || vec[1] == -1.0f || vec[1] == 1.0f || ( vec[1] == 0.0f && vec[2] == 0.0f )
break; // axial || vec[2] == -1.0f || vec[2] == 1.0f || ( vec[2] == 0.0f && vec[0] == 0.0f ) ) {
} continue; // axial, only test non-axial edges
}
if ( k != 3 ) {
continue; // only test non-axial edges
} }
/* debug code */ /* debug code */
//% Sys_Printf( "-------------\n" ); //% Sys_Printf( "-------------\n" );
// try the six possible slanted axials from this edge // try the six possible slanted axials from this edge
for ( axis = 0; axis < 3; axis++ ) { for ( int axis = 0; axis < 3; axis++ ) {
for ( dir = -1; dir <= 1; dir += 2 ) { for ( int dir = -1; dir <= 1; dir += 2 ) {
// construct a plane // construct a plane
vec2.set( 0 ); Vector3 vec2( 0 );
vec2[axis] = dir; vec2[axis] = dir;
Plane3f plane;
plane.normal() = vector3_cross( vec, vec2 ); plane.normal() = vector3_cross( vec, vec2 );
if ( VectorNormalize( plane.normal() ) < 0.5f ) { if ( VectorNormalize( plane.normal() ) < 0.5f ) {
continue; continue;
} }
plane.dist() = vector3_dot( ( *w )[j], plane.normal() ); plane.dist() = vector3_dot( sides[i].winding[j], plane.normal() );
// if all the points on all the sides are // if all the points on all the sides are
// behind this plane, it is a proper edge bevel // behind this plane, it is a proper edge bevel
for ( k = 0; k < buildBrush->numsides; k++ ) { auto iside = sides.begin();
for ( ; iside != sides.end(); ++iside ) {
// if this plane has already been used, skip it // if this plane has already been used, skip it
if ( PlaneEqual( mapplanes[buildBrush->sides[k].planenum], plane ) ) { if ( PlaneEqual( mapplanes[iside->planenum], plane ) ) {
if( buildBrush->sides[k].bevel ){ /* handle bevel surfaceflags */ if( iside->bevel ){ /* handle bevel surfaceflags */
buildBrush->sides[k].surfaceFlags |= ( s->surfaceFlags & surfaceFlagsMask ); iside->surfaceFlags |= ( sides[i].surfaceFlags & surfaceFlagsMask );
} }
break; break;
} }
w2 = buildBrush->sides[k].winding; const winding_t& w2 = iside->winding;
if ( !w2 ) { if ( w2.empty() ) {
continue; continue;
} }
minBack = 0.0f; float minBack = 0.0f;
bool point_in_front = false; const auto point_in_front = [&w2, &plane, &minBack](){
for ( const Vector3& point : *w2 ) { for ( const Vector3& point : w2 ) {
d = plane3_distance_to_point( plane, point ); const float d = plane3_distance_to_point( plane, point );
if ( d > 0.1f ) { if ( d > 0.1f ) {
point_in_front = true; return true;
break; // point in front
} }
value_minimize( minBack, d ); value_minimize( minBack, d );
} }
return false;
};
// if some point was at the front // if some point was at the front
if ( point_in_front ) { if ( point_in_front() ) {
break; break;
} }
@ -755,7 +731,7 @@ void AddBrushBevels( void ){
} }
} }
if ( k != buildBrush->numsides ) { if ( iside != sides.end() ) {
continue; // wasn't part of the outer hull continue; // wasn't part of the outer hull
} }
@ -763,17 +739,15 @@ void AddBrushBevels( void ){
//% Sys_Printf( "n = %f %f %f\n", normal[ 0 ], normal[ 1 ], normal[ 2 ] ); //% Sys_Printf( "n = %f %f %f\n", normal[ 0 ], normal[ 1 ], normal[ 2 ] );
// add this plane // add this plane
if ( buildBrush->numsides == MAX_BUILD_SIDES ) { if ( sides.size() == MAX_BUILD_SIDES ) {
xml_Select( "MAX_BUILD_SIDES", buildBrush->entityNum, buildBrush->brushNum, true ); xml_Select( "MAX_BUILD_SIDES", buildBrush.entityNum, buildBrush.brushNum, true );
} }
s2 = &buildBrush->sides[buildBrush->numsides]; side_t& s2 = sides.emplace_back();
buildBrush->numsides++;
memset( s2, 0, sizeof( *s2 ) );
s2->planenum = FindFloatPlane( plane, 1, &( *w )[ j ] ); s2.planenum = FindFloatPlane( plane, 1, &sides[i].winding[ j ] );
s2->contentFlags = buildBrush->sides[0].contentFlags; s2.contentFlags = sides[0].contentFlags;
s2->surfaceFlags = ( s->surfaceFlags & surfaceFlagsMask ); /* handle bevel surfaceflags */ s2.surfaceFlags = ( sides[i].surfaceFlags & surfaceFlagsMask ); /* handle bevel surfaceflags */
s2->bevel = true; s2.bevel = true;
c_edgebevels++; c_edgebevels++;
} }
} }
@ -783,12 +757,6 @@ void AddBrushBevels( void ){
/*
FinishBrush()
produces a final brush based on the buildBrush->sides array
and links it to the current entity
*/
static void MergeOrigin( entity_t& ent, const Vector3& origin ){ static void MergeOrigin( entity_t& ent, const Vector3& origin ){
char string[128]; char string[128];
@ -801,38 +769,41 @@ static void MergeOrigin( entity_t& ent, const Vector3& origin ){
ent.setKeyValue( "origin", string ); ent.setKeyValue( "origin", string );
} }
brush_t *FinishBrush( bool noCollapseGroups ){ /*
brush_t *b; FinishBrush()
produces a final brush based on the buildBrush->sides array
and links it to the current entity
*/
static void FinishBrush( bool noCollapseGroups ){
/* create windings for sides and bounds for brush */ /* create windings for sides and bounds for brush */
if ( !CreateBrushWindings( buildBrush ) ) { if ( !CreateBrushWindings( buildBrush ) ) {
return NULL; return;
} }
/* origin brushes are removed, but they set the rotation origin for the rest of the brushes in the entity. /* origin brushes are removed, but they set the rotation origin for the rest of the brushes in the entity.
after the entire entity is parsed, the planenums and texinfos will be adjusted for the origin brush */ after the entire entity is parsed, the planenums and texinfos will be adjusted for the origin brush */
if ( buildBrush->compileFlags & C_ORIGIN ) { if ( buildBrush.compileFlags & C_ORIGIN ) {
Sys_Printf( "Entity %i (%s), Brush %i: origin brush detected\n", Sys_Printf( "Entity %i (%s), Brush %i: origin brush detected\n",
mapEnt->mapEntityNum, mapEnt->classname(), entitySourceBrushes ); mapEnt->mapEntityNum, mapEnt->classname(), entitySourceBrushes );
if ( entities.size() == 1 ) { if ( entities.size() == 1 ) {
Sys_FPrintf( SYS_WRN, "Entity %i, Brush %i: origin brushes not allowed in world\n", Sys_FPrintf( SYS_WRN, "Entity %i, Brush %i: origin brushes not allowed in world\n",
mapEnt->mapEntityNum, entitySourceBrushes ); mapEnt->mapEntityNum, entitySourceBrushes );
return NULL; return;
} }
MergeOrigin( entities.back(), buildBrush->minmax.origin() ); MergeOrigin( entities.back(), buildBrush.minmax.origin() );
/* don't keep this brush */ /* don't keep this brush */
return NULL; return;
} }
/* determine if the brush is an area portal */ /* determine if the brush is an area portal */
if ( buildBrush->compileFlags & C_AREAPORTAL ) { if ( buildBrush.compileFlags & C_AREAPORTAL ) {
if ( entities.size() != 1 ) { if ( entities.size() != 1 ) {
Sys_FPrintf( SYS_WRN, "Entity %zu (%s), Brush %i: areaportals only allowed in world\n", entities.size() - 1, mapEnt->classname(), entitySourceBrushes ); Sys_FPrintf( SYS_WRN, "Entity %zu (%s), Brush %i: areaportals only allowed in world\n", entities.size() - 1, mapEnt->classname(), entitySourceBrushes );
return NULL; return;
} }
} }
@ -842,47 +813,30 @@ brush_t *FinishBrush( bool noCollapseGroups ){
} }
/* keep it */ /* keep it */
b = CopyBrush( buildBrush ); /* link opaque brushes to head of list, translucent brushes to end */
brush_t& b = ( buildBrush.opaque )? mapEnt->brushes.emplace_front( buildBrush )
: mapEnt->brushes.emplace_back( buildBrush );
/* set map entity and brush numbering */ /* set map entity and brush numbering */
b->entityNum = mapEnt->mapEntityNum; b.entityNum = mapEnt->mapEntityNum;
b->brushNum = entitySourceBrushes; b.brushNum = entitySourceBrushes;
/* set original */ /* set original */
b->original = b; b.original = &b;
/* link opaque brushes to head of list, translucent brushes to end */
if ( b->opaque || mapEnt->lastBrush == NULL ) {
b->next = mapEnt->brushes;
mapEnt->brushes = b;
if ( mapEnt->lastBrush == NULL ) {
mapEnt->lastBrush = b;
}
}
else
{
b->next = NULL;
mapEnt->lastBrush->next = b;
mapEnt->lastBrush = b;
}
/* link colorMod volume brushes to the entity directly */ /* link colorMod volume brushes to the entity directly */
if ( b->contentShader != NULL && if ( b.contentShader != NULL &&
b->contentShader->colorMod != NULL && b.contentShader->colorMod != NULL &&
b->contentShader->colorMod->type == EColorMod::Volume ) { b.contentShader->colorMod->type == EColorMod::Volume ) {
b->nextColorModBrush = mapEnt->colorModBrushes; mapEnt->colorModBrushes.push_back( &b );
mapEnt->colorModBrushes = b;
} }
/* return to sender */
return b;
} }
/* /*
TextureAxisFromPlane() TextureAxisFromPlane()
determines best orthagonal axis to project a texture onto a wall determines best orthogonal axis to project a texture onto a wall
(must be identical in radiant!) (must be identical in radiant!)
*/ */
@ -1003,19 +957,9 @@ void QuakeTextureVecs( const plane_t& plane, float shift[ 2 ], float rotate, flo
*/ */
static void ParseRawBrush( bool onlyLights ){ static void ParseRawBrush( bool onlyLights ){
side_t *side;
DoubleVector3 planePoints[ 3 ];
int planenum;
shaderInfo_t *si;
float shift[ 2 ];
float rotate = 0;
float scale[ 2 ];
int flags;
/* initial setup */ /* initial setup */
buildBrush->numsides = 0; buildBrush.sides.clear();
buildBrush->detail = false; buildBrush.detail = false;
/* bp */ /* bp */
if ( g_brushType == EBrushType::Bp ) { if ( g_brushType == EBrushType::Bp ) {
@ -1048,29 +992,41 @@ static void ParseRawBrush( bool onlyLights ){
UnGetToken(); UnGetToken();
/* test side count */ /* test side count */
if ( buildBrush->numsides >= MAX_BUILD_SIDES ) { if ( buildBrush.sides.size() >= MAX_BUILD_SIDES ) {
xml_Select( "MAX_BUILD_SIDES", buildBrush->entityNum, buildBrush->brushNum, true ); xml_Select( "MAX_BUILD_SIDES", buildBrush.entityNum, buildBrush.brushNum, true );
} }
/* add side */ /* add side */
side = &buildBrush->sides[ buildBrush->numsides ]; side_t& side = buildBrush.sides.emplace_back();
memset( side, 0, sizeof( *side ) );
buildBrush->numsides++;
/* read the three point plane definition */ /* read the three point plane definition */
DoubleVector3 planePoints[ 3 ];
Parse1DMatrix( 3, planePoints[ 0 ].data() ); Parse1DMatrix( 3, planePoints[ 0 ].data() );
Parse1DMatrix( 3, planePoints[ 1 ].data() ); Parse1DMatrix( 3, planePoints[ 1 ].data() );
Parse1DMatrix( 3, planePoints[ 2 ].data() ); Parse1DMatrix( 3, planePoints[ 2 ].data() );
/* find the plane number */
side.planenum = MapPlaneFromPoints( planePoints );
PlaneFromPoints( side.plane, planePoints );
/* bp: read the texture matrix */ /* bp: read the texture matrix */
if ( g_brushType == EBrushType::Bp ) { if ( g_brushType == EBrushType::Bp ) {
Parse2DMatrix( 2, 3, side->texMat->data() ); Parse2DMatrix( 2, 3, side.texMat->data() );
} }
/* read shader name */ /* read shader name */
GetToken( false ); GetToken( false );
const auto shader = String64()( "textures/", token ); const auto shader = String64()( "textures/", token );
/* set default flags and values */
shaderInfo_t *si = onlyLights? &shaderInfo[ 0 ]
: ShaderInfoForShader( shader );
side.shaderInfo = si;
side.surfaceFlags = si->surfaceFlags;
side.contentFlags = si->contentFlags;
side.compileFlags = si->compileFlags;
side.value = si->value;
/* AP or 220? */ /* AP or 220? */
if ( g_brushType == EBrushType::Undefined ){ if ( g_brushType == EBrushType::Undefined ){
GetToken( false ); GetToken( false );
@ -1086,6 +1042,8 @@ static void ParseRawBrush( bool onlyLights ){
} }
if ( g_brushType == EBrushType::Quake ) { if ( g_brushType == EBrushType::Quake ) {
float shift[ 2 ], rotate, scale[ 2 ];
GetToken( false ); GetToken( false );
shift[ 0 ] = atof( token ); shift[ 0 ] = atof( token );
GetToken( false ); GetToken( false );
@ -1096,19 +1054,27 @@ static void ParseRawBrush( bool onlyLights ){
scale[ 0 ] = atof( token ); scale[ 0 ] = atof( token );
GetToken( false ); GetToken( false );
scale[ 1 ] = atof( token ); scale[ 1 ] = atof( token );
/* ydnar: gs mods: bias texture shift */
if ( !si->globalTexture ) {
shift[ 0 ] -= ( floor( shift[ 0 ] / si->shaderWidth ) * si->shaderWidth );
shift[ 1 ] -= ( floor( shift[ 1 ] / si->shaderHeight ) * si->shaderHeight );
}
/* get the texture mapping for this texturedef / plane combination */
QuakeTextureVecs( mapplanes[ side.planenum ], shift, rotate, scale, side.vecs );
} }
else if ( g_brushType == EBrushType::Valve220 ){ else if ( g_brushType == EBrushType::Valve220 ){
int axis, comp; for ( int axis = 0; axis < 2; ++axis ){
for ( axis = 0; axis < 2; ++axis ){
MatchToken( "[" ); MatchToken( "[" );
for ( comp = 0; comp < 4; ++comp ){ for ( int comp = 0; comp < 4; ++comp ){
GetToken( false ); GetToken( false );
side->vecs[axis][comp] = atof( token ); side.vecs[axis][comp] = atof( token );
} }
MatchToken( "]" ); MatchToken( "]" );
} }
GetToken( false ); GetToken( false ); // rotate
rotate = atof( token ); float scale[2];
GetToken( false ); GetToken( false );
scale[ 0 ] = atof( token ); scale[ 0 ] = atof( token );
GetToken( false ); GetToken( false );
@ -1116,27 +1082,8 @@ static void ParseRawBrush( bool onlyLights ){
if ( !scale[0] ) scale[0] = 1.f; if ( !scale[0] ) scale[0] = 1.f;
if ( !scale[1] ) scale[1] = 1.f; if ( !scale[1] ) scale[1] = 1.f;
for ( axis = 0; axis < 2; ++axis ) for ( int axis = 0; axis < 2; ++axis )
side->vecs[axis].vec3() /= scale[axis]; side.vecs[axis].vec3() /= scale[axis];
}
/* set default flags and values */
if ( onlyLights ) {
si = &shaderInfo[ 0 ];
}
else{
si = ShaderInfoForShader( shader );
}
side->shaderInfo = si;
side->surfaceFlags = si->surfaceFlags;
side->contentFlags = si->contentFlags;
side->compileFlags = si->compileFlags;
side->value = si->value;
/* ydnar: gs mods: bias texture shift */
if ( !si->globalTexture ) {
shift[ 0 ] -= ( floor( shift[ 0 ] / si->shaderWidth ) * si->shaderWidth );
shift[ 1 ] -= ( floor( shift[ 1 ] / si->shaderHeight ) * si->shaderHeight );
} }
/* /*
@ -1153,9 +1100,9 @@ static void ParseRawBrush( bool onlyLights ){
if ( TokenAvailable() ) { if ( TokenAvailable() ) {
/* get detail bit from map content flags */ /* get detail bit from map content flags */
GetToken( false ); GetToken( false );
flags = atoi( token ); const int flags = atoi( token );
if ( flags & C_DETAIL ) { if ( flags & C_DETAIL ) {
side->compileFlags |= C_DETAIL; side.compileFlags |= C_DETAIL;
} }
/* historical */ /* historical */
@ -1164,16 +1111,6 @@ static void ParseRawBrush( bool onlyLights ){
GetToken( false ); GetToken( false );
//% td.value = atoi( token ); //% td.value = atoi( token );
} }
/* find the plane number */
planenum = MapPlaneFromPoints( planePoints );
side->planenum = planenum;
PlaneFromPoints( side->plane, planePoints );
/* bp: get the texture mapping for this texturedef / plane combination */
if ( g_brushType == EBrushType::Quake ) {
QuakeTextureVecs( mapplanes[ planenum ], shift, rotate, scale, side->vecs );
}
} }
/* bp */ /* bp */
@ -1193,44 +1130,37 @@ static void ParseRawBrush( bool onlyLights ){
also removes planes without any normal also removes planes without any normal
*/ */
bool RemoveDuplicateBrushPlanes( brush_t *b ){ bool RemoveDuplicateBrushPlanes( brush_t& b ){
int i, j, k; auto& sides = b.sides;
side_t *sides;
sides = b->sides;
for ( i = 1 ; i < b->numsides ; i++ ) {
for( auto it = sides.cbegin(); it != sides.cend(); ){
// check for a degenerate plane // check for a degenerate plane
if ( sides[i].planenum == -1 ) { if ( it->planenum == -1 ) {
xml_Select( "degenerate plane", b->entityNum, b->brushNum, false ); xml_Select( "degenerate plane", b.entityNum, b.brushNum, false );
// remove it // remove it
for ( k = i + 1 ; k < b->numsides ; k++ ) { it = sides.erase( it );
sides[k - 1] = sides[k]; }
else{
++it;
} }
b->numsides--;
i--;
continue;
} }
for ( size_t i = 0; i < sides.size(); ++i ) {
// check for duplication and mirroring // check for duplication and mirroring
for ( j = 0 ; j < i ; j++ ) { for ( size_t j = i + 1; j < sides.size(); ) {
if ( sides[i].planenum == sides[j].planenum ) { if ( sides[i].planenum == sides[j].planenum ) {
xml_Select( "duplicate plane", b->entityNum, b->brushNum, false ); xml_Select( "duplicate plane", b.entityNum, b.brushNum, false );
// remove the second duplicate // remove the second duplicate
for ( k = i + 1 ; k < b->numsides ; k++ ) { sides.erase( sides.cbegin() + j );
sides[k - 1] = sides[k];
} }
b->numsides--; else if ( sides[i].planenum == ( sides[j].planenum ^ 1 ) ) {
i--;
break;
}
if ( sides[i].planenum == ( sides[j].planenum ^ 1 ) ) {
// mirror plane, brush is invalid // mirror plane, brush is invalid
xml_Select( "mirrored plane", b->entityNum, b->brushNum, false ); xml_Select( "mirrored plane", b.entityNum, b.brushNum, false );
return false; return false;
} }
else{
++j;
}
} }
} }
return true; return true;
@ -1253,10 +1183,10 @@ static void ParseBrush( bool onlyLights, bool noCollapseGroups ){
} }
/* set some defaults */ /* set some defaults */
buildBrush->portalareas[ 0 ] = -1; buildBrush.portalareas[ 0 ] = -1;
buildBrush->portalareas[ 1 ] = -1; buildBrush.portalareas[ 1 ] = -1;
buildBrush->entityNum = numMapEntities - 1; buildBrush.entityNum = numMapEntities - 1;
buildBrush->brushNum = entitySourceBrushes; buildBrush.brushNum = entitySourceBrushes;
/* if there are mirrored planes, the entire brush is invalid */ /* if there are mirrored planes, the entire brush is invalid */
if ( !RemoveDuplicateBrushPlanes( buildBrush ) ) { if ( !RemoveDuplicateBrushPlanes( buildBrush ) ) {
@ -1267,20 +1197,17 @@ static void ParseBrush( bool onlyLights, bool noCollapseGroups ){
SetBrushContents( buildBrush ); SetBrushContents( buildBrush );
/* allow detail brushes to be removed */ /* allow detail brushes to be removed */
if ( nodetail && ( buildBrush->compileFlags & C_DETAIL ) ) { if ( nodetail && ( buildBrush.compileFlags & C_DETAIL ) ) {
//% FreeBrush( buildBrush );
return; return;
} }
/* allow liquid brushes to be removed */ /* allow liquid brushes to be removed */
if ( nowater && ( buildBrush->compileFlags & C_LIQUID ) ) { if ( nowater && ( buildBrush.compileFlags & C_LIQUID ) ) {
//% FreeBrush( buildBrush );
return; return;
} }
/* ydnar: allow hint brushes to be removed */ /* ydnar: allow hint brushes to be removed */
if ( noHint && ( buildBrush->compileFlags & C_HINT ) ) { if ( noHint && ( buildBrush.compileFlags & C_HINT ) ) {
//% FreeBrush( buildBrush );
return; return;
} }
@ -1299,49 +1226,36 @@ static void ParseBrush( bool onlyLights, bool noCollapseGroups ){
void AdjustBrushesForOrigin( entity_t *ent ); void AdjustBrushesForOrigin( entity_t *ent );
void MoveBrushesToWorld( entity_t *ent ){ void MoveBrushesToWorld( entity_t *ent ){
brush_t *b, *next;
parseMesh_t *pm;
/* we need to undo the common/origin adjustment, and instead shift them by the entity key origin */ /* we need to undo the common/origin adjustment, and instead shift them by the entity key origin */
ent->originbrush_origin = -ent->origin; ent->originbrush_origin = -ent->origin;
AdjustBrushesForOrigin( ent ); AdjustBrushesForOrigin( ent );
ent->originbrush_origin.set( 0 ); ent->originbrush_origin.set( 0 );
/* move brushes */ /* move brushes */
for ( b = ent->brushes; b != NULL; b = next ) for ( brushlist_t::const_iterator next, b = ent->brushes.begin(); b != ent->brushes.end(); b = next )
{ {
/* get next brush */ /* get next brush */
next = b->next; next = std::next( b );
/* link opaque brushes to head of list, translucent brushes to end */ /* link opaque brushes to head of list, translucent brushes to end */
if ( b->opaque || entities[ 0 ].lastBrush == NULL ) { if ( b->opaque ) {
b->next = entities[ 0 ].brushes; entities[ 0 ].brushes.splice( entities[ 0 ].brushes.begin(), ent->brushes, b );
entities[ 0 ].brushes = b;
if ( entities[ 0 ].lastBrush == NULL ) {
entities[ 0 ].lastBrush = b;
}
} }
else else
{ {
b->next = NULL; entities[ 0 ].brushes.splice( entities[ 0 ].brushes.end(), ent->brushes, b );
entities[ 0 ].lastBrush->next = b;
entities[ 0 ].lastBrush = b;
} }
} }
ent->brushes = NULL;
/* ydnar: move colormod brushes */ /* ydnar: move colormod brushes */
if ( ent->colorModBrushes != NULL ) { if ( !ent->colorModBrushes.empty() ) {
for ( b = ent->colorModBrushes; b->nextColorModBrush != NULL; b = b->nextColorModBrush ) ; entities[ 0 ].colorModBrushes.insert( entities[ 0 ].colorModBrushes.end(), ent->colorModBrushes.begin(), ent->colorModBrushes.end() );
ent->colorModBrushes.clear();
b->nextColorModBrush = entities[ 0 ].colorModBrushes;
entities[ 0 ].colorModBrushes = ent->colorModBrushes;
ent->colorModBrushes = NULL;
} }
/* move patches */ /* move patches */
if ( ent->patches != NULL ) { if ( ent->patches != NULL ) {
parseMesh_t *pm;
for ( pm = ent->patches; pm->next != NULL; pm = pm->next ) ; for ( pm = ent->patches; pm->next != NULL; pm = pm->next ) ;
pm->next = entities[ 0 ].patches; pm->next = entities[ 0 ].patches;
@ -1358,28 +1272,18 @@ void MoveBrushesToWorld( entity_t *ent ){
*/ */
void AdjustBrushesForOrigin( entity_t *ent ){ void AdjustBrushesForOrigin( entity_t *ent ){
int i;
side_t *s;
float newdist;
brush_t *b;
parseMesh_t *p;
/* walk brush list */ /* walk brush list */
for ( b = ent->brushes; b != NULL; b = b->next ) for ( brush_t& b : ent->brushes )
{ {
/* offset brush planes */ /* offset brush planes */
for ( i = 0; i < b->numsides; i++ ) for ( side_t& side : b.sides )
{ {
/* get brush side */
s = &b->sides[ i ];
/* offset side plane */ /* offset side plane */
newdist = -plane3_distance_to_point( mapplanes[ s->planenum ].plane, ent->originbrush_origin ); const float newdist = -plane3_distance_to_point( mapplanes[ side.planenum ].plane, ent->originbrush_origin );
/* find a new plane */ /* find a new plane */
s->planenum = FindFloatPlane( mapplanes[ s->planenum ].normal(), newdist, 0, NULL ); side.planenum = FindFloatPlane( mapplanes[ side.planenum ].normal(), newdist, 0, NULL );
s->plane.dist() = -plane3_distance_to_point( s->plane, ent->originbrush_origin ); side.plane.dist() = -plane3_distance_to_point( side.plane, ent->originbrush_origin );
} }
/* rebuild brush windings (ydnar: just offsetting the winding above should be fine) */ /* rebuild brush windings (ydnar: just offsetting the winding above should be fine) */
@ -1387,9 +1291,9 @@ void AdjustBrushesForOrigin( entity_t *ent ){
} }
/* walk patch list */ /* walk patch list */
for ( p = ent->patches; p != NULL; p = p->next ) for ( parseMesh_t *p = ent->patches; p != NULL; p = p->next )
{ {
for ( i = 0; i < ( p->mesh.width * p->mesh.height ); i++ ) for ( int i = 0; i < ( p->mesh.width * p->mesh.height ); i++ )
p->mesh.verts[ i ].xyz -= ent->originbrush_origin; p->mesh.verts[ i ].xyz -= ent->originbrush_origin;
} }
} }
@ -1402,20 +1306,16 @@ void AdjustBrushesForOrigin( entity_t *ent ){
*/ */
void SetEntityBounds( entity_t *e ){ void SetEntityBounds( entity_t *e ){
int i;
brush_t *b;
parseMesh_t *p;
MinMax minmax; MinMax minmax;
/* walk the entity's brushes/patches and determine bounds */ /* walk the entity's brushes/patches and determine bounds */
for ( b = e->brushes; b; b = b->next ) for ( const brush_t& b : e->brushes )
{ {
minmax.extend( b->minmax ); minmax.extend( b.minmax );
} }
for ( p = e->patches; p; p = p->next ) for ( parseMesh_t *p = e->patches; p; p = p->next )
{ {
for ( i = 0; i < ( p->mesh.width * p->mesh.height ); i++ ) for ( int i = 0; i < ( p->mesh.width * p->mesh.height ); i++ )
minmax.extend( p->mesh.verts[ i ].xyz ); minmax.extend( p->mesh.verts[ i ].xyz );
} }
@ -1424,11 +1324,11 @@ void SetEntityBounds( entity_t *e ){
e->read_keyvalue( minmax.maxs, "max" ); e->read_keyvalue( minmax.maxs, "max" );
/* store the bounds */ /* store the bounds */
for ( b = e->brushes; b; b = b->next ) for ( brush_t& b : e->brushes )
{ {
b->eMinmax = minmax; b.eMinmax = minmax;
} }
for ( p = e->patches; p; p = p->next ) for ( parseMesh_t *p = e->patches; p; p = p->next )
{ {
p->eMinmax = minmax; p->eMinmax = minmax;
} }
@ -1447,12 +1347,10 @@ void LoadEntityIndexMap( entity_t *e ){
byte *pixels; byte *pixels;
unsigned int *pixels32; unsigned int *pixels32;
indexMap_t *im; indexMap_t *im;
brush_t *b;
parseMesh_t *p;
/* this only works with bmodel ents */ /* this only works with bmodel ents */
if ( e->brushes == NULL && e->patches == NULL ) { if ( e->brushes.empty() && e->patches == NULL ) {
return; return;
} }
@ -1566,9 +1464,9 @@ void LoadEntityIndexMap( entity_t *e ){
} }
/* store the index map in every brush/patch in the entity */ /* store the index map in every brush/patch in the entity */
for ( b = e->brushes; b != NULL; b = b->next ) for ( brush_t& b : e->brushes )
b->im = im; b.im = im;
for ( p = e->patches; p != NULL; p = p->next ) for ( parseMesh_t *p = e->patches; p != NULL; p = p->next )
p->im = im; p->im = im;
} }
@ -1584,9 +1482,6 @@ void LoadEntityIndexMap( entity_t *e ){
*/ */
static bool ParseMapEntity( bool onlyLights, bool noCollapseGroups ){ static bool ParseMapEntity( bool onlyLights, bool noCollapseGroups ){
brush_t *brush;
parseMesh_t *patch;
/* eof check */ /* eof check */
if ( !GetToken( true ) ) { if ( !GetToken( true ) ) {
return false; return false;
@ -1716,18 +1611,18 @@ static bool ParseMapEntity( bool onlyLights, bool noCollapseGroups ){
Sys_Printf( "Entity %d (%s) has lightmap sample size of %d\n", mapEnt->mapEntityNum, classname, lightmapSampleSize ); Sys_Printf( "Entity %d (%s) has lightmap sample size of %d\n", mapEnt->mapEntityNum, classname, lightmapSampleSize );
/* attach stuff to everything in the entity */ /* attach stuff to everything in the entity */
for ( brush = mapEnt->brushes; brush != NULL; brush = brush->next ) for ( brush_t& brush : mapEnt->brushes )
{ {
brush->entityNum = mapEnt->mapEntityNum; brush.entityNum = mapEnt->mapEntityNum;
brush->castShadows = castShadows; brush.castShadows = castShadows;
brush->recvShadows = recvShadows; brush.recvShadows = recvShadows;
brush->lightmapSampleSize = lightmapSampleSize; brush.lightmapSampleSize = lightmapSampleSize;
brush->lightmapScale = lightmapScale; brush.lightmapScale = lightmapScale;
brush->celShader = celShader; brush.celShader = celShader;
brush->shadeAngleDegrees = shadeAngle; brush.shadeAngleDegrees = shadeAngle;
} }
for ( patch = mapEnt->patches; patch != NULL; patch = patch->next ) for ( parseMesh_t *patch = mapEnt->patches; patch != NULL; patch = patch->next )
{ {
patch->entityNum = mapEnt->mapEntityNum; patch->entityNum = mapEnt->mapEntityNum;
patch->castShadows = castShadows; patch->castShadows = castShadows;
@ -1775,8 +1670,7 @@ static bool ParseMapEntity( bool onlyLights, bool noCollapseGroups ){
void LoadMapFile( char *filename, bool onlyLights, bool noCollapseGroups ){ void LoadMapFile( char *filename, bool onlyLights, bool noCollapseGroups ){
FILE *file; FILE *file;
brush_t *b; int oldNumEntities = 0;
int oldNumEntities = 0, numMapBrushes;
/* note it */ /* note it */
@ -1804,7 +1698,7 @@ void LoadMapFile( char *filename, bool onlyLights, bool noCollapseGroups ){
g_brushType = EBrushType::Undefined; g_brushType = EBrushType::Undefined;
/* allocate a very large temporary brush for building the brushes as they are loaded */ /* allocate a very large temporary brush for building the brushes as they are loaded */
buildBrush = AllocBrush( MAX_BUILD_SIDES ); buildBrush.sides.reserve( MAX_BUILD_SIDES );
/* parse the map file */ /* parse the map file */
while ( ParseMapEntity( onlyLights, noCollapseGroups ) ) ; while ( ParseMapEntity( onlyLights, noCollapseGroups ) ) ;
@ -1818,13 +1712,13 @@ void LoadMapFile( char *filename, bool onlyLights, bool noCollapseGroups ){
{ {
/* set map bounds */ /* set map bounds */
g_mapMinmax.clear(); g_mapMinmax.clear();
for ( b = entities[ 0 ].brushes; b; b = b->next ) for ( const brush_t& brush : entities[ 0 ].brushes )
{ {
g_mapMinmax.extend( b->minmax ); g_mapMinmax.extend( brush.minmax );
} }
/* get brush counts */ /* get brush counts */
numMapBrushes = CountBrushList( entities[ 0 ].brushes ); const int numMapBrushes = entities[ 0 ].brushes.size();
if ( (float) c_detail / (float) numMapBrushes < 0.10f && numMapBrushes > 500 ) { if ( (float) c_detail / (float) numMapBrushes < 0.10f && numMapBrushes > 500 ) {
Sys_Warning( "Over 90 percent structural map detected. Compile time may be adversely affected.\n" ); Sys_Warning( "Over 90 percent structural map detected. Compile time may be adversely affected.\n" );
} }

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] );
} }
FreeWinding( w ); else{
ClipSideIntoTree_r( front, side, node->children[0] ); ClipSideIntoTree_r( front, side, node->children[0] );
ClipSideIntoTree_r( back, side, node->children[1] ); 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 */ /* duplicate the up-facing side */
w = ReverseWinding( *w ); side_t& newSide = *new side_t( side );
newSide = safe_malloc( sizeof( *side ) ); newSide.visibleHull = ReverseWinding( w );
*newSide = *side; newSide.planenum ^= 1;
newSide->visibleHull = w;
newSide->planenum ^= 1;
/* save this winding as a visible surface */ /* save this winding as a visible surface */
DrawSurfaceForSide( e, b, newSide, *w ); DrawSurfaceForSide( e, b, newSide, newSide.visibleHull ); // references new side by sideref, leak!
}
} }
} }
} }
@ -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 );
} }
} }