diff options
author | rtk0c <[email protected]> | 2022-05-08 10:57:17 -0700 |
---|---|---|
committer | rtk0c <[email protected]> | 2022-05-08 10:57:17 -0700 |
commit | cb4f56fc221d89b6f237ad0e9fdab7fc23e3e877 (patch) | |
tree | 2c1d70fad981625f5e1be2e22d672ab27897ae90 | |
parent | 3f80b0ee6c1432e9ac6bb4716aa9c3b0ac9b231f (diff) |
Changeset: 31 Improved camera controls
-rw-r--r-- | source/Camera.cpp | 3 | ||||
-rw-r--r-- | source/Camera.hpp | 9 | ||||
-rw-r--r-- | source/EditorCorePrivate.cpp | 108 |
3 files changed, 81 insertions, 39 deletions
diff --git a/source/Camera.cpp b/source/Camera.cpp index 4c1f881..39f0369 100644 --- a/source/Camera.cpp +++ b/source/Camera.cpp @@ -8,6 +8,7 @@ Camera::Camera() : eye(0.0f, 0.0f, 0.0f) , target(0.0, 0.0f, -2.0f) , pixelsPerMeter{ 50.0f } // Basic default + , fov{ M_PI / 4 } // 45deg is the convention , perspective{ false } // { } @@ -36,7 +37,7 @@ glm::mat4 Camera::CalcViewMatrix() const { glm::mat4 Camera::CalcProjectionMatrix() const { if (perspective) { - return glm::perspective(90.0f, AppConfig::mainWindowAspectRatio, 0.1f, 1000.0f); + return glm::perspective(fov, AppConfig::mainWindowAspectRatio, 0.1f, 1000.0f); } else { float widthMeters = AppConfig::mainWindowWidth / pixelsPerMeter; float heightMeters = AppConfig::mainWindowHeight / pixelsPerMeter; diff --git a/source/Camera.hpp b/source/Camera.hpp index 72c16f3..7bf0a6c 100644 --- a/source/Camera.hpp +++ b/source/Camera.hpp @@ -8,7 +8,16 @@ public: std::string name; glm::vec3 eye; glm::vec3 target; + + // --- Orthographic settings --- float pixelsPerMeter; + // --- Orthographic settings --- + + // ---- Perspective settings --- + /// In radians + float fov; + // ---- Perspective settings --- + bool perspective; public: diff --git a/source/EditorCorePrivate.cpp b/source/EditorCorePrivate.cpp index de48ea2..4b578dd 100644 --- a/source/EditorCorePrivate.cpp +++ b/source/EditorCorePrivate.cpp @@ -383,12 +383,22 @@ void EditorInstance::Show() { auto& lastFrameInfo = const_cast<RendererFrameInfo&>(mApp->GetWorldRenderer()->GetLastFrameInfo()); auto& view = lastFrameInfo.matrixView; auto& proj = lastFrameInfo.matrixProj; + +#if 0 ImGuizmo::ViewManipulate( glm::value_ptr(view), 200.0f, // TODO ImVec2(viewManipulateRight - 128, viewManipulateTop), ImVec2(128, 128), 0x10101010); + // Extract eye and target position from view matrix + // - View matrix transforms world space to view space + // - Inverse view matrix should transform view space into world space + // - In view space, camera's pos is (0,0,0) and the look/forward vector should be (0,0,-1) + auto invView = glm::inverse(view); + camera.eye = invView * glm::vec4(0, 0, 0, 1); + camera.target = camera.eye + glm::vec3(invView * glm::vec4(0, 0, -1, 1)); +#endif // TODO draw this as a part of the world so it doesn't block objects #if 0 @@ -400,14 +410,6 @@ void EditorInstance::Show() { 100.f); #endif - // Extract eye and target position from view matrix - // - View matrix transforms world space to view space - // - Inverse view matrix should transform view space into world space - // - In view space, camera's pos is (0,0,0) and the look/forward vector should be (0,0,-1) - auto invView = glm::inverse(view); - camera.eye = invView * glm::vec4(0, 0, 0, 1); - camera.target = camera.eye + glm::vec3(invView * glm::vec4(0, 0, -1, 1)); - { // Camera controls auto cameraPos = camera.eye; auto cameraForward = glm::normalize(camera.target - camera.eye); @@ -415,25 +417,34 @@ void EditorInstance::Show() { cameraForward.y = 0.0f; if (mMoveCamKeyboard) { - constexpr float kCameraMoveSpeed = 5.0f; if (ImGui::IsKeyDown(ImGuiKey_W)) { - cameraPos += kCameraMoveSpeed * cameraForward; + cameraPos += mMoveCamSlideSpeed * cameraForward; } if (ImGui::IsKeyDown(ImGuiKey_S)) { auto cameraBack = glm::normalize(-cameraForward); - cameraPos += kCameraMoveSpeed * cameraBack; + cameraPos += mMoveCamSlideSpeed * cameraBack; } if (ImGui::IsKeyDown(ImGuiKey_A)) { - auto cameraLeft = glm::normalize(glm::cross(cameraForward, glm::vec3(0, 1, 0))); - cameraPos += kCameraMoveSpeed * cameraLeft; + auto cameraRight = glm::normalize(glm::cross(cameraForward, glm::vec3(0, 1, 0))); + auto cameraLeft = -cameraRight; + cameraPos += mMoveCamSlideSpeed * cameraLeft; } if (ImGui::IsKeyDown(ImGuiKey_D)) { - auto cameraLeft = glm::normalize(glm::cross(cameraForward, glm::vec3(0, 1, 0))); - auto cameraRight = -cameraLeft; - cameraPos += kCameraMoveSpeed * cameraRight; + auto cameraRight = glm::normalize(glm::cross(cameraForward, glm::vec3(0, 1, 0))); + cameraPos += mMoveCamSlideSpeed * cameraRight; + } + if (ImGui::IsKeyDown(ImGuiKey_Space)) { + cameraPos.y += mMoveCamSlideSpeed; + } + if (ImGui::IsKeyDown(ImGuiKey_LeftShift)) { + cameraPos.y -= mMoveCamSlideSpeed; } } + if (mMoveCamScrollWheel) { + cameraPos += cameraForward * io.MouseWheel * mMoveCamScrollSpeed; + } + camera.SetEyePos(cameraPos); } } else { @@ -569,12 +580,25 @@ void EditorInstance::ShowWorldProperties() { } auto& camera = *mApp->GetActiveCamera(); + + // vvv Camera settings (per instance) ImGui::TextUnformatted("Active camera:"); ImGui::Indent(); -#define CAMERA_POS_TEXT "at (%.3f, %.3f, %.3f)\nlooking at (%.3f, %.3f, %.3f)", camera.eye.x, camera.eye.y, camera.eye.z, camera.target.x, camera.target.y, camera.target.z + ImGui::TextUnformatted(camera.name.c_str()); - ImGui::Text(CAMERA_POS_TEXT); - if (ImGui::BeginPopupContextItem("##CTXMENU")) { + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Object at <%p>", &camera); + } + + ImGui::InputFloat3("Eye", glm::value_ptr(camera.eye)); + if (ImGui::IsMouseReleased(ImGuiMouseButton_Right) && ImGui::IsItemHovered()) { + ImGui::OpenPopup("##CTXMENU"); + } + ImGui::InputFloat3("Target", glm::value_ptr(camera.target)); + if (ImGui::IsMouseReleased(ImGuiMouseButton_Right) && ImGui::IsItemHovered()) { + ImGui::OpenPopup("##CTXMENU"); + } + if (ImGui::BeginPopup("##CTXMENU", ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings)) { if (ImGui::MenuItem("Reset to origin")) { camera.SetEyePos(glm::vec3(1.0f, 1.0f, 1.0f)); } @@ -582,15 +606,9 @@ void EditorInstance::ShowWorldProperties() { camera.eye = glm::vec3(0, 0, 1); camera.target = glm::vec3(0, 0, 0); } - if (ImGui::MenuItem("Copy")) { - char buffer[2048]; - int result = snprintf(buffer, sizeof(buffer), CAMERA_POS_TEXT); - ImGui::SetClipboardText(buffer); - ImGui::AddNotification(ImGuiToast(ImGuiToastType_Success, "Copied to clipboard.")); - } ImGui::EndPopup(); } -#undef CAMERA_POS_TEXT + if (IsCurrentCameraEditor()) { const char* preview; switch (mEcm) { @@ -607,7 +625,7 @@ void EditorInstance::ShowWorldProperties() { camera.SetHasPerspective(false); } } - if (ImGui::Selectable("Side 3D view", mEcm == ECM_Side3D)) { + if (ImGui::Selectable("Side 3D view", mEcm == ECM_Side3D, ImGuiSelectableFlags_None)) { if (mEcm != ECM_Side3D) { mEcm = ECM_Side3D; @@ -619,11 +637,10 @@ void EditorInstance::ShowWorldProperties() { camera.target.z = 0.0f; // New setup: move the eye back at an angle - glm::vec3 vec; - vec.x = std::cos(60.0f); - vec.y = 0.0f; - vec.z = std::sin(60.0f); - camera.eye = camera.target + 4.0f * vec; + camera.eye = camera.target; + camera.eye.x += 4.0f * std::cos(60.0f); + camera.eye.y += 0.0f; + camera.eye.z += 4.0f * std::sin(60.0f); camera.SetHasPerspective(true); } @@ -632,17 +649,32 @@ void EditorInstance::ShowWorldProperties() { } } + ImGui::Checkbox("Perspective", &camera.perspective); + if (camera.perspective) { + float fovDegress = camera.fov / M_PI * 180.0f; + if (ImGui::SliderFloat("FOV", &fovDegress, 1.0f, 180.0f)) { + camera.fov = fovDegress / 180.0f * M_PI; + } + } else { + if (ImGui::InputFloat("Pixels per meter", &camera.pixelsPerMeter)) { + camera.pixelsPerMeter = std::max(camera.pixelsPerMeter, 0.0f); + } + } + + ImGui::Unindent(); + // ^^^ Camera settings (per instance) + // vvv Camera control settings + ImGui::TextUnformatted("Camera controls:"); + ImGui::Indent(); + ImGui::Checkbox("Move camera with WASD", &mMoveCamKeyboard); - ImGui::SliderFloat("Camera slide speed", &mMoveCamSlideSpeed, 0.1f, 10.0f); + ImGui::SliderFloat("Slide speed", &mMoveCamSlideSpeed, 0.1f, 10.0f); ImGui::Checkbox("Move camera with scoll wheel", &mMoveCamScrollWheel); - ImGui::SliderFloat("Camera scroll speed", &mMoveCamScrollSpeed, 0.01, 10.0f); - - if (ImGui::InputFloat("Pixels per meter", &camera.pixelsPerMeter)) { - camera.pixelsPerMeter = std::max(camera.pixelsPerMeter, 0.0f); - } + ImGui::SliderFloat("Scroll speed", &mMoveCamScrollSpeed, 0.01, 10.0f); ImGui::Unindent(); + // ^^^ Camera control settings } // TOOD move resource-specific and gameobject-specific inspector code into attachments mechanism |