]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - contrib/bobtoolz/DBrush.cpp
reformat code! now the code is only ugly on the *inside*
[xonotic/netradiant.git] / contrib / bobtoolz / DBrush.cpp
index a0d97699c3411818f17ecf69c4cc0d822a78a263..a5b18cef377b441694504dfb05b48599e7fbb79b 100644 (file)
 // Construction/Destruction
 //////////////////////////////////////////////////////////////////////
 
-DBrush::DBrush( int ID ){
-       m_nBrushID = ID;
-       bBoundsBuilt = false;
-       QER_entity = NULL;
-       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( const vec3_t va, const vec3_t vb, const vec3_t vc, const _QERFaceData* texData ){
+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 ( std::list<DPlane *>::const_iterator p1 = faceList.begin(); p1 != faceList.end(); p1++ )
-       {
-               std::list<DPlane *>::const_iterator p2 = p1;
-               for ( p2++; p2 != faceList.end(); p2++ )
-               {
-                       std::list<DPlane *>::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 );
-                                               }
+    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<DPlane *>::const_iterator p1 = faceList.begin(); p1 != faceList.end(); p1++) {
+        std::list<DPlane *>::const_iterator p2 = p1;
+        for (p2++; p2 != faceList.end(); p2++) {
+            std::list<DPlane *>::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]);
+                }
+            }
+        }
+    }
 
 #if GDEF_DEBUG
 //     Sys_Printf("%i points on brush\n", pointList.size());
 #endif
 
-       return static_cast<int>( pointList.size() );
+    return static_cast<int>( pointList.size());
 }
 
-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 );
+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);
 }
-typedef ReferenceCaller<DBrush, void(const _QERFaceData&), DBrush_addFace> DBrushAddFaceCaller;
 
-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 );
+typedef ReferenceCaller<DBrush, void(const _QERFaceData &), DBrush_addFace> DBrushAddFaceCaller;
+
+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);
 }
-typedef ReferenceCaller<DBrush, void(const _QERFaceData&), DBrush_addFaceTextured> DBrushAddFaceTexturedCaller;
 
-void DBrush::LoadFromBrush( scene::Instance& brush, bool textured ){
-       ClearFaces();
-       ClearPoints();
+typedef ReferenceCaller<DBrush, void(const _QERFaceData &), DBrush_addFaceTextured> DBrushAddFaceTexturedCaller;
+
+void DBrush::LoadFromBrush(scene::Instance &brush, bool textured)
+{
+    ClearFaces();
+    ClearPoints();
 
-       GlobalBrushCreator().Brush_forEachFace( brush.path().top(), textured ? BrushFaceDataCallback( DBrushAddFaceTexturedCaller( *this ) ) : BrushFaceDataCallback( DBrushAddFaceCaller( *this ) ) );
+    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();
+    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
+int DBrush::PointPosition(vec3_t pnt)
+{
+    int state = POINT_IN_BRUSH; // if nothing happens point is inside brush
 
-       for ( std::list<DPlane *>::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
-       {
-               float dist = ( *chkPlane )->DistanceToPoint( pnt );
+    for (std::list<DPlane *>::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
-       }
+        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;
+    return state;
 }
 
-void DBrush::ClearPoints(){
-       for ( std::list<DPoint *>::const_iterator deadPoint = pointList.begin(); deadPoint != pointList.end(); deadPoint++ ) {
-               delete *deadPoint;
-       }
-       pointList.clear();
+void DBrush::ClearPoints()
+{
+    for (std::list<DPoint *>::const_iterator deadPoint = pointList.begin(); deadPoint != pointList.end(); deadPoint++) {
+        delete *deadPoint;
+    }
+    pointList.clear();
 }
 
-void DBrush::ClearFaces(){
-       bBoundsBuilt = false;
-       for ( std::list<DPlane *>::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++ )
-       {
-               delete *deadPlane;
-       }
-       faceList.clear();
+void DBrush::ClearFaces()
+{
+    bBoundsBuilt = false;
+    for (std::list<DPlane *>::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 );
+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<DPoint *>::const_iterator chkPoint = pointList.begin(); chkPoint != pointList.end(); chkPoint++ )
-       {
-               if ( **chkPoint == pnt ) {
-                       return true;
-               }
-       }
+bool DBrush::HasPoint(vec3_t pnt)
+{
+    for (std::list<DPoint *>::const_iterator chkPoint = pointList.begin(); chkPoint != pointList.end(); chkPoint++) {
+        if (**chkPoint == pnt) {
+            return true;
+        }
+    }
 
-       return false;
+    return false;
 }
 
-int DBrush::RemoveRedundantPlanes(){
-       int cnt = 0;
-       std::list<DPlane *>::iterator chkPlane;
+int DBrush::RemoveRedundantPlanes()
+{
+    int cnt = 0;
+    std::list<DPlane *>::iterator chkPlane;
+
+    // find duplicate planes
+    std::list<DPlane *>::iterator p1 = faceList.begin();
 
-       // find duplicate planes
-       std::list<DPlane *>::iterator p1 = faceList.begin();
+    while (p1 != faceList.end()) {
+        std::list<DPlane *>::iterator p2 = p1;
 
-       while ( p1 != faceList.end() )
-       {
-               std::list<DPlane *>::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
+                }
 
-               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++;
+        }
+    }
 
-                               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
+    //+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<DPlane *>::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<DPoint *>::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<DPlane *>::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<DPlane *>::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<DPlane *>::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<DPlane *>::const_iterator iplPlane;
-
-       for ( iplPlane = faceList.begin(); iplPlane != faceList.end(); iplPlane++ )
-       {
-
-               bool allInFront = true;
-               for ( std::list<DPoint *>::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<DPoint *>::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<DPlane *>::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<DPoint *>::const_iterator first = pointList.begin();
-               VectorCopy( ( *first )->_pnt, bbox_min );
-               VectorCopy( ( *first )->_pnt, bbox_max );
-
-               std::list<DPoint *>::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<Str>* exclusionList ){
-       for ( std::list<DPlane *>::const_iterator resetPlane = faceList.begin(); resetPlane != faceList.end(); resetPlane++ )
-       {
-               bool set = false;
-
-               if ( exclusionList ) {
-                       for ( std::list<Str>::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<DPlane *>::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<DPlane *>::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<DPlane *>::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<DPlane *>::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<DPlane *>::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<DPlane *>::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<DPlane *>::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<DPlane *>::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<DPlane *>::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<DPoint *>::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<DPlane *>::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++ ) {
-               if ( *deadPlane == plane ) {
-                       delete *deadPlane;
-                       faceList.remove( plane );
-               }
-       }
+        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<DPlane *>::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<DPoint *>::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<DPlane *>::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<DPlane *>::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<DPlane *>::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<DPlane *>::const_iterator iplPlane;
+
+    for (iplPlane = faceList.begin(); iplPlane != faceList.end(); iplPlane++) {
+
+        bool allInFront = true;
+        for (std::list<DPoint *>::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<DPoint *>::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<DPlane *>::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<DPoint *>::const_iterator first = pointList.begin();
+        VectorCopy((*first)->_pnt, bbox_min);
+        VectorCopy((*first)->_pnt, bbox_max);
+
+        std::list<DPoint *>::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<Str> *exclusionList)
+{
+    for (std::list<DPlane *>::const_iterator resetPlane = faceList.begin();
+         resetPlane != faceList.end(); resetPlane++) {
+        bool set = false;
+
+        if (exclusionList) {
+            for (std::list<Str>::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<DPlane *>::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<DPlane *>::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<DPlane *>::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<DPlane *>::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<DPlane *>::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<DPlane *>::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<DPlane *>::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<DPlane *>::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<DPlane *>::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<DPoint *>::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<DPlane *>::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++) {
+        if (*deadPlane == plane) {
+            delete *deadPlane;
+            faceList.remove(plane);
+        }
+    }
 }