// 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;
}
예제 #2
0
VMatrix SetupMatrixReflection(const VPlane &thePlane)
{
	VMatrix mReflect, mBack, mForward;
	Vector vOrigin, N;

	N = thePlane.m_Normal;

	mReflect.Init( 
		-2.0f*N.x*N.x + 1.0f,	-2.0f*N.x*N.y,			-2.0f*N.x*N.z,			0.0f,
		-2.0f*N.y*N.x,			-2.0f*N.y*N.y + 1.0f,	-2.0f*N.y*N.z,			0.0f,
		-2.0f*N.z*N.x,			-2.0f*N.z*N.y,			-2.0f*N.z*N.z + 1.0f,	0.0f,
		0.0f,					0.0f,					0.0f,					1.0f
		);

	vOrigin = thePlane.GetPointOnPlane();

	mBack.Identity();
	mBack.SetTranslation(-vOrigin);

	mForward.Identity();
	mForward.SetTranslation(vOrigin);

	// (multiplied in reverse order, so it translates to the origin point,
	// reflects, and translates back).
	return mForward * mReflect * mBack;
}
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;
}
예제 #4
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;
}
예제 #5
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_FireSmoke::FindClipPlane( void )
{
	m_bClipTested	= true;
	m_flClipPerc	= 1.0f;

	trace_t	tr;
	Vector	end( 0.0f, 0.0f, SMOKE_RISE_RATE*SMOKE_LIFETIME );
	
	UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin()+end, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr );

	//If the ceiling is too close, reject smoke
	if ( tr.fraction < 0.5f )
	{
		m_nFlags &= ~bitsFIRESMOKE_SMOKE;
		return;
	}

	if ( tr.fraction < 1.0f )
	{
		m_planeClip.Init( tr.plane.normal, tr.plane.dist );
		m_nFlags		|= bitsFIRESMOKE_SMOKE_COLLISION;
		m_flClipPerc	= tr.fraction * 0.5f;
	}
}