Gui: improve scale handling in SoFCCSysDragger

Because of the scale transformion in Link, the dragger may have
undesired behavior. This patch checks scaling factor in scenegraph
transformation, and auto scale the dragger axis accordingly.
This commit is contained in:
Zheng, Lei
2019-10-05 10:24:05 +08:00
committed by wmayer
parent e8389219b2
commit b81485d72d
3 changed files with 56 additions and 10 deletions

View File

@@ -39,6 +39,7 @@
#include <Inventor/nodes/SoSphere.h>
#include <Inventor/nodes/SoOrthographicCamera.h>
#include <Inventor/nodes/SoPerspectiveCamera.h>
#include <Inventor/actions/SoGLRenderAction.h>
#include <Inventor/SbRotation.h>
@@ -638,6 +639,8 @@ void SoFCCSysDragger::initClass()
}
SoFCCSysDragger::SoFCCSysDragger()
:axisScale(1.0f,1.0f,1.0f)
,scaleInited(false)
{
SO_KIT_CONSTRUCTOR(SoFCCSysDragger);
@@ -939,6 +942,44 @@ void SoFCCSysDragger::cameraCB(void *data, SoSensor *)
sudoThis->idleSensor.schedule();
}
void SoFCCSysDragger::GLRender(SoGLRenderAction * action)
{
if(!scaleInited) {
scaleInited = true;
updateDraggerCache(action->getCurPath());
updateAxisScale();
}
inherited::GLRender(action);
}
void SoFCCSysDragger::updateAxisScale() {
SbMatrix localToWorld = getLocalToWorldMatrix();
SbVec3f origin;
localToWorld.multVecMatrix(SbVec3f(0.0, 0.0, 0.0), origin);
SbVec3f vx,vy,vz;
localToWorld.multVecMatrix(SbVec3f(1.0f, 0.0f, 0.0f), vx);
localToWorld.multVecMatrix(SbVec3f(0.0f, 1.0f, 0.0f), vy);
localToWorld.multVecMatrix(SbVec3f(0.0f, 0.0f, 1.0f), vz);
float x = std::max((vx-origin).length(),1e-7f);
float y = std::max((vy-origin).length(),1e-7f);
float z = std::max((vz-origin).length(),1e-7f);
if(!axisScale.equals(SbVec3f(x,y,z),1e-7f)) {
axisScale.setValue(x,y,z);
idleCB(this,&idleSensor);
}
}
void SoFCCSysDragger::handleEvent(SoHandleEventAction * action)
{
this->ref();
inherited::handleEvent(action);
updateAxisScale();
this->unref();
}
void SoFCCSysDragger::idleCB(void *data, SoSensor *)
{
SoFCCSysDragger *sudoThis = reinterpret_cast<SoFCCSysDragger *>(data);
@@ -953,7 +994,9 @@ void SoFCCSysDragger::idleCB(void *data, SoSensor *)
SbViewVolume viewVolume = camera->getViewVolume();
float radius = sudoThis->draggerSize.getValue() / 2.0;
float localScale = viewVolume.getWorldToScreenScale(origin, radius);
SbVec3f scaleVector(localScale, localScale, localScale);
float sx,sy,sz;
sudoThis->axisScale.getValue(sx,sy,sz);
SbVec3f scaleVector(localScale/sx, localScale/sy, localScale/sz);
SoScale *localScaleNode = SO_GET_ANY_PART(sudoThis, "scaleNode", SoScale);
localScaleNode->scaleFactor.setValue(scaleVector);
sudoThis->autoScaleResult.setValue(localScale);

View File

@@ -239,8 +239,11 @@ public:
bool isHiddenRotationZ(); //!< is x rotation dragger hidden.
//@}
virtual void GLRender(SoGLRenderAction * action);
protected:
virtual SbBool setUpConnections(SbBool onoff, SbBool doitalways = FALSE) override;
virtual void handleEvent(SoHandleEventAction * action) override;
static void translationSensorCB(void *f, SoSensor *);
static void rotationSensorCB(void *f, SoSensor *);
@@ -255,6 +258,14 @@ protected:
SoFieldSensor cameraSensor;
private:
// Used to compensate for axis scale in world transformation when doing
// auto scale.
SbVec3f axisScale;
bool scaleInited;
void updateAxisScale();
typedef SoDragger inherited;
};

View File

@@ -2572,15 +2572,7 @@ void ViewProviderLink::setEditViewer(Gui::View3DInventorViewer* viewer, int ModN
viewer->setupEditingRoot(group,&dragCtx->preTransform);
}else{
SoFCCSysDragger* dragger = static_cast<SoFCCSysDragger*>(pcDragger.get());
auto doc = Application::Instance->editDocument();
if(doc) {
Base::Vector3d v0, v1(1,0,0);
doc->getEditingTransform().multVec(v0,v0);
doc->getEditingTransform().multVec(v1,v1);
// Compensate for possible scaling
dragger->draggerSize.setValue(0.05f / (v1-v0).Length());
} else
dragger->draggerSize.setValue(0.05f);
dragger->draggerSize.setValue(0.05f);
dragger->setUpAutoScale(viewer->getSoRenderManager()->getCamera());
viewer->setupEditingRoot(pcDragger,&dragCtx->preTransform);