//===========================================================================
// NOTE: the original face is invalid after splitting
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void AAS_SplitFace(tmp_face_t *face, vec3_t normal, float dist,
							tmp_face_t **frontface, tmp_face_t **backface)
{
	winding_t *frontw, *backw;

	//
	*frontface = *backface = NULL;

	ClipWindingEpsilon(face->winding, normal, dist, FACECLIP_EPSILON, &frontw, &backw);

#ifdef DEBUG
	//
	if (frontw)
	{
		if (WindingIsTiny(frontw))
		{
			Log_Write("AAS_SplitFace: tiny back face\r\n");
			FreeWinding(frontw);
			frontw = NULL;
		} //end if
	} //end if
	if (backw)
	{
		if (WindingIsTiny(backw))
		{
			Log_Write("AAS_SplitFace: tiny back face\r\n");
			FreeWinding(backw);
			backw = NULL;
		} //end if
	} //end if
#endif //DEBUG
	//if the winding was split
	if (frontw)
	{
		//check bounds
		(*frontface) = AAS_AllocTmpFace();
		(*frontface)->planenum = face->planenum;
		(*frontface)->winding = frontw;
		(*frontface)->faceflags = face->faceflags;
	} //end if
	if (backw)
	{
		//check bounds
		(*backface) = AAS_AllocTmpFace();
		(*backface)->planenum = face->planenum;
		(*backface)->winding = backw;
		(*backface)->faceflags = face->faceflags;
	} //end if
} //end of the function AAS_SplitFace
Beispiel #2
0
//===========================================================================
// create a tmp AAS area from a leaf node
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
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;

	//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_WATER) tmparea->contents |= AREACONTENTS_WATER;
	if (node->contents & CONTENTS_LAVA) tmparea->contents |= AREACONTENTS_LAVA;
	if (node->contents & CONTENTS_SLIME) tmparea->contents |= AREACONTENTS_SLIME;
	if (node->contents & CONTENTS_NOTTEAM1) tmparea->contents |= AREACONTENTS_NOTTEAM1;
	if (node->contents & CONTENTS_NOTTEAM2) tmparea->contents |= AREACONTENTS_NOTTEAM2;

	//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:		-
//===========================================================================
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
Beispiel #4
0
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};
//	vec3_t mins, maxs;
//	qboolean allowFreeIfSmall = 1;

//	VectorClear( mins );
//	VectorClear( maxs );

	//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 | CONTENTS_MONSTERCLIP ) ) {
				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
/*
		// RF, add this face to the bounds
		if (p->tmpface->faceflags & FACE_GROUND) {
			WindingBounds( p->winding, mins, maxs );
		}

		// RF, if this face has a solid at the other side, and it is not a GROUND, then we cannot free if its too small
		if (allowFreeIfSmall && (p->tmpface->faceflags & FACE_SOLID) && !(p->tmpface->faceflags & FACE_GROUND)) {
			// make sure it's not a ceiling
			if (!(DotProduct(cfg.phys_gravitydirection, mapplanes[p->tmpface->planenum].normal) > cfg.phys_maxsteepness)) {
				allowFreeIfSmall = 0;
			}
		}
*/
	} //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;
	}
/*
	// RF, if we are using only ground areas, then ignore areas that arent grounded or attached to ladders, or underwater
	if (groundonly && !(areafaceflags & (FACE_GROUND|FACE_LADDER)) && !(tmparea->contents & (AREACONTENTS_WATER|AREACONTENTS_SLIME|AREACONTENTS_LAVA))) {
		numGroundOnlyFreed++;
		tmparea->invalid = true;
	}
*/
/*
	// RF, if this is a really small area, and it is surrounded by non-solid portals, then nuke it
	if (allowFreeIfSmall && !(areafaceflags & (FACE_LADDER)) && VectorDistance( mins, maxs ) < 32) {
		numTinyFreed++;
		tmparea->invalid = true;
	}
*/
	//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