@ -12,14 +12,150 @@
# include "CameraInput.h"
# include <AzCore/Console/IConsole.h>
# include <AzCore/Math/MathUtils.h>
# include <AzCore/Math/Plane.h>
# include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
# include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
# include <AzFramework/Windowing/WindowBus.h>
namespace AzFramework
{
void CameraSystem : : HandleEvents ( const InputEvent & event )
AZ_CVAR (
float , ed_cameraSystemDefaultPlaneHeight , 34.0f , nullptr , AZ : : ConsoleFunctorFlags : : Null ,
" The default height of the ground plane to do intersection tests against when orbiting " ) ;
AZ_CVAR ( float , ed_cameraSystemBoostMultiplier , 3.0f , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR ( float , ed_cameraSystemTranslateSpeed , 10.0f , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR ( float , ed_cameraSystemOrbitDollyScrollSpeed , 0.02f , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR ( float , ed_cameraSystemOrbitDollyCursorSpeed , 0.01f , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR ( float , ed_cameraSystemScrollTranslateSpeed , 0.02f , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR ( float , ed_cameraSystemDefaultOrbitDistance , 60.0f , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR ( float , ed_cameraSystemMaxOrbitDistance , 100.0f , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR ( float , ed_cameraSystemLookSmoothness , 5.0f , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR ( float , ed_cameraSystemTranslateSmoothness , 5.0f , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR ( float , ed_cameraSystemRotateSpeed , 0.005f , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR ( float , ed_cameraSystemPanSpeed , 0.01f , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR ( bool , ed_cameraSystemPanInvertX , true , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR ( bool , ed_cameraSystemPanInvertY , true , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR (
AZ : : CVarFixedString , ed_cameraSystemTranslateForwardKey , " keyboard_key_alphanumeric_W " , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR (
AZ : : CVarFixedString , ed_cameraSystemTranslateBackwardKey , " keyboard_key_alphanumeric_S " , nullptr , AZ : : ConsoleFunctorFlags : : Null ,
" " ) ;
AZ_CVAR (
AZ : : CVarFixedString , ed_cameraSystemTranslateLeftKey , " keyboard_key_alphanumeric_A " , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR (
AZ : : CVarFixedString , ed_cameraSystemTranslateRightKey , " keyboard_key_alphanumeric_D " , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR ( AZ : : CVarFixedString , ed_cameraSystemTranslateUpKey , " keyboard_key_alphanumeric_E " , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR (
AZ : : CVarFixedString , ed_cameraSystemTranslateDownKey , " keyboard_key_alphanumeric_Q " , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR (
AZ : : CVarFixedString , ed_cameraSystemTranslateBoostKey , " keyboard_key_modifier_shift_l " , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR ( AZ : : CVarFixedString , ed_cameraSystemOrbitKey , " keyboard_key_modifier_alt_l " , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR ( AZ : : CVarFixedString , ed_cameraSystemFreeLookButton , " mouse_button_right " , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR ( AZ : : CVarFixedString , ed_cameraSystemFreePanButton , " mouse_button_middle " , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR ( AZ : : CVarFixedString , ed_cameraSystemOrbitLookButton , " mouse_button_left " , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR ( AZ : : CVarFixedString , ed_cameraSystemOrbitDollyButton , " mouse_button_right " , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
AZ_CVAR ( AZ : : CVarFixedString , ed_cameraSystemOrbitPanButton , " mouse_button_middle " , nullptr , AZ : : ConsoleFunctorFlags : : Null , " " ) ;
static InputChannelId CameraTranslateForwardId ;
static InputChannelId CameraTranslateBackwardId ;
static InputChannelId CameraTranslateLeftId ;
static InputChannelId CameraTranslateRightId ;
static InputChannelId CameraTranslateDownId ;
static InputChannelId CameraTranslateUpId ;
static InputChannelId CameraTranslateBoostId ;
static InputChannelId CameraOrbitId ;
// externed elsewhere
InputChannelId CameraFreeLookButton ;
InputChannelId CameraFreePanButton ;
InputChannelId CameraOrbitLookButton ;
InputChannelId CameraOrbitDollyButton ;
InputChannelId CameraOrbitPanButton ;
void ReloadCameraKeyBindings ( )
{
const AZ : : CVarFixedString & forward = ed_cameraSystemTranslateForwardKey ;
CameraTranslateForwardId = InputChannelId ( forward . c_str ( ) ) ;
const AZ : : CVarFixedString & backward = ed_cameraSystemTranslateBackwardKey ;
CameraTranslateBackwardId = InputChannelId ( backward . c_str ( ) ) ;
const AZ : : CVarFixedString & left = ed_cameraSystemTranslateLeftKey ;
CameraTranslateLeftId = InputChannelId ( left . c_str ( ) ) ;
const AZ : : CVarFixedString & right = ed_cameraSystemTranslateRightKey ;
CameraTranslateRightId = InputChannelId ( right . c_str ( ) ) ;
const AZ : : CVarFixedString & down = ed_cameraSystemTranslateDownKey ;
CameraTranslateDownId = InputChannelId ( down . c_str ( ) ) ;
const AZ : : CVarFixedString & up = ed_cameraSystemTranslateUpKey ;
CameraTranslateUpId = InputChannelId ( up . c_str ( ) ) ;
const AZ : : CVarFixedString & boost = ed_cameraSystemTranslateBoostKey ;
CameraTranslateBoostId = InputChannelId ( boost . c_str ( ) ) ;
const AZ : : CVarFixedString & orbit = ed_cameraSystemOrbitKey ;
CameraOrbitId = InputChannelId ( orbit . c_str ( ) ) ;
const AZ : : CVarFixedString & freeLook = ed_cameraSystemFreeLookButton ;
CameraFreeLookButton = InputChannelId ( freeLook . c_str ( ) ) ;
const AZ : : CVarFixedString & freePan = ed_cameraSystemFreePanButton ;
CameraFreePanButton = InputChannelId ( freePan . c_str ( ) ) ;
const AZ : : CVarFixedString & orbitLook = ed_cameraSystemOrbitLookButton ;
CameraOrbitLookButton = InputChannelId ( orbitLook . c_str ( ) ) ;
const AZ : : CVarFixedString & orbitDolly = ed_cameraSystemOrbitDollyButton ;
CameraOrbitDollyButton = InputChannelId ( orbitDolly . c_str ( ) ) ;
const AZ : : CVarFixedString & orbitPan = ed_cameraSystemOrbitPanButton ;
CameraOrbitPanButton = InputChannelId ( orbitPan . c_str ( ) ) ;
}
static void ReloadCameraKeyBindingsConsole ( const AZ : : ConsoleCommandContainer & )
{
ReloadCameraKeyBindings ( ) ;
}
AZ_CONSOLEFREEFUNC ( ReloadCameraKeyBindingsConsole , AZ : : ConsoleFunctorFlags : : Null , " Reload keybindings for the modern camera system " ) ;
// Based on paper by David Eberly - https://www.geometrictools.com/Documentation/EulerAngles.pdf
AZ : : Vector3 EulerAngles ( const AZ : : Matrix3x3 & orientation )
{
float x ;
float y ;
float z ;
// 2.4 Factor as RzRyRx
if ( orientation . GetElement ( 2 , 0 ) < 1.0f )
{
if ( orientation . GetElement ( 2 , 0 ) > - 1.0f )
{
x = std : : atan2 ( orientation . GetElement ( 2 , 1 ) , orientation . GetElement ( 2 , 2 ) ) ;
y = std : : asin ( - orientation . GetElement ( 2 , 0 ) ) ;
z = std : : atan2 ( orientation . GetElement ( 1 , 0 ) , orientation . GetElement ( 0 , 0 ) ) ;
}
else
{
x = 0.0f ;
y = AZ : : Constants : : Pi * 0.5f ;
z = - std : : atan2 ( - orientation . GetElement ( 2 , 1 ) , orientation . GetElement ( 1 , 1 ) ) ;
}
}
else
{
x = 0.0f ;
y = - AZ : : Constants : : Pi * 0.5f ;
z = std : : atan2 ( - orientation . GetElement ( 1 , 2 ) , orientation . GetElement ( 1 , 1 ) ) ;
}
return { x , y , z } ;
}
void UpdateCameraFromTransform ( Camera & camera , const AZ : : Transform & transform )
{
const auto eulerAngles = AzFramework : : EulerAngles ( AZ : : Matrix3x3 : : CreateFromTransform ( transform ) ) ;
camera . m_lookAt = transform . GetTranslation ( ) ;
camera . m_pitch = eulerAngles . GetX ( ) ;
camera . m_yaw = eulerAngles . GetZ ( ) ;
}
bool CameraSystem : : HandleEvents ( const InputEvent & event )
{
if ( const auto & cursor_motion = AZStd : : get_if < CursorMotionEvent > ( & event ) )
{
@ -30,10 +166,10 @@ namespace AzFramework
m_scrollDelta = scroll - > m_delta ;
}
m_cameras . HandleEvents ( event ) ;
return m_cameras . HandleEvents ( event ) ;
}
Camera CameraSystem : : StepCamera ( const Camera & targetCamera , float deltaTime )
Camera CameraSystem : : StepCamera ( const Camera & targetCamera , const float deltaTime )
{
const auto cursorDelta = m_currentCursorPosition . has_value ( ) & & m_lastCursorPosition . has_value ( )
? m_currentCursorPosition . value ( ) - m_lastCursorPosition . value ( )
@ -51,36 +187,41 @@ namespace AzFramework
return nextCamera ;
}
void Cameras : : AddCamera ( AZStd : : shared_ptr < CameraInput > camera _i nput)
void Cameras : : AddCamera ( AZStd : : shared_ptr < CameraInput > camera I nput)
{
m_idleCameraInputs . push_back ( AZStd : : move ( camera _i nput) ) ;
m_idleCameraInputs . push_back ( AZStd : : move ( camera I nput) ) ;
}
void Cameras : : HandleEvents ( const InputEvent & event )
bool Cameras : : HandleEvents ( const InputEvent & event )
{
for ( auto & camera_input : m_activeCameraInputs )
bool handling = false ;
for ( auto & cameraInput : m_activeCameraInputs )
{
camera_input - > HandleEvents ( event ) ;
cameraInput - > HandleEvents ( event ) ;
handling = ! cameraInput - > Idle ( ) | | handling ;
}
for ( auto & camera _i nput : m_idleCameraInputs )
for ( auto & camera I nput : m_idleCameraInputs )
{
camera _i nput- > HandleEvents ( event ) ;
camera I nput- > HandleEvents ( event ) ;
}
return handling ;
}
Camera Cameras : : StepCamera ( const Camera & targetCamera , const ScreenVector & cursorDelta , float scrollDelta , const float deltaTime )
Camera Cameras : : StepCamera ( const Camera & targetCamera , const ScreenVector & cursorDelta , const float scrollDelta , const float deltaTime )
{
for ( int i = 0 ; i < m_idleCameraInputs . size ( ) ; )
{
auto & camera _i nput = m_idleCameraInputs [ i ] ;
const bool can _begin = camera_i nput- > Beginning ( ) & &
auto & camera I nput = m_idleCameraInputs [ i ] ;
const bool can Begin = cameraI nput- > Beginning ( ) & &
std : : all_of ( m_activeCameraInputs . cbegin ( ) , m_activeCameraInputs . cend ( ) ,
[ ] ( const auto & input ) { return ! input - > Exclusive ( ) ; } ) & &
( ! camera_input - > Exclusive ( ) | | ( camera_input - > Exclusive ( ) & & m_activeCameraInputs . empty ( ) ) ) ;
if ( can_begin )
( ! cameraInput - > Exclusive ( ) | | ( cameraInput - > Exclusive ( ) & & m_activeCameraInputs . empty ( ) ) ) ;
if ( canBegin )
{
m_activeCameraInputs . push_back ( camera _i nput) ;
m_activeCameraInputs . push_back ( camera I nput) ;
using AZStd : : swap ;
swap ( m_idleCameraInputs [ i ] , m_idleCameraInputs [ m_idleCameraInputs . size ( ) - 1 ] ) ;
m_idleCameraInputs . pop_back ( ) ;
@ -93,25 +234,25 @@ namespace AzFramework
// accumulate
Camera nextCamera = targetCamera ;
for ( auto & camera _i nput : m_activeCameraInputs )
for ( auto & camera I nput : m_activeCameraInputs )
{
nextCamera = camera _i nput- > StepCamera ( nextCamera , cursorDelta , scrollDelta , deltaTime ) ;
nextCamera = camera I nput- > StepCamera ( nextCamera , cursorDelta , scrollDelta , deltaTime ) ;
}
for ( int i = 0 ; i < m_activeCameraInputs . size ( ) ; )
{
auto & camera _i nput = m_activeCameraInputs [ i ] ;
if ( camera _i nput- > Ending ( ) )
auto & camera I nput = m_activeCameraInputs [ i ] ;
if ( camera I nput- > Ending ( ) )
{
camera _i nput- > ClearActivation ( ) ;
m_idleCameraInputs . push_back ( camera _i nput) ;
camera I nput- > ClearActivation ( ) ;
m_idleCameraInputs . push_back ( camera I nput) ;
using AZStd : : swap ;
swap ( m_activeCameraInputs [ i ] , m_activeCameraInputs [ m_activeCameraInputs . size ( ) - 1 ] ) ;
m_activeCameraInputs . pop_back ( ) ;
}
else
{
camera _i nput- > ContinueActivation ( ) ;
camera I nput- > ContinueActivation ( ) ;
i + + ;
}
}
@ -134,7 +275,7 @@ namespace AzFramework
{
if ( const auto & input = AZStd : : get_if < DiscreteInputEvent > ( & event ) )
{
if ( input - > m_channelId = = m_ c hannelId)
if ( input - > m_channelId = = m_ rotateC hannelId)
{
if ( input - > m_state = = InputChannel : : State : : Began )
{
@ -154,14 +295,14 @@ namespace AzFramework
{
Camera nextCamera = targetCamera ;
nextCamera . m_pitch += float ( cursorDelta . m_y ) * m_props . m_r otateSpeed;
nextCamera . m_yaw += float ( cursorDelta . m_x ) * m_props . m_r otateSpeed;
nextCamera . m_pitch -= float ( cursorDelta . m_y ) * ed_cameraSystemR otateSpeed;
nextCamera . m_yaw -= float ( cursorDelta . m_x ) * ed_cameraSystemR otateSpeed;
auto clamp_r otation = [ ] ( const float angle ) { return std : : fmod ( angle + AZ : : Constants : : Two Over Pi, AZ : : Constants : : Two Over Pi) ; } ;
const auto clampR otation = [ ] ( const float angle ) { return std : : fmod ( angle + AZ : : Constants : : Two Pi, AZ : : Constants : : Two Pi) ; } ;
nextCamera . m_yaw = clamp _r otation( nextCamera . m_yaw ) ;
nextCamera . m_yaw = clamp R otation( nextCamera . m_yaw ) ;
// clamp pitch to be +-90 degrees
nextCamera . m_pitch = AZ : : GetClamp ( nextCamera . m_pitch , - AZ : : Constants : : Pi * 0.5f , AZ : : Constants : : Pi * 0.5f ) ;
nextCamera . m_pitch = AZ : : GetClamp ( nextCamera . m_pitch , - AZ : : Constants : : Half Pi, AZ : : Constants : : Half Pi) ;
return nextCamera ;
}
@ -170,7 +311,7 @@ namespace AzFramework
{
if ( const auto & input = AZStd : : get_if < DiscreteInputEvent > ( & event ) )
{
if ( input - > m_channelId = = InputDeviceMouse: : Button : : Middle )
if ( input - > m_channelId = = m_panChannelId )
{
if ( input - > m_state = = InputChannel : : State : : Began )
{
@ -190,51 +331,50 @@ namespace AzFramework
{
Camera nextCamera = targetCamera ;
const auto pan _a xes = m_panAxesFn ( nextCamera ) ;
const auto pan A xes = m_panAxesFn ( nextCamera ) ;
const auto delta _pan_x = float ( cursorDelta . m_x ) * pan _axes. m_horizontalAxis * m_props . m_p anSpeed;
const auto delta _pan_y = float ( cursorDelta . m_y ) * pan _axes. m_verticalAxis * m_props . m_p anSpeed;
const auto delta PanX = float ( cursorDelta . m_x ) * pan Axes. m_horizontalAxis * ed_cameraSystemP anSpeed;
const auto delta PanY = float ( cursorDelta . m_y ) * pan Axes. m_verticalAxis * ed_cameraSystemP anSpeed;
const auto inv = [ ] ( const bool invert ) {
constexpr float Dir [ ] = { 1.0f , - 1.0f } ;
return Dir [ static_cast < int > ( invert ) ] ;
} ;
nextCamera . m_lookAt + = delta _pan_x * inv ( m_props . m_p anInvertX) ;
nextCamera . m_lookAt + = delta _pan_y * - inv ( m_props . m_p anInvertY) ;
nextCamera . m_lookAt + = delta PanX * inv ( ed_cameraSystemP anInvertX) ;
nextCamera . m_lookAt + = delta PanY * - inv ( ed_cameraSystemP anInvertY) ;
return nextCamera ;
}
TranslateCameraInput : : TranslationType TranslateCameraInput : : translationFromKey ( InputChannelId channelId )
{
// note: remove hard-coded InputDevice keys
if ( channelId = = InputDeviceKeyboard : : Key : : AlphanumericW )
if ( channelId = = CameraTranslateForwardId )
{
return TranslationType : : Forward ;
}
if ( channelId = = InputDeviceKeyboard: : Key : : AlphanumericS )
if ( channelId = = CameraTranslateBackwardId )
{
return TranslationType : : Backward ;
}
if ( channelId = = InputDeviceKeyboard: : Key : : AlphanumericA )
if ( channelId = = CameraTranslateLeftId )
{
return TranslationType : : Left ;
}
if ( channelId = = InputDeviceKeyboard: : Key : : AlphanumericD )
if ( channelId = = CameraTranslateRightId )
{
return TranslationType : : Right ;
}
if ( channelId = = InputDeviceKeyboard: : Key : : AlphanumericQ )
if ( channelId = = CameraTranslateDownId )
{
return TranslationType : : Down ;
}
if ( channelId = = InputDeviceKeyboard: : Key : : AlphanumericE )
if ( channelId = = CameraTranslateUpId )
{
return TranslationType : : Up ;
}
@ -259,19 +399,19 @@ namespace AzFramework
BeginActivation ( ) ;
}
if ( input - > m_channelId = = InputDeviceKeyboard: : Key : : ModifierShiftL )
if ( input - > m_channelId = = CameraTranslateBoostId )
{
m_boost = true ;
}
}
else if ( input - > m_state = = InputChannel : : State : : Ended )
{
m_translation ^= translationFromKey ( input - > m_channelId ) ;
m_translation &= ~ ( translationFromKey ( input - > m_channelId ) ) ;
if ( m_translation = = TranslationType : : Nil )
{
EndActivation ( ) ;
}
if ( input - > m_channelId = = InputDeviceKeyboard: : Key : : ModifierShiftL )
if ( input - > m_channelId = = CameraTranslateBoostId )
{
m_boost = false ;
}
@ -285,13 +425,13 @@ namespace AzFramework
{
Camera nextCamera = targetCamera ;
const auto translation _b asis = m_translationAxesFn ( nextCamera ) ;
const auto axisX = translation _b asis. GetBasisX ( ) ;
const auto axisY = translation _b asis. GetBasisY ( ) ;
const auto axisZ = translation _b asis. GetBasisZ ( ) ;
const auto translation B asis = m_translationAxesFn ( nextCamera ) ;
const auto axisX = translation B asis. GetBasisX ( ) ;
const auto axisY = translation B asis. GetBasisY ( ) ;
const auto axisZ = translation B asis. GetBasisZ ( ) ;
const float speed = [ boost = m_boost , props = m_props ]( ) {
return props. m_translateSpeed * ( boost ? props . m_b oostMultiplier : 1.0f ) ;
const float speed = [ boost = m_boost ]( ) {
return ed_cameraSystemTranslateSpeed * ( boost ? ed_cameraSystemB oostMultiplier : 1.0f ) ;
} ( ) ;
if ( ( m_translation & TranslationType : : Forward ) = = TranslationType : : Forward )
@ -342,12 +482,8 @@ namespace AzFramework
{
if ( const auto * input = AZStd : : get_if < DiscreteInputEvent > ( & event ) )
{
if ( input - > m_channelId = = InputDeviceKeyboard: : Key : : ModifierAltL )
if ( input - > m_channelId = = CameraOrbitId )
{
if ( input - > m_state = = InputChannel : : State : : Updated )
{
goto end ;
}
if ( input - > m_state = = InputChannel : : State : : Began )
{
BeginActivation ( ) ;
@ -358,7 +494,7 @@ namespace AzFramework
}
}
}
end :
if ( Active ( ) )
{
m_orbitCameras . HandleEvents ( event ) ;
@ -366,29 +502,29 @@ namespace AzFramework
}
Camera OrbitCameraInput : : StepCamera (
const Camera & targetCamera , const ScreenVector & cursorDelta , const float scrollDelta , float deltaTime )
const Camera & targetCamera , const ScreenVector & cursorDelta , const float scrollDelta , const float deltaTime )
{
Camera nextCamera = targetCamera ;
if ( Beginning ( ) )
{
float hit_distance = 0.0f ;
if ( AZ : : Plane : : CreateFromNormalAndPoint ( AZ : : Vector3 : : CreateAxisZ ( ) , AZ : : Vector3 : : Create Zero ( ) )
. CastRay ( targetCamera . Translation ( ) , targetCamera . Rotation ( ) . GetBasisY ( ) * m_props . m_maxOrbitDistance , hit_distance ) )
if ( AZ : : Plane : : CreateFromNormalAndPoint ( AZ : : Vector3 : : CreateAxisZ ( ) , AZ : : Vector3 : : Create Axis Z( ed_cameraSystemDefaultPlaneHeight ) )
. CastRay ( targetCamera . Translation ( ) , targetCamera . Rotation ( ) . GetBasisY ( ) , hit_distance ) )
{
hit_distance = AZStd : : min < float > ( hit_distance , ed_cameraSystemMaxOrbitDistance ) ;
nextCamera . m_lookDist = - hit_distance ;
nextCamera . m_lookAt = targetCamera . Translation ( ) + targetCamera . Rotation ( ) . GetBasisY ( ) * hit_distance ;
}
else
{
nextCamera . m_lookDist = - m_props. m_default OrbitDistance;
nextCamera . m_lookAt = targetCamera . Translation ( ) + targetCamera . Rotation ( ) . GetBasisY ( ) * m_props. m_default OrbitDistance;
nextCamera . m_lookDist = - ed_cameraSystemMax OrbitDistance;
nextCamera . m_lookAt = targetCamera . Translation ( ) + targetCamera . Rotation ( ) . GetBasisY ( ) * ed_cameraSystemMax OrbitDistance;
}
}
if ( Active ( ) )
{
// todo: need to return nested cameras to idle state when ending
nextCamera = m_orbitCameras . StepCamera ( nextCamera , cursorDelta , scrollDelta , deltaTime ) ;
}
@ -413,10 +549,10 @@ namespace AzFramework
Camera OrbitDollyScrollCameraInput : : StepCamera (
const Camera & targetCamera , [[maybe_unused]] const ScreenVector & cursorDelta , const float scrollDelta ,
[[maybe_unused]] float deltaTime )
[[maybe_unused]] const float deltaTime )
{
Camera nextCamera = targetCamera ;
nextCamera . m_lookDist = AZ : : GetMin ( nextCamera . m_lookDist + scrollDelta * m_props. m_dolly Speed, 0.0f ) ;
nextCamera . m_lookDist = AZ : : GetMin ( nextCamera . m_lookDist + scrollDelta * ed_cameraSystemOrbitDollyScroll Speed, 0.0f ) ;
EndActivation ( ) ;
return nextCamera ;
}
@ -425,7 +561,7 @@ namespace AzFramework
{
if ( const auto & input = AZStd : : get_if < DiscreteInputEvent > ( & event ) )
{
if ( input - > m_channelId = = InputDeviceMouse: : Button : : Right )
if ( input - > m_channelId = = m_dollyChannelId )
{
if ( input - > m_state = = InputChannel : : State : : Began )
{
@ -444,7 +580,7 @@ namespace AzFramework
[[maybe_unused]] const float deltaTime )
{
Camera nextCamera = targetCamera ;
nextCamera . m_lookDist = AZ : : GetMin ( nextCamera . m_lookDist + float ( cursorDelta . m_y ) * m_props. m_dolly Speed, 0.0f ) ;
nextCamera . m_lookDist = AZ : : GetMin ( nextCamera . m_lookDist + float ( cursorDelta . m_y ) * ed_cameraSystemOrbitDollyCursor Speed, 0.0f ) ;
return nextCamera ;
}
@ -457,7 +593,7 @@ namespace AzFramework
}
Camera ScrollTranslationCameraInput : : StepCamera (
const Camera & targetCamera , [[maybe_unused]] const ScreenVector & cursorDelta , float scrollDelta ,
const Camera & targetCamera , [[maybe_unused]] const ScreenVector & cursorDelta , const float scrollDelta ,
[[maybe_unused]] const float deltaTime )
{
Camera nextCamera = targetCamera ;
@ -465,38 +601,39 @@ namespace AzFramework
const auto translation_basis = LookTranslation ( nextCamera ) ;
const auto axisY = translation_basis . GetBasisY ( ) ;
nextCamera . m_lookAt + = axisY * scrollDelta * m_props. m_t ranslateSpeed;
nextCamera . m_lookAt + = axisY * scrollDelta * ed_cameraSystemScrollT ranslateSpeed;
EndActivation ( ) ;
return nextCamera ;
}
Camera SmoothCamera ( const Camera & currentCamera , const Camera & targetCamera , const SmoothProps & props , const float deltaTime )
Camera SmoothCamera ( const Camera & currentCamera , const Camera & targetCamera , const float deltaTime )
{
const auto clamp_rotation = [ ] ( const float angle ) { return std : : fmod ( angle + AZ : : Constants : : TwoPi , AZ : : Constants : : TwoPi ) ; } ;
// keep yaw in 0 - 360 range
float target _y aw = clamp_rotation ( targetCamera . m_yaw ) ;
const float current _y aw = clamp_rotation ( currentCamera . m_yaw ) ;
float target Y aw = clamp_rotation ( targetCamera . m_yaw ) ;
const float current Y aw = clamp_rotation ( currentCamera . m_yaw ) ;
auto sign = [ ] ( const float value ) { return static_cast < float > ( ( 0.0f < value ) - ( value < 0.0f ) ) ; } ;
// return the sign of the float input (-1, 0, 1)
const auto sign = [ ] ( const float value ) { return aznumeric_cast < float > ( ( 0.0f < value ) - ( value < 0.0f ) ) ; } ;
// ensure smooth transition when moving across 0 - 360 boundary
const float yaw _delta = target_yaw - current_y aw;
if ( std : : abs ( yaw _d elta) > = AZ : : Constants : : Pi )
const float yaw Delta = targetYaw - currentY aw;
if ( std : : abs ( yaw D elta) > = AZ : : Constants : : Pi )
{
target _y aw - = AZ : : Constants : : TwoPi * sign ( yaw _d elta) ;
target Y aw - = AZ : : Constants : : TwoPi * sign ( yaw D elta) ;
}
Camera camera ;
// note: the math for the lerp smoothing implementation for camera rotation and translation was inspired by this excellent
// note: the math for the lerp smoothing implementation for camera rotation and translation was inspired by this excellent
// article by Scott Lembcke: https://www.gamasutra.com/blogs/ScottLembcke/20180404/316046/Improved_Lerp_Smoothing.php
const float lookRate = std : : exp2 ( props. m_l ookSmoothness) ;
const float lookRate = std : : exp2 ( ed_cameraSystemL ookSmoothness) ;
const float lookT = std : : exp2 ( - lookRate * deltaTime ) ;
camera . m_pitch = AZ : : Lerp ( targetCamera . m_pitch , currentCamera . m_pitch , lookT ) ;
camera . m_yaw = AZ : : Lerp ( target _yaw, current_y aw, lookT ) ;
const float moveRate = std : : exp2 ( props. m_mov eSmoothness) ;
camera . m_yaw = AZ : : Lerp ( target Yaw, currentY aw, lookT ) ;
const float moveRate = std : : exp2 ( ed_cameraSystemTranslat eSmoothness) ;
const float moveT = std : : exp2 ( - moveRate * deltaTime ) ;
camera . m_lookDist = AZ : : Lerp ( targetCamera . m_lookDist , currentCamera . m_lookDist , moveT ) ;
camera . m_lookAt = targetCamera . m_lookAt . Lerp ( currentCamera . m_lookAt , moveT ) ;
@ -508,20 +645,24 @@ namespace AzFramework
const auto & inputChannelId = inputChannel . GetInputChannelId ( ) ;
const auto & inputDeviceId = inputChannel . GetInputDevice ( ) . GetInputDeviceId ( ) ;
if ( inputChannelId = = InputDeviceMouse : : SystemCursorPosition )
const bool wasMouseButton =
AZStd : : any_of ( InputDeviceMouse : : Button : : All . begin ( ) , InputDeviceMouse : : Button : : All . end ( ) , [ inputChannelId ] ( const auto & button ) {
return button = = inputChannelId ;
} ) ;
if ( inputChannelId = = InputDeviceMouse : : Movement : : X | | inputChannelId = = InputDeviceMouse : : Movement : : Y )
{
AZ : : Vector2 systemCursorPositionNormalized = AZ : : Vector2 : : CreateZero ( ) ;
InputSystemCursorRequestBus : : EventResult (
systemCursorPositionNormalized , inputDeviceId , & InputSystemCursorRequestBus : : Events : : GetSystemCursorPositionNormalized ) ;
const auto * position = inputChannel . GetCustomData < AzFramework : : InputChannel : : PositionData2D > ( ) ;
AZ_Assert ( position , " Expected PositionData2D but found nullptr " ) ;
return CursorMotionEvent { ScreenPoint (
systemCursorPositionNormalized . GetX ( ) * windowSize . m_width , systemCursorPositionNormalized . GetY ( ) * windowSize . m_height ) } ;
position- > m_normalizedPosition . GetX ( ) * windowSize . m_width , position- > m_normalizedPosition . GetY ( ) * windowSize . m_height ) } ;
}
else if ( inputChannelId = = InputDeviceMouse : : Movement : : Z )
{
return ScrollEvent { inputChannel . GetValue ( ) } ;
}
else if ( InputDeviceMouse: : IsMouseDevice ( inputDeviceId ) | | InputDeviceKeyboard : : IsKeyboardDevice ( inputDeviceId ) )
else if ( wasMouseButton | | InputDeviceKeyboard : : IsKeyboardDevice ( inputDeviceId ) )
{
return DiscreteInputEvent { inputChannelId , inputChannel . GetState ( ) } ;
}