bool CPHActivationShape:: Activate (const Fvector need_size,u16 steps,float max_displacement,float max_rotation,bool un_freeze_later/* =false*/) { #ifdef DEBUG if(ph_dbg_draw_mask.test(phDbgDrawDeathActivationBox)) { DBG_OpenCashedDraw(); Fmatrix M; PHDynamicData::DMXPStoFMX(dBodyGetRotation(m_body),dBodyGetPosition(m_body),M); Fvector v;dGeomBoxGetLengths(m_geom,cast_fp(v));v.mul(0.5f); DBG_DrawOBB(M,v,D3DCOLOR_XRGB(0,255,0)); } #endif VERIFY(m_geom&&m_body); CPHObject::activate(); ph_world->Freeze(); UnFreeze(); max_depth=0.f; dGeomUserDataSetObjectContactCallback(m_geom,GetMaxDepthCallback) ; //ph_world->Step(); ph_world->StepTouch(); u16 num_it =15; float fnum_it=float(num_it); float fnum_steps=float(steps); float fnum_steps_r=1.f/fnum_steps; float resolve_depth=0.01f; float max_vel=max_depth/fnum_it*fnum_steps_r/fixed_step; float limit_l_vel=_max(_max(need_size.x,need_size.y),need_size.z)/fnum_it*fnum_steps_r/fixed_step; if(limit_l_vel>default_l_limit) limit_l_vel=default_l_limit; if(max_vel>limit_l_vel) max_vel=limit_l_vel; float max_a_vel=max_rotation/fnum_it*fnum_steps_r/fixed_step; if(max_a_vel>default_w_limit) max_a_vel=default_w_limit; //ph_world->CutVelocity(0.f,0.f); dGeomUserDataSetCallbackData(m_geom,this); dGeomUserDataSetObjectContactCallback( m_geom, ActivateTestDepthCallback ); if( m_flags.test( flStaticEnvironment ) ) dGeomUserDataAddObjectContactCallback(m_geom,StaticEnvironment); max_depth=0.f; Fvector from_size; Fvector step_size,size; dGeomBoxGetLengths(m_geom,cast_fp(from_size)); step_size.sub(need_size,from_size); step_size.mul(fnum_steps_r); size.set(from_size); bool ret=false; V_PH_WORLD_STATE temp_state; ph_world->GetState(temp_state); for(int m=0;steps>m;++m) { //float param =fnum_steps_r*(1+m); //InterpolateBox(id,param); size.add(step_size); dGeomBoxSetLengths(m_geom,size.x,size.y,size.z); u16 attempts=10; do{ ret=false; for(int i=0;num_it>i;++i) { max_depth=0.f; ph_world->Step(); CHECK_POS(Position(),"pos after ph_world->Step()",false); ph_world->CutVelocity(max_vel,max_a_vel); CHECK_POS(Position(),"pos after CutVelocity",true); //if(m==0&&i==0)ph_world->GetState(temp_state); if(max_depth < resolve_depth) { ret=true; break; } } attempts--; }while(!ret&&attempts>0); #ifdef DEBUG Msg("correction attempts %d",10-attempts); #endif } RestoreVelocityState(temp_state); CHECK_POS(Position(),"pos after RestoreVelocityState(temp_state);",true); if(!un_freeze_later)ph_world->UnFreeze(); #ifdef DEBUG if(ph_dbg_draw_mask.test(phDbgDrawDeathActivationBox)) { DBG_OpenCashedDraw(); Fmatrix M; PHDynamicData::DMXPStoFMX(dBodyGetRotation(m_body),dBodyGetPosition(m_body),M); Fvector v;v.set(need_size);v.mul(0.5f); DBG_DrawOBB(M,v,D3DCOLOR_XRGB(0,255,255)); DBG_ClosedCashedDraw(30000); } #endif return ret; }
float CExplosive::ExplosionEffect(collide::rq_results& storage, CExplosive*exp_obj,CPhysicsShellHolder*blasted_obj, const Fvector &expl_centre, const float expl_radius) { const Fmatrix &obj_xform=blasted_obj->XFORM(); Fmatrix inv_obj_form;inv_obj_form.invert(obj_xform); Fvector local_exp_center;inv_obj_form.transform_tiny(local_exp_center,expl_centre); const Fbox &l_b1 = blasted_obj->BoundingBox(); if(l_b1.contains(local_exp_center)) return 1.f; Fvector l_c, l_d;l_b1.get_CD(l_c,l_d); float effective_volume=l_d.x*l_d.y*l_d.z; float max_s=effective_volume/(_min(_min(l_d.x,l_d.y),l_d.z)); if(blasted_obj->PPhysicsShell()&&blasted_obj->PPhysicsShell()->isActive()) { float ph_volume=blasted_obj->PPhysicsShell()->getVolume(); if(ph_volume<effective_volume)effective_volume=ph_volume; } float effect=0.f; #ifdef DEBUG if(ph_dbg_draw_mask.test(phDbgDrawExplosions)) { Fmatrix dbg_box_m;dbg_box_m.set(obj_xform); dbg_box_m.c.set(l_c);obj_xform.transform(dbg_box_m.c); DBG_DrawOBB(dbg_box_m,l_d,D3DCOLOR_XRGB(255,255,0)); } #endif for(u16 i=0;i<TEST_RAYS_PER_OBJECT;++i){ Fvector l_source_p,l_end_p; l_end_p.random_point(l_d); l_end_p.add(l_c); obj_xform.transform_tiny(l_end_p); GetRaySourcePos(exp_obj,expl_centre,l_source_p); Fvector l_local_source_p;inv_obj_form.transform_tiny(l_local_source_p,l_source_p); if(l_b1.contains(l_local_source_p)) { effect+=1.f;continue; } Fvector l_dir; l_dir.sub(l_end_p,l_source_p); float mag=l_dir.magnitude(); if(fis_zero(mag)) return 1.f; l_dir.mul(1.f/mag); #ifdef DEBUG if(ph_dbg_draw_mask.test(phDbgDrawExplosions)) { DBG_DrawPoint(l_source_p,0.1f,D3DCOLOR_XRGB(0,0,255)); DBG_DrawPoint(l_end_p,0.1f,D3DCOLOR_XRGB(0,0,255)); DBG_DrawLine(l_source_p,l_end_p,D3DCOLOR_XRGB(0,0,255)); } #endif #ifdef DEBUG float l_S=effective_volume*(_abs(l_dir.dotproduct(obj_xform.i))/l_d.x+_abs(l_dir.dotproduct(obj_xform.j))/l_d.y+_abs(l_dir.dotproduct(obj_xform.k))/l_d.z); float add_eff=_sqrt(l_S/max_s)*TestPassEffect(l_source_p,l_dir,mag,expl_radius,storage,blasted_obj); effect+=add_eff; if(ph_dbg_draw_mask.test(phDbgDrawExplosions)) { Msg("dist %f,effect R %f",mag,expl_radius); Msg("test pass effect %f",add_eff); Msg("S effect %f",_sqrt(l_S/max_s)); Msg("dist/overlap effect, %f",add_eff/_sqrt(l_S/max_s)); } #else float l_S=effective_volume*(_abs(l_dir.dotproduct(obj_xform.i))/l_d.x+_abs(l_dir.dotproduct(obj_xform.j))/l_d.y+_abs(l_dir.dotproduct(obj_xform.k))/l_d.z); effect+=_sqrt(l_S/max_s)*TestPassEffect(l_source_p,l_dir,mag,expl_radius,storage,blasted_obj); #endif } #ifdef DEBUG if(ph_dbg_draw_mask.test(phDbgDrawExplosions)) { Msg("damage effect %f",effect/TEST_RAYS_PER_OBJECT); } #endif return effect/TEST_RAYS_PER_OBJECT; }