aas_facemerging.c (9058B)
1 /* 2 =========================================================================== 3 Copyright (C) 1999-2005 Id Software, Inc. 4 5 This file is part of Quake III Arena source code. 6 7 Quake III Arena source code is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the License, 10 or (at your option) any later version. 11 12 Quake III Arena source code is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with Foobar; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 =========================================================================== 21 */ 22 23 #include "qbsp.h" 24 #include "../botlib/aasfile.h" 25 #include "aas_create.h" 26 27 //=========================================================================== 28 // 29 // Parameter: - 30 // Returns: - 31 // Changes Globals: - 32 //=========================================================================== 33 int AAS_TryMergeFaces(tmp_face_t *face1, tmp_face_t *face2) 34 { 35 winding_t *neww; 36 37 #ifdef DEBUG 38 if (!face1->winding) Error("face1 %d without winding", face1->num); 39 if (!face2->winding) Error("face2 %d without winding", face2->num); 40 #endif //DEBUG 41 // 42 if (face1->faceflags != face2->faceflags) return false; 43 //NOTE: if the front or back area is zero this doesn't mean there's 44 //a real area. It means there's solid at that side of the face 45 //if both faces have the same front area 46 if (face1->frontarea == face2->frontarea) 47 { 48 //if both faces have the same back area 49 if (face1->backarea == face2->backarea) 50 { 51 //if the faces are in the same plane 52 if (face1->planenum == face2->planenum) 53 { 54 //if they have both a front and a back area (no solid on either side) 55 if (face1->frontarea && face1->backarea) 56 { 57 neww = MergeWindings(face1->winding, face2->winding, 58 mapplanes[face1->planenum].normal); 59 } //end if 60 else 61 { 62 //this function is to be found in l_poly.c 63 neww = TryMergeWinding(face1->winding, face2->winding, 64 mapplanes[face1->planenum].normal); 65 } //end else 66 if (neww) 67 { 68 FreeWinding(face1->winding); 69 face1->winding = neww; 70 if (face2->frontarea) AAS_RemoveFaceFromArea(face2, face2->frontarea); 71 if (face2->backarea) AAS_RemoveFaceFromArea(face2, face2->backarea); 72 AAS_FreeTmpFace(face2); 73 return true; 74 } //end if 75 } //end if 76 else if ((face1->planenum & ~1) == (face2->planenum & ~1)) 77 { 78 Log_Write("face %d and %d, same front and back area but flipped planes\r\n", 79 face1->num, face2->num); 80 } //end if 81 } //end if 82 } //end if 83 return false; 84 } //end of the function AAS_TryMergeFaces 85 /* 86 int AAS_TryMergeFaces(tmp_face_t *face1, tmp_face_t *face2) 87 { 88 winding_t *neww; 89 90 #ifdef DEBUG 91 if (!face1->winding) Error("face1 %d without winding", face1->num); 92 if (!face2->winding) Error("face2 %d without winding", face2->num); 93 #endif //DEBUG 94 //if the faces are in the same plane 95 if ((face1->planenum & ~1) != (face2->planenum & ~1)) return false; 96 // if (face1->planenum != face2->planenum) return false; 97 //NOTE: if the front or back area is zero this doesn't mean there's 98 //a real area. It means there's solid at that side of the face 99 //if both faces have the same front area 100 if (face1->frontarea != face2->frontarea || 101 face1->backarea != face2->backarea) 102 { 103 if (!face1->frontarea || !face1->backarea || 104 !face2->frontarea || !face2->backarea) return false; 105 else if (face1->frontarea != face2->backarea || 106 face1->backarea != face2->frontarea) return false; 107 // return false; 108 } //end if 109 //this function is to be found in l_poly.c 110 neww = TryMergeWinding(face1->winding, face2->winding, 111 mapplanes[face1->planenum].normal); 112 if (!neww) return false; 113 // 114 FreeWinding(face1->winding); 115 face1->winding = neww; 116 //remove face2 117 if (face2->frontarea) 118 AAS_RemoveFaceFromArea(face2, &tmpaasworld.areas[face2->frontarea]); 119 if (face2->backarea) 120 AAS_RemoveFaceFromArea(face2, &tmpaasworld.areas[face2->backarea]); 121 return true; 122 } //end of the function AAS_TryMergeFaces*/ 123 //=========================================================================== 124 // 125 // Parameter: - 126 // Returns: - 127 // Changes Globals: - 128 //=========================================================================== 129 void AAS_MergeAreaFaces(void) 130 { 131 int num_facemerges = 0; 132 int side1, side2, restart; 133 tmp_area_t *tmparea, *lasttmparea; 134 tmp_face_t *face1, *face2; 135 136 Log_Write("AAS_MergeAreaFaces\r\n"); 137 qprintf("%6d face merges", num_facemerges); 138 //NOTE: first convex area is a dummy 139 lasttmparea = tmpaasworld.areas; 140 for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next) 141 { 142 restart = false; 143 // 144 if (tmparea->invalid) continue; 145 // 146 for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1]) 147 { 148 side1 = face1->frontarea != tmparea; 149 for (face2 = face1->next[side1]; face2; face2 = face2->next[side2]) 150 { 151 side2 = face2->frontarea != tmparea; 152 //if succesfully merged 153 if (AAS_TryMergeFaces(face1, face2)) 154 { 155 //start over again after merging two faces 156 restart = true; 157 num_facemerges++; 158 qprintf("\r%6d", num_facemerges); 159 AAS_CheckArea(tmparea); 160 break; 161 } //end if 162 } //end for 163 if (restart) 164 { 165 tmparea = lasttmparea; 166 break; 167 } //end if 168 } //end for 169 lasttmparea = tmparea; 170 } //end for 171 qprintf("\n"); 172 Log_Write("%6d face merges\r\n", num_facemerges); 173 } //end of the function AAS_MergeAreaFaces 174 //=========================================================================== 175 // 176 // Parameter: - 177 // Returns: - 178 // Changes Globals: - 179 //=========================================================================== 180 void AAS_MergePlaneFaces(tmp_area_t *tmparea, int planenum) 181 { 182 tmp_face_t *face1, *face2, *nextface2; 183 winding_t *neww; 184 int side1, side2; 185 186 for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1]) 187 { 188 side1 = face1->frontarea != tmparea; 189 if (face1->planenum != planenum) continue; 190 // 191 for (face2 = face1->next[side1]; face2; face2 = nextface2) 192 { 193 side2 = face2->frontarea != tmparea; 194 nextface2 = face2->next[side2]; 195 // 196 if ((face2->planenum & ~1) != (planenum & ~1)) continue; 197 // 198 neww = MergeWindings(face1->winding, face2->winding, 199 mapplanes[face1->planenum].normal); 200 FreeWinding(face1->winding); 201 face1->winding = neww; 202 if (face2->frontarea) AAS_RemoveFaceFromArea(face2, face2->frontarea); 203 if (face2->backarea) AAS_RemoveFaceFromArea(face2, face2->backarea); 204 AAS_FreeTmpFace(face2); 205 // 206 nextface2 = face1->next[side1]; 207 } //end for 208 } //end for 209 } //end of the function AAS_MergePlaneFaces 210 //=========================================================================== 211 // 212 // Parameter: - 213 // Returns: - 214 // Changes Globals: - 215 //=========================================================================== 216 int AAS_CanMergePlaneFaces(tmp_area_t *tmparea, int planenum) 217 { 218 tmp_area_t *frontarea, *backarea; 219 tmp_face_t *face1; 220 int side1, merge, faceflags; 221 222 frontarea = backarea = NULL; 223 merge = false; 224 for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1]) 225 { 226 side1 = face1->frontarea != tmparea; 227 if ((face1->planenum & ~1) != (planenum & ~1)) continue; 228 if (!frontarea && !backarea) 229 { 230 frontarea = face1->frontarea; 231 backarea = face1->backarea; 232 faceflags = face1->faceflags; 233 } //end if 234 else 235 { 236 if (frontarea != face1->frontarea) return false; 237 if (backarea != face1->backarea) return false; 238 if (faceflags != face1->faceflags) return false; 239 merge = true; 240 } //end else 241 } //end for 242 return merge; 243 } //end of the function AAS_CanMergePlaneFaces 244 //=========================================================================== 245 // 246 // Parameter: - 247 // Returns: - 248 // Changes Globals: - 249 //=========================================================================== 250 void AAS_MergeAreaPlaneFaces(void) 251 { 252 int num_facemerges = 0; 253 int side1; 254 tmp_area_t *tmparea, *nexttmparea; 255 tmp_face_t *face1; 256 257 Log_Write("AAS_MergePlaneFaces\r\n"); 258 qprintf("%6d plane face merges", num_facemerges); 259 //NOTE: first convex area is a dummy 260 for (tmparea = tmpaasworld.areas; tmparea; tmparea = nexttmparea) 261 { 262 nexttmparea = tmparea->l_next; 263 // 264 if (tmparea->invalid) continue; 265 // 266 for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1]) 267 { 268 side1 = face1->frontarea != tmparea; 269 // 270 if (AAS_CanMergePlaneFaces(tmparea, face1->planenum)) 271 { 272 AAS_MergePlaneFaces(tmparea, face1->planenum); 273 nexttmparea = tmparea; 274 num_facemerges++; 275 qprintf("\r%6d", num_facemerges); 276 break; 277 } //end if 278 } //end for 279 } //end for 280 qprintf("\n"); 281 Log_Write("%6d plane face merges\r\n", num_facemerges); 282 } //end of the function AAS_MergeAreaPlaneFaces