Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

aas_store.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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 //#define NOTHREEVERTEXFACES
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 //vertex hash
00053 int *aas_vertexchain;                       // the next vertex in a hash chain
00054 int aas_hashverts[VERTEX_HASH_SIZE*VERTEX_HASH_SIZE];   // a vertex number, or 0 for no verts
00055 //plane hash
00056 int *aas_planechain;
00057 int aas_hashplanes[PLANE_HASH_SIZE];
00058 //edge hash
00059 int *aas_edgechain;
00060 int aas_hashedges[EDGE_HASH_SIZE];
00061 
00062 int allocatedaasmem = 0;
00063 
00064 int groundfacesonly = false;//true;
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 //maximums of everything
00084 max_aas_t max_aas;
00085 
00086 //===========================================================================
00087 //
00088 // Parameter:               -
00089 // Returns:                 -
00090 // Changes Globals:     -
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 } //end of the function AAS_CountTmpNodes
00098 //===========================================================================
00099 //
00100 // Parameter:               -
00101 // Returns:                 -
00102 // Changes Globals:     -
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     } //end for
00117     //
00118     numareas = 0;
00119     for (a = tmpaasworld.areas; a; a = a->l_next)
00120     {
00121         numareas++;
00122     } //end for
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 } //end of the function AAS_InitMaxAAS
00138 //===========================================================================
00139 //
00140 // Parameter:               -
00141 // Returns:                 -
00142 // Changes Globals:     -
00143 //===========================================================================
00144 void AAS_AllocMaxAAS(void)
00145 {
00146     int i;
00147 
00148     AAS_InitMaxAAS();
00149     //bounding boxes
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     //vertexes
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     //planes
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     //edges
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     //edge index
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     //faces
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     //face index
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     //convex areas
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     //convex area settings
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     //reachablity list
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     //nodes of the bsp tree
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     //cluster portals
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     //cluster portal index
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     //cluster
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     //reset the has stuff
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 } //end of the function AAS_AllocMaxAAS
00223 //===========================================================================
00224 //
00225 // Parameter:               -
00226 // Returns:                 -
00227 // Changes Globals:     -
00228 //===========================================================================
00229 void AAS_FreeMaxAAS(void)
00230 {
00231     //bounding boxes
00232     if (aasworld.bboxes) FreeMemory(aasworld.bboxes);
00233     aasworld.bboxes = NULL;
00234     aasworld.numbboxes = 0;
00235     //vertexes
00236     if (aasworld.vertexes) FreeMemory(aasworld.vertexes);
00237     aasworld.vertexes = NULL;
00238     aasworld.numvertexes = 0;
00239     //planes
00240     if (aasworld.planes) FreeMemory(aasworld.planes);
00241     aasworld.planes = NULL;
00242     aasworld.numplanes = 0;
00243     //edges
00244     if (aasworld.edges) FreeMemory(aasworld.edges);
00245     aasworld.edges = NULL;
00246     aasworld.numedges = 0;
00247     //edge index
00248     if (aasworld.edgeindex) FreeMemory(aasworld.edgeindex);
00249     aasworld.edgeindex = NULL;
00250     aasworld.edgeindexsize = 0;
00251     //faces
00252     if (aasworld.faces) FreeMemory(aasworld.faces);
00253     aasworld.faces = NULL;
00254     aasworld.numfaces = 0;
00255     //face index
00256     if (aasworld.faceindex) FreeMemory(aasworld.faceindex);
00257     aasworld.faceindex = NULL;
00258     aasworld.faceindexsize = 0;
00259     //convex areas
00260     if (aasworld.areas) FreeMemory(aasworld.areas);
00261     aasworld.areas = NULL;
00262     aasworld.numareas = 0;
00263     //convex area settings
00264     if (aasworld.areasettings) FreeMemory(aasworld.areasettings);
00265     aasworld.areasettings = NULL;
00266     aasworld.numareasettings = 0;
00267     //reachablity list
00268     if (aasworld.reachability) FreeMemory(aasworld.reachability);
00269     aasworld.reachability = NULL;
00270     aasworld.reachabilitysize = 0;
00271     //nodes of the bsp tree
00272     if (aasworld.nodes) FreeMemory(aasworld.nodes);
00273     aasworld.nodes = NULL;
00274     aasworld.numnodes = 0;
00275     //cluster portals
00276     if (aasworld.portals) FreeMemory(aasworld.portals);
00277     aasworld.portals = NULL;
00278     aasworld.numportals = 0;
00279     //cluster portal index
00280     if (aasworld.portalindex) FreeMemory(aasworld.portalindex);
00281     aasworld.portalindex = NULL;
00282     aasworld.portalindexsize = 0;
00283     //clusters
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 } //end of the function AAS_FreeMaxAAS
00300 //===========================================================================
00301 //
00302 // Parameter:               -
00303 // Returns:                 -
00304 // Changes Globals:     -
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     } //end if
00319     
00320     return y*VERTEX_HASH_SIZE + x;
00321 } //end of the function AAS_HashVec
00322 //===========================================================================
00323 // returns true if the vertex was found in the list
00324 // stores the vertex number in *vnum
00325 // stores a new vertex if not stored already
00326 //
00327 // Parameter:               -
00328 // Returns:                 -
00329 // Changes Globals:     -
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     } //end for
00349 
00350     h = AAS_HashVec(vert);
00351     //if the vertex was outside the valid range
00352     if (h == -1)
00353     {
00354         *vnum = -1;
00355         return true;
00356     } //end if
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         } //end if
00367     } //end for
00368 #else //VERTEX_HASHING
00369     //check if the vertex is already stored
00370     //stupid linear search
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                 } //end if
00385             } //end if
00386         } //end if
00387     } //end for
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     } //end if
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 } //end of the function AAS_GetVertex
00405 //===========================================================================
00406 //
00407 // Parameter:               -
00408 // Returns:                 -
00409 // Changes Globals:     -
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     } //end if
00420     else
00421     {
00422         vnum1 = v2;
00423         vnum2 = v1;
00424     } //end else
00425     return (vnum1 + vnum2) & (EDGE_HASH_SIZE-1);
00426 } //end of the function AAS_HashVec
00427 //===========================================================================
00428 //
00429 // Parameter:               -
00430 // Returns:                 -
00431 // Changes Globals:     -
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 } //end of the function AAS_AddEdgeToHash
00445 //===========================================================================
00446 //
00447 // Parameter:               -
00448 // Returns:                 -
00449 // Changes Globals:     -
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             } //end if
00467         } //end if
00468         else if (edge->v[1] == v1num)
00469         {
00470             if (edge->v[0] == v2num)
00471             {
00472                 //negative for a reversed edge
00473                 *edgenum = -e;
00474                 return true;
00475             } //end if
00476         } //end else
00477     } //end for
00478     return false;
00479 } //end of the function AAS_FindHashedPlane
00480 //===========================================================================
00481 // returns true if the edge was found
00482 // stores the edge number in *edgenum (negative if reversed edge)
00483 // stores new edge if not stored already
00484 // returns zero when the edge is degenerate
00485 //
00486 // Parameter:               -
00487 // Returns:                 -
00488 // Changes Globals:     -
00489 //===========================================================================
00490 qboolean AAS_GetEdge(vec3_t v1, vec3_t v2, int *edgenum)
00491 {
00492     int v1num, v2num;
00493     qboolean found;
00494 
00495     //the first edge is a dummy
00496     if (aasworld.numedges == 0) aasworld.numedges = 1;
00497 
00498     found = AAS_GetVertex(v1, &v1num);
00499     found &= AAS_GetVertex(v2, &v2num);
00500     //if one of the vertexes was outside the valid range
00501     if (v1num == -1 || v2num == -1)
00502     {
00503         *edgenum = 0;
00504         return true;
00505     } //end if
00506     //if both vertexes are the same or snapped onto each other
00507     if (v1num == v2num)
00508     {
00509         *edgenum = 0;
00510         return true;
00511     } //end if
00512     //if both vertexes where already stored
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                 } //end if
00528             } //end if
00529             else if (aasworld.edges[i].v[1] == v1num)
00530             {
00531                 if (aasworld.edges[i].v[0] == v2num)
00532                 {
00533                     //negative for a reversed edge
00534                     *edgenum = -i;
00535                     return true;
00536                 } //end if
00537             } //end else
00538         } //end for
00539 #endif //EDGE_HASHING
00540     } //end if
00541     if (aasworld.numedges >= max_aas.max_edges)
00542     {
00543         Error("AAS_MAX_EDGES = %d", max_aas.max_edges);
00544     } //end if
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 } //end of the function AAS_GetEdge
00554 //===========================================================================
00555 //
00556 // Parameter:               -
00557 // Returns:                 -
00558 // Changes Globals:     -
00559 //===========================================================================
00560 int AAS_PlaneTypeForNormal(vec3_t normal)
00561 {
00562     vec_t   ax, ay, az;
00563     
00564     //NOTE: epsilon used
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 } //end of the function AAS_PlaneTypeForNormal
00580 //===========================================================================
00581 //
00582 // Parameter:               -
00583 // Returns:                 -
00584 // Changes Globals:     -
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 } //end of the function AAS_AddPlaneToHash
00599 //===========================================================================
00600 //
00601 // Parameter:               -
00602 // Returns:                 -
00603 // Changes Globals:     -
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                 } //end if
00623             } //end if
00624         } //end if
00625     } //end if
00626     return false;
00627 } //end of the function AAS_PlaneEqual
00628 //===========================================================================
00629 //
00630 // Parameter:               -
00631 // Returns:                 -
00632 // Changes Globals:     -
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         } //end if
00645     } //end for
00646     return false;
00647 } //end of the function AAS_FindPlane
00648 //===========================================================================
00649 //
00650 // Parameter:               -
00651 // Returns:                 -
00652 // Changes Globals:     -
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     //search the border bins as well
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             } //end if
00675         } //end for
00676     } //end for
00677     return false;
00678 } //end of the function AAS_FindHashedPlane
00679 //===========================================================================
00680 //
00681 // Parameter:               -
00682 // Returns:                 -
00683 // Changes Globals:     -
00684 //===========================================================================
00685 qboolean AAS_GetPlane(vec3_t normal, vec_t dist, int *planenum)
00686 {
00687     aas_plane_t *plane, temp;
00688 
00689     //if (AAS_FindPlane(normal, dist, planenum)) return true;
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     } //end if
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     //allways put axial planes facing positive first
00710     if (plane->type < 3)
00711     {
00712         if (plane->normal[0] < 0 || plane->normal[1] < 0 || plane->normal[2] < 0)
00713         {
00714             // flip order
00715             temp = *plane;
00716             *plane = *(plane+1);
00717             *(plane+1) = temp;
00718             *planenum = aasworld.numplanes - 1;
00719             return false;
00720         } //end if
00721     } //end if
00722     *planenum = aasworld.numplanes - 2;
00723     //add the planes to the hash
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     //add the plane to the hash
00736     AAS_AddPlaneToHash(aasworld.numplanes - 1);
00737     return false;
00738 #endif //STOREPLANESDOUBLE
00739 } //end of the function AAS_GetPlane
00740 //===========================================================================
00741 //
00742 // Parameter:               -
00743 // Returns:                 -
00744 // Changes Globals:     -
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     //face zero is a dummy, because of the face index with negative numbers
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     } //end if
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         } //end if
00771         j = (i+1) % w->numpoints;
00772         AAS_GetEdge(w->p[i], w->p[j], &edgenum);
00773         //if the edge wasn't degenerate
00774         if (edgenum)
00775         {
00776             aasworld.edgeindex[aasworld.edgeindexsize++] = edgenum;
00777             face->numedges++;
00778         } //end if
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         } //end else
00784     } //end for
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     } //end if
00795     *facenum = aasworld.numfaces;
00796     aasworld.numfaces++;
00797     return true;
00798 } //end of the function AAS_GetFace
00799 //===========================================================================
00800 //
00801 // Parameter:               -
00802 // Returns:                 -
00803 // Changes Globals:     -
00804 //===========================================================================
00805 /*
00806 qboolean AAS_GetFace(winding_t *w, plane_t *p, int side, int *facenum)
00807 {
00808     aas_edgeindex_t edges[1024];
00809     int planenum, numedges, i;
00810     int j, edgenum;
00811     qboolean foundplane, foundedges;
00812     aas_face_t *face;
00813 
00814     //face zero is a dummy, because of the face index with negative numbers
00815     if (aasworld.numfaces == 0) aasworld.numfaces = 1;
00816 
00817     foundplane = AAS_GetPlane(p->normal, p->dist, &planenum);
00818 
00819     foundedges = true;
00820     numedges = w->numpoints;
00821     for (i = 0; i < w->numpoints; i++)
00822     {
00823         if (i >= 1024) Error("AAS_GetFace: more than %d edges\n", 1024);
00824         foundedges &= AAS_GetEdge(w->p[i], w->p[(i+1 >= w->numpoints ? 0 : i+1)], &edges[i]);
00825     } //end for
00826 
00827     //FIXME: use portal number instead of a search
00828     //if the plane and all edges already existed
00829     if (foundplane && foundedges)
00830     {
00831         for (i = 0; i < aasworld.numfaces; i++)
00832         {
00833             face = &aasworld.faces[i];
00834             if (planenum == face->planenum)
00835             {
00836                 if (numedges == face->numedges)
00837                 {
00838                     for (j = 0; j < numedges; j++)
00839                     {
00840                         edgenum = abs(aasworld.edgeindex[face->firstedge + j]);
00841                         if (abs(edges[i]) != edgenum) break;
00842                     } //end for
00843                     if (j == numedges)
00844                     {
00845                         //jippy found the face
00846                         *facenum = -i;
00847                         return true;
00848                     } //end if
00849                 } //end if
00850             } //end if
00851         } //end for
00852     } //end if
00853     if (aasworld.numfaces >= max_aas.max_faces)
00854     {
00855         Error("AAS_MAX_FACES = %d", max_aas.max_faces);
00856     } //end if
00857     face = &aasworld.faces[aasworld.numfaces];
00858     face->planenum = planenum;
00859     face->faceflags = 0;
00860     face->numedges = numedges;
00861     face->firstedge = aasworld.edgeindexsize;
00862     face->frontarea = 0;
00863     face->backarea = 0;
00864     for (i = 0; i < numedges; i++)
00865     {
00866         if (aasworld.edgeindexsize >= max_aas.max_edgeindexsize)
00867         {
00868             Error("AAS_MAX_EDGEINDEXSIZE = %d", max_aas.max_edgeindexsize);
00869         } //end if
00870         aasworld.edgeindex[aasworld.edgeindexsize++] = edges[i];
00871     } //end for
00872     *facenum = aasworld.numfaces;
00873     aasworld.numfaces++;
00874     return false;
00875 } //end of the function AAS_GetFace*/
00876 //===========================================================================
00877 //
00878 // Parameter:               -
00879 // Returns:                 -
00880 // Changes Globals:     -
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 } //end of the function AAS_StoreAreaSettings
00895 //===========================================================================
00896 //
00897 // Parameter:               -
00898 // Returns:                 -
00899 // Changes Globals:     -
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     //when the area is merged go to the merged area
00914     //FIXME: this isn't necessary anymore because the tree
00915     //          is refreshed after area merging
00916     while(tmparea->mergedarea) tmparea = tmparea->mergedarea;
00917     //
00918     if (tmparea->invalid) Error("AAS_StoreArea: tried to store invalid area");
00919     //if there is an aas area already stored for this tmp area
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     } //end if
00926     //area zero is a dummy
00927     if (aasworld.numareas == 0) aasworld.numareas = 1;
00928     //create an area from this leaf
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 //  Log_Write("tmparea %d became aasarea %d\r\n", tmparea->areanum, aasarea->areanum);
00937     //store the aas area number at the tmp area
00938     tmparea->aasareanum = aasarea->areanum;
00939     //
00940     for (tmpface = tmparea->tmpfaces; tmpface; tmpface = tmpface->next[side])
00941     {
00942         side = tmpface->frontarea != tmparea;
00943         //if there's an aas face created for the tmp face already
00944         if (tmpface->aasfacenum)
00945         {
00946             //we're at the back of the face so use a negative index
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             } //end if
00953 #endif //DEBUG
00954             aasface = &aasworld.faces[tmpface->aasfacenum];
00955             aasface->backarea = aasarea->areanum;
00956         } //end if
00957         else
00958         {
00959             plane = &mapplanes[tmpface->planenum ^ side];
00960             if (side)
00961             {
00962                 w = tmpface->winding;
00963                 tmpface->winding = ReverseWinding(tmpface->winding);
00964             } //end if
00965             if (!AAS_GetFace(tmpface->winding, plane, 0, &aasfacenum)) continue;
00966             if (side)
00967             {
00968                 FreeWinding(tmpface->winding);
00969                 tmpface->winding = w;
00970             } //end if
00971             aasface = &aasworld.faces[aasfacenum];
00972             aasface->frontarea = aasarea->areanum;
00973             aasface->backarea = 0;
00974             aasface->faceflags = tmpface->faceflags;
00975             //set the face number at the tmp face
00976             tmpface->aasfacenum = aasfacenum;
00977         } //end else
00978         //add face points to the area bounds and
00979         //calculate the face 'center'
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             } //end for
00989         } //end for
00990         VectorScale(facecenter, 1.0 / (aasface->numedges * 2.0), facecenter);
00991         //add the face 'center' to the area 'center'
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         } //end if
00998         aasworld.faceindex[aasworld.faceindexsize++] = aasfacenum;
00999         aasarea->numfaces++;
01000     } //end for
01001     //if the area has no faces at all (return 0, = solid leaf)
01002     if (!aasarea->numfaces) return 0;
01003     //
01004     VectorScale(aasarea->center, 1.0 / aasarea->numfaces, aasarea->center);
01005     //Log_Write("area %d center %f %f %f\r\n", aasworld.numareas,
01006     //              aasarea->center[0], aasarea->center[1], aasarea->center[2]);
01007     //store the area settings
01008     AAS_StoreAreaSettings(tmparea->settings);
01009     //
01010     //Log_Write("tmp area %d became aas area %d\r\n", tmpareanum, aasarea->areanum);
01011     qprintf("\r%6d", aasarea->areanum);
01012     //
01013     aasworld.numareas++;
01014     return -(aasworld.numareas - 1);
01015 } //end of the function AAS_StoreArea
01016 //===========================================================================
01017 //
01018 // Parameter:               -
01019 // Returns:                 -
01020 // Changes Globals:     -
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     //if it is a solid leaf
01029     if (!tmpnode) return 0;
01030     //negative so it's an area
01031     if (tmpnode->tmparea) return AAS_StoreArea(tmpnode->tmparea);
01032     //it's another node
01033     //the first node is a dummy
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     } //end if
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 } //end of the function AAS_StoreTree_r
01047 //===========================================================================
01048 //
01049 // Parameter:               -
01050 // Returns:                 -
01051 // Changes Globals:     -
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     } //end if
01059     aasworld.numbboxes = cfg.numbboxes;
01060     memcpy(aasworld.bboxes, cfg.bboxes, cfg.numbboxes * sizeof(aas_bbox_t));
01061 } //end of the function AAS_StoreBoundingBoxes
01062 //===========================================================================
01063 //
01064 // Parameter:               -
01065 // Returns:                 -
01066 // Changes Globals:     -
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     //start with node 1 because node zero is a dummy
01078     AAS_StoreTree_r(tmpaasworld.nodes);
01079     qprintf("\n");
01080     Log_Write("%6d areas stored\r\n", aasworld.numareas);
01081     aasworld.loaded = true;
01082 } //end of the function AAS_StoreFile

Generated on Thu Aug 25 12:37:14 2005 for Quake III Arena by  doxygen 1.3.9.1