aboutsummaryrefslogtreecommitdiffstats
path: root/code/bspc/aas_areamerging.c
diff options
context:
space:
mode:
Diffstat (limited to 'code/bspc/aas_areamerging.c')
-rwxr-xr-xcode/bspc/aas_areamerging.c780
1 files changed, 390 insertions, 390 deletions
diff --git a/code/bspc/aas_areamerging.c b/code/bspc/aas_areamerging.c
index c5f82d2..f9de65f 100755
--- a/code/bspc/aas_areamerging.c
+++ b/code/bspc/aas_areamerging.c
@@ -1,390 +1,390 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Foobar; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-
-#include "qbsp.h"
-#include "../botlib/aasfile.h"
-#include "aas_create.h"
-#include "aas_store.h"
-
-#define CONVEX_EPSILON 0.3
-
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-tmp_node_t *AAS_RefreshMergedTree_r(tmp_node_t *tmpnode)
-{
- tmp_area_t *tmparea;
-
- //if this is a solid leaf
- if (!tmpnode) return NULL;
- //if this is an area leaf
- if (tmpnode->tmparea)
- {
- tmparea = tmpnode->tmparea;
- while(tmparea->mergedarea) tmparea = tmparea->mergedarea;
- tmpnode->tmparea = tmparea;
- return tmpnode;
- } //end if
- //do the children recursively
- tmpnode->children[0] = AAS_RefreshMergedTree_r(tmpnode->children[0]);
- tmpnode->children[1] = AAS_RefreshMergedTree_r(tmpnode->children[1]);
- return tmpnode;
-} //end of the function AAS_RefreshMergedTree_r
-//===========================================================================
-// returns true if the two given faces would create a non-convex area at
-// the given sides, otherwise false is returned
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-int NonConvex(tmp_face_t *face1, tmp_face_t *face2, int side1, int side2)
-{
- int i;
- winding_t *w1, *w2;
- plane_t *plane1, *plane2;
-
- w1 = face1->winding;
- w2 = face2->winding;
-
- plane1 = &mapplanes[face1->planenum ^ side1];
- plane2 = &mapplanes[face2->planenum ^ side2];
-
- //check if one of the points of face1 is at the back of the plane of face2
- for (i = 0; i < w1->numpoints; i++)
- {
- if (DotProduct(plane2->normal, w1->p[i]) - plane2->dist < -CONVEX_EPSILON) return true;
- } //end for
- //check if one of the points of face2 is at the back of the plane of face1
- for (i = 0; i < w2->numpoints; i++)
- {
- if (DotProduct(plane1->normal, w2->p[i]) - plane1->dist < -CONVEX_EPSILON) return true;
- } //end for
-
- return false;
-} //end of the function NonConvex
-//===========================================================================
-// try to merge the areas at both sides of the given face
-//
-// Parameter: seperatingface : face that seperates two areas
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-int AAS_TryMergeFaceAreas(tmp_face_t *seperatingface)
-{
- int side1, side2, area1faceflags, area2faceflags;
- tmp_area_t *tmparea1, *tmparea2, *newarea;
- tmp_face_t *face1, *face2, *nextface1, *nextface2;
-
- tmparea1 = seperatingface->frontarea;
- tmparea2 = seperatingface->backarea;
-
- //areas must have the same presence type
- if (tmparea1->presencetype != tmparea2->presencetype) return false;
- //areas must have the same area contents
- if (tmparea1->contents != tmparea2->contents) return false;
- //areas must have the same bsp model inside (or both none)
- if (tmparea1->modelnum != tmparea2->modelnum) return false;
-
- area1faceflags = 0;
- area2faceflags = 0;
- for (face1 = tmparea1->tmpfaces; face1; face1 = face1->next[side1])
- {
- side1 = (face1->frontarea != tmparea1);
- //debug: check if the area belongs to the area
- if (face1->frontarea != tmparea1 &&
- face1->backarea != tmparea1) Error("face does not belong to area1");
- //just continue if the face is seperating the two areas
- //NOTE: a result of this is that ground and gap areas can
- // be merged if the seperating face is the gap
- if ((face1->frontarea == tmparea1 &&
- face1->backarea == tmparea2) ||
- (face1->frontarea == tmparea2 &&
- face1->backarea == tmparea1)) continue;
- //get area1 face flags
- area1faceflags |= face1->faceflags;
- if (AAS_GapFace(face1, side1)) area1faceflags |= FACE_GAP;
- //
- for (face2 = tmparea2->tmpfaces; face2; face2 = face2->next[side2])
- {
- side2 = (face2->frontarea != tmparea2);
- //debug: check if the area belongs to the area
- if (face2->frontarea != tmparea2 &&
- face2->backarea != tmparea2) Error("face does not belong to area2");
- //just continue if the face is seperating the two areas
- //NOTE: a result of this is that ground and gap areas can
- // be merged if the seperating face is the gap
- if ((face2->frontarea == tmparea1 &&
- face2->backarea == tmparea2) ||
- (face2->frontarea == tmparea2 &&
- face2->backarea == tmparea1)) continue;
- //get area2 face flags
- area2faceflags |= face2->faceflags;
- if (AAS_GapFace(face2, side2)) area2faceflags |= FACE_GAP;
- //if the two faces would create a non-convex area
- if (NonConvex(face1, face2, side1, side2)) return false;
- } //end for
- } //end for
- //if one area has gap faces (that aren't seperating the two areas)
- //and the other has ground faces (that aren't seperating the two areas),
- //the areas can't be merged
- if (((area1faceflags & FACE_GROUND) && (area2faceflags & FACE_GAP)) ||
- ((area2faceflags & FACE_GROUND) && (area1faceflags & FACE_GAP)))
- {
-// Log_Print(" can't merge: ground/gap\n");
- return false;
- } //end if
-
-// Log_Print("merged area %d & %d to %d with %d faces\n", tmparea1->areanum, tmparea2->areanum, newarea->areanum, numfaces);
-// return false;
- //
- //AAS_CheckArea(tmparea1);
- //AAS_CheckArea(tmparea2);
- //create the new area
- newarea = AAS_AllocTmpArea();
- newarea->presencetype = tmparea1->presencetype;
- newarea->contents = tmparea1->contents;
- newarea->modelnum = tmparea1->modelnum;
- newarea->tmpfaces = NULL;
-
- //add all the faces (except the seperating ones) from the first area
- //to the new area
- for (face1 = tmparea1->tmpfaces; face1; face1 = nextface1)
- {
- side1 = (face1->frontarea != tmparea1);
- nextface1 = face1->next[side1];
- //don't add seperating faces
- if ((face1->frontarea == tmparea1 &&
- face1->backarea == tmparea2) ||
- (face1->frontarea == tmparea2 &&
- face1->backarea == tmparea1))
- {
- continue;
- } //end if
- //
- AAS_RemoveFaceFromArea(face1, tmparea1);
- AAS_AddFaceSideToArea(face1, side1, newarea);
- } //end for
- //add all the faces (except the seperating ones) from the second area
- //to the new area
- for (face2 = tmparea2->tmpfaces; face2; face2 = nextface2)
- {
- side2 = (face2->frontarea != tmparea2);
- nextface2 = face2->next[side2];
- //don't add seperating faces
- if ((face2->frontarea == tmparea1 &&
- face2->backarea == tmparea2) ||
- (face2->frontarea == tmparea2 &&
- face2->backarea == tmparea1))
- {
- continue;
- } //end if
- //
- AAS_RemoveFaceFromArea(face2, tmparea2);
- AAS_AddFaceSideToArea(face2, side2, newarea);
- } //end for
- //free all shared faces
- for (face1 = tmparea1->tmpfaces; face1; face1 = nextface1)
- {
- side1 = (face1->frontarea != tmparea1);
- nextface1 = face1->next[side1];
- //
- AAS_RemoveFaceFromArea(face1, face1->frontarea);
- AAS_RemoveFaceFromArea(face1, face1->backarea);
- AAS_FreeTmpFace(face1);
- } //end for
- //
- tmparea1->mergedarea = newarea;
- tmparea1->invalid = true;
- tmparea2->mergedarea = newarea;
- tmparea2->invalid = true;
- //
- AAS_CheckArea(newarea);
- AAS_FlipAreaFaces(newarea);
-// Log_Print("merged area %d & %d to %d with %d faces\n", tmparea1->areanum, tmparea2->areanum, newarea->areanum);
- return true;
-} //end of the function AAS_TryMergeFaceAreas
-//===========================================================================
-// try to merge areas
-// merged areas are added to the end of the convex area list so merging
-// will be tried for those areas as well
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: tmpaasworld
-//===========================================================================
-/*
-void AAS_MergeAreas(void)
-{
- int side, nummerges;
- tmp_area_t *tmparea, *othertmparea;
- tmp_face_t *face;
-
- nummerges = 0;
- Log_Write("AAS_MergeAreas\r\n");
- qprintf("%6d areas merged", 1);
- //first merge grounded areas only
- //NOTE: this is useless because the area settings aren't available yet
- for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next)
- {
-// Log_Print("checking area %d\n", i);
- //if the area is invalid
- if (tmparea->invalid)
- {
-// Log_Print(" area invalid\n");
- continue;
- } //end if
- //
-// if (!(tmparea->settings->areaflags & AREA_GROUNDED)) continue;
- //
- for (face = tmparea->tmpfaces; face; face = face->next[side])
- {
- side = (face->frontarea != tmparea);
- //if the face has both a front and back area
- if (face->frontarea && face->backarea)
- {
- //
- if (face->frontarea == tmparea) othertmparea = face->backarea;
- else othertmparea = face->frontarea;
-// if (!(othertmparea->settings->areaflags & AREA_GROUNDED)) continue;
-// Log_Print(" checking area %d with %d\n", face->frontarea, face->backarea);
- if (AAS_TryMergeFaceAreas(face))
- {
- qprintf("\r%6d", ++nummerges);
- break;
- } //end if
- } //end if
- } //end for
- } //end for
- //merge all areas
- for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next)
- {
-// Log_Print("checking area %d\n", i);
- //if the area is invalid
- if (tmparea->invalid)
- {
-// Log_Print(" area invalid\n");
- continue;
- } //end if
- //
- for (face = tmparea->tmpfaces; face; face = face->next[side])
- {
- side = (face->frontarea != tmparea);
- //if the face has both a front and back area
- if (face->frontarea && face->backarea)
- {
-// Log_Print(" checking area %d with %d\n", face->frontarea, face->backarea);
- if (AAS_TryMergeFaceAreas(face))
- {
- qprintf("\r%6d", ++nummerges);
- break;
- } //end if
- } //end if
- } //end for
- } //end for
- Log_Print("\r%6d areas merged\n", nummerges);
- //refresh the merged tree
- AAS_RefreshMergedTree_r(tmpaasworld.nodes);
-} //end of the function AAS_MergeAreas*/
-
-int AAS_GroundArea(tmp_area_t *tmparea)
-{
- tmp_face_t *face;
- int side;
-
- for (face = tmparea->tmpfaces; face; face = face->next[side])
- {
- side = (face->frontarea != tmparea);
- if (face->faceflags & FACE_GROUND) return true;
- } //end for
- return false;
-} //end of the function AAS_GroundArea
-
-void AAS_MergeAreas(void)
-{
- int side, nummerges, merges, groundfirst;
- tmp_area_t *tmparea, *othertmparea;
- tmp_face_t *face;
-
- nummerges = 0;
- Log_Write("AAS_MergeAreas\r\n");
- qprintf("%6d areas merged", 1);
- //
- groundfirst = true;
- //for (i = 0; i < 4 || merges; i++)
- while(1)
- {
- //if (i < 2) groundfirst = true;
- //else groundfirst = false;
- //
- merges = 0;
- //first merge grounded areas only
- for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next)
- {
- //if the area is invalid
- if (tmparea->invalid)
- {
- continue;
- } //end if
- //
- if (groundfirst)
- {
- if (!AAS_GroundArea(tmparea)) continue;
- } //end if
- //
- for (face = tmparea->tmpfaces; face; face = face->next[side])
- {
- side = (face->frontarea != tmparea);
- //if the face has both a front and back area
- if (face->frontarea && face->backarea)
- {
- //
- if (face->frontarea == tmparea) othertmparea = face->backarea;
- else othertmparea = face->frontarea;
- //
- if (groundfirst)
- {
- if (!AAS_GroundArea(othertmparea)) continue;
- } //end if
- if (AAS_TryMergeFaceAreas(face))
- {
- qprintf("\r%6d", ++nummerges);
- merges++;
- break;
- } //end if
- } //end if
- } //end for
- } //end for
- if (!merges)
- {
- if (groundfirst) groundfirst = false;
- else break;
- } //end if
- } //end for
- qprintf("\n");
- Log_Write("%6d areas merged\r\n", nummerges);
- //refresh the merged tree
- AAS_RefreshMergedTree_r(tmpaasworld.nodes);
-} //end of the function AAS_MergeAreas
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+#include "qbsp.h"
+#include "../botlib/aasfile.h"
+#include "aas_create.h"
+#include "aas_store.h"
+
+#define CONVEX_EPSILON 0.3
+
+//===========================================================================
+//
+// Parameter: -
+// Returns: -
+// Changes Globals: -
+//===========================================================================
+tmp_node_t *AAS_RefreshMergedTree_r(tmp_node_t *tmpnode)
+{
+ tmp_area_t *tmparea;
+
+ //if this is a solid leaf
+ if (!tmpnode) return NULL;
+ //if this is an area leaf
+ if (tmpnode->tmparea)
+ {
+ tmparea = tmpnode->tmparea;
+ while(tmparea->mergedarea) tmparea = tmparea->mergedarea;
+ tmpnode->tmparea = tmparea;
+ return tmpnode;
+ } //end if
+ //do the children recursively
+ tmpnode->children[0] = AAS_RefreshMergedTree_r(tmpnode->children[0]);
+ tmpnode->children[1] = AAS_RefreshMergedTree_r(tmpnode->children[1]);
+ return tmpnode;
+} //end of the function AAS_RefreshMergedTree_r
+//===========================================================================
+// returns true if the two given faces would create a non-convex area at
+// the given sides, otherwise false is returned
+//
+// Parameter: -
+// Returns: -
+// Changes Globals: -
+//===========================================================================
+int NonConvex(tmp_face_t *face1, tmp_face_t *face2, int side1, int side2)
+{
+ int i;
+ winding_t *w1, *w2;
+ plane_t *plane1, *plane2;
+
+ w1 = face1->winding;
+ w2 = face2->winding;
+
+ plane1 = &mapplanes[face1->planenum ^ side1];
+ plane2 = &mapplanes[face2->planenum ^ side2];
+
+ //check if one of the points of face1 is at the back of the plane of face2
+ for (i = 0; i < w1->numpoints; i++)
+ {
+ if (DotProduct(plane2->normal, w1->p[i]) - plane2->dist < -CONVEX_EPSILON) return true;
+ } //end for
+ //check if one of the points of face2 is at the back of the plane of face1
+ for (i = 0; i < w2->numpoints; i++)
+ {
+ if (DotProduct(plane1->normal, w2->p[i]) - plane1->dist < -CONVEX_EPSILON) return true;
+ } //end for
+
+ return false;
+} //end of the function NonConvex
+//===========================================================================
+// try to merge the areas at both sides of the given face
+//
+// Parameter: seperatingface : face that seperates two areas
+// Returns: -
+// Changes Globals: -
+//===========================================================================
+int AAS_TryMergeFaceAreas(tmp_face_t *seperatingface)
+{
+ int side1, side2, area1faceflags, area2faceflags;
+ tmp_area_t *tmparea1, *tmparea2, *newarea;
+ tmp_face_t *face1, *face2, *nextface1, *nextface2;
+
+ tmparea1 = seperatingface->frontarea;
+ tmparea2 = seperatingface->backarea;
+
+ //areas must have the same presence type
+ if (tmparea1->presencetype != tmparea2->presencetype) return false;
+ //areas must have the same area contents
+ if (tmparea1->contents != tmparea2->contents) return false;
+ //areas must have the same bsp model inside (or both none)
+ if (tmparea1->modelnum != tmparea2->modelnum) return false;
+
+ area1faceflags = 0;
+ area2faceflags = 0;
+ for (face1 = tmparea1->tmpfaces; face1; face1 = face1->next[side1])
+ {
+ side1 = (face1->frontarea != tmparea1);
+ //debug: check if the area belongs to the area
+ if (face1->frontarea != tmparea1 &&
+ face1->backarea != tmparea1) Error("face does not belong to area1");
+ //just continue if the face is seperating the two areas
+ //NOTE: a result of this is that ground and gap areas can
+ // be merged if the seperating face is the gap
+ if ((face1->frontarea == tmparea1 &&
+ face1->backarea == tmparea2) ||
+ (face1->frontarea == tmparea2 &&
+ face1->backarea == tmparea1)) continue;
+ //get area1 face flags
+ area1faceflags |= face1->faceflags;
+ if (AAS_GapFace(face1, side1)) area1faceflags |= FACE_GAP;
+ //
+ for (face2 = tmparea2->tmpfaces; face2; face2 = face2->next[side2])
+ {
+ side2 = (face2->frontarea != tmparea2);
+ //debug: check if the area belongs to the area
+ if (face2->frontarea != tmparea2 &&
+ face2->backarea != tmparea2) Error("face does not belong to area2");
+ //just continue if the face is seperating the two areas
+ //NOTE: a result of this is that ground and gap areas can
+ // be merged if the seperating face is the gap
+ if ((face2->frontarea == tmparea1 &&
+ face2->backarea == tmparea2) ||
+ (face2->frontarea == tmparea2 &&
+ face2->backarea == tmparea1)) continue;
+ //get area2 face flags
+ area2faceflags |= face2->faceflags;
+ if (AAS_GapFace(face2, side2)) area2faceflags |= FACE_GAP;
+ //if the two faces would create a non-convex area
+ if (NonConvex(face1, face2, side1, side2)) return false;
+ } //end for
+ } //end for
+ //if one area has gap faces (that aren't seperating the two areas)
+ //and the other has ground faces (that aren't seperating the two areas),
+ //the areas can't be merged
+ if (((area1faceflags & FACE_GROUND) && (area2faceflags & FACE_GAP)) ||
+ ((area2faceflags & FACE_GROUND) && (area1faceflags & FACE_GAP)))
+ {
+// Log_Print(" can't merge: ground/gap\n");
+ return false;
+ } //end if
+
+// Log_Print("merged area %d & %d to %d with %d faces\n", tmparea1->areanum, tmparea2->areanum, newarea->areanum, numfaces);
+// return false;
+ //
+ //AAS_CheckArea(tmparea1);
+ //AAS_CheckArea(tmparea2);
+ //create the new area
+ newarea = AAS_AllocTmpArea();
+ newarea->presencetype = tmparea1->presencetype;
+ newarea->contents = tmparea1->contents;
+ newarea->modelnum = tmparea1->modelnum;
+ newarea->tmpfaces = NULL;
+
+ //add all the faces (except the seperating ones) from the first area
+ //to the new area
+ for (face1 = tmparea1->tmpfaces; face1; face1 = nextface1)
+ {
+ side1 = (face1->frontarea != tmparea1);
+ nextface1 = face1->next[side1];
+ //don't add seperating faces
+ if ((face1->frontarea == tmparea1 &&
+ face1->backarea == tmparea2) ||
+ (face1->frontarea == tmparea2 &&
+ face1->backarea == tmparea1))
+ {
+ continue;
+ } //end if
+ //
+ AAS_RemoveFaceFromArea(face1, tmparea1);
+ AAS_AddFaceSideToArea(face1, side1, newarea);
+ } //end for
+ //add all the faces (except the seperating ones) from the second area
+ //to the new area
+ for (face2 = tmparea2->tmpfaces; face2; face2 = nextface2)
+ {
+ side2 = (face2->frontarea != tmparea2);
+ nextface2 = face2->next[side2];
+ //don't add seperating faces
+ if ((face2->frontarea == tmparea1 &&
+ face2->backarea == tmparea2) ||
+ (face2->frontarea == tmparea2 &&
+ face2->backarea == tmparea1))
+ {
+ continue;
+ } //end if
+ //
+ AAS_RemoveFaceFromArea(face2, tmparea2);
+ AAS_AddFaceSideToArea(face2, side2, newarea);
+ } //end for
+ //free all shared faces
+ for (face1 = tmparea1->tmpfaces; face1; face1 = nextface1)
+ {
+ side1 = (face1->frontarea != tmparea1);
+ nextface1 = face1->next[side1];
+ //
+ AAS_RemoveFaceFromArea(face1, face1->frontarea);
+ AAS_RemoveFaceFromArea(face1, face1->backarea);
+ AAS_FreeTmpFace(face1);
+ } //end for
+ //
+ tmparea1->mergedarea = newarea;
+ tmparea1->invalid = true;
+ tmparea2->mergedarea = newarea;
+ tmparea2->invalid = true;
+ //
+ AAS_CheckArea(newarea);
+ AAS_FlipAreaFaces(newarea);
+// Log_Print("merged area %d & %d to %d with %d faces\n", tmparea1->areanum, tmparea2->areanum, newarea->areanum);
+ return true;
+} //end of the function AAS_TryMergeFaceAreas
+//===========================================================================
+// try to merge areas
+// merged areas are added to the end of the convex area list so merging
+// will be tried for those areas as well
+//
+// Parameter: -
+// Returns: -
+// Changes Globals: tmpaasworld
+//===========================================================================
+/*
+void AAS_MergeAreas(void)
+{
+ int side, nummerges;
+ tmp_area_t *tmparea, *othertmparea;
+ tmp_face_t *face;
+
+ nummerges = 0;
+ Log_Write("AAS_MergeAreas\r\n");
+ qprintf("%6d areas merged", 1);
+ //first merge grounded areas only
+ //NOTE: this is useless because the area settings aren't available yet
+ for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next)
+ {
+// Log_Print("checking area %d\n", i);
+ //if the area is invalid
+ if (tmparea->invalid)
+ {
+// Log_Print(" area invalid\n");
+ continue;
+ } //end if
+ //
+// if (!(tmparea->settings->areaflags & AREA_GROUNDED)) continue;
+ //
+ for (face = tmparea->tmpfaces; face; face = face->next[side])
+ {
+ side = (face->frontarea != tmparea);
+ //if the face has both a front and back area
+ if (face->frontarea && face->backarea)
+ {
+ //
+ if (face->frontarea == tmparea) othertmparea = face->backarea;
+ else othertmparea = face->frontarea;
+// if (!(othertmparea->settings->areaflags & AREA_GROUNDED)) continue;
+// Log_Print(" checking area %d with %d\n", face->frontarea, face->backarea);
+ if (AAS_TryMergeFaceAreas(face))
+ {
+ qprintf("\r%6d", ++nummerges);
+ break;
+ } //end if
+ } //end if
+ } //end for
+ } //end for
+ //merge all areas
+ for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next)
+ {
+// Log_Print("checking area %d\n", i);
+ //if the area is invalid
+ if (tmparea->invalid)
+ {
+// Log_Print(" area invalid\n");
+ continue;
+ } //end if
+ //
+ for (face = tmparea->tmpfaces; face; face = face->next[side])
+ {
+ side = (face->frontarea != tmparea);
+ //if the face has both a front and back area
+ if (face->frontarea && face->backarea)
+ {
+// Log_Print(" checking area %d with %d\n", face->frontarea, face->backarea);
+ if (AAS_TryMergeFaceAreas(face))
+ {
+ qprintf("\r%6d", ++nummerges);
+ break;
+ } //end if
+ } //end if
+ } //end for
+ } //end for
+ Log_Print("\r%6d areas merged\n", nummerges);
+ //refresh the merged tree
+ AAS_RefreshMergedTree_r(tmpaasworld.nodes);
+} //end of the function AAS_MergeAreas*/
+
+int AAS_GroundArea(tmp_area_t *tmparea)
+{
+ tmp_face_t *face;
+ int side;
+
+ for (face = tmparea->tmpfaces; face; face = face->next[side])
+ {
+ side = (face->frontarea != tmparea);
+ if (face->faceflags & FACE_GROUND) return true;
+ } //end for
+ return false;
+} //end of the function AAS_GroundArea
+
+void AAS_MergeAreas(void)
+{
+ int side, nummerges, merges, groundfirst;
+ tmp_area_t *tmparea, *othertmparea;
+ tmp_face_t *face;
+
+ nummerges = 0;
+ Log_Write("AAS_MergeAreas\r\n");
+ qprintf("%6d areas merged", 1);
+ //
+ groundfirst = true;
+ //for (i = 0; i < 4 || merges; i++)
+ while(1)
+ {
+ //if (i < 2) groundfirst = true;
+ //else groundfirst = false;
+ //
+ merges = 0;
+ //first merge grounded areas only
+ for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next)
+ {
+ //if the area is invalid
+ if (tmparea->invalid)
+ {
+ continue;
+ } //end if
+ //
+ if (groundfirst)
+ {
+ if (!AAS_GroundArea(tmparea)) continue;
+ } //end if
+ //
+ for (face = tmparea->tmpfaces; face; face = face->next[side])
+ {
+ side = (face->frontarea != tmparea);
+ //if the face has both a front and back area
+ if (face->frontarea && face->backarea)
+ {
+ //
+ if (face->frontarea == tmparea) othertmparea = face->backarea;
+ else othertmparea = face->frontarea;
+ //
+ if (groundfirst)
+ {
+ if (!AAS_GroundArea(othertmparea)) continue;
+ } //end if
+ if (AAS_TryMergeFaceAreas(face))
+ {
+ qprintf("\r%6d", ++nummerges);
+ merges++;
+ break;
+ } //end if
+ } //end if
+ } //end for
+ } //end for
+ if (!merges)
+ {
+ if (groundfirst) groundfirst = false;
+ else break;
+ } //end if
+ } //end for
+ qprintf("\n");
+ Log_Write("%6d areas merged\r\n", nummerges);
+ //refresh the merged tree
+ AAS_RefreshMergedTree_r(tmpaasworld.nodes);
+} //end of the function AAS_MergeAreas