// 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; }
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; }