/* ============ idMapBrush::Write ============ */ bool idMapBrush::Write( idFile *fp, int primitiveNum, const idVec3 &origin ) const { int i; idMapBrushSide *side; fp->WriteFloatString( "// primitive %d\n{\n brushDef3\n {\n", primitiveNum ); // write brush epairs for ( i = 0; i < epairs.GetNumKeyVals(); i++) { fp->WriteFloatString( " \"%s\" \"%s\"\n", epairs.GetKeyVal(i)->GetKey().c_str(), epairs.GetKeyVal(i)->GetValue().c_str()); } // write brush sides for ( i = 0; i < GetNumSides(); i++ ) { side = GetSide( i ); fp->WriteFloatString( " ( %f %f %f %f ) ", side->plane[0], side->plane[1], side->plane[2], side->plane[3] ); fp->WriteFloatString( "( ( %f %f %f ) ( %f %f %f ) ) \"%s\" 0 0 0\n", side->texMat[0][0], side->texMat[0][1], side->texMat[0][2], side->texMat[1][0], side->texMat[1][1], side->texMat[1][2], side->material.c_str() ); } fp->WriteFloatString( " }\n}\n" ); return true; }
/* =============== idMapBrush::GetGeometryCRC =============== */ unsigned int idMapBrush::GetGeometryCRC( void ) const { int i, j; idMapBrushSide *mapSide; unsigned int crc; crc = 0; for ( i = 0; i < GetNumSides(); i++ ) { mapSide = GetSide(i); for ( j = 0; j < 4; j++ ) { crc ^= FloatCRC( mapSide->GetPlane()[j] ); } crc ^= StringCRC( mapSide->GetMaterial() ); } return crc; }
/* ============ idBrush::TryMerge ============ */ bool idBrush::TryMerge( const idBrush* brush, const idPlaneSet& planeList ) { int i, j, k, l, m, seperatingPlane; const idBrush* brushes[2]; const idWinding* w; const idPlane* plane; // brush bounds should overlap for( i = 0; i < 3; i++ ) { if( bounds[0][i] > brush->bounds[1][i] + 0.1f ) { return false; } if( bounds[1][i] < brush->bounds[0][i] - 0.1f ) { return false; } } // the brushes should share an opposite plane seperatingPlane = -1; for( i = 0; i < GetNumSides(); i++ ) { for( j = 0; j < brush->GetNumSides(); j++ ) { if( GetSide( i )->GetPlaneNum() == ( brush->GetSide( j )->GetPlaneNum() ^ 1 ) ) { // may only have one seperating plane if( seperatingPlane != -1 ) { return false; } seperatingPlane = GetSide( i )->GetPlaneNum(); break; } } } if( seperatingPlane == -1 ) { return false; } brushes[0] = this; brushes[1] = brush; for( i = 0; i < 2; i++ ) { j = !i; for( k = 0; k < brushes[i]->GetNumSides(); k++ ) { // if the brush side plane is the seprating plane if( !( ( brushes[i]->GetSide( k )->GetPlaneNum() ^ seperatingPlane ) >> 1 ) ) { continue; } plane = &brushes[i]->GetSide( k )->GetPlane(); // all the non seperating brush sides of the other brush should be at the back or on the plane for( l = 0; l < brushes[j]->GetNumSides(); l++ ) { w = brushes[j]->GetSide( l )->GetWinding(); if( !w ) { continue; } if( !( ( brushes[j]->GetSide( l )->GetPlaneNum() ^ seperatingPlane ) >> 1 ) ) { continue; } for( m = 0; m < w->GetNumPoints(); m++ ) { if( plane->Distance( ( *w )[m].ToVec3() ) > 0.1f ) { return false; } } } } } // add any sides from the other brush to this brush for( i = 0; i < brush->GetNumSides(); i++ ) { for( j = 0; j < GetNumSides(); j++ ) { if( !( ( brush->GetSide( i )->GetPlaneNum() ^ GetSide( j )->GetPlaneNum() ) >> 1 ) ) { break; } } if( j < GetNumSides() ) { sides[j]->flags &= brush->GetSide( i )->GetFlags(); continue; } sides.Append( brush->GetSide( i )->Copy() ); } // remove any side from this brush that is the opposite of a side of the other brush for( i = 0; i < GetNumSides(); i++ ) { for( j = 0; j < brush->GetNumSides(); j++ ) { if( GetSide( i )->GetPlaneNum() == ( brush->GetSide( j )->GetPlaneNum() ^ 1 ) ) { break; } } if( j < brush->GetNumSides() ) { delete sides[i]; sides.RemoveIndex( i ); i--; continue; } } contents |= brush->contents; CreateWindings(); BoundBrush(); return true; }