// Given a line segment from vStart to vEnd
// and a list of convex polygons in pSurfInfos and nSurfInfos, 
// fill in the list of which polygons the segment intersects.
// Returns the number of intersected surfaces.
static int IntersectSegmentWithSurfInfos(
	const Vector &vStart,
	const Vector &vEnd,
	SurfInfo *pSurfInfos,
	const int nSurfInfos,
	SurfInfo ** pIntersections,
	Vector *pIntersectionPositions,
	int nMaxIntersections)
{
	if(nMaxIntersections == 0)
		return 0;

	int nIntersections = 0;
	for(int i=0; i < nSurfInfos; i++)
	{
		SurfInfo *pSurf = &pSurfInfos[i];

		// Does it intersect the plane?
		float dot1 = pSurf->m_Plane.DistTo(vStart);
		float dot2 = pSurf->m_Plane.DistTo(vEnd);
		if((dot1 > 0) != (dot2 > 0))
		{
			float t = dot1 / (dot1 - dot2);
			Vector vIntersection = vStart + (vEnd - vStart) * t;
			
			// If the intersection is behind any edge plane, then it's not inside the polygon.
			unsigned long iEdge;
			for(iEdge=0; iEdge < pSurf->m_nVerts; iEdge++)
			{
				VPlane edgePlane;
				edgePlane.m_Normal = pSurf->m_Plane.m_Normal.Cross(pSurf->m_Verts[iEdge] - pSurf->m_Verts[(iEdge+1)%pSurf->m_nVerts]);
				VectorNormalize( edgePlane.m_Normal );
				edgePlane.m_Dist = edgePlane.m_Normal.Dot(pSurf->m_Verts[iEdge]);

				if(edgePlane.DistTo(vIntersection) < 0.0f)
					break;
			}

			if(iEdge == pSurf->m_nVerts)
			{
				pIntersections[nIntersections] = pSurf;
				pIntersectionPositions[nIntersections] = vIntersection;
				++nIntersections;
				if(nIntersections >= nMaxIntersections)
					break;
			}
		}
	}

	return nIntersections;
}
bool CFuncAreaPortalBase::UpdateVisibility( const Vector &vOrigin, float fovDistanceAdjustFactor, bool &bIsOpenOnClient )
{
	// NOTE: We leave bIsOpenOnClient alone on purpose here. See the header for a description of why.
	
	if( m_portalNumber == -1 )
		return false;

	// See if the viewer is on the backside.
	VPlane plane;
	if( !engine->GetAreaPortalPlane( vOrigin, m_portalNumber, &plane ) )
		return true; // leave it open if there's an error here for some reason

	bool bOpen = false;
	if( plane.DistTo( vOrigin ) + VIEWER_PADDING > 0 )
		bOpen = true;

	return bOpen;
}
Пример #3
0
bool CFuncAreaPortalBase::UpdateVisibility( const CUtlVector< Vector > &vecOrigins, float fovDistanceAdjustFactor, bool &bIsOpenOnClient )
{
	// NOTE: We leave bIsOpenOnClient alone on purpose here. See the header for a description of why.
	
	if( m_portalNumber == -1 )
		return false;

	// See if the viewer is on the backside.
	for ( int i = 0; i < vecOrigins.Count(); ++i )
	{
		const Vector &vOrigin = vecOrigins[ i ];
		VPlane plane;
		if( !engine->GetAreaPortalPlane( vOrigin, m_portalNumber, &plane ) )
			return true; // leave it open if there's an error here for some reason

		// If either players' origin is on the front, the areaportal is considered opened...
		if( plane.DistTo( vOrigin ) + VIEWER_PADDING > 0 )
			return true;
	}

	return false;
}