Beispiel #1
0
/*
============
idAASLocal::GetWallEdges
============
*/
int idAASLocal::GetWallEdges( int areaNum, const idBounds &bounds, int travelFlags, int *edges, int maxEdges ) const {
	int i, j, k, l, face1Num, face2Num, edge1Num, edge2Num, numEdges, absEdge1Num;
	int *areaQueue, curArea, queueStart, queueEnd;
	byte *areasVisited;
	const aasArea_t *area;
	const aasFace_t *face1, *face2;
	idReachability *reach;
	if( !file ) {
		return 0;
	}
	numEdges = 0;
	areasVisited = ( byte * ) _alloca16( file->GetNumAreas() );
	memset( areasVisited, 0, file->GetNumAreas() * sizeof( byte ) );
	areaQueue = ( int * ) _alloca16( file->GetNumAreas() * sizeof( int ) );
	queueStart = -1;
	queueEnd = 0;
	areaQueue[0] = areaNum;
	areasVisited[areaNum] = true;
	for( curArea = areaNum; queueStart < queueEnd; curArea = areaQueue[++queueStart] ) {
		area = &file->GetArea( curArea );
		for( i = 0; i < area->numFaces; i++ ) {
			face1Num = file->GetFaceIndex( area->firstFace + i );
			face1 = &file->GetFace( abs( face1Num ) );
			if( !( face1->flags & FACE_FLOOR ) ) {
				continue;
			}
			for( j = 0; j < face1->numEdges; j++ ) {
				edge1Num = file->GetEdgeIndex( face1->firstEdge + j );
				absEdge1Num = abs( edge1Num );
				// test if the edge is shared by another floor face of this area
				for( k = 0; k < area->numFaces; k++ ) {
					if( k == i ) {
						continue;
					}
					face2Num = file->GetFaceIndex( area->firstFace + k );
					face2 = &file->GetFace( abs( face2Num ) );
					if( !( face2->flags & FACE_FLOOR ) ) {
						continue;
					}
					for( l = 0; l < face2->numEdges; l++ ) {
						edge2Num = abs( file->GetEdgeIndex( face2->firstEdge + l ) );
						if( edge2Num == absEdge1Num ) {
							break;
						}
					}
					if( l < face2->numEdges ) {
						break;
					}
				}
				if( k < area->numFaces ) {
					continue;
				}
				// test if the edge is used by a reachability
				for( reach = area->reach; reach; reach = reach->next ) {
					if( reach->travelType & travelFlags ) {
						if( reach->edgeNum == absEdge1Num ) {
							break;
						}
					}
				}
				if( reach ) {
					continue;
				}
				// test if the edge is already in the list
				for( k = 0; k < numEdges; k++ ) {
					if( edge1Num == edges[k] ) {
						break;
					}
				}
				if( k < numEdges ) {
					continue;
				}
				// add the edge to the list
				edges[numEdges++] = edge1Num;
				if( numEdges >= maxEdges ) {
					return numEdges;
				}
			}
		}
		// add new areas to the queue
		for( reach = area->reach; reach; reach = reach->next ) {
			if( reach->travelType & travelFlags ) {
				// if the area the reachability leads to hasn't been visited yet and the area bounds touch the search bounds
				if( !areasVisited[reach->toAreaNum] && bounds.IntersectsBounds( file->GetArea( reach->toAreaNum ).bounds ) ) {
					areaQueue[queueEnd++] = reach->toAreaNum;
					areasVisited[reach->toAreaNum] = true;
				}
			}
		}
	}
	return numEdges;
}