mirror of
https://github.com/id-Software/RTCW-SP.git
synced 2026-03-19 16:39:24 +01:00
1181 lines
37 KiB
C
1181 lines
37 KiB
C
/*
|
||
===========================================================================
|
||
|
||
Return to Castle Wolfenstein single player GPL Source Code
|
||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||
|
||
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (RTCW SP Source Code).
|
||
|
||
RTCW SP 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 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
RTCW SP 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 RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||
|
||
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||
|
||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||
|
||
===========================================================================
|
||
*/
|
||
|
||
//===========================================================================
|
||
//
|
||
// Name: aas_create.c
|
||
// Function: Creation of AAS
|
||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||
// Last update: 1997-12-04
|
||
// Tab Size: 3
|
||
//===========================================================================
|
||
|
||
#include "qbsp.h"
|
||
#include "../botlib/aasfile.h"
|
||
#include "aas_create.h"
|
||
#include "aas_store.h"
|
||
#include "aas_gsubdiv.h"
|
||
#include "aas_facemerging.h"
|
||
#include "aas_areamerging.h"
|
||
#include "aas_edgemelting.h"
|
||
#include "aas_prunenodes.h"
|
||
#include "aas_cfg.h"
|
||
#include "../game/surfaceflags.h"
|
||
|
||
#define AREAONFACESIDE( face, area ) ( face->frontarea != area )
|
||
|
||
tmp_aas_t tmpaasworld;
|
||
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_InitTmpAAS( void ) {
|
||
//tmp faces
|
||
tmpaasworld.numfaces = 0;
|
||
tmpaasworld.facenum = 0;
|
||
tmpaasworld.faces = NULL;
|
||
//tmp convex areas
|
||
tmpaasworld.numareas = 0;
|
||
tmpaasworld.areanum = 0;
|
||
tmpaasworld.areas = NULL;
|
||
//tmp nodes
|
||
tmpaasworld.numnodes = 0;
|
||
tmpaasworld.nodes = NULL;
|
||
//
|
||
tmpaasworld.nodebuffer = NULL;
|
||
} //end of the function AAS_InitTmpAAS
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_FreeTmpAAS( void ) {
|
||
tmp_face_t *f, *nextf;
|
||
tmp_area_t *a, *nexta;
|
||
tmp_nodebuf_t *nb, *nextnb;
|
||
|
||
//free all the faces
|
||
for ( f = tmpaasworld.faces; f; f = nextf )
|
||
{
|
||
nextf = f->l_next;
|
||
if ( f->winding ) {
|
||
FreeWinding( f->winding );
|
||
}
|
||
FreeMemory( f );
|
||
} //end if
|
||
//free all tmp areas
|
||
for ( a = tmpaasworld.areas; a; a = nexta )
|
||
{
|
||
nexta = a->l_next;
|
||
if ( a->settings ) {
|
||
FreeMemory( a->settings );
|
||
}
|
||
FreeMemory( a );
|
||
} //end for
|
||
//free all the tmp nodes
|
||
for ( nb = tmpaasworld.nodebuffer; nb; nb = nextnb )
|
||
{
|
||
nextnb = nb->next;
|
||
FreeMemory( nb );
|
||
} //end for
|
||
} //end of the function AAS_FreeTmpAAS
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
tmp_face_t *AAS_AllocTmpFace( void ) {
|
||
tmp_face_t *tmpface;
|
||
|
||
tmpface = (tmp_face_t *) GetClearedMemory( sizeof( tmp_face_t ) );
|
||
tmpface->num = tmpaasworld.facenum++;
|
||
tmpface->l_prev = NULL;
|
||
tmpface->l_next = tmpaasworld.faces;
|
||
if ( tmpaasworld.faces ) {
|
||
tmpaasworld.faces->l_prev = tmpface;
|
||
}
|
||
tmpaasworld.faces = tmpface;
|
||
tmpaasworld.numfaces++;
|
||
return tmpface;
|
||
} //end of the function AAS_AllocTmpFace
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_FreeTmpFace( tmp_face_t *tmpface ) {
|
||
if ( tmpface->l_next ) {
|
||
tmpface->l_next->l_prev = tmpface->l_prev;
|
||
}
|
||
if ( tmpface->l_prev ) {
|
||
tmpface->l_prev->l_next = tmpface->l_next;
|
||
} else { tmpaasworld.faces = tmpface->l_next;}
|
||
//free the winding
|
||
if ( tmpface->winding ) {
|
||
FreeWinding( tmpface->winding );
|
||
}
|
||
//free the face
|
||
FreeMemory( tmpface );
|
||
tmpaasworld.numfaces--;
|
||
} //end of the function AAS_FreeTmpFace
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
tmp_area_t *AAS_AllocTmpArea( void ) {
|
||
tmp_area_t *tmparea;
|
||
|
||
tmparea = (tmp_area_t *) GetClearedMemory( sizeof( tmp_area_t ) );
|
||
tmparea->areanum = tmpaasworld.areanum++;
|
||
tmparea->l_prev = NULL;
|
||
tmparea->l_next = tmpaasworld.areas;
|
||
if ( tmpaasworld.areas ) {
|
||
tmpaasworld.areas->l_prev = tmparea;
|
||
}
|
||
tmpaasworld.areas = tmparea;
|
||
tmpaasworld.numareas++;
|
||
return tmparea;
|
||
} //end of the function AAS_AllocTmpArea
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_FreeTmpArea( tmp_area_t *tmparea ) {
|
||
if ( tmparea->l_next ) {
|
||
tmparea->l_next->l_prev = tmparea->l_prev;
|
||
}
|
||
if ( tmparea->l_prev ) {
|
||
tmparea->l_prev->l_next = tmparea->l_next;
|
||
} else { tmpaasworld.areas = tmparea->l_next;}
|
||
if ( tmparea->settings ) {
|
||
FreeMemory( tmparea->settings );
|
||
}
|
||
FreeMemory( tmparea );
|
||
tmpaasworld.numareas--;
|
||
} //end of the function AAS_FreeTmpArea
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
tmp_node_t *AAS_AllocTmpNode( void ) {
|
||
tmp_nodebuf_t *nodebuf;
|
||
|
||
if ( !tmpaasworld.nodebuffer ||
|
||
tmpaasworld.nodebuffer->numnodes >= NODEBUF_SIZE ) {
|
||
nodebuf = (tmp_nodebuf_t *) GetClearedMemory( sizeof( tmp_nodebuf_t ) );
|
||
nodebuf->next = tmpaasworld.nodebuffer;
|
||
nodebuf->numnodes = 0;
|
||
tmpaasworld.nodebuffer = nodebuf;
|
||
} //end if
|
||
tmpaasworld.numnodes++;
|
||
return &tmpaasworld.nodebuffer->nodes[tmpaasworld.nodebuffer->numnodes++];
|
||
} //end of the function AAS_AllocTmpNode
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_FreeTmpNode( tmp_node_t *tmpnode ) {
|
||
tmpaasworld.numnodes--;
|
||
} //end of the function AAS_FreeTmpNode
|
||
//===========================================================================
|
||
// returns true if the face is a gap from the given side
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
int AAS_GapFace( tmp_face_t *tmpface, int side ) {
|
||
vec3_t invgravity;
|
||
|
||
//if the face is a solid or ground face it can't be a gap
|
||
if ( tmpface->faceflags & ( FACE_GROUND | FACE_SOLID ) ) {
|
||
return 0;
|
||
}
|
||
|
||
VectorCopy( cfg.phys_gravitydirection, invgravity );
|
||
VectorInverse( invgravity );
|
||
|
||
return ( DotProduct( invgravity, mapplanes[tmpface->planenum ^ side].normal ) > cfg.phys_maxsteepness );
|
||
} //end of the function AAS_GapFace
|
||
//===========================================================================
|
||
// returns true if the face is a ground face
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
int AAS_GroundFace( tmp_face_t *tmpface ) {
|
||
vec3_t invgravity;
|
||
|
||
//must be a solid face
|
||
if ( !( tmpface->faceflags & FACE_SOLID ) ) {
|
||
return 0;
|
||
}
|
||
|
||
VectorCopy( cfg.phys_gravitydirection, invgravity );
|
||
VectorInverse( invgravity );
|
||
|
||
return ( DotProduct( invgravity, mapplanes[tmpface->planenum].normal ) > cfg.phys_maxsteepness );
|
||
} //end of the function AAS_GroundFace
|
||
//===========================================================================
|
||
// adds the side of a face to an area
|
||
//
|
||
// side : 0 = front side
|
||
// 1 = back side
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_AddFaceSideToArea( tmp_face_t *tmpface, int side, tmp_area_t *tmparea ) {
|
||
int tmpfaceside;
|
||
|
||
if ( side ) {
|
||
if ( tmpface->backarea ) {
|
||
Error( "AAS_AddFaceSideToArea: already a back area\n" );
|
||
}
|
||
} //end if
|
||
else
|
||
{
|
||
if ( tmpface->frontarea ) {
|
||
Error( "AAS_AddFaceSideToArea: already a front area\n" );
|
||
}
|
||
} //end else
|
||
|
||
if ( side ) {
|
||
tmpface->backarea = tmparea;
|
||
} else { tmpface->frontarea = tmparea;}
|
||
|
||
if ( tmparea->tmpfaces ) {
|
||
tmpfaceside = tmparea->tmpfaces->frontarea != tmparea;
|
||
tmparea->tmpfaces->prev[tmpfaceside] = tmpface;
|
||
} //end if
|
||
tmpface->next[side] = tmparea->tmpfaces;
|
||
tmpface->prev[side] = NULL;
|
||
tmparea->tmpfaces = tmpface;
|
||
} //end of the function AAS_AddFaceSideToArea
|
||
//===========================================================================
|
||
// remove (a side of) a face from an area
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_RemoveFaceFromArea( tmp_face_t *tmpface, tmp_area_t *tmparea ) {
|
||
int side, prevside, nextside;
|
||
|
||
if ( tmpface->frontarea != tmparea &&
|
||
tmpface->backarea != tmparea ) {
|
||
Error( "AAS_RemoveFaceFromArea: face not part of the area" );
|
||
} //end if
|
||
side = tmpface->frontarea != tmparea;
|
||
if ( tmpface->prev[side] ) {
|
||
prevside = tmpface->prev[side]->frontarea != tmparea;
|
||
tmpface->prev[side]->next[prevside] = tmpface->next[side];
|
||
} //end if
|
||
else
|
||
{
|
||
tmparea->tmpfaces = tmpface->next[side];
|
||
} //end else
|
||
if ( tmpface->next[side] ) {
|
||
nextside = tmpface->next[side]->frontarea != tmparea;
|
||
tmpface->next[side]->prev[nextside] = tmpface->prev[side];
|
||
} //end if
|
||
//remove the area number from the face depending on the side
|
||
if ( side ) {
|
||
tmpface->backarea = NULL;
|
||
} else { tmpface->frontarea = NULL;}
|
||
tmpface->prev[side] = NULL;
|
||
tmpface->next[side] = NULL;
|
||
} //end of the function AAS_RemoveFaceFromArea
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_CheckArea( tmp_area_t *tmparea ) {
|
||
int side;
|
||
tmp_face_t *face;
|
||
plane_t *plane;
|
||
vec3_t wcenter, acenter = {0, 0, 0};
|
||
vec3_t normal;
|
||
float n, dist;
|
||
|
||
if ( tmparea->invalid ) {
|
||
Log_Print( "AAS_CheckArea: invalid area\n" );
|
||
}
|
||
for ( n = 0, face = tmparea->tmpfaces; face; face = face->next[side] )
|
||
{
|
||
//side of the face the area is on
|
||
side = face->frontarea != tmparea;
|
||
WindingCenter( face->winding, wcenter );
|
||
VectorAdd( acenter, wcenter, acenter );
|
||
n++;
|
||
} //end for
|
||
n = 1 / n;
|
||
VectorScale( acenter, n, acenter );
|
||
for ( face = tmparea->tmpfaces; face; face = face->next[side] )
|
||
{
|
||
//side of the face the area is on
|
||
side = face->frontarea != tmparea;
|
||
|
||
#ifdef L_DEBUG
|
||
if ( WindingError( face->winding ) ) {
|
||
Log_Write( "AAS_CheckArea: area %d face %d: %s\r\n", tmparea->areanum,
|
||
face->num, WindingErrorString() );
|
||
} //end if
|
||
#endif L_DEBUG
|
||
|
||
plane = &mapplanes[face->planenum ^ side];
|
||
|
||
if ( DotProduct( plane->normal, acenter ) - plane->dist < 0 ) {
|
||
Log_Print( "AAS_CheckArea: area %d face %d is flipped\n", tmparea->areanum, face->num );
|
||
Log_Print( "AAS_CheckArea: area %d center is %f %f %f\n", tmparea->areanum, acenter[0], acenter[1], acenter[2] );
|
||
} //end if
|
||
//check if the winding plane is the same as the face plane
|
||
WindingPlane( face->winding, normal, &dist );
|
||
plane = &mapplanes[face->planenum];
|
||
#ifdef L_DEBUG
|
||
if ( fabs( dist - plane->dist ) > 0.4 ||
|
||
fabs( normal[0] - plane->normal[0] ) > 0.0001 ||
|
||
fabs( normal[1] - plane->normal[1] ) > 0.0001 ||
|
||
fabs( normal[2] - plane->normal[2] ) > 0.0001 ) {
|
||
Log_Write( "AAS_CheckArea: area %d face %d winding plane unequal to face plane\r\n",
|
||
tmparea->areanum, face->num );
|
||
} //end if
|
||
#endif L_DEBUG
|
||
} //end for
|
||
} //end of the function AAS_CheckArea
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_CheckFaceWindingPlane( tmp_face_t *face ) {
|
||
float dist, sign1, sign2;
|
||
vec3_t normal;
|
||
plane_t *plane;
|
||
winding_t *w;
|
||
|
||
//check if the winding plane is the same as the face plane
|
||
WindingPlane( face->winding, normal, &dist );
|
||
plane = &mapplanes[face->planenum];
|
||
//
|
||
sign1 = DotProduct( plane->normal, normal );
|
||
//
|
||
if ( fabs( dist - plane->dist ) > 0.4 ||
|
||
fabs( normal[0] - plane->normal[0] ) > 0.0001 ||
|
||
fabs( normal[1] - plane->normal[1] ) > 0.0001 ||
|
||
fabs( normal[2] - plane->normal[2] ) > 0.0001 ) {
|
||
VectorInverse( normal );
|
||
dist = -dist;
|
||
if ( fabs( dist - plane->dist ) > 0.4 ||
|
||
fabs( normal[0] - plane->normal[0] ) > 0.0001 ||
|
||
fabs( normal[1] - plane->normal[1] ) > 0.0001 ||
|
||
fabs( normal[2] - plane->normal[2] ) > 0.0001 ) {
|
||
Log_Write( "AAS_CheckFaceWindingPlane: face %d winding plane unequal to face plane\r\n",
|
||
face->num );
|
||
//
|
||
sign2 = DotProduct( plane->normal, normal );
|
||
if ( ( sign1 < 0 && sign2 > 0 ) ||
|
||
( sign1 > 0 && sign2 < 0 ) ) {
|
||
Log_Write( "AAS_CheckFaceWindingPlane: face %d winding reversed\r\n",
|
||
face->num );
|
||
w = face->winding;
|
||
face->winding = ReverseWinding( w );
|
||
FreeWinding( w );
|
||
} //end if
|
||
} //end if
|
||
else
|
||
{
|
||
Log_Write( "AAS_CheckFaceWindingPlane: face %d winding reversed\r\n",
|
||
face->num );
|
||
w = face->winding;
|
||
face->winding = ReverseWinding( w );
|
||
FreeWinding( w );
|
||
} //end else
|
||
} //end if
|
||
} //end of the function AAS_CheckFaceWindingPlane
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_CheckAreaWindingPlanes( void ) {
|
||
int side;
|
||
tmp_area_t *tmparea;
|
||
tmp_face_t *face;
|
||
|
||
Log_Write( "AAS_CheckAreaWindingPlanes:\r\n" );
|
||
for ( tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next )
|
||
{
|
||
if ( tmparea->invalid ) {
|
||
continue;
|
||
}
|
||
for ( face = tmparea->tmpfaces; face; face = face->next[side] )
|
||
{
|
||
side = face->frontarea != tmparea;
|
||
AAS_CheckFaceWindingPlane( face );
|
||
} //end for
|
||
} //end for
|
||
} //end of the function AAS_CheckAreaWindingPlanes
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_FlipAreaFaces( tmp_area_t *tmparea ) {
|
||
int side;
|
||
tmp_face_t *face;
|
||
plane_t *plane;
|
||
vec3_t wcenter, acenter = {0, 0, 0};
|
||
//winding_t *w;
|
||
float n;
|
||
|
||
for ( n = 0, face = tmparea->tmpfaces; face; face = face->next[side] )
|
||
{
|
||
if ( !face->frontarea ) {
|
||
Error( "face %d has no front area\n", face->num );
|
||
}
|
||
//side of the face the area is on
|
||
side = face->frontarea != tmparea;
|
||
WindingCenter( face->winding, wcenter );
|
||
VectorAdd( acenter, wcenter, acenter );
|
||
n++;
|
||
} //end for
|
||
n = 1 / n;
|
||
VectorScale( acenter, n, acenter );
|
||
for ( face = tmparea->tmpfaces; face; face = face->next[side] )
|
||
{
|
||
//side of the face the area is on
|
||
side = face->frontarea != tmparea;
|
||
|
||
plane = &mapplanes[face->planenum ^ side];
|
||
|
||
if ( DotProduct( plane->normal, acenter ) - plane->dist < 0 ) {
|
||
Log_Print( "area %d face %d flipped: front area %d, back area %d\n", tmparea->areanum, face->num,
|
||
face->frontarea ? face->frontarea->areanum : 0,
|
||
face->backarea ? face->backarea->areanum : 0 );
|
||
/*
|
||
face->planenum = face->planenum ^ 1;
|
||
w = face->winding;
|
||
face->winding = ReverseWinding(w);
|
||
FreeWinding(w);
|
||
*/
|
||
} //end if
|
||
#ifdef L_DEBUG
|
||
{
|
||
float dist;
|
||
vec3_t normal;
|
||
|
||
//check if the winding plane is the same as the face plane
|
||
WindingPlane( face->winding, normal, &dist );
|
||
plane = &mapplanes[face->planenum];
|
||
if ( fabs( dist - plane->dist ) > 0.4 ||
|
||
fabs( normal[0] - plane->normal[0] ) > 0.0001 ||
|
||
fabs( normal[1] - plane->normal[1] ) > 0.0001 ||
|
||
fabs( normal[2] - plane->normal[2] ) > 0.0001 ) {
|
||
Log_Write( "area %d face %d winding plane unequal to face plane\r\n",
|
||
tmparea->areanum, face->num );
|
||
} //end if
|
||
}
|
||
#endif
|
||
} //end for
|
||
} //end of the function AAS_FlipAreaFaces
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_RemoveAreaFaceColinearPoints( void ) {
|
||
int side;
|
||
tmp_face_t *face;
|
||
tmp_area_t *tmparea;
|
||
|
||
//FIXME: loop over the faces instead of area->faces
|
||
for ( tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next )
|
||
{
|
||
for ( face = tmparea->tmpfaces; face; face = face->next[side] )
|
||
{
|
||
side = face->frontarea != tmparea;
|
||
RemoveColinearPoints( face->winding );
|
||
// RemoveEqualPoints(face->winding, 0.1);
|
||
} //end for
|
||
} //end for
|
||
} //end of the function AAS_RemoveAreaFaceColinearPoints
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_RemoveTinyFaces( void ) {
|
||
int side, num;
|
||
tmp_face_t *face, *nextface;
|
||
tmp_area_t *tmparea;
|
||
|
||
//FIXME: loop over the faces instead of area->faces
|
||
Log_Write( "AAS_RemoveTinyFaces\r\n" );
|
||
num = 0;
|
||
for ( tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next )
|
||
{
|
||
for ( face = tmparea->tmpfaces; face; face = nextface )
|
||
{
|
||
side = face->frontarea != tmparea;
|
||
nextface = face->next[side];
|
||
//
|
||
if ( WindingArea( face->winding ) < 1 ) {
|
||
if ( face->frontarea ) {
|
||
AAS_RemoveFaceFromArea( face, face->frontarea );
|
||
}
|
||
if ( face->backarea ) {
|
||
AAS_RemoveFaceFromArea( face, face->backarea );
|
||
}
|
||
AAS_FreeTmpFace( face );
|
||
//Log_Write("area %d face %d is tiny\r\n", tmparea->areanum, face->num);
|
||
num++;
|
||
} //end if
|
||
} //end for
|
||
} //end for
|
||
Log_Write( "%d tiny faces removed\r\n", num );
|
||
} //end of the function AAS_RemoveTinyFaces
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_CreateAreaSettings( void ) {
|
||
int i, flags, side, numgrounded, numladderareas, numliquidareas;
|
||
tmp_face_t *face;
|
||
tmp_area_t *tmparea;
|
||
int count;
|
||
|
||
numgrounded = 0;
|
||
numladderareas = 0;
|
||
numliquidareas = 0;
|
||
Log_Write( "AAS_CreateAreaSettings\r\n" );
|
||
i = 0;
|
||
qprintf( "%6d areas provided with settings", i );
|
||
for ( tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next )
|
||
{
|
||
//if the area is invalid there no need to create settings for it
|
||
if ( tmparea->invalid ) {
|
||
continue;
|
||
}
|
||
|
||
tmparea->settings = (tmp_areasettings_t *) GetClearedMemory( sizeof( tmp_areasettings_t ) );
|
||
tmparea->settings->contents = tmparea->contents;
|
||
tmparea->settings->modelnum = tmparea->modelnum;
|
||
flags = 0;
|
||
count = 0;
|
||
tmparea->settings->groundsteepness = 0.0;
|
||
for ( face = tmparea->tmpfaces; face; face = face->next[side] )
|
||
{
|
||
side = face->frontarea != tmparea;
|
||
flags |= face->faceflags;
|
||
// Ridah, add this face's steepness
|
||
if ( face->faceflags & FACE_GROUND ) {
|
||
tmparea->settings->groundsteepness += ( 1.0 - mapplanes[face->planenum ^ side].normal[2] );
|
||
count++;
|
||
}
|
||
} //end for
|
||
tmparea->settings->groundsteepness /= (float)count;
|
||
if ( tmparea->settings->groundsteepness > 1.0 ) {
|
||
tmparea->settings->groundsteepness = 1.0;
|
||
}
|
||
if ( tmparea->settings->groundsteepness < 0.0 ) {
|
||
tmparea->settings->groundsteepness = 0.0;
|
||
}
|
||
tmparea->settings->areaflags = 0;
|
||
if ( flags & FACE_GROUND ) {
|
||
tmparea->settings->areaflags |= AREA_GROUNDED;
|
||
numgrounded++;
|
||
} //end if
|
||
if ( flags & FACE_LADDER ) {
|
||
tmparea->settings->areaflags |= AREA_LADDER;
|
||
numladderareas++;
|
||
} //end if
|
||
if ( tmparea->contents & ( AREACONTENTS_WATER |
|
||
AREACONTENTS_SLIME |
|
||
AREACONTENTS_LAVA ) ) {
|
||
tmparea->settings->areaflags |= AREA_LIQUID;
|
||
numliquidareas++;
|
||
} //end if
|
||
//presence type of the area
|
||
tmparea->settings->presencetype = tmparea->presencetype;
|
||
//
|
||
qprintf( "\r%6d", ++i );
|
||
} //end for
|
||
qprintf( "\n" );
|
||
#ifdef AASINFO
|
||
Log_Print( "%6d grounded areas\n", numgrounded );
|
||
Log_Print( "%6d ladder areas\n", numladderareas );
|
||
Log_Print( "%6d liquid areas\n", numliquidareas );
|
||
#endif //AASINFO
|
||
} //end of the function AAS_CreateAreaSettings
|
||
//===========================================================================
|
||
// create a tmp AAS area from a leaf node
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
//portal_t *globalPortalDebug;
|
||
tmp_node_t *AAS_CreateArea( node_t *node ) {
|
||
int pside;
|
||
int areafaceflags;
|
||
portal_t *p;
|
||
tmp_face_t *tmpface;
|
||
tmp_area_t *tmparea;
|
||
tmp_node_t *tmpnode;
|
||
//vec3_t up = {0, 0, 1}; // TTimo: unused
|
||
|
||
//create an area from this leaf
|
||
tmparea = AAS_AllocTmpArea();
|
||
tmparea->tmpfaces = NULL;
|
||
//clear the area face flags
|
||
areafaceflags = 0;
|
||
//make aas faces from the portals
|
||
for ( p = node->portals; p; p = p->next[pside] )
|
||
{
|
||
pside = ( p->nodes[1] == node );
|
||
//don't create faces from very small portals
|
||
// if (WindingArea(p->winding) < 1) continue;
|
||
//if there's already a face created for this portal
|
||
if ( p->tmpface ) {
|
||
//add the back side of the face to the area
|
||
AAS_AddFaceSideToArea( p->tmpface, 1, tmparea );
|
||
} //end if
|
||
else
|
||
{
|
||
tmpface = AAS_AllocTmpFace();
|
||
//set the face pointer at the portal so we can see from
|
||
//the portal there's a face created for it
|
||
p->tmpface = tmpface;
|
||
//FIXME: test this change
|
||
//tmpface->planenum = (p->planenum & ~1) | pside;
|
||
tmpface->planenum = p->planenum ^ pside;
|
||
if ( pside ) {
|
||
tmpface->winding = ReverseWinding( p->winding );
|
||
} else { tmpface->winding = CopyWinding( p->winding );}
|
||
#ifdef L_DEBUG
|
||
//
|
||
AAS_CheckFaceWindingPlane( tmpface );
|
||
#endif //L_DEBUG
|
||
//if there's solid at the other side of the portal
|
||
if ( p->nodes[!pside]->contents & ( CONTENTS_SOLID | CONTENTS_PLAYERCLIP ) ) {
|
||
tmpface->faceflags |= FACE_SOLID;
|
||
} //end if
|
||
//else there is no solid at the other side and if there
|
||
//is a liquid at this side
|
||
else if ( node->contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) {
|
||
tmpface->faceflags |= FACE_LIQUID;
|
||
//if there's no liquid at the other side
|
||
if ( !( p->nodes[!pside]->contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) ) {
|
||
tmpface->faceflags |= FACE_LIQUIDSURFACE;
|
||
} //end if
|
||
} //end else
|
||
//if there's ladder contents at other side of the portal
|
||
if ( ( p->nodes[pside]->contents & CONTENTS_LADDER ) ||
|
||
( p->nodes[!pside]->contents & CONTENTS_LADDER ) ) {
|
||
|
||
//NOTE: doesn't have to be solid at the other side because
|
||
// when standing one can use a crouch area (which is not solid)
|
||
// as a ladder
|
||
// imagine a ladder one can walk underthrough,
|
||
// under the ladder against the ladder is a crouch area
|
||
// the (vertical) sides of this crouch area area also used as
|
||
// ladder sides when standing (not crouched)
|
||
tmpface->faceflags |= FACE_LADDER;
|
||
} //end if
|
||
//if it is possible to stand on the face
|
||
if ( AAS_GroundFace( tmpface ) ) {
|
||
tmpface->faceflags |= FACE_GROUND;
|
||
} //end if
|
||
//
|
||
areafaceflags |= tmpface->faceflags;
|
||
//no aas face number yet (zero is a dummy in the aasworld faces)
|
||
tmpface->aasfacenum = 0;
|
||
//add the front side of the face to the area
|
||
AAS_AddFaceSideToArea( tmpface, 0, tmparea );
|
||
} //end else
|
||
} //end for
|
||
qprintf( "\r%6d", tmparea->areanum );
|
||
//presence type in the area
|
||
tmparea->presencetype = ~node->expansionbboxes & cfg.allpresencetypes;
|
||
//
|
||
tmparea->contents = 0;
|
||
if ( node->contents & CONTENTS_CLUSTERPORTAL ) {
|
||
tmparea->contents |= AREACONTENTS_CLUSTERPORTAL;
|
||
}
|
||
if ( node->contents & CONTENTS_MOVER ) {
|
||
tmparea->contents |= AREACONTENTS_MOVER;
|
||
}
|
||
if ( node->contents & CONTENTS_TELEPORTER ) {
|
||
tmparea->contents |= AREACONTENTS_TELEPORTER;
|
||
}
|
||
if ( node->contents & CONTENTS_JUMPPAD ) {
|
||
tmparea->contents |= AREACONTENTS_JUMPPAD;
|
||
}
|
||
if ( node->contents & CONTENTS_DONOTENTER ) {
|
||
tmparea->contents |= AREACONTENTS_DONOTENTER;
|
||
}
|
||
if ( node->contents & CONTENTS_DONOTENTER_LARGE ) {
|
||
tmparea->contents |= AREACONTENTS_DONOTENTER_LARGE;
|
||
}
|
||
if ( node->contents & CONTENTS_WATER ) {
|
||
tmparea->contents |= AREACONTENTS_WATER;
|
||
}
|
||
if ( node->contents & CONTENTS_LAVA ) {
|
||
tmparea->contents |= AREACONTENTS_LAVA;
|
||
}
|
||
if ( node->contents & CONTENTS_SLIME ) {
|
||
tmparea->contents |= AREACONTENTS_SLIME;
|
||
}
|
||
|
||
//store the bsp model that's inside this node
|
||
tmparea->modelnum = node->modelnum;
|
||
//sorta check for flipped area faces (remove??)
|
||
AAS_FlipAreaFaces( tmparea );
|
||
//check if the area is ok (remove??)
|
||
AAS_CheckArea( tmparea );
|
||
//
|
||
tmpnode = AAS_AllocTmpNode();
|
||
tmpnode->planenum = 0;
|
||
tmpnode->children[0] = 0;
|
||
tmpnode->children[1] = 0;
|
||
tmpnode->tmparea = tmparea;
|
||
//
|
||
return tmpnode;
|
||
} //end of the function AAS_CreateArea
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
tmp_node_t *AAS_CreateAreas_r( node_t *node ) {
|
||
tmp_node_t *tmpnode;
|
||
|
||
//recurse down to leafs
|
||
if ( node->planenum != PLANENUM_LEAF ) {
|
||
//the first tmp node is a dummy
|
||
tmpnode = AAS_AllocTmpNode();
|
||
tmpnode->planenum = node->planenum;
|
||
tmpnode->children[0] = AAS_CreateAreas_r( node->children[0] );
|
||
tmpnode->children[1] = AAS_CreateAreas_r( node->children[1] );
|
||
return tmpnode;
|
||
} //end if
|
||
//areas won't be created for solid leafs
|
||
if ( node->contents & CONTENTS_SOLID ) {
|
||
//just return zero for a solid leaf (in tmp AAS NULL is a solid leaf)
|
||
return NULL;
|
||
} //end if
|
||
|
||
return AAS_CreateArea( node );
|
||
} //end of the function AAS_CreateAreas_r
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_CreateAreas( node_t *node ) {
|
||
Log_Write( "AAS_CreateAreas\r\n" );
|
||
qprintf( "%6d areas created", 0 );
|
||
tmpaasworld.nodes = AAS_CreateAreas_r( node );
|
||
qprintf( "\n" );
|
||
Log_Write( "%6d areas created\r\n", tmpaasworld.numareas );
|
||
} //end of the function AAS_CreateAreas
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_PrintNumGroundFaces( void ) {
|
||
tmp_face_t *tmpface;
|
||
int numgroundfaces = 0;
|
||
|
||
for ( tmpface = tmpaasworld.faces; tmpface; tmpface = tmpface->l_next )
|
||
{
|
||
if ( tmpface->faceflags & FACE_GROUND ) {
|
||
numgroundfaces++;
|
||
} //end if
|
||
} //end for
|
||
qprintf( "%6d ground faces\n", numgroundfaces );
|
||
} //end of the function AAS_PrintNumGroundFaces
|
||
//===========================================================================
|
||
// checks the number of shared faces between the given two areas
|
||
// since areas are convex they should only have ONE shared face
|
||
// however due to crappy face merging there are sometimes several
|
||
// shared faces
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_CheckAreaSharedFaces( tmp_area_t *tmparea1, tmp_area_t *tmparea2 ) {
|
||
int numsharedfaces, side;
|
||
tmp_face_t *face1, *sharedface;
|
||
|
||
if ( tmparea1->invalid || tmparea2->invalid ) {
|
||
return;
|
||
}
|
||
|
||
sharedface = NULL;
|
||
numsharedfaces = 0;
|
||
for ( face1 = tmparea1->tmpfaces; face1; face1 = face1->next[side] )
|
||
{
|
||
side = face1->frontarea != tmparea1;
|
||
if ( face1->backarea == tmparea2 || face1->frontarea == tmparea2 ) {
|
||
sharedface = face1;
|
||
numsharedfaces++;
|
||
} //end if
|
||
} //end if
|
||
if ( !sharedface ) {
|
||
return;
|
||
}
|
||
//the areas should only have one shared face
|
||
if ( numsharedfaces > 1 ) {
|
||
Log_Write( "---- tmp area %d and %d have %d shared faces\r\n",
|
||
tmparea1->areanum, tmparea2->areanum, numsharedfaces );
|
||
for ( face1 = tmparea1->tmpfaces; face1; face1 = face1->next[side] )
|
||
{
|
||
side = face1->frontarea != tmparea1;
|
||
if ( face1->backarea == tmparea2 || face1->frontarea == tmparea2 ) {
|
||
Log_Write( "face %d, planenum = %d, face->frontarea = %d face->backarea = %d\r\n",
|
||
face1->num, face1->planenum, face1->frontarea->areanum, face1->backarea->areanum );
|
||
} //end if
|
||
} //end if
|
||
} //end if
|
||
} //end of the function AAS_CheckAreaSharedFaces
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_CheckSharedFaces( void ) {
|
||
tmp_area_t *tmparea1, *tmparea2;
|
||
|
||
for ( tmparea1 = tmpaasworld.areas; tmparea1; tmparea1 = tmparea1->l_next )
|
||
{
|
||
for ( tmparea2 = tmpaasworld.areas; tmparea2; tmparea2 = tmparea2->l_next )
|
||
{
|
||
if ( tmparea1 == tmparea2 ) {
|
||
continue;
|
||
}
|
||
AAS_CheckAreaSharedFaces( tmparea1, tmparea2 );
|
||
} //end for
|
||
} //end for
|
||
} //end of the function AAS_CheckSharedFaces
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_FlipFace( tmp_face_t *face ) {
|
||
tmp_area_t *frontarea, *backarea;
|
||
winding_t *w;
|
||
|
||
frontarea = face->frontarea;
|
||
backarea = face->backarea;
|
||
//must have an area at both sides before flipping is allowed
|
||
if ( !frontarea || !backarea ) {
|
||
return;
|
||
}
|
||
//flip the face winding
|
||
w = face->winding;
|
||
face->winding = ReverseWinding( w );
|
||
FreeWinding( w );
|
||
//flip the face plane
|
||
face->planenum ^= 1;
|
||
//flip the face areas
|
||
AAS_RemoveFaceFromArea( face, frontarea );
|
||
AAS_RemoveFaceFromArea( face, backarea );
|
||
AAS_AddFaceSideToArea( face, 1, frontarea );
|
||
AAS_AddFaceSideToArea( face, 0, backarea );
|
||
} //end of the function AAS_FlipFace
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
/*
|
||
void AAS_FlipAreaSharedFaces(tmp_area_t *tmparea1, tmp_area_t *tmparea2)
|
||
{
|
||
int numsharedfaces, side, area1facing, area2facing;
|
||
tmp_face_t *face1, *sharedface;
|
||
|
||
if (tmparea1->invalid || tmparea2->invalid) return;
|
||
|
||
sharedface = NULL;
|
||
numsharedfaces = 0;
|
||
area1facing = 0; //number of shared faces facing towards area 1
|
||
area2facing = 0; //number of shared faces facing towards area 2
|
||
for (face1 = tmparea1->tmpfaces; face1; face1 = face1->next[side])
|
||
{
|
||
side = face1->frontarea != tmparea1;
|
||
if (face1->backarea == tmparea2 || face1->frontarea == tmparea2)
|
||
{
|
||
sharedface = face1;
|
||
numsharedfaces++;
|
||
if (face1->frontarea == tmparea1) area1facing++;
|
||
else area2facing++;
|
||
} //end if
|
||
} //end if
|
||
if (!sharedface) return;
|
||
//if there's only one shared face
|
||
if (numsharedfaces <= 1) return;
|
||
//if all the shared faces are facing to the same area
|
||
if (numsharedfaces == area1facing || numsharedfaces == area2facing) return;
|
||
//
|
||
do
|
||
{
|
||
for (face1 = tmparea1->tmpfaces; face1; face1 = face1->next[side])
|
||
{
|
||
side = face1->frontarea != tmparea1;
|
||
if (face1->backarea == tmparea2 || face1->frontarea == tmparea2)
|
||
{
|
||
if (face1->frontarea != tmparea1)
|
||
{
|
||
AAS_FlipFace(face1);
|
||
break;
|
||
} //end if
|
||
} //end if
|
||
} //end for
|
||
} while(face1);
|
||
} //end of the function AAS_FlipAreaSharedFaces
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_FlipSharedFaces(void)
|
||
{
|
||
int i;
|
||
tmp_area_t *tmparea1, *tmparea2;
|
||
|
||
i = 0;
|
||
qprintf("%6d areas checked for shared face flipping", i);
|
||
for (tmparea1 = tmpaasworld.areas; tmparea1; tmparea1 = tmparea1->l_next)
|
||
{
|
||
if (tmparea1->invalid) continue;
|
||
for (tmparea2 = tmpaasworld.areas; tmparea2; tmparea2 = tmparea2->l_next)
|
||
{
|
||
if (tmparea2->invalid) continue;
|
||
if (tmparea1 == tmparea2) continue;
|
||
AAS_FlipAreaSharedFaces(tmparea1, tmparea2);
|
||
} //end for
|
||
qprintf("\r%6d", ++i);
|
||
} //end for
|
||
Log_Print("\r%6d areas checked for shared face flipping\n", i);
|
||
} //end of the function AAS_FlipSharedFaces
|
||
*/
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_FlipSharedFaces( void ) {
|
||
int i, side1, side2;
|
||
tmp_area_t *tmparea1;
|
||
tmp_face_t *face1, *face2;
|
||
|
||
i = 0;
|
||
qprintf( "%6d areas checked for shared face flipping", i );
|
||
for ( tmparea1 = tmpaasworld.areas; tmparea1; tmparea1 = tmparea1->l_next )
|
||
{
|
||
if ( tmparea1->invalid ) {
|
||
continue;
|
||
}
|
||
for ( face1 = tmparea1->tmpfaces; face1; face1 = face1->next[side1] )
|
||
{
|
||
side1 = face1->frontarea != tmparea1;
|
||
if ( !face1->frontarea || !face1->backarea ) {
|
||
continue;
|
||
}
|
||
//
|
||
for ( face2 = face1->next[side1]; face2; face2 = face2->next[side2] )
|
||
{
|
||
side2 = face2->frontarea != tmparea1;
|
||
if ( !face2->frontarea || !face2->backarea ) {
|
||
continue;
|
||
}
|
||
//
|
||
if ( face1->frontarea == face2->backarea &&
|
||
face1->backarea == face2->frontarea ) {
|
||
AAS_FlipFace( face2 );
|
||
} //end if
|
||
//recheck side
|
||
side2 = face2->frontarea != tmparea1;
|
||
} //end for
|
||
} //end for
|
||
qprintf( "\r%6d", ++i );
|
||
} //end for
|
||
qprintf( "\n" );
|
||
Log_Print( "%6d areas checked for shared face flipping\r\n", i );
|
||
} //end of the function AAS_FlipSharedFaces
|
||
//===========================================================================
|
||
// creates an .AAS file with the given name
|
||
// a MAP should be loaded before calling this
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AAS_Create( char *aasfile ) {
|
||
entity_t *e;
|
||
tree_t *tree;
|
||
double start_time;
|
||
|
||
//for a possible leak file
|
||
strcpy( source, aasfile );
|
||
StripExtension( source );
|
||
//the time started
|
||
start_time = I_FloatTime();
|
||
//set the default number of threads (depends on number of processors)
|
||
ThreadSetDefault();
|
||
//set the global entity number to the world model
|
||
entity_num = 0;
|
||
//the world entity
|
||
e = &entities[entity_num];
|
||
//process the whole world
|
||
tree = ProcessWorldBrushes( e->firstbrush, e->firstbrush + e->numbrushes );
|
||
//if the conversion is cancelled
|
||
if ( cancelconversion ) {
|
||
Tree_Free( tree );
|
||
return;
|
||
} //end if
|
||
//display BSP tree creation time
|
||
Log_Print( "BSP tree created in %5.0f seconds\n", I_FloatTime() - start_time );
|
||
//prune the bsp tree
|
||
Tree_PruneNodes( tree->headnode );
|
||
//if the conversion is cancelled
|
||
if ( cancelconversion ) {
|
||
Tree_Free( tree );
|
||
return;
|
||
} //end if
|
||
//create the tree portals
|
||
MakeTreePortals( tree );
|
||
//if the conversion is cancelled
|
||
if ( cancelconversion ) {
|
||
Tree_Free( tree );
|
||
return;
|
||
} //end if
|
||
//Marks all nodes that can be reached by entites
|
||
if ( FloodEntities( tree ) ) {
|
||
//fill out nodes that can't be reached
|
||
FillOutside( tree->headnode );
|
||
} //end if
|
||
else
|
||
{
|
||
LeakFile( tree );
|
||
Error( "**** leaked ****\n" );
|
||
return;
|
||
} //end else
|
||
//create AAS from the BSP tree
|
||
//==========================================
|
||
//initialize tmp aas
|
||
AAS_InitTmpAAS();
|
||
//create the convex areas from the leaves
|
||
AAS_CreateAreas( tree->headnode );
|
||
//free the BSP tree because it isn't used anymore
|
||
if ( freetree ) {
|
||
Tree_Free( tree );
|
||
}
|
||
//try to merge area faces
|
||
AAS_MergeAreaFaces();
|
||
//do gravitational subdivision
|
||
AAS_GravitationalSubdivision();
|
||
//merge faces if possible
|
||
AAS_MergeAreaFaces();
|
||
AAS_RemoveAreaFaceColinearPoints();
|
||
//merge areas if possible
|
||
AAS_MergeAreas();
|
||
//NOTE: prune nodes directly after area merging
|
||
AAS_PruneNodes();
|
||
//flip shared faces so they are all facing to the same area
|
||
AAS_FlipSharedFaces();
|
||
AAS_RemoveAreaFaceColinearPoints();
|
||
//merge faces if possible
|
||
AAS_MergeAreaFaces();
|
||
//merge area faces in the same plane
|
||
AAS_MergeAreaPlaneFaces();
|
||
//do ladder subdivision
|
||
AAS_LadderSubdivision();
|
||
//FIXME: melting is buggy
|
||
AAS_MeltAreaFaceWindings();
|
||
//remove tiny faces
|
||
AAS_RemoveTinyFaces();
|
||
//create area settings
|
||
AAS_CreateAreaSettings();
|
||
//check if the winding plane is equal to the face plane
|
||
//AAS_CheckAreaWindingPlanes();
|
||
//
|
||
//AAS_CheckSharedFaces();
|
||
//==========================================
|
||
//if the conversion is cancelled
|
||
if ( cancelconversion ) {
|
||
Tree_Free( tree );
|
||
AAS_FreeTmpAAS();
|
||
return;
|
||
} //end if
|
||
//store the created AAS stuff in the AAS file format and write the file
|
||
AAS_StoreFile( aasfile );
|
||
//free the temporary AAS memory
|
||
AAS_FreeTmpAAS();
|
||
//display creation time
|
||
Log_Print( "\nAAS created in %5.0f seconds\n", I_FloatTime() - start_time );
|
||
} //end of the function AAS_Create
|