feat/vtk-3d-view #7
|
|
@ -4,10 +4,13 @@
|
|||
|
||||
#include <vtkCamera.h>
|
||||
#include <vtkCellPicker.h>
|
||||
#include <vtkMath.h>
|
||||
#include <vtkNew.h>
|
||||
#include <vtkObjectFactory.h>
|
||||
#include <vtkRenderWindow.h>
|
||||
#include <vtkRenderWindowInteractor.h>
|
||||
#include <vtkRenderer.h>
|
||||
#include <vtkTransform.h>
|
||||
|
||||
namespace geopro::render::interact {
|
||||
|
||||
|
|
@ -74,30 +77,55 @@ void PickInteractorStyle::OnLeftButtonDown() {
|
|||
// 单击命中 → 选中所在切片(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 默认拖动(旋转/平移)。
|
||||
// 不在按下时动相机(动相机=跳);绕选中物旋转在 Rotate() 内做(增量绕支点,不跳)。
|
||||
Superclass::OnLeftButtonDown();
|
||||
}
|
||||
|
||||
void PickInteractorStyle::Rotate() {
|
||||
Vec3 c;
|
||||
if (!this->CurrentRenderer || !getRotateCenter || !getRotateCenter(c)) {
|
||||
Superclass::Rotate(); // 无选中物 → 默认绕焦点旋转
|
||||
return;
|
||||
}
|
||||
auto* rwi = this->Interactor;
|
||||
auto* cam = this->CurrentRenderer->GetActiveCamera();
|
||||
if (!rwi || !cam) return;
|
||||
const int dx = rwi->GetEventPosition()[0] - rwi->GetLastEventPosition()[0];
|
||||
const int dy = rwi->GetEventPosition()[1] - rwi->GetLastEventPosition()[1];
|
||||
const int* size = this->CurrentRenderer->GetRenderWindow()->GetSize();
|
||||
if (size[0] <= 0 || size[1] <= 0) return;
|
||||
// 与 TrackballCamera 同口径的角度映射。
|
||||
const double azimuth = dx * (-20.0 / size[0]) * this->MotionFactor;
|
||||
const double elevation = dy * (-20.0 / size[1]) * this->MotionFactor;
|
||||
|
||||
double up[3], dop[3], right[3];
|
||||
cam->GetViewUp(up);
|
||||
cam->GetDirectionOfProjection(dop); // 归一化的 (focal-pos)
|
||||
vtkMath::Cross(dop, up, right); // 屏幕"右"轴
|
||||
vtkMath::Normalize(right);
|
||||
|
||||
// 绕中心 c 的支点:T(c)·R(up,azimuth)·R(right,elevation)·T(-c),作用于 position/focal;up 只转不平移。
|
||||
vtkNew<vtkTransform> t;
|
||||
t->Identity();
|
||||
t->Translate(c[0], c[1], c[2]);
|
||||
t->RotateWXYZ(azimuth, up[0], up[1], up[2]);
|
||||
t->RotateWXYZ(elevation, right[0], right[1], right[2]);
|
||||
t->Translate(-c[0], -c[1], -c[2]);
|
||||
|
||||
double pos[3], foc[3], npos[3], nfoc[3], nup[3];
|
||||
cam->GetPosition(pos);
|
||||
cam->GetFocalPoint(foc);
|
||||
t->TransformPoint(pos, npos);
|
||||
t->TransformPoint(foc, nfoc);
|
||||
t->TransformVector(up, nup); // 仅旋转部分作用于向量
|
||||
cam->SetPosition(npos);
|
||||
cam->SetFocalPoint(nfoc);
|
||||
cam->SetViewUp(nup);
|
||||
cam->OrthogonalizeViewUp();
|
||||
if (this->AutoAdjustCameraClippingRange) this->CurrentRenderer->ResetCameraClippingRange();
|
||||
rwi->Render();
|
||||
}
|
||||
|
||||
void PickInteractorStyle::OnMouseWheelForward() {
|
||||
if (onWheelStep && onWheelStep(+1)) return; // 有选中切片 → 推进,消费滚轮
|
||||
Superclass::OnMouseWheelForward(); // 否则默认缩放
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@ public:
|
|||
void OnLeftButtonDown() override;
|
||||
void OnMouseWheelForward() override;
|
||||
void OnMouseWheelBackward() override;
|
||||
// 绕选中物中心旋转(D39):有 getRotateCenter 时, 绕该中心增量旋转整个相机(位置+焦点+up),
|
||||
// 中心在世界/屏幕都不动→不跳; 否则回退默认(绕焦点)。
|
||||
void Rotate() override;
|
||||
|
||||
protected:
|
||||
PickInteractorStyle() = default;
|
||||
|
|
|
|||
Loading…
Reference in New Issue