osgEarth 2.1.1
|
00001 /* -*-c++-*- */ 00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph 00003 * Copyright 2008-2010 Pelican Mapping 00004 * http://osgearth.org 00005 * 00006 * osgEarth is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU Lesser General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> 00018 */ 00019 #include <osgEarth/Utils> 00020 #include <osg/Version> 00021 #include <osg/CoordinateSystemNode> 00022 00023 using namespace osgEarth; 00024 00025 //------------------------------------------------------------------------ 00026 00027 void osgEarth::removeEventHandler(osgViewer::View* view, osgGA::GUIEventHandler* handler) 00028 { 00029 osgViewer::View::EventHandlers::iterator itr = std::find(view->getEventHandlers().begin(), view->getEventHandlers().end(), handler); 00030 if (itr != view->getEventHandlers().end()) 00031 { 00032 view->getEventHandlers().erase(itr); 00033 } 00034 } 00035 00036 //------------------------------------------------------------------------ 00037 00038 CullNodeByHorizon::CullNodeByHorizon( const osg::Vec3d& world, const osg::EllipsoidModel* model ) : 00039 _world(world), 00040 _r2(model->getRadiusPolar() * model->getRadiusPolar()) 00041 { 00042 //nop 00043 } 00044 00045 void 00046 CullNodeByHorizon::operator()(osg::Node* node, osg::NodeVisitor* nv) 00047 { 00048 if ( nv ) 00049 { 00050 osg::Vec3d eye, center, up; 00051 osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>( nv ); 00052 cv->getCurrentCamera()->getViewMatrixAsLookAt(eye,center,up); 00053 00054 double d2 = eye.length2(); 00055 double horiz2 = d2 - _r2; 00056 00057 double dist2 = (_world-eye).length2(); 00058 00059 if ( dist2 < horiz2 ) 00060 { 00061 traverse(node, nv); 00062 } 00063 } 00064 } 00065 00066 //------------------------------------------------------------------------ 00067 00068 CullNodeByNormal::CullNodeByNormal( const osg::Vec3d& normal ) 00069 { 00070 _normal = normal; 00071 //_normal.normalize(); 00072 } 00073 00074 void 00075 CullNodeByNormal::operator()(osg::Node* node, osg::NodeVisitor* nv) 00076 { 00077 osg::Vec3d eye, center, up; 00078 osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>( nv ); 00079 00080 cv->getCurrentCamera()->getViewMatrixAsLookAt(eye,center,up); 00081 00082 eye.normalize(); 00083 osg::Vec3d normal = _normal; 00084 normal.normalize(); 00085 00086 double dotProduct = eye * normal; 00087 if ( dotProduct > 0.0 ) 00088 { 00089 traverse(node, nv); 00090 } 00091 } 00092 00093 //------------------------------------------------------------------------ 00094 00095 #undef LC 00096 #define LC "[PixelAutoTransform] " 00097 00098 PixelAutoTransform::PixelAutoTransform() : 00099 osg::AutoTransform() 00100 { 00101 // deactivate culling for the first traversal. We will reactivate it later. 00102 setCullingActive( false ); 00103 } 00104 00105 void 00106 PixelAutoTransform::accept( osg::NodeVisitor& nv ) 00107 { 00108 if ( nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR ) 00109 { 00110 // re-activate culling now that the first cull traversal has taken place. 00111 this->setCullingActive( true ); 00112 osg::CullStack* cs = dynamic_cast<osg::CullStack*>(&nv); 00113 if ( cs ) 00114 { 00115 osg::Viewport::value_type width = _previousWidth; 00116 osg::Viewport::value_type height = _previousHeight; 00117 00118 osg::Viewport* viewport = cs->getViewport(); 00119 if (viewport) 00120 { 00121 width = viewport->width(); 00122 height = viewport->height(); 00123 } 00124 00125 osg::Vec3d eyePoint = cs->getEyeLocal(); 00126 osg::Vec3d localUp = cs->getUpLocal(); 00127 osg::Vec3d position = getPosition(); 00128 00129 const osg::Matrix& projection = *(cs->getProjectionMatrix()); 00130 00131 bool doUpdate = _firstTimeToInitEyePoint || _dirty; 00132 if ( !_firstTimeToInitEyePoint ) 00133 { 00134 osg::Vec3d dv = _previousEyePoint - eyePoint; 00135 00136 if (dv.length2() > getAutoUpdateEyeMovementTolerance() * (eyePoint-getPosition()).length2()) 00137 { 00138 doUpdate = true; 00139 } 00140 else 00141 { 00142 osg::Vec3d dupv = _previousLocalUp - localUp; 00143 00144 // rotating the camera only affects ROTATE_TO_* 00145 if ((_autoRotateMode && dupv.length2() > getAutoUpdateEyeMovementTolerance()) || 00146 (width != _previousWidth || height != _previousHeight) || 00147 (projection != _previousProjection) || 00148 (position != _previousPosition) ) 00149 { 00150 doUpdate = true; 00151 } 00152 } 00153 } 00154 _firstTimeToInitEyePoint = false; 00155 00156 if ( doUpdate ) 00157 { 00158 if ( getAutoScaleToScreen() ) 00159 { 00160 double radius = 00161 _sizingNode.valid() ? _sizingNode->getBound().radius() : 00162 getNumChildren() > 0 ? getChild(0)->getBound().radius() : 00163 0.48; 00164 00165 double pixels = cs->pixelSize( getPosition(), radius ); 00166 00167 double scaledMinPixels = _minPixels * _minimumScale; 00168 double scale = pixels < scaledMinPixels ? scaledMinPixels / pixels : 1.0; 00169 00170 OE_DEBUG << LC 00171 << "Pixels = " << pixels << ", minPix = " << _minPixels << ", scale = " << scale 00172 << std::endl; 00173 00174 setScale( scale ); 00175 } 00176 00177 _previousEyePoint = eyePoint; 00178 _previousLocalUp = localUp; 00179 _previousWidth = width; 00180 _previousHeight = height; 00181 _previousProjection = projection; 00182 _previousPosition = position; 00183 00184 _matrixDirty = true; 00185 } 00186 00187 if (_autoRotateMode==ROTATE_TO_SCREEN) 00188 { 00189 osg::Vec3d translation; 00190 osg::Quat rotation; 00191 osg::Vec3d scale; 00192 osg::Quat so; 00193 00194 cs->getModelViewMatrix()->decompose( translation, rotation, scale, so ); 00195 00196 setRotation(rotation.inverse()); 00197 } 00198 else if (_autoRotateMode==ROTATE_TO_CAMERA) 00199 { 00200 osg::Vec3d PosToEye = _position - eyePoint; 00201 osg::Matrix lookto = osg::Matrix::lookAt( 00202 osg::Vec3d(0,0,0), PosToEye, localUp); 00203 osg::Quat q; 00204 q.set(osg::Matrix::inverse(lookto)); 00205 setRotation(q); 00206 } 00207 00208 #if OSG_MIN_VERSION_REQUIRED(3,0,0) 00209 else if (_autoRotateMode==ROTATE_TO_AXIS) 00210 { 00211 osg::Matrix matrix; 00212 osg::Vec3 ev(eyePoint - _position); 00213 00214 switch(_cachedMode) 00215 { 00216 case(AXIAL_ROT_Z_AXIS): 00217 { 00218 ev.z() = 0.0f; 00219 float ev_length = ev.length(); 00220 if (ev_length>0.0f) 00221 { 00222 //float rotation_zrotation_z = atan2f(ev.x(),ev.y()); 00223 //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f); 00224 float inv = 1.0f/ev_length; 00225 float s = ev.x()*inv; 00226 float c = -ev.y()*inv; 00227 matrix(0,0) = c; 00228 matrix(1,0) = -s; 00229 matrix(0,1) = s; 00230 matrix(1,1) = c; 00231 } 00232 break; 00233 } 00234 case(AXIAL_ROT_Y_AXIS): 00235 { 00236 ev.y() = 0.0f; 00237 float ev_length = ev.length(); 00238 if (ev_length>0.0f) 00239 { 00240 //float rotation_zrotation_z = atan2f(ev.x(),ev.y()); 00241 //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f); 00242 float inv = 1.0f/ev_length; 00243 float s = -ev.z()*inv; 00244 float c = ev.x()*inv; 00245 matrix(0,0) = c; 00246 matrix(2,0) = s; 00247 matrix(0,2) = -s; 00248 matrix(2,2) = c; 00249 } 00250 break; 00251 } 00252 case(AXIAL_ROT_X_AXIS): 00253 { 00254 ev.x() = 0.0f; 00255 float ev_length = ev.length(); 00256 if (ev_length>0.0f) 00257 { 00258 //float rotation_zrotation_z = atan2f(ev.x(),ev.y()); 00259 //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f); 00260 float inv = 1.0f/ev_length; 00261 float s = -ev.z()*inv; 00262 float c = -ev.y()*inv; 00263 matrix(1,1) = c; 00264 matrix(2,1) = -s; 00265 matrix(1,2) = s; 00266 matrix(2,2) = c; 00267 } 00268 break; 00269 } 00270 case(ROTATE_TO_AXIS): // need to implement 00271 { 00272 float ev_side = ev*_side; 00273 float ev_normal = ev*_normal; 00274 float rotation = atan2f(ev_side,ev_normal); 00275 matrix.makeRotate(rotation,_axis); 00276 break; 00277 } 00278 } 00279 osg::Quat q; 00280 q.set(matrix); 00281 setRotation(q); 00282 } 00283 #endif 00284 00285 _dirty = false; 00286 } 00287 } 00288 00289 // finally, skip AT's accept and do Transform. 00290 Transform::accept(nv); 00291 00292 } 00293 00294 void 00295 PixelAutoTransform::dirty() 00296 { 00297 _dirty = true; 00298 setCullingActive( false ); 00299 }