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 00020 #include <osgEarth/DrapeableNode> 00021 #include <osgEarth/Utils> 00022 #include <osgEarth/FindNode> 00023 00024 using namespace osgEarth; 00025 00026 DrapeableNode::DrapeableNode( MapNode* mapNode, bool draped ) : 00027 _mapNode ( mapNode ), 00028 _newDraped( draped ), 00029 _draped ( false ), 00030 _dirty ( false ) 00031 { 00032 // create a container group that will house the culler. This culler 00033 // allows a draped node, which sits under the MapNode's OverlayDecorator, 00034 // to "track" the traversal state of the DrapeableNode itself. 00035 _nodeContainer = new osg::Group(); 00036 _nodeContainer->setCullCallback( new CullNodeByFrameNumber() ); 00037 _nodeContainer->setStateSet( this->getOrCreateStateSet() ); // share the stateset 00038 } 00039 00040 void 00041 DrapeableNode::applyChanges() 00042 { 00043 if ( _newDraped != _draped ) 00044 { 00045 setDrapedImpl( _newDraped ); 00046 } 00047 00048 if ( _newNode.valid() ) 00049 { 00050 setNodeImpl( _newNode.get() ); 00051 _newNode = 0L; 00052 } 00053 } 00054 00055 void 00056 DrapeableNode::setNode( osg::Node* node ) 00057 { 00058 _newNode = node; 00059 if ( !_dirty ) 00060 { 00061 _dirty = true; 00062 ADJUST_UPDATE_TRAV_COUNT( this, 1 ); 00063 } 00064 } 00065 00066 void 00067 DrapeableNode::setDraped( bool draped ) 00068 { 00069 _newDraped = draped; 00070 if ( !_dirty ) 00071 { 00072 _dirty = true; 00073 ADJUST_UPDATE_TRAV_COUNT( this, 1 ); 00074 } 00075 } 00076 00077 void 00078 DrapeableNode::setNodeImpl( osg::Node* node ) 00079 { 00080 if ( _node.valid() ) 00081 { 00082 if ( _draped && _mapNode.valid() ) 00083 { 00084 _mapNode->getOverlayGroup()->removeChild( _nodeContainer.get() ); 00085 _mapNode->updateOverlayGraph(); 00086 } 00087 else 00088 { 00089 this->removeChild( _node.get() ); 00090 } 00091 } 00092 00093 _node = node; 00094 _nodeContainer->removeChildren( 0, _nodeContainer->getNumChildren() ); 00095 00096 if ( _node.valid() ) 00097 { 00098 if ( _draped && _mapNode.valid() ) 00099 { 00100 _nodeContainer->addChild( _node.get() ); 00101 _mapNode->getOverlayGroup()->addChild( _nodeContainer.get() ); 00102 _mapNode->updateOverlayGraph(); 00103 } 00104 else 00105 { 00106 this->addChild( _node.get() ); 00107 } 00108 } 00109 } 00110 00111 void 00112 DrapeableNode::setDrapedImpl( bool value ) 00113 { 00114 if ( _draped != value ) 00115 { 00116 osg::ref_ptr<osg::Node> save = _node.get(); 00117 if ( save.valid() ) 00118 setNode( 0L ); 00119 00120 _draped = value; 00121 00122 if ( save.valid() ) 00123 setNode( save.get() ); 00124 } 00125 } 00126 00127 00128 void 00129 DrapeableNode::traverse( osg::NodeVisitor& nv ) 00130 { 00131 if ( _draped && nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR && _node.valid() && _mapNode.valid() ) 00132 { 00133 CullNodeByFrameNumber* cb = static_cast<CullNodeByFrameNumber*>(_nodeContainer->getCullCallback()); 00134 cb->_frame = nv.getFrameStamp()->getFrameNumber(); 00135 } 00136 00137 if ( nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR ) 00138 { 00139 if ( _dirty ) 00140 { 00141 applyChanges(); 00142 00143 _dirty = false; 00144 ADJUST_UPDATE_TRAV_COUNT( this, -1 ); 00145 } 00146 00147 // traverse the subgraph 00148 if ( _nodeContainer.valid() && this->getNumChildrenRequiringUpdateTraversal() > 0 ) 00149 { 00150 _nodeContainer->accept( nv ); 00151 } 00152 } 00153 00154 osg::Group::traverse( nv ); 00155 }