/* =========================================================================== Return to Castle Wolfenstein single player GPL Source Code Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company. This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”). RTCW SP Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. RTCW SP Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with RTCW SP Source Code. If not, see . In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. =========================================================================== */ //=========================================================================== // // Name: aas_facemerging.c // Function: Merging of Faces // Programmer: Mr Elusive (MrElusive@demigod.demon.nl) // Last update: 1997-12-04 // Tab Size: 3 //=========================================================================== #include "qbsp.h" #include "../botlib/aasfile.h" #include "aas_create.h" //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int AAS_TryMergeFaces( tmp_face_t *face1, tmp_face_t *face2 ) { winding_t *neww; #ifdef DEBUG if ( !face1->winding ) { Error( "face1 %d without winding", face1->num ); } if ( !face2->winding ) { Error( "face2 %d without winding", face2->num ); } #endif //DEBUG // if ( face1->faceflags != face2->faceflags ) { return false; } //NOTE: if the front or back area is zero this doesn't mean there's //a real area. It means there's solid at that side of the face //if both faces have the same front area if ( face1->frontarea == face2->frontarea ) { //if both faces have the same back area if ( face1->backarea == face2->backarea ) { //if the faces are in the same plane if ( face1->planenum == face2->planenum ) { //if they have both a front and a back area (no solid on either side) if ( face1->frontarea && face1->backarea ) { neww = MergeWindings( face1->winding, face2->winding, mapplanes[face1->planenum].normal ); } //end if else { //this function is to be found in l_poly.c neww = TryMergeWinding( face1->winding, face2->winding, mapplanes[face1->planenum].normal ); } //end else if ( neww ) { FreeWinding( face1->winding ); face1->winding = neww; if ( face2->frontarea ) { AAS_RemoveFaceFromArea( face2, face2->frontarea ); } if ( face2->backarea ) { AAS_RemoveFaceFromArea( face2, face2->backarea ); } AAS_FreeTmpFace( face2 ); return true; } //end if } //end if else if ( ( face1->planenum & ~1 ) == ( face2->planenum & ~1 ) ) { Log_Write( "face %d and %d, same front and back area but flipped planes\r\n", face1->num, face2->num ); } //end if } //end if } //end if return false; } //end of the function AAS_TryMergeFaces /* int AAS_TryMergeFaces(tmp_face_t *face1, tmp_face_t *face2) { winding_t *neww; #ifdef DEBUG if (!face1->winding) Error("face1 %d without winding", face1->num); if (!face2->winding) Error("face2 %d without winding", face2->num); #endif //DEBUG //if the faces are in the same plane if ((face1->planenum & ~1) != (face2->planenum & ~1)) return false; // if (face1->planenum != face2->planenum) return false; //NOTE: if the front or back area is zero this doesn't mean there's //a real area. It means there's solid at that side of the face //if both faces have the same front area if (face1->frontarea != face2->frontarea || face1->backarea != face2->backarea) { if (!face1->frontarea || !face1->backarea || !face2->frontarea || !face2->backarea) return false; else if (face1->frontarea != face2->backarea || face1->backarea != face2->frontarea) return false; // return false; } //end if //this function is to be found in l_poly.c neww = TryMergeWinding(face1->winding, face2->winding, mapplanes[face1->planenum].normal); if (!neww) return false; // FreeWinding(face1->winding); face1->winding = neww; //remove face2 if (face2->frontarea) AAS_RemoveFaceFromArea(face2, &tmpaasworld.areas[face2->frontarea]); if (face2->backarea) AAS_RemoveFaceFromArea(face2, &tmpaasworld.areas[face2->backarea]); return true; } //end of the function AAS_TryMergeFaces*/ //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void AAS_MergeAreaFaces( void ) { int num_facemerges = 0; int side1, side2, restart; tmp_area_t *tmparea, *lasttmparea; tmp_face_t *face1, *face2; Log_Write( "AAS_MergeAreaFaces\r\n" ); qprintf( "%6d face merges", num_facemerges ); //NOTE: first convex area is a dummy lasttmparea = tmpaasworld.areas; for ( tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next ) { restart = false; // if ( tmparea->invalid ) { continue; } // for ( face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1] ) { side1 = face1->frontarea != tmparea; for ( face2 = face1->next[side1]; face2; face2 = face2->next[side2] ) { side2 = face2->frontarea != tmparea; //if succesfully merged if ( AAS_TryMergeFaces( face1, face2 ) ) { //start over again after merging two faces restart = true; num_facemerges++; qprintf( "\r%6d", num_facemerges ); AAS_CheckArea( tmparea ); break; } //end if } //end for if ( restart ) { tmparea = lasttmparea; break; } //end if } //end for lasttmparea = tmparea; } //end for qprintf( "\n" ); Log_Write( "%6d face merges\r\n", num_facemerges ); } //end of the function AAS_MergeAreaFaces //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void AAS_MergePlaneFaces( tmp_area_t *tmparea, int planenum ) { tmp_face_t *face1, *face2, *nextface2; winding_t *neww; int side1, side2; for ( face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1] ) { side1 = face1->frontarea != tmparea; if ( face1->planenum != planenum ) { continue; } // for ( face2 = face1->next[side1]; face2; face2 = nextface2 ) { side2 = face2->frontarea != tmparea; nextface2 = face2->next[side2]; // if ( ( face2->planenum & ~1 ) != ( planenum & ~1 ) ) { continue; } // neww = MergeWindings( face1->winding, face2->winding, mapplanes[face1->planenum].normal ); FreeWinding( face1->winding ); face1->winding = neww; if ( face2->frontarea ) { AAS_RemoveFaceFromArea( face2, face2->frontarea ); } if ( face2->backarea ) { AAS_RemoveFaceFromArea( face2, face2->backarea ); } AAS_FreeTmpFace( face2 ); // nextface2 = face1->next[side1]; } //end for } //end for } //end of the function AAS_MergePlaneFaces //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int AAS_CanMergePlaneFaces( tmp_area_t *tmparea, int planenum ) { tmp_area_t *frontarea, *backarea; tmp_face_t *face1; int side1, merge, faceflags = 0; // TTimo: init frontarea = backarea = NULL; merge = false; for ( face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1] ) { side1 = face1->frontarea != tmparea; if ( ( face1->planenum & ~1 ) != ( planenum & ~1 ) ) { continue; } if ( !frontarea && !backarea ) { frontarea = face1->frontarea; backarea = face1->backarea; faceflags = face1->faceflags; } //end if else { if ( frontarea != face1->frontarea ) { return false; } if ( backarea != face1->backarea ) { return false; } if ( faceflags != face1->faceflags ) { return false; } merge = true; } //end else } //end for return merge; } //end of the function AAS_CanMergePlaneFaces //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void AAS_MergeAreaPlaneFaces( void ) { int num_facemerges = 0; int side1; tmp_area_t *tmparea, *nexttmparea; tmp_face_t *face1; Log_Write( "AAS_MergePlaneFaces\r\n" ); qprintf( "%6d plane face merges", num_facemerges ); //NOTE: first convex area is a dummy for ( tmparea = tmpaasworld.areas; tmparea; tmparea = nexttmparea ) { nexttmparea = tmparea->l_next; // if ( tmparea->invalid ) { continue; } // for ( face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1] ) { side1 = face1->frontarea != tmparea; // if ( AAS_CanMergePlaneFaces( tmparea, face1->planenum ) ) { AAS_MergePlaneFaces( tmparea, face1->planenum ); nexttmparea = tmparea; num_facemerges++; qprintf( "\r%6d", num_facemerges ); break; } //end if } //end for } //end for qprintf( "\n" ); Log_Write( "%6d plane face merges\r\n", num_facemerges ); } //end of the function AAS_MergeAreaPlaneFaces