diff --git a/Sources/CryGame C++/Solution1/CryGame/Hand.cpp b/Sources/CryGame C++/Solution1/CryGame/Hand.cpp index 79b6008..2eed814 100644 --- a/Sources/CryGame C++/Solution1/CryGame/Hand.cpp +++ b/Sources/CryGame C++/Solution1/CryGame/Hand.cpp @@ -40,6 +40,9 @@ void CHand::Init() m_pCharacter->StartAnimation(defaultIdle,ccap); m_pCharacter->Update(); m_pCharacter->ForceUpdate(); + m_pCharacter->EnableLastIdleAnimationRestart(0); + HideOtherHand(); + m_pCharacter->SetFlags(m_pCharacter->GetFlags() | CS_FLAG_DRAW_NEAR); } } @@ -52,21 +55,78 @@ void CHand::Reset() } } -void CHand::Update(const Vec3& pos, const Ang3& angles) +void CHand::Update(const Matrix34& controllerTransform) { + if (!m_pCharacter) + return; + + m_pCharacter->Update(); + m_pCharacter->ForceUpdate(); + m_pCharacter->ForceReskin(); + ICryBone* bone = m_pCharacter->GetBoneByName(GetHandBone()); + Matrix34 gripTransform = ((Matrix34)GetTransposed44(bone->GetAbsoluteMatrix())) * Matrix34::CreateTranslationMat(Vec3(0, -0.1f, -0.018f)); + + Matrix34 handTransform = controllerTransform * gripTransform.GetInverted(); + m_pos = handTransform.GetTranslation(); + m_ang = ToAnglesDeg(handTransform); } -void CHand::Render(const SRendParams& _RendParams) +void CHand::Render(const SRendParams& _RendParams, const Vec3& basePos) { if (!m_pCharacter) return; + HideUpperArms(GetHandBone()); + HideUpperArms(GetOtherHandBone()); + if (m_pCharacter->GetFlags()&CS_FLAG_DRAW_MODEL) { SRendParams RendParams = _RendParams; RendParams.vPos = m_pos; RendParams.vAngles = m_ang; + m_pCharacter->Draw(RendParams, basePos); + } +} + +void CHand::HideUpperArms(const char* boneName) +{ + ICryBone* bone = m_pCharacter->GetBoneByName(boneName); - m_pCharacter->Draw(RendParams, m_pos); + Vec3 pos = bone->GetAbsoluteMatrix().GetTranslationOLD(); + + // scale the parent bones to zero to effectively hide those parts of the arms - we only want to see the hands in VR + // this will create some weird cut off at the hands, but it is the best we can do in code, without editing all the models + bone = bone->GetParent(); + for (int i = 0; i < 3 && bone != nullptr; ++i) + { + Matrix44& m = const_cast(bone->GetAbsoluteMatrix()); + m = Matrix44(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); + m.SetTranslationOLD(pos); + bone = bone->GetParent(); } } + +void CHand::HideOtherHand() +{ + ICryBone* bone = m_pCharacter->GetBoneByName(GetOtherHandBone()); + if (!bone || !bone->GetParent()) + return; + bone = bone->GetParent()->GetParent(); + if (!bone) + return; + + Matrix44 zeroScale(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); + bone->DoNotCalculateBoneRelativeMatrix(true); + Matrix44& boneMatrix = const_cast(bone->GetRelativeMatrix()); + boneMatrix = zeroScale; +} + +const char* CHand::GetHandBone() const +{ + return m_handSide == 1 ? "Bone03" : "Bone19"; +} + +const char* CHand::GetOtherHandBone() const +{ + return m_handSide == 1 ? "Bone19" : "Bone03"; +} diff --git a/Sources/CryGame C++/Solution1/CryGame/Hand.h b/Sources/CryGame C++/Solution1/CryGame/Hand.h index 06ff4ba..9bfa7a2 100644 --- a/Sources/CryGame C++/Solution1/CryGame/Hand.h +++ b/Sources/CryGame C++/Solution1/CryGame/Hand.h @@ -9,10 +9,16 @@ class CHand void Init(); void Reset(); - void Update(const Vec3& pos, const Ang3& angles); - void Render(const SRendParams& _RendParams); + void Update(const Matrix34& controllerTransform); + void Render(const SRendParams& _RendParams, const Vec3& basePos); private: + void HideUpperArms(const char* boneName); + void HideOtherHand(); + + const char* GetHandBone() const; + const char* GetOtherHandBone() const; + int m_handSide; ICryCharInstance* m_pCharacter; CPlayer* m_pPlayer; diff --git a/Sources/CryGame C++/Solution1/CryGame/XPlayer.cpp b/Sources/CryGame C++/Solution1/CryGame/XPlayer.cpp index ceefd91..9fa63b8 100644 --- a/Sources/CryGame C++/Solution1/CryGame/XPlayer.cpp +++ b/Sources/CryGame C++/Solution1/CryGame/XPlayer.cpp @@ -401,6 +401,15 @@ CPlayer::~CPlayer() delete m_pDynLight; m_pDynLight=NULL; } + + for (int i = 0; i < 2; ++i) + { + if (m_handModel[i]) + { + delete m_handModel[i]; + m_handModel[i] = nullptr; + } + } } ////////////////////////////////////////////////////////////////////// @@ -458,6 +467,12 @@ bool CPlayer::Init() GoStand(); + for (int i = 0; i < 2; ++i) + { + m_handModel[i] = new CHand(i, this); + m_handModel[i]->Init(); + } + return true; } @@ -4987,6 +5002,25 @@ void CPlayer::OnDraw(const SRendParams & _RendParams) // if nRecursionLevel is not 0 - use only 3tp person view ( for reflections ) int nRecursionLevel = (int)m_pGame->GetSystem()->GetIRenderer()->EF_Query(EFQ_RecurseLevel) - 1; + + if (m_bFirstPerson && !nRecursionLevel && !GetVehicle() && !m_pMountedWeapon) + { + bool hideOffHand = GetSelectedWeapon() && (m_twoHandWeaponMode || m_stats.reloading); + if (!hideOffHand) + { + Matrix34 worldControllerTransform = GetWorldControllerTransform(m_offHand) * Matrix33::CreateRotationY(gf_PI_DIV_2); + m_handModel[m_offHand]->Update(worldControllerTransform); + m_handModel[m_offHand]->Render(_RendParams, m_pEntity->GetPos()); + } + + if (!GetSelectedWeapon()) + { + Matrix34 worldControllerTransform = GetWorldControllerTransform(m_mainHand) * Matrix33::CreateRotationY(-gf_PI_DIV_2); + m_handModel[m_mainHand]->Update(worldControllerTransform); + m_handModel[m_mainHand]->Render(_RendParams, m_pEntity->GetPos()); + } + } + // draw first person weapon if(m_bFirstPerson && !nRecursionLevel && m_stats.drawfpweapon && m_nSelectedWeaponID != -1) { diff --git a/Sources/CryGame C++/Solution1/CryGame/XPlayer.h b/Sources/CryGame C++/Solution1/CryGame/XPlayer.h index 995878f..faff6a0 100644 --- a/Sources/CryGame C++/Solution1/CryGame/XPlayer.h +++ b/Sources/CryGame C++/Solution1/CryGame/XPlayer.h @@ -28,6 +28,7 @@ #include "ScriptObjectStream.h" #include "ScriptObjectVector.h" #include "FireType.h" +#include "Hand.h" #include "SynchedRandomSeed.h" // CSynchedRandomSeed ////////////////////////////////////////////////////////////////////// @@ -1169,6 +1170,9 @@ enum eInVehiclestate Vec3 m_swingDir; Vec3 m_prevFireAngles; + + // visible bare hands + CHand* m_handModel[2] = { nullptr }; }; #endif // __GAME_PLAYER_H__