osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthUtil/ObjectLocator.cpp

Go to the documentation of this file.
00001 #include <osgEarthUtil/ObjectLocator>
00002 
00003 using namespace osgEarth;
00004 using namespace osgEarth::Util;
00005 
00006 #define LC "[ObjectLocator] "
00007 
00008 /***************************************************************************/
00009 
00010 namespace
00011 {
00012     void getHPRFromQuat(const osg::Quat& q, double& h, double& p, double& r)
00013     {
00014         osg::Matrixd rot(q);
00015         p = asin(rot(1,2));
00016         if( osg::equivalent(osg::absolute(p), osg::PI_2) )
00017         {
00018             r = 0.0;
00019             h = atan2( rot(0,1), rot(0,0) );
00020         }
00021         else
00022         {
00023             r = atan2( rot(0,2), rot(2,2) );
00024             h = atan2( rot(1,0), rot(1,1) );
00025         }
00026         h = osg::RadiansToDegrees(h);
00027         p = osg::RadiansToDegrees(p);
00028         r = osg::RadiansToDegrees(r);
00029     }
00030 }
00031 
00032 /***************************************************************************/
00033 
00034 ObjectLocator::ObjectLocator(const osgEarth::Map* map) :
00035 _map                ( map ),
00036 _componentsToInherit( COMP_ALL ),
00037 _timestamp          ( 0.0 ),
00038 _isEmpty            ( true ),
00039 _rotOrder           ( HPR )
00040 {
00041     if ( !_map.valid() )
00042         OE_WARN << LC << "Illegal: cannot create an ObjectLocator with a NULL Map." << std::endl;
00043 }
00044 
00045 ObjectLocator::ObjectLocator(ObjectLocator* parentLoc, unsigned int inheritMask ) :
00046 _timestamp( 0.0 ),
00047 _isEmpty  ( false ),
00048 _rotOrder ( HPR )
00049 {
00050     setParentLocator( parentLoc, inheritMask );
00051     _map = parentLoc->_map.get();
00052 }
00053 
00054 bool
00055 ObjectLocator::isEmpty() const
00056 {
00057     return _parentLoc.valid() ? _parentLoc->isEmpty() : _isEmpty;
00058 }
00059 
00060 void
00061 ObjectLocator::setParentLocator( ObjectLocator* newParent, unsigned int inheritMask )
00062 {
00063     if ( newParent == this )
00064     {
00065         OE_WARN << LC << "Illegal state, locator cannot be its own parent." << std::endl;
00066         return;
00067     }
00068 
00069     _parentLoc = newParent;
00070     _componentsToInherit = inheritMask;
00071 
00072     if ( newParent )
00073     {
00074         _map = newParent->_map.get();
00075     }
00076 
00077     if ( !_map.valid() )
00078     {
00079         OE_WARN << "Illegal state, cannot create a Locator with a NULL srs" << std::endl;
00080     }
00081 
00082     dirty();
00083 }
00084 
00085 void
00086 ObjectLocator::setPosition( const osg::Vec3d& pos )
00087 {
00088     _pos = pos;
00089     _isEmpty = false;
00090     dirty();
00091 }
00092 
00093 void
00094 ObjectLocator::setOrientation( const osg::Vec3d& hpr )
00095 {
00096     _hpr = hpr;
00097     _isEmpty = false;
00098     dirty();
00099 }
00100 
00101 bool
00102 ObjectLocator::getLocatorPosition( osg::Vec3d& output ) const
00103 {
00104     if ( !isValid() )
00105         return false;
00106 
00107     output = _pos;
00108 
00109     if ( _parentLoc.valid() && (_componentsToInherit & COMP_POSITION) != 0 )
00110     {
00111         osg::Vec3d parentPos;
00112         _parentLoc->getLocatorPosition( parentPos );
00113         output += parentPos;
00114     }
00115 
00116     return true;
00117 }
00118 
00119 bool
00120 ObjectLocator::getPositionMatrix( osg::Matrixd& output ) const
00121 {
00122     osg::Vec3d pos;
00123     if ( !getLocatorPosition(pos) )
00124         return false;
00125 
00126     if ( _map->isGeocentric() )
00127     {
00128         _map->getProfile()->getSRS()->getEllipsoid()->computeLocalToWorldTransformFromLatLongHeight(
00129             osg::DegreesToRadians(pos.y()),
00130             osg::DegreesToRadians(pos.x()),
00131             pos.z(),
00132             output );
00133     }
00134     else
00135     {
00136         output.makeTranslate(pos);
00137     }
00138 
00139     return true;
00140 }
00141 
00142 bool
00143 ObjectLocator::getLocatorOrientation( osg::Vec3d& output ) const
00144 {
00145     if ( !isValid() )
00146         return false;
00147 
00148     output = _hpr;
00149 
00150     if ( _parentLoc.valid() && (_componentsToInherit & COMP_ORIENTATION) != 0 )
00151     {
00152         osg::Vec3d parentHPR;
00153         _parentLoc->getLocatorOrientation( parentHPR );
00154         output += parentHPR;
00155     }
00156 
00157     return true;
00158 }
00159 
00160 bool
00161 ObjectLocator::getOrientationMatrix( osg::Matrixd& output, unsigned inherit ) const
00162 {
00163     if ( !isValid() )
00164         return false;
00165 
00166     if ( (inherit & COMP_ORIENTATION) == 0 )
00167         return true;
00168 
00169     if ( _hpr[0] != 0.0 || _hpr[1] != 0.0 || _hpr[2] != 0.0 )
00170     {
00171         // first figure out the orientation
00172         osg::Quat azim_q;
00173         if ( inherit & COMP_HEADING )
00174             azim_q = osg::Quat( osg::DegreesToRadians(_hpr[0]), osg::Vec3d(0,0,1) );
00175 
00176         osg::Quat pitch_q;
00177         if ( inherit & COMP_PITCH )
00178             pitch_q = osg::Quat( -osg::DegreesToRadians(_hpr[1]), osg::Vec3d(1,0,0) );
00179 
00180         osg::Quat roll_q;
00181         if ( inherit & COMP_ROLL )
00182             roll_q = osg::Quat( osg::DegreesToRadians(_hpr[2]), osg::Vec3d(0,1,0) );
00183 
00184         // these look backwards, but it's actually a fast way to avoid inverting a matrix
00185         if ( _rotOrder == HPR )
00186             output.set( roll_q.conj() * pitch_q.conj() * azim_q.conj() );
00187         else if ( _rotOrder == RPH )
00188             output.set( azim_q.conj() * pitch_q.conj() * roll_q.conj() );
00189 
00190     }
00191 
00192     if ( _parentLoc.valid() && (_componentsToInherit * COMP_ORIENTATION) != 0 )
00193     {
00194         osg::Matrixd parentRot;
00195         if ( _parentLoc->getOrientationMatrix(parentRot, _componentsToInherit) )
00196             output = output * parentRot;
00197     }
00198 
00199     return true;
00200 }
00201 
00202 bool
00203 ObjectLocator::getLocatorMatrix( osg::Matrixd& output, unsigned comps ) const
00204 {
00205     bool ok = true;
00206     osg::Matrixd pos, rot;
00207 
00208     if ( comps & COMP_POSITION )
00209         if ( !getPositionMatrix(pos) )
00210             ok = false;
00211 
00212     if ( comps & COMP_ORIENTATION )
00213         if ( !getOrientationMatrix(rot, comps) )
00214             ok = false;
00215 
00216     output = rot * pos;
00217     return ok;
00218 }
00219 
00220 bool
00221 ObjectLocator::inSyncWith( int exRev ) const
00222 {
00223     return _parentLoc.valid() ? _parentLoc->inSyncWith( exRev ) :
00224         osgEarth::Revisioned<osg::Referenced>::inSyncWith( exRev );
00225 }
00226 
00227 /***************************************************************************/
00228 
00229 ObjectLocatorNode::ObjectLocatorNode()
00230 {
00231     setNumChildrenRequiringUpdateTraversal( 1 );
00232 }
00233 
00234 ObjectLocatorNode::ObjectLocatorNode( const ObjectLocatorNode& rhs, const osg::CopyOp& op ) :
00235 osg::MatrixTransform( rhs, op ),
00236 _matrixRevision( rhs._matrixRevision ),
00237 _locator( rhs._locator.get() )
00238 {
00239     setNumChildrenRequiringUpdateTraversal( 1 );
00240     setLocator( _locator.get() ); // to update the trav count
00241 }
00242 
00243 ObjectLocatorNode::ObjectLocatorNode( ObjectLocator* locator ) :
00244 _matrixRevision( -1 )
00245 {
00246     setNumChildrenRequiringUpdateTraversal( 1 );
00247     setLocator( locator );
00248 }
00249 
00250 ObjectLocatorNode::ObjectLocatorNode( const Map* map ) :
00251 _matrixRevision( -1 )
00252 {
00253     setNumChildrenRequiringUpdateTraversal( 1 );
00254     setLocator( new ObjectLocator(map) );
00255 }
00256 
00257 void
00258 ObjectLocatorNode::setLocator( ObjectLocator* locator )
00259 {
00260     _locator = locator;
00261     _matrixRevision = -1;    
00262 }
00263 
00264 
00265 void
00266 ObjectLocatorNode::traverse(osg::NodeVisitor &nv)
00267 {
00268     if (nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
00269     {
00270         update();
00271     }
00272     osg::MatrixTransform::traverse( nv );
00273 }
00274 
00275 void
00276 ObjectLocatorNode::update()
00277 {
00278     if ( _locator.valid() && _locator->outOfSyncWith( _matrixRevision ) )
00279     {
00280         osg::Matrix mat;
00281         if ( _locator->getLocatorMatrix( mat ) )
00282         {
00283             this->setMatrix( mat );
00284             this->dirtyBound();
00285             _locator->sync( _matrixRevision );
00286         }
00287     }
00288 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines