{
if ( nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR )
{
this->setCullingActive( true );
osg::CullStack* cs = dynamic_cast<osg::CullStack*>(&nv);
if ( cs )
{
osg::Viewport::value_type width = _previousWidth;
osg::Viewport::value_type height = _previousHeight;
osg::Viewport* viewport = cs->getViewport();
if (viewport)
{
width = viewport->width();
height = viewport->height();
}
osg::Vec3d eyePoint = cs->getEyeLocal();
osg::Vec3d localUp = cs->getUpLocal();
osg::Vec3d position = getPosition();
const osg::Matrix& projection = *(cs->getProjectionMatrix());
bool doUpdate = _firstTimeToInitEyePoint || _dirty;
if ( !_firstTimeToInitEyePoint )
{
osg::Vec3d dv = _previousEyePoint - eyePoint;
if (dv.length2() > getAutoUpdateEyeMovementTolerance() * (eyePoint-getPosition()).length2())
{
doUpdate = true;
}
else
{
osg::Vec3d dupv = _previousLocalUp - localUp;
if ((_autoRotateMode && dupv.length2() > getAutoUpdateEyeMovementTolerance()) ||
(width != _previousWidth || height != _previousHeight) ||
(projection != _previousProjection) ||
(position != _previousPosition) )
{
doUpdate = true;
}
}
}
_firstTimeToInitEyePoint = false;
if ( doUpdate )
{
if ( getAutoScaleToScreen() )
{
double radius =
_sizingNode.valid() ? _sizingNode->getBound().radius() :
getNumChildren() > 0 ? getChild(0)->getBound().radius() :
0.48;
double pixels = cs->pixelSize( getPosition(), radius );
double scaledMinPixels = _minPixels * _minimumScale;
double scale = pixels < scaledMinPixels ? scaledMinPixels / pixels : 1.0;
OE_DEBUG << LC
<< "Pixels = " << pixels << ", minPix = " << _minPixels << ", scale = " << scale
<< std::endl;
setScale( scale );
}
_previousEyePoint = eyePoint;
_previousLocalUp = localUp;
_previousWidth = width;
_previousHeight = height;
_previousProjection = projection;
_previousPosition = position;
_matrixDirty = true;
}
if (_autoRotateMode==ROTATE_TO_SCREEN)
{
osg::Vec3d translation;
osg::Quat rotation;
osg::Vec3d scale;
osg::Quat so;
cs->getModelViewMatrix()->decompose( translation, rotation, scale, so );
setRotation(rotation.inverse());
}
else if (_autoRotateMode==ROTATE_TO_CAMERA)
{
osg::Vec3d PosToEye = _position - eyePoint;
osg::Matrix lookto = osg::Matrix::lookAt(
osg::Vec3d(0,0,0), PosToEye, localUp);
osg::Quat q;
q.set(osg::Matrix::inverse(lookto));
setRotation(q);
}
#if OSG_MIN_VERSION_REQUIRED(3,0,0)
else if (_autoRotateMode==ROTATE_TO_AXIS)
{
osg::Matrix matrix;
osg::Vec3 ev(eyePoint - _position);
switch(_cachedMode)
{
case(AXIAL_ROT_Z_AXIS):
{
ev.z() = 0.0f;
float ev_length = ev.length();
if (ev_length>0.0f)
{
float inv = 1.0f/ev_length;
float s = ev.x()*inv;
float c = -ev.y()*inv;
matrix(0,0) = c;
matrix(1,0) = -s;
matrix(0,1) = s;
matrix(1,1) = c;
}
break;
}
case(AXIAL_ROT_Y_AXIS):
{
ev.y() = 0.0f;
float ev_length = ev.length();
if (ev_length>0.0f)
{
float inv = 1.0f/ev_length;
float s = -ev.z()*inv;
float c = ev.x()*inv;
matrix(0,0) = c;
matrix(2,0) = s;
matrix(0,2) = -s;
matrix(2,2) = c;
}
break;
}
case(AXIAL_ROT_X_AXIS):
{
ev.x() = 0.0f;
float ev_length = ev.length();
if (ev_length>0.0f)
{
float inv = 1.0f/ev_length;
float s = -ev.z()*inv;
float c = -ev.y()*inv;
matrix(1,1) = c;
matrix(2,1) = -s;
matrix(1,2) = s;
matrix(2,2) = c;
}
break;
}
case(ROTATE_TO_AXIS):
{
float ev_side = ev*_side;
float ev_normal = ev*_normal;
float rotation = atan2f(ev_side,ev_normal);
matrix.makeRotate(rotation,_axis);
break;
}
}
osg::Quat q;
q.set(matrix);
setRotation(q);
}
#endif
_dirty = false;
}
}
Transform::accept(nv);
}