void Vision::feel_vision_query (Fmatrix& mFull, Fvector& P) { CFrustum Frustum ; Frustum.CreateFromMatrix (mFull,FRUSTUM_P_LRTB|FRUSTUM_P_FAR); // Traverse object database r_spatial.clear_not_free (); g_SpatialSpace->q_frustum ( r_spatial, 0, STYPE_VISIBLEFORAI, Frustum ); // Determine visibility for dynamic part of scene seen.clear_and_reserve () ; for (u32 o_it=0; o_it<r_spatial.size(); o_it++) { ISpatial* spatial = r_spatial [o_it]; CObject* object = spatial->dcast_CObject (); if (object && feel_vision_isRelevant(object)) seen.push_back (object); } if (seen.size()>1) { std::sort (seen.begin(),seen.end()); xr_vector<CObject*>::iterator end = std::unique (seen.begin(),seen.end()); if (end!=seen.end()) seen.erase (end,seen.end()); } }
void CActor::PickupModeUpdate() { if(!m_bPickupMode) return; // kUSE key pressed if(!IsGameTypeSingle()) return; //подбирание объекта if( m_pObjectWeLookingAt && m_pObjectWeLookingAt->cast_inventory_item() && m_pObjectWeLookingAt->cast_inventory_item()->Useful() && m_pUsableObject && !m_pUsableObject->nonscript_usable() && !Level().m_feel_deny.is_object_denied(m_pObjectWeLookingAt) ) { m_pUsableObject->use(this); Game().SendPickUpEvent(ID(), m_pObjectWeLookingAt->ID()); } feel_touch_update (Position(), m_fPickupInfoRadius); CFrustum frustum; frustum.CreateFromMatrix(Device.mFullTransform, FRUSTUM_P_LRTB|FRUSTUM_P_FAR); for(xr_vector<CObject*>::iterator it = feel_touch.begin(); it != feel_touch.end(); it++) { if (CanPickItem(frustum, Device.vCameraPosition, *it)) PickupInfoDraw(*it); } }
void CActor::PickupModeUpdate() { if(!m_bPickupMode) return; if (GameID() != GAME_SINGLE) return; //подбирание объекта if(inventory().m_pTarget && inventory().m_pTarget->Useful() && m_pUsableObject && m_pUsableObject->nonscript_usable() && !Level().m_feel_deny.is_object_denied(smart_cast<CGameObject*>(inventory().m_pTarget)) ) { NET_Packet P; u_EventGen(P, GE_OWNERSHIP_TAKE, ID()); P.w_u16(inventory().m_pTarget->object().ID()); u_EventSend(P); } //. ????? GetNearest ????? feel_touch_update (Position(), /*inventory().GetTakeDist()*/m_fPickupInfoRadius); CFrustum frustum; frustum.CreateFromMatrix(Device.mFullTransform,FRUSTUM_P_LRTB|FRUSTUM_P_FAR); //. slow (ray-query test) for(xr_vector<CObject*>::iterator it = feel_touch.begin(); it != feel_touch.end(); it++) if (CanPickItem(frustum,Device.vCameraPosition,*it)) PickupInfoDraw(*it); }
void __stdcall CHOM::MT_RENDER() { MT.Enter (); bool b_main_menu_is_active = (g_pGamePersistent->m_pMainMenu && g_pGamePersistent->m_pMainMenu->IsActive() ); if (MT_frame_rendered!=Device.dwFrame && !b_main_menu_is_active) { CFrustum ViewBase; ViewBase.CreateFromMatrix (Device.mFullTransform, FRUSTUM_P_LRTB + FRUSTUM_P_FAR); Enable (); Render (ViewBase); } MT.Leave (); }
////////////////////////////////////////////////////////////////////////// // sub-space rendering - shortcut to render with frustum extracted from matrix void R_dsgraph_structure::r_dsgraph_render_subspace (IRender_Sector* _sector, Fmatrix& mCombined, Fvector& _cop, BOOL _dynamic, BOOL _precise_portals) { CFrustum temp; temp.CreateFromMatrix (mCombined, FRUSTUM_P_ALL); r_dsgraph_render_subspace (_sector,&temp,mCombined,_cop,_dynamic,_precise_portals); }
void CActor::PickupModeUpdate_COD () { if (Level().CurrentViewEntity() != this || !g_b_COD_PickUpMode) return; if (!g_Alive() || eacFirstEye != cam_active) { CurrentGameUI()->UIMainIngameWnd->SetPickUpItem(NULL); return; }; CFrustum frustum; frustum.CreateFromMatrix (Device.mFullTransform, FRUSTUM_P_LRTB|FRUSTUM_P_FAR); ISpatialResult.clear_not_free (); g_SpatialSpace->q_frustum (ISpatialResult, 0, STYPE_COLLIDEABLE, frustum); float maxlen = 1000.0f; CInventoryItem* pNearestItem = NULL; for (u32 o_it=0; o_it<ISpatialResult.size(); o_it++) { ISpatial* spatial = ISpatialResult[o_it]; CInventoryItem* pIItem = smart_cast<CInventoryItem*> (spatial->dcast_CObject ()); if (0 == pIItem) continue; if (pIItem->object().H_Parent() != NULL) continue; if (!pIItem->CanTake()) continue; if ( smart_cast<CExplosiveRocket*>( &pIItem->object() ) ) continue; CGrenade* pGrenade = smart_cast<CGrenade*> (spatial->dcast_CObject ()); if (pGrenade && !pGrenade->Useful()) continue; CMissile* pMissile = smart_cast<CMissile*> (spatial->dcast_CObject ()); if (pMissile && !pMissile->Useful()) continue; Fvector A, B, tmp; pIItem->object().Center (A); if (A.distance_to_sqr(Position())>4) continue; tmp.sub(A, cam_Active()->vPosition); B.mad(cam_Active()->vPosition, cam_Active()->vDirection, tmp.dotproduct(cam_Active()->vDirection)); float len = B.distance_to_sqr(A); if (len > 1) continue; if (maxlen>len && !pIItem->object().getDestroy()) { maxlen = len; pNearestItem = pIItem; }; } if(pNearestItem) { CFrustum frustum; frustum.CreateFromMatrix (Device.mFullTransform,FRUSTUM_P_LRTB|FRUSTUM_P_FAR); if (!CanPickItem(frustum, Device.vCameraPosition, &pNearestItem->object())) pNearestItem = NULL; } if (pNearestItem && pNearestItem->cast_game_object()) { if (Level().m_feel_deny.is_object_denied(pNearestItem->cast_game_object())) pNearestItem = NULL; } if (pNearestItem && pNearestItem->cast_game_object()) { if(!pNearestItem->cast_game_object()->getVisible()) pNearestItem = NULL; } CurrentGameUI()->UIMainIngameWnd->SetPickUpItem(pNearestItem); if (pNearestItem && m_bPickupMode) { CUsableScriptObject* pUsableObject = smart_cast<CUsableScriptObject*>(pNearestItem); if(pUsableObject && (!m_pUsableObject)) pUsableObject->use(this); //подбирание объекта Game().SendPickUpEvent(ID(), pNearestItem->object().ID()); } };
void CLightShadows::render () { // Gain access to collision-DB CDB::MODEL* DB = g_pGameLevel->ObjectSpace.GetStaticModel(); CDB::TRI* TRIS = DB->get_tris(); Fvector* VERTS = DB->get_verts(); int slot_line = S_rt_size/S_size; // Projection and xform float _43 = Device.mProject._43; Device.mProject._43 -= 0.002f; RCache.set_xform_world (Fidentity); RCache.set_xform_project (Device.mProject); Fvector View = Device.vCameraPosition; // Render shadows RCache.set_Shader (sh_World); RCache.set_Geometry (geom_World); int batch = 0; u32 Offset = 0; FVF::LIT* pv = (FVF::LIT*) RCache.Vertex.Lock (batch_size*3,geom_World->vb_stride,Offset); for (u32 s_it=0; s_it<shadows.size(); s_it++) { Device.Statistic->RenderDUMP_Srender.Begin (); shadow& S = shadows[s_it]; float Le = S.L->color.intensity()*S.E; int s_x = S.slot%slot_line; int s_y = S.slot/slot_line; Fvector2 t_scale, t_offset; t_scale.set (float(S_size)/float(S_rt_size),float(S_size)/float(S_rt_size)); t_scale.mul (.5f); t_offset.set(float(s_x)/float(slot_line),float(s_y)/float(slot_line)); t_offset.x += .5f/S_rt_size; t_offset.y += .5f/S_rt_size; // Search the cache cache_item* CI = 0; BOOL bValid = FALSE; cache_item CI_what; CI_what.O = S.O; CI_what.L = S.L; CI_what.tris=0; xr_vector<cache_item>::iterator CI_ptr = std::lower_bound(cache.begin(),cache.end(),CI_what,cache_search); if (CI_ptr==cache.end()) { // empty ? CI_ptr = cache.insert (CI_ptr,CI_what); CI = &*CI_ptr; bValid = FALSE; } else { if (CI_ptr->O != CI_what.O || CI_ptr->L != CI_what.L) { // we found something different CI_ptr = cache.insert (CI_ptr,CI_what); CI = &*CI_ptr; bValid = FALSE; } else { // Everything, OK. Check if info is still relevant... CI = &*CI_ptr; bValid = TRUE; if (!CI->Op.similar(CI->O->renderable.xform.c)) bValid = FALSE; else if (!CI->Lp.similar(CI->L->position)) bValid = FALSE; } } CI->time = Device.dwTimeGlobal; // acess time if (!bValid) { // Frustum CFrustum F; F.CreateFromMatrix (S.M,FRUSTUM_P_ALL); // Query xrc.frustum_options (0); xrc.frustum_query (DB,F); if (0==xrc.r_count()) continue; // Clip polys by frustum tess.clear (); for (CDB::RESULT* p = xrc.r_begin(); p!=xrc.r_end(); p++) { VERIFY((p->id>=0)&&(p->id<DB->get_tris_count())); // CDB::TRI& t = TRIS[p->id]; if (t.suppress_shadows) continue; sPoly A,B; A.push_back (VERTS[t.verts[0]]); A.push_back (VERTS[t.verts[1]]); A.push_back (VERTS[t.verts[2]]); // Calc plane, throw away degenerate tris and invisible to light polygons Fplane P; float mag = 0; Fvector t1,t2,n; t1.sub (A[0],A[1]); t2.sub (A[0],A[2]); n.crossproduct (t1,t2); mag = n.square_magnitude(); if (mag<EPS_S) continue; n.mul (1.f/_sqrt(mag)); P.build_unit_normal (A[0],n); float DOT_Fade = P.classify(S.L->position); if (DOT_Fade<0) continue; // Clip polygon sPoly* clip = F.ClipPoly (A,B); if (0==clip) continue; // Triangulate poly for (u32 v=2; v<clip->size(); v++) { tess.push_back (tess_tri()); tess_tri& T = tess.back(); T.v[0] = (*clip)[0]; T.v[1] = (*clip)[v-1]; T.v[2] = (*clip)[v]; T.N = P.n; } } // Remember params which builded cache item CI->O = S.O; CI->Op = CI->O->renderable.xform.c; CI->L = S.L; CI->Lp = CI->L->position; CI->tcnt = tess.size(); //Msg ("---free--- %x",u32(CI->tris)); xr_free (CI->tris); VERIFY(0==CI->tris); if (tess.size()) { CI->tris = xr_alloc<tess_tri>(CI->tcnt); //Msg ("---alloc--- %x",u32(CI->tris)); CopyMemory (CI->tris,&*tess.begin(),CI->tcnt * sizeof(tess_tri)); } } // Fill VB for (u32 tid=0; tid<CI->tcnt; tid++) { tess_tri& TT = CI->tris[tid]; Fvector* v = TT.v; Fvector T; Fplane ttp; ttp.build_unit_normal(v[0],TT.N); if (ttp.classify(View)<0) continue; int c0 = PLC_calc(v[0],TT.N,S.L,Le,S.C); int c1 = PLC_calc(v[1],TT.N,S.L,Le,S.C); int c2 = PLC_calc(v[2],TT.N,S.L,Le,S.C); if (c0>S_clip && c1>S_clip && c2>S_clip) continue; clamp (c0,S_ambient,255); clamp (c1,S_ambient,255); clamp (c2,S_ambient,255); S.M.transform(T,v[0]); pv->set(v[0],CLS(c0),(T.x+1)*t_scale.x+t_offset.x,(1-T.y)*t_scale.y+t_offset.y); pv++; S.M.transform(T,v[1]); pv->set(v[1],CLS(c1),(T.x+1)*t_scale.x+t_offset.x,(1-T.y)*t_scale.y+t_offset.y); pv++; S.M.transform(T,v[2]); pv->set(v[2],CLS(c2),(T.x+1)*t_scale.x+t_offset.x,(1-T.y)*t_scale.y+t_offset.y); pv++; batch++; if (batch==batch_size) { // Flush RCache.Vertex.Unlock (batch*3,geom_World->vb_stride); RCache.Render (D3DPT_TRIANGLELIST,Offset,batch); pv = (FVF::LIT*) RCache.Vertex.Lock(batch_size*3,geom_World->vb_stride,Offset); batch = 0; } } Device.Statistic->RenderDUMP_Srender.End (); } // Flush if nessesary RCache.Vertex.Unlock (batch*3,geom_World->vb_stride); if (batch) { RCache.Render (D3DPT_TRIANGLELIST,Offset,batch); } // Clear all shadows and free old entries in the cache shadows.clear (); for (int cit=0; cit<int(cache.size()); cit++) { cache_item& ci = cache[cit]; u32 time = Device.dwTimeGlobal - ci.time; if (time > cache_old) { //Msg ("---free--- %x",u32(ci.tris)); xr_free (ci.tris); VERIFY(0==ci.tris); cache.erase (cache.begin()+cit); cit --; } } // Projection Device.mProject._43 = _43; RCache.set_xform_project (Device.mProject); }
void CHOM::Render_DB (CFrustum& base) { //Update projection matrices on every frame to ensure valid HOM culling float view_dim = occ_dim_0; Fmatrix m_viewport = { view_dim/2.f, 0.0f, 0.0f, 0.0f, 0.0f, -view_dim/2.f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, view_dim/2.f + 0 + 0, view_dim/2.f + 0 + 0, 0.0f, 1.0f }; Fmatrix m_viewport_01 = { 1.f/2.f, 0.0f, 0.0f, 0.0f, 0.0f, -1.f/2.f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.f/2.f + 0 + 0, 1.f/2.f + 0 + 0, 0.0f, 1.0f }; m_xform.mul (m_viewport, Device.mFullTransform); m_xform_01.mul (m_viewport_01, Device.mFullTransform); // Query DB xrc.frustum_options (0); xrc.frustum_query (m_pModel,base); if (0==xrc.r_count()) return; // Prepare CDB::RESULT* it = xrc.r_begin (); CDB::RESULT* end = xrc.r_end (); Fvector COP = Device.vCameraPosition; end = std::remove_if (it,end,pred_fb(m_pTris)); std::sort (it,end,pred_fb(m_pTris,COP)); // Build frustum with near plane only CFrustum clip; clip.CreateFromMatrix (Device.mFullTransform,FRUSTUM_P_NEAR); sPoly src,dst; u32 _frame = Device.dwFrame ; #ifdef DEBUG tris_in_frame = xrc.r_count(); tris_in_frame_visible = 0; #endif // Perfrom selection, sorting, culling for (; it!=end; it++) { // Control skipping occTri& T = m_pTris [it->id]; u32 next = _frame + ::Random.randI(3,10); // Test for good occluder - should be improved :) if (!(T.flags || (T.plane.classify(COP)>0))) { T.skip=next; continue; } // Access to triangle vertices CDB::TRI& t = m_pModel->get_tris() [it->id]; Fvector* v = m_pModel->get_verts(); src.clear (); dst.clear (); src.push_back (v[t.verts[0]]); src.push_back (v[t.verts[1]]); src.push_back (v[t.verts[2]]); sPoly* P = clip.ClipPoly (src,dst); if (0==P) { T.skip=next; continue; } // XForm and Rasterize #ifdef DEBUG tris_in_frame_visible ++; #endif u32 pixels = 0; int limit = int(P->size())-1; for (int v=1; v<limit; v++) { m_xform.transform (T.raster[0],(*P)[0]); m_xform.transform (T.raster[1],(*P)[v+0]); m_xform.transform (T.raster[2],(*P)[v+1]); pixels += Raster.rasterize(&T); } if (0==pixels) { T.skip=next; continue; } } }