Hi,
On 18/07/2011 13:19, David Cofer wrote:
Hi,
I am using the Drag handlers with an autotransform on them (see code
below). I have it set to AutoscaleToScreen. This works great as long
as I only have 1 view of the scene. When I have multiple views
though, I get a problem where zooming in on one will cause the
autotransform to change the scale of the dragger. I can click on the
dragger just fine in that window, but when I go back to the other
window and try and click on the dragger it is no longer scaled
correctly. As an example, if I zoom in to view A then the translate
drag handler become larger. I can click anywhere on them and they
work correctly. When I go to View B that is zoomed out then I can
click not only on the visual representation of the drag handler, but
on a projection of it that extends past the visual end of the axis.
If I do this the opposite way (Zoom out A and look at zoomed in B),
then the opposite happens. I can only click on the drag handler on a
smaller portion of the visible axis.
I looked around and found this post
(http://forum.openscenegraph.org/viewtopic.php?t=4637&highlight=).
The issue you are hitting up against is a limitation of
osg::AutoTransform in that it only has a single set of state so
when you have two or more views that require different stats you'll
get issues with both views attempting to sets it's value. The only
way to solve this would be to refactor osg::AutoTransform to have
multiple states in some way.
It looks like this may be related to this problem, but I am not sure.
It is.
Does anyone have any experience with this issue? Is this issue caused
by the state problem of autotransform?
Yes, basically the autotransform's scale is set when it is visited by
the cull traversal of a specific view, so it renders at the correct
size. Picking is also a traversal, but just gets the bounds calculated
on the latest cull traversal and this could be from any view...
Has anyone else found a way
around this problem? Does anyone have any suggestions for an easy way
to get around this problem without redoing the autotransform node?
I've recently worked around this by doing picking in a specific view's
camera callback. My pick handler now basically queues picks to be
executed after the camera's cull traversal has happened and this ensures
the correct scale is used during picking.
I'm not sure how easy this would be to do for the draggers...
Only other option is to make autotransform more intelligent or add
another type of visitor to osg.
jp
Here is my drag handler code.
Code:
VsDragger::VsDragger(VsMovableItem *lpParent, BOOL bAllowTranslateX,
BOOL bAllowTranslateY, BOOL bAllowTranslateZ, BOOL bAllowRotateX,
BOOL bAllowRotateY, BOOL bAllowRotateZ) { if(!lpParent)
THROW_ERROR(Al_Err_lParentNotDefined, Al_Err_strParentNotDefined);
m_lpVsParent = lpParent;
//Create the gripperMT and default it to loc=0, rot=0 m_osgGripperMT
= new osg::MatrixTransform(); osg::Matrix osgMT;
osgMT.makeIdentity(); m_osgGripperMT->setMatrix(osgMT);
m_osgGripperMT->addChild(this); _autoTransform = new
osg::AutoTransform; _autoTransform->setAutoScaleToScreen(true);
addChild(_autoTransform.get());
_sizeTransform = new osg::MatrixTransform; // Screen coordinates
because of AutoTransform parent
_sizeTransform->setMatrix(osg::Matrix::scale(100, 100, 100));
_autoTransform->addChild(_sizeTransform.get());
_tbDragger = new VsTrackballDragger(bAllowRotateX, bAllowRotateY,
bAllowRotateZ); _tbDragger->setName("TrackballDragger");
//addChild(_tbDragger.get());
_sizeTransform->addChild(_tbDragger.get());
_transDragger = new VsTranslateAxisDragger(bAllowTranslateX,
bAllowTranslateY, bAllowTranslateZ);
_transDragger->setName("TranslateAxisDragger");
//addChild(_transDragger.get());
_sizeTransform->addChild(_transDragger.get());
this->addDragger(_tbDragger.get());
this->addDragger(_transDragger.get());
this->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL,
osg::StateAttribute::ON);
this->setParentDragger(getParentDragger()); }
VsDragger::~VsDragger(void) { }
void VsDragger::setupDefaultGeometry() {
_tbDragger->setupDefaultGeometry();
_transDragger->setupDefaultGeometry();
SetupMatrix(); }
void VsDragger::AddToScene() { SetupMatrix(); if(m_lpVsParent&&
m_lpVsParent->RootGroup()&& m_osgGripperMT.valid())
if(!m_lpVsParent->RootGroup()->containsNode(m_osgGripperMT.get()))
m_lpVsParent->RootGroup()->addChild(m_osgGripperMT.get()); }
void VsDragger::RemoveFromScene() { if(m_lpVsParent&&
m_lpVsParent->RootGroup()&& m_osgGripperMT.valid())
if(m_lpVsParent->RootGroup()->containsNode(m_osgGripperMT.get()))
m_lpVsParent->RootGroup()->removeChild(m_osgGripperMT.get()); }
void VsDragger::SetupMatrix() { if(m_lpVsParent&&
m_lpVsParent->RootGroup()&& m_osgGripperMT.valid()) { //This gives
the radius of the boundign sphere for the selected part. //We will
multiply that by 2 and then scale the entire dragger by that amount.
//We will also use that setting for the minimum scale of the
autotransform. float fltMaxDim =
m_lpVsParent->Physics_GetBoundingRadius();
Simulator *lpSim = GetSimulator(); if(fltMaxDim>
(lpSim->InverseDistanceUnits()/2.0f)) fltMaxDim =
(lpSim->InverseDistanceUnits()/2.0f);
//Use an equation to calculate the radius here. This seemed to work
best. //I tried several size values and found a good radius scale
that fit it. Then //I did a regression to find this equation of the
line for the radius. float fltRadius = fltMaxDim*0.501794454f +
0.639290375f;
//We are dividing the number by 100 because we are using a
_sizeTransform that scales it up by 100.
_autoTransform->setMinimumScale( (fltRadius*0.01f) );
//We use the final matrix here instead of local matrix because the
joint can have an additional offset that //must be taken into account
when setting up the dragger.
m_osgGripperMT->setMatrix(m_lpVsParent->FinalMatrix()); //Set the
matrix for the dragger back to default. osg::Matrix mtNull =
osg::Matrix::identity(); mtNull *=
osg::Matrix::scale(fltRadius,fltRadius,fltRadius);
this->setMatrix(mtNull);
//Lets setup the grip to zero out the rotation of the body so that it
points //to the default axis of the parent it is connected to.
osg::Matrix tempMT = m_lpVsParent->LocalMatrix(), invMT;
tempMT.setTrans(osg::Vec3f(0, 0, 0)); invMT.invert(tempMT);
//We want to scale the translate axis to be 1.5 times as big as the
rotate axis dragger. // Scale the translate dragger up a bit,
otherwise the axes // will be in the trackball dragger's sphere and
we won't be // able to pick them. float axesScale = 1.5; invMT =
invMT * osg::Matrix::scale(axesScale,axesScale,axesScale);
_transDragger->setMatrix(invMT); } }
Thank you!
Cheers, David
------------------ Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=41431#41431
_______________________________________________ osg-users mailing
list [email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
--
This message is subject to the CSIR's copyright terms and conditions, e-mail legal notice, and implemented Open Document Format (ODF) standard.
The full disclaimer details can be found at http://www.csir.co.za/disclaimer.html.
This message has been scanned for viruses and dangerous content by MailScanner,
and is believed to be clean.
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org