aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2022-05-08 10:57:17 -0700
committerrtk0c <[email protected]>2022-05-08 10:57:17 -0700
commitcb4f56fc221d89b6f237ad0e9fdab7fc23e3e877 (patch)
tree2c1d70fad981625f5e1be2e22d672ab27897ae90
parent3f80b0ee6c1432e9ac6bb4716aa9c3b0ac9b231f (diff)
Changeset: 31 Improved camera controls
-rw-r--r--source/Camera.cpp3
-rw-r--r--source/Camera.hpp9
-rw-r--r--source/EditorCorePrivate.cpp108
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