//void CEntity::Hit (float perc, Fvector &dir, CObject* who, s16 element,Fvector position_in_object_space, float impulse, ALife::EHitType hit_type) void CEntity::Hit (SHit* pHDS) { // if (bDebug) Log("Process HIT: ", *cName()); // *** process hit calculations // Calc impulse Fvector vLocalDir; float m = pHDS->dir.magnitude(); VERIFY (m>EPS); // convert impulse into local coordinate system Fmatrix mInvXForm; mInvXForm.invert (XFORM()); mInvXForm.transform_dir (vLocalDir,pHDS->dir); vLocalDir.invert (); // hit impulse if(pHDS->impulse) HitImpulse (pHDS->impulse,pHDS->dir,vLocalDir); // @@@: WT // Calc amount (correct only on local player) float lost_health = CalcCondition(pHDS->damage()); // Signal hit if(BI_NONE!=pHDS->bone()) HitSignal(lost_health,vLocalDir,pHDS->who,pHDS->boneID); // If Local() - perform some logic if (Local() && !g_Alive() && !AlreadyDie() && (m_killer_id == ALife::_OBJECT_ID(-1))) { KillEntity (pHDS->whoID); } //must be last!!! @slipch inherited::Hit(pHDS); }
//---------------------------------------------------- // Skeletal motion //---------------------------------------------------- static void CalculateAnim(CBone* bone, CSMotion* motion, Fmatrix& parent) { Flags8 flags; flags.zero(); if (motion) flags = motion->GetMotionFlags(bone->SelfID); Fmatrix& M = bone->_MTransform(); Fmatrix& L = bone->_LTransform(); const Fvector& r = bone->_Rotate(); if (flags.is(st_BoneMotion::flWorldOrient)){ M.setXYZi (r.x,r.y,r.z); M.c.set (bone->_Offset()); L.mul (parent,M); L.i.set (M.i); L.j.set (M.j); L.k.set (M.k); Fmatrix LI; LI.invert(parent); M.mulA_43 (LI); }else{ M.setXYZi (r.x,r.y,r.z); M.c.set (bone->_Offset()); L.mul (parent,M); } bone->_RenderTransform().mul_43(bone->_LTransform(),bone->_RITransform()); // Calculate children for (BoneIt b_it=bone->children.begin(); b_it!=bone->children.end(); b_it++) CalculateAnim (*b_it,motion,bone->_LTransform()); }
void CWeaponStatMgun::UpdateBarrelDir() { IKinematics* K = smart_cast<IKinematics*>(Visual()); m_fire_bone_xform = K->LL_GetTransform(m_fire_bone); m_fire_bone_xform.mulA_43 (XFORM()); m_fire_pos.set (0,0,0); m_fire_bone_xform.transform_tiny(m_fire_pos); m_fire_dir.set (0,0,1); m_fire_bone_xform.transform_dir (m_fire_dir); m_allow_fire = true; Fmatrix XFi; XFi.invert (XFORM()); Fvector dep; XFi.transform_dir (dep,m_destEnemyDir); {// x angle m_i_bind_x_xform.transform_dir(dep); dep.normalize(); m_tgt_x_rot = angle_normalize_signed(m_bind_x_rot-dep.getP()); float sv_x = m_tgt_x_rot; clamp (m_tgt_x_rot,-m_lim_x_rot.y,-m_lim_x_rot.x); if (!fsimilar(sv_x,m_tgt_x_rot,EPS_L)) m_allow_fire=FALSE; } {// y angle m_i_bind_y_xform.transform_dir(dep); dep.normalize(); m_tgt_y_rot = angle_normalize_signed(m_bind_y_rot-dep.getH()); float sv_y = m_tgt_y_rot; clamp (m_tgt_y_rot,-m_lim_y_rot.y,-m_lim_y_rot.x); if (!fsimilar(sv_y,m_tgt_y_rot,EPS_L)) m_allow_fire=FALSE; } m_cur_x_rot = angle_inertion_var(m_cur_x_rot,m_tgt_x_rot,0.5f,3.5f,PI_DIV_6,Device.fTimeDelta); m_cur_y_rot = angle_inertion_var(m_cur_y_rot,m_tgt_y_rot,0.5f,3.5f,PI_DIV_6,Device.fTimeDelta); }
void CIKLimb::Calculate(CKinematics* K,const Fmatrix &obj) { SCalculateData cd(this,K,obj); m_prev_state_anim=true; Collide(&cd); if(cd.m_tri) { Matrix m ; GoalMatrix (m,&cd) ; #ifdef DEBUG if(m_limb.SetGoal(m,ph_dbg_draw_mask.test(phDbgIKLimits))) #else if(m_limb.SetGoal(m,TRUE)) #endif { Fmatrix hip; CBoneData& BD=K->LL_GetData(m_bones[0]); hip.mul_43(K->LL_GetTransform(BD.GetParentID()),BD.bind_transform); hip.invert(); float x[7]; Fvector pos; pos.set(K->LL_GetTransform(m_bones[1]).c); hip.transform_tiny(pos); xm2im.transform_tiny(pos); if(m_limb.SolveByPos(cast_fp(pos),x)) { cd.m_angles=x; CalculateBones(&cd); m_prev_state_anim=false; } } } }
void CGameObject::dbg_DrawSkeleton () { CCF_Skeleton* Skeleton = smart_cast<CCF_Skeleton*>(collidable.model); if (!Skeleton) return; Skeleton->_dbg_refresh(); const CCF_Skeleton::ElementVec& Elements = Skeleton->_GetElements(); for (CCF_Skeleton::ElementVec::const_iterator I=Elements.begin(); I!=Elements.end(); I++){ if (!I->valid()) continue; switch (I->type){ case SBoneShape::stBox:{ Fmatrix M; M.invert (I->b_IM); Fvector h_size = I->b_hsize; Level().debug_renderer().draw_obb (M, h_size, color_rgba(0, 255, 0, 255)); }break; case SBoneShape::stCylinder:{ Fmatrix M; M.c.set (I->c_cylinder.m_center); M.k.set (I->c_cylinder.m_direction); Fvector h_size; h_size.set (I->c_cylinder.m_radius,I->c_cylinder.m_radius,I->c_cylinder.m_height*0.5f); Fvector::generate_orthonormal_basis(M.k,M.j,M.i); Level().debug_renderer().draw_obb (M, h_size, color_rgba(0, 127, 255, 255)); }break; case SBoneShape::stSphere:{ Fmatrix l_ball; l_ball.scale (I->s_sphere.R, I->s_sphere.R, I->s_sphere.R); l_ball.translate_add(I->s_sphere.P); Level().debug_renderer().draw_ellipse(l_ball, color_rgba(0, 255, 0, 255)); }break; }; }; }
door::door ( CPhysicObject* object ) : m_object ( *object ), m_state ( door_state_open ), m_previous_state ( door_state_open ), m_target_state ( door_state_open ), m_registered_position ( object->Position() ), m_locked ( false ) { VERIFY ( valid(m_state) ); VERIFY ( valid(m_target_state) ); VERIFY ( valid(m_previous_state) ); R_ASSERT ( m_object.get_door_vectors( m_closed_vector, m_open_vector ) ); Fmatrix invert; invert.invert ( m_object.XFORM() ); invert.transform_dir ( m_open_vector ); invert.transform_dir ( m_closed_vector ); float const length = 1.1f; m_open_vector.mul ( length ); m_closed_vector.mul ( length ); m_object.spatial.type |= STYPE_VISIBLEFORAI; }
bool CEditShape::RayPick(float& distance, const Fvector& start, const Fvector& direction, SRayPickInfo* pinf) { float dist = distance; for (ShapeIt it=shapes.begin(); it!=shapes.end(); it++){ switch (it->type){ case cfSphere:{ Fvector S,D; Fmatrix M; M.invert (FTransformR); M.transform_dir (D,direction); FITransform.transform_tiny(S,start); Fsphere& T = it->data.sphere; float bk_r = T.R; // T.R = FScale.x; T.intersect (S,D,dist); if (dist<=0.f) dist = distance; T.R = bk_r; }break; case cfBox:{ Fbox box; box.identity (); Fmatrix BI; BI.invert (it->data.box); Fvector S,D,S1,D1,P; FITransform.transform_tiny (S,start); FITransform.transform_dir (D,direction); BI.transform_tiny (S1,S); BI.transform_dir (D1,D); Fbox::ERP_Result rp_res = box.Pick2(S1,D1,P); if (rp_res==Fbox::rpOriginOutside){ it->data.box.transform_tiny (P); FTransform.transform_tiny (P); P.sub (start); dist = P.magnitude(); } }break; } } if (dist<distance){ distance = dist; return true; } return false; }
void occRasterizer::on_dbg_render() { #if DEBUG if( !ps_r2_ls_flags_ext.is(R_FLAGEXT_HOM_DEPTH_DRAW) ) { dbg_HOM_draw_initialized = false; return; } for ( int i = 0; i< occ_dim_0; ++i) { for ( int j = 0; j< occ_dim_0; ++j) { if( bDebug ) { Fvector quad,left_top,right_bottom,box_center,box_r; quad.set( (float)j-occ_dim_0/2.f, -((float)i-occ_dim_0/2.f), (float)bufDepth_0[i][j]/occQ_s32); Device.mProject; float z = -Device.mProject._43/(float)(Device.mProject._33-quad.z); left_top.set ( quad.x*z/Device.mProject._11/(occ_dim_0/2.f), quad.y*z/Device.mProject._22/(occ_dim_0/2.f), z); right_bottom.set ( (quad.x+1)*z/Device.mProject._11/(occ_dim_0/2.f), (quad.y+1)*z/Device.mProject._22/(occ_dim_0/2.f), z); box_center.set ((right_bottom.x + left_top.x)/2, (right_bottom.y + left_top.y)/2, z); box_r = right_bottom; box_r.sub(box_center); Fmatrix inv; inv.invert(Device.mView); inv.transform( box_center ); inv.transform_dir( box_r ); pixel_box& tmp = dbg_pixel_boxes[ i*occ_dim_0+j]; tmp.center = box_center; tmp.radius = box_r; tmp.z = quad.z; dbg_HOM_draw_initialized = true; } if( !dbg_HOM_draw_initialized ) return; pixel_box& tmp = dbg_pixel_boxes[ i*occ_dim_0+j]; Fmatrix Transform; Transform.identity(); Transform.translate(tmp.center); // draw wire Device.SetNearer(TRUE); RCache.set_Shader (dxRenderDeviceRender::Instance().m_SelectionShader); RCache.dbg_DrawOBB( Transform, tmp.radius, D3DCOLOR_XRGB(u32(255*pow(tmp.z,20.f)),u32(255*(1-pow(tmp.z,20.f))),0) ); Device.SetNearer(FALSE); } } #endif }
void PHDynamicData::InterpolateTransform(Fmatrix &transform){ //DMXPStoFMX(dBodyGetRotation(body), // dBodyGetPosition(body),BoneTransform); body_interpolation.InterpolateRotation(transform); body_interpolation.InterpolatePosition(transform.c); Fmatrix zero; zero.set (ZeroTransform); zero.invert (); //BoneTransform.mulB(zero); transform.mulB_43 (zero); }
void CGroupObject::NumSetPosition(const Fvector& pos) { inherited::NumSetPosition(pos); Fmatrix prev; prev.invert(FTransform); UpdateTransform(true); for (ObjectIt it=m_Objects.begin(); it!=m_Objects.end(); it++){ Fvector v=(*it)->PPosition; prev.transform_tiny(v); FTransform.transform_tiny(v); (*it)->PPosition=v; } }
void PHDynamicData::CalculateData() { DMXPStoFMX(dBodyGetRotation(body), dBodyGetPosition(body),BoneTransform); Fmatrix zero; zero.set(ZeroTransform); zero.invert(); BoneTransform.mulB_43(zero); for(unsigned int i=0;i<numOfChilds;++i){ Childs[i].CalculateR_N_PosOfChilds(body); } }
void CCameraManager::Dump() { Fmatrix mInvCamera; Fvector _R,_U,_T,_P; mInvCamera.invert(Device.mView); _R.set( mInvCamera._11, mInvCamera._12, mInvCamera._13 ); _U.set( mInvCamera._21, mInvCamera._22, mInvCamera._23 ); _T.set( mInvCamera._31, mInvCamera._32, mInvCamera._33 ); _P.set( mInvCamera._41, mInvCamera._42, mInvCamera._43 ); Log("CCameraManager::Dump::vPosition = ",_P); Log("CCameraManager::Dump::vDirection = ",_T); Log("CCameraManager::Dump::vNormal = ",_U); Log("CCameraManager::Dump::vRight = ",_R); }
bool CKinematics:: PickBone (const Fmatrix &parent_xform, Fvector& normal, float& dist, const Fvector& start, const Fvector& dir, u16 bone_id) { Fvector S,D;//normal = {0,0,0} // transform ray from world to model Fmatrix P; P.invert (parent_xform); P.transform_tiny (S,start); P.transform_dir (D,dir); for (u32 i=0; i<children.size(); i++) if (LL_GetChild(i)->PickBone(normal,dist,S,D,bone_id)) { parent_xform.transform_dir (normal); return true; } return false; }
void CGroupObject::NumSetScale(const Fvector& scale) { Fvector old_s = PScale; inherited::NumSetScale(scale); Fmatrix prev; prev.invert(FTransform); UpdateTransform(true); Fvector ds; ds.sub(FScale,old_s); for (ObjectIt it=m_Objects.begin(); it!=m_Objects.end(); it++){ Fvector s=(*it)->PScale; s.add(ds); (*it)->PScale=s; Fvector v=(*it)->PPosition; prev.transform_tiny(v); FTransform.transform_tiny(v); (*it)->PPosition=v; } }
void CGroupObject::Move(Fvector& amount) { Fvector old_r=FRotation; inherited::Move(amount); Fmatrix prev; prev.invert(FTransform); UpdateTransform(true); Fvector dr; dr.sub(FRotation,old_r); for (ObjectIt it=m_Objects.begin(); it!=m_Objects.end(); it++){ Fvector r=(*it)->PRotation; r.add(dr); (*it)->PRotation=r; Fvector v=(*it)->PPosition; prev.transform_tiny(v); FTransform.transform_tiny(v); (*it)->PPosition=v; } }
void CHelicopter::UpdateMGunDir() { IKinematics* K = smart_cast<IKinematics*>(Visual()); m_fire_bone_xform = K->LL_GetTransform(m_fire_bone); m_fire_bone_xform.mulA_43 (XFORM()); m_fire_pos.set (0,0,0); m_fire_bone_xform.transform_tiny(m_fire_pos); m_fire_dir.set (0,0,1); m_fire_bone_xform.transform_dir(m_fire_dir); m_fire_dir.sub (m_enemy.destEnemyPos,m_fire_pos).normalize_safe(); m_left_rocket_bone_xform = K->LL_GetTransform(m_left_rocket_bone); m_left_rocket_bone_xform.mulA_43 (XFORM()); m_left_rocket_bone_xform.c.y += 1.0f; //.fake m_right_rocket_bone_xform = K->LL_GetTransform(m_right_rocket_bone); m_right_rocket_bone_xform.mulA_43 (XFORM()); m_right_rocket_bone_xform.c.y += 1.0f; //.fake m_allow_fire = TRUE; Fmatrix XFi; XFi.invert (XFORM()); Fvector dep; XFi.transform_tiny (dep,m_enemy.destEnemyPos); {// x angle Fvector A_; A_.sub(dep,m_bind_x); m_i_bind_x_xform.transform_dir(A_); A_.normalize(); m_tgt_rot.x = angle_normalize_signed(m_bind_rot.x-A_.getP()); float sv_x = m_tgt_rot.x; clamp (m_tgt_rot.x,-m_lim_x_rot.y,-m_lim_x_rot.x); if (!fsimilar(sv_x,m_tgt_rot.x,EPS_L)) m_allow_fire=FALSE; } {// y angle Fvector A_; A_.sub(dep,m_bind_y); m_i_bind_y_xform.transform_dir(A_); A_.normalize(); m_tgt_rot.y = angle_normalize_signed(m_bind_rot.y-A_.getH()); float sv_y = m_tgt_rot.y; clamp (m_tgt_rot.y,-m_lim_y_rot.y,-m_lim_y_rot.x); if (!fsimilar(sv_y,m_tgt_rot.y,EPS_L)) m_allow_fire=FALSE; } if ((angle_difference(m_cur_rot.x,m_tgt_rot.x)>deg2rad(m_barrel_dir_tolerance))|| (angle_difference(m_cur_rot.y,m_tgt_rot.y)>deg2rad(m_barrel_dir_tolerance))) m_allow_fire=FALSE; }
void CPHShell::Activate(const Fmatrix &m0,float dt01,const Fmatrix &m2,bool disable){ if(isActive())return; activate(disable); // ELEMENT_I i; mXFORM.set(m0); //for(i=elements.begin();elements.end() != i;++i){ // (*i)->Activate(m0,dt01, m2, disable); //} { ELEMENT_I i=elements.begin(),e=elements.end(); for(;i!=e;++i)(*i)->Activate(mXFORM,disable); } { JOINT_I i=joints.begin(),e=joints.end(); for(;i!=e;++i) (*i)->Activate(); } Fmatrix m; { Fmatrix old_m = mXFORM;//+GetGlobalTransformDynamic update mXFORM; GetGlobalTransformDynamic (&m); mXFORM = old_m; } m.invert();m.mulA_43 (mXFORM); TransformPosition(m); if(PKinematics()) { SetCallbacks( ); } //bActive=true; //bActivating=true; m_flags.set(flActive,TRUE); m_flags.set(flActivating,TRUE); spatial_register(); /////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// //mXFORM.set(m0); //Activate(disable); Fvector lin_vel; lin_vel.sub(m2.c,m0.c); set_LinearVel(lin_vel); }
void CGroupObject::NumSetRotation(const Fvector& rot) { Fvector old_r; FTransformR.getXYZ(old_r); inherited::NumSetRotation(rot); Fmatrix prev; prev.invert(FTransform); UpdateTransform(true); Fvector dr; dr.sub(FRotation,old_r); for (ObjectIt it=m_Objects.begin(); it!=m_Objects.end(); it++){ Fvector r=(*it)->PRotation; r.add(dr); (*it)->PRotation=r; Fvector v=(*it)->PPosition; prev.transform_tiny(v); FTransform.transform_tiny(v); (*it)->PPosition=v; } }
bool CBone::Pick(float& dist, const Fvector& S, const Fvector& D, const Fmatrix& parent) { Fvector start, dir; Fmatrix M; M.mul_43(parent,_LTransform()); M.invert(); M.transform_tiny(start,S); M.transform_dir(dir,D); switch (shape.type){ case SBoneShape::stBox: return shape.box.intersect (start,dir,dist); case SBoneShape::stSphere: return shape.sphere.intersect (start,dir,dist); case SBoneShape::stCylinder:return shape.cylinder.intersect (start,dir,dist); default: Fsphere S; S.P.set(0,0,0); S.R=0.025f; return S.intersect(start,dir,dist); } }
void CCarWeapon::UpdateBarrelDir() { CKinematics* K = smart_cast<CKinematics*>(m_object->Visual()); m_fire_bone_xform = K->LL_GetTransform(m_fire_bone); m_fire_bone_xform.mulA_43(m_object->XFORM()); m_fire_pos.set(0,0,0); m_fire_bone_xform.transform_tiny(m_fire_pos); m_fire_dir.set(0,0,1); m_fire_bone_xform.transform_dir(m_fire_dir); m_fire_norm.set(0,1,0); m_fire_bone_xform.transform_dir(m_fire_norm); m_allow_fire = true; Fmatrix XFi; XFi.invert (m_object->XFORM()); Fvector dep; XFi.transform_dir (dep,m_destEnemyDir); {// x angle m_i_bind_x_xform.transform_dir(dep); dep.normalize(); m_tgt_x_rot = angle_normalize_signed(m_bind_x_rot-dep.getP()); clamp (m_tgt_x_rot,-m_lim_x_rot.y,-m_lim_x_rot.x); } {// y angle m_i_bind_y_xform.transform_dir(dep); dep.normalize(); m_tgt_y_rot = angle_normalize_signed(m_bind_y_rot-dep.getH()); clamp (m_tgt_y_rot,-m_lim_y_rot.y,-m_lim_y_rot.x); } m_cur_x_rot = angle_inertion_var(m_cur_x_rot,m_tgt_x_rot,m_min_gun_speed,m_max_gun_speed,PI,Device.fTimeDelta); m_cur_y_rot = angle_inertion_var(m_cur_y_rot,m_tgt_y_rot,m_min_gun_speed,m_max_gun_speed,PI,Device.fTimeDelta); static float dir_eps = deg2rad(5.0f); if( !fsimilar(m_cur_x_rot,m_tgt_x_rot,dir_eps)|| !fsimilar(m_cur_y_rot,m_tgt_y_rot,dir_eps)) m_allow_fire=FALSE; #if (0) if(Device.dwFrame%200==0){ Msg("m_cur_x_rot=[%f]",m_cur_x_rot); Msg("m_cur_y_rot=[%f]",m_cur_y_rot); } #endif }
BOOL CDemoPlay::ProcessCam(SCamEffectorInfo& info) { // skeep a few frames before counting if (Device.dwPrecacheFrame) return TRUE; if (stat_started) { //g_SASH.DisplayFrame(Device.fTimeGlobal); } else { //g_SASH.StartBenchmark(); stat_Start(); } // Per-frame statistics { stat_table.push_back (stat_Timer_frame.GetElapsed_sec()); stat_Timer_frame.Start (); } // Process motion if (m_pMotion) { Fvector R; Fmatrix mRotate; m_pMotion->_Evaluate (m_MParam->Frame(),info.p,R); m_MParam->Update (Device.fTimeDelta,1.f,true); fLifeTime -= Device.fTimeDelta; if (m_MParam->bWrapped) { stat_Stop(); stat_Start(); } mRotate.setXYZi (R.x,R.y,R.z); info.d.set (mRotate.k); info.n.set (mRotate.j); } else { if (seq.empty()) { g_pGameLevel->Cameras().RemoveCamEffector(cefDemo); return TRUE; } fStartTime += Device.fTimeDelta; float ip; float p = fStartTime/fSpeed; float t = modff(p, &ip); int frame = iFloor(ip); VERIFY (t>=0); if (frame>=m_count) { dwCyclesLeft -- ; if (0==dwCyclesLeft) return FALSE; fStartTime = 0 ; // just continue // stat_Stop (); // stat_Start (); } int f1=frame; FIX(f1); int f2=f1+1; FIX(f2); int f3=f2+1; FIX(f3); int f4=f3+1; FIX(f4); Fmatrix *m1,*m2,*m3,*m4; Fvector v[4]; m1 = (Fmatrix *) &seq[f1]; m2 = (Fmatrix *) &seq[f2]; m3 = (Fmatrix *) &seq[f3]; m4 = (Fmatrix *) &seq[f4]; for (int i=0; i<4; i++) { v[0].x = m1->m[i][0]; v[0].y = m1->m[i][1]; v[0].z = m1->m[i][2]; v[1].x = m2->m[i][0]; v[1].y = m2->m[i][1]; v[1].z = m2->m[i][2]; v[2].x = m3->m[i][0]; v[2].y = m3->m[i][1]; v[2].z = m3->m[i][2]; v[3].x = m4->m[i][0]; v[3].y = m4->m[i][1]; v[3].z = m4->m[i][2]; spline1 ( t, &(v[0]), (Fvector *) &(Device.mView.m[i][0]) ); } Fmatrix mInvCamera; mInvCamera.invert(Device.mView); info.n.set( mInvCamera._21, mInvCamera._22, mInvCamera._23 ); info.d.set( mInvCamera._31, mInvCamera._32, mInvCamera._33 ); info.p.set( mInvCamera._41, mInvCamera._42, mInvCamera._43 ); fLifeTime-=Device.fTimeDelta; } return TRUE; }
void CIKLimb::GoalMatrix(Matrix &M,SCalculateData* cd) { VERIFY(cd->m_tri&&cd->m_tri_hight!=-dInfinity); const Fmatrix &obj=*cd->m_obj; CDB::TRI *tri=cd->m_tri; CKinematics *K=cd->m_K; Fvector* pVerts = Level().ObjectSpace.GetStaticVerts(); Fvector normal; normal.mknormal (pVerts[tri->verts[0]],pVerts[tri->verts[1]],pVerts[tri->verts[2]]); VERIFY(!fis_zero(normal.magnitude())); Fmatrix iobj;iobj.invert(obj);iobj.transform_dir(normal); Fmatrix xm;xm.set(K->LL_GetTransform(m_bones[2])); //Fvector dbg; //dbg.set(Fvector().mul(normal,normal.y*tri_hight // -normal.dotproduct(xm.i)*m_toe_position.x // -normal.dotproduct(xm.j)*m_toe_position.y // -normal.dotproduct(xm.k)*m_toe_position.z-m_toe_position.x // )); normal.invert(); Fvector ax;ax.crossproduct(normal,xm.i); float s=ax.magnitude(); if(!fis_zero(s)) { ax.mul(1.f/s); xm.mulA_43(Fmatrix().rotation(ax,asinf(-s))); } Fvector otri;iobj.transform_tiny(otri,pVerts[tri->verts[0]]); float tp=normal.dotproduct(otri); Fvector add; add.set(Fvector().mul(normal,-m_toe_position.x+tp-xm.c.dotproduct(normal))); xm.c.add(add); Fmatrix H; CBoneData& bd=K->LL_GetData(m_bones[0]); H.set(bd.bind_transform); H.mulA_43(K->LL_GetTransform(bd.GetParentID())); H.c.set(K->LL_GetTransform(m_bones[0]).c); #ifdef DEBUG if(ph_dbg_draw_mask.test(phDbgIKAnimGoalOnly)) xm.set(K->LL_GetTransform(m_bones[2])); if(ph_dbg_draw_mask.test(phDbgDrawIKGoal)) { Fmatrix DBGG; DBGG.mul_43(obj,xm); DBG_DrawMatrix(DBGG,0.2f); DBGG.mul_43(obj,H); DBG_DrawMatrix(DBGG,0.2f); } #endif H.invert(); Fmatrix G; G.mul_43(H,xm); XM2IM(G,M); }
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 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 ); }
void CKinematics::AddWallmark(const Fmatrix* parent_xform, const Fvector3& start, const Fvector3& dir, ref_shader shader, float size) { Fvector S,D,normal = {0,0,0}; // transform ray from world to model Fmatrix P; P.invert (*parent_xform); P.transform_tiny (S,start); P.transform_dir (D,dir); // find pick point float dist = flt_max; BOOL picked = FALSE; DEFINE_VECTOR (Fobb,OBBVec,OBBVecIt); OBBVec cache_obb; cache_obb.resize (LL_BoneCount()); for (u16 k=0; k<LL_BoneCount(); k++){ CBoneData& BD = LL_GetData(k); if (LL_GetBoneVisible(k)&&!BD.shape.flags.is(SBoneShape::sfNoPickable)){ Fobb& obb = cache_obb[k]; obb.transform (BD.obb,LL_GetBoneInstance(k).mTransform); if (CDB::TestRayOBB(S,D, obb)) for (u32 i=0; i<children.size(); i++) if (LL_GetChild(i)->PickBone(normal,dist,S,D,k)) picked=TRUE; } } if (!picked) return; // calculate contact point Fvector cp; cp.mad (S,D,dist); // collect collide boxes Fsphere test_sphere; test_sphere.set (cp,size); U16Vec test_bones; test_bones.reserve (LL_BoneCount()); for (k=0; k<LL_BoneCount(); k++){ CBoneData& BD = LL_GetData(k); if (LL_GetBoneVisible(k)&&!BD.shape.flags.is(SBoneShape::sfNoPickable)){ Fobb& obb = cache_obb[k]; if (CDB::TestSphereOBB(test_sphere, obb)) test_bones.push_back(k); } } // find similar wm for (u32 wm_idx=0; wm_idx<wallmarks.size(); wm_idx++){ intrusive_ptr<CSkeletonWallmark>& wm = wallmarks[wm_idx]; if (wm->Similar(shader,cp,0.02f)){ if (wm_idx<wallmarks.size()-1) wm = wallmarks.back(); wallmarks.pop_back(); break; } } // ok. allocate wallmark intrusive_ptr<CSkeletonWallmark> wm = xr_new<CSkeletonWallmark>(this,parent_xform,shader,cp,Device.fTimeGlobal); wm->m_LocalBounds.set (cp,size*2.f); wm->XFORM()->transform_tiny (wm->m_Bounds.P,cp); wm->m_Bounds.R = wm->m_Bounds.R; Fvector tmp; tmp.invert (D); normal.add(tmp).normalize (); // build UV projection matrix Fmatrix mView,mRot; BuildMatrix (mView,1/(0.9f*size),normal,cp); mRot.rotateZ (::Random.randF(deg2rad(-20.f),deg2rad(20.f))); mView.mulA_43 (mRot); // fill vertices for (u32 i=0; i<children.size(); i++){ CSkeletonX* S = LL_GetChild(i); for (U16It b_it=test_bones.begin(); b_it!=test_bones.end(); b_it++) S->FillVertices (mView,*wm,normal,size,*b_it); } wallmarks.push_back (wm); }