more c++ in q3map2
This commit is contained in:
parent
99f4a4a767
commit
f492ab27eb
|
|
@ -40,16 +40,7 @@ void pw( const winding_t& w ){
|
||||||
AllocWinding
|
AllocWinding
|
||||||
=============
|
=============
|
||||||
*/
|
*/
|
||||||
winding_t *AllocWinding( int points ){
|
winding_t AllocWinding( int points ){
|
||||||
if ( points >= MAX_POINTS_ON_WINDING ) {
|
|
||||||
Error( "AllocWinding failed: MAX_POINTS_ON_WINDING exceeded" );
|
|
||||||
}
|
|
||||||
winding_t *w = new winding_t;
|
|
||||||
w->reserve( points );
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
|
|
||||||
winding_t AllocWinding_( int points ){
|
|
||||||
if ( points >= MAX_POINTS_ON_WINDING ) {
|
if ( points >= MAX_POINTS_ON_WINDING ) {
|
||||||
Error( "AllocWinding failed: MAX_POINTS_ON_WINDING exceeded" );
|
Error( "AllocWinding failed: MAX_POINTS_ON_WINDING exceeded" );
|
||||||
}
|
}
|
||||||
|
|
@ -58,18 +49,6 @@ winding_t AllocWinding_( int points ){
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
=============
|
|
||||||
FreeWinding
|
|
||||||
=============
|
|
||||||
*/
|
|
||||||
void FreeWinding( winding_t *w ){
|
|
||||||
if ( !w ) {
|
|
||||||
Error( "FreeWinding: winding is NULL" );
|
|
||||||
}
|
|
||||||
delete w;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
============
|
============
|
||||||
RemoveColinearPoints
|
RemoveColinearPoints
|
||||||
|
|
@ -255,7 +234,7 @@ winding_accu_t BaseWindingForPlaneAccu( const Plane3& plane ){
|
||||||
error, and can lead to all sorts of disappearing triangle problems.
|
error, and can lead to all sorts of disappearing triangle problems.
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
winding_t *BaseWindingForPlane( const Plane3f& plane ){
|
winding_t BaseWindingForPlane( const Plane3f& plane ){
|
||||||
int i, x;
|
int i, x;
|
||||||
float max, v;
|
float max, v;
|
||||||
Vector3 org, vright, vup;
|
Vector3 org, vright, vup;
|
||||||
|
|
@ -302,7 +281,7 @@ winding_t *BaseWindingForPlane( const Plane3f& plane ){
|
||||||
vright *= MAX_WORLD_COORD * 2;
|
vright *= MAX_WORLD_COORD * 2;
|
||||||
|
|
||||||
// project a really big axis aligned box onto the plane
|
// project a really big axis aligned box onto the plane
|
||||||
return new winding_t{
|
return winding_t{
|
||||||
org - vright + vup,
|
org - vright + vup,
|
||||||
org + vright + vup,
|
org + vright + vup,
|
||||||
org + vright - vup,
|
org + vright - vup,
|
||||||
|
|
@ -310,25 +289,13 @@ winding_t *BaseWindingForPlane( const Plane3f& plane ){
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
==================
|
|
||||||
CopyWinding
|
|
||||||
==================
|
|
||||||
*/
|
|
||||||
winding_t *CopyWinding( const winding_t *w ){
|
|
||||||
if ( !w ) {
|
|
||||||
Error( "CopyWinding: winding is NULL" );
|
|
||||||
}
|
|
||||||
return new winding_t( *w );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==================
|
==================
|
||||||
CopyWindingAccuToRegular
|
CopyWindingAccuToRegular
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
winding_t *CopyWindingAccuToRegular( const winding_accu_t& w ){
|
winding_t CopyWindingAccuToRegular( const winding_accu_t& w ){
|
||||||
return new winding_t( w.begin(), w.end() );
|
return winding_t( w.begin(), w.end() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -336,8 +303,8 @@ winding_t *CopyWindingAccuToRegular( const winding_accu_t& w ){
|
||||||
ReverseWinding
|
ReverseWinding
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
winding_t *ReverseWinding( const winding_t& w ){
|
winding_t ReverseWinding( const winding_t& w ){
|
||||||
return new winding_t( w.crbegin(), w.crend() );
|
return winding_t( w.crbegin(), w.crend() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -346,8 +313,7 @@ winding_t *ReverseWinding( const winding_t& w ){
|
||||||
ClipWindingEpsilon
|
ClipWindingEpsilon
|
||||||
=============
|
=============
|
||||||
*/
|
*/
|
||||||
void ClipWindingEpsilonStrict( const winding_t& in, const Plane3f& plane,
|
std::pair<winding_t, winding_t> ClipWindingEpsilonStrict( const winding_t& in, const Plane3f& plane, float epsilon ){
|
||||||
float epsilon, winding_t *&front, winding_t *&back ){
|
|
||||||
float dists[MAX_POINTS_ON_WINDING + 4];
|
float dists[MAX_POINTS_ON_WINDING + 4];
|
||||||
EPlaneSide sides[MAX_POINTS_ON_WINDING + 4];
|
EPlaneSide sides[MAX_POINTS_ON_WINDING + 4];
|
||||||
int counts[3] = { 0 };
|
int counts[3] = { 0 };
|
||||||
|
|
@ -373,41 +339,37 @@ void ClipWindingEpsilonStrict( const winding_t& in, const Plane3f& plane,
|
||||||
sides[i] = sides[0];
|
sides[i] = sides[0];
|
||||||
dists[i] = dists[0];
|
dists[i] = dists[0];
|
||||||
|
|
||||||
front = back = NULL;
|
|
||||||
|
|
||||||
if ( !counts[eSideFront] && !counts[eSideBack] ) {
|
if ( !counts[eSideFront] && !counts[eSideBack] ) {
|
||||||
return;
|
return {};
|
||||||
}
|
}
|
||||||
if ( !counts[eSideFront] ) {
|
if ( !counts[eSideFront] ) {
|
||||||
back = CopyWinding( &in );
|
return { {}, in };
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if ( !counts[eSideBack] ) {
|
if ( !counts[eSideBack] ) {
|
||||||
front = CopyWinding( &in );
|
return { in, {} };
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t maxpts = in.size() + 4; // cant use counts[0]+2 because
|
const size_t maxpts = in.size() + 4; // cant use counts[0]+2 because
|
||||||
// of fp grouping errors
|
// of fp grouping errors
|
||||||
|
|
||||||
front = AllocWinding( maxpts );
|
winding_t front = AllocWinding( maxpts );
|
||||||
back = AllocWinding( maxpts );
|
winding_t back = AllocWinding( maxpts );
|
||||||
|
|
||||||
for ( i = 0 ; i < in.size() ; i++ )
|
for ( i = 0; i < in.size(); i++ )
|
||||||
{
|
{
|
||||||
const Vector3& p1 = in[i];
|
const Vector3& p1 = in[i];
|
||||||
|
|
||||||
if ( sides[i] == eSideOn ) {
|
if ( sides[i] == eSideOn ) {
|
||||||
front->push_back( p1 );
|
front.push_back( p1 );
|
||||||
back->push_back( p1 );
|
back.push_back( p1 );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( sides[i] == eSideFront ) {
|
if ( sides[i] == eSideFront ) {
|
||||||
front->push_back( p1 );
|
front.push_back( p1 );
|
||||||
}
|
}
|
||||||
if ( sides[i] == eSideBack ) {
|
if ( sides[i] == eSideBack ) {
|
||||||
back->push_back( p1 );
|
back.push_back( p1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( sides[i + 1] == eSideOn || sides[i + 1] == sides[i] ) {
|
if ( sides[i + 1] == eSideOn || sides[i + 1] == sides[i] ) {
|
||||||
|
|
@ -431,22 +393,24 @@ void ClipWindingEpsilonStrict( const winding_t& in, const Plane3f& plane,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
front->push_back( mid );
|
front.push_back( mid );
|
||||||
back->push_back( mid );
|
back.push_back( mid );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( front->size() > MAX_POINTS_ON_WINDING || back->size() > MAX_POINTS_ON_WINDING ) {
|
if ( front.size() > MAX_POINTS_ON_WINDING || back.size() > MAX_POINTS_ON_WINDING ) {
|
||||||
Error( "ClipWinding: MAX_POINTS_ON_WINDING" );
|
Error( "ClipWinding: MAX_POINTS_ON_WINDING" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return { front, back };
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClipWindingEpsilon( const winding_t& in, const Plane3f& plane,
|
std::pair<winding_t, winding_t> ClipWindingEpsilon( const winding_t& in, const Plane3f& plane, float epsilon ){
|
||||||
float epsilon, winding_t *&front, winding_t *&back ){
|
auto [front, back] = ClipWindingEpsilonStrict( in, plane, epsilon );
|
||||||
ClipWindingEpsilonStrict( in, plane, epsilon, front, back );
|
|
||||||
/* apparently most code expects that in the winding-on-plane case, the back winding is the original winding */
|
/* apparently most code expects that in the winding-on-plane case, the back winding is the original winding */
|
||||||
if ( !front && !back ) {
|
if ( front.empty() && back.empty() ) {
|
||||||
back = CopyWinding( &in );
|
back = in;
|
||||||
}
|
}
|
||||||
|
return { front, back };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -587,8 +551,8 @@ void ChopWindingInPlaceAccu( winding_accu_t& inout, const Plane3& plane, float c
|
||||||
ChopWindingInPlace
|
ChopWindingInPlace
|
||||||
=============
|
=============
|
||||||
*/
|
*/
|
||||||
void ChopWindingInPlace( winding_t *&inout, const Plane3f& plane, float epsilon ){
|
void ChopWindingInPlace( winding_t& inout, const Plane3f& plane, float epsilon ){
|
||||||
winding_t& in = *inout;
|
const winding_t& in = inout;
|
||||||
float dists[MAX_POINTS_ON_WINDING + 4];
|
float dists[MAX_POINTS_ON_WINDING + 4];
|
||||||
EPlaneSide sides[MAX_POINTS_ON_WINDING + 4];
|
EPlaneSide sides[MAX_POINTS_ON_WINDING + 4];
|
||||||
int counts[3] = { 0 };
|
int counts[3] = { 0 };
|
||||||
|
|
@ -614,8 +578,7 @@ void ChopWindingInPlace( winding_t *&inout, const Plane3f& plane, float epsilon
|
||||||
dists[i] = dists[0];
|
dists[i] = dists[0];
|
||||||
|
|
||||||
if ( !counts[eSideFront] ) {
|
if ( !counts[eSideFront] ) {
|
||||||
FreeWinding( inout );
|
inout.clear();
|
||||||
inout = NULL;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( !counts[eSideBack] ) {
|
if ( !counts[eSideBack] ) {
|
||||||
|
|
@ -668,27 +631,7 @@ void ChopWindingInPlace( winding_t *&inout, const Plane3f& plane, float epsilon
|
||||||
Error( "ClipWinding: MAX_POINTS_ON_WINDING" );
|
Error( "ClipWinding: MAX_POINTS_ON_WINDING" );
|
||||||
}
|
}
|
||||||
|
|
||||||
inout->swap( f );
|
inout.swap( f );
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
ChopWinding
|
|
||||||
|
|
||||||
Returns the fragment of in that is on the front side
|
|
||||||
of the cliping plane. The original is freed.
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
winding_t *ChopWinding( winding_t *in, const Plane3f& plane ){
|
|
||||||
winding_t *f, *b;
|
|
||||||
|
|
||||||
ClipWindingEpsilon( *in, plane, ON_EPSILON, f, b );
|
|
||||||
FreeWinding( in );
|
|
||||||
if ( b ) {
|
|
||||||
FreeWinding( b );
|
|
||||||
}
|
|
||||||
return f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -794,7 +737,7 @@ EPlaneSide WindingOnPlaneSide( const winding_t& w, const Plane3f& plane ){
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
#define MAX_HULL_POINTS 128
|
#define MAX_HULL_POINTS 128
|
||||||
void AddWindingToConvexHull( const winding_t& w, winding_t *&hull, const Vector3& normal ) {
|
void AddWindingToConvexHull( const winding_t& w, winding_t& hull, const Vector3& normal ) {
|
||||||
int j, k;
|
int j, k;
|
||||||
int numHullPoints, numNew;
|
int numHullPoints, numNew;
|
||||||
Vector3 hullPoints[MAX_HULL_POINTS];
|
Vector3 hullPoints[MAX_HULL_POINTS];
|
||||||
|
|
@ -803,13 +746,13 @@ void AddWindingToConvexHull( const winding_t& w, winding_t *&hull, const Vect
|
||||||
bool hullSide[MAX_HULL_POINTS];
|
bool hullSide[MAX_HULL_POINTS];
|
||||||
bool outside;
|
bool outside;
|
||||||
|
|
||||||
if ( hull == nullptr ) {
|
if ( hull.empty() ) {
|
||||||
hull = CopyWinding( &w );
|
hull = w;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
numHullPoints = hull->size();
|
numHullPoints = hull.size();
|
||||||
memcpy( hullPoints, hull->data(), numHullPoints * sizeof( Vector3 ) );
|
memcpy( hullPoints, hull.data(), numHullPoints * sizeof( Vector3 ) );
|
||||||
|
|
||||||
for ( const Vector3 &p : w ) {
|
for ( const Vector3 &p : w ) {
|
||||||
// calculate hull side vectors
|
// calculate hull side vectors
|
||||||
|
|
@ -861,5 +804,5 @@ void AddWindingToConvexHull( const winding_t& w, winding_t *&hull, const Vect
|
||||||
memcpy( hullPoints, newHullPoints, numHullPoints * sizeof( Vector3 ) );
|
memcpy( hullPoints, newHullPoints, numHullPoints * sizeof( Vector3 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
*hull = winding_t( hullPoints, hullPoints + numHullPoints );
|
hull = winding_t( hullPoints, hullPoints + numHullPoints );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,28 +40,22 @@ enum EPlaneSide
|
||||||
eSideCross = 3,
|
eSideCross = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
winding_t *AllocWinding( int points );
|
winding_t AllocWinding( int points );
|
||||||
winding_t AllocWinding_( int points );
|
|
||||||
float WindingArea( const winding_t& w );
|
float WindingArea( const winding_t& w );
|
||||||
Vector3 WindingCenter( const winding_t& w );
|
Vector3 WindingCenter( const winding_t& w );
|
||||||
void ClipWindingEpsilon( const winding_t& in, const Plane3f& plane,
|
std::pair<winding_t, winding_t> ClipWindingEpsilon( const winding_t& in, const Plane3f& plane, float epsilon ); // returns { front, back } windings pair
|
||||||
float epsilon, winding_t *&front, winding_t *&back );
|
std::pair<winding_t, winding_t> ClipWindingEpsilonStrict( const winding_t& in, const Plane3f& plane, float epsilon ); // returns { front, back } windings pair
|
||||||
void ClipWindingEpsilonStrict( const winding_t& in, const Plane3f& plane,
|
winding_t ReverseWinding( const winding_t& w );
|
||||||
float epsilon, winding_t *&front, winding_t *&back );
|
winding_t BaseWindingForPlane( const Plane3f& plane );
|
||||||
winding_t *ChopWinding( winding_t *in, const Plane3f& plane );
|
|
||||||
winding_t *CopyWinding( const winding_t *w );
|
|
||||||
winding_t *ReverseWinding( const winding_t& w );
|
|
||||||
winding_t *BaseWindingForPlane( const Plane3f& plane );
|
|
||||||
void CheckWinding( const winding_t& w );
|
void CheckWinding( const winding_t& w );
|
||||||
Plane3f WindingPlane( const winding_t& w );
|
Plane3f WindingPlane( const winding_t& w );
|
||||||
void RemoveColinearPoints( winding_t& w );
|
void RemoveColinearPoints( winding_t& w );
|
||||||
EPlaneSide WindingOnPlaneSide( const winding_t& w, const Plane3f& plane );
|
EPlaneSide WindingOnPlaneSide( const winding_t& w, const Plane3f& plane );
|
||||||
void FreeWinding( winding_t *w );
|
|
||||||
void WindingExtendBounds( const winding_t& w, MinMax& minmax );
|
void WindingExtendBounds( const winding_t& w, MinMax& minmax );
|
||||||
|
|
||||||
void AddWindingToConvexHull( const winding_t& w, winding_t *&hull, const Vector3& normal );
|
void AddWindingToConvexHull( const winding_t& w, winding_t& hull, const Vector3& normal );
|
||||||
|
|
||||||
void ChopWindingInPlace( winding_t *&w, const Plane3f& plane, float epsilon );
|
void ChopWindingInPlace( winding_t& w, const Plane3f& plane, float epsilon );
|
||||||
// frees the original if clipped
|
// frees the original if clipped
|
||||||
|
|
||||||
void pw( const winding_t& w );
|
void pw( const winding_t& w );
|
||||||
|
|
@ -76,4 +70,4 @@ using winding_accu_t = std::vector<DoubleVector3>;
|
||||||
|
|
||||||
winding_accu_t BaseWindingForPlaneAccu( const Plane3& plane );
|
winding_accu_t BaseWindingForPlaneAccu( const Plane3& plane );
|
||||||
void ChopWindingInPlaceAccu( winding_accu_t& w, const Plane3& plane, float epsilon );
|
void ChopWindingInPlaceAccu( winding_accu_t& w, const Plane3& plane, float epsilon );
|
||||||
winding_t *CopyWindingAccuToRegular( const winding_accu_t& w );
|
winding_t CopyWindingAccuToRegular( const winding_accu_t& w );
|
||||||
|
|
|
||||||
|
|
@ -44,17 +44,14 @@
|
||||||
allocates and assigns a brush side reference
|
allocates and assigns a brush side reference
|
||||||
*/
|
*/
|
||||||
|
|
||||||
sideRef_t *AllocSideRef( side_t *side, sideRef_t *next ){
|
sideRef_t *AllocSideRef( const side_t *side, sideRef_t *next ){
|
||||||
sideRef_t *sideRef;
|
|
||||||
|
|
||||||
|
|
||||||
/* dummy check */
|
/* dummy check */
|
||||||
if ( side == NULL ) {
|
if ( side == NULL ) {
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate and return */
|
/* allocate and return */
|
||||||
sideRef = safe_malloc( sizeof( *sideRef ) );
|
sideRef_t *sideRef = safe_malloc( sizeof( *sideRef ) );
|
||||||
sideRef->side = side;
|
sideRef->side = side;
|
||||||
sideRef->next = next;
|
sideRef->next = next;
|
||||||
return sideRef;
|
return sideRef;
|
||||||
|
|
@ -62,110 +59,6 @@ sideRef_t *AllocSideRef( side_t *side, sideRef_t *next ){
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
CountBrushList()
|
|
||||||
counts the number of brushes in a brush linked list
|
|
||||||
*/
|
|
||||||
|
|
||||||
int CountBrushList( brush_t *brushes ){
|
|
||||||
int c = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/* count brushes */
|
|
||||||
for ( ; brushes != NULL; brushes = brushes->next )
|
|
||||||
c++;
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
AllocBrush()
|
|
||||||
allocates a new brush
|
|
||||||
*/
|
|
||||||
|
|
||||||
brush_t *AllocBrush( int numSides ){
|
|
||||||
return safe_calloc( offsetof_array( brush_t, sides, numSides ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
FreeBrush()
|
|
||||||
frees a single brush and all sides/windings
|
|
||||||
*/
|
|
||||||
|
|
||||||
void FreeBrush( brush_t *b ){
|
|
||||||
int i;
|
|
||||||
|
|
||||||
|
|
||||||
/* error check */
|
|
||||||
if ( *( (unsigned int*) b ) == 0xFEFEFEFE ) {
|
|
||||||
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "WARNING: Attempt to free an already freed brush!\n" );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* free brush sides */
|
|
||||||
for ( i = 0; i < b->numsides; i++ )
|
|
||||||
if ( b->sides[i].winding != NULL ) {
|
|
||||||
FreeWinding( b->sides[ i ].winding );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ydnar: overwrite it */
|
|
||||||
memset( b, 0xFE, offsetof_array( brush_t, sides, b->numsides ) );
|
|
||||||
*( (unsigned int*) b ) = 0xFEFEFEFE;
|
|
||||||
|
|
||||||
/* free it */
|
|
||||||
free( b );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
FreeBrushList()
|
|
||||||
frees a linked list of brushes
|
|
||||||
*/
|
|
||||||
|
|
||||||
void FreeBrushList( brush_t *brushes ){
|
|
||||||
brush_t *next;
|
|
||||||
|
|
||||||
|
|
||||||
/* walk brush list */
|
|
||||||
for ( ; brushes != NULL; brushes = next )
|
|
||||||
{
|
|
||||||
next = brushes->next;
|
|
||||||
FreeBrush( brushes );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
CopyBrush()
|
|
||||||
duplicates the brush, sides, and windings
|
|
||||||
*/
|
|
||||||
|
|
||||||
brush_t *CopyBrush( const brush_t *brush ){
|
|
||||||
/* copy brush */
|
|
||||||
brush_t *newBrush = AllocBrush( brush->numsides );
|
|
||||||
memcpy( newBrush, brush, offsetof_array( brush_t, sides, brush->numsides ) );
|
|
||||||
|
|
||||||
/* ydnar: nuke linked list */
|
|
||||||
newBrush->next = NULL;
|
|
||||||
|
|
||||||
/* copy sides */
|
|
||||||
for ( int i = 0; i < brush->numsides; i++ )
|
|
||||||
{
|
|
||||||
if ( brush->sides[ i ].winding != NULL ) {
|
|
||||||
newBrush->sides[ i ].winding = CopyWinding( brush->sides[ i ].winding );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return it */
|
|
||||||
return newBrush;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -174,17 +67,14 @@ brush_t *CopyBrush( const brush_t *brush ){
|
||||||
returns false if the brush doesn't enclose a valid volume
|
returns false if the brush doesn't enclose a valid volume
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool BoundBrush( brush_t *brush ){
|
bool BoundBrush( brush_t& brush ){
|
||||||
brush->minmax.clear();
|
brush.minmax.clear();
|
||||||
for ( int i = 0; i < brush->numsides; i++ )
|
for ( const side_t& side : brush.sides )
|
||||||
{
|
{
|
||||||
const winding_t *w = brush->sides[ i ].winding;
|
WindingExtendBounds( side.winding, brush.minmax );
|
||||||
if ( w != NULL ) {
|
|
||||||
WindingExtendBounds( *w, brush->minmax );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return brush->minmax.valid() && c_worldMinmax.surrounds( brush->minmax );
|
return brush.minmax.valid() && c_worldMinmax.surrounds( brush.minmax );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -290,19 +180,20 @@ DoubleVector3 SnapWeldVectorAccu( const DoubleVector3& a, const DoubleVector3& b
|
||||||
|
|
||||||
#define DEGENERATE_EPSILON 0.1
|
#define DEGENERATE_EPSILON 0.1
|
||||||
|
|
||||||
bool FixWinding( winding_t *w ){
|
bool FixWinding( winding_t& w ){
|
||||||
bool valid = true;
|
bool valid = true;
|
||||||
|
|
||||||
/* dummy check */
|
/* dummy check */
|
||||||
if ( !w ) {
|
if ( w.empty() ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check all verts */
|
/* check all verts */
|
||||||
for ( winding_t::iterator i = w->end() - 1, j = w->begin(); j != w->end(); i = j, ++j )
|
for ( winding_t::iterator i = w.begin(); i != w.end(); )
|
||||||
{
|
{
|
||||||
|
winding_t::iterator j = ( std::next( i ) == w.end() )? w.begin() : std::next( i );
|
||||||
/* don't remove points if winding is a triangle */
|
/* don't remove points if winding is a triangle */
|
||||||
if ( w->size() == 3 ) {
|
if ( w.size() == 3 ) {
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -312,17 +203,20 @@ bool FixWinding( winding_t *w ){
|
||||||
//Sys_FPrintf( SYS_WRN | SYS_VRBflag, "WARNING: Degenerate winding edge found, fixing...\n" );
|
//Sys_FPrintf( SYS_WRN | SYS_VRBflag, "WARNING: Degenerate winding edge found, fixing...\n" );
|
||||||
|
|
||||||
/* create an average point (ydnar 2002-01-26: using nearest-integer weld preference) */
|
/* create an average point (ydnar 2002-01-26: using nearest-integer weld preference) */
|
||||||
*i = SnapWeldVector( *i, *j );
|
*j = SnapWeldVector( *i, *j );
|
||||||
//VectorAdd( w->p[ i ], w->p[ j ], vec );
|
//VectorAdd( w[ i ], w[ j ], vec );
|
||||||
//VectorScale( vec, 0.5, w->p[ i ] );
|
//VectorScale( vec, 0.5, w[ i ] );
|
||||||
|
|
||||||
/* move the remaining verts */
|
/* move the remaining verts */
|
||||||
w->erase( j );
|
i = w.erase( i );
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* one last check and return */
|
/* one last check and return */
|
||||||
if ( w->size() < 3 ) {
|
if ( w.size() < 3 ) {
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
return valid;
|
return valid;
|
||||||
|
|
@ -387,25 +281,25 @@ bool FixWindingAccu( winding_accu_t& w ){
|
||||||
returns false if the brush doesn't enclose a valid volume
|
returns false if the brush doesn't enclose a valid volume
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool CreateBrushWindings( brush_t *brush ){
|
bool CreateBrushWindings( brush_t& brush ){
|
||||||
/* walk the list of brush sides */
|
/* walk the list of brush sides */
|
||||||
for ( int i = 0; i < brush->numsides; i++ )
|
for ( size_t i = 0; i < brush.sides.size(); ++i )
|
||||||
{
|
{
|
||||||
/* get side and plane */
|
/* get side and plane */
|
||||||
side_t& side = brush->sides[ i ];
|
side_t& side = brush.sides[ i ];
|
||||||
const plane_t& plane = mapplanes[ side.planenum ];
|
const plane_t& plane = mapplanes[ side.planenum ];
|
||||||
|
|
||||||
/* make huge winding */
|
/* make huge winding */
|
||||||
#if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
|
#if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
|
||||||
winding_accu_t w = BaseWindingForPlaneAccu( ( side.plane.normal() != g_vector3_identity )? side.plane : Plane3( plane.plane ) );
|
winding_accu_t w = BaseWindingForPlaneAccu( ( side.plane.normal() != g_vector3_identity )? side.plane : Plane3( plane.plane ) );
|
||||||
#else
|
#else
|
||||||
winding_t *w = BaseWindingForPlane( plane.plane );
|
winding_t w = BaseWindingForPlane( plane.plane );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* walk the list of brush sides */
|
/* walk the list of brush sides */
|
||||||
for ( int j = 0; j < brush->numsides && !w.empty(); j++ )
|
for ( size_t j = 0; j < brush.sides.size() && !w.empty(); ++j )
|
||||||
{
|
{
|
||||||
const side_t& cside = brush->sides[ j ];
|
const side_t& cside = brush.sides[ j ];
|
||||||
const plane_t& cplane = mapplanes[ cside.planenum ^ 1 ];
|
const plane_t& cplane = mapplanes[ cside.planenum ^ 1 ];
|
||||||
if ( i == j
|
if ( i == j
|
||||||
|| cside.planenum == ( side.planenum ^ 1 ) /* back side clipaway */
|
|| cside.planenum == ( side.planenum ^ 1 ) /* back side clipaway */
|
||||||
|
|
@ -432,9 +326,12 @@ bool CreateBrushWindings( brush_t *brush ){
|
||||||
/* set side winding */
|
/* set side winding */
|
||||||
#if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
|
#if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
|
||||||
FixWindingAccu( w );
|
FixWindingAccu( w );
|
||||||
side.winding = ( w.size() >= 3 ? CopyWindingAccuToRegular( w ) : NULL );
|
if( w.size() >= 3 )
|
||||||
|
side.winding = CopyWindingAccuToRegular( w );
|
||||||
|
else
|
||||||
|
side.winding.clear();
|
||||||
#else
|
#else
|
||||||
side.winding = w;
|
side.winding.swap( w );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -452,20 +349,16 @@ bool CreateBrushWindings( brush_t *brush ){
|
||||||
Creates a new axial brush
|
Creates a new axial brush
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
brush_t *BrushFromBounds( const Vector3& mins, const Vector3& maxs ){
|
brush_t BrushFromBounds( const Vector3& mins, const Vector3& maxs ){
|
||||||
brush_t *b;
|
brush_t b;
|
||||||
int i;
|
b.sides.resize( 6 );
|
||||||
float dist;
|
for ( int i = 0 ; i < 3 ; i++ )
|
||||||
|
|
||||||
b = AllocBrush( 6 );
|
|
||||||
b->numsides = 6;
|
|
||||||
for ( i = 0 ; i < 3 ; i++ )
|
|
||||||
{
|
{
|
||||||
dist = maxs[i];
|
float dist = maxs[i];
|
||||||
b->sides[i].planenum = FindFloatPlane( g_vector3_axes[i], dist, 1, &maxs );
|
b.sides[i].planenum = FindFloatPlane( g_vector3_axes[i], dist, 1, &maxs );
|
||||||
|
|
||||||
dist = -mins[i];
|
dist = -mins[i];
|
||||||
b->sides[3 + i].planenum = FindFloatPlane( -g_vector3_axes[i], dist, 1, &mins );
|
b.sides[3 + i].planenum = FindFloatPlane( -g_vector3_axes[i], dist, 1, &mins );
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateBrushWindings( b );
|
CreateBrushWindings( b );
|
||||||
|
|
@ -479,45 +372,25 @@ brush_t *BrushFromBounds( const Vector3& mins, const Vector3& maxs ){
|
||||||
|
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
float BrushVolume( brush_t *brush ){
|
float BrushVolume( const brush_t& brush ){
|
||||||
int i;
|
float volume = 0;
|
||||||
const winding_t *w;
|
|
||||||
Vector3 corner;
|
|
||||||
float volume;
|
|
||||||
|
|
||||||
if ( !brush ) {
|
for ( auto i = brush.sides.cbegin(); i != brush.sides.cend(); ++i ){
|
||||||
return 0;
|
// grab the first valid point as the corner
|
||||||
}
|
if( !i->winding.empty() ){
|
||||||
|
const Vector3 corner = i->winding[0];
|
||||||
// grab the first valid point as the corner
|
// make tetrahedrons to all other faces
|
||||||
|
for ( ++i; i != brush.sides.cend(); ++i )
|
||||||
w = NULL;
|
{
|
||||||
for ( i = 0 ; i < brush->numsides ; i++ )
|
if ( !i->winding.empty() ) {
|
||||||
{
|
volume += -plane3_distance_to_point( mapplanes[i->planenum].plane, corner ) * WindingArea( i->winding );
|
||||||
w = brush->sides[i].winding;
|
}
|
||||||
if ( w ) {
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( !w ) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
corner = ( *w )[0];
|
|
||||||
|
|
||||||
// make tetrahedrons to all other faces
|
return volume / 3;
|
||||||
|
|
||||||
volume = 0;
|
|
||||||
for ( ; i < brush->numsides ; i++ )
|
|
||||||
{
|
|
||||||
w = brush->sides[i].winding;
|
|
||||||
if ( !w ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
volume += -plane3_distance_to_point( mapplanes[brush->sides[i].planenum].plane, corner ) * WindingArea( *w );
|
|
||||||
}
|
|
||||||
|
|
||||||
volume /= 3;
|
|
||||||
return volume;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -527,10 +400,7 @@ float BrushVolume( brush_t *brush ){
|
||||||
writes a map with the split bsp brushes
|
writes a map with the split bsp brushes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void WriteBSPBrushMap( const char *name, brush_t *list ){
|
void WriteBSPBrushMap( const char *name, const brushlist_t& list ){
|
||||||
side_t *s;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* note it */
|
/* note it */
|
||||||
Sys_Printf( "Writing %s\n", name );
|
Sys_Printf( "Writing %s\n", name );
|
||||||
|
|
||||||
|
|
@ -539,22 +409,20 @@ void WriteBSPBrushMap( const char *name, brush_t *list ){
|
||||||
|
|
||||||
fprintf( f, "{\n\"classname\" \"worldspawn\"\n" );
|
fprintf( f, "{\n\"classname\" \"worldspawn\"\n" );
|
||||||
|
|
||||||
for ( ; list; list = list->next )
|
for ( const brush_t& brush : list )
|
||||||
{
|
{
|
||||||
fprintf( f, "{\n" );
|
fprintf( f, "{\n" );
|
||||||
for ( i = 0, s = list->sides; i < list->numsides; i++, s++ )
|
for ( const side_t& side : brush.sides )
|
||||||
{
|
{
|
||||||
// TODO: See if we can use a smaller winding to prevent resolution loss.
|
// TODO: See if we can use a smaller winding to prevent resolution loss.
|
||||||
// Is WriteBSPBrushMap() used only to decompile maps?
|
// Is WriteBSPBrushMap() used only to decompile maps?
|
||||||
winding_t *w = BaseWindingForPlane( mapplanes[s->planenum].plane );
|
const winding_t w = BaseWindingForPlane( mapplanes[side.planenum].plane );
|
||||||
const winding_t& wr = *w;
|
|
||||||
|
|
||||||
fprintf( f, "( %i %i %i ) ", (int)wr[0][0], (int)wr[0][1], (int)wr[0][2] );
|
fprintf( f, "( %i %i %i ) ", (int)w[0][0], (int)w[0][1], (int)w[0][2] );
|
||||||
fprintf( f, "( %i %i %i ) ", (int)wr[1][0], (int)wr[1][1], (int)wr[1][2] );
|
fprintf( f, "( %i %i %i ) ", (int)w[1][0], (int)w[1][1], (int)w[1][2] );
|
||||||
fprintf( f, "( %i %i %i ) ", (int)wr[2][0], (int)wr[2][1], (int)wr[2][2] );
|
fprintf( f, "( %i %i %i ) ", (int)w[2][0], (int)w[2][1], (int)w[2][2] );
|
||||||
|
|
||||||
fprintf( f, "notexture 0 0 0 1 1\n" );
|
fprintf( f, "notexture 0 0 0 1 1\n" );
|
||||||
FreeWinding( w );
|
|
||||||
}
|
}
|
||||||
fprintf( f, "}\n" );
|
fprintf( f, "}\n" );
|
||||||
}
|
}
|
||||||
|
|
@ -571,11 +439,7 @@ void WriteBSPBrushMap( const char *name, brush_t *list ){
|
||||||
adds brush reference to any intersecting bsp leafnode
|
adds brush reference to any intersecting bsp leafnode
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int FilterBrushIntoTree_r( brush_t *b, node_t *node ){
|
int FilterBrushIntoTree_r( brush_t* b, node_t *node ){
|
||||||
brush_t *front, *back;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
|
|
||||||
/* dummy check */
|
/* dummy check */
|
||||||
if ( b == NULL ) {
|
if ( b == NULL ) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -584,8 +448,7 @@ int FilterBrushIntoTree_r( brush_t *b, node_t *node ){
|
||||||
/* add it to the leaf list */
|
/* add it to the leaf list */
|
||||||
if ( node->planenum == PLANENUM_LEAF ) {
|
if ( node->planenum == PLANENUM_LEAF ) {
|
||||||
/* something somewhere is hammering brushlist */
|
/* something somewhere is hammering brushlist */
|
||||||
b->next = node->brushlist;
|
node->brushlist.push_front( std::move( *b ) );
|
||||||
node->brushlist = b;
|
|
||||||
|
|
||||||
/* classify the leaf by the structural brush */
|
/* classify the leaf by the structural brush */
|
||||||
if ( !b->detail ) {
|
if ( !b->detail ) {
|
||||||
|
|
@ -604,11 +467,10 @@ int FilterBrushIntoTree_r( brush_t *b, node_t *node ){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* split it by the node plane */
|
/* split it by the node plane */
|
||||||
c = b->numsides;
|
auto [front, back] = SplitBrush( *b, node->planenum );
|
||||||
SplitBrush( b, node->planenum, &front, &back );
|
delete b;
|
||||||
FreeBrush( b );
|
|
||||||
|
|
||||||
c = 0;
|
int c = 0;
|
||||||
c += FilterBrushIntoTree_r( front, node->children[ 0 ] );
|
c += FilterBrushIntoTree_r( front, node->children[ 0 ] );
|
||||||
c += FilterBrushIntoTree_r( back, node->children[ 1 ] );
|
c += FilterBrushIntoTree_r( back, node->children[ 1 ] );
|
||||||
|
|
||||||
|
|
@ -622,11 +484,8 @@ int FilterBrushIntoTree_r( brush_t *b, node_t *node ){
|
||||||
fragment all the detail brushes into the structural leafs
|
fragment all the detail brushes into the structural leafs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree ){
|
void FilterDetailBrushesIntoTree( entity_t *e, tree_t& tree ){
|
||||||
brush_t *b, *newb;
|
int c_unique = 0, c_clusters = 0;
|
||||||
int r;
|
|
||||||
int c_unique, c_clusters;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
|
|
||||||
/* note it */
|
/* note it */
|
||||||
|
|
@ -635,22 +494,21 @@ void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree ){
|
||||||
/* walk the list of brushes */
|
/* walk the list of brushes */
|
||||||
c_unique = 0;
|
c_unique = 0;
|
||||||
c_clusters = 0;
|
c_clusters = 0;
|
||||||
for ( b = e->brushes; b; b = b->next )
|
for ( brush_t& b : e->brushes )
|
||||||
{
|
{
|
||||||
if ( !b->detail ) {
|
if ( !b.detail ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
c_unique++;
|
c_unique++;
|
||||||
newb = CopyBrush( b );
|
const int r = FilterBrushIntoTree_r( new brush_t( b ), tree.headnode );
|
||||||
r = FilterBrushIntoTree_r( newb, tree->headnode );
|
|
||||||
c_clusters += r;
|
c_clusters += r;
|
||||||
|
|
||||||
/* mark all sides as visible so drawsurfs are created */
|
/* mark all sides as visible so drawsurfs are created */
|
||||||
if ( r ) {
|
if ( r ) {
|
||||||
for ( i = 0; i < b->numsides; i++ )
|
for ( side_t& side : b.sides )
|
||||||
{
|
{
|
||||||
if ( b->sides[ i ].winding ) {
|
if ( !side.winding.empty() ) {
|
||||||
b->sides[ i ].visible = true;
|
side.visible = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -668,30 +526,24 @@ void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree ){
|
||||||
Mark the leafs as opaque and areaportals
|
Mark the leafs as opaque and areaportals
|
||||||
=====================
|
=====================
|
||||||
*/
|
*/
|
||||||
void FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree ) {
|
void FilterStructuralBrushesIntoTree( entity_t *e, tree_t& tree ) {
|
||||||
brush_t *b, *newb;
|
int c_unique = 0, c_clusters = 0;
|
||||||
int r;
|
|
||||||
int c_unique, c_clusters;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
Sys_FPrintf( SYS_VRB, "--- FilterStructuralBrushesIntoTree ---\n" );
|
Sys_FPrintf( SYS_VRB, "--- FilterStructuralBrushesIntoTree ---\n" );
|
||||||
|
|
||||||
c_unique = 0;
|
for ( brush_t& b : e->brushes ) {
|
||||||
c_clusters = 0;
|
if ( b.detail ) {
|
||||||
for ( b = e->brushes ; b ; b = b->next ) {
|
|
||||||
if ( b->detail ) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
c_unique++;
|
c_unique++;
|
||||||
newb = CopyBrush( b );
|
const int r = FilterBrushIntoTree_r( new brush_t( b ), tree.headnode );
|
||||||
r = FilterBrushIntoTree_r( newb, tree->headnode );
|
|
||||||
c_clusters += r;
|
c_clusters += r;
|
||||||
|
|
||||||
// mark all sides as visible so drawsurfs are created
|
// mark all sides as visible so drawsurfs are created
|
||||||
if ( r ) {
|
if ( r ) {
|
||||||
for ( i = 0 ; i < b->numsides ; i++ ) {
|
for ( side_t& side : b.sides ) {
|
||||||
if ( b->sides[i].winding ) {
|
if ( !side.winding.empty() ) {
|
||||||
b->sides[i].visible = true;
|
side.visible = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -703,28 +555,6 @@ void FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
AllocTree
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
tree_t *AllocTree( void ){
|
|
||||||
tree_t *tree = safe_calloc( sizeof( *tree ) );
|
|
||||||
tree->minmax.clear();
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
AllocNode
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
node_t *AllocNode( void ){
|
|
||||||
return safe_calloc( sizeof( node_t ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
================
|
||||||
WindingIsTiny
|
WindingIsTiny
|
||||||
|
|
@ -776,24 +606,21 @@ bool WindingIsHuge( const winding_t& w ){
|
||||||
|
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
int BrushMostlyOnSide( brush_t *brush, plane_t *plane ){
|
int BrushMostlyOnSide( const brush_t& brush, const Plane3f& plane ){
|
||||||
float max = 0;
|
float max = 0;
|
||||||
int side = PSIDE_FRONT;
|
int side = PSIDE_FRONT;
|
||||||
for ( int i = 0 ; i < brush->numsides ; i++ )
|
for ( const side_t& s : brush.sides )
|
||||||
{
|
{
|
||||||
winding_t *w = brush->sides[i].winding;
|
for ( const Vector3& p : s.winding )
|
||||||
if ( w ) {
|
{
|
||||||
for ( const Vector3& p : *w )
|
const double d = plane3_distance_to_point( plane, p );
|
||||||
{
|
if ( d > max ) {
|
||||||
const double d = plane3_distance_to_point( plane->plane, p );
|
max = d;
|
||||||
if ( d > max ) {
|
side = PSIDE_FRONT;
|
||||||
max = d;
|
}
|
||||||
side = PSIDE_FRONT;
|
if ( -d > max ) {
|
||||||
}
|
max = -d;
|
||||||
if ( -d > max ) {
|
side = PSIDE_BACK;
|
||||||
max = -d;
|
|
||||||
side = PSIDE_BACK;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -807,30 +634,16 @@ int BrushMostlyOnSide( brush_t *brush, plane_t *plane ){
|
||||||
generates two new brushes, leaving the original unchanged
|
generates two new brushes, leaving the original unchanged
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back ){
|
std::pair<brush_t*, brush_t*> SplitBrush( const brush_t& brush, int planenum ){
|
||||||
brush_t *b[2];
|
const Plane3f& plane = mapplanes[planenum].plane;
|
||||||
int i, j;
|
|
||||||
winding_t *w, *cw[2], *midwinding;
|
|
||||||
plane_t *plane, *plane2;
|
|
||||||
side_t *s, *cs;
|
|
||||||
float d_front, d_back;
|
|
||||||
|
|
||||||
|
|
||||||
*front = NULL;
|
|
||||||
*back = NULL;
|
|
||||||
plane = &mapplanes[planenum];
|
|
||||||
|
|
||||||
// check all points
|
// check all points
|
||||||
d_front = d_back = 0;
|
float d_front = 0, d_back = 0;
|
||||||
for ( i = 0 ; i < brush->numsides ; i++ )
|
for ( const side_t& side : brush.sides )
|
||||||
{
|
{
|
||||||
w = brush->sides[i].winding;
|
for ( const Vector3& p : side.winding )
|
||||||
if ( !w ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for ( const Vector3& p : *w )
|
|
||||||
{
|
{
|
||||||
const float d = plane3_distance_to_point( plane->plane, p );
|
const float d = plane3_distance_to_point( plane, p );
|
||||||
if ( d > 0 ) {
|
if ( d > 0 ) {
|
||||||
value_maximize( d_front, d );
|
value_maximize( d_front, d );
|
||||||
}
|
}
|
||||||
|
|
@ -842,140 +655,117 @@ void SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back )
|
||||||
|
|
||||||
if ( d_front < 0.1 ) { // PLANESIDE_EPSILON)
|
if ( d_front < 0.1 ) { // PLANESIDE_EPSILON)
|
||||||
// only on back
|
// only on back
|
||||||
*back = CopyBrush( brush );
|
return { {}, new brush_t( brush ) };
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( d_back > -0.1 ) { // PLANESIDE_EPSILON)
|
if ( d_back > -0.1 ) { // PLANESIDE_EPSILON)
|
||||||
// only on front
|
// only on front
|
||||||
*front = CopyBrush( brush );
|
return { new brush_t( brush ), {} };
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a new winding from the split plane
|
// create a new winding from the split plane
|
||||||
w = BaseWindingForPlane( plane->plane );
|
winding_t midwinding = BaseWindingForPlane( plane );
|
||||||
for ( i = 0 ; i < brush->numsides && w ; i++ )
|
for ( const side_t& side : brush.sides )
|
||||||
{
|
{
|
||||||
plane2 = &mapplanes[brush->sides[i].planenum ^ 1];
|
ChopWindingInPlace( midwinding, mapplanes[side.planenum ^ 1].plane, 0 ); // PLANESIDE_EPSILON);
|
||||||
ChopWindingInPlace( w, plane2->plane, 0 ); // PLANESIDE_EPSILON);
|
if( midwinding.empty() )
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !w || WindingIsTiny( *w ) ) { // the brush isn't really split
|
if ( midwinding.empty() || WindingIsTiny( midwinding ) ) { // the brush isn't really split
|
||||||
int side;
|
const int side = BrushMostlyOnSide( brush, plane );
|
||||||
|
|
||||||
side = BrushMostlyOnSide( brush, plane );
|
|
||||||
if ( side == PSIDE_FRONT ) {
|
|
||||||
*front = CopyBrush( brush );
|
|
||||||
}
|
|
||||||
if ( side == PSIDE_BACK ) {
|
if ( side == PSIDE_BACK ) {
|
||||||
*back = CopyBrush( brush );
|
return { {}, new brush_t( brush ) };
|
||||||
|
}
|
||||||
|
else { // side == PSIDE_FRONT
|
||||||
|
return { new brush_t( brush ), {} };
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( WindingIsHuge( *w ) ) {
|
if ( WindingIsHuge( midwinding ) ) {
|
||||||
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "WARNING: huge winding\n" );
|
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "WARNING: huge winding\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
midwinding = w;
|
|
||||||
|
|
||||||
// split it for real
|
// split it for real
|
||||||
|
brush_t *b[2];
|
||||||
for ( i = 0 ; i < 2 ; i++ )
|
for ( int i = 0; i < 2; i++ )
|
||||||
{
|
{
|
||||||
b[i] = AllocBrush( brush->numsides + 1 );
|
b[i] = new brush_t( brush );
|
||||||
memcpy( b[i], brush, sizeof( brush_t ) );
|
b[i]->sides.clear();
|
||||||
b[i]->numsides = 0;
|
|
||||||
b[i]->next = NULL;
|
|
||||||
b[i]->original = brush->original;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// split all the current windings
|
// split all the current windings
|
||||||
|
|
||||||
for ( i = 0 ; i < brush->numsides ; i++ )
|
for ( const side_t& side : brush.sides )
|
||||||
{
|
{
|
||||||
s = &brush->sides[i];
|
if ( !side.winding.empty() ) {
|
||||||
w = s->winding;
|
winding_t cw[2];
|
||||||
if ( !w ) {
|
std::tie( cw[0], cw[1] ) =
|
||||||
continue;
|
ClipWindingEpsilonStrict( side.winding, plane, 0 /*PLANESIDE_EPSILON*/ ); /* strict, in parallel case we get the face back because it also is the midwinding */
|
||||||
}
|
for ( int i = 0; i < 2; i++ )
|
||||||
ClipWindingEpsilonStrict( *w, plane->plane,
|
{
|
||||||
0 /*PLANESIDE_EPSILON*/, cw[0], cw[1] ); /* strict, in parallel case we get the face back because it also is the midwinding */
|
if ( !cw[i].empty() ) {
|
||||||
for ( j = 0 ; j < 2 ; j++ )
|
side_t& cs = b[i]->sides.emplace_back( side );
|
||||||
{
|
cs.winding.swap( cw[i] );
|
||||||
if ( !cw[j] ) {
|
}
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
cs = &b[j]->sides[b[j]->numsides];
|
|
||||||
b[j]->numsides++;
|
|
||||||
*cs = *s;
|
|
||||||
cs->winding = cw[j];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// see if we have valid polygons on both sides
|
// see if we have valid polygons on both sides
|
||||||
for ( i = 0 ; i < 2 ; i++ )
|
for ( int i = 0; i < 2; i++ )
|
||||||
{
|
{
|
||||||
if ( b[i]->numsides < 3 || !BoundBrush( b[i] ) ) {
|
if ( b[i]->sides.size() < 3 || !BoundBrush( *b[i] ) ) {
|
||||||
if ( b[i]->numsides >= 3 ) {
|
if ( b[i]->sides.size() >= 3 ) {
|
||||||
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "bogus brush after clip\n" );
|
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "bogus brush after clip\n" );
|
||||||
}
|
}
|
||||||
FreeBrush( b[i] );
|
delete b[i];
|
||||||
b[i] = NULL;
|
b[i] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !( b[0] && b[1] ) ) {
|
if ( b[0] == nullptr || b[1] == nullptr ) {
|
||||||
if ( !b[0] && !b[1] ) {
|
if ( b[0] == nullptr && b[1] == nullptr ) {
|
||||||
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "split removed brush\n" );
|
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "split removed brush\n" );
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "split not on both sides\n" );
|
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "split not on both sides\n" );
|
||||||
}
|
}
|
||||||
if ( b[0] ) {
|
if ( b[0] != nullptr ) {
|
||||||
FreeBrush( b[0] );
|
delete b[0];
|
||||||
*front = CopyBrush( brush );
|
return { new brush_t( brush ), {} };
|
||||||
}
|
}
|
||||||
if ( b[1] ) {
|
else if ( b[1] != nullptr ) {
|
||||||
FreeBrush( b[1] );
|
delete b[1];
|
||||||
*back = CopyBrush( brush );
|
return { {}, new brush_t( brush ) };
|
||||||
}
|
}
|
||||||
return;
|
return{};
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the midwinding to both sides
|
// add the midwinding to both sides
|
||||||
for ( i = 0 ; i < 2 ; i++ )
|
for ( int i = 0; i < 2; i++ )
|
||||||
{
|
{
|
||||||
cs = &b[i]->sides[b[i]->numsides];
|
side_t& cs = b[i]->sides.emplace_back();
|
||||||
b[i]->numsides++;
|
|
||||||
|
|
||||||
cs->planenum = planenum ^ i ^ 1;
|
cs.planenum = planenum ^ i ^ 1;
|
||||||
cs->shaderInfo = NULL;
|
cs.shaderInfo = NULL;
|
||||||
if ( i == 0 ) {
|
if ( i == 0 ) {
|
||||||
cs->winding = CopyWinding( midwinding );
|
cs.winding = midwinding; // copy
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
cs->winding = midwinding;
|
cs.winding.swap( midwinding ); // move
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for ( int i = 0; i < 2; i++ )
|
||||||
{
|
{
|
||||||
float v1;
|
if ( BrushVolume( *b[i] ) < 1.0 ) {
|
||||||
int i;
|
delete b[i];
|
||||||
|
b[i] = NULL;
|
||||||
|
// Sys_FPrintf( SYS_WRN | SYS_VRBflag, "tiny volume after clip\n" );
|
||||||
for ( i = 0 ; i < 2 ; i++ )
|
|
||||||
{
|
|
||||||
v1 = BrushVolume( b[i] );
|
|
||||||
if ( v1 < 1.0 ) {
|
|
||||||
FreeBrush( b[i] );
|
|
||||||
b[i] = NULL;
|
|
||||||
// Sys_FPrintf( SYS_WRN | SYS_VRBflag, "tiny volume after clip\n" );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*front = b[0];
|
return{ b[0], b[1] };
|
||||||
*back = b[1];
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,11 +47,11 @@ static void autocaulk_write(){
|
||||||
int flava = 8;
|
int flava = 8;
|
||||||
ApplySurfaceParm( "lava", &flava, NULL, NULL );
|
ApplySurfaceParm( "lava", &flava, NULL, NULL );
|
||||||
|
|
||||||
for ( brush_t* b = entities[0].brushes; b; b = b->next ) {
|
for ( const brush_t& b : entities[0].brushes ) {
|
||||||
fprintf( file, "%i ", b->brushNum );
|
fprintf( file, "%i ", b.brushNum );
|
||||||
shaderInfo_t* contentShader = b->contentShader;
|
const shaderInfo_t* contentShader = b.contentShader;
|
||||||
for( int i = 0; i < b->numsides; ++i ){
|
for( const side_t& side : b.sides ){
|
||||||
if( b->sides[i].visibleHull || ( b->sides[i].compileFlags & C_NODRAW ) ){
|
if( !side.visibleHull.empty() || ( side.compileFlags & C_NODRAW ) ){
|
||||||
fprintf( file, "-" );
|
fprintf( file, "-" );
|
||||||
}
|
}
|
||||||
else if( contentShader->compileFlags & C_LIQUID ){
|
else if( contentShader->compileFlags & C_LIQUID ){
|
||||||
|
|
@ -62,7 +62,7 @@ static void autocaulk_write(){
|
||||||
else
|
else
|
||||||
fprintf( file, "w" );
|
fprintf( file, "w" );
|
||||||
}
|
}
|
||||||
else if( b->compileFlags & C_TRANSLUCENT ){
|
else if( b.compileFlags & C_TRANSLUCENT ){
|
||||||
if( contentShader->compileFlags & C_SOLID )
|
if( contentShader->compileFlags & C_SOLID )
|
||||||
fprintf( file, "N" );
|
fprintf( file, "N" );
|
||||||
else
|
else
|
||||||
|
|
@ -170,7 +170,7 @@ static void SetCloneModelNumbers( void ){
|
||||||
for ( std::size_t i = 1; i < entities.size(); ++i )
|
for ( std::size_t i = 1; i < entities.size(); ++i )
|
||||||
{
|
{
|
||||||
/* only entities with brushes or patches get a model number */
|
/* only entities with brushes or patches get a model number */
|
||||||
if ( entities[ i ].brushes == NULL && entities[ i ].patches == NULL ) {
|
if ( entities[ i ].brushes.empty() && entities[ i ].patches == NULL ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -190,7 +190,7 @@ static void SetCloneModelNumbers( void ){
|
||||||
for ( std::size_t i = 1; i < entities.size(); ++i )
|
for ( std::size_t i = 1; i < entities.size(); ++i )
|
||||||
{
|
{
|
||||||
/* only entities with brushes or patches get a model number */
|
/* only entities with brushes or patches get a model number */
|
||||||
if ( entities[ i ].brushes == NULL && entities[ i ].patches == NULL ) {
|
if ( entities[ i ].brushes.empty() && entities[ i ].patches == NULL ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -220,7 +220,7 @@ static void SetCloneModelNumbers( void ){
|
||||||
entities[ i ].setKeyValue( "model", modelValue );
|
entities[ i ].setKeyValue( "model", modelValue );
|
||||||
|
|
||||||
/* nuke the brushes/patches for this entity (fixme: leak!) */
|
/* nuke the brushes/patches for this entity (fixme: leak!) */
|
||||||
entities[ i ].brushes = NULL;
|
brushlist_t *leak = new brushlist_t( std::move( entities[ i ].brushes ) ); // are brushes referenced elsewhere, so we do not nuke them really?
|
||||||
entities[ i ].patches = NULL;
|
entities[ i ].patches = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -284,8 +284,6 @@ static void FixBrushSides( entity_t *e ){
|
||||||
|
|
||||||
void ProcessWorldModel( void ){
|
void ProcessWorldModel( void ){
|
||||||
entity_t *e;
|
entity_t *e;
|
||||||
tree_t *tree;
|
|
||||||
facelist_t faces;
|
|
||||||
xmlNodePtr polyline, leaknode;
|
xmlNodePtr polyline, leaknode;
|
||||||
char level[ 2 ];
|
char level[ 2 ];
|
||||||
const char *value;
|
const char *value;
|
||||||
|
|
@ -321,8 +319,8 @@ void ProcessWorldModel( void ){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* build an initial bsp tree using all of the sides of all of the structural brushes */
|
/* build an initial bsp tree using all of the sides of all of the structural brushes */
|
||||||
faces = MakeStructuralBSPFaceList( entities[ 0 ].brushes );
|
facelist_t faces = MakeStructuralBSPFaceList( entities[ 0 ].brushes );
|
||||||
tree = FaceBSP( faces );
|
tree_t tree = FaceBSP( faces );
|
||||||
MakeTreePortals( tree );
|
MakeTreePortals( tree );
|
||||||
FilterStructuralBrushesIntoTree( e, tree );
|
FilterStructuralBrushesIntoTree( e, tree );
|
||||||
|
|
||||||
|
|
@ -353,7 +351,7 @@ void ProcessWorldModel( void ){
|
||||||
|
|
||||||
if ( leakStatus != EFloodEntities::Empty ) { /* if no entities exist, this would accidentally the whole map, and that IS bad */
|
if ( leakStatus != EFloodEntities::Empty ) { /* if no entities exist, this would accidentally the whole map, and that IS bad */
|
||||||
/* rebuild a better bsp tree using only the sides that are visible from the inside */
|
/* rebuild a better bsp tree using only the sides that are visible from the inside */
|
||||||
FillOutside( tree->headnode );
|
FillOutside( tree.headnode );
|
||||||
|
|
||||||
/* chop the sides to the convex hull of their visible fragments, giving us the smallest polygons */
|
/* chop the sides to the convex hull of their visible fragments, giving us the smallest polygons */
|
||||||
ClipSidesIntoTree( e, tree );
|
ClipSidesIntoTree( e, tree );
|
||||||
|
|
@ -372,7 +370,7 @@ void ProcessWorldModel( void ){
|
||||||
|
|
||||||
/* flood again to discard portals in the void (also required for _skybox) */
|
/* flood again to discard portals in the void (also required for _skybox) */
|
||||||
FloodEntities( tree );
|
FloodEntities( tree );
|
||||||
FillOutside( tree->headnode );
|
FillOutside( tree.headnode );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* save out information for visibility processing */
|
/* save out information for visibility processing */
|
||||||
|
|
@ -405,7 +403,7 @@ void ProcessWorldModel( void ){
|
||||||
|
|
||||||
/* subdivide each drawsurf as required by shader tesselation */
|
/* subdivide each drawsurf as required by shader tesselation */
|
||||||
if ( !nosubdivide ) {
|
if ( !nosubdivide ) {
|
||||||
SubdivideFaceSurfaces( e, tree );
|
SubdivideFaceSurfaces( e );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add in any vertexes required to fix t-junctions */
|
/* add in any vertexes required to fix t-junctions */
|
||||||
|
|
@ -433,7 +431,7 @@ void ProcessWorldModel( void ){
|
||||||
/* ydnar: fog hull */
|
/* ydnar: fog hull */
|
||||||
if ( entities[ 0 ].read_keyvalue( value, "_foghull" ) ) {
|
if ( entities[ 0 ].read_keyvalue( value, "_foghull" ) ) {
|
||||||
const auto shader = String64()( "textures/", value );
|
const auto shader = String64()( "textures/", value );
|
||||||
MakeFogHullSurfs( e, tree, shader );
|
MakeFogHullSurfs( e, shader );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ydnar: bug 645: do flares for lights */
|
/* ydnar: bug 645: do flares for lights */
|
||||||
|
|
@ -484,7 +482,7 @@ void ProcessWorldModel( void ){
|
||||||
FixBrushSides( e );
|
FixBrushSides( e );
|
||||||
|
|
||||||
/* finish */
|
/* finish */
|
||||||
EndModel( e, tree->headnode );
|
EndModel( e, tree.headnode );
|
||||||
FreeTree( tree );
|
FreeTree( tree );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -496,15 +494,9 @@ void ProcessWorldModel( void ){
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void ProcessSubModel( void ){
|
void ProcessSubModel( void ){
|
||||||
entity_t *e;
|
|
||||||
tree_t *tree;
|
|
||||||
brush_t *b, *bc;
|
|
||||||
node_t *node;
|
|
||||||
|
|
||||||
|
|
||||||
/* start a brush model */
|
/* start a brush model */
|
||||||
BeginModel();
|
BeginModel();
|
||||||
e = &entities[ mapEntityNum ];
|
entity_t *e = &entities[ mapEntityNum ];
|
||||||
e->firstDrawSurf = numMapDrawSurfs;
|
e->firstDrawSurf = numMapDrawSurfs;
|
||||||
|
|
||||||
/* ydnar: gs mods */
|
/* ydnar: gs mods */
|
||||||
|
|
@ -514,10 +506,9 @@ void ProcessSubModel( void ){
|
||||||
PatchMapDrawSurfs( e );
|
PatchMapDrawSurfs( e );
|
||||||
|
|
||||||
/* allocate a tree */
|
/* allocate a tree */
|
||||||
node = AllocNode();
|
tree_t tree{};
|
||||||
node->planenum = PLANENUM_LEAF;
|
tree.headnode = AllocNode();
|
||||||
tree = AllocTree();
|
tree.headnode->planenum = PLANENUM_LEAF;
|
||||||
tree->headnode = node;
|
|
||||||
|
|
||||||
/* add the sides to the tree */
|
/* add the sides to the tree */
|
||||||
ClipSidesIntoTree( e, tree );
|
ClipSidesIntoTree( e, tree );
|
||||||
|
|
@ -532,16 +523,11 @@ void ProcessSubModel( void ){
|
||||||
EmitBrushes( e->brushes, &e->firstBrush, &e->numBrushes );
|
EmitBrushes( e->brushes, &e->firstBrush, &e->numBrushes );
|
||||||
|
|
||||||
/* just put all the brushes in headnode */
|
/* just put all the brushes in headnode */
|
||||||
for ( b = e->brushes; b; b = b->next )
|
tree.headnode->brushlist = e->brushes;
|
||||||
{
|
|
||||||
bc = CopyBrush( b );
|
|
||||||
bc->next = node->brushlist;
|
|
||||||
node->brushlist = bc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* subdivide each drawsurf as required by shader tesselation */
|
/* subdivide each drawsurf as required by shader tesselation */
|
||||||
if ( !nosubdivide ) {
|
if ( !nosubdivide ) {
|
||||||
SubdivideFaceSurfaces( e, tree );
|
SubdivideFaceSurfaces( e );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add in any vertexes required to fix t-junctions */
|
/* add in any vertexes required to fix t-junctions */
|
||||||
|
|
@ -568,7 +554,7 @@ void ProcessSubModel( void ){
|
||||||
FixBrushSides( e );
|
FixBrushSides( e );
|
||||||
|
|
||||||
/* finish */
|
/* finish */
|
||||||
EndModel( e, node );
|
EndModel( e, tree.headnode );
|
||||||
FreeTree( tree );
|
FreeTree( tree );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -597,7 +583,7 @@ void ProcessModels( void ){
|
||||||
{
|
{
|
||||||
/* get entity */
|
/* get entity */
|
||||||
const entity_t& entity = entities[ mapEntityNum ];
|
const entity_t& entity = entities[ mapEntityNum ];
|
||||||
if ( entity.brushes == NULL && entity.patches == NULL ) {
|
if ( entity.brushes.empty() && entity.patches == NULL ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -726,10 +726,7 @@ void PseudoCompileBSP( bool need_tree ){
|
||||||
char modelValue[16];
|
char modelValue[16];
|
||||||
entity_t *entity;
|
entity_t *entity;
|
||||||
facelist_t faces;
|
facelist_t faces;
|
||||||
tree_t *tree;
|
tree_t tree{};
|
||||||
node_t *node;
|
|
||||||
brush_t *brush;
|
|
||||||
side_t *side;
|
|
||||||
|
|
||||||
SetDrawSurfacesBuffer();
|
SetDrawSurfacesBuffer();
|
||||||
mapDrawSurfs = safe_calloc( sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
|
mapDrawSurfs = safe_calloc( sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
|
||||||
|
|
@ -741,7 +738,7 @@ void PseudoCompileBSP( bool need_tree ){
|
||||||
{
|
{
|
||||||
/* get entity */
|
/* get entity */
|
||||||
entity = &entities[ mapEntityNum ];
|
entity = &entities[ mapEntityNum ];
|
||||||
if ( entity->brushes == NULL && entity->patches == NULL ) {
|
if ( entity->brushes.empty() && entity->patches == NULL ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -762,33 +759,28 @@ void PseudoCompileBSP( bool need_tree ){
|
||||||
if ( mapEntityNum == 0 && need_tree ) {
|
if ( mapEntityNum == 0 && need_tree ) {
|
||||||
faces = MakeStructuralBSPFaceList( entities[0].brushes );
|
faces = MakeStructuralBSPFaceList( entities[0].brushes );
|
||||||
tree = FaceBSP( faces );
|
tree = FaceBSP( faces );
|
||||||
node = tree->headnode;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
node = AllocNode();
|
tree.headnode = AllocNode();
|
||||||
node->planenum = PLANENUM_LEAF;
|
tree.headnode->planenum = PLANENUM_LEAF;
|
||||||
tree = AllocTree();
|
|
||||||
tree->headnode = node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* a minimized ClipSidesIntoTree */
|
/* a minimized ClipSidesIntoTree */
|
||||||
for ( brush = entity->brushes; brush; brush = brush->next )
|
for ( const brush_t& brush : entity->brushes )
|
||||||
{
|
{
|
||||||
/* walk the brush sides */
|
/* walk the brush sides */
|
||||||
for ( int j = 0; j < brush->numsides; j++ )
|
for ( const side_t& side : brush.sides )
|
||||||
{
|
{
|
||||||
/* get side */
|
if ( side.winding.empty() ) {
|
||||||
side = &brush->sides[ j ];
|
|
||||||
if ( side->winding == NULL ) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* shader? */
|
/* shader? */
|
||||||
if ( side->shaderInfo == NULL ) {
|
if ( side.shaderInfo == NULL ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* save this winding as a visible surface */
|
/* save this winding as a visible surface */
|
||||||
DrawSurfaceForSide( entity, brush, side, *side->winding );
|
DrawSurfaceForSide( entity, brush, side, side.winding );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -805,7 +797,7 @@ void PseudoCompileBSP( bool need_tree ){
|
||||||
FilterDetailBrushesIntoTree( entity, tree );
|
FilterDetailBrushesIntoTree( entity, tree );
|
||||||
|
|
||||||
EmitBrushes( entity->brushes, &entity->firstBrush, &entity->numBrushes );
|
EmitBrushes( entity->brushes, &entity->firstBrush, &entity->numBrushes );
|
||||||
EndModel( entity, node );
|
EndModel( entity, tree.headnode );
|
||||||
}
|
}
|
||||||
EndBSPFile( false );
|
EndBSPFile( false );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,14 +47,14 @@ static float Det3x3( float a00, float a01, float a02,
|
||||||
+ a02 * ( a10 * a21 - a11 * a20 );
|
+ a02 * ( a10 * a21 - a11 * a20 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetBestSurfaceTriangleMatchForBrushside( side_t *buildSide, bspDrawVert_t *bestVert[3] ){
|
void GetBestSurfaceTriangleMatchForBrushside( const side_t& buildSide, bspDrawVert_t *bestVert[3] ){
|
||||||
bspDrawSurface_t *s;
|
bspDrawSurface_t *s;
|
||||||
int i;
|
int i;
|
||||||
int t;
|
int t;
|
||||||
float best = 0;
|
float best = 0;
|
||||||
float thisarea;
|
float thisarea;
|
||||||
bspDrawVert_t *vert[3];
|
bspDrawVert_t *vert[3];
|
||||||
const plane_t& buildPlane = mapplanes[buildSide->planenum];
|
const plane_t& buildPlane = mapplanes[buildSide.planenum];
|
||||||
int matches = 0;
|
int matches = 0;
|
||||||
|
|
||||||
// first, start out with NULLs
|
// first, start out with NULLs
|
||||||
|
|
@ -66,7 +66,7 @@ void GetBestSurfaceTriangleMatchForBrushside( side_t *buildSide, bspDrawVert_t *
|
||||||
if ( s->surfaceType != MST_PLANAR && s->surfaceType != MST_TRIANGLE_SOUP ) {
|
if ( s->surfaceType != MST_PLANAR && s->surfaceType != MST_TRIANGLE_SOUP ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( !strEqual( buildSide->shaderInfo->shader, bspShaders[s->shaderNum].shader ) ) {
|
if ( !strEqual( buildSide.shaderInfo->shader, bspShaders[s->shaderNum].shader ) ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for ( t = 0; t + 3 <= s->numIndexes; t += 3 )
|
for ( t = 0; t + 3 <= s->numIndexes; t += 3 )
|
||||||
|
|
@ -98,7 +98,7 @@ void GetBestSurfaceTriangleMatchForBrushside( side_t *buildSide, bspDrawVert_t *
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Okay. Correct surface type, correct shader, correct plane. Let's start with the business...
|
// Okay. Correct surface type, correct shader, correct plane. Let's start with the business...
|
||||||
winding_t *polygon = CopyWinding( buildSide->winding );
|
winding_t polygon( buildSide.winding );
|
||||||
for ( i = 0; i < 3; ++i )
|
for ( i = 0; i < 3; ++i )
|
||||||
{
|
{
|
||||||
// 0: 1, 2
|
// 0: 1, 2
|
||||||
|
|
@ -110,11 +110,11 @@ void GetBestSurfaceTriangleMatchForBrushside( side_t *buildSide, bspDrawVert_t *
|
||||||
Plane3f plane( vector3_cross( v2 - v1, buildPlane.normal() ), 0 );
|
Plane3f plane( vector3_cross( v2 - v1, buildPlane.normal() ), 0 );
|
||||||
plane.dist() = vector3_dot( v1, plane.normal() );
|
plane.dist() = vector3_dot( v1, plane.normal() );
|
||||||
ChopWindingInPlace( polygon, plane, distanceEpsilon );
|
ChopWindingInPlace( polygon, plane, distanceEpsilon );
|
||||||
if ( !polygon ) {
|
if ( polygon.empty() ) {
|
||||||
goto exwinding;
|
goto exwinding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
thisarea = WindingArea( *polygon );
|
thisarea = WindingArea( polygon );
|
||||||
if ( thisarea > 0 ) {
|
if ( thisarea > 0 ) {
|
||||||
++matches;
|
++matches;
|
||||||
}
|
}
|
||||||
|
|
@ -124,13 +124,12 @@ void GetBestSurfaceTriangleMatchForBrushside( side_t *buildSide, bspDrawVert_t *
|
||||||
bestVert[1] = vert[1];
|
bestVert[1] = vert[1];
|
||||||
bestVert[2] = vert[2];
|
bestVert[2] = vert[2];
|
||||||
}
|
}
|
||||||
FreeWinding( polygon );
|
|
||||||
exwinding:
|
exwinding:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//if(!striEqualPrefix(buildSide->shaderInfo->shader, "textures/common/"))
|
//if(!striEqualPrefix(buildSide.shaderInfo->shader, "textures/common/"))
|
||||||
// fprintf(stderr, "brushside with %s: %d matches (%f area)\n", buildSide->shaderInfo->shader, matches, best);
|
// fprintf(stderr, "brushside with %s: %d matches (%f area)\n", buildSide.shaderInfo->shader, matches, best);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FRAC( x ) ( ( x ) - floor( x ) )
|
#define FRAC( x ) ( ( x ) - floor( x ) )
|
||||||
|
|
@ -195,43 +194,26 @@ static void ConvertOriginBrush( FILE *f, int num, const Vector3& origin, bool br
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ConvertBrushFast( FILE *f, int num, bspBrush_t *brush, const Vector3& origin, bool brushPrimitives ){
|
static void ConvertBrushFast( FILE *f, int num, bspBrush_t *brush, const Vector3& origin, bool brushPrimitives ){
|
||||||
int i;
|
|
||||||
bspBrushSide_t *side;
|
|
||||||
side_t *buildSide;
|
|
||||||
bspShader_t *shader;
|
|
||||||
const char *texture;
|
|
||||||
plane_t *buildPlane;
|
|
||||||
Vector3 pts[ 3 ];
|
|
||||||
|
|
||||||
|
|
||||||
/* clear out build brush */
|
/* clear out build brush */
|
||||||
for ( i = 0; i < buildBrush->numsides; i++ )
|
buildBrush.sides.clear();
|
||||||
{
|
|
||||||
buildSide = &buildBrush->sides[ i ];
|
|
||||||
if ( buildSide->winding != NULL ) {
|
|
||||||
FreeWinding( buildSide->winding );
|
|
||||||
buildSide->winding = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buildBrush->numsides = 0;
|
|
||||||
|
|
||||||
bool modelclip = false;
|
bool modelclip = false;
|
||||||
/* try to guess if thats model clip */
|
/* try to guess if thats model clip */
|
||||||
if ( force ){
|
if ( force ){
|
||||||
int notNoShader = 0;
|
int notNoShader = 0;
|
||||||
modelclip = true;
|
modelclip = true;
|
||||||
for ( i = 0; i < brush->numSides; i++ )
|
for ( int i = 0; i < brush->numSides; i++ )
|
||||||
{
|
{
|
||||||
/* get side */
|
/* get side */
|
||||||
side = &bspBrushSides[ brush->firstSide + i ];
|
const bspBrushSide_t& side = bspBrushSides[ brush->firstSide + i ];
|
||||||
|
|
||||||
/* get shader */
|
/* get shader */
|
||||||
if ( side->shaderNum < 0 || side->shaderNum >= numBSPShaders ) {
|
if ( side.shaderNum < 0 || side.shaderNum >= numBSPShaders ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
shader = &bspShaders[ side->shaderNum ];
|
const bspShader_t& shader = bspShaders[ side.shaderNum ];
|
||||||
//"noshader" happens on modelclip and unwanted sides ( usually breaking complex brushes )
|
//"noshader" happens on modelclip and unwanted sides ( usually breaking complex brushes )
|
||||||
if( !striEqual( shader->shader, "noshader" ) ){
|
if( !striEqual( shader.shader, "noshader" ) ){
|
||||||
notNoShader++;
|
notNoShader++;
|
||||||
}
|
}
|
||||||
if( notNoShader > 1 ){
|
if( notNoShader > 1 ){
|
||||||
|
|
@ -242,28 +224,26 @@ static void ConvertBrushFast( FILE *f, int num, bspBrush_t *brush, const Vector3
|
||||||
}
|
}
|
||||||
|
|
||||||
/* iterate through bsp brush sides */
|
/* iterate through bsp brush sides */
|
||||||
for ( i = 0; i < brush->numSides; i++ )
|
for ( int i = 0; i < brush->numSides; i++ )
|
||||||
{
|
{
|
||||||
/* get side */
|
/* get side */
|
||||||
side = &bspBrushSides[ brush->firstSide + i ];
|
const bspBrushSide_t& side = bspBrushSides[ brush->firstSide + i ];
|
||||||
|
|
||||||
/* get shader */
|
/* get shader */
|
||||||
if ( side->shaderNum < 0 || side->shaderNum >= numBSPShaders ) {
|
if ( side.shaderNum < 0 || side.shaderNum >= numBSPShaders ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
shader = &bspShaders[ side->shaderNum ];
|
const bspShader_t& shader = bspShaders[ side.shaderNum ];
|
||||||
//"noshader" happens on modelclip and unwanted sides ( usually breaking complex brushes )
|
//"noshader" happens on modelclip and unwanted sides ( usually breaking complex brushes )
|
||||||
if( striEqual( shader->shader, "default" ) || ( striEqual( shader->shader, "noshader" ) && !modelclip ) )
|
if( striEqual( shader.shader, "default" ) || ( striEqual( shader.shader, "noshader" ) && !modelclip ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* add build side */
|
/* add build side */
|
||||||
buildSide = &buildBrush->sides[ buildBrush->numsides ];
|
buildBrush.sides.emplace_back();
|
||||||
buildBrush->numsides++;
|
|
||||||
|
|
||||||
/* tag it */
|
/* tag it */
|
||||||
buildSide->shaderInfo = ShaderInfoForShader( shader->shader );
|
buildBrush.sides.back().shaderInfo = ShaderInfoForShader( shader.shader );
|
||||||
buildSide->planenum = side->planeNum;
|
buildBrush.sides.back().planenum = side.planeNum;
|
||||||
buildSide->winding = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !CreateBrushWindings( buildBrush ) ) {
|
if ( !CreateBrushWindings( buildBrush ) ) {
|
||||||
|
|
@ -280,31 +260,26 @@ static void ConvertBrushFast( FILE *f, int num, bspBrush_t *brush, const Vector3
|
||||||
}
|
}
|
||||||
|
|
||||||
/* iterate through build brush sides */
|
/* iterate through build brush sides */
|
||||||
for ( i = 0; i < buildBrush->numsides; i++ )
|
for ( side_t& buildSide : buildBrush.sides )
|
||||||
{
|
{
|
||||||
/* get build side */
|
|
||||||
buildSide = &buildBrush->sides[ i ];
|
|
||||||
|
|
||||||
/* get plane */
|
/* get plane */
|
||||||
buildPlane = &mapplanes[ buildSide->planenum ];
|
const plane_t& buildPlane = mapplanes[ buildSide.planenum ];
|
||||||
|
|
||||||
/* dummy check */
|
/* dummy check */
|
||||||
if ( buildSide->shaderInfo == NULL || buildSide->winding == NULL ) {
|
if ( buildSide.shaderInfo == NULL || buildSide.winding.empty() ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get texture name */
|
/* get texture name */
|
||||||
if ( striEqualPrefix( buildSide->shaderInfo->shader, "textures/" ) ) {
|
const char *texture = striEqualPrefix( buildSide.shaderInfo->shader, "textures/" )
|
||||||
texture = buildSide->shaderInfo->shader + 9;
|
? buildSide.shaderInfo->shader + 9
|
||||||
}
|
: buildSide.shaderInfo->shader;
|
||||||
else{
|
|
||||||
texture = buildSide->shaderInfo->shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Vector3 pts[ 3 ];
|
||||||
{
|
{
|
||||||
Vector3 vecs[ 2 ];
|
Vector3 vecs[ 2 ];
|
||||||
MakeNormalVectors( buildPlane->normal(), vecs[ 0 ], vecs[ 1 ] );
|
MakeNormalVectors( buildPlane.normal(), vecs[ 0 ], vecs[ 1 ] );
|
||||||
pts[ 0 ] = buildPlane->normal() * buildPlane->dist() + origin;
|
pts[ 0 ] = buildPlane.normal() * buildPlane.dist() + origin;
|
||||||
pts[ 1 ] = pts[ 0 ] + vecs[ 0 ] * 256.0f;
|
pts[ 1 ] = pts[ 0 ] + vecs[ 0 ] * 256.0f;
|
||||||
pts[ 2 ] = pts[ 0 ] + vecs[ 1 ] * 256.0f;
|
pts[ 2 ] = pts[ 0 ] + vecs[ 1 ] * 256.0f;
|
||||||
}
|
}
|
||||||
|
|
@ -343,43 +318,26 @@ static void ConvertBrushFast( FILE *f, int num, bspBrush_t *brush, const Vector3
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& origin, bool brushPrimitives ){
|
static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& origin, bool brushPrimitives ){
|
||||||
int i, j;
|
|
||||||
bspBrushSide_t *side;
|
|
||||||
side_t *buildSide;
|
|
||||||
bspShader_t *shader;
|
|
||||||
const char *texture;
|
|
||||||
Vector3 pts[ 3 ];
|
|
||||||
bspDrawVert_t *vert[3];
|
|
||||||
|
|
||||||
|
|
||||||
/* clear out build brush */
|
/* clear out build brush */
|
||||||
for ( i = 0; i < buildBrush->numsides; i++ )
|
buildBrush.sides.clear();
|
||||||
{
|
|
||||||
buildSide = &buildBrush->sides[ i ];
|
|
||||||
if ( buildSide->winding != NULL ) {
|
|
||||||
FreeWinding( buildSide->winding );
|
|
||||||
buildSide->winding = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buildBrush->numsides = 0;
|
|
||||||
|
|
||||||
bool modelclip = false;
|
bool modelclip = false;
|
||||||
/* try to guess if thats model clip */
|
/* try to guess if thats model clip */
|
||||||
if ( force ){
|
if ( force ){
|
||||||
int notNoShader = 0;
|
int notNoShader = 0;
|
||||||
modelclip = true;
|
modelclip = true;
|
||||||
for ( i = 0; i < brush->numSides; i++ )
|
for ( int i = 0; i < brush->numSides; i++ )
|
||||||
{
|
{
|
||||||
/* get side */
|
/* get side */
|
||||||
side = &bspBrushSides[ brush->firstSide + i ];
|
const bspBrushSide_t& side = bspBrushSides[ brush->firstSide + i ];
|
||||||
|
|
||||||
/* get shader */
|
/* get shader */
|
||||||
if ( side->shaderNum < 0 || side->shaderNum >= numBSPShaders ) {
|
if ( side.shaderNum < 0 || side.shaderNum >= numBSPShaders ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
shader = &bspShaders[ side->shaderNum ];
|
const bspShader_t& shader = bspShaders[ side.shaderNum ];
|
||||||
//"noshader" happens on modelclip and unwanted sides ( usually breaking complex brushes )
|
//"noshader" happens on modelclip and unwanted sides ( usually breaking complex brushes )
|
||||||
if( !striEqual( shader->shader, "noshader" ) ){
|
if( !striEqual( shader.shader, "noshader" ) ){
|
||||||
notNoShader++;
|
notNoShader++;
|
||||||
}
|
}
|
||||||
if( notNoShader > 1 ){
|
if( notNoShader > 1 ){
|
||||||
|
|
@ -390,28 +348,26 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
|
||||||
}
|
}
|
||||||
|
|
||||||
/* iterate through bsp brush sides */
|
/* iterate through bsp brush sides */
|
||||||
for ( i = 0; i < brush->numSides; i++ )
|
for ( int i = 0; i < brush->numSides; i++ )
|
||||||
{
|
{
|
||||||
/* get side */
|
/* get side */
|
||||||
side = &bspBrushSides[ brush->firstSide + i ];
|
const bspBrushSide_t& side = bspBrushSides[ brush->firstSide + i ];
|
||||||
|
|
||||||
/* get shader */
|
/* get shader */
|
||||||
if ( side->shaderNum < 0 || side->shaderNum >= numBSPShaders ) {
|
if ( side.shaderNum < 0 || side.shaderNum >= numBSPShaders ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
shader = &bspShaders[ side->shaderNum ];
|
const bspShader_t& shader = bspShaders[ side.shaderNum ];
|
||||||
//"noshader" happens on modelclip and unwanted sides ( usually breaking complex brushes )
|
//"noshader" happens on modelclip and unwanted sides ( usually breaking complex brushes )
|
||||||
if( striEqual( shader->shader, "default" ) || ( striEqual( shader->shader, "noshader" ) && !modelclip ) )
|
if( striEqual( shader.shader, "default" ) || ( striEqual( shader.shader, "noshader" ) && !modelclip ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* add build side */
|
/* add build side */
|
||||||
buildSide = &buildBrush->sides[ buildBrush->numsides ];
|
buildBrush.sides.emplace_back();
|
||||||
buildBrush->numsides++;
|
|
||||||
|
|
||||||
/* tag it */
|
/* tag it */
|
||||||
buildSide->shaderInfo = ShaderInfoForShader( shader->shader );
|
buildBrush.sides.back().shaderInfo = ShaderInfoForShader( shader.shader );
|
||||||
buildSide->planenum = side->planeNum;
|
buildBrush.sides.back().planenum = side.planeNum;
|
||||||
buildSide->winding = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make brush windings */
|
/* make brush windings */
|
||||||
|
|
@ -429,42 +385,38 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
|
||||||
}
|
}
|
||||||
|
|
||||||
/* iterate through build brush sides */
|
/* iterate through build brush sides */
|
||||||
for ( i = 0; i < buildBrush->numsides; i++ )
|
for ( side_t& buildSide : buildBrush.sides )
|
||||||
{
|
{
|
||||||
/* get build side */
|
|
||||||
buildSide = &buildBrush->sides[ i ];
|
|
||||||
|
|
||||||
/* get plane */
|
/* get plane */
|
||||||
const plane_t& buildPlane = mapplanes[ buildSide->planenum ];
|
const plane_t& buildPlane = mapplanes[ buildSide.planenum ];
|
||||||
|
|
||||||
/* dummy check */
|
/* dummy check */
|
||||||
if ( buildSide->shaderInfo == NULL || buildSide->winding == NULL ) {
|
if ( buildSide.shaderInfo == NULL || buildSide.winding.empty() ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// st-texcoords -> texMat block
|
// st-texcoords -> texMat block
|
||||||
// start out with dummy
|
// start out with dummy
|
||||||
buildSide->texMat[0] = { 1 / 32.0, 0, 0 };
|
buildSide.texMat[0] = { 1 / 32.0, 0, 0 };
|
||||||
buildSide->texMat[1] = { 0, 1 / 32.0, 0 };
|
buildSide.texMat[1] = { 0, 1 / 32.0, 0 };
|
||||||
|
|
||||||
// find surface for this side (by brute force)
|
// find surface for this side (by brute force)
|
||||||
// surface format:
|
// surface format:
|
||||||
// - meshverts point in pairs of three into verts
|
// - meshverts point in pairs of three into verts
|
||||||
// - (triangles)
|
// - (triangles)
|
||||||
// - find the triangle that has most in common with our side
|
// - find the triangle that has most in common with our
|
||||||
|
bspDrawVert_t *vert[3];
|
||||||
GetBestSurfaceTriangleMatchForBrushside( buildSide, vert );
|
GetBestSurfaceTriangleMatchForBrushside( buildSide, vert );
|
||||||
|
|
||||||
/* get texture name */
|
/* get texture name */
|
||||||
if ( striEqualPrefix( buildSide->shaderInfo->shader, "textures/" ) ) {
|
const char *texture = striEqualPrefix( buildSide.shaderInfo->shader, "textures/" )
|
||||||
texture = buildSide->shaderInfo->shader + 9;
|
? buildSide.shaderInfo->shader + 9
|
||||||
}
|
: buildSide.shaderInfo->shader;
|
||||||
else{
|
|
||||||
texture = buildSide->shaderInfo->shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Vector3 pts[ 3 ];
|
||||||
/* recheck and fix winding points, fails occur somehow */
|
/* recheck and fix winding points, fails occur somehow */
|
||||||
int match = 0;
|
int match = 0;
|
||||||
for ( const Vector3& p : ( *buildSide->winding ) ){
|
for ( const Vector3& p : buildSide.winding ){
|
||||||
if ( fabs( plane3_distance_to_point( buildPlane.plane, p ) ) < distanceEpsilon ) {
|
if ( fabs( plane3_distance_to_point( buildPlane.plane, p ) ) < distanceEpsilon ) {
|
||||||
pts[ match ] = p;
|
pts[ match ] = p;
|
||||||
match++;
|
match++;
|
||||||
|
|
@ -476,8 +428,7 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
|
||||||
|
|
||||||
if( match > 2 ){
|
if( match > 2 ){
|
||||||
//Sys_Printf( "pointsKK " );
|
//Sys_Printf( "pointsKK " );
|
||||||
Plane3f testplane;
|
if ( Plane3f testplane; PlaneFromPoints( testplane, pts ) ){
|
||||||
if ( PlaneFromPoints( testplane, pts ) ){
|
|
||||||
if( !PlaneEqual( buildPlane, testplane ) ){
|
if( !PlaneEqual( buildPlane, testplane ) ){
|
||||||
//Sys_Printf( "1: %f %f %f %f\n2: %f %f %f %f\n", buildPlane->normal[0], buildPlane->normal[1], buildPlane->normal[2], buildPlane->dist, testplane[0], testplane[1], testplane[2], testplane[3] );
|
//Sys_Printf( "1: %f %f %f %f\n2: %f %f %f %f\n", buildPlane->normal[0], buildPlane->normal[1], buildPlane->normal[2], buildPlane->dist, testplane[0], testplane[1], testplane[2], testplane[3] );
|
||||||
match--;
|
match--;
|
||||||
|
|
@ -493,8 +444,8 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
|
||||||
if( match > 2 ){
|
if( match > 2 ){
|
||||||
//Sys_Printf( "ok " );
|
//Sys_Printf( "ok " );
|
||||||
/* offset by origin */
|
/* offset by origin */
|
||||||
for ( j = 0; j < 3; j++ )
|
for ( Vector3& pt : pts )
|
||||||
pts[ j ] += origin;
|
pt += origin;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
Vector3 vecs[ 2 ];
|
Vector3 vecs[ 2 ];
|
||||||
|
|
@ -552,7 +503,7 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
|
||||||
xyJ[0], xyJ[1], stJ[i],
|
xyJ[0], xyJ[1], stJ[i],
|
||||||
xyK[0], xyK[1], stK[i]
|
xyK[0], xyK[1], stK[i]
|
||||||
);
|
);
|
||||||
buildSide->texMat[i] = { D0 / D, D1 / D, D2 / D };
|
buildSide.texMat[i] = { D0 / D, D1 / D, D2 / D };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
|
@ -572,8 +523,8 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
|
||||||
pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ],
|
pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ],
|
||||||
pts[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 2 ],
|
pts[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 2 ],
|
||||||
pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
|
pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
|
||||||
buildSide->texMat[0][0], buildSide->texMat[0][1], FRAC( buildSide->texMat[0][2] ),
|
buildSide.texMat[0][0], buildSide.texMat[0][1], FRAC( buildSide.texMat[0][2] ),
|
||||||
buildSide->texMat[1][0], buildSide->texMat[1][1], FRAC( buildSide->texMat[1][2] ),
|
buildSide.texMat[1][0], buildSide.texMat[1][1], FRAC( buildSide.texMat[1][2] ),
|
||||||
texture,
|
texture,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
@ -609,12 +560,12 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
|
||||||
tv = 2;
|
tv = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
stI[0] = vert[0]->st[0] * buildSide->shaderInfo->shaderWidth;
|
stI[0] = vert[0]->st[0] * buildSide.shaderInfo->shaderWidth;
|
||||||
stI[1] = vert[0]->st[1] * buildSide->shaderInfo->shaderHeight;
|
stI[1] = vert[0]->st[1] * buildSide.shaderInfo->shaderHeight;
|
||||||
stJ[0] = vert[1]->st[0] * buildSide->shaderInfo->shaderWidth;
|
stJ[0] = vert[1]->st[0] * buildSide.shaderInfo->shaderWidth;
|
||||||
stJ[1] = vert[1]->st[1] * buildSide->shaderInfo->shaderHeight;
|
stJ[1] = vert[1]->st[1] * buildSide.shaderInfo->shaderHeight;
|
||||||
stK[0] = vert[2]->st[0] * buildSide->shaderInfo->shaderWidth;
|
stK[0] = vert[2]->st[0] * buildSide.shaderInfo->shaderWidth;
|
||||||
stK[1] = vert[2]->st[1] * buildSide->shaderInfo->shaderHeight;
|
stK[1] = vert[2]->st[1] * buildSide.shaderInfo->shaderHeight;
|
||||||
|
|
||||||
D = Det3x3(
|
D = Det3x3(
|
||||||
vert[0]->xyz[sv], vert[0]->xyz[tv], 1,
|
vert[0]->xyz[sv], vert[0]->xyz[tv], 1,
|
||||||
|
|
@ -664,8 +615,8 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
|
||||||
scale[0] = 1.0 / sqrt( sts[0][0] * sts[0][0] + sts[0][1] * sts[0][1] );
|
scale[0] = 1.0 / sqrt( sts[0][0] * sts[0][0] + sts[0][1] * sts[0][1] );
|
||||||
scale[1] = 1.0 / sqrt( sts[1][0] * sts[1][0] + sts[1][1] * sts[1][1] );
|
scale[1] = 1.0 / sqrt( sts[1][0] * sts[1][0] + sts[1][1] * sts[1][1] );
|
||||||
rotate = radians_to_degrees( atan2( sts[0][1] * vecs[0][sv] - sts[1][0] * vecs[1][tv], sts[0][0] * vecs[0][sv] + sts[1][1] * vecs[1][tv] ) );
|
rotate = radians_to_degrees( atan2( sts[0][1] * vecs[0][sv] - sts[1][0] * vecs[1][tv], sts[0][0] * vecs[0][sv] + sts[1][1] * vecs[1][tv] ) );
|
||||||
shift[0] = buildSide->shaderInfo->shaderWidth * FRAC( sts[0][2] / buildSide->shaderInfo->shaderWidth );
|
shift[0] = buildSide.shaderInfo->shaderWidth * FRAC( sts[0][2] / buildSide.shaderInfo->shaderWidth );
|
||||||
shift[1] = buildSide->shaderInfo->shaderHeight * FRAC( sts[1][2] / buildSide->shaderInfo->shaderHeight );
|
shift[1] = buildSide.shaderInfo->shaderHeight * FRAC( sts[1][2] / buildSide.shaderInfo->shaderHeight );
|
||||||
|
|
||||||
/* print brush side */
|
/* print brush side */
|
||||||
/* ( 640 24 -224 ) ( 448 24 -224 ) ( 448 -232 -224 ) common/caulk 0 48 0 0.500000 0.500000 0 0 0 */
|
/* ( 640 24 -224 ) ( 448 24 -224 ) ( 448 -232 -224 ) common/caulk 0 48 0 0.500000 0.500000 0 0 0 */
|
||||||
|
|
@ -681,11 +632,11 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( !striEqualPrefix( buildSide->shaderInfo->shader, "textures/common/" )
|
if ( !striEqualPrefix( buildSide.shaderInfo->shader, "textures/common/" )
|
||||||
&& !striEqualPrefix( buildSide->shaderInfo->shader, "textures/system/" )
|
&& !striEqualPrefix( buildSide.shaderInfo->shader, "textures/system/" )
|
||||||
&& !strEqual( buildSide->shaderInfo->shader, "noshader" )
|
&& !strEqual( buildSide.shaderInfo->shader, "noshader" )
|
||||||
&& !strEqual( buildSide->shaderInfo->shader, "default" ) ) {
|
&& !strEqual( buildSide.shaderInfo->shader, "default" ) ) {
|
||||||
//fprintf( stderr, "no matching triangle for brushside using %s (hopefully nobody can see this side anyway)\n", buildSide->shaderInfo->shader );
|
//fprintf( stderr, "no matching triangle for brushside using %s (hopefully nobody can see this side anyway)\n", buildSide.shaderInfo->shader );
|
||||||
texture = "common/WTF";
|
texture = "common/WTF";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -882,9 +833,9 @@ static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, const Vector
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate a build brush */
|
/* allocate a build brush */
|
||||||
buildBrush = AllocBrush( 512 );
|
buildBrush.sides.reserve( MAX_BUILD_SIDES );
|
||||||
buildBrush->entityNum = 0;
|
buildBrush.entityNum = 0;
|
||||||
buildBrush->original = buildBrush;
|
buildBrush.original = &buildBrush;
|
||||||
|
|
||||||
if ( origin != g_vector3_identity ) {
|
if ( origin != g_vector3_identity ) {
|
||||||
ConvertOriginBrush( f, -1, origin, brushPrimitives );
|
ConvertOriginBrush( f, -1, origin, brushPrimitives );
|
||||||
|
|
@ -903,9 +854,6 @@ static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, const Vector
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free the build brush */
|
|
||||||
free( buildBrush );
|
|
||||||
|
|
||||||
/* go through each drawsurf in the model */
|
/* go through each drawsurf in the model */
|
||||||
for ( i = 0; i < model->numBSPSurfaces; i++ )
|
for ( i = 0; i < model->numBSPSurfaces; i++ )
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -493,33 +493,29 @@ void ProcessDecals( void ){
|
||||||
projects a decal onto a winding
|
projects a decal onto a winding
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds, winding_t *w ){
|
static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds, winding_t& w ){
|
||||||
int i, j;
|
int i, j;
|
||||||
winding_t *front, *back;
|
|
||||||
mapDrawSurface_t *ds2;
|
mapDrawSurface_t *ds2;
|
||||||
bspDrawVert_t *dv;
|
bspDrawVert_t *dv;
|
||||||
Plane3f plane;
|
Plane3f plane;
|
||||||
|
|
||||||
|
|
||||||
/* dummy check */
|
/* dummy check */
|
||||||
if ( w->size() < 3 ) {
|
if ( w.size() < 3 ) {
|
||||||
FreeWinding( w );
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* offset by entity origin */
|
/* offset by entity origin */
|
||||||
for ( Vector3& p : *w )
|
for ( Vector3& p : w )
|
||||||
p += entityOrigin;
|
p += entityOrigin;
|
||||||
|
|
||||||
/* make a plane from the winding */
|
/* make a plane from the winding */
|
||||||
if ( !PlaneFromPoints( plane, w->data() ) ) {
|
if ( !PlaneFromPoints( plane, w.data() ) ) {
|
||||||
FreeWinding( w );
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* backface check */
|
/* backface check */
|
||||||
if ( vector3_dot( dp->planes[ 0 ].normal(), plane.normal() ) < -0.0001f ) {
|
if ( vector3_dot( dp->planes[ 0 ].normal(), plane.normal() ) < -0.0001f ) {
|
||||||
FreeWinding( w );
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -527,25 +523,20 @@ static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds,
|
||||||
for ( i = 0; i < dp->numPlanes; i++ )
|
for ( i = 0; i < dp->numPlanes; i++ )
|
||||||
{
|
{
|
||||||
/* chop winding by the plane */
|
/* chop winding by the plane */
|
||||||
ClipWindingEpsilonStrict( *w, dp->planes[ i ], 0.0625f, front, back ); /* strict, if identical plane we don't want to keep it */
|
auto [front, back] = ClipWindingEpsilonStrict( w, dp->planes[ i ], 0.0625f ); /* strict, if identical plane we don't want to keep it */
|
||||||
FreeWinding( w );
|
|
||||||
|
|
||||||
/* lose the front fragment */
|
/* lose the front fragment */
|
||||||
if ( front != NULL ) {
|
|
||||||
FreeWinding( front );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if nothing left in back, then bail */
|
/* if nothing left in back, then bail */
|
||||||
if ( back == NULL ) {
|
if ( back.empty() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reset winding */
|
/* reset winding */
|
||||||
w = back;
|
w.swap( back );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* nothing left? */
|
/* nothing left? */
|
||||||
if ( w == NULL || w->size() < 3 ) {
|
if ( w.size() < 3 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -563,7 +554,7 @@ static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds,
|
||||||
ds2->fogNum = ds->fogNum; /* why was this -1? */
|
ds2->fogNum = ds->fogNum; /* why was this -1? */
|
||||||
ds2->lightmapScale = ds->lightmapScale;
|
ds2->lightmapScale = ds->lightmapScale;
|
||||||
ds2->shadeAngleDegrees = ds->shadeAngleDegrees;
|
ds2->shadeAngleDegrees = ds->shadeAngleDegrees;
|
||||||
ds2->numVerts = w->size();
|
ds2->numVerts = w.size();
|
||||||
ds2->verts = safe_calloc( ds2->numVerts * sizeof( *ds2->verts ) );
|
ds2->verts = safe_calloc( ds2->numVerts * sizeof( *ds2->verts ) );
|
||||||
|
|
||||||
/* set vertexes */
|
/* set vertexes */
|
||||||
|
|
@ -573,12 +564,12 @@ static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds,
|
||||||
dv = &ds2->verts[ i ];
|
dv = &ds2->verts[ i ];
|
||||||
|
|
||||||
/* set alpha */
|
/* set alpha */
|
||||||
const float d = plane3_distance_to_point( dp->planes[ 0 ], ( *w )[ i ] );
|
const float d = plane3_distance_to_point( dp->planes[ 0 ], w[ i ] );
|
||||||
const float d2 = plane3_distance_to_point( dp->planes[ 1 ], ( *w )[ i ] );
|
const float d2 = plane3_distance_to_point( dp->planes[ 1 ], w[ i ] );
|
||||||
const float alpha = 255.0f * d2 / ( d + d2 );
|
const float alpha = 255.0f * d2 / ( d + d2 );
|
||||||
|
|
||||||
/* set misc */
|
/* set misc */
|
||||||
dv->xyz = ( *w )[ i ] - entityOrigin;
|
dv->xyz = w[ i ] - entityOrigin;
|
||||||
dv->normal = plane.normal();
|
dv->normal = plane.normal();
|
||||||
dv->st[ 0 ] = vector3_dot( dv->xyz, dp->texMat[ 0 ].vec3() ) + dp->texMat[ 0 ][ 3 ];
|
dv->st[ 0 ] = vector3_dot( dv->xyz, dp->texMat[ 0 ].vec3() ) + dp->texMat[ 0 ][ 3 ];
|
||||||
dv->st[ 1 ] = vector3_dot( dv->xyz, dp->texMat[ 1 ].vec3() ) + dp->texMat[ 1 ][ 3 ];
|
dv->st[ 1 ] = vector3_dot( dv->xyz, dp->texMat[ 1 ].vec3() ) + dp->texMat[ 1 ][ 3 ];
|
||||||
|
|
@ -614,7 +605,7 @@ static void ProjectDecalOntoFace( decalProjector_t *dp, mapDrawSurface_t *ds ){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate decal */
|
/* generate decal */
|
||||||
winding_t *w = WindingFromDrawSurf( ds );
|
winding_t w = WindingFromDrawSurf( ds );
|
||||||
ProjectDecalOntoWinding( dp, ds, w );
|
ProjectDecalOntoWinding( dp, ds, w );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -628,7 +619,6 @@ static void ProjectDecalOntoFace( decalProjector_t *dp, mapDrawSurface_t *ds ){
|
||||||
static void ProjectDecalOntoPatch( decalProjector_t *dp, mapDrawSurface_t *ds ){
|
static void ProjectDecalOntoPatch( decalProjector_t *dp, mapDrawSurface_t *ds ){
|
||||||
int x, y, pw[ 5 ], r, iterations;
|
int x, y, pw[ 5 ], r, iterations;
|
||||||
mesh_t src, *mesh, *subdivided;
|
mesh_t src, *mesh, *subdivided;
|
||||||
winding_t *w;
|
|
||||||
|
|
||||||
|
|
||||||
/* backface check */
|
/* backface check */
|
||||||
|
|
@ -668,18 +658,18 @@ static void ProjectDecalOntoPatch( decalProjector_t *dp, mapDrawSurface_t *ds ){
|
||||||
r = ( x + y ) & 1;
|
r = ( x + y ) & 1;
|
||||||
|
|
||||||
/* generate decal for first triangle */
|
/* generate decal for first triangle */
|
||||||
w = AllocWinding( 3 );
|
winding_t w{
|
||||||
w->push_back( mesh->verts[ pw[ r + 0 ] ].xyz );
|
mesh->verts[ pw[ r + 0 ] ].xyz,
|
||||||
w->push_back( mesh->verts[ pw[ r + 1 ] ].xyz );
|
mesh->verts[ pw[ r + 1 ] ].xyz,
|
||||||
w->push_back( mesh->verts[ pw[ r + 2 ] ].xyz );
|
mesh->verts[ pw[ r + 2 ] ].xyz };
|
||||||
ProjectDecalOntoWinding( dp, ds, w );
|
ProjectDecalOntoWinding( dp, ds, w );
|
||||||
|
|
||||||
/* generate decal for second triangle */
|
/* generate decal for second triangle */
|
||||||
w = AllocWinding( 3 );
|
winding_t w2{
|
||||||
w->push_back( mesh->verts[ pw[ r + 0 ] ].xyz );
|
mesh->verts[ pw[ r + 0 ] ].xyz,
|
||||||
w->push_back( mesh->verts[ pw[ r + 2 ] ].xyz );
|
mesh->verts[ pw[ r + 2 ] ].xyz,
|
||||||
w->push_back( mesh->verts[ pw[ r + 3 ] ].xyz );
|
mesh->verts[ pw[ r + 3 ] ].xyz };
|
||||||
ProjectDecalOntoWinding( dp, ds, w );
|
ProjectDecalOntoWinding( dp, ds, w2 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -714,10 +704,10 @@ static void ProjectDecalOntoTriangles( decalProjector_t *dp, mapDrawSurface_t *d
|
||||||
for ( int i = 0; i < ds->numIndexes; i += 3 )
|
for ( int i = 0; i < ds->numIndexes; i += 3 )
|
||||||
{
|
{
|
||||||
/* generate decal */
|
/* generate decal */
|
||||||
winding_t *w = AllocWinding( 3 );
|
winding_t w{
|
||||||
w->push_back( ds->verts[ ds->indexes[ i ] ].xyz );
|
ds->verts[ ds->indexes[ i ] ].xyz,
|
||||||
w->push_back( ds->verts[ ds->indexes[ i + 1 ] ].xyz );
|
ds->verts[ ds->indexes[ i + 1 ] ].xyz,
|
||||||
w->push_back( ds->verts[ ds->indexes[ i + 2 ] ].xyz );
|
ds->verts[ ds->indexes[ i + 2 ] ].xyz };
|
||||||
ProjectDecalOntoWinding( dp, ds, w );
|
ProjectDecalOntoWinding( dp, ds, w );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ int c_faceLeafs;
|
||||||
finds the best split plane for this node
|
finds the best split plane for this node
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void SelectSplitPlaneNum( node_t *node, const facelist_t& list, int *splitPlaneNum, int *compileFlags ){
|
static void SelectSplitPlaneNum( const node_t *node, const facelist_t& list, int *splitPlaneNum, int *compileFlags ){
|
||||||
//int frontC,backC,splitsC,facingC;
|
//int frontC,backC,splitsC,facingC;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -217,21 +217,17 @@ void BuildFaceTree_r( node_t *node, facelist_t& list ){
|
||||||
|
|
||||||
/* switch on side */
|
/* switch on side */
|
||||||
if ( side == eSideCross ) {
|
if ( side == eSideCross ) {
|
||||||
winding_t *frontWinding, *backWinding;
|
auto [frontWinding, backWinding] = ClipWindingEpsilonStrict( split.w, plane.plane, CLIP_EPSILON * 2 ); /* strict; if no winding is left, we have a "virtually identical" plane and don't want to split by it */
|
||||||
ClipWindingEpsilonStrict( split.w, plane.plane, CLIP_EPSILON * 2,
|
if ( !frontWinding.empty() ) {
|
||||||
frontWinding, backWinding ); /* strict; if no winding is left, we have a "virtually identical" plane and don't want to split by it */
|
|
||||||
if ( frontWinding ) {
|
|
||||||
face_t& newFace = childLists[0].emplace_front();
|
face_t& newFace = childLists[0].emplace_front();
|
||||||
newFace.w.swap( *frontWinding );
|
newFace.w.swap( frontWinding );
|
||||||
FreeWinding( frontWinding );
|
|
||||||
newFace.planenum = split.planenum;
|
newFace.planenum = split.planenum;
|
||||||
newFace.priority = split.priority;
|
newFace.priority = split.priority;
|
||||||
newFace.compileFlags = split.compileFlags;
|
newFace.compileFlags = split.compileFlags;
|
||||||
}
|
}
|
||||||
if ( backWinding ) {
|
if ( !backWinding.empty() ) {
|
||||||
face_t& newFace = childLists[1].emplace_front();
|
face_t& newFace = childLists[1].emplace_front();
|
||||||
newFace.w.swap( *backWinding );
|
newFace.w.swap( backWinding );
|
||||||
FreeWinding( backWinding );
|
|
||||||
newFace.planenum = split.planenum;
|
newFace.planenum = split.planenum;
|
||||||
newFace.priority = split.priority;
|
newFace.priority = split.priority;
|
||||||
newFace.compileFlags = split.compileFlags;
|
newFace.compileFlags = split.compileFlags;
|
||||||
|
|
@ -299,15 +295,15 @@ void BuildFaceTree_r( node_t *node, facelist_t& list ){
|
||||||
List will be freed before returning
|
List will be freed before returning
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
tree_t *FaceBSP( facelist_t& list ) {
|
tree_t FaceBSP( facelist_t& list ) {
|
||||||
Sys_FPrintf( SYS_VRB, "--- FaceBSP ---\n" );
|
Sys_FPrintf( SYS_VRB, "--- FaceBSP ---\n" );
|
||||||
|
|
||||||
tree_t *tree = AllocTree();
|
tree_t tree{};
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for ( const face_t& face : list )
|
for ( const face_t& face : list )
|
||||||
{
|
{
|
||||||
WindingExtendBounds( face.w, tree->minmax );
|
WindingExtendBounds( face.w, tree.minmax );
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
Sys_FPrintf( SYS_VRB, "%9d faces\n", count );
|
Sys_FPrintf( SYS_VRB, "%9d faces\n", count );
|
||||||
|
|
@ -317,11 +313,11 @@ tree_t *FaceBSP( facelist_t& list ) {
|
||||||
plane.counter = 0;
|
plane.counter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
tree->headnode = AllocNode();
|
tree.headnode = AllocNode();
|
||||||
tree->headnode->minmax = tree->minmax;
|
tree.headnode->minmax = tree.minmax;
|
||||||
c_faceLeafs = 0;
|
c_faceLeafs = 0;
|
||||||
|
|
||||||
BuildFaceTree_r( tree->headnode, list );
|
BuildFaceTree_r( tree.headnode, list );
|
||||||
|
|
||||||
Sys_FPrintf( SYS_VRB, "%9d leafs\n", c_faceLeafs );
|
Sys_FPrintf( SYS_VRB, "%9d leafs\n", c_faceLeafs );
|
||||||
|
|
||||||
|
|
@ -335,21 +331,20 @@ tree_t *FaceBSP( facelist_t& list ) {
|
||||||
get structural brush faces
|
get structural brush faces
|
||||||
*/
|
*/
|
||||||
|
|
||||||
facelist_t MakeStructuralBSPFaceList( const brush_t *list ){
|
facelist_t MakeStructuralBSPFaceList( const brushlist_t& list ){
|
||||||
facelist_t flist;
|
facelist_t flist;
|
||||||
|
|
||||||
for ( const brush_t *b = list; b != NULL; b = b->next )
|
for ( const brush_t &b : list )
|
||||||
{
|
{
|
||||||
if ( !deepBSP && b->detail ) {
|
if ( !deepBSP && b.detail ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i = 0; i < b->numsides; i++ )
|
for ( const side_t& s : b.sides )
|
||||||
{
|
{
|
||||||
/* get side and winding */
|
/* get winding */
|
||||||
const side_t& s = b->sides[ i ];
|
const winding_t& w = s.winding;
|
||||||
const winding_t *w = s.winding;
|
if ( w.empty() ) {
|
||||||
if ( w == NULL ) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -360,10 +355,10 @@ facelist_t MakeStructuralBSPFaceList( const brush_t *list ){
|
||||||
|
|
||||||
/* allocate a face */
|
/* allocate a face */
|
||||||
face_t& f = flist.emplace_front();
|
face_t& f = flist.emplace_front();
|
||||||
f.w = *w;
|
f.w = w;
|
||||||
f.planenum = s.planenum & ~1;
|
f.planenum = s.planenum & ~1;
|
||||||
f.compileFlags = s.compileFlags; /* ydnar */
|
f.compileFlags = s.compileFlags; /* ydnar */
|
||||||
if ( b->detail ) {
|
if ( b.detail ) {
|
||||||
f.compileFlags |= C_DETAIL;
|
f.compileFlags |= C_DETAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -394,21 +389,20 @@ facelist_t MakeStructuralBSPFaceList( const brush_t *list ){
|
||||||
get visible brush faces
|
get visible brush faces
|
||||||
*/
|
*/
|
||||||
|
|
||||||
facelist_t MakeVisibleBSPFaceList( const brush_t *list ){
|
facelist_t MakeVisibleBSPFaceList( const brushlist_t& list ){
|
||||||
facelist_t flist;
|
facelist_t flist;
|
||||||
|
|
||||||
for ( const brush_t *b = list; b != NULL; b = b->next )
|
for ( const brush_t& b : list )
|
||||||
{
|
{
|
||||||
if ( !deepBSP && b->detail ) {
|
if ( !deepBSP && b.detail ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i = 0; i < b->numsides; i++ )
|
for ( const side_t& s : b.sides )
|
||||||
{
|
{
|
||||||
/* get side and winding */
|
/* get winding */
|
||||||
const side_t& s = b->sides[ i ];
|
const winding_t& w = s.visibleHull;
|
||||||
const winding_t *w = s.visibleHull;
|
if ( w.empty() ) {
|
||||||
if ( w == NULL ) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -419,10 +413,10 @@ facelist_t MakeVisibleBSPFaceList( const brush_t *list ){
|
||||||
|
|
||||||
/* allocate a face */
|
/* allocate a face */
|
||||||
face_t& f = flist.emplace_front();
|
face_t& f = flist.emplace_front();
|
||||||
f.w = *w;
|
f.w = w;
|
||||||
f.planenum = s.planenum & ~1;
|
f.planenum = s.planenum & ~1;
|
||||||
f.compileFlags = s.compileFlags; /* ydnar */
|
f.compileFlags = s.compileFlags; /* ydnar */
|
||||||
if ( b->detail ) {
|
if ( b.detail ) {
|
||||||
f.compileFlags |= C_DETAIL;
|
f.compileFlags |= C_DETAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -244,9 +244,8 @@ void SplitMeshByPlane( mesh_t *in, const Plane3f& plane, mesh_t **front, mesh_t
|
||||||
chops a patch up by a fog brush
|
chops a patch up by a fog brush
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool ChopPatchSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){
|
bool ChopPatchSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, const brush_t *b ){
|
||||||
int i, j;
|
int i, j;
|
||||||
side_t *s;
|
|
||||||
mesh_t *outside[MAX_BRUSH_SIDES];
|
mesh_t *outside[MAX_BRUSH_SIDES];
|
||||||
int numOutside;
|
int numOutside;
|
||||||
mesh_t *m, *front, *back;
|
mesh_t *m, *front, *back;
|
||||||
|
|
@ -259,8 +258,7 @@ bool ChopPatchSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){
|
||||||
// some messy patch clipping issues
|
// some messy patch clipping issues
|
||||||
|
|
||||||
for ( i = 4 ; i <= 5 ; i++ ) {
|
for ( i = 4 ; i <= 5 ; i++ ) {
|
||||||
s = &b->sides[ i ];
|
const plane_t& plane = mapplanes[ b->sides[ i ].planenum ];
|
||||||
const plane_t& plane = mapplanes[ s->planenum ];
|
|
||||||
|
|
||||||
SplitMeshByPlane( m, plane.plane, &front, &back );
|
SplitMeshByPlane( m, plane.plane, &front, &back );
|
||||||
|
|
||||||
|
|
@ -331,26 +329,23 @@ bool ChopPatchSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){
|
||||||
creates a winding from a surface's verts
|
creates a winding from a surface's verts
|
||||||
*/
|
*/
|
||||||
|
|
||||||
winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds ){
|
winding_t WindingFromDrawSurf( const mapDrawSurface_t *ds ){
|
||||||
winding_t *w;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
// we use the first point of the surface, maybe something more clever would be useful
|
// we use the first point of the surface, maybe something more clever would be useful
|
||||||
// (actually send the whole draw surface would be cool?)
|
// (actually send the whole draw surface would be cool?)
|
||||||
if ( ds->numVerts >= MAX_POINTS_ON_WINDING ) {
|
if ( ds->numVerts >= MAX_POINTS_ON_WINDING ) {
|
||||||
const int max = std::min( ds->numVerts, 256 );
|
const int max = std::min( ds->numVerts, 256 );
|
||||||
Vector3 p[256];
|
Vector3 p[256];
|
||||||
|
|
||||||
for ( i = 0; i < max; i++ ) {
|
for ( int i = 0; i < max; i++ ) {
|
||||||
p[i] = ds->verts[i].xyz;
|
p[i] = ds->verts[i].xyz;
|
||||||
}
|
}
|
||||||
|
|
||||||
xml_Winding( "WindingFromDrawSurf failed: MAX_POINTS_ON_WINDING exceeded", p, max, true );
|
xml_Winding( "WindingFromDrawSurf failed: MAX_POINTS_ON_WINDING exceeded", p, max, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
w = AllocWinding( ds->numVerts );
|
winding_t w = AllocWinding( ds->numVerts );
|
||||||
for ( i = 0; i < ds->numVerts; i++ ) {
|
for ( int i = 0; i < ds->numVerts; i++ ) {
|
||||||
w->push_back( ds->verts[i].xyz );
|
w.push_back( ds->verts[i].xyz );
|
||||||
}
|
}
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
@ -362,13 +357,8 @@ winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds ){
|
||||||
chops up a face drawsurface by a fog brush, with a potential fragment left inside
|
chops up a face drawsurface by a fog brush, with a potential fragment left inside
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool ChopFaceSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){
|
bool ChopFaceSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, const brush_t *b ){
|
||||||
int i, j;
|
std::list<winding_t> outside;
|
||||||
side_t *s;
|
|
||||||
winding_t *w;
|
|
||||||
winding_t *front, *back;
|
|
||||||
winding_t *outside[ MAX_BRUSH_SIDES ];
|
|
||||||
int numOutside;
|
|
||||||
mapDrawSurface_t *newds;
|
mapDrawSurface_t *newds;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -378,58 +368,51 @@ bool ChopFaceSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initial setup */
|
/* initial setup */
|
||||||
w = WindingFromDrawSurf( ds );
|
winding_t w = WindingFromDrawSurf( ds );
|
||||||
numOutside = 0;
|
|
||||||
|
|
||||||
/* chop by each brush side */
|
/* chop by each brush side */
|
||||||
for ( i = 0; i < b->numsides; i++ )
|
for ( const side_t& side : b->sides )
|
||||||
{
|
{
|
||||||
/* get brush side and plane */
|
/* get brush plane */
|
||||||
s = &b->sides[ i ];
|
const plane_t& plane = mapplanes[ side.planenum ];
|
||||||
const plane_t& plane = mapplanes[ s->planenum ];
|
|
||||||
|
|
||||||
/* handle coplanar outfacing (don't fog) */
|
/* handle coplanar outfacing (don't fog) */
|
||||||
if ( ds->sideRef->side->planenum == s->planenum ) {
|
if ( ds->sideRef->side->planenum == side.planenum ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle coplanar infacing (keep inside) */
|
/* handle coplanar infacing (keep inside) */
|
||||||
if ( ( ds->sideRef->side->planenum ^ 1 ) == s->planenum ) {
|
if ( ( ds->sideRef->side->planenum ^ 1 ) == side.planenum ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* general case */
|
/* general case */
|
||||||
ClipWindingEpsilonStrict( *w, plane.plane, ON_EPSILON, front, back ); /* strict; if plane is "almost identical" to face, both ways to continue can be wrong, so we better not fog it */
|
auto [front, back] = ClipWindingEpsilonStrict( w, plane.plane, ON_EPSILON ); /* strict; if plane is "almost identical" to face, both ways to continue can be wrong, so we better not fog it */
|
||||||
FreeWinding( w );
|
|
||||||
|
|
||||||
if ( back == NULL ) {
|
if ( back.empty() ) {
|
||||||
/* nothing actually contained inside */
|
/* nothing actually contained inside */
|
||||||
for ( j = 0; j < numOutside; j++ )
|
|
||||||
FreeWinding( outside[ j ] );
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( front != NULL ) {
|
if ( !front.empty() ) {
|
||||||
if ( numOutside == MAX_BRUSH_SIDES ) {
|
if ( outside.size() == MAX_BRUSH_SIDES ) {
|
||||||
Error( "MAX_BRUSH_SIDES" );
|
Error( "MAX_BRUSH_SIDES" );
|
||||||
}
|
}
|
||||||
outside[ numOutside ] = front;
|
outside.push_back( std::move( front ) );
|
||||||
numOutside++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
w = back;
|
w.swap( back );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fixme: celshaded surface fragment errata */
|
/* fixme: celshaded surface fragment errata */
|
||||||
|
|
||||||
/* all of outside fragments become separate drawsurfs */
|
/* all of outside fragments become separate drawsurfs */
|
||||||
numFogFragments += numOutside;
|
numFogFragments += outside.size();
|
||||||
s = ds->sideRef->side;
|
const side_t *s = ds->sideRef->side;
|
||||||
for ( i = 0; i < numOutside; i++ )
|
for ( const winding_t& wi : outside )
|
||||||
{
|
{
|
||||||
newds = DrawSurfaceForSide( e, ds->mapBrush, s, *outside[ i ] );
|
newds = DrawSurfaceForSide( e, *ds->mapBrush, *s, wi );
|
||||||
newds->fogNum = ds->fogNum;
|
newds->fogNum = ds->fogNum;
|
||||||
FreeWinding( outside[ i ] );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ydnar: the old code neglected to snap to 0.125 for the fragment
|
/* ydnar: the old code neglected to snap to 0.125 for the fragment
|
||||||
|
|
@ -437,7 +420,7 @@ bool ChopFaceSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){
|
||||||
the right thing and uses the original surface's brush side */
|
the right thing and uses the original surface's brush side */
|
||||||
|
|
||||||
/* build a drawsurf for it */
|
/* build a drawsurf for it */
|
||||||
newds = DrawSurfaceForSide( e, ds->mapBrush, s, *w );
|
newds = DrawSurfaceForSide( e, *ds->mapBrush, *s, w );
|
||||||
if ( newds == NULL ) {
|
if ( newds == NULL ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -562,16 +545,11 @@ void FogDrawSurfaces( entity_t *e ){
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int FogForPoint( const Vector3& point, float epsilon ){
|
int FogForPoint( const Vector3& point, float epsilon ){
|
||||||
int fogNum, i, j;
|
|
||||||
bool inside;
|
|
||||||
brush_t *brush;
|
|
||||||
|
|
||||||
|
|
||||||
/* start with bogus fog num */
|
/* start with bogus fog num */
|
||||||
fogNum = defaultFogNum;
|
int fogNum = defaultFogNum;
|
||||||
|
|
||||||
/* walk the list of fog volumes */
|
/* walk the list of fog volumes */
|
||||||
for ( i = 0; i < numMapFogs; i++ )
|
for ( int i = 0; i < numMapFogs; i++ )
|
||||||
{
|
{
|
||||||
/* sof2: global fog doesn't reference a brush */
|
/* sof2: global fog doesn't reference a brush */
|
||||||
if ( mapFogs[ i ].brush == NULL ) {
|
if ( mapFogs[ i ].brush == NULL ) {
|
||||||
|
|
@ -579,15 +557,13 @@ int FogForPoint( const Vector3& point, float epsilon ){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get fog brush */
|
|
||||||
brush = mapFogs[ i ].brush;
|
|
||||||
|
|
||||||
/* check point against all planes */
|
/* check point against all planes */
|
||||||
inside = true;
|
bool inside = true;
|
||||||
for ( j = 0; j < brush->numsides && inside; j++ )
|
for ( const side_t& side : mapFogs[ i ].brush->sides )
|
||||||
{
|
{
|
||||||
if ( plane3_distance_to_point( mapplanes[ brush->sides[ j ].planenum ].plane, point ) > epsilon ) {
|
if ( plane3_distance_to_point( mapplanes[ side.planenum ].plane, point ) > epsilon ) {
|
||||||
inside = false;
|
inside = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -628,7 +604,7 @@ int FogForBounds( const MinMax& minmax, float epsilon ){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get fog brush */
|
/* get fog brush */
|
||||||
brush_t *brush = mapFogs[ i ].brush;
|
const brush_t *brush = mapFogs[ i ].brush;
|
||||||
|
|
||||||
/* get bounds */
|
/* get bounds */
|
||||||
const MinMax fogMinmax( brush->minmax.mins - Vector3( epsilon ),
|
const MinMax fogMinmax( brush->minmax.mins - Vector3( epsilon ),
|
||||||
|
|
@ -663,11 +639,6 @@ int FogForBounds( const MinMax& minmax, float epsilon ){
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void CreateMapFogs( void ){
|
void CreateMapFogs( void ){
|
||||||
int j;
|
|
||||||
brush_t *brush;
|
|
||||||
fog_t *fog;
|
|
||||||
|
|
||||||
|
|
||||||
/* skip? */
|
/* skip? */
|
||||||
if ( nofog ) {
|
if ( nofog ) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -680,10 +651,10 @@ void CreateMapFogs( void ){
|
||||||
for ( const auto& e : entities )
|
for ( const auto& e : entities )
|
||||||
{
|
{
|
||||||
/* walk entity brushes */
|
/* walk entity brushes */
|
||||||
for ( brush = e.brushes; brush != NULL; brush = brush->next )
|
for ( const brush_t& brush : e.brushes )
|
||||||
{
|
{
|
||||||
/* ignore non-fog brushes */
|
/* ignore non-fog brushes */
|
||||||
if ( !brush->contentShader->fogParms ) {
|
if ( !brush.contentShader->fogParms ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -693,21 +664,21 @@ void CreateMapFogs( void ){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set up fog */
|
/* set up fog */
|
||||||
fog = &mapFogs[ numMapFogs++ ];
|
fog_t& fog = mapFogs[ numMapFogs++ ];
|
||||||
fog->si = brush->contentShader;
|
fog.si = brush.contentShader;
|
||||||
fog->brush = brush;
|
fog.brush = &brush;
|
||||||
fog->visibleSide = -1;
|
fog.visibleSide = -1;
|
||||||
|
|
||||||
/* if shader specifies an explicit direction, then find a matching brush side with an opposed normal */
|
/* if shader specifies an explicit direction, then find a matching brush side with an opposed normal */
|
||||||
if ( vector3_length( fog->si->fogDir ) ) {
|
if ( vector3_length( fog.si->fogDir ) ) {
|
||||||
/* flip it */
|
/* flip it */
|
||||||
const Vector3 invFogDir = -fog->si->fogDir;
|
const Vector3 invFogDir = -fog.si->fogDir;
|
||||||
|
|
||||||
/* find the brush side */
|
/* find the brush side */
|
||||||
for ( j = 0; j < brush->numsides; j++ )
|
for ( size_t j = 0; j < brush.sides.size(); ++j )
|
||||||
{
|
{
|
||||||
if ( VectorCompare( invFogDir, mapplanes[ brush->sides[ j ].planenum ].normal() ) ) {
|
if ( VectorCompare( invFogDir, mapplanes[ brush.sides[ j ].planenum ].normal() ) ) {
|
||||||
fog->visibleSide = j;
|
fog.visibleSide = j;
|
||||||
//% Sys_Printf( "Brush num: %d Side num: %d\n", fog->brushNum, fog->visibleSide );
|
//% Sys_Printf( "Brush num: %d Side num: %d\n", fog->brushNum, fog->visibleSide );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -728,20 +699,20 @@ void CreateMapFogs( void ){
|
||||||
Sys_FPrintf( SYS_VRB, "Map has global fog shader %s\n", globalFog );
|
Sys_FPrintf( SYS_VRB, "Map has global fog shader %s\n", globalFog );
|
||||||
|
|
||||||
/* set up fog */
|
/* set up fog */
|
||||||
fog = &mapFogs[ numMapFogs++ ];
|
fog_t& fog = mapFogs[ numMapFogs++ ];
|
||||||
fog->si = ShaderInfoForShaderNull( globalFog );
|
fog.si = ShaderInfoForShaderNull( globalFog );
|
||||||
if ( fog->si == NULL ) {
|
if ( fog.si == NULL ) {
|
||||||
Error( "Invalid shader \"%s\" referenced trying to add global fog", globalFog );
|
Error( "Invalid shader \"%s\" referenced trying to add global fog", globalFog );
|
||||||
}
|
}
|
||||||
fog->brush = NULL;
|
fog.brush = NULL;
|
||||||
fog->visibleSide = -1;
|
fog.visibleSide = -1;
|
||||||
|
|
||||||
/* set as default fog */
|
/* set as default fog */
|
||||||
defaultFogNum = numMapFogs - 1;
|
defaultFogNum = numMapFogs - 1;
|
||||||
|
|
||||||
/* mark all worldspawn brushes as fogged */
|
/* mark all worldspawn brushes as fogged */
|
||||||
for ( brush = entities[ 0 ].brushes; brush != NULL; brush = brush->next )
|
for ( brush_t& brush : entities[ 0 ].brushes )
|
||||||
ApplySurfaceParm( "fog", &brush->contentFlags, NULL, &brush->compileFlags );
|
ApplySurfaceParm( "fog", &brush.contentFlags, NULL, &brush.compileFlags );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* emit some stats */
|
/* emit some stats */
|
||||||
|
|
|
||||||
|
|
@ -54,14 +54,14 @@
|
||||||
TTimo: builds a polyline xml node
|
TTimo: builds a polyline xml node
|
||||||
=============
|
=============
|
||||||
*/
|
*/
|
||||||
xmlNodePtr LeakFile( tree_t *tree ){
|
xmlNodePtr LeakFile( const tree_t& tree ){
|
||||||
Vector3 mid;
|
Vector3 mid;
|
||||||
FILE *linefile;
|
FILE *linefile;
|
||||||
node_t *node;
|
const node_t *node;
|
||||||
int count;
|
int count;
|
||||||
xmlNodePtr xml_node, point;
|
xmlNodePtr xml_node, point;
|
||||||
|
|
||||||
if ( !tree->outside_node.occupied ) {
|
if ( !tree.outside_node.occupied ) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,12 +76,12 @@ xmlNodePtr LeakFile( tree_t *tree ){
|
||||||
xml_node = xmlNewNode( NULL, (const xmlChar*)"polyline" );
|
xml_node = xmlNewNode( NULL, (const xmlChar*)"polyline" );
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
node = &tree->outside_node;
|
node = &tree.outside_node;
|
||||||
while ( node->occupied > 1 )
|
while ( node->occupied > 1 )
|
||||||
{
|
{
|
||||||
int next;
|
int next;
|
||||||
portal_t *p, *nextportal = NULL;
|
const portal_t *p, *nextportal = NULL;
|
||||||
node_t *nextnode = NULL;
|
const node_t *nextnode = NULL;
|
||||||
int s;
|
int s;
|
||||||
|
|
||||||
// find the best portal exit
|
// find the best portal exit
|
||||||
|
|
@ -97,7 +97,7 @@ xmlNodePtr LeakFile( tree_t *tree ){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node = nextnode;
|
node = nextnode;
|
||||||
mid = WindingCenter( *nextportal->winding );
|
mid = WindingCenter( nextportal->winding );
|
||||||
fprintf( linefile, "%f %f %f\n", mid[0], mid[1], mid[2] );
|
fprintf( linefile, "%f %f %f\n", mid[0], mid[1], mid[2] );
|
||||||
point = xml_NodeForVec( mid );
|
point = xml_NodeForVec( mid );
|
||||||
xmlAddChild( xml_node, point );
|
xmlAddChild( xml_node, point );
|
||||||
|
|
|
||||||
|
|
@ -468,7 +468,7 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw
|
||||||
light.si = si;
|
light.si = si;
|
||||||
light.fade = 1.0f;
|
light.fade = 1.0f;
|
||||||
/* create a regular winding */
|
/* create a regular winding */
|
||||||
light.w = AllocWinding_( rw->numVerts );
|
light.w = AllocWinding( rw->numVerts );
|
||||||
for ( i = 0; i < rw->numVerts; i++ )
|
for ( i = 0; i < rw->numVerts; i++ )
|
||||||
{
|
{
|
||||||
light.w.push_back( rw->verts[ i ].xyz );
|
light.w.push_back( rw->verts[ i ].xyz );
|
||||||
|
|
@ -548,7 +548,7 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create a regular winding */
|
/* create a regular winding */
|
||||||
splash.w = AllocWinding_( rw->numVerts );
|
splash.w = AllocWinding( rw->numVerts );
|
||||||
for ( i = 0; i < rw->numVerts; i++ )
|
for ( i = 0; i < rw->numVerts; i++ )
|
||||||
splash.w.push_back( rw->verts[rw->numVerts - 1 - i].xyz + normal * si->backsplashDistance );
|
splash.w.push_back( rw->verts[rw->numVerts - 1 - i].xyz + normal * si->backsplashDistance );
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -718,13 +718,12 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor
|
||||||
if ( PlaneFromPoints( plane, points ) ) {
|
if ( PlaneFromPoints( plane, points ) ) {
|
||||||
|
|
||||||
/* build a brush */
|
/* build a brush */
|
||||||
buildBrush = AllocBrush( 48 );
|
buildBrush.sides.reserve( MAX_BUILD_SIDES );
|
||||||
buildBrush->entityNum = mapEntityNum;
|
buildBrush.entityNum = mapEntityNum;
|
||||||
buildBrush->original = buildBrush;
|
buildBrush.contentShader = si;
|
||||||
buildBrush->contentShader = si;
|
buildBrush.compileFlags = si->compileFlags;
|
||||||
buildBrush->compileFlags = si->compileFlags;
|
buildBrush.contentFlags = si->contentFlags;
|
||||||
buildBrush->contentFlags = si->contentFlags;
|
buildBrush.detail = true;
|
||||||
buildBrush->detail = true;
|
|
||||||
|
|
||||||
//snap points before using them for further calculations
|
//snap points before using them for further calculations
|
||||||
//precision suffers a lot, when two of normal values are under .00025 (often no collision, knocking up effect in ioq3)
|
//precision suffers a lot, when two of normal values are under .00025 (often no collision, knocking up effect in ioq3)
|
||||||
|
|
@ -893,24 +892,25 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* set up brush sides */
|
/* set up brush sides */
|
||||||
buildBrush->numsides = 4;
|
buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
|
||||||
buildBrush->sides[ 0 ].shaderInfo = si;
|
buildBrush.sides.resize( 4 );
|
||||||
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags;
|
buildBrush.sides[ 0 ].shaderInfo = si;
|
||||||
for ( j = 1; j < buildBrush->numsides; j++ ) {
|
buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
|
||||||
|
for ( j = 1; j < 4; j++ ) {
|
||||||
if ( debugClip ) {
|
if ( debugClip ) {
|
||||||
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
|
buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
|
||||||
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
|
buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
|
buildBrush.sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
points[3] = points[0]; // for cyclic usage
|
points[3] = points[0]; // for cyclic usage
|
||||||
|
|
||||||
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
|
buildBrush.sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
|
||||||
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
|
buildBrush.sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
|
||||||
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
|
buildBrush.sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
|
||||||
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
|
buildBrush.sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1033,25 +1033,26 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* set up brush sides */
|
/* set up brush sides */
|
||||||
buildBrush->numsides = 5;
|
buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
|
||||||
buildBrush->sides[ 0 ].shaderInfo = si;
|
buildBrush.sides.resize( 5 );
|
||||||
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags;
|
buildBrush.sides[ 0 ].shaderInfo = si;
|
||||||
for ( j = 1; j < buildBrush->numsides; j++ ) {
|
buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
|
||||||
|
for ( j = 1; j < 5; j++ ) {
|
||||||
if ( debugClip ) {
|
if ( debugClip ) {
|
||||||
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
|
buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
|
||||||
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
|
buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
|
buildBrush.sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
points[3] = points[0]; // for cyclic usage
|
points[3] = points[0]; // for cyclic usage
|
||||||
|
|
||||||
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
|
buildBrush.sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
|
||||||
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
|
buildBrush.sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
|
||||||
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
|
buildBrush.sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
|
||||||
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
|
buildBrush.sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
|
||||||
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
|
buildBrush.sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1087,25 +1088,26 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor
|
||||||
reverse.dist() += clipDepth;
|
reverse.dist() += clipDepth;
|
||||||
|
|
||||||
/* set up brush sides */
|
/* set up brush sides */
|
||||||
buildBrush->numsides = 5;
|
buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
|
||||||
buildBrush->sides[ 0 ].shaderInfo = si;
|
buildBrush.sides.resize( 5 );
|
||||||
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags;
|
buildBrush.sides[ 0 ].shaderInfo = si;
|
||||||
for ( j = 1; j < buildBrush->numsides; j++ ) {
|
buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
|
||||||
|
for ( j = 1; j < 5; j++ ) {
|
||||||
if ( debugClip ) {
|
if ( debugClip ) {
|
||||||
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
|
buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
|
||||||
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
|
buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
|
buildBrush.sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
points[3] = points[0]; // for cyclic usage
|
points[3] = points[0]; // for cyclic usage
|
||||||
|
|
||||||
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
|
buildBrush.sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
|
||||||
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
|
buildBrush.sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
|
||||||
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
|
buildBrush.sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
|
||||||
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
|
buildBrush.sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
|
||||||
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
|
buildBrush.sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1166,25 +1168,26 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor
|
||||||
reverse.dist() += clipDepth;
|
reverse.dist() += clipDepth;
|
||||||
|
|
||||||
/* set up brush sides */
|
/* set up brush sides */
|
||||||
buildBrush->numsides = 5;
|
buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
|
||||||
buildBrush->sides[ 0 ].shaderInfo = si;
|
buildBrush.sides.resize( 5 );
|
||||||
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags;
|
buildBrush.sides[ 0 ].shaderInfo = si;
|
||||||
for ( j = 1; j < buildBrush->numsides; j++ ) {
|
buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
|
||||||
|
for ( j = 1; j < 5; j++ ) {
|
||||||
if ( debugClip ) {
|
if ( debugClip ) {
|
||||||
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
|
buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
|
||||||
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
|
buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
|
buildBrush.sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
points[3] = points[0]; // for cyclic usage
|
points[3] = points[0]; // for cyclic usage
|
||||||
|
|
||||||
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
|
buildBrush.sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
|
||||||
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
|
buildBrush.sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
|
||||||
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
|
buildBrush.sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
|
||||||
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
|
buildBrush.sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
|
||||||
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
|
buildBrush.sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1230,25 +1233,26 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* set up brush sides */
|
/* set up brush sides */
|
||||||
buildBrush->numsides = 5;
|
buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
|
||||||
buildBrush->sides[ 0 ].shaderInfo = si;
|
buildBrush.sides.resize( 5 );
|
||||||
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags;
|
buildBrush.sides[ 0 ].shaderInfo = si;
|
||||||
for ( j = 1; j < buildBrush->numsides; j++ ) {
|
buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
|
||||||
|
for ( j = 1; j < 5; j++ ) {
|
||||||
if ( debugClip ) {
|
if ( debugClip ) {
|
||||||
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
|
buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
|
||||||
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
|
buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
|
buildBrush.sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
points[3] = points[0]; // for cyclic usage
|
points[3] = points[0]; // for cyclic usage
|
||||||
|
|
||||||
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
|
buildBrush.sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
|
||||||
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
|
buildBrush.sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
|
||||||
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
|
buildBrush.sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
|
||||||
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
|
buildBrush.sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
|
||||||
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
|
buildBrush.sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1293,30 +1297,30 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* set up brush sides */
|
/* set up brush sides */
|
||||||
buildBrush->numsides = 4;
|
buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
|
||||||
buildBrush->sides[ 0 ].shaderInfo = si;
|
buildBrush.sides.resize( 4 );
|
||||||
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags;
|
buildBrush.sides[ 0 ].shaderInfo = si;
|
||||||
for ( j = 1; j < buildBrush->numsides; j++ ) {
|
buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
|
||||||
|
for ( j = 1; j < 4; j++ ) {
|
||||||
if ( debugClip ) {
|
if ( debugClip ) {
|
||||||
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
|
buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
|
||||||
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
|
buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
|
buildBrush.sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
points[3] = points[0]; // for cyclic usage
|
points[3] = points[0]; // for cyclic usage
|
||||||
|
|
||||||
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
|
buildBrush.sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
|
||||||
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 1 ] ); // p[0] contains points[1] and points[2]
|
buildBrush.sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 1 ] ); // p[0] contains points[1] and points[2]
|
||||||
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 0 ] ); // p[1] contains points[0] and points[1]
|
buildBrush.sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 0 ] ); // p[1] contains points[0] and points[1]
|
||||||
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
|
buildBrush.sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Sys_Warning( "triangle (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) of %s was not autoclipped\n",
|
Sys_Warning( "triangle (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) of %s was not autoclipped\n",
|
||||||
points[0][0], points[0][1], points[0][2], points[1][0], points[1][1], points[1][2], points[2][0], points[2][1], points[2][2], name );
|
points[0][0], points[0][1], points[0][2], points[1][0], points[1][1], points[1][2], points[2][0], points[2][1], points[2][2], name );
|
||||||
free( buildBrush );
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1359,25 +1363,26 @@ default_CLIPMODEL:
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* set up brush sides */
|
/* set up brush sides */
|
||||||
buildBrush->numsides = 5;
|
buildBrush.sides.clear(); // clear, so resize() will value-initialize elements
|
||||||
buildBrush->sides[ 0 ].shaderInfo = si;
|
buildBrush.sides.resize( 5 );
|
||||||
buildBrush->sides[ 0 ].surfaceFlags = si->surfaceFlags;
|
buildBrush.sides[ 0 ].shaderInfo = si;
|
||||||
for ( j = 1; j < buildBrush->numsides; j++ ) {
|
buildBrush.sides[ 0 ].surfaceFlags = si->surfaceFlags;
|
||||||
|
for ( j = 1; j < 5; j++ ) {
|
||||||
if ( debugClip ) {
|
if ( debugClip ) {
|
||||||
buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
|
buildBrush.sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" );
|
||||||
buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
|
buildBrush.sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
|
buildBrush.sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
points[3] = points[0]; // for cyclic usage
|
points[3] = points[0]; // for cyclic usage
|
||||||
|
|
||||||
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
|
buildBrush.sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
|
||||||
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
|
buildBrush.sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
|
||||||
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
|
buildBrush.sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
|
||||||
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
|
buildBrush.sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
|
||||||
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
|
buildBrush.sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1385,14 +1390,13 @@ default_CLIPMODEL:
|
||||||
if ( CreateBrushWindings( buildBrush ) ) {
|
if ( CreateBrushWindings( buildBrush ) ) {
|
||||||
AddBrushBevels();
|
AddBrushBevels();
|
||||||
//% EmitBrushes( buildBrush, NULL, NULL );
|
//% EmitBrushes( buildBrush, NULL, NULL );
|
||||||
buildBrush->next = entities[ mapEntityNum ].brushes;
|
brush_t& newBrush = entities[ mapEntityNum ].brushes.emplace_front( buildBrush );
|
||||||
entities[ mapEntityNum ].brushes = buildBrush;
|
newBrush.original = &newBrush;
|
||||||
entities[ mapEntityNum ].numBrushes++;
|
entities[ mapEntityNum ].numBrushes++;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
Sys_Warning( "triangle (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) of %s was not autoclipped\n",
|
Sys_Warning( "triangle (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) of %s was not autoclipped\n",
|
||||||
points[0][0], points[0][1], points[0][2], points[1][0], points[1][1], points[1][2], points[2][0], points[2][1], points[2][2], name );
|
points[0][0], points[0][1], points[0][2], points[1][0], points[1][1], points[1][2], points[2][0], points[2][1], points[2][2], name );
|
||||||
free( buildBrush );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,24 +34,7 @@
|
||||||
|
|
||||||
|
|
||||||
/* ydnar: to fix broken portal windings */
|
/* ydnar: to fix broken portal windings */
|
||||||
extern bool FixWinding( winding_t *w );
|
extern bool FixWinding( winding_t& w );
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
===========
|
|
||||||
AllocPortal
|
|
||||||
===========
|
|
||||||
*/
|
|
||||||
portal_t *AllocPortal( void ){
|
|
||||||
return safe_calloc( sizeof( portal_t ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreePortal( portal_t *p ){
|
|
||||||
if ( p->winding ) {
|
|
||||||
FreeWinding( p->winding );
|
|
||||||
}
|
|
||||||
free( p );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -157,7 +140,7 @@ void RemovePortalFromNode( portal_t *portal, node_t *l ){
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
void PrintPortal( const portal_t *p ){
|
void PrintPortal( const portal_t *p ){
|
||||||
for ( const Vector3& point : ( *p->winding ) )
|
for ( const Vector3& point : p->winding )
|
||||||
Sys_Printf( "(%5.0f,%5.0f,%5.0f)\n", point[0], point[1], point[2] );
|
Sys_Printf( "(%5.0f,%5.0f,%5.0f)\n", point[0], point[1], point[2] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -169,59 +152,46 @@ void PrintPortal( const portal_t *p ){
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
#define SIDESPACE 8
|
#define SIDESPACE 8
|
||||||
void MakeHeadnodePortals( tree_t *tree ){
|
void MakeHeadnodePortals( tree_t& tree ){
|
||||||
int i, j, n;
|
portal_t *portals[6];
|
||||||
portal_t *p, *portals[6];
|
|
||||||
plane_t bplanes[6];
|
|
||||||
node_t *node;
|
|
||||||
|
|
||||||
node = tree->headnode;
|
|
||||||
|
|
||||||
// pad with some space so there will never be null volume leafs
|
// pad with some space so there will never be null volume leafs
|
||||||
const MinMax bounds( tree->minmax.mins - Vector3( SIDESPACE ),
|
const MinMax bounds( tree.minmax.mins - Vector3( SIDESPACE ),
|
||||||
tree->minmax.maxs + Vector3( SIDESPACE ) );
|
tree.minmax.maxs + Vector3( SIDESPACE ) );
|
||||||
if ( !bounds.valid() ) {
|
if ( !bounds.valid() ) {
|
||||||
Error( "Backwards tree volume" );
|
Error( "Backwards tree volume" );
|
||||||
}
|
}
|
||||||
|
|
||||||
tree->outside_node.planenum = PLANENUM_LEAF;
|
tree.outside_node.planenum = PLANENUM_LEAF;
|
||||||
tree->outside_node.brushlist = NULL;
|
tree.outside_node.brushlist.clear();
|
||||||
tree->outside_node.portals = NULL;
|
tree.outside_node.portals = NULL;
|
||||||
tree->outside_node.opaque = false;
|
tree.outside_node.opaque = false;
|
||||||
|
|
||||||
for ( i = 0 ; i < 3 ; i++ )
|
for ( int i = 0 ; i < 3 ; i++ )
|
||||||
for ( j = 0 ; j < 2 ; j++ )
|
for ( int j = 0 ; j < 2 ; j++ )
|
||||||
{
|
{
|
||||||
n = j * 3 + i;
|
portal_t *p = portals[j * 3 + i] = AllocPortal();
|
||||||
|
|
||||||
p = AllocPortal();
|
|
||||||
portals[n] = p;
|
|
||||||
|
|
||||||
plane_t *pl = &bplanes[n];
|
|
||||||
memset( pl, 0, sizeof( *pl ) );
|
|
||||||
if ( j ) {
|
if ( j ) {
|
||||||
pl->normal()[i] = -1;
|
p->plane.plane = Plane3f( -g_vector3_axes[i], -bounds.maxs[i] );
|
||||||
pl->dist() = -bounds.maxs[i];
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pl->normal()[i] = 1;
|
p->plane.plane = Plane3f( g_vector3_axes[i], bounds.mins[i] );
|
||||||
pl->dist() = bounds.mins[i];
|
|
||||||
}
|
}
|
||||||
p->plane = *pl;
|
p->winding = BaseWindingForPlane( p->plane.plane );
|
||||||
p->winding = BaseWindingForPlane( pl->plane );
|
AddPortalToNodes( p, tree.headnode, &tree.outside_node );
|
||||||
AddPortalToNodes( p, node, &tree->outside_node );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// clip the basewindings by all the other planes
|
// clip the basewindings by all the other planes
|
||||||
for ( i = 0 ; i < 6 ; i++ )
|
for ( int i = 0 ; i < 6 ; i++ )
|
||||||
{
|
{
|
||||||
for ( j = 0 ; j < 6 ; j++ )
|
for ( int j = 0 ; j < 6 ; j++ )
|
||||||
{
|
{
|
||||||
if ( j == i ) {
|
if ( j == i ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ChopWindingInPlace( portals[i]->winding, bplanes[j].plane, ON_EPSILON );
|
ChopWindingInPlace( portals[i]->winding, portals[j]->plane.plane, ON_EPSILON );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -237,14 +207,11 @@ void MakeHeadnodePortals( tree_t *tree ){
|
||||||
#define BASE_WINDING_EPSILON 0.001
|
#define BASE_WINDING_EPSILON 0.001
|
||||||
#define SPLIT_WINDING_EPSILON 0.001
|
#define SPLIT_WINDING_EPSILON 0.001
|
||||||
|
|
||||||
winding_t *BaseWindingForNode( node_t *node ){
|
winding_t BaseWindingForNode( const node_t *node ){
|
||||||
winding_t *w;
|
winding_t w = BaseWindingForPlane( mapplanes[node->planenum].plane );
|
||||||
node_t *n;
|
|
||||||
|
|
||||||
w = BaseWindingForPlane( mapplanes[node->planenum].plane );
|
|
||||||
|
|
||||||
// clip by all the parents
|
// clip by all the parents
|
||||||
for ( n = node->parent ; n && w ; )
|
for ( const node_t *n = node->parent; n && !w.empty(); )
|
||||||
{
|
{
|
||||||
const plane_t& plane = mapplanes[n->planenum];
|
const plane_t& plane = mapplanes[n->planenum];
|
||||||
|
|
||||||
|
|
@ -273,14 +240,12 @@ winding_t *BaseWindingForNode( node_t *node ){
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
void MakeNodePortal( node_t *node ){
|
void MakeNodePortal( node_t *node ){
|
||||||
portal_t *new_portal, *p;
|
|
||||||
winding_t *w;
|
|
||||||
int side;
|
int side;
|
||||||
|
|
||||||
w = BaseWindingForNode( node );
|
winding_t w = BaseWindingForNode( node );
|
||||||
|
|
||||||
// clip the portal by all the other portals in the node
|
// clip the portal by all the other portals in the node
|
||||||
for ( p = node->portals ; p && w; p = p->next[side] )
|
for ( const portal_t *p = node->portals; p && !w.empty(); p = p->next[side] )
|
||||||
{
|
{
|
||||||
if ( p->nodes[0] == node ) {
|
if ( p->nodes[0] == node ) {
|
||||||
side = 0;
|
side = 0;
|
||||||
|
|
@ -296,7 +261,7 @@ void MakeNodePortal( node_t *node ){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !w ) {
|
if ( w.empty() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -305,21 +270,19 @@ void MakeNodePortal( node_t *node ){
|
||||||
#if 0
|
#if 0
|
||||||
if ( !FixWinding( w ) ) {
|
if ( !FixWinding( w ) ) {
|
||||||
c_badportals++;
|
c_badportals++;
|
||||||
FreeWinding( w );
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ( WindingIsTiny( *w ) ) {
|
if ( WindingIsTiny( w ) ) {
|
||||||
c_tinyportals++;
|
c_tinyportals++;
|
||||||
FreeWinding( w );
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_portal = AllocPortal();
|
portal_t *new_portal = AllocPortal();
|
||||||
new_portal->plane = mapplanes[node->planenum];
|
new_portal->plane = mapplanes[node->planenum];
|
||||||
new_portal->onnode = node;
|
new_portal->onnode = node;
|
||||||
new_portal->winding = w;
|
new_portal->winding.swap( w );
|
||||||
new_portal->compileFlags = node->compileFlags;
|
new_portal->compileFlags = node->compileFlags;
|
||||||
AddPortalToNodes( new_portal, node->children[0], node->children[1] );
|
AddPortalToNodes( new_portal, node->children[0], node->children[1] );
|
||||||
}
|
}
|
||||||
|
|
@ -334,17 +297,15 @@ void MakeNodePortal( node_t *node ){
|
||||||
==============
|
==============
|
||||||
*/
|
*/
|
||||||
void SplitNodePortals( node_t *node ){
|
void SplitNodePortals( node_t *node ){
|
||||||
portal_t *p, *next_portal, *new_portal;
|
|
||||||
node_t *f, *b, *other_node;
|
node_t *f, *b, *other_node;
|
||||||
int side;
|
|
||||||
winding_t *frontwinding, *backwinding;
|
|
||||||
|
|
||||||
const plane_t& plane = mapplanes[node->planenum];
|
const plane_t& plane = mapplanes[node->planenum];
|
||||||
f = node->children[0];
|
f = node->children[0];
|
||||||
b = node->children[1];
|
b = node->children[1];
|
||||||
|
|
||||||
for ( p = node->portals ; p ; p = next_portal )
|
for ( portal_t *next_portal, *p = node->portals; p; p = next_portal )
|
||||||
{
|
{
|
||||||
|
int side;
|
||||||
if ( p->nodes[0] == node ) {
|
if ( p->nodes[0] == node ) {
|
||||||
side = 0;
|
side = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -363,45 +324,41 @@ void SplitNodePortals( node_t *node ){
|
||||||
//
|
//
|
||||||
// cut the portal into two portals, one on each side of the cut plane
|
// cut the portal into two portals, one on each side of the cut plane
|
||||||
//
|
//
|
||||||
ClipWindingEpsilon( *p->winding, plane.plane,
|
auto [frontwinding, backwinding] = ClipWindingEpsilon( p->winding, plane.plane, SPLIT_WINDING_EPSILON ); /* not strict, we want to always keep one of them even if coplanar */
|
||||||
SPLIT_WINDING_EPSILON, frontwinding, backwinding ); /* not strict, we want to always keep one of them even if coplanar */
|
|
||||||
|
|
||||||
if ( frontwinding && WindingIsTiny( *frontwinding ) ) {
|
if ( !frontwinding.empty() && WindingIsTiny( frontwinding ) ) {
|
||||||
if ( !f->tinyportals ) {
|
if ( !f->tinyportals ) {
|
||||||
f->referencepoint = ( *frontwinding )[0];
|
f->referencepoint = frontwinding[0];
|
||||||
}
|
}
|
||||||
f->tinyportals++;
|
f->tinyportals++;
|
||||||
if ( !other_node->tinyportals ) {
|
if ( !other_node->tinyportals ) {
|
||||||
other_node->referencepoint = ( *frontwinding )[0];
|
other_node->referencepoint = frontwinding[0];
|
||||||
}
|
}
|
||||||
other_node->tinyportals++;
|
other_node->tinyportals++;
|
||||||
|
|
||||||
FreeWinding( frontwinding );
|
frontwinding.clear();
|
||||||
frontwinding = NULL;
|
|
||||||
c_tinyportals++;
|
c_tinyportals++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( backwinding && WindingIsTiny( *backwinding ) ) {
|
if ( !backwinding.empty() && WindingIsTiny( backwinding ) ) {
|
||||||
if ( !b->tinyportals ) {
|
if ( !b->tinyportals ) {
|
||||||
b->referencepoint = ( *backwinding )[0];
|
b->referencepoint = backwinding[0];
|
||||||
}
|
}
|
||||||
b->tinyportals++;
|
b->tinyportals++;
|
||||||
if ( !other_node->tinyportals ) {
|
if ( !other_node->tinyportals ) {
|
||||||
other_node->referencepoint = ( *backwinding )[0];
|
other_node->referencepoint = backwinding[0];
|
||||||
}
|
}
|
||||||
other_node->tinyportals++;
|
other_node->tinyportals++;
|
||||||
|
|
||||||
FreeWinding( backwinding );
|
backwinding.clear();
|
||||||
backwinding = NULL;
|
|
||||||
c_tinyportals++;
|
c_tinyportals++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !frontwinding && !backwinding ) { // tiny windings on both sides
|
if ( frontwinding.empty() && backwinding.empty() ) { // tiny windings on both sides
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !frontwinding ) {
|
if ( frontwinding.empty() ) {
|
||||||
FreeWinding( backwinding );
|
|
||||||
if ( side == 0 ) {
|
if ( side == 0 ) {
|
||||||
AddPortalToNodes( p, b, other_node );
|
AddPortalToNodes( p, b, other_node );
|
||||||
}
|
}
|
||||||
|
|
@ -410,8 +367,7 @@ void SplitNodePortals( node_t *node ){
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( !backwinding ) {
|
if ( backwinding.empty() ) {
|
||||||
FreeWinding( frontwinding );
|
|
||||||
if ( side == 0 ) {
|
if ( side == 0 ) {
|
||||||
AddPortalToNodes( p, f, other_node );
|
AddPortalToNodes( p, f, other_node );
|
||||||
}
|
}
|
||||||
|
|
@ -422,11 +378,10 @@ void SplitNodePortals( node_t *node ){
|
||||||
}
|
}
|
||||||
|
|
||||||
// the winding is split
|
// the winding is split
|
||||||
new_portal = AllocPortal();
|
p->winding.clear();
|
||||||
*new_portal = *p;
|
portal_t *new_portal = new portal_t( *p ); // AllocPortal()
|
||||||
new_portal->winding = backwinding;
|
new_portal->winding.swap( backwinding );
|
||||||
FreeWinding( p->winding );
|
p->winding.swap( frontwinding );
|
||||||
p->winding = frontwinding;
|
|
||||||
|
|
||||||
if ( side == 0 ) {
|
if ( side == 0 ) {
|
||||||
AddPortalToNodes( p, f, other_node );
|
AddPortalToNodes( p, f, other_node );
|
||||||
|
|
@ -457,7 +412,7 @@ void CalcNodeBounds( node_t *node ){
|
||||||
for ( p = node->portals; p; p = p->next[s] )
|
for ( p = node->portals; p; p = p->next[s] )
|
||||||
{
|
{
|
||||||
s = ( p->nodes[1] == node );
|
s = ( p->nodes[1] == node );
|
||||||
WindingExtendBounds( *p->winding, node->minmax );
|
WindingExtendBounds( p->winding, node->minmax );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -479,8 +434,8 @@ void MakeTreePortals_r( node_t *node ){
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !c_worldMinmax.surrounds( node->minmax ) ) {
|
if ( !c_worldMinmax.surrounds( node->minmax ) ) {
|
||||||
if ( node->portals && node->portals->winding ) {
|
if ( node->portals && !node->portals->winding.empty() ) {
|
||||||
xml_Winding( "WARNING: Node With Unbounded Volume", node->portals->winding->data(), node->portals->winding->size(), false );
|
xml_Winding( "WARNING: Node With Unbounded Volume", node->portals->winding.data(), node->portals->winding.size(), false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( node->planenum == PLANENUM_LEAF ) {
|
if ( node->planenum == PLANENUM_LEAF ) {
|
||||||
|
|
@ -499,10 +454,10 @@ void MakeTreePortals_r( node_t *node ){
|
||||||
MakeTreePortals
|
MakeTreePortals
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
void MakeTreePortals( tree_t *tree ){
|
void MakeTreePortals( tree_t& tree ){
|
||||||
Sys_FPrintf( SYS_VRB, "--- MakeTreePortals ---\n" );
|
Sys_FPrintf( SYS_VRB, "--- MakeTreePortals ---\n" );
|
||||||
MakeHeadnodePortals( tree );
|
MakeHeadnodePortals( tree );
|
||||||
MakeTreePortals_r( tree->headnode );
|
MakeTreePortals_r( tree.headnode );
|
||||||
Sys_FPrintf( SYS_VRB, "%9d tiny portals\n", c_tinyportals );
|
Sys_FPrintf( SYS_VRB, "%9d tiny portals\n", c_tinyportals );
|
||||||
Sys_FPrintf( SYS_VRB, "%9d bad portals\n", c_badportals ); /* ydnar */
|
Sys_FPrintf( SYS_VRB, "%9d bad portals\n", c_badportals ); /* ydnar */
|
||||||
}
|
}
|
||||||
|
|
@ -591,16 +546,14 @@ bool PlaceOccupant( node_t *headnode, const Vector3& origin, const entity_t *occ
|
||||||
=============
|
=============
|
||||||
*/
|
*/
|
||||||
|
|
||||||
EFloodEntities FloodEntities( tree_t *tree ){
|
EFloodEntities FloodEntities( tree_t& tree ){
|
||||||
bool r, inside, skybox;
|
bool r, inside, skybox;
|
||||||
node_t *headnode;
|
|
||||||
const char *value;
|
const char *value;
|
||||||
|
|
||||||
|
|
||||||
headnode = tree->headnode;
|
|
||||||
Sys_FPrintf( SYS_VRB, "--- FloodEntities ---\n" );
|
Sys_FPrintf( SYS_VRB, "--- FloodEntities ---\n" );
|
||||||
inside = false;
|
inside = false;
|
||||||
tree->outside_node.occupied = 0;
|
tree.outside_node.occupied = 0;
|
||||||
|
|
||||||
c_floodedleafs = 0;
|
c_floodedleafs = 0;
|
||||||
for ( std::size_t i = 1; i < entities.size(); ++i )
|
for ( std::size_t i = 1; i < entities.size(); ++i )
|
||||||
|
|
@ -617,7 +570,7 @@ EFloodEntities FloodEntities( tree_t *tree ){
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* also allow bmodel entities outside, as they could be on a moving path that will go into the map */
|
/* also allow bmodel entities outside, as they could be on a moving path that will go into the map */
|
||||||
if ( e.brushes != NULL || e.patches != NULL || e.classname_is( "_decal" ) ) { //_decal primitive is freed at this point
|
if ( !e.brushes.empty() || e.patches != NULL || e.classname_is( "_decal" ) ) { //_decal primitive is freed at this point
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -653,7 +606,7 @@ EFloodEntities FloodEntities( tree_t *tree ){
|
||||||
//% origin[ 2 ] += 4096;
|
//% origin[ 2 ] += 4096;
|
||||||
|
|
||||||
/* find leaf */
|
/* find leaf */
|
||||||
r = PlaceOccupant( headnode, origin, &e, skybox );
|
r = PlaceOccupant( tree.headnode, origin, &e, skybox );
|
||||||
if ( r ) {
|
if ( r ) {
|
||||||
inside = true;
|
inside = true;
|
||||||
}
|
}
|
||||||
|
|
@ -668,7 +621,7 @@ EFloodEntities FloodEntities( tree_t *tree ){
|
||||||
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "no entities in open -- no filling\n" );
|
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "no entities in open -- no filling\n" );
|
||||||
return EFloodEntities::Empty;
|
return EFloodEntities::Empty;
|
||||||
}
|
}
|
||||||
if ( tree->outside_node.occupied ) {
|
if ( tree.outside_node.occupied ) {
|
||||||
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "entity reached from outside -- leak detected\n" );
|
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "entity reached from outside -- leak detected\n" );
|
||||||
return EFloodEntities::Leaked;
|
return EFloodEntities::Leaked;
|
||||||
}
|
}
|
||||||
|
|
@ -696,7 +649,6 @@ int c_areas;
|
||||||
void FloodAreas_r( node_t *node ){
|
void FloodAreas_r( node_t *node ){
|
||||||
int s;
|
int s;
|
||||||
portal_t *p;
|
portal_t *p;
|
||||||
brush_t *b;
|
|
||||||
|
|
||||||
|
|
||||||
if ( node->areaportal ) {
|
if ( node->areaportal ) {
|
||||||
|
|
@ -705,7 +657,7 @@ void FloodAreas_r( node_t *node ){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this node is part of an area portal brush */
|
/* this node is part of an area portal brush */
|
||||||
b = node->brushlist->original;
|
brush_t *b = node->brushlist.front().original;
|
||||||
|
|
||||||
/* if the current area has already touched this portal, we are done */
|
/* if the current area has already touched this portal, we are done */
|
||||||
if ( b->portalareas[ 0 ] == c_areas || b->portalareas[ 1 ] == c_areas ) {
|
if ( b->portalareas[ 0 ] == c_areas || b->portalareas[ 1 ] == c_areas ) {
|
||||||
|
|
@ -786,9 +738,7 @@ void FindAreas_r( node_t *node ){
|
||||||
CheckAreas_r
|
CheckAreas_r
|
||||||
=============
|
=============
|
||||||
*/
|
*/
|
||||||
void CheckAreas_r( node_t *node ){
|
void CheckAreas_r( const node_t *node ){
|
||||||
brush_t *b;
|
|
||||||
|
|
||||||
if ( node->planenum != PLANENUM_LEAF ) {
|
if ( node->planenum != PLANENUM_LEAF ) {
|
||||||
CheckAreas_r( node->children[0] );
|
CheckAreas_r( node->children[0] );
|
||||||
CheckAreas_r( node->children[1] );
|
CheckAreas_r( node->children[1] );
|
||||||
|
|
@ -805,7 +755,7 @@ void CheckAreas_r( node_t *node ){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( node->areaportal ) {
|
if ( node->areaportal ) {
|
||||||
b = node->brushlist->original;
|
const brush_t *b = node->brushlist.front().original;
|
||||||
|
|
||||||
// check if the areaportal touches two areas
|
// check if the areaportal touches two areas
|
||||||
if ( b->portalareas[0] == -1 || b->portalareas[1] == -1 ) {
|
if ( b->portalareas[0] == -1 || b->portalareas[1] == -1 ) {
|
||||||
|
|
@ -846,16 +796,16 @@ void FloodSkyboxArea_r( node_t *node ){
|
||||||
mark each leaf with an area, bounded by C_AREAPORTAL
|
mark each leaf with an area, bounded by C_AREAPORTAL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void FloodAreas( tree_t *tree ){
|
void FloodAreas( tree_t& tree ){
|
||||||
Sys_FPrintf( SYS_VRB, "--- FloodAreas ---\n" );
|
Sys_FPrintf( SYS_VRB, "--- FloodAreas ---\n" );
|
||||||
FindAreas_r( tree->headnode );
|
FindAreas_r( tree.headnode );
|
||||||
|
|
||||||
/* ydnar: flood all skybox nodes */
|
/* ydnar: flood all skybox nodes */
|
||||||
FloodSkyboxArea_r( tree->headnode );
|
FloodSkyboxArea_r( tree.headnode );
|
||||||
|
|
||||||
/* check for areaportal brushes that don't touch two areas */
|
/* check for areaportal brushes that don't touch two areas */
|
||||||
/* ydnar: fix this rather than just silence the warnings */
|
/* ydnar: fix this rather than just silence the warnings */
|
||||||
//% CheckAreas_r( tree->headnode );
|
//% CheckAreas_r( tree.headnode );
|
||||||
|
|
||||||
Sys_FPrintf( SYS_VRB, "%9d areas\n", c_areas );
|
Sys_FPrintf( SYS_VRB, "%9d areas\n", c_areas );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ void WriteFloat( FILE *f, float v ){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CountVisportals_r( node_t *node ){
|
void CountVisportals_r( const node_t *node ){
|
||||||
int s;
|
int s;
|
||||||
|
|
||||||
// decision node
|
// decision node
|
||||||
|
|
@ -75,9 +75,8 @@ void CountVisportals_r( node_t *node ){
|
||||||
|
|
||||||
for ( const portal_t *p = node->portals; p; p = p->next[s] )
|
for ( const portal_t *p = node->portals; p; p = p->next[s] )
|
||||||
{
|
{
|
||||||
const winding_t *w = p->winding;
|
|
||||||
s = ( p->nodes[1] == node );
|
s = ( p->nodes[1] == node );
|
||||||
if ( w && p->nodes[0] == node ) {
|
if ( !p->winding.empty() && p->nodes[0] == node ) {
|
||||||
if ( !PortalPassable( p ) ) {
|
if ( !PortalPassable( p ) ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -94,7 +93,7 @@ void CountVisportals_r( node_t *node ){
|
||||||
WritePortalFile_r
|
WritePortalFile_r
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
void WritePortalFile_r( node_t *node ){
|
void WritePortalFile_r( const node_t *node ){
|
||||||
int s, flags;
|
int s, flags;
|
||||||
|
|
||||||
// decision node
|
// decision node
|
||||||
|
|
@ -110,9 +109,9 @@ void WritePortalFile_r( node_t *node ){
|
||||||
|
|
||||||
for (const portal_t *p = node->portals; p; p = p->next[s] )
|
for (const portal_t *p = node->portals; p; p = p->next[s] )
|
||||||
{
|
{
|
||||||
const winding_t *w = p->winding;
|
const winding_t& w = p->winding;
|
||||||
s = ( p->nodes[1] == node );
|
s = ( p->nodes[1] == node );
|
||||||
if ( w && p->nodes[0] == node ) {
|
if ( !w.empty() && p->nodes[0] == node ) {
|
||||||
if ( !PortalPassable( p ) ) {
|
if ( !PortalPassable( p ) ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -126,11 +125,11 @@ void WritePortalFile_r( node_t *node ){
|
||||||
// the changeover point between different axis. interpret the
|
// the changeover point between different axis. interpret the
|
||||||
// plane the same way vis will, and flip the side orders if needed
|
// plane the same way vis will, and flip the side orders if needed
|
||||||
// FIXME: is this still relevant?
|
// FIXME: is this still relevant?
|
||||||
if ( vector3_dot( p->plane.normal(), WindingPlane( *w ).normal() ) < 0.99 ) { // backwards...
|
if ( vector3_dot( p->plane.normal(), WindingPlane( w ).normal() ) < 0.99 ) { // backwards...
|
||||||
fprintf( pf, "%zu %i %i ", w->size(), p->nodes[1]->cluster, p->nodes[0]->cluster );
|
fprintf( pf, "%zu %i %i ", w.size(), p->nodes[1]->cluster, p->nodes[0]->cluster );
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
fprintf( pf, "%zu %i %i ", w->size(), p->nodes[0]->cluster, p->nodes[1]->cluster );
|
fprintf( pf, "%zu %i %i ", w.size(), p->nodes[0]->cluster, p->nodes[1]->cluster );
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = 0;
|
flags = 0;
|
||||||
|
|
@ -148,7 +147,7 @@ void WritePortalFile_r( node_t *node ){
|
||||||
fprintf( pf, "%d ", flags );
|
fprintf( pf, "%d ", flags );
|
||||||
|
|
||||||
/* write the winding */
|
/* write the winding */
|
||||||
for ( const Vector3 point : *w )
|
for ( const Vector3 point : w )
|
||||||
{
|
{
|
||||||
fprintf( pf, "(" );
|
fprintf( pf, "(" );
|
||||||
WriteFloat( pf, point.x() );
|
WriteFloat( pf, point.x() );
|
||||||
|
|
@ -162,7 +161,7 @@ void WritePortalFile_r( node_t *node ){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CountSolidFaces_r( node_t *node ){
|
void CountSolidFaces_r( const node_t *node ){
|
||||||
int s;
|
int s;
|
||||||
|
|
||||||
// decision node
|
// decision node
|
||||||
|
|
@ -178,9 +177,8 @@ void CountSolidFaces_r( node_t *node ){
|
||||||
|
|
||||||
for ( const portal_t *p = node->portals; p; p = p->next[s] )
|
for ( const portal_t *p = node->portals; p; p = p->next[s] )
|
||||||
{
|
{
|
||||||
const winding_t *w = p->winding;
|
|
||||||
s = ( p->nodes[1] == node );
|
s = ( p->nodes[1] == node );
|
||||||
if ( w ) {
|
if ( !p->winding.empty() ) {
|
||||||
if ( PortalPassable( p ) ) {
|
if ( PortalPassable( p ) ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -199,7 +197,7 @@ void CountSolidFaces_r( node_t *node ){
|
||||||
WriteFaceFile_r
|
WriteFaceFile_r
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
void WriteFaceFile_r( node_t *node ){
|
void WriteFaceFile_r( const node_t *node ){
|
||||||
int s;
|
int s;
|
||||||
|
|
||||||
// decision node
|
// decision node
|
||||||
|
|
@ -215,9 +213,9 @@ void WriteFaceFile_r( node_t *node ){
|
||||||
|
|
||||||
for ( const portal_t *p = node->portals; p; p = p->next[s] )
|
for ( const portal_t *p = node->portals; p; p = p->next[s] )
|
||||||
{
|
{
|
||||||
const winding_t *w = p->winding;
|
const winding_t& w = p->winding;
|
||||||
s = ( p->nodes[1] == node );
|
s = ( p->nodes[1] == node );
|
||||||
if ( w ) {
|
if ( !w.empty() ) {
|
||||||
if ( PortalPassable( p ) ) {
|
if ( PortalPassable( p ) ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -227,8 +225,8 @@ void WriteFaceFile_r( node_t *node ){
|
||||||
// write out to the file
|
// write out to the file
|
||||||
|
|
||||||
if ( p->nodes[0] == node ) {
|
if ( p->nodes[0] == node ) {
|
||||||
fprintf( pf, "%zu %i ", w->size(), p->nodes[0]->cluster );
|
fprintf( pf, "%zu %i ", w.size(), p->nodes[0]->cluster );
|
||||||
for ( const Vector3& point : *w )
|
for ( const Vector3& point : w )
|
||||||
{
|
{
|
||||||
fprintf( pf, "(" );
|
fprintf( pf, "(" );
|
||||||
WriteFloat( pf, point.x() );
|
WriteFloat( pf, point.x() );
|
||||||
|
|
@ -240,8 +238,8 @@ void WriteFaceFile_r( node_t *node ){
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf( pf, "%zu %i ", w->size(), p->nodes[1]->cluster );
|
fprintf( pf, "%zu %i ", w.size(), p->nodes[1]->cluster );
|
||||||
for ( winding_t::const_reverse_iterator point = w->crbegin(); point != w->crend(); ++point )
|
for ( winding_t::const_reverse_iterator point = w.crbegin(); point != w.crend(); ++point )
|
||||||
{
|
{
|
||||||
fprintf( pf, "(" );
|
fprintf( pf, "(" );
|
||||||
WriteFloat( pf, point->x() );
|
WriteFloat( pf, point->x() );
|
||||||
|
|
@ -332,7 +330,7 @@ void NumberLeafs_r( node_t *node, int c ){
|
||||||
NumberClusters
|
NumberClusters
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
void NumberClusters( tree_t *tree ) {
|
void NumberClusters( tree_t& tree ) {
|
||||||
num_visclusters = 0;
|
num_visclusters = 0;
|
||||||
num_visportals = 0;
|
num_visportals = 0;
|
||||||
num_solidfaces = 0;
|
num_solidfaces = 0;
|
||||||
|
|
@ -340,9 +338,9 @@ void NumberClusters( tree_t *tree ) {
|
||||||
Sys_FPrintf( SYS_VRB, "--- NumberClusters ---\n" );
|
Sys_FPrintf( SYS_VRB, "--- NumberClusters ---\n" );
|
||||||
|
|
||||||
// set the cluster field in every leaf and count the total number of portals
|
// set the cluster field in every leaf and count the total number of portals
|
||||||
NumberLeafs_r( tree->headnode, -1 );
|
NumberLeafs_r( tree.headnode, -1 );
|
||||||
CountVisportals_r( tree->headnode );
|
CountVisportals_r( tree.headnode );
|
||||||
CountSolidFaces_r( tree->headnode );
|
CountSolidFaces_r( tree.headnode );
|
||||||
|
|
||||||
Sys_FPrintf( SYS_VRB, "%9d visclusters\n", num_visclusters );
|
Sys_FPrintf( SYS_VRB, "%9d visclusters\n", num_visclusters );
|
||||||
Sys_FPrintf( SYS_VRB, "%9d visportals\n", num_visportals );
|
Sys_FPrintf( SYS_VRB, "%9d visportals\n", num_visportals );
|
||||||
|
|
@ -354,7 +352,7 @@ void NumberClusters( tree_t *tree ) {
|
||||||
WritePortalFile
|
WritePortalFile
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
void WritePortalFile( tree_t *tree ){
|
void WritePortalFile( const tree_t& tree ){
|
||||||
Sys_FPrintf( SYS_VRB, "--- WritePortalFile ---\n" );
|
Sys_FPrintf( SYS_VRB, "--- WritePortalFile ---\n" );
|
||||||
|
|
||||||
// write the file
|
// write the file
|
||||||
|
|
@ -367,8 +365,8 @@ void WritePortalFile( tree_t *tree ){
|
||||||
fprintf( pf, "%i\n", num_visportals );
|
fprintf( pf, "%i\n", num_visportals );
|
||||||
fprintf( pf, "%i\n", num_solidfaces );
|
fprintf( pf, "%i\n", num_solidfaces );
|
||||||
|
|
||||||
WritePortalFile_r( tree->headnode );
|
WritePortalFile_r( tree.headnode );
|
||||||
WriteFaceFile_r( tree->headnode );
|
WriteFaceFile_r( tree.headnode );
|
||||||
|
|
||||||
fclose( pf );
|
fclose( pf );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -739,9 +739,9 @@ struct side_t
|
||||||
Vector3 texMat[ 2 ]; /* brush primitive texture matrix */
|
Vector3 texMat[ 2 ]; /* brush primitive texture matrix */
|
||||||
Vector4 vecs[ 2 ]; /* old-style texture coordinate mapping */
|
Vector4 vecs[ 2 ]; /* old-style texture coordinate mapping */
|
||||||
|
|
||||||
Plane3 plane; /* optional plane in double precision for building windings */
|
Plane3 plane{ 0, 0, 0, 0 }; /* optional plane in double precision for building windings */
|
||||||
winding_t *winding;
|
winding_t winding;
|
||||||
winding_t *visibleHull; /* convex hull of all visible fragments */
|
winding_t visibleHull; /* convex hull of all visible fragments */
|
||||||
|
|
||||||
shaderInfo_t *shaderInfo;
|
shaderInfo_t *shaderInfo;
|
||||||
|
|
||||||
|
|
@ -759,7 +759,7 @@ struct side_t
|
||||||
struct sideRef_t
|
struct sideRef_t
|
||||||
{
|
{
|
||||||
sideRef_t *next;
|
sideRef_t *next;
|
||||||
side_t *side;
|
const side_t *side;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -775,8 +775,6 @@ struct indexMap_t
|
||||||
|
|
||||||
struct brush_t
|
struct brush_t
|
||||||
{
|
{
|
||||||
brush_t *next;
|
|
||||||
brush_t *nextColorModBrush; /* ydnar: colorMod volume brushes go here */
|
|
||||||
brush_t *original; /* chopped up brushes will reference the originals */
|
brush_t *original; /* chopped up brushes will reference the originals */
|
||||||
|
|
||||||
int entityNum, brushNum; /* editor numbering */
|
int entityNum, brushNum; /* editor numbering */
|
||||||
|
|
@ -804,16 +802,16 @@ struct brush_t
|
||||||
int portalareas[ 2 ];
|
int portalareas[ 2 ];
|
||||||
|
|
||||||
MinMax minmax;
|
MinMax minmax;
|
||||||
int numsides;
|
|
||||||
|
|
||||||
side_t sides[]; /* variably sized */
|
std::vector<side_t> sides;
|
||||||
};
|
};
|
||||||
|
using brushlist_t = std::list<brush_t>;
|
||||||
|
|
||||||
|
|
||||||
struct fog_t
|
struct fog_t
|
||||||
{
|
{
|
||||||
shaderInfo_t *si;
|
shaderInfo_t *si;
|
||||||
brush_t *brush;
|
const brush_t *brush;
|
||||||
int visibleSide; /* the brush side that ray tests need to clip against (-1 == none) */
|
int visibleSide; /* the brush side that ray tests need to clip against (-1 == none) */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -914,7 +912,7 @@ struct mapDrawSurface_t
|
||||||
|
|
||||||
shaderInfo_t *shaderInfo;
|
shaderInfo_t *shaderInfo;
|
||||||
shaderInfo_t *celShader;
|
shaderInfo_t *celShader;
|
||||||
brush_t *mapBrush;
|
const brush_t *mapBrush;
|
||||||
parseMesh_t *mapMesh;
|
parseMesh_t *mapMesh;
|
||||||
sideRef_t *sideRef;
|
sideRef_t *sideRef;
|
||||||
|
|
||||||
|
|
@ -974,7 +972,7 @@ struct drawSurfRef_t
|
||||||
struct metaTriangle_t
|
struct metaTriangle_t
|
||||||
{
|
{
|
||||||
shaderInfo_t *si;
|
shaderInfo_t *si;
|
||||||
side_t *side;
|
const side_t *side;
|
||||||
int entityNum, surfaceNum, planeNum, fogNum, sampleSize, castShadows, recvShadows;
|
int entityNum, surfaceNum, planeNum, fogNum, sampleSize, castShadows, recvShadows;
|
||||||
float shadeAngleDegrees;
|
float shadeAngleDegrees;
|
||||||
Plane3f plane;
|
Plane3f plane;
|
||||||
|
|
@ -992,7 +990,8 @@ struct epair_t
|
||||||
struct entity_t
|
struct entity_t
|
||||||
{
|
{
|
||||||
Vector3 origin{ 0 };
|
Vector3 origin{ 0 };
|
||||||
brush_t *brushes, *lastBrush, *colorModBrushes;
|
brushlist_t brushes;
|
||||||
|
std::vector<brush_t*> colorModBrushes;
|
||||||
parseMesh_t *patches;
|
parseMesh_t *patches;
|
||||||
int mapEntityNum, firstDrawSurf;
|
int mapEntityNum, firstDrawSurf;
|
||||||
int firstBrush, numBrushes; /* only valid during BSP compile */
|
int firstBrush, numBrushes; /* only valid during BSP compile */
|
||||||
|
|
@ -1059,10 +1058,8 @@ struct node_t
|
||||||
int planenum; /* -1 = leaf node */
|
int planenum; /* -1 = leaf node */
|
||||||
node_t *parent;
|
node_t *parent;
|
||||||
MinMax minmax; /* valid after portalization */
|
MinMax minmax; /* valid after portalization */
|
||||||
brush_t *volume; /* one for each leaf/node */
|
|
||||||
|
|
||||||
/* nodes only */
|
/* nodes only */
|
||||||
side_t *side; /* the side that created the node */
|
|
||||||
node_t *children[ 2 ];
|
node_t *children[ 2 ];
|
||||||
int compileFlags; /* ydnar: hint, antiportal */
|
int compileFlags; /* ydnar: hint, antiportal */
|
||||||
int tinyportals;
|
int tinyportals;
|
||||||
|
|
@ -1075,7 +1072,7 @@ struct node_t
|
||||||
bool sky; /* ydnar: a sky leaf */
|
bool sky; /* ydnar: a sky leaf */
|
||||||
int cluster; /* for portalfile writing */
|
int cluster; /* for portalfile writing */
|
||||||
int area; /* for areaportals */
|
int area; /* for areaportals */
|
||||||
brush_t *brushlist; /* fragments of all brushes in this leaf */
|
brushlist_t brushlist; /* fragments of all brushes in this leaf */
|
||||||
drawSurfRef_t *drawSurfReferences;
|
drawSurfRef_t *drawSurfReferences;
|
||||||
|
|
||||||
int occupied; /* 1 or greater can reach entity */
|
int occupied; /* 1 or greater can reach entity */
|
||||||
|
|
@ -1093,11 +1090,10 @@ struct portal_t
|
||||||
node_t *onnode; /* NULL = outside box */
|
node_t *onnode; /* NULL = outside box */
|
||||||
node_t *nodes[ 2 ]; /* [ 0 ] = front side of plane */
|
node_t *nodes[ 2 ]; /* [ 0 ] = front side of plane */
|
||||||
portal_t *next[ 2 ];
|
portal_t *next[ 2 ];
|
||||||
winding_t *winding;
|
winding_t winding;
|
||||||
|
|
||||||
bool sidefound; /* false if ->side hasn't been checked */
|
bool sidefound; /* false if ->side hasn't been checked */
|
||||||
int compileFlags; /* from original face that caused the split */
|
int compileFlags; /* from original face that caused the split */
|
||||||
side_t *side; /* NULL = non-visible */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1551,28 +1547,20 @@ int ConvertBSPToOBJ( char *bspName );
|
||||||
|
|
||||||
|
|
||||||
/* brush.c */
|
/* brush.c */
|
||||||
sideRef_t *AllocSideRef( side_t *side, sideRef_t *next );
|
sideRef_t *AllocSideRef( const side_t *side, sideRef_t *next );
|
||||||
int CountBrushList( brush_t *brushes );
|
bool BoundBrush( brush_t& brush );
|
||||||
brush_t *AllocBrush( int numsides );
|
|
||||||
void FreeBrush( brush_t *brushes );
|
|
||||||
void FreeBrushList( brush_t *brushes );
|
|
||||||
brush_t *CopyBrush( const brush_t *brush );
|
|
||||||
bool BoundBrush( brush_t *brush );
|
|
||||||
Vector3 SnapWeldVector( const Vector3& a, const Vector3& b );
|
Vector3 SnapWeldVector( const Vector3& a, const Vector3& b );
|
||||||
bool CreateBrushWindings( brush_t *brush );
|
bool CreateBrushWindings( brush_t& brush );
|
||||||
brush_t *BrushFromBounds( const Vector3& mins, const Vector3& maxs );
|
brush_t BrushFromBounds( const Vector3& mins, const Vector3& maxs );
|
||||||
float BrushVolume( brush_t *brush );
|
float BrushVolume( const brush_t& brush );
|
||||||
void WriteBSPBrushMap( const char *name, brush_t *list );
|
void WriteBSPBrushMap( const char *name, const brushlist_t& list );
|
||||||
|
|
||||||
void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree );
|
void FilterDetailBrushesIntoTree( entity_t *e, tree_t& tree );
|
||||||
void FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree );
|
void FilterStructuralBrushesIntoTree( entity_t *e, tree_t& tree );
|
||||||
|
|
||||||
bool WindingIsTiny( const winding_t& w );
|
bool WindingIsTiny( const winding_t& w );
|
||||||
|
|
||||||
void SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back );
|
std::pair<brush_t*, brush_t*> SplitBrush( const brush_t& brush, int planenum );
|
||||||
|
|
||||||
tree_t *AllocTree( void );
|
|
||||||
node_t *AllocNode( void );
|
|
||||||
|
|
||||||
|
|
||||||
/* mesh.c */
|
/* mesh.c */
|
||||||
|
|
@ -1600,11 +1588,10 @@ inline int FindFloatPlane( const Vector3& normal, float dist, i
|
||||||
}
|
}
|
||||||
bool PlaneEqual( const plane_t& p, const Plane3f& plane );
|
bool PlaneEqual( const plane_t& p, const Plane3f& plane );
|
||||||
void AddBrushBevels( void );
|
void AddBrushBevels( void );
|
||||||
brush_t *FinishBrush( bool noCollapseGroups );
|
|
||||||
|
|
||||||
|
|
||||||
/* portals.c */
|
/* portals.c */
|
||||||
void MakeHeadnodePortals( tree_t *tree );
|
void MakeHeadnodePortals( tree_t& tree );
|
||||||
void MakeNodePortal( node_t *node );
|
void MakeNodePortal( node_t *node );
|
||||||
void SplitNodePortals( node_t *node );
|
void SplitNodePortals( node_t *node );
|
||||||
|
|
||||||
|
|
@ -1616,32 +1603,33 @@ enum class EFloodEntities
|
||||||
Good,
|
Good,
|
||||||
Empty
|
Empty
|
||||||
};
|
};
|
||||||
EFloodEntities FloodEntities( tree_t *tree );
|
EFloodEntities FloodEntities( tree_t& tree );
|
||||||
void FillOutside( node_t *headnode );
|
void FillOutside( node_t *headnode );
|
||||||
void FloodAreas( tree_t *tree );
|
void FloodAreas( tree_t& tree );
|
||||||
void FreePortal( portal_t *p );
|
inline portal_t *AllocPortal( void ){ return new portal_t(); }
|
||||||
|
inline void FreePortal( portal_t *p ){ delete p; }
|
||||||
|
|
||||||
void MakeTreePortals( tree_t *tree );
|
void MakeTreePortals( tree_t& tree );
|
||||||
|
|
||||||
|
|
||||||
/* leakfile.c */
|
/* leakfile.c */
|
||||||
xmlNodePtr LeakFile( tree_t *tree );
|
xmlNodePtr LeakFile( const tree_t& tree );
|
||||||
|
|
||||||
|
|
||||||
/* prtfile.c */
|
/* prtfile.c */
|
||||||
void NumberClusters( tree_t *tree );
|
void NumberClusters( tree_t& tree );
|
||||||
void WritePortalFile( tree_t *tree );
|
void WritePortalFile( const tree_t& tree );
|
||||||
|
|
||||||
|
|
||||||
/* writebsp.c */
|
/* writebsp.c */
|
||||||
void SetModelNumbers( void );
|
void SetModelNumbers( void );
|
||||||
void SetLightStyles( void );
|
void SetLightStyles( void );
|
||||||
|
|
||||||
int EmitShader( const char *shader, int *contentFlags, int *surfaceFlags );
|
int EmitShader( const char *shader, const int *contentFlags, const int *surfaceFlags );
|
||||||
|
|
||||||
void BeginBSPFile( void );
|
void BeginBSPFile( void );
|
||||||
void EndBSPFile( bool do_write );
|
void EndBSPFile( bool do_write );
|
||||||
void EmitBrushes( brush_t *brushes, int *firstBrush, int *numBrushes );
|
void EmitBrushes( brushlist_t& brushes, int *firstBrush, int *numBrushes );
|
||||||
void EmitFogs( void );
|
void EmitFogs( void );
|
||||||
|
|
||||||
void BeginModel( void );
|
void BeginModel( void );
|
||||||
|
|
@ -1649,10 +1637,11 @@ void EndModel( entity_t *e, node_t *headnode );
|
||||||
|
|
||||||
|
|
||||||
/* tree.c */
|
/* tree.c */
|
||||||
void FreeTree( tree_t *tree );
|
void FreeTree( tree_t& tree );
|
||||||
void FreeTree_r( node_t *node );
|
void FreeTree_r( node_t *node );
|
||||||
void PrintTree_r( node_t *node, int depth );
|
void PrintTree_r( const node_t *node, int depth );
|
||||||
void FreeTreePortals_r( node_t *node );
|
void FreeTreePortals_r( node_t *node );
|
||||||
|
inline node_t *AllocNode(){ return new node_t(); }
|
||||||
|
|
||||||
|
|
||||||
/* patch.c */
|
/* patch.c */
|
||||||
|
|
@ -1667,7 +1656,7 @@ void FixTJunctions( entity_t *e );
|
||||||
|
|
||||||
|
|
||||||
/* fog.c */
|
/* fog.c */
|
||||||
winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds );
|
winding_t WindingFromDrawSurf( const mapDrawSurface_t *ds );
|
||||||
void FogDrawSurfaces( entity_t *e );
|
void FogDrawSurfaces( entity_t *e );
|
||||||
int FogForPoint( const Vector3& point, float epsilon );
|
int FogForPoint( const Vector3& point, float epsilon );
|
||||||
int FogForBounds( const MinMax& minmax, float epsilon );
|
int FogForBounds( const MinMax& minmax, float epsilon );
|
||||||
|
|
@ -1675,9 +1664,9 @@ void CreateMapFogs( void );
|
||||||
|
|
||||||
|
|
||||||
/* facebsp.c */
|
/* facebsp.c */
|
||||||
facelist_t MakeStructuralBSPFaceList( const brush_t *list );
|
facelist_t MakeStructuralBSPFaceList( const brushlist_t& list );
|
||||||
facelist_t MakeVisibleBSPFaceList( const brush_t *list );
|
facelist_t MakeVisibleBSPFaceList( const brushlist_t& list );
|
||||||
tree_t *FaceBSP( facelist_t& list );
|
tree_t FaceBSP( facelist_t& list );
|
||||||
|
|
||||||
|
|
||||||
/* model.c */
|
/* model.c */
|
||||||
|
|
@ -1701,17 +1690,17 @@ mapDrawSurface_t *MakeCelSurface( mapDrawSurface_t *src, shaderInfo_t
|
||||||
bool IsTriangleDegenerate( bspDrawVert_t *points, int a, int b, int c );
|
bool IsTriangleDegenerate( bspDrawVert_t *points, int a, int b, int c );
|
||||||
void ClearSurface( mapDrawSurface_t *ds );
|
void ClearSurface( mapDrawSurface_t *ds );
|
||||||
void AddEntitySurfaceModels( entity_t *e );
|
void AddEntitySurfaceModels( entity_t *e );
|
||||||
mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, const winding_t& w );
|
mapDrawSurface_t *DrawSurfaceForSide( const entity_t *e, const brush_t& b, const side_t& s, const winding_t& w );
|
||||||
mapDrawSurface_t *DrawSurfaceForMesh( entity_t *e, parseMesh_t *p, mesh_t *mesh );
|
mapDrawSurface_t *DrawSurfaceForMesh( entity_t *e, parseMesh_t *p, mesh_t *mesh );
|
||||||
mapDrawSurface_t *DrawSurfaceForFlare( int entNum, const Vector3& origin, const Vector3& normal, const Vector3& color, const char *flareShader, int lightStyle );
|
mapDrawSurface_t *DrawSurfaceForFlare( int entNum, const Vector3& origin, const Vector3& normal, const Vector3& color, const char *flareShader, int lightStyle );
|
||||||
mapDrawSurface_t *DrawSurfaceForShader( const char *shader );
|
mapDrawSurface_t *DrawSurfaceForShader( const char *shader );
|
||||||
void ClipSidesIntoTree( entity_t *e, tree_t *tree );
|
void ClipSidesIntoTree( entity_t *e, const tree_t& tree );
|
||||||
void MakeDebugPortalSurfs( tree_t *tree );
|
void MakeDebugPortalSurfs( const tree_t& tree );
|
||||||
void MakeFogHullSurfs( entity_t *e, tree_t *tree, const char *shader );
|
void MakeFogHullSurfs( entity_t *e, const char *shader );
|
||||||
void SubdivideFaceSurfaces( entity_t *e, tree_t *tree );
|
void SubdivideFaceSurfaces( entity_t *e );
|
||||||
void AddEntitySurfaceModels( entity_t *e );
|
void AddEntitySurfaceModels( entity_t *e );
|
||||||
int AddSurfaceModels( mapDrawSurface_t *ds );
|
int AddSurfaceModels( mapDrawSurface_t *ds );
|
||||||
void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree );
|
void FilterDrawsurfsIntoTree( entity_t *e, tree_t& tree );
|
||||||
void EmitPatchSurface( entity_t *e, mapDrawSurface_t *ds );
|
void EmitPatchSurface( entity_t *e, mapDrawSurface_t *ds );
|
||||||
void EmitTriangleSurface( mapDrawSurface_t *ds );
|
void EmitTriangleSurface( mapDrawSurface_t *ds );
|
||||||
|
|
||||||
|
|
@ -2112,7 +2101,7 @@ Q_EXTERN int numMapFogs Q_ASSIGN( 0 );
|
||||||
Q_EXTERN fog_t mapFogs[ MAX_MAP_FOGS ];
|
Q_EXTERN fog_t mapFogs[ MAX_MAP_FOGS ];
|
||||||
|
|
||||||
Q_EXTERN entity_t *mapEnt;
|
Q_EXTERN entity_t *mapEnt;
|
||||||
Q_EXTERN brush_t *buildBrush;
|
Q_EXTERN brush_t buildBrush;
|
||||||
Q_EXTERN EBrushType g_brushType Q_ASSIGN( EBrushType::Undefined );
|
Q_EXTERN EBrushType g_brushType Q_ASSIGN( EBrushType::Undefined );
|
||||||
|
|
||||||
Q_EXTERN int numStrippedLights Q_ASSIGN( 0 );
|
Q_EXTERN int numStrippedLights Q_ASSIGN( 0 );
|
||||||
|
|
|
||||||
|
|
@ -761,12 +761,13 @@ shaderInfo_t *GetIndexedShader( const shaderInfo_t *parent, const indexMap_t *im
|
||||||
/*
|
/*
|
||||||
DrawSurfaceForSide()
|
DrawSurfaceForSide()
|
||||||
creates a SURF_FACE drawsurface from a given brush side and winding
|
creates a SURF_FACE drawsurface from a given brush side and winding
|
||||||
|
stores references to given brush and side
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const double SNAP_FLOAT_TO_INT = 8.0;
|
const double SNAP_FLOAT_TO_INT = 8.0;
|
||||||
const double SNAP_INT_TO_FLOAT = ( 1.0 / SNAP_FLOAT_TO_INT );
|
const double SNAP_INT_TO_FLOAT = ( 1.0 / SNAP_FLOAT_TO_INT );
|
||||||
|
|
||||||
mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, const winding_t& w ){
|
mapDrawSurface_t *DrawSurfaceForSide( const entity_t *e, const brush_t& b, const side_t& s, const winding_t& w ){
|
||||||
mapDrawSurface_t *ds;
|
mapDrawSurface_t *ds;
|
||||||
shaderInfo_t *si, *parent;
|
shaderInfo_t *si, *parent;
|
||||||
bspDrawVert_t *dv;
|
bspDrawVert_t *dv;
|
||||||
|
|
@ -779,7 +780,7 @@ mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, const
|
||||||
|
|
||||||
|
|
||||||
/* ydnar: don't make a drawsurf for culled sides */
|
/* ydnar: don't make a drawsurf for culled sides */
|
||||||
if ( s->culled ) {
|
if ( s.culled ) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -789,24 +790,24 @@ mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, const
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get shader */
|
/* get shader */
|
||||||
si = s->shaderInfo;
|
si = s.shaderInfo;
|
||||||
|
|
||||||
/* ydnar: gs mods: check for indexed shader */
|
/* ydnar: gs mods: check for indexed shader */
|
||||||
if ( si->indexed && b->im != NULL ) {
|
if ( si->indexed && b.im != NULL ) {
|
||||||
/* indexed */
|
/* indexed */
|
||||||
indexed = true;
|
indexed = true;
|
||||||
|
|
||||||
/* get shader indexes for each point */
|
/* get shader indexes for each point */
|
||||||
for ( size_t i = 0; i < w.size(); i++ )
|
for ( size_t i = 0; i < w.size(); i++ )
|
||||||
{
|
{
|
||||||
shaderIndexes[ i ] = GetShaderIndexForPoint( b->im, b->eMinmax, w[ i ] );
|
shaderIndexes[ i ] = GetShaderIndexForPoint( b.im, b.eMinmax, w[ i ] );
|
||||||
offsets[ i ] = b->im->offsets[ shaderIndexes[ i ] ];
|
offsets[ i ] = b.im->offsets[ shaderIndexes[ i ] ];
|
||||||
//% Sys_Printf( "%f ", offsets[ i ] );
|
//% Sys_Printf( "%f ", offsets[ i ] );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get matching shader and set alpha */
|
/* get matching shader and set alpha */
|
||||||
parent = si;
|
parent = si;
|
||||||
si = GetIndexedShader( parent, b->im, w.size(), shaderIndexes );
|
si = GetIndexedShader( parent, b.im, w.size(), shaderIndexes );
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
indexed = false;
|
indexed = false;
|
||||||
|
|
@ -821,25 +822,25 @@ mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, const
|
||||||
|
|
||||||
/* ydnar: gs mods */
|
/* ydnar: gs mods */
|
||||||
ds = AllocDrawSurface( ESurfaceType::Face );
|
ds = AllocDrawSurface( ESurfaceType::Face );
|
||||||
ds->entityNum = b->entityNum;
|
ds->entityNum = b.entityNum;
|
||||||
ds->castShadows = b->castShadows;
|
ds->castShadows = b.castShadows;
|
||||||
ds->recvShadows = b->recvShadows;
|
ds->recvShadows = b.recvShadows;
|
||||||
|
|
||||||
ds->planar = true;
|
ds->planar = true;
|
||||||
ds->planeNum = s->planenum;
|
ds->planeNum = s.planenum;
|
||||||
ds->lightmapVecs[ 2 ] = mapplanes[ s->planenum ].normal();
|
ds->lightmapVecs[ 2 ] = mapplanes[ s.planenum ].normal();
|
||||||
|
|
||||||
ds->shaderInfo = si;
|
ds->shaderInfo = si;
|
||||||
ds->mapBrush = b;
|
ds->mapBrush = &b;
|
||||||
ds->sideRef = AllocSideRef( s, NULL );
|
ds->sideRef = AllocSideRef( &s, NULL );
|
||||||
ds->fogNum = -1;
|
ds->fogNum = -1;
|
||||||
ds->sampleSize = b->lightmapSampleSize;
|
ds->sampleSize = b.lightmapSampleSize;
|
||||||
ds->lightmapScale = b->lightmapScale;
|
ds->lightmapScale = b.lightmapScale;
|
||||||
ds->numVerts = w.size();
|
ds->numVerts = w.size();
|
||||||
ds->verts = safe_calloc( ds->numVerts * sizeof( *ds->verts ) );
|
ds->verts = safe_calloc( ds->numVerts * sizeof( *ds->verts ) );
|
||||||
|
|
||||||
/* compute s/t coordinates from brush primitive texture matrix (compute axis base) */
|
/* compute s/t coordinates from brush primitive texture matrix (compute axis base) */
|
||||||
ComputeAxisBase( mapplanes[ s->planenum ].normal(), texX, texY );
|
ComputeAxisBase( mapplanes[ s.planenum ].normal(), texX, texY );
|
||||||
|
|
||||||
/* create the vertexes */
|
/* create the vertexes */
|
||||||
for ( size_t j = 0; j < w.size(); j++ )
|
for ( size_t j = 0; j < w.size(); j++ )
|
||||||
|
|
@ -874,21 +875,21 @@ mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, const
|
||||||
/* calculate texture s/t from brush primitive texture matrix */
|
/* calculate texture s/t from brush primitive texture matrix */
|
||||||
x = vector3_dot( vTranslated, texX );
|
x = vector3_dot( vTranslated, texX );
|
||||||
y = vector3_dot( vTranslated, texY );
|
y = vector3_dot( vTranslated, texY );
|
||||||
dv->st[ 0 ] = s->texMat[ 0 ][ 0 ] * x + s->texMat[ 0 ][ 1 ] * y + s->texMat[ 0 ][ 2 ];
|
dv->st[ 0 ] = s.texMat[ 0 ][ 0 ] * x + s.texMat[ 0 ][ 1 ] * y + s.texMat[ 0 ][ 2 ];
|
||||||
dv->st[ 1 ] = s->texMat[ 1 ][ 0 ] * x + s->texMat[ 1 ][ 1 ] * y + s->texMat[ 1 ][ 2 ];
|
dv->st[ 1 ] = s.texMat[ 1 ][ 0 ] * x + s.texMat[ 1 ][ 1 ] * y + s.texMat[ 1 ][ 2 ];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* old quake-style or valve 220 texturing */
|
/* old quake-style or valve 220 texturing */
|
||||||
else {
|
else {
|
||||||
/* nearest-axial projection */
|
/* nearest-axial projection */
|
||||||
dv->st[ 0 ] = s->vecs[ 0 ][ 3 ] + vector3_dot( s->vecs[ 0 ].vec3(), vTranslated );
|
dv->st[ 0 ] = s.vecs[ 0 ][ 3 ] + vector3_dot( s.vecs[ 0 ].vec3(), vTranslated );
|
||||||
dv->st[ 1 ] = s->vecs[ 1 ][ 3 ] + vector3_dot( s->vecs[ 1 ].vec3(), vTranslated );
|
dv->st[ 1 ] = s.vecs[ 1 ][ 3 ] + vector3_dot( s.vecs[ 1 ].vec3(), vTranslated );
|
||||||
dv->st[ 0 ] /= si->shaderWidth;
|
dv->st[ 0 ] /= si->shaderWidth;
|
||||||
dv->st[ 1 ] /= si->shaderHeight;
|
dv->st[ 1 ] /= si->shaderHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy normal */
|
/* copy normal */
|
||||||
dv->normal = mapplanes[ s->planenum ].normal();
|
dv->normal = mapplanes[ s.planenum ].normal();
|
||||||
|
|
||||||
/* ydnar: set color */
|
/* ydnar: set color */
|
||||||
for ( int k = 0; k < MAX_LIGHTMAPS; k++ )
|
for ( int k = 0; k < MAX_LIGHTMAPS; k++ )
|
||||||
|
|
@ -902,11 +903,11 @@ mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, const
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set cel shader */
|
/* set cel shader */
|
||||||
ds->celShader = b->celShader;
|
ds->celShader = b.celShader;
|
||||||
|
|
||||||
/* set shade angle */
|
/* set shade angle */
|
||||||
if ( b->shadeAngleDegrees > 0.0f ) {
|
if ( b.shadeAngleDegrees > 0.0f ) {
|
||||||
ds->shadeAngleDegrees = b->shadeAngleDegrees;
|
ds->shadeAngleDegrees = b.shadeAngleDegrees;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ydnar: gs mods: moved st biasing elsewhere */
|
/* ydnar: gs mods: moved st biasing elsewhere */
|
||||||
|
|
@ -1202,25 +1203,24 @@ static void AddSurfaceFlare( mapDrawSurface_t *ds, const Vector3& entityOrigin )
|
||||||
subdivides a face surface until it is smaller than the specified size (subdivisions)
|
subdivides a face surface until it is smaller than the specified size (subdivisions)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void SubdivideFace_r( entity_t *e, brush_t *brush, side_t *side, const winding_t *w, int fogNum, float subdivisions ){
|
static void SubdivideFace_r( entity_t *e, const brush_t& brush, const side_t& side, winding_t& w, int fogNum, float subdivisions ){
|
||||||
int axis;
|
int axis;
|
||||||
MinMax bounds;
|
MinMax bounds;
|
||||||
const float epsilon = 0.1;
|
const float epsilon = 0.1;
|
||||||
int subFloor, subCeil;
|
int subFloor, subCeil;
|
||||||
winding_t *frontWinding, *backWinding;
|
|
||||||
mapDrawSurface_t *ds;
|
mapDrawSurface_t *ds;
|
||||||
|
|
||||||
|
|
||||||
/* dummy check */
|
/* dummy check */
|
||||||
if ( w == NULL ) {
|
if ( w.empty() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( w->size() < 3 ) {
|
if ( w.size() < 3 ) {
|
||||||
Error( "SubdivideFace_r: Bad w->numpoints (%zu < 3)", w->size() );
|
Error( "SubdivideFace_r: Bad w->numpoints (%zu < 3)", w.size() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* determine surface bounds */
|
/* determine surface bounds */
|
||||||
WindingExtendBounds( *w, bounds );
|
WindingExtendBounds( w, bounds );
|
||||||
|
|
||||||
/* split the face */
|
/* split the face */
|
||||||
for ( axis = 0; axis < 3; axis++ )
|
for ( axis = 0; axis < 3; axis++ )
|
||||||
|
|
@ -1239,14 +1239,14 @@ static void SubdivideFace_r( entity_t *e, brush_t *brush, side_t *side, const wi
|
||||||
/* subdivide if necessary */
|
/* subdivide if necessary */
|
||||||
if ( ( subCeil - subFloor ) > subdivisions ) {
|
if ( ( subCeil - subFloor ) > subdivisions ) {
|
||||||
/* clip the winding */
|
/* clip the winding */
|
||||||
ClipWindingEpsilon( *w, plane, epsilon, frontWinding, backWinding ); /* not strict; we assume we always keep a winding */
|
auto [frontWinding, backWinding] = ClipWindingEpsilon( w, plane, epsilon ); /* not strict; we assume we always keep a winding */
|
||||||
|
|
||||||
/* the clip may not produce two polygons if it was epsilon close */
|
/* the clip may not produce two polygons if it was epsilon close */
|
||||||
if ( frontWinding == NULL ) {
|
if ( frontWinding.empty() ) {
|
||||||
w = backWinding;
|
w.swap( backWinding );
|
||||||
}
|
}
|
||||||
else if ( backWinding == NULL ) {
|
else if ( backWinding.empty() ) {
|
||||||
w = frontWinding;
|
w.swap( frontWinding );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1258,7 +1258,7 @@ static void SubdivideFace_r( entity_t *e, brush_t *brush, side_t *side, const wi
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create a face surface */
|
/* create a face surface */
|
||||||
ds = DrawSurfaceForSide( e, brush, side, *w );
|
ds = DrawSurfaceForSide( e, brush, side, w );
|
||||||
|
|
||||||
/* set correct fog num */
|
/* set correct fog num */
|
||||||
ds->fogNum = fogNum;
|
ds->fogNum = fogNum;
|
||||||
|
|
@ -1272,13 +1272,9 @@ static void SubdivideFace_r( entity_t *e, brush_t *brush, side_t *side, const wi
|
||||||
ydnar: and subdivide surfaces that exceed specified texture coordinate range
|
ydnar: and subdivide surfaces that exceed specified texture coordinate range
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void SubdivideFaceSurfaces( entity_t *e, tree_t *tree ){
|
void SubdivideFaceSurfaces( entity_t *e ){
|
||||||
int i, j, numBaseDrawSurfs, fogNum;
|
int i, j, numBaseDrawSurfs, fogNum;
|
||||||
mapDrawSurface_t *ds;
|
mapDrawSurface_t *ds;
|
||||||
brush_t *brush;
|
|
||||||
side_t *side;
|
|
||||||
shaderInfo_t *si;
|
|
||||||
winding_t *w;
|
|
||||||
float range, size, subdivisions, s2;
|
float range, size, subdivisions, s2;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1298,11 +1294,11 @@ void SubdivideFaceSurfaces( entity_t *e, tree_t *tree ){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get bits */
|
/* get bits */
|
||||||
brush = ds->mapBrush;
|
const brush_t *brush = ds->mapBrush;
|
||||||
side = ds->sideRef->side;
|
const side_t& side = *ds->sideRef->side;
|
||||||
|
|
||||||
/* check subdivision for shader */
|
/* check subdivision for shader */
|
||||||
si = side->shaderInfo;
|
const shaderInfo_t *si = side.shaderInfo;
|
||||||
if ( si == NULL ) {
|
if ( si == NULL ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -1347,11 +1343,11 @@ void SubdivideFaceSurfaces( entity_t *e, tree_t *tree ){
|
||||||
fogNum = ds->fogNum;
|
fogNum = ds->fogNum;
|
||||||
|
|
||||||
/* make a winding and free the surface */
|
/* make a winding and free the surface */
|
||||||
w = WindingFromDrawSurf( ds );
|
winding_t w = WindingFromDrawSurf( ds );
|
||||||
ClearSurface( ds );
|
ClearSurface( ds );
|
||||||
|
|
||||||
/* subdivide it */
|
/* subdivide it */
|
||||||
SubdivideFace_r( e, brush, side, w, fogNum, subdivisions );
|
SubdivideFace_r( e, *brush, side, w, fogNum, subdivisions );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1365,46 +1361,40 @@ void SubdivideFaceSurfaces( entity_t *e, tree_t *tree ){
|
||||||
====================
|
====================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void ClipSideIntoTree_r( winding_t *w, side_t *side, node_t *node ){
|
void ClipSideIntoTree_r( const winding_t& w, side_t& side, const node_t *node ){
|
||||||
winding_t *front, *back;
|
if ( w.empty() ) {
|
||||||
|
|
||||||
if ( !w ) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( node->planenum != PLANENUM_LEAF ) {
|
if ( node->planenum != PLANENUM_LEAF ) {
|
||||||
if ( side->planenum == node->planenum ) {
|
if ( side.planenum == node->planenum ) {
|
||||||
ClipSideIntoTree_r( w, side, node->children[0] );
|
ClipSideIntoTree_r( w, side, node->children[0] );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( side->planenum == ( node->planenum ^ 1 ) ) {
|
if ( side.planenum == ( node->planenum ^ 1 ) ) {
|
||||||
ClipSideIntoTree_r( w, side, node->children[1] );
|
ClipSideIntoTree_r( w, side, node->children[1] );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Plane3f& plane = mapplanes[ node->planenum ].plane;
|
const Plane3f& plane = mapplanes[ node->planenum ].plane;
|
||||||
ClipWindingEpsilonStrict( *w, plane,
|
auto [front, back] = ClipWindingEpsilonStrict( w, plane, ON_EPSILON ); /* strict, we handle the "winding disappeared" case */
|
||||||
ON_EPSILON, front, back ); /* strict, we handle the "winding disappeared" case */
|
if ( front.empty() && back.empty() ) {
|
||||||
if ( !front && !back ) {
|
|
||||||
/* in doubt, register it in both nodes */
|
/* in doubt, register it in both nodes */
|
||||||
front = CopyWinding( w );
|
ClipSideIntoTree_r( w, side, node->children[0] );
|
||||||
back = CopyWinding( w );
|
ClipSideIntoTree_r( w, side, node->children[1] );
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ClipSideIntoTree_r( front, side, node->children[0] );
|
||||||
|
ClipSideIntoTree_r( back, side, node->children[1] );
|
||||||
}
|
}
|
||||||
FreeWinding( w );
|
|
||||||
|
|
||||||
ClipSideIntoTree_r( front, side, node->children[0] );
|
|
||||||
ClipSideIntoTree_r( back, side, node->children[1] );
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if opaque leaf, don't add
|
// if opaque leaf, don't add
|
||||||
if ( !node->opaque ) {
|
if ( !node->opaque ) {
|
||||||
AddWindingToConvexHull( *w, side->visibleHull, mapplanes[ side->planenum ].normal() );
|
AddWindingToConvexHull( w, side.visibleHull, mapplanes[ side.planenum ].normal() );
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeWinding( w );
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1422,44 +1412,42 @@ static int g_numHiddenFaces, g_numCoinFaces;
|
||||||
determines if a brushside lies inside another brush
|
determines if a brushside lies inside another brush
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool SideInBrush( side_t *side, brush_t *b ){
|
bool SideInBrush( side_t& side, const brush_t& b ){
|
||||||
/* ignore sides w/o windings or shaders */
|
/* ignore sides w/o windings or shaders */
|
||||||
if ( side->winding == NULL || side->shaderInfo == NULL ) {
|
if ( side.winding.empty() || side.shaderInfo == NULL ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ignore culled sides and translucent brushes */
|
/* ignore culled sides and translucent brushes */
|
||||||
if ( side->culled || ( b->compileFlags & C_TRANSLUCENT ) ) {
|
if ( side.culled || ( b.compileFlags & C_TRANSLUCENT ) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* side iterator */
|
/* side iterator */
|
||||||
for ( int i = 0; i < b->numsides; i++ )
|
for ( const side_t& bside : b.sides )
|
||||||
{
|
{
|
||||||
/* fail if any sides are caulk */
|
/* fail if any sides are caulk */
|
||||||
if ( b->sides[ i ].compileFlags & C_NODRAW ) {
|
if ( bside.compileFlags & C_NODRAW ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if side's winding is on or behind the plane */
|
/* check if side's winding is on or behind the plane */
|
||||||
const Plane3f& plane = mapplanes[ b->sides[ i ].planenum ].plane;
|
const Plane3f& plane = mapplanes[ bside.planenum ].plane;
|
||||||
const EPlaneSide s = WindingOnPlaneSide( *side->winding, plane );
|
const EPlaneSide s = WindingOnPlaneSide( side.winding, plane );
|
||||||
if ( s == eSideFront || s == eSideCross ) {
|
if ( s == eSideFront || s == eSideCross ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if( s == eSideOn && b->sides[ i ].culled && vector3_dot( mapplanes[ side->planenum ].normal(), plane.normal() ) > 0 ) /* don't cull by freshly culled with matching plane */
|
if( s == eSideOn && bside.culled && vector3_dot( mapplanes[ side.planenum ].normal(), plane.normal() ) > 0 ) /* don't cull by freshly culled with matching plane */
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* don't cull autosprite or polygonoffset surfaces */
|
/* don't cull autosprite or polygonoffset surfaces */
|
||||||
if ( side->shaderInfo ) {
|
if ( side.shaderInfo->autosprite || side.shaderInfo->polygonOffset ) {
|
||||||
if ( side->shaderInfo->autosprite || side->shaderInfo->polygonOffset ) {
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* inside */
|
/* inside */
|
||||||
side->culled = true;
|
side.culled = true;
|
||||||
g_numHiddenFaces++;
|
g_numHiddenFaces++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1471,11 +1459,7 @@ bool SideInBrush( side_t *side, brush_t *b ){
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void CullSides( entity_t *e ){
|
void CullSides( entity_t *e ){
|
||||||
int numPoints;
|
int k, l, first, second, dir;
|
||||||
int i, j, k, l, first, second, dir;
|
|
||||||
const winding_t *w1, *w2;
|
|
||||||
brush_t *b1, *b2;
|
|
||||||
side_t *side1, *side2;
|
|
||||||
|
|
||||||
|
|
||||||
/* note it */
|
/* note it */
|
||||||
|
|
@ -1485,18 +1469,18 @@ void CullSides( entity_t *e ){
|
||||||
g_numCoinFaces = 0;
|
g_numCoinFaces = 0;
|
||||||
|
|
||||||
/* brush interator 1 */
|
/* brush interator 1 */
|
||||||
for ( b1 = e->brushes; b1; b1 = b1->next )
|
for ( brushlist_t::iterator b1 = e->brushes.begin(); b1 != e->brushes.end(); ++b1 )
|
||||||
{
|
{
|
||||||
/* sides check */
|
/* sides check */
|
||||||
if ( b1->numsides < 1 ) {
|
if ( b1->sides.empty() ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* brush iterator 2 */
|
/* brush iterator 2 */
|
||||||
for ( b2 = b1->next; b2; b2 = b2->next )
|
for ( brushlist_t::iterator b2 = std::next( b1 ); b2 != e->brushes.end(); ++b2 )
|
||||||
{
|
{
|
||||||
/* sides check */
|
/* sides check */
|
||||||
if ( b2->numsides < 1 ) {
|
if ( b2->sides.empty() ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1511,56 +1495,52 @@ void CullSides( entity_t *e ){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cull inside sides */
|
/* cull inside sides */
|
||||||
for ( i = 0; i < b1->numsides; i++ )
|
for ( side_t& side : b1->sides )
|
||||||
SideInBrush( &b1->sides[ i ], b2 );
|
SideInBrush( side, *b2 );
|
||||||
for ( i = 0; i < b2->numsides; i++ )
|
for ( side_t& side : b2->sides )
|
||||||
SideInBrush( &b2->sides[ i ], b1 );
|
SideInBrush( side, *b1 );
|
||||||
|
|
||||||
/* side iterator 1 */
|
/* side iterator 1 */
|
||||||
for ( i = 0; i < b1->numsides; i++ )
|
for ( side_t& side1 : b1->sides )
|
||||||
{
|
{
|
||||||
/* winding check */
|
/* winding check */
|
||||||
side1 = &b1->sides[ i ];
|
winding_t& w1 = side1.winding;
|
||||||
w1 = side1->winding;
|
if ( w1.empty() ) {
|
||||||
if ( w1 == NULL ) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
numPoints = w1->size();
|
const int numPoints = w1.size();
|
||||||
if ( side1->shaderInfo == NULL ) {
|
if ( side1.shaderInfo == NULL ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* side iterator 2 */
|
/* side iterator 2 */
|
||||||
for ( j = 0; j < b2->numsides; j++ )
|
for ( side_t& side2 : b2->sides )
|
||||||
{
|
{
|
||||||
/* winding check */
|
/* winding check */
|
||||||
side2 = &b2->sides[ j ];
|
winding_t& w2 = side2.winding;
|
||||||
w2 = side2->winding;
|
if ( w2.empty() ) {
|
||||||
if ( w2 == NULL ) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( side2->shaderInfo == NULL ) {
|
if ( side2.shaderInfo == NULL ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( w1->size() != w2->size() ) {
|
if ( w1.size() != w2.size() ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( side1->culled && side2->culled ) {
|
if ( side1.culled && side2.culled ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* compare planes */
|
/* compare planes */
|
||||||
if ( ( side1->planenum & ~0x00000001 ) != ( side2->planenum & ~0x00000001 ) ) {
|
if ( ( side1.planenum & ~0x00000001 ) != ( side2.planenum & ~0x00000001 ) ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get autosprite and polygonoffset status */
|
/* get autosprite and polygonoffset status */
|
||||||
if ( side1->shaderInfo &&
|
if ( side1.shaderInfo->autosprite || side1.shaderInfo->polygonOffset ) {
|
||||||
( side1->shaderInfo->autosprite || side1->shaderInfo->polygonOffset ) ) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( side2->shaderInfo &&
|
if ( side2.shaderInfo->autosprite || side2.shaderInfo->polygonOffset ) {
|
||||||
( side2->shaderInfo->autosprite || side2->shaderInfo->polygonOffset ) ) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1568,7 +1548,7 @@ void CullSides( entity_t *e ){
|
||||||
first = -1;
|
first = -1;
|
||||||
for ( k = 0; k < numPoints; k++ )
|
for ( k = 0; k < numPoints; k++ )
|
||||||
{
|
{
|
||||||
if ( VectorCompare( ( *w1 )[ 0 ], ( *w2 )[ k ] ) ) {
|
if ( VectorCompare( w1[ 0 ], w2[ k ] ) ) {
|
||||||
first = k;
|
first = k;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1586,7 +1566,7 @@ void CullSides( entity_t *e ){
|
||||||
else{
|
else{
|
||||||
second = 0;
|
second = 0;
|
||||||
}
|
}
|
||||||
if ( vector3_equal_epsilon( ( *w1 )[ 1 ], ( *w2 )[ second ], CULL_EPSILON ) ) {
|
if ( vector3_equal_epsilon( w1[ 1 ], w2[ second ], CULL_EPSILON ) ) {
|
||||||
dir = 1;
|
dir = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1597,7 +1577,7 @@ void CullSides( entity_t *e ){
|
||||||
else{
|
else{
|
||||||
second = numPoints - 1;
|
second = numPoints - 1;
|
||||||
}
|
}
|
||||||
if ( vector3_equal_epsilon( ( *w1 )[ 1 ], ( *w2 )[ second ], CULL_EPSILON ) ) {
|
if ( vector3_equal_epsilon( w1[ 1 ], w2[ second ], CULL_EPSILON ) ) {
|
||||||
dir = -1;
|
dir = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1609,7 +1589,7 @@ void CullSides( entity_t *e ){
|
||||||
l = first;
|
l = first;
|
||||||
for ( k = 0; k < numPoints; k++ )
|
for ( k = 0; k < numPoints; k++ )
|
||||||
{
|
{
|
||||||
if ( !vector3_equal_epsilon( ( *w1 )[ k ], ( *w2 )[ l ], CULL_EPSILON ) ) {
|
if ( !vector3_equal_epsilon( w1[ k ], w2[ l ], CULL_EPSILON ) ) {
|
||||||
k = 100000;
|
k = 100000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1626,18 +1606,18 @@ void CullSides( entity_t *e ){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cull face 1 */
|
/* cull face 1 */
|
||||||
if ( !side2->culled && !( side2->compileFlags & C_TRANSLUCENT ) && !( side2->compileFlags & C_NODRAW ) ) {
|
if ( !side2.culled && !( side2.compileFlags & C_TRANSLUCENT ) && !( side2.compileFlags & C_NODRAW ) ) {
|
||||||
side1->culled = true;
|
side1.culled = true;
|
||||||
g_numCoinFaces++;
|
g_numCoinFaces++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( side1->planenum == side2->planenum && side1->culled ) {
|
if ( side1.planenum == side2.planenum && side1.culled ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cull face 2 */
|
/* cull face 2 */
|
||||||
if ( !side1->culled && !( side1->compileFlags & C_TRANSLUCENT ) && !( side1->compileFlags & C_NODRAW ) ) {
|
if ( !side1.culled && !( side1.compileFlags & C_TRANSLUCENT ) && !( side1.compileFlags & C_NODRAW ) ) {
|
||||||
side2->culled = true;
|
side2.culled = true;
|
||||||
g_numCoinFaces++;
|
g_numCoinFaces++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1665,14 +1645,7 @@ void CullSides( entity_t *e ){
|
||||||
to be trimmed off automatically.
|
to be trimmed off automatically.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void ClipSidesIntoTree( entity_t *e, tree_t *tree ){
|
void ClipSidesIntoTree( entity_t *e, const tree_t& tree ){
|
||||||
brush_t *b;
|
|
||||||
int i;
|
|
||||||
winding_t *w;
|
|
||||||
side_t *side, *newSide;
|
|
||||||
shaderInfo_t *si;
|
|
||||||
|
|
||||||
|
|
||||||
/* ydnar: cull brush sides */
|
/* ydnar: cull brush sides */
|
||||||
CullSides( e );
|
CullSides( e );
|
||||||
|
|
||||||
|
|
@ -1680,30 +1653,25 @@ void ClipSidesIntoTree( entity_t *e, tree_t *tree ){
|
||||||
Sys_FPrintf( SYS_VRB, "--- ClipSidesIntoTree ---\n" );
|
Sys_FPrintf( SYS_VRB, "--- ClipSidesIntoTree ---\n" );
|
||||||
|
|
||||||
/* walk the brush list */
|
/* walk the brush list */
|
||||||
for ( b = e->brushes; b; b = b->next )
|
for ( brush_t& b : e->brushes )
|
||||||
{
|
{
|
||||||
/* walk the brush sides */
|
/* walk the brush sides */
|
||||||
for ( i = 0; i < b->numsides; i++ )
|
for ( side_t& side : b.sides )
|
||||||
{
|
{
|
||||||
/* get side */
|
if ( side.winding.empty() ) {
|
||||||
side = &b->sides[ i ];
|
|
||||||
if ( side->winding == NULL ) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy the winding */
|
side.visibleHull.clear();
|
||||||
w = CopyWinding( side->winding );
|
ClipSideIntoTree_r( side.winding, side, tree.headnode );
|
||||||
side->visibleHull = NULL;
|
|
||||||
ClipSideIntoTree_r( w, side, tree->headnode );
|
|
||||||
|
|
||||||
/* anything left? */
|
/* anything left? */
|
||||||
w = side->visibleHull;
|
if ( side.visibleHull.empty() ) {
|
||||||
if ( w == NULL ) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* shader? */
|
/* shader? */
|
||||||
si = side->shaderInfo;
|
const shaderInfo_t *si = side.shaderInfo;
|
||||||
if ( si == NULL ) {
|
if ( si == NULL ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -1715,27 +1683,21 @@ void ClipSidesIntoTree( entity_t *e, tree_t *tree ){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* always use the original winding for autosprites and noclip faces */
|
/* always use the original winding for autosprites and noclip faces */
|
||||||
if ( si->autosprite || si->noClip ) {
|
const winding_t& w = ( si->autosprite || si->noClip )? side.winding : side.visibleHull;
|
||||||
w = side->winding;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* save this winding as a visible surface */
|
/* save this winding as a visible surface */
|
||||||
DrawSurfaceForSide( e, b, side, *w );
|
DrawSurfaceForSide( e, b, side, w );
|
||||||
|
|
||||||
/* make a back side for fog */
|
/* make a back side for fog */
|
||||||
if ( !( si->compileFlags & C_FOG ) ) {
|
if ( si->compileFlags & C_FOG ) {
|
||||||
continue;
|
/* duplicate the up-facing side */
|
||||||
|
side_t& newSide = *new side_t( side );
|
||||||
|
newSide.visibleHull = ReverseWinding( w );
|
||||||
|
newSide.planenum ^= 1;
|
||||||
|
|
||||||
|
/* save this winding as a visible surface */
|
||||||
|
DrawSurfaceForSide( e, b, newSide, newSide.visibleHull ); // references new side by sideref, leak!
|
||||||
}
|
}
|
||||||
|
|
||||||
/* duplicate the up-facing side */
|
|
||||||
w = ReverseWinding( *w );
|
|
||||||
newSide = safe_malloc( sizeof( *side ) );
|
|
||||||
*newSide = *side;
|
|
||||||
newSide->visibleHull = w;
|
|
||||||
newSide->planenum ^= 1;
|
|
||||||
|
|
||||||
/* save this winding as a visible surface */
|
|
||||||
DrawSurfaceForSide( e, b, newSide, *w );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1910,14 +1872,11 @@ int FilterPointConvexHullIntoTree_r( Vector3 *points[], const int npoints, mapDr
|
||||||
filters a winding from a drawsurface into the tree
|
filters a winding from a drawsurface into the tree
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int FilterWindingIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node ){
|
int FilterWindingIntoTree_r( winding_t& w, mapDrawSurface_t *ds, node_t *node ){
|
||||||
int refs = 0;
|
int refs = 0;
|
||||||
winding_t *fat, *front, *back;
|
|
||||||
shaderInfo_t *si;
|
|
||||||
|
|
||||||
|
|
||||||
/* get shaderinfo */
|
/* get shaderinfo */
|
||||||
si = ds->shaderInfo;
|
const shaderInfo_t *si = ds->shaderInfo;
|
||||||
|
|
||||||
/* ydnar: is this the head node? */
|
/* ydnar: is this the head node? */
|
||||||
if ( node->parent == NULL && si != NULL && si->minmax.valid() ) {
|
if ( node->parent == NULL && si != NULL && si->minmax.valid() ) {
|
||||||
|
|
@ -1929,17 +1888,16 @@ int FilterWindingIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node ){
|
||||||
|
|
||||||
/* 'fatten' the winding by the shader mins/maxs (parsed from vertexDeform move) */
|
/* 'fatten' the winding by the shader mins/maxs (parsed from vertexDeform move) */
|
||||||
/* note this winding is completely invalid (concave, nonplanar, etc) */
|
/* note this winding is completely invalid (concave, nonplanar, etc) */
|
||||||
fat = AllocWinding( w->size() * 3 + 3 );
|
winding_t fat( w.size() * 3 + 3 );
|
||||||
fat->resize( w->size() * 3 + 3 );
|
for ( size_t i = 0; i < w.size(); i++ )
|
||||||
for ( size_t i = 0; i < w->size(); i++ )
|
|
||||||
{
|
{
|
||||||
( *fat )[ i ] = ( *w )[ i ];
|
fat[ i ] = w[ i ];
|
||||||
( *fat )[ i + ( w->size() + 1 ) ] = ( *w )[ i ] + si->minmax.mins;
|
fat[ i + ( w.size() + 1 ) ] = w[ i ] + si->minmax.mins;
|
||||||
( *fat )[ i + ( w->size() + 1 ) * 2 ] = ( *w )[ i ] + si->minmax.maxs;
|
fat[ i + ( w.size() + 1 ) * 2 ] = w[ i ] + si->minmax.maxs;
|
||||||
}
|
}
|
||||||
( *fat )[ w->size() ] = ( *w )[ 0 ];
|
fat[ w.size() ] = w[ 0 ];
|
||||||
( *fat )[ w->size() * 2 ] = ( *w )[ 0 ] + si->minmax.mins;
|
fat[ w.size() * 2 ] = w[ 0 ] + si->minmax.mins;
|
||||||
( *fat )[ w->size() * 3 ] = ( *w )[ 0 ] + si->minmax.maxs;
|
fat[ w.size() * 3 ] = w[ 0 ] + si->minmax.maxs;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* note: this winding is STILL not suitable for ClipWindingEpsilon, and
|
* note: this winding is STILL not suitable for ClipWindingEpsilon, and
|
||||||
|
|
@ -1949,8 +1907,7 @@ int FilterWindingIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node ){
|
||||||
* it worse
|
* it worse
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FreeWinding( w );
|
w.swap( fat );
|
||||||
w = fat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* is this a decision node? */
|
/* is this a decision node? */
|
||||||
|
|
@ -1989,23 +1946,23 @@ int FilterWindingIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node ){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clip the winding by this plane */
|
/* clip the winding by this plane */
|
||||||
ClipWindingEpsilonStrict( *w, plane1, ON_EPSILON, front, back ); /* strict; we handle the "winding disappeared" case */
|
auto [front, back] = ClipWindingEpsilonStrict( w, plane1, ON_EPSILON ); /* strict; we handle the "winding disappeared" case */
|
||||||
|
|
||||||
/* filter by this plane */
|
/* filter by this plane */
|
||||||
refs = 0;
|
refs = 0;
|
||||||
if ( front == NULL && back == NULL ) {
|
if ( front.empty() && back.empty() ) {
|
||||||
/* same plane, this is an ugly hack */
|
/* same plane, this is an ugly hack */
|
||||||
/* but better too many than too few refs */
|
/* but better too many than too few refs */
|
||||||
refs += FilterWindingIntoTree_r( CopyWinding( w ), ds, node->children[ 0 ] );
|
winding_t wcopy( w );
|
||||||
refs += FilterWindingIntoTree_r( CopyWinding( w ), ds, node->children[ 1 ] );
|
refs += FilterWindingIntoTree_r( wcopy, ds, node->children[ 0 ] );
|
||||||
|
refs += FilterWindingIntoTree_r( w, ds, node->children[ 1 ] );
|
||||||
}
|
}
|
||||||
if ( front != NULL ) {
|
if ( !front.empty() ) {
|
||||||
refs += FilterWindingIntoTree_r( front, ds, node->children[ 0 ] );
|
refs += FilterWindingIntoTree_r( front, ds, node->children[ 0 ] );
|
||||||
}
|
}
|
||||||
if ( back != NULL ) {
|
if ( !back.empty() ) {
|
||||||
refs += FilterWindingIntoTree_r( back, ds, node->children[ 1 ] );
|
refs += FilterWindingIntoTree_r( back, ds, node->children[ 1 ] );
|
||||||
}
|
}
|
||||||
FreeWinding( w );
|
|
||||||
|
|
||||||
/* return */
|
/* return */
|
||||||
return refs;
|
return refs;
|
||||||
|
|
@ -2022,14 +1979,10 @@ int FilterWindingIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node ){
|
||||||
filters a planar winding face drawsurface into the bsp tree
|
filters a planar winding face drawsurface into the bsp tree
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int FilterFaceIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
|
int FilterFaceIntoTree( mapDrawSurface_t *ds, tree_t& tree ){
|
||||||
winding_t *w;
|
|
||||||
int refs = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/* make a winding and filter it into the tree */
|
/* make a winding and filter it into the tree */
|
||||||
w = WindingFromDrawSurf( ds );
|
winding_t w = WindingFromDrawSurf( ds );
|
||||||
refs = FilterWindingIntoTree_r( w, ds, tree->headnode );
|
int refs = FilterWindingIntoTree_r( w, ds, tree.headnode );
|
||||||
|
|
||||||
/* return */
|
/* return */
|
||||||
return refs;
|
return refs;
|
||||||
|
|
@ -2044,7 +1997,7 @@ int FilterFaceIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
|
||||||
|
|
||||||
#define FILTER_SUBDIVISION 8
|
#define FILTER_SUBDIVISION 8
|
||||||
|
|
||||||
static int FilterPatchIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
|
static int FilterPatchIntoTree( mapDrawSurface_t *ds, tree_t& tree ){
|
||||||
int x, y, refs = 0;
|
int x, y, refs = 0;
|
||||||
|
|
||||||
for ( y = 0; y + 2 < ds->patchHeight; y += 2 )
|
for ( y = 0; y + 2 < ds->patchHeight; y += 2 )
|
||||||
|
|
@ -2060,7 +2013,7 @@ static int FilterPatchIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
|
||||||
points[6] = &ds->verts[( y + 2 ) * ds->patchWidth + ( x + 0 )].xyz;
|
points[6] = &ds->verts[( y + 2 ) * ds->patchWidth + ( x + 0 )].xyz;
|
||||||
points[7] = &ds->verts[( y + 2 ) * ds->patchWidth + ( x + 1 )].xyz;
|
points[7] = &ds->verts[( y + 2 ) * ds->patchWidth + ( x + 1 )].xyz;
|
||||||
points[8] = &ds->verts[( y + 2 ) * ds->patchWidth + ( x + 2 )].xyz;
|
points[8] = &ds->verts[( y + 2 ) * ds->patchWidth + ( x + 2 )].xyz;
|
||||||
refs += FilterPointConvexHullIntoTree_r( points, 9, ds, tree->headnode );
|
refs += FilterPointConvexHullIntoTree_r( points, 9, ds, tree.headnode );
|
||||||
}
|
}
|
||||||
|
|
||||||
return refs;
|
return refs;
|
||||||
|
|
@ -2073,9 +2026,8 @@ static int FilterPatchIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
|
||||||
filters a triangle surface (meta, model) into the bsp
|
filters a triangle surface (meta, model) into the bsp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int FilterTrianglesIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
|
static int FilterTrianglesIntoTree( mapDrawSurface_t *ds, tree_t& tree ){
|
||||||
int i, refs;
|
int i, refs;
|
||||||
winding_t *w;
|
|
||||||
|
|
||||||
|
|
||||||
/* ydnar: gs mods: this was creating bogus triangles before */
|
/* ydnar: gs mods: this was creating bogus triangles before */
|
||||||
|
|
@ -2090,16 +2042,16 @@ static int FilterTrianglesIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make a triangle winding and filter it into the tree */
|
/* make a triangle winding and filter it into the tree */
|
||||||
w = AllocWinding( 3 );
|
winding_t w{
|
||||||
w->push_back( ds->verts[ ds->indexes[ i ] ].xyz );
|
ds->verts[ ds->indexes[ i ] ].xyz,
|
||||||
w->push_back( ds->verts[ ds->indexes[ i + 1 ] ].xyz );
|
ds->verts[ ds->indexes[ i + 1 ] ].xyz,
|
||||||
w->push_back( ds->verts[ ds->indexes[ i + 2 ] ].xyz );
|
ds->verts[ ds->indexes[ i + 2 ] ].xyz };
|
||||||
refs += FilterWindingIntoTree_r( w, ds, tree->headnode );
|
refs += FilterWindingIntoTree_r( w, ds, tree.headnode );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* use point filtering as well */
|
/* use point filtering as well */
|
||||||
for ( i = 0; i < ds->numVerts; i++ )
|
for ( i = 0; i < ds->numVerts; i++ )
|
||||||
refs += FilterPointIntoTree_r( ds->verts[ i ].xyz, ds, tree->headnode );
|
refs += FilterPointIntoTree_r( ds->verts[ i ].xyz, ds, tree.headnode );
|
||||||
|
|
||||||
return refs;
|
return refs;
|
||||||
}
|
}
|
||||||
|
|
@ -2111,10 +2063,9 @@ static int FilterTrianglesIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
|
||||||
filters a foliage surface (wolf et/splash damage)
|
filters a foliage surface (wolf et/splash damage)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int FilterFoliageIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
|
static int FilterFoliageIntoTree( mapDrawSurface_t *ds, tree_t& tree ){
|
||||||
int f, i, refs;
|
int f, i, refs;
|
||||||
bspDrawVert_t *instance;
|
bspDrawVert_t *instance;
|
||||||
winding_t *w;
|
|
||||||
|
|
||||||
|
|
||||||
/* walk origin list */
|
/* walk origin list */
|
||||||
|
|
@ -2135,17 +2086,17 @@ static int FilterFoliageIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make a triangle winding and filter it into the tree */
|
/* make a triangle winding and filter it into the tree */
|
||||||
w = AllocWinding( 3 );
|
winding_t w{
|
||||||
w->push_back( instance->xyz + ds->verts[ ds->indexes[ i ] ].xyz );
|
instance->xyz + ds->verts[ ds->indexes[ i ] ].xyz,
|
||||||
w->push_back( instance->xyz + ds->verts[ ds->indexes[ i + 1 ] ].xyz );
|
instance->xyz + ds->verts[ ds->indexes[ i + 1 ] ].xyz,
|
||||||
w->push_back( instance->xyz + ds->verts[ ds->indexes[ i + 2 ] ].xyz );
|
instance->xyz + ds->verts[ ds->indexes[ i + 2 ] ].xyz };
|
||||||
refs += FilterWindingIntoTree_r( w, ds, tree->headnode );
|
refs += FilterWindingIntoTree_r( w, ds, tree.headnode );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* use point filtering as well */
|
/* use point filtering as well */
|
||||||
for ( i = 0; i < ( ds->numVerts - ds->numFoliageInstances ); i++ )
|
for ( i = 0; i < ( ds->numVerts - ds->numFoliageInstances ); i++ )
|
||||||
{
|
{
|
||||||
refs += FilterPointIntoTree_r( instance->xyz + ds->verts[ i ].xyz, ds, tree->headnode );
|
refs += FilterPointIntoTree_r( instance->xyz + ds->verts[ i ].xyz, ds, tree.headnode );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2158,8 +2109,8 @@ static int FilterFoliageIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
|
||||||
FilterFlareIntoTree()
|
FilterFlareIntoTree()
|
||||||
simple point filtering for flare surfaces
|
simple point filtering for flare surfaces
|
||||||
*/
|
*/
|
||||||
static int FilterFlareSurfIntoTree( mapDrawSurface_t *ds, tree_t *tree ){
|
static int FilterFlareSurfIntoTree( mapDrawSurface_t *ds, tree_t& tree ){
|
||||||
return FilterPointIntoTree_r( ds->lightmapOrigin, ds, tree->headnode );
|
return FilterPointIntoTree_r( ds->lightmapOrigin, ds, tree.headnode );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2741,10 +2692,9 @@ static void EmitFaceSurface( mapDrawSurface_t *ds ){
|
||||||
generates drawsurfaces for passable portals in the bsp
|
generates drawsurfaces for passable portals in the bsp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void MakeDebugPortalSurfs_r( node_t *node, shaderInfo_t *si ){
|
static void MakeDebugPortalSurfs_r( const node_t *node, shaderInfo_t *si ){
|
||||||
int i, k, c, s;
|
int i, k, c, s;
|
||||||
portal_t *p;
|
const portal_t *p;
|
||||||
winding_t *w;
|
|
||||||
mapDrawSurface_t *ds;
|
mapDrawSurface_t *ds;
|
||||||
bspDrawVert_t *dv;
|
bspDrawVert_t *dv;
|
||||||
|
|
||||||
|
|
@ -2765,30 +2715,29 @@ static void MakeDebugPortalSurfs_r( node_t *node, shaderInfo_t *si ){
|
||||||
for ( c = 0, p = node->portals; p != NULL; c++, p = p->next[ s ] )
|
for ( c = 0, p = node->portals; p != NULL; c++, p = p->next[ s ] )
|
||||||
{
|
{
|
||||||
/* get winding and side even/odd */
|
/* get winding and side even/odd */
|
||||||
w = p->winding;
|
const winding_t& w = p->winding;
|
||||||
s = ( p->nodes[ 1 ] == node );
|
s = ( p->nodes[ 1 ] == node );
|
||||||
|
|
||||||
/* is this a valid portal for this leaf? */
|
/* is this a valid portal for this leaf? */
|
||||||
if ( w && p->nodes[ 0 ] == node ) {
|
if ( !w.empty() && p->nodes[ 0 ] == node ) {
|
||||||
/* is this portal passable? */
|
/* is this portal passable? */
|
||||||
if ( !PortalPassable( p ) ) {
|
if ( !PortalPassable( p ) ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check max points */
|
/* check max points */
|
||||||
if ( w->size() > 64 ) {
|
if ( w.size() > 64 ) {
|
||||||
Error( "MakePortalSurfs_r: w->numpoints = %zu", w->size() );
|
Error( "MakePortalSurfs_r: w->numpoints = %zu", w.size() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate a drawsurface */
|
/* allocate a drawsurface */
|
||||||
ds = AllocDrawSurface( ESurfaceType::Face );
|
ds = AllocDrawSurface( ESurfaceType::Face );
|
||||||
ds->shaderInfo = si;
|
ds->shaderInfo = si;
|
||||||
ds->planar = true;
|
ds->planar = true;
|
||||||
ds->sideRef = AllocSideRef( p->side, NULL );
|
|
||||||
ds->planeNum = FindFloatPlane( p->plane.plane, 0, NULL );
|
ds->planeNum = FindFloatPlane( p->plane.plane, 0, NULL );
|
||||||
ds->lightmapVecs[ 2 ] = p->plane.normal();
|
ds->lightmapVecs[ 2 ] = p->plane.normal();
|
||||||
ds->fogNum = -1;
|
ds->fogNum = -1;
|
||||||
ds->numVerts = w->size();
|
ds->numVerts = w.size();
|
||||||
ds->verts = safe_calloc( ds->numVerts * sizeof( *ds->verts ) );
|
ds->verts = safe_calloc( ds->numVerts * sizeof( *ds->verts ) );
|
||||||
|
|
||||||
/* walk the winding */
|
/* walk the winding */
|
||||||
|
|
@ -2798,7 +2747,7 @@ static void MakeDebugPortalSurfs_r( node_t *node, shaderInfo_t *si ){
|
||||||
dv = ds->verts + i;
|
dv = ds->verts + i;
|
||||||
|
|
||||||
/* set it */
|
/* set it */
|
||||||
dv->xyz = ( *w )[ i ];
|
dv->xyz = w[ i ];
|
||||||
dv->normal = p->plane.normal();
|
dv->normal = p->plane.normal();
|
||||||
dv->st = { 0, 0 };
|
dv->st = { 0, 0 };
|
||||||
for ( k = 0; k < MAX_LIGHTMAPS; k++ )
|
for ( k = 0; k < MAX_LIGHTMAPS; k++ )
|
||||||
|
|
@ -2818,7 +2767,7 @@ static void MakeDebugPortalSurfs_r( node_t *node, shaderInfo_t *si ){
|
||||||
generates drawsurfaces for passable portals in the bsp
|
generates drawsurfaces for passable portals in the bsp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void MakeDebugPortalSurfs( tree_t *tree ){
|
void MakeDebugPortalSurfs( const tree_t& tree ){
|
||||||
shaderInfo_t *si;
|
shaderInfo_t *si;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2829,7 +2778,7 @@ void MakeDebugPortalSurfs( tree_t *tree ){
|
||||||
si = ShaderInfoForShader( "debugportals" );
|
si = ShaderInfoForShader( "debugportals" );
|
||||||
|
|
||||||
/* walk the tree */
|
/* walk the tree */
|
||||||
MakeDebugPortalSurfs_r( tree->headnode, si );
|
MakeDebugPortalSurfs_r( tree.headnode, si );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2839,7 +2788,7 @@ void MakeDebugPortalSurfs( tree_t *tree ){
|
||||||
generates drawsurfaces for a foghull (this MUST use a sky shader)
|
generates drawsurfaces for a foghull (this MUST use a sky shader)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void MakeFogHullSurfs( entity_t *e, tree_t *tree, const char *shader ){
|
void MakeFogHullSurfs( entity_t *e, const char *shader ){
|
||||||
shaderInfo_t *si;
|
shaderInfo_t *si;
|
||||||
mapDrawSurface_t *ds;
|
mapDrawSurface_t *ds;
|
||||||
int indexes[] =
|
int indexes[] =
|
||||||
|
|
@ -3231,17 +3180,8 @@ void AddEntitySurfaceModels( entity_t *e ){
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void VolumeColorMods( entity_t *e, mapDrawSurface_t *ds ){
|
static void VolumeColorMods( entity_t *e, mapDrawSurface_t *ds ){
|
||||||
int i, j;
|
|
||||||
brush_t *b;
|
|
||||||
|
|
||||||
|
|
||||||
/* early out */
|
|
||||||
if ( e->colorModBrushes == NULL ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* iterate brushes */
|
/* iterate brushes */
|
||||||
for ( b = e->colorModBrushes; b != NULL; b = b->nextColorModBrush )
|
for ( const brush_t *b : e->colorModBrushes )
|
||||||
{
|
{
|
||||||
/* worldspawn alpha brushes affect all, grouped ones only affect original entity */
|
/* worldspawn alpha brushes affect all, grouped ones only affect original entity */
|
||||||
if ( b->entityNum != 0 && b->entityNum != ds->entityNum ) {
|
if ( b->entityNum != 0 && b->entityNum != ds->entityNum ) {
|
||||||
|
|
@ -3254,10 +3194,11 @@ static void VolumeColorMods( entity_t *e, mapDrawSurface_t *ds ){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* iterate verts */
|
/* iterate verts */
|
||||||
for ( i = 0; i < ds->numVerts; i++ )
|
for ( int i = 0; i < ds->numVerts; i++ )
|
||||||
{
|
{
|
||||||
/* iterate planes */
|
/* iterate planes */
|
||||||
for ( j = 0; j < b->numsides; j++ )
|
size_t j;
|
||||||
|
for ( j = 0; j < b->sides.size(); j++ )
|
||||||
{
|
{
|
||||||
/* point-plane test */
|
/* point-plane test */
|
||||||
if ( plane3_distance_to_point( mapplanes[ b->sides[ j ].planenum ].plane, ds->verts[ i ].xyz ) > 1.0f ) {
|
if ( plane3_distance_to_point( mapplanes[ b->sides[ j ].planenum ].plane, ds->verts[ i ].xyz ) > 1.0f ) {
|
||||||
|
|
@ -3266,7 +3207,7 @@ static void VolumeColorMods( entity_t *e, mapDrawSurface_t *ds ){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* apply colormods */
|
/* apply colormods */
|
||||||
if ( j == b->numsides ) {
|
if ( j == b->sides.size() ) {
|
||||||
ColorMod( b->contentShader->colorMod, 1, &ds->verts[ i ] );
|
ColorMod( b->contentShader->colorMod, 1, &ds->verts[ i ] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3282,7 +3223,7 @@ static void VolumeColorMods( entity_t *e, mapDrawSurface_t *ds ){
|
||||||
will have valid final indexes
|
will have valid final indexes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree ){
|
void FilterDrawsurfsIntoTree( entity_t *e, tree_t& tree ){
|
||||||
int i, j;
|
int i, j;
|
||||||
mapDrawSurface_t *ds;
|
mapDrawSurface_t *ds;
|
||||||
shaderInfo_t *si;
|
shaderInfo_t *si;
|
||||||
|
|
@ -3311,7 +3252,7 @@ void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree ){
|
||||||
|
|
||||||
/* ydnar: skybox surfaces are special */
|
/* ydnar: skybox surfaces are special */
|
||||||
if ( ds->skybox ) {
|
if ( ds->skybox ) {
|
||||||
refs = AddReferenceToTree_r( ds, tree->headnode, true );
|
refs = AddReferenceToTree_r( ds, tree.headnode, true );
|
||||||
ds->skybox = false;
|
ds->skybox = false;
|
||||||
sb = true;
|
sb = true;
|
||||||
}
|
}
|
||||||
|
|
@ -3421,7 +3362,7 @@ void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree ){
|
||||||
/* handle foghull surfaces */
|
/* handle foghull surfaces */
|
||||||
case ESurfaceType::Foghull:
|
case ESurfaceType::Foghull:
|
||||||
if ( refs == 0 ) {
|
if ( refs == 0 ) {
|
||||||
refs = AddReferenceToTree_r( ds, tree->headnode, false );
|
refs = AddReferenceToTree_r( ds, tree.headnode, false );
|
||||||
}
|
}
|
||||||
if ( refs > 0 ) {
|
if ( refs > 0 ) {
|
||||||
EmitTriangleSurface( ds );
|
EmitTriangleSurface( ds );
|
||||||
|
|
|
||||||
|
|
@ -91,15 +91,8 @@ void FreeTree_r( node_t *node ){
|
||||||
FreeTree_r( node->children[1] );
|
FreeTree_r( node->children[1] );
|
||||||
}
|
}
|
||||||
|
|
||||||
// free bspbrushes
|
|
||||||
FreeBrushList( node->brushlist );
|
|
||||||
|
|
||||||
// free the node
|
// free the node
|
||||||
if ( node->volume ) {
|
delete node;
|
||||||
FreeBrush( node->volume );
|
|
||||||
}
|
|
||||||
|
|
||||||
free( node );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -108,25 +101,24 @@ void FreeTree_r( node_t *node ){
|
||||||
FreeTree
|
FreeTree
|
||||||
=============
|
=============
|
||||||
*/
|
*/
|
||||||
void FreeTree( tree_t *tree ){
|
void FreeTree( tree_t& tree ){
|
||||||
FreeTreePortals_r( tree->headnode );
|
FreeTreePortals_r( tree.headnode );
|
||||||
FreeTree_r( tree->headnode );
|
FreeTree_r( tree.headnode );
|
||||||
free( tree );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===============================================================
|
//===============================================================
|
||||||
|
|
||||||
void PrintTree_r( node_t *node, int depth ){
|
void PrintTree_r( const node_t *node, int depth ){
|
||||||
for ( int i = 0; i < depth; i++ )
|
for ( int i = 0; i < depth; i++ )
|
||||||
Sys_Printf( " " );
|
Sys_Printf( " " );
|
||||||
if ( node->planenum == PLANENUM_LEAF ) {
|
if ( node->planenum == PLANENUM_LEAF ) {
|
||||||
if ( !node->brushlist ) {
|
if ( node->brushlist.empty() ) {
|
||||||
Sys_Printf( "NULL\n" );
|
Sys_Printf( "NULL\n" );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for ( const brush_t *bb = node->brushlist; bb; bb = bb->next )
|
for ( const brush_t& bb : node->brushlist )
|
||||||
Sys_Printf( "%d ", bb->original->brushNum );
|
Sys_Printf( "%d ", bb.original->brushNum );
|
||||||
Sys_Printf( "\n" );
|
Sys_Printf( "\n" );
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
emits a bsp shader entry
|
emits a bsp shader entry
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int EmitShader( const char *shader, int *contentFlags, int *surfaceFlags ){
|
int EmitShader( const char *shader, const int *contentFlags, const int *surfaceFlags ){
|
||||||
int i;
|
int i;
|
||||||
shaderInfo_t *si;
|
shaderInfo_t *si;
|
||||||
|
|
||||||
|
|
@ -132,7 +132,6 @@ void EmitPlanes( void ){
|
||||||
|
|
||||||
void EmitLeaf( node_t *node ){
|
void EmitLeaf( node_t *node ){
|
||||||
bspLeaf_t *leaf_p;
|
bspLeaf_t *leaf_p;
|
||||||
brush_t *b;
|
|
||||||
drawSurfRef_t *dsr;
|
drawSurfRef_t *dsr;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -153,18 +152,18 @@ void EmitLeaf( node_t *node ){
|
||||||
|
|
||||||
/* emit leaf brushes */
|
/* emit leaf brushes */
|
||||||
leaf_p->firstBSPLeafBrush = numBSPLeafBrushes;
|
leaf_p->firstBSPLeafBrush = numBSPLeafBrushes;
|
||||||
for ( b = node->brushlist; b; b = b->next )
|
for ( const brush_t& b : node->brushlist )
|
||||||
{
|
{
|
||||||
/* something is corrupting brushes */
|
/* something is corrupting brushes */
|
||||||
if ( (size_t) b < 256 ) {
|
// if ( (size_t) b < 256 ) {
|
||||||
Sys_Warning( "Node brush list corrupted (0x%08X)\n", b );
|
// Sys_Warning( "Node brush list corrupted (0x%08X)\n", b );
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
//% if( b->guard != 0xDEADBEEF )
|
//% if( b->guard != 0xDEADBEEF )
|
||||||
//% Sys_Printf( "Brush %6d: 0x%08X Guard: 0x%08X Next: 0x%08X Original: 0x%08X Sides: %d\n", b->brushNum, b, b, b->next, b->original, b->numsides );
|
//% Sys_Printf( "Brush %6d: 0x%08X Guard: 0x%08X Next: 0x%08X Original: 0x%08X Sides: %d\n", b->brushNum, b, b, b->next, b->original, b->numsides );
|
||||||
|
|
||||||
AUTOEXPAND_BY_REALLOC_BSP( LeafBrushes, 1024 );
|
AUTOEXPAND_BY_REALLOC_BSP( LeafBrushes, 1024 );
|
||||||
bspLeafBrushes[ numBSPLeafBrushes ] = b->original->outputNum;
|
bspLeafBrushes[ numBSPLeafBrushes ] = b.original->outputNum;
|
||||||
numBSPLeafBrushes++;
|
numBSPLeafBrushes++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -247,12 +246,10 @@ int EmitDrawNode_r( node_t *node ){
|
||||||
============
|
============
|
||||||
*/
|
*/
|
||||||
void SetModelNumbers( void ){
|
void SetModelNumbers( void ){
|
||||||
int models;
|
int models = 1;
|
||||||
char value[16];
|
|
||||||
|
|
||||||
models = 1;
|
|
||||||
for ( std::size_t i = 1; i < entities.size(); ++i ) {
|
for ( std::size_t i = 1; i < entities.size(); ++i ) {
|
||||||
if ( entities[i].brushes || entities[i].patches ) {
|
if ( !entities[i].brushes.empty() || entities[i].patches ) {
|
||||||
|
char value[16];
|
||||||
sprintf( value, "*%i", models );
|
sprintf( value, "*%i", models );
|
||||||
models++;
|
models++;
|
||||||
entities[i].setKeyValue( "model", value );
|
entities[i].setKeyValue( "model", value );
|
||||||
|
|
@ -404,9 +401,7 @@ void EndBSPFile( bool do_write ){
|
||||||
writes the brush list to the bsp
|
writes the brush list to the bsp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void EmitBrushes( brush_t *brushes, int *firstBrush, int *numBrushes ){
|
void EmitBrushes( brushlist_t& brushes, int *firstBrush, int *numBrushes ){
|
||||||
int j;
|
|
||||||
brush_t *b;
|
|
||||||
bspBrush_t *db;
|
bspBrush_t *db;
|
||||||
bspBrushSide_t *cp;
|
bspBrushSide_t *cp;
|
||||||
|
|
||||||
|
|
@ -420,45 +415,45 @@ void EmitBrushes( brush_t *brushes, int *firstBrush, int *numBrushes ){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* walk list of brushes */
|
/* walk list of brushes */
|
||||||
for ( b = brushes; b != NULL; b = b->next )
|
for ( brush_t& b : brushes )
|
||||||
{
|
{
|
||||||
/* check limits */
|
/* check limits */
|
||||||
AUTOEXPAND_BY_REALLOC_BSP( Brushes, 1024 );
|
AUTOEXPAND_BY_REALLOC_BSP( Brushes, 1024 );
|
||||||
|
|
||||||
/* get bsp brush */
|
/* get bsp brush */
|
||||||
b->outputNum = numBSPBrushes;
|
b.outputNum = numBSPBrushes;
|
||||||
db = &bspBrushes[ numBSPBrushes ];
|
db = &bspBrushes[ numBSPBrushes ];
|
||||||
numBSPBrushes++;
|
numBSPBrushes++;
|
||||||
if ( numBrushes != NULL ) {
|
if ( numBrushes != NULL ) {
|
||||||
( *numBrushes )++;
|
( *numBrushes )++;
|
||||||
}
|
}
|
||||||
|
|
||||||
db->shaderNum = EmitShader( b->contentShader->shader, &b->contentShader->contentFlags, &b->contentShader->surfaceFlags );
|
db->shaderNum = EmitShader( b.contentShader->shader, &b.contentShader->contentFlags, &b.contentShader->surfaceFlags );
|
||||||
db->firstSide = numBSPBrushSides;
|
db->firstSide = numBSPBrushSides;
|
||||||
|
|
||||||
/* walk sides */
|
/* walk sides */
|
||||||
db->numSides = 0;
|
db->numSides = 0;
|
||||||
for ( j = 0; j < b->numsides; j++ )
|
for ( side_t& side : b.sides )
|
||||||
{
|
{
|
||||||
/* set output number to bogus initially */
|
/* set output number to bogus initially */
|
||||||
b->sides[ j ].outputNum = -1;
|
side.outputNum = -1;
|
||||||
|
|
||||||
/* check count */
|
/* check count */
|
||||||
AUTOEXPAND_BY_REALLOC_BSP( BrushSides, 1024 );
|
AUTOEXPAND_BY_REALLOC_BSP( BrushSides, 1024 );
|
||||||
|
|
||||||
/* emit side */
|
/* emit side */
|
||||||
b->sides[ j ].outputNum = numBSPBrushSides;
|
side.outputNum = numBSPBrushSides;
|
||||||
cp = &bspBrushSides[ numBSPBrushSides ];
|
cp = &bspBrushSides[ numBSPBrushSides ];
|
||||||
db->numSides++;
|
db->numSides++;
|
||||||
numBSPBrushSides++;
|
numBSPBrushSides++;
|
||||||
cp->planeNum = b->sides[ j ].planenum;
|
cp->planeNum = side.planenum;
|
||||||
|
|
||||||
/* emit shader */
|
/* emit shader */
|
||||||
if ( b->sides[ j ].shaderInfo ) {
|
if ( side.shaderInfo ) {
|
||||||
cp->shaderNum = EmitShader( b->sides[ j ].shaderInfo->shader, &b->sides[ j ].shaderInfo->contentFlags, &b->sides[ j ].shaderInfo->surfaceFlags );
|
cp->shaderNum = EmitShader( side.shaderInfo->shader, &side.shaderInfo->contentFlags, &side.shaderInfo->surfaceFlags );
|
||||||
}
|
}
|
||||||
else if( b->sides[ j ].bevel ) { /* emit surfaceFlags for bevels to get correct physics at walkable brush edges and vertices */
|
else if( side.bevel ) { /* emit surfaceFlags for bevels to get correct physics at walkable brush edges and vertices */
|
||||||
cp->shaderNum = EmitShader( NULL, NULL, &b->sides[ j ].surfaceFlags );
|
cp->shaderNum = EmitShader( NULL, NULL, &side.surfaceFlags );
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
cp->shaderNum = EmitShader( NULL, NULL, NULL );
|
cp->shaderNum = EmitShader( NULL, NULL, NULL );
|
||||||
|
|
@ -507,7 +502,7 @@ void EmitFogs( void ){
|
||||||
/* find visible side */
|
/* find visible side */
|
||||||
for ( j = 0; j < 6; j++ )
|
for ( j = 0; j < 6; j++ )
|
||||||
{
|
{
|
||||||
if ( mapFogs[ i ].brush->sides[ j ].visibleHull != NULL ) {
|
if ( !mapFogs[ i ].brush->sides[ j ].visibleHull.empty() ) {
|
||||||
Sys_Printf( "Fog %d has visible side %d\n", i, j );
|
Sys_Printf( "Fog %d has visible side %d\n", i, j );
|
||||||
bspFogs[ i ].visibleSide = j;
|
bspFogs[ i ].visibleSide = j;
|
||||||
break;
|
break;
|
||||||
|
|
@ -536,17 +531,17 @@ void BeginModel( void ){
|
||||||
const entity_t& e = entities[ mapEntityNum ];
|
const entity_t& e = entities[ mapEntityNum ];
|
||||||
|
|
||||||
/* bound the brushes */
|
/* bound the brushes */
|
||||||
for ( const brush_t *b = e.brushes; b; b = b->next )
|
for ( const brush_t& b : e.brushes )
|
||||||
{
|
{
|
||||||
/* ignore non-real brushes (origin, etc) */
|
/* ignore non-real brushes (origin, etc) */
|
||||||
if ( b->numsides == 0 ) {
|
if ( b.sides.empty() ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
minmax.extend( b->minmax );
|
minmax.extend( b.minmax );
|
||||||
|
|
||||||
/* ydnar: lightgrid bounds */
|
/* ydnar: lightgrid bounds */
|
||||||
if ( b->compileFlags & C_LIGHTGRID ) {
|
if ( b.compileFlags & C_LIGHTGRID ) {
|
||||||
lgMinmax.extend( b->minmax );
|
lgMinmax.extend( b.minmax );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user