osgEarth 2.1.1
Public Member Functions | Private Member Functions | Private Attributes

osgEarth::Util::ClampCallback Class Reference

List of all members.

Public Member Functions

 ClampCallback (osg::Node *terrainNode=NULL)
void setTerrainNode (osg::Node *terrainNode)
osg::Node * getTerrainNode () const
double getOffset () const
void setOffset (double offset)
void setIntersectionMask (unsigned int intersectionMask)
unsigned int getIntersectionMask () const
virtual void operator() (osg::Node *node, osg::NodeVisitor *nv)

Private Member Functions

bool clamp (const osg::Vec3d &pos, osg::Vec3d &out) const
bool clampGeometry (osg::Geometry *geom, const osg::Matrixd &localToWorld, const osg::Matrixd &worldToLocal) const

Private Attributes

unsigned int _intersectionMask
osg::observer_ptr
< osg::CoordinateSystemNode > 
_csn
osg::ref_ptr< osg::Node > _terrainNode
int _lastCulledFrame
double _offset

Detailed Description

ClampCallback is a callback you can attach to either MatrixTransforms or Geodes to clamp them against the terrain. If you attach this callback to a MatrixTransform, it will adjust the matrix so that the object is clamped to the ground. If you attach this callback to a Geode, it will clamp all of the vertices in the Geode's geometry to the ground.

Definition at line 40 of file ClampCallback.


Constructor & Destructor Documentation

ClampCallback::ClampCallback ( osg::Node *  terrainNode = NULL)

Creates a new ClampCallback

Parameters:
Thenode to clamp to

Definition at line 35 of file ClampCallback.cpp.

{
    _offset = 0;
    _lastCulledFrame = 0;
    setTerrainNode( terrainNode );
    _intersectionMask = 0xffffffff;
}

Member Function Documentation

bool ClampCallback::clamp ( const osg::Vec3d &  pos,
osg::Vec3d &  out 
) const [private]

Definition at line 43 of file ClampCallback.cpp.

{
    //Return if there is no terrain node assigned
    if (!_terrainNode.valid()) return false;    

    //Compute the up vector
    osg::Vec3d up = _csn.valid() ? _csn->computeLocalUpVector( pos ) : osg::Vec3d(0,0,1);
    up.normalize();

    double segOffset = 50000;

    osg::Vec3d start = pos + (up * segOffset);
    osg::Vec3d end = pos - (up * segOffset);
    
    osgUtil::LineSegmentIntersector* i = new osgUtil::LineSegmentIntersector( start, end );
    
    osgUtil::IntersectionVisitor iv;
    iv.setTraversalMask(_intersectionMask);
    iv.setIntersector( i );
    _terrainNode->accept( iv );

    osgUtil::LineSegmentIntersector::Intersections& results = i->getIntersections();
    if ( !results.empty() )
    {
        const osgUtil::LineSegmentIntersector::Intersection& result = *results.begin();
        out = result.getWorldIntersectPoint();
        out += (up * _offset);
        return true;
    }
    return false;    
}
bool ClampCallback::clampGeometry ( osg::Geometry *  geom,
const osg::Matrixd &  localToWorld,
const osg::Matrixd &  worldToLocal 
) const [private]

Definition at line 75 of file ClampCallback.cpp.

{
    osg::Vec3Array* verts = static_cast<osg::Vec3Array*>(geom->getVertexArray());
    for (unsigned int i = 0; i < verts->size(); ++i)
    {
        osg::Vec3d pos = (*verts)[i];
        pos = pos * localToWorld;
        
        osg::Vec3d out;
        if (clamp(pos, out))
        {
            out = out * worldToLocal;
            (*verts)[i].set(out.x(), out.y(), out.z() );
        }
    }
    geom->dirtyBound();
    geom->dirtyDisplayList();

    return true;
}
unsigned int osgEarth::Util::ClampCallback::getIntersectionMask ( ) const

Gets the intersection mask to use when clamping

double osgEarth::Util::ClampCallback::getOffset ( ) const [inline]

Gets the offset that should be applied after clamping along the world's up vector

Definition at line 64 of file ClampCallback.

{ return _offset;}
osg::Node* osgEarth::Util::ClampCallback::getTerrainNode ( ) const [inline]

Gets the terrain node to clamp against

Definition at line 59 of file ClampCallback.

{ return _terrainNode.get(); }
void ClampCallback::operator() ( osg::Node *  node,
osg::NodeVisitor *  nv 
) [virtual]

Definition at line 105 of file ClampCallback.cpp.

{
    if (nv->getVisitorType() == NodeVisitor::UPDATE_VISITOR)
    {
        //Only clamp if this node has been culled in the last few frames
        if (nv->getFrameStamp()->getFrameNumber() - _lastCulledFrame < 2)
        {
            osg::MatrixTransform* mt = dynamic_cast<osg::MatrixTransform*>(node);
            if (mt)
            {
                osg::Matrixd matrix = mt->getMatrix();
                osg::Vec3d pos = matrix.getTrans();
                osg::Vec3d clamped;
                if (clamp(pos, clamped))
                {
                    //We need to translate the current matrix by an amount that would move the current position to the clamped position
                    osg::Vec3d trans = (clamped - pos );
                    matrix *= osg::Matrixd::translate( trans );
                    mt->setMatrix( matrix );
                }
            }
            else
            {
                osg::Geode* geode = dynamic_cast<osg::Geode*>(node);
                if (geode)
                {
                    osg::Matrixd localToWorld = osg::computeLocalToWorld( nv->getNodePath() );
                    osg::Matrixd worldToLocal = osg::computeWorldToLocal( nv->getNodePath() );

                    for (unsigned int i = 0; i < geode->getNumDrawables(); ++i)
                    {
                        osg::Geometry* geom = geode->getDrawable(i)->asGeometry();
                        if (geom)
                        {
                            clampGeometry( geom, localToWorld, worldToLocal);
                        }
                    }
                }
            }
        }
    }
    else if (nv->getVisitorType() == NodeVisitor::CULL_VISITOR)
    {                   
        _lastCulledFrame = nv->getFrameStamp()->getFrameNumber();
    }
    //Continue traversal
    traverse(node, nv);
}
void osgEarth::Util::ClampCallback::setIntersectionMask ( unsigned int  intersectionMask)

Sets the intersection mask to use when clamping

void ClampCallback::setOffset ( double  offset)

Sets the offset that should be applied after clamping along the world's up vector

Definition at line 155 of file ClampCallback.cpp.

{
    _offset = offset;
}
void ClampCallback::setTerrainNode ( osg::Node *  terrainNode)

Sets the terrain node to clamp against

Definition at line 96 of file ClampCallback.cpp.

{
    _terrainNode = terrainNode;
    if (_terrainNode.valid())
    {
        _csn = findTopMostNodeOfType<osg::CoordinateSystemNode>(_terrainNode.get());
    }
}

Member Data Documentation

osg::observer_ptr<osg::CoordinateSystemNode> osgEarth::Util::ClampCallback::_csn [private]

Definition at line 90 of file ClampCallback.

Definition at line 88 of file ClampCallback.

Definition at line 94 of file ClampCallback.

Definition at line 96 of file ClampCallback.

osg::ref_ptr< osg::Node > osgEarth::Util::ClampCallback::_terrainNode [private]

Definition at line 92 of file ClampCallback.


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