diff --git a/src/Layers/xrRender/FTreeVisual.cpp b/src/Layers/xrRender/FTreeVisual.cpp index ea4f4481ff2..984658239e6 100644 --- a/src/Layers/xrRender/FTreeVisual.cpp +++ b/src/Layers/xrRender/FTreeVisual.cpp @@ -114,7 +114,7 @@ struct FTreeVisual_setup Fvector4 wave; Fvector4 wind; - FTreeVisual_setup(): dwFrame(0), scale(0) {} + FTreeVisual_setup(): dwFrame(0), scale(M_MIN_SCALE) {} void calculate() { diff --git a/src/Layers/xrRender/SkeletonCustom.cpp b/src/Layers/xrRender/SkeletonCustom.cpp index c33af6aa5bf..b68279abadc 100644 --- a/src/Layers/xrRender/SkeletonCustom.cpp +++ b/src/Layers/xrRender/SkeletonCustom.cpp @@ -489,17 +489,21 @@ void CKinematics::Release() void CKinematics::LL_SetBoneVisible(u16 bone_id, BOOL val, BOOL bRecursive) { - VERIFY(bone_id < LL_BoneCount()); - u64 mask = u64(1) << bone_id; - visimask.set(mask, val); - if (!visimask.is(mask)) - { - bone_instances[bone_id].mTransform.scale(0.f, 0.f, 0.f); - } - else - { - CalculateBones_Invalidate(); - } + VERIFY(bone_id < LL_BoneCount()); + if (bone_id >= LL_BoneCount()) + return; + u64 mask = u64(1) << bone_id; + visimask.set(mask, val); + if (!visimask.is(mask)) + { + bone_instances[bone_id].mTransform.scale(M_MIN_SCALE, M_MIN_SCALE, M_MIN_SCALE); + if (LL_GetData(bone_id).GetParentID() < LL_BoneCount() && LL_GetData(bone_id).GetParentID() != BI_NONE) + bone_instances[bone_id].mTransform.c = LL_GetBoneInstance(LL_GetData(bone_id).GetParentID()).mTransform.c; + } + else + { + CalculateBones_Invalidate(); + } bone_instances[bone_id].mRenderTransform.mul_43( bone_instances[bone_id].mTransform, (*bones)[bone_id]->m2b_transform); if (bRecursive) @@ -525,7 +529,7 @@ void CKinematics::LL_SetBonesVisible(u64 mask) { Fmatrix& A = bone_instances[b].mTransform; Fmatrix& B = bone_instances[b].mRenderTransform; - A.scale(0.f, 0.f, 0.f); + A.scale(M_MIN_SCALE, M_MIN_SCALE, M_MIN_SCALE); B.mul_43(A, (*bones)[b]->m2b_transform); } } diff --git a/src/Layers/xrRender/r__dsgraph_build.cpp b/src/Layers/xrRender/r__dsgraph_build.cpp index bc226a5b609..0c0b6e00f90 100644 --- a/src/Layers/xrRender/r__dsgraph_build.cpp +++ b/src/Layers/xrRender/r__dsgraph_build.cpp @@ -815,6 +815,7 @@ void R_dsgraph_structure::build_subspace() IGameObject* O = g_pGameLevel->CurrentViewEntity(); if (O) { + O->RenderFirstPersonBody(context_id, O); CROS_impl* R = (CROS_impl*)O->ROS(); if (R) R->update(O); diff --git a/src/Layers/xrRender_R2/r2.cpp b/src/Layers/xrRender_R2/r2.cpp index 196cb2f0015..d08fca0819b 100644 --- a/src/Layers/xrRender_R2/r2.cpp +++ b/src/Layers/xrRender_R2/r2.cpp @@ -8,6 +8,7 @@ #include "Layers/xrRender/SkeletonCustom.h" #include "Layers/xrRender/dxWallMarkArray.h" #include "Layers/xrRender/dxUIShader.h" +#include "xrEngine/xr_object.h" #if defined(USE_DX11) #include "Layers/xrRenderDX11/3DFluid/dx113DFluidManager.h" diff --git a/src/xrCore/_matrix.h b/src/xrCore/_matrix.h index f487f2f3ce2..0df3baa8d47 100644 --- a/src/xrCore/_matrix.h +++ b/src/xrCore/_matrix.h @@ -532,4 +532,6 @@ inline bool _valid(const Fmatrix& m) extern XRCORE_API Fmatrix Fidentity; +constexpr float M_MIN_SCALE = 0.01f; + #endif diff --git a/src/xrEngine/CameraManager.cpp b/src/xrEngine/CameraManager.cpp index b0b9990b833..cf21a99713f 100644 --- a/src/xrEngine/CameraManager.cpp +++ b/src/xrEngine/CameraManager.cpp @@ -312,7 +312,7 @@ void CCameraManager::UpdatePPEffectors() pp_affected.validate("after applying pp"); } -void CCameraManager::ApplyDevice() +void CCameraManager::ApplyDevice(float override_fnear) { ZoneScoped; // Device params @@ -326,7 +326,7 @@ void CCameraManager::ApplyDevice() // projection Device.fFOV = m_cam_info.fFov; Device.fASPECT = m_cam_info.fAspect; - Device.mProject.build_projection(deg2rad(m_cam_info.fFov), m_cam_info.fAspect, m_cam_info.fNear, m_cam_info.fFar); + Device.mProject.build_projection(deg2rad(m_cam_info.fFov), m_cam_info.fAspect, !fis_zero(override_fnear) ? override_fnear : m_cam_info.fNear, m_cam_info.fFar); // Apply offset required for Nvidia Ansel Device.mProject._31 = -m_cam_info.offsetX; diff --git a/src/xrEngine/CameraManager.h b/src/xrEngine/CameraManager.h index b8c9f126bd5..5ddb689e940 100644 --- a/src/xrEngine/CameraManager.h +++ b/src/xrEngine/CameraManager.h @@ -57,7 +57,7 @@ class ENGINE_API CCameraManager float fFAR_Dest, u32 flags); void UpdateFromCamera(const CCameraBase* C); - void ApplyDevice(); + void ApplyDevice(float override_fnear = 0.0f); static void ResetPP(); CCameraManager(bool bApplyOnUpdate); diff --git a/src/xrEngine/xr_object.h b/src/xrEngine/xr_object.h index 578c9103a2d..502d946adf9 100644 --- a/src/xrEngine/xr_object.h +++ b/src/xrEngine/xr_object.h @@ -308,6 +308,7 @@ class XR_NOVTABLE IGameObject virtual void ShouldProcessOnRender(bool should_process) = 0; virtual void OnRender() = 0; #endif + virtual void RenderFirstPersonBody(u32 context_id, IRenderable* root) {}; virtual void reinit() = 0; virtual void reload(pcstr section) = 0; // network diff --git a/src/xrGame/Actor.cpp b/src/xrGame/Actor.cpp index 1573ff6df54..549abe520d8 100644 --- a/src/xrGame/Actor.cpp +++ b/src/xrGame/Actor.cpp @@ -76,6 +76,9 @@ #include "xrCore/xr_token.h" #include "xrEngine/Rain.h" +#include "xrEngine/xr_collide_form.h" + +#include "xrPhysics/PHSimpleCharacter.h" //const u32 patch_frames = 50; //const float respawn_delay = 1.f; @@ -83,6 +86,11 @@ constexpr float default_feedback_duration = 0.2f; +constexpr Fvector aabb_offsets[8] = { + {-1, -1, -1}, {-1, 1, -1}, { 1, 1, -1}, { 1, -1, -1}, + {-1, -1, 1}, {-1, 1, 1}, { 1, 1, 1}, { 1, -1, 1} +}; + extern float cammera_into_collision_shift; extern int g_first_person_death; extern ENGINE_API Fvector4 ps_ssfx_hud_drops_1; @@ -100,7 +108,9 @@ Flags32 psActorFlags = AF_AUTOPICKUP | AF_RUN_BACKWARD | AF_IMPORTANT_SAVE | - AF_MULTI_ITEM_PICKUP + AF_MULTI_ITEM_PICKUP | + AF_FIRST_PERSON_BODY | + AF_FIRST_PERSON_BODY_DEBUG }; int psActorSleepTime = 1; @@ -243,6 +253,9 @@ CActor::~CActor() //Alundaio: For car xr_delete(m_vehicle_anims); //-Alundaio + + if (m_firstPersonBody) + xr_delete(m_firstPersonBody); } void CActor::reinit() @@ -463,6 +476,19 @@ void CActor::Load(LPCSTR section) m_sInventoryBoxUseAction = "inventory_box_use"; //--------------------------------------------------------------------- m_sHeadShotParticle = READ_IF_EXISTS(pSettings, r_string, section, "HeadShotParticle", 0); + + // initialize bones for first person body + m_firstPersonBodyBonesToHide = + { + { Visual()->dcast_PKinematics()->LL_BoneID("bip01_head"), true }, + { Visual()->dcast_PKinematics()->LL_BoneID("bip01_l_clavicle"), true }, + { Visual()->dcast_PKinematics()->LL_BoneID("bip01_r_clavicle"), true }, + }; + + m_firstPersonBodyBonesToIgnoreAnims = + { + { Visual()->dcast_PKinematics()->LL_BoneID("bip01_head"), false}, + }; } void CActor::PHHit(SHit& H) { m_pPhysics_support->in_Hit(H, false); } @@ -812,6 +838,9 @@ void CActor::Die(IGameObject* who) #ifdef DEBUG Msg("--- Actor [%s] dies !", this->Name()); #endif // #ifdef DEBUG + m_timeOfDeath = Device.dwTimeGlobal; + m_fpDeathCamOfffsetTime = m_timeOfDeath + 1000; + inherited::Die(who); if (OnServer()) @@ -1260,6 +1289,96 @@ void CActor::UpdateCL() UpdateVisorRainDrops(); UpdateVisor(); + + UpdateFirstPersonBodyBox(); + if (psActorFlags.test(AF_FIRST_PERSON_BODY_DEBUG)) + character_physics_support()->movement()->character()->InUpdateCL(); +} + +void CActor::TransformAndModifyAABB(const Fmatrix& transform, const Fvector& scale, Fbox& aabb) const +{ +#ifdef DEBUG + const bool isDebugMode = psActorFlags.test(AF_FIRST_PERSON_BODY_DEBUG); + Fvector corners[8]; + for (int i = 0; i < 8; ++i) + { + transform.transform_tiny(corners[i], Fvector().mul(scale, aabb_offsets[i])); + aabb.modify(corners[i]); + + if (isDebugMode) + DBG_DrawPoint(corners[i], 0.01f, color_xrgb(255, 0, 0)); + } + + if (isDebugMode) + DBG_DrawOBB(transform, scale, color_rgba(0, 255, 0, 255)); +#else + Fvector corners[8]; + for (int i = 0; i < 8; ++i) + { + transform.transform_tiny(corners[i], Fvector().mul(scale, aabb_offsets[i])); + aabb.modify(corners[i]); + } +#endif +} + +void CActor::UpdateFirstPersonBodyBox() +{ + constexpr float CAMERA_HALF_SIZE = 0.1f; + auto kinematics = PKinematics(Visual()); + const u16 boneCount = kinematics->LL_BoneCount(); + const bool isDebugMode = psActorFlags.test(AF_FIRST_PERSON_BODY_DEBUG); + + Fbox newAABB; + newAABB.invalidate(); + + const Fvector cameraScale({ CAMERA_HALF_SIZE, CAMERA_HALF_SIZE, CAMERA_HALF_SIZE }); + TransformAndModifyAABB(m_firstPersonCameraXform, cameraScale, newAABB); + + for (u16 i = 0; i < boneCount; i++) + { + const auto& boneData = kinematics->LL_GetData(i); + if (boneData.GetParentID() == BI_NONE) + continue; + + Fobb obb = kinematics->LL_GetBox(i); + Fmatrix boneMatrix, boneMatrixRes; + + obb.xform_get(boneMatrix); + boneMatrixRes.mul(kinematics->LL_GetTransform(i), boneMatrix); + boneMatrix.mul(XFORM(), boneMatrixRes); + + TransformAndModifyAABB(boneMatrix, obb.m_halfsize, newAABB); + } + + auto movementSupport = character_physics_support()->movement(); + Fbox& dynamicAABB = movementSupport->GetDynamicAABB(); + dynamicAABB.set(newAABB); + + Fvector center, radius; + dynamicAABB.getcenter(center); + dynamicAABB.getradius(radius); + + const Fbox& originalBox = movementSupport->Box(); + const dVector3 originalSize = { + originalBox.x2 - originalBox.x1, + originalBox.y2 - originalBox.y1, + originalBox.z2 - originalBox.z1 + }; + + const dVector3 dynamicSize = { + dynamicAABB.x2 - dynamicAABB.x1, + dynamicAABB.y2 - dynamicAABB.y1, + dynamicAABB.z2 - dynamicAABB.z1 + }; + + Fvector centerOffset = center; + centerOffset.sub(Position()); + + Fvector cameraOffset = m_firstPersonCameraXform.c; + cameraOffset.sub(Position()); + + auto character = movementSupport->character(); + character->SetBox(dynamicSize, centerOffset, cameraOffset); } float NET_Jump = 0; @@ -1332,6 +1451,7 @@ void CActor::shedule_Update(u32 DT) //------------------------------------------------ { g_cl_CheckControls(mstate_wishful, NET_SavedAccel, NET_Jump, dt); + m_firstPersonBodyXform = XFORM(); { /* if (mstate_real & mcJump) @@ -1576,6 +1696,7 @@ void CActor::shedule_Update(u32 DT) void CActor::renderable_Render(u32 context_id, IRenderable* root) { VERIFY(_valid(XFORM())); + inherited::renderable_Render(context_id, root); CInventoryOwner::renderable_Render(context_id, root); } @@ -1588,6 +1709,113 @@ bool CActor::renderable_ShadowGenerate() return inherited::renderable_ShadowGenerate(); } +bool CActor::FirstPersonBodyEnabled() +{ + return psActorFlags.test(AF_FIRST_PERSON_BODY) && cam_active == eacFirstEye; +} + +bool CActor::FirstPersonBodyActive() +{ + return m_firstPersonBody; +} + +void CActor::RenderFirstPersonBody(u32 context_id, IRenderable* root) +{ + ScopeLock lock{ &render_lock }; + IKinematics* realBodyK = Visual()->dcast_PKinematics(); + + auto obb = realBodyK->LL_GetData(m_head).obb; + Fmatrix Mbox; + obb.xform_get(Mbox); + const Fmatrix& Mbone = realBodyK->LL_GetBoneInstance(m_head).mTransform; + Fmatrix X; + m_firstPersonCameraXform.mul_43(XFORM(), X.mul_43(Mbone, Mbox)); + + if (!FirstPersonBodyEnabled()) + return; + + if (!m_firstPersonBody) // initialize first person body if necessary + { + m_firstPersonBody = GEnv.Render->model_Duplicate(Visual()); + g_SetAnimation(mstate_real, true); // Yohji: hacky way to reset anim state / bones when our visual changes + return; + } + + IKinematics* kinematics = m_firstPersonBody->dcast_PKinematics(); + + // Add body to render + GEnv.Render->add_Visual(context_id, root, m_firstPersonBody, m_firstPersonBodyXform); + m_firstPersonBody->getVisData().hom_frame = Device.dwFrame; + + PIItem pItem = inventory().ActiveItem(); + bool noItemEquipped = 0 == pItem; + + // On death or unarmed, show arms + if (!g_Alive() || noItemEquipped) + { + m_firstPersonBodyBonesToHide[m_l_clavicle] = false; + m_firstPersonBodyBonesToHide[m_r_clavicle] = false; + + for (auto [boneId, vis] : m_firstPersonBodyBonesToIgnoreAnims) + { + m_firstPersonBodyBonesToIgnoreAnims[boneId] = false; + } + } + else + { + m_firstPersonBodyBonesToHide[m_l_clavicle] = true; + m_firstPersonBodyBonesToHide[m_r_clavicle] = true; + + for (auto [boneId, vis] : m_firstPersonBodyBonesToIgnoreAnims) + { + m_firstPersonBodyBonesToIgnoreAnims[boneId] = true; + } + } + + // Copy transforms from actual body visual, excluding hidden bones and bones we don't want to animate + const u16 bones_count = kinematics->LL_BoneCount(); + for (u16 i = 0; i < bones_count; ++i) + { + if (m_firstPersonBodyBonesToIgnoreAnims.find(i) != m_firstPersonBodyBonesToIgnoreAnims.end() && m_firstPersonBodyBonesToIgnoreAnims[i]) + continue; + if (m_firstPersonBodyBonesToHide.find(i) != m_firstPersonBodyBonesToHide.end() && m_firstPersonBodyBonesToHide[i]) + continue; + + kinematics->LL_GetTransform(i).set(realBodyK->LL_GetTransform(i)); + kinematics->LL_GetTransform_R(i).set(realBodyK->LL_GetTransform_R(i)); + } + + // Hide/show bones AFTER copying transforms so we update all child bones properly + for (auto [boneId, hide] : m_firstPersonBodyBonesToHide) + { + kinematics->LL_SetBoneVisible(boneId, hide ? FALSE : TRUE, TRUE); + } + +#ifdef DEBUG + string1024 text; + CGameFont* F = UI().Font().pFontArial14; + F->SetAligment(CGameFont::alLeft); + F->OutSetI(-.9, 0); + F->SetColor(color_rgba(255, 0, 0, 255)); + xr_sprintf(text, "first person body position [%3.3f %3.3f %3.3f]", m_firstPersonBodyXform.c.x, m_firstPersonBodyXform.c.y, m_firstPersonBodyXform.c.z); + F->OutNext(text); + xr_sprintf(text, "first person body direction [%3.3f %3.3f %3.3f]", m_firstPersonBodyXform.k.x, m_firstPersonBodyXform.k.y, m_firstPersonBodyXform.k.z); + F->OutNext(text); + xr_sprintf(text, "m_firstPersonCameraXform pos [%3.3f %3.3f %3.3f]", m_firstPersonCameraXform.c.x, m_firstPersonCameraXform.c.y, m_firstPersonCameraXform.c.z); + F->OutNext(text); + xr_sprintf(text, "m_firstPersonCameraXform dir [%3.3f %3.3f %3.3f]", m_firstPersonCameraXform.k.x, m_firstPersonCameraXform.k.y, m_firstPersonCameraXform.k.z); + F->OutNext(text); + xr_sprintf(text, "m_firstPersonCameraXform norm [%3.3f %3.3f %3.3f]", m_firstPersonCameraXform.i.x, m_firstPersonCameraXform.i.y, m_firstPersonCameraXform.i.z); + F->OutNext(text); + xr_sprintf(text, "cameras[eacFirstEye] vPosition [%3.3f %3.3f %3.3f]", cameras[eacFirstEye]->vPosition.x, cameras[eacFirstEye]->vPosition.y, cameras[eacFirstEye]->vPosition.z); + F->OutNext(text); + xr_sprintf(text, "cameras[eacFirstEye] vDirection [%3.3f %3.3f %3.3f]", cameras[eacFirstEye]->vDirection.x, cameras[eacFirstEye]->vDirection.y, cameras[eacFirstEye]->vDirection.z); + F->OutNext(text); + xr_sprintf(text, "cameras[eacFirstEye] vNormal [%3.3f %3.3f %3.3f]", cameras[eacFirstEye]->vNormal.x, cameras[eacFirstEye]->vNormal.y, cameras[eacFirstEye]->vNormal.z); + F->OutNext(text); +#endif // DEBUG +} + void CActor::g_PerformDrop() { b_DropActivated = FALSE; diff --git a/src/xrGame/Actor.h b/src/xrGame/Actor.h index 627e7d9f8a5..f2533706bf8 100644 --- a/src/xrGame/Actor.h +++ b/src/xrGame/Actor.h @@ -102,6 +102,22 @@ class CActor : public CEntityAlive, // Render void renderable_Render(u32 context_id, IRenderable* root) override; virtual bool renderable_ShadowGenerate(); + // First person body + void TransformAndModifyAABB(const Fmatrix& transform, const Fvector& scale, Fbox& aabb) const; + bool FirstPersonBodyEnabled(); + bool FirstPersonBodyActive(); + void UpdateFirstPersonBodyBox(); + virtual void RenderFirstPersonBody(u32 context_id, IRenderable* root); + IRenderVisual* m_firstPersonBody{}; + xr_unordered_map m_firstPersonBodyBonesToHide; + xr_unordered_map m_firstPersonBodyBonesToIgnoreAnims; + u32 m_timeOfDeath{}; + u32 m_fpDeathCamOfffsetTime{}; + Fmatrix m_firstPersonBodyXform{Fidentity}; + Fmatrix m_firstPersonCameraXform{}; + + Lock render_lock{}; + void feel_sound_new(IGameObject* who, int type, const CSound_UserDataPtr& user_data, const Fvector& position, float power) override; virtual Feel::Sound* dcast_FeelSound() { return this; } @@ -294,15 +310,15 @@ class CActor : public CEntityAlive, // callback на анимации модели актера void SetCallbacks(); void ResetCallbacks(); - static void Spin0Callback(CBoneInstance*); - static void Spin1Callback(CBoneInstance*); - static void ShoulderCallback(CBoneInstance*); + static void Spine0Callback(CBoneInstance*); + static void Spine1Callback(CBoneInstance*); + static void Spine2Callback(CBoneInstance*); static void HeadCallback(CBoneInstance*); static void VehicleHeadCallback(CBoneInstance*); virtual const SRotation Orientation() const { return r_torso; }; SRotation& Orientation() { return r_torso; }; - void g_SetAnimation(u32 mstate_rl); + void g_SetAnimation(u32 mstate_rl, bool force = false); void g_SetSprintAnimation(u32 mstate_rl, MotionID& head, MotionID& torso, MotionID& legs); public: @@ -511,19 +527,19 @@ class CActor : public CEntityAlive, protected: //косточки используемые при стрельбе - int m_r_hand; - int m_l_finger1; - int m_r_finger2; - int m_head; - int m_eye_left; - int m_eye_right; - - int m_l_clavicle; - int m_r_clavicle; - int m_spine2; - int m_spine1; - int m_spine; - int m_neck; + int m_r_hand{}; + int m_l_finger1{}; + int m_r_finger2{}; + int m_head{}; + int m_eye_left{}; + int m_eye_right{}; + + int m_l_clavicle{}; + int m_r_clavicle{}; + int m_spine2{}; + int m_spine1{}; + int m_spine{}; + int m_neck{}; ////////////////////////////////////////////////////////////////////////// // Network diff --git a/src/xrGame/ActorAnimation.cpp b/src/xrGame/ActorAnimation.cpp index 8403dd2ca0e..874393b0caf 100644 --- a/src/xrGame/ActorAnimation.cpp +++ b/src/xrGame/ActorAnimation.cpp @@ -30,6 +30,7 @@ static const float p_spin0_factor = 0.0f; static const float p_spin1_factor = 0.2f; static const float p_shoulder_factor = 0.7f; static const float p_head_factor = 0.1f; +static const float p_head_unarmed_factor = 0.9f; static const float r_spin0_factor = 0.3f; static const float r_spin1_factor = 0.3f; static const float r_shoulder_factor = 0.2f; @@ -38,7 +39,7 @@ static const float r_head_factor = 0.2f; CBlend* PlayMotionByParts( IKinematicsAnimated* sa, MotionID motion_ID, BOOL bMixIn, PlayCallback Callback, LPVOID CallbackParam); -void CActor::Spin0Callback(CBoneInstance* B) +void CActor::Spine0Callback(CBoneInstance* B) { CActor* A = static_cast(B->callback_param()); VERIFY(A); @@ -52,7 +53,7 @@ void CActor::Spin0Callback(CBoneInstance* B) B->mTransform.mulA_43(spin); B->mTransform.c = c; } -void CActor::Spin1Callback(CBoneInstance* B) +void CActor::Spine1Callback(CBoneInstance* B) { CActor* A = static_cast(B->callback_param()); VERIFY(A); @@ -66,7 +67,7 @@ void CActor::Spin1Callback(CBoneInstance* B) B->mTransform.mulA_43(spin); B->mTransform.c = c; } -void CActor::ShoulderCallback(CBoneInstance* B) +void CActor::Spine2Callback(CBoneInstance* B) { CActor* A = static_cast(B->callback_param()); VERIFY(A); @@ -74,8 +75,9 @@ void CActor::ShoulderCallback(CBoneInstance* B) float bone_yaw = angle_normalize_signed(A->r_torso.yaw - A->r_model_yaw - A->r_model_yaw_delta) * y_shoulder_factor; float bone_pitch = angle_normalize_signed(A->r_torso.pitch) * p_shoulder_factor; float bone_roll = angle_normalize_signed(A->r_torso.roll) * r_shoulder_factor; + float correctedPitch = A->inventory().GetActiveSlot() == NO_ACTIVE_SLOT ? 0.f : bone_pitch; // yohji: force arms pitch to be neutral when we are unarmed Fvector c = B->mTransform.c; - spin.setXYZ(-bone_pitch, bone_yaw, bone_roll); + spin.setXYZ(-correctedPitch, bone_yaw, bone_roll); B->mTransform.mulA_43(spin); B->mTransform.c = c; } @@ -85,7 +87,8 @@ void CActor::HeadCallback(CBoneInstance* B) VERIFY(A); Fmatrix spin; float bone_yaw = angle_normalize_signed(A->r_torso.yaw - A->r_model_yaw - A->r_model_yaw_delta) * y_head_factor; - float bone_pitch = angle_normalize_signed(A->r_torso.pitch) * p_head_factor; + float correctedHeadFactor = A->inventory().GetActiveSlot() == NO_ACTIVE_SLOT ? p_head_unarmed_factor : p_head_factor; + float bone_pitch = angle_normalize_signed(A->cam_Active()->GetWorldPitch()) * correctedHeadFactor; float bone_roll = angle_normalize_signed(A->r_torso.roll) * r_head_factor; Fvector c = B->mTransform.c; spin.setXYZ(-bone_pitch, bone_yaw, bone_roll); @@ -321,17 +324,17 @@ constexpr pcstr mov_state[] = { }; #endif // DEBUG -void CActor::g_SetAnimation(u32 mstate_rl) +void CActor::g_SetAnimation(u32 mstate_rl, bool force) { if (!g_Alive()) { if (m_current_legs || m_current_torso) { -// SActorState* ST = 0; -// if (mstate_rl & mcCrouch) -// ST = &m_anims->m_crouch; -// else -// ST = &m_anims->m_normal; + SActorState* ST = 0; + if (mstate_rl & mcCrouch) + ST = &m_anims->m_crouch; + else + ST = &m_anims->m_normal; mstate_real = 0; m_current_legs.invalidate(); m_current_torso.invalidate(); @@ -515,6 +518,9 @@ void CActor::g_SetAnimation(u32 mstate_rl) default: M_torso = TW->moving[moving_idx]; break; } } + + if (!M_torso) + M_torso = ST->m_torso[4].moving[moving_idx]; //Alundaio: Fix torso animations for binoc } else if (M) { @@ -561,10 +567,12 @@ void CActor::g_SetAnimation(u32 mstate_rl) } } } + else if (!m_bAnimTorsoPlayed) + M_torso = ST->m_torso[4].moving[moving_idx]; //Alundaio: Fix torso animations for no weapon } // XXX: check why 'mid' was unused - //MotionID mid = smart_cast(Visual())->ID_Cycle("norm_idle_0"); + MotionID mid = smart_cast(Visual())->ID_Cycle("norm_idle_0"); if (!M_legs) { @@ -606,7 +614,7 @@ void CActor::g_SetAnimation(u32 mstate_rl) m_current_head = M_head; } - if (m_current_legs != M_legs) + if (m_current_legs != M_legs || force) { float pos = 0.f; VERIFY(!m_current_legs_blend || !fis_zero(m_current_legs_blend->timeTotal)); diff --git a/src/xrGame/ActorCameras.cpp b/src/xrGame/ActorCameras.cpp index fd6f485bb87..5052a715330 100644 --- a/src/xrGame/ActorCameras.cpp +++ b/src/xrGame/ActorCameras.cpp @@ -24,6 +24,11 @@ #include "xrPhysics/ActorCameraCollision.h" #include "IKLimbsController.h" #include "GamePersistent.h" +#include "Actor.h" + +#include "debug_renderer.h" + +extern Fvector g_first_person_cam_offset; void CActor::cam_Set(EActorCameras style) { @@ -320,8 +325,7 @@ void CActor::cam_Update(float dt, float fFOV) } Fvector point = { 0, CurrentHeight + current_ik_cam_shift, 0 }; - - Fvector dangle = {0, 0, 0}; + Fvector dangle = { 0, 0, 0 }; Fmatrix xform; xform.setXYZ(0, r_torso.yaw, 0); xform.translate_over(XFORM().c); @@ -362,6 +366,18 @@ void CActor::cam_Update(float dt, float fFOV) CCameraBase* C = cam_Active(); + if (FirstPersonBodyActive()) // update camera position with offset for first person body + { + m_firstPersonCameraXform.c.mad(Direction(), g_first_person_cam_offset.z); + point = m_firstPersonCameraXform.c; + _viewport_near = HUD_VIEWPORT_NEAR * .3f; + Visual()->dcast_PKinematics()->CalculateBones(true); + +#ifdef DEBUG + DBG_DrawOBB(m_firstPersonCameraXform, Fvector{ 0.1, 0.1, 0.1 }, color_xrgb(255, 0, 0)); +#endif + } + C->Update(point, dangle); C->f_fov = fFOV; @@ -370,7 +386,19 @@ void CActor::cam_Update(float dt, float fFOV) cameras[eacFirstEye]->Update(point, dangle); cameras[eacFirstEye]->f_fov = fFOV; } - if (Level().CurrentEntity() == this) + + if (FirstPersonBodyActive() && !g_Alive()) // override camera position / direction for first person body on death + { + float timeScalar = Device.dwTimeGlobal > m_fpDeathCamOfffsetTime ? 1.0f : (float)(1000 - (m_fpDeathCamOfffsetTime - Device.dwTimeGlobal)) / 1000.f; + Fvector fpDeathPos; + fpDeathPos.set(m_firstPersonCameraXform.c); + fpDeathPos.mad(m_firstPersonCameraXform.i, .15f); + + cameras[eacFirstEye]->vDirection.lerp(cameras[eacFirstEye]->vDirection, m_firstPersonCameraXform.k, timeScalar); + cameras[eacFirstEye]->vNormal.lerp(cameras[eacFirstEye]->vNormal, m_firstPersonCameraXform.i, timeScalar); + cameras[eacFirstEye]->vPosition.lerp(cameras[eacFirstEye]->vPosition, fpDeathPos, timeScalar); + } + if (!FirstPersonBodyActive() && Level().CurrentEntity() == this) { collide_camera(*cameras[eacFirstEye], _viewport_near, this); } @@ -392,7 +420,7 @@ void CActor::cam_Update(float dt, float fFOV) const bool allow = !Level().Cameras().GetCamEffector(cefDemo) && !Level().Cameras().GetCamEffector(cefAnsel); if (eacFirstEye == cam_active && allow) { - Cameras().ApplyDevice(); + Cameras().ApplyDevice(_viewport_near); } } } diff --git a/src/xrGame/Actor_Flags.h b/src/xrGame/Actor_Flags.h index 58f44fa36b6..d831b8160a9 100644 --- a/src/xrGame/Actor_Flags.h +++ b/src/xrGame/Actor_Flags.h @@ -15,6 +15,8 @@ enum AF_MULTI_ITEM_PICKUP = (1 << 11), AF_LOADING_STAGES = (1 << 12), AF_ALWAYS_USE_ATTITUDE_SENSORS = (1 << 13), // or only when zooming if false + AF_FIRST_PERSON_BODY = (1 << 14), + AF_FIRST_PERSON_BODY_DEBUG = (1 << 15), }; extern Flags32 psActorFlags; diff --git a/src/xrGame/Actor_Movement.cpp b/src/xrGame/Actor_Movement.cpp index 2beec1b8db5..2f4092367f9 100644 --- a/src/xrGame/Actor_Movement.cpp +++ b/src/xrGame/Actor_Movement.cpp @@ -153,7 +153,7 @@ void CActor::g_cl_ValidateMState(float dt, u32 mstate_wf) }; }; }; - +extern Fvector g_first_person_cam_offset; void CActor::g_cl_CheckControls(u32 mstate_wf, Fvector& vControlAccel, float& Jump, float dt) { float cam_eff_factor = 0.0f; @@ -419,7 +419,11 @@ void CActor::g_Orientate(u32 mstate_rl, float dt) } // lerp angle for "effect" and capture torso data from camera - angle_lerp(r_model_yaw_delta, calc_yaw, PI_MUL_4, dt); + float diff = abs(calc_yaw - r_model_yaw_delta); // yohji: smoother transition when turning + if (diff > EPS) + { + angle_lerp(r_model_yaw_delta, calc_yaw, PI * diff, dt); + } // build matrix Fmatrix mXFORM; @@ -528,10 +532,12 @@ void CActor::g_cl_Orientate(u32 mstate_rl, float dt) { // if camera rotated more than 45 degrees - align model with it float ty = angle_normalize(r_torso.yaw); - if (_abs(r_model_yaw - ty) > PI_DIV_4) + float minYaw = PI_DIV_4; + if (FirstPersonBodyActive()) // yohji: model should always align to first person body in first person body mode, looks more natural + minYaw = 0.f; + if (_abs(r_model_yaw - ty) > minYaw) { r_model_yaw_dest = ty; - // mstate_real |= mcTurn; } if (_abs(r_model_yaw - r_model_yaw_dest) < EPS_L) diff --git a/src/xrGame/Actor_Network.cpp b/src/xrGame/Actor_Network.cpp index 0d5e95cd7a3..8bd01570a4e 100644 --- a/src/xrGame/Actor_Network.cpp +++ b/src/xrGame/Actor_Network.cpp @@ -835,27 +835,19 @@ void CActor::SetCallbacks() { IKinematics* V = smart_cast(Visual()); VERIFY(V); - u16 spine0_bone = V->LL_BoneID("bip01_spine"); - u16 spine1_bone = V->LL_BoneID("bip01_spine1"); - u16 shoulder_bone = V->LL_BoneID("bip01_spine2"); - u16 head_bone = V->LL_BoneID("bip01_head"); - V->LL_GetBoneInstance(u16(spine0_bone)).set_callback(bctCustom, Spin0Callback, this); - V->LL_GetBoneInstance(u16(spine1_bone)).set_callback(bctCustom, Spin1Callback, this); - V->LL_GetBoneInstance(u16(shoulder_bone)).set_callback(bctCustom, ShoulderCallback, this); - V->LL_GetBoneInstance(u16(head_bone)).set_callback(bctCustom, HeadCallback, this); + V->LL_GetBoneInstance(u16(m_spine)).set_callback(bctCustom, Spine0Callback, this); + V->LL_GetBoneInstance(u16(m_spine1)).set_callback(bctCustom, Spine1Callback, this); + V->LL_GetBoneInstance(u16(m_spine2)).set_callback(bctCustom, Spine2Callback, this); + V->LL_GetBoneInstance(u16(m_head)).set_callback(bctCustom, HeadCallback, this); } void CActor::ResetCallbacks() { IKinematics* V = smart_cast(Visual()); VERIFY(V); - u16 spine0_bone = V->LL_BoneID("bip01_spine"); - u16 spine1_bone = V->LL_BoneID("bip01_spine1"); - u16 shoulder_bone = V->LL_BoneID("bip01_spine2"); - u16 head_bone = V->LL_BoneID("bip01_head"); - V->LL_GetBoneInstance(u16(spine0_bone)).reset_callback(); - V->LL_GetBoneInstance(u16(spine1_bone)).reset_callback(); - V->LL_GetBoneInstance(u16(shoulder_bone)).reset_callback(); - V->LL_GetBoneInstance(u16(head_bone)).reset_callback(); + V->LL_GetBoneInstance(u16(m_spine)).reset_callback(); + V->LL_GetBoneInstance(u16(m_spine1)).reset_callback(); + V->LL_GetBoneInstance(u16(m_spine2)).reset_callback(); + V->LL_GetBoneInstance(u16(m_head)).reset_callback(); } void CActor::OnChangeVisual() @@ -916,6 +908,9 @@ void CActor::ChangeVisual(shared_str NewVisual) return; } + if (m_firstPersonBody) + GEnv.Render->model_Delete(m_firstPersonBody); + cNameVisual_set(NewVisual); g_SetAnimation(mstate_real); diff --git a/src/xrGame/CameraFirstEye.cpp b/src/xrGame/CameraFirstEye.cpp index 39209929c71..ce1c6c8f158 100644 --- a/src/xrGame/CameraFirstEye.cpp +++ b/src/xrGame/CameraFirstEye.cpp @@ -75,6 +75,10 @@ void CCameraFirstEye::Update(Fvector& point, Fvector& noise_dangle) void CCameraFirstEye::Move(int cmd, float val, float factor) { + CActor* pActor = smart_cast(parent); + if (pActor && !pActor->g_Alive() && pActor->FirstPersonBodyEnabled()) + return; + if (bClampPitch) { while (pitch < lim_pitch[0]) diff --git a/src/xrGame/CameraFirstEye.h b/src/xrGame/CameraFirstEye.h index 31ff8288908..417dfb63e13 100644 --- a/src/xrGame/CameraFirstEye.h +++ b/src/xrGame/CameraFirstEye.h @@ -9,6 +9,7 @@ class CCameraFirstEye : public CCameraBase Fvector lookat_point; bool lookat_active; void UpdateLookat(); + void UpdateFirstPerson(Fvector& point, Fvector& noise_dangle); public: CCameraFirstEye(IGameObject* p, u32 flags = 0); diff --git a/src/xrGame/CharacterPhysicsSupport.cpp b/src/xrGame/CharacterPhysicsSupport.cpp index 531984879a6..3a308f3640f 100644 --- a/src/xrGame/CharacterPhysicsSupport.cpp +++ b/src/xrGame/CharacterPhysicsSupport.cpp @@ -723,7 +723,9 @@ bool CCharacterPhysicsSupport::CollisionCorrectObjPos(const Fvector& start_from, activation_res, vbox, activation_pos, mXFORM, not_collide_characters, set_rotation, &m_EntityAlife); ////////////////// - m_EntityAlife.Position().sub(activation_res, shift); + auto actor = smart_cast(&m_EntityAlife); + if (!(actor && actor->FirstPersonBodyEnabled() && !actor->g_Alive())) + m_EntityAlife.Position().sub(activation_res, shift); if (m_pPhysicsShell) m_pPhysicsShell->EnableCollision(); diff --git a/src/xrGame/PHDebug.cpp b/src/xrGame/PHDebug.cpp index 84c3e054a89..31a884acf6b 100644 --- a/src/xrGame/PHDebug.cpp +++ b/src/xrGame/PHDebug.cpp @@ -823,7 +823,7 @@ void DBG_DrawBones(const Fmatrix& xform, IKinematics* K) Fmatrix bone_pos = bi.mTransform; // K->Bone_GetAnimPos( bone_pos, i, u8(-1), false ); - DBG_DrawMatrix(Fmatrix().mul_43(xform, bone_pos), 0.1); + //DBG_DrawMatrix(Fmatrix().mul_43(xform, bone_pos), 0.1); u16 bp = bd.GetParentID(); if (BI_NONE != bp) diff --git a/src/xrGame/PHDebug.h b/src/xrGame/PHDebug.h index 81e940498a4..b932b7070a1 100644 --- a/src/xrGame/PHDebug.h +++ b/src/xrGame/PHDebug.h @@ -56,6 +56,7 @@ void DBG_DrawTri(CDB::TRI* T, const Fvector* V_verts, u32 c); void DBG_DrawLine(const Fvector& p0, const Fvector& p1, u32 c); void DBG_DrawAABB(const Fvector& center, const Fvector& AABB, u32 c); void DBG_DrawOBB(const Fmatrix& m, const Fvector h, u32 c); +void DBG_DrawOBB(const Fobb& b, u32 c); void DBG_DrawPoint(const Fvector& p, float size, u32 c); void DBG_DrawMatrix(const Fmatrix& m, float size, u8 a = 255); void DBG_DrawRotationX( diff --git a/src/xrGame/PHMovementControl.cpp b/src/xrGame/PHMovementControl.cpp index 1e3b113bd7b..dee8b1cbce9 100644 --- a/src/xrGame/PHMovementControl.cpp +++ b/src/xrGame/PHMovementControl.cpp @@ -60,6 +60,7 @@ CPHMovementControl::CPHMovementControl(IGameObject* parent) eOldEnvironment = peInAir; eEnvironment = peInAir; aabb.set(-def_X_SIZE_2, 0, -def_Z_SIZE_2, def_X_SIZE_2, def_Y_SIZE_2 * 2, def_Z_SIZE_2); + dynamic_aabb.set(aabb); fMass = 100; fMinCrashSpeed = 12.0f; fMaxCrashSpeed = 25.0f; diff --git a/src/xrGame/PHMovementControl.h b/src/xrGame/PHMovementControl.h index 72afeeb7c99..6bdf1dc9c3e 100644 --- a/src/xrGame/PHMovementControl.h +++ b/src/xrGame/PHMovementControl.h @@ -109,6 +109,7 @@ class CPHMovementControl : public IPHMovementControl EEnvironment eOldEnvironment; EEnvironment eEnvironment; Fbox aabb; + Fbox dynamic_aabb; Fbox boxes[4]; u32 trying_times[4]; @@ -298,6 +299,8 @@ class CPHMovementControl : public IPHMovementControl CPHCharacter* character() { return m_character; }; void NetRelcase(IGameObject* O); + Fbox& GetDynamicAABB() { return dynamic_aabb; }; + private: void actor_calculate(Fvector& vAccel, const Fvector& camDir, float ang_speed, float jump, float dt, bool bLight); void UpdateCollisionDamage(); diff --git a/src/xrGame/Weapon.cpp b/src/xrGame/Weapon.cpp index c556cb13eba..b4bdf5643d0 100644 --- a/src/xrGame/Weapon.cpp +++ b/src/xrGame/Weapon.cpp @@ -180,7 +180,8 @@ void CWeapon::UpdateXForm() if ((HandDependence() == hd1Hand) || (GetState() == eReload) || (!E->g_Alive())) boneL = boneR2; - V->CalculateBones(); + BOOL forceExact = psActorFlags.test(AF_FIRST_PERSON_BODY) ? TRUE : FALSE; + V->CalculateBones(forceExact); Fmatrix& mL = V->LL_GetTransform(u16(boneL)); Fmatrix& mR = V->LL_GetTransform(u16(boneR)); // Calculate diff --git a/src/xrGame/ai_obstacle.cpp b/src/xrGame/ai_obstacle.cpp index c887b572f28..82285430bc7 100644 --- a/src/xrGame/ai_obstacle.cpp +++ b/src/xrGame/ai_obstacle.cpp @@ -98,7 +98,7 @@ void ai_obstacle::compute_matrix(Fmatrix& result, const Fvector& additional) u16 visible_bone_count = kinematics->LL_VisibleBoneCount(); if (!visible_bone_count) { - result.scale(0.f, 0.f, 0.f); + result.scale(M_MIN_SCALE, M_MIN_SCALE, M_MIN_SCALE); return; } diff --git a/src/xrGame/console_commands.cpp b/src/xrGame/console_commands.cpp index 680dd543bbe..4ff2345b118 100644 --- a/src/xrGame/console_commands.cpp +++ b/src/xrGame/console_commands.cpp @@ -112,6 +112,8 @@ int g_first_person_death = 0; int g_normalize_mouse_sens = 0; int g_normalize_upgrade_mouse_sens = 0; +Fvector g_first_person_cam_offset = { 0.f, 0.f, 0.f }; + void register_mp_console_commands(); //----------------------------------------------------------- @@ -2205,6 +2207,10 @@ void CCC_RegisterCommands() CMD3(CCC_Mask, "g_important_save", &psActorFlags, AF_IMPORTANT_SAVE); CMD3(CCC_Mask, "g_loading_stages", &psActorFlags, AF_LOADING_STAGES); CMD3(CCC_Mask, "g_always_use_attitude_sensors", &psActorFlags, AF_ALWAYS_USE_ATTITUDE_SENSORS); + CMD3(CCC_Mask, "g_first_person_body", &psActorFlags, AF_FIRST_PERSON_BODY); + CMD3(CCC_Mask, "g_first_person_body_debug", &psActorFlags, AF_FIRST_PERSON_BODY_DEBUG); + + CMD4(CCC_Vector3, "g_first_person_cam_offset", &g_first_person_cam_offset, Fvector().set(-10, -10, -10), Fvector().set(10, 10, 10)); CMD4(CCC_Integer, "g_inv_highlight_equipped", &g_inv_highlight_equipped, 0, 1); CMD4(CCC_Integer, "g_first_person_death", &g_first_person_death, 0, 1); diff --git a/src/xrPhysics/PHCharacter.h b/src/xrPhysics/PHCharacter.h index b9fa5bb1da9..6fa4bd5cf60 100644 --- a/src/xrPhysics/PHCharacter.h +++ b/src/xrPhysics/PHCharacter.h @@ -124,7 +124,9 @@ class CPHCharacter : virtual void GroundNormal(Fvector& norm) = 0; virtual void Create(dVector3 /**sizes**/) = 0; virtual void Destroy(void) = 0; + virtual void InUpdateCL() = 0; virtual void SetBox(const dVector3& sizes) = 0; + virtual void SetBox(const dVector3& sizes, Fvector& position, Fvector& camPosition) = 0; virtual void SetAcceleration(Fvector accel) = 0; virtual void SetForcedPhysicsControl(bool v) {} virtual bool ForcedPhysicsControl() { return false; } diff --git a/src/xrPhysics/PHSimpleCharacter.cpp b/src/xrPhysics/PHSimpleCharacter.cpp index 7bf50d2da5c..d7d2648f5b3 100644 --- a/src/xrPhysics/PHSimpleCharacter.cpp +++ b/src/xrPhysics/PHSimpleCharacter.cpp @@ -205,6 +205,34 @@ void CPHSimpleCharacter::TestPathCallback( ch->b_side_contact = true; } +void CPHSimpleCharacter::InUpdateCL() +{ +#ifdef DEBUG + const dReal k = 1.20f; + dReal doun = m_radius * _sqrt(1.f - 1.f / k / k) / 2.f; + float test_radius = m_radius * 2.f; + float test_height = test_radius + m_radius / 2.f; + + Fvector t1{ cast_fv(dGeomGetPosition(m_geom_shell)) }; + Fvector t2{ cast_fv(dGeomGetPosition(m_hat)) }; + Fvector t3{ cast_fv(dGeomGetPosition(m_wheel)) }; + Fvector t4{ cast_fv(dGeomGetPosition(m_cap)) }; + + Fmatrix object_form; + object_form.set(m_phys_ref_object->ObjectXFORM()); + + object_form.transform_tiny(t1); + object_form.transform_tiny(t2); + object_form.transform_tiny(t3); + object_form.transform_tiny(t4); + + debug_output().DBG_DrawPoint(t1, .1f, color_xrgb(255, 0, 0)); + debug_output().DBG_DrawPoint(t2, .1f, color_xrgb(255, 0, 0)); + debug_output().DBG_DrawPoint(t3, .1f, color_xrgb(255, 0, 0)); + debug_output().DBG_DrawPoint(t4, .1f, color_xrgb(255, 0, 0)); +#endif // DEBUG +} + void CPHSimpleCharacter::SetBox(const dVector3& sizes) { m_radius = std::min(sizes[0], sizes[2]) / 2.f; @@ -229,6 +257,40 @@ void CPHSimpleCharacter::SetBox(const dVector3& sizes) dGeomSphereSetRadius(m_cap, test_radius); dGeomSetPosition(m_cap, 0.f, test_height, 0.f); } + +void CPHSimpleCharacter::SetBox(const dVector3& sizes, Fvector& position, Fvector& camPos) +{ + m_dynamic_radius = std::max(sizes[0], sizes[2]) / 2.f; + + const dReal k = 1.20f; + dReal doun = m_radius * _sqrt(1.f - 1.f / k / k) / 2.f; + + dGeomCylinderSetParams(m_geom_shell, m_dynamic_radius / k, m_cyl_hight); + dGeomSetPosition(m_hat, camPos.x, m_cyl_hight, camPos.z); + dGeomSetPosition(m_geom_shell, position.x, m_cyl_hight / 2.f - doun, position.z); + + return; + + m_radius = std::max(sizes[0], sizes[2]) / 2.f; + m_cyl_hight = sizes[1]; + if (m_cyl_hight < 0.f) + m_cyl_hight = 0.01f; + // m_geom_shell=dCreateCylinder(0,m_radius/k,m_cyl_hight+doun); + dGeomCylinderSetParams(m_geom_shell, m_radius / k, m_cyl_hight); + // m_wheel=dCreateSphere(0,m_radius); + //dGeomSphereSetRadius(m_wheel, m_radius); + // m_hat=dCreateSphere(0,m_radius/k); + //dGeomSphereSetRadius(m_hat, m_radius / k); + + //dGeomSetPosition(m_geom_shell, position.x, 0.01f, position.z); + + float test_radius = m_radius * 2.f; + float test_height = m_cyl_hight + m_radius / 2.f; + // m_cap=dCreateSphere(0,test_radius); + dGeomSphereSetRadius(m_cap, test_radius); + dGeomSetPosition(m_cap, 0.f, test_height, 0.f); +} + void CPHSimpleCharacter::get_Box(Fvector& sz, Fvector& c) const { float r, h; @@ -262,9 +324,8 @@ void CPHSimpleCharacter::Create(dVector3 sizes) dReal doun = m_radius * _sqrt(1.f - 1.f / k / k) / 2.f; m_geom_shell = dCreateCylinder(0, m_radius / k, m_cyl_hight + doun); - - m_wheel = dCreateSphere(0, m_radius); - m_hat = dCreateSphere(0, m_radius / k); + m_wheel = dCreateSphere(0, 0.f); + m_hat = dCreateSphere(0, 0.f); m_shell_transform = dCreateGeomTransform(0); dGeomTransformSetCleanup(m_shell_transform, 0); diff --git a/src/xrPhysics/PHSimpleCharacter.h b/src/xrPhysics/PHSimpleCharacter.h index 7cecfb274b6..2bef4a096f6 100644 --- a/src/xrPhysics/PHSimpleCharacter.h +++ b/src/xrPhysics/PHSimpleCharacter.h @@ -71,6 +71,7 @@ class CPHSimpleCharacter : public CPHCharacter, ICollisionDamageInfo dSpaceID m_space; dReal m_radius; + dReal m_dynamic_radius; dReal m_cyl_hight; /////////////////////////////////// // dJointID m_capture_joint; @@ -183,6 +184,7 @@ class CPHSimpleCharacter : public CPHCharacter, ICollisionDamageInfo virtual void EnableObject(CPHObject* obj); virtual void Enable(); virtual void SetBox(const dVector3& sizes); + virtual void SetBox(const dVector3& sizes, Fvector& position, Fvector& camPosition); virtual bool UpdateRestrictionType(CPHCharacter* ach); // get-set virtual void SetObjectContactCallback(ObjectContactCallbackFun* callback); @@ -294,6 +296,7 @@ class CPHSimpleCharacter : public CPHCharacter, ICollisionDamageInfo #ifdef DEBUG virtual void OnRender(); #endif + virtual void InUpdateCL(); }; const dReal def_spring_rate = 0.5f; diff --git a/src/xrPhysics/tri-colliderknoopc/dcTriListCollider.cpp b/src/xrPhysics/tri-colliderknoopc/dcTriListCollider.cpp index cf658e14d5f..65eed183fea 100644 --- a/src/xrPhysics/tri-colliderknoopc/dcTriListCollider.cpp +++ b/src/xrPhysics/tri-colliderknoopc/dcTriListCollider.cpp @@ -58,9 +58,9 @@ int dcTriListCollider::CollideCylinder(dxGeom* Cylinder, int Flags, dContactGeom AABB.z = REAL(0.5) * dFabs(R[9] * CylinderLength) + (_sqrt(R[8] * R[8] + R[10] * R[10]) * CylinderRadius); const dReal* velocity = dBodyGetLinearVel(dGeomGetBody(Cylinder)); - AABB.x += dFabs(velocity[0]) * 0.04f; - AABB.y += dFabs(velocity[1]) * 0.04f; - AABB.z += dFabs(velocity[2]) * 0.04f; + //AABB.x += dFabs(velocity[0]) * 0.04f; + //AABB.y += dFabs(velocity[1]) * 0.04f; + //AABB.z += dFabs(velocity[2]) * 0.04f; CylTri ct(*this); return dSortTriPrimitiveCollide(ct, Cylinder, Geometry, Flags, Contacts, Stride, AABB); @@ -80,9 +80,9 @@ int dcTriListCollider::CollideSphere(dxGeom* Sphere, int Flags, dContactGeom* Co AABB.z = SphereRadius; const dReal* velocity = dBodyGetLinearVel(dGeomGetBody(Sphere)); - AABB.x += dFabs(velocity[0]) * 0.04f; - AABB.y += dFabs(velocity[1]) * 0.04f; - AABB.z += dFabs(velocity[2]) * 0.04f; + //AABB.x += dFabs(velocity[0]) * 0.04f; + //AABB.y += dFabs(velocity[1]) * 0.04f; + //AABB.z += dFabs(velocity[2]) * 0.04f; SphereTri st(*this); return dSortTriPrimitiveCollide(st, Sphere, Geometry, Flags, Contacts, Stride, AABB); }