void CTeleWhirlwindObject:: keep () { CPhysicsShell* p = get_object() ->PPhysicsShell(); if(!p||!p->isActive()) return; else { p->SetAirResistance(0.f,0.f); p->set_ApplyByGravity(FALSE); } u16 element_number = p ->get_ElementsNumber(); Fvector center = m_telekinesis ->Center(); CPhysicsElement* maxE=p->get_ElementByStoreOrder(0); for(u16 element=0;element<element_number;++element) { CPhysicsElement* E= p->get_ElementByStoreOrder(element); if(maxE->getMass()<E->getMass())maxE=E; Fvector dir;dir.sub(center,E->mass_Center()); dir.normalize_safe(); Fvector vel; E->get_LinearVel(vel); float force=dir.dotproduct(vel)*E->getMass()/2.f; if(force<0.f) { dir.mul(force); } } maxE->setTorque(Fvector().set(0,500.f,0)); Fvector dist;dist.sub(center,maxE->mass_Center()); if(dist.magnitude()>m_telekinesis->keep_radius()*1.5f) { p->setTorque(Fvector().set(0,0,0)); p->setForce(Fvector().set(0,0,0)); p->set_LinearVel(Fvector().set(0,0,0)); p->set_AngularVel(Fvector().set(0,0,0)); p->set_ApplyByGravity(TRUE); switch_state(TS_Raise); } }
CPhysicsShell* P_build_Shell (CGameObject* obj,bool not_active_state,BONE_P_MAP* bone_map) { CKinematics* pKinematics=smart_cast<CKinematics*>(obj->Visual()); CPhysicsShell* pPhysicsShell = P_create_Shell(); #ifdef DEBUG pPhysicsShell->dbg_obj=smart_cast<CPhysicsShellHolder*>(obj); #endif pPhysicsShell->build_FromKinematics(pKinematics,bone_map); pPhysicsShell->set_PhysicsRefObject(smart_cast<CPhysicsShellHolder*>(obj)); pPhysicsShell->mXFORM.set(obj->XFORM()); pPhysicsShell->Activate(not_active_state);//, //m_pPhysicsShell->SmoothElementsInertia(0.3f); pPhysicsShell->SetAirResistance();//0.0014f,1.5f return pPhysicsShell; }
void CTeleWhirlwindObject:: raise (float step) { CPhysicsShell* p = get_object() ->PPhysicsShell(); if(!p||!p->isActive()) return; else { p->SetAirResistance(0.f,0.f); p->set_ApplyByGravity(TRUE); } u16 element_number = p ->get_ElementsNumber(); Fvector center = m_telekinesis ->Center(); CPhysicsElement* maxE=p->get_ElementByStoreOrder(0); for(u16 element=0;element<element_number;++element) { float k=strength;//600.f; float predict_v_eps=0.1f; float mag_eps =.01f; CPhysicsElement* E= p->get_ElementByStoreOrder(element); if(maxE->getMass()<E->getMass()) maxE=E; if (!E->isActive()) continue; Fvector pos=E->mass_Center(); Fvector diff; diff.sub(center,pos); float mag=_sqrt(diff.x*diff.x+diff.z*diff.z); Fvector lc;lc.set(center); if(mag>1.f) { lc.y/=mag; } diff.sub(lc,pos); mag=diff.magnitude(); float accel=k/mag/mag/mag;//*E->getMass() Fvector dir; if(mag<mag_eps) { accel=0.f; //Fvector zer;zer.set(0,0,0); //E->set_LinearVel(zer); dir.random_dir(); } else { dir.set(diff);dir.mul(1.f/mag); } Fvector vel; E->get_LinearVel(vel); float delta_v=accel*fixed_step; Fvector delta_vel; delta_vel.set(dir);delta_vel.mul(delta_v); Fvector predict_vel;predict_vel.add(vel,delta_vel); Fvector delta_pos;delta_pos.set(predict_vel);delta_pos.mul(fixed_step); Fvector predict_pos;predict_pos.add(pos,delta_pos); Fvector predict_diff;predict_diff.sub(lc,predict_pos); float predict_mag=predict_diff.magnitude(); float predict_v=predict_vel.magnitude(); Fvector force;force.set(dir); if(predict_mag>mag && predict_vel.dotproduct(dir)>0.f && predict_v>predict_v_eps) { Fvector motion_dir;motion_dir.set(predict_vel);motion_dir.mul(1.f/predict_v); float needed_d=diff.dotproduct(motion_dir); Fvector needed_diff;needed_diff.set(motion_dir);needed_diff.mul(needed_d); Fvector nearest_p;nearest_p.add(pos,needed_diff);// Fvector needed_vel;needed_vel.set(needed_diff);needed_vel.mul(1.f/fixed_step); force.sub(needed_vel,vel); force.mul(E->getMass()/fixed_step); } else { force.mul(accel*E->getMass()); } E->applyForce(force.x,force.y+get_object()->EffectiveGravity()*E->getMass(),force.z); } Fvector dist;dist.sub(center,maxE->mass_Center()); if(dist.magnitude()<m_telekinesis->keep_radius()&&b_destroyable) { p->setTorque(Fvector().set(0,0,0)); p->setForce(Fvector().set(0,0,0)); p->set_LinearVel(Fvector().set(0,0,0)); p->set_AngularVel(Fvector().set(0,0,0)); switch_state(TS_Keep); } }