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;