void dbg_draw_viewport( const T &cam_info, float _viewport_near ) { VERIFY( _viewport_near > 0.f ); const Fvector near_plane_center = Fvector().mad( cam_info.Position(), cam_info.Direction(), _viewport_near ); float h_w, h_h; viewport_size ( _viewport_near, cam_info, h_w, h_h ); const Fvector right = Fvector().mul( cam_info.Right(), h_w ); const Fvector up = Fvector().mul( cam_info.Up(), h_h ); const Fvector top_left = Fvector().sub( near_plane_center, right ).add( up ); const Fvector top_right = Fvector().add( near_plane_center, right ).add( up ); const Fvector bottom_left = Fvector().sub( near_plane_center, right ).sub( up ); const Fvector bottom_right = Fvector().add( near_plane_center, right ).sub( up ); DBG_DrawLine( cam_info.Position(), top_left, D3DCOLOR_XRGB(255, 0, 0 ) ); DBG_DrawLine( cam_info.Position(), top_right, D3DCOLOR_XRGB(255, 0, 0 ) ); DBG_DrawLine( cam_info.Position(), bottom_left, D3DCOLOR_XRGB(255, 0, 0 ) ); DBG_DrawLine( cam_info.Position(), bottom_right, D3DCOLOR_XRGB(255, 0, 0 ) ); DBG_DrawLine( top_right, top_left, D3DCOLOR_XRGB(255, 0, 0 ) ); DBG_DrawLine( bottom_right, top_right, D3DCOLOR_XRGB(255, 0, 0 ) ); DBG_DrawLine( top_left, bottom_left, D3DCOLOR_XRGB(255, 0, 0 ) ); DBG_DrawLine( bottom_left, bottom_right, D3DCOLOR_XRGB(255, 0, 0 ) ); }
bool CIKFoot::make_shift( Fmatrix &xm,const Fvector &cl_point, bool collide, const Fplane &p, const Fvector &pick_dir )const { Fvector shift = pick_dir; //Fvector toe; ToePosition( toe ); xm.transform_tiny( toe ); Fvector point; xm.transform_tiny( point, cl_point ); float dot = p.n.dotproduct( shift ); if( _abs( dot ) < min_dot ) { shift.add( Fvector( ).mul( p.n, min_dot - _abs( dot ) ) ); dot = p.n.dotproduct( shift ); } VERIFY( !fis_zero( dot ) ); float shift_m = ( -p.d - p.n.dotproduct( point ) )/dot; if(collide && shift_m > 0.f ) return false; clamp( shift_m, -collide_dist, collide_dist ); shift.mul( shift_m ); xm.c.add( shift ); #if 0 if(shift_m > 0.f) { DBG_OpenCashedDraw(); DBG_DrawLine( toe, Fvector().add( toe, shift ), D3DCOLOR_XRGB( 255, 255, 255 ) ); DBG_ClosedCashedDraw( 1000 ); } #endif return true; }
void object_shift:: dbg_draw ( const Fmatrix ¤t_pos, const extrapolation::points &predict , const Fvector& start ) const { Fvector p0; current_pos.transform_tiny( p0, start ); Fmatrix predicted_pos; predict.extrapolate( predicted_pos, taget_time ); Fvector p1; predicted_pos.transform_tiny( p1, start ); const u16 nb_points = 200; float time_global = Device.fTimeGlobal; if( time_global > taget_time ) time_global = taget_time; float time = taget_time - time_global; float time_passed = time_global - current_time; if(fis_zero(time)) return; float time_quant = ( time ) / nb_points; const Fvector vadd = Fvector().sub( p1, p0 ).mul( 1.f/nb_points ); for( u16 i = 0; i < nb_points; ++i ) { float fshift0 = current + delta_shift( time_passed + time_quant * i ); float fshift1 = current + delta_shift( time_passed + time_quant * ( i + 1 ) ); Fvector v0 = Fvector().add( p0, Fvector().mul( vadd, float( i ) ) ).add( Fvector().set( 0, fshift0, 0 ) ); Fvector v1 = Fvector().add( p0, Fvector().mul( vadd, float( i + 1 ) ) ).add( Fvector().set( 0, fshift1, 0 ) ); DBG_DrawLine( v0, v1, D3DCOLOR_XRGB( 0, 255, 0 ) ); } float start_shift = current + delta_shift( time_passed ); float end_shift = current + delta_shift( time_passed + time ); DBG_DrawLine( Fvector().add( p0, Fvector().set( 0, start_shift, 0 ) ) , Fvector().add( p1, Fvector().set( 0, end_shift, 0 ) ), D3DCOLOR_XRGB( 255, 0, 0 ) ); }
bool Pick( ik_pick_result &r, const ik_pick_query &q , CObject* ignore_object) { VERIFY( q.is_valid() ); float range = q.range(); collide::rq_result R; bool collided = false; Fvector pos = q.pos(); while( g_pGameLevel->ObjectSpace.RayPick( pos, q.dir(), range, collide::rqtBoth, R, ignore_object ) ) { Fvector next_pos = pos; float next_range = range; collided = get_plane( r, next_pos, next_range , R, range, pos, q.dir() ); if( collided ) break; range = next_range; pos = next_pos; if( range < EPS ) break; } #ifdef DEBUG if( ph_dbg_draw_mask1.test( phDbgDrawIKCollision ) && collided && !R.O ) { CDB::TRI *tri = Level( ).ObjectSpace.GetStaticTris( ) + R.element; Fvector p = q.pos();p.add( Fvector( ).mul( q.dir(), range ) ); DBG_DrawLine(pos,p,D3DCOLOR_XRGB( 255, 0, 0 ) ); if( tri ) { DBG_DrawTri( tri,Level( ).ObjectSpace.GetStaticVerts( ), D3DCOLOR_XRGB( 255, 0, 0 ) ); } } #endif return collided; }
void CActor::Hit (SHit* pHDS) { pHDS->aim_bullet = false; SHit HDS = *pHDS; if( HDS.hit_type<ALife::eHitTypeBurn || HDS.hit_type >= ALife::eHitTypeMax ) { string256 err; sprintf (err, "Unknown/unregistered hit type [%d]", HDS.hit_type); R_ASSERT2 (0, err ); } #ifdef DEBUG if(ph_dbg_draw_mask.test(phDbgCharacterControl)) { DBG_OpenCashedDraw(); Fvector to;to.add(Position(),Fvector().mul(HDS.dir,HDS.phys_impulse())); DBG_DrawLine(Position(),to,D3DCOLOR_XRGB(124,124,0)); DBG_ClosedCashedDraw(500); } #endif bool bPlaySound = true; if (!g_Alive()) bPlaySound = false; if (!IsGameTypeSingle() && !g_pGamePersistent->bDedicatedServer) { game_PlayerState* ps = Game().GetPlayerByGameID(ID()); if (ps && ps->testFlag(GAME_PLAYER_FLAG_INVINCIBLE)) { bPlaySound = false; if (Device.dwFrame != last_hit_frame && HDS.bone() != BI_NONE) { // вычислить позицию и направленность партикла Fmatrix pos; CParticlesPlayer::MakeXFORM(this,HDS.bone(),HDS.dir,HDS.p_in_bone_space,pos); // установить particles CParticlesObject* ps = NULL; if (eacFirstEye == cam_active && this == Level().CurrentEntity()) ps = CParticlesObject::Create(invincibility_fire_shield_1st,TRUE); else ps = CParticlesObject::Create(invincibility_fire_shield_3rd,TRUE); ps->UpdateParent(pos,Fvector().set(0.f,0.f,0.f)); GamePersistent().ps_needtoplay.push_back(ps); }; }; last_hit_frame = Device.dwFrame; }; if( !g_pGamePersistent->bDedicatedServer && !sndHit[HDS.hit_type].empty() && (ALife::eHitTypeTelepatic != HDS.hit_type)) { ref_sound& S = sndHit[HDS.hit_type][Random.randI(sndHit[HDS.hit_type].size())]; bool b_snd_hit_playing = sndHit[HDS.hit_type].end() != std::find_if(sndHit[HDS.hit_type].begin(), sndHit[HDS.hit_type].end(), playing_pred()); if(ALife::eHitTypeExplosion == HDS.hit_type) { if (this == Level().CurrentControlEntity()) { S.set_volume(10.0f); if(!m_sndShockEffector){ m_sndShockEffector = xr_new<SndShockEffector>(); m_sndShockEffector->Start(this, float(S._handle()->length_ms()), HDS.damage() ); } } else bPlaySound = false; } if (bPlaySound && !b_snd_hit_playing) { Fvector point = Position(); point.y += CameraHeight(); S.play_at_pos (this, point); }; } //slow actor, only when he gets hit if(HDS.hit_type == ALife::eHitTypeWound || HDS.hit_type == ALife::eHitTypeStrike) { hit_slowmo = HDS.damage(); clamp (hit_slowmo,0.0f,1.f); } else hit_slowmo = 0.f; //--------------------------------------------------------------- if (Level().CurrentViewEntity() == this && !g_pGamePersistent->bDedicatedServer && HDS.hit_type == ALife::eHitTypeFireWound) { CObject* pLastHitter = Level().Objects.net_Find(m_iLastHitterID); CObject* pLastHittingWeapon = Level().Objects.net_Find(m_iLastHittingWeaponID); HitSector(pLastHitter, pLastHittingWeapon); }; if ((mstate_real&mcSprint) && Level().CurrentControlEntity() == this && HDS.hit_type != ALife::eHitTypeTelepatic && HDS.hit_type != ALife::eHitTypeRadiation ) { // mstate_real &=~mcSprint; mstate_wishful &=~mcSprint; }; if(!g_pGamePersistent->bDedicatedServer) { HitMark (HDS.damage(), HDS.dir, HDS.who, HDS.bone(), HDS.p_in_bone_space, HDS.impulse, HDS.hit_type); } switch (GameID()) { case GAME_SINGLE: { float hit_power = HitArtefactsOnBelt(HDS.damage(), HDS.hit_type); if (GodMode())//psActorFlags.test(AF_GODMODE)) { HDS.power = 0.0f; // inherited::Hit(0.f,dir,who,element,position_in_bone_space,impulse, hit_type); inherited::Hit(&HDS); return; } else { //inherited::Hit (hit_power,dir,who,element,position_in_bone_space, impulse, hit_type); HDS.power = hit_power; inherited::Hit(&HDS); }; } break; default: { m_bWasBackStabbed = false; if (HDS.hit_type == ALife::eHitTypeWound_2 && Check_for_BackStab_Bone(HDS.bone())) { // convert impulse into local coordinate system Fmatrix mInvXForm; mInvXForm.invert (XFORM()); Fvector vLocalDir; mInvXForm.transform_dir (vLocalDir,HDS.dir); vLocalDir.invert (); Fvector a = {0,0,1}; float res = a.dotproduct(vLocalDir); if (res < -0.707) { game_PlayerState* ps = Game().GetPlayerByGameID(ID()); if (!ps || !ps->testFlag(GAME_PLAYER_FLAG_INVINCIBLE)) m_bWasBackStabbed = true; } }; float hit_power = 0; if (m_bWasBackStabbed) hit_power = 100000; else hit_power = HitArtefactsOnBelt(HDS.damage(), HDS.hit_type); HDS.power = hit_power; inherited::Hit (&HDS); //inherited::Hit (hit_power,dir,who,element,position_in_bone_space, impulse, hit_type, 0.0f); } break; } }
void CIKLimbsController::Calculate( ) { update_blend( m_legs_blend ); Fmatrix &obj = m_object->XFORM( ); #ifdef DEBUG if( ph_dbg_draw_mask1.test( phDbgDrawIKSHiftObject ) ) _object_shift.dbg_draw( obj, _pose_extrapolation, Fvector().set( 0,2.5f,0)); #endif SCalculateData cd[max_size]; xr_vector<CIKLimb>::iterator i, b = _bone_chains.begin(), e = _bone_chains.end(); for( i = b ; e != i; ++i ) { cd[i-b] = SCalculateData ( *i, obj ); LimbCalculate( cd[i-b] ); } IKinematics *K = m_object->Visual()->dcast_PKinematics( ); u16 root = K->LL_GetBoneRoot( ) ; CBoneInstance &root_bi = K->LL_GetBoneInstance(root); BOOL sv_root_cb_ovwr = root_bi.callback_overwrite(); BoneCallback sv_root_cb = root_bi.callback(); root_bi.set_callback( root_bi.callback_type(), 0, root_bi.callback_param(), TRUE ); if( ik_shift_object )//&& ! m_object->animation_movement_controlled( ) { ShiftObject( cd ); } const u16 sz =(u16)_bone_chains.size(); for(u16 j = 0; sz > j; ++j ) cd[j].m_limb->SetGoal( cd[j] ); for(u16 j = 0; sz > j; ++j ) { cd[j].m_limb->SolveBones( cd[j] ); #ifdef DEBUG if( ph_dbg_draw_mask1.test( phDbgDrawIKPredict ) ) { //IKinematics *K = m_object->Visual()->dcast_PKinematics( ); u16 ref_bone_id = cd[j].m_limb->dbg_ref_bone_id(); Fmatrix m =Fmatrix().mul( obj, K->LL_GetTransform( ref_bone_id ) ); Fvector toe; cd[j].m_limb->dbg_ik_foot().ToePosition( toe ); m.transform_tiny( toe ); DBG_DrawLine( toe, Fvector().add( toe, Fvector().set( 0, -_object_shift.shift(), 0 ) ), D3DCOLOR_XRGB( 255, 0, 0 ) ); } #endif } ObjectShift( 0, cd ); root_bi.set_callback( root_bi.callback_type(), sv_root_cb, root_bi.callback_param(), sv_root_cb_ovwr ); }
bool CPhysicObject::get_door_vectors ( Fvector& closed, Fvector& open ) const { VERIFY(Visual()); IKinematics *K = Visual()->dcast_PKinematics(); VERIFY(K); u16 door_bone = K->LL_BoneID("door"); if( door_bone==BI_NONE ) return false; const CBoneData &bd = K->LL_GetData( door_bone ); const SBoneShape &shape = bd.shape; if( shape.type != SBoneShape::stBox ) return false; if( shape.flags.test( SBoneShape::sfNoPhysics ) ) return false; Fmatrix start_bone_pos; K->Bone_GetAnimPos( start_bone_pos, door_bone, u8(-1), true ); Fmatrix start_pos = Fmatrix().mul_43( XFORM(), start_bone_pos ); const Fobb &box = shape.box; Fvector center_pos; start_pos.transform_tiny( center_pos, box.m_translate ); Fvector door_dir; start_pos.transform_dir(door_dir, box.m_rotate.i ); Fvector door_dir_local = box.m_rotate.i ; //Fvector door_dir_bone; start_bone_pos.transform_dir(door_dir_bone, box.m_rotate.i ); const Fvector det_vector = Fvector().sub( center_pos, start_pos.c ); if( door_dir.dotproduct( det_vector ) < 0.f ) { door_dir.invert(); door_dir_local.invert(); //door_dir_bone.invert(); } const SJointIKData &joint = bd.IK_data; if( joint.type != jtJoint ) return false; const Fvector2& limits = joint.limits[1].limit; //if( limits.y < EPS ) //limits.y - limits.x < EPS // return false; if( M_PI - limits.y < EPS && M_PI + limits.x < EPS ) return false; Fmatrix to_hi = Fmatrix().rotateY( -limits.x ); to_hi.transform_dir( open, door_dir_local ); Fmatrix to_lo = Fmatrix().rotateY( -limits.y ); to_lo.transform_dir( closed, door_dir_local ); start_pos.transform_dir(open); start_pos.transform_dir(closed); //DBG_OpenCashedDraw( ); #ifdef DEBUG if(dbg_draw_doors) { DBG_DrawMatrix( Fidentity, 10.0f ); DBG_DrawMatrix( XFORM(), .5f, 100 ); DBG_DrawMatrix( start_pos, 0.2f,100 ); const Fvector pos = start_pos.c.add( Fvector().set(0,0.2f,0) ); const Fvector pos1 = start_pos.c.add( Fvector().set(0,0.3f,0) ); DBG_DrawLine( pos, Fvector( ).add( pos, open ), D3DCOLOR_XRGB( 0, 255, 0 ) ); DBG_DrawLine( pos, Fvector( ).add( pos, closed ), D3DCOLOR_XRGB( 255, 0, 0 ) ); DBG_DrawLine( pos1, Fvector( ).add( pos1, det_vector ), D3DCOLOR_XRGB( 255, 255, 0 ) ); } #endif //DBG_ClosedCashedDraw( 50000000 ); return true; }
void character_hit_animation_controller::PlayHitMotion( const Fvector &dir, const Fvector &bone_pos, u16 bi, CEntityAlive &ea )const { IRenderVisual *pV = ea.Visual( ); IKinematicsAnimated* CA = smart_cast<IKinematicsAnimated*>( pV ); IKinematics* K = smart_cast<IKinematics*>( pV ); //play_cycle(CA,all_shift_down,1,block_times[6],1) ; if( !( K->LL_BoneCount( ) > bi ) ) return; Fvector dr = dir; Fmatrix m; GetBaseMatrix( m, ea ); #ifdef DEBUG if( ph_dbg_draw_mask1.test( phDbgHitAnims ) ) { DBG_OpenCashedDraw(); DBG_DrawLine( m.c, Fvector( ).sub( m.c, Fvector( ).mul( dir, 1.5 ) ), D3DCOLOR_XRGB( 255, 0, 255 ) ); DBG_ClosedCashedDraw( 1000 ); } #endif m.invert( ); m.transform_dir( dr ); // Fvector hit_point; K->LL_GetTransform( bi ).transform_tiny( hit_point, bone_pos ); ea.XFORM( ).transform_tiny( hit_point ); m.transform_tiny( hit_point ); Fvector torqu; torqu.crossproduct( dr, hit_point ); hit_point.x = 0; float rotational_ammount = hit_point.magnitude( ) * g_params.power_factor * g_params.rotational_power_factor;//_abs(torqu.x) if( torqu.x < 0 ) play_cycle( CA, hit_downr, 3, block_blends[7], 1 ) ; else play_cycle( CA, hit_downl, 3, block_blends[6], 1 ) ; if( !IsEffected( bi, *K ) ) return; if( torqu.x<0 ) play_cycle( CA, turn_right, 2, block_blends[4], rotational_ammount ) ; else play_cycle( CA, turn_left, 2, block_blends[5], rotational_ammount ) ; //CA->LL_SetChannelFactor(3,rotational_ammount); dr.x = 0; dr.normalize_safe(); dr.mul(g_params.power_factor); if( dr.y > g_params.side_sensitivity_threshold ) play_cycle( CA, rthit_motion, 2, block_blends[0], _abs( dr.y ) ) ; else if( dr.y < -g_params.side_sensitivity_threshold ) play_cycle( CA, lthit_motion, 2, block_blends[1], _abs( dr.y ) ) ; if( dr.z<0.f ) play_cycle( CA, fvhit_motion, 2, block_blends[2], _abs(dr.z) ) ; else play_cycle( CA, bkhit_motion, 2, block_blends[3], _abs( dr.z ) ) ; CA->LL_SetChannelFactor( 2, g_params.anim_channel_factor ); }
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; }