//проверка на попадание "осколком" по объекту ICF static BOOL grenade_hit_callback(collide::rq_result& result, LPVOID params) { SExpQParams& ep = *(SExpQParams*)params; u16 mtl_idx = GAMEMTL_NONE_IDX; if(result.O){ CKinematics* V = 0; if (0!=(V=smart_cast<CKinematics*>(result.O->Visual()))){ CBoneData& B= V->LL_GetData((u16)result.element); mtl_idx = B.game_mtl_idx; } }else{ //получить треугольник и узнать его материал CDB::TRI* T = Level().ObjectSpace.GetStaticTris()+result.element; mtl_idx = T->material; } SGameMtl* mtl = GMLib.GetMaterialByIdx(mtl_idx); ep.shoot_factor *=mtl->fShootFactor; #ifdef DEBUG if(ph_dbg_draw_mask.test(phDbgDrawExplosions)) { Fvector p;p.set(ep.l_dir);p.mul(result.range);p.add(ep.source_p); u8 c =u8(mtl->fShootFactor*255.f); DBG_DrawPoint(p,0.1f,D3DCOLOR_XRGB(255-c,0,c)); } #endif return (ep.shoot_factor>0.01f); }
void ik_foot_collider::collide( SIKCollideData &cld, const ik_foot_geom &foot_geom, CGameObject *O, bool foot_step ) { VERIFY( foot_geom.is_valid() ); cld.collided = false; float pick_dist = collide_dist; //if( foot_step ) pick_dist += reach_dist ; ////////////////////////////////////////////////////////////////////////////////////// const Fvector& toe_pick_v = cld.m_pick_dir; const Fvector pos_toe = Fvector().sub( foot_geom.pos_toe(), Fvector( ).mul( toe_pick_v, collide_dist ) ); ik_pick_query q_toe( ik_foot_geom::toe, pos_toe, toe_pick_v, pick_dist ); //////////////////////////////////////////////////////////////////////////////////////// const Fvector hill_pick_v = cld.m_pick_dir; const Fvector pos_heel = Fvector().sub( foot_geom.pos_heel(), Fvector( ).mul( hill_pick_v, collide_dist ) ); ik_pick_query q_heel( ik_foot_geom::heel, pos_heel, hill_pick_v, pick_dist ); ////////////////////////////////////////////////////////////////////////////////////////// const Fvector side_pick_v = cld.m_pick_dir; const Fvector pos_side = Fvector().sub( foot_geom.pos_side(), Fvector( ).mul( side_pick_v, collide_dist ) ); ik_pick_query q_side( ik_foot_geom::side, pos_side, side_pick_v, pick_dist ); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if( previous_toe_query.is_equal ( q_toe ) && previous_heel_query.is_equal( q_heel ) && previous_side_query.is_equal( q_side ) ){ cld = previous_data; return; } const float foot_length = Fvector().sub( pos_toe, pos_heel ).magnitude() * 1.5f; previous_heel_query = q_heel; previous_side_query = q_side; previous_toe_query = q_toe; ik_pick_result r_toe(ik_foot_geom::toe); cld.collided = Pick( r_toe, q_toe, O ); cld.m_plane = r_toe.p; cld.m_collide_point = ik_foot_geom::toe; ////////////////////////////////////////////////////////////////////////////////////// #ifdef DEBUG if( ph_dbg_draw_mask1.test( phDbgDrawIKCollision ) ) { DBG_DrawPoint( pos_toe, 0.01, D3DCOLOR_XRGB( 255, 0, 0)); if(cld.collided) DBG_DrawPoint( r_toe.position, 0.01, D3DCOLOR_XRGB( 0, 0, 255)); } #endif ik_pick_result r_heel(ik_foot_geom::heel); bool heel_collided = Pick( r_heel, q_heel, O ) ; ik_pick_result r_side(ik_foot_geom::side); bool side_collided = Pick( r_side, q_side, O ) ; bool toe_heel_compatible = cld.collided && heel_collided && Fvector().sub( r_heel.position, r_toe.position ).magnitude() < foot_length; bool toe_side_compatible = cld.collided && side_collided && Fvector().sub( r_side.position, r_toe.position ).magnitude() < foot_length; /* if( hill_collided ) { if( !cld.collided || (r_hill.position.y - r_toe.position.y) > EPS ) { cld.m_plane = r_heel.p; cld.m_collide_point = ik_foot_geom::heel; cld.collided = true; cld.m_pick_dir = heel_pick_v; } } */ if( toe_heel_compatible && toe_side_compatible ) { Fplane plane; tri_plane( r_toe.position, r_heel.position , r_side.position, plane ); if( plane.n.dotproduct( r_toe.p.n ) < 0.f ) { plane.n.invert(); plane.d = -plane.d; } cld.m_plane = plane; #ifdef DEBUG if( ph_dbg_draw_mask1.test( phDbgDrawIKCollision ) ) { DBG_DrawPoint( pos_toe, 0.01, D3DCOLOR_XRGB( 255, 0, 0)); if(cld.collided) { DBG_DrawTri( r_toe.position, r_heel.position, r_side.position, D3DCOLOR_XRGB( 0, 0, 255), false ); } } #endif previous_data = cld; return; } float hight = -FLT_MAX; ik_pick_result r = r_toe; if( cld.collided ) { hight = r_toe.position.y; } if( heel_collided && r_heel.position.y > hight ) { r = r_heel; hight = r_heel.position.y; cld.collided = true; } if( side_collided && r_side.position.y > hight ) { r = r_side; hight = r_side.position.y; cld.collided = true; } if( cld.collided ) { cld.m_plane = r.p; cld.m_collide_point =r.point; previous_data = cld; return; } //chose_best_plane( cld.m_plane, pick_v, plane, r_hill.p, r_toe.p ); previous_data = cld; /* float u,v,d; if( ( !cld.collided || !( CDB::TestRayTri(pos_hill, pick_v, r_toe.triangle, u, v, d, true ) && d > 0.f ) ) && Pick( r_hill, pos_hill, pick_v, pick_dist, O ) ) { if( !cld.collided || r_hill.position.y > r_toe.position.y ) { cld.m_plane = r_hill.p; cld.m_collide_point = SIKCollideData::heel; } //else //{ // ik_pick_result r_foot; // Fvector pos_foot = Fvector().sub( foot.c, Fvector( ).mul( pick_v, collide_dist ) ); // if( cld.collided && Pick( r_foot, pos_foot, pick_v, pick_dist, O ) ) // { // Fplane plane; // tri_plane( r_toe.position, r_hill.position , r_foot.position, plane ); // DBG_DrawTri(r_toe.position, r_hill.position, r_foot.position , D3DCOLOR_XRGB( 255, 255, 255 ), false ); // // if( plane.n.dotproduct( r_hill.p.n ) < 0.f ) // { // plane.n.invert(); // plane.d = -cld.m_plane.d; // // } // chose_best_plane( cld.m_plane, pick_v, plane, r_hill.p, r_toe.p ); // } //} cld.collided = true; } */ }
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 ); } }
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; }
bool CIKFoot::GetFootStepMatrix( ik_goal_matrix &m, const Fmatrix &g_anim, const SIKCollideData &cld, bool collide, bool rotation, bool b_make_shift/*=true*/ )const { const Fmatrix global_anim = g_anim; Fvector local_point; ToePosition( local_point ); //toe position in bone[2] space Fvector global_point; global_anim.transform_tiny( global_point, local_point ); //non collided toe in global space Fvector foot_normal; FootNormal( foot_normal ); global_anim.transform_dir( foot_normal ); #ifdef DEBUG //if( ph_dbg_draw_mask.test( phDbgDrawIKGoal ) ) //{ // DBG_DrawLine( global_point, Fvector().add( global_point, foot_normal ), D3DCOLOR_XRGB( 0, 255, 255) ); //} #endif if( cld.m_collide_point == ik_foot_geom::heel || cld.m_collide_point == ik_foot_geom::side ) { Fmatrix foot;ref_bone_to_foot( foot, g_anim ); Fvector heel; HeelPosition( heel ); foot.transform_tiny(global_point, heel ); #ifdef DEBUG if( ph_dbg_draw_mask.test( phDbgDrawIKGoal ) ) DBG_DrawPoint( global_point, 0.01, D3DCOLOR_XRGB( 0, 255, 255)); #endif Fmatrix foot_to_ref; ref_bone_to_foot_transform(foot_to_ref).transform_tiny(local_point, heel ); } float dtoe_tri =-cld.m_plane.d - cld.m_plane.n.dotproduct( global_point ); if( !cld.collided || _abs( dtoe_tri ) > collide_dist ) { m.set( global_anim, ik_goal_matrix::cl_free ); return false; } Fplane p = cld.m_plane; Fmatrix xm; xm.set( global_anim ); ik_goal_matrix::e_collide_state cl_state = ik_goal_matrix::cl_undefined; if( rotation )//!collide || ik_allign_free_foot cl_state = rotate( xm, p, foot_normal, global_point, collide ); if( b_make_shift && make_shift( xm, local_point, collide, p, cld.m_pick_dir ) ) switch( cl_state ) { case ik_goal_matrix::cl_aligned : break; case ik_goal_matrix::cl_undefined : case ik_goal_matrix::cl_free : cl_state = ik_goal_matrix::cl_translational; break; case ik_goal_matrix::cl_rotational: cl_state = ik_goal_matrix::cl_mixed; break; default: NODEFAULT; } else if( cl_state == ik_goal_matrix::cl_undefined ) cl_state = ik_goal_matrix::cl_free; VERIFY( _valid( xm ) ); m.set( xm, cl_state ); #ifdef DEBUG if(ph_dbg_draw_mask.test( phDbgDrawIKGoal )) { DBG_DrawPoint( global_point, 0.03f, D3DCOLOR_RGBA( 255, 0, 0, 255 ) ); } if(!fsimilar( _abs( DET( g_anim ) - 1.f ), _abs( DET( m.get() ) - 1.f ), 0.001f ) ) Msg("scale g_anim: %f scale m: %f ", DET( g_anim ) , DET( m.get() ) ); #endif return true; }