osgEarth 2.1.1
|
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 }