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; } }

IC void q_scalem(Fmatrix &m, float v) { Fquaternion q; q.set(m); q_scale(q,v); m.rotation(q); }

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 CParticleGroup::SItem::StartRelatedChild(CParticleEffect* emitter, LPCSTR eff_name, PAPI::Particle& m) { CParticleEffect*C = static_cast<CParticleEffect*>(RImplementation.model_CreatePE(eff_name)); Fmatrix M; M.identity(); Fvector vel; vel.sub(m.pos,m.posB); vel.div(fDT_STEP); if (emitter->m_RT_Flags.is(CParticleEffect::flRT_XFORM)){ M.set (emitter->m_XFORM); M.transform_dir (vel); }; Fvector p; M.transform_tiny (p,m.pos); M.c.set (p); C->Play (); C->UpdateParent (M,vel,FALSE); _children_related.push_back(C); }

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 CActor::RenderText (LPCSTR Text, Fvector dpos, float* pdup, u32 color) { if (!g_Alive()) return; CBoneInstance& BI = smart_cast<CKinematics*>(Visual())->LL_GetBoneInstance(u16(m_head)); Fmatrix M; smart_cast<CKinematics*>(Visual())->CalculateBones (); M.mul (XFORM(),BI.mTransform); //------------------------------------------------ Fvector v0, v1; v0.set(M.c); v1.set(M.c); Fvector T = Device.vCameraTop; v1.add(T); Fvector v0r, v1r; Device.mFullTransform.transform(v0r,v0); Device.mFullTransform.transform(v1r,v1); float size = v1r.distance_to(v0r); CGameFont* pFont = HUD().Font().pFontArial14; if (!pFont) return; // float OldFontSize = pFont->GetHeight (); float delta_up = 0.0f; if (size < mid_size) delta_up = upsize; else delta_up = upsize*(mid_size/size); dpos.y += delta_up; if (size > mid_size) size = mid_size; // float NewFontSize = size/mid_size * fontsize; //------------------------------------------------ M.c.y += dpos.y; Fvector4 v_res; Device.mFullTransform.transform(v_res,M.c); if (v_res.z < 0 || v_res.w < 0) return; if (v_res.x < -1.f || v_res.x > 1.f || v_res.y<-1.f || v_res.y>1.f) return; float x = (1.f + v_res.x)/2.f * (Device.dwWidth); float y = (1.f - v_res.y)/2.f * (Device.dwHeight); pFont->SetAligment (CGameFont::alCenter); pFont->SetColor (color); // pFont->SetHeight (NewFontSize); pFont->Out (x,y,Text); //------------------------------------------------- // pFont->SetHeight(OldFontSize); *pdup = delta_up; };

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 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; } }

void CActor::MoveActor (Fvector NewPos, Fvector NewDir) { Fmatrix M = XFORM(); M.translate(NewPos); r_model_yaw = NewDir.y; r_torso.yaw = NewDir.y; r_torso.pitch = -NewDir.x; unaffected_r_torso.yaw = r_torso.yaw; unaffected_r_torso.pitch= r_torso.pitch; unaffected_r_torso.roll = 0;//r_torso.roll; r_torso_tgt_roll = 0; cam_Active()->Set (-unaffected_r_torso.yaw,unaffected_r_torso.pitch,unaffected_r_torso.roll); ForceTransform(M); m_bInInterpolation = false; }

void CArtefact::UpdateXForm() { if (Device.dwFrame!=dwXF_Frame) { dwXF_Frame = Device.dwFrame; if (0==H_Parent()) return; // Get access to entity and its visual CEntityAlive* E = smart_cast<CEntityAlive*>(H_Parent()); if(!E) return ; const CInventoryOwner *parent = smart_cast<const CInventoryOwner*>(E); if (parent && parent->use_simplified_visual()) return; VERIFY (E); IKinematics* V = smart_cast<IKinematics*> (E->Visual()); VERIFY (V); if(CAttachableItem::enabled()) return; // Get matrices int boneL = -1, boneR = -1, boneR2 = -1; E->g_WeaponBones (boneL,boneR,boneR2); if (boneR == -1) return; boneL = boneR2; V->CalculateBones (); Fmatrix& mL = V->LL_GetTransform(u16(boneL)); Fmatrix& mR = V->LL_GetTransform(u16(boneR)); // Calculate Fmatrix mRes; Fvector R,D,N; D.sub (mL.c,mR.c); D.normalize_safe(); R.crossproduct (mR.j,D); R.normalize_safe(); N.crossproduct (D,R); N.normalize_safe(); mRes.set (R,N,D,mR.c); mRes.mulA_43 (E->XFORM()); // UpdatePosition (mRes); XFORM().mul (mRes,offset()); } }

void CSpaceRestrictionShape::fill_shape (const CCF_Shape::shape_def &shape) { Fvector start,dest; switch (shape.type) { case 0 : { start.sub (Fvector().set(shape.data.sphere.P),Fvector().set(shape.data.sphere.R,0.f,shape.data.sphere.R)); dest.add (Fvector().set(shape.data.sphere.P),Fvector().set(shape.data.sphere.R,0.f,shape.data.sphere.R)); start.add (m_restrictor->Position()); dest.add (m_restrictor->Position()); break; } case 1 : { Fvector points[8] = { Fvector().set(-.5f,-.5f,-.5f), Fvector().set(-.5f,-.5f,+.5f), Fvector().set(-.5f,+.5f,-.5f), Fvector().set(-.5f,+.5f,+.5f), Fvector().set(+.5f,-.5f,-.5f), Fvector().set(+.5f,-.5f,+.5f), Fvector().set(+.5f,+.5f,-.5f), Fvector().set(+.5f,+.5f,+.5f) }; start = Fvector().set(flt_max,flt_max,flt_max); dest = Fvector().set(flt_min,flt_min,flt_min); Fmatrix Q; Q.mul_43 (m_restrictor->XFORM(),shape.data.box); Fvector temp; for (int i=0; i<8; ++i) { Q.transform_tiny (temp,points[i]); start.x = _min(start.x,temp.x); start.y = _min(start.y,temp.y); start.z = _min(start.z,temp.z); dest.x = _max(dest.x,temp.x); dest.y = _max(dest.y,temp.y); dest.z = _max(dest.z,temp.z); } break; } default : NODEFAULT; } ai().level_graph().iterate_vertices(start,dest,CBorderMergePredicate(this)); #ifdef DEBUG ai().level_graph().iterate_vertices(start,dest,CShapeTestPredicate(this)); #endif }

void game_cl_Deathmatch::PlayParticleEffect(LPCSTR EffName, Fvector& pos) { if (!EffName) return; // вычислить позицию и направленность партикла Fmatrix M; M.translate(pos); // CParticlesPlayer::MakeXFORM(pObj,0,Fvector().set(0.f,1.f,0.f),Fvector().set(0.f,0.f,0.f),pos); // установить particles CParticlesObject* ps = NULL; ps = CParticlesObject::Create(EffName,TRUE); ps->UpdateParent(M,Fvector().set(0.f,0.f,0.f)); GamePersistent().ps_needtoplay.push_back(ps); }

CParticlesObject* CBaseMonster::PlayParticles(const shared_str& name, const Fvector &position, const Fvector &dir, BOOL auto_remove, BOOL xformed) { CParticlesObject* ps = CParticlesObject::Create(name.c_str(),auto_remove); // вычислить позицию и направленность партикла Fmatrix matrix; matrix.identity (); matrix.k.set (dir); Fvector::generate_orthonormal_basis_normalized(matrix.k,matrix.j,matrix.i); matrix.translate_over (position); (xformed) ? ps->SetXFORM (matrix) : ps->UpdateParent(matrix,zero_vel); ps->Play (false); return ps; }

void CLevelDebug::draw_object_info() { // handle all of the objects for (OBJECT_INFO_MAP_IT it = m_objects_info.begin(); it != m_objects_info.end(); ++it) { // если объект невалидный - удалить информацию if (!it->first || it->first->getDestroy()) { for (CLASS_INFO_MAP_IT it_class = it->second.begin(); it_class != it->second.end(); ++it_class){ xr_delete(it_class->second); } m_objects_info.erase(it); break; } Fmatrix res; res.mul (Device.mFullTransform,it->first->XFORM()); Fvector4 v_res; float delta_height = 0.f; // handle all of the classes for (CLASS_INFO_MAP_IT class_it = it->second.begin(); class_it != it->second.end(); ++class_it) { // get up on 2 meters res.transform(v_res, class_it->second->get_shift_pos()); // check if the object in sight if (v_res.z < 0 || v_res.w < 0) continue; if (v_res.x < -1.f || v_res.x > 1.f || v_res.y<-1.f || v_res.y>1.f) continue; // get real (x,y) float x = (1.f + v_res.x)/2.f * (Device.dwWidth); float y = (1.f - v_res.y)/2.f * (Device.dwHeight) - delta_height; float start_y = y; // handle all of the text inside class class_it->second->draw_info(x,y); delta_height = start_y - y; } } }

void CGroupObject::RotateParent(Fvector& axis, float angle ) { inherited::RotateParent(axis,angle); Fmatrix Ginv; Ginv.set (FITransformRP); UpdateTransform (true); for (ObjectIt it=m_Objects.begin(); it!=m_Objects.end(); it++){ Fmatrix O,On; O.mul (Ginv,(*it)->FTransformRP); On.mul (FTransform,O); Fvector xyz; On.getXYZ (xyz); (*it)->NumSetRotation(xyz); (*it)->NumSetPosition(On.c); // (*it)->PivotRotateParent(m_old,FTransform,axis,angle); } }

void CDrawUtilities::DrawPlane (const Fvector& center, const Fvector2& scale, const Fvector& rotate, u32 clr_s, u32 clr_w, BOOL bCull, BOOL bSolid, BOOL bWire) { Fmatrix M; M.setHPB (rotate.y,rotate.x,rotate.z); M.translate_over(center); // fill VB _VertexStream* Stream = &RCache.Vertex; u32 vBase; if (bSolid){ DU_DRAW_SH(dxRenderDeviceRender::Instance().m_SelectionShader); FVF::L* pv = (FVF::L*)Stream->Lock(5,vs_L->vb_stride,vBase); pv->set (-scale.x, 0, -scale.y, clr_s); M.transform_tiny(pv->p); pv++; pv->set (-scale.x, 0, +scale.y, clr_s); M.transform_tiny(pv->p); pv++; pv->set (+scale.x, 0, +scale.y, clr_s); M.transform_tiny(pv->p); pv++; pv->set (+scale.x, 0, -scale.y, clr_s); M.transform_tiny(pv->p); pv++; pv->set (*(pv-4)); Stream->Unlock(5,vs_L->vb_stride); if (!bCull) DU_DRAW_RS(D3DRS_CULLMODE,D3DCULL_NONE); DU_DRAW_DP (D3DPT_TRIANGLEFAN,vs_L,vBase,2); if (!bCull) DU_DRAW_RS(D3DRS_CULLMODE,D3DCULL_CCW); } if (bWire){ DU_DRAW_SH(dxRenderDeviceRender::Instance().m_WireShader); FVF::L* pv = (FVF::L*)Stream->Lock(5,vs_L->vb_stride,vBase); pv->set (-scale.x, 0, -scale.y, clr_w); M.transform_tiny(pv->p); pv++; pv->set (+scale.x, 0, -scale.y, clr_w); M.transform_tiny(pv->p); pv++; pv->set (+scale.x, 0, +scale.y, clr_w); M.transform_tiny(pv->p); pv++; pv->set (-scale.x, 0, +scale.y, clr_w); M.transform_tiny(pv->p); pv++; pv->set (*(pv-4)); Stream->Unlock(5,vs_L->vb_stride); DU_DRAW_DP (D3DPT_LINESTRIP,vs_L,vBase,4); } }

void CDrawUtilities::DrawPlane (const Fvector& p, const Fvector& n, const Fvector2& scale, u32 clr_s, u32 clr_w, BOOL bCull, BOOL bSolid, BOOL bWire) { if (n.square_magnitude()<EPS_S) return; // build final rotation / translation Fvector L_dir,L_up=n,L_right; L_dir.set (0,0,1); if (_abs(L_up.dotproduct(L_dir))>.99f) L_dir.set(1,0,0); L_right.crossproduct(L_up,L_dir); L_right.normalize (); L_dir.crossproduct (L_right,L_up); L_dir.normalize (); Fmatrix mR; mR.i = L_right; mR._14 = 0; mR.j = L_up; mR._24 = 0; mR.k = L_dir; mR._34 = 0; mR.c = p; mR._44 = 1; // fill VB _VertexStream* Stream = &RCache.Vertex; u32 vBase; if (bSolid){ DU_DRAW_SH(dxRenderDeviceRender::Instance().m_SelectionShader); FVF::L* pv = (FVF::L*)Stream->Lock(5,vs_L->vb_stride,vBase); pv->set (-scale.x, 0, -scale.y, clr_s); mR.transform_tiny(pv->p); pv++; pv->set (-scale.x, 0, +scale.y, clr_s); mR.transform_tiny(pv->p); pv++; pv->set (+scale.x, 0, +scale.y, clr_s); mR.transform_tiny(pv->p); pv++; pv->set (+scale.x, 0, -scale.y, clr_s); mR.transform_tiny(pv->p); pv++; pv->set (*(pv-4)); Stream->Unlock(5,vs_L->vb_stride); if (!bCull) DU_DRAW_RS(D3DRS_CULLMODE,D3DCULL_NONE); DU_DRAW_DP (D3DPT_TRIANGLEFAN,vs_L,vBase,2); if (!bCull) DU_DRAW_RS(D3DRS_CULLMODE,D3DCULL_CCW); } if (bWire){ DU_DRAW_SH(dxRenderDeviceRender::Instance().m_WireShader); FVF::L* pv = (FVF::L*)Stream->Lock(5,vs_L->vb_stride,vBase); pv->set (-scale.x, 0, -scale.y, clr_w); mR.transform_tiny(pv->p); pv++; pv->set (+scale.x, 0, -scale.y, clr_w); mR.transform_tiny(pv->p); pv++; pv->set (+scale.x, 0, +scale.y, clr_w); mR.transform_tiny(pv->p); pv++; pv->set (-scale.x, 0, +scale.y, clr_w); mR.transform_tiny(pv->p); pv++; pv->set (*(pv-4)); Stream->Unlock(5,vs_L->vb_stride); DU_DRAW_DP (D3DPT_LINESTRIP,vs_L,vBase,4); } }

void CPhysicObject::PH_A_CrPr () { if (m_just_after_spawn) { VERIFY(Visual()); IKinematics *K = Visual()->dcast_PKinematics(); VERIFY( K ); if (!PPhysicsShell()) { return; } if(!PPhysicsShell()->isFullActive()) { K->CalculateBones_Invalidate(); K->CalculateBones(TRUE); } PPhysicsShell()->GetGlobalTransformDynamic(&XFORM()); K->CalculateBones_Invalidate(); K->CalculateBones(TRUE); #if 0 Fbox bb= BoundingBox (); DBG_OpenCashedDraw (); Fvector c,r,p; bb.get_CD(c,r ); XFORM().transform_tiny(p,c); DBG_DrawAABB( p, r,D3DCOLOR_XRGB(255, 0, 0)); //PPhysicsShell()->XFORM().transform_tiny(c); Fmatrix mm; PPhysicsShell()->GetGlobalTransformDynamic(&mm); mm.transform_tiny(p,c); DBG_DrawAABB( p, r,D3DCOLOR_XRGB(0, 255, 0)); DBG_ClosedCashedDraw (50000); #endif spatial_move(); m_just_after_spawn = false; VERIFY(!OnServer()); PPhysicsShell()->get_ElementByStoreOrder(0)->Fix(); PPhysicsShell()->SetIgnoreStatic (); //PPhysicsShell()->SetIgnoreDynamic (); //PPhysicsShell()->DisableCollision(); } //CalculateInterpolationParams() };

void CIKLimb::BonesCallback1 (CBoneInstance* B) { SCalculateData* D=(SCalculateData*)B->Callback_Param; CIKLimb* L=D->m_limb ; float const *x=D->m_angles ; Fmatrix bm;//B->mTransform ; bm.rotateY(x[3]) ; CKinematics *K=D->m_K; CBoneData& BD=K->LL_GetData(L->m_bones[1]); Fmatrix cmp_save;cmp_save.set(B->mTransform) ; B->mTransform.mul_43(K->LL_GetTransform(BD.GetParentID()),BD.bind_transform); Fmatrix dd;dd.mul_43(Fmatrix().invert(B->mTransform),cmp_save); Fvector a;dd.getXYZ(a); B->mTransform.mulB_43(bm) ; Fmatrix cmp_savei;cmp_savei.invert(cmp_save); Fmatrix dif;dif.mul_43(cmp_savei,B->mTransform); }

void CCar::cb_Steer (CBoneInstance* B) { VERIFY2(fsimilar(DET(B->mTransform),1.f,DET_CHECK_EPS),"Bones receive returns 0 matrix"); CCar* C = static_cast<CCar*>(B->callback_param()); Fmatrix m; m.rotateZ(C->m_steer_angle); B->mTransform.mulB_43 (m); #ifdef DEBUG if( !fsimilar(DET(B->mTransform),1.f,DET_CHECK_EPS) ){ Log("RotatingZ angle=",C->m_steer_angle); VERIFY2(0,"Bones callback returns BAD!!! matrix"); } #endif }

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); } }

bool CActor::g_LadderOrient() { Fvector leader_norm; character_physics_support()->movement()->GroundNormal(leader_norm); if(_abs(leader_norm.y)>M_SQRT1_2) return false; //leader_norm.y=0.f; float mag=leader_norm.magnitude(); if(mag<EPS_L) return false; leader_norm.div(mag); leader_norm.invert(); Fmatrix M;M.set(Fidentity); M.k.set(leader_norm); M.j.set(0.f,1.f,0.f); generate_orthonormal_basis1(M.k,M.j,M.i); M.i.invert(); //M.j.invert(); //Fquaternion q1,q2,q3; //q1.set(XFORM()); //q2.set(M); //q3.slerp(q1,q2,dt); //Fvector angles1,angles2,angles3; //XFORM().getHPB(angles1.x,angles1.y,angles1.z); //M.getHPB(angles2.x,angles2.y,angles2.z); ////angle_lerp(angles3.x,angles1.x,angles2.x,dt); ////angle_lerp(angles3.y,angles1.y,angles2.y,dt); ////angle_lerp(angles3.z,angles1.z,angles2.z,dt); //angles3.lerp(angles1,angles2,dt); ////angle_lerp(angles3.y,angles1.y,angles2.y,dt); ////angle_lerp(angles3.z,angles1.z,angles2.z,dt); //angle_lerp(angles3.x,angles1.x,angles2.x,dt); //XFORM().setHPB(angles3.x,angles3.y,angles3.z); Fvector position; position.set(Position()); //XFORM().rotation(q3); VERIFY2(_valid(M),"Invalide matrix in g_LadderOrient"); XFORM().set(M); VERIFY2(_valid(position),"Invalide position in g_LadderOrient"); Position().set(position); VERIFY(_valid(XFORM())); return true; }

void CAI_Trader::LookAtActor(CBoneInstance *B) { Fvector dir; dir.sub(Level().CurrentEntity()->Position(),Position()); float yaw,pitch; dir.getHP(yaw, pitch); float h,p,b; XFORM().getHPB(h,p,b); float cur_yaw = h; float dy = _abs(angle_normalize_signed(yaw - cur_yaw)); if (angle_normalize_signed(yaw - cur_yaw) > 0) dy *= -1.f; Fmatrix M; M.setHPB (0.f, -dy, 0.f); B->mTransform.mulB_43(M); }

void CSpaceRestrictorWrapper::fill_shape (const CShapeData::shape_def &shape) { Fvector start,dest; switch (shape.type) { case 0 : { start.sub (Fvector().set(shape.data.sphere.P),Fvector().set(shape.data.sphere.R,0.f,shape.data.sphere.R)); dest.add (Fvector().set(shape.data.sphere.P),Fvector().set(shape.data.sphere.R,0.f,shape.data.sphere.R)); start.add (object().o_Position); dest.add (object().o_Position); break; } case 1 : { Fvector points[8] = { Fvector().set(-.5f,-.5f,-.5f), Fvector().set(-.5f,-.5f,+.5f), Fvector().set(-.5f,+.5f,-.5f), Fvector().set(-.5f,+.5f,+.5f), Fvector().set(+.5f,-.5f,-.5f), Fvector().set(+.5f,-.5f,+.5f), Fvector().set(+.5f,+.5f,-.5f), Fvector().set(+.5f,+.5f,+.5f) }; start = Fvector().set(flt_max,flt_max,flt_max); dest = Fvector().set(flt_min,flt_min,flt_min); Fmatrix Q; Q.mul_43 (m_xform,shape.data.box); Fvector temp; for (int i=0; i<8; ++i) { Q.transform_tiny (temp,points[i]); start.x = _min(start.x,temp.x); start.y = _min(start.y,temp.y); start.z = _min(start.z,temp.z); dest.x = _max(dest.x,temp.x); dest.y = _max(dest.y,temp.y); dest.z = _max(dest.z,temp.z); } break; } default : NODEFAULT; } level_graph().iterate_vertices (start,dest,border_merge_predicate(this,m_level_graph)); }

void CShootingObject::UpdateFlameParticles () { if(0==m_sFlameParticlesCurrent.size()) return; if(!m_pFlameParticles) return; Fmatrix pos; pos.set (get_ParticlesXFORM() ); pos.c.set (get_CurrentFirePoint() ); m_pFlameParticles->SetXFORM (pos); if(!m_pFlameParticles->IsLooped() && !m_pFlameParticles->IsPlaying() && !m_pFlameParticles->PSI_alive()) { m_pFlameParticles->Stop(); CParticlesObject::Destroy(m_pFlameParticles); } }

void CActor::RenderIndicator (Fvector dpos, float r1, float r2, ref_shader IndShader) { if (!g_Alive()) return; u32 dwOffset = 0,dwCount = 0; FVF::LIT* pv_start = (FVF::LIT*)RCache.Vertex.Lock(4,hFriendlyIndicator->vb_stride,dwOffset); FVF::LIT* pv = pv_start; // base rect CBoneInstance& BI = smart_cast<CKinematics*>(Visual())->LL_GetBoneInstance(u16(m_head)); Fmatrix M; smart_cast<CKinematics*>(Visual())->CalculateBones (); M.mul (XFORM(),BI.mTransform); Fvector pos = M.c; pos.add(dpos); const Fvector& T = Device.vCameraTop; const Fvector& R = Device.vCameraRight; Fvector Vr, Vt; Vr.x = R.x*r1; Vr.y = R.y*r1; Vr.z = R.z*r1; Vt.x = T.x*r2; Vt.y = T.y*r2; Vt.z = T.z*r2; Fvector a,b,c,d; a.sub (Vt,Vr); b.add (Vt,Vr); c.invert (a); d.invert (b); pv->set (d.x+pos.x,d.y+pos.y,d.z+pos.z, 0xffffffff, 0.f,1.f); pv++; pv->set (a.x+pos.x,a.y+pos.y,a.z+pos.z, 0xffffffff, 0.f,0.f); pv++; pv->set (c.x+pos.x,c.y+pos.y,c.z+pos.z, 0xffffffff, 1.f,1.f); pv++; pv->set (b.x+pos.x,b.y+pos.y,b.z+pos.z, 0xffffffff, 1.f,0.f); pv++; // render dwCount = u32(pv-pv_start); RCache.Vertex.Unlock (dwCount,hFriendlyIndicator->vb_stride); RCache.set_xform_world (Fidentity); RCache.set_Shader (IndShader); RCache.set_Geometry (hFriendlyIndicator); RCache.Render (D3DPT_TRIANGLESTRIP,dwOffset,0, dwCount, 0, 2); };

bool __fastcall TUI_ControlShapeAdd::AfterAppendCallback(TShiftState Shift, CCustomObject* obj) { CEditShape* shape = dynamic_cast<CEditShape*>(obj); R_ASSERT(shape); TfraShape* F = (TfraShape*)parent_tool->pFrame; if (F->ebTypeSphere->Down){ Fsphere S; S.identity(); shape->add_sphere(S); if (!Shift.Contains(ssAlt)) F->ebTypeSphere->Down = false; return true; }else if (F->ebTypeBox->Down){ Fmatrix M; M.identity(); shape->add_box(M); if (!Shift.Contains(ssAlt)) F->ebTypeBox->Down = false; return true; }else{ ELog.DlgMsg(mtInformation,"Select shape type at first."); } return false; }

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 }

void CBone::ShapeRotate(const Fvector& _amount) { Fvector amount=_amount; Fmatrix _IT;_IT.invert(_LTransform()); if (Tools->GetSettings(etfCSParent)) _IT.transform_dir(amount); switch (shape.type){ case SBoneShape::stBox:{ Fmatrix R; R.setXYZi(amount.x,amount.y,amount.z); shape.box.transform(shape.box,R); }break; case SBoneShape::stSphere: break; case SBoneShape::stCylinder:{ Fmatrix R; R.setXYZi(amount.x,amount.y,amount.z); R.transform_dir(shape.cylinder.m_direction); }break; } }

void CPhysicsShellHolder::correct_spawn_pos() { VERIFY (PPhysicsShell()); Fvector size; Fvector c; get_box (PPhysicsShell(),XFORM(),size,c); CPHActivationShape activation_shape; activation_shape.Create (c,size,this); activation_shape.set_rotation (XFORM()); PPhysicsShell()->DisableCollision (); activation_shape.Activate (size,1,1.f,M_PI/8.f); //// VERIFY (valid_pos(activation_shape.Position(),phBoundaries)); // if (!valid_pos(activation_shape.Position(),phBoundaries)) { // CPHActivationShape activation_shape; // activation_shape.Create (c,size,this); // activation_shape.set_rotation (XFORM()); // activation_shape.Activate (size,1,1.f,M_PI/8.f); //// VERIFY (valid_pos(activation_shape.Position(),phBoundaries)); // } PPhysicsShell()->EnableCollision (); Fvector ap = activation_shape.Position(); #ifdef DEBUG if (!valid_pos(ap,phBoundaries)) { Msg("not valid position %f,%f,%f",ap.x,ap.y,ap.z); Msg("size %f,%f,%f",size.x,size.y,size.z); Msg("Object: %s",Name()); Msg("Visual: %s",*(cNameVisual())); Msg("Object pos %f,%f,%f",Position().x,Position().y,Position().z); } #endif // DEBUG VERIFY (valid_pos(activation_shape.Position(),phBoundaries)); Fmatrix trans; trans.identity (); trans.c.sub (ap,c); PPhysicsShell()->TransformPosition (trans); PPhysicsShell()->GetGlobalTransformDynamic(&XFORM()); activation_shape.Destroy (); }