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

aas_create.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_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 //#define AW_DEBUG
00036 //#define L_DEBUG
00037 
00038 #define AREAONFACESIDE(face, area)      (face->frontarea != area)
00039 
00040 tmp_aas_t tmpaasworld;
00041 
00042 //===========================================================================
00043 //
00044 // Parameter:               -
00045 // Returns:                 -
00046 // Changes Globals:     -
00047 //===========================================================================
00048 void AAS_InitTmpAAS(void)
00049 {
00050     //tmp faces
00051     tmpaasworld.numfaces = 0;
00052     tmpaasworld.facenum = 0;
00053     tmpaasworld.faces = NULL;
00054     //tmp convex areas
00055     tmpaasworld.numareas = 0;
00056     tmpaasworld.areanum = 0;
00057     tmpaasworld.areas = NULL;
00058     //tmp nodes
00059     tmpaasworld.numnodes = 0;
00060     tmpaasworld.nodes = NULL;
00061     //
00062     tmpaasworld.nodebuffer = NULL;
00063 } //end of the function AAS_InitTmpAAS
00064 //===========================================================================
00065 //
00066 // Parameter:               -
00067 // Returns:                 -
00068 // Changes Globals:     -
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     //free all the faces
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     } //end if
00083     //free all tmp areas
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     } //end for
00090     //free all the tmp nodes
00091     for (nb = tmpaasworld.nodebuffer; nb; nb = nextnb)
00092     {
00093         nextnb = nb->next;
00094         FreeMemory(nb);
00095     } //end for
00096 } //end of the function AAS_FreeTmpAAS
00097 //===========================================================================
00098 //
00099 // Parameter:               -
00100 // Returns:                 -
00101 // Changes Globals:     -
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 } //end of the function AAS_AllocTmpFace
00116 //===========================================================================
00117 //
00118 // Parameter:               -
00119 // Returns:                 -
00120 // Changes Globals:     -
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     //free the winding
00128     if (tmpface->winding) FreeWinding(tmpface->winding);
00129     //free the face
00130     FreeMemory(tmpface);
00131     tmpaasworld.numfaces--;
00132 } //end of the function AAS_FreeTmpFace
00133 //===========================================================================
00134 //
00135 // Parameter:               -
00136 // Returns:                 -
00137 // Changes Globals:     -
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 } //end of the function AAS_AllocTmpArea
00152 //===========================================================================
00153 //
00154 // Parameter:               -
00155 // Returns:                 -
00156 // Changes Globals:     -
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 } //end of the function AAS_FreeTmpArea
00167 //===========================================================================
00168 //
00169 // Parameter:               -
00170 // Returns:                 -
00171 // Changes Globals:     -
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     } //end if
00185     tmpaasworld.numnodes++;
00186     return &tmpaasworld.nodebuffer->nodes[tmpaasworld.nodebuffer->numnodes++];
00187 } //end of the function AAS_AllocTmpNode
00188 //===========================================================================
00189 //
00190 // Parameter:               -
00191 // Returns:                 -
00192 // Changes Globals:     -
00193 //===========================================================================
00194 void AAS_FreeTmpNode(tmp_node_t *tmpnode)
00195 {
00196     tmpaasworld.numnodes--;
00197 } //end of the function AAS_FreeTmpNode
00198 //===========================================================================
00199 // returns true if the face is a gap from the given side
00200 //
00201 // Parameter:               -
00202 // Returns:                 -
00203 // Changes Globals:     -
00204 //===========================================================================
00205 int AAS_GapFace(tmp_face_t *tmpface, int side)
00206 {
00207     vec3_t invgravity;
00208 
00209     //if the face is a solid or ground face it can't be a gap
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 } //end of the function AAS_GapFace
00217 //===========================================================================
00218 // returns true if the face is a ground face
00219 //
00220 // Parameter:               -
00221 // Returns:                 -
00222 // Changes Globals:     -
00223 //===========================================================================
00224 int AAS_GroundFace(tmp_face_t *tmpface)
00225 {
00226     vec3_t invgravity;
00227 
00228     //must be a solid face
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 } //end of the function AAS_GroundFace
00236 //===========================================================================
00237 // adds the side of a face to an area
00238 //
00239 // side :   0 = front side
00240 //              1 = back side
00241 //
00242 // Parameter:               -
00243 // Returns:                 -
00244 // Changes Globals:     -
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     } //end if
00254     else
00255     {
00256         if (tmpface->frontarea) Error("AAS_AddFaceSideToArea: already a front area\n");
00257     } //end else
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     } //end if
00267     tmpface->next[side] = tmparea->tmpfaces;
00268     tmpface->prev[side] = NULL;
00269     tmparea->tmpfaces = tmpface;
00270 } //end of the function AAS_AddFaceSideToArea
00271 //===========================================================================
00272 // remove (a side of) a face from an area
00273 //
00274 // Parameter:               -
00275 // Returns:                 -
00276 // Changes Globals:     -
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     } //end if
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     } //end if
00293     else
00294     {
00295         tmparea->tmpfaces = tmpface->next[side];
00296     } //end else
00297     if (tmpface->next[side])
00298     {
00299         nextside = tmpface->next[side]->frontarea != tmparea;
00300         tmpface->next[side]->prev[nextside] = tmpface->prev[side];
00301     } //end if
00302     //remove the area number from the face depending on the side
00303     if (side) tmpface->backarea = NULL;
00304     else tmpface->frontarea = NULL;
00305     tmpface->prev[side] = NULL;
00306     tmpface->next[side] = NULL;
00307 } //end of the function AAS_RemoveFaceFromArea
00308 //===========================================================================
00309 //
00310 // Parameter:               -
00311 // Returns:                 -
00312 // Changes Globals:     -
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         //side of the face the area is on
00327         side = face->frontarea != tmparea;
00328         WindingCenter(face->winding, wcenter);
00329         VectorAdd(acenter, wcenter, acenter);
00330         n++;
00331     } //end for
00332     n = 1 / n;
00333     VectorScale(acenter, n, acenter);
00334     for (face = tmparea->tmpfaces; face; face = face->next[side])
00335     {
00336         //side of the face the area is on
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         } //end if
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         } //end if
00354         //check if the winding plane is the same as the face plane
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         } //end if
00366 #endif L_DEBUG
00367     } //end for
00368 } //end of the function AAS_CheckArea
00369 //===========================================================================
00370 //
00371 // Parameter:               -
00372 // Returns:                 -
00373 // Changes Globals:     -
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     //check if the winding plane is the same as the face plane
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             } //end if
00413         } //end if
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         } //end else
00422     } //end if
00423 } //end of the function AAS_CheckFaceWindingPlane
00424 //===========================================================================
00425 //
00426 // Parameter:               -
00427 // Returns:                 -
00428 // Changes Globals:     -
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         } //end for
00445     } //end for
00446 } //end of the function AAS_CheckAreaWindingPlanes
00447 //===========================================================================
00448 //
00449 // Parameter:               -
00450 // Returns:                 -
00451 // Changes Globals:     -
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     //winding_t *w;
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         //side of the face the area is on
00466         side = face->frontarea != tmparea;
00467         WindingCenter(face->winding, wcenter);
00468         VectorAdd(acenter, wcenter, acenter);
00469         n++;
00470     } //end for
00471     n = 1 / n;
00472     VectorScale(acenter, n, acenter);
00473     for (face = tmparea->tmpfaces; face; face = face->next[side])
00474     {
00475         //side of the face the area is on
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             face->planenum = face->planenum ^ 1;
00487             w = face->winding;
00488             face->winding = ReverseWinding(w);
00489             FreeWinding(w);
00490             */
00491         } //end if
00492 #ifdef L_DEBUG
00493         {
00494             float dist;
00495             vec3_t normal;
00496 
00497             //check if the winding plane is the same as the face plane
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             } //end if
00508         }
00509 #endif
00510     } //end for
00511 } //end of the function AAS_FlipAreaFaces
00512 //===========================================================================
00513 //
00514 // Parameter:               -
00515 // Returns:                 -
00516 // Changes Globals:     -
00517 //===========================================================================
00518 void AAS_RemoveAreaFaceColinearPoints(void)
00519 {
00520     int side;
00521     tmp_face_t *face;
00522     tmp_area_t *tmparea;
00523 
00524     //FIXME: loop over the faces instead of area->faces
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 //          RemoveEqualPoints(face->winding, 0.1);
00532         } //end for
00533     } //end for
00534 } //end of the function AAS_RemoveAreaFaceColinearPoints
00535 //===========================================================================
00536 //
00537 // Parameter:               -
00538 // Returns:                 -
00539 // Changes Globals:     -
00540 //===========================================================================
00541 void AAS_RemoveTinyFaces(void)
00542 {
00543     int side, num;
00544     tmp_face_t *face, *nextface;
00545     tmp_area_t *tmparea;
00546 
00547     //FIXME: loop over the faces instead of area->faces
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                 //Log_Write("area %d face %d is tiny\r\n", tmparea->areanum, face->num);
00563                 num++;
00564             } //end if
00565         } //end for
00566     } //end for
00567     Log_Write("%d tiny faces removed\r\n", num);
00568 } //end of the function AAS_RemoveTinyFaces
00569 //===========================================================================
00570 //
00571 // Parameter:               -
00572 // Returns:                 -
00573 // Changes Globals:     -
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         //if the area is invalid there no need to create settings for it
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         } //end for
00601         tmparea->settings->areaflags = 0;
00602         if (flags & FACE_GROUND)
00603         {
00604             tmparea->settings->areaflags |= AREA_GROUNDED;
00605             numgrounded++;
00606         } //end if
00607         if (flags & FACE_LADDER)
00608         {
00609             tmparea->settings->areaflags |= AREA_LADDER;
00610             numladderareas++;
00611         } //end if
00612         if (tmparea->contents & (AREACONTENTS_WATER |
00613                                             AREACONTENTS_SLIME |
00614                                             AREACONTENTS_LAVA))
00615         {
00616             tmparea->settings->areaflags |= AREA_LIQUID;
00617             numliquidareas++;
00618         } //end if
00619         //presence type of the area
00620         tmparea->settings->presencetype = tmparea->presencetype;
00621         //
00622         qprintf("\r%6d", ++i);
00623     } //end for
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 } //end of the function AAS_CreateAreaSettings
00631 //===========================================================================
00632 // create a tmp AAS area from a leaf node
00633 //
00634 // Parameter:               -
00635 // Returns:                 -
00636 // Changes Globals:     -
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     //create an area from this leaf
00649     tmparea = AAS_AllocTmpArea();
00650     tmparea->tmpfaces = NULL;
00651     //clear the area face flags
00652     areafaceflags = 0;
00653     //make aas faces from the portals
00654     for (p = node->portals; p; p = p->next[pside])
00655     {
00656         pside = (p->nodes[1] == node);
00657         //don't create faces from very small portals
00658 //      if (WindingArea(p->winding) < 1) continue;
00659         //if there's already a face created for this portal
00660         if (p->tmpface)
00661         {
00662             //add the back side of the face to the area
00663             AAS_AddFaceSideToArea(p->tmpface, 1, tmparea);
00664         } //end if
00665         else
00666         {
00667             tmpface = AAS_AllocTmpFace();
00668             //set the face pointer at the portal so we can see from
00669             //the portal there's a face created for it
00670             p->tmpface = tmpface;
00671             //FIXME: test this change
00672             //tmpface->planenum = (p->planenum & ~1) | pside;
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             //if there's solid at the other side of the portal
00681             if (p->nodes[!pside]->contents & (CONTENTS_SOLID | CONTENTS_PLAYERCLIP))
00682             {
00683                 tmpface->faceflags |= FACE_SOLID;
00684             } //end if
00685             //else there is no solid at the other side and if there
00686             //is a liquid at this side
00687             else if (node->contents & (CONTENTS_WATER|CONTENTS_SLIME|CONTENTS_LAVA))
00688             {
00689                 tmpface->faceflags |= FACE_LIQUID;
00690                 //if there's no liquid at the other side
00691                 if (!(p->nodes[!pside]->contents & (CONTENTS_WATER|CONTENTS_SLIME|CONTENTS_LAVA)))
00692                 {
00693                     tmpface->faceflags |= FACE_LIQUIDSURFACE;
00694                 } //end if
00695             } //end else
00696             //if there's ladder contents at other side of the portal
00697             if ((p->nodes[pside]->contents & CONTENTS_LADDER) ||
00698                     (p->nodes[!pside]->contents & CONTENTS_LADDER))
00699             {
00700 
00701                 //NOTE: doesn't have to be solid at the other side because
00702                 // when standing one can use a crouch area (which is not solid)
00703                 // as a ladder
00704                 // imagine a ladder one can walk underthrough,
00705                 // under the ladder against the ladder is a crouch area
00706                 // the (vertical) sides of this crouch area area also used as
00707                 // ladder sides when standing (not crouched)
00708                 tmpface->faceflags |= FACE_LADDER;
00709             } //end if
00710             //if it is possible to stand on the face
00711             if (AAS_GroundFace(tmpface))
00712             {
00713                 tmpface->faceflags |= FACE_GROUND;
00714             } //end if
00715             //
00716             areafaceflags |= tmpface->faceflags;
00717             //no aas face number yet (zero is a dummy in the aasworld faces)
00718             tmpface->aasfacenum = 0;
00719             //add the front side of the face to the area
00720             AAS_AddFaceSideToArea(tmpface, 0, tmparea);
00721         } //end else
00722     } //end for
00723     qprintf("\r%6d", tmparea->areanum);
00724     //presence type in the area
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     //store the bsp model that's inside this node
00740     tmparea->modelnum = node->modelnum;
00741     //sorta check for flipped area faces (remove??)
00742     AAS_FlipAreaFaces(tmparea);
00743     //check if the area is ok (remove??)
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 } //end of the function AAS_CreateArea
00754 //===========================================================================
00755 //
00756 // Parameter:               -
00757 // Returns:                 -
00758 // Changes Globals:     -
00759 //===========================================================================
00760 tmp_node_t *AAS_CreateAreas_r(node_t *node)
00761 {
00762     tmp_node_t *tmpnode;
00763 
00764     //recurse down to leafs
00765     if (node->planenum != PLANENUM_LEAF)
00766     {
00767         //the first tmp node is a dummy
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     } //end if
00774     //areas won't be created for solid leafs
00775     if (node->contents & CONTENTS_SOLID)
00776     {
00777         //just return zero for a solid leaf (in tmp AAS NULL is a solid leaf)
00778         return NULL;
00779     } //end if
00780 
00781     return AAS_CreateArea(node);
00782 } //end of the function AAS_CreateAreas_r
00783 //===========================================================================
00784 //
00785 // Parameter:               -
00786 // Returns:                 -
00787 // Changes Globals:     -
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 } //end of the function AAS_CreateAreas
00797 //===========================================================================
00798 //
00799 // Parameter:               -
00800 // Returns:                 -
00801 // Changes Globals:     -
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         } //end if
00814     } //end for
00815     qprintf("%6d ground faces\n", numgroundfaces);
00816 } //end of the function AAS_PrintNumGroundFaces
00817 //===========================================================================
00818 // checks the number of shared faces between the given two areas
00819 // since areas are convex they should only have ONE shared face
00820 // however due to crappy face merging there are sometimes several
00821 // shared faces
00822 //
00823 // Parameter:               -
00824 // Returns:                 -
00825 // Changes Globals:     -
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         } //end if
00844     } //end if
00845     if (!sharedface) return;
00846     //the areas should only have one shared face
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             } //end if
00859         } //end if
00860     } //end if
00861 } //end of the function AAS_CheckAreaSharedFaces
00862 //===========================================================================
00863 //
00864 // Parameter:               -
00865 // Returns:                 -
00866 // Changes Globals:     -
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         } //end for
00879     } //end for
00880 } //end of the function AAS_CheckSharedFaces
00881 //===========================================================================
00882 //
00883 // Parameter:               -
00884 // Returns:                 -
00885 // Changes Globals:     -
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     //must have an area at both sides before flipping is allowed
00895     if (!frontarea || !backarea) return;
00896     //flip the face winding
00897     w = face->winding;
00898     face->winding = ReverseWinding(w);
00899     FreeWinding(w);
00900     //flip the face plane
00901     face->planenum ^= 1;
00902     //flip the face areas
00903     AAS_RemoveFaceFromArea(face, frontarea);
00904     AAS_RemoveFaceFromArea(face, backarea);
00905     AAS_AddFaceSideToArea(face, 1, frontarea);
00906     AAS_AddFaceSideToArea(face, 0, backarea);
00907 } //end of the function AAS_FlipFace
00908 //===========================================================================
00909 //
00910 // Parameter:               -
00911 // Returns:                 -
00912 // Changes Globals:     -
00913 //===========================================================================
00914 /*
00915 void AAS_FlipAreaSharedFaces(tmp_area_t *tmparea1, tmp_area_t *tmparea2)
00916 {
00917     int numsharedfaces, side, area1facing, area2facing;
00918     tmp_face_t *face1, *sharedface;
00919 
00920     if (tmparea1->invalid || tmparea2->invalid) return;
00921 
00922     sharedface = NULL;
00923     numsharedfaces = 0;
00924     area1facing = 0;        //number of shared faces facing towards area 1
00925     area2facing = 0;        //number of shared faces facing towards area 2
00926     for (face1 = tmparea1->tmpfaces; face1; face1 = face1->next[side])
00927     {
00928         side = face1->frontarea != tmparea1;
00929         if (face1->backarea == tmparea2 || face1->frontarea == tmparea2)
00930         {
00931             sharedface = face1;
00932             numsharedfaces++;
00933             if (face1->frontarea == tmparea1) area1facing++;
00934             else area2facing++;
00935         } //end if
00936     } //end if
00937     if (!sharedface) return;
00938     //if there's only one shared face
00939     if (numsharedfaces <= 1) return;
00940     //if all the shared faces are facing to the same area
00941     if (numsharedfaces == area1facing || numsharedfaces == area2facing) return;
00942     //
00943     do
00944     {
00945         for (face1 = tmparea1->tmpfaces; face1; face1 = face1->next[side])
00946         {
00947             side = face1->frontarea != tmparea1;
00948             if (face1->backarea == tmparea2 || face1->frontarea == tmparea2)
00949             {
00950                 if (face1->frontarea != tmparea1)
00951                 {
00952                     AAS_FlipFace(face1);
00953                     break;
00954                 } //end if
00955             } //end if
00956         } //end for
00957     } while(face1);
00958 } //end of the function AAS_FlipAreaSharedFaces
00959 //===========================================================================
00960 //
00961 // Parameter:               -
00962 // Returns:                 -
00963 // Changes Globals:     -
00964 //===========================================================================
00965 void AAS_FlipSharedFaces(void)
00966 {
00967     int i;
00968     tmp_area_t *tmparea1, *tmparea2;
00969 
00970     i = 0;
00971     qprintf("%6d areas checked for shared face flipping", i);
00972     for (tmparea1 = tmpaasworld.areas; tmparea1; tmparea1 = tmparea1->l_next)
00973     {
00974         if (tmparea1->invalid) continue;
00975         for (tmparea2 = tmpaasworld.areas; tmparea2; tmparea2 = tmparea2->l_next)
00976         {
00977             if (tmparea2->invalid) continue;
00978             if (tmparea1 == tmparea2) continue;
00979             AAS_FlipAreaSharedFaces(tmparea1, tmparea2);
00980         } //end for
00981         qprintf("\r%6d", ++i);
00982     } //end for
00983     Log_Print("\r%6d areas checked for shared face flipping\n", i);
00984 } //end of the function AAS_FlipSharedFaces
00985 */
00986 //===========================================================================
00987 //
00988 // Parameter:               -
00989 // Returns:                 -
00990 // Changes Globals:     -
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                 } //end if
01018                 //recheck side
01019                 side2 = face2->frontarea != tmparea1;
01020             } //end for
01021         } //end for
01022         qprintf("\r%6d", ++i);
01023     } //end for
01024     qprintf("\n");
01025     Log_Write("%6d areas checked for shared face flipping\r\n", i);
01026 } //end of the function AAS_FlipSharedFaces
01027 //===========================================================================
01028 // creates an .AAS file with the given name
01029 // a MAP should be loaded before calling this
01030 //
01031 // Parameter:               -
01032 // Returns:                 -
01033 // Changes Globals:     -
01034 //===========================================================================
01035 void AAS_Create(char *aasfile)
01036 {
01037     entity_t    *e;
01038     tree_t *tree;
01039     double start_time;
01040 
01041     //for a possible leak file
01042     strcpy(source, aasfile);
01043     StripExtension(source);
01044     //the time started
01045     start_time = I_FloatTime();
01046     //set the default number of threads (depends on number of processors)
01047     ThreadSetDefault();
01048     //set the global entity number to the world model
01049     entity_num = 0;
01050     //the world entity
01051     e = &entities[entity_num];
01052     //process the whole world
01053     tree = ProcessWorldBrushes(e->firstbrush, e->firstbrush + e->numbrushes);
01054     //if the conversion is cancelled
01055     if (cancelconversion)
01056     {
01057         Tree_Free(tree);
01058         return;
01059     } //end if
01060     //display BSP tree creation time
01061     Log_Print("BSP tree created in %5.0f seconds\n", I_FloatTime() - start_time);
01062     //prune the bsp tree
01063     Tree_PruneNodes(tree->headnode);
01064     //if the conversion is cancelled
01065     if (cancelconversion)
01066     {
01067         Tree_Free(tree);
01068         return;
01069     } //end if
01070     //create the tree portals
01071     MakeTreePortals(tree);
01072     //if the conversion is cancelled
01073     if (cancelconversion)
01074     {
01075         Tree_Free(tree);
01076         return;
01077     } //end if
01078     //Marks all nodes that can be reached by entites
01079     if (FloodEntities(tree))
01080     {
01081         //fill out nodes that can't be reached
01082         FillOutside(tree->headnode);
01083     } //end if
01084     else
01085     {
01086         LeakFile(tree);
01087         Error("**** leaked ****\n");
01088         return;
01089     } //end else
01090     //create AAS from the BSP tree
01091     //==========================================
01092     //initialize tmp aas
01093     AAS_InitTmpAAS();
01094     //create the convex areas from the leaves
01095     AAS_CreateAreas(tree->headnode);
01096     //free the BSP tree because it isn't used anymore
01097     if (freetree) Tree_Free(tree);
01098     //try to merge area faces
01099     AAS_MergeAreaFaces();
01100     //do gravitational subdivision
01101     AAS_GravitationalSubdivision();
01102     //merge faces if possible
01103     AAS_MergeAreaFaces();
01104     AAS_RemoveAreaFaceColinearPoints();
01105     //merge areas if possible
01106     AAS_MergeAreas();
01107     //NOTE: prune nodes directly after area merging
01108     AAS_PruneNodes();
01109     //flip shared faces so they are all facing to the same area
01110     AAS_FlipSharedFaces();
01111     AAS_RemoveAreaFaceColinearPoints();
01112     //merge faces if possible
01113     AAS_MergeAreaFaces();
01114     //merge area faces in the same plane
01115     AAS_MergeAreaPlaneFaces();
01116     //do ladder subdivision
01117     AAS_LadderSubdivision();
01118     //FIXME: melting is buggy
01119     AAS_MeltAreaFaceWindings();
01120     //remove tiny faces
01121     AAS_RemoveTinyFaces();
01122     //create area settings
01123     AAS_CreateAreaSettings();
01124     //check if the winding plane is equal to the face plane
01125     //AAS_CheckAreaWindingPlanes();
01126     //
01127     //AAS_CheckSharedFaces();
01128     //==========================================
01129     //if the conversion is cancelled
01130     if (cancelconversion)
01131     {
01132         Tree_Free(tree);
01133         AAS_FreeTmpAAS();
01134         return;
01135     } //end if
01136     //store the created AAS stuff in the AAS file format and write the file
01137     AAS_StoreFile(aasfile);
01138     //free the temporary AAS memory
01139     AAS_FreeTmpAAS();
01140     //display creation time
01141     Log_Print("\nAAS created in %5.0f seconds\n", I_FloatTime() - start_time);
01142 } //end of the function AAS_Create

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