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_file.h"
00026 #include "aas_store.h"
00027 #include "aas_create.h"
00028 #include "aas_cfg.h"
00029
00030
00031
00032
00033 #define STOREPLANESDOUBLE
00034
00035 #define VERTEX_EPSILON 0.1 //NOTE: changed from 0.5
00036 #define DIST_EPSILON 0.05 //NOTE: changed from 0.9
00037 #define NORMAL_EPSILON 0.0001 //NOTE: changed from 0.005
00038 #define INTEGRAL_EPSILON 0.01
00039
00040 #define VERTEX_HASHING
00041 #define VERTEX_HASH_SHIFT 7
00042 #define VERTEX_HASH_SIZE ((MAX_MAP_BOUNDS>>(VERTEX_HASH_SHIFT-1))+1) //was 64
00043
00044 #define PLANE_HASHING
00045 #define PLANE_HASH_SIZE 1024 //must be power of 2
00046
00047 #define EDGE_HASHING
00048 #define EDGE_HASH_SIZE 1024 //must be power of 2
00049
00050 aas_t aasworld;
00051
00052
00053 int *aas_vertexchain;
00054 int aas_hashverts[VERTEX_HASH_SIZE*VERTEX_HASH_SIZE];
00055
00056 int *aas_planechain;
00057 int aas_hashplanes[PLANE_HASH_SIZE];
00058
00059 int *aas_edgechain;
00060 int aas_hashedges[EDGE_HASH_SIZE];
00061
00062 int allocatedaasmem = 0;
00063
00064 int groundfacesonly = false;
00065
00066 typedef struct max_aas_s
00067 {
00068 int max_bboxes;
00069 int max_vertexes;
00070 int max_planes;
00071 int max_edges;
00072 int max_edgeindexsize;
00073 int max_faces;
00074 int max_faceindexsize;
00075 int max_areas;
00076 int max_areasettings;
00077 int max_reachabilitysize;
00078 int max_nodes;
00079 int max_portals;
00080 int max_portalindexsize;
00081 int max_clusters;
00082 } max_aas_t;
00083
00084 max_aas_t max_aas;
00085
00086
00087
00088
00089
00090
00091
00092 int AAS_CountTmpNodes(tmp_node_t *tmpnode)
00093 {
00094 if (!tmpnode) return 0;
00095 return AAS_CountTmpNodes(tmpnode->children[0]) +
00096 AAS_CountTmpNodes(tmpnode->children[1]) + 1;
00097 }
00098
00099
00100
00101
00102
00103
00104 void AAS_InitMaxAAS(void)
00105 {
00106 int numfaces, numpoints, numareas;
00107 tmp_face_t *f;
00108 tmp_area_t *a;
00109
00110 numpoints = 0;
00111 numfaces = 0;
00112 for (f = tmpaasworld.faces; f; f = f->l_next)
00113 {
00114 numfaces++;
00115 if (f->winding) numpoints += f->winding->numpoints;
00116 }
00117
00118 numareas = 0;
00119 for (a = tmpaasworld.areas; a; a = a->l_next)
00120 {
00121 numareas++;
00122 }
00123 max_aas.max_bboxes = AAS_MAX_BBOXES;
00124 max_aas.max_vertexes = numpoints + 1;
00125 max_aas.max_planes = nummapplanes;
00126 max_aas.max_edges = numpoints + 1;
00127 max_aas.max_edgeindexsize = (numpoints + 1) * 3;
00128 max_aas.max_faces = numfaces + 10;
00129 max_aas.max_faceindexsize = (numfaces + 10) * 2;
00130 max_aas.max_areas = numareas + 10;
00131 max_aas.max_areasettings = numareas + 10;
00132 max_aas.max_reachabilitysize = 0;
00133 max_aas.max_nodes = AAS_CountTmpNodes(tmpaasworld.nodes) + 10;
00134 max_aas.max_portals = 0;
00135 max_aas.max_portalindexsize = 0;
00136 max_aas.max_clusters = 0;
00137 }
00138
00139
00140
00141
00142
00143
00144 void AAS_AllocMaxAAS(void)
00145 {
00146 int i;
00147
00148 AAS_InitMaxAAS();
00149
00150 aasworld.numbboxes = 0;
00151 aasworld.bboxes = (aas_bbox_t *) GetClearedMemory(max_aas.max_bboxes * sizeof(aas_bbox_t));
00152 allocatedaasmem += max_aas.max_bboxes * sizeof(aas_bbox_t);
00153
00154 aasworld.numvertexes = 0;
00155 aasworld.vertexes = (aas_vertex_t *) GetClearedMemory(max_aas.max_vertexes * sizeof(aas_vertex_t));
00156 allocatedaasmem += max_aas.max_vertexes * sizeof(aas_vertex_t);
00157
00158 aasworld.numplanes = 0;
00159 aasworld.planes = (aas_plane_t *) GetClearedMemory(max_aas.max_planes * sizeof(aas_plane_t));
00160 allocatedaasmem += max_aas.max_planes * sizeof(aas_plane_t);
00161
00162 aasworld.numedges = 0;
00163 aasworld.edges = (aas_edge_t *) GetClearedMemory(max_aas.max_edges * sizeof(aas_edge_t));
00164 allocatedaasmem += max_aas.max_edges * sizeof(aas_edge_t);
00165
00166 aasworld.edgeindexsize = 0;
00167 aasworld.edgeindex = (aas_edgeindex_t *) GetClearedMemory(max_aas.max_edgeindexsize * sizeof(aas_edgeindex_t));
00168 allocatedaasmem += max_aas.max_edgeindexsize * sizeof(aas_edgeindex_t);
00169
00170 aasworld.numfaces = 0;
00171 aasworld.faces = (aas_face_t *) GetClearedMemory(max_aas.max_faces * sizeof(aas_face_t));
00172 allocatedaasmem += max_aas.max_faces * sizeof(aas_face_t);
00173
00174 aasworld.faceindexsize = 0;
00175 aasworld.faceindex = (aas_faceindex_t *) GetClearedMemory(max_aas.max_faceindexsize * sizeof(aas_faceindex_t));
00176 allocatedaasmem += max_aas.max_faceindexsize * sizeof(aas_faceindex_t);
00177
00178 aasworld.numareas = 0;
00179 aasworld.areas = (aas_area_t *) GetClearedMemory(max_aas.max_areas * sizeof(aas_area_t));
00180 allocatedaasmem += max_aas.max_areas * sizeof(aas_area_t);
00181
00182 aasworld.numareasettings = 0;
00183 aasworld.areasettings = (aas_areasettings_t *) GetClearedMemory(max_aas.max_areasettings * sizeof(aas_areasettings_t));
00184 allocatedaasmem += max_aas.max_areasettings * sizeof(aas_areasettings_t);
00185
00186 aasworld.reachabilitysize = 0;
00187 aasworld.reachability = (aas_reachability_t *) GetClearedMemory(max_aas.max_reachabilitysize * sizeof(aas_reachability_t));
00188 allocatedaasmem += max_aas.max_reachabilitysize * sizeof(aas_reachability_t);
00189
00190 aasworld.numnodes = 0;
00191 aasworld.nodes = (aas_node_t *) GetClearedMemory(max_aas.max_nodes * sizeof(aas_node_t));
00192 allocatedaasmem += max_aas.max_nodes * sizeof(aas_node_t);
00193
00194 aasworld.numportals = 0;
00195 aasworld.portals = (aas_portal_t *) GetClearedMemory(max_aas.max_portals * sizeof(aas_portal_t));
00196 allocatedaasmem += max_aas.max_portals * sizeof(aas_portal_t);
00197
00198 aasworld.portalindexsize = 0;
00199 aasworld.portalindex = (aas_portalindex_t *) GetClearedMemory(max_aas.max_portalindexsize * sizeof(aas_portalindex_t));
00200 allocatedaasmem += max_aas.max_portalindexsize * sizeof(aas_portalindex_t);
00201
00202 aasworld.numclusters = 0;
00203 aasworld.clusters = (aas_cluster_t *) GetClearedMemory(max_aas.max_clusters * sizeof(aas_cluster_t));
00204 allocatedaasmem += max_aas.max_clusters * sizeof(aas_cluster_t);
00205
00206 Log_Print("allocated ");
00207 PrintMemorySize(allocatedaasmem);
00208 Log_Print(" of AAS memory\n");
00209
00210 aas_vertexchain = (int *) GetClearedMemory(max_aas.max_vertexes * sizeof(int));
00211 aas_planechain = (int *) GetClearedMemory(max_aas.max_planes * sizeof(int));
00212 aas_edgechain = (int *) GetClearedMemory(max_aas.max_edges * sizeof(int));
00213
00214 for (i = 0; i < max_aas.max_vertexes; i++) aas_vertexchain[i] = -1;
00215 for (i = 0; i < VERTEX_HASH_SIZE * VERTEX_HASH_SIZE; i++) aas_hashverts[i] = -1;
00216
00217 for (i = 0; i < max_aas.max_planes; i++) aas_planechain[i] = -1;
00218 for (i = 0; i < PLANE_HASH_SIZE; i++) aas_hashplanes[i] = -1;
00219
00220 for (i = 0; i < max_aas.max_edges; i++) aas_edgechain[i] = -1;
00221 for (i = 0; i < EDGE_HASH_SIZE; i++) aas_hashedges[i] = -1;
00222 }
00223
00224
00225
00226
00227
00228
00229 void AAS_FreeMaxAAS(void)
00230 {
00231
00232 if (aasworld.bboxes) FreeMemory(aasworld.bboxes);
00233 aasworld.bboxes = NULL;
00234 aasworld.numbboxes = 0;
00235
00236 if (aasworld.vertexes) FreeMemory(aasworld.vertexes);
00237 aasworld.vertexes = NULL;
00238 aasworld.numvertexes = 0;
00239
00240 if (aasworld.planes) FreeMemory(aasworld.planes);
00241 aasworld.planes = NULL;
00242 aasworld.numplanes = 0;
00243
00244 if (aasworld.edges) FreeMemory(aasworld.edges);
00245 aasworld.edges = NULL;
00246 aasworld.numedges = 0;
00247
00248 if (aasworld.edgeindex) FreeMemory(aasworld.edgeindex);
00249 aasworld.edgeindex = NULL;
00250 aasworld.edgeindexsize = 0;
00251
00252 if (aasworld.faces) FreeMemory(aasworld.faces);
00253 aasworld.faces = NULL;
00254 aasworld.numfaces = 0;
00255
00256 if (aasworld.faceindex) FreeMemory(aasworld.faceindex);
00257 aasworld.faceindex = NULL;
00258 aasworld.faceindexsize = 0;
00259
00260 if (aasworld.areas) FreeMemory(aasworld.areas);
00261 aasworld.areas = NULL;
00262 aasworld.numareas = 0;
00263
00264 if (aasworld.areasettings) FreeMemory(aasworld.areasettings);
00265 aasworld.areasettings = NULL;
00266 aasworld.numareasettings = 0;
00267
00268 if (aasworld.reachability) FreeMemory(aasworld.reachability);
00269 aasworld.reachability = NULL;
00270 aasworld.reachabilitysize = 0;
00271
00272 if (aasworld.nodes) FreeMemory(aasworld.nodes);
00273 aasworld.nodes = NULL;
00274 aasworld.numnodes = 0;
00275
00276 if (aasworld.portals) FreeMemory(aasworld.portals);
00277 aasworld.portals = NULL;
00278 aasworld.numportals = 0;
00279
00280 if (aasworld.portalindex) FreeMemory(aasworld.portalindex);
00281 aasworld.portalindex = NULL;
00282 aasworld.portalindexsize = 0;
00283
00284 if (aasworld.clusters) FreeMemory(aasworld.clusters);
00285 aasworld.clusters = NULL;
00286 aasworld.numclusters = 0;
00287
00288 Log_Print("freed ");
00289 PrintMemorySize(allocatedaasmem);
00290 Log_Print(" of AAS memory\n");
00291 allocatedaasmem = 0;
00292
00293 if (aas_vertexchain) FreeMemory(aas_vertexchain);
00294 aas_vertexchain = NULL;
00295 if (aas_planechain) FreeMemory(aas_planechain);
00296 aas_planechain = NULL;
00297 if (aas_edgechain) FreeMemory(aas_edgechain);
00298 aas_edgechain = NULL;
00299 }
00300
00301
00302
00303
00304
00305
00306 unsigned AAS_HashVec(vec3_t vec)
00307 {
00308 int x, y;
00309
00310 x = (MAX_MAP_BOUNDS + (int)(vec[0]+0.5)) >> VERTEX_HASH_SHIFT;
00311 y = (MAX_MAP_BOUNDS + (int)(vec[1]+0.5)) >> VERTEX_HASH_SHIFT;
00312
00313 if (x < 0 || x >= VERTEX_HASH_SIZE || y < 0 || y >= VERTEX_HASH_SIZE)
00314 {
00315 Log_Print("WARNING! HashVec: point %f %f %f outside valid range\n", vec[0], vec[1], vec[2]);
00316 Log_Print("This should never happen!\n");
00317 return -1;
00318 }
00319
00320 return y*VERTEX_HASH_SIZE + x;
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 qboolean AAS_GetVertex(vec3_t v, int *vnum)
00332 {
00333 int i;
00334 #ifndef VERTEX_HASHING
00335 float diff;
00336 #endif //VERTEX_HASHING
00337
00338 #ifdef VERTEX_HASHING
00339 int h, vn;
00340 vec3_t vert;
00341
00342 for (i = 0; i < 3; i++)
00343 {
00344 if ( fabs(v[i] - Q_rint(v[i])) < INTEGRAL_EPSILON)
00345 vert[i] = Q_rint(v[i]);
00346 else
00347 vert[i] = v[i];
00348 }
00349
00350 h = AAS_HashVec(vert);
00351
00352 if (h == -1)
00353 {
00354 *vnum = -1;
00355 return true;
00356 }
00357
00358 for (vn = aas_hashverts[h]; vn >= 0; vn = aas_vertexchain[vn])
00359 {
00360 if (fabs(aasworld.vertexes[vn][0] - vert[0]) < VERTEX_EPSILON
00361 && fabs(aasworld.vertexes[vn][1] - vert[1]) < VERTEX_EPSILON
00362 && fabs(aasworld.vertexes[vn][2] - vert[2]) < VERTEX_EPSILON)
00363 {
00364 *vnum = vn;
00365 return true;
00366 }
00367 }
00368 #else //VERTEX_HASHING
00369
00370
00371 for (i = 0; i < aasworld.numvertexes; i++)
00372 {
00373 diff = vert[0] - aasworld.vertexes[i][0];
00374 if (diff < VERTEX_EPSILON && diff > -VERTEX_EPSILON)
00375 {
00376 diff = vert[1] - aasworld.vertexes[i][1];
00377 if (diff < VERTEX_EPSILON && diff > -VERTEX_EPSILON)
00378 {
00379 diff = vert[2] - aasworld.vertexes[i][2];
00380 if (diff < VERTEX_EPSILON && diff > -VERTEX_EPSILON)
00381 {
00382 *vnum = i;
00383 return true;
00384 }
00385 }
00386 }
00387 }
00388 #endif //VERTEX_HASHING
00389
00390 if (aasworld.numvertexes >= max_aas.max_vertexes)
00391 {
00392 Error("AAS_MAX_VERTEXES = %d", max_aas.max_vertexes);
00393 }
00394 VectorCopy(vert, aasworld.vertexes[aasworld.numvertexes]);
00395 *vnum = aasworld.numvertexes;
00396
00397 #ifdef VERTEX_HASHING
00398 aas_vertexchain[aasworld.numvertexes] = aas_hashverts[h];
00399 aas_hashverts[h] = aasworld.numvertexes;
00400 #endif //VERTEX_HASHING
00401
00402 aasworld.numvertexes++;
00403 return false;
00404 }
00405
00406
00407
00408
00409
00410
00411 unsigned AAS_HashEdge(int v1, int v2)
00412 {
00413 int vnum1, vnum2;
00414
00415 if (v1 < v2)
00416 {
00417 vnum1 = v1;
00418 vnum2 = v2;
00419 }
00420 else
00421 {
00422 vnum1 = v2;
00423 vnum2 = v1;
00424 }
00425 return (vnum1 + vnum2) & (EDGE_HASH_SIZE-1);
00426 }
00427
00428
00429
00430
00431
00432
00433 void AAS_AddEdgeToHash(int edgenum)
00434 {
00435 int hash;
00436 aas_edge_t *edge;
00437
00438 edge = &aasworld.edges[edgenum];
00439
00440 hash = AAS_HashEdge(edge->v[0], edge->v[1]);
00441
00442 aas_edgechain[edgenum] = aas_hashedges[hash];
00443 aas_hashedges[hash] = edgenum;
00444 }
00445
00446
00447
00448
00449
00450
00451 qboolean AAS_FindHashedEdge(int v1num, int v2num, int *edgenum)
00452 {
00453 int e, hash;
00454 aas_edge_t *edge;
00455
00456 hash = AAS_HashEdge(v1num, v2num);
00457 for (e = aas_hashedges[hash]; e >= 0; e = aas_edgechain[e])
00458 {
00459 edge = &aasworld.edges[e];
00460 if (edge->v[0] == v1num)
00461 {
00462 if (edge->v[1] == v2num)
00463 {
00464 *edgenum = e;
00465 return true;
00466 }
00467 }
00468 else if (edge->v[1] == v1num)
00469 {
00470 if (edge->v[0] == v2num)
00471 {
00472
00473 *edgenum = -e;
00474 return true;
00475 }
00476 }
00477 }
00478 return false;
00479 }
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 qboolean AAS_GetEdge(vec3_t v1, vec3_t v2, int *edgenum)
00491 {
00492 int v1num, v2num;
00493 qboolean found;
00494
00495
00496 if (aasworld.numedges == 0) aasworld.numedges = 1;
00497
00498 found = AAS_GetVertex(v1, &v1num);
00499 found &= AAS_GetVertex(v2, &v2num);
00500
00501 if (v1num == -1 || v2num == -1)
00502 {
00503 *edgenum = 0;
00504 return true;
00505 }
00506
00507 if (v1num == v2num)
00508 {
00509 *edgenum = 0;
00510 return true;
00511 }
00512
00513 if (found)
00514 {
00515 #ifdef EDGE_HASHING
00516 if (AAS_FindHashedEdge(v1num, v2num, edgenum)) return true;
00517 #else
00518 int i;
00519 for (i = 1; i < aasworld.numedges; i++)
00520 {
00521 if (aasworld.edges[i].v[0] == v1num)
00522 {
00523 if (aasworld.edges[i].v[1] == v2num)
00524 {
00525 *edgenum = i;
00526 return true;
00527 }
00528 }
00529 else if (aasworld.edges[i].v[1] == v1num)
00530 {
00531 if (aasworld.edges[i].v[0] == v2num)
00532 {
00533
00534 *edgenum = -i;
00535 return true;
00536 }
00537 }
00538 }
00539 #endif //EDGE_HASHING
00540 }
00541 if (aasworld.numedges >= max_aas.max_edges)
00542 {
00543 Error("AAS_MAX_EDGES = %d", max_aas.max_edges);
00544 }
00545 aasworld.edges[aasworld.numedges].v[0] = v1num;
00546 aasworld.edges[aasworld.numedges].v[1] = v2num;
00547 *edgenum = aasworld.numedges;
00548 #ifdef EDGE_HASHING
00549 AAS_AddEdgeToHash(*edgenum);
00550 #endif //EDGE_HASHING
00551 aasworld.numedges++;
00552 return false;
00553 }
00554
00555
00556
00557
00558
00559
00560 int AAS_PlaneTypeForNormal(vec3_t normal)
00561 {
00562 vec_t ax, ay, az;
00563
00564
00565 if ( (normal[0] >= 1.0 -NORMAL_EPSILON) ||
00566 (normal[0] <= -1.0 + NORMAL_EPSILON)) return PLANE_X;
00567 if ( (normal[1] >= 1.0 -NORMAL_EPSILON) ||
00568 (normal[1] <= -1.0 + NORMAL_EPSILON)) return PLANE_Y;
00569 if ( (normal[2] >= 1.0 -NORMAL_EPSILON) ||
00570 (normal[2] <= -1.0 + NORMAL_EPSILON)) return PLANE_Z;
00571
00572 ax = fabs(normal[0]);
00573 ay = fabs(normal[1]);
00574 az = fabs(normal[2]);
00575
00576 if (ax >= ay && ax >= az) return PLANE_ANYX;
00577 if (ay >= ax && ay >= az) return PLANE_ANYY;
00578 return PLANE_ANYZ;
00579 }
00580
00581
00582
00583
00584
00585
00586 void AAS_AddPlaneToHash(int planenum)
00587 {
00588 int hash;
00589 aas_plane_t *plane;
00590
00591 plane = &aasworld.planes[planenum];
00592
00593 hash = (int)fabs(plane->dist) / 8;
00594 hash &= (PLANE_HASH_SIZE-1);
00595
00596 aas_planechain[planenum] = aas_hashplanes[hash];
00597 aas_hashplanes[hash] = planenum;
00598 }
00599
00600
00601
00602
00603
00604
00605 int AAS_PlaneEqual(vec3_t normal, float dist, int planenum)
00606 {
00607 float diff;
00608
00609 diff = dist - aasworld.planes[planenum].dist;
00610 if (diff > -DIST_EPSILON && diff < DIST_EPSILON)
00611 {
00612 diff = normal[0] - aasworld.planes[planenum].normal[0];
00613 if (diff > -NORMAL_EPSILON && diff < NORMAL_EPSILON)
00614 {
00615 diff = normal[1] - aasworld.planes[planenum].normal[1];
00616 if (diff > -NORMAL_EPSILON && diff < NORMAL_EPSILON)
00617 {
00618 diff = normal[2] - aasworld.planes[planenum].normal[2];
00619 if (diff > -NORMAL_EPSILON && diff < NORMAL_EPSILON)
00620 {
00621 return true;
00622 }
00623 }
00624 }
00625 }
00626 return false;
00627 }
00628
00629
00630
00631
00632
00633
00634 qboolean AAS_FindPlane(vec3_t normal, float dist, int *planenum)
00635 {
00636 int i;
00637
00638 for (i = 0; i < aasworld.numplanes; i++)
00639 {
00640 if (AAS_PlaneEqual(normal, dist, i))
00641 {
00642 *planenum = i;
00643 return true;
00644 }
00645 }
00646 return false;
00647 }
00648
00649
00650
00651
00652
00653
00654 qboolean AAS_FindHashedPlane(vec3_t normal, float dist, int *planenum)
00655 {
00656 int i, p;
00657 aas_plane_t *plane;
00658 int hash, h;
00659
00660 hash = (int)fabs(dist) / 8;
00661 hash &= (PLANE_HASH_SIZE-1);
00662
00663
00664 for (i = -1; i <= 1; i++)
00665 {
00666 h = (hash+i)&(PLANE_HASH_SIZE-1);
00667 for (p = aas_hashplanes[h]; p >= 0; p = aas_planechain[p])
00668 {
00669 plane = &aasworld.planes[p];
00670 if (AAS_PlaneEqual(normal, dist, p))
00671 {
00672 *planenum = p;
00673 return true;
00674 }
00675 }
00676 }
00677 return false;
00678 }
00679
00680
00681
00682
00683
00684
00685 qboolean AAS_GetPlane(vec3_t normal, vec_t dist, int *planenum)
00686 {
00687 aas_plane_t *plane, temp;
00688
00689
00690 if (AAS_FindHashedPlane(normal, dist, planenum)) return true;
00691
00692 if (aasworld.numplanes >= max_aas.max_planes-1)
00693 {
00694 Error("AAS_MAX_PLANES = %d", max_aas.max_planes);
00695 }
00696
00697 #ifdef STOREPLANESDOUBLE
00698 plane = &aasworld.planes[aasworld.numplanes];
00699 VectorCopy(normal, plane->normal);
00700 plane->dist = dist;
00701 plane->type = (plane+1)->type = PlaneTypeForNormal(plane->normal);
00702
00703 VectorCopy(normal, (plane+1)->normal);
00704 VectorNegate((plane+1)->normal, (plane+1)->normal);
00705 (plane+1)->dist = -dist;
00706
00707 aasworld.numplanes += 2;
00708
00709
00710 if (plane->type < 3)
00711 {
00712 if (plane->normal[0] < 0 || plane->normal[1] < 0 || plane->normal[2] < 0)
00713 {
00714
00715 temp = *plane;
00716 *plane = *(plane+1);
00717 *(plane+1) = temp;
00718 *planenum = aasworld.numplanes - 1;
00719 return false;
00720 }
00721 }
00722 *planenum = aasworld.numplanes - 2;
00723
00724 AAS_AddPlaneToHash(aasworld.numplanes - 1);
00725 AAS_AddPlaneToHash(aasworld.numplanes - 2);
00726 return false;
00727 #else
00728 plane = &aasworld.planes[aasworld.numplanes];
00729 VectorCopy(normal, plane->normal);
00730 plane->dist = dist;
00731 plane->type = AAS_PlaneTypeForNormal(normal);
00732
00733 *planenum = aasworld.numplanes;
00734 aasworld.numplanes++;
00735
00736 AAS_AddPlaneToHash(aasworld.numplanes - 1);
00737 return false;
00738 #endif //STOREPLANESDOUBLE
00739 }
00740
00741
00742
00743
00744
00745
00746 qboolean AAS_GetFace(winding_t *w, plane_t *p, int side, int *facenum)
00747 {
00748 int edgenum, i, j;
00749 aas_face_t *face;
00750
00751
00752 if (aasworld.numfaces == 0) aasworld.numfaces = 1;
00753
00754 if (aasworld.numfaces >= max_aas.max_faces)
00755 {
00756 Error("AAS_MAX_FACES = %d", max_aas.max_faces);
00757 }
00758 face = &aasworld.faces[aasworld.numfaces];
00759 AAS_GetPlane(p->normal, p->dist, &face->planenum);
00760 face->faceflags = 0;
00761 face->firstedge = aasworld.edgeindexsize;
00762 face->frontarea = 0;
00763 face->backarea = 0;
00764 face->numedges = 0;
00765 for (i = 0; i < w->numpoints; i++)
00766 {
00767 if (aasworld.edgeindexsize >= max_aas.max_edgeindexsize)
00768 {
00769 Error("AAS_MAX_EDGEINDEXSIZE = %d", max_aas.max_edgeindexsize);
00770 }
00771 j = (i+1) % w->numpoints;
00772 AAS_GetEdge(w->p[i], w->p[j], &edgenum);
00773
00774 if (edgenum)
00775 {
00776 aasworld.edgeindex[aasworld.edgeindexsize++] = edgenum;
00777 face->numedges++;
00778 }
00779 else if (verbose)
00780 {
00781 Log_Write("AAS_GetFace: face %d had degenerate edge %d-%d\r\n",
00782 aasworld.numfaces, i, j);
00783 }
00784 }
00785 if (face->numedges < 1
00786 #ifdef NOTHREEVERTEXFACES
00787 || face->numedges < 3
00788 #endif //NOTHREEVERTEXFACES
00789 )
00790 {
00791 memset(&aasworld.faces[aasworld.numfaces], 0, sizeof(aas_face_t));
00792 Log_Write("AAS_GetFace: face %d was tiny\r\n", aasworld.numfaces);
00793 return false;
00794 }
00795 *facenum = aasworld.numfaces;
00796 aasworld.numfaces++;
00797 return true;
00798 }
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882 void AAS_StoreAreaSettings(tmp_areasettings_t *tmpareasettings)
00883 {
00884 aas_areasettings_t *areasettings;
00885
00886 if (aasworld.numareasettings == 0) aasworld.numareasettings = 1;
00887 areasettings = &aasworld.areasettings[aasworld.numareasettings++];
00888 areasettings->areaflags = tmpareasettings->areaflags;
00889 areasettings->presencetype = tmpareasettings->presencetype;
00890 areasettings->contents = tmpareasettings->contents;
00891 if (tmpareasettings->modelnum > AREACONTENTS_MAXMODELNUM)
00892 Log_Print("WARNING: more than %d mover models\n", AREACONTENTS_MAXMODELNUM);
00893 areasettings->contents |= (tmpareasettings->modelnum & AREACONTENTS_MAXMODELNUM) << AREACONTENTS_MODELNUMSHIFT;
00894 }
00895
00896
00897
00898
00899
00900
00901 int AAS_StoreArea(tmp_area_t *tmparea)
00902 {
00903 int side, edgenum, i;
00904 plane_t *plane;
00905 tmp_face_t *tmpface;
00906 aas_area_t *aasarea;
00907 aas_edge_t *edge;
00908 aas_face_t *aasface;
00909 aas_faceindex_t aasfacenum;
00910 vec3_t facecenter;
00911 winding_t *w;
00912
00913
00914
00915
00916 while(tmparea->mergedarea) tmparea = tmparea->mergedarea;
00917
00918 if (tmparea->invalid) Error("AAS_StoreArea: tried to store invalid area");
00919
00920 if (tmparea->aasareanum) return -tmparea->aasareanum;
00921
00922 if (aasworld.numareas >= max_aas.max_areas)
00923 {
00924 Error("AAS_MAX_AREAS = %d", max_aas.max_areas);
00925 }
00926
00927 if (aasworld.numareas == 0) aasworld.numareas = 1;
00928
00929 aasarea = &aasworld.areas[aasworld.numareas];
00930 aasarea->areanum = aasworld.numareas;
00931 aasarea->numfaces = 0;
00932 aasarea->firstface = aasworld.faceindexsize;
00933 ClearBounds(aasarea->mins, aasarea->maxs);
00934 VectorClear(aasarea->center);
00935
00936
00937
00938 tmparea->aasareanum = aasarea->areanum;
00939
00940 for (tmpface = tmparea->tmpfaces; tmpface; tmpface = tmpface->next[side])
00941 {
00942 side = tmpface->frontarea != tmparea;
00943
00944 if (tmpface->aasfacenum)
00945 {
00946
00947 aasfacenum = -tmpface->aasfacenum;
00948 #ifdef DEBUG
00949 if (tmpface->aasfacenum < 0 || tmpface->aasfacenum > max_aas.max_faces)
00950 {
00951 Error("AAS_CreateTree_r: face number out of range");
00952 }
00953 #endif //DEBUG
00954 aasface = &aasworld.faces[tmpface->aasfacenum];
00955 aasface->backarea = aasarea->areanum;
00956 }
00957 else
00958 {
00959 plane = &mapplanes[tmpface->planenum ^ side];
00960 if (side)
00961 {
00962 w = tmpface->winding;
00963 tmpface->winding = ReverseWinding(tmpface->winding);
00964 }
00965 if (!AAS_GetFace(tmpface->winding, plane, 0, &aasfacenum)) continue;
00966 if (side)
00967 {
00968 FreeWinding(tmpface->winding);
00969 tmpface->winding = w;
00970 }
00971 aasface = &aasworld.faces[aasfacenum];
00972 aasface->frontarea = aasarea->areanum;
00973 aasface->backarea = 0;
00974 aasface->faceflags = tmpface->faceflags;
00975
00976 tmpface->aasfacenum = aasfacenum;
00977 }
00978
00979
00980 VectorClear(facecenter);
00981 for (edgenum = 0; edgenum < aasface->numedges; edgenum++)
00982 {
00983 edge = &aasworld.edges[abs(aasworld.edgeindex[aasface->firstedge + edgenum])];
00984 for (i = 0; i < 2; i++)
00985 {
00986 AddPointToBounds(aasworld.vertexes[edge->v[i]], aasarea->mins, aasarea->maxs);
00987 VectorAdd(aasworld.vertexes[edge->v[i]], facecenter, facecenter);
00988 }
00989 }
00990 VectorScale(facecenter, 1.0 / (aasface->numedges * 2.0), facecenter);
00991
00992 VectorAdd(aasarea->center, facecenter, aasarea->center);
00993
00994 if (aasworld.faceindexsize >= max_aas.max_faceindexsize)
00995 {
00996 Error("AAS_MAX_FACEINDEXSIZE = %d", max_aas.max_faceindexsize);
00997 }
00998 aasworld.faceindex[aasworld.faceindexsize++] = aasfacenum;
00999 aasarea->numfaces++;
01000 }
01001
01002 if (!aasarea->numfaces) return 0;
01003
01004 VectorScale(aasarea->center, 1.0 / aasarea->numfaces, aasarea->center);
01005
01006
01007
01008 AAS_StoreAreaSettings(tmparea->settings);
01009
01010
01011 qprintf("\r%6d", aasarea->areanum);
01012
01013 aasworld.numareas++;
01014 return -(aasworld.numareas - 1);
01015 }
01016
01017
01018
01019
01020
01021
01022 int AAS_StoreTree_r(tmp_node_t *tmpnode)
01023 {
01024 int aasnodenum;
01025 plane_t *plane;
01026 aas_node_t *aasnode;
01027
01028
01029 if (!tmpnode) return 0;
01030
01031 if (tmpnode->tmparea) return AAS_StoreArea(tmpnode->tmparea);
01032
01033
01034 if (aasworld.numnodes == 0) aasworld.numnodes = 1;
01035 if (aasworld.numnodes >= max_aas.max_nodes)
01036 {
01037 Error("AAS_MAX_NODES = %d", max_aas.max_nodes);
01038 }
01039 aasnodenum = aasworld.numnodes;
01040 aasnode = &aasworld.nodes[aasworld.numnodes++];
01041 plane = &mapplanes[tmpnode->planenum];
01042 AAS_GetPlane(plane->normal, plane->dist, &aasnode->planenum);
01043 aasnode->children[0] = AAS_StoreTree_r(tmpnode->children[0]);
01044 aasnode->children[1] = AAS_StoreTree_r(tmpnode->children[1]);
01045 return aasnodenum;
01046 }
01047
01048
01049
01050
01051
01052
01053 void AAS_StoreBoundingBoxes(void)
01054 {
01055 if (cfg.numbboxes > max_aas.max_bboxes)
01056 {
01057 Error("more than %d bounding boxes", max_aas.max_bboxes);
01058 }
01059 aasworld.numbboxes = cfg.numbboxes;
01060 memcpy(aasworld.bboxes, cfg.bboxes, cfg.numbboxes * sizeof(aas_bbox_t));
01061 }
01062
01063
01064
01065
01066
01067
01068 void AAS_StoreFile(char *filename)
01069 {
01070 AAS_AllocMaxAAS();
01071
01072 Log_Write("AAS_StoreFile\r\n");
01073
01074 AAS_StoreBoundingBoxes();
01075
01076 qprintf("%6d areas stored", 0);
01077
01078 AAS_StoreTree_r(tmpaasworld.nodes);
01079 qprintf("\n");
01080 Log_Write("%6d areas stored\r\n", aasworld.numareas);
01081 aasworld.loaded = true;
01082 }