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;
float BrushVolume( const brush_t& brush ){
float volume = 0;
if ( !brush ) {
return 0;
}
// grab the first valid point as the corner
w = NULL;
for ( i = 0 ; i < brush->numsides ; i++ )
{
w = brush->sides[i].winding;
if ( w ) {
for ( auto i = brush.sides.cbegin(); i != brush.sides.cend(); ++i ){
// grab the first valid point as the corner
if( !i->winding.empty() ){
const Vector3 corner = i->winding[0];
// make tetrahedrons to all other faces
for ( ++i; i != brush.sides.cend(); ++i )
{
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,24 +606,21 @@ bool WindingIsHuge( const winding_t& w ){
==================
*/
int BrushMostlyOnSide( brush_t *brush, plane_t *plane ){
int BrushMostlyOnSide( const brush_t& brush, const Plane3f& plane ){
float max = 0;
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 )
{
const double d = plane3_distance_to_point( plane->plane, p );
if ( d > max ) {
max = d;
side = PSIDE_FRONT;
}
if ( -d > max ) {
max = -d;
side = PSIDE_BACK;
}
for ( const Vector3& p : s.winding )
{
const double d = plane3_distance_to_point( plane, p );
if ( d > max ) {
max = d;
side = PSIDE_FRONT;
}
if ( -d > max ) {
max = -d;
side = PSIDE_BACK;
}
}
}
@ -807,30 +634,16 @@ int BrushMostlyOnSide( brush_t *brush, plane_t *plane ){
generates two new brushes, leaving the original unchanged
*/
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 ( !cw[j] ) {
continue;
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[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] );
b[i] = NULL;
// Sys_FPrintf( SYS_WRN | SYS_VRBflag, "tiny volume after clip\n" );
}
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 );

File diff suppressed because it is too large Load Diff

View File

@ -718,13 +718,12 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor
if ( PlaneFromPoints( plane, points ) ) {
/* 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] );
}
else{
ClipSideIntoTree_r( front, side, node->children[0] );
ClipSideIntoTree_r( back, side, node->children[1] );
}
FreeWinding( w );
ClipSideIntoTree_r( front, side, node->children[0] );
ClipSideIntoTree_r( back, side, node->children[1] );
return;
}
// 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 ) {
return false;
}
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 */
side_t& newSide = *new side_t( side );
newSide.visibleHull = ReverseWinding( w );
newSide.planenum ^= 1;
/* save this winding as a visible surface */
DrawSurfaceForSide( e, b, newSide, newSide.visibleHull ); // references new side by sideref, leak!
}
/* duplicate the up-facing side */
w = ReverseWinding( *w );
newSide = safe_malloc( sizeof( *side ) );
*newSide = *side;
newSide->visibleHull = w;
newSide->planenum ^= 1;
/* save this winding as a visible surface */
DrawSurfaceForSide( e, b, newSide, *w );
}
}
}
@ -1910,14 +1872,11 @@ int FilterPointConvexHullIntoTree_r( Vector3 *points[], const int npoints, mapDr
filters a winding from a drawsurface into the tree
*/
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 );
}
}