Initial commit

This commit is contained in:
alexpete
2021-03-05 11:26:34 -08:00
commit a10351f38d
27091 changed files with 5521199 additions and 0 deletions
@@ -0,0 +1,359 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "CrySystem_precompiled.h"
#include "DebugCamera.h"
#include "ISystem.h"
#include "Cry_Camera.h"
#include "IViewSystem.h"
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
#include <AzFramework/Input/Devices/Gamepad/InputDeviceGamepad.h>
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
using namespace AzFramework;
namespace LegacyViewSystem
{
const float g_moveScaleIncrement = 0.1f;
const float g_moveScaleMin = 0.01f;
const float g_moveScaleMax = 10.0f;
const float g_mouseMoveScale = 0.1f;
const float g_gamepadRotationSpeed = 5.0f;
const float g_mouseMaxRotationSpeed = 270.0f;
const float g_moveSpeed = 10.0f;
const float g_maxPitch = 85.0f;
const float g_boostMultiplier = 10.0f;
const float g_minRotationSpeed = 15.0f;
const float g_maxRotationSpeed = 70.0f;
///////////////////////////////////////////////////////////////////////////////
DebugCamera::DebugCamera()
: m_mouseMoveMode(0)
, m_isYInverted(0)
, m_cameraMode(DebugCamera::ModeOff)
, m_cameraYawInput(0.0f)
, m_cameraPitchInput(0.0f)
, m_cameraYaw(0.0f)
, m_cameraPitch(0.0f)
, m_moveInput(ZERO)
, m_moveScale(1.0f)
, m_oldMoveScale(1.0f)
, m_position(ZERO)
, m_view(IDENTITY)
{
InputChannelEventListener::Connect();
}
///////////////////////////////////////////////////////////////////////////////
DebugCamera::~DebugCamera()
{
InputChannelEventListener::Disconnect();
}
///////////////////////////////////////////////////////////////////////////////
void DebugCamera::OnEnable()
{
m_position = gEnv->pSystem->GetViewCamera().GetPosition();
m_moveInput = Vec3_Zero;
Ang3 cameraAngles = Ang3(gEnv->pSystem->GetViewCamera().GetMatrix());
m_cameraYaw = RAD2DEG(cameraAngles.z);
m_cameraPitch = RAD2DEG(cameraAngles.x);
m_view = Matrix33(Ang3(DEG2RAD(m_cameraPitch), 0.0f, DEG2RAD(m_cameraYaw)));
m_cameraYawInput = 0.0f;
m_cameraPitchInput = 0.0f;
m_mouseMoveMode = 0;
m_cameraMode = DebugCamera::ModeFree;
}
///////////////////////////////////////////////////////////////////////////////
void DebugCamera::OnDisable()
{
m_mouseMoveMode = 0;
m_cameraMode = DebugCamera::ModeOff;
}
///////////////////////////////////////////////////////////////////////////////
void DebugCamera::OnInvertY()
{
m_isYInverted = !m_isYInverted;
}
///////////////////////////////////////////////////////////////////////////////
void DebugCamera::OnNextMode()
{
if (m_cameraMode == DebugCamera::ModeFree)
{
m_cameraMode = DebugCamera::ModeFixed;
}
// ...
else if (m_cameraMode == DebugCamera::ModeFixed)
{
// this is the last mode, go to disabled.
OnDisable();
}
}
///////////////////////////////////////////////////////////////////////////////
void DebugCamera::Update()
{
if (m_cameraMode == DebugCamera::ModeOff)
{
return;
}
float rotationSpeed = clamp_tpl(m_moveScale, g_minRotationSpeed, g_maxRotationSpeed);
UpdateYaw(m_cameraYawInput * rotationSpeed * gEnv->pTimer->GetFrameTime());
UpdatePitch(m_cameraPitchInput * rotationSpeed * gEnv->pTimer->GetFrameTime());
m_view = Matrix33(Ang3(DEG2RAD(m_cameraPitch), 0.0f, DEG2RAD(m_cameraYaw)));
UpdatePosition(m_moveInput);
// update the listener of the active view
if (IView* view = gEnv->pSystem->GetIViewSystem()->GetActiveView())
{
view->UpdateAudioListener(Matrix34(m_view, m_position));
}
}
///////////////////////////////////////////////////////////////////////////////
void DebugCamera::PostUpdate()
{
if (m_cameraMode == DebugCamera::ModeOff)
{
return;
}
CCamera& camera = gEnv->pSystem->GetViewCamera();
camera.SetMatrix(Matrix34(m_view, m_position));
const float FONT_COLOR[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
gEnv->pRenderer->Draw2dLabel(0.0f, 700.0f, 1.3f, FONT_COLOR, false,
"Debug Camera: pos [ %.3f, %.3f, %.3f ] p/y [ %.1f, %.1f ] dir [ %.3f, %.3f, %.3f ] scl %.2f inv %d",
m_position.x, m_position.y, m_position.z,
m_cameraPitch, m_cameraYaw,
m_view.GetColumn1().x, m_view.GetColumn1().y, m_view.GetColumn1().z,
m_moveScale,
m_isYInverted);
}
///////////////////////////////////////////////////////////////////////////////
bool DebugCamera::OnInputChannelEventFiltered(const InputChannel& inputChannel)
{
if (!IsEnabled() || m_cameraMode == DebugCamera::ModeFixed || gEnv->pConsole->IsOpened())
{
return false;
}
const InputDeviceId& deviceId = inputChannel.GetInputDevice().GetInputDeviceId();
const InputChannelId& channelId = inputChannel.GetInputChannelId();
const float eventValue = inputChannel.GetValue();
if (InputDeviceKeyboard::IsKeyboardDevice(deviceId))
{
if (channelId == InputDeviceKeyboard::Key::AlphanumericW)
{
m_moveInput.y = eventValue;
}
else if (channelId == InputDeviceKeyboard::Key::AlphanumericS)
{
m_moveInput.y = -eventValue;
}
else if (channelId == InputDeviceKeyboard::Key::AlphanumericA)
{
m_moveInput.x = -eventValue;
}
else if (channelId == InputDeviceKeyboard::Key::AlphanumericD)
{
m_moveInput.x = eventValue;
}
else if (channelId == InputDeviceKeyboard::Key::ModifierShiftL)
{
if (inputChannel.IsStateEnded())
{
m_moveScale = m_oldMoveScale;
}
else if (inputChannel.IsStateBegan())
{
m_oldMoveScale = m_moveScale;
m_moveScale = clamp_tpl(m_moveScale * g_boostMultiplier, g_moveScaleMin, g_moveScaleMax);
}
}
}
else if (InputDeviceMouse::IsMouseDevice(deviceId))
{
if (channelId == InputDeviceMouse::Movement::Z)
{
if (inputChannel.GetValue() > 0)
{
m_moveScale = clamp_tpl(m_moveScale + g_moveScaleIncrement, g_moveScaleMin, g_moveScaleMax);
}
else
{
m_moveScale = clamp_tpl(m_moveScale - g_moveScaleIncrement, g_moveScaleMin, g_moveScaleMax);
}
}
else if (channelId == InputDeviceMouse::Movement::X)
{
//KC: If both left and right mouse buttons are pressed then use
//the mouse movement for horizontal movement.
if (2 != m_mouseMoveMode)
{
UpdateYaw(fsgnf(-eventValue) * clamp_tpl(fabs_tpl(eventValue) * m_moveScale, 0.0f, g_mouseMaxRotationSpeed) * gEnv->pTimer->GetFrameTime());
}
else
{
UpdatePosition(Vec3(eventValue * g_mouseMoveScale, 0.0f, 0.0f));
}
}
else if (channelId == InputDeviceMouse::Movement::Y)
{
//KC: If both left and right mouse buttons are pressed then use
//the mouse movement for vertical movement.
if (2 != m_mouseMoveMode)
{
UpdatePitch(fsgnf(-eventValue) * clamp_tpl(fabs_tpl(eventValue) * m_moveScale, 0.0f, g_mouseMaxRotationSpeed) * gEnv->pTimer->GetFrameTime());
}
else
{
UpdatePosition(Vec3(0.0f, 0.0f, -eventValue * g_mouseMoveScale));
}
}
else if (channelId == InputDeviceMouse::Button::Left)
{
if (inputChannel.IsStateEnded())
{
m_mouseMoveMode = clamp_tpl(m_mouseMoveMode - 1, 0, 2);
}
else
{
m_mouseMoveMode = clamp_tpl(m_mouseMoveMode + 1, 0, 2);
}
}
else if (channelId == InputDeviceMouse::Button::Right)
{
if (inputChannel.IsStateEnded())
{
m_mouseMoveMode = clamp_tpl(m_mouseMoveMode - 1, 0, 2);
}
else
{
m_mouseMoveMode = clamp_tpl(m_mouseMoveMode + 1, 0, 2);
}
}
}
else if (InputDeviceGamepad::IsGamepadDevice(deviceId))
{
if (channelId == InputDeviceGamepad::Button::DU)
{
m_moveScale = clamp_tpl(m_moveScale + g_moveScaleIncrement, g_moveScaleMin, g_moveScaleMax);
}
else if (channelId == InputDeviceGamepad::Button::DD)
{
m_moveScale = clamp_tpl(m_moveScale - g_moveScaleIncrement, g_moveScaleMin, g_moveScaleMax);
}
else if (channelId == InputDeviceGamepad::Trigger::L2)
{
m_moveInput.z = -eventValue;
}
else if (channelId == InputDeviceGamepad::Trigger::R2)
{
m_moveInput.z = eventValue;
}
else if (channelId == InputDeviceGamepad::ThumbStickAxis1D::LX)
{
m_moveInput.x = eventValue;
}
else if (channelId == InputDeviceGamepad::ThumbStickAxis1D::LY)
{
m_moveInput.y = eventValue;
}
else if (channelId == InputDeviceGamepad::ThumbStickAxis1D::RX)
{
m_cameraYawInput = -eventValue * g_gamepadRotationSpeed;
}
else if (channelId == InputDeviceGamepad::ThumbStickAxis1D::RY)
{
m_cameraPitchInput = eventValue * g_gamepadRotationSpeed;
}
//KC: Use the shoulder buttons to temporarily boost or reduce the scale.
else if (channelId == InputDeviceGamepad::Button::L1)
{
if (inputChannel.IsStateEnded())
{
m_moveScale = m_oldMoveScale;
}
else if (inputChannel.IsStateBegan())
{
m_oldMoveScale = m_moveScale;
m_moveScale = clamp_tpl(m_moveScale / g_boostMultiplier, g_moveScaleMin, g_moveScaleMax);
}
}
else if (channelId == InputDeviceGamepad::Button::R1)
{
if (inputChannel.IsStateEnded())
{
m_moveScale = m_oldMoveScale;
}
else if (inputChannel.IsStateBegan())
{
m_oldMoveScale = m_moveScale;
m_moveScale = clamp_tpl(m_moveScale * g_boostMultiplier, g_moveScaleMin, g_moveScaleMax);
}
}
}
return false;
}
///////////////////////////////////////////////////////////////////////////////
void DebugCamera::UpdatePitch(float amount)
{
if (m_isYInverted)
{
amount = -amount;
}
m_cameraPitch += amount;
m_cameraPitch = clamp_tpl(m_cameraPitch, -g_maxPitch, g_maxPitch);
}
///////////////////////////////////////////////////////////////////////////////
void DebugCamera::UpdateYaw(float amount)
{
m_cameraYaw += amount;
if (m_cameraYaw < 0.0f)
{
m_cameraYaw += 360.0f;
}
else if (m_cameraYaw >= 360.0f)
{
m_cameraYaw -= 360.0f;
}
}
///////////////////////////////////////////////////////////////////////////////
void DebugCamera::UpdatePosition(const Vec3& amount)
{
Vec3 diff = amount * g_moveSpeed * m_moveScale * gEnv->pTimer->GetFrameTime();
MovePosition(diff);
}
void DebugCamera::MovePosition(const Vec3& offset)
{
m_position += m_view.GetColumn0() * offset.x;
m_position += m_view.GetColumn1() * offset.y;
m_position += m_view.GetColumn2() * offset.z;
}
} // namespace LegacyViewSystem
@@ -0,0 +1,83 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzFramework/Input/Events/InputChannelEventListener.h>
namespace LegacyViewSystem
{
///////////////////////////////////////////////////////////////////////////////
class DebugCamera
: public AzFramework::InputChannelEventListener
{
public:
enum Mode
{
ModeOff, // no debug cam
ModeFree, // free-fly
ModeFixed, // fixed cam, control goes back to game
};
DebugCamera();
~DebugCamera() override;
void Update();
void PostUpdate();
bool IsEnabled();
bool IsFixed();
bool IsFree();
// AzFramework::InputChannelEventListener
bool OnInputChannelEventFiltered(const AzFramework::InputChannel& inputChannel) override;
void OnEnable();
void OnDisable();
void OnInvertY();
void OnNextMode();
void UpdatePitch(float amount);
void UpdateYaw(float amount);
void UpdatePosition(const Vec3& amount);
void MovePosition(const Vec3& offset);
protected:
int m_mouseMoveMode;
int m_isYInverted;
int m_cameraMode;
float m_cameraYawInput;
float m_cameraPitchInput;
float m_cameraYaw;
float m_cameraPitch;
Vec3 m_moveInput;
float m_moveScale;
float m_oldMoveScale;
Vec3 m_position;
Matrix33 m_view;
};
inline bool DebugCamera::IsEnabled()
{
return m_cameraMode != DebugCamera::ModeOff;
}
inline bool DebugCamera::IsFixed()
{
return m_cameraMode == DebugCamera::ModeFixed;
}
inline bool DebugCamera::IsFree()
{
return m_cameraMode == DebugCamera::ModeFree;
}
} // namespace LegacyViewSystem
@@ -0,0 +1,675 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "CrySystem_precompiled.h"
#include <Cry_Camera.h>
#include <HMDBus.h>
#include "View.h"
#include <AzCore/Math/MathUtils.h>
#include <IStereoRenderer.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Component/Entity.h>
#include <Random.h>
#include <MathConversion.h>
namespace LegacyViewSystem
{
static ICVar* pCamShakeMult = 0;
static ICVar* pHmdReferencePoint = 0;
//------------------------------------------------------------------------
CView::CView(ISystem* pSystem)
: m_pSystem(pSystem)
, m_linkedTo(0)
, m_frameAdditiveAngles(0.0f, 0.0f, 0.0f)
, m_scale(1.0f)
, m_zoomedScale(1.0f)
{
if (!pCamShakeMult)
{
pCamShakeMult = gEnv->pConsole->GetCVar("c_shakeMult");
}
if (!pHmdReferencePoint)
{
pHmdReferencePoint = gEnv->pConsole->GetCVar("hmd_reference_point");
}
}
//------------------------------------------------------------------------
CView::~CView()
{
}
//-----------------------------------------------------------------------
void CView::Release()
{
delete this;
}
//------------------------------------------------------------------------
void CView::Update(float frameTime, bool isActive)
{
//FIXME:some cameras may need to be updated always
if (!isActive)
{
return;
}
if (m_azEntity)
{
m_viewParams.SaveLast();
CCamera* pSysCam = &m_pSystem->GetViewCamera();
//process screen shaking
ProcessShaking(frameTime);
//FIXME:to let the updateView implementation use the correct shakeVector
m_viewParams.currentShakeShift = m_viewParams.rotation * m_viewParams.currentShakeShift;
m_viewParams.frameTime = frameTime;
//update view position/rotation
if (m_azEntity != nullptr)
{
auto entityTransform = m_azEntity->GetTransform();
if (entityTransform != nullptr)
{
AZ::Transform transform = entityTransform->GetWorldTM();
m_viewParams.position = AZVec3ToLYVec3(transform.GetTranslation());
m_viewParams.rotation = AZQuaternionToLYQuaternion(transform.GetRotation());
}
}
ApplyFrameAdditiveAngles(m_viewParams.rotation);
const float fNearZ = gEnv->pSystem->GetIViewSystem()->GetDefaultZNear();
//see if the view have to use a custom near clipping plane
const float nearPlane = (m_viewParams.nearplane >= CAMERA_MIN_NEAR) ? (m_viewParams.nearplane) : fNearZ;
const float farPlane = (m_viewParams.farplane > 0.f) ? m_viewParams.farplane : gEnv->p3DEngine->GetMaxViewDistance();
float fov = (m_viewParams.fov < 0.001f) ? DEFAULT_FOV : m_viewParams.fov;
// [VR] specific
// Modify FOV based on the HMD device configuration
bool hmdActive = false;
bool isRenderingToHMD = gEnv->pRenderer->GetIStereoRenderer()->IsRenderingToHMD();
if (isRenderingToHMD)
{
const AZ::VR::HMDDeviceInfo* deviceInfo = nullptr;
EBUS_EVENT_RESULT(deviceInfo, AZ::VR::HMDDeviceRequestBus, GetDeviceInfo);
if (deviceInfo)
{
//Add 12 degrees to the FOV here used for culling.
//It won't be used for rendering, just to make sure we don't cull
//anything out incorrectly.
//This value was decided based on experimentation with the HTC Vive
//and works perfectly fine for the Oculus Rift
const float fovCorrection = 12.0f;
fov = deviceInfo->fovV + DEG2RAD(fovCorrection);
}
}
m_camera.SetFrustum(pSysCam->GetViewSurfaceX(), pSysCam->GetViewSurfaceZ(), fov, nearPlane, farPlane, pSysCam->GetPixelAspectRatio());
//apply shake & set the view matrix
m_viewParams.rotation *= m_viewParams.currentShakeQuat;
m_viewParams.rotation.NormalizeSafe();
m_viewParams.position += m_viewParams.currentShakeShift;
// Blending between cameras needs to happen after Camera space rendering calculations have been applied
// so that the m_viewParams.position is in World Space again
m_viewParams.UpdateBlending(frameTime);
// [VR] specific
// Add HMD's pose tracking on top of current camera pose
// Each game-title can decide whether to keep this functionality here or (most likely)
// move it somewhere else.
Quat q = m_viewParams.rotation;
Vec3 pos = m_viewParams.position;
Vec3 p = Vec3(ZERO);
if (isRenderingToHMD)
{
//This HMD tracking state is used JUST for use in the visibility system.
//RT_SetStereoCamera in D3DRendPipeline will override this info before rendering with the absolute
//latest tracking info.
const AZ::VR::TrackingState* trackingState = nullptr;
EBUS_EVENT_RESULT(trackingState, AZ::VR::HMDDeviceRequestBus, GetTrackingState);
if (trackingState && trackingState->CheckStatusFlags(AZ::VR::HMDStatus_IsUsable))
{
p = q * AZVec3ToLYVec3(trackingState->pose.position);
q = q * AZQuaternionToLYQuaternion(trackingState->pose.orientation);
}
}
Matrix34 viewMtx(q);
viewMtx.SetTranslation(pos + p);
m_camera.SetMatrix(viewMtx);
m_camera.SetEntityRotation(m_viewParams.rotation);
m_camera.SetEntityPos(pos);
}
else
{
m_linkedTo = AZ::EntityId(0);
}
}
//-----------------------------------------------------------------------
void CView::ApplyFrameAdditiveAngles(Quat& cameraOrientation)
{
if ((m_frameAdditiveAngles.x != 0.f) || (m_frameAdditiveAngles.y != 0.f) || (m_frameAdditiveAngles.z != 0.f))
{
Ang3 cameraAngles(cameraOrientation);
cameraAngles += m_frameAdditiveAngles;
cameraOrientation.SetRotationXYZ(cameraAngles);
m_frameAdditiveAngles.Set(0.0f, 0.0f, 0.0f);
}
}
//------------------------------------------------------------------------
void CView::SetViewShake(Ang3 shakeAngle, Vec3 shakeShift, float duration, float frequency, float randomness, int shakeID, bool bFlipVec, bool bUpdateOnly, bool bGroundOnly)
{
SShakeParams params;
params.shakeAngle = shakeAngle;
params.shakeShift = shakeShift;
params.frequency = frequency;
params.randomness = randomness;
params.shakeID = shakeID;
params.bFlipVec = bFlipVec;
params.bUpdateOnly = bUpdateOnly;
params.bGroundOnly = bGroundOnly;
params.fadeInDuration = 0; //
params.fadeOutDuration = duration; // originally it was faded out from start. that is why the values are set this way here, to preserve compatibility.
params.sustainDuration = 0; //
SetViewShakeEx(params);
}
//------------------------------------------------------------------------
void CView::SetViewShakeEx(const SShakeParams& params)
{
float shakeMult = GetScale();
if (shakeMult < 0.001f)
{
return;
}
int shakes(m_shakes.size());
SShake* pSetShake(NULL);
for (int i = 0; i < shakes; ++i)
{
SShake* pShake = &m_shakes[i];
if (pShake->ID == params.shakeID)
{
pSetShake = pShake;
break;
}
}
if (!pSetShake)
{
m_shakes.push_back(SShake(params.shakeID));
pSetShake = &m_shakes.back();
}
if (pSetShake)
{
// this can be set dynamically
pSetShake->frequency = max(0.00001f, params.frequency);
// the following are set on a 'new' shake as well
if (params.bUpdateOnly == false)
{
pSetShake->amount = params.shakeAngle * shakeMult;
pSetShake->amountVector = params.shakeShift * shakeMult;
pSetShake->randomness = params.randomness;
pSetShake->doFlip = params.bFlipVec;
pSetShake->groundOnly = params.bGroundOnly;
pSetShake->isSmooth = params.isSmooth;
pSetShake->permanent = params.bPermanent;
pSetShake->fadeInDuration = params.fadeInDuration;
pSetShake->sustainDuration = params.sustainDuration;
pSetShake->fadeOutDuration = params.fadeOutDuration;
pSetShake->timeDone = 0;
pSetShake->updating = true;
pSetShake->interrupted = false;
pSetShake->goalShake = Quat(ZERO);
pSetShake->goalShakeSpeed = Quat(ZERO);
pSetShake->goalShakeVector = Vec3(ZERO);
pSetShake->goalShakeVectorSpeed = Vec3(ZERO);
pSetShake->nextShake = 0.0f;
}
}
}
//------------------------------------------------------------------------
void CView::SetScale(const float scale)
{
CRY_ASSERT_MESSAGE(scale == 1.0f || m_scale == 1.0f, "Attempting to CView::SetScale but has already been set!");
m_scale = scale;
}
void CView::SetZoomedScale(const float scale)
{
CRY_ASSERT_MESSAGE(scale == 1.0f || m_zoomedScale == 1.0f, "Attempting to CView::SetZoomedScale but has already been set!");
m_zoomedScale = scale;
}
//------------------------------------------------------------------------
const float CView::GetScale()
{
float shakeMult(pCamShakeMult->GetFVal());
return m_scale * shakeMult * m_zoomedScale;
}
//------------------------------------------------------------------------
void CView::ProcessShaking(float frameTime)
{
m_viewParams.currentShakeQuat.SetIdentity();
m_viewParams.currentShakeShift.zero();
m_viewParams.shakingRatio = 0;
m_viewParams.groundOnly = false;
int shakes(m_shakes.size());
for (int i = 0; i < shakes; ++i)
{
ProcessShake(&m_shakes[i], frameTime);
}
}
//------------------------------------------------------------------------
void CView::ProcessShake(SShake* pShake, float frameTime)
{
if (!pShake->updating)
{
return;
}
pShake->timeDone += frameTime;
if (pShake->isSmooth)
{
ProcessShakeSmooth(pShake, frameTime);
}
else
{
ProcessShakeNormal(pShake, frameTime);
}
}
//------------------------------------------------------------------------
void CView::ProcessShakeNormal(SShake* pShake, float frameTime)
{
float endSustain = pShake->fadeInDuration + pShake->sustainDuration;
float totalDuration = endSustain + pShake->fadeOutDuration;
bool finalDamping = (!pShake->permanent && pShake->timeDone > totalDuration) || (pShake->interrupted && pShake->ratio < 0.05f);
if (finalDamping)
{
ProcessShakeNormal_FinalDamping(pShake, frameTime);
}
else
{
ProcessShakeNormal_CalcRatio(pShake, frameTime, endSustain);
ProcessShakeNormal_DoShaking(pShake, frameTime);
//for the global shaking ratio keep the biggest
if (pShake->groundOnly)
{
m_viewParams.groundOnly = true;
}
m_viewParams.shakingRatio = max(m_viewParams.shakingRatio, pShake->ratio);
m_viewParams.currentShakeQuat *= pShake->shakeQuat;
m_viewParams.currentShakeShift += pShake->shakeVector;
}
}
//////////////////////////////////////////////////////////////////////////
void CView::ProcessShakeSmooth(SShake* pShake, float frameTime)
{
assert(pShake->timeDone >= 0);
float endTimeFadeIn = pShake->fadeInDuration;
float endTimeSustain = pShake->sustainDuration + endTimeFadeIn;
float totalTime = endTimeSustain + pShake->fadeOutDuration;
if (pShake->interrupted && endTimeFadeIn <= pShake->timeDone && pShake->timeDone < endTimeSustain)
{
pShake->timeDone = endTimeSustain;
}
float damping = 1.f;
if (pShake->timeDone < endTimeFadeIn)
{
damping = pShake->timeDone / endTimeFadeIn;
}
else if (endTimeSustain < pShake->timeDone && pShake->timeDone < totalTime)
{
damping = (totalTime - pShake->timeDone) / (totalTime - endTimeSustain);
}
else if (totalTime <= pShake->timeDone)
{
pShake->shakeQuat.SetIdentity();
pShake->shakeVector.zero();
pShake->ratio = 0.0f;
pShake->nextShake = 0.0f;
pShake->flip = false;
pShake->updating = false;
return;
}
ProcessShakeSmooth_DoShaking(pShake, frameTime);
if (pShake->groundOnly)
{
m_viewParams.groundOnly = true;
}
pShake->ratio = (3.f - 2.f * damping) * damping * damping; // smooth ration change
m_viewParams.shakingRatio = max(m_viewParams.shakingRatio, pShake->ratio);
m_viewParams.currentShakeQuat *= Quat::CreateSlerp(IDENTITY, pShake->shakeQuat, pShake->ratio);
m_viewParams.currentShakeShift += Vec3::CreateLerp(ZERO, pShake->shakeVector, pShake->ratio);
}
//////////////////////////////////////////////////////////////////////////
void CView::GetRandomQuat(Quat& quat, SShake* pShake)
{
quat.SetRotationXYZ(pShake->amount);
float randomAmt(pShake->randomness);
float len(fabs(pShake->amount.x) + fabs(pShake->amount.y) + fabs(pShake->amount.z));
len /= 3.f;
float r = len * randomAmt;
quat *= Quat::CreateRotationXYZ(Ang3(cry_random(-r, r), cry_random(-r, r), cry_random(-r, r)));
}
//////////////////////////////////////////////////////////////////////////
void CView::GetRandomVector(Vec3& vec, SShake* pShake)
{
vec = pShake->amountVector;
float randomAmt(pShake->randomness);
float len = fabs(pShake->amountVector.x) + fabs(pShake->amountVector.y) + fabs(pShake->amountVector.z);
len /= 3.f;
float r = len * randomAmt;
vec += Vec3(cry_random(-r, r), cry_random(-r, r), cry_random(-r, r));
}
//////////////////////////////////////////////////////////////////////////
void CView::CubeInterpolateQuat(float t, SShake* pShake)
{
Quat p0 = pShake->startShake;
Quat p1 = pShake->goalShake;
Quat v0 = pShake->startShakeSpeed * 0.5f;
Quat v1 = pShake->goalShakeSpeed * 0.5f;
pShake->shakeQuat = (((p0 * 2.f + p1 * -2.f + v0 + v1) * t
+ (p0 * -3.f + p1 * 3.f + v0 * -2.f - v1)) * t
+ (v0)) * t
+ p0;
pShake->shakeQuat.Normalize();
}
//////////////////////////////////////////////////////////////////////////
void CView::CubeInterpolateVector(float t, SShake* pShake)
{
Vec3 p0 = pShake->startShakeVector;
Vec3 p1 = pShake->goalShakeVector;
Vec3 v0 = pShake->startShakeVectorSpeed * 0.8f;
Vec3 v1 = pShake->goalShakeVectorSpeed * 0.8f;
pShake->shakeVector = (((p0 * 2.f + p1 * -2.f + v0 + v1) * t
+ (p0 * -3.f + p1 * 3.f + v0 * -2.f - v1)) * t
+ (v0)) * t
+ p0;
}
//////////////////////////////////////////////////////////////////////////
void CView::ProcessShakeSmooth_DoShaking(SShake* pShake, float frameTime)
{
if (pShake->nextShake <= 0.0f)
{
pShake->nextShake = pShake->frequency;
pShake->startShake = pShake->goalShake;
pShake->startShakeSpeed = pShake->goalShakeSpeed;
pShake->startShakeVector = pShake->goalShakeVector;
pShake->startShakeVectorSpeed = pShake->goalShakeVectorSpeed;
GetRandomQuat(pShake->goalShake, pShake);
GetRandomQuat(pShake->goalShakeSpeed, pShake);
GetRandomVector(pShake->goalShakeVector, pShake);
GetRandomVector(pShake->goalShakeVectorSpeed, pShake);
if (pShake->flip)
{
pShake->goalShake.Invert();
pShake->goalShakeSpeed.Invert();
pShake->goalShakeVector = -pShake->goalShakeVector;
pShake->goalShakeVectorSpeed = -pShake->goalShakeVectorSpeed;
}
if (pShake->doFlip)
{
pShake->flip = !pShake->flip;
}
}
pShake->nextShake -= frameTime;
float t = (pShake->frequency - pShake->nextShake) / pShake->frequency;
CubeInterpolateQuat(t, pShake);
CubeInterpolateVector(t, pShake);
}
//////////////////////////////////////////////////////////////////////////
void CView::ProcessShakeNormal_FinalDamping(SShake* pShake, float frameTime)
{
pShake->shakeQuat = Quat::CreateSlerp(pShake->shakeQuat, IDENTITY, frameTime * 5.0f);
m_viewParams.currentShakeQuat *= pShake->shakeQuat;
pShake->shakeVector = Vec3::CreateLerp(pShake->shakeVector, ZERO, frameTime * 5.0f);
m_viewParams.currentShakeShift += pShake->shakeVector;
float svlen2(pShake->shakeVector.len2());
bool quatIsIdentity(Quat::IsEquivalent(IDENTITY, pShake->shakeQuat, 0.0001f));
if (quatIsIdentity && svlen2 < 0.01f)
{
pShake->shakeQuat.SetIdentity();
pShake->shakeVector.zero();
pShake->ratio = 0.0f;
pShake->nextShake = 0.0f;
pShake->flip = false;
pShake->updating = false;
}
}
// "ratio" is the amplitude of the shaking
void CView::ProcessShakeNormal_CalcRatio(SShake* pShake, float frameTime, float endSustain)
{
const float FADEOUT_TIME_WHEN_INTERRUPTED = 0.5f;
if (pShake->interrupted)
{
pShake->ratio = max(0.f, pShake->ratio - (frameTime / FADEOUT_TIME_WHEN_INTERRUPTED)); // fadeout after interrupted
}
else
if (pShake->timeDone >= endSustain && pShake->fadeOutDuration > 0)
{
float timeFading = pShake->timeDone - endSustain;
pShake->ratio = clamp_tpl(1.f - timeFading / pShake->fadeOutDuration, 0.f, 1.f); // fadeOut
}
else
if (pShake->timeDone >= pShake->fadeInDuration)
{
pShake->ratio = 1.f; // sustain
}
else
{
pShake->ratio = min(1.f, pShake->timeDone / pShake->fadeInDuration); // fadeIn
}
if (pShake->permanent && pShake->timeDone >= pShake->fadeInDuration && !pShake->interrupted)
{
pShake->ratio = 1.f; // permanent standing
}
}
//////////////////////////////////////////////////////////////////////////
void CView::ProcessShakeNormal_DoShaking(SShake* pShake, float frameTime)
{
float t;
if (pShake->nextShake <= 0.0f)
{
//angular
pShake->goalShake.SetRotationXYZ(pShake->amount);
if (pShake->flip)
{
pShake->goalShake.Invert();
}
//translational
pShake->goalShakeVector = pShake->amountVector;
if (pShake->flip)
{
pShake->goalShakeVector = -pShake->goalShakeVector;
}
if (pShake->doFlip)
{
pShake->flip = !pShake->flip;
}
//randomize it a little
float randomAmt(pShake->randomness);
float len(fabs(pShake->amount.x) + fabs(pShake->amount.y) + fabs(pShake->amount.z));
len /= 3.0f;
float r = len * randomAmt;
pShake->goalShake *= Quat::CreateRotationXYZ(Ang3(cry_random(-r, r), cry_random(-r, r), cry_random(-r, r)));
//translational randomization
len = fabs(pShake->amountVector.x) + fabs(pShake->amountVector.y) + fabs(pShake->amountVector.z);
len /= 3.0f;
r = len * randomAmt;
pShake->goalShakeVector += Vec3(cry_random(-r, r), cry_random(-r, r), cry_random(-r, r));
//damp & bounce it in a non linear fashion
t = 1.0f - (pShake->ratio * pShake->ratio);
pShake->goalShake = Quat::CreateSlerp(pShake->goalShake, IDENTITY, t);
pShake->goalShakeVector = Vec3::CreateLerp(pShake->goalShakeVector, ZERO, t);
pShake->nextShake = pShake->frequency;
}
pShake->nextShake = max(0.0f, pShake->nextShake - frameTime);
t = min(1.0f, frameTime * (1.0f / pShake->frequency));
pShake->shakeQuat = Quat::CreateSlerp(pShake->shakeQuat, pShake->goalShake, t);
pShake->shakeQuat.Normalize();
pShake->shakeVector = Vec3::CreateLerp(pShake->shakeVector, pShake->goalShakeVector, t);
}
//------------------------------------------------------------------------
void CView::StopShake(int shakeID)
{
uint32 num = m_shakes.size();
for (uint32 i = 0; i < num; ++i)
{
if (m_shakes[i].ID == shakeID && m_shakes[i].updating)
{
m_shakes[i].interrupted = true;
}
}
}
//------------------------------------------------------------------------
void CView::ResetShaking()
{
// disable shakes
std::vector<SShake>::iterator iter = m_shakes.begin();
std::vector<SShake>::iterator iterEnd = m_shakes.end();
while (iter != iterEnd)
{
SShake& shake = *iter;
shake.updating = false;
shake.timeDone = 0;
++iter;
}
}
//------------------------------------------------------------------------
void CView::LinkTo(AZ::Entity* follow)
{
CRY_ASSERT(follow);
m_azEntity = follow;
m_linkedTo = follow->GetId();
m_viewParams.targetPos = Vec3();// This should be quickly overwritten by the camera's acutal position from its matrix
}
//------------------------------------------------------------------------
void CView::Unlink()
{
m_azEntity = nullptr;
m_linkedTo.SetInvalid();
m_viewParams.targetPos = Vec3();
}
//------------------------------------------------------------------------
void CView::SetFrameAdditiveCameraAngles(const Ang3& addFrameAngles)
{
m_frameAdditiveAngles = addFrameAngles;
}
void CView::GetMemoryUsage(ICrySizer* s) const
{
s->AddObject(this, sizeof(*this));
s->AddObject(m_shakes);
}
void CView::Serialize(TSerialize ser)
{
if (ser.IsReading())
{
ResetShaking();
}
}
void CView::PostSerialize()
{
}
//////////////////////////////////////////////////////////////////////////
void CView::UpdateAudioListener([[maybe_unused]] Matrix34 const& rMatrix)
{
}
//////////////////////////////////////////////////////////////////////////
void CView::SetActive([[maybe_unused]] bool const bActive)
{
}
} // namespace LegacyViewSystem
+161
View File
@@ -0,0 +1,161 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
// Description : View System interfaces.
# pragma once
#include "IViewSystem.h"
#include <Cry_Camera.h>
class CGameObject;
namespace LegacyViewSystem
{
class CView
: public IView
{
public:
CView(ISystem* pSystem);
virtual ~CView();
//shaking
struct SShake
{
bool updating;
bool flip;
bool doFlip;
bool groundOnly;
bool permanent;
bool interrupted; // when forcefully stopped
bool isSmooth;
int ID;
float nextShake;
float timeDone;
float sustainDuration;
float fadeInDuration;
float fadeOutDuration;
float frequency;
float ratio;
float randomness;
Quat startShake;
Quat startShakeSpeed;
Vec3 startShakeVector;
Vec3 startShakeVectorSpeed;
Quat goalShake;
Quat goalShakeSpeed;
Vec3 goalShakeVector;
Vec3 goalShakeVectorSpeed;
Ang3 amount;
Vec3 amountVector;
Quat shakeQuat;
Vec3 shakeVector;
SShake(int shakeID)
{
memset(this, 0, sizeof(SShake));
startShake.SetIdentity();
startShakeSpeed.SetIdentity();
goalShake.SetIdentity();
shakeQuat.SetIdentity();
randomness = 0.5f;
ID = shakeID;
}
void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const { /*nothing*/}
};
// IView
virtual void Release();
virtual void Update(float frameTime, bool isActive);
virtual void ProcessShaking(float frameTime);
virtual void ProcessShake(SShake* pShake, float frameTime);
virtual void ResetShaking();
virtual void ResetBlending() { m_viewParams.ResetBlending(); }
virtual void LinkTo(AZ::Entity* follow);
virtual void Unlink();
virtual AZ::EntityId GetLinkedId() {return m_linkedTo; };
virtual void SetCurrentParams(SViewParams& params) { m_viewParams = params; };
virtual const SViewParams* GetCurrentParams() {return &m_viewParams; }
virtual void SetViewShake(Ang3 shakeAngle, Vec3 shakeShift, float duration, float frequency, float randomness, int shakeID, bool bFlipVec = true, bool bUpdateOnly = false, bool bGroundOnly = false);
virtual void SetViewShakeEx(const SShakeParams& params);
virtual void StopShake(int shakeID);
virtual void SetFrameAdditiveCameraAngles(const Ang3& addFrameAngles);
virtual void SetScale(const float scale);
virtual void SetZoomedScale(const float scale);
virtual void SetActive(const bool bActive);
// ~IView
void Serialize(TSerialize ser) override;
void PostSerialize() override;
CCamera& GetCamera() override { return m_camera; }
const CCamera& GetCamera() const override { return m_camera; }
void UpdateAudioListener(const Matrix34& rMatrix) override;
void GetMemoryUsage(ICrySizer* s) const;
protected:
void ProcessShakeNormal(SShake* pShake, float frameTime);
void ProcessShakeNormal_FinalDamping(SShake* pShake, float frameTime);
void ProcessShakeNormal_CalcRatio(SShake* pShake, float frameTime, float endSustain);
void ProcessShakeNormal_DoShaking(SShake* pShake, float frameTime);
void ProcessShakeSmooth(SShake* pShake, float frameTime);
void ProcessShakeSmooth_DoShaking(SShake* pShake, float frameTime);
void ApplyFrameAdditiveAngles(Quat& cameraOrientation);
const float GetScale();
private:
void GetRandomQuat(Quat& quat, SShake* pShake);
void GetRandomVector(Vec3& vec3, SShake* pShake);
void CubeInterpolateQuat(float t, SShake* pShake);
void CubeInterpolateVector(float t, SShake* pShake);
protected:
bool m_active;
AZ::EntityId m_linkedTo;
AZ::Entity* m_azEntity = nullptr;
SViewParams m_viewParams;
CCamera m_camera;
ISystem* m_pSystem;
std::vector<SShake> m_shakes;
Ang3 m_frameAdditiveAngles; // Used mainly for cinematics, where the game can slightly override camera orientation
float m_scale;
float m_zoomedScale;
};
} // namespace LegacyViewSystem
@@ -0,0 +1,727 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "CrySystem_precompiled.h"
#include <AzCore/Component/ComponentApplicationBus.h>
#include <Cry_Camera.h>
#include <ILevelSystem.h>
#include "ViewSystem.h"
#include "PNoise3.h"
#include "DebugCamera.h"
#include <MathConversion.h>
#include <AzCore/Casting/lossy_cast.h>
#define VS_CALL_LISTENERS(func) \
{ \
size_t count = m_listeners.size(); \
if (count > 0) \
{ \
const size_t memSize = count * sizeof(IViewSystemListener*); \
PREFAST_SUPPRESS_WARNING(6255) IViewSystemListener * *pArray = (IViewSystemListener**) alloca(memSize); \
memcpy(pArray, &*m_listeners.begin(), memSize); \
while (count--) \
{ \
(*pArray)->func; ++pArray; \
} \
} \
}
namespace LegacyViewSystem
{
void ToggleDebugCamera([[maybe_unused]] IConsoleCmdArgs* pArgs)
{
#if !defined(_RELEASE)
if (!gEnv->IsDedicated())
{
DebugCamera* debugCamera = CViewSystem::s_debugCamera;
if (debugCamera)
{
if (!debugCamera->IsEnabled())
{
debugCamera->OnEnable();
}
else
{
debugCamera->OnNextMode();
}
}
}
#endif
}
void ToggleDebugCameraInvertY([[maybe_unused]] IConsoleCmdArgs* pArgs)
{
#if !defined(_RELEASE)
if (!gEnv->IsDedicated())
{
DebugCamera* debugCamera = CViewSystem::s_debugCamera;
if (debugCamera)
{
debugCamera->OnInvertY();
}
}
#endif
}
void DebugCameraMove([[maybe_unused]] IConsoleCmdArgs* pArgs)
{
#if !defined(_RELEASE)
if (!gEnv->IsDedicated())
{
if (pArgs->GetArgCount() != 4)
{
CryLogAlways("debugCameraMove requires 3 args, not %d.", pArgs->GetArgCount() - 1);
return;
}
DebugCamera* debugCamera = CViewSystem::s_debugCamera;
if (debugCamera && debugCamera->IsFree())
{
Vec3::value_type x = azlossy_cast<float>(atof(pArgs->GetArg(1)));
Vec3::value_type y = azlossy_cast<float>(atof(pArgs->GetArg(2)));
Vec3::value_type z = azlossy_cast<float>(atof(pArgs->GetArg(3)));
Vec3 newPos(x, y, z);
debugCamera->MovePosition(newPos);
}
}
#endif
}
DebugCamera* CViewSystem::s_debugCamera = nullptr;
//------------------------------------------------------------------------
CViewSystem::CViewSystem(ISystem* pSystem)
: m_pSystem(pSystem)
, m_activeViewId(0)
, m_nextViewIdToAssign(1000)
, m_preSequenceViewId(0)
, m_cutsceneViewId(0)
, m_cutsceneCount(0)
, m_bOverridenCameraRotation(false)
, m_bActiveViewFromSequence(false)
, m_fBlendInPosSpeed(0.0f)
, m_fBlendInRotSpeed(0.0f)
, m_bPerformBlendOut(false)
, m_useDeferredViewSystemUpdate(false)
, m_bControlsAudioListeners(true)
{
#if !defined(_RELEASE) && !defined(DEDICATED_SERVER)
if (!s_debugCamera)
{
s_debugCamera = new DebugCamera;
}
REGISTER_COMMAND("debugCameraToggle", ToggleDebugCamera, VF_DEV_ONLY, "Toggle the debug camera.\n");
REGISTER_COMMAND("debugCameraInvertY", ToggleDebugCameraInvertY, VF_DEV_ONLY, "Toggle debug camera Y-axis inversion.\n");
REGISTER_COMMAND("debugCameraMove", DebugCameraMove, VF_DEV_ONLY, "Move the debug camera the specified distance (x y z).\n");
gEnv->pConsole->CreateKeyBind("ctrl_keyboard_key_punctuation_backslash", "debugCameraToggle");
gEnv->pConsole->CreateKeyBind("alt_keyboard_key_punctuation_backslash", "debugCameraInvertY");
#endif
REGISTER_CVAR2("cl_camera_noise", &m_fCameraNoise, -1, 0,
"Adds hand-held like camera noise to the camera view. \n The higher the value, the higher the noise.\n A value <= 0 disables it.");
REGISTER_CVAR2("cl_camera_noise_freq", &m_fCameraNoiseFrequency, 2.5326173f, 0,
"Defines camera noise frequency for the camera view. \n The higher the value, the higher the noise.");
REGISTER_CVAR2("cl_ViewSystemDebug", &m_nViewSystemDebug, 0, VF_CHEAT,
"Sets Debug information of the ViewSystem.");
REGISTER_CVAR2("cl_DefaultNearPlane", &m_fDefaultCameraNearZ, DEFAULT_NEAR, VF_CHEAT,
"The default camera near plane. ");
//Register as level system listener
if (m_pSystem->GetILevelSystem())
{
m_pSystem->GetILevelSystem()->AddListener(this);
}
Camera::CameraSystemRequestBus::Handler::BusConnect();
}
//------------------------------------------------------------------------
CViewSystem::~CViewSystem()
{
Camera::CameraSystemRequestBus::Handler::BusDisconnect();
ClearAllViews();
IConsole* pConsole = gEnv->pConsole;
CRY_ASSERT(pConsole);
pConsole->UnregisterVariable("cl_camera_noise", true);
pConsole->UnregisterVariable("cl_camera_noise_freq", true);
pConsole->UnregisterVariable("cl_ViewSystemDebug", true);
pConsole->UnregisterVariable("cl_DefaultNearPlane", true);
//Remove as level system listener
if (m_pSystem->GetILevelSystem())
{
m_pSystem->GetILevelSystem()->RemoveListener(this);
}
}
//------------------------------------------------------------------------
void CViewSystem::Update(float frameTime)
{
FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
if (gEnv->IsDedicated())
{
return;
}
if (s_debugCamera)
{
s_debugCamera->Update();
}
CView* const pActiveView = static_cast<CView*>(GetActiveView());
TViewMap::const_iterator Iter(m_views.begin());
TViewMap::const_iterator const IterEnd(m_views.end());
for (; Iter != IterEnd; ++Iter)
{
IView* const pView = Iter->second;
bool const bIsActive = (pView == pActiveView);
pView->Update(frameTime, bIsActive);
if (bIsActive)
{
CCamera& rCamera = pView->GetCamera();
if (!s_debugCamera || !s_debugCamera->IsEnabled())
{
pView->UpdateAudioListener(rCamera.GetMatrix());
}
if (const SViewParams* currentParams = pView->GetCurrentParams())
{
SViewParams copyCurrentParams = *currentParams;
rCamera.SetJustActivated(copyCurrentParams.justActivated);
copyCurrentParams.justActivated = false;
pView->SetCurrentParams(copyCurrentParams);
}
if (m_bOverridenCameraRotation)
{
// When camera rotation is overridden.
Vec3 pos = rCamera.GetMatrix().GetTranslation();
Matrix34 camTM(m_overridenCameraRotation);
camTM.SetTranslation(pos);
rCamera.SetMatrix(camTM);
}
else
{
// Normal setting of the camera
if (m_fCameraNoise > 0)
{
Matrix33 m = Matrix33(rCamera.GetMatrix());
m.OrthonormalizeFast();
Ang3 aAng1 = Ang3::GetAnglesXYZ(m);
//Ang3 aAng2 = RAD2DEG(aAng1);
Matrix34 camTM = rCamera.GetMatrix();
Vec3 pos = camTM.GetTranslation();
camTM.SetIdentity();
const float fScale = 0.1f;
CPNoise3* pNoise = m_pSystem->GetNoiseGen();
float fRes = pNoise->Noise1D(gEnv->pTimer->GetCurrTime() * m_fCameraNoiseFrequency);
aAng1.x += fRes * m_fCameraNoise * fScale;
pos.z -= fRes * m_fCameraNoise * fScale;
fRes = pNoise->Noise1D(17 + gEnv->pTimer->GetCurrTime() * m_fCameraNoiseFrequency);
aAng1.y -= fRes * m_fCameraNoise * fScale;
//aAng1.z+=fRes*0.025f; // left / right movement should be much less visible
camTM.SetRotationXYZ(aAng1);
camTM.SetTranslation(pos);
rCamera.SetMatrix(camTM);
}
}
m_pSystem->SetViewCamera(rCamera);
}
}
if (s_debugCamera)
{
s_debugCamera->PostUpdate();
}
// Display debug info on screen
if (m_nViewSystemDebug)
{
DebugDraw();
}
}
//------------------------------------------------------------------------
IView* CViewSystem::CreateView()
{
CView* newView = new CView(m_pSystem);
if (newView)
{
AddView(newView);
}
return newView;
}
unsigned int CViewSystem::AddView(IView* pView)
{
assert(pView);
m_views.insert(TViewMap::value_type(m_nextViewIdToAssign, pView));
return m_nextViewIdToAssign++;
}
void CViewSystem::RemoveView(IView* pView)
{
RemoveViewById(GetViewId(pView));
}
void CViewSystem::RemoveView(unsigned int viewId)
{
RemoveViewById(viewId);
}
void CViewSystem::RemoveViewById(unsigned int viewId)
{
TViewMap::iterator iter = m_views.find(viewId);
if (iter != m_views.end())
{
if (viewId == m_activeViewId)
{
m_activeViewId = 0;
}
if (viewId == m_preSequenceViewId)
{
m_preSequenceViewId = 0;
}
SAFE_RELEASE(iter->second);
m_views.erase(iter);
}
}
//------------------------------------------------------------------------
void CViewSystem::SetActiveView(IView* pView)
{
if (pView != NULL)
{
IView* const pPrevView = GetView(m_activeViewId);
if (pPrevView != pView)
{
if (pPrevView != NULL)
{
pPrevView->SetActive(false);
}
pView->SetActive(true);
m_activeViewId = GetViewId(pView);
}
}
else
{
m_activeViewId = ~0;
}
m_bActiveViewFromSequence = false;
}
//------------------------------------------------------------------------
void CViewSystem::SetActiveView(unsigned int viewId)
{
IView* const pPrevView = GetView(m_activeViewId);
if (pPrevView != NULL)
{
pPrevView->SetActive(false);
}
IView* const pView = GetView(viewId);
if (pView != NULL)
{
pView->SetActive(true);
m_activeViewId = viewId;
m_bActiveViewFromSequence = false;
}
}
//------------------------------------------------------------------------
IView* CViewSystem::GetView(unsigned int viewId)
{
TViewMap::iterator it = m_views.find(viewId);
if (it != m_views.end())
{
return it->second;
}
return NULL;
}
//------------------------------------------------------------------------
IView* CViewSystem::GetActiveView()
{
return GetView(m_activeViewId);
}
//------------------------------------------------------------------------
unsigned int CViewSystem::GetViewId(IView* pView)
{
for (TViewMap::iterator it = m_views.begin(); it != m_views.end(); ++it)
{
IView* tView = it->second;
if (tView == pView)
{
return it->first;
}
}
return 0;
}
//------------------------------------------------------------------------
unsigned int CViewSystem::GetActiveViewId()
{
// cutscene can override the games id of the active view
if (m_cutsceneCount && m_cutsceneViewId)
{
return m_cutsceneViewId;
}
return m_activeViewId;
}
//------------------------------------------------------------------------
IView* CViewSystem::GetViewByEntityId(const AZ::EntityId& id, bool forceCreate)
{
for (TViewMap::iterator it = m_views.begin(); it != m_views.end(); ++it)
{
IView* tView = it->second;
if (tView && tView->GetLinkedId() == id)
{
return tView;
}
}
if (forceCreate)
{
// Component Camera
AZ::Entity* entity = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationBus::Events::FindEntity, id);
if (entity)
{
if (IView* pNew = CreateView())
{
pNew->LinkTo(entity);
return pNew;
}
}
}
return nullptr;
}
//------------------------------------------------------------------------
void CViewSystem::SetActiveCamera(const SCameraParams& params)
{
IView* pView = NULL;
if (params.cameraEntityId.IsValid())
{
pView = GetViewByEntityId(params.cameraEntityId, true);
if (pView)
{
SViewParams viewParams = *pView->GetCurrentParams();
viewParams.fov = params.fov;
viewParams.nearplane = params.nearZ;
if (m_bActiveViewFromSequence == false && m_preSequenceViewId == 0)
{
m_preSequenceViewId = m_activeViewId;
IView* pPrevView = GetView(m_activeViewId);
if (pPrevView && m_fBlendInPosSpeed > 0.0f && m_fBlendInRotSpeed > 0.0f)
{
viewParams.blendPosSpeed = m_fBlendInPosSpeed;
viewParams.blendRotSpeed = m_fBlendInRotSpeed;
viewParams.BlendFrom(*pPrevView->GetCurrentParams());
}
}
if (m_activeViewId != GetViewId(pView) && params.justActivated)
{
viewParams.justActivated = true;
}
pView->SetCurrentParams(viewParams);
// make this one the active view
SetActiveView(pView);
m_bActiveViewFromSequence = true;
}
}
else
{
if (m_preSequenceViewId != 0)
{
// Restore m_preSequenceViewId view
IView* pActiveView = GetView(m_activeViewId);
IView* pNewView = GetView(m_preSequenceViewId);
if (pActiveView && pNewView && m_bPerformBlendOut)
{
SViewParams activeViewParams = *pActiveView->GetCurrentParams();
SViewParams newViewParams = *pNewView->GetCurrentParams();
newViewParams.BlendFrom(activeViewParams);
newViewParams.blendPosSpeed = activeViewParams.blendPosSpeed;
newViewParams.blendRotSpeed = activeViewParams.blendRotSpeed;
if (m_activeViewId != m_preSequenceViewId && params.justActivated)
{
newViewParams.justActivated = true;
}
pNewView->SetCurrentParams(newViewParams);
SetActiveView(m_preSequenceViewId);
}
else if (pActiveView && m_activeViewId != m_preSequenceViewId && params.justActivated)
{
SViewParams activeViewParams = *pActiveView->GetCurrentParams();
activeViewParams.justActivated = true;
if (pNewView)
{
pNewView->SetCurrentParams(activeViewParams);
SetActiveView(m_preSequenceViewId);
}
}
m_preSequenceViewId = 0;
m_bActiveViewFromSequence = false;
}
}
m_cutsceneViewId = GetViewId(pView);
VS_CALL_LISTENERS(OnCameraChange(params));
}
//------------------------------------------------------------------------
void CViewSystem::BeginCutScene(IAnimSequence* pSeq, [[maybe_unused]] unsigned long dwFlags, bool bResetFX)
{
m_cutsceneCount++;
IConsole* pCon = gEnv->pConsole;
if (m_cutsceneCount == 1)
{
gEnv->p3DEngine->ResetPostEffects();
}
VS_CALL_LISTENERS(OnBeginCutScene(pSeq, bResetFX));
}
//------------------------------------------------------------------------
void CViewSystem::EndCutScene(IAnimSequence* pSeq, [[maybe_unused]] unsigned long dwFlags)
{
m_cutsceneCount -= (m_cutsceneCount > 0);
IConsole* pCon = gEnv->pConsole;
if (m_cutsceneCount == 0)
{
gEnv->p3DEngine->ResetPostEffects();
}
ClearCutsceneViews();
VS_CALL_LISTENERS(OnEndCutScene(pSeq));
}
void CViewSystem::SendGlobalEvent([[maybe_unused]] const char* pszEvent)
{
// TODO: broadcast to script system
}
//////////////////////////////////////////////////////////////////////////
void CViewSystem::SetOverrideCameraRotation(bool bOverride, Quat rotation)
{
m_bOverridenCameraRotation = bOverride;
m_overridenCameraRotation = rotation;
}
//////////////////////////////////////////////////////////////////////////
void CViewSystem::UpdateSoundListeners()
{
assert(gEnv->IsEditor() && !gEnv->IsEditorGameMode());
// In Editor we may want to control global listeners outside of the game view.
if (m_bControlsAudioListeners)
{
IView* const pActiveView = static_cast<IView*>(GetActiveView());
TViewMap::const_iterator Iter(m_views.begin());
TViewMap::const_iterator const IterEnd(m_views.end());
for (; Iter != IterEnd; ++Iter)
{
IView* const pView = Iter->second;
bool const bIsActive = (pView == pActiveView);
CCamera const& rCamera = bIsActive ? gEnv->pSystem->GetViewCamera() : pView->GetCamera();
pView->UpdateAudioListener(rCamera.GetMatrix());
}
}
}
//////////////////////////////////////////////////////////////////
void CViewSystem::OnLoadingStart([[maybe_unused]] ILevelInfo* pLevel)
{
//If the level is being restarted (IsSerializingFile() == 1)
//views should not be cleared, because the main view (player one) won't be recreated in this case
//Views will only be cleared when loading a new map, or loading a saved game (IsSerizlizingFile() == 2)
bool shouldClearViews = gEnv->pSystem ? (gEnv->pSystem->IsSerializingFile() != 1) : false;
if (shouldClearViews)
{
ClearAllViews();
}
}
/////////////////////////////////////////////////////////////////////
void CViewSystem::OnUnloadComplete([[maybe_unused]] ILevel* pLevel)
{
bool shouldClearViews = gEnv->pSystem ? (gEnv->pSystem->IsSerializingFile() != 1) : false;
if (shouldClearViews)
{
ClearAllViews();
}
assert(m_listeners.empty());
stl::free_container(m_listeners);
}
/////////////////////////////////////////////////////////////////////
void CViewSystem::ClearCutsceneViews()
{
//First switch to previous camera if available
//In practice, the camera should be already restored before reaching this point, but just in case.
if (m_preSequenceViewId != 0)
{
SCameraParams camParams;
camParams.cameraEntityId.SetInvalid(); //Setting to invalid will try to switch to previous camera
camParams.fov = 60.0f;
camParams.nearZ = DEFAULT_NEAR;
camParams.justActivated = true;
SetActiveCamera(camParams);
}
}
///////////////////////////////////////////
void CViewSystem::ClearAllViews()
{
TViewMap::iterator end = m_views.end();
for (TViewMap::iterator it = m_views.begin(); it != end; ++it)
{
SAFE_RELEASE(it->second);
}
stl::free_container(m_views);
m_preSequenceViewId = 0;
m_activeViewId = 0;
}
////////////////////////////////////////////////////////////////////
void CViewSystem::DebugDraw()
{
IRenderer* pRenderer = gEnv->pRenderer;
if (pRenderer)
{
float xpos = 20;
float ypos = 15;
float fColor[4] = {1.0f, 1.0f, 1.0f, 0.7f};
float fColorRed[4] = {1.0f, 0.0f, 0.0f, 0.7f};
float fColorGreen[4] = {0.0f, 1.0f, 0.0f, 0.7f};
pRenderer->Draw2dLabel(xpos, 5, 1.35f, fColor, false, "ViewSystem Stats: %" PRISIZE_T " Views ", m_views.size());
IView* pActiveView = GetActiveView();
for (TViewMap::iterator it = m_views.begin(); it != m_views.end(); ++it)
{
IView* pView = it->second;
const CCamera& cam = pView->GetCamera();
bool isActive = (pView == pActiveView);
Vec3 pos = cam.GetPosition();
Ang3 ang = cam.GetAngles();
pRenderer->Draw2dLabel(xpos, ypos, 1.35f, isActive ? fColorGreen : fColorRed, false, "View Camera: %p . View Id: %d, pos (%f, %f, %f), ang (%f, %f, %f)", &cam, it->first, pos.x, pos.y, pos.z, ang.x, ang.y, ang.z);
ypos += 11;
}
}
}
//////////////////////////////////////////////////////////////////////////
void CViewSystem::GetMemoryUsage(ICrySizer* s) const
{
SIZER_SUBCOMPONENT_NAME(s, "ViewSystem");
s->Add(*this);
s->AddContainer(m_views);
}
void CViewSystem::Serialize(TSerialize ser)
{
TViewMap::iterator iter = m_views.begin();
TViewMap::iterator iterEnd = m_views.end();
while (iter != iterEnd)
{
iter->second->Serialize(ser);
++iter;
}
}
void CViewSystem::PostSerialize()
{
TViewMap::iterator iter = m_views.begin();
TViewMap::iterator iterEnd = m_views.end();
while (iter != iterEnd)
{
iter->second->PostSerialize();
++iter;
}
}
///////////////////////////////////////////////////////////////////////////
void CViewSystem::SetControlAudioListeners(bool bActive)
{
m_bControlsAudioListeners = bActive;
TViewMap::const_iterator Iter(m_views.begin());
TViewMap::const_iterator const IterEnd(m_views.end());
for (; Iter != IterEnd; ++Iter)
{
Iter->second->SetActive(bActive);
}
}
} // namespace LegacyViewSystem
@@ -0,0 +1,160 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
// Description : View System interfaces.
#pragma once
#include "View.h"
#include "IMovieSystem.h"
#include <ILevelSystem.h>
#include <AzFramework/Components/CameraBus.h>
namespace LegacyViewSystem
{
class DebugCamera;
class CViewSystem
: public IViewSystem
, public IMovieUser
, public ILevelSystemListener
, public Camera::CameraSystemRequestBus::Handler
{
private:
typedef std::map<unsigned int, IView*> TViewMap;
typedef std::vector<unsigned int> TViewIdVector;
public:
//IViewSystem
virtual IView* CreateView();
virtual unsigned int AddView(IView* pView) override;
virtual void RemoveView(IView* pView);
virtual void RemoveView(unsigned int viewId);
virtual void SetActiveView(IView* pView);
virtual void SetActiveView(unsigned int viewId);
//CameraSystemRequestBus
AZ::EntityId GetActiveCamera() override { return m_activeViewId ? GetActiveView()->GetLinkedId() : AZ::EntityId(); }
//utility functions
virtual IView* GetView(unsigned int viewId);
virtual IView* GetActiveView();
virtual unsigned int GetViewId(IView* pView);
virtual unsigned int GetActiveViewId();
virtual void Serialize(TSerialize ser);
virtual void PostSerialize();
virtual IView* GetViewByEntityId(const AZ::EntityId& id, bool forceCreate);
virtual float GetDefaultZNear() { return m_fDefaultCameraNearZ; };
virtual void SetBlendParams(float fBlendPosSpeed, float fBlendRotSpeed, bool performBlendOut) { m_fBlendInPosSpeed = fBlendPosSpeed; m_fBlendInRotSpeed = fBlendRotSpeed; m_bPerformBlendOut = performBlendOut; };
virtual void SetOverrideCameraRotation(bool bOverride, Quat rotation);
virtual bool IsPlayingCutScene() const
{
return m_cutsceneCount > 0;
}
virtual void UpdateSoundListeners();
virtual void SetDeferredViewSystemUpdate(bool const bDeferred){ m_useDeferredViewSystemUpdate = bDeferred; }
virtual bool UseDeferredViewSystemUpdate() const { return m_useDeferredViewSystemUpdate; }
virtual void SetControlAudioListeners(bool const bActive);
//~IViewSystem
//IMovieUser
virtual void SetActiveCamera(const SCameraParams& Params);
virtual void BeginCutScene(IAnimSequence* pSeq, unsigned long dwFlags, bool bResetFX);
virtual void EndCutScene(IAnimSequence* pSeq, unsigned long dwFlags);
virtual void SendGlobalEvent(const char* pszEvent);
//~IMovieUser
// ILevelSystemListener
virtual void OnLevelNotFound([[maybe_unused]] const char* levelName) {};
virtual void OnLoadingStart(ILevelInfo* pLevel);
virtual void OnLoadingComplete([[maybe_unused]] ILevel* pLevel) {};
virtual void OnLoadingError([[maybe_unused]] ILevelInfo* pLevel, [[maybe_unused]] const char* error) {};
virtual void OnLoadingProgress([[maybe_unused]] ILevelInfo* pLevel, [[maybe_unused]] int progressAmount) {};
virtual void OnUnloadComplete(ILevel* pLevel);
//~ILevelSystemListener
CViewSystem(ISystem* pSystem);
~CViewSystem();
void Release() override { delete this; };
void Update(float frameTime) override;
virtual void ForceUpdate(float elapsed) { Update(elapsed); }
//void RegisterViewClass(const char *name, IView *(*func)());
bool AddListener(IViewSystemListener* pListener)
{
return stl::push_back_unique(m_listeners, pListener);
}
bool RemoveListener(IViewSystemListener* pListener)
{
return stl::find_and_erase(m_listeners, pListener);
}
void GetMemoryUsage(ICrySizer* s) const;
void ClearAllViews();
private:
void RemoveViewById(unsigned int viewId);
void ClearCutsceneViews();
void DebugDraw();
ISystem* m_pSystem;
//TViewClassMap m_viewClasses;
TViewMap m_views;
// Listeners
std::vector<IViewSystemListener*> m_listeners;
unsigned int m_activeViewId;
unsigned int m_nextViewIdToAssign; // next id which will be assigned
unsigned int m_preSequenceViewId; // viewId before a movie cam dropped in
unsigned int m_cutsceneViewId;
unsigned int m_cutsceneCount;
bool m_bActiveViewFromSequence;
bool m_bOverridenCameraRotation;
Quat m_overridenCameraRotation;
float m_fCameraNoise;
float m_fCameraNoiseFrequency;
float m_fDefaultCameraNearZ;
float m_fBlendInPosSpeed;
float m_fBlendInRotSpeed;
bool m_bPerformBlendOut;
int m_nViewSystemDebug;
bool m_useDeferredViewSystemUpdate;
bool m_bControlsAudioListeners;
public:
static DebugCamera* s_debugCamera;
};
} // namespace LegacyViewSystem