BVB Source Codes

CRYENGINE Show View.cpp Source code

Return Download CRYENGINE: download View.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /*************************************************************************
  4.    -------------------------------------------------------------------------
  5.    $Id$
  6.    $DateTime$
  7.  
  8.    -------------------------------------------------------------------------
  9.    History:
  10.    - 20:9:2004     : Created by Filippo De Luca
  11.    - September 2010: Jens Sch枚bel created a smooth extended camera shake
  12.  
  13. *************************************************************************/
  14. #include "StdAfx.h"
  15.  
  16. #include <CryMath/Cry_Camera.h>
  17. #include <CrySystem/VR/IHMDDevice.h>
  18. #include <CrySystem/VR/IHMDManager.h>
  19. #include <ITimeDemoRecorder.h>
  20. #include "View.h"
  21. #include "GameObjects/GameObject.h"
  22. #include "IGameSessionHandler.h"
  23.  
  24. #include "ViewSystem.h"
  25.  
  26. namespace
  27. {
  28. static ICVar* pCamShakeMult = 0;
  29. static ICVar* pHmdTrackingOrigin = 0;
  30. }
  31. //------------------------------------------------------------------------
  32. CView::CView(ISystem* const pSystem)
  33.         : m_pSystem(pSystem)
  34.         , m_linkedTo(0)
  35.         , m_frameAdditiveAngles(0.0f, 0.0f, 0.0f)
  36.         , m_scale(1.0f)
  37.         , m_zoomedScale(1.0f)
  38.         , m_pAudioListener(nullptr)
  39. {
  40.         if (!pCamShakeMult)
  41.         {
  42.                 pCamShakeMult = gEnv->pConsole->GetCVar("c_shakeMult");
  43.         }
  44.         if (!pHmdTrackingOrigin)
  45.         {
  46.                 pHmdTrackingOrigin = gEnv->pConsole->GetCVar("hmd_tracking_origin");
  47.         }
  48.  
  49.         CreateAudioListener();
  50. }
  51.  
  52. //------------------------------------------------------------------------
  53. CView::~CView()
  54. {
  55.         if (m_pAudioListener != nullptr)
  56.         {
  57.                 gEnv->pEntitySystem->RemoveEntityEventListener(m_pAudioListener->GetId(), ENTITY_EVENT_DONE, this);
  58.                 gEnv->pEntitySystem->RemoveEntity(m_pAudioListener->GetId(), true);
  59.                 m_pAudioListener = nullptr;
  60.         }
  61. }
  62.  
  63. //-----------------------------------------------------------------------
  64. void CView::Release()
  65. {
  66.         delete this;
  67. }
  68.  
  69. //------------------------------------------------------------------------
  70. void CView::Update(float frameTime, bool isActive)
  71. {
  72.         //FIXME:some cameras may need to be updated always
  73.         if (!isActive)
  74.                 return;
  75.  
  76.         CGameObject* pLinkedTo = GetLinkedGameObject();
  77.         if (pLinkedTo && !pLinkedTo->CanUpdateView())
  78.                 pLinkedTo = nullptr;
  79.         IEntity* pEntity = pLinkedTo ? 0 : GetLinkedEntity();
  80.  
  81.         if (pLinkedTo || pEntity)
  82.         {
  83.                 m_viewParams.SaveLast();
  84.  
  85.                 CCamera* pSysCam = &m_pSystem->GetViewCamera();
  86.  
  87.                 //process screen shaking
  88.                 ProcessShaking(frameTime);
  89.  
  90.                 //FIXME:to let the updateView implementation use the correct shakeVector
  91.                 m_viewParams.currentShakeShift = m_viewParams.rotation * m_viewParams.currentShakeShift;
  92.  
  93.                 m_viewParams.frameTime = frameTime;
  94.                 //update view position/rotation
  95.                 if (pLinkedTo)
  96.                 {
  97.                         pLinkedTo->UpdateView(m_viewParams);
  98.                         if (!m_viewParams.position.IsValid())
  99.                         {
  100.                                 m_viewParams.position = m_viewParams.GetPositionLast();
  101.                                 CRY_ASSERT_MESSAGE(0, "Camera position is invalid, reverting to old position");
  102.                         }
  103.                         if (!m_viewParams.rotation.IsValid())
  104.                         {
  105.                                 m_viewParams.rotation = m_viewParams.GetRotationLast();
  106.                                 CRY_ASSERT_MESSAGE(0, "Camera rotation is invalid, reverting to old rotation");
  107.                         }
  108.                 }
  109.                 else
  110.                 {
  111.                         Matrix34 mat = pEntity->GetWorldTM();
  112.                         mat.OrthonormalizeFast();
  113.                         m_viewParams.position = mat.GetTranslation();
  114.                         m_viewParams.rotation = Quat(mat);
  115.                 }
  116.  
  117.                 ApplyFrameAdditiveAngles(m_viewParams.rotation);
  118.  
  119.                 if (pLinkedTo)
  120.                 {
  121.                         pLinkedTo->PostUpdateView(m_viewParams);
  122.                 }
  123.  
  124.                 const float fNearZ = gEnv->pGameFramework->GetIViewSystem()->GetDefaultZNear();
  125.  
  126.                 //see if the view have to use a custom near clipping plane
  127.                 const float nearPlane = (m_viewParams.nearplane >= 0.01f) ? (m_viewParams.nearplane) : fNearZ;
  128.                 const float farPlane = gEnv->p3DEngine->GetMaxViewDistance();
  129.                 float fov = (m_viewParams.fov < 0.001f) ? DEFAULT_FOV : m_viewParams.fov;
  130.  
  131.                 // [VR] specific
  132.                 // Modify FOV based on the HDM device configuration
  133.                 IHmdManager* pHmdManager = gEnv->pSystem->GetHmdManager();
  134.                 IHmdDevice* pHmdDevice = nullptr;
  135.                 bool bHmdTrackingEnabled = false;
  136.                 if (pHmdManager)
  137.                 {
  138.                         pHmdDevice = pHmdManager->GetHmdDevice();
  139.                         if (pHmdDevice)
  140.                         {
  141.                                 const HmdTrackingState& sensorState = pHmdDevice->GetLocalTrackingState();
  142.                                 if (sensorState.CheckStatusFlags(eHmdStatus_IsUsable) && static_cast<CViewSystem*>(gEnv->pGameFramework->GetIViewSystem())->ShouldApplyHmdOffset())
  143.                                 {
  144.                                         bHmdTrackingEnabled = true;
  145.                                 }
  146.                         }
  147.  
  148.  
  149.                         if (pHmdManager->IsStereoSetupOk())
  150.                         {
  151.                                 const IHmdDevice* pDev = pHmdManager->GetHmdDevice();
  152.                                 const HmdTrackingState& sensorState = pDev->GetLocalTrackingState();
  153.                                 if (sensorState.CheckStatusFlags(eHmdStatus_IsUsable))
  154.                                 {
  155.                                         float arf_notUsed;
  156.                                         pDev->GetCameraSetupInfo(fov, arf_notUsed);
  157.                                 }
  158.                         }
  159.                 }
  160.  
  161.                 m_camera.SetFrustum(pSysCam->GetViewSurfaceX(), pSysCam->GetViewSurfaceZ(), fov, nearPlane, farPlane, pSysCam->GetPixelAspectRatio());
  162.  
  163.                 //TODO: (14, 06, 2010, "the player view should always get updated, this due to the hud being visable, without shocking, in cutscenes - todo is to see if we can optimise this code");
  164.                 IActor* pActor = gEnv->pGameFramework->GetClientActor();
  165.                 if (pActor)
  166.                 {
  167.                         CGameObject* const linkToObj = static_cast<CGameObject*>(pActor->GetEntity()->GetProxy(ENTITY_PROXY_USER));
  168.  
  169.                         if (linkToObj && linkToObj != pLinkedTo)
  170.                         {
  171.                                 linkToObj->PostUpdateView(m_viewParams);
  172.                         }
  173.                 }
  174.  
  175.                 //apply shake & set the view matrix
  176.                 m_viewParams.rotation *= m_viewParams.currentShakeQuat;
  177.                 m_viewParams.rotation.NormalizeSafe();
  178.                 m_viewParams.position += m_viewParams.currentShakeShift;
  179.  
  180.                 // Camera space Rendering calculations on Entity
  181.                 if (pLinkedTo)
  182.                 {
  183.                         IEntity* pLinkedToEntity = pLinkedTo->GetEntity();
  184.                         if (pLinkedToEntity)
  185.                         {
  186.                                 const int slotIndex = 0;
  187.                                 uint32 entityFlags = pLinkedToEntity->GetSlotFlags(slotIndex);
  188.                                 if (entityFlags & ENTITY_SLOT_RENDER_NEAREST)
  189.                                 {
  190.                                         // Get camera pos relative to entity
  191.                                         const Vec3 cameraLocalPos = m_viewParams.position;
  192.  
  193.                                         // Set entity's camera space position
  194.                                         const Vec3 cameraSpacePos(-cameraLocalPos * m_viewParams.rotation);
  195.                                         pLinkedToEntity->SetSlotCameraSpacePos(slotIndex, cameraSpacePos);
  196.  
  197.                                         // Add world pos onto camera local pos
  198.                                         m_viewParams.position = pLinkedToEntity->GetWorldPos() + cameraLocalPos;
  199.                                 }
  200.                         }
  201.                 }
  202.  
  203.                 // Blending between cameras needs to happen after Camera space rendering calculations have been applied
  204.                 // so that the m_viewParams.position is in World Space again
  205.                 m_viewParams.UpdateBlending(frameTime);
  206.  
  207.                 // [VR] specific
  208.                 // Add HMD's pose tracking on top of current camera pose
  209.                 // Each game-title can decide whether to keep this functionality here or (most likely)
  210.                 // move it somewhere else.
  211.  
  212.                 Quat q = m_viewParams.rotation;
  213.                 Vec3 pos = m_viewParams.position;
  214.                 Vec3 p = Vec3(ZERO);
  215.  
  216.                 // Uses the recorded tracking if time demo is on playback
  217.                 // Otherwise uses real tracking from device
  218.                 ITimeDemoRecorder* pTimeDemoRecorder = gEnv->pGameFramework->GetITimeDemoRecorder();
  219.  
  220.                 if (pTimeDemoRecorder && pTimeDemoRecorder->IsPlaying())
  221.                 {
  222.                         STimeDemoFrameRecord record;
  223.                         pTimeDemoRecorder->GetCurrentFrameRecord(record);
  224.  
  225.                         p = q * record.hmdPositionOffset;
  226.                         q = q * record.hmdViewRotation;
  227.                 }
  228.                 else if (bHmdTrackingEnabled)
  229.                 {
  230.                         pHmdDevice->SetAsynCameraCallback(this);
  231.                         if (pHmdTrackingOrigin && pHmdTrackingOrigin->GetIVal() == (int)EHmdTrackingOrigin::Floor)
  232.                         {
  233.                                 const IEntity* pEnt = GetLinkedEntity();
  234.                                 if (const IActor* pActor = gEnv->pGameFramework->GetClientActor())
  235.                                 {
  236.                                         if (pEnt && pActor->GetEntity() == pEnt)
  237.                                         {
  238.                                                 q = pEnt->GetWorldRotation();
  239.                                                 pos = pEnt->GetWorldPos();
  240.                                         }
  241.                                 }
  242.                         }
  243.  
  244.                         const HmdTrackingState& sensorState = pHmdDevice->GetLocalTrackingState();
  245.                         p = q * sensorState.pose.position;
  246.                         q = q * sensorState.pose.orientation;
  247.                 }
  248.  
  249.                 Matrix34 viewMtx(q);
  250.                 viewMtx.SetTranslation(pos + p);
  251.                 m_camera.SetMatrix(viewMtx);
  252.         }
  253.         else
  254.         {
  255.                 m_linkedTo = 0;
  256.  
  257.                 CCryAction* pCryAction = CCryAction::GetCryAction();
  258.                 if (!pCryAction->IsGameSessionMigrating())    // If we're host migrating, leave the camera where it was
  259.                 {
  260.                         // Check if we're leaving a game mid way through - if we are then stop the camera from being reset for a frame or 2 before the unload happens
  261.                         if (!pCryAction->GetIGameSessionHandler()->IsMidGameLeaving())
  262.                         {
  263.                                 m_camera.SetPosition(Vec3(1, 1, 1));
  264.                         }
  265.                 }
  266.         }
  267. }
  268.  
  269. //////////////////////////////////////////////////////////////////////////
  270. bool CView::OnAsyncCameraCallback(const HmdTrackingState& sensorState, IHmdDevice::AsyncCameraContext& context)
  271. {
  272.         ITimeDemoRecorder* pTimeDemoRecorder = gEnv->pGameFramework->GetITimeDemoRecorder();
  273.         if (pTimeDemoRecorder && pTimeDemoRecorder->IsPlaying())
  274.         {
  275.                 return false;
  276.         }
  277.  
  278.         Quat q = m_viewParams.rotation;
  279.         Vec3 pos = m_viewParams.position;
  280.         Vec3 p = Vec3(ZERO);
  281.  
  282.         if (pHmdTrackingOrigin && pHmdTrackingOrigin->GetIVal() == (int)EHmdTrackingOrigin::Floor)
  283.         {
  284.                 const IEntity* pEnt = GetLinkedEntity();
  285.                 if (const IActor* pActor = gEnv->pGameFramework->GetClientActor())
  286.                 {
  287.                         if (pEnt && pActor->GetEntity() == pEnt)
  288.                         {
  289.                                 q = pEnt->GetWorldRotation();
  290.                                 pos = pEnt->GetWorldPos();
  291.                         }
  292.                 }
  293.         }
  294.         p = q * sensorState.pose.position;
  295.         q = q * sensorState.pose.orientation;
  296.  
  297.         Matrix34 viewMtx(q);
  298.         viewMtx.SetTranslation(pos + p);
  299.         context.outputCameraMatrix = viewMtx;
  300.  
  301.         return true;
  302. }
  303.  
  304. //-----------------------------------------------------------------------
  305. void CView::ApplyFrameAdditiveAngles(Quat& cameraOrientation)
  306. {
  307.         if ((m_frameAdditiveAngles.x != 0.f) || (m_frameAdditiveAngles.y != 0.f) || (m_frameAdditiveAngles.z != 0.f))
  308.         {
  309.                 Ang3 cameraAngles(cameraOrientation);
  310.                 cameraAngles += m_frameAdditiveAngles;
  311.  
  312.                 cameraOrientation.SetRotationXYZ(cameraAngles);
  313.  
  314.                 m_frameAdditiveAngles.Set(0.0f, 0.0f, 0.0f);
  315.         }
  316. }
  317.  
  318. //------------------------------------------------------------------------
  319. void CView::SetViewShake(Ang3 shakeAngle, Vec3 shakeShift, float duration, float frequency, float randomness, int shakeID, bool bFlipVec, bool bUpdateOnly, bool bGroundOnly)
  320. {
  321.         SShakeParams params;
  322.         params.shakeAngle = shakeAngle;
  323.         params.shakeShift = shakeShift;
  324.         params.frequency = frequency;
  325.         params.randomness = randomness;
  326.         params.shakeID = shakeID;
  327.         params.bFlipVec = bFlipVec;
  328.         params.bUpdateOnly = bUpdateOnly;
  329.         params.bGroundOnly = bGroundOnly;
  330.         params.fadeInDuration = 0;          //
  331.         params.fadeOutDuration = duration;  // originally it was faded out from start. that is why the values are set this way here, to preserve compatibility.
  332.         params.sustainDuration = 0;         //
  333.  
  334.         SetViewShakeEx(params);
  335. }
  336.  
  337. //------------------------------------------------------------------------
  338. void CView::SetViewShakeEx(const SShakeParams& params)
  339. {
  340.         float shakeMult = GetScale();
  341.         if (shakeMult < 0.001f)
  342.                 return;
  343.  
  344.         int shakes(m_shakes.size());
  345.         SShake* pSetShake(nullptr);
  346.  
  347.         for (int i = 0; i < shakes; ++i)
  348.         {
  349.                 SShake* pShake = &m_shakes[i];
  350.                 if (pShake->ID == params.shakeID)
  351.                 {
  352.                         pSetShake = pShake;
  353.                         break;
  354.                 }
  355.         }
  356.  
  357.         if (!pSetShake)
  358.         {
  359.                 m_shakes.push_back(SShake(params.shakeID));
  360.                 pSetShake = &m_shakes.back();
  361.         }
  362.  
  363.         if (pSetShake)
  364.         {
  365.                 // this can be set dynamically
  366.                 pSetShake->frequency = max(0.00001f, params.frequency);
  367.  
  368.                 // the following are set on a 'new' shake as well
  369.                 if (params.bUpdateOnly == false)
  370.                 {
  371.                         pSetShake->amount = params.shakeAngle * shakeMult;
  372.                         pSetShake->amountVector = params.shakeShift * shakeMult;
  373.                         pSetShake->randomness = params.randomness;
  374.                         pSetShake->doFlip = params.bFlipVec;
  375.                         pSetShake->groundOnly = params.bGroundOnly;
  376.                         pSetShake->isSmooth = params.isSmooth;
  377.                         pSetShake->permanent = params.bPermanent;
  378.                         pSetShake->fadeInDuration = params.fadeInDuration;
  379.                         pSetShake->sustainDuration = params.sustainDuration;
  380.                         pSetShake->fadeOutDuration = params.fadeOutDuration;
  381.                         pSetShake->timeDone = 0;
  382.                         pSetShake->updating = true;
  383.                         pSetShake->interrupted = false;
  384.                         pSetShake->goalShake = Quat(ZERO);
  385.                         pSetShake->goalShakeSpeed = Quat(ZERO);
  386.                         pSetShake->goalShakeVector = Vec3(ZERO);
  387.                         pSetShake->goalShakeVectorSpeed = Vec3(ZERO);
  388.                         pSetShake->nextShake = 0.0f;
  389.                 }
  390.         }
  391. }
  392.  
  393. //------------------------------------------------------------------------
  394. void CView::SetScale(const float scale)
  395. {
  396.         CRY_ASSERT_MESSAGE(scale == 1.0f || m_scale == 1.0f, "Attempting to CView::SetScale but has already been set!");
  397.         m_scale = scale;
  398. }
  399.  
  400. void CView::SetZoomedScale(const float scale)
  401. {
  402.         CRY_ASSERT_MESSAGE(scale == 1.0f || m_zoomedScale == 1.0f, "Attempting to CView::SetZoomedScale but has already been set!");
  403.         m_zoomedScale = scale;
  404. }
  405.  
  406. //------------------------------------------------------------------------
  407. const float CView::GetScale()
  408. {
  409.         float shakeMult(pCamShakeMult->GetFVal());
  410.         return m_scale * shakeMult * m_zoomedScale;
  411. }
  412.  
  413. //------------------------------------------------------------------------
  414. void CView::ProcessShaking(float frameTime)
  415. {
  416.         m_viewParams.currentShakeQuat.SetIdentity();
  417.         m_viewParams.currentShakeShift.zero();
  418.         m_viewParams.shakingRatio = 0;
  419.         m_viewParams.groundOnly = false;
  420.  
  421.         int shakes(m_shakes.size());
  422.         for (int i = 0; i < shakes; ++i)
  423.                 ProcessShake(&m_shakes[i], frameTime);
  424. }
  425.  
  426. //------------------------------------------------------------------------
  427. void CView::ProcessShake(SShake* pShake, float frameTime)
  428. {
  429.         if (!pShake->updating)
  430.                 return;
  431.  
  432.         pShake->timeDone += frameTime;
  433.  
  434.         if (pShake->isSmooth)
  435.         {
  436.                 ProcessShakeSmooth(pShake, frameTime);
  437.         }
  438.         else
  439.         {
  440.                 ProcessShakeNormal(pShake, frameTime);
  441.         }
  442. }
  443.  
  444. //------------------------------------------------------------------------
  445. void CView::ProcessShakeNormal(SShake* pShake, float frameTime)
  446. {
  447.         float endSustain = pShake->fadeInDuration + pShake->sustainDuration;
  448.         float totalDuration = endSustain + pShake->fadeOutDuration;
  449.  
  450.         bool finalDamping = (!pShake->permanent && pShake->timeDone > totalDuration) || (pShake->interrupted && pShake->ratio < 0.05f);
  451.  
  452.         if (finalDamping)
  453.                 ProcessShakeNormal_FinalDamping(pShake, frameTime);
  454.         else
  455.         {
  456.                 ProcessShakeNormal_CalcRatio(pShake, frameTime, endSustain);
  457.                 ProcessShakeNormal_DoShaking(pShake, frameTime);
  458.  
  459.                 //for the global shaking ratio keep the biggest
  460.                 if (pShake->groundOnly)
  461.                         m_viewParams.groundOnly = true;
  462.                 m_viewParams.shakingRatio = max(m_viewParams.shakingRatio, pShake->ratio);
  463.                 m_viewParams.currentShakeQuat *= pShake->shakeQuat;
  464.                 m_viewParams.currentShakeShift += pShake->shakeVector;
  465.         }
  466. }
  467.  
  468. //////////////////////////////////////////////////////////////////////////
  469. void CView::ProcessShakeSmooth(SShake* pShake, float frameTime)
  470. {
  471.         assert(pShake->timeDone >= 0);
  472.  
  473.         float endTimeFadeIn = pShake->fadeInDuration;
  474.         float endTimeSustain = pShake->sustainDuration + endTimeFadeIn;
  475.         float totalTime = endTimeSustain + pShake->fadeOutDuration;
  476.  
  477.         if (pShake->interrupted && endTimeFadeIn <= pShake->timeDone && pShake->timeDone < endTimeSustain)
  478.         {
  479.                 pShake->timeDone = endTimeSustain;
  480.         }
  481.  
  482.         float damping = 1.f;
  483.         if (pShake->timeDone < endTimeFadeIn)
  484.         {
  485.                 damping = pShake->timeDone / endTimeFadeIn;
  486.         }
  487.         else if (endTimeSustain < pShake->timeDone && pShake->timeDone < totalTime)
  488.         {
  489.                 damping = (totalTime - pShake->timeDone) / (totalTime - endTimeSustain);
  490.         }
  491.         else if (totalTime <= pShake->timeDone)
  492.         {
  493.                 pShake->shakeQuat.SetIdentity();
  494.                 pShake->shakeVector.zero();
  495.                 pShake->ratio = 0.0f;
  496.                 pShake->nextShake = 0.0f;
  497.                 pShake->flip = false;
  498.                 pShake->updating = false;
  499.                 return;
  500.         }
  501.  
  502.         ProcessShakeSmooth_DoShaking(pShake, frameTime);
  503.  
  504.         if (pShake->groundOnly)
  505.                 m_viewParams.groundOnly = true;
  506.         pShake->ratio = (3.f - 2.f * damping) * damping * damping; // smooth ration change
  507.         m_viewParams.shakingRatio = max(m_viewParams.shakingRatio, pShake->ratio);
  508.         m_viewParams.currentShakeQuat *= Quat::CreateSlerp(IDENTITY, pShake->shakeQuat, pShake->ratio);
  509.         m_viewParams.currentShakeShift += Vec3::CreateLerp(ZERO, pShake->shakeVector, pShake->ratio);
  510. }
  511.  
  512. //////////////////////////////////////////////////////////////////////////
  513. void CView::GetRandomQuat(Quat& quat, SShake* pShake)
  514. {
  515.         quat.SetRotationXYZ(pShake->amount);
  516.         float randomAmt(pShake->randomness);
  517.         float len(fabs(pShake->amount.x) + fabs(pShake->amount.y) + fabs(pShake->amount.z));
  518.         len /= 3.f;
  519.         float r = len * randomAmt;
  520.         quat *= Quat::CreateRotationXYZ(Ang3(cry_random(-r, r), cry_random(-r, r), cry_random(-r, r)));
  521. }
  522.  
  523. //////////////////////////////////////////////////////////////////////////
  524. void CView::GetRandomVector(Vec3& vec, SShake* pShake)
  525. {
  526.         vec = pShake->amountVector;
  527.         float randomAmt(pShake->randomness);
  528.         float len = fabs(pShake->amountVector.x) + fabs(pShake->amountVector.y) + fabs(pShake->amountVector.z);
  529.         len /= 3.f;
  530.         float r = len * randomAmt;
  531.         vec += Vec3(cry_random(-r, r), cry_random(-r, r), cry_random(-r, r));
  532. }
  533.  
  534. //////////////////////////////////////////////////////////////////////////
  535. void CView::CubeInterpolateQuat(float t, SShake* pShake)
  536. {
  537.         Quat p0 = pShake->startShake;
  538.         Quat p1 = pShake->goalShake;
  539.         Quat v0 = pShake->startShakeSpeed * 0.5f;
  540.         Quat v1 = pShake->goalShakeSpeed * 0.5f;
  541.  
  542.         pShake->shakeQuat = (((p0 * 2.f + p1 * -2.f + v0 + v1) * t
  543.                               + (p0 * -3.f + p1 * 3.f + v0 * -2.f - v1)) * t
  544.                              + (v0)) * t
  545.                             + p0;
  546.  
  547.         pShake->shakeQuat.Normalize();
  548. }
  549.  
  550. //////////////////////////////////////////////////////////////////////////
  551. void CView::CubeInterpolateVector(float t, SShake* pShake)
  552. {
  553.         Vec3 p0 = pShake->startShakeVector;
  554.         Vec3 p1 = pShake->goalShakeVector;
  555.         Vec3 v0 = pShake->startShakeVectorSpeed * 0.8f;
  556.         Vec3 v1 = pShake->goalShakeVectorSpeed * 0.8f;
  557.  
  558.         pShake->shakeVector = (((p0 * 2.f + p1 * -2.f + v0 + v1) * t
  559.                                 + (p0 * -3.f + p1 * 3.f + v0 * -2.f - v1)) * t
  560.                                + (v0)) * t
  561.                               + p0;
  562.  
  563. }
  564.  
  565. //////////////////////////////////////////////////////////////////////////
  566. void CView::ProcessShakeSmooth_DoShaking(SShake* pShake, float frameTime)
  567. {
  568.         if (pShake->nextShake <= 0.0f)
  569.         {
  570.                 pShake->nextShake = pShake->frequency;
  571.  
  572.                 pShake->startShake = pShake->goalShake;
  573.                 pShake->startShakeSpeed = pShake->goalShakeSpeed;
  574.                 pShake->startShakeVector = pShake->goalShakeVector;
  575.                 pShake->startShakeVectorSpeed = pShake->goalShakeVectorSpeed;
  576.  
  577.                 GetRandomQuat(pShake->goalShake, pShake);
  578.                 GetRandomQuat(pShake->goalShakeSpeed, pShake);
  579.                 GetRandomVector(pShake->goalShakeVector, pShake);
  580.                 GetRandomVector(pShake->goalShakeVectorSpeed, pShake);
  581.  
  582.                 if (pShake->flip)
  583.                 {
  584.                         pShake->goalShake.Invert();
  585.                         pShake->goalShakeSpeed.Invert();
  586.                         pShake->goalShakeVector = -pShake->goalShakeVector;
  587.                         pShake->goalShakeVectorSpeed = -pShake->goalShakeVectorSpeed;
  588.                 }
  589.  
  590.                 if (pShake->doFlip)
  591.                         pShake->flip = !pShake->flip;
  592.  
  593.         }
  594.  
  595.         pShake->nextShake -= frameTime;
  596.  
  597.         float t = (pShake->frequency - pShake->nextShake) / pShake->frequency;
  598.         CubeInterpolateQuat(t, pShake);
  599.         CubeInterpolateVector(t, pShake);
  600. }
  601.  
  602. //////////////////////////////////////////////////////////////////////////
  603. void CView::ProcessShakeNormal_FinalDamping(SShake* pShake, float frameTime)
  604. {
  605.         pShake->shakeQuat = Quat::CreateSlerp(pShake->shakeQuat, IDENTITY, frameTime * 5.0f);
  606.         m_viewParams.currentShakeQuat *= pShake->shakeQuat;
  607.  
  608.         pShake->shakeVector = Vec3::CreateLerp(pShake->shakeVector, ZERO, frameTime * 5.0f);
  609.         m_viewParams.currentShakeShift += pShake->shakeVector;
  610.  
  611.         float svlen2(pShake->shakeVector.len2());
  612.         bool quatIsIdentity(Quat::IsEquivalent(IDENTITY, pShake->shakeQuat, 0.0001f));
  613.  
  614.         if (quatIsIdentity && svlen2 < 0.01f)
  615.         {
  616.                 pShake->shakeQuat.SetIdentity();
  617.                 pShake->shakeVector.zero();
  618.  
  619.                 pShake->ratio = 0.0f;
  620.                 pShake->nextShake = 0.0f;
  621.                 pShake->flip = false;
  622.  
  623.                 pShake->updating = false;
  624.         }
  625. }
  626.  
  627. // "ratio" is the amplitude of the shaking
  628. void CView::ProcessShakeNormal_CalcRatio(SShake* pShake, float frameTime, float endSustain)
  629. {
  630.         const float FADEOUT_TIME_WHEN_INTERRUPTED = 0.5f;
  631.  
  632.         if (pShake->interrupted)
  633.                 pShake->ratio = max(0.f, pShake->ratio - (frameTime / FADEOUT_TIME_WHEN_INTERRUPTED));    // fadeout after interrupted
  634.         else if (pShake->timeDone >= endSustain && pShake->fadeOutDuration > 0)
  635.         {
  636.                 float timeFading = pShake->timeDone - endSustain;
  637.                 pShake->ratio = clamp_tpl(1.f - timeFading / pShake->fadeOutDuration, 0.f, 1.f);   // fadeOut
  638.         }
  639.         else if (pShake->timeDone >= pShake->fadeInDuration)
  640.         {
  641.                 pShake->ratio = 1.f; // sustain
  642.         }
  643.         else
  644.         {
  645.                 pShake->ratio = min(1.f, pShake->timeDone / pShake->fadeInDuration);   // fadeIn
  646.         }
  647.  
  648.         if (pShake->permanent && pShake->timeDone >= pShake->fadeInDuration && !pShake->interrupted)
  649.                 pShake->ratio = 1.f; // permanent standing
  650. }
  651.  
  652. //////////////////////////////////////////////////////////////////////////
  653. void CView::ProcessShakeNormal_DoShaking(SShake* pShake, float frameTime)
  654. {
  655.         float t;
  656.         if (pShake->nextShake <= 0.0f)
  657.         {
  658.                 //angular
  659.                 pShake->goalShake.SetRotationXYZ(pShake->amount);
  660.                 if (pShake->flip)
  661.                         pShake->goalShake.Invert();
  662.  
  663.                 //translational
  664.                 pShake->goalShakeVector = pShake->amountVector;
  665.                 if (pShake->flip)
  666.                         pShake->goalShakeVector = -pShake->goalShakeVector;
  667.  
  668.                 if (pShake->doFlip)
  669.                         pShake->flip = !pShake->flip;
  670.  
  671.                 //randomize it a little
  672.                 float randomAmt(pShake->randomness);
  673.                 float len(fabs(pShake->amount.x) + fabs(pShake->amount.y) + fabs(pShake->amount.z));
  674.                 len /= 3.0f;
  675.                 float r = len * randomAmt;
  676.                 pShake->goalShake *= Quat::CreateRotationXYZ(Ang3(cry_random(-r, r), cry_random(-r, r), cry_random(-r, r)));
  677.  
  678.                 //translational randomization
  679.                 len = fabs(pShake->amountVector.x) + fabs(pShake->amountVector.y) + fabs(pShake->amountVector.z);
  680.                 len /= 3.0f;
  681.                 r = len * randomAmt;
  682.                 pShake->goalShakeVector += Vec3(cry_random(-r, r), cry_random(-r, r), cry_random(-r, r));
  683.  
  684.                 //damp & bounce it in a non linear fashion
  685.                 t = 1.0f - (pShake->ratio * pShake->ratio);
  686.                 pShake->goalShake = Quat::CreateSlerp(pShake->goalShake, IDENTITY, t);
  687.                 pShake->goalShakeVector = Vec3::CreateLerp(pShake->goalShakeVector, ZERO, t);
  688.  
  689.                 pShake->nextShake = pShake->frequency;
  690.         }
  691.  
  692.         pShake->nextShake = max(0.0f, pShake->nextShake - frameTime);
  693.  
  694.         t = min(1.0f, frameTime * (1.0f / pShake->frequency));
  695.         pShake->shakeQuat = Quat::CreateSlerp(pShake->shakeQuat, pShake->goalShake, t);
  696.         pShake->shakeQuat.Normalize();
  697.         pShake->shakeVector = Vec3::CreateLerp(pShake->shakeVector, pShake->goalShakeVector, t);
  698. }
  699.  
  700. //------------------------------------------------------------------------
  701. void CView::StopShake(int shakeID)
  702. {
  703.         uint32 num = m_shakes.size();
  704.         for (uint32 i = 0; i < num; ++i)
  705.         {
  706.                 if (m_shakes[i].ID == shakeID && m_shakes[i].updating)
  707.                 {
  708.                         m_shakes[i].interrupted = true;
  709.                 }
  710.         }
  711. }
  712.  
  713. //------------------------------------------------------------------------
  714. void CView::ResetShaking()
  715. {
  716.         // disable shakes
  717.         std::vector<SShake>::iterator iter = m_shakes.begin();
  718.         std::vector<SShake>::iterator iterEnd = m_shakes.end();
  719.         while (iter != iterEnd)
  720.         {
  721.                 SShake& shake = *iter;
  722.                 shake.updating = false;
  723.                 shake.timeDone = 0;
  724.                 ++iter;
  725.         }
  726. }
  727.  
  728. //------------------------------------------------------------------------
  729. void CView::LinkTo(IGameObject* follow)
  730. {
  731.         CRY_ASSERT(follow);
  732.         m_linkedTo = follow->GetEntityId();
  733.         m_viewParams.targetPos = follow->GetEntity()->GetWorldPos();
  734. }
  735.  
  736. //------------------------------------------------------------------------
  737. void CView::LinkTo(IEntity* follow)
  738. {
  739.         CRY_ASSERT(follow);
  740.         m_linkedTo = follow->GetId();
  741.         m_viewParams.targetPos = follow->GetWorldPos();
  742. }
  743.  
  744. //------------------------------------------------------------------------
  745. void CView::SetFrameAdditiveCameraAngles(const Ang3& addFrameAngles)
  746. {
  747.         m_frameAdditiveAngles = addFrameAngles;
  748. }
  749.  
  750. //------------------------------------------------------------------------
  751. CGameObject* CView::GetLinkedGameObject()
  752. {
  753.         IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_linkedTo);
  754.  
  755.         if (!pEntity)
  756.                 return nullptr;
  757.  
  758.         return static_cast<CGameObject*>(pEntity->GetProxy(ENTITY_PROXY_USER));
  759. }
  760.  
  761. //------------------------------------------------------------------------
  762. IEntity* CView::GetLinkedEntity()
  763. {
  764.         IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_linkedTo);
  765.         return pEntity;
  766. }
  767.  
  768. void CView::GetMemoryUsage(ICrySizer* s) const
  769. {
  770.         s->AddObject(this, sizeof(*this));
  771.         s->AddObject(m_shakes);
  772. }
  773.  
  774. void CView::Serialize(TSerialize ser)
  775. {
  776.         if (ser.IsReading())
  777.         {
  778.                 ResetShaking();
  779.         }
  780. }
  781.  
  782. //////////////////////////////////////////////////////////////////////////
  783. void CView::PostSerialize()
  784. {
  785.         CreateAudioListener();
  786. }
  787.  
  788. //////////////////////////////////////////////////////////////////////////
  789. void CView::OnEntityEvent(IEntity* pEntity, SEntityEvent& event)
  790. {
  791.         switch (event.event)
  792.         {
  793.         case ENTITY_EVENT_DONE:
  794.                 {
  795.                         // In case something destroys our listener entity before we had the chance to remove it.
  796.                         if ((m_pAudioListener != nullptr) && (pEntity->GetId() == m_pAudioListener->GetId()))
  797.                         {
  798.                                 gEnv->pEntitySystem->RemoveEntityEventListener(m_pAudioListener->GetId(), ENTITY_EVENT_DONE, this);
  799.                                 m_pAudioListener = nullptr;
  800.                         }
  801.  
  802.                         break;
  803.                 }
  804.         default:
  805.                 {
  806.                         break;
  807.                 }
  808.         }
  809. }
  810.  
  811. //////////////////////////////////////////////////////////////////////////
  812. void CView::CreateAudioListener()
  813. {
  814.         if (m_pAudioListener == nullptr)
  815.         {
  816.                 SEntitySpawnParams oEntitySpawnParams;
  817.                 oEntitySpawnParams.sName = "AudioListener";
  818.                 oEntitySpawnParams.pClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("AudioListener");
  819.  
  820.                 // We don't want the audio listener to serialize as the entity gets completely removed and recreated during save/load!
  821.                 // NOTE: If we set ENTITY_FLAG_NO_SAVE *after* we spawn the entity, it will make it to m_dynamicEntities in GameSerialize.cpp
  822.                 // (via CGameSerialize::OnSpawn) and GameSerialize will attempt to serialize it despite the flag with current (5.2.2) implementation
  823.                 oEntitySpawnParams.nFlags = ENTITY_FLAG_TRIGGER_AREAS | ENTITY_FLAG_NO_SAVE;
  824.                 oEntitySpawnParams.nFlagsExtended = ENTITY_FLAG_EXTENDED_AUDIO_LISTENER;
  825.                 m_pAudioListener = gEnv->pEntitySystem->SpawnEntity(oEntitySpawnParams, true);
  826.                 if (m_pAudioListener != nullptr)
  827.                 {
  828.                         gEnv->pEntitySystem->AddEntityEventListener(m_pAudioListener->GetId(), ENTITY_EVENT_DONE, this);
  829.                         CryFixedStringT<64> sTemp;
  830.                         sTemp.Format("AudioListener(%d)", static_cast<int>(m_pAudioListener->GetId()));
  831.                         m_pAudioListener->SetName(sTemp.c_str());
  832.  
  833.                         IEntityAudioComponent* pIEntityAudioComponent = m_pAudioListener->GetOrCreateComponent<IEntityAudioComponent>();
  834.                         CRY_ASSERT(pIEntityAudioComponent);
  835.                 }
  836.                 else
  837.                 {
  838.                         CryFatalError("<Audio>: Audio listener creation failed in CView::CreateAudioListener!");
  839.                 }
  840.         }
  841.         else
  842.         {
  843.                 m_pAudioListener->SetFlagsExtended(m_pAudioListener->GetFlagsExtended() | ENTITY_FLAG_EXTENDED_AUDIO_LISTENER);
  844.                 m_pAudioListener->InvalidateTM(ENTITY_XFORM_POS);
  845.         }
  846. }
  847.  
  848. //////////////////////////////////////////////////////////////////////////
  849. void CView::UpdateAudioListener(Matrix34 const& rMatrix)
  850. {
  851.         if (m_pAudioListener != nullptr)
  852.         {
  853.                 m_pAudioListener->SetWorldTM(rMatrix);
  854.         }
  855. }
  856.  
  857. //////////////////////////////////////////////////////////////////////////
  858. void CView::SetActive(bool const bActive)
  859. {
  860.         if (bActive)
  861.         {
  862.                 // Make sure we have a valid audio listener entity on an active view!
  863.                 CreateAudioListener();
  864.         }
  865.         else if (m_pAudioListener != nullptr && (m_pAudioListener->GetFlags() & ENTITY_FLAG_TRIGGER_AREAS) != 0)
  866.         {
  867.                 gEnv->pEntitySystem->GetAreaManager()->ExitAllAreas(m_pAudioListener->GetId());
  868.                 m_pAudioListener->SetFlagsExtended(m_pAudioListener->GetFlagsExtended() & ~ENTITY_FLAG_EXTENDED_AUDIO_LISTENER);
  869.         }
  870. }
  871.  
downloadView.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top