From 8d94247dd931bcd3d3ceb7b35190989a8bfa2ffc Mon Sep 17 00:00:00 2001 From: gaozheng Date: Tue, 16 Jun 2026 11:27:42 +0800 Subject: [PATCH] =?UTF-8?q?feat(vtk):=20D39=20=E4=BB=A5=E9=80=89=E4=B8=AD?= =?UTF-8?q?=E4=B8=89=E7=BB=B4=E4=BD=93/=E5=88=87=E7=89=87=E4=B8=BA?= =?UTF-8?q?=E4=B8=AD=E5=BF=83=E6=97=8B=E8=BD=AC=E8=A7=86=E5=9B=BE(?= =?UTF-8?q?=E4=B8=8D=E8=B7=B3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 正确做法: 点击只选中(不动相机)→切换点选不跳; 在'按下开始拖动'那刻才把焦点设到 选中切片中心(焦点+位置同步补偿 delta→视向/距离不变、画面不跳), 之后默认 TrackballCamera 即绕该中心旋转。PickInteractorStyle 加 getRotateCenter 回调, InteractionManager 提供 选中切片中心; 无选中则绕默认焦点。ctest 221/221 --- src/render/interact/InteractionManager.cpp | 7 +++++++ src/render/interact/PickInteractorStyle.cpp | 23 ++++++++++++++++++++- src/render/interact/PickInteractorStyle.hpp | 3 +++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/render/interact/InteractionManager.cpp b/src/render/interact/InteractionManager.cpp index e8a4b17..9120546 100644 --- a/src/render/interact/InteractionManager.cpp +++ b/src/render/interact/InteractionManager.cpp @@ -41,6 +41,12 @@ void InteractionManager::installStyle() { style_->onPick = [this](const Vec3& w) { onPicked(w); }; style_->onDoubleClick = [this](const Vec3& w) { onDoubleClicked(w); }; style_->onWheelStep = [this](int dir) { return onWheel(dir); }; + // D39: 提供旋转中心 = 选中切片中心(有选中→true)。style 在按下拖动时据此绕选中切片旋转。 + style_->getRotateCenter = [this](Vec3& c) { + if (selected_ < 0 || selected_ >= static_cast(slices_.size())) return false; + c = slices_[static_cast(selected_)]->center(); + return true; + }; interactor_->SetInteractorStyle(style_); } @@ -50,6 +56,7 @@ void InteractionManager::uninstallStyle() { style_->onPick = nullptr; style_->onDoubleClick = nullptr; style_->onWheelStep = nullptr; + style_->getRotateCenter = nullptr; } // 从 interactor 上彻底摘除自定义 style,避免 interactor 仍持空回调 style(评审 H2)。 if (interactor_) interactor_->SetInteractorStyle(nullptr); diff --git a/src/render/interact/PickInteractorStyle.cpp b/src/render/interact/PickInteractorStyle.cpp index 9791747..2593f7f 100644 --- a/src/render/interact/PickInteractorStyle.cpp +++ b/src/render/interact/PickInteractorStyle.cpp @@ -2,6 +2,7 @@ #include +#include #include #include #include @@ -70,9 +71,29 @@ void PickInteractorStyle::OnLeftButtonDown() { return; // 不进入拖动旋转 } if (hit) { - // 单击命中 → 选中 + 设旋转中心为命中点(拖动绕其旋转)。 + // 单击命中 → 选中所在切片(onPick 内仅选中, 不动相机)。 if (onPick) onPick(world); } + // D39: 有选中三维体/切片时,按下开始拖动前把焦点设到其中心——焦点与位置同步平移同一 delta, + // 视向/距离不变(画面不跳),之后默认 TrackballCamera 即绕该中心旋转。无选中则绕默认焦点。 + // 只在"按下"时设(不是选中时),故切换点选切片不会跳。 + if (getRotateCenter && iren) { + Vec3 c; + if (getRotateCenter(c)) { + const int* p2 = iren->GetEventPosition(); + if (auto* ren = iren->FindPokedRenderer(p2[0], p2[1])) { + if (auto* cam = ren->GetActiveCamera()) { + double f[3], pp[3]; + cam->GetFocalPoint(f); + cam->GetPosition(pp); + cam->SetFocalPoint(c[0], c[1], c[2]); + cam->SetPosition(pp[0] + (c[0] - f[0]), pp[1] + (c[1] - f[1]), + pp[2] + (c[2] - f[2])); + ren->ResetCameraClippingRange(); + } + } + } + } // 始终保留 TrackballCamera 默认拖动(旋转/平移)。 Superclass::OnLeftButtonDown(); } diff --git a/src/render/interact/PickInteractorStyle.hpp b/src/render/interact/PickInteractorStyle.hpp index f66c554..8478b8b 100644 --- a/src/render/interact/PickInteractorStyle.hpp +++ b/src/render/interact/PickInteractorStyle.hpp @@ -27,6 +27,9 @@ public: // 滚轮步进:dir=+1 前/-1 后。返回 true 表示已被消费(有选中切片推进), // false 则执行默认相机缩放。 std::function onWheelStep; + // 取当前旋转中心(D39):有选中三维体/切片→填其中心、返回 true;否则 false(绕默认焦点)。 + // 在"按下开始拖动"时调用一次,把焦点设到该中心(位置同步补偿,画面不变)→ 之后绕它旋转、不跳。 + std::function getRotateCenter; void OnLeftButtonDown() override; void OnMouseWheelForward() override;