X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=contrib%2Fbobtoolz%2FDBrush.cpp;h=a5b18cef377b441694504dfb05b48599e7fbb79b;hb=6a7dedc09f1a4b72077e0012bf0499a0005973d6;hp=3e54e79717b554c6857a43bf87c721fb48dedc85;hpb=02e6ff2dcb60910c2f19e95021e52c71db3f794b;p=xonotic%2Fnetradiant.git diff --git a/contrib/bobtoolz/DBrush.cpp b/contrib/bobtoolz/DBrush.cpp index 3e54e797..a5b18cef 100644 --- a/contrib/bobtoolz/DBrush.cpp +++ b/contrib/bobtoolz/DBrush.cpp @@ -21,851 +21,871 @@ // ////////////////////////////////////////////////////////////////////// -#include "StdAfx.h" +#include "DBrush.h" +#include "globaldefs.h" -#ifdef _WIN32 +#if GDEF_COMPILER_MSVC #pragma warning(disable : 4786) #endif -#include "DBrush.h" +#include +#include "str.h" + +#include "DPoint.h" +#include "DPlane.h" +#include "DEPair.h" +#include "DPatch.h" +#include "DEntity.h" #include "DWinding.h" + #include "dialogs/dialogs-gtk.h" #include "misc.h" +#include "iundo.h" + +#include "generic/referencecounted.h" + +#include "scenelib.h" + ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// -DBrush::DBrush( int ID ){ - m_nBrushID = ID; - bBoundsBuilt = FALSE; - QER_brush = NULL; +DBrush::DBrush(int ID) +{ + m_nBrushID = ID; + bBoundsBuilt = false; + QER_entity = NULL; + QER_brush = NULL; } -DBrush::~DBrush(){ - ClearFaces(); - ClearPoints(); +DBrush::~DBrush() +{ + ClearFaces(); + ClearPoints(); } ////////////////////////////////////////////////////////////////////// // Implementation ////////////////////////////////////////////////////////////////////// -DPlane* DBrush::AddFace( vec3_t va, vec3_t vb, vec3_t vc, _QERFaceData* texData ){ -#ifdef _DEBUG +DPlane *DBrush::AddFace(const vec3_t va, const vec3_t vb, const vec3_t vc, const _QERFaceData *texData) +{ +#if GDEF_DEBUG // Sys_Printf("(%f %f %f) (%f %f %f) (%f %f %f)\n", va[0], va[1], va[2], vb[0], vb[1], vb[2], vc[0], vc[1], vc[2]); #endif - bBoundsBuilt = FALSE; - DPlane* newFace = new DPlane( va, vb, vc, texData ); - faceList.push_back( newFace ); - - return newFace; -} - -int DBrush::BuildPoints(){ - ClearPoints(); - - if ( faceList.size() <= 3 ) { // if less than 3 faces, there can be no points - return 0; // with only 3 faces u can't have a bounded soild - - } - for ( list::const_iterator p1 = faceList.begin(); p1 != faceList.end(); p1++ ) - { - list::const_iterator p2 = p1; - for ( p2++; p2 != faceList.end(); p2++ ) - { - list::const_iterator p3 = p2; - for ( p3++; p3 != faceList.end(); p3++ ) - { - vec3_t pnt; - if ( ( *p1 )->PlaneIntersection( *p2, *p3, pnt ) ) { - int pos = PointPosition( pnt ); - - if ( pos == POINT_IN_BRUSH ) { // ???? shouldn't happen here - Sys_Printf( "ERROR:: Build Brush Points: Point IN brush!!!\n" ); - } - else if ( pos == POINT_ON_BRUSH ) { // normal point - if ( !HasPoint( pnt ) ) { - AddPoint( pnt ); - } + bBoundsBuilt = false; + DPlane *newFace = new DPlane(va, vb, vc, texData); + faceList.push_back(newFace); + + return newFace; +} + +int DBrush::BuildPoints() +{ + ClearPoints(); + + if (faceList.size() <= 3) { // if less than 3 faces, there can be no points + return 0; // with only 3 faces u can't have a bounded soild + + } + for (std::list::const_iterator p1 = faceList.begin(); p1 != faceList.end(); p1++) { + std::list::const_iterator p2 = p1; + for (p2++; p2 != faceList.end(); p2++) { + std::list::const_iterator p3 = p2; + for (p3++; p3 != faceList.end(); p3++) { + vec3_t pnt; + if ((*p1)->PlaneIntersection(*p2, *p3, pnt)) { + int pos = PointPosition(pnt); + + if (pos == POINT_IN_BRUSH) { // ???? shouldn't happen here + globalErrorStream() << "ERROR:: Build Brush Points: Point IN brush!!!\n"; + } else if (pos == POINT_ON_BRUSH) { // normal point + if (!HasPoint(pnt)) { + AddPoint(pnt); + } /* else Sys_Printf("Duplicate Point Found, pyramids ahoy!!!!!\n");*/ - // point lies on more that 3 planes - } + // point lies on more that 3 planes + } - // otherwise point is removed due to another plane.. + // otherwise point is removed due to another plane.. - // Sys_Printf("(%f, %f, %f)\n", pnt[0], pnt[1], pnt[2]); - } - } - } - } + // Sys_Printf("(%f, %f, %f)\n", pnt[0], pnt[1], pnt[2]); + } + } + } + } -#ifdef _DEBUG +#if GDEF_DEBUG // Sys_Printf("%i points on brush\n", pointList.size()); #endif - return pointList.size(); + return static_cast( pointList.size()); } -void DBrush::LoadFromBrush_t( brush_t* brush, bool textured ){ - ClearFaces(); - ClearPoints(); +void DBrush_addFace(DBrush &brush, const _QERFaceData &faceData) +{ + brush.AddFace(vector3_to_array(faceData.m_p0), vector3_to_array(faceData.m_p1), vector3_to_array(faceData.m_p2), 0); +} - for ( int i = g_FuncTable.m_pfnGetFaceCount( brush ) - 1; i >= 0 ; i-- ) - { // running backwards so i dont have to use the count function each time (OPT) - _QERFaceData* faceData = g_FuncTable.m_pfnGetFaceData( brush, i ); +typedef ReferenceCaller DBrushAddFaceCaller; - if ( faceData == NULL ) { - DoMessageBox( "Null pointer returned", "WARNING!", MB_OK ); - } +void DBrush_addFaceTextured(DBrush &brush, const _QERFaceData &faceData) +{ + brush.AddFace(vector3_to_array(faceData.m_p0), vector3_to_array(faceData.m_p1), vector3_to_array(faceData.m_p2), + &faceData); +} - if ( textured ) { - AddFace( faceData->m_v1, faceData->m_v2, faceData->m_v3, faceData ); - } - else{ - AddFace( faceData->m_v1, faceData->m_v2, faceData->m_v3, NULL ); - } - } - - QER_brush = brush; -} - -int DBrush::PointPosition( vec3_t pnt ){ - int state = POINT_IN_BRUSH; // if nothing happens point is inside brush - - for ( list::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ ) - { - float dist = ( *chkPlane )->DistanceToPoint( pnt ); - - if ( dist > MAX_ROUND_ERROR ) { - return POINT_OUT_BRUSH; // if point is in front of plane, it CANT be in the brush - } - else if ( fabs( dist ) < MAX_ROUND_ERROR ) { - state = POINT_ON_BRUSH; // if point is ON plane point is either ON the brush - } - // or outside it, it can no longer be in it - } - - return state; -} - -void DBrush::ClearPoints(){ - for ( list::const_iterator deadPoint = pointList.begin(); deadPoint != pointList.end(); deadPoint++ ) { - delete *deadPoint; - } - pointList.clear(); -} - -void DBrush::ClearFaces(){ - bBoundsBuilt = FALSE; - for ( list::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++ ) - { - delete *deadPlane; - } - faceList.clear(); -} - -void DBrush::AddPoint( vec3_t pnt ){ - DPoint* newPoint = new DPoint; - VectorCopy( pnt, newPoint->_pnt ); - pointList.push_back( newPoint ); -} - -bool DBrush::HasPoint( vec3_t pnt ){ - for ( list::const_iterator chkPoint = pointList.begin(); chkPoint != pointList.end(); chkPoint++ ) - { - if ( **chkPoint == pnt ) { - return TRUE; - } - } - - return FALSE; -} - -int DBrush::RemoveRedundantPlanes(){ - int cnt = 0; - list::iterator chkPlane; - - // find duplicate planes - list::iterator p1 = faceList.begin(); - - while ( p1 != faceList.end() ) - { - list::iterator p2 = p1; - - for ( p2++; p2 != faceList.end(); p2++ ) - { - if ( **p1 == **p2 ) { - if ( !strcmp( ( *p1 )->texInfo.m_TextureName, "textures/common/caulk" ) ) { - delete *p1; - p1 = faceList.erase( p1 ); // duplicate plane - } - else - { - delete *p2; - p2 = faceList.erase( p2 ); // duplicate plane - } - - cnt++; - break; - } - } - - if ( p2 == faceList.end() ) { - p1++; - } - } - - //+djbob kill planes with bad normal, they are more of a nuisance than losing a brush - chkPlane = faceList.begin(); - while ( chkPlane != faceList.end() ) - { - if ( VectorLength( ( *chkPlane )->normal ) == 0 ) { // plane has bad normal - delete *chkPlane; - chkPlane = faceList.erase( chkPlane ); - cnt++; - } - else { - chkPlane++; - } - } - //-djbob - - if ( pointList.size() == 0 ) { // if points may not have been built, build them -/* if(BuildPoints() == 0) // just let the planes die if they are all bad - return cnt;*/ - BuildPoints(); - } - - chkPlane = faceList.begin(); - while ( chkPlane != faceList.end() ) - { - if ( ( *chkPlane )->IsRedundant( pointList ) ) { // checks that plane "0wnz" :), 3 or more points - delete *chkPlane; - chkPlane = faceList.erase( chkPlane ); - cnt++; - } - else{ - chkPlane++; - } - } - - return cnt; -} - -bool DBrush::GetBounds( vec3_t min, vec3_t max ){ - BuildBounds(); - - if ( !bBoundsBuilt ) { - return FALSE; - } - - VectorCopy( bbox_min, min ); - VectorCopy( bbox_max, max ); - - return TRUE; -} - -bool DBrush::BBoxCollision( DBrush* chkBrush ){ - vec3_t min1, min2; - vec3_t max1, max2; - - GetBounds( min1, max1 ); - chkBrush->GetBounds( min2, max2 ); - - if ( min1[0] >= max2[0] ) { - return FALSE; - } - if ( min1[1] >= max2[1] ) { - return FALSE; - } - if ( min1[2] >= max2[2] ) { - return FALSE; - } - - if ( max1[0] <= min2[0] ) { - return FALSE; - } - if ( max1[1] <= min2[1] ) { - return FALSE; - } - if ( max1[2] <= min2[2] ) { - return FALSE; - } - - return TRUE; -} - -DPlane* DBrush::HasPlane( DPlane* chkPlane ){ - for ( list::const_iterator brushPlane = faceList.begin(); brushPlane != faceList.end(); brushPlane++ ) - { - if ( **brushPlane == *chkPlane ) { - return *brushPlane; - } - } - return NULL; -} - -bool DBrush::IsCutByPlane( DPlane *cuttingPlane ){ - bool isInFront; - - if ( pointList.size() == 0 ) { - if ( BuildPoints() == 0 ) { - return FALSE; - } - } - - list::const_iterator chkPnt = pointList.begin(); - - if ( chkPnt == pointList.end() ) { - return FALSE; - } - - float dist = cuttingPlane->DistanceToPoint( ( *chkPnt )->_pnt ); - - if ( dist > MAX_ROUND_ERROR ) { - isInFront = FALSE; - } - else if ( dist < MAX_ROUND_ERROR ) { - isInFront = TRUE; - } - else{ - return TRUE; - } - - for ( chkPnt++ = pointList.begin(); chkPnt != pointList.end(); chkPnt++ ) - { - dist = cuttingPlane->DistanceToPoint( ( *chkPnt )->_pnt ); - - if ( dist > MAX_ROUND_ERROR ) { - if ( isInFront ) { - return TRUE; - } - } - else if ( dist < MAX_ROUND_ERROR ) { - if ( !isInFront ) { - return TRUE; - } - } - else{ - return TRUE; - } - } - - return FALSE; -} - -brush_t* DBrush::BuildInRadiant( bool allowDestruction, int* changeCnt, entity_t* entity ){ - if ( allowDestruction ) { - bool kill = TRUE; - - for ( list::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ ) - { - if ( ( *chkPlane )->m_bChkOk ) { - kill = FALSE; - break; - } - } - if ( kill ) { - return NULL; - } - } - - //+djbob: fixed bug when brush had no faces "phantom brush" in radiant. - if ( faceList.size() < 4 ) { - Sys_Printf( "Possible Phantom Brush Found, will not rebuild\n" ); - return NULL; - } - //-djbob - - QER_brush = (brush_t*)g_FuncTable.m_pfnCreateBrushHandle(); - - for ( list::const_iterator buildPlane = faceList.begin(); buildPlane != faceList.end(); buildPlane++ ) { - if ( ( *buildPlane )->AddToBrush_t( QER_brush ) && changeCnt ) { - ( *changeCnt )++; - } - } - - if ( entity ) { - g_FuncTable.m_pfnCommitBrushHandleToEntity( QER_brush, entity ); - g_BrushTable.m_pfnBrush_Build( QER_brush, false, false, false, false ); - g_BrushTable.m_pfnBrush_AddToList( QER_brush, g_AppDataTable.m_pfnSelectedBrushes() ); - } - else { - g_FuncTable.m_pfnCommitBrushHandle( QER_brush ); - } - - return QER_brush; -} - -void DBrush::CutByPlane( DPlane *cutPlane, DBrush **newBrush1, DBrush **newBrush2 ){ - if ( !IsCutByPlane( cutPlane ) ) { - *newBrush1 = NULL; - *newBrush2 = NULL; - return; - } - - DBrush* b1 = new DBrush; - DBrush* b2 = new DBrush; - - for ( list::const_iterator parsePlane = faceList.begin(); parsePlane != faceList.end(); parsePlane++ ) - { - b1->AddFace( ( *parsePlane )->points[0], ( *parsePlane )->points[1], ( *parsePlane )->points[2], NULL ); - b2->AddFace( ( *parsePlane )->points[0], ( *parsePlane )->points[1], ( *parsePlane )->points[2], NULL ); - } - - b1->AddFace( cutPlane->points[0], cutPlane->points[1], cutPlane->points[2], NULL ); - b2->AddFace( cutPlane->points[2], cutPlane->points[1], cutPlane->points[0], NULL ); - - b1->RemoveRedundantPlanes(); - b2->RemoveRedundantPlanes(); - - *newBrush1 = b1; - *newBrush2 = b2; -} - -bool DBrush::IntersectsWith( DBrush *chkBrush ){ - if ( pointList.size() == 0 ) { - if ( BuildPoints() == 0 ) { - return FALSE; // invalid brush!!!! - - } - } - if ( chkBrush->pointList.size() == 0 ) { - if ( chkBrush->BuildPoints() == 0 ) { - return FALSE; // invalid brush!!!! - - } - } - if ( !BBoxCollision( chkBrush ) ) { - return FALSE; - } - - list::const_iterator iplPlane; - - for ( iplPlane = faceList.begin(); iplPlane != faceList.end(); iplPlane++ ) - { - - bool allInFront = TRUE; - for ( list::const_iterator iPoint = chkBrush->pointList.begin(); iPoint != chkBrush->pointList.end(); iPoint++ ) - { - if ( ( *iplPlane )->DistanceToPoint( ( *iPoint )->_pnt ) < -MAX_ROUND_ERROR ) { - allInFront = FALSE; - break; - } - } - if ( allInFront ) { - return FALSE; - } - } - - for ( iplPlane = chkBrush->faceList.begin(); iplPlane != chkBrush->faceList.end(); iplPlane++ ) - { - bool allInFront = TRUE; - for ( list::const_iterator iPoint = pointList.begin(); iPoint != pointList.end(); iPoint++ ) - { - if ( ( *iplPlane )->DistanceToPoint( ( *iPoint )->_pnt ) < -MAX_ROUND_ERROR ) { - allInFront = FALSE; - break; - } - } - if ( allInFront ) { - return FALSE; - } - } - - return TRUE; -} - -bool DBrush::IntersectsWith( DPlane* p1, DPlane* p2, vec3_t v ) { - vec3_t vDown = { 0, 0, -1 }; - - list::const_iterator iplPlane; - for ( iplPlane = faceList.begin(); iplPlane != faceList.end(); iplPlane++ ) { - DPlane* p = ( *iplPlane ); - - vec_t d = DotProduct( p->normal, vDown ); - if ( d >= 0 ) { - continue; - } - if ( p->PlaneIntersection( p1, p2, v ) ) { - if ( PointPosition( v ) != POINT_OUT_BRUSH ) { - return TRUE; - } - } - } - - return FALSE; -} - -void DBrush::BuildBounds(){ - if ( !bBoundsBuilt ) { - if ( pointList.size() == 0 ) { // if points may not have been built, build them - if ( BuildPoints() == 0 ) { - return; - } - } - - list::const_iterator first = pointList.begin(); - VectorCopy( ( *first )->_pnt, bbox_min ); - VectorCopy( ( *first )->_pnt, bbox_max ); - - list::const_iterator point = pointList.begin(); - for ( point++; point != pointList.end(); point++ ) - { - if ( ( *point )->_pnt[0] > bbox_max[0] ) { - bbox_max[0] = ( *point )->_pnt[0]; - } - if ( ( *point )->_pnt[1] > bbox_max[1] ) { - bbox_max[1] = ( *point )->_pnt[1]; - } - if ( ( *point )->_pnt[2] > bbox_max[2] ) { - bbox_max[2] = ( *point )->_pnt[2]; - } - - if ( ( *point )->_pnt[0] < bbox_min[0] ) { - bbox_min[0] = ( *point )->_pnt[0]; - } - if ( ( *point )->_pnt[1] < bbox_min[1] ) { - bbox_min[1] = ( *point )->_pnt[1]; - } - if ( ( *point )->_pnt[2] < bbox_min[2] ) { - bbox_min[2] = ( *point )->_pnt[2]; - } - } - - bBoundsBuilt = TRUE; - } -} - -bool DBrush::BBoxTouch( DBrush *chkBrush ){ - vec3_t min1, min2; - vec3_t max1, max2; - - GetBounds( min1, max1 ); - chkBrush->GetBounds( min2, max2 ); - - if ( ( min1[0] - max2[0] ) > MAX_ROUND_ERROR ) { - return FALSE; - } - if ( ( min1[1] - max2[1] ) > MAX_ROUND_ERROR ) { - return FALSE; - } - if ( ( min1[2] - max2[2] ) > MAX_ROUND_ERROR ) { - return FALSE; - } - - if ( ( min2[0] - max1[0] ) > MAX_ROUND_ERROR ) { - return FALSE; - } - if ( ( min2[1] - max1[1] ) > MAX_ROUND_ERROR ) { - return FALSE; - } - if ( ( min2[2] - max1[2] ) > MAX_ROUND_ERROR ) { - return FALSE; - } - - int cnt = 0; - - if ( ( min2[0] - max1[0] ) == 0 ) { - cnt++; - } - - if ( ( min2[1] - max1[1] ) == 0 ) { - cnt++; - } - - if ( ( min2[2] - max1[2] ) == 0 ) { - cnt++; - } - - if ( ( min1[0] - max2[0] ) == 0 ) { - cnt++; - } - - if ( ( min1[1] - max2[1] ) == 0 ) { - cnt++; - } - - if ( ( min1[2] - max2[2] ) == 0 ) { - cnt++; - } - - if ( cnt > 1 ) { - return FALSE; - } - - return TRUE; -} - -void DBrush::ResetChecks( list* exclusionList ){ - for ( list::const_iterator resetPlane = faceList.begin(); resetPlane != faceList.end(); resetPlane++ ) - { - bool set = FALSE; - - if ( exclusionList ) { - for ( list::iterator eTexture = exclusionList->begin(); eTexture != exclusionList->end(); eTexture++ ) - { - if ( strstr( ( *resetPlane )->texInfo.m_TextureName, eTexture->GetBuffer() ) ) { - set = TRUE; - break; - } - } - } - - ( *resetPlane )->m_bChkOk = set; - } -} - -DPlane* DBrush::HasPlaneInverted( DPlane *chkPlane ){ - for ( list::const_iterator brushPlane = faceList.begin(); brushPlane != faceList.end(); brushPlane++ ) - { - if ( **brushPlane != *chkPlane ) { - if ( fabs( ( *brushPlane )->_d + chkPlane->_d ) < 0.1 ) { - return ( *brushPlane ); - } - } - } - return NULL; -} - -bool DBrush::HasTexture( const char *textureName ){ - for ( list::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ ) - { - if ( strstr( ( *chkPlane )->texInfo.m_TextureName, textureName ) ) { - return TRUE; - } - - } - return FALSE; -} - -bool DBrush::IsDetail(){ - for ( list::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ ) - { - if ( ( *chkPlane )->texInfo.m_nContents & FACE_DETAIL ) { - return TRUE; - } - - } - return FALSE; -} - -void DBrush::BuildFromWinding( DWinding *w ){ - if ( w->numpoints < 3 ) { - Sys_ERROR( "Winding has invalid number of points" ); - return; - } - - DPlane* wPlane = w->WindingPlane(); - - DWinding* w2; - w2 = w->CopyWinding(); - int i; - for ( i = 0; i < w2->numpoints; i++ ) - VectorAdd( w2->p[i], wPlane->normal, w2->p[i] ); - - AddFace( w2->p[0], w2->p[1], w2->p[2], NULL ); - AddFace( w->p[2], w->p[1], w->p[0], NULL ); - - for ( i = 0; i < w->numpoints - 1; i++ ) - AddFace( w2->p[i], w->p[i], w->p[i + 1], NULL ); - AddFace( w2->p[w->numpoints - 1], w->p[w->numpoints - 1], w->p[0], NULL ); - - delete wPlane; - delete w2; -} - -void DBrush::SaveToFile( FILE *pFile ){ - fprintf( pFile, "{\n" ); - - for ( list::const_iterator pp = faceList.begin(); pp != faceList.end(); pp++ ) - { - char buffer[512]; - - sprintf( buffer, "( %.0f %.0f %.0f ) ( %.0f %.0f %.0f ) ( %.0f %.0f %.0f ) %s %.0f %.0f %f %f %.0f 0 0 0\n", - ( *pp )->points[0][0], ( *pp )->points[0][1], ( *pp )->points[0][2], - ( *pp )->points[1][0], ( *pp )->points[1][1], ( *pp )->points[1][2], - ( *pp )->points[2][0], ( *pp )->points[2][1], ( *pp )->points[2][2], - ( *pp )->texInfo.m_TextureName, - ( *pp )->texInfo.m_fShift[0], ( *pp )->texInfo.m_fShift[1], - ( *pp )->texInfo.m_fScale[0], ( *pp )->texInfo.m_fScale[0], - ( *pp )->texInfo.m_fRotate ); - - fprintf( pFile, "%s", buffer ); - } - - fprintf( pFile, "}\n" ); -} - -void DBrush::Rotate( vec3_t vOrigin, vec3_t vRotation ){ - for ( list::const_iterator rotPlane = faceList.begin(); rotPlane != faceList.end(); rotPlane++ ) - { - for ( int i = 0; i < 3; i++ ) - VectorRotate( ( *rotPlane )->points[i], vRotation, vOrigin ); - - ( *rotPlane )->Rebuild(); - } -} - -void DBrush::RotateAboutCentre( vec3_t vRotation ){ - vec3_t min, max, centre; - GetBounds( min, max ); - VectorAdd( min, max, centre ); - VectorScale( centre, 0.5f, centre ); - - Rotate( centre, vRotation ); -} - -bool DBrush::ResetTextures( const char* textureName, float fScale[2], float fShift[2], int rotation, const char* newTextureName, - int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation ){ - if ( textureName ) { - bool changed = FALSE; - for ( list::const_iterator resetPlane = faceList.begin(); resetPlane != faceList.end(); resetPlane++ ) - { - if ( !strcmp( ( *resetPlane )->texInfo.m_TextureName, textureName ) ) { - if ( bResetTextureName ) { - strcpy( ( *resetPlane )->texInfo.m_TextureName, newTextureName ); - } - - if ( bResetScale[0] ) { - ( *resetPlane )->texInfo.m_fScale[0] = fScale[0]; - } - if ( bResetScale[1] ) { - ( *resetPlane )->texInfo.m_fScale[1] = fScale[1]; - } - - if ( bResetShift[0] ) { - ( *resetPlane )->texInfo.m_fShift[0] = fShift[0]; - } - if ( bResetShift[1] ) { - ( *resetPlane )->texInfo.m_fShift[1] = fShift[1]; - } - - if ( bResetRotation ) { - ( *resetPlane )->texInfo.m_fRotate = (float)rotation; - } - - changed = TRUE; - } - } - return changed; // no point rebuilding unless we need to, only slows things down - } - else - { - for ( list::const_iterator resetPlane = faceList.begin(); resetPlane != faceList.end(); resetPlane++ ) - { - if ( bResetTextureName ) { - strcpy( ( *resetPlane )->texInfo.m_TextureName, newTextureName ); - } - - if ( bResetScale[0] ) { - ( *resetPlane )->texInfo.m_fScale[0] = fScale[0]; - } - if ( bResetScale[1] ) { - ( *resetPlane )->texInfo.m_fScale[1] = fScale[1]; - } - - if ( bResetShift[0] ) { - ( *resetPlane )->texInfo.m_fShift[0] = fShift[0]; - } - if ( bResetShift[1] ) { - ( *resetPlane )->texInfo.m_fShift[1] = fShift[1]; - } - - if ( bResetRotation ) { - ( *resetPlane )->texInfo.m_fRotate = (float)rotation; - } - } - return TRUE; - } -} - -bool DBrush::operator ==( DBrush* other ){ - list::const_iterator chkPlane; - - for ( chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ ) - { - if ( !other->HasPlane( ( *chkPlane ) ) ) { - return FALSE; - } - } - - for ( chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ ) - { - if ( !HasPlane( ( *chkPlane ) ) ) { - return FALSE; - } - } - - return TRUE; -} - -DPlane* DBrush::AddFace( vec3_t va, vec3_t vb, vec3_t vc, const char *textureName, bool bDetail ){ - bBoundsBuilt = FALSE; - DPlane* newFace = new DPlane( va, vb, vc, textureName, bDetail ); - faceList.push_back( newFace ); - - return newFace; -} - -DPlane* DBrush::FindPlaneWithClosestNormal( vec_t* normal ) { - vec_t bestDot = -2; - DPlane* bestDotPlane = NULL; - list::const_iterator chkPlane; - for ( chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ ) { - DPlane* pPlane = ( *chkPlane ); - - vec_t dot = DotProduct( pPlane->normal, normal ); - if ( dot > bestDot ) { - bestDot = dot; - bestDotPlane = pPlane; - } - } - - return bestDotPlane; -} - -int DBrush::FindPointsForPlane( DPlane* plane, DPoint** pnts, int maxpnts ) { - int numpnts = 0; - - if ( !maxpnts ) { - return 0; - } - - BuildPoints(); - - for ( list::const_iterator points = pointList.begin(); points != pointList.end(); points++ ) { - DPoint* point = ( *points ); - - if ( fabs( plane->DistanceToPoint( point->_pnt ) ) < MAX_ROUND_ERROR ) { - pnts[numpnts] = point; - numpnts++; - - if ( numpnts >= maxpnts ) { - return numpnts; - } - - } - } - - return numpnts; -} +typedef ReferenceCaller DBrushAddFaceTexturedCaller; + +void DBrush::LoadFromBrush(scene::Instance &brush, bool textured) +{ + ClearFaces(); + ClearPoints(); + + GlobalBrushCreator().Brush_forEachFace(brush.path().top(), + textured ? BrushFaceDataCallback(DBrushAddFaceTexturedCaller(*this)) + : BrushFaceDataCallback(DBrushAddFaceCaller(*this))); + + QER_entity = brush.path().parent().get_pointer(); + QER_brush = brush.path().top().get_pointer(); +} + +int DBrush::PointPosition(vec3_t pnt) +{ + int state = POINT_IN_BRUSH; // if nothing happens point is inside brush + + for (std::list::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++) { + float dist = (*chkPlane)->DistanceToPoint(pnt); -void DBrush::RemovePlane( DPlane* plane ) { - bBoundsBuilt = FALSE; - for ( list::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++ ) { - if ( *deadPlane == plane ) { - delete *deadPlane; - faceList.remove( plane ); - } - } + if (dist > MAX_ROUND_ERROR) { + return POINT_OUT_BRUSH; // if point is in front of plane, it CANT be in the brush + } else if (fabs(dist) < MAX_ROUND_ERROR) { + state = POINT_ON_BRUSH; // if point is ON plane point is either ON the brush + } + // or outside it, it can no longer be in it + } + + return state; +} + +void DBrush::ClearPoints() +{ + for (std::list::const_iterator deadPoint = pointList.begin(); deadPoint != pointList.end(); deadPoint++) { + delete *deadPoint; + } + pointList.clear(); +} + +void DBrush::ClearFaces() +{ + bBoundsBuilt = false; + for (std::list::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++) { + delete *deadPlane; + } + faceList.clear(); } -void DBrush::RemoveFromRadiant( void ) { - if ( QER_brush ) { - g_FuncTable.m_pfnDeleteBrushHandle( QER_brush ); - } +void DBrush::AddPoint(vec3_t pnt) +{ + DPoint *newPoint = new DPoint; + VectorCopy(pnt, newPoint->_pnt); + pointList.push_back(newPoint); +} + +bool DBrush::HasPoint(vec3_t pnt) +{ + for (std::list::const_iterator chkPoint = pointList.begin(); chkPoint != pointList.end(); chkPoint++) { + if (**chkPoint == pnt) { + return true; + } + } + + return false; +} + +int DBrush::RemoveRedundantPlanes() +{ + int cnt = 0; + std::list::iterator chkPlane; + + // find duplicate planes + std::list::iterator p1 = faceList.begin(); + + while (p1 != faceList.end()) { + std::list::iterator p2 = p1; + + for (p2++; p2 != faceList.end(); p2++) { + if (**p1 == **p2) { + if (!strcmp((*p1)->m_shader.c_str(), "textures/common/caulk")) { + delete *p1; + p1 = faceList.erase(p1); // duplicate plane + } else { + delete *p2; + p2 = faceList.erase(p2); // duplicate plane + } + + cnt++; + break; + } + } + + if (p2 == faceList.end()) { + p1++; + } + } + + //+djbob kill planes with bad normal, they are more of a nuisance than losing a brush + chkPlane = faceList.begin(); + while (chkPlane != faceList.end()) { + if (VectorLength((*chkPlane)->normal) == 0) { // plane has bad normal + delete *chkPlane; + chkPlane = faceList.erase(chkPlane); + cnt++; + } else { + chkPlane++; + } + } + //-djbob + + if (pointList.size() == 0) { // if points may not have been built, build them +/* if(BuildPoints() == 0) // just let the planes die if they are all bad + return cnt;*/ + BuildPoints(); + } + + chkPlane = faceList.begin(); + while (chkPlane != faceList.end()) { + if ((*chkPlane)->IsRedundant(pointList)) { // checks that plane "0wnz" :), 3 or more points + delete *chkPlane; + chkPlane = faceList.erase(chkPlane); + cnt++; + } else { + chkPlane++; + } + } + + return cnt; +} + +bool DBrush::GetBounds(vec3_t min, vec3_t max) +{ + BuildBounds(); + + if (!bBoundsBuilt) { + return false; + } + + VectorCopy(bbox_min, min); + VectorCopy(bbox_max, max); + + return true; +} + +bool DBrush::BBoxCollision(DBrush *chkBrush) +{ + vec3_t min1, min2; + vec3_t max1, max2; + + GetBounds(min1, max1); + chkBrush->GetBounds(min2, max2); + + if (min1[0] >= max2[0]) { + return false; + } + if (min1[1] >= max2[1]) { + return false; + } + if (min1[2] >= max2[2]) { + return false; + } + + if (max1[0] <= min2[0]) { + return false; + } + if (max1[1] <= min2[1]) { + return false; + } + if (max1[2] <= min2[2]) { + return false; + } + + return true; +} + +DPlane *DBrush::HasPlane(DPlane *chkPlane) +{ + for (std::list::const_iterator brushPlane = faceList.begin(); + brushPlane != faceList.end(); brushPlane++) { + if (**brushPlane == *chkPlane) { + return *brushPlane; + } + } + return NULL; +} + +bool DBrush::IsCutByPlane(DPlane *cuttingPlane) +{ + bool isInFront; + + if (pointList.size() == 0) { + if (BuildPoints() == 0) { + return false; + } + } + + std::list::const_iterator chkPnt = pointList.begin(); + + if (chkPnt == pointList.end()) { + return false; + } + + float dist = cuttingPlane->DistanceToPoint((*chkPnt)->_pnt); + + if (dist > MAX_ROUND_ERROR) { + isInFront = false; + } else if (dist < MAX_ROUND_ERROR) { + isInFront = true; + } else { + return true; + } + + for (chkPnt++ = pointList.begin(); chkPnt != pointList.end(); chkPnt++) { + dist = cuttingPlane->DistanceToPoint((*chkPnt)->_pnt); + + if (dist > MAX_ROUND_ERROR) { + if (isInFront) { + return true; + } + } else if (dist < MAX_ROUND_ERROR) { + if (!isInFront) { + return true; + } + } else { + return true; + } + } + + return false; +} + + +scene::Node *DBrush::BuildInRadiant(bool allowDestruction, int *changeCnt, scene::Node *entity) +{ + if (allowDestruction) { + bool kill = true; + + for (std::list::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++) { + if ((*chkPlane)->m_bChkOk) { + kill = false; + break; + } + } + if (kill) { + return NULL; + } + } + + //+djbob: fixed bug when brush had no faces "phantom brush" in radiant. + if (faceList.size() < 4) { + globalErrorStream() << "Possible Phantom Brush Found, will not rebuild\n"; + return NULL; + } + //-djbob + + NodeSmartReference node(GlobalBrushCreator().createBrush()); + + for (std::list::const_iterator buildPlane = faceList.begin(); + buildPlane != faceList.end(); buildPlane++) { + if ((*buildPlane)->AddToBrush(node) && changeCnt) { + (*changeCnt)++; + } + } + + if (entity) { + Node_getTraversable(*entity)->insert(node); + } else { + Node_getTraversable(GlobalRadiant().getMapWorldEntity())->insert(node); + } + + QER_entity = entity; + QER_brush = node.get_pointer(); + + return node.get_pointer(); +} + +void DBrush::CutByPlane(DPlane *cutPlane, DBrush **newBrush1, DBrush **newBrush2) +{ + if (!IsCutByPlane(cutPlane)) { + *newBrush1 = NULL; + *newBrush2 = NULL; + return; + } + + DBrush *b1 = new DBrush; + DBrush *b2 = new DBrush; + + for (std::list::const_iterator parsePlane = faceList.begin(); + parsePlane != faceList.end(); parsePlane++) { + b1->AddFace((*parsePlane)->points[0], (*parsePlane)->points[1], (*parsePlane)->points[2], NULL); + b2->AddFace((*parsePlane)->points[0], (*parsePlane)->points[1], (*parsePlane)->points[2], NULL); + } + + b1->AddFace(cutPlane->points[0], cutPlane->points[1], cutPlane->points[2], NULL); + b2->AddFace(cutPlane->points[2], cutPlane->points[1], cutPlane->points[0], NULL); + + b1->RemoveRedundantPlanes(); + b2->RemoveRedundantPlanes(); + + *newBrush1 = b1; + *newBrush2 = b2; +} + +bool DBrush::IntersectsWith(DBrush *chkBrush) +{ + if (pointList.size() == 0) { + if (BuildPoints() == 0) { + return false; // invalid brush!!!! + + } + } + if (chkBrush->pointList.size() == 0) { + if (chkBrush->BuildPoints() == 0) { + return false; // invalid brush!!!! + + } + } + if (!BBoxCollision(chkBrush)) { + return false; + } + + std::list::const_iterator iplPlane; + + for (iplPlane = faceList.begin(); iplPlane != faceList.end(); iplPlane++) { + + bool allInFront = true; + for (std::list::const_iterator iPoint = chkBrush->pointList.begin(); + iPoint != chkBrush->pointList.end(); iPoint++) { + if ((*iplPlane)->DistanceToPoint((*iPoint)->_pnt) < -MAX_ROUND_ERROR) { + allInFront = false; + break; + } + } + if (allInFront) { + return false; + } + } + + for (iplPlane = chkBrush->faceList.begin(); iplPlane != chkBrush->faceList.end(); iplPlane++) { + bool allInFront = true; + for (std::list::const_iterator iPoint = pointList.begin(); iPoint != pointList.end(); iPoint++) { + if ((*iplPlane)->DistanceToPoint((*iPoint)->_pnt) < -MAX_ROUND_ERROR) { + allInFront = false; + break; + } + } + if (allInFront) { + return false; + } + } + + return true; +} + +bool DBrush::IntersectsWith(DPlane *p1, DPlane *p2, vec3_t v) +{ + vec3_t vDown = {0, 0, -1}; + + std::list::const_iterator iplPlane; + for (iplPlane = faceList.begin(); iplPlane != faceList.end(); iplPlane++) { + DPlane *p = (*iplPlane); + + vec_t d = DotProduct(p->normal, vDown); + if (d >= 0) { + continue; + } + if (p->PlaneIntersection(p1, p2, v)) { + if (PointPosition(v) != POINT_OUT_BRUSH) { + return true; + } + } + } + + return false; +} + +void DBrush::BuildBounds() +{ + if (!bBoundsBuilt) { + if (pointList.size() == 0) { // if points may not have been built, build them + if (BuildPoints() == 0) { + return; + } + } + + std::list::const_iterator first = pointList.begin(); + VectorCopy((*first)->_pnt, bbox_min); + VectorCopy((*first)->_pnt, bbox_max); + + std::list::const_iterator point = pointList.begin(); + for (point++; point != pointList.end(); point++) { + if ((*point)->_pnt[0] > bbox_max[0]) { + bbox_max[0] = (*point)->_pnt[0]; + } + if ((*point)->_pnt[1] > bbox_max[1]) { + bbox_max[1] = (*point)->_pnt[1]; + } + if ((*point)->_pnt[2] > bbox_max[2]) { + bbox_max[2] = (*point)->_pnt[2]; + } + + if ((*point)->_pnt[0] < bbox_min[0]) { + bbox_min[0] = (*point)->_pnt[0]; + } + if ((*point)->_pnt[1] < bbox_min[1]) { + bbox_min[1] = (*point)->_pnt[1]; + } + if ((*point)->_pnt[2] < bbox_min[2]) { + bbox_min[2] = (*point)->_pnt[2]; + } + } + + bBoundsBuilt = true; + } +} + +bool DBrush::BBoxTouch(DBrush *chkBrush) +{ + vec3_t min1, min2; + vec3_t max1, max2; + + GetBounds(min1, max1); + chkBrush->GetBounds(min2, max2); + + if ((min1[0] - max2[0]) > MAX_ROUND_ERROR) { + return false; + } + if ((min1[1] - max2[1]) > MAX_ROUND_ERROR) { + return false; + } + if ((min1[2] - max2[2]) > MAX_ROUND_ERROR) { + return false; + } + + if ((min2[0] - max1[0]) > MAX_ROUND_ERROR) { + return false; + } + if ((min2[1] - max1[1]) > MAX_ROUND_ERROR) { + return false; + } + if ((min2[2] - max1[2]) > MAX_ROUND_ERROR) { + return false; + } + + int cnt = 0; + + if ((min2[0] - max1[0]) == 0) { + cnt++; + } + + if ((min2[1] - max1[1]) == 0) { + cnt++; + } + + if ((min2[2] - max1[2]) == 0) { + cnt++; + } + + if ((min1[0] - max2[0]) == 0) { + cnt++; + } + + if ((min1[1] - max2[1]) == 0) { + cnt++; + } + + if ((min1[2] - max2[2]) == 0) { + cnt++; + } + + if (cnt > 1) { + return false; + } + + return true; +} + +void DBrush::ResetChecks(std::list *exclusionList) +{ + for (std::list::const_iterator resetPlane = faceList.begin(); + resetPlane != faceList.end(); resetPlane++) { + bool set = false; + + if (exclusionList) { + for (std::list::iterator eTexture = exclusionList->begin(); + eTexture != exclusionList->end(); eTexture++) { + if (strstr((*resetPlane)->m_shader.c_str(), eTexture->GetBuffer())) { + set = true; + break; + } + } + } + + (*resetPlane)->m_bChkOk = set; + } +} + +DPlane *DBrush::HasPlaneInverted(DPlane *chkPlane) +{ + for (std::list::const_iterator brushPlane = faceList.begin(); + brushPlane != faceList.end(); brushPlane++) { + if (**brushPlane != *chkPlane) { + if (fabs((*brushPlane)->_d + chkPlane->_d) < 0.1) { + return (*brushPlane); + } + } + } + return NULL; +} + +bool DBrush::HasTexture(const char *textureName) +{ + for (std::list::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++) { + if (strstr((*chkPlane)->m_shader.c_str(), textureName)) { + return true; + } + + } + return false; +} + +bool DBrush::IsDetail() +{ + for (std::list::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++) { + if ((*chkPlane)->texInfo.contents & FACE_DETAIL) { + return true; + } + + } + return false; +} + +void DBrush::BuildFromWinding(DWinding *w) +{ + if (w->numpoints < 3) { + globalErrorStream() << "Winding has invalid number of points"; + return; + } + + DPlane *wPlane = w->WindingPlane(); + + DWinding *w2; + w2 = w->CopyWinding(); + int i; + for (i = 0; i < w2->numpoints; i++) + VectorAdd(w2->p[i], wPlane->normal, w2->p[i]); + + AddFace(w2->p[0], w2->p[1], w2->p[2], NULL); + AddFace(w->p[2], w->p[1], w->p[0], NULL); + + for (i = 0; i < w->numpoints - 1; i++) { + AddFace(w2->p[i], w->p[i], w->p[i + 1], NULL); + } + AddFace(w2->p[w->numpoints - 1], w->p[w->numpoints - 1], w->p[0], NULL); + + delete wPlane; + delete w2; +} + +void DBrush::SaveToFile(FILE *pFile) +{ + fprintf(pFile, "{\n"); + + for (std::list::const_iterator pp = faceList.begin(); pp != faceList.end(); pp++) { + char buffer[512]; + + sprintf(buffer, "( %.0f %.0f %.0f ) ( %.0f %.0f %.0f ) ( %.0f %.0f %.0f ) %s %.0f %.0f %f %f %.0f 0 0 0\n", + (*pp)->points[0][0], (*pp)->points[0][1], (*pp)->points[0][2], + (*pp)->points[1][0], (*pp)->points[1][1], (*pp)->points[1][2], + (*pp)->points[2][0], (*pp)->points[2][1], (*pp)->points[2][2], + (*pp)->m_shader.c_str(), + (*pp)->texInfo.m_texdef.shift[0], (*pp)->texInfo.m_texdef.shift[1], + (*pp)->texInfo.m_texdef.scale[0], (*pp)->texInfo.m_texdef.scale[0], + (*pp)->texInfo.m_texdef.rotate); + + fprintf(pFile, "%s", buffer); + } + + fprintf(pFile, "}\n"); +} + +void DBrush::Rotate(vec3_t vOrigin, vec3_t vRotation) +{ + for (std::list::const_iterator rotPlane = faceList.begin(); rotPlane != faceList.end(); rotPlane++) { + for (int i = 0; i < 3; i++) { + VectorRotate((*rotPlane)->points[i], vRotation, vOrigin); + } + + (*rotPlane)->Rebuild(); + } +} + +void DBrush::RotateAboutCentre(vec3_t vRotation) +{ + vec3_t min, max, centre; + GetBounds(min, max); + VectorAdd(min, max, centre); + VectorScale(centre, 0.5f, centre); + + Rotate(centre, vRotation); +} + +bool DBrush::ResetTextures(const char *textureName, float fScale[2], float fShift[2], int rotation, + const char *newTextureName, + int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation) +{ + if (textureName) { + bool changed = false; + for (std::list::const_iterator resetPlane = faceList.begin(); + resetPlane != faceList.end(); resetPlane++) { + if (!strcmp((*resetPlane)->m_shader.c_str(), textureName)) { + if (bResetTextureName) { + (*resetPlane)->m_shader = newTextureName; + } + + if (bResetScale[0]) { + (*resetPlane)->texInfo.m_texdef.scale[0] = fScale[0]; + } + if (bResetScale[1]) { + (*resetPlane)->texInfo.m_texdef.scale[1] = fScale[1]; + } + + if (bResetShift[0]) { + (*resetPlane)->texInfo.m_texdef.shift[0] = fShift[0]; + } + if (bResetShift[1]) { + (*resetPlane)->texInfo.m_texdef.shift[1] = fShift[1]; + } + + if (bResetRotation) { + (*resetPlane)->texInfo.m_texdef.rotate = (float) rotation; + } + + changed = true; + } + } + return changed; // no point rebuilding unless we need to, only slows things down + } else { + for (std::list::const_iterator resetPlane = faceList.begin(); + resetPlane != faceList.end(); resetPlane++) { + if (bResetTextureName) { + (*resetPlane)->m_shader = newTextureName; + } + + if (bResetScale[0]) { + (*resetPlane)->texInfo.m_texdef.scale[0] = fScale[0]; + } + if (bResetScale[1]) { + (*resetPlane)->texInfo.m_texdef.scale[1] = fScale[1]; + } + + if (bResetShift[0]) { + (*resetPlane)->texInfo.m_texdef.shift[0] = fShift[0]; + } + if (bResetShift[1]) { + (*resetPlane)->texInfo.m_texdef.shift[1] = fShift[1]; + } + + if (bResetRotation) { + (*resetPlane)->texInfo.m_texdef.rotate = (float) rotation; + } + } + return true; + } +} + +bool DBrush::operator==(DBrush *other) +{ + std::list::const_iterator chkPlane; + + for (chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++) { + if (!other->HasPlane((*chkPlane))) { + return false; + } + } + + for (chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++) { + if (!HasPlane((*chkPlane))) { + return false; + } + } + + return true; +} + +DPlane *DBrush::AddFace(const vec3_t va, const vec3_t vb, const vec3_t vc, const char *textureName, bool bDetail) +{ + bBoundsBuilt = false; + DPlane *newFace = new DPlane(va, vb, vc, textureName, bDetail); + faceList.push_back(newFace); + + return newFace; +} + +DPlane *DBrush::FindPlaneWithClosestNormal(vec_t *normal) +{ + vec_t bestDot = -2; + DPlane *bestDotPlane = NULL; + std::list::const_iterator chkPlane; + for (chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++) { + DPlane *pPlane = (*chkPlane); + + vec_t dot = DotProduct(pPlane->normal, normal); + if (dot > bestDot) { + bestDot = dot; + bestDotPlane = pPlane; + } + } + + return bestDotPlane; +} + +int DBrush::FindPointsForPlane(DPlane *plane, DPoint **pnts, int maxpnts) +{ + int numpnts = 0; + + if (!maxpnts) { + return 0; + } + + BuildPoints(); + + for (std::list::const_iterator points = pointList.begin(); points != pointList.end(); points++) { + DPoint *point = (*points); + + if (fabs(plane->DistanceToPoint(point->_pnt)) < MAX_ROUND_ERROR) { + pnts[numpnts] = point; + numpnts++; + + if (numpnts >= maxpnts) { + return numpnts; + } + + } + } + + return numpnts; +} + +void DBrush::RemovePlane(DPlane *plane) +{ + bBoundsBuilt = false; + for (std::list::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++) { + if (*deadPlane == plane) { + delete *deadPlane; + faceList.remove(plane); + } + } }