level/vis_flow.c
/*
==============
ClipToSeperators

Source, pass, and target are an ordering of portals.

Generates separating planes candidates by taking two points from source and one
point from pass, and clips target by them.

If target is totally clipped away, that portal can not be seen through.

Normal clip keeps target on the same side as pass, which is correct if the
order goes source, pass, target.  If the order goes pass, source, target then
flipclip should be set.
==============
*/
ClipToSeperators
Source, pass, and target are an ordering of portals.

Generates separating planes candidates by taking two points from source and one
point from pass, and clips target by them.

If target is totally clipped away, that portal can not be seen through.

Normal clip keeps target on the same side as pass, which is correct if the
order goes source, pass, target.  If the order goes pass, source, target then
flipclip should be set.
ClipToSeperators Source pass and target are an ordering of portals . Generates separating planes candidates by taking two points from source and one point from pass and clips target by them . If target is totally clipped away that portal can not be seen through . Normal clip keeps target on the same side as pass which is correct if the order goes source pass target . If the order goes pass source target then flipclip should be set .
viswinding_t *ClipToSeperators (viswinding_t *source, viswinding_t *pass, viswinding_t *target, bool flipclip)
{
	int			i, j, k, l;
	plane_t		plane;
	vec3_t		v1, v2;
	vec_t		d, epcompare;
	vec_t		length;
	bool		fliptest;
	for (i=0 ; i<source->numpoints ; i++)
	{
		l = (i+1)%source->numpoints;
		VectorSubtract (source->points[l], source->points[i], v1);
		for (j=0 ; j<pass->numpoints ; j++)
		{
			VectorSubtract (pass->points[j], source->points[i], v2);
			CrossProduct(v1, v2, plane.normal);
			length = DotProduct(plane.normal, plane.normal);
			if (length < ON_EPSILON)
				continue;
			length = 1/sqrt(length);
			VectorScale( plane.normal, length, plane.normal );
			plane.dist = DotProduct (pass->points[j], plane.normal);
		 find out which side of the generated seperating plane has the
		 source portal
			fliptest = false;
			for (k=0 ; k<source->numpoints ; k++)
			{
				if (k == i || k == l)
					continue;
				d = DotProduct (source->points[k], plane.normal) - plane.dist;
				if (d < -ON_EPSILON)
				{	 source is on the negative side, so we want all
					 pass and target on the positive side
					fliptest = false;
					break;
				}
				else if (d > ON_EPSILON)
				{	 source is on the positive side, so we want all
					 pass and target on the negative side
					fliptest = true;
					break;
				}
			}
			if (k == source->numpoints)
				continue;		 planar with source portal
		 flip the normal if the source portal is backwards
			if (fliptest)
			{
				VectorInverse (plane.normal);
				plane.dist = -plane.dist;
			}
		 if all of the pass portal points are now on the positive side,
		 this is the seperating plane
			 LordHavoc: rewrote this to be faster
			for (k=0;k<j;k++)
			{
				d = DotProduct (pass->points[k], plane.normal) - plane.dist;
				if (d < -ON_EPSILON) goto cliptoseperatorscontinue;
				else if (d > ON_EPSILON) {epcompare = plane.dist - ON_EPSILON;goto cliptoseperatorsloop1;}
			}
			for (k=j+1;k<pass->numpoints;k++)
			{
				d = DotProduct (pass->points[k], plane.normal) - plane.dist;
				if (d < -ON_EPSILON) goto cliptoseperatorscontinue;
				else if (d > ON_EPSILON) {epcompare = plane.dist - ON_EPSILON;goto cliptoseperatorsloop2;}
			}
			continue;
			for (;k<j;k++)
			{
				if (DotProduct(pass->points[k], plane.normal) < epcompare) goto cliptoseperatorscontinue;
cliptoseperatorsloop1:
				;
			}
			for (k=j+1;k<pass->numpoints;k++)
			{
				if (DotProduct(pass->points[k], plane.normal) < epcompare) goto cliptoseperatorscontinue;
cliptoseperatorsloop2:
				;
			}
			/*
			 original code
			counts[0] = counts[1] = counts[2] = 0;
			for (k=0 ; k<pass->numpoints ; k++)
			{
				if (k==j)
					continue;
				d = DotProduct (pass->points[k], plane.normal) - plane.dist;
				if (d < -ON_EPSILON)
					break;
				else if (d > ON_EPSILON)
					counts[0]++;
				else
					counts[2]++;
			}
			if (k != pass->numpoints)
				continue;	 points on negative side, not a seperating plane
			if (!counts[0])
			{
				continue;	 planar with seperating plane
			}
			*/
		 flip the normal if we want the back side
			if (flipclip)
			{
				VectorInverse(plane.normal);
				plane.dist = -plane.dist;
			}
		 clip target by the seperating plane
			target = ClipVisWinding (target, &plane, false);
			if (!target)
				return NULL;		 target is not visible
			if (rvis)
				break;
cliptoseperatorscontinue:
			;
		}
	}
	return target;
}
viswinding_t * ClipToSeperators ( viswinding_t * source , viswinding_t * pass , viswinding_t * target , bool flipclip ) { int i , j , k , l ; plane_t plane ; vec3_t v1 , v2 ; vec_t d , epcompare ; vec_t length ; bool fliptest ; for ( i = 0 ; i < source -> numpoints ; i ++ ) { l = ( i + 1 ) % source -> numpoints ; VectorSubtract ( source -> points [ l ] , source -> points [ i ] , v1 ) ; for ( j = 0 ; j < pass -> numpoints ; j ++ ) { VectorSubtract ( pass -> points [ j ] , source -> points [ i ] , v2 ) ; CrossProduct ( v1 , v2 , plane . normal ) ; length = DotProduct ( plane . normal , plane . normal ) ; if ( length < ON_EPSILON ) continue ; length = 1 / sqrt ( length ) ; VectorScale ( plane . normal , length , plane . normal ) ; plane . dist = DotProduct ( pass -> points [ j ] , plane . normal ) ; fliptest = false ; for ( k = 0 ; k < source -> numpoints ; k ++ ) { if ( k == i || k == l ) continue ; d = DotProduct ( source -> points [ k ] , plane . normal ) - plane . dist ; if ( d < - ON_EPSILON ) { fliptest = false ; break ; } else if ( d > ON_EPSILON ) { fliptest = true ; break ; } } if ( k == source -> numpoints ) continue ; if ( fliptest ) { VectorInverse ( plane . normal ) ; plane . dist = - plane . dist ; } for ( k = 0 ; k < j ; k ++ ) { d = DotProduct ( pass -> points [ k ] , plane . normal ) - plane . dist ; if ( d < - ON_EPSILON ) goto cliptoseperatorscontinue ; else if ( d > ON_EPSILON ) { epcompare = plane . dist - ON_EPSILON ; goto cliptoseperatorsloop1 ; } } for ( k = j + 1 ; k < pass -> numpoints ; k ++ ) { d = DotProduct ( pass -> points [ k ] , plane . normal ) - plane . dist ; if ( d < - ON_EPSILON ) goto cliptoseperatorscontinue ; else if ( d > ON_EPSILON ) { epcompare = plane . dist - ON_EPSILON ; goto cliptoseperatorsloop2 ; } } continue ; for ( ; k < j ; k ++ ) { if ( DotProduct ( pass -> points [ k ] , plane . normal ) < epcompare ) goto cliptoseperatorscontinue ; cliptoseperatorsloop1 : ; } for ( k = j + 1 ; k < pass -> numpoints ; k ++ ) { if ( DotProduct ( pass -> points [ k ] , plane . normal ) < epcompare ) goto cliptoseperatorscontinue ; cliptoseperatorsloop2 : ; } if ( flipclip ) { VectorInverse ( plane . normal ) ; plane . dist = - plane . dist ; } target = ClipVisWinding ( target , & plane , false ) ; if ( ! target ) return NULL ; if ( rvis ) break ; cliptoseperatorscontinue : ; } } return target ; }
ClipToSeperators
Source, pass, and target are an ordering of portals.
ClipToSeperators Source pass and target are an ordering of portals .
//	int			counts[3]; // check all combinations // find a vertex of pass that makes a plane that puts all of the // vertexes of pass on the front side and all of the vertexes of // source on the back side // if points don't make a valid plane, skip it // // find out which side of the generated seperating plane has the // source portal // // source is on the negative side, so we want all // pass and target on the positive side // source is on the positive side, so we want all // pass and target on the negative side // planar with source portal // // flip the normal if the source portal is backwards // // // if all of the pass portal points are now on the positive side, // this is the seperating plane // // LordHavoc: rewrote this to be faster /*
			// original code
			counts[0] = counts[1] = counts[2] = 0;
			for (k=0 ; k<pass->numpoints ; k++)
			{
				if (k==j)
					continue;
				d = DotProduct (pass->points[k], plane.normal) - plane.dist;
				if (d < -ON_EPSILON)
					break;
				else if (d > ON_EPSILON)
					counts[0]++;
				else
					counts[2]++;
			}
			if (k != pass->numpoints)
				continue;	// points on negative side, not a seperating plane

			if (!counts[0])
			{
				continue;	// planar with seperating plane
			}
			*/ // // flip the normal if we want the back side // // // clip target by the seperating plane // // target is not visible