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::Check_for_AutoPickUp() { // mp only if (!psActorFlags.test(AF_AUTOPICKUP)) return; if (IsGameTypeSingle()) return; if (Level().CurrentControlEntity() != this) return; if (!g_Alive()) return; Fvector bc; bc.add (Position(), m_AutoPickUp_AABB_Offset); Fbox APU_Box; APU_Box.set (Fvector().sub(bc, m_AutoPickUp_AABB), Fvector().add(bc, m_AutoPickUp_AABB)); xr_vector<ISpatial*> ISpatialResult; g_SpatialSpace->q_box (ISpatialResult, 0, STYPE_COLLIDEABLE, bc, m_AutoPickUp_AABB); // Determine visibility for dynamic part of scene 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->CanTake()) continue; if (Level().m_feel_deny.is_object_denied(spatial->dcast_CObject()) ) continue; CGrenade* pGrenade = smart_cast<CGrenade*> (pIItem); if (pGrenade) continue; if (APU_Box.Pick(pIItem->object().Position(), pIItem->object().Position())) { if (GameID() == eGameIDDeathmatch || GameID() == eGameIDTeamDeathmatch) { if (pIItem->BaseSlot() == INV_SLOT_2 || pIItem->BaseSlot() == INV_SLOT_3 ) { if (inventory().ItemFromSlot(pIItem->BaseSlot())) continue; } } Game().SendPickUpEvent(ID(), pIItem->object().ID()); } } }
BOOL CObjectSpace::_RayPick ( const Fvector &start, const Fvector &dir, float range, rq_target tgt, rq_result& R, CObject* ignore_object) { r_temp.r_clear (); R.O = 0; R.range = range; R.element = -1; // static test if (tgt&rqtStatic){ xrc.ray_options (CDB::OPT_ONLYNEAREST | CDB::OPT_CULL); xrc.ray_query (&Static,start,dir,range); if (xrc.r_count()) R.set_if_less(xrc.r_begin()); } // dynamic test if (tgt&rqtDyn){ collide::ray_defs Q (start,dir,R.range,CDB::OPT_ONLYNEAREST|CDB::OPT_CULL,tgt); // traverse object database u32 d_flags = STYPE_COLLIDEABLE|((tgt&rqtObstacle)?STYPE_OBSTACLE:0)|((tgt&rqtShape)?STYPE_SHAPE:0); g_SpatialSpace->q_ray (r_spatial,0,d_flags,start,dir,range); // Determine visibility for dynamic part of scene for (u32 o_it=0; o_it<r_spatial.size(); o_it++){ ISpatial* spatial = r_spatial[o_it]; CObject* collidable = spatial->dcast_CObject(); if (0==collidable) continue; if (collidable==ignore_object) continue; ECollisionFormType tp = collidable->collidable.model->Type(); if (((tgt&(rqtObject|rqtObstacle))&&(tp==cftObject))||((tgt&rqtShape)&&(tp==cftShape))){ u32 C = D3DCOLOR_XRGB (64,64,64); Q.range = R.range; if (collidable->collidable.model->_RayQuery(Q,r_temp)){ C = D3DCOLOR_XRGB(128,128,196); R.set_if_less (r_temp.r_begin()); } #ifdef DEBUG if (bDebug){ Fsphere S; S.P = spatial->spatial.sphere.P; S.R = spatial->spatial.sphere.R; m_pRender->dbgAddSphere(S,C); //dbg_S.push_back (mk_pair(S,C)); } #endif } } } return (R.element>=0); }
void CLightProjector::set_object (IRenderable* O) { if ((0==O) || (receivers.size()>=P_o_count)) current = 0; else { if (!O->renderable_ShadowReceive() || RImplementation.val_bInvisible || ((CROS_impl*)O->renderable_ROS())->shadow_recv_frame==Device.dwFrame) { current = 0; return; } const vis_data &vis = O->renderable.visual->getVisData(); Fvector C; O->renderable.xform.transform_tiny (C,vis.sphere.P); float R = vis.sphere.R; float D = C.distance_to (Device.vCameraPosition)+R; if (D < clipD(R)) current = O; else current = 0; if (current) { ISpatial* spatial = dynamic_cast<ISpatial*> (O); if (0==spatial) current= 0; else { spatial->spatial_updatesector (); if (0==spatial->spatial.sector) { CObject* obj = dynamic_cast<CObject*>(O); if (obj) Msg ("! Invalid object '%s' position. Outside of sector structure.",obj->cName().c_str()); current = 0; } } } if (current) { CROS_impl* LT = (CROS_impl*)current->renderable_ROS (); LT->shadow_recv_frame = Device.dwFrame; receivers.push_back (current); } } }
// sub-space rendering - main procedure void R_dsgraph_structure::r_dsgraph_render_subspace (IRender_Sector* _sector, CFrustum* _frustum, Fmatrix& mCombined, Fvector& _cop, BOOL _dynamic, BOOL _precise_portals) { VERIFY (_sector); RImplementation.marker ++; // !!! critical here // Save and build new frustum, disable HOM CFrustum ViewSave = ViewBase; ViewBase = *_frustum; View = &ViewBase; if (_precise_portals && RImplementation.rmPortals) { // Check if camera is too near to some portal - if so force DualRender Fvector box_radius; box_radius.set (EPS_L*20,EPS_L*20,EPS_L*20); RImplementation.Sectors_xrc.box_options (CDB::OPT_FULL_TEST); RImplementation.Sectors_xrc.box_query (RImplementation.rmPortals,_cop,box_radius); for (int K=0; K<RImplementation.Sectors_xrc.r_count(); K++) { CPortal* pPortal = (CPortal*) RImplementation.Portals[RImplementation.rmPortals->get_tris()[RImplementation.Sectors_xrc.r_begin()[K].id].dummy]; pPortal->bDualRender = TRUE; } } // Traverse sector/portal structure PortalTraverser.traverse ( _sector, ViewBase, _cop, mCombined, 0 ); // Determine visibility for static geometry hierrarhy for (u32 s_it=0; s_it<PortalTraverser.r_sectors.size(); s_it++) { CSector* sector = (CSector*)PortalTraverser.r_sectors[s_it]; IRender_Visual* root = sector->root(); for (u32 v_it=0; v_it<sector->r_frustums.size(); v_it++) { set_Frustum (&(sector->r_frustums[v_it])); add_Geometry (root); } } if (_dynamic) { set_Object (0); // Traverse object database g_SpatialSpace->q_frustum ( lstRenderables, ISpatial_DB::O_ORDERED, STYPE_RENDERABLE, ViewBase ); // Determine visibility for dynamic part of scene for (u32 o_it=0; o_it<lstRenderables.size(); o_it++) { ISpatial* spatial = lstRenderables[o_it]; CSector* sector = (CSector*)spatial->spatial.sector; if (0==sector) continue; // disassociated from S/P structure if (PortalTraverser.i_marker != sector->r_marker) continue; // inactive (untouched) sector for (u32 v_it=0; v_it<sector->r_frustums.size(); v_it++) { set_Frustum (&(sector->r_frustums[v_it])); if (!View->testSphere_dirty(spatial->spatial.sphere.P,spatial->spatial.sphere.R)) continue; // renderable IRenderable* renderable = spatial->dcast_Renderable (); if (0==renderable) continue; // unknown, but renderable object (r1_glow???) renderable->renderable_Render (); } } } // Restore ViewBase = ViewSave; View = 0; }
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 CRender::Calculate () { #ifdef _GPA_ENABLED TAL_SCOPED_TASK_NAMED( "CRender::Calculate()" ); #endif // _GPA_ENABLED Device.Statistic->RenderCALC.Begin(); // Transfer to global space to avoid deep pointer access IRender_Target* T = getTarget (); float fov_factor = _sqr (90.f / Device.fFOV); g_fSCREEN = float(T->get_width()*T->get_height())*fov_factor*(EPS_S+ps_r__LOD); r_ssaDISCARD = _sqr(ps_r__ssaDISCARD) /g_fSCREEN; r_ssaDONTSORT = _sqr(ps_r__ssaDONTSORT/3) /g_fSCREEN; r_ssaLOD_A = _sqr(ps_r1_ssaLOD_A/3) /g_fSCREEN; r_ssaLOD_B = _sqr(ps_r1_ssaLOD_B/3) /g_fSCREEN; r_ssaGLOD_start = _sqr(ps_r__GLOD_ssa_start/3)/g_fSCREEN; r_ssaGLOD_end = _sqr(ps_r__GLOD_ssa_end/3) /g_fSCREEN; r_ssaHZBvsTEX = _sqr(ps_r__ssaHZBvsTEX/3) /g_fSCREEN; // Frustum & HOM rendering ViewBase.CreateFromMatrix (Device.mFullTransform,FRUSTUM_P_LRTB|FRUSTUM_P_FAR); View = 0; HOM.Enable (); HOM.Render (ViewBase); gm_SetNearer (FALSE); phase = PHASE_NORMAL; // Detect camera-sector if (!vLastCameraPos.similar(Device.vCameraPosition,EPS_S)) { CSector* pSector = (CSector*)detectSector(Device.vCameraPosition); if (pSector && (pSector!=pLastSector)) g_pGamePersistent->OnSectorChanged( translateSector(pSector) ); if (0==pSector) pSector = pLastSector; pLastSector = pSector; vLastCameraPos.set(Device.vCameraPosition); } // Check if camera is too near to some portal - if so force DualRender if (rmPortals) { Fvector box_radius; box_radius.set(EPS_L*2,EPS_L*2,EPS_L*2); Sectors_xrc.box_options (CDB::OPT_FULL_TEST); Sectors_xrc.box_query (rmPortals,Device.vCameraPosition,box_radius); for (int K=0; K<Sectors_xrc.r_count(); K++) { CPortal* pPortal = (CPortal*) Portals[rmPortals->get_tris()[Sectors_xrc.r_begin()[K].id].dummy]; pPortal->bDualRender = TRUE; } } // if (L_DB) L_DB->Update(); // Main process marker ++; if (pLastSector) { // Traverse sector/portal structure PortalTraverser.traverse ( pLastSector, ViewBase, Device.vCameraPosition, Device.mFullTransform, CPortalTraverser::VQ_HOM + CPortalTraverser::VQ_SSA + CPortalTraverser::VQ_FADE ); // Determine visibility for static geometry hierrarhy if (psDeviceFlags.test(rsDrawStatic)) { for (u32 s_it=0; s_it<PortalTraverser.r_sectors.size(); s_it++) { CSector* sector = (CSector*)PortalTraverser.r_sectors[s_it]; dxRender_Visual* root = sector->root(); for (u32 v_it=0; v_it<sector->r_frustums.size(); v_it++) { set_Frustum (&(sector->r_frustums[v_it])); add_Geometry (root); } } } // Traverse object database if (psDeviceFlags.test(rsDrawDynamic)) { g_SpatialSpace->q_frustum ( lstRenderables, ISpatial_DB::O_ORDERED, STYPE_RENDERABLE + STYPE_LIGHTSOURCE, ViewBase ); // Exact sorting order (front-to-back) std::sort (lstRenderables.begin(),lstRenderables.end(),pred_sp_sort); // Determine visibility for dynamic part of scene set_Object (0); g_hud->Render_First ( ); // R1 shadows g_hud->Render_Last ( ); u32 uID_LTRACK = 0xffffffff; if (phase==PHASE_NORMAL) { uLastLTRACK ++; if (lstRenderables.size()) uID_LTRACK = uLastLTRACK%lstRenderables.size(); // update light-vis for current entity / actor CObject* O = g_pGameLevel->CurrentViewEntity(); if (O) { CROS_impl* R = (CROS_impl*) O->ROS(); if (R) R->update (O); } } for (u32 o_it=0; o_it<lstRenderables.size(); o_it++) { ISpatial* spatial = lstRenderables[o_it]; spatial->spatial_updatesector (); CSector* sector = (CSector*)spatial->spatial.sector ; if (0==sector) continue; // disassociated from S/P structure // Filter only not light spatial if (PortalTraverser.i_marker != sector->r_marker && (spatial->spatial.type & STYPE_RENDERABLE) ) continue; // inactive (untouched) sector if (spatial->spatial.type & STYPE_RENDERABLE) { for (u32 v_it=0; v_it<sector->r_frustums.size(); v_it++) { set_Frustum (&(sector->r_frustums[v_it])); if (!View->testSphere_dirty(spatial->spatial.sphere.P,spatial->spatial.sphere.R) /*&& (spatial->spatial.type & STYPE_RENDERABLE)*/) continue; // renderable IRenderable* renderable = spatial->dcast_Renderable (); if (0==renderable) { // It may be an glow CGlow* glow = dynamic_cast<CGlow*>(spatial); VERIFY (glow); L_Glows->add (glow); } else { // Occlusiond vis_data& v_orig = renderable->renderable.visual->getVisData(); vis_data v_copy = v_orig; v_copy.box.xform (renderable->renderable.xform); BOOL bVisible = HOM.visible(v_copy); v_orig.accept_frame = v_copy.accept_frame; v_orig.marker = v_copy.marker; v_orig.hom_frame = v_copy.hom_frame; v_orig.hom_tested = v_copy.hom_tested; if (!bVisible) break; // exit loop on frustums // rendering if (o_it==uID_LTRACK && renderable->renderable_ROS()) { // track lighting environment CROS_impl* T = (CROS_impl*)renderable->renderable_ROS(); T->update (renderable); } set_Object (renderable); renderable->renderable_Render (); set_Object (0); //? is it needed at all } break; // exit loop on frustums } } else { if ( ViewBase.testSphere_dirty(spatial->spatial.sphere.P,spatial->spatial.sphere.R) ) { VERIFY (spatial->spatial.type & STYPE_LIGHTSOURCE); // lightsource light* L = (light*) spatial->dcast_Light (); VERIFY (L); if (L->spatial.sector) { vis_data& vis = L->get_homdata ( ); if (HOM.visible(vis)) L_DB->add_light (L); } } } } } // Calculate miscelaneous stuff L_Shadows->calculate (); L_Projector->calculate (); } else { set_Object (0); /* g_pGameLevel->pHUD->Render_First (); g_pGameLevel->pHUD->Render_Last (); // Calculate miscelaneous stuff L_Shadows->calculate (); L_Projector->calculate (); */ } // End calc Device.Statistic->RenderCALC.End (); }
void CLightProjector::calculate () { #ifdef _GPA_ENABLED TAL_SCOPED_TASK_NAMED( "CLightProjector::calculate()" ); #endif // _GPA_ENABLED if (receivers.empty()) return; // perform validate / markup for (u32 r_it=0; r_it<receivers.size(); r_it++) { // validate BOOL bValid = TRUE; IRenderable* O = receivers[r_it]; CROS_impl* LT = (CROS_impl*)O->renderable_ROS(); int slot = LT->shadow_recv_slot; if (slot<0 || slot>=P_o_count) bValid = FALSE; // invalid slot else if (cache[slot].O!=O) bValid = FALSE; // not the same object else { // seems to be valid Fbox bb; bb.xform (O->renderable.visual->getVisData().box,O->renderable.xform); if (cache[slot].BB.contains(bb)) { // inside, but maybe timelimit exceeded? if (Device.dwTimeGlobal > cache[slot].dwTimeValid) bValid = FALSE; // timeout } else bValid = FALSE; // out of bounds } // if (bValid) { // Ok, use cached version cache[slot].dwFrame = Device.dwFrame; } else { taskid.push_back (r_it); } } if (taskid.empty()) return; // Begin Device.Statistic->RenderDUMP_Pcalc.Begin (); RCache.set_RT (RT->pRT); RCache.set_ZB (RImplementation.Target->pTempZB); CHK_DX(HW.pDevice->Clear (0,0, D3DCLEAR_ZBUFFER | (HW.Caps.bStencil?D3DCLEAR_STENCIL:0), 0,1,0 )); RCache.set_xform_world (Fidentity); // reallocate/reassociate structures + perform all the work for (u32 c_it=0; c_it<cache.size(); c_it++) { if (taskid.empty()) break; if (Device.dwFrame==cache[c_it].dwFrame) continue; // found not used slot int tid = taskid.back(); taskid.pop_back(); recv& R = cache [c_it]; IRenderable* O = receivers [tid]; const vis_data& vis = O->renderable.visual->getVisData(); CROS_impl* LT = (CROS_impl*)O->renderable_ROS(); VERIFY2 (_valid(O->renderable.xform),"Invalid object transformation"); VERIFY2 (_valid(vis.sphere.P),"Invalid object's visual sphere"); Fvector C; O->renderable.xform.transform_tiny (C,vis.sphere.P); R.O = O; R.C = C; R.C.y += vis.sphere.R*0.1f; //. YURA: 0.1 can be more R.BB.xform (vis.box,O->renderable.xform).scale(0.1f); R.dwTimeValid = Device.dwTimeGlobal + ::Random.randI(time_min,time_max); LT->shadow_recv_slot = c_it; // Msg ("[%f,%f,%f]-%f",C.C.x,C.C.y,C.C.z,C.O->renderable.visual->vis.sphere.R); // calculate projection-matrix Fmatrix mProject; float p_R = R.O->renderable.visual->getVisData().sphere.R * 1.1f; //VERIFY2 (p_R>EPS_L,"Object has no physical size"); VERIFY3 (p_R>EPS_L,"Object has no physical size", R.O->renderable.visual->getDebugName().c_str()); float p_hat = p_R/P_cam_dist; float p_asp = 1.f; float p_near = P_cam_dist-EPS_L; float p_far = P_cam_dist+p_R+P_cam_range; mProject.build_projection_HAT (p_hat,p_asp,p_near,p_far); RCache.set_xform_project (mProject); // calculate view-matrix Fmatrix mView; Fvector v_C, v_Cs, v_N; v_C.set (R.C); v_Cs = v_C; v_C.y += P_cam_dist; v_N.set (0,0,1); VERIFY (_valid(v_C) && _valid(v_Cs) && _valid(v_N)); // validate Fvector v; v.sub (v_Cs,v_C);; #ifdef DEBUG if ((v.x*v.x+v.y*v.y+v.z*v.z)<=flt_zero) { CObject* OO = dynamic_cast<CObject*>(R.O); Msg("Object[%s] Visual[%s] has invalid position. ",*OO->cName(),*OO->cNameVisual()); Fvector cc; OO->Center(cc); Log("center=",cc); Log("visual_center=",OO->Visual()->getVisData().sphere.P); Log("full_matrix=",OO->XFORM()); Log ("v_N",v_N); Log ("v_C",v_C); Log ("v_Cs",v_Cs); Log("all bones transform:--------"); CKinematics* K = dynamic_cast<CKinematics*>(OO->Visual()); for(u16 ii=0; ii<K->LL_BoneCount();++ii){ Fmatrix tr; tr = K->LL_GetTransform(ii); Log("bone ",K->LL_BoneName_dbg(ii)); Log("bone_matrix",tr); } Log("end-------"); } #endif // handle invalid object-bug if ((v.x*v.x+v.y*v.y+v.z*v.z)<=flt_zero) { // invalidate record, so that object will be unshadowed, but doesn't crash R.dwTimeValid = Device.dwTimeGlobal; LT->shadow_recv_frame = Device.dwFrame-1; LT->shadow_recv_slot = -1; continue ; } mView.build_camera (v_C,v_Cs,v_N); RCache.set_xform_view (mView); // Select slot, set viewport int s_x = c_it%P_o_line; int s_y = c_it/P_o_line; D3DVIEWPORT9 VP = {s_x*P_o_size,s_y*P_o_size,P_o_size,P_o_size,0,1 }; CHK_DX (HW.pDevice->SetViewport(&VP)); // Clear color to ambience Fvector& cap = LT->get_approximate(); CHK_DX (HW.pDevice->Clear(0,0, D3DCLEAR_TARGET, color_rgba_f(cap.x,cap.y,cap.z, (cap.x+cap.y+cap.z)/4.f), 1, 0 )); // calculate uv-gen matrix and clamper Fmatrix mCombine; mCombine.mul (mProject,mView); Fmatrix mTemp; float fSlotSize = float(P_o_size)/float(P_rt_size); float fSlotX = float(s_x*P_o_size)/float(P_rt_size); float fSlotY = float(s_y*P_o_size)/float(P_rt_size); float fTexelOffs = (.5f / P_rt_size); Fmatrix m_TexelAdjust = { 0.5f/*x-scale*/, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f/*y-scale*/, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f/*z-range*/, 0.0f, 0.5f/*x-bias*/, 0.5f + fTexelOffs/*y-bias*/, 0.0f/*z-bias*/, 1.0f }; R.UVgen.mul (m_TexelAdjust,mCombine); mTemp.scale (fSlotSize,fSlotSize,1); R.UVgen.mulA_44 (mTemp); mTemp.translate (fSlotX+fTexelOffs,fSlotY+fTexelOffs,0); R.UVgen.mulA_44 (mTemp); // Build bbox and render Fvector min,max; Fbox BB; min.set (R.C.x-p_R, R.C.y-(p_R+P_cam_range), R.C.z-p_R); max.set (R.C.x+p_R, R.C.y+0, R.C.z+p_R); BB.set (min,max); R.UVclamp_min.set (min).add (.05f); // shrink a little R.UVclamp_max.set (max).sub (.05f); // shrink a little ISpatial* spatial = dynamic_cast<ISpatial*> (O); if (spatial) { spatial->spatial_updatesector (); if (spatial->spatial.sector) RImplementation.r_dsgraph_render_R1_box (spatial->spatial.sector,BB,SE_R1_LMODELS); } //if (spatial) RImplementation.r_dsgraph_render_subspace (spatial->spatial.sector,mCombine,v_C,FALSE); } // Blur /* { // Fill vertex buffer u32 Offset; FVF::TL4uv* pv = (FVF::TL4uv*) RCache.Vertex.Lock (4,geom_Blur.stride(),Offset); RImplementation.ApplyBlur4 (pv,P_rt_size,P_rt_size,P_blur_kernel); RCache.Vertex.Unlock (4,geom_Blur.stride()); // Actual rendering (pass0, temp2real) RCache.set_RT (RT->pRT); RCache.set_ZB (NULL); RCache.set_Shader (sh_BlurTR ); RCache.set_Geometry (geom_Blur ); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } */ // Finita la comedia Device.Statistic->RenderDUMP_Pcalc.End (); RCache.set_xform_project (Device.mProject); RCache.set_xform_view (Device.mView); }
void dx103DFluidRenderer::CalculateLighting(const dx103DFluidData &FluidData, FogLighting &LightData) { m_lstRenderables.clear_not_free(); LightData.Reset(); const dx103DFluidData::Settings &VolumeSettings = FluidData.GetSettings(); Fvector4 hemi_color = g_pGamePersistent->Environment().CurrentEnv->hemi_color; //hemi_color.mul(0.2f); hemi_color.mul(VolumeSettings.m_fHemi); LightData.m_vLightIntencity.set(hemi_color.x, hemi_color.y, hemi_color.z); LightData.m_vLightIntencity.add(g_pGamePersistent->Environment().CurrentEnv->ambient); const Fmatrix &Transform = FluidData.GetTransform(); Fbox box; box.min = Fvector3().set(-0.5f, -0.5f, -0.5f); box.max = Fvector3().set( 0.5f, 0.5f, 0.5f); box.xform(Transform); Fvector3 center; Fvector3 size; box.getcenter(center); box.getradius(size); // Traverse object database g_SpatialSpace->q_box ( m_lstRenderables, 0, //ISpatial_DB::O_ORDERED, STYPE_LIGHTSOURCE, center, size ); u32 iNumRenderables = m_lstRenderables.size(); // Determine visibility for dynamic part of scene for (u32 i=0; i<iNumRenderables; ++i) { ISpatial* spatial = m_lstRenderables[i]; // Light light* pLight = (light*) spatial->dcast_Light(); VERIFY(pLight); if (pLight->flags.bStatic) continue; float d = pLight->position.distance_to(Transform.c); float R = pLight->range + _max( size.x, _max( size.y, size.z ) ); if ( d >= R ) continue; Fvector3 LightIntencity; LightIntencity.set(pLight->color.r, pLight->color.g, pLight->color.b); //LightIntencity.mul(0.5f); //if (!pLight->flags.bStatic) // LightIntencity.mul(0.5f); float r = pLight->range; float a = clampr(1.f - d/(r+EPS),0.f,1.f)*(pLight->flags.bStatic?1.f:2.f); LightIntencity.mul(a); LightData.m_vLightIntencity.add(LightIntencity); } //LightData.m_vLightIntencity.set( 1.0f, 0.5f, 0.0f); //LightData.m_vLightIntencity.set( 1.0f, 1.0f, 1.0f); }
BOOL CObjectSpace::_RayTest ( const Fvector &start, const Fvector &dir, float range, collide::rq_target tgt, collide::ray_cache* cache, CObject* ignore_object) { VERIFY (_abs(dir.magnitude()-1)<EPS); r_temp.r_clear (); xrc.ray_options (CDB::OPT_ONLYFIRST); collide::ray_defs Q (start,dir,range,CDB::OPT_ONLYFIRST,tgt); // dynamic test if (tgt&rqtDyn){ u32 d_flags = STYPE_COLLIDEABLE|((tgt&rqtObstacle)?STYPE_OBSTACLE:0)|((tgt&rqtShape)?STYPE_SHAPE:0); // traverse object database g_SpatialSpace->q_ray (r_spatial,0,d_flags,start,dir,range); // Determine visibility for dynamic part of scene for (u32 o_it=0; o_it<r_spatial.size(); o_it++) { ISpatial* spatial = r_spatial[o_it]; CObject* collidable = spatial->dcast_CObject (); if (collidable && (collidable!=ignore_object)) { ECollisionFormType tp = collidable->collidable.model->Type(); if ((tgt&(rqtObject|rqtObstacle))&&(tp==cftObject)&&collidable->collidable.model->_RayQuery(Q,r_temp)) return TRUE; if ((tgt&rqtShape)&&(tp==cftShape)&&collidable->collidable.model->_RayQuery(Q,r_temp)) return TRUE; } } } // static test if (tgt&rqtStatic){ // If we get here - test static model if (cache) { // 0. similar query??? if (cache->similar(start,dir,range)) { return cache->result; } // 1. Check cached polygon float _u,_v,_range; if (CDB::TestRayTri(start,dir,cache->verts,_u,_v,_range,false)) { if (_range>0 && _range<range) return TRUE; } // 2. Polygon doesn't pick - real database query xrc.ray_query (&Static,start,dir,range); if (0==xrc.r_count()) { cache->set (start,dir,range,FALSE); return FALSE; } else { // cache polygon cache->set (start,dir,range,TRUE); CDB::RESULT* R = xrc.r_begin(); CDB::TRI& T = Static.get_tris() [ R->id ]; Fvector* V = Static.get_verts(); cache->verts[0].set (V[T.verts[0]]); cache->verts[1].set (V[T.verts[1]]); cache->verts[2].set (V[T.verts[2]]); return TRUE; } } else { xrc.ray_query (&Static,start,dir,range); return xrc.r_count (); } } return FALSE; }
void CExplosive::Explode() { VERIFY(0xffff != Initiator()); VERIFY(m_explosion_flags.test(flReadyToExplode));//m_bReadyToExplode VERIFY(!ph_world->Processing()); //m_bExploding = true; m_explosion_flags.set(flExploding,TRUE); cast_game_object()->processing_activate(); Fvector& pos = m_vExplodePos; Fvector& dir = m_vExplodeDir; #ifdef DEBUG if(ph_dbg_draw_mask.test(phDbgDrawExplosions)) { DBG_OpenCashedDraw(); DBG_DrawPoint(pos,0.3f,D3DCOLOR_XRGB(255,0,0)); } #endif // Msg("---------CExplosive Explode [%d] frame[%d]",cast_game_object()->ID(), Device.dwFrame); OnBeforeExplosion(); //играем звук взрыва Sound->play_at_pos(sndExplode, 0, pos, false); //показываем эффекты m_wallmark_manager.PlaceWallmarks (pos); Fvector vel; smart_cast<CPhysicsShellHolder*>(cast_game_object())->PHGetLinearVell(vel); Fmatrix explode_matrix; explode_matrix.identity(); explode_matrix.j.set(dir); Fvector::generate_orthonormal_basis(explode_matrix.j, explode_matrix.i, explode_matrix.k); explode_matrix.c.set(pos); CParticlesObject* pStaticPG; pStaticPG = CParticlesObject::Create(*m_sExplodeParticles,!m_bDynamicParticles); if (m_bDynamicParticles) m_pExpParticle = pStaticPG; pStaticPG->UpdateParent(explode_matrix,vel); pStaticPG->Play(); //включаем подсветку от взрыва StartLight(); //trace frags Fvector frag_dir; ////////////////////////////// //осколки ////////////////////////////// //------------------------------------- bool SendHits = false; if (OnServer()) SendHits = true; else SendHits = false; for(int i = 0; i < m_iFragsNum; ++i){ frag_dir.random_dir (); frag_dir.normalize (); CCartridge cartridge; cartridge.m_kDist = 1.f; cartridge.m_kHit = 1.f; cartridge.m_kImpulse = 1.f; cartridge.m_kPierce = 1.f; cartridge.fWallmarkSize = fWallmarkSize; cartridge.bullet_material_idx = GMLib.GetMaterialIdx(WEAPON_MATERIAL_NAME); cartridge.m_flags.set (CCartridge::cfTracer,FALSE); Level().BulletManager().AddBullet( pos, frag_dir, m_fFragmentSpeed, m_fFragHit, m_fFragHitImpulse, Initiator(), cast_game_object()->ID(), m_eHitTypeFrag, m_fFragsRadius, cartridge, SendHits ); } if (cast_game_object()->Remote()) return; ///////////////////////////////// //взрывная волна //////////////////////////////// //--------------------------------------------------------------------- xr_vector<ISpatial*> ISpatialResult; g_SpatialSpace->q_sphere(ISpatialResult,0,STYPE_COLLIDEABLE,pos,m_fBlastRadius); m_blasted_objects.clear (); for (u32 o_it=0; o_it<ISpatialResult.size(); o_it++) { ISpatial* spatial = ISpatialResult[o_it]; // feel_touch_new(spatial->dcast_CObject()); CPhysicsShellHolder *pGameObject = smart_cast<CPhysicsShellHolder*>(spatial->dcast_CObject()); if(pGameObject && cast_game_object()->ID() != pGameObject->ID()) m_blasted_objects.push_back(pGameObject); } GetExplosionBox(m_vExplodeSize); START_PROFILE("explosive/activate explosion box") ActivateExplosionBox(m_vExplodeSize,m_vExplodePos); STOP_PROFILE //--------------------------------------------------------------------- #ifdef DEBUG if(ph_dbg_draw_mask.test(phDbgDrawExplosions)) { DBG_ClosedCashedDraw(100000); } #endif ////////////////////////////////////////////////////////////////////////// // Explode Effector ////////////// CGameObject* GO = smart_cast<CGameObject*>(Level().CurrentEntity()); CActor* pActor = smart_cast<CActor*>(GO); if(pActor) { float dist_to_actor = pActor->Position().distance_to(pos); float max_dist = EFFECTOR_RADIUS; if (dist_to_actor < max_dist) AddEffector (pActor, effExplodeHit, effector.effect_sect_name, (max_dist - dist_to_actor) / max_dist ); } }
void CROS_impl::update (IRenderable* O) { // clip & verify if (dwFrame==Device.dwFrame) return; dwFrame = Device.dwFrame; if (0==O) return; if (0==O->renderable.visual) return; VERIFY (dynamic_cast<CROS_impl*> (O->renderable_ROS())); float dt = Device.fTimeDelta; CObject* _object = dynamic_cast<CObject*> (O); // select sample, randomize position inside object Fvector position; O->renderable.xform.transform_tiny (position,O->renderable.visual->vis.sphere.P); float radius; radius = O->renderable.visual->vis.sphere.R; position.y += .3f * radius; Fvector direction; direction.random_dir(); //. position.mad(direction,0.25f*radius); //. position.mad(direction,0.025f*radius); // sun-tracing #if RENDER==R_R1 light* sun = (light*)RImplementation.L_DB->sun_adapted._get() ; #else light* sun = (light*)RImplementation.Lights.sun_adapted._get() ; #endif if (MODE & IRender_ObjectSpecific::TRACE_SUN) { if (--result_sun < 0) { result_sun += ::Random.randI(lt_hemisamples/4,lt_hemisamples/2) ; Fvector direction; direction.set (sun->direction).invert().normalize (); sun_value = !(g_pGameLevel->ObjectSpace.RayTest(position,direction,500.f,collide::rqtBoth,&cache_sun,_object))?1.f:0.f; } } // hemi-tracing bool bFirstTime = (0==result_count); if (MODE & IRender_ObjectSpecific::TRACE_HEMI) { for (u32 it=0; it<(u32)ps_r2_dhemi_count; it++) { // five samples per one frame u32 sample = 0 ; if (result_count<lt_hemisamples) { sample=result_count; result_count++; } else { sample=(result_iterator%lt_hemisamples); result_iterator++; } // take sample Fvector direction; direction.set (hdir[sample][0],hdir[sample][1],hdir[sample][2]).normalize (); //. result[sample] = !g_pGameLevel->ObjectSpace.RayTest(position,direction,50.f,collide::rqtBoth,&cache[sample],_object); result[sample] = !g_pGameLevel->ObjectSpace.RayTest(position,direction,50.f,collide::rqtStatic,&cache[sample],_object); // Msg ("%d:-- %s",sample,result[sample]?"true":"false"); } } // hemi & sun: update and smooth // float l_f = dt*lt_smooth; // float l_i = 1.f-l_f; int _pass = 0; for (int it=0; it<result_count; it++) if (result[it]) _pass ++; hemi_value = float (_pass)/float(result_count?result_count:1); hemi_value *= ps_r2_dhemi_scale; if (bFirstTime) hemi_smooth = hemi_value; update_smooth () ; // light-tracing BOOL bTraceLights = MODE & IRender_ObjectSpecific::TRACE_LIGHTS; if ((!O->renderable_ShadowGenerate()) && (!O->renderable_ShadowReceive())) bTraceLights = FALSE; if (bTraceLights) { // Select nearest lights Fvector bb_size = {radius,radius,radius}; g_SpatialSpace->q_box (RImplementation.lstSpatial,0,STYPE_LIGHTSOURCE,position,bb_size); for (u32 o_it=0; o_it<RImplementation.lstSpatial.size(); o_it++) { ISpatial* spatial = RImplementation.lstSpatial[o_it]; light* source = (light*) (spatial->dcast_Light()); VERIFY (source); // sanity check float R = radius+source->range; if (position.distance_to(source->position) < R) add (source); } // Trace visibility lights.clear (); float traceR = radius*.5f; for (s32 id=0; id<s32(track.size()); id++) { // remove untouched lights xr_vector<CROS_impl::Item>::iterator I = track.begin()+id; if (I->frame_touched!=Device.dwFrame) { track.erase(I) ; id-- ; continue ; } // Trace visibility Fvector P,D; float amount = 0; light* xrL = I->source; Fvector& LP = xrL->position; P.mad (position,P.random_dir(),traceR); // Random point inside range // point/spot float f = D.sub(P,LP).magnitude(); if (g_pGameLevel->ObjectSpace.RayTest(LP,D.div(f),f,collide::rqtStatic,&I->cache,_object)) amount -= lt_dec; else amount += lt_inc; I->test += amount * dt; clamp (I->test,-.5f,1.f); I->energy = .9f*I->energy + .1f*I->test; // float E = I->energy * xrL->color.intensity (); if (E > EPS) { // Select light lights.push_back (CROS_impl::Light()) ; CROS_impl::Light& L = lights.back() ; L.source = xrL ; L.color.mul_rgb (xrL->color,I->energy/2) ; L.energy = I->energy/2 ; if (!xrL->flags.bStatic) { L.color.mul_rgb(.5f); L.energy *= .5f; } } } // Sun float E = sun_smooth * sun->color.intensity (); if (E > EPS) { // Select light lights.push_back (CROS_impl::Light()) ; CROS_impl::Light& L = lights.back() ; L.source = sun ; L.color.mul_rgb (sun->color,sun_smooth/2) ; L.energy = sun_smooth ; } // Sort lights by importance - important for R1-shadows std::sort (lights.begin(),lights.end(), pred_energy); } // Process ambient lighting and approximate average lighting // Process our lights to find average luminiscense CEnvDescriptor& desc = g_pGamePersistent->Environment().CurrentEnv; Fvector accum = { desc.ambient.x, desc.ambient.y, desc.ambient.z }; Fvector hemi = { desc.hemi_color.x, desc.hemi_color.y, desc.hemi_color.z }; Fvector sun_ = { desc.sun_color.x, desc.sun_color.y, desc.sun_color.z }; if (MODE & IRender_ObjectSpecific::TRACE_HEMI ) hemi.mul(hemi_smooth); else hemi.mul(.2f); accum.add ( hemi ); if (MODE & IRender_ObjectSpecific::TRACE_SUN ) sun_.mul(sun_smooth); else sun_.mul(.2f); accum.add ( sun_ ); if (MODE & IRender_ObjectSpecific::TRACE_LIGHTS ) { Fvector lacc = { 0,0,0 }; for (u32 lit=0; lit<lights.size(); lit++) { float d = lights[lit].source->position.distance_to(position); float r = lights[lit].source->range; float a = clampr(1.f - d/(r+EPS),0.f,1.f)*(lights[lit].source->flags.bStatic?1.f:2.f); lacc.x += lights[lit].color.r*a; lacc.y += lights[lit].color.g*a; lacc.z += lights[lit].color.b*a; } // lacc.x *= desc.lmap_color.x; // lacc.y *= desc.lmap_color.y; // lacc.z *= desc.lmap_color.z; // Msg ("- rgb[%f,%f,%f]",lacc.x,lacc.y,lacc.z); accum.add (lacc); } else accum.set ( .1f, .1f, .1f ); approximate = accum; }
void CRender::render_main (Fmatrix& m_ViewProjection, bool _fportals) { // Msg ("---begin"); marker ++; // Calculate sector(s) and their objects if (pLastSector) { //!!! //!!! BECAUSE OF PARALLEL HOM RENDERING TRY TO DELAY ACCESS TO HOM AS MUCH AS POSSIBLE //!!! { // Traverse object database g_SpatialSpace->q_frustum ( lstRenderables, ISpatial_DB::O_ORDERED, STYPE_RENDERABLE + STYPE_LIGHTSOURCE, ViewBase ); // (almost) Exact sorting order (front-to-back) std::sort (lstRenderables.begin(),lstRenderables.end(),pred_sp_sort); // Determine visibility for dynamic part of scene set_Object (0); u32 uID_LTRACK = 0xffffffff; if (phase==PHASE_NORMAL) { uLastLTRACK ++; if (lstRenderables.size()) uID_LTRACK = uLastLTRACK%lstRenderables.size(); // update light-vis for current entity / actor CObject* O = g_pGameLevel->CurrentViewEntity(); if (O) { CROS_impl* R = (CROS_impl*) O->ROS(); if (R) R->update (O); } // update light-vis for selected entity // track lighting environment if (lstRenderables.size()) { IRenderable* renderable = lstRenderables[uID_LTRACK]->dcast_Renderable (); if (renderable) { CROS_impl* T = (CROS_impl*)renderable->renderable_ROS (); if (T) T->update (renderable); } } } } // Traverse sector/portal structure PortalTraverser.traverse ( pLastSector, ViewBase, Device.vCameraPosition, m_ViewProjection, CPortalTraverser::VQ_HOM + CPortalTraverser::VQ_SSA + CPortalTraverser::VQ_FADE //. disabled scissoring (HW.Caps.bScissor?CPortalTraverser::VQ_SCISSOR:0) // generate scissoring info ); // Determine visibility for static geometry hierrarhy for (u32 s_it=0; s_it<PortalTraverser.r_sectors.size(); s_it++) { CSector* sector = (CSector*)PortalTraverser.r_sectors[s_it]; IRender_Visual* root = sector->root(); for (u32 v_it=0; v_it<sector->r_frustums.size(); v_it++) { set_Frustum (&(sector->r_frustums[v_it])); add_Geometry (root); } } // Traverse frustums for (u32 o_it=0; o_it<lstRenderables.size(); o_it++) { ISpatial* spatial = lstRenderables[o_it]; spatial->spatial_updatesector (); CSector* sector = (CSector*)spatial->spatial.sector; if (0==sector) continue; // disassociated from S/P structure if (spatial->spatial.type & STYPE_LIGHTSOURCE) { // lightsource light* L = (light*) (spatial->dcast_Light()); VERIFY (L); float lod = L->get_LOD (); if (lod>EPS_L) { vis_data& vis = L->get_homdata ( ); if (HOM.visible(vis)) Lights.add_light (L); } continue ; } if (PortalTraverser.i_marker != sector->r_marker) continue; // inactive (untouched) sector for (u32 v_it=0; v_it<sector->r_frustums.size(); v_it++) { CFrustum& view = sector->r_frustums[v_it]; if (!view.testSphere_dirty(spatial->spatial.sphere.P,spatial->spatial.sphere.R)) continue; if (spatial->spatial.type & STYPE_RENDERABLE) { // renderable IRenderable* renderable = spatial->dcast_Renderable (); VERIFY (renderable); // Occlusion vis_data& v_orig = renderable->renderable.visual->vis; vis_data v_copy = v_orig; v_copy.box.xform (renderable->renderable.xform); BOOL bVisible = HOM.visible(v_copy); v_orig.marker = v_copy.marker; v_orig.accept_frame = v_copy.accept_frame; v_orig.hom_frame = v_copy.hom_frame; v_orig.hom_tested = v_copy.hom_tested; if (!bVisible) break; // exit loop on frustums // Rendering set_Object (renderable); renderable->renderable_Render (); set_Object (0); } break; // exit loop on frustums } } if (g_pGameLevel && (phase==PHASE_NORMAL)) g_pGameLevel->pHUD->Render_Last(); // HUD } else { set_Object (0); if (g_pGameLevel && (phase==PHASE_NORMAL)) g_pGameLevel->pHUD->Render_Last(); // HUD } }