/* ============ idBrush::Subtract ============ */ bool idBrush::Subtract( const idBrush* b, idBrushList& list ) const { int i; idBrush* front, *back; const idBrush* in; list.Clear(); in = this; for( i = 0; i < b->sides.Num() && in; i++ ) { in->Split( b->sides[i]->plane, b->sides[i]->planeNum, &front, &back ); if( in != this ) { delete in; } if( front ) { list.AddToTail( front ); } in = back; } // if didn't really intersect if( !in ) { list.Free(); return false; } delete in; return true; }
/* ============ idAASBuild::AddBrushForMapBrush ============ */ idBrushList idAASBuild::AddBrushesForMapBrush( const idMapBrush* mapBrush, const idVec3& origin, const idMat3& axis, int entityNum, int primitiveNum, idBrushList brushList ) { int contents, i; idMapBrushSide* mapSide; const idMaterial* mat; idList<idBrushSide*> sideList; idBrush* brush; idPlane plane; contents = 0; for( i = 0; i < mapBrush->GetNumSides(); i++ ) { mapSide = mapBrush->GetSide( i ); mat = declManager->FindMaterial( mapSide->GetMaterial() ); contents |= mat->GetContentFlags(); plane = mapSide->GetPlane(); plane.FixDegeneracies( DEGENERATE_DIST_EPSILON ); sideList.Append( new idBrushSide( plane, -1 ) ); } contents = ContentsForAAS( contents ); if( !contents ) { for( i = 0; i < sideList.Num(); i++ ) { delete sideList[i]; } return brushList; } brush = new idBrush(); brush->SetContents( contents ); if( !brush->FromSides( sideList ) ) { common->Warning( "brush primitive %d on entity %d is degenerate", primitiveNum, entityNum ); delete brush; return brushList; } brush->SetEntityNum( entityNum ); brush->SetPrimitiveNum( primitiveNum ); brush->Transform( origin, axis ); brushList.AddToTail( brush ); return brushList; }
/* ============ idBrushList::Split ============ */ void idBrushList::Split( const idPlane& plane, int planeNum, idBrushList& frontList, idBrushList& backList, bool useBrushSavedPlaneSide ) { idBrush* b, *front, *back; frontList.Clear(); backList.Clear(); if( !useBrushSavedPlaneSide ) { for( b = head; b; b = b->next ) { b->Split( plane, planeNum, &front, &back ); if( front ) { frontList.AddToTail( front ); } if( back ) { backList.AddToTail( back ); } } return; } for( b = head; b; b = b->next ) { if( b->savedPlaneSide & BRUSH_PLANESIDE_BOTH ) { b->Split( plane, planeNum, &front, &back ); if( front ) { frontList.AddToTail( front ); } if( back ) { backList.AddToTail( back ); } } else if( b->savedPlaneSide & BRUSH_PLANESIDE_FRONT ) { frontList.AddToTail( b->Copy() ); } else { backList.AddToTail( b->Copy() ); } } }
/* ============ idAASBuild::AddBrushesForPatch ============ */ idBrushList idAASBuild::AddBrushesForMapPatch( const idMapPatch* mapPatch, const idVec3& origin, const idMat3& axis, int entityNum, int primitiveNum, idBrushList brushList ) { int i, j, contents, validBrushes; float dot; int v1, v2, v3, v4; idFixedWinding w; idPlane plane; idVec3 d1, d2; idBrush* brush; idSurface_Patch mesh; const idMaterial* mat; mat = declManager->FindMaterial( mapPatch->GetMaterial() ); contents = ContentsForAAS( mat->GetContentFlags() ); if( !contents ) { return brushList; } mesh = idSurface_Patch( *mapPatch ); // if the patch has an explicit number of subdivisions use it to avoid cracks if( mapPatch->GetExplicitlySubdivided() ) { mesh.SubdivideExplicit( mapPatch->GetHorzSubdivisions(), mapPatch->GetVertSubdivisions(), false, true ); } else { mesh.Subdivide( DEFAULT_CURVE_MAX_ERROR_CD, DEFAULT_CURVE_MAX_ERROR_CD, DEFAULT_CURVE_MAX_LENGTH_CD, false ); } validBrushes = 0; for( i = 0; i < mesh.GetWidth() - 1; i++ ) { for( j = 0; j < mesh.GetHeight() - 1; j++ ) { v1 = j * mesh.GetWidth() + i; v2 = v1 + 1; v3 = v1 + mesh.GetWidth() + 1; v4 = v1 + mesh.GetWidth(); d1 = mesh[v2].xyz - mesh[v1].xyz; d2 = mesh[v3].xyz - mesh[v1].xyz; plane.SetNormal( d1.Cross( d2 ) ); if( plane.Normalize() != 0.0f ) { plane.FitThroughPoint( mesh[v1].xyz ); dot = plane.Distance( mesh[v4].xyz ); // if we can turn it into a quad if( idMath::Fabs( dot ) < 0.1f ) { w.Clear(); w += mesh[v1].xyz; w += mesh[v2].xyz; w += mesh[v3].xyz; w += mesh[v4].xyz; brush = new idBrush(); brush->SetContents( contents ); if( brush->FromWinding( w, plane ) ) { brush->SetEntityNum( entityNum ); brush->SetPrimitiveNum( primitiveNum ); brush->SetFlag( BFL_PATCH ); brush->Transform( origin, axis ); brushList.AddToTail( brush ); validBrushes++; } else { delete brush; } continue; } else { // create one of the triangles w.Clear(); w += mesh[v1].xyz; w += mesh[v2].xyz; w += mesh[v3].xyz; brush = new idBrush(); brush->SetContents( contents ); if( brush->FromWinding( w, plane ) ) { brush->SetEntityNum( entityNum ); brush->SetPrimitiveNum( primitiveNum ); brush->SetFlag( BFL_PATCH ); brush->Transform( origin, axis ); brushList.AddToTail( brush ); validBrushes++; } else { delete brush; } } } // create the other triangle d1 = mesh[v3].xyz - mesh[v1].xyz; d2 = mesh[v4].xyz - mesh[v1].xyz; plane.SetNormal( d1.Cross( d2 ) ); if( plane.Normalize() != 0.0f ) { plane.FitThroughPoint( mesh[v1].xyz ); w.Clear(); w += mesh[v1].xyz; w += mesh[v3].xyz; w += mesh[v4].xyz; brush = new idBrush(); brush->SetContents( contents ); if( brush->FromWinding( w, plane ) ) { brush->SetEntityNum( entityNum ); brush->SetPrimitiveNum( primitiveNum ); brush->SetFlag( BFL_PATCH ); brush->Transform( origin, axis ); brushList.AddToTail( brush ); validBrushes++; } else { delete brush; } } } } if( !validBrushes ) { common->Warning( "patch primitive %d on entity %d is completely degenerate", primitiveNum, entityNum ); } return brushList; }