00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "qbsp.h"
00024 #include "../botlib/aasfile.h"
00025 #include "aas_create.h"
00026 #include "aas_store.h"
00027
00028 #define CONVEX_EPSILON 0.3
00029
00030
00031
00032
00033
00034
00035
00036 tmp_node_t *AAS_RefreshMergedTree_r(tmp_node_t *tmpnode)
00037 {
00038 tmp_area_t *tmparea;
00039
00040
00041 if (!tmpnode) return NULL;
00042
00043 if (tmpnode->tmparea)
00044 {
00045 tmparea = tmpnode->tmparea;
00046 while(tmparea->mergedarea) tmparea = tmparea->mergedarea;
00047 tmpnode->tmparea = tmparea;
00048 return tmpnode;
00049 }
00050
00051 tmpnode->children[0] = AAS_RefreshMergedTree_r(tmpnode->children[0]);
00052 tmpnode->children[1] = AAS_RefreshMergedTree_r(tmpnode->children[1]);
00053 return tmpnode;
00054 }
00055
00056
00057
00058
00059
00060
00061
00062
00063 int NonConvex(tmp_face_t *face1, tmp_face_t *face2, int side1, int side2)
00064 {
00065 int i;
00066 winding_t *w1, *w2;
00067 plane_t *plane1, *plane2;
00068
00069 w1 = face1->winding;
00070 w2 = face2->winding;
00071
00072 plane1 = &mapplanes[face1->planenum ^ side1];
00073 plane2 = &mapplanes[face2->planenum ^ side2];
00074
00075
00076 for (i = 0; i < w1->numpoints; i++)
00077 {
00078 if (DotProduct(plane2->normal, w1->p[i]) - plane2->dist < -CONVEX_EPSILON) return true;
00079 }
00080
00081 for (i = 0; i < w2->numpoints; i++)
00082 {
00083 if (DotProduct(plane1->normal, w2->p[i]) - plane1->dist < -CONVEX_EPSILON) return true;
00084 }
00085
00086 return false;
00087 }
00088
00089
00090
00091
00092
00093
00094
00095 int AAS_TryMergeFaceAreas(tmp_face_t *seperatingface)
00096 {
00097 int side1, side2, area1faceflags, area2faceflags;
00098 tmp_area_t *tmparea1, *tmparea2, *newarea;
00099 tmp_face_t *face1, *face2, *nextface1, *nextface2;
00100
00101 tmparea1 = seperatingface->frontarea;
00102 tmparea2 = seperatingface->backarea;
00103
00104
00105 if (tmparea1->presencetype != tmparea2->presencetype) return false;
00106
00107 if (tmparea1->contents != tmparea2->contents) return false;
00108
00109 if (tmparea1->modelnum != tmparea2->modelnum) return false;
00110
00111 area1faceflags = 0;
00112 area2faceflags = 0;
00113 for (face1 = tmparea1->tmpfaces; face1; face1 = face1->next[side1])
00114 {
00115 side1 = (face1->frontarea != tmparea1);
00116
00117 if (face1->frontarea != tmparea1 &&
00118 face1->backarea != tmparea1) Error("face does not belong to area1");
00119
00120
00121
00122 if ((face1->frontarea == tmparea1 &&
00123 face1->backarea == tmparea2) ||
00124 (face1->frontarea == tmparea2 &&
00125 face1->backarea == tmparea1)) continue;
00126
00127 area1faceflags |= face1->faceflags;
00128 if (AAS_GapFace(face1, side1)) area1faceflags |= FACE_GAP;
00129
00130 for (face2 = tmparea2->tmpfaces; face2; face2 = face2->next[side2])
00131 {
00132 side2 = (face2->frontarea != tmparea2);
00133
00134 if (face2->frontarea != tmparea2 &&
00135 face2->backarea != tmparea2) Error("face does not belong to area2");
00136
00137
00138
00139 if ((face2->frontarea == tmparea1 &&
00140 face2->backarea == tmparea2) ||
00141 (face2->frontarea == tmparea2 &&
00142 face2->backarea == tmparea1)) continue;
00143
00144 area2faceflags |= face2->faceflags;
00145 if (AAS_GapFace(face2, side2)) area2faceflags |= FACE_GAP;
00146
00147 if (NonConvex(face1, face2, side1, side2)) return false;
00148 }
00149 }
00150
00151
00152
00153 if (((area1faceflags & FACE_GROUND) && (area2faceflags & FACE_GAP)) ||
00154 ((area2faceflags & FACE_GROUND) && (area1faceflags & FACE_GAP)))
00155 {
00156
00157 return false;
00158 }
00159
00160
00161
00162
00163
00164
00165
00166 newarea = AAS_AllocTmpArea();
00167 newarea->presencetype = tmparea1->presencetype;
00168 newarea->contents = tmparea1->contents;
00169 newarea->modelnum = tmparea1->modelnum;
00170 newarea->tmpfaces = NULL;
00171
00172
00173
00174 for (face1 = tmparea1->tmpfaces; face1; face1 = nextface1)
00175 {
00176 side1 = (face1->frontarea != tmparea1);
00177 nextface1 = face1->next[side1];
00178
00179 if ((face1->frontarea == tmparea1 &&
00180 face1->backarea == tmparea2) ||
00181 (face1->frontarea == tmparea2 &&
00182 face1->backarea == tmparea1))
00183 {
00184 continue;
00185 }
00186
00187 AAS_RemoveFaceFromArea(face1, tmparea1);
00188 AAS_AddFaceSideToArea(face1, side1, newarea);
00189 }
00190
00191
00192 for (face2 = tmparea2->tmpfaces; face2; face2 = nextface2)
00193 {
00194 side2 = (face2->frontarea != tmparea2);
00195 nextface2 = face2->next[side2];
00196
00197 if ((face2->frontarea == tmparea1 &&
00198 face2->backarea == tmparea2) ||
00199 (face2->frontarea == tmparea2 &&
00200 face2->backarea == tmparea1))
00201 {
00202 continue;
00203 }
00204
00205 AAS_RemoveFaceFromArea(face2, tmparea2);
00206 AAS_AddFaceSideToArea(face2, side2, newarea);
00207 }
00208
00209 for (face1 = tmparea1->tmpfaces; face1; face1 = nextface1)
00210 {
00211 side1 = (face1->frontarea != tmparea1);
00212 nextface1 = face1->next[side1];
00213
00214 AAS_RemoveFaceFromArea(face1, face1->frontarea);
00215 AAS_RemoveFaceFromArea(face1, face1->backarea);
00216 AAS_FreeTmpFace(face1);
00217 }
00218
00219 tmparea1->mergedarea = newarea;
00220 tmparea1->invalid = true;
00221 tmparea2->mergedarea = newarea;
00222 tmparea2->invalid = true;
00223
00224 AAS_CheckArea(newarea);
00225 AAS_FlipAreaFaces(newarea);
00226
00227 return true;
00228 }
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 int AAS_GroundArea(tmp_area_t *tmparea)
00313 {
00314 tmp_face_t *face;
00315 int side;
00316
00317 for (face = tmparea->tmpfaces; face; face = face->next[side])
00318 {
00319 side = (face->frontarea != tmparea);
00320 if (face->faceflags & FACE_GROUND) return true;
00321 }
00322 return false;
00323 }
00324
00325 void AAS_MergeAreas(void)
00326 {
00327 int side, nummerges, merges, groundfirst;
00328 tmp_area_t *tmparea, *othertmparea;
00329 tmp_face_t *face;
00330
00331 nummerges = 0;
00332 Log_Write("AAS_MergeAreas\r\n");
00333 qprintf("%6d areas merged", 1);
00334
00335 groundfirst = true;
00336
00337 while(1)
00338 {
00339
00340
00341
00342 merges = 0;
00343
00344 for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next)
00345 {
00346
00347 if (tmparea->invalid)
00348 {
00349 continue;
00350 }
00351
00352 if (groundfirst)
00353 {
00354 if (!AAS_GroundArea(tmparea)) continue;
00355 }
00356
00357 for (face = tmparea->tmpfaces; face; face = face->next[side])
00358 {
00359 side = (face->frontarea != tmparea);
00360
00361 if (face->frontarea && face->backarea)
00362 {
00363
00364 if (face->frontarea == tmparea) othertmparea = face->backarea;
00365 else othertmparea = face->frontarea;
00366
00367 if (groundfirst)
00368 {
00369 if (!AAS_GroundArea(othertmparea)) continue;
00370 }
00371 if (AAS_TryMergeFaceAreas(face))
00372 {
00373 qprintf("\r%6d", ++nummerges);
00374 merges++;
00375 break;
00376 }
00377 }
00378 }
00379 }
00380 if (!merges)
00381 {
00382 if (groundfirst) groundfirst = false;
00383 else break;
00384 }
00385 }
00386 qprintf("\n");
00387 Log_Write("%6d areas merged\r\n", nummerges);
00388
00389 AAS_RefreshMergedTree_r(tmpaasworld.nodes);
00390 }