void CPHCollisionDamageReceiver::CollisionCallback(bool& do_colide,bool bo1,dContact& c,SGameMtl* material_1,SGameMtl* material_2) { if(material_1->Flags.test(SGameMtl::flPassable)||material_2->Flags.test(SGameMtl::flPassable))return; dBodyID b1 = dGeomGetBody(c.geom.g1) ; dBodyID b2 = dGeomGetBody(c.geom.g2) ; dxGeomUserData *ud_self = bo1 ? retrieveGeomUserData(c.geom.g1):retrieveGeomUserData(c.geom.g2); dxGeomUserData *ud_damager = bo1 ? retrieveGeomUserData(c.geom.g2):retrieveGeomUserData(c.geom.g1); SGameMtl *material_self = bo1 ? material_1:material_2; SGameMtl *material_damager = bo1 ? material_2:material_1; VERIFY (ud_self); CPhysicsShellHolder *o_self = ud_self->ph_ref_object; CPhysicsShellHolder *o_damager = NULL;if(ud_damager)o_damager=ud_damager->ph_ref_object; u16 source_id = o_damager ? o_damager->ID():u16(-1); CPHCollisionDamageReceiver *dr =o_self->PHCollisionDamageReceiver(); VERIFY2(dr,"wrong callback"); float damager_material_factor=material_damager->fBounceDamageFactor; if(ud_damager&&ud_damager->ph_object&&ud_damager->ph_object->CastType()==CPHObject::tpCharacter) { CCharacterPhysicsSupport* phs=o_damager->character_physics_support(); if(phs->IsSpecificDamager())damager_material_factor=phs->BonceDamageFactor(); } float dfs=(material_self->fBounceDamageFactor+damager_material_factor); if(fis_zero(dfs)) return; Fvector dir;dir.set(*(Fvector*)c.geom.normal); Fvector pos; pos.sub(*(Fvector*)c.geom.pos,*(Fvector*)dGeomGetPosition(bo1 ? c.geom.g1:c.geom.g2));//it is not true pos in bone space dr->Hit(source_id,ud_self->bone_id,E_NL(b1,b2,c.geom.normal)*damager_material_factor/dfs,dir,pos); }
void CClimableObject::ObjectContactCallback(bool& do_colide,bool bo1,dContact& c,SGameMtl * /*material_1*/,SGameMtl * /*material_2*/) { dxGeomUserData* usr_data_1= retrieveGeomUserData(c.geom.g1); dxGeomUserData* usr_data_2=retrieveGeomUserData(c.geom.g2); dxGeomUserData* usr_data_ch=NULL; dxGeomUserData* usr_data_lad=NULL; CClimableObject* this_object=NULL; CPHCharacter* ch=NULL; float norm_sign=0.f; if(bo1) { usr_data_ch=usr_data_2; usr_data_lad=usr_data_1; norm_sign=-1.f; } else { norm_sign=1.f; usr_data_ch=usr_data_1; usr_data_lad=usr_data_2; } if(usr_data_ch&&usr_data_ch->ph_object&&usr_data_ch->ph_object->CastType()==CPHObject::tpCharacter) ch=static_cast<CPHCharacter*>(usr_data_ch->ph_object); else { do_colide=false; return; } VERIFY(ch); VERIFY(usr_data_lad); this_object=static_cast<CClimableObject*>(usr_data_lad->ph_ref_object); VERIFY(this_object); if(!this_object->BeforeLadder(ch,-0.1f)) do_colide=false; }
void CCar::SWheel::WheellCollisionCallback(bool& do_colide,bool bo1,dContact& c,SGameMtl* material_1,SGameMtl* material_2) { dxGeomUserData *ud1 = retrieveGeomUserData(c.geom.g1) ; dxGeomUserData *ud2 = retrieveGeomUserData(c.geom.g2) ; applywheelCollisionParams (ud1,do_colide,c,material_1,material_2) ; applywheelCollisionParams (ud2,do_colide,c,material_1,material_2) ; }
void CPHCapture::object_contactCallbackFun(bool& do_colide,bool bo1,dContact& c,SGameMtl * /*material_1*/,SGameMtl * /*material_2*/) { dxGeomUserData *l_pUD1 = NULL; dxGeomUserData *l_pUD2 = NULL; l_pUD1 = retrieveGeomUserData(c.geom.g1); l_pUD2 = retrieveGeomUserData(c.geom.g2); if(! l_pUD1) return; if(!l_pUD2) return; //CEntityAlive* capturer=smart_cast<CEntityAlive*>(l_pUD1->ph_ref_object); IPhysicsShellHolder* capturer=(l_pUD1->ph_ref_object); if(capturer) { IPHCapture* icapture=capturer->PHCapture(); CPHCapture* capture = static_cast<CPHCapture*>(icapture); if(capture) { if(capture->m_taget_element->PhysicsRefObject()==l_pUD2->ph_ref_object) { do_colide = false; capture->m_taget_element->Enable(); if(capture->e_state==CPHCapture::cstReleased) capture->ReleaseInCallBack(); } } } capturer=l_pUD2->ph_ref_object; if(capturer) { CPHCapture* capture=static_cast<CPHCapture*>(capturer->PHCapture()); if(capture) { if(capture->m_taget_element->PhysicsRefObject()==l_pUD1->ph_ref_object) { do_colide = false; capture->m_taget_element->Enable(); if(capture->e_state==CPHCapture::cstReleased) capture->ReleaseInCallBack(); } } } }
void OnCharacterContactInDeath(bool& do_colide,bool bo1,dContact& c,SGameMtl * /*material_1*/,SGameMtl * /*material_2*/) { dSurfaceParameters &surface=c.surface; CCharacterPhysicsSupport* l_character_physic_support=0; if (bo1) { l_character_physic_support=(CCharacterPhysicsSupport*)retrieveGeomUserData(c.geom.g1)->callback_data; } else { l_character_physic_support=(CCharacterPhysicsSupport*)retrieveGeomUserData(c.geom.g2)->callback_data; } surface.mu=l_character_physic_support->m_curr_skin_friction_in_death; }
void StaticEnvironment ( bool& do_colide, bool bo1, dContact& c, SGameMtl* material_1, SGameMtl* material_2 ) { dJointID contact_joint = dJointCreateContact(0, ContactGroup, &c); if(bo1) { ((CPHActivationShape*)(retrieveGeomUserData(c.geom.g1)->callback_data))->DActiveIsland()->ConnectJoint(contact_joint); dJointAttach (contact_joint, dGeomGetBody(c.geom.g1), 0); } else { ((CPHActivationShape*)(retrieveGeomUserData(c.geom.g2)->callback_data))->DActiveIsland()->ConnectJoint(contact_joint); dJointAttach (contact_joint, 0, dGeomGetBody(c.geom.g2)); } do_colide=false; }
IPhysicsShellHolder* CPHActivationShape::ref_object () { VERIFY(m_geom); dxGeomUserData* ud = retrieveGeomUserData( m_geom ); VERIFY( ud ); return ud->ph_ref_object; }
void TTestDepthCallback (bool& do_colide,bool bo1,dContact& c,SGameMtl* material_1,SGameMtl* material_2) { if(saved_callback)saved_callback(do_colide,bo1,c,material_1,material_2); if(do_colide&&!material_1->Flags.test(SGameMtl::flPassable) &&!material_2->Flags.test(SGameMtl::flPassable)) { float& depth=c.geom.depth; float test_depth=depth-Pars::decrement_depth; save_max(max_depth,test_depth); c.surface.mu*=Pars::calback_friction_factor; if(test_depth>Pars::depth_to_use_force) { float force = Pars::callback_force_factor*ph_world->Gravity(); dBodyID b1=dGeomGetBody(c.geom.g1); dBodyID b2=dGeomGetBody(c.geom.g2); if(b1)dBodyAddForce(b1,c.geom.normal[0]*force,c.geom.normal[1]*force,c.geom.normal[2]*force); if(b2)dBodyAddForce(b2,-c.geom.normal[0]*force,-c.geom.normal[1]*force,-c.geom.normal[2]*force); dxGeomUserData* ud1=retrieveGeomUserData(c.geom.g1); dxGeomUserData* ud2=retrieveGeomUserData(c.geom.g2); if(ud1) { CPhysicsShell* phsl=ud1->ph_ref_object->PPhysicsShell(); if(phsl) phsl->Enable(); } if(ud2) { CPhysicsShell* phsl=ud2->ph_ref_object->PPhysicsShell(); if(phsl) phsl->Enable(); } do_colide=false; } else if(test_depth>Pars::depth_to_change_softness_pars) { c.surface.soft_cfm=Pars::callback_cfm_factor; c.surface.soft_erp=Pars::callback_erp_factor; } limit_above(depth,Pars::max_real_depth); } }
void CollisionCallbackDead(bool& do_colide,bool bo1,dContact& c,SGameMtl* material_1,SGameMtl* material_2) { do_colide=true; CHelicopter *l_this = bo1 ? smart_cast<CHelicopter*>(retrieveGeomUserData(c.geom.g1)->ph_ref_object) : smart_cast<CHelicopter*>(retrieveGeomUserData(c.geom.g2)->ph_ref_object); if(l_this&& !l_this->m_exploded) l_this->m_ready_explode=true; }
//вызывается при столкновении мочалки с чем-то void CBastArtefact::ObjectContactCallback(bool& /**do_colide/**/,bool bo1,dContact& c,SGameMtl * /*material_1*/,SGameMtl * /*material_2*/) { dxGeomUserData *l_pUD1 = NULL; dxGeomUserData *l_pUD2 = NULL; l_pUD1 = retrieveGeomUserData(c.geom.g1); l_pUD2 = retrieveGeomUserData(c.geom.g2); if(!l_pUD1 || !l_pUD2) return; //определить кто есть кто, из двух столкнувшихся предметов CBastArtefact *pBastArtefact = l_pUD1 ? smart_cast<CBastArtefact*>(l_pUD1->ph_ref_object) : NULL; if(!pBastArtefact) pBastArtefact = l_pUD2 ? smart_cast<CBastArtefact*>(l_pUD2->ph_ref_object) : NULL; if(!pBastArtefact) return; if(!pBastArtefact->IsAttacking()) return; CEntityAlive *pEntityAlive = NULL; pEntityAlive = l_pUD1 ? smart_cast<CEntityAlive*>(l_pUD1->ph_ref_object) : NULL; if(!pEntityAlive) pEntityAlive = l_pUD2 ? smart_cast<CEntityAlive*>(l_pUD2->ph_ref_object) : NULL; pBastArtefact->BastCollision(pEntityAlive); }
IC static int CollideIntoGroup(dGeomID o1, dGeomID o2,dJointGroupID jointGroup,CPHIsland* world,const int &MAX_CONTACTS) { const int RS= 800+10; const int N = RS; static dContact contacts[RS]; int collided_contacts=0; // get the contacts up to a maximum of N contacts int n; VERIFY (o1); VERIFY (o2); VERIFY(&contacts[0].geom); n = dCollide(o1, o2, N, &contacts[0].geom, sizeof(dContact)); if(n>N-1) n=N-1; int i; for(i = 0; i < n; ++i) { dContact &c =contacts[i]; dContactGeom &cgeom =c.geom; dSurfaceParameters &surface=c.surface; dGeomID g1 =cgeom.g1; dGeomID g2 =cgeom.g2; bool pushing_neg= false; bool do_collide = true; dxGeomUserData* usr_data_1 =NULL; dxGeomUserData* usr_data_2 =NULL; u16 material_idx_1 =0; u16 material_idx_2 =0; surface.mu =1.f;// 5000.f; surface.soft_erp=1.f;//ERP(world_spring,world_damping); surface.soft_cfm=1.f;//CFM(world_spring,world_damping); surface.bounce = 0.01f;//0.1f; surface.bounce_vel =1.5f;//0.005f; usr_data_1 = retrieveGeomUserData(g1); usr_data_2 = retrieveGeomUserData(g2); /////////////////////////////////////////////////////////////////////////////////////////////////// if(usr_data_2) material_idx_2=usr_data_2->material; if(usr_data_1) material_idx_1=usr_data_1->material; bool is_tri_1=dTriListClass == dGeomGetClass(g1); bool is_tri_2=dTriListClass == dGeomGetClass(g2); if(!is_tri_2&&!is_tri_1) surface.mode=0; if(is_tri_1) material_idx_1=(u16)surface.mode; if(is_tri_2) material_idx_2=(u16)surface.mode; SGameMtl* material_1=GMLib.GetMaterialByIdx(material_idx_1); SGameMtl* material_2=GMLib.GetMaterialByIdx(material_idx_2); ////////////////params can be changed in callbacks////////////////////////////////////////////////////////////////////////// surface.mode =dContactApprox1|dContactSoftERP|dContactSoftCFM; float spring =material_2->fPHSpring*material_1->fPHSpring*world_spring; float damping =material_2->fPHDamping*material_1->fPHDamping*world_damping; surface.soft_erp=ERP(spring,damping); surface.soft_cfm=CFM(spring,damping); surface.mu=material_2->fPHFriction*material_1->fPHFriction; ///////////////////////////////////////////////////////////////////////////////////////////////// Flags32 &flags_1=material_1->Flags; Flags32 &flags_2=material_2->Flags; if(is_tri_1) { #pragma warning(push) #pragma warning(disable:4245) if(material_1->Flags.test(SGameMtl::flSlowDown)&&!(usr_data_2->pushing_neg||usr_data_2->pushing_b_neg)) #pragma warning(pop) { dBodyID body=dGeomGetBody(g2); R_ASSERT2(body,"static - static collision !!!"); if(material_1->Flags.test(SGameMtl::flLiquid)) { add_contact_body_effector(body,c,material_1); } else { if(!usr_data_2 || !usr_data_2->ph_object || !usr_data_2->ph_object->IsRayMotion()) { add_contact_body_effector(body,c,material_1); } } } if(material_1->Flags.test(SGameMtl::flPassable)) do_collide=false; // if(material_2->Flags.is(SGameMtl::flClimable)) // do_collide=false; } if(is_tri_2) { #pragma warning(push) #pragma warning(disable:4245) if(material_2->Flags.test(SGameMtl::flSlowDown)&&!(usr_data_1->pushing_neg||usr_data_1->pushing_b_neg)) #pragma warning(pop) { dBodyID body=dGeomGetBody(g1); R_ASSERT2(body,"static - static collision !!!"); if(material_2->Flags.test(SGameMtl::flLiquid)) { add_contact_body_effector(body,c,material_2); } else { if(!usr_data_1 || !usr_data_1->ph_object || !usr_data_1->ph_object->IsRayMotion()) { add_contact_body_effector(body,c,material_2); } } } if(material_2->Flags.test(SGameMtl::flPassable)) do_collide=false; } if(flags_1.test(SGameMtl::flBounceable)&&flags_2.test(SGameMtl::flBounceable)) { surface.mode |= dContactBounce; surface.bounce_vel = _max(material_1->fPHBounceStartVelocity,material_2->fPHBounceStartVelocity); surface.bounce = _min(material_1->fPHBouncing,material_2->fPHBouncing); } ///////////////////////////////////////////////////////////////////////////////////////////////// if(usr_data_2&&usr_data_2->object_callbacks){ usr_data_2->object_callbacks->Call(do_collide,false,c,material_1,material_2); } if(usr_data_1&&usr_data_1->object_callbacks){ usr_data_1->object_callbacks->Call(do_collide,true,c,material_1,material_2); } if(usr_data_2){ usr_data_2->pushing_b_neg = usr_data_2->pushing_b_neg && !GMLib.GetMaterialByIdx(usr_data_2->b_neg_tri->material)->Flags.test(SGameMtl::flPassable); usr_data_2->pushing_neg = usr_data_2->pushing_neg && !GMLib.GetMaterialByIdx(usr_data_2->neg_tri->material)->Flags.test(SGameMtl::flPassable); pushing_neg=usr_data_2->pushing_b_neg||usr_data_2->pushing_neg; if(usr_data_2->ph_object){ usr_data_2->ph_object->InitContact(&c,do_collide,material_idx_1,material_idx_2); } } /////////////////////////////////////////////////////////////////////////////////////// if(usr_data_1){ usr_data_1->pushing_b_neg = usr_data_1->pushing_b_neg && !GMLib.GetMaterialByIdx(usr_data_1->b_neg_tri->material)->Flags.test(SGameMtl::flPassable); usr_data_1->pushing_neg = usr_data_1->pushing_neg && !GMLib.GetMaterialByIdx(usr_data_1->neg_tri->material)->Flags.test(SGameMtl::flPassable); pushing_neg=usr_data_1->pushing_b_neg||usr_data_1->pushing_neg; if(usr_data_1->ph_object){ usr_data_1->ph_object->InitContact(&c,do_collide,material_idx_1,material_idx_2); } } if (pushing_neg) surface.mu=dInfinity; if (do_collide && collided_contacts<MAX_CONTACTS) { ++collided_contacts; #ifdef DEBUG if( ph_dbg_draw_mask.test(phDbgDrawContacts) ) DBG_DrawContact(c); #endif dJointID contact_joint = dJointCreateContact(0, jointGroup, &c); world->ConnectJoint(contact_joint); dJointAttach (contact_joint, dGeomGetBody(g1), dGeomGetBody(g2)); } } return collided_contacts; }