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 #include "aas_gsubdiv.h"
00028 #include "aas_facemerging.h"
00029 #include "aas_areamerging.h"
00030 #include "aas_edgemelting.h"
00031 #include "aas_prunenodes.h"
00032 #include "aas_cfg.h"
00033 #include "../game/surfaceflags.h"
00034
00035
00036
00037
00038 #define AREAONFACESIDE(face, area) (face->frontarea != area)
00039
00040 tmp_aas_t tmpaasworld;
00041
00042
00043
00044
00045
00046
00047
00048 void AAS_InitTmpAAS(void)
00049 {
00050
00051 tmpaasworld.numfaces = 0;
00052 tmpaasworld.facenum = 0;
00053 tmpaasworld.faces = NULL;
00054
00055 tmpaasworld.numareas = 0;
00056 tmpaasworld.areanum = 0;
00057 tmpaasworld.areas = NULL;
00058
00059 tmpaasworld.numnodes = 0;
00060 tmpaasworld.nodes = NULL;
00061
00062 tmpaasworld.nodebuffer = NULL;
00063 }
00064
00065
00066
00067
00068
00069
00070 void AAS_FreeTmpAAS(void)
00071 {
00072 tmp_face_t *f, *nextf;
00073 tmp_area_t *a, *nexta;
00074 tmp_nodebuf_t *nb, *nextnb;
00075
00076
00077 for (f = tmpaasworld.faces; f; f = nextf)
00078 {
00079 nextf = f->l_next;
00080 if (f->winding) FreeWinding(f->winding);
00081 FreeMemory(f);
00082 }
00083
00084 for (a = tmpaasworld.areas; a; a = nexta)
00085 {
00086 nexta = a->l_next;
00087 if (a->settings) FreeMemory(a->settings);
00088 FreeMemory(a);
00089 }
00090
00091 for (nb = tmpaasworld.nodebuffer; nb; nb = nextnb)
00092 {
00093 nextnb = nb->next;
00094 FreeMemory(nb);
00095 }
00096 }
00097
00098
00099
00100
00101
00102
00103 tmp_face_t *AAS_AllocTmpFace(void)
00104 {
00105 tmp_face_t *tmpface;
00106
00107 tmpface = (tmp_face_t *) GetClearedMemory(sizeof(tmp_face_t));
00108 tmpface->num = tmpaasworld.facenum++;
00109 tmpface->l_prev = NULL;
00110 tmpface->l_next = tmpaasworld.faces;
00111 if (tmpaasworld.faces) tmpaasworld.faces->l_prev = tmpface;
00112 tmpaasworld.faces = tmpface;
00113 tmpaasworld.numfaces++;
00114 return tmpface;
00115 }
00116
00117
00118
00119
00120
00121
00122 void AAS_FreeTmpFace(tmp_face_t *tmpface)
00123 {
00124 if (tmpface->l_next) tmpface->l_next->l_prev = tmpface->l_prev;
00125 if (tmpface->l_prev) tmpface->l_prev->l_next = tmpface->l_next;
00126 else tmpaasworld.faces = tmpface->l_next;
00127
00128 if (tmpface->winding) FreeWinding(tmpface->winding);
00129
00130 FreeMemory(tmpface);
00131 tmpaasworld.numfaces--;
00132 }
00133
00134
00135
00136
00137
00138
00139 tmp_area_t *AAS_AllocTmpArea(void)
00140 {
00141 tmp_area_t *tmparea;
00142
00143 tmparea = (tmp_area_t *) GetClearedMemory(sizeof(tmp_area_t));
00144 tmparea->areanum = tmpaasworld.areanum++;
00145 tmparea->l_prev = NULL;
00146 tmparea->l_next = tmpaasworld.areas;
00147 if (tmpaasworld.areas) tmpaasworld.areas->l_prev = tmparea;
00148 tmpaasworld.areas = tmparea;
00149 tmpaasworld.numareas++;
00150 return tmparea;
00151 }
00152
00153
00154
00155
00156
00157
00158 void AAS_FreeTmpArea(tmp_area_t *tmparea)
00159 {
00160 if (tmparea->l_next) tmparea->l_next->l_prev = tmparea->l_prev;
00161 if (tmparea->l_prev) tmparea->l_prev->l_next = tmparea->l_next;
00162 else tmpaasworld.areas = tmparea->l_next;
00163 if (tmparea->settings) FreeMemory(tmparea->settings);
00164 FreeMemory(tmparea);
00165 tmpaasworld.numareas--;
00166 }
00167
00168
00169
00170
00171
00172
00173 tmp_node_t *AAS_AllocTmpNode(void)
00174 {
00175 tmp_nodebuf_t *nodebuf;
00176
00177 if (!tmpaasworld.nodebuffer ||
00178 tmpaasworld.nodebuffer->numnodes >= NODEBUF_SIZE)
00179 {
00180 nodebuf = (tmp_nodebuf_t *) GetClearedMemory(sizeof(tmp_nodebuf_t));
00181 nodebuf->next = tmpaasworld.nodebuffer;
00182 nodebuf->numnodes = 0;
00183 tmpaasworld.nodebuffer = nodebuf;
00184 }
00185 tmpaasworld.numnodes++;
00186 return &tmpaasworld.nodebuffer->nodes[tmpaasworld.nodebuffer->numnodes++];
00187 }
00188
00189
00190
00191
00192
00193
00194 void AAS_FreeTmpNode(tmp_node_t *tmpnode)
00195 {
00196 tmpaasworld.numnodes--;
00197 }
00198
00199
00200
00201
00202
00203
00204
00205 int AAS_GapFace(tmp_face_t *tmpface, int side)
00206 {
00207 vec3_t invgravity;
00208
00209
00210 if (tmpface->faceflags & (FACE_GROUND | FACE_SOLID)) return 0;
00211
00212 VectorCopy(cfg.phys_gravitydirection, invgravity);
00213 VectorInverse(invgravity);
00214
00215 return (DotProduct(invgravity, mapplanes[tmpface->planenum ^ side].normal) > cfg.phys_maxsteepness);
00216 }
00217
00218
00219
00220
00221
00222
00223
00224 int AAS_GroundFace(tmp_face_t *tmpface)
00225 {
00226 vec3_t invgravity;
00227
00228
00229 if (!(tmpface->faceflags & FACE_SOLID)) return 0;
00230
00231 VectorCopy(cfg.phys_gravitydirection, invgravity);
00232 VectorInverse(invgravity);
00233
00234 return (DotProduct(invgravity, mapplanes[tmpface->planenum].normal) > cfg.phys_maxsteepness);
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 void AAS_AddFaceSideToArea(tmp_face_t *tmpface, int side, tmp_area_t *tmparea)
00247 {
00248 int tmpfaceside;
00249
00250 if (side)
00251 {
00252 if (tmpface->backarea) Error("AAS_AddFaceSideToArea: already a back area\n");
00253 }
00254 else
00255 {
00256 if (tmpface->frontarea) Error("AAS_AddFaceSideToArea: already a front area\n");
00257 }
00258
00259 if (side) tmpface->backarea = tmparea;
00260 else tmpface->frontarea = tmparea;
00261
00262 if (tmparea->tmpfaces)
00263 {
00264 tmpfaceside = tmparea->tmpfaces->frontarea != tmparea;
00265 tmparea->tmpfaces->prev[tmpfaceside] = tmpface;
00266 }
00267 tmpface->next[side] = tmparea->tmpfaces;
00268 tmpface->prev[side] = NULL;
00269 tmparea->tmpfaces = tmpface;
00270 }
00271
00272
00273
00274
00275
00276
00277
00278 void AAS_RemoveFaceFromArea(tmp_face_t *tmpface, tmp_area_t *tmparea)
00279 {
00280 int side, prevside, nextside;
00281
00282 if (tmpface->frontarea != tmparea &&
00283 tmpface->backarea != tmparea)
00284 {
00285 Error("AAS_RemoveFaceFromArea: face not part of the area");
00286 }
00287 side = tmpface->frontarea != tmparea;
00288 if (tmpface->prev[side])
00289 {
00290 prevside = tmpface->prev[side]->frontarea != tmparea;
00291 tmpface->prev[side]->next[prevside] = tmpface->next[side];
00292 }
00293 else
00294 {
00295 tmparea->tmpfaces = tmpface->next[side];
00296 }
00297 if (tmpface->next[side])
00298 {
00299 nextside = tmpface->next[side]->frontarea != tmparea;
00300 tmpface->next[side]->prev[nextside] = tmpface->prev[side];
00301 }
00302
00303 if (side) tmpface->backarea = NULL;
00304 else tmpface->frontarea = NULL;
00305 tmpface->prev[side] = NULL;
00306 tmpface->next[side] = NULL;
00307 }
00308
00309
00310
00311
00312
00313
00314 void AAS_CheckArea(tmp_area_t *tmparea)
00315 {
00316 int side;
00317 tmp_face_t *face;
00318 plane_t *plane;
00319 vec3_t wcenter, acenter = {0, 0, 0};
00320 vec3_t normal;
00321 float n, dist;
00322
00323 if (tmparea->invalid) Log_Print("AAS_CheckArea: invalid area\n");
00324 for (n = 0, face = tmparea->tmpfaces; face; face = face->next[side])
00325 {
00326
00327 side = face->frontarea != tmparea;
00328 WindingCenter(face->winding, wcenter);
00329 VectorAdd(acenter, wcenter, acenter);
00330 n++;
00331 }
00332 n = 1 / n;
00333 VectorScale(acenter, n, acenter);
00334 for (face = tmparea->tmpfaces; face; face = face->next[side])
00335 {
00336
00337 side = face->frontarea != tmparea;
00338
00339 #ifdef L_DEBUG
00340 if (WindingError(face->winding))
00341 {
00342 Log_Write("AAS_CheckArea: area %d face %d: %s\r\n", tmparea->areanum,
00343 face->num, WindingErrorString());
00344 }
00345 #endif L_DEBUG
00346
00347 plane = &mapplanes[face->planenum ^ side];
00348
00349 if (DotProduct(plane->normal, acenter) - plane->dist < 0)
00350 {
00351 Log_Print("AAS_CheckArea: area %d face %d is flipped\n", tmparea->areanum, face->num);
00352 Log_Print("AAS_CheckArea: area %d center is %f %f %f\n", tmparea->areanum, acenter[0], acenter[1], acenter[2]);
00353 }
00354
00355 WindingPlane(face->winding, normal, &dist);
00356 plane = &mapplanes[face->planenum];
00357 #ifdef L_DEBUG
00358 if (fabs(dist - plane->dist) > 0.4 ||
00359 fabs(normal[0] - plane->normal[0]) > 0.0001 ||
00360 fabs(normal[1] - plane->normal[1]) > 0.0001 ||
00361 fabs(normal[2] - plane->normal[2]) > 0.0001)
00362 {
00363 Log_Write("AAS_CheckArea: area %d face %d winding plane unequal to face plane\r\n",
00364 tmparea->areanum, face->num);
00365 }
00366 #endif L_DEBUG
00367 }
00368 }
00369
00370
00371
00372
00373
00374
00375 void AAS_CheckFaceWindingPlane(tmp_face_t *face)
00376 {
00377 float dist, sign1, sign2;
00378 vec3_t normal;
00379 plane_t *plane;
00380 winding_t *w;
00381
00382
00383 WindingPlane(face->winding, normal, &dist);
00384 plane = &mapplanes[face->planenum];
00385
00386 sign1 = DotProduct(plane->normal, normal);
00387
00388 if (fabs(dist - plane->dist) > 0.4 ||
00389 fabs(normal[0] - plane->normal[0]) > 0.0001 ||
00390 fabs(normal[1] - plane->normal[1]) > 0.0001 ||
00391 fabs(normal[2] - plane->normal[2]) > 0.0001)
00392 {
00393 VectorInverse(normal);
00394 dist = -dist;
00395 if (fabs(dist - plane->dist) > 0.4 ||
00396 fabs(normal[0] - plane->normal[0]) > 0.0001 ||
00397 fabs(normal[1] - plane->normal[1]) > 0.0001 ||
00398 fabs(normal[2] - plane->normal[2]) > 0.0001)
00399 {
00400 Log_Write("AAS_CheckFaceWindingPlane: face %d winding plane unequal to face plane\r\n",
00401 face->num);
00402
00403 sign2 = DotProduct(plane->normal, normal);
00404 if ((sign1 < 0 && sign2 > 0) ||
00405 (sign1 > 0 && sign2 < 0))
00406 {
00407 Log_Write("AAS_CheckFaceWindingPlane: face %d winding reversed\r\n",
00408 face->num);
00409 w = face->winding;
00410 face->winding = ReverseWinding(w);
00411 FreeWinding(w);
00412 }
00413 }
00414 else
00415 {
00416 Log_Write("AAS_CheckFaceWindingPlane: face %d winding reversed\r\n",
00417 face->num);
00418 w = face->winding;
00419 face->winding = ReverseWinding(w);
00420 FreeWinding(w);
00421 }
00422 }
00423 }
00424
00425
00426
00427
00428
00429
00430 void AAS_CheckAreaWindingPlanes(void)
00431 {
00432 int side;
00433 tmp_area_t *tmparea;
00434 tmp_face_t *face;
00435
00436 Log_Write("AAS_CheckAreaWindingPlanes:\r\n");
00437 for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next)
00438 {
00439 if (tmparea->invalid) continue;
00440 for (face = tmparea->tmpfaces; face; face = face->next[side])
00441 {
00442 side = face->frontarea != tmparea;
00443 AAS_CheckFaceWindingPlane(face);
00444 }
00445 }
00446 }
00447
00448
00449
00450
00451
00452
00453 void AAS_FlipAreaFaces(tmp_area_t *tmparea)
00454 {
00455 int side;
00456 tmp_face_t *face;
00457 plane_t *plane;
00458 vec3_t wcenter, acenter = {0, 0, 0};
00459
00460 float n;
00461
00462 for (n = 0, face = tmparea->tmpfaces; face; face = face->next[side])
00463 {
00464 if (!face->frontarea) Error("face %d has no front area\n", face->num);
00465
00466 side = face->frontarea != tmparea;
00467 WindingCenter(face->winding, wcenter);
00468 VectorAdd(acenter, wcenter, acenter);
00469 n++;
00470 }
00471 n = 1 / n;
00472 VectorScale(acenter, n, acenter);
00473 for (face = tmparea->tmpfaces; face; face = face->next[side])
00474 {
00475
00476 side = face->frontarea != tmparea;
00477
00478 plane = &mapplanes[face->planenum ^ side];
00479
00480 if (DotProduct(plane->normal, acenter) - plane->dist < 0)
00481 {
00482 Log_Print("area %d face %d flipped: front area %d, back area %d\n", tmparea->areanum, face->num,
00483 face->frontarea ? face->frontarea->areanum : 0,
00484 face->backarea ? face->backarea->areanum : 0);
00485
00486
00487
00488
00489
00490
00491 }
00492 #ifdef L_DEBUG
00493 {
00494 float dist;
00495 vec3_t normal;
00496
00497
00498 WindingPlane(face->winding, normal, &dist);
00499 plane = &mapplanes[face->planenum];
00500 if (fabs(dist - plane->dist) > 0.4 ||
00501 fabs(normal[0] - plane->normal[0]) > 0.0001 ||
00502 fabs(normal[1] - plane->normal[1]) > 0.0001 ||
00503 fabs(normal[2] - plane->normal[2]) > 0.0001)
00504 {
00505 Log_Write("area %d face %d winding plane unequal to face plane\r\n",
00506 tmparea->areanum, face->num);
00507 }
00508 }
00509 #endif
00510 }
00511 }
00512
00513
00514
00515
00516
00517
00518 void AAS_RemoveAreaFaceColinearPoints(void)
00519 {
00520 int side;
00521 tmp_face_t *face;
00522 tmp_area_t *tmparea;
00523
00524
00525 for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next)
00526 {
00527 for (face = tmparea->tmpfaces; face; face = face->next[side])
00528 {
00529 side = face->frontarea != tmparea;
00530 RemoveColinearPoints(face->winding);
00531
00532 }
00533 }
00534 }
00535
00536
00537
00538
00539
00540
00541 void AAS_RemoveTinyFaces(void)
00542 {
00543 int side, num;
00544 tmp_face_t *face, *nextface;
00545 tmp_area_t *tmparea;
00546
00547
00548 Log_Write("AAS_RemoveTinyFaces\r\n");
00549 num = 0;
00550 for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next)
00551 {
00552 for (face = tmparea->tmpfaces; face; face = nextface)
00553 {
00554 side = face->frontarea != tmparea;
00555 nextface = face->next[side];
00556
00557 if (WindingArea(face->winding) < 1)
00558 {
00559 if (face->frontarea) AAS_RemoveFaceFromArea(face, face->frontarea);
00560 if (face->backarea) AAS_RemoveFaceFromArea(face, face->backarea);
00561 AAS_FreeTmpFace(face);
00562
00563 num++;
00564 }
00565 }
00566 }
00567 Log_Write("%d tiny faces removed\r\n", num);
00568 }
00569
00570
00571
00572
00573
00574
00575 void AAS_CreateAreaSettings(void)
00576 {
00577 int i, flags, side, numgrounded, numladderareas, numliquidareas;
00578 tmp_face_t *face;
00579 tmp_area_t *tmparea;
00580
00581 numgrounded = 0;
00582 numladderareas = 0;
00583 numliquidareas = 0;
00584 Log_Write("AAS_CreateAreaSettings\r\n");
00585 i = 0;
00586 qprintf("%6d areas provided with settings", i);
00587 for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next)
00588 {
00589
00590 if (tmparea->invalid) continue;
00591
00592 tmparea->settings = (tmp_areasettings_t *) GetClearedMemory(sizeof(tmp_areasettings_t));
00593 tmparea->settings->contents = tmparea->contents;
00594 tmparea->settings->modelnum = tmparea->modelnum;
00595 flags = 0;
00596 for (face = tmparea->tmpfaces; face; face = face->next[side])
00597 {
00598 side = face->frontarea != tmparea;
00599 flags |= face->faceflags;
00600 }
00601 tmparea->settings->areaflags = 0;
00602 if (flags & FACE_GROUND)
00603 {
00604 tmparea->settings->areaflags |= AREA_GROUNDED;
00605 numgrounded++;
00606 }
00607 if (flags & FACE_LADDER)
00608 {
00609 tmparea->settings->areaflags |= AREA_LADDER;
00610 numladderareas++;
00611 }
00612 if (tmparea->contents & (AREACONTENTS_WATER |
00613 AREACONTENTS_SLIME |
00614 AREACONTENTS_LAVA))
00615 {
00616 tmparea->settings->areaflags |= AREA_LIQUID;
00617 numliquidareas++;
00618 }
00619
00620 tmparea->settings->presencetype = tmparea->presencetype;
00621
00622 qprintf("\r%6d", ++i);
00623 }
00624 qprintf("\n");
00625 #ifdef AASINFO
00626 Log_Print("%6d grounded areas\n", numgrounded);
00627 Log_Print("%6d ladder areas\n", numladderareas);
00628 Log_Print("%6d liquid areas\n", numliquidareas);
00629 #endif //AASINFO
00630 }
00631
00632
00633
00634
00635
00636
00637
00638 tmp_node_t *AAS_CreateArea(node_t *node)
00639 {
00640 int pside;
00641 int areafaceflags;
00642 portal_t *p;
00643 tmp_face_t *tmpface;
00644 tmp_area_t *tmparea;
00645 tmp_node_t *tmpnode;
00646 vec3_t up = {0, 0, 1};
00647
00648
00649 tmparea = AAS_AllocTmpArea();
00650 tmparea->tmpfaces = NULL;
00651
00652 areafaceflags = 0;
00653
00654 for (p = node->portals; p; p = p->next[pside])
00655 {
00656 pside = (p->nodes[1] == node);
00657
00658
00659
00660 if (p->tmpface)
00661 {
00662
00663 AAS_AddFaceSideToArea(p->tmpface, 1, tmparea);
00664 }
00665 else
00666 {
00667 tmpface = AAS_AllocTmpFace();
00668
00669
00670 p->tmpface = tmpface;
00671
00672
00673 tmpface->planenum = p->planenum ^ pside;
00674 if (pside) tmpface->winding = ReverseWinding(p->winding);
00675 else tmpface->winding = CopyWinding(p->winding);
00676 #ifdef L_DEBUG
00677
00678 AAS_CheckFaceWindingPlane(tmpface);
00679 #endif //L_DEBUG
00680
00681 if (p->nodes[!pside]->contents & (CONTENTS_SOLID | CONTENTS_PLAYERCLIP))
00682 {
00683 tmpface->faceflags |= FACE_SOLID;
00684 }
00685
00686
00687 else if (node->contents & (CONTENTS_WATER|CONTENTS_SLIME|CONTENTS_LAVA))
00688 {
00689 tmpface->faceflags |= FACE_LIQUID;
00690
00691 if (!(p->nodes[!pside]->contents & (CONTENTS_WATER|CONTENTS_SLIME|CONTENTS_LAVA)))
00692 {
00693 tmpface->faceflags |= FACE_LIQUIDSURFACE;
00694 }
00695 }
00696
00697 if ((p->nodes[pside]->contents & CONTENTS_LADDER) ||
00698 (p->nodes[!pside]->contents & CONTENTS_LADDER))
00699 {
00700
00701
00702
00703
00704
00705
00706
00707
00708 tmpface->faceflags |= FACE_LADDER;
00709 }
00710
00711 if (AAS_GroundFace(tmpface))
00712 {
00713 tmpface->faceflags |= FACE_GROUND;
00714 }
00715
00716 areafaceflags |= tmpface->faceflags;
00717
00718 tmpface->aasfacenum = 0;
00719
00720 AAS_AddFaceSideToArea(tmpface, 0, tmparea);
00721 }
00722 }
00723 qprintf("\r%6d", tmparea->areanum);
00724
00725 tmparea->presencetype = ~node->expansionbboxes & cfg.allpresencetypes;
00726
00727 tmparea->contents = 0;
00728 if (node->contents & CONTENTS_CLUSTERPORTAL) tmparea->contents |= AREACONTENTS_CLUSTERPORTAL;
00729 if (node->contents & CONTENTS_MOVER) tmparea->contents |= AREACONTENTS_MOVER;
00730 if (node->contents & CONTENTS_TELEPORTER) tmparea->contents |= AREACONTENTS_TELEPORTER;
00731 if (node->contents & CONTENTS_JUMPPAD) tmparea->contents |= AREACONTENTS_JUMPPAD;
00732 if (node->contents & CONTENTS_DONOTENTER) tmparea->contents |= AREACONTENTS_DONOTENTER;
00733 if (node->contents & CONTENTS_WATER) tmparea->contents |= AREACONTENTS_WATER;
00734 if (node->contents & CONTENTS_LAVA) tmparea->contents |= AREACONTENTS_LAVA;
00735 if (node->contents & CONTENTS_SLIME) tmparea->contents |= AREACONTENTS_SLIME;
00736 if (node->contents & CONTENTS_NOTTEAM1) tmparea->contents |= AREACONTENTS_NOTTEAM1;
00737 if (node->contents & CONTENTS_NOTTEAM2) tmparea->contents |= AREACONTENTS_NOTTEAM2;
00738
00739
00740 tmparea->modelnum = node->modelnum;
00741
00742 AAS_FlipAreaFaces(tmparea);
00743
00744 AAS_CheckArea(tmparea);
00745
00746 tmpnode = AAS_AllocTmpNode();
00747 tmpnode->planenum = 0;
00748 tmpnode->children[0] = 0;
00749 tmpnode->children[1] = 0;
00750 tmpnode->tmparea = tmparea;
00751
00752 return tmpnode;
00753 }
00754
00755
00756
00757
00758
00759
00760 tmp_node_t *AAS_CreateAreas_r(node_t *node)
00761 {
00762 tmp_node_t *tmpnode;
00763
00764
00765 if (node->planenum != PLANENUM_LEAF)
00766 {
00767
00768 tmpnode = AAS_AllocTmpNode();
00769 tmpnode->planenum = node->planenum;
00770 tmpnode->children[0] = AAS_CreateAreas_r(node->children[0]);
00771 tmpnode->children[1] = AAS_CreateAreas_r(node->children[1]);
00772 return tmpnode;
00773 }
00774
00775 if (node->contents & CONTENTS_SOLID)
00776 {
00777
00778 return NULL;
00779 }
00780
00781 return AAS_CreateArea(node);
00782 }
00783
00784
00785
00786
00787
00788
00789 void AAS_CreateAreas(node_t *node)
00790 {
00791 Log_Write("AAS_CreateAreas\r\n");
00792 qprintf("%6d areas created", 0);
00793 tmpaasworld.nodes = AAS_CreateAreas_r(node);
00794 qprintf("\n");
00795 Log_Write("%6d areas created\r\n", tmpaasworld.numareas);
00796 }
00797
00798
00799
00800
00801
00802
00803 void AAS_PrintNumGroundFaces(void)
00804 {
00805 tmp_face_t *tmpface;
00806 int numgroundfaces = 0;
00807
00808 for (tmpface = tmpaasworld.faces; tmpface; tmpface = tmpface->l_next)
00809 {
00810 if (tmpface->faceflags & FACE_GROUND)
00811 {
00812 numgroundfaces++;
00813 }
00814 }
00815 qprintf("%6d ground faces\n", numgroundfaces);
00816 }
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827 void AAS_CheckAreaSharedFaces(tmp_area_t *tmparea1, tmp_area_t *tmparea2)
00828 {
00829 int numsharedfaces, side;
00830 tmp_face_t *face1, *sharedface;
00831
00832 if (tmparea1->invalid || tmparea2->invalid) return;
00833
00834 sharedface = NULL;
00835 numsharedfaces = 0;
00836 for (face1 = tmparea1->tmpfaces; face1; face1 = face1->next[side])
00837 {
00838 side = face1->frontarea != tmparea1;
00839 if (face1->backarea == tmparea2 || face1->frontarea == tmparea2)
00840 {
00841 sharedface = face1;
00842 numsharedfaces++;
00843 }
00844 }
00845 if (!sharedface) return;
00846
00847 if (numsharedfaces > 1)
00848 {
00849 Log_Write("---- tmp area %d and %d have %d shared faces\r\n",
00850 tmparea1->areanum, tmparea2->areanum, numsharedfaces);
00851 for (face1 = tmparea1->tmpfaces; face1; face1 = face1->next[side])
00852 {
00853 side = face1->frontarea != tmparea1;
00854 if (face1->backarea == tmparea2 || face1->frontarea == tmparea2)
00855 {
00856 Log_Write("face %d, planenum = %d, face->frontarea = %d face->backarea = %d\r\n",
00857 face1->num, face1->planenum, face1->frontarea->areanum, face1->backarea->areanum);
00858 }
00859 }
00860 }
00861 }
00862
00863
00864
00865
00866
00867
00868 void AAS_CheckSharedFaces(void)
00869 {
00870 tmp_area_t *tmparea1, *tmparea2;
00871
00872 for (tmparea1 = tmpaasworld.areas; tmparea1; tmparea1 = tmparea1->l_next)
00873 {
00874 for (tmparea2 = tmpaasworld.areas; tmparea2; tmparea2 = tmparea2->l_next)
00875 {
00876 if (tmparea1 == tmparea2) continue;
00877 AAS_CheckAreaSharedFaces(tmparea1, tmparea2);
00878 }
00879 }
00880 }
00881
00882
00883
00884
00885
00886
00887 void AAS_FlipFace(tmp_face_t *face)
00888 {
00889 tmp_area_t *frontarea, *backarea;
00890 winding_t *w;
00891
00892 frontarea = face->frontarea;
00893 backarea = face->backarea;
00894
00895 if (!frontarea || !backarea) return;
00896
00897 w = face->winding;
00898 face->winding = ReverseWinding(w);
00899 FreeWinding(w);
00900
00901 face->planenum ^= 1;
00902
00903 AAS_RemoveFaceFromArea(face, frontarea);
00904 AAS_RemoveFaceFromArea(face, backarea);
00905 AAS_AddFaceSideToArea(face, 1, frontarea);
00906 AAS_AddFaceSideToArea(face, 0, backarea);
00907 }
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992 void AAS_FlipSharedFaces(void)
00993 {
00994 int i, side1, side2;
00995 tmp_area_t *tmparea1;
00996 tmp_face_t *face1, *face2;
00997
00998 i = 0;
00999 qprintf("%6d areas checked for shared face flipping", i);
01000 for (tmparea1 = tmpaasworld.areas; tmparea1; tmparea1 = tmparea1->l_next)
01001 {
01002 if (tmparea1->invalid) continue;
01003 for (face1 = tmparea1->tmpfaces; face1; face1 = face1->next[side1])
01004 {
01005 side1 = face1->frontarea != tmparea1;
01006 if (!face1->frontarea || !face1->backarea) continue;
01007
01008 for (face2 = face1->next[side1]; face2; face2 = face2->next[side2])
01009 {
01010 side2 = face2->frontarea != tmparea1;
01011 if (!face2->frontarea || !face2->backarea) continue;
01012
01013 if (face1->frontarea == face2->backarea &&
01014 face1->backarea == face2->frontarea)
01015 {
01016 AAS_FlipFace(face2);
01017 }
01018
01019 side2 = face2->frontarea != tmparea1;
01020 }
01021 }
01022 qprintf("\r%6d", ++i);
01023 }
01024 qprintf("\n");
01025 Log_Write("%6d areas checked for shared face flipping\r\n", i);
01026 }
01027
01028
01029
01030
01031
01032
01033
01034
01035 void AAS_Create(char *aasfile)
01036 {
01037 entity_t *e;
01038 tree_t *tree;
01039 double start_time;
01040
01041
01042 strcpy(source, aasfile);
01043 StripExtension(source);
01044
01045 start_time = I_FloatTime();
01046
01047 ThreadSetDefault();
01048
01049 entity_num = 0;
01050
01051 e = &entities[entity_num];
01052
01053 tree = ProcessWorldBrushes(e->firstbrush, e->firstbrush + e->numbrushes);
01054
01055 if (cancelconversion)
01056 {
01057 Tree_Free(tree);
01058 return;
01059 }
01060
01061 Log_Print("BSP tree created in %5.0f seconds\n", I_FloatTime() - start_time);
01062
01063 Tree_PruneNodes(tree->headnode);
01064
01065 if (cancelconversion)
01066 {
01067 Tree_Free(tree);
01068 return;
01069 }
01070
01071 MakeTreePortals(tree);
01072
01073 if (cancelconversion)
01074 {
01075 Tree_Free(tree);
01076 return;
01077 }
01078
01079 if (FloodEntities(tree))
01080 {
01081
01082 FillOutside(tree->headnode);
01083 }
01084 else
01085 {
01086 LeakFile(tree);
01087 Error("**** leaked ****\n");
01088 return;
01089 }
01090
01091
01092
01093 AAS_InitTmpAAS();
01094
01095 AAS_CreateAreas(tree->headnode);
01096
01097 if (freetree) Tree_Free(tree);
01098
01099 AAS_MergeAreaFaces();
01100
01101 AAS_GravitationalSubdivision();
01102
01103 AAS_MergeAreaFaces();
01104 AAS_RemoveAreaFaceColinearPoints();
01105
01106 AAS_MergeAreas();
01107
01108 AAS_PruneNodes();
01109
01110 AAS_FlipSharedFaces();
01111 AAS_RemoveAreaFaceColinearPoints();
01112
01113 AAS_MergeAreaFaces();
01114
01115 AAS_MergeAreaPlaneFaces();
01116
01117 AAS_LadderSubdivision();
01118
01119 AAS_MeltAreaFaceWindings();
01120
01121 AAS_RemoveTinyFaces();
01122
01123 AAS_CreateAreaSettings();
01124
01125
01126
01127
01128
01129
01130 if (cancelconversion)
01131 {
01132 Tree_Free(tree);
01133 AAS_FreeTmpAAS();
01134 return;
01135 }
01136
01137 AAS_StoreFile(aasfile);
01138
01139 AAS_FreeTmpAAS();
01140
01141 Log_Print("\nAAS created in %5.0f seconds\n", I_FloatTime() - start_time);
01142 }