1 // Owner Drawn Gauge helper class
3 // Written by Harald JOHNSEN, started May 2005.
5 // Copyright (C) 2005 Harald JOHNSEN
7 // Ported to OSG by Tim Moore - Jun 2007
9 // Heavily modified to be usable for the 2d Canvas by Thomas Geymayer - April 2012
10 // Supports now multisampling/mipmapping, usage of the stencil buffer and placing
11 // the texture in the scene by certain filter criteria
13 // This program is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU General Public License as
15 // published by the Free Software Foundation; either version 2 of the
16 // License, or (at your option) any later version.
18 // This program is distributed in the hope that it will be useful, but
19 // WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // General Public License for more details.
23 // You should have received a copy of the GNU General Public License
24 // along with this program; if not, write to the Free Software
25 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
33 #include <osg/Texture2D>
34 #include <osg/AlphaFunc>
35 #include <osg/BlendFunc>
38 #include <osg/NodeVisitor>
40 #include <osg/PolygonMode>
41 #include <osg/ShadeModel>
42 #include <osg/StateSet>
43 #include <osg/FrameBufferObject> // for GL_DEPTH_STENCIL_EXT on Windows
45 #include <osgDB/FileNameUtils>
47 #include <simgear/canvas/CanvasObjectPlacement.hxx>
48 #include <simgear/scene/material/EffectGeode.hxx>
49 #include <simgear/scene/util/RenderConstants.hxx>
51 #include <Main/globals.hxx>
52 #include <Scenery/scenery.hxx>
53 #include "od_gauge.hxx"
57 //------------------------------------------------------------------------------
58 FGODGauge::FGODGauge()
63 //------------------------------------------------------------------------------
64 FGODGauge::~FGODGauge()
70 * Replace a texture in the airplane model with the gauge texture.
72 class ReplaceStaticTextureVisitor:
73 public osg::NodeVisitor
77 typedef osg::ref_ptr<osg::Group> GroupPtr;
78 typedef osg::ref_ptr<osg::Material> MaterialPtr;
80 ReplaceStaticTextureVisitor( const char* name,
81 osg::Texture2D* new_texture ):
82 osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
83 _tex_name( osgDB::getSimpleFileName(name) ),
84 _new_texture(new_texture),
88 ReplaceStaticTextureVisitor( SGPropertyNode* placement,
89 osg::Texture2D* new_texture,
90 osg::NodeCallback* cull_callback = 0,
91 const simgear::canvas::CanvasWeakPtr& canvas =
92 simgear::canvas::CanvasWeakPtr() ):
93 osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
94 _tex_name( osgDB::getSimpleFileName(
95 placement->getStringValue("texture"))
97 _node_name( placement->getStringValue("node") ),
98 _parent_name( placement->getStringValue("parent") ),
100 _new_texture(new_texture),
101 _cull_callback(cull_callback),
104 if( _tex_name.empty()
105 && _node_name.empty()
106 && _parent_name.empty() )
111 "No filter criterion for replacing texture. "
112 " Every texture will be replaced!"
117 * Get a list of groups which have been inserted into the scene graph to
118 * replace the given texture
120 simgear::canvas::Placements& getPlacements()
125 virtual void apply(osg::Geode& node)
127 simgear::EffectGeode* eg = dynamic_cast<simgear::EffectGeode*>(&node);
130 simgear::Effect* eff = eg->getEffect();
133 osg::StateSet* ss = eff->getDefaultStateSet();
137 osg::Group *parent = node.getParent(0);
138 if( !_node_name.empty() && getNodeName(*parent) != _node_name )
141 if( !_parent_name.empty() )
143 // Traverse nodes upwards starting at the parent node (skip current
145 const osg::NodePath& np = getNodePath();
147 for( int i = static_cast<int>(np.size()) - 2; i >= 0; --i )
149 const osg::Node* path_segment = np[i];
150 const osg::Node* path_parent = path_segment->getParent(0);
152 // A node without a name is always the parent of the root node of
153 // the model just containing the file name
154 if( path_parent && path_parent->getName().empty() )
157 if( path_segment->getName() == _parent_name )
168 for( size_t unit = 0; unit < ss->getNumTextureAttributeLists(); ++unit )
170 osg::Texture2D* tex = dynamic_cast<osg::Texture2D*>
172 ss->getTextureAttribute(unit, osg::StateAttribute::TEXTURE)
175 if( !tex || !tex->getImage() || tex == _new_texture )
178 if( !_tex_name.empty() )
180 std::string tex_name = tex->getImage()->getFileName();
181 std::string tex_name_simple = osgDB::getSimpleFileName(tex_name);
182 if( !osgDB::equalCaseInsensitive(_tex_name, tex_name_simple) )
186 // insert a new group between the geode an it's parent which overrides
188 GroupPtr group = new osg::Group;
189 group->setName("canvas texture group");
191 parent->removeChild(eg);
192 parent->addChild(group);
195 group->setCullCallback(_cull_callback);
197 osg::StateSet* stateSet = group->getOrCreateStateSet();
198 stateSet->setTextureAttribute( unit, _new_texture,
199 osg::StateAttribute::OVERRIDE );
200 stateSet->setTextureMode( unit, GL_TEXTURE_2D,
201 osg::StateAttribute::ON );
203 _placements.push_back( simgear::canvas::PlacementPtr(
204 new simgear::canvas::ObjectPlacement(_node, group, _canvas)
211 "Replaced texture '" << _tex_name << "'"
212 << " for object '" << parent->getName() << "'"
213 << (!_parent_name.empty() ? " with parent '" + _parent_name + "'"
222 std::string _tex_name, ///<! Name of texture to be replaced
223 _node_name, ///<! Only replace if node name matches
224 _parent_name; ///<! Only replace if any parent node matches
225 /// given name (all the tree upwards)
227 SGPropertyNode_ptr _node;
228 osg::Texture2D *_new_texture;
229 osg::NodeCallback *_cull_callback;
231 simgear::canvas::CanvasWeakPtr _canvas;
232 simgear::canvas::Placements _placements;
234 const std::string& getNodeName(const osg::Node& node) const
236 if( !node.getName().empty() )
237 return node.getName();
239 // Special handling for pick animation which clears the name of the object
240 // and instead sets the name of a parent group with one or two groups
241 // attached (one for normal rendering and one for the picking highlight).
242 osg::Group const* parent = node.getParent(0);
243 if( parent->getName() == "pick render group" )
244 return parent->getParent(0)->getName();
246 return node.getName();
250 //------------------------------------------------------------------------------
251 simgear::canvas::Placements
252 FGODGauge::set_texture( osg::Node* branch,
254 osg::Texture2D* new_texture )
256 ReplaceStaticTextureVisitor visitor(name, new_texture);
257 branch->accept(visitor);
258 return visitor.getPlacements();
261 //------------------------------------------------------------------------------
262 simgear::canvas::Placements
263 FGODGauge::set_aircraft_texture( const char* name,
264 osg::Texture2D* new_texture )
268 globals->get_scenery()->get_aircraft_branch(),
274 //------------------------------------------------------------------------------
275 simgear::canvas::Placements
276 FGODGauge::set_texture( osg::Node* branch,
277 SGPropertyNode* placement,
278 osg::Texture2D* new_texture,
279 osg::NodeCallback* cull_callback,
280 const simgear::canvas::CanvasWeakPtr& canvas )
282 ReplaceStaticTextureVisitor visitor( placement,
286 branch->accept(visitor);
287 return visitor.getPlacements();
290 //------------------------------------------------------------------------------
291 simgear::canvas::Placements
292 FGODGauge::set_aircraft_texture( SGPropertyNode* placement,
293 osg::Texture2D* new_texture,
294 osg::NodeCallback* cull_callback,
295 const simgear::canvas::CanvasWeakPtr& canvas )
299 globals->get_scenery()->get_aircraft_branch(),