bool ESceneObjectTools::GetBox (Fbox& bb) { bb.invalidate (); Fbox bbo; for (ObjectIt a_it=m_Objects.begin(); a_it!=m_Objects.end(); a_it++){ (*a_it)->GetBox (bbo); bb.merge (bbo); } return bb.is_valid(); }
IC BOOL ValidateMerge (Fbox& bb_base, Fbox& bb, float& volume, float SLimit) { // Size Fbox merge; merge.merge (bb_base,bb); Fvector sz; merge.getsize (sz); sz.add (EPS_L); if (sz.x>SLimit) return FALSE; // Don't exceed limits (4/3 GEOM) if (sz.y>SLimit) return FALSE; if (sz.z>SLimit) return FALSE; // Volume volume = merge.getvolume (); // OK return TRUE; }
void ESceneAIMapTool::GetBBox(Fbox& bb, bool bSelOnly) { switch (LTools->GetSubTarget()){ case estAIMapNode:{ if (bSelOnly){ for (AINodeIt it=m_Nodes.begin(); it!=m_Nodes.end(); it++) if ((*it)->flags.is(SAINode::flSelected)){ bb.modify(Fvector().add((*it)->Pos,-m_Params.fPatchSize*0.5f)); bb.modify(Fvector().add((*it)->Pos,m_Params.fPatchSize*0.5f)); } }else{ bb.merge (m_AIBBox); } }break; } }
void EScene::ZoomExtents( ObjClassID cls, BOOL bSel ) { Fbox BB; BB.invalidate(); if (cls==OBJCLASS_DUMMY){ SceneToolsMapPairIt _I = m_SceneTools.begin(); SceneToolsMapPairIt _E = m_SceneTools.end(); for (; _I!=_E; _I++) if (_I->second){ Fbox bb; bb.invalidate(); _I->second->GetBBox (bb,bSel); if (bb.is_valid()) BB.merge(bb); } }else{ ESceneToolBase* mt = GetTool(cls); if (mt) mt->GetBBox(BB,bSel); } if (BB.is_valid()) Device.m_Camera.ZoomExtents(BB); else ELog.Msg(mtError,"Can't calculate bounding box. Nothing selected or some object unsupported this function."); }
bool CGroupObject::GetBox(Fbox& bb) { bb.invalidate (); // update box for (ObjectIt it=m_Objects.begin(); it!=m_Objects.end(); it++){ switch((*it)->ClassID){ case OBJCLASS_SPAWNPOINT: case OBJCLASS_SCENEOBJECT:{ Fbox box; if ((*it)->GetBox(box)) bb.merge(box); }break; default: bb.modify((*it)->PPosition); } } if (!bb.is_valid()){ bb.set (PPosition,PPosition); bb.grow (EMPTY_GROUP_SIZE); } return bb.is_valid(); }
BOOL CreateNode(Fvector& vAt, vertex& N) { // *** Query and cache polygons for ray-casting Fvector PointUp; PointUp.set(vAt); PointUp.y += RCAST_Depth; SnapXZ (PointUp); Fvector PointDown; PointDown.set(vAt); PointDown.y -= RCAST_Depth; SnapXZ (PointDown); Fbox BB; BB.set (PointUp,PointUp); BB.grow(g_params.fPatchSize/2); // box 1 Fbox B2; B2.set (PointDown,PointDown); B2.grow(g_params.fPatchSize/2); // box 2 BB.merge(B2 ); BoxQuery(BB,false ); u32 dwCount = XRC.r_count(); if (dwCount==0) { // Log("chasm1"); return FALSE; // chasm? } // *** Transfer triangles and compute sector R_ASSERT(dwCount<RCAST_MaxTris); static svector<tri,RCAST_MaxTris> tris; tris.clear(); for (u32 i=0; i<dwCount; i++) { tri& D = tris.last(); CDB::RESULT &rp = XRC.r_begin()[i]; CDB::TRI& T = *(Level.get_tris()+rp.id); D.v[0].set (rp.verts[0]); D.v[1].set (rp.verts[1]); D.v[2].set (rp.verts[2]); D.sector = T.sector; D.N.mknormal(D.v[0],D.v[1],D.v[2]); if (D.N.y<=0) continue; tris.inc (); } if (tris.size()==0) { // Log("chasm2"); return FALSE; // chasm? } // *** Perform ray-casts and calculate sector WORD Sector = 0xfffe; // mark as first time static svector<Fvector,RCAST_Total> points; points.clear(); static svector<Fvector,RCAST_Total> normals; normals.clear(); Fvector P,D; D.set(0,-1,0); float coeff = 0.5f*g_params.fPatchSize/float(RCAST_Count); for (int x=-RCAST_Count; x<=RCAST_Count; x++) { P.x = vAt.x + coeff*float(x); for (int z=-RCAST_Count; z<=RCAST_Count; z++) { P.z = vAt.z + coeff*float(z); P.y = vAt.y + 10.f; float tri_min_range = flt_max; int tri_selected = -1; float range,u,v; for (i=0; i<u32(tris.size()); i++) { if (CDB::TestRayTri(P,D,tris[i].v,u,v,range,false)) { if (range<tri_min_range) { tri_min_range = range; tri_selected = i; } } } if (tri_selected>=0) { P.y -= tri_min_range; points.push_back(P); normals.push_back(tris[tri_selected].N); WORD TS = WORD(tris[tri_selected].sector); if (Sector==0xfffe) Sector = TS; else if (Sector!=TS) Sector=InvalidSector; } } } if (points.size()<3) { // Msg ("Failed to create node at [%f,%f,%f].",vAt.x,vAt.y,vAt.z); return FALSE; } if (float(points.size())/float(RCAST_Total) < 0.7f) { // Msg ("Partial chasm at [%f,%f,%f].",vAt.x,vAt.y,vAt.z); return FALSE; } // *** Calc normal Fvector vNorm; vNorm.set(0,0,0); for (u32 n=0; n<normals.size(); n++) vNorm.add(normals[n]); vNorm.div(float(normals.size())); vNorm.normalize(); /* { // second algorithm (Magic) Fvector N,O; N.set(vNorm); O.set(points[0]); Mgc::OrthogonalPlaneFit( points.size(),(Mgc::Vector3*)points.begin(), *((Mgc::Vector3*)&O), *((Mgc::Vector3*)&N) ); if (N.y<0) N.invert(); N.normalize(); vNorm.lerp(vNorm,N,.3f); vNorm.normalize(); } */ // *** Align plane Fvector vOffs; vOffs.set(0,-1000,0); Fplane PL; PL.build(vOffs,vNorm); for (u32 p=0; p<points.size(); p++) { float dist = PL.classify(points[p]); if (dist>0) { vOffs = points[p]; PL.build(vOffs,vNorm); } } // *** Create node and register it N.Sector =Sector; // sector N.Plane.build (vOffs,vNorm); // build plane D.set (0,1,0); N.Plane.intersectRayPoint(PointDown,D,N.Pos); // "project" position // *** Validate results vNorm.set(0,1,0); if (vNorm.dotproduct(N.Plane.n)<_cos(deg2rad(60.f))) return FALSE; float y_old = vAt.y; float y_new = N.Pos.y; if (y_old>y_new) { // down if (y_old-y_new > g_params.fCanDOWN ) return FALSE; } else { // up if (y_new-y_old > g_params.fCanUP ) return FALSE; } // *** Validate plane { Fvector PLP; D.set(0,-1,0); int num_successed_rays = 0; for (int x=-RCAST_Count; x<=RCAST_Count; x++) { P.x = N.Pos.x + coeff*float(x); for (int z=-RCAST_Count; z<=RCAST_Count; z++) { P.z = N.Pos.z + coeff*float(z); P.y = N.Pos.y; N.Plane.intersectRayPoint(P,D,PLP); // "project" position P.y = PLP.y+RCAST_VALID*0.01f; float tri_min_range = flt_max; int tri_selected = -1; float range,u,v; for (i=0; i<float(tris.size()); i++) { if (CDB::TestRayTri(P,D,tris[i].v,u,v,range,false)) { if (range<tri_min_range) { tri_min_range = range; tri_selected = i; } } } if (tri_selected>=0) { if (tri_min_range<RCAST_VALID) num_successed_rays++; } } } float perc = float(num_successed_rays)/float(RCAST_Total); if (perc < 0.5f) { // Msg ("Floating node."); return FALSE; } } // *** Mask check // ??? return TRUE; }
BOOL ESceneAIMapTool::CreateNode(Fvector& vAt, SAINode& N, bool bIC) { // *** Query and cache polygons for ray-casting Fvector PointUp; PointUp.set(vAt); PointUp.y += RCAST_Depth; SnapXZ (PointUp,m_Params.fPatchSize); Fvector PointDown; PointDown.set(vAt); PointDown.y -= RCAST_Depth; SnapXZ (PointDown,m_Params.fPatchSize); Fbox BB; BB.set (PointUp,PointUp); BB.grow(m_Params.fPatchSize/2); // box 1 Fbox B2; B2.set (PointDown,PointDown); B2.grow(m_Params.fPatchSize/2); // box 2 BB.merge (B2); if (m_CFModel) { /* for(u32 i=0; i<m_CFModel->get_tris_count(); ++i) { CDB::TRI* tri = (m_CFModel->get_tris()+i); if(tri->material!=0) Msg("non-default material"); } */ Scene->BoxQuery(PQ,BB,CDB::OPT_FULL_TEST,m_CFModel); }else Scene->BoxQuery(PQ,BB,CDB::OPT_FULL_TEST,GetSnapList()); DWORD dwCount = PQ.r_count(); if (dwCount==0){ // Log("chasm1"); return FALSE; // chasm? } // *** Transfer triangles and compute sector // R_ASSERT(dwCount<RCAST_MaxTris); static xr_vector<tri> tris; tris.reserve(RCAST_MaxTris); tris.clear(); for (DWORD i=0; i<dwCount; i++) { SPickQuery::SResult* R = PQ.r_begin()+i; if (R->e_obj&&R->e_mesh) { CSurface* surf = R->e_mesh->GetSurfaceByFaceID(R->tag); //. SGameMtl* mtl = GMLib.GetMaterialByID(surf->_GameMtl()); //. if (mtl->Flags.is(SGameMtl::flPassable))continue; Shader_xrLC* c_sh = Device.ShaderXRLC.Get(surf->_ShaderXRLCName()); if (!c_sh->flags.bCollision) continue; } /* if(m_CFModel) { u16 mtl_id = R->material; if(std::find(m_ignored_materials.begin(), m_ignored_materials.end(), mtl_id) != m_ignored_materials.end() ) { //. Msg("--ignore"); continue; } } */ tris.push_back (tri()); tri& D = tris.back(); Fvector* V = R->verts; D.v[0] = &V[0]; D.v[1] = &V[1]; D.v[2] = &V[2]; D.N.mknormal(*D.v[0],*D.v[1],*D.v[2]); if (D.N.y<=0) tris.pop_back (); } if (tris.size()==0){ // Log("chasm2"); return FALSE; // chasm? } static xr_vector<Fvector> points; points.reserve(RCAST_Total); points.clear(); static xr_vector<Fvector> normals; normals.reserve(RCAST_Total);normals.clear(); Fvector P,D; D.set(0,-1,0); float coeff = 0.5f*m_Params.fPatchSize/float(RCAST_Count); for (int x=-RCAST_Count; x<=RCAST_Count; x++) { P.x = vAt.x + coeff*float(x); for (int z=-RCAST_Count; z<=RCAST_Count; z++) { P.z = vAt.z + coeff*float(z); P.y = vAt.y + 10.f; float tri_min_range = flt_max; int tri_selected = -1; float range,u,v; for (i=0; i<DWORD(tris.size()); i++){ if (ETOOLS::TestRayTriA(P,D,tris[i].v,u,v,range,false)){ if (range<tri_min_range){ tri_min_range = range; tri_selected = i; } } } if (tri_selected>=0) { P.y -= tri_min_range; points.push_back(P); normals.push_back(tris[tri_selected].N); } } } if (points.size()<3) { // Msg ("Failed to create node at [%f,%f,%f].",vAt.x,vAt.y,vAt.z); return FALSE; } //. float rc_lim = bIC?0.015f:0.7f; if (float(points.size())/float(RCAST_Total) < rc_lim) { // Msg ("Partial chasm at [%f,%f,%f].",vAt.x,vAt.y,vAt.z); return FALSE; } // *** Calc normal Fvector vNorm; vNorm.set(0,0,0); for (DWORD n=0; n<normals.size(); n++) vNorm.add(normals[n]); vNorm.div(float(normals.size())); vNorm.normalize(); /* { // second algorithm (Magic) Fvector N,O; N.set(vNorm); O.set(points[0]); Mgc::OrthogonalPlaneFit( points.size(),(Mgc::Vector3*)points.begin(), *((Mgc::Vector3*)&O), *((Mgc::Vector3*)&N) ); if (N.y<0) N.invert(); N.normalize(); vNorm.lerp(vNorm,N,.3f); vNorm.normalize(); } */ // *** Align plane Fvector vOffs; vOffs.set(0,-1000,0); Fplane PL; PL.build(vOffs,vNorm); for (DWORD p=0; p<points.size(); p++) { float dist = PL.classify(points[p]); if (dist>0) { vOffs = points[p]; PL.build(vOffs,vNorm); } } // *** Create node and register it N.Plane.build (vOffs,vNorm); // build plane D.set (0,1,0); N.Plane.intersectRayPoint(PointDown,D,N.Pos); // "project" position // *** Validate results vNorm.set(0,1,0); if (vNorm.dotproduct(N.Plane.n)<_cos(deg2rad(60.f))) return FALSE; float y_old = vAt.y; float y_new = N.Pos.y; if (y_old>y_new) { // down if (y_old-y_new > m_Params.fCanDOWN ) return FALSE; } else { // up if (y_new-y_old > m_Params.fCanUP ) return FALSE; } // *** Validate plane { Fvector PLP; D.set(0,-1,0); int num_successed_rays = 0; for (int x=-RCAST_Count; x<=RCAST_Count; x++) { P.x = N.Pos.x + coeff*float(x); for (int z=-RCAST_Count; z<=RCAST_Count; z++) { P.z = N.Pos.z + coeff*float(z); P.y = N.Pos.y; N.Plane.intersectRayPoint(P,D,PLP); // "project" position P.y = PLP.y+RCAST_VALID*0.01f; float tri_min_range = flt_max; int tri_selected = -1; float range,u,v; for (i=0; i<tris.size(); i++){ if (ETOOLS::TestRayTriA(P,D,tris[i].v,u,v,range,false)){ if (range<tri_min_range){ tri_min_range = range; tri_selected = i; } } } if (tri_selected>=0){ if (tri_min_range<RCAST_VALID) num_successed_rays++; } } } float perc = float(num_successed_rays)/float(RCAST_Total); //. if (!bIC&&(perc < 0.5f)){ float perc_lim = bIC?0.015f:0.5f; if (perc < perc_lim){ // Msg ("Floating node."); return FALSE; } } // *** Mask check // ??? return TRUE; }
BOOL ValidNode(vertex& N) { // *** Query and cache polygons for ray-casting Fvector PointUp; PointUp.set(N.Pos); PointUp.y += RCAST_Depth/2; Fvector PointDown; PointDown.set(N.Pos); PointDown.y -= RCAST_Depth/2; Fbox BB; BB.set (PointUp,PointUp); BB.grow(g_params.fPatchSize/2); // box 1 Fbox B2; B2.set (PointDown,PointDown); B2.grow(g_params.fPatchSize/2); // box 2 BB.merge(B2 ); BoxQuery(BB,false ); u32 dwCount = XRC.r_count(); if (dwCount==0) { Log("chasm1"); return FALSE; // chasm? } // *** Transfer triangles and compute sector R_ASSERT(dwCount<RCAST_MaxTris); static svector<tri,RCAST_MaxTris> tris; tris.clear(); for (u32 i=0; i<dwCount; i++) { tri& D = tris.last(); CDB::RESULT&rp = XRC.r_begin()[i]; *(Level.get_tris()+XRC.r_begin()[i].id); D.v[0].set (rp.verts[0]); D.v[1].set (rp.verts[1]); D.v[2].set (rp.verts[2]); Fvector N; N.mknormal (D.v[0],D.v[1],D.v[2]); if (N.y<=0) continue; tris.inc (); } if (tris.size()==0) { Log("chasm2"); return FALSE; // chasm? } // *** Perform ray-casts and calculate sector Fvector P,D,PLP; D.set(0,-1,0); float coeff = 0.5f*g_params.fPatchSize/float(RCAST_Count); int num_successed_rays = 0; for (int x=-RCAST_Count; x<=RCAST_Count; x++) { P.x = N.Pos.x + coeff*float(x); for (int z=-RCAST_Count; z<=RCAST_Count; z++) { P.z = N.Pos.z + coeff*float(z); P.y = N.Pos.y; N.Plane.intersectRayPoint(P,D,PLP); // "project" position P.y = PLP.y+RCAST_DepthValid/2; float tri_min_range = flt_max; int tri_selected = -1; float range = 0.f,u,v; for (i=0; i<u32(tris.size()); i++) { if (CDB::TestRayTri(P,D,tris[i].v,u,v,range,false)) { if (range<tri_min_range) { tri_min_range = range; tri_selected = i; } } } if (tri_selected>=0) { if (range<RCAST_DepthValid) num_successed_rays++; } } } if (float(num_successed_rays)/float(RCAST_Total) < 0.5f) { Msg ("Floating node."); return FALSE; } return TRUE; }
void CParticleGroup::SItem::OnFrame(u32 u_dt, const CPGDef::SEffect& def, Fbox& box, bool& bPlaying) { CParticleEffect* E = static_cast<CParticleEffect*>(_effect); if (E){ E->OnFrame (u_dt); if (E->IsPlaying()){ bPlaying = true; if (E->vis.box.is_valid()) box.merge (E->vis.box); if (def.m_Flags.is(CPGDef::SEffect::flOnPlayChild)&&def.m_OnPlayChildName.size()){ PAPI::Particle* particles; u32 p_cnt; PAPI::ParticleManager()->GetParticles(E->GetHandleEffect(),particles,p_cnt); VERIFY(p_cnt==_children_related.size()); if (p_cnt){ for(u32 i = 0; i < p_cnt; i++){ PAPI::Particle &m = particles[i]; CParticleEffect* C = static_cast<CParticleEffect*>(_children_related[i]); Fmatrix M; M.translate(m.pos); Fvector vel; vel.sub(m.pos,m.posB); vel.div(fDT_STEP); C->UpdateParent (M,vel,FALSE); } } } } } VisualVecIt it; if (!_children_related.empty()){ for (it=_children_related.begin(); it!=_children_related.end(); it++){ CParticleEffect* E = static_cast<CParticleEffect*>(*it); if (E){ E->OnFrame (u_dt); if (E->IsPlaying()){ bPlaying = true; if (E->vis.box.is_valid()) box.merge (E->vis.box); }else{ if (def.m_Flags.is(CPGDef::SEffect::flOnPlayChildRewind)){ E->Play (); } } } } } if (!_children_free.empty()){ u32 rem_cnt = 0; for (it=_children_free.begin(); it!=_children_free.end(); it++){ CParticleEffect* E = static_cast<CParticleEffect*>(*it); if (E){ E->OnFrame (u_dt); if (E->IsPlaying()){ bPlaying = true; if (E->vis.box.is_valid()) box.merge (E->vis.box); }else{ rem_cnt++ ; ::Render->model_Delete(*it); } } } // remove if stopped if (rem_cnt){ VisualVecIt new_end=std::remove_if(_children_free.begin(),_children_free.end(),zero_vis_pred()); _children_free.erase(new_end,_children_free.end()); } } // Msg("C: %d CS: %d",_children.size(),_children_stopped.size()); }