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
=============
*/
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 ){
winding_t AllocWinding( int points ){
if ( points >= MAX_POINTS_ON_WINDING ) {
Error( "AllocWinding failed: MAX_POINTS_ON_WINDING exceeded" );
}
@ -58,18 +49,6 @@ winding_t AllocWinding_( int points ){
return w;
}
/*
=============
FreeWinding
=============
*/
void FreeWinding( winding_t *w ){
if ( !w ) {
Error( "FreeWinding: winding is NULL" );
}
delete w;
}
/*
============
RemoveColinearPoints
@ -255,7 +234,7 @@ winding_accu_t BaseWindingForPlaneAccu( const Plane3& plane ){
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;
float max, v;
Vector3 org, vright, vup;
@ -302,7 +281,7 @@ winding_t *BaseWindingForPlane( const Plane3f& plane ){
vright *= MAX_WORLD_COORD * 2;
// 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,
@ -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
==================
*/
winding_t *CopyWindingAccuToRegular( const winding_accu_t& w ){
return new winding_t( w.begin(), w.end() );
winding_t CopyWindingAccuToRegular( const winding_accu_t& w ){
return winding_t( w.begin(), w.end() );
}
/*
@ -336,8 +303,8 @@ winding_t *CopyWindingAccuToRegular( const winding_accu_t& w ){
ReverseWinding
==================
*/
winding_t *ReverseWinding( const winding_t& w ){
return new winding_t( w.crbegin(), w.crend() );
winding_t ReverseWinding( const winding_t& w ){
return winding_t( w.crbegin(), w.crend() );
}
@ -346,8 +313,7 @@ winding_t *ReverseWinding( const winding_t& w ){
ClipWindingEpsilon
=============
*/
void ClipWindingEpsilonStrict( const winding_t& in, const Plane3f& plane,
float epsilon, winding_t *&front, winding_t *&back ){
std::pair<winding_t, winding_t> ClipWindingEpsilonStrict( const winding_t& in, const Plane3f& plane, float epsilon ){
float dists[MAX_POINTS_ON_WINDING + 4];
EPlaneSide sides[MAX_POINTS_ON_WINDING + 4];
int counts[3] = { 0 };
@ -373,41 +339,37 @@ void ClipWindingEpsilonStrict( const winding_t& in, const Plane3f& plane,
sides[i] = sides[0];
dists[i] = dists[0];
front = back = NULL;
if ( !counts[eSideFront] && !counts[eSideBack] ) {
return;
return {};
}
if ( !counts[eSideFront] ) {
back = CopyWinding( &in );
return;
return { {}, in };
}
if ( !counts[eSideBack] ) {
front = CopyWinding( &in );
return;
return { in, {} };
}
const size_t maxpts = in.size() + 4; // cant use counts[0]+2 because
// of fp grouping errors
front = AllocWinding( maxpts );
back = AllocWinding( maxpts );
winding_t front = 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];
if ( sides[i] == eSideOn ) {
front->push_back( p1 );
back->push_back( p1 );
front.push_back( p1 );
back.push_back( p1 );
continue;
}
if ( sides[i] == eSideFront ) {
front->push_back( p1 );
front.push_back( p1 );
}
if ( sides[i] == eSideBack ) {
back->push_back( p1 );
back.push_back( p1 );
}
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 );
back->push_back( mid );
front.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" );
}
return { front, back };
}
void ClipWindingEpsilon( const winding_t& in, const Plane3f& plane,
float epsilon, winding_t *&front, winding_t *&back ){
ClipWindingEpsilonStrict( in, plane, epsilon, front, back );
std::pair<winding_t, winding_t> ClipWindingEpsilon( const winding_t& in, const Plane3f& plane, float epsilon ){
auto [front, back] = ClipWindingEpsilonStrict( in, plane, epsilon );
/* apparently most code expects that in the winding-on-plane case, the back winding is the original winding */
if ( !front && !back ) {
back = CopyWinding( &in );
if ( front.empty() && back.empty() ) {
back = in;
}
return { front, back };
}
@ -587,8 +551,8 @@ void ChopWindingInPlaceAccu( winding_accu_t& inout, const Plane3& plane, float c
ChopWindingInPlace
=============
*/
void ChopWindingInPlace( winding_t *&inout, const Plane3f& plane, float epsilon ){
winding_t& in = *inout;
void ChopWindingInPlace( winding_t& inout, const Plane3f& plane, float epsilon ){
const winding_t& in = inout;
float dists[MAX_POINTS_ON_WINDING + 4];
EPlaneSide sides[MAX_POINTS_ON_WINDING + 4];
int counts[3] = { 0 };
@ -614,8 +578,7 @@ void ChopWindingInPlace( winding_t *&inout, const Plane3f& plane, float epsilon
dists[i] = dists[0];
if ( !counts[eSideFront] ) {
FreeWinding( inout );
inout = NULL;
inout.clear();
return;
}
if ( !counts[eSideBack] ) {
@ -668,27 +631,7 @@ void ChopWindingInPlace( winding_t *&inout, const Plane3f& plane, float epsilon
Error( "ClipWinding: MAX_POINTS_ON_WINDING" );
}
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;
inout.swap( f );
}
@ -794,7 +737,7 @@ EPlaneSide WindingOnPlaneSide( const winding_t& w, const Plane3f& plane ){
=================
*/
#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 numHullPoints, numNew;
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 outside;
if ( hull == nullptr ) {
hull = CopyWinding( &w );
if ( hull.empty() ) {
hull = w;
return;
}
numHullPoints = hull->size();
memcpy( hullPoints, hull->data(), numHullPoints * sizeof( Vector3 ) );
numHullPoints = hull.size();
memcpy( hullPoints, hull.data(), numHullPoints * sizeof( Vector3 ) );
for ( const Vector3 &p : w ) {
// 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 ) );
}
*hull = winding_t( hullPoints, hullPoints + numHullPoints );
hull = winding_t( hullPoints, hullPoints + numHullPoints );
}

View File

@ -40,28 +40,22 @@ enum EPlaneSide
eSideCross = 3,
};
winding_t *AllocWinding( int points );
winding_t AllocWinding_( int points );
winding_t AllocWinding( int points );
float WindingArea( const winding_t& w );
Vector3 WindingCenter( const winding_t& w );
void ClipWindingEpsilon( const winding_t& in, const Plane3f& plane,
float epsilon, winding_t *&front, winding_t *&back );
void ClipWindingEpsilonStrict( const winding_t& in, const Plane3f& plane,
float epsilon, winding_t *&front, winding_t *&back );
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 );
std::pair<winding_t, winding_t> ClipWindingEpsilon( const winding_t& in, const Plane3f& plane, float epsilon ); // returns { front, back } windings pair
std::pair<winding_t, winding_t> ClipWindingEpsilonStrict( const winding_t& in, const Plane3f& plane, float epsilon ); // returns { front, back } windings pair
winding_t ReverseWinding( const winding_t& w );
winding_t BaseWindingForPlane( const Plane3f& plane );
void CheckWinding( const winding_t& w );
Plane3f WindingPlane( const winding_t& w );
void RemoveColinearPoints( winding_t& w );
EPlaneSide WindingOnPlaneSide( const winding_t& w, const Plane3f& plane );
void FreeWinding( winding_t *w );
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
void pw( const winding_t& w );
@ -76,4 +70,4 @@ using winding_accu_t = std::vector<DoubleVector3>;
winding_accu_t BaseWindingForPlaneAccu( const Plane3& plane );
void ChopWindingInPlaceAccu( winding_accu_t& w, const Plane3& plane, float epsilon );
winding_t *CopyWindingAccuToRegular( const winding_accu_t& w );
winding_t CopyWindingAccuToRegular( const winding_accu_t& w );

View File

@ -44,17 +44,14 @@
allocates and assigns a brush side reference
*/
sideRef_t *AllocSideRef( side_t *side, sideRef_t *next ){
sideRef_t *sideRef;
sideRef_t *AllocSideRef( const side_t *side, sideRef_t *next ){
/* dummy check */
if ( side == NULL ) {
return next;
}
/* allocate and return */
sideRef = safe_malloc( sizeof( *sideRef ) );
sideRef_t *sideRef = safe_malloc( sizeof( *sideRef ) );
sideRef->side = side;
sideRef->next = next;
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
*/
bool BoundBrush( brush_t *brush ){
brush->minmax.clear();
for ( int i = 0; i < brush->numsides; i++ )
bool BoundBrush( brush_t& brush ){
brush.minmax.clear();
for ( const side_t& side : brush.sides )
{
const winding_t *w = brush->sides[ i ].winding;
if ( w != NULL ) {
WindingExtendBounds( *w, brush->minmax );
}
WindingExtendBounds( side.winding, 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
bool FixWinding( winding_t *w ){
bool FixWinding( winding_t& w ){
bool valid = true;
/* dummy check */
if ( !w ) {
if ( w.empty() ) {
return false;
}
/* 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 */
if ( w->size() == 3 ) {
if ( w.size() == 3 ) {
return valid;
}
@ -312,17 +203,20 @@ bool FixWinding( winding_t *w ){
//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) */
*i = SnapWeldVector( *i, *j );
//VectorAdd( w->p[ i ], w->p[ j ], vec );
//VectorScale( vec, 0.5, w->p[ i ] );
*j = SnapWeldVector( *i, *j );
//VectorAdd( w[ i ], w[ j ], vec );
//VectorScale( vec, 0.5, w[ i ] );
/* move the remaining verts */
w->erase( j );
i = w.erase( i );
}
else{
++i;
}
}
/* one last check and return */
if ( w->size() < 3 ) {
if ( w.size() < 3 ) {
valid = false;
}
return valid;
@ -387,25 +281,25 @@ bool FixWindingAccu( winding_accu_t& w ){
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 */
for ( int i = 0; i < brush->numsides; i++ )
for ( size_t i = 0; i < brush.sides.size(); ++i )
{
/* get side and plane */
side_t& side = brush->sides[ i ];
side_t& side = brush.sides[ i ];
const plane_t& plane = mapplanes[ side.planenum ];
/* make huge winding */
#if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
winding_accu_t w = BaseWindingForPlaneAccu( ( side.plane.normal() != g_vector3_identity )? side.plane : Plane3( plane.plane ) );
#else
winding_t *w = BaseWindingForPlane( plane.plane );
winding_t w = BaseWindingForPlane( plane.plane );
#endif
/* walk the list of brush sides */
for ( int j = 0; j < brush->numsides && !w.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 ];
if ( i == j
|| cside.planenum == ( side.planenum ^ 1 ) /* back side clipaway */
@ -432,9 +326,12 @@ bool CreateBrushWindings( brush_t *brush ){
/* set side winding */
#if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
FixWindingAccu( w );
side.winding = ( w.size() >= 3 ? CopyWindingAccuToRegular( w ) : NULL );
if( w.size() >= 3 )
side.winding = CopyWindingAccuToRegular( w );
else
side.winding.clear();
#else
side.winding = w;
side.winding.swap( w );
#endif
}
@ -452,20 +349,16 @@ bool CreateBrushWindings( brush_t *brush ){
Creates a new axial brush
==================
*/
brush_t *BrushFromBounds( const Vector3& mins, const Vector3& maxs ){
brush_t *b;
int i;
float dist;
b = AllocBrush( 6 );
b->numsides = 6;
for ( i = 0 ; i < 3 ; i++ )
brush_t BrushFromBounds( const Vector3& mins, const Vector3& maxs ){
brush_t b;
b.sides.resize( 6 );
for ( int i = 0 ; i < 3 ; i++ )
{
dist = maxs[i];
b->sides[i].planenum = FindFloatPlane( g_vector3_axes[i], dist, 1, &maxs );
float dist = maxs[i];
b.sides[i].planenum = FindFloatPlane( g_vector3_axes[i], dist, 1, &maxs );
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 );
@ -479,45 +372,25 @@ brush_t *BrushFromBounds( const Vector3& mins, const Vector3& maxs ){
==================
*/
float BrushVolume( brush_t *brush ){
int i;
const winding_t *w;
Vector3 corner;
float volume;
if ( !brush ) {
return 0;
}
float BrushVolume( const brush_t& brush ){
float volume = 0;
for ( auto i = brush.sides.cbegin(); i != brush.sides.cend(); ++i ){
// grab the first valid point as the corner
w = NULL;
for ( i = 0 ; i < brush->numsides ; i++ )
if( !i->winding.empty() ){
const Vector3 corner = i->winding[0];
// make tetrahedrons to all other faces
for ( ++i; i != brush.sides.cend(); ++i )
{
w = brush->sides[i].winding;
if ( w ) {
if ( !i->winding.empty() ) {
volume += -plane3_distance_to_point( mapplanes[i->planenum].plane, corner ) * WindingArea( i->winding );
}
}
break;
}
}
if ( !w ) {
return 0;
}
corner = ( *w )[0];
// make tetrahedrons to all other faces
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;
return volume / 3;
}
@ -527,10 +400,7 @@ float BrushVolume( brush_t *brush ){
writes a map with the split bsp brushes
*/
void WriteBSPBrushMap( const char *name, brush_t *list ){
side_t *s;
int i;
void WriteBSPBrushMap( const char *name, const brushlist_t& list ){
/* note it */
Sys_Printf( "Writing %s\n", name );
@ -539,22 +409,20 @@ void WriteBSPBrushMap( const char *name, brush_t *list ){
fprintf( f, "{\n\"classname\" \"worldspawn\"\n" );
for ( ; list; list = list->next )
for ( const brush_t& brush : list )
{
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.
// Is WriteBSPBrushMap() used only to decompile maps?
winding_t *w = BaseWindingForPlane( mapplanes[s->planenum].plane );
const winding_t& wr = *w;
const winding_t w = BaseWindingForPlane( mapplanes[side.planenum].plane );
fprintf( f, "( %i %i %i ) ", (int)wr[0][0], (int)wr[0][1], (int)wr[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)wr[2][0], (int)wr[2][1], (int)wr[2][2] );
fprintf( f, "( %i %i %i ) ", (int)w[0][0], (int)w[0][1], (int)w[0][2] );
fprintf( f, "( %i %i %i ) ", (int)w[1][0], (int)w[1][1], (int)w[1][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" );
FreeWinding( w );
}
fprintf( f, "}\n" );
}
@ -571,11 +439,7 @@ void WriteBSPBrushMap( const char *name, brush_t *list ){
adds brush reference to any intersecting bsp leafnode
*/
int FilterBrushIntoTree_r( brush_t *b, node_t *node ){
brush_t *front, *back;
int c;
int FilterBrushIntoTree_r( brush_t* b, node_t *node ){
/* dummy check */
if ( b == NULL ) {
return 0;
@ -584,8 +448,7 @@ int FilterBrushIntoTree_r( brush_t *b, node_t *node ){
/* add it to the leaf list */
if ( node->planenum == PLANENUM_LEAF ) {
/* something somewhere is hammering brushlist */
b->next = node->brushlist;
node->brushlist = b;
node->brushlist.push_front( std::move( *b ) );
/* classify the leaf by the structural brush */
if ( !b->detail ) {
@ -604,11 +467,10 @@ int FilterBrushIntoTree_r( brush_t *b, node_t *node ){
}
/* split it by the node plane */
c = b->numsides;
SplitBrush( b, node->planenum, &front, &back );
FreeBrush( b );
auto [front, back] = SplitBrush( *b, node->planenum );
delete b;
c = 0;
int c = 0;
c += FilterBrushIntoTree_r( front, node->children[ 0 ] );
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
*/
void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree ){
brush_t *b, *newb;
int r;
int c_unique, c_clusters;
int i;
void FilterDetailBrushesIntoTree( entity_t *e, tree_t& tree ){
int c_unique = 0, c_clusters = 0;
/* note it */
@ -635,22 +494,21 @@ void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree ){
/* walk the list of brushes */
c_unique = 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;
}
c_unique++;
newb = CopyBrush( b );
r = FilterBrushIntoTree_r( newb, tree->headnode );
const int r = FilterBrushIntoTree_r( new brush_t( b ), tree.headnode );
c_clusters += r;
/* mark all sides as visible so drawsurfs are created */
if ( r ) {
for ( i = 0; i < b->numsides; i++ )
for ( side_t& side : b.sides )
{
if ( b->sides[ i ].winding ) {
b->sides[ i ].visible = true;
if ( !side.winding.empty() ) {
side.visible = true;
}
}
}
@ -668,30 +526,24 @@ void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree ){
Mark the leafs as opaque and areaportals
=====================
*/
void FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree ) {
brush_t *b, *newb;
int r;
int c_unique, c_clusters;
int i;
void FilterStructuralBrushesIntoTree( entity_t *e, tree_t& tree ) {
int c_unique = 0, c_clusters = 0;
Sys_FPrintf( SYS_VRB, "--- FilterStructuralBrushesIntoTree ---\n" );
c_unique = 0;
c_clusters = 0;
for ( b = e->brushes ; b ; b = b->next ) {
if ( b->detail ) {
for ( brush_t& b : e->brushes ) {
if ( b.detail ) {
continue;
}
c_unique++;
newb = CopyBrush( b );
r = FilterBrushIntoTree_r( newb, tree->headnode );
const int r = FilterBrushIntoTree_r( new brush_t( b ), tree.headnode );
c_clusters += r;
// mark all sides as visible so drawsurfs are created
if ( r ) {
for ( i = 0 ; i < b->numsides ; i++ ) {
if ( b->sides[i].winding ) {
b->sides[i].visible = true;
for ( side_t& side : b.sides ) {
if ( !side.winding.empty() ) {
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
@ -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;
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;
if ( w ) {
for ( const Vector3& p : *w )
for ( const Vector3& p : s.winding )
{
const double d = plane3_distance_to_point( plane->plane, p );
const double d = plane3_distance_to_point( plane, p );
if ( d > max ) {
max = d;
side = PSIDE_FRONT;
@ -796,7 +624,6 @@ int BrushMostlyOnSide( brush_t *brush, plane_t *plane ){
}
}
}
}
return side;
}
@ -807,30 +634,16 @@ int BrushMostlyOnSide( brush_t *brush, plane_t *plane ){
generates two new brushes, leaving the original unchanged
*/
void SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back ){
brush_t *b[2];
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];
std::pair<brush_t*, brush_t*> SplitBrush( const brush_t& brush, int planenum ){
const Plane3f& plane = mapplanes[planenum].plane;
// check all points
d_front = d_back = 0;
for ( i = 0 ; i < brush->numsides ; i++ )
float d_front = 0, d_back = 0;
for ( const side_t& side : brush.sides )
{
w = brush->sides[i].winding;
if ( !w ) {
continue;
}
for ( const Vector3& p : *w )
for ( const Vector3& p : side.winding )
{
const float d = plane3_distance_to_point( plane->plane, p );
const float d = plane3_distance_to_point( plane, p );
if ( d > 0 ) {
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)
// only on back
*back = CopyBrush( brush );
return;
return { {}, new brush_t( brush ) };
}
if ( d_back > -0.1 ) { // PLANESIDE_EPSILON)
// only on front
*front = CopyBrush( brush );
return;
return { new brush_t( brush ), {} };
}
// create a new winding from the split plane
w = BaseWindingForPlane( plane->plane );
for ( i = 0 ; i < brush->numsides && w ; i++ )
winding_t midwinding = BaseWindingForPlane( plane );
for ( const side_t& side : brush.sides )
{
plane2 = &mapplanes[brush->sides[i].planenum ^ 1];
ChopWindingInPlace( w, plane2->plane, 0 ); // PLANESIDE_EPSILON);
ChopWindingInPlace( midwinding, mapplanes[side.planenum ^ 1].plane, 0 ); // PLANESIDE_EPSILON);
if( midwinding.empty() )
break;
}
if ( !w || WindingIsTiny( *w ) ) { // the brush isn't really split
int side;
side = BrushMostlyOnSide( brush, plane );
if ( side == PSIDE_FRONT ) {
*front = CopyBrush( brush );
}
if ( midwinding.empty() || WindingIsTiny( midwinding ) ) { // the brush isn't really split
const int side = BrushMostlyOnSide( brush, plane );
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" );
}
midwinding = w;
// split it for real
for ( i = 0 ; i < 2 ; i++ )
brush_t *b[2];
for ( int i = 0; i < 2; i++ )
{
b[i] = AllocBrush( brush->numsides + 1 );
memcpy( b[i], brush, sizeof( brush_t ) );
b[i]->numsides = 0;
b[i]->next = NULL;
b[i]->original = brush->original;
b[i] = new brush_t( brush );
b[i]->sides.clear();
}
// split all the current windings
for ( i = 0 ; i < brush->numsides ; i++ )
for ( const side_t& side : brush.sides )
{
s = &brush->sides[i];
w = s->winding;
if ( !w ) {
continue;
}
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 ( !side.winding.empty() ) {
winding_t cw[2];
std::tie( cw[0], cw[1] ) =
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++ )
{
if ( !cw[j] ) {
continue;
if ( !cw[i].empty() ) {
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
for ( i = 0 ; i < 2 ; i++ )
for ( int i = 0; i < 2; i++ )
{
if ( b[i]->numsides < 3 || !BoundBrush( b[i] ) ) {
if ( b[i]->numsides >= 3 ) {
if ( b[i]->sides.size() < 3 || !BoundBrush( *b[i] ) ) {
if ( b[i]->sides.size() >= 3 ) {
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "bogus brush after clip\n" );
}
FreeBrush( b[i] );
delete b[i];
b[i] = NULL;
}
}
if ( !( b[0] && b[1] ) ) {
if ( !b[0] && !b[1] ) {
if ( b[0] == nullptr || b[1] == nullptr ) {
if ( b[0] == nullptr && b[1] == nullptr ) {
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "split removed brush\n" );
}
else{
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "split not on both sides\n" );
}
if ( b[0] ) {
FreeBrush( b[0] );
*front = CopyBrush( brush );
if ( b[0] != nullptr ) {
delete b[0];
return { new brush_t( brush ), {} };
}
if ( b[1] ) {
FreeBrush( b[1] );
*back = CopyBrush( brush );
else if ( b[1] != nullptr ) {
delete b[1];
return { {}, new brush_t( brush ) };
}
return;
return{};
}
// 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];
b[i]->numsides++;
side_t& cs = b[i]->sides.emplace_back();
cs->planenum = planenum ^ i ^ 1;
cs->shaderInfo = NULL;
cs.planenum = planenum ^ i ^ 1;
cs.shaderInfo = NULL;
if ( i == 0 ) {
cs->winding = CopyWinding( midwinding );
cs.winding = midwinding; // copy
}
else{
cs->winding = midwinding;
cs.winding.swap( midwinding ); // move
}
}
for ( int i = 0; i < 2; i++ )
{
float v1;
int i;
for ( i = 0 ; i < 2 ; i++ )
{
v1 = BrushVolume( b[i] );
if ( v1 < 1.0 ) {
FreeBrush( b[i] );
if ( BrushVolume( *b[i] ) < 1.0 ) {
delete b[i];
b[i] = NULL;
// Sys_FPrintf( SYS_WRN | SYS_VRBflag, "tiny volume after clip\n" );
}
}
}
*front = b[0];
*back = b[1];
return{ b[0], b[1] };
}

View File

@ -47,11 +47,11 @@ static void autocaulk_write(){
int flava = 8;
ApplySurfaceParm( "lava", &flava, NULL, NULL );
for ( brush_t* b = entities[0].brushes; b; b = b->next ) {
fprintf( file, "%i ", b->brushNum );
shaderInfo_t* contentShader = b->contentShader;
for( int i = 0; i < b->numsides; ++i ){
if( b->sides[i].visibleHull || ( b->sides[i].compileFlags & C_NODRAW ) ){
for ( const brush_t& b : entities[0].brushes ) {
fprintf( file, "%i ", b.brushNum );
const shaderInfo_t* contentShader = b.contentShader;
for( const side_t& side : b.sides ){
if( !side.visibleHull.empty() || ( side.compileFlags & C_NODRAW ) ){
fprintf( file, "-" );
}
else if( contentShader->compileFlags & C_LIQUID ){
@ -62,7 +62,7 @@ static void autocaulk_write(){
else
fprintf( file, "w" );
}
else if( b->compileFlags & C_TRANSLUCENT ){
else if( b.compileFlags & C_TRANSLUCENT ){
if( contentShader->compileFlags & C_SOLID )
fprintf( file, "N" );
else
@ -170,7 +170,7 @@ static void SetCloneModelNumbers( void ){
for ( std::size_t i = 1; i < entities.size(); ++i )
{
/* 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;
}
@ -190,7 +190,7 @@ static void SetCloneModelNumbers( void ){
for ( std::size_t i = 1; i < entities.size(); ++i )
{
/* 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;
}
@ -220,7 +220,7 @@ static void SetCloneModelNumbers( void ){
entities[ i ].setKeyValue( "model", modelValue );
/* 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;
}
}
@ -284,8 +284,6 @@ static void FixBrushSides( entity_t *e ){
void ProcessWorldModel( void ){
entity_t *e;
tree_t *tree;
facelist_t faces;
xmlNodePtr polyline, leaknode;
char level[ 2 ];
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 */
faces = MakeStructuralBSPFaceList( entities[ 0 ].brushes );
tree = FaceBSP( faces );
facelist_t faces = MakeStructuralBSPFaceList( entities[ 0 ].brushes );
tree_t tree = FaceBSP( faces );
MakeTreePortals( 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 */
/* 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 */
ClipSidesIntoTree( e, tree );
@ -372,7 +370,7 @@ void ProcessWorldModel( void ){
/* flood again to discard portals in the void (also required for _skybox) */
FloodEntities( tree );
FillOutside( tree->headnode );
FillOutside( tree.headnode );
}
/* save out information for visibility processing */
@ -405,7 +403,7 @@ void ProcessWorldModel( void ){
/* subdivide each drawsurf as required by shader tesselation */
if ( !nosubdivide ) {
SubdivideFaceSurfaces( e, tree );
SubdivideFaceSurfaces( e );
}
/* add in any vertexes required to fix t-junctions */
@ -433,7 +431,7 @@ void ProcessWorldModel( void ){
/* ydnar: fog hull */
if ( entities[ 0 ].read_keyvalue( value, "_foghull" ) ) {
const auto shader = String64()( "textures/", value );
MakeFogHullSurfs( e, tree, shader );
MakeFogHullSurfs( e, shader );
}
/* ydnar: bug 645: do flares for lights */
@ -484,7 +482,7 @@ void ProcessWorldModel( void ){
FixBrushSides( e );
/* finish */
EndModel( e, tree->headnode );
EndModel( e, tree.headnode );
FreeTree( tree );
}
@ -496,15 +494,9 @@ void ProcessWorldModel( void ){
*/
void ProcessSubModel( void ){
entity_t *e;
tree_t *tree;
brush_t *b, *bc;
node_t *node;
/* start a brush model */
BeginModel();
e = &entities[ mapEntityNum ];
entity_t *e = &entities[ mapEntityNum ];
e->firstDrawSurf = numMapDrawSurfs;
/* ydnar: gs mods */
@ -514,10 +506,9 @@ void ProcessSubModel( void ){
PatchMapDrawSurfs( e );
/* allocate a tree */
node = AllocNode();
node->planenum = PLANENUM_LEAF;
tree = AllocTree();
tree->headnode = node;
tree_t tree{};
tree.headnode = AllocNode();
tree.headnode->planenum = PLANENUM_LEAF;
/* add the sides to the tree */
ClipSidesIntoTree( e, tree );
@ -532,16 +523,11 @@ void ProcessSubModel( void ){
EmitBrushes( e->brushes, &e->firstBrush, &e->numBrushes );
/* just put all the brushes in headnode */
for ( b = e->brushes; b; b = b->next )
{
bc = CopyBrush( b );
bc->next = node->brushlist;
node->brushlist = bc;
}
tree.headnode->brushlist = e->brushes;
/* subdivide each drawsurf as required by shader tesselation */
if ( !nosubdivide ) {
SubdivideFaceSurfaces( e, tree );
SubdivideFaceSurfaces( e );
}
/* add in any vertexes required to fix t-junctions */
@ -568,7 +554,7 @@ void ProcessSubModel( void ){
FixBrushSides( e );
/* finish */
EndModel( e, node );
EndModel( e, tree.headnode );
FreeTree( tree );
}
@ -597,7 +583,7 @@ void ProcessModels( void ){
{
/* get entity */
const entity_t& entity = entities[ mapEntityNum ];
if ( entity.brushes == NULL && entity.patches == NULL ) {
if ( entity.brushes.empty() && entity.patches == NULL ) {
continue;
}

View File

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

View File

@ -47,14 +47,14 @@ static float Det3x3( float a00, float a01, float a02,
+ 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;
int i;
int t;
float best = 0;
float thisarea;
bspDrawVert_t *vert[3];
const plane_t& buildPlane = mapplanes[buildSide->planenum];
const plane_t& buildPlane = mapplanes[buildSide.planenum];
int matches = 0;
// 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 ) {
continue;
}
if ( !strEqual( buildSide->shaderInfo->shader, bspShaders[s->shaderNum].shader ) ) {
if ( !strEqual( buildSide.shaderInfo->shader, bspShaders[s->shaderNum].shader ) ) {
continue;
}
for ( t = 0; t + 3 <= s->numIndexes; t += 3 )
@ -98,7 +98,7 @@ void GetBestSurfaceTriangleMatchForBrushside( side_t *buildSide, bspDrawVert_t *
continue;
}
// 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 )
{
// 0: 1, 2
@ -110,11 +110,11 @@ void GetBestSurfaceTriangleMatchForBrushside( side_t *buildSide, bspDrawVert_t *
Plane3f plane( vector3_cross( v2 - v1, buildPlane.normal() ), 0 );
plane.dist() = vector3_dot( v1, plane.normal() );
ChopWindingInPlace( polygon, plane, distanceEpsilon );
if ( !polygon ) {
if ( polygon.empty() ) {
goto exwinding;
}
}
thisarea = WindingArea( *polygon );
thisarea = WindingArea( polygon );
if ( thisarea > 0 ) {
++matches;
}
@ -124,13 +124,12 @@ void GetBestSurfaceTriangleMatchForBrushside( side_t *buildSide, bspDrawVert_t *
bestVert[1] = vert[1];
bestVert[2] = vert[2];
}
FreeWinding( polygon );
exwinding:
;
}
}
//if(!striEqualPrefix(buildSide->shaderInfo->shader, "textures/common/"))
// fprintf(stderr, "brushside with %s: %d matches (%f area)\n", buildSide->shaderInfo->shader, matches, best);
//if(!striEqualPrefix(buildSide.shaderInfo->shader, "textures/common/"))
// fprintf(stderr, "brushside with %s: %d matches (%f area)\n", buildSide.shaderInfo->shader, matches, best);
}
#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 ){
int i;
bspBrushSide_t *side;
side_t *buildSide;
bspShader_t *shader;
const char *texture;
plane_t *buildPlane;
Vector3 pts[ 3 ];
/* clear out build brush */
for ( i = 0; i < buildBrush->numsides; i++ )
{
buildSide = &buildBrush->sides[ i ];
if ( buildSide->winding != NULL ) {
FreeWinding( buildSide->winding );
buildSide->winding = NULL;
}
}
buildBrush->numsides = 0;
buildBrush.sides.clear();
bool modelclip = false;
/* try to guess if thats model clip */
if ( force ){
int notNoShader = 0;
modelclip = true;
for ( i = 0; i < brush->numSides; i++ )
for ( int i = 0; i < brush->numSides; i++ )
{
/* get side */
side = &bspBrushSides[ brush->firstSide + i ];
const bspBrushSide_t& side = bspBrushSides[ brush->firstSide + i ];
/* get shader */
if ( side->shaderNum < 0 || side->shaderNum >= numBSPShaders ) {
if ( side.shaderNum < 0 || side.shaderNum >= numBSPShaders ) {
continue;
}
shader = &bspShaders[ side->shaderNum ];
const bspShader_t& shader = bspShaders[ side.shaderNum ];
//"noshader" happens on modelclip and unwanted sides ( usually breaking complex brushes )
if( !striEqual( shader->shader, "noshader" ) ){
if( !striEqual( shader.shader, "noshader" ) ){
notNoShader++;
}
if( notNoShader > 1 ){
@ -242,28 +224,26 @@ static void ConvertBrushFast( FILE *f, int num, bspBrush_t *brush, const Vector3
}
/* iterate through bsp brush sides */
for ( i = 0; i < brush->numSides; i++ )
for ( int i = 0; i < brush->numSides; i++ )
{
/* get side */
side = &bspBrushSides[ brush->firstSide + i ];
const bspBrushSide_t& side = bspBrushSides[ brush->firstSide + i ];
/* get shader */
if ( side->shaderNum < 0 || side->shaderNum >= numBSPShaders ) {
if ( side.shaderNum < 0 || side.shaderNum >= numBSPShaders ) {
continue;
}
shader = &bspShaders[ side->shaderNum ];
const bspShader_t& shader = bspShaders[ side.shaderNum ];
//"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;
/* add build side */
buildSide = &buildBrush->sides[ buildBrush->numsides ];
buildBrush->numsides++;
buildBrush.sides.emplace_back();
/* tag it */
buildSide->shaderInfo = ShaderInfoForShader( shader->shader );
buildSide->planenum = side->planeNum;
buildSide->winding = NULL;
buildBrush.sides.back().shaderInfo = ShaderInfoForShader( shader.shader );
buildBrush.sides.back().planenum = side.planeNum;
}
if ( !CreateBrushWindings( buildBrush ) ) {
@ -280,31 +260,26 @@ static void ConvertBrushFast( FILE *f, int num, bspBrush_t *brush, const Vector3
}
/* 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 */
buildPlane = &mapplanes[ buildSide->planenum ];
const plane_t& buildPlane = mapplanes[ buildSide.planenum ];
/* dummy check */
if ( buildSide->shaderInfo == NULL || buildSide->winding == NULL ) {
if ( buildSide.shaderInfo == NULL || buildSide.winding.empty() ) {
continue;
}
/* get texture name */
if ( striEqualPrefix( buildSide->shaderInfo->shader, "textures/" ) ) {
texture = buildSide->shaderInfo->shader + 9;
}
else{
texture = buildSide->shaderInfo->shader;
}
const char *texture = striEqualPrefix( buildSide.shaderInfo->shader, "textures/" )
? buildSide.shaderInfo->shader + 9
: buildSide.shaderInfo->shader;
Vector3 pts[ 3 ];
{
Vector3 vecs[ 2 ];
MakeNormalVectors( buildPlane->normal(), vecs[ 0 ], vecs[ 1 ] );
pts[ 0 ] = buildPlane->normal() * buildPlane->dist() + origin;
MakeNormalVectors( buildPlane.normal(), vecs[ 0 ], vecs[ 1 ] );
pts[ 0 ] = buildPlane.normal() * buildPlane.dist() + origin;
pts[ 1 ] = pts[ 0 ] + vecs[ 0 ] * 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 ){
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 */
for ( i = 0; i < buildBrush->numsides; i++ )
{
buildSide = &buildBrush->sides[ i ];
if ( buildSide->winding != NULL ) {
FreeWinding( buildSide->winding );
buildSide->winding = NULL;
}
}
buildBrush->numsides = 0;
buildBrush.sides.clear();
bool modelclip = false;
/* try to guess if thats model clip */
if ( force ){
int notNoShader = 0;
modelclip = true;
for ( i = 0; i < brush->numSides; i++ )
for ( int i = 0; i < brush->numSides; i++ )
{
/* get side */
side = &bspBrushSides[ brush->firstSide + i ];
const bspBrushSide_t& side = bspBrushSides[ brush->firstSide + i ];
/* get shader */
if ( side->shaderNum < 0 || side->shaderNum >= numBSPShaders ) {
if ( side.shaderNum < 0 || side.shaderNum >= numBSPShaders ) {
continue;
}
shader = &bspShaders[ side->shaderNum ];
const bspShader_t& shader = bspShaders[ side.shaderNum ];
//"noshader" happens on modelclip and unwanted sides ( usually breaking complex brushes )
if( !striEqual( shader->shader, "noshader" ) ){
if( !striEqual( shader.shader, "noshader" ) ){
notNoShader++;
}
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 */
for ( i = 0; i < brush->numSides; i++ )
for ( int i = 0; i < brush->numSides; i++ )
{
/* get side */
side = &bspBrushSides[ brush->firstSide + i ];
const bspBrushSide_t& side = bspBrushSides[ brush->firstSide + i ];
/* get shader */
if ( side->shaderNum < 0 || side->shaderNum >= numBSPShaders ) {
if ( side.shaderNum < 0 || side.shaderNum >= numBSPShaders ) {
continue;
}
shader = &bspShaders[ side->shaderNum ];
const bspShader_t& shader = bspShaders[ side.shaderNum ];
//"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;
/* add build side */
buildSide = &buildBrush->sides[ buildBrush->numsides ];
buildBrush->numsides++;
buildBrush.sides.emplace_back();
/* tag it */
buildSide->shaderInfo = ShaderInfoForShader( shader->shader );
buildSide->planenum = side->planeNum;
buildSide->winding = NULL;
buildBrush.sides.back().shaderInfo = ShaderInfoForShader( shader.shader );
buildBrush.sides.back().planenum = side.planeNum;
}
/* 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 */
for ( i = 0; i < buildBrush->numsides; i++ )
for ( side_t& buildSide : buildBrush.sides )
{
/* get build side */
buildSide = &buildBrush->sides[ i ];
/* get plane */
const plane_t& buildPlane = mapplanes[ buildSide->planenum ];
const plane_t& buildPlane = mapplanes[ buildSide.planenum ];
/* dummy check */
if ( buildSide->shaderInfo == NULL || buildSide->winding == NULL ) {
if ( buildSide.shaderInfo == NULL || buildSide.winding.empty() ) {
continue;
}
// st-texcoords -> texMat block
// start out with dummy
buildSide->texMat[0] = { 1 / 32.0, 0, 0 };
buildSide->texMat[1] = { 0, 1 / 32.0, 0 };
buildSide.texMat[0] = { 1 / 32.0, 0, 0 };
buildSide.texMat[1] = { 0, 1 / 32.0, 0 };
// find surface for this side (by brute force)
// surface format:
// - meshverts point in pairs of three into verts
// - (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 );
/* get texture name */
if ( striEqualPrefix( buildSide->shaderInfo->shader, "textures/" ) ) {
texture = buildSide->shaderInfo->shader + 9;
}
else{
texture = buildSide->shaderInfo->shader;
}
const char *texture = striEqualPrefix( buildSide.shaderInfo->shader, "textures/" )
? buildSide.shaderInfo->shader + 9
: buildSide.shaderInfo->shader;
Vector3 pts[ 3 ];
/* recheck and fix winding points, fails occur somehow */
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 ) {
pts[ match ] = p;
match++;
@ -476,8 +428,7 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
if( match > 2 ){
//Sys_Printf( "pointsKK " );
Plane3f testplane;
if ( PlaneFromPoints( testplane, pts ) ){
if ( Plane3f testplane; PlaneFromPoints( testplane, pts ) ){
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] );
match--;
@ -493,8 +444,8 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
if( match > 2 ){
//Sys_Printf( "ok " );
/* offset by origin */
for ( j = 0; j < 3; j++ )
pts[ j ] += origin;
for ( Vector3& pt : pts )
pt += origin;
}
else{
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],
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{
@ -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[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 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[1][0], buildSide->texMat[1][1], FRAC( buildSide->texMat[1][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] ),
texture,
0
);
@ -609,12 +560,12 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
tv = 2;
}
stI[0] = vert[0]->st[0] * buildSide->shaderInfo->shaderWidth;
stI[1] = vert[0]->st[1] * buildSide->shaderInfo->shaderHeight;
stJ[0] = vert[1]->st[0] * buildSide->shaderInfo->shaderWidth;
stJ[1] = vert[1]->st[1] * buildSide->shaderInfo->shaderHeight;
stK[0] = vert[2]->st[0] * buildSide->shaderInfo->shaderWidth;
stK[1] = vert[2]->st[1] * buildSide->shaderInfo->shaderHeight;
stI[0] = vert[0]->st[0] * buildSide.shaderInfo->shaderWidth;
stI[1] = vert[0]->st[1] * buildSide.shaderInfo->shaderHeight;
stJ[0] = vert[1]->st[0] * buildSide.shaderInfo->shaderWidth;
stJ[1] = vert[1]->st[1] * buildSide.shaderInfo->shaderHeight;
stK[0] = vert[2]->st[0] * buildSide.shaderInfo->shaderWidth;
stK[1] = vert[2]->st[1] * buildSide.shaderInfo->shaderHeight;
D = Det3x3(
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[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] ) );
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[0] = buildSide.shaderInfo->shaderWidth * FRAC( sts[0][2] / buildSide.shaderInfo->shaderWidth );
shift[1] = buildSide.shaderInfo->shaderHeight * FRAC( sts[1][2] / buildSide.shaderInfo->shaderHeight );
/* print brush side */
/* ( 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
{
if ( !striEqualPrefix( buildSide->shaderInfo->shader, "textures/common/" )
&& !striEqualPrefix( buildSide->shaderInfo->shader, "textures/system/" )
&& !strEqual( buildSide->shaderInfo->shader, "noshader" )
&& !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 );
if ( !striEqualPrefix( buildSide.shaderInfo->shader, "textures/common/" )
&& !striEqualPrefix( buildSide.shaderInfo->shader, "textures/system/" )
&& !strEqual( buildSide.shaderInfo->shader, "noshader" )
&& !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 );
texture = "common/WTF";
}
@ -882,9 +833,9 @@ static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, const Vector
}
/* allocate a build brush */
buildBrush = AllocBrush( 512 );
buildBrush->entityNum = 0;
buildBrush->original = buildBrush;
buildBrush.sides.reserve( MAX_BUILD_SIDES );
buildBrush.entityNum = 0;
buildBrush.original = &buildBrush;
if ( origin != g_vector3_identity ) {
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 */
for ( i = 0; i < model->numBSPSurfaces; i++ )
{

View File

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

View File

@ -42,7 +42,7 @@ int c_faceLeafs;
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;
@ -217,21 +217,17 @@ void BuildFaceTree_r( node_t *node, facelist_t& list ){
/* switch on side */
if ( side == eSideCross ) {
winding_t *frontWinding, *backWinding;
ClipWindingEpsilonStrict( split.w, plane.plane, CLIP_EPSILON * 2,
frontWinding, backWinding ); /* strict; if no winding is left, we have a "virtually identical" plane and don't want to split by it */
if ( frontWinding ) {
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 */
if ( !frontWinding.empty() ) {
face_t& newFace = childLists[0].emplace_front();
newFace.w.swap( *frontWinding );
FreeWinding( frontWinding );
newFace.w.swap( frontWinding );
newFace.planenum = split.planenum;
newFace.priority = split.priority;
newFace.compileFlags = split.compileFlags;
}
if ( backWinding ) {
if ( !backWinding.empty() ) {
face_t& newFace = childLists[1].emplace_front();
newFace.w.swap( *backWinding );
FreeWinding( backWinding );
newFace.w.swap( backWinding );
newFace.planenum = split.planenum;
newFace.priority = split.priority;
newFace.compileFlags = split.compileFlags;
@ -299,15 +295,15 @@ void BuildFaceTree_r( node_t *node, facelist_t& list ){
List will be freed before returning
================
*/
tree_t *FaceBSP( facelist_t& list ) {
tree_t FaceBSP( facelist_t& list ) {
Sys_FPrintf( SYS_VRB, "--- FaceBSP ---\n" );
tree_t *tree = AllocTree();
tree_t tree{};
int count = 0;
for ( const face_t& face : list )
{
WindingExtendBounds( face.w, tree->minmax );
WindingExtendBounds( face.w, tree.minmax );
count++;
}
Sys_FPrintf( SYS_VRB, "%9d faces\n", count );
@ -317,11 +313,11 @@ tree_t *FaceBSP( facelist_t& list ) {
plane.counter = 0;
}
tree->headnode = AllocNode();
tree->headnode->minmax = tree->minmax;
tree.headnode = AllocNode();
tree.headnode->minmax = tree.minmax;
c_faceLeafs = 0;
BuildFaceTree_r( tree->headnode, list );
BuildFaceTree_r( tree.headnode, list );
Sys_FPrintf( SYS_VRB, "%9d leafs\n", c_faceLeafs );
@ -335,21 +331,20 @@ tree_t *FaceBSP( facelist_t& list ) {
get structural brush faces
*/
facelist_t MakeStructuralBSPFaceList( const brush_t *list ){
facelist_t MakeStructuralBSPFaceList( const brushlist_t& list ){
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;
}
for ( int i = 0; i < b->numsides; i++ )
for ( const side_t& s : b.sides )
{
/* get side and winding */
const side_t& s = b->sides[ i ];
const winding_t *w = s.winding;
if ( w == NULL ) {
/* get winding */
const winding_t& w = s.winding;
if ( w.empty() ) {
continue;
}
@ -360,10 +355,10 @@ facelist_t MakeStructuralBSPFaceList( const brush_t *list ){
/* allocate a face */
face_t& f = flist.emplace_front();
f.w = *w;
f.w = w;
f.planenum = s.planenum & ~1;
f.compileFlags = s.compileFlags; /* ydnar */
if ( b->detail ) {
if ( b.detail ) {
f.compileFlags |= C_DETAIL;
}
@ -394,21 +389,20 @@ facelist_t MakeStructuralBSPFaceList( const brush_t *list ){
get visible brush faces
*/
facelist_t MakeVisibleBSPFaceList( const brush_t *list ){
facelist_t MakeVisibleBSPFaceList( const brushlist_t& list ){
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;
}
for ( int i = 0; i < b->numsides; i++ )
for ( const side_t& s : b.sides )
{
/* get side and winding */
const side_t& s = b->sides[ i ];
const winding_t *w = s.visibleHull;
if ( w == NULL ) {
/* get winding */
const winding_t& w = s.visibleHull;
if ( w.empty() ) {
continue;
}
@ -419,10 +413,10 @@ facelist_t MakeVisibleBSPFaceList( const brush_t *list ){
/* allocate a face */
face_t& f = flist.emplace_front();
f.w = *w;
f.w = w;
f.planenum = s.planenum & ~1;
f.compileFlags = s.compileFlags; /* ydnar */
if ( b->detail ) {
if ( b.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
*/
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;
side_t *s;
mesh_t *outside[MAX_BRUSH_SIDES];
int numOutside;
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
for ( i = 4 ; i <= 5 ; i++ ) {
s = &b->sides[ i ];
const plane_t& plane = mapplanes[ s->planenum ];
const plane_t& plane = mapplanes[ b->sides[ i ].planenum ];
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
*/
winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds ){
winding_t *w;
int i;
winding_t WindingFromDrawSurf( const mapDrawSurface_t *ds ){
// we use the first point of the surface, maybe something more clever would be useful
// (actually send the whole draw surface would be cool?)
if ( ds->numVerts >= MAX_POINTS_ON_WINDING ) {
const int max = std::min( ds->numVerts, 256 );
Vector3 p[256];
for ( i = 0; i < max; i++ ) {
for ( int i = 0; i < max; i++ ) {
p[i] = ds->verts[i].xyz;
}
xml_Winding( "WindingFromDrawSurf failed: MAX_POINTS_ON_WINDING exceeded", p, max, true );
}
w = AllocWinding( ds->numVerts );
for ( i = 0; i < ds->numVerts; i++ ) {
w->push_back( ds->verts[i].xyz );
winding_t w = AllocWinding( ds->numVerts );
for ( int i = 0; i < ds->numVerts; i++ ) {
w.push_back( ds->verts[i].xyz );
}
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
*/
bool ChopFaceSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){
int i, j;
side_t *s;
winding_t *w;
winding_t *front, *back;
winding_t *outside[ MAX_BRUSH_SIDES ];
int numOutside;
bool ChopFaceSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, const brush_t *b ){
std::list<winding_t> outside;
mapDrawSurface_t *newds;
@ -378,58 +368,51 @@ bool ChopFaceSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){
}
/* initial setup */
w = WindingFromDrawSurf( ds );
numOutside = 0;
winding_t w = WindingFromDrawSurf( ds );
/* chop by each brush side */
for ( i = 0; i < b->numsides; i++ )
for ( const side_t& side : b->sides )
{
/* get brush side and plane */
s = &b->sides[ i ];
const plane_t& plane = mapplanes[ s->planenum ];
/* get brush plane */
const plane_t& plane = mapplanes[ side.planenum ];
/* handle coplanar outfacing (don't fog) */
if ( ds->sideRef->side->planenum == s->planenum ) {
if ( ds->sideRef->side->planenum == side.planenum ) {
return false;
}
/* handle coplanar infacing (keep inside) */
if ( ( ds->sideRef->side->planenum ^ 1 ) == s->planenum ) {
if ( ( ds->sideRef->side->planenum ^ 1 ) == side.planenum ) {
continue;
}
/* 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 */
FreeWinding( w );
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 */
if ( back == NULL ) {
if ( back.empty() ) {
/* nothing actually contained inside */
for ( j = 0; j < numOutside; j++ )
FreeWinding( outside[ j ] );
return false;
}
if ( front != NULL ) {
if ( numOutside == MAX_BRUSH_SIDES ) {
if ( !front.empty() ) {
if ( outside.size() == MAX_BRUSH_SIDES ) {
Error( "MAX_BRUSH_SIDES" );
}
outside[ numOutside ] = front;
numOutside++;
outside.push_back( std::move( front ) );
}
w = back;
w.swap( back );
}
/* fixme: celshaded surface fragment errata */
/* all of outside fragments become separate drawsurfs */
numFogFragments += numOutside;
s = ds->sideRef->side;
for ( i = 0; i < numOutside; i++ )
numFogFragments += outside.size();
const side_t *s = ds->sideRef->side;
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;
FreeWinding( outside[ i ] );
}
/* 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 */
/* build a drawsurf for it */
newds = DrawSurfaceForSide( e, ds->mapBrush, s, *w );
newds = DrawSurfaceForSide( e, *ds->mapBrush, *s, w );
if ( newds == NULL ) {
return false;
}
@ -562,16 +545,11 @@ void FogDrawSurfaces( entity_t *e ){
*/
int FogForPoint( const Vector3& point, float epsilon ){
int fogNum, i, j;
bool inside;
brush_t *brush;
/* start with bogus fog num */
fogNum = defaultFogNum;
int fogNum = defaultFogNum;
/* 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 */
if ( mapFogs[ i ].brush == NULL ) {
@ -579,15 +557,13 @@ int FogForPoint( const Vector3& point, float epsilon ){
continue;
}
/* get fog brush */
brush = mapFogs[ i ].brush;
/* check point against all planes */
inside = true;
for ( j = 0; j < brush->numsides && inside; j++ )
bool inside = true;
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;
break;
}
}
@ -628,7 +604,7 @@ int FogForBounds( const MinMax& minmax, float epsilon ){
}
/* get fog brush */
brush_t *brush = mapFogs[ i ].brush;
const brush_t *brush = mapFogs[ i ].brush;
/* get bounds */
const MinMax fogMinmax( brush->minmax.mins - Vector3( epsilon ),
@ -663,11 +639,6 @@ int FogForBounds( const MinMax& minmax, float epsilon ){
*/
void CreateMapFogs( void ){
int j;
brush_t *brush;
fog_t *fog;
/* skip? */
if ( nofog ) {
return;
@ -680,10 +651,10 @@ void CreateMapFogs( void ){
for ( const auto& e : entities )
{
/* walk entity brushes */
for ( brush = e.brushes; brush != NULL; brush = brush->next )
for ( const brush_t& brush : e.brushes )
{
/* ignore non-fog brushes */
if ( !brush->contentShader->fogParms ) {
if ( !brush.contentShader->fogParms ) {
continue;
}
@ -693,21 +664,21 @@ void CreateMapFogs( void ){
}
/* set up fog */
fog = &mapFogs[ numMapFogs++ ];
fog->si = brush->contentShader;
fog->brush = brush;
fog->visibleSide = -1;
fog_t& fog = mapFogs[ numMapFogs++ ];
fog.si = brush.contentShader;
fog.brush = &brush;
fog.visibleSide = -1;
/* 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 */
const Vector3 invFogDir = -fog->si->fogDir;
const Vector3 invFogDir = -fog.si->fogDir;
/* 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() ) ) {
fog->visibleSide = j;
if ( VectorCompare( invFogDir, mapplanes[ brush.sides[ j ].planenum ].normal() ) ) {
fog.visibleSide = j;
//% Sys_Printf( "Brush num: %d Side num: %d\n", fog->brushNum, fog->visibleSide );
break;
}
@ -728,20 +699,20 @@ void CreateMapFogs( void ){
Sys_FPrintf( SYS_VRB, "Map has global fog shader %s\n", globalFog );
/* set up fog */
fog = &mapFogs[ numMapFogs++ ];
fog->si = ShaderInfoForShaderNull( globalFog );
if ( fog->si == NULL ) {
fog_t& fog = mapFogs[ numMapFogs++ ];
fog.si = ShaderInfoForShaderNull( globalFog );
if ( fog.si == NULL ) {
Error( "Invalid shader \"%s\" referenced trying to add global fog", globalFog );
}
fog->brush = NULL;
fog->visibleSide = -1;
fog.brush = NULL;
fog.visibleSide = -1;
/* set as default fog */
defaultFogNum = numMapFogs - 1;
/* mark all worldspawn brushes as fogged */
for ( brush = entities[ 0 ].brushes; brush != NULL; brush = brush->next )
ApplySurfaceParm( "fog", &brush->contentFlags, NULL, &brush->compileFlags );
for ( brush_t& brush : entities[ 0 ].brushes )
ApplySurfaceParm( "fog", &brush.contentFlags, NULL, &brush.compileFlags );
}
/* emit some stats */

View File

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

View File

@ -468,7 +468,7 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw
light.si = si;
light.fade = 1.0f;
/* create a regular winding */
light.w = AllocWinding_( rw->numVerts );
light.w = AllocWinding( rw->numVerts );
for ( i = 0; i < rw->numVerts; i++ )
{
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 */
splash.w = AllocWinding_( rw->numVerts );
splash.w = AllocWinding( rw->numVerts );
for ( i = 0; i < rw->numVerts; i++ )
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
*/
void SetBrushContents( brush_t *b ){
int contentFlags, compileFlags;
side_t *s;
int i;
//% bool mixed;
void SetBrushContents( brush_t& b ){
if( b.sides.empty() )
return;
//% bool mixed = false;
/* get initial compile flags from first side */
s = &b->sides[ 0 ];
contentFlags = s->contentFlags;
compileFlags = s->compileFlags;
b->contentShader = s->shaderInfo;
//% mixed = false;
auto s = b.sides.cbegin();
int contentFlags = s->contentFlags;
int compileFlags = s->compileFlags;
b.contentShader = s->shaderInfo;
/* get the content/compile flags for every side in the brush */
//for ( i = 1; i < b->numsides; i++, s++ )
for ( i = 1; i < b->numsides; i++ )
for ( ++s; s != b.sides.cend(); ++s )
{
s = &b->sides[ i ];
if ( s->shaderInfo == NULL ) {
continue;
}
@ -486,36 +481,36 @@ void SetBrushContents( brush_t *b ){
compileFlags |= s->compileFlags;
/* resolve inconsistency, when brush content was determined by 1st face */
if ( b->contentShader->compileFlags & C_LIQUID ){
if ( b.contentShader->compileFlags & C_LIQUID ){
continue;
}
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;
}
else if ( s->compileFlags & C_FOG ){
b->contentShader = s->shaderInfo;
b.contentShader = s->shaderInfo;
}
//playerclip
else if ( b->contentShader->contentFlags & 0x10000 ){
else if ( b.contentShader->contentFlags & 0x10000 ){
continue;
}
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;
}
else if (!( s->compileFlags & C_SOLID )){
b->contentShader = s->shaderInfo;
b.contentShader = s->shaderInfo;
}
}
/* ydnar: getting rid of this stupid warning */
//% 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 */
if ( ( compileFlags & C_DETAIL ) && ( compileFlags & C_STRUCTURAL ) ) {
@ -536,20 +531,20 @@ void SetBrushContents( brush_t *b ){
/* detail? */
if ( compileFlags & C_DETAIL ) {
c_detail++;
b->detail = true;
b.detail = true;
}
else
{
c_structural++;
b->detail = false;
b.detail = false;
}
/* opaque? */
if ( compileFlags & C_TRANSLUCENT ) {
b->opaque = false;
b.opaque = false;
}
else{
b->opaque = true;
b.opaque = true;
}
/* areaportal? */
@ -558,8 +553,8 @@ void SetBrushContents( brush_t *b ){
}
/* set brush flags */
b->contentFlags = contentFlags;
b->compileFlags = compileFlags;
b.contentFlags = contentFlags;
b.compileFlags = compileFlags;
}
@ -572,102 +567,89 @@ void SetBrushContents( brush_t *b ){
*/
void AddBrushBevels( void ){
int axis, dir;
int i, k, order;
side_t sidetemp;
side_t *s, *s2;
const winding_t *w, *w2;
Plane3f plane;
Vector3 vec, vec2;
float d, minBack;
int surfaceFlagsMask = game->brushBevelsSurfaceFlagsMask;
const int surfaceFlagsMask = game->brushBevelsSurfaceFlagsMask;
auto& sides = buildBrush.sides;
//
// add the axial planes
//
order = 0;
for ( axis = 0; axis < 3; axis++ ) {
for ( dir = -1; dir <= 1; dir += 2, order++ ) {
size_t order = 0;
for ( size_t axis = 0; axis < 3; axis++ ) {
for ( int dir = -1; dir <= 1; dir += 2, order++ ) {
// 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 */
#if 0
if ( dir > 0 ) {
if ( mapplanes[s->planenum].normal()[axis] >= 0.9999f ) {
if ( mapplanes[sides[i].planenum].normal()[axis] >= 0.9999f ) {
break;
}
}
else {
if ( mapplanes[s->planenum].normal()[axis] <= -0.9999f ) {
if ( mapplanes[sides[i].planenum].normal()[axis] <= -0.9999f ) {
break;
}
}
#else
if ( ( dir > 0 && mapplanes[ s->planenum ].normal()[ axis ] == 1.0f ) ||
( dir < 0 && mapplanes[ s->planenum ].normal()[ axis ] == -1.0f ) ) {
if ( ( dir > 0 && mapplanes[ sides[i].planenum ].normal()[ axis ] == 1.0f ) ||
( dir < 0 && mapplanes[ sides[i].planenum ].normal()[ axis ] == -1.0f ) ) {
break;
}
#endif
}
if ( i == buildBrush->numsides ) {
if ( i == sides.size() ) {
// add a new side
if ( buildBrush->numsides == MAX_BUILD_SIDES ) {
xml_Select( "MAX_BUILD_SIDES", buildBrush->entityNum, buildBrush->brushNum, true );
if ( sides.size() == MAX_BUILD_SIDES ) {
xml_Select( "MAX_BUILD_SIDES", buildBrush.entityNum, buildBrush.brushNum, true );
}
memset( s, 0, sizeof( *s ) );
buildBrush->numsides++;
side_t& s = sides.emplace_back();
Plane3f plane;
plane.normal().set( 0 );
plane.normal()[axis] = dir;
if ( dir == 1 ) {
/* ydnar: adding bevel plane snapping for fewer bsp planes */
if ( bevelSnap > 0 ) {
plane.dist() = floor( buildBrush->minmax.maxs[ axis ] / bevelSnap ) * bevelSnap;
plane.dist() = floor( buildBrush.minmax.maxs[ axis ] / bevelSnap ) * bevelSnap;
}
else{
plane.dist() = buildBrush->minmax.maxs[ axis ];
plane.dist() = buildBrush.minmax.maxs[ axis ];
}
}
else
{
/* ydnar: adding bevel plane snapping for fewer bsp planes */
if ( bevelSnap > 0 ) {
plane.dist() = -ceil( buildBrush->minmax.mins[ axis ] / bevelSnap ) * bevelSnap;
plane.dist() = -ceil( buildBrush.minmax.mins[ axis ] / bevelSnap ) * bevelSnap;
}
else{
plane.dist() = -buildBrush->minmax.mins[ axis ];
plane.dist() = -buildBrush.minmax.mins[ axis ];
}
}
s->planenum = FindFloatPlane( plane, 0, NULL );
s->contentFlags = buildBrush->sides[ 0 ].contentFlags;
s.planenum = FindFloatPlane( plane, 0, NULL );
s.contentFlags = sides[ 0 ].contentFlags;
/* handle bevel surfaceflags for topmost one only: assuming that only walkable ones are meaningful */
if( axis == 2 && dir == 1 ){
for ( int j = 0; j < buildBrush->numsides; j++ ) {
s2 = buildBrush->sides + j;
w = s2->winding;
if ( !w ) {
continue;
}
for ( const Vector3& po : *w ) {
if ( fabs( plane.dist() - po[axis] ) < .1f ) {
s->surfaceFlags |= ( s2->surfaceFlags & surfaceFlagsMask );
for ( const side_t& side : sides ) {
for ( const Vector3& point : side.winding ) {
if ( fabs( plane.dist() - point[axis] ) < .1f ) {
s.surfaceFlags |= ( side.surfaceFlags & surfaceFlagsMask );
break;
}
}
}
}
s->bevel = true;
s.bevel = true;
c_boxbevels++;
}
// if the plane is not in it canonical order, swap it
if ( i != order ) {
sidetemp = buildBrush->sides[order];
buildBrush->sides[order] = buildBrush->sides[i];
buildBrush->sides[i] = sidetemp;
std::swap( sides[order], sides[i] );
}
}
}
@ -675,76 +657,70 @@ void AddBrushBevels( void ){
//
// add the edge bevels
//
if ( buildBrush->numsides == 6 ) {
if ( sides.size() == 6 ) {
return; // pure axial
}
// test the non-axial plane edges
for ( i = 6; i < buildBrush->numsides; i++ ) {
s = buildBrush->sides + i;
w = s->winding;
if ( !w ) {
continue;
}
for ( size_t j = 0; j < w->size(); j++ ) {
k = ( j + 1 ) % w->size();
vec = ( *w )[j] - ( *w )[k];
for ( size_t i = 6; i < sides.size(); ++i ) {
for ( size_t j = 0; j < sides[i].winding.size(); j++ ) {
Vector3 vec = sides[i].winding[j] - sides[i].winding[( ( j + 1 ) == sides[i].winding.size() )? 0 : ( j + 1 )];
if ( VectorNormalize( vec ) < 0.5f ) {
continue;
}
SnapNormal( vec );
for ( k = 0; k < 3; k++ ) {
if ( vec[k] == -1.0f || vec[k] == 1.0f || ( vec[k] == 0.0f && vec[( k + 1 ) % 3] == 0.0f ) ) {
break; // axial
}
}
if ( k != 3 ) {
continue; // only test non-axial edges
if ( vec[0] == -1.0f || vec[0] == 1.0f || ( vec[0] == 0.0f && vec[1] == 0.0f )
|| vec[1] == -1.0f || vec[1] == 1.0f || ( vec[1] == 0.0f && vec[2] == 0.0f )
|| vec[2] == -1.0f || vec[2] == 1.0f || ( vec[2] == 0.0f && vec[0] == 0.0f ) ) {
continue; // axial, only test non-axial edges
}
/* debug code */
//% Sys_Printf( "-------------\n" );
// try the six possible slanted axials from this edge
for ( axis = 0; axis < 3; axis++ ) {
for ( dir = -1; dir <= 1; dir += 2 ) {
for ( int axis = 0; axis < 3; axis++ ) {
for ( int dir = -1; dir <= 1; dir += 2 ) {
// construct a plane
vec2.set( 0 );
Vector3 vec2( 0 );
vec2[axis] = dir;
Plane3f plane;
plane.normal() = vector3_cross( vec, vec2 );
if ( VectorNormalize( plane.normal() ) < 0.5f ) {
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
// 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 ( PlaneEqual( mapplanes[buildBrush->sides[k].planenum], plane ) ) {
if( buildBrush->sides[k].bevel ){ /* handle bevel surfaceflags */
buildBrush->sides[k].surfaceFlags |= ( s->surfaceFlags & surfaceFlagsMask );
if ( PlaneEqual( mapplanes[iside->planenum], plane ) ) {
if( iside->bevel ){ /* handle bevel surfaceflags */
iside->surfaceFlags |= ( sides[i].surfaceFlags & surfaceFlagsMask );
}
break;
}
w2 = buildBrush->sides[k].winding;
if ( !w2 ) {
const winding_t& w2 = iside->winding;
if ( w2.empty() ) {
continue;
}
minBack = 0.0f;
bool point_in_front = false;
for ( const Vector3& point : *w2 ) {
d = plane3_distance_to_point( plane, point );
float minBack = 0.0f;
const auto point_in_front = [&w2, &plane, &minBack](){
for ( const Vector3& point : w2 ) {
const float d = plane3_distance_to_point( plane, point );
if ( d > 0.1f ) {
point_in_front = true;
break; // point in front
return true;
}
value_minimize( minBack, d );
}
return false;
};
// if some point was at the front
if ( point_in_front ) {
if ( point_in_front() ) {
break;
}
@ -755,7 +731,7 @@ void AddBrushBevels( void ){
}
}
if ( k != buildBrush->numsides ) {
if ( iside != sides.end() ) {
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 ] );
// add this plane
if ( buildBrush->numsides == MAX_BUILD_SIDES ) {
xml_Select( "MAX_BUILD_SIDES", buildBrush->entityNum, buildBrush->brushNum, true );
if ( sides.size() == MAX_BUILD_SIDES ) {
xml_Select( "MAX_BUILD_SIDES", buildBrush.entityNum, buildBrush.brushNum, true );
}
s2 = &buildBrush->sides[buildBrush->numsides];
buildBrush->numsides++;
memset( s2, 0, sizeof( *s2 ) );
side_t& s2 = sides.emplace_back();
s2->planenum = FindFloatPlane( plane, 1, &( *w )[ j ] );
s2->contentFlags = buildBrush->sides[0].contentFlags;
s2->surfaceFlags = ( s->surfaceFlags & surfaceFlagsMask ); /* handle bevel surfaceflags */
s2->bevel = true;
s2.planenum = FindFloatPlane( plane, 1, &sides[i].winding[ j ] );
s2.contentFlags = sides[0].contentFlags;
s2.surfaceFlags = ( sides[i].surfaceFlags & surfaceFlagsMask ); /* handle bevel surfaceflags */
s2.bevel = true;
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 ){
char string[128];
@ -801,38 +769,41 @@ static void MergeOrigin( entity_t& ent, const Vector3& origin ){
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 */
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.
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",
mapEnt->mapEntityNum, mapEnt->classname(), entitySourceBrushes );
if ( entities.size() == 1 ) {
Sys_FPrintf( SYS_WRN, "Entity %i, Brush %i: origin brushes not allowed in world\n",
mapEnt->mapEntityNum, entitySourceBrushes );
return NULL;
return;
}
MergeOrigin( entities.back(), buildBrush->minmax.origin() );
MergeOrigin( entities.back(), buildBrush.minmax.origin() );
/* don't keep this brush */
return NULL;
return;
}
/* determine if the brush is an area portal */
if ( buildBrush->compileFlags & C_AREAPORTAL ) {
if ( buildBrush.compileFlags & C_AREAPORTAL ) {
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 );
return NULL;
return;
}
}
@ -842,47 +813,30 @@ brush_t *FinishBrush( bool noCollapseGroups ){
}
/* 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 */
b->entityNum = mapEnt->mapEntityNum;
b->brushNum = entitySourceBrushes;
b.entityNum = mapEnt->mapEntityNum;
b.brushNum = entitySourceBrushes;
/* set original */
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;
}
b.original = &b;
/* link colorMod volume brushes to the entity directly */
if ( b->contentShader != NULL &&
b->contentShader->colorMod != NULL &&
b->contentShader->colorMod->type == EColorMod::Volume ) {
b->nextColorModBrush = mapEnt->colorModBrushes;
mapEnt->colorModBrushes = b;
if ( b.contentShader != NULL &&
b.contentShader->colorMod != NULL &&
b.contentShader->colorMod->type == EColorMod::Volume ) {
mapEnt->colorModBrushes.push_back( &b );
}
/* return to sender */
return b;
}
/*
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!)
*/
@ -1003,19 +957,9 @@ void QuakeTextureVecs( const plane_t& plane, float shift[ 2 ], float rotate, flo
*/
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 */
buildBrush->numsides = 0;
buildBrush->detail = false;
buildBrush.sides.clear();
buildBrush.detail = false;
/* bp */
if ( g_brushType == EBrushType::Bp ) {
@ -1048,29 +992,41 @@ static void ParseRawBrush( bool onlyLights ){
UnGetToken();
/* test side count */
if ( buildBrush->numsides >= MAX_BUILD_SIDES ) {
xml_Select( "MAX_BUILD_SIDES", buildBrush->entityNum, buildBrush->brushNum, true );
if ( buildBrush.sides.size() >= MAX_BUILD_SIDES ) {
xml_Select( "MAX_BUILD_SIDES", buildBrush.entityNum, buildBrush.brushNum, true );
}
/* add side */
side = &buildBrush->sides[ buildBrush->numsides ];
memset( side, 0, sizeof( *side ) );
buildBrush->numsides++;
side_t& side = buildBrush.sides.emplace_back();
/* read the three point plane definition */
DoubleVector3 planePoints[ 3 ];
Parse1DMatrix( 3, planePoints[ 0 ].data() );
Parse1DMatrix( 3, planePoints[ 1 ].data() );
Parse1DMatrix( 3, planePoints[ 2 ].data() );
/* find the plane number */
side.planenum = MapPlaneFromPoints( planePoints );
PlaneFromPoints( side.plane, planePoints );
/* bp: read the texture matrix */
if ( g_brushType == EBrushType::Bp ) {
Parse2DMatrix( 2, 3, side->texMat->data() );
Parse2DMatrix( 2, 3, side.texMat->data() );
}
/* read shader name */
GetToken( false );
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? */
if ( g_brushType == EBrushType::Undefined ){
GetToken( false );
@ -1086,6 +1042,8 @@ static void ParseRawBrush( bool onlyLights ){
}
if ( g_brushType == EBrushType::Quake ) {
float shift[ 2 ], rotate, scale[ 2 ];
GetToken( false );
shift[ 0 ] = atof( token );
GetToken( false );
@ -1096,19 +1054,27 @@ static void ParseRawBrush( bool onlyLights ){
scale[ 0 ] = atof( token );
GetToken( false );
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 ){
int axis, comp;
for ( axis = 0; axis < 2; ++axis ){
for ( int axis = 0; axis < 2; ++axis ){
MatchToken( "[" );
for ( comp = 0; comp < 4; ++comp ){
for ( int comp = 0; comp < 4; ++comp ){
GetToken( false );
side->vecs[axis][comp] = atof( token );
side.vecs[axis][comp] = atof( token );
}
MatchToken( "]" );
}
GetToken( false );
rotate = atof( token );
GetToken( false ); // rotate
float scale[2];
GetToken( false );
scale[ 0 ] = atof( token );
GetToken( false );
@ -1116,27 +1082,8 @@ static void ParseRawBrush( bool onlyLights ){
if ( !scale[0] ) scale[0] = 1.f;
if ( !scale[1] ) scale[1] = 1.f;
for ( axis = 0; axis < 2; ++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 );
for ( int axis = 0; axis < 2; ++axis )
side.vecs[axis].vec3() /= scale[axis];
}
/*
@ -1153,9 +1100,9 @@ static void ParseRawBrush( bool onlyLights ){
if ( TokenAvailable() ) {
/* get detail bit from map content flags */
GetToken( false );
flags = atoi( token );
const int flags = atoi( token );
if ( flags & C_DETAIL ) {
side->compileFlags |= C_DETAIL;
side.compileFlags |= C_DETAIL;
}
/* historical */
@ -1164,16 +1111,6 @@ static void ParseRawBrush( bool onlyLights ){
GetToken( false );
//% 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 */
@ -1193,44 +1130,37 @@ static void ParseRawBrush( bool onlyLights ){
also removes planes without any normal
*/
bool RemoveDuplicateBrushPlanes( brush_t *b ){
int i, j, k;
side_t *sides;
sides = b->sides;
for ( i = 1 ; i < b->numsides ; i++ ) {
bool RemoveDuplicateBrushPlanes( brush_t& b ){
auto& sides = b.sides;
for( auto it = sides.cbegin(); it != sides.cend(); ){
// check for a degenerate plane
if ( sides[i].planenum == -1 ) {
xml_Select( "degenerate plane", b->entityNum, b->brushNum, false );
if ( it->planenum == -1 ) {
xml_Select( "degenerate plane", b.entityNum, b.brushNum, false );
// remove it
for ( k = i + 1 ; k < b->numsides ; k++ ) {
sides[k - 1] = sides[k];
it = sides.erase( it );
}
else{
++it;
}
b->numsides--;
i--;
continue;
}
for ( size_t i = 0; i < sides.size(); ++i ) {
// 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 ) {
xml_Select( "duplicate plane", b->entityNum, b->brushNum, false );
xml_Select( "duplicate plane", b.entityNum, b.brushNum, false );
// remove the second duplicate
for ( k = i + 1 ; k < b->numsides ; k++ ) {
sides[k - 1] = sides[k];
sides.erase( sides.cbegin() + j );
}
b->numsides--;
i--;
break;
}
if ( sides[i].planenum == ( sides[j].planenum ^ 1 ) ) {
else if ( sides[i].planenum == ( sides[j].planenum ^ 1 ) ) {
// 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;
}
else{
++j;
}
}
}
return true;
@ -1253,10 +1183,10 @@ static void ParseBrush( bool onlyLights, bool noCollapseGroups ){
}
/* set some defaults */
buildBrush->portalareas[ 0 ] = -1;
buildBrush->portalareas[ 1 ] = -1;
buildBrush->entityNum = numMapEntities - 1;
buildBrush->brushNum = entitySourceBrushes;
buildBrush.portalareas[ 0 ] = -1;
buildBrush.portalareas[ 1 ] = -1;
buildBrush.entityNum = numMapEntities - 1;
buildBrush.brushNum = entitySourceBrushes;
/* if there are mirrored planes, the entire brush is invalid */
if ( !RemoveDuplicateBrushPlanes( buildBrush ) ) {
@ -1267,20 +1197,17 @@ static void ParseBrush( bool onlyLights, bool noCollapseGroups ){
SetBrushContents( buildBrush );
/* allow detail brushes to be removed */
if ( nodetail && ( buildBrush->compileFlags & C_DETAIL ) ) {
//% FreeBrush( buildBrush );
if ( nodetail && ( buildBrush.compileFlags & C_DETAIL ) ) {
return;
}
/* allow liquid brushes to be removed */
if ( nowater && ( buildBrush->compileFlags & C_LIQUID ) ) {
//% FreeBrush( buildBrush );
if ( nowater && ( buildBrush.compileFlags & C_LIQUID ) ) {
return;
}
/* ydnar: allow hint brushes to be removed */
if ( noHint && ( buildBrush->compileFlags & C_HINT ) ) {
//% FreeBrush( buildBrush );
if ( noHint && ( buildBrush.compileFlags & C_HINT ) ) {
return;
}
@ -1299,49 +1226,36 @@ static void ParseBrush( bool onlyLights, bool noCollapseGroups ){
void AdjustBrushesForOrigin( 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 */
ent->originbrush_origin = -ent->origin;
AdjustBrushesForOrigin( ent );
ent->originbrush_origin.set( 0 );
/* 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 */
next = b->next;
next = std::next( b );
/* link opaque brushes to head of list, translucent brushes to end */
if ( b->opaque || entities[ 0 ].lastBrush == NULL ) {
b->next = entities[ 0 ].brushes;
entities[ 0 ].brushes = b;
if ( entities[ 0 ].lastBrush == NULL ) {
entities[ 0 ].lastBrush = b;
}
if ( b->opaque ) {
entities[ 0 ].brushes.splice( entities[ 0 ].brushes.begin(), ent->brushes, b );
}
else
{
b->next = NULL;
entities[ 0 ].lastBrush->next = b;
entities[ 0 ].lastBrush = b;
entities[ 0 ].brushes.splice( entities[ 0 ].brushes.end(), ent->brushes, b );
}
}
ent->brushes = NULL;
/* ydnar: move colormod brushes */
if ( ent->colorModBrushes != NULL ) {
for ( b = ent->colorModBrushes; b->nextColorModBrush != NULL; b = b->nextColorModBrush ) ;
b->nextColorModBrush = entities[ 0 ].colorModBrushes;
entities[ 0 ].colorModBrushes = ent->colorModBrushes;
ent->colorModBrushes = NULL;
if ( !ent->colorModBrushes.empty() ) {
entities[ 0 ].colorModBrushes.insert( entities[ 0 ].colorModBrushes.end(), ent->colorModBrushes.begin(), ent->colorModBrushes.end() );
ent->colorModBrushes.clear();
}
/* move patches */
if ( ent->patches != NULL ) {
parseMesh_t *pm;
for ( pm = ent->patches; pm->next != NULL; pm = pm->next ) ;
pm->next = entities[ 0 ].patches;
@ -1358,28 +1272,18 @@ void MoveBrushesToWorld( entity_t *ent ){
*/
void AdjustBrushesForOrigin( entity_t *ent ){
int i;
side_t *s;
float newdist;
brush_t *b;
parseMesh_t *p;
/* walk brush list */
for ( b = ent->brushes; b != NULL; b = b->next )
for ( brush_t& b : ent->brushes )
{
/* 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 */
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 */
s->planenum = FindFloatPlane( mapplanes[ s->planenum ].normal(), newdist, 0, NULL );
s->plane.dist() = -plane3_distance_to_point( s->plane, ent->originbrush_origin );
side.planenum = FindFloatPlane( mapplanes[ side.planenum ].normal(), newdist, 0, NULL );
side.plane.dist() = -plane3_distance_to_point( side.plane, ent->originbrush_origin );
}
/* rebuild brush windings (ydnar: just offsetting the winding above should be fine) */
@ -1387,9 +1291,9 @@ void AdjustBrushesForOrigin( entity_t *ent ){
}
/* 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;
}
}
@ -1402,20 +1306,16 @@ void AdjustBrushesForOrigin( entity_t *ent ){
*/
void SetEntityBounds( entity_t *e ){
int i;
brush_t *b;
parseMesh_t *p;
MinMax minmax;
/* 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 );
}
@ -1424,11 +1324,11 @@ void SetEntityBounds( entity_t *e ){
e->read_keyvalue( minmax.maxs, "max" );
/* 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;
}
@ -1447,12 +1347,10 @@ void LoadEntityIndexMap( entity_t *e ){
byte *pixels;
unsigned int *pixels32;
indexMap_t *im;
brush_t *b;
parseMesh_t *p;
/* this only works with bmodel ents */
if ( e->brushes == NULL && e->patches == NULL ) {
if ( e->brushes.empty() && e->patches == NULL ) {
return;
}
@ -1566,9 +1464,9 @@ void LoadEntityIndexMap( entity_t *e ){
}
/* store the index map in every brush/patch in the entity */
for ( b = e->brushes; b != NULL; b = b->next )
b->im = im;
for ( p = e->patches; p != NULL; p = p->next )
for ( brush_t& b : e->brushes )
b.im = im;
for ( parseMesh_t *p = e->patches; p != NULL; p = p->next )
p->im = im;
}
@ -1584,9 +1482,6 @@ void LoadEntityIndexMap( entity_t *e ){
*/
static bool ParseMapEntity( bool onlyLights, bool noCollapseGroups ){
brush_t *brush;
parseMesh_t *patch;
/* eof check */
if ( !GetToken( true ) ) {
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 );
/* 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->castShadows = castShadows;
brush->recvShadows = recvShadows;
brush->lightmapSampleSize = lightmapSampleSize;
brush->lightmapScale = lightmapScale;
brush->celShader = celShader;
brush->shadeAngleDegrees = shadeAngle;
brush.entityNum = mapEnt->mapEntityNum;
brush.castShadows = castShadows;
brush.recvShadows = recvShadows;
brush.lightmapSampleSize = lightmapSampleSize;
brush.lightmapScale = lightmapScale;
brush.celShader = celShader;
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->castShadows = castShadows;
@ -1775,8 +1670,7 @@ static bool ParseMapEntity( bool onlyLights, bool noCollapseGroups ){
void LoadMapFile( char *filename, bool onlyLights, bool noCollapseGroups ){
FILE *file;
brush_t *b;
int oldNumEntities = 0, numMapBrushes;
int oldNumEntities = 0;
/* note it */
@ -1804,7 +1698,7 @@ void LoadMapFile( char *filename, bool onlyLights, bool noCollapseGroups ){
g_brushType = EBrushType::Undefined;
/* 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 */
while ( ParseMapEntity( onlyLights, noCollapseGroups ) ) ;
@ -1818,13 +1712,13 @@ void LoadMapFile( char *filename, bool onlyLights, bool noCollapseGroups ){
{
/* set map bounds */
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 */
numMapBrushes = CountBrushList( entities[ 0 ].brushes );
const int numMapBrushes = entities[ 0 ].brushes.size();
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" );
}

View File

@ -718,13 +718,12 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor
if ( PlaneFromPoints( plane, points ) ) {
/* build a brush */
buildBrush = AllocBrush( 48 );
buildBrush->entityNum = mapEntityNum;
buildBrush->original = buildBrush;
buildBrush->contentShader = si;
buildBrush->compileFlags = si->compileFlags;
buildBrush->contentFlags = si->contentFlags;
buildBrush->detail = true;
buildBrush.sides.reserve( MAX_BUILD_SIDES );
buildBrush.entityNum = mapEntityNum;
buildBrush.contentShader = si;
buildBrush.compileFlags = si->compileFlags;
buildBrush.contentFlags = si->contentFlags;
buildBrush.detail = true;
//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)
@ -893,24 +892,25 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor
}
#endif
/* set up brush sides */
buildBrush->numsides = 4;
buildBrush->sides[ 0 ].shaderInfo = si;
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < buildBrush->numsides; j++ ) {
buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
buildBrush.sides.resize( 4 );
buildBrush.sides[ 0 ].shaderInfo = si;
buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < 4; j++ ) {
if ( debugClip ) {
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
}
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
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[ 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[ 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[ 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]
}
@ -1033,25 +1033,26 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor
}
#endif
/* set up brush sides */
buildBrush->numsides = 5;
buildBrush->sides[ 0 ].shaderInfo = si;
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < buildBrush->numsides; j++ ) {
buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
buildBrush.sides.resize( 5 );
buildBrush.sides[ 0 ].shaderInfo = si;
buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < 5; j++ ) {
if ( debugClip ) {
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
}
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
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[ 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[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
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[ 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[ 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;
/* set up brush sides */
buildBrush->numsides = 5;
buildBrush->sides[ 0 ].shaderInfo = si;
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < buildBrush->numsides; j++ ) {
buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
buildBrush.sides.resize( 5 );
buildBrush.sides[ 0 ].shaderInfo = si;
buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < 5; j++ ) {
if ( debugClip ) {
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
}
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
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[ 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[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
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[ 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[ 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;
/* set up brush sides */
buildBrush->numsides = 5;
buildBrush->sides[ 0 ].shaderInfo = si;
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < buildBrush->numsides; j++ ) {
buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
buildBrush.sides.resize( 5 );
buildBrush.sides[ 0 ].shaderInfo = si;
buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < 5; j++ ) {
if ( debugClip ) {
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
}
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
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[ 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[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
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[ 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[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
}
@ -1230,25 +1233,26 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor
}
#endif
/* set up brush sides */
buildBrush->numsides = 5;
buildBrush->sides[ 0 ].shaderInfo = si;
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < buildBrush->numsides; j++ ) {
buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
buildBrush.sides.resize( 5 );
buildBrush.sides[ 0 ].shaderInfo = si;
buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < 5; j++ ) {
if ( debugClip ) {
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
}
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
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[ 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[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
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[ 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[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
}
@ -1293,30 +1297,30 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor
}
#endif
/* set up brush sides */
buildBrush->numsides = 4;
buildBrush->sides[ 0 ].shaderInfo = si;
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < buildBrush->numsides; j++ ) {
buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
buildBrush.sides.resize( 4 );
buildBrush.sides[ 0 ].shaderInfo = si;
buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < 4; j++ ) {
if ( debugClip ) {
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
}
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
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[ 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[ 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[ 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]
}
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",
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;
}
}
@ -1359,25 +1363,26 @@ default_CLIPMODEL:
}
#endif
/* set up brush sides */
buildBrush->numsides = 5;
buildBrush->sides[ 0 ].shaderInfo = si;
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < buildBrush->numsides; j++ ) {
buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
buildBrush.sides.resize( 5 );
buildBrush.sides[ 0 ].shaderInfo = si;
buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
for ( j = 1; j < 5; j++ ) {
if ( debugClip ) {
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
}
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
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[ 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[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
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[ 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[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
}
@ -1385,14 +1390,13 @@ default_CLIPMODEL:
if ( CreateBrushWindings( buildBrush ) ) {
AddBrushBevels();
//% EmitBrushes( buildBrush, NULL, NULL );
buildBrush->next = entities[ mapEntityNum ].brushes;
entities[ mapEntityNum ].brushes = buildBrush;
brush_t& newBrush = entities[ mapEntityNum ].brushes.emplace_front( buildBrush );
newBrush.original = &newBrush;
entities[ mapEntityNum ].numBrushes++;
}
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",
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 */
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 );
}
extern bool FixWinding( winding_t& w );
@ -157,7 +140,7 @@ void RemovePortalFromNode( portal_t *portal, node_t *l ){
//============================================================================
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] );
}
@ -169,59 +152,46 @@ void PrintPortal( const portal_t *p ){
================
*/
#define SIDESPACE 8
void MakeHeadnodePortals( tree_t *tree ){
int i, j, n;
portal_t *p, *portals[6];
plane_t bplanes[6];
node_t *node;
node = tree->headnode;
void MakeHeadnodePortals( tree_t& tree ){
portal_t *portals[6];
// pad with some space so there will never be null volume leafs
const MinMax bounds( tree->minmax.mins - Vector3( SIDESPACE ),
tree->minmax.maxs + Vector3( SIDESPACE ) );
const MinMax bounds( tree.minmax.mins - Vector3( SIDESPACE ),
tree.minmax.maxs + Vector3( SIDESPACE ) );
if ( !bounds.valid() ) {
Error( "Backwards tree volume" );
}
tree->outside_node.planenum = PLANENUM_LEAF;
tree->outside_node.brushlist = NULL;
tree->outside_node.portals = NULL;
tree->outside_node.opaque = false;
tree.outside_node.planenum = PLANENUM_LEAF;
tree.outside_node.brushlist.clear();
tree.outside_node.portals = NULL;
tree.outside_node.opaque = false;
for ( i = 0 ; i < 3 ; i++ )
for ( j = 0 ; j < 2 ; j++ )
for ( int i = 0 ; i < 3 ; i++ )
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 ) {
pl->normal()[i] = -1;
pl->dist() = -bounds.maxs[i];
p->plane.plane = Plane3f( -g_vector3_axes[i], -bounds.maxs[i] );
}
else
{
pl->normal()[i] = 1;
pl->dist() = bounds.mins[i];
p->plane.plane = Plane3f( g_vector3_axes[i], bounds.mins[i] );
}
p->plane = *pl;
p->winding = BaseWindingForPlane( pl->plane );
AddPortalToNodes( p, node, &tree->outside_node );
p->winding = BaseWindingForPlane( p->plane.plane );
AddPortalToNodes( p, tree.headnode, &tree.outside_node );
}
// 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 ) {
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 SPLIT_WINDING_EPSILON 0.001
winding_t *BaseWindingForNode( node_t *node ){
winding_t *w;
node_t *n;
w = BaseWindingForPlane( mapplanes[node->planenum].plane );
winding_t BaseWindingForNode( const node_t *node ){
winding_t w = BaseWindingForPlane( mapplanes[node->planenum].plane );
// 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];
@ -273,14 +240,12 @@ winding_t *BaseWindingForNode( node_t *node ){
==================
*/
void MakeNodePortal( node_t *node ){
portal_t *new_portal, *p;
winding_t *w;
int side;
w = BaseWindingForNode( node );
winding_t w = BaseWindingForNode( 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 ) {
side = 0;
@ -296,7 +261,7 @@ void MakeNodePortal( node_t *node ){
}
if ( !w ) {
if ( w.empty() ) {
return;
}
@ -305,21 +270,19 @@ void MakeNodePortal( node_t *node ){
#if 0
if ( !FixWinding( w ) ) {
c_badportals++;
FreeWinding( w );
return;
}
#endif
if ( WindingIsTiny( *w ) ) {
if ( WindingIsTiny( w ) ) {
c_tinyportals++;
FreeWinding( w );
return;
}
new_portal = AllocPortal();
portal_t *new_portal = AllocPortal();
new_portal->plane = mapplanes[node->planenum];
new_portal->onnode = node;
new_portal->winding = w;
new_portal->winding.swap( w );
new_portal->compileFlags = node->compileFlags;
AddPortalToNodes( new_portal, node->children[0], node->children[1] );
}
@ -334,17 +297,15 @@ void MakeNodePortal( node_t *node ){
==============
*/
void SplitNodePortals( node_t *node ){
portal_t *p, *next_portal, *new_portal;
node_t *f, *b, *other_node;
int side;
winding_t *frontwinding, *backwinding;
const plane_t& plane = mapplanes[node->planenum];
f = node->children[0];
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 ) {
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
//
ClipWindingEpsilon( *p->winding, plane.plane,
SPLIT_WINDING_EPSILON, frontwinding, backwinding ); /* not strict, we want to always keep one of them even if coplanar */
auto [frontwinding, backwinding] = ClipWindingEpsilon( p->winding, plane.plane, SPLIT_WINDING_EPSILON ); /* 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 ) {
f->referencepoint = ( *frontwinding )[0];
f->referencepoint = frontwinding[0];
}
f->tinyportals++;
if ( !other_node->tinyportals ) {
other_node->referencepoint = ( *frontwinding )[0];
other_node->referencepoint = frontwinding[0];
}
other_node->tinyportals++;
FreeWinding( frontwinding );
frontwinding = NULL;
frontwinding.clear();
c_tinyportals++;
}
if ( backwinding && WindingIsTiny( *backwinding ) ) {
if ( !backwinding.empty() && WindingIsTiny( backwinding ) ) {
if ( !b->tinyportals ) {
b->referencepoint = ( *backwinding )[0];
b->referencepoint = backwinding[0];
}
b->tinyportals++;
if ( !other_node->tinyportals ) {
other_node->referencepoint = ( *backwinding )[0];
other_node->referencepoint = backwinding[0];
}
other_node->tinyportals++;
FreeWinding( backwinding );
backwinding = NULL;
backwinding.clear();
c_tinyportals++;
}
if ( !frontwinding && !backwinding ) { // tiny windings on both sides
if ( frontwinding.empty() && backwinding.empty() ) { // tiny windings on both sides
continue;
}
if ( !frontwinding ) {
FreeWinding( backwinding );
if ( frontwinding.empty() ) {
if ( side == 0 ) {
AddPortalToNodes( p, b, other_node );
}
@ -410,8 +367,7 @@ void SplitNodePortals( node_t *node ){
}
continue;
}
if ( !backwinding ) {
FreeWinding( frontwinding );
if ( backwinding.empty() ) {
if ( side == 0 ) {
AddPortalToNodes( p, f, other_node );
}
@ -422,11 +378,10 @@ void SplitNodePortals( node_t *node ){
}
// the winding is split
new_portal = AllocPortal();
*new_portal = *p;
new_portal->winding = backwinding;
FreeWinding( p->winding );
p->winding = frontwinding;
p->winding.clear();
portal_t *new_portal = new portal_t( *p ); // AllocPortal()
new_portal->winding.swap( backwinding );
p->winding.swap( frontwinding );
if ( side == 0 ) {
AddPortalToNodes( p, f, other_node );
@ -457,7 +412,7 @@ void CalcNodeBounds( node_t *node ){
for ( p = node->portals; p; p = p->next[s] )
{
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 ( node->portals && node->portals->winding ) {
xml_Winding( "WARNING: Node With Unbounded Volume", node->portals->winding->data(), node->portals->winding->size(), false );
if ( node->portals && !node->portals->winding.empty() ) {
xml_Winding( "WARNING: Node With Unbounded Volume", node->portals->winding.data(), node->portals->winding.size(), false );
}
}
if ( node->planenum == PLANENUM_LEAF ) {
@ -499,10 +454,10 @@ void MakeTreePortals_r( node_t *node ){
MakeTreePortals
==================
*/
void MakeTreePortals( tree_t *tree ){
void MakeTreePortals( tree_t& tree ){
Sys_FPrintf( SYS_VRB, "--- MakeTreePortals ---\n" );
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 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;
node_t *headnode;
const char *value;
headnode = tree->headnode;
Sys_FPrintf( SYS_VRB, "--- FloodEntities ---\n" );
inside = false;
tree->outside_node.occupied = 0;
tree.outside_node.occupied = 0;
c_floodedleafs = 0;
for ( std::size_t i = 1; i < entities.size(); ++i )
@ -617,7 +570,7 @@ EFloodEntities FloodEntities( tree_t *tree ){
}
#endif
/* 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;
}
@ -653,7 +606,7 @@ EFloodEntities FloodEntities( tree_t *tree ){
//% origin[ 2 ] += 4096;
/* find leaf */
r = PlaceOccupant( headnode, origin, &e, skybox );
r = PlaceOccupant( tree.headnode, origin, &e, skybox );
if ( r ) {
inside = true;
}
@ -668,7 +621,7 @@ EFloodEntities FloodEntities( tree_t *tree ){
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "no entities in open -- no filling\n" );
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" );
return EFloodEntities::Leaked;
}
@ -696,7 +649,6 @@ int c_areas;
void FloodAreas_r( node_t *node ){
int s;
portal_t *p;
brush_t *b;
if ( node->areaportal ) {
@ -705,7 +657,7 @@ void FloodAreas_r( node_t *node ){
}
/* 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 ( b->portalareas[ 0 ] == c_areas || b->portalareas[ 1 ] == c_areas ) {
@ -786,9 +738,7 @@ void FindAreas_r( node_t *node ){
CheckAreas_r
=============
*/
void CheckAreas_r( node_t *node ){
brush_t *b;
void CheckAreas_r( const node_t *node ){
if ( node->planenum != PLANENUM_LEAF ) {
CheckAreas_r( node->children[0] );
CheckAreas_r( node->children[1] );
@ -805,7 +755,7 @@ void CheckAreas_r( node_t *node ){
}
}
if ( node->areaportal ) {
b = node->brushlist->original;
const brush_t *b = node->brushlist.front().original;
// check if the areaportal touches two areas
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
*/
void FloodAreas( tree_t *tree ){
void FloodAreas( tree_t& tree ){
Sys_FPrintf( SYS_VRB, "--- FloodAreas ---\n" );
FindAreas_r( tree->headnode );
FindAreas_r( tree.headnode );
/* ydnar: flood all skybox nodes */
FloodSkyboxArea_r( tree->headnode );
FloodSkyboxArea_r( tree.headnode );
/* check for areaportal brushes that don't touch two areas */
/* 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 );
}

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

View File

@ -739,9 +739,9 @@ struct side_t
Vector3 texMat[ 2 ]; /* brush primitive texture matrix */
Vector4 vecs[ 2 ]; /* old-style texture coordinate mapping */
Plane3 plane; /* optional plane in double precision for building windings */
winding_t *winding;
winding_t *visibleHull; /* convex hull of all visible fragments */
Plane3 plane{ 0, 0, 0, 0 }; /* optional plane in double precision for building windings */
winding_t winding;
winding_t visibleHull; /* convex hull of all visible fragments */
shaderInfo_t *shaderInfo;
@ -759,7 +759,7 @@ struct side_t
struct sideRef_t
{
sideRef_t *next;
side_t *side;
const side_t *side;
};
@ -775,8 +775,6 @@ struct indexMap_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 */
int entityNum, brushNum; /* editor numbering */
@ -804,16 +802,16 @@ struct brush_t
int portalareas[ 2 ];
MinMax minmax;
int numsides;
side_t sides[]; /* variably sized */
std::vector<side_t> sides;
};
using brushlist_t = std::list<brush_t>;
struct fog_t
{
shaderInfo_t *si;
brush_t *brush;
const brush_t *brush;
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 *celShader;
brush_t *mapBrush;
const brush_t *mapBrush;
parseMesh_t *mapMesh;
sideRef_t *sideRef;
@ -974,7 +972,7 @@ struct drawSurfRef_t
struct metaTriangle_t
{
shaderInfo_t *si;
side_t *side;
const side_t *side;
int entityNum, surfaceNum, planeNum, fogNum, sampleSize, castShadows, recvShadows;
float shadeAngleDegrees;
Plane3f plane;
@ -992,7 +990,8 @@ struct epair_t
struct entity_t
{
Vector3 origin{ 0 };
brush_t *brushes, *lastBrush, *colorModBrushes;
brushlist_t brushes;
std::vector<brush_t*> colorModBrushes;
parseMesh_t *patches;
int mapEntityNum, firstDrawSurf;
int firstBrush, numBrushes; /* only valid during BSP compile */
@ -1059,10 +1058,8 @@ struct node_t
int planenum; /* -1 = leaf node */
node_t *parent;
MinMax minmax; /* valid after portalization */
brush_t *volume; /* one for each leaf/node */
/* nodes only */
side_t *side; /* the side that created the node */
node_t *children[ 2 ];
int compileFlags; /* ydnar: hint, antiportal */
int tinyportals;
@ -1075,7 +1072,7 @@ struct node_t
bool sky; /* ydnar: a sky leaf */
int cluster; /* for portalfile writing */
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;
int occupied; /* 1 or greater can reach entity */
@ -1093,11 +1090,10 @@ struct portal_t
node_t *onnode; /* NULL = outside box */
node_t *nodes[ 2 ]; /* [ 0 ] = front side of plane */
portal_t *next[ 2 ];
winding_t *winding;
winding_t winding;
bool sidefound; /* false if ->side hasn't been checked */
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 */
sideRef_t *AllocSideRef( side_t *side, sideRef_t *next );
int CountBrushList( brush_t *brushes );
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 );
sideRef_t *AllocSideRef( const side_t *side, sideRef_t *next );
bool BoundBrush( brush_t& brush );
Vector3 SnapWeldVector( const Vector3& a, const Vector3& b );
bool CreateBrushWindings( brush_t *brush );
brush_t *BrushFromBounds( const Vector3& mins, const Vector3& maxs );
float BrushVolume( brush_t *brush );
void WriteBSPBrushMap( const char *name, brush_t *list );
bool CreateBrushWindings( brush_t& brush );
brush_t BrushFromBounds( const Vector3& mins, const Vector3& maxs );
float BrushVolume( const brush_t& brush );
void WriteBSPBrushMap( const char *name, const brushlist_t& list );
void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree );
void FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree );
void FilterDetailBrushesIntoTree( entity_t *e, tree_t& tree );
void FilterStructuralBrushesIntoTree( entity_t *e, tree_t& tree );
bool WindingIsTiny( const winding_t& w );
void SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back );
tree_t *AllocTree( void );
node_t *AllocNode( void );
std::pair<brush_t*, brush_t*> SplitBrush( const brush_t& brush, int planenum );
/* mesh.c */
@ -1600,11 +1588,10 @@ inline int FindFloatPlane( const Vector3& normal, float dist, i
}
bool PlaneEqual( const plane_t& p, const Plane3f& plane );
void AddBrushBevels( void );
brush_t *FinishBrush( bool noCollapseGroups );
/* portals.c */
void MakeHeadnodePortals( tree_t *tree );
void MakeHeadnodePortals( tree_t& tree );
void MakeNodePortal( node_t *node );
void SplitNodePortals( node_t *node );
@ -1616,32 +1603,33 @@ enum class EFloodEntities
Good,
Empty
};
EFloodEntities FloodEntities( tree_t *tree );
EFloodEntities FloodEntities( tree_t& tree );
void FillOutside( node_t *headnode );
void FloodAreas( tree_t *tree );
void FreePortal( portal_t *p );
void FloodAreas( tree_t& tree );
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 */
xmlNodePtr LeakFile( tree_t *tree );
xmlNodePtr LeakFile( const tree_t& tree );
/* prtfile.c */
void NumberClusters( tree_t *tree );
void WritePortalFile( tree_t *tree );
void NumberClusters( tree_t& tree );
void WritePortalFile( const tree_t& tree );
/* writebsp.c */
void SetModelNumbers( 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 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 BeginModel( void );
@ -1649,10 +1637,11 @@ void EndModel( entity_t *e, node_t *headnode );
/* tree.c */
void FreeTree( tree_t *tree );
void FreeTree( tree_t& tree );
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 );
inline node_t *AllocNode(){ return new node_t(); }
/* patch.c */
@ -1667,7 +1656,7 @@ void FixTJunctions( entity_t *e );
/* fog.c */
winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds );
winding_t WindingFromDrawSurf( const mapDrawSurface_t *ds );
void FogDrawSurfaces( entity_t *e );
int FogForPoint( const Vector3& point, float epsilon );
int FogForBounds( const MinMax& minmax, float epsilon );
@ -1675,9 +1664,9 @@ void CreateMapFogs( void );
/* facebsp.c */
facelist_t MakeStructuralBSPFaceList( const brush_t *list );
facelist_t MakeVisibleBSPFaceList( const brush_t *list );
tree_t *FaceBSP( facelist_t& list );
facelist_t MakeStructuralBSPFaceList( const brushlist_t& list );
facelist_t MakeVisibleBSPFaceList( const brushlist_t& list );
tree_t FaceBSP( facelist_t& list );
/* 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 );
void ClearSurface( mapDrawSurface_t *ds );
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 *DrawSurfaceForFlare( int entNum, const Vector3& origin, const Vector3& normal, const Vector3& color, const char *flareShader, int lightStyle );
mapDrawSurface_t *DrawSurfaceForShader( const char *shader );
void ClipSidesIntoTree( entity_t *e, tree_t *tree );
void MakeDebugPortalSurfs( tree_t *tree );
void MakeFogHullSurfs( entity_t *e, tree_t *tree, const char *shader );
void SubdivideFaceSurfaces( entity_t *e, tree_t *tree );
void ClipSidesIntoTree( entity_t *e, const tree_t& tree );
void MakeDebugPortalSurfs( const tree_t& tree );
void MakeFogHullSurfs( entity_t *e, const char *shader );
void SubdivideFaceSurfaces( entity_t *e );
void AddEntitySurfaceModels( entity_t *e );
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 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 entity_t *mapEnt;
Q_EXTERN brush_t *buildBrush;
Q_EXTERN brush_t buildBrush;
Q_EXTERN EBrushType g_brushType Q_ASSIGN( EBrushType::Undefined );
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()
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_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;
shaderInfo_t *si, *parent;
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 */
if ( s->culled ) {
if ( s.culled ) {
return NULL;
}
@ -789,24 +790,24 @@ mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, const
}
/* get shader */
si = s->shaderInfo;
si = s.shaderInfo;
/* ydnar: gs mods: check for indexed shader */
if ( si->indexed && b->im != NULL ) {
if ( si->indexed && b.im != NULL ) {
/* indexed */
indexed = true;
/* get shader indexes for each point */
for ( size_t i = 0; i < w.size(); i++ )
{
shaderIndexes[ i ] = GetShaderIndexForPoint( b->im, b->eMinmax, w[ i ] );
offsets[ i ] = b->im->offsets[ shaderIndexes[ i ] ];
shaderIndexes[ i ] = GetShaderIndexForPoint( b.im, b.eMinmax, w[ i ] );
offsets[ i ] = b.im->offsets[ shaderIndexes[ i ] ];
//% Sys_Printf( "%f ", offsets[ i ] );
}
/* get matching shader and set alpha */
parent = si;
si = GetIndexedShader( parent, b->im, w.size(), shaderIndexes );
si = GetIndexedShader( parent, b.im, w.size(), shaderIndexes );
}
else{
indexed = false;
@ -821,25 +822,25 @@ mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, const
/* ydnar: gs mods */
ds = AllocDrawSurface( ESurfaceType::Face );
ds->entityNum = b->entityNum;
ds->castShadows = b->castShadows;
ds->recvShadows = b->recvShadows;
ds->entityNum = b.entityNum;
ds->castShadows = b.castShadows;
ds->recvShadows = b.recvShadows;
ds->planar = true;
ds->planeNum = s->planenum;
ds->lightmapVecs[ 2 ] = mapplanes[ s->planenum ].normal();
ds->planeNum = s.planenum;
ds->lightmapVecs[ 2 ] = mapplanes[ s.planenum ].normal();
ds->shaderInfo = si;
ds->mapBrush = b;
ds->sideRef = AllocSideRef( s, NULL );
ds->mapBrush = &b;
ds->sideRef = AllocSideRef( &s, NULL );
ds->fogNum = -1;
ds->sampleSize = b->lightmapSampleSize;
ds->lightmapScale = b->lightmapScale;
ds->sampleSize = b.lightmapSampleSize;
ds->lightmapScale = b.lightmapScale;
ds->numVerts = w.size();
ds->verts = safe_calloc( ds->numVerts * sizeof( *ds->verts ) );
/* 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 */
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 */
x = vector3_dot( vTranslated, texX );
y = vector3_dot( vTranslated, texY );
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[ 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 ];
}
/* old quake-style or valve 220 texturing */
else {
/* nearest-axial projection */
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[ 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[ 0 ] /= si->shaderWidth;
dv->st[ 1 ] /= si->shaderHeight;
}
/* copy normal */
dv->normal = mapplanes[ s->planenum ].normal();
dv->normal = mapplanes[ s.planenum ].normal();
/* ydnar: set color */
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 */
ds->celShader = b->celShader;
ds->celShader = b.celShader;
/* set shade angle */
if ( b->shadeAngleDegrees > 0.0f ) {
ds->shadeAngleDegrees = b->shadeAngleDegrees;
if ( b.shadeAngleDegrees > 0.0f ) {
ds->shadeAngleDegrees = b.shadeAngleDegrees;
}
/* 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)
*/
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;
MinMax bounds;
const float epsilon = 0.1;
int subFloor, subCeil;
winding_t *frontWinding, *backWinding;
mapDrawSurface_t *ds;
/* dummy check */
if ( w == NULL ) {
if ( w.empty() ) {
return;
}
if ( w->size() < 3 ) {
Error( "SubdivideFace_r: Bad w->numpoints (%zu < 3)", w->size() );
if ( w.size() < 3 ) {
Error( "SubdivideFace_r: Bad w->numpoints (%zu < 3)", w.size() );
}
/* determine surface bounds */
WindingExtendBounds( *w, bounds );
WindingExtendBounds( w, bounds );
/* split the face */
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 */
if ( ( subCeil - subFloor ) > subdivisions ) {
/* 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 */
if ( frontWinding == NULL ) {
w = backWinding;
if ( frontWinding.empty() ) {
w.swap( backWinding );
}
else if ( backWinding == NULL ) {
w = frontWinding;
else if ( backWinding.empty() ) {
w.swap( frontWinding );
}
else
{
@ -1258,7 +1258,7 @@ static void SubdivideFace_r( entity_t *e, brush_t *brush, side_t *side, const wi
}
/* create a face surface */
ds = DrawSurfaceForSide( e, brush, side, *w );
ds = DrawSurfaceForSide( e, brush, side, w );
/* set correct fog num */
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
*/
void SubdivideFaceSurfaces( entity_t *e, tree_t *tree ){
void SubdivideFaceSurfaces( entity_t *e ){
int i, j, numBaseDrawSurfs, fogNum;
mapDrawSurface_t *ds;
brush_t *brush;
side_t *side;
shaderInfo_t *si;
winding_t *w;
float range, size, subdivisions, s2;
@ -1298,11 +1294,11 @@ void SubdivideFaceSurfaces( entity_t *e, tree_t *tree ){
}
/* get bits */
brush = ds->mapBrush;
side = ds->sideRef->side;
const brush_t *brush = ds->mapBrush;
const side_t& side = *ds->sideRef->side;
/* check subdivision for shader */
si = side->shaderInfo;
const shaderInfo_t *si = side.shaderInfo;
if ( si == NULL ) {
continue;
}
@ -1347,11 +1343,11 @@ void SubdivideFaceSurfaces( entity_t *e, tree_t *tree ){
fogNum = ds->fogNum;
/* make a winding and free the surface */
w = WindingFromDrawSurf( ds );
winding_t w = WindingFromDrawSurf( ds );
ClearSurface( ds );
/* 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 ){
winding_t *front, *back;
if ( !w ) {
void ClipSideIntoTree_r( const winding_t& w, side_t& side, const node_t *node ){
if ( w.empty() ) {
return;
}
if ( node->planenum != PLANENUM_LEAF ) {
if ( side->planenum == node->planenum ) {
if ( side.planenum == node->planenum ) {
ClipSideIntoTree_r( w, side, node->children[0] );
return;
}
if ( side->planenum == ( node->planenum ^ 1 ) ) {
if ( side.planenum == ( node->planenum ^ 1 ) ) {
ClipSideIntoTree_r( w, side, node->children[1] );
return;
}
const Plane3f& plane = mapplanes[ node->planenum ].plane;
ClipWindingEpsilonStrict( *w, plane,
ON_EPSILON, front, back ); /* strict, we handle the "winding disappeared" case */
if ( !front && !back ) {
auto [front, back] = ClipWindingEpsilonStrict( w, plane, ON_EPSILON ); /* strict, we handle the "winding disappeared" case */
if ( front.empty() && back.empty() ) {
/* in doubt, register it in both nodes */
front = CopyWinding( w );
back = CopyWinding( w );
ClipSideIntoTree_r( w, side, node->children[0] );
ClipSideIntoTree_r( w, side, node->children[1] );
}
FreeWinding( w );
else{
ClipSideIntoTree_r( front, side, node->children[0] );
ClipSideIntoTree_r( back, side, node->children[1] );
}
return;
}
// if opaque leaf, don't add
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
*/
bool SideInBrush( side_t *side, brush_t *b ){
bool SideInBrush( side_t& side, const brush_t& b ){
/* ignore sides w/o windings or shaders */
if ( side->winding == NULL || side->shaderInfo == NULL ) {
if ( side.winding.empty() || side.shaderInfo == NULL ) {
return true;
}
/* ignore culled sides and translucent brushes */
if ( side->culled || ( b->compileFlags & C_TRANSLUCENT ) ) {
if ( side.culled || ( b.compileFlags & C_TRANSLUCENT ) ) {
return false;
}
/* side iterator */
for ( int i = 0; i < b->numsides; i++ )
for ( const side_t& bside : b.sides )
{
/* fail if any sides are caulk */
if ( b->sides[ i ].compileFlags & C_NODRAW ) {
if ( bside.compileFlags & C_NODRAW ) {
return false;
}
/* check if side's winding is on or behind the plane */
const Plane3f& plane = mapplanes[ b->sides[ i ].planenum ].plane;
const EPlaneSide s = WindingOnPlaneSide( *side->winding, plane );
const Plane3f& plane = mapplanes[ bside.planenum ].plane;
const EPlaneSide s = WindingOnPlaneSide( side.winding, plane );
if ( s == eSideFront || s == eSideCross ) {
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;
}
/* 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;
}
}
/* inside */
side->culled = true;
side.culled = true;
g_numHiddenFaces++;
return true;
}
@ -1471,11 +1459,7 @@ bool SideInBrush( side_t *side, brush_t *b ){
*/
void CullSides( entity_t *e ){
int numPoints;
int i, j, k, l, first, second, dir;
const winding_t *w1, *w2;
brush_t *b1, *b2;
side_t *side1, *side2;
int k, l, first, second, dir;
/* note it */
@ -1485,18 +1469,18 @@ void CullSides( entity_t *e ){
g_numCoinFaces = 0;
/* 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 */
if ( b1->numsides < 1 ) {
if ( b1->sides.empty() ) {
continue;
}
/* 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 */
if ( b2->numsides < 1 ) {
if ( b2->sides.empty() ) {
continue;
}
@ -1511,56 +1495,52 @@ void CullSides( entity_t *e ){
}
/* cull inside sides */
for ( i = 0; i < b1->numsides; i++ )
SideInBrush( &b1->sides[ i ], b2 );
for ( i = 0; i < b2->numsides; i++ )
SideInBrush( &b2->sides[ i ], b1 );
for ( side_t& side : b1->sides )
SideInBrush( side, *b2 );
for ( side_t& side : b2->sides )
SideInBrush( side, *b1 );
/* side iterator 1 */
for ( i = 0; i < b1->numsides; i++ )
for ( side_t& side1 : b1->sides )
{
/* winding check */
side1 = &b1->sides[ i ];
w1 = side1->winding;
if ( w1 == NULL ) {
winding_t& w1 = side1.winding;
if ( w1.empty() ) {
continue;
}
numPoints = w1->size();
if ( side1->shaderInfo == NULL ) {
const int numPoints = w1.size();
if ( side1.shaderInfo == NULL ) {
continue;
}
/* side iterator 2 */
for ( j = 0; j < b2->numsides; j++ )
for ( side_t& side2 : b2->sides )
{
/* winding check */
side2 = &b2->sides[ j ];
w2 = side2->winding;
if ( w2 == NULL ) {
winding_t& w2 = side2.winding;
if ( w2.empty() ) {
continue;
}
if ( side2->shaderInfo == NULL ) {
if ( side2.shaderInfo == NULL ) {
continue;
}
if ( w1->size() != w2->size() ) {
if ( w1.size() != w2.size() ) {
continue;
}
if ( side1->culled && side2->culled ) {
if ( side1.culled && side2.culled ) {
continue;
}
/* compare planes */
if ( ( side1->planenum & ~0x00000001 ) != ( side2->planenum & ~0x00000001 ) ) {
if ( ( side1.planenum & ~0x00000001 ) != ( side2.planenum & ~0x00000001 ) ) {
continue;
}
/* get autosprite and polygonoffset status */
if ( side1->shaderInfo &&
( side1->shaderInfo->autosprite || side1->shaderInfo->polygonOffset ) ) {
if ( side1.shaderInfo->autosprite || side1.shaderInfo->polygonOffset ) {
continue;
}
if ( side2->shaderInfo &&
( side2->shaderInfo->autosprite || side2->shaderInfo->polygonOffset ) ) {
if ( side2.shaderInfo->autosprite || side2.shaderInfo->polygonOffset ) {
continue;
}
@ -1568,7 +1548,7 @@ void CullSides( entity_t *e ){
first = -1;
for ( k = 0; k < numPoints; k++ )
{
if ( VectorCompare( ( *w1 )[ 0 ], ( *w2 )[ k ] ) ) {
if ( VectorCompare( w1[ 0 ], w2[ k ] ) ) {
first = k;
break;
}
@ -1586,7 +1566,7 @@ void CullSides( entity_t *e ){
else{
second = 0;
}
if ( vector3_equal_epsilon( ( *w1 )[ 1 ], ( *w2 )[ second ], CULL_EPSILON ) ) {
if ( vector3_equal_epsilon( w1[ 1 ], w2[ second ], CULL_EPSILON ) ) {
dir = 1;
}
else
@ -1597,7 +1577,7 @@ void CullSides( entity_t *e ){
else{
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;
}
}
@ -1609,7 +1589,7 @@ void CullSides( entity_t *e ){
l = first;
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;
}
@ -1626,18 +1606,18 @@ void CullSides( entity_t *e ){
}
/* cull face 1 */
if ( !side2->culled && !( side2->compileFlags & C_TRANSLUCENT ) && !( side2->compileFlags & C_NODRAW ) ) {
side1->culled = true;
if ( !side2.culled && !( side2.compileFlags & C_TRANSLUCENT ) && !( side2.compileFlags & C_NODRAW ) ) {
side1.culled = true;
g_numCoinFaces++;
}
if ( side1->planenum == side2->planenum && side1->culled ) {
if ( side1.planenum == side2.planenum && side1.culled ) {
continue;
}
/* cull face 2 */
if ( !side1->culled && !( side1->compileFlags & C_TRANSLUCENT ) && !( side1->compileFlags & C_NODRAW ) ) {
side2->culled = true;
if ( !side1.culled && !( side1.compileFlags & C_TRANSLUCENT ) && !( side1.compileFlags & C_NODRAW ) ) {
side2.culled = true;
g_numCoinFaces++;
}
@ -1665,14 +1645,7 @@ void CullSides( entity_t *e ){
to be trimmed off automatically.
*/
void ClipSidesIntoTree( entity_t *e, tree_t *tree ){
brush_t *b;
int i;
winding_t *w;
side_t *side, *newSide;
shaderInfo_t *si;
void ClipSidesIntoTree( entity_t *e, const tree_t& tree ){
/* ydnar: cull brush sides */
CullSides( e );
@ -1680,30 +1653,25 @@ void ClipSidesIntoTree( entity_t *e, tree_t *tree ){
Sys_FPrintf( SYS_VRB, "--- ClipSidesIntoTree ---\n" );
/* walk the brush list */
for ( b = e->brushes; b; b = b->next )
for ( brush_t& b : e->brushes )
{
/* walk the brush sides */
for ( i = 0; i < b->numsides; i++ )
for ( side_t& side : b.sides )
{
/* get side */
side = &b->sides[ i ];
if ( side->winding == NULL ) {
if ( side.winding.empty() ) {
continue;
}
/* copy the winding */
w = CopyWinding( side->winding );
side->visibleHull = NULL;
ClipSideIntoTree_r( w, side, tree->headnode );
side.visibleHull.clear();
ClipSideIntoTree_r( side.winding, side, tree.headnode );
/* anything left? */
w = side->visibleHull;
if ( w == NULL ) {
if ( side.visibleHull.empty() ) {
continue;
}
/* shader? */
si = side->shaderInfo;
const shaderInfo_t *si = side.shaderInfo;
if ( si == NULL ) {
continue;
}
@ -1715,27 +1683,21 @@ void ClipSidesIntoTree( entity_t *e, tree_t *tree ){
}
/* always use the original winding for autosprites and noclip faces */
if ( si->autosprite || si->noClip ) {
w = side->winding;
}
const winding_t& w = ( si->autosprite || si->noClip )? side.winding : side.visibleHull;
/* save this winding as a visible surface */
DrawSurfaceForSide( e, b, side, *w );
DrawSurfaceForSide( e, b, side, w );
/* make a back side for fog */
if ( !( si->compileFlags & C_FOG ) ) {
continue;
}
if ( si->compileFlags & C_FOG ) {
/* duplicate the up-facing side */
w = ReverseWinding( *w );
newSide = safe_malloc( sizeof( *side ) );
*newSide = *side;
newSide->visibleHull = w;
newSide->planenum ^= 1;
side_t& newSide = *new side_t( side );
newSide.visibleHull = ReverseWinding( w );
newSide.planenum ^= 1;
/* save this winding as a visible surface */
DrawSurfaceForSide( e, b, newSide, *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
*/
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;
winding_t *fat, *front, *back;
shaderInfo_t *si;
/* get shaderinfo */
si = ds->shaderInfo;
const shaderInfo_t *si = ds->shaderInfo;
/* ydnar: is this the head node? */
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) */
/* note this winding is completely invalid (concave, nonplanar, etc) */
fat = AllocWinding( w->size() * 3 + 3 );
fat->resize( w->size() * 3 + 3 );
for ( size_t i = 0; i < w->size(); i++ )
winding_t fat( w.size() * 3 + 3 );
for ( size_t i = 0; i < w.size(); i++ )
{
( *fat )[ i ] = ( *w )[ i ];
( *fat )[ i + ( w->size() + 1 ) ] = ( *w )[ i ] + si->minmax.mins;
( *fat )[ i + ( w->size() + 1 ) * 2 ] = ( *w )[ i ] + si->minmax.maxs;
fat[ i ] = w[ i ];
fat[ i + ( w.size() + 1 ) ] = w[ i ] + si->minmax.mins;
fat[ i + ( w.size() + 1 ) * 2 ] = w[ i ] + si->minmax.maxs;
}
( *fat )[ w->size() ] = ( *w )[ 0 ];
( *fat )[ w->size() * 2 ] = ( *w )[ 0 ] + si->minmax.mins;
( *fat )[ w->size() * 3 ] = ( *w )[ 0 ] + si->minmax.maxs;
fat[ w.size() ] = w[ 0 ];
fat[ w.size() * 2 ] = w[ 0 ] + si->minmax.mins;
fat[ w.size() * 3 ] = w[ 0 ] + si->minmax.maxs;
/*
* 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
*/
FreeWinding( w );
w = fat;
w.swap( fat );
}
/* 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 */
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 */
refs = 0;
if ( front == NULL && back == NULL ) {
if ( front.empty() && back.empty() ) {
/* same plane, this is an ugly hack */
/* but better too many than too few refs */
refs += FilterWindingIntoTree_r( CopyWinding( w ), ds, node->children[ 0 ] );
refs += FilterWindingIntoTree_r( CopyWinding( w ), ds, node->children[ 1 ] );
winding_t wcopy( w );
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 ] );
}
if ( back != NULL ) {
if ( !back.empty() ) {
refs += FilterWindingIntoTree_r( back, ds, node->children[ 1 ] );
}
FreeWinding( w );
/* return */
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
*/
int FilterFaceIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
winding_t *w;
int refs = 0;
int FilterFaceIntoTree( mapDrawSurface_t *ds, tree_t& tree ){
/* make a winding and filter it into the tree */
w = WindingFromDrawSurf( ds );
refs = FilterWindingIntoTree_r( w, ds, tree->headnode );
winding_t w = WindingFromDrawSurf( ds );
int refs = FilterWindingIntoTree_r( w, ds, tree.headnode );
/* return */
return refs;
@ -2044,7 +1997,7 @@ int FilterFaceIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
#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;
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[7] = &ds->verts[( y + 2 ) * ds->patchWidth + ( x + 1 )].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;
@ -2073,9 +2026,8 @@ static int FilterPatchIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
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;
winding_t *w;
/* 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 */
w = AllocWinding( 3 );
w->push_back( ds->verts[ ds->indexes[ i ] ].xyz );
w->push_back( ds->verts[ ds->indexes[ i + 1 ] ].xyz );
w->push_back( ds->verts[ ds->indexes[ i + 2 ] ].xyz );
refs += FilterWindingIntoTree_r( w, ds, tree->headnode );
winding_t w{
ds->verts[ ds->indexes[ i ] ].xyz,
ds->verts[ ds->indexes[ i + 1 ] ].xyz,
ds->verts[ ds->indexes[ i + 2 ] ].xyz };
refs += FilterWindingIntoTree_r( w, ds, tree.headnode );
}
/* use point filtering as well */
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;
}
@ -2111,10 +2063,9 @@ static int FilterTrianglesIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
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;
bspDrawVert_t *instance;
winding_t *w;
/* 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 */
w = AllocWinding( 3 );
w->push_back( instance->xyz + ds->verts[ ds->indexes[ i ] ].xyz );
w->push_back( instance->xyz + ds->verts[ ds->indexes[ i + 1 ] ].xyz );
w->push_back( instance->xyz + ds->verts[ ds->indexes[ i + 2 ] ].xyz );
refs += FilterWindingIntoTree_r( w, ds, tree->headnode );
winding_t w{
instance->xyz + ds->verts[ ds->indexes[ i ] ].xyz,
instance->xyz + ds->verts[ ds->indexes[ i + 1 ] ].xyz,
instance->xyz + ds->verts[ ds->indexes[ i + 2 ] ].xyz };
refs += FilterWindingIntoTree_r( w, ds, tree.headnode );
}
/* use point filtering as well */
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()
simple point filtering for flare surfaces
*/
static int FilterFlareSurfIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
return FilterPointIntoTree_r( ds->lightmapOrigin, ds, tree->headnode );
static int FilterFlareSurfIntoTree( mapDrawSurface_t *ds, tree_t& tree ){
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
*/
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;
portal_t *p;
winding_t *w;
const portal_t *p;
mapDrawSurface_t *ds;
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 ] )
{
/* get winding and side even/odd */
w = p->winding;
const winding_t& w = p->winding;
s = ( p->nodes[ 1 ] == node );
/* 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? */
if ( !PortalPassable( p ) ) {
continue;
}
/* check max points */
if ( w->size() > 64 ) {
Error( "MakePortalSurfs_r: w->numpoints = %zu", w->size() );
if ( w.size() > 64 ) {
Error( "MakePortalSurfs_r: w->numpoints = %zu", w.size() );
}
/* allocate a drawsurface */
ds = AllocDrawSurface( ESurfaceType::Face );
ds->shaderInfo = si;
ds->planar = true;
ds->sideRef = AllocSideRef( p->side, NULL );
ds->planeNum = FindFloatPlane( p->plane.plane, 0, NULL );
ds->lightmapVecs[ 2 ] = p->plane.normal();
ds->fogNum = -1;
ds->numVerts = w->size();
ds->numVerts = w.size();
ds->verts = safe_calloc( ds->numVerts * sizeof( *ds->verts ) );
/* walk the winding */
@ -2798,7 +2747,7 @@ static void MakeDebugPortalSurfs_r( node_t *node, shaderInfo_t *si ){
dv = ds->verts + i;
/* set it */
dv->xyz = ( *w )[ i ];
dv->xyz = w[ i ];
dv->normal = p->plane.normal();
dv->st = { 0, 0 };
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
*/
void MakeDebugPortalSurfs( tree_t *tree ){
void MakeDebugPortalSurfs( const tree_t& tree ){
shaderInfo_t *si;
@ -2829,7 +2778,7 @@ void MakeDebugPortalSurfs( tree_t *tree ){
si = ShaderInfoForShader( "debugportals" );
/* 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)
*/
void MakeFogHullSurfs( entity_t *e, tree_t *tree, const char *shader ){
void MakeFogHullSurfs( entity_t *e, const char *shader ){
shaderInfo_t *si;
mapDrawSurface_t *ds;
int indexes[] =
@ -3231,17 +3180,8 @@ void AddEntitySurfaceModels( entity_t *e ){
*/
static void VolumeColorMods( entity_t *e, mapDrawSurface_t *ds ){
int i, j;
brush_t *b;
/* early out */
if ( e->colorModBrushes == NULL ) {
return;
}
/* 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 */
if ( b->entityNum != 0 && b->entityNum != ds->entityNum ) {
@ -3254,10 +3194,11 @@ static void VolumeColorMods( entity_t *e, mapDrawSurface_t *ds ){
}
/* iterate verts */
for ( i = 0; i < ds->numVerts; i++ )
for ( int i = 0; i < ds->numVerts; i++ )
{
/* iterate planes */
for ( j = 0; j < b->numsides; j++ )
size_t j;
for ( j = 0; j < b->sides.size(); j++ )
{
/* point-plane test */
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 */
if ( j == b->numsides ) {
if ( j == b->sides.size() ) {
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
*/
void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree ){
void FilterDrawsurfsIntoTree( entity_t *e, tree_t& tree ){
int i, j;
mapDrawSurface_t *ds;
shaderInfo_t *si;
@ -3311,7 +3252,7 @@ void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree ){
/* ydnar: skybox surfaces are special */
if ( ds->skybox ) {
refs = AddReferenceToTree_r( ds, tree->headnode, true );
refs = AddReferenceToTree_r( ds, tree.headnode, true );
ds->skybox = false;
sb = true;
}
@ -3421,7 +3362,7 @@ void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree ){
/* handle foghull surfaces */
case ESurfaceType::Foghull:
if ( refs == 0 ) {
refs = AddReferenceToTree_r( ds, tree->headnode, false );
refs = AddReferenceToTree_r( ds, tree.headnode, false );
}
if ( refs > 0 ) {
EmitTriangleSurface( ds );

View File

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

View File

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