Gui: Improve lookAtPoint (#13556)

* Gui: Rename NavigationStyle::pan to setupPanningPlane

* Gui: Replace duplicate code with NavigationStyle::setupPanningPlane

* Gui: Use panning plane when hit point not found in lookAtPoint

Also enables navigation animations when pressing MMB while the mouse is not over an object

* Gui: Remove unused methods
This commit is contained in:
Bas Ruigrok
2024-05-06 17:45:14 +02:00
committed by GitHub
parent d977689b47
commit 5ba93dd9f0
12 changed files with 67 additions and 109 deletions

View File

@@ -172,9 +172,7 @@ SbBool BlenderNavigationStyle::processSoEvent(const SoEvent * const ev)
case SoMouseButtonEvent::BUTTON3:
if (press) {
this->centerTime = ev->getTime();
float ratio = vp.getViewportAspectRatio();
SbViewVolume vv = viewer->getSoRenderManager()->getCamera()->getViewVolume(ratio);
this->panningplane = vv.getPlane(viewer->getSoRenderManager()->getCamera()->focalDistance.getValue());
setupPanningPlane(getCamera());
this->lockrecenter = false;
}
else {
@@ -182,10 +180,7 @@ SbBool BlenderNavigationStyle::processSoEvent(const SoEvent * const ev)
float dci = (float)QApplication::doubleClickInterval()/1000.0f;
// is it just a middle click?
if (tmp.getValue() < dci && !this->lockrecenter) {
if (!this->lookAtPoint(pos)) {
panToCenter(panningplane, posn);
this->interactiveCountDec();
}
lookAtPoint(pos);
processed = true;
}
}

View File

@@ -179,9 +179,7 @@ SbBool CADNavigationStyle::processSoEvent(const SoEvent * const ev)
case SoMouseButtonEvent::BUTTON3:
if (press) {
this->centerTime = ev->getTime();
float ratio = vp.getViewportAspectRatio();
SbViewVolume vv = viewer->getSoRenderManager()->getCamera()->getViewVolume(ratio);
this->panningplane = vv.getPlane(viewer->getSoRenderManager()->getCamera()->focalDistance.getValue());
setupPanningPlane(getCamera());
this->lockrecenter = false;
}
else {
@@ -189,10 +187,7 @@ SbBool CADNavigationStyle::processSoEvent(const SoEvent * const ev)
float dci = (float)QApplication::doubleClickInterval()/1000.0f;
// is it just a middle click?
if (tmp.getValue() < dci && !this->lockrecenter) {
if (!this->lookAtPoint(pos)) {
panToCenter(panningplane, posn);
this->interactiveCountDec();
}
lookAtPoint(pos);
processed = true;
}
}

View File

@@ -297,7 +297,8 @@ public:
//MMB click
if(ev.isPress(3) && ev.mbstate() == 0x010){
ev.flags->processed = true;
ns.onSetRotationCenter(ev.inventor_event->getPosition());
ns.setupPanningPlane(ns.viewer->getCamera());
ns.lookAtPoint(ev.inventor_event->getPosition());
return transit<NS::AwaitingReleaseState>();
}
@@ -314,8 +315,10 @@ public:
bool press = (kbev->getState() == SoKeyboardEvent::DOWN);
switch (kbev->getKey()) {
case SoKeyboardEvent::H:
if (!press)
ns.onSetRotationCenter(kbev->getPosition());
if (!press) {
ns.setupPanningPlane(ns.viewer->getCamera());
ns.lookAtPoint(kbev->getPosition());
}
break;
case SoKeyboardEvent::PAGE_UP:
if(!press){
@@ -538,7 +541,7 @@ public:
if (ns.logging)
Base::Console().Log(" -> PanState\n");
this->ratio = ns.viewer->getSoRenderManager()->getViewportRegion().getViewportAspectRatio();
ns.pan(ns.viewer->getSoRenderManager()->getCamera());//set up panningplane
ns.setupPanningPlane(ns.viewer->getSoRenderManager()->getCamera());//set up panningplane
}
virtual ~PanState() = default;
@@ -585,7 +588,7 @@ public:
if (ns.logging)
Base::Console().Log(" -> StickyPanState\n");
this->ratio = ns.viewer->getSoRenderManager()->getViewportRegion().getViewportAspectRatio();
ns.pan(ns.viewer->getSoRenderManager()->getCamera());//set up panningplane
ns.setupPanningPlane(ns.viewer->getSoRenderManager()->getCamera());//set up panningplane
}
virtual ~StickyPanState(){
auto &ns = this->outermost_context().ns;
@@ -631,7 +634,7 @@ public:
this->base_pos = static_cast<const NS::Event*>(this->triggering_event())->inventor_event->getPosition();
if (ns.logging)
Base::Console().Log(" -> TiltState\n");
ns.pan(ns.viewer->getSoRenderManager()->getCamera());//set up panningplane
ns.setupPanningPlane(ns.viewer->getSoRenderManager()->getCamera());//set up panningplane
}
virtual ~TiltState() = default;
@@ -681,7 +684,7 @@ public:
this->base_pos = static_cast<const NS::Event*>(this->triggering_event())->inventor_event->getPosition();
if (ns.logging)
Base::Console().Log(" -> GestureState\n");
ns.pan(ns.viewer->getSoRenderManager()->getCamera());//set up panningplane
ns.setupPanningPlane(ns.viewer->getSoRenderManager()->getCamera());//set up panningplane
this->ratio = ns.viewer->getSoRenderManager()->getViewportRegion().getViewportAspectRatio();
enableTilt = !(App::GetApplication().GetParameterGroupByPath
("User parameter:BaseApp/Preferences/View")->GetBool("DisableTouchTilt",true));
@@ -1007,16 +1010,6 @@ void GestureNavigationStyle::onRollGesture(int direction)
}
void GestureNavigationStyle::onSetRotationCenter(SbVec2s cursor){
SbBool ret = NavigationStyle::lookAtPoint(cursor);
if(!ret){
this->interactiveCountDec(); //this was in original gesture nav. Not sure what is it needed for --DeepSOIC
Base::Console().Log(
"No object under cursor! Can't set new center of rotation.\n");
}
}
void GestureNavigationStyle::EventQueue::post(const NS::Event& ev)
{
ev.flags->processed = true;

View File

@@ -107,8 +107,6 @@ public: //gesture reactions
///Roll gesture is like: press LMB, press RMB, release LMB, release RMB.
/// This function is called by state machine whenever it picks up roll gesture.
void onRollGesture(int direction);
///Called by state machine, when set-rotation-center gesture is detected (MMB click, or H key)
void onSetRotationCenter(SbVec2s cursor);
};
}

View File

@@ -126,9 +126,7 @@ SbBool InventorNavigationStyle::processSoEvent(const SoEvent * const ev)
if (press && ev->wasShiftDown() &&
(this->currentmode != NavigationStyle::SELECTION)) {
this->centerTime = ev->getTime();
float ratio = vp.getViewportAspectRatio();
SbViewVolume vv = viewer->getSoRenderManager()->getCamera()->getViewVolume(ratio);
this->panningplane = vv.getPlane(viewer->getSoRenderManager()->getCamera()->focalDistance.getValue());
setupPanningPlane(getCamera());
this->lockrecenter = false;
}
else if (!press && ev->wasShiftDown() &&
@@ -137,10 +135,7 @@ SbBool InventorNavigationStyle::processSoEvent(const SoEvent * const ev)
float dci = (float)QApplication::doubleClickInterval()/1000.0f;
// is it just a left click?
if (tmp.getValue() < dci && !this->lockrecenter) {
if (!this->lookAtPoint(pos)) {
panToCenter(panningplane, posn);
this->interactiveCountDec();
}
lookAtPoint(pos);
processed = true;
}
}
@@ -191,9 +186,7 @@ SbBool InventorNavigationStyle::processSoEvent(const SoEvent * const ev)
case SoMouseButtonEvent::BUTTON3:
if (press) {
this->centerTime = ev->getTime();
float ratio = vp.getViewportAspectRatio();
SbViewVolume vv = viewer->getSoRenderManager()->getCamera()->getViewVolume(ratio);
this->panningplane = vv.getPlane(viewer->getSoRenderManager()->getCamera()->focalDistance.getValue());
setupPanningPlane(getCamera());
this->lockrecenter = false;
}
else {
@@ -201,10 +194,7 @@ SbBool InventorNavigationStyle::processSoEvent(const SoEvent * const ev)
float dci = (float)QApplication::doubleClickInterval()/1000.0f;
// is it just a middle click?
if (tmp.getValue() < dci && !this->lockrecenter) {
if (!this->lookAtPoint(pos)) {
panToCenter(panningplane, posn);
this->interactiveCountDec();
}
lookAtPoint(pos);
processed = true;
}
}

View File

@@ -280,13 +280,9 @@ SbBool MayaGestureNavigationStyle::processSoEvent(const SoEvent * const ev)
switch (event->getKey()) {
case SoKeyboardEvent::H:
processed = true;
if(!press){
SbBool ret = NavigationStyle::lookAtPoint(event->getPosition());
if(!ret){
this->interactiveCountDec();
Base::Console().Log(
"No object under cursor! Can't set new center of rotation.\n");
}
if (!press) {
setupPanningPlane(viewer->getCamera());
lookAtPoint(event->getPosition());
}
break;
default:
@@ -397,7 +393,7 @@ SbBool MayaGestureNavigationStyle::processSoEvent(const SoEvent * const ev)
//reset/start move detection machine
this->mousedownPos = pos;
this->mouseMoveThresholdBroken = false;
pan(viewer->getSoRenderManager()->getCamera());//set up panningplane
setupPanningPlane(viewer->getSoRenderManager()->getCamera());//set up panningplane
int &cnt = this->mousedownConsumedCount;
this->mousedownConsumedEvents[cnt] = *event;//hopefully, a shallow copy is enough. There are no pointers stored in events, apparently. Will lose a subclass, though.
cnt++;
@@ -431,12 +427,8 @@ SbBool MayaGestureNavigationStyle::processSoEvent(const SoEvent * const ev)
setViewingMode(NavigationStyle::PANNING);
} else if(press){
// if not PANNING then look at point
SbBool ret = NavigationStyle::lookAtPoint(event->getPosition());
if(!ret){
this->interactiveCountDec();
Base::Console().Log(
"No object under cursor! Can't set new center of rotation.\n");
}
setupPanningPlane(viewer->getCamera());
lookAtPoint(event->getPosition());
}
processed = true;
break;
@@ -480,11 +472,11 @@ SbBool MayaGestureNavigationStyle::processSoEvent(const SoEvent * const ev)
if (gesture->state == SoGestureEvent::SbGSStart
|| gesture->state == SoGestureEvent::SbGSUpdate) {//even if we didn't get a start, assume the first update is a start (sort-of fail-safe).
if (type.isDerivedFrom(SoGesturePanEvent::getClassTypeId())) {
pan(viewer->getSoRenderManager()->getCamera());//set up panning plane
setupPanningPlane(viewer->getSoRenderManager()->getCamera());//set up panning plane
setViewingMode(NavigationStyle::PANNING);
processed = true;
} else if (type.isDerivedFrom(SoGesturePinchEvent::getClassTypeId())) {
pan(viewer->getSoRenderManager()->getCamera());//set up panning plane
setupPanningPlane(viewer->getSoRenderManager()->getCamera());//set up panning plane
setRotationCenter(getFocalPoint());
setViewingMode(NavigationStyle::DRAGGING);
processed = true;

View File

@@ -327,27 +327,41 @@ void NavigationStyle::seekToPoint(const SbVec3f& scenepos)
viewer->seekToPoint(scenepos);
}
SbBool NavigationStyle::lookAtPoint(const SbVec2s screenpos)
void NavigationStyle::lookAtPoint(const SbVec2s screenpos)
{
SoCamera* cam = viewer->getSoRenderManager()->getCamera();
if (!cam)
return false;
const SoCamera* camera = viewer->getCamera();
if (!camera) {
return;
}
SoRayPickAction rpaction(viewer->getSoRenderManager()->getViewportRegion());
SoRayPickAction rpaction(viewer->getViewportRegion());
rpaction.setPoint(screenpos);
rpaction.setRadius(viewer->getPickRadius());
rpaction.apply(viewer->getSoRenderManager()->getSceneGraph());
SoPickedPoint * picked = rpaction.getPickedPoint();
if (!picked) {
this->interactiveCountInc();
return false;
const SoPickedPoint* picked = rpaction.getPickedPoint();
// Point is either the hitpoint or the projected point on the panning plane
SbVec3f point;
if (picked) {
point = picked->getPoint();
}
else {
const SbViewportRegion& vp = viewer->getViewportRegion();
const float aspectratio = vp.getViewportAspectRatio();
SbViewVolume vv = camera->getViewVolume(aspectratio);
// See note in Coin docs for SoCamera::getViewVolume re:viewport mapping
if (aspectratio < 1.0) {
vv.scale(1.0 / aspectratio);
}
SbLine line;
vv.projectPointToLine(normalizePixelPos(screenpos), line);
panningplane.intersect(line, point);
}
SbVec3f hitpoint;
hitpoint = picked->getPoint();
lookAtPoint(hitpoint);
return true;
lookAtPoint(point);
}
void NavigationStyle::lookAtPoint(const SbVec3f& position)
@@ -593,35 +607,28 @@ void NavigationStyle::panCamera(SoCamera * cam, float aspectratio, const SbPlane
}
}
void NavigationStyle::pan(SoCamera* camera)
void NavigationStyle::setupPanningPlane(const SoCamera* camera)
{
// The plane we're projecting the mouse coordinates to get 3D
// coordinates should stay the same during the whole pan
// operation, so we should calculate this value here.
if (!camera) { // can happen for empty scenegraph
if (!camera) { // can happen for empty scenegraph
this->panningplane = SbPlane(SbVec3f(0, 0, 1), 0);
}
else {
const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion();
float aspectratio = vp.getViewportAspectRatio();
const SbViewportRegion& vp = viewer->getViewportRegion();
const float aspectratio = vp.getViewportAspectRatio();
SbViewVolume vv = camera->getViewVolume(aspectratio);
// See note in Coin docs for SoCamera::getViewVolume re:viewport mapping
if(aspectratio < 1.0)
if (aspectratio < 1.0) {
vv.scale(1.0 / aspectratio);
}
this->panningplane = vv.getPlane(camera->focalDistance.getValue());
}
}
void NavigationStyle::panToCenter(const SbPlane & pplane, const SbVec2f & currpos)
{
const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion();
float ratio = vp.getViewportAspectRatio();
panCamera(viewer->getSoRenderManager()->getCamera(), ratio, pplane, SbVec2f(0.5,0.5), currpos);
this->rotationCenterFound = false;
}
/** Dependent on the camera type this will either shrink or expand the
* height of the viewport (orthogonal camera) or move the camera
* closer or further away from the focal point in the scene.
@@ -1382,7 +1389,7 @@ void NavigationStyle::setViewingMode(const ViewerMode newmode)
case PANNING:
animator->stop();
pan(viewer->getSoRenderManager()->getCamera());
setupPanningPlane(viewer->getSoRenderManager()->getCamera());
this->interactiveCountInc();
break;

View File

@@ -197,7 +197,7 @@ protected:
void setSeekMode(SbBool enable);
SbBool seekToPoint(const SbVec2s screenpos);
void seekToPoint(const SbVec3f& scenepos);
SbBool lookAtPoint(const SbVec2s screenpos);
void lookAtPoint(const SbVec2s screenpos);
void lookAtPoint(const SbVec3f& position);
void panCamera(SoCamera * camera,
@@ -205,8 +205,7 @@ protected:
const SbPlane & panplane,
const SbVec2f & previous,
const SbVec2f & current);
void pan(SoCamera* camera);
void panToCenter(const SbPlane & pplane, const SbVec2f & currpos);
void setupPanningPlane(const SoCamera* camera);
int getDelta() const;
void zoom(SoCamera * camera, float diffvalue);
void zoomByCursor(const SbVec2f & thispos, const SbVec2f & prevpos);

View File

@@ -170,9 +170,7 @@ SbBool OpenCascadeNavigationStyle::processSoEvent(const SoEvent * const ev)
case SoMouseButtonEvent::BUTTON3:
if (press) {
this->centerTime = ev->getTime();
float ratio = vp.getViewportAspectRatio();
SbViewVolume vv = viewer->getSoRenderManager()->getCamera()->getViewVolume(ratio);
this->panningplane = vv.getPlane(viewer->getSoRenderManager()->getCamera()->focalDistance.getValue());
setupPanningPlane(getCamera());
this->lockrecenter = false;
}
else if (this->currentmode == NavigationStyle::PANNING) {

View File

@@ -170,9 +170,7 @@ SbBool OpenSCADNavigationStyle::processSoEvent(const SoEvent * const ev)
this->button3down = press;
if (press) {
this->centerTime = ev->getTime();
float ratio = vp.getViewportAspectRatio();
SbViewVolume vv = viewer->getSoRenderManager()->getCamera()->getViewVolume(ratio);
this->panningplane = vv.getPlane(viewer->getSoRenderManager()->getCamera()->focalDistance.getValue());
setupPanningPlane(getCamera());
this->lockrecenter = false;
}
else if (curmode == NavigationStyle::PANNING) {

View File

@@ -171,9 +171,7 @@ SbBool RevitNavigationStyle::processSoEvent(const SoEvent * const ev)
case SoMouseButtonEvent::BUTTON3:
if (press) {
this->centerTime = ev->getTime();
float ratio = vp.getViewportAspectRatio();
SbViewVolume vv = viewer->getSoRenderManager()->getCamera()->getViewVolume(ratio);
this->panningplane = vv.getPlane(viewer->getSoRenderManager()->getCamera()->focalDistance.getValue());
setupPanningPlane(getCamera());
this->lockrecenter = false;
}
else {
@@ -181,10 +179,7 @@ SbBool RevitNavigationStyle::processSoEvent(const SoEvent * const ev)
float dci = (float)QApplication::doubleClickInterval()/1000.0f;
// is it just a middle click?
if (tmp.getValue() < dci && !this->lockrecenter) {
if (!this->lookAtPoint(pos)) {
panToCenter(panningplane, posn);
this->interactiveCountDec();
}
lookAtPoint(pos);
processed = true;
}
}

View File

@@ -163,9 +163,7 @@ SbBool TinkerCADNavigationStyle::processSoEvent(const SoEvent * const ev)
this->button3down = press;
if (press) {
this->centerTime = ev->getTime();
float ratio = vp.getViewportAspectRatio();
SbViewVolume vv = viewer->getSoRenderManager()->getCamera()->getViewVolume(ratio);
this->panningplane = vv.getPlane(viewer->getSoRenderManager()->getCamera()->focalDistance.getValue());
setupPanningPlane(getCamera());
}
else if (curmode == NavigationStyle::PANNING) {
newmode = NavigationStyle::IDLE;