.. _program_listing_file_Source_Camera_Src_FlyThroughCamera.cpp: Program Listing for File FlyThroughCamera.cpp ============================================= |exhale_lsh| :ref:`Return to documentation for file ` (``Source\Camera\Src\FlyThroughCamera.cpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #include "Camera/FlyThroughCamera.h" #include "Math/Transform.h" #include "Math/Geometry.h" #include "Core/Events.h" namespace Azura { namespace { const Vector3f UNIT_LOOK = Vector3f(0, 0, 1); const Vector3f UNIT_RIGHT = Vector3f(1, 0, 0); const Vector3f UNIT_UP = Vector3f(0, 1, 0); } // namespace FlyThroughCamera::FlyThroughCamera(U32 width, U32 height) : Camera(width, height), m_cachedMouseX(width / 2.0f), m_cachedMouseY(height / 2.0f) { FlyThroughCamera::Recompute(); } void FlyThroughCamera::Recompute() { const Matrix4f transform = Matrix4f::FromRotationMatrix(Matrix4f::RotationY(m_theta)) * Matrix4f::FromRotationMatrix(Matrix3f::RotationX(m_phi)); m_look = (transform * Vector4f(UNIT_LOOK, 0)).xyz(); m_up = (transform * Vector4f(UNIT_UP, 0)).xyz(); m_right = (transform * Vector4f(UNIT_RIGHT, 0)).xyz(); m_ref = m_look.Normalized(); m_ref += m_eye; m_view = Transform::LookAt(m_ref, m_eye, m_up); m_proj = Transform::Perspective(m_fovY, m_aspect, m_nearClip, m_farClip); m_viewProj = m_proj * m_view; m_invViewProj = m_viewProj.Inverse(); } void FlyThroughCamera::OnMouseEvent(MouseEvent mouseEvent) { if (mouseEvent.m_internalType != MouseEventType::MouseUpdate) { return; } const float currentX = mouseEvent.m_eventX; const float currentY = mouseEvent.m_eventY; const float diffX = currentX - m_cachedMouseX; const float diffY = currentY - m_cachedMouseY; RotateAboutRight(diffY * m_sensitivity * 2.0f); RotateAboutUp(diffX * m_sensitivity * 2.0f); Recompute(); } void FlyThroughCamera::OnKeyEvent(KeyEvent keyEvent) { if (keyEvent.m_internalType == KeyEventType::KeyPress) { switch (keyEvent.m_key) { case KeyboardKey::W: m_moveForwardFactor = 1; break; case KeyboardKey::S: m_moveForwardFactor = -1; break; case KeyboardKey::D: m_moveRightFactor = 1; break; case KeyboardKey::A: m_moveRightFactor = -1; break; case KeyboardKey::Unmapped: case KeyboardKey::Esc: default: break; } } else if (keyEvent.m_internalType == KeyEventType::KeyRelease) { switch (keyEvent.m_key) { case KeyboardKey::W: m_moveForwardFactor = 0; break; case KeyboardKey::S: m_moveForwardFactor = 0; break; case KeyboardKey::D: m_moveRightFactor = 0; break; case KeyboardKey::A: m_moveRightFactor = 0; break; case KeyboardKey::Unmapped: case KeyboardKey::Esc: case KeyboardKey::Up: case KeyboardKey::Down: case KeyboardKey::Left: case KeyboardKey::Right: case KeyboardKey::T: case KeyboardKey::Y: default: break; } } } void FlyThroughCamera::SetTranslationStepSize(float amount) { m_stepSize = amount; } void FlyThroughCamera::RotateAboutUp(float degrees) { m_theta += Math::ToRadians(degrees); if (m_theta >= Math::TWO_PI) { m_theta = m_theta - Math::TWO_PI; } if (m_theta < 0) { m_theta = Math::TWO_PI + m_theta; } } void FlyThroughCamera::SetAngleAboutRight(float ndcY) { const float deg = ndcY * 89 * -1; m_phi = Math::ToRadians(deg); } void FlyThroughCamera::RotateAboutRight(float degrees) { m_phi += Math::ToRadians(degrees); if (m_phi >= Math::PI_OVER2) { m_phi = Math::PI_OVER2 - Math::ONE_DEGREE_RADIAN; } if (m_phi <= -Math::PI_OVER2) { m_phi = -Math::PI_OVER2 + Math::ONE_DEGREE_RADIAN; } } void FlyThroughCamera::TranslateAlongLook(float amt) { const Vector3f translation = m_look * amt; m_eye += translation; m_ref += translation; } void FlyThroughCamera::TranslateAlongRight(float amt) { const Vector3f translation = m_right * amt; m_eye += translation; m_ref += translation; } void FlyThroughCamera::Update(float timeDelta) { const float distance = m_stepSize * timeDelta; bool needsRecompute = false; if (m_moveForwardFactor != 0) { TranslateAlongLook(distance * m_moveForwardFactor); needsRecompute = true; } if (m_moveRightFactor != 0) { TranslateAlongRight(distance * m_moveRightFactor); needsRecompute = true; } if (needsRecompute) { Recompute(); } } } // namespace Azura