From 230ff5bb5ed570a46bf004462b1f79d557b3b4ed Mon Sep 17 00:00:00 2001 From: Stanislav Denisov Date: Fri, 6 Feb 2026 07:15:58 +0100 Subject: [PATCH] Fix orbital camera mode transition (#1537) --- Editor/CameraWindow.cpp | 34 ++++++++++++++++++++++++++++++++++ Editor/Editor.cpp | 17 +++++++++++++---- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/Editor/CameraWindow.cpp b/Editor/CameraWindow.cpp index 6031cb30d..09ba1621b 100644 --- a/Editor/CameraWindow.cpp +++ b/Editor/CameraWindow.cpp @@ -207,6 +207,40 @@ void CameraWindow::Create(EditorComponent* _editor) fpsCheckBox.OnClick([this](wi::gui::EventArgs args) { editor->main->config.GetSection("camera").Set("fps", args.bValue); editor->main->config.Commit(); + + if (!args.bValue) + { + // Transitioning from FPS to Orbital: + // camera_transform holds full world transform from FPS mode, + // decompose it into camera_target (pivot point with rotation) + // and camera_transform (local Z offset as the orbit arm) + auto& editorscene = editor->GetCurrentEditorScene(); + const CameraComponent& camera = editorscene.camera; + + float arm_length = 10.0f; + XMVECTOR eye = camera.GetEye(); + XMVECTOR at = camera.GetAt(); + XMVECTOR target_pos = XMVectorAdd(eye, at * arm_length); + + // Build a look-at rotation for the target (facing from target back to eye) + XMVECTOR target_forward = XMVector3Normalize(XMVectorSubtract(eye, target_pos)); + XMVECTOR up = XMVectorSet(0, 1, 0, 0); + XMVECTOR right = XMVector3Normalize(XMVector3Cross(up, target_forward)); + up = XMVector3Cross(target_forward, right); + XMMATRIX rot_matrix = XMMATRIX(right, up, target_forward, XMVectorSet(0, 0, 0, 1)); + XMVECTOR target_quat = XMQuaternionRotationMatrix(rot_matrix); + + editorscene.camera_target = {}; + XMStoreFloat3(&editorscene.camera_target.translation_local, target_pos); + XMStoreFloat4(&editorscene.camera_target.rotation_local, target_quat); + editorscene.camera_target.UpdateTransform(); + + editorscene.camera_transform = {}; + editorscene.camera_transform.translation_local = XMFLOAT3(0, 0, -arm_length); + editorscene.camera_transform.UpdateTransform_Parented(editorscene.camera_target); + + editorscene.cam_move = {}; + } }); AddWidget(&fpsCheckBox); diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index f41cb4463..83e1fa048 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -6732,12 +6732,21 @@ void EditorComponent::FocusCameraOnSelected() centerV = XMLoadFloat3(&aabb_center); } + XMVECTOR target_forward = XMVector3Normalize(XMVectorNegate(camera.GetAt())); + XMVECTOR up = XMVectorSet(0, 1, 0, 0); + XMVECTOR right = XMVector3Normalize(XMVector3Cross(up, target_forward)); + up = XMVector3Cross(target_forward, right); + XMMATRIX rot_matrix = XMMATRIX(right, up, target_forward, XMVectorSet(0, 0, 0, 1)); + XMVECTOR target_quat = XMQuaternionRotationMatrix(rot_matrix); + editorscene.camera_target = {}; - editorscene.camera_target.Translate(centerV); + XMStoreFloat3(&editorscene.camera_target.translation_local, centerV); + XMStoreFloat4(&editorscene.camera_target.rotation_local, target_quat); editorscene.camera_target.UpdateTransform(); - editorscene.camera_transform.translation_local = {}; - editorscene.camera_transform.Translate(centerV - camera.GetAt() * focus_offset); - editorscene.camera_transform.UpdateTransform(); + + editorscene.camera_transform = {}; + editorscene.camera_transform.translation_local = XMFLOAT3(0, 0, -focus_offset); + editorscene.camera_transform.UpdateTransform_Parented(editorscene.camera_target); editorscene.cam_move = {}; }