osgEarth 2.1.1
Public Member Functions | Protected Attributes

osgEarth::PixelAutoTransform Class Reference

List of all members.

Public Member Functions

 PixelAutoTransform ()
void setMinPixelWidthAtScaleOne (double pixels)
void setSizingNode (osg::Node *node)
void dirty ()
void accept (osg::NodeVisitor &nv)

Protected Attributes

double _minPixels
bool _dirty
osg::observer_ptr< osg::Node > _sizingNode

Detailed Description

A pixel-based AutoTransform variant.

Definition at line 216 of file Utils.


Constructor & Destructor Documentation

PixelAutoTransform::PixelAutoTransform ( )

Definition at line 98 of file Utils.cpp.

                                       :
osg::AutoTransform()
{
    // deactivate culling for the first traversal. We will reactivate it later.
    setCullingActive( false );
}

Member Function Documentation

void PixelAutoTransform::accept ( osg::NodeVisitor &  nv)

Definition at line 106 of file Utils.cpp.

{
    if ( nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR )
    {
        // re-activate culling now that the first cull traversal has taken place.
        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;

                    // rotating the camera only affects ROTATE_TO_*
                    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 rotation_zrotation_z = atan2f(ev.x(),ev.y());
                            //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.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 rotation_zrotation_z = atan2f(ev.x(),ev.y());
                            //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.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 rotation_zrotation_z = atan2f(ev.x(),ev.y());
                            //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.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): // need to implement 
                    {
                        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;
        }
    }

    // finally, skip AT's accept and do Transform.
    Transform::accept(nv);

}
void PixelAutoTransform::dirty ( )

Forces a recalculation of the autoscale on the next traversal (this usually doesn't happen unless the camera moves)

Definition at line 295 of file Utils.cpp.

{
    _dirty = true;
    setCullingActive( false );
}
void osgEarth::PixelAutoTransform::setMinPixelWidthAtScaleOne ( double  pixels) [inline]

Sets the minimim width of the object, in pixels, when the scale factor is 1.0.

Definition at line 225 of file Utils.

{ _minPixels = pixels; }
void osgEarth::PixelAutoTransform::setSizingNode ( osg::Node *  node) [inline]

Sets the node to use to calculate the screen size. If this is NULL, it will use the size of the first child node.

Definition at line 231 of file Utils.

{ _sizingNode = node; dirty(); }

Member Data Documentation

Definition at line 244 of file Utils.

Definition at line 243 of file Utils.

osg::observer_ptr<osg::Node> osgEarth::PixelAutoTransform::_sizingNode [protected]

Definition at line 245 of file Utils.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines