diff --git a/examples/ExampleApps/MovingCubeApp.cpp b/examples/ExampleApps/MovingCubeApp.cpp index 24874fd..9297ee5 100644 --- a/examples/ExampleApps/MovingCubeApp.cpp +++ b/examples/ExampleApps/MovingCubeApp.cpp @@ -16,6 +16,7 @@ #include "Scene/Camera.hpp" #include "Scene/SimpleAnimationController.hpp" #include "Scene/SequenceAnimationController.hpp" +#include "Scene/MorphableCameraController.hpp" #include "Scene/UI/PerformanceInfo.hpp" #include "Input/InputManager.hpp" #include "Host/GraphicsAppManager.hpp" @@ -37,7 +38,8 @@ namespace OpenVulkano class MovingCubeAppImpl final : public MovingCubeApp { Scene::Scene m_scene; - Scene::PerspectiveCamera m_camera; + Scene::MorphableCamera m_camera; + Scene::MorphableCameraController m_morphableCameraControl; FreeCamCameraController m_cameraControl; Scene::Material m_material; Scene::Shader m_shader; @@ -74,48 +76,54 @@ namespace OpenVulkano CompleteSceneElement(dest); } - void CreatePlane(SceneElement *dest, const Math::Vector4f& color) + void CreatePlane(SceneElement *dest, const Math::Vector4f &color) { dest->m_geometry = Scene::GeometryFactory::MakePlane(1, 1, color); CompleteSceneElement(dest); } - void CreateSphere(SceneElement *dest, const Math::Vector4f& color) + void CreateSphere(SceneElement *dest, const Math::Vector4f &color) { dest->m_geometry = Scene::GeometryFactory::MakeSphere(1, 32, 16, color); CompleteSceneElement(dest); } - void CreateHemisphere(SceneElement *dest, const Math::Vector4f& color) + void CreateHemisphere(SceneElement *dest, const Math::Vector4f &color) { dest->m_geometry = Scene::GeometryFactory::MakeHemisphere(1, 16, 16, color); CompleteSceneElement(dest); } - void CreateTriangle(SceneElement *dest, const Math::Vector4f& color) + void CreateTriangle(SceneElement *dest, const Math::Vector4f &color) { - dest->m_geometry = Scene::GeometryFactory::MakeTriangle(Math::Vector3f(0.5, 0., 0.), Math::Vector3f(0., 0.5, 0.), Math::Vector3f(-0.5, 0., 0.), color); + dest->m_geometry = Scene::GeometryFactory::MakeTriangle( + Math::Vector3f(0.5, 0., 0.), Math::Vector3f(0., 0.5, 0.), Math::Vector3f(-0.5, 0., 0.), color); CompleteSceneElement(dest); } - void CreateCylinder(SceneElement *dest, const Math::Vector4f& color) + void CreateCylinder(SceneElement *dest, const Math::Vector4f &color) { dest->m_geometry = Scene::GeometryFactory::MakeCylinder(1, 3, 64, color); CompleteSceneElement(dest); } - void CreatePyramid(SceneElement *dest, const Math::Vector4f& color) + void CreatePyramid(SceneElement *dest, const Math::Vector4f &color) { dest->m_geometry = Scene::GeometryFactory::MakePyramid(0.5, 2, color); CompleteSceneElement(dest); } public: + MovingCubeAppImpl() : m_camera(90, 16, 9, 0.1, 1000) + { + m_morphableCameraControl.Init(&m_camera); + m_cameraControl.Init(&m_camera); + } + void Init() override { auto engineConfig = EngineConfiguration::GetEngineConfiguration(); m_camera.Init(70, 16, 9, 0.1, 100); - // m_camera.SetMatrix(OpenVulkano::Math::Utils::translate(OpenVulkano::Math::Matrix4f(1), OpenVulkano::Math::Vector3f_SIMD(0, 0, -50))); m_scene.Init(); m_scene.SetCamera(&m_camera); @@ -136,16 +144,23 @@ namespace OpenVulkano Math::Pose srcPose(Math::Quaternion(), Math::Vector3f_SIMD(-3, 0, 0)); Math::Pose destPose(Math::Quaternion(), Math::Vector3f_SIMD(3, 0, 0)); m_simpleAnimationController.SetPoses(srcPose, destPose); - m_simpleAnimationController.m_completionEvent += EventHandler(this, &MovingCubeAppImpl::OnSimpleAnimationCompleted); + m_simpleAnimationController.m_completionEvent += + EventHandler(this, &MovingCubeAppImpl::OnSimpleAnimationCompleted); m_sequenceAnimationController.EnableLoop(true); m_sequenceAnimationController.SetNode(&m_redBox.m_node); - m_sequenceAnimationController.AddAnimationStep(Math::PoseF(Math::Utils::normalize(Math::QuaternionF(1, 0, 0, 1)), Math::Vector3f_SIMD(0, 0, 1)), 5); - m_sequenceAnimationController.AddAnimationStep(Math::PoseF(Math::Utils::normalize(Math::QuaternionF(2, 1, 0, 1)), Math::Vector3f_SIMD(1, 1, -1)), 3); - m_sequenceAnimationController.AddAnimationStep(Math::PoseF(Math::Utils::normalize(Math::QuaternionF(1, 1, 1, 1)), Math::Vector3f_SIMD(2, 1, -2)), 3); - m_sequenceAnimationController.AddAnimationStep(Math::PoseF(Math::Utils::normalize(Math::QuaternionF(0, 1, 1, 0)), Math::Vector3f_SIMD(2, 1, -1)), 3); - m_sequenceAnimationController.AddAnimationStep(Math::PoseF(Math::Utils::normalize(Math::QuaternionF(3, 2, 1, 1)), Math::Vector3f_SIMD(1, 1, -1)), 3); - m_sequenceAnimationController.AddAnimationStep(Math::PoseF(Math::Utils::normalize(Math::QuaternionF(0, 0, 1, 1)), Math::Vector3f_SIMD(0, 1, 0)), 1); + m_sequenceAnimationController.AddAnimationStep( + Math::PoseF(Math::Utils::normalize(Math::QuaternionF(1, 0, 0, 1)), Math::Vector3f_SIMD(0, 0, 1)), 5); + m_sequenceAnimationController.AddAnimationStep( + Math::PoseF(Math::Utils::normalize(Math::QuaternionF(2, 1, 0, 1)), Math::Vector3f_SIMD(1, 1, -1)), 3); + m_sequenceAnimationController.AddAnimationStep( + Math::PoseF(Math::Utils::normalize(Math::QuaternionF(1, 1, 1, 1)), Math::Vector3f_SIMD(2, 1, -2)), 3); + m_sequenceAnimationController.AddAnimationStep( + Math::PoseF(Math::Utils::normalize(Math::QuaternionF(0, 1, 1, 0)), Math::Vector3f_SIMD(2, 1, -1)), 3); + m_sequenceAnimationController.AddAnimationStep( + Math::PoseF(Math::Utils::normalize(Math::QuaternionF(3, 2, 1, 1)), Math::Vector3f_SIMD(1, 1, -1)), 3); + m_sequenceAnimationController.AddAnimationStep( + Math::PoseF(Math::Utils::normalize(Math::QuaternionF(0, 0, 1, 1)), Math::Vector3f_SIMD(0, 1, 0)), 1); m_sequenceAnimationController.SetAnimationPoseResetTime(10); CreatePlane(&m_plane, Math::Vector4f(0.3, 0.6, 0.9, 1.0)); @@ -180,22 +195,15 @@ namespace OpenVulkano void Tick() override { m_cameraControl.Tick(); + m_morphableCameraControl.Tick(); m_simpleAnimationController.Tick(); m_sequenceAnimationController.Tick(); } - void Close() override - { - } + void Close() override {} }; - IGraphicsApp* MovingCubeApp::Create() - { - return new MovingCubeAppImpl(); - } + IGraphicsApp *MovingCubeApp::Create() { return new MovingCubeAppImpl(); } - std::unique_ptr MovingCubeApp::CreateUnique() - { - return std::make_unique(); - } + std::unique_ptr MovingCubeApp::CreateUnique() { return std::make_unique(); } } diff --git a/openVulkanoCpp/Scene/Camera.hpp b/openVulkanoCpp/Scene/Camera.hpp index 612f6b3..f8b718c 100644 --- a/openVulkanoCpp/Scene/Camera.hpp +++ b/openVulkanoCpp/Scene/Camera.hpp @@ -233,7 +233,7 @@ namespace OpenVulkano::Scene return 2.0f * atanf(tanf(m_fov * 0.5f) * m_aspect); } - void UpdateProjectionMatrix() final + void UpdateProjectionMatrix() { m_projection = Math::Utils::perspectiveRH_ZO(m_fov, m_aspect, m_nearPlane, m_farPlane); UpdateViewProjectionMatrix(); diff --git a/openVulkanoCpp/Scene/Material.hpp b/openVulkanoCpp/Scene/Material.hpp index 59b199b..5c6e206 100644 --- a/openVulkanoCpp/Scene/Material.hpp +++ b/openVulkanoCpp/Scene/Material.hpp @@ -18,6 +18,6 @@ namespace OpenVulkano::Scene struct Material { MaterialProperties properties; - Texture* texture; + Texture* texture = nullptr; }; } diff --git a/openVulkanoCpp/Scene/MorphableCamera.cpp b/openVulkanoCpp/Scene/MorphableCamera.cpp new file mode 100644 index 0000000..3643bf6 --- /dev/null +++ b/openVulkanoCpp/Scene/MorphableCamera.cpp @@ -0,0 +1,42 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "MorphableCamera.hpp" + +namespace OpenVulkano::Scene +{ + namespace + { + Math::Matrix4f BlendMatrices(const Math::Matrix4f& mat1, const Math::Matrix4f& mat2, float t) + { + Math::Matrix4f result; + for (int i = 0; i < 4; ++i) + { + result[i] = Math::Utils::mix(mat1[i], mat2[i], t); + } + return result; + } + } + void MorphableCamera::UpdateProjectionMatrix() + { + PerspectiveCamera::UpdateProjectionMatrix(); + if (m_morphState != 0) + { + float aspectH = m_aspect; + float aspectV = 1; + if (m_morphState == 1) + { + m_projection = Math::Utils::orthoRH_ZO(-aspectH, aspectH, -aspectV, aspectV, m_nearPlane, m_farPlane); + } + else + { + m_orthoMatrix = Math::Utils::orthoRH_ZO(-aspectH, aspectH, -aspectV, aspectV, m_nearPlane, m_farPlane); + m_projection = BlendMatrices(m_projection, m_orthoMatrix, m_morphState); + } + UpdateViewProjectionMatrix(); + } + } +} \ No newline at end of file diff --git a/openVulkanoCpp/Scene/MorphableCamera.hpp b/openVulkanoCpp/Scene/MorphableCamera.hpp new file mode 100644 index 0000000..47b8b10 --- /dev/null +++ b/openVulkanoCpp/Scene/MorphableCamera.hpp @@ -0,0 +1,33 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "Camera.hpp" +#include "Math/Math.hpp" + +namespace OpenVulkano::Scene +{ + class MorphableCamera : public PerspectiveCamera + { + float m_morphState; + Math::Matrix4f m_orthoMatrix; + + public: + MorphableCamera(float fovDegrees, float width, float height, float nearPlane, float farPlane) + : PerspectiveCamera(fovDegrees, nearPlane, farPlane, width, height), m_morphState(0.0f) + { + UpdateProjectionMatrix(); + } + + void SetMorphState(float state) + { + m_morphState = Math::Utils::clamp(state, 0.0f, 1.0f); + UpdateProjectionMatrix(); + } + + void UpdateProjectionMatrix() override; + }; +} \ No newline at end of file diff --git a/openVulkanoCpp/Scene/MorphableCameraController.cpp b/openVulkanoCpp/Scene/MorphableCameraController.cpp new file mode 100644 index 0000000..af3371c --- /dev/null +++ b/openVulkanoCpp/Scene/MorphableCameraController.cpp @@ -0,0 +1,65 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "MorphableCameraController.hpp" +#include "Input/InputManager.hpp" +#include "Input/InputKey.hpp" +#include "Base/FrameMetadata.hpp" +#include "Scene/Camera.hpp" + +namespace OpenVulkano::Scene +{ + MorphableCameraController::MorphableCameraController(MorphableCamera* camera) + : CameraController(camera) + , m_animationDuration(1.0f) + , m_currentTime(0.0f) + , m_isMorphing(false) + , m_targetMorphStatePerspective(false) + { + auto input = OpenVulkano::Input::InputManager::GetInstance(); + m_actionMorph = input->GetAction("morph"); + } + + void MorphableCameraController::Init(MorphableCamera* camera) + { + CameraController::Init(camera); + m_actionMorph->BindKey(Input::InputKey::Keyboard::KEY_P); + } + + void MorphableCameraController::Tick() + { + auto input = OpenVulkano::Input::InputManager::GetInstance(); + + bool isMorphingDown = input->GetButton(m_actionMorph); + if (!m_wasMorphingKeyDown && isMorphingDown) + { + m_isMorphing = true; + m_currentTime = 0.0f; + m_targetMorphStatePerspective = !m_targetMorphStatePerspective; + } + m_wasMorphingKeyDown = isMorphingDown; + + if (m_isMorphing) + { + m_currentTime += CURRENT_FRAME.frameTime; + if (m_currentTime > m_animationDuration) m_currentTime = m_animationDuration; + float t = m_currentTime / m_animationDuration; + if (t >= 1.0f) + { + t = 1.0f; + m_isMorphing = false; + } + float newState = m_targetMorphStatePerspective ? t : (1.0f - t); + static_cast(GetCamera())->SetMorphState(newState); + } + } + + void MorphableCameraController::SetTargetState(bool toPerspective) + { + m_targetMorphStatePerspective = toPerspective; + m_isMorphing = true; + } +} \ No newline at end of file diff --git a/openVulkanoCpp/Scene/MorphableCameraController.hpp b/openVulkanoCpp/Scene/MorphableCameraController.hpp new file mode 100644 index 0000000..be9cb87 --- /dev/null +++ b/openVulkanoCpp/Scene/MorphableCameraController.hpp @@ -0,0 +1,37 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "MorphableCamera.hpp" +#include "Controller/CameraController.hpp" +#include "Input/InputManager.hpp" +#include "Input/InputKey.hpp" +#include "Math/Math.hpp" + +namespace OpenVulkano::Scene +{ + class MorphableCameraController final : public CameraController + { + double m_animationDuration; + double m_currentTime; + bool m_isMorphing; + bool m_targetMorphStatePerspective; // true for perspective, false for orthographic + + Input::InputAction* m_actionMorph; + bool m_wasMorphingKeyDown = false; + + public: + MorphableCameraController(MorphableCamera* camera = nullptr); + + void Init(MorphableCamera* camera); + void Tick() override; + + void SetDuration(double duration) { m_animationDuration = duration; } + double GetDuration() { return m_animationDuration; } + void SetTargetState(bool toPerspective); + void Reset() { m_currentTime = 0; } + }; +} \ No newline at end of file