Esempio n. 1
0
//===========================================================================
//
// 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
Esempio n. 2
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void AAS_MergePlaneFaces(tmp_area_t *tmparea, int planenum)
{
	tmp_face_t *face1, *face2, *nextface2;
	winding_t *neww;
	int side1, side2;

	for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1])
	{
		side1 = face1->frontarea != tmparea;
		if (face1->planenum != planenum) continue;
		//
		for (face2 = face1->next[side1]; face2; face2 = nextface2)
		{
			side2 = face2->frontarea != tmparea;
			nextface2 = face2->next[side2];
			//
			if ((face2->planenum & ~1) != (planenum & ~1)) continue;
			//
			neww = MergeWindings(face1->winding, face2->winding,
								mapplanes[face1->planenum].normal);
			FreeWinding(face1->winding);
			face1->winding = neww;
			if (face2->frontarea) AAS_RemoveFaceFromArea(face2, face2->frontarea);
			if (face2->backarea) AAS_RemoveFaceFromArea(face2, face2->backarea);
			AAS_FreeTmpFace(face2);
			//
			nextface2 = face1->next[side1];
		} //end for
	} //end for
} //end of the function AAS_MergePlaneFaces
Esempio n. 3
0
//===========================================================================
//
// 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
Esempio n. 4
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
int AAS_TryMergeFaces( tmp_face_t *face1, tmp_face_t *face2 ) {
	winding_t *neww;

#ifdef DEBUG
	if ( !face1->winding ) {
		Error( "face1 %d without winding", face1->num );
	}
	if ( !face2->winding ) {
		Error( "face2 %d without winding", face2->num );
	}
#endif //DEBUG
	   //
	if ( face1->faceflags != face2->faceflags ) {
		return false;
	}
	//NOTE: if the front or back area is zero this doesn't mean there's
	//a real area. It means there's solid at that side of the face
	//if both faces have the same front area
	if ( face1->frontarea == face2->frontarea ) {
		//if both faces have the same back area
		if ( face1->backarea == face2->backarea ) {
			//if the faces are in the same plane
			if ( face1->planenum == face2->planenum ) {
				//if they have both a front and a back area (no solid on either side)
				if ( face1->frontarea && face1->backarea ) {
					neww = MergeWindings( face1->winding, face2->winding,
										  mapplanes[face1->planenum].normal );
				} //end if
				else
				{
					//this function is to be found in l_poly.c
					neww = TryMergeWinding( face1->winding, face2->winding,
											mapplanes[face1->planenum].normal );
				} //end else
				if ( neww ) {
					FreeWinding( face1->winding );
					face1->winding = neww;
					if ( face2->frontarea ) {
						AAS_RemoveFaceFromArea( face2, face2->frontarea );
					}
					if ( face2->backarea ) {
						AAS_RemoveFaceFromArea( face2, face2->backarea );
					}
					AAS_FreeTmpFace( face2 );
					return true;
				} //end if
			} //end if
			else if ( ( face1->planenum & ~1 ) == ( face2->planenum & ~1 ) ) {
				Log_Write( "face %d and %d, same front and back area but flipped planes\r\n",
						   face1->num, face2->num );
			} //end if
		} //end if
	} //end if
	return false;
} //end of the function AAS_TryMergeFaces
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void AAS_SplitArea( tmp_area_t *tmparea, int planenum, tmp_area_t **frontarea, tmp_area_t **backarea ) {
	int side;
	tmp_area_t *facefrontarea, *facebackarea, *faceotherarea;
	tmp_face_t *face, *frontface, *backface, *splitface, *nextface;
	winding_t *splitwinding;
	plane_t *splitplane;

/*
#ifdef AW_DEBUG
	int facesplits, groundsplits, epsilonface;
	Log_Print("\n----------------------\n");
	Log_Print("splitting area %d\n", areanum);
	Log_Print("with normal = \'%f %f %f\', dist = %f\n", normal[0], normal[1], normal[2], dist);
	AAS_TestSplitPlane(areanum, normal, dist, &facesplits, &groundsplits, &epsilonface);
	Log_Print("face splits = %d\nground splits = %d\n", facesplits, groundsplits);
	if (epsilonface) Log_Print("aaahh epsilon face\n");
#endif //AW_DEBUG*/
	//the original area

	AAS_FlipAreaFaces( tmparea );
	AAS_CheckArea( tmparea );
	//
	splitplane = &mapplanes[planenum];
/*	//create a split winding, first base winding for plane
	splitwinding = BaseWindingForPlane(splitplane->normal, splitplane->dist);
	//chop with all the faces of the area
	for (face = tmparea->tmpfaces; face && splitwinding; face = face->next[side])
	{
		//side of the face the original area was on
		side = face->frontarea != tmparea->areanum;
		plane = &mapplanes[face->planenum ^ side];
		ChopWindingInPlace(&splitwinding, plane->normal, plane->dist, 0); // PLANESIDE_EPSILON);
	} //end for*/
	splitwinding = AAS_SplitWinding( tmparea, planenum );
	if ( !splitwinding ) {
/*
#ifdef DEBUG
		AAS_TestSplitPlane(areanum, normal, dist, &facesplits, &groundsplits, &epsilonface);
		Log_Print("\nface splits = %d\nground splits = %d\n", facesplits, groundsplits);
		if (epsilonface) Log_Print("aaahh epsilon face\n");
#endif //DEBUG*/
		Error( "AAS_SplitArea: no split winding when splitting area %d\n", tmparea->areanum );
	} //end if
	  //create a split face
	splitface = AAS_AllocTmpFace();
	//get the map plane
	splitface->planenum = planenum;
	//store the split winding
	splitface->winding = splitwinding;
	//the new front area
	( *frontarea ) = AAS_AllocTmpArea();
	( *frontarea )->presencetype = tmparea->presencetype;
	( *frontarea )->contents = tmparea->contents;
	( *frontarea )->modelnum = tmparea->modelnum;
	( *frontarea )->tmpfaces = NULL;
	//the new back area
	( *backarea ) = AAS_AllocTmpArea();
	( *backarea )->presencetype = tmparea->presencetype;
	( *backarea )->contents = tmparea->contents;
	( *backarea )->modelnum = tmparea->modelnum;
	( *backarea )->tmpfaces = NULL;
	//add the split face to the new areas
	AAS_AddFaceSideToArea( splitface, 0, ( *frontarea ) );
	AAS_AddFaceSideToArea( splitface, 1, ( *backarea ) );

	//split all the faces of the original area
	for ( face = tmparea->tmpfaces; face; face = nextface )
	{
		//side of the face the original area was on
		side = face->frontarea != tmparea;
		//next face of the original area
		nextface = face->next[side];
		//front area of the face
		facefrontarea = face->frontarea;
		//back area of the face
		facebackarea = face->backarea;
		//remove the face from both the front and back areas
		if ( facefrontarea ) {
			AAS_RemoveFaceFromArea( face, facefrontarea );
		}
		if ( facebackarea ) {
			AAS_RemoveFaceFromArea( face, facebackarea );
		}
		//split the face
		AAS_SplitFace( face, splitplane->normal, splitplane->dist, &frontface, &backface );
		//free the original face
		AAS_FreeTmpFace( face );
		//get the number of the area at the other side of the face
		if ( side ) {
			faceotherarea = facefrontarea;
		} else { faceotherarea = facebackarea;}
		//if there is an area at the other side of the original face
		if ( faceotherarea ) {
			if ( frontface ) {
				AAS_AddFaceSideToArea( frontface, !side, faceotherarea );
			}
			if ( backface ) {
				AAS_AddFaceSideToArea( backface, !side, faceotherarea );
			}
		} //end if
		  //add the front and back part left after splitting the original face to the new areas
		if ( frontface ) {
			AAS_AddFaceSideToArea( frontface, side, ( *frontarea ) );
		}
		if ( backface ) {
			AAS_AddFaceSideToArea( backface, side, ( *backarea ) );
		}
	} //end for

	if ( !( *frontarea )->tmpfaces ) {
		Log_Print( "AAS_SplitArea: front area without faces\n" );
	}
	if ( !( *backarea )->tmpfaces ) {
		Log_Print( "AAS_SplitArea: back area without faces\n" );
	}

	tmparea->invalid = true;
/*
#ifdef AW_DEBUG
	for (i = 0, face = frontarea->tmpfaces; face; face = face->next[side])
	{
		side = face->frontarea != frontarea->areanum;
		i++;
	} //end for
	Log_Print("created front area %d with %d faces\n", frontarea->areanum, i);

	for (i = 0, face = backarea->tmpfaces; face; face = face->next[side])
	{
		side = face->frontarea != backarea->areanum;
		i++;
	} //end for
	Log_Print("created back area %d with %d faces\n", backarea->areanum, i);
#endif //AW_DEBUG*/

	AAS_FlipAreaFaces( ( *frontarea ) );
	AAS_FlipAreaFaces( ( *backarea ) );
	//
	AAS_CheckArea( ( *frontarea ) );
	AAS_CheckArea( ( *backarea ) );
} //end of the function AAS_SplitArea
//===========================================================================
// 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