BOOL CActor::CanPickItem(const CFrustum& frustum, const Fvector& from, CObject* item) { BOOL bOverlaped = FALSE; Fvector dir,to; item->Center (to); float range = dir.sub(to,from).magnitude(); if (range>0.25f){ if (frustum.testSphere_dirty(to,item->Radius())){ dir.div (range); collide::ray_defs RD(from, dir, range, CDB::OPT_CULL, collide::rqtBoth); VERIFY (!fis_zero(RD.dir.square_magnitude())); RQR.r_clear (); Level().ObjectSpace.RayQuery(RQR,RD, info_trace_callback, &bOverlaped, NULL, item); } } return !bOverlaped; }
bool CEditShape::FrustumPick(const CFrustum& frustum) { const Fmatrix& M = _Transform(); for (ShapeIt it=shapes.begin(); it!=shapes.end(); it++){ switch (it->type){ case cfSphere:{ Fvector C; Fsphere& T = it->data.sphere; M.transform_tiny(C,T.P); if (frustum.testSphere_dirty(C,T.R*FScale.x)) return true; }break; case cfBox:{ Fbox box; box.identity (); Fmatrix B = it->data.box; B.mulA_43 (_Transform()); box.xform (B); u32 mask = 0xff; if (frustum.testAABB(box.data(),mask)) return true; }break; } } return false; }
bool ESoundSource::FrustumPick(const CFrustum& frustum) { return (frustum.testSphere_dirty(m_Params.position,VIS_RADIUS))?true:false; }
bool EParticlesObject::FrustumPick(const CFrustum& frustum) { return (frustum.testSphere_dirty(PPosition,PSOBJECT_SIZE))?true:false; }
void CSector::traverse (CFrustum &F, _scissor& R_scissor) { // Register traversal process if (r_marker != PortalTraverser.i_marker) { r_marker = PortalTraverser.i_marker; PortalTraverser.r_sectors.push_back (this); r_frustums.clear (); r_scissors.clear (); } r_frustums.push_back (F); r_scissors.push_back (R_scissor); // Search visible portals and go through them sPoly S,D; for (u32 I=0; I<m_portals.size(); I++) { if (m_portals[I]->marker == PortalTraverser.i_marker) continue; CPortal* PORTAL = m_portals[I]; CSector* pSector; // Select sector (allow intersecting portals to be finely classified) if (PORTAL->bDualRender) { pSector = PORTAL->getSector (this); } else { pSector = PORTAL->getSectorBack (PortalTraverser.i_vBase); if (pSector==this) continue; if (pSector==PortalTraverser.i_start) continue; } // Early-out sphere if (!F.testSphere_dirty(PORTAL->S.P,PORTAL->S.R)) continue; // SSA (if required) if (PortalTraverser.i_options&CPortalTraverser::VQ_SSA) { Fvector dir2portal; dir2portal.sub (PORTAL->S.P, PortalTraverser.i_vBase); float R = PORTAL->S.R ; float distSQ = dir2portal.square_magnitude(); float ssa = R*R/distSQ; dir2portal.div (_sqrt(distSQ)); ssa *= _abs(PORTAL->P.n.dotproduct(dir2portal)); if (ssa<r_ssaDISCARD) continue; if (PortalTraverser.i_options&CPortalTraverser::VQ_FADE) { if (ssa<r_ssaLOD_A) PortalTraverser.fade_portal (PORTAL,ssa); if (ssa<r_ssaLOD_B) continue ; } } // Clip by frustum svector<Fvector,8>& POLY = PORTAL->getPoly(); S.assign (&*POLY.begin(),POLY.size()); D.clear(); sPoly* P = F.ClipPoly(S,D); if (0==P) continue; // Scissor and optimized HOM-testing _scissor scissor ; if (PortalTraverser.i_options&CPortalTraverser::VQ_SCISSOR && (!PORTAL->bDualRender)) { // Build scissor rectangle in projection-space Fbox2 bb; bb.invalidate(); float depth = flt_max; sPoly& p = *P; for (u32 vit=0; vit<p.size(); vit++) { Fvector4 t; Fmatrix& M = PortalTraverser.i_mXFORM_01; Fvector& v = p[vit]; t.x = v.x*M._11 + v.y*M._21 + v.z*M._31 + M._41; t.y = v.x*M._12 + v.y*M._22 + v.z*M._32 + M._42; t.z = v.x*M._13 + v.y*M._23 + v.z*M._33 + M._43; t.w = v.x*M._14 + v.y*M._24 + v.z*M._34 + M._44; t.mul (1.f/t.w); if (t.x < bb.min.x) bb.min.x = t.x; if (t.x > bb.max.x) bb.max.x = t.x; if (t.y < bb.min.y) bb.min.y = t.y; if (t.y > bb.max.y) bb.max.y = t.y; if (t.z < depth) depth = t.z; } // Msg ("bb(%s): (%f,%f)-(%f,%f), d=%f", PORTAL->bDualRender?"true":"false",bb.min.x, bb.min.y, bb.max.x, bb.max.y,depth); if (depth<EPS) { scissor = R_scissor; // Cull by HOM (slower algo) if ( (PortalTraverser.i_options&CPortalTraverser::VQ_HOM) && (!RImplementation.HOM.visible(*P)) ) continue; } else { // perform intersection (this is just to be sure, it is probably clipped in 3D already) if (bb.min.x > R_scissor.min.x) scissor.min.x = bb.min.x; else scissor.min.x = R_scissor.min.x; if (bb.min.y > R_scissor.min.y) scissor.min.y = bb.min.y; else scissor.min.y = R_scissor.min.y; if (bb.max.x < R_scissor.max.x) scissor.max.x = bb.max.x; else scissor.max.x = R_scissor.max.x; if (bb.max.y < R_scissor.max.y) scissor.max.y = bb.max.y; else scissor.max.y = R_scissor.max.y; scissor.depth = depth; // Msg ("scissor: (%f,%f)-(%f,%f)", scissor.min.x, scissor.min.y, scissor.max.x, scissor.max.y); // Check if box is non-empty if (scissor.min.x >= scissor.max.x) continue; if (scissor.min.y >= scissor.max.y) continue; // Cull by HOM (faster algo) if ( (PortalTraverser.i_options&CPortalTraverser::VQ_HOM) && (!RImplementation.HOM.visible(scissor,depth)) ) continue; } } else { scissor = R_scissor; // Cull by HOM (slower algo) if ( (PortalTraverser.i_options&CPortalTraverser::VQ_HOM) && (!RImplementation.HOM.visible(*P)) ) continue; } // Create _new_ frustum and recurse CFrustum Clip; Clip.CreateFromPortal (P, PORTAL->P.n, PortalTraverser.i_vBase,PortalTraverser.i_mXFORM); PORTAL->marker = PortalTraverser.i_marker; PORTAL->bDualRender = FALSE; pSector->traverse (Clip,scissor); } }
bool CLight::FrustumPick(const CFrustum& frustum) { // return (frustum.testSphere(m_Position,m_Range))?true:false; return (frustum.testSphere_dirty(PPosition,VIS_RADIUS))?true:false; }
bool CGlow::FrustumPick(const CFrustum& frustum) { return (frustum.testSphere_dirty(PPosition,m_fRadius))?true:false; }