diff --git a/src/Gui/DlgSettings3DView.ui b/src/Gui/DlgSettings3DView.ui
index 11fbe268f9..4e48fa2966 100644
--- a/src/Gui/DlgSettings3DView.ui
+++ b/src/Gui/DlgSettings3DView.ui
@@ -323,6 +323,22 @@
+ -
+
+
+ Drag at cursor
+
+
+ false
+
+
+ DragAtCursor
+
+
+ View
+
+
+
-
@@ -624,6 +640,7 @@
checkBoxZoomAtCursor
spinBoxZoomStep
checkBoxInvertZoom
+ checkBoxDragAtCursor
FloatSpinBox_EyeDistance
checkBoxBacklight
backlightColor
diff --git a/src/Gui/DlgSettings3DViewImp.cpp b/src/Gui/DlgSettings3DViewImp.cpp
index f6811e4ddb..888b8e57fa 100644
--- a/src/Gui/DlgSettings3DViewImp.cpp
+++ b/src/Gui/DlgSettings3DViewImp.cpp
@@ -89,6 +89,7 @@ void DlgSettings3DViewImp::saveSettings()
checkBoxZoomAtCursor->onSave();
checkBoxInvertZoom->onSave();
spinBoxZoomStep->onSave();
+ checkBoxDragAtCursor->onSave();
CheckBox_CornerCoordSystem->onSave();
CheckBox_ShowFPS->onSave();
CheckBox_useVBO->onSave();
@@ -107,6 +108,7 @@ void DlgSettings3DViewImp::loadSettings()
checkBoxZoomAtCursor->onRestore();
checkBoxInvertZoom->onRestore();
spinBoxZoomStep->onRestore();
+ checkBoxDragAtCursor->onRestore();
CheckBox_CornerCoordSystem->onRestore();
CheckBox_ShowFPS->onRestore();
CheckBox_useVBO->onRestore();
diff --git a/src/Gui/NavigationStyle.cpp b/src/Gui/NavigationStyle.cpp
index d239035a27..3f22ed20d1 100644
--- a/src/Gui/NavigationStyle.cpp
+++ b/src/Gui/NavigationStyle.cpp
@@ -53,8 +53,9 @@ struct NavigationStyleP {
int animationsteps;
int animationdelta;
SbVec3f focal1, focal2;
- SbVec3f startDragPoint;
- SbBool dragPointFound;
+ SbVec3f rotationCenter;
+ SbBool rotationCenterFound;
+ NavigationStyle::RotationCenterMode rotationCenterMode;
SbBool dragAtCursor;
SbRotation endRotation;
SoTimerSensor * animsensor;
@@ -68,7 +69,8 @@ struct NavigationStyleP {
this->animsensor = 0;
this->sensitivity = 2.0f;
this->resetcursorpos = false;
- this->dragPointFound = false;
+ this->rotationCenterFound = false;
+ this->rotationCenterMode = NavigationStyle::ScenePointAtCursor;
this->dragAtCursor = false;
}
static void viewAnimationCB(void * data, SoSensor * sensor);
@@ -239,6 +241,8 @@ void NavigationStyle::initialize()
("User parameter:BaseApp/Preferences/View")->GetBool("ZoomAtCursor",true);
this->zoomStep = App::GetApplication().GetParameterGroupByPath
("User parameter:BaseApp/Preferences/View")->GetFloat("ZoomStep",0.2f);
+ PRIVATE(this)->dragAtCursor = App::GetApplication().GetParameterGroupByPath
+ ("User parameter:BaseApp/Preferences/View")->GetBool("DragAtCursor",false);
}
void NavigationStyle::finalize()
@@ -331,7 +335,7 @@ void NavigationStyle::lookAtPoint(const SbVec3f& pos)
{
SoCamera* cam = viewer->getSoRenderManager()->getCamera();
if (cam == 0) return;
- PRIVATE(this)->dragPointFound = false;
+ PRIVATE(this)->rotationCenterFound = false;
// Find global coordinates of focal point.
SbVec3f direction;
@@ -667,7 +671,7 @@ void NavigationStyle::panToCenter(const SbPlane & pplane, const SbVec2f & currpo
const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion();
float ratio = vp.getViewportAspectRatio();
panCamera(viewer->getSoRenderManager()->getCamera(), ratio, pplane, SbVec2f(0.5,0.5), currpos);
- PRIVATE(this)->dragPointFound = false;
+ PRIVATE(this)->rotationCenterFound = false;
}
/** Dependent on the camera type this will either shrink or expand the
@@ -852,6 +856,33 @@ void NavigationStyle::doRotate(SoCamera * camera, float angle, const SbVec2f& po
}
+SbVec3f NavigationStyle::getRotationCenter(SbBool* ok) const
+{
+ if (ok)
+ *ok = PRIVATE(this)->rotationCenterFound;
+ return PRIVATE(this)->rotationCenter;
+}
+
+void NavigationStyle::setRotationCenter(const SbVec3f& cnt)
+{
+ PRIVATE(this)->rotationCenter = cnt;
+ PRIVATE(this)->rotationCenterFound = true;
+}
+
+SbVec3f NavigationStyle::getFocalPoint() const
+{
+ SoCamera* cam = viewer->getSoRenderManager()->getCamera();
+ if (cam == 0)
+ return SbVec3f(0,0,0);
+
+ // Find global coordinates of focal point.
+ SbVec3f direction;
+ cam->orientation.getValue().multVec(SbVec3f(0, 0, -1), direction);
+ SbVec3f focal = cam->position.getValue() +
+ cam->focalDistance.getValue() * direction;
+ return focal;
+}
+
/** Uses the sphere sheet projector to map the mouseposition onto
* a 3D point and find a rotation from this and the last calculated point.
*/
@@ -866,8 +897,8 @@ void NavigationStyle::spin(const SbVec2f & pointerpos)
lastpos[0] = float(this->log.position[1][0]) / float(std::max((int)(glsize[0]-1), 1));
lastpos[1] = float(this->log.position[1][1]) / float(std::max((int)(glsize[1]-1), 1));
- if (PRIVATE(this)->dragAtCursor && PRIVATE(this)->dragPointFound) {
- SbVec3f hitpoint = PRIVATE(this)->startDragPoint;
+ if (PRIVATE(this)->dragAtCursor && PRIVATE(this)->rotationCenterFound) {
+ SbVec3f hitpoint = PRIVATE(this)->rotationCenter;
// set to the given position
SbVec3f direction;
@@ -894,7 +925,7 @@ void NavigationStyle::spin(const SbVec2f & pointerpos)
r.invert();
this->reorientCamera(viewer->getSoRenderManager()->getCamera(), r);
- if (PRIVATE(this)->dragAtCursor && PRIVATE(this)->dragPointFound) {
+ if (PRIVATE(this)->dragAtCursor && PRIVATE(this)->rotationCenterFound) {
float ratio = vp.getViewportAspectRatio();
SbViewVolume vv = viewer->getSoRenderManager()->getCamera()->getViewVolume(vp.getViewportAspectRatio());
SbPlane panplane = vv.getPlane(viewer->getSoRenderManager()->getCamera()->focalDistance.getValue());
@@ -996,15 +1027,44 @@ void NavigationStyle::saveCursorPosition(const SoEvent * const ev)
// get the 3d point to the screen position, if possible
if (PRIVATE(this)->dragAtCursor) {
- SoRayPickAction rpaction(viewer->getSoRenderManager()->getViewportRegion());
- rpaction.setPoint(this->localPos);
- rpaction.setRadius(viewer->getPickRadius());
- rpaction.apply(viewer->getSoRenderManager()->getSceneGraph());
+ //Option to get point on model (slow) or always on focal plane (fast)
+ switch (PRIVATE(this)->rotationCenterMode) {
+ case ScenePointAtCursor:
+ {
+ SoRayPickAction rpaction(viewer->getSoRenderManager()->getViewportRegion());
+ rpaction.setPoint(this->localPos);
+ rpaction.setRadius(viewer->getPickRadius());
+ rpaction.apply(viewer->getSoRenderManager()->getSceneGraph());
- SoPickedPoint * picked = rpaction.getPickedPoint();
- if (picked) {
- PRIVATE(this)->dragPointFound = true;
- PRIVATE(this)->startDragPoint = picked->getPoint();
+ SoPickedPoint * picked = rpaction.getPickedPoint();
+ if (picked) {
+ setRotationCenter(picked->getPoint());
+ break;
+ }
+ }
+ // mode is FocalPointAtCursor or a ScenePointAtCursor failed
+ case FocalPointAtCursor:
+ {
+ // get the intersection point of the ray and the focal plane
+ const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion();
+ float ratio = vp.getViewportAspectRatio();
+
+ SoCamera* cam = viewer->getSoRenderManager()->getCamera();
+ if (!cam) return; // no camera
+ SbViewVolume vv = cam->getViewVolume(ratio);
+
+ SbLine line;
+ SbVec2f currpos = ev->getNormalizedPosition(vp);
+ vv.projectPointToLine(currpos, line);
+ SbVec3f current_planept;
+ SbPlane panplane = vv.getPlane(cam->focalDistance.getValue());
+ panplane.intersect(line, current_planept);
+
+ setRotationCenter(current_planept);
+ break;
+ }
+ default:
+ break;
}
}
}
@@ -1173,6 +1233,26 @@ SbBool NavigationStyle::isZoomAtCursor() const
return this->zoomAtCursor;
}
+void NavigationStyle::setRotationCenterMode(NavigationStyle::RotationCenterMode mode)
+{
+ PRIVATE(this)->rotationCenterMode = mode;
+}
+
+NavigationStyle::RotationCenterMode NavigationStyle::getRotationCenterMode() const
+{
+ return PRIVATE(this)->rotationCenterMode;
+}
+
+void NavigationStyle::setDragAtCursor(SbBool on)
+{
+ PRIVATE(this)->dragAtCursor = on;
+}
+
+SbBool NavigationStyle::isDragAtCursor() const
+{
+ return PRIVATE(this)->dragAtCursor;
+}
+
void NavigationStyle::startSelection(AbstractMouseSelection* mouse)
{
if (!mouse)
diff --git a/src/Gui/NavigationStyle.h b/src/Gui/NavigationStyle.h
index 8e73988cdc..7f29a6acbe 100644
--- a/src/Gui/NavigationStyle.h
+++ b/src/Gui/NavigationStyle.h
@@ -98,6 +98,11 @@ public:
Trackball
};
+ enum RotationCenterMode {
+ ScenePointAtCursor, /**< Find the point in the scene at the cursor position. If there is no point then the focal plane is used */
+ FocalPointAtCursor /**< Find the point on the focal plane at the cursor postion. */
+ };
+
public:
NavigationStyle();
virtual ~NavigationStyle();
@@ -125,6 +130,12 @@ public:
SbBool isZoomAtCursor() const;
void zoomIn();
void zoomOut();
+ void setDragAtCursor(SbBool);
+ SbBool isDragAtCursor() const;
+ void setRotationCenterMode(RotationCenterMode);
+ RotationCenterMode getRotationCenterMode() const;
+ void setRotationCenter(const SbVec3f& cnt);
+ SbVec3f getFocalPoint() const;
void updateAnimation();
void redraw();
@@ -166,6 +177,7 @@ protected:
SbBool seekToPoint(const SbVec2s screenpos);
void seekToPoint(const SbVec3f& scenepos);
SbBool lookAtPoint(const SbVec2s screenpos);
+ SbVec3f getRotationCenter(SbBool*) const;
void reorientCamera(SoCamera * camera, const SbRotation & rot);
void panCamera(SoCamera * camera,
diff --git a/src/Gui/View3DInventor.cpp b/src/Gui/View3DInventor.cpp
index 730246de1a..4113b97741 100644
--- a/src/Gui/View3DInventor.cpp
+++ b/src/Gui/View3DInventor.cpp
@@ -348,6 +348,10 @@ void View3DInventor::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::M
float val = rGrp.GetFloat("ZoomStep", 0.0f);
_viewer->navigationStyle()->setZoomStep(val);
}
+ else if (strcmp(Reason,"DragAtCursor") == 0) {
+ bool on = rGrp.GetBool("DragAtCursor", false);
+ _viewer->navigationStyle()->setDragAtCursor(on);
+ }
else if (strcmp(Reason,"EyeDistance") == 0) {
_viewer->getSoRenderManager()->setStereoOffset(rGrp.GetFloat("EyeDistance",5.0));
}