void CODEGeom::set_obj_contact_cb(ObjectContactCallbackFun* occb) { if(!m_geom_transform) return; if(geom()) { VERIFY(dGeomGetUserData(geom())); dGeomUserDataSetObjectContactCallback(geom(),occb); } else { VERIFY(dGeomGetUserData(m_geom_transform)); dGeomUserDataSetObjectContactCallback(m_geom_transform,occb); } }
void CPHActivationShape::Create(const Fvector start_pos,const Fvector start_size,IPhysicsShellHolder* ref_obj,EType _type/*=etBox*/,u16 flags) { VERIFY(ref_obj); R_ASSERT(_valid( start_pos ) ); R_ASSERT( _valid( start_size ) ); m_body = dBodyCreate (0) ; dMass m; dMassSetSphere(&m,1.f,100000.f); dMassAdjust(&m,1.f); dBodySetMass(m_body,&m); switch(_type) { case etBox: m_geom = dCreateBox (0,start_size.x,start_size.y,start_size.z) ; break; case etSphere: m_geom = dCreateSphere (0,start_size.x); break; }; dGeomCreateUserData (m_geom) ; dGeomUserDataSetObjectContactCallback(m_geom,ActivateTestDepthCallback) ; dGeomUserDataSetPhysicsRefObject(m_geom,ref_obj) ; dGeomSetBody (m_geom,m_body) ; dBodySetPosition (m_body,start_pos.x,start_pos.y,start_pos.z) ; Island() .AddBody (m_body) ; dBodyEnable (m_body) ; m_safe_state .create(m_body) ; spatial_register () ; m_flags.set(flags,TRUE); }
bool CPHActivationShape:: Activate (const Fvector need_size,u16 steps,float max_displacement,float max_rotation,bool un_freeze_later/* =false*/) { #ifdef DEBUG if(debug_output().ph_dbg_draw_mask().test(phDbgDrawDeathActivationBox)) { debug_output().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); debug_output().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(debug_output().ph_dbg_draw_mask().test(phDbgDrawDeathActivationBox)) { debug_output().DBG_OpenCashedDraw(); Fmatrix M; PHDynamicData::DMXPStoFMX(dBodyGetRotation(m_body),dBodyGetPosition(m_body),M); Fvector v;v.set(need_size);v.mul(0.5f); debug_output().DBG_DrawOBB(M,v,D3DCOLOR_XRGB(0,255,255)); debug_output().DBG_ClosedCashedDraw(30000); } #endif return ret; }