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 library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Library General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Library General Public License for more details.
23 // You should have received a copy of the GNU Library General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 # include <simgear_config.h>
31 #include "ODGauge.hxx"
33 #include "CanvasSystemAdapter.hxx"
35 #include <simgear/debug/logstream.hxx>
36 #include <simgear/scene/util/RenderConstants.hxx>
38 #include <osg/Texture2D>
39 #include <osg/AlphaFunc>
40 #include <osg/BlendFunc>
43 #include <osg/PolygonMode>
44 #include <osg/ShadeModel>
45 #include <osg/StateSet>
46 #include <osg/FrameBufferObject> // for GL_DEPTH_STENCIL_EXT on Windows
47 #include <osg/Version>
48 #include <osgUtil/RenderBin>
58 public osgUtil::RenderBin
64 PreOrderBin( const RenderBin& rhs,
65 const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY ):
66 RenderBin(rhs, copyop)
69 virtual osg::Object* cloneType() const
71 return new PreOrderBin();
73 virtual osg::Object* clone(const osg::CopyOp& copyop) const
75 return new PreOrderBin(*this,copyop);
77 virtual bool isSameKindAs(const osg::Object* obj) const
79 return dynamic_cast<const PreOrderBin*>(obj) != 0L;
81 virtual const char* className() const
88 // Do not sort to keep traversal order...
92 #ifndef OSG_INIT_SINGLETON_PROXY
94 * http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk/include/osg/Object
96 * Helper macro that creates a static proxy object to call singleton function
97 * on it's construction, ensuring that the singleton gets initialized at
100 # define OSG_INIT_SINGLETON_PROXY(ProxyName, Func)\
101 static struct ProxyName{ ProxyName() { Func; } } s_##ProxyName;
104 OSG_INIT_SINGLETON_PROXY(
106 (osgUtil::RenderBin::addRenderBinPrototype("PreOrderBin", new PreOrderBin))
109 //----------------------------------------------------------------------------
116 _coverage_samples( 0 ),
122 //----------------------------------------------------------------------------
128 //----------------------------------------------------------------------------
129 void ODGauge::setSize(int size_x, int size_y)
132 _size_y = size_y < 0 ? size_x : size_y;
137 texture->setTextureSize(_size_x, _size_y);
140 //----------------------------------------------------------------------------
141 void ODGauge::setViewSize(int width, int height)
144 _view_height = height < 0 ? width : height;
147 updateCoordinateFrame();
150 //----------------------------------------------------------------------------
151 osg::Vec2s ODGauge::getViewSize() const
153 return osg::Vec2s(_view_width, _view_height);
156 //----------------------------------------------------------------------------
157 void ODGauge::useImageCoords(bool use)
159 if( updateFlag(USE_IMAGE_COORDS, use) && texture )
160 updateCoordinateFrame();
163 //----------------------------------------------------------------------------
164 void ODGauge::useStencil(bool use)
166 if( updateFlag(USE_STENCIL, use) && texture )
170 //----------------------------------------------------------------------------
171 void ODGauge::useAdditiveBlend(bool use)
173 if( updateFlag(USE_ADDITIVE_BLEND, use) && camera )
177 //----------------------------------------------------------------------------
178 void ODGauge::setSampling( bool mipmapping,
179 int coverage_samples,
182 if( !updateFlag(USE_MIPMAPPING, mipmapping)
183 && _coverage_samples == coverage_samples
184 && _color_samples == color_samples )
187 if( color_samples > coverage_samples )
193 "ODGauge::setSampling: color_samples > coverage_samples not allowed!"
195 color_samples = coverage_samples;
198 _coverage_samples = coverage_samples;
199 _color_samples = color_samples;
204 //----------------------------------------------------------------------------
205 void ODGauge::setRender(bool render)
207 // Only the far camera should trigger this texture to be rendered.
208 camera->setNodeMask(render ? simgear::BACKGROUND_BIT : 0);
211 //----------------------------------------------------------------------------
212 bool ODGauge::serviceable() const
214 return _flags & AVAILABLE;
217 //----------------------------------------------------------------------------
218 void ODGauge::allocRT(osg::NodeCallback* camera_cull_callback)
220 camera = new osg::Camera;
221 camera->setDataVariance(osg::Object::DYNAMIC);
222 camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
223 camera->setRenderOrder(osg::Camera::PRE_RENDER);
224 camera->setClearColor(osg::Vec4(0.0f, 0.0f, 0.0f , 0.0f));
225 camera->setClearStencil(0);
226 camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT,
227 osg::Camera::FRAME_BUFFER );
229 if( camera_cull_callback )
230 camera->setCullCallback(camera_cull_callback);
233 updateCoordinateFrame();
236 osg::StateSet* stateSet = camera->getOrCreateStateSet();
237 stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
238 stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
239 stateSet->setMode(GL_FOG, osg::StateAttribute::OFF);
240 stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
241 stateSet->setAttributeAndModes(
242 new osg::PolygonMode( osg::PolygonMode::FRONT_AND_BACK,
243 osg::PolygonMode::FILL ),
244 osg::StateAttribute::ON );
245 stateSet->setAttributeAndModes(
246 new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.001f),
247 osg::StateAttribute::ON );
248 stateSet->setAttribute(new osg::ShadeModel(osg::ShadeModel::FLAT));
252 texture = new osg::Texture2D;
253 texture->setResizeNonPowerOfTwoHint(false);
254 texture->setTextureSize(_size_x, _size_y);
255 texture->setInternalFormat(GL_RGBA);
261 if( Canvas::getSystemAdapter() )
262 Canvas::getSystemAdapter()->addCamera(camera.get());
267 //----------------------------------------------------------------------------
268 void ODGauge::reinit()
270 osg::NodeCallback* cull_callback =
272 #if OSG_VERSION_LESS_THAN(3,3,2)
273 ? camera->getCullCallback()
275 ? dynamic_cast<osg::NodeCallback*>(camera->getCullCallback())
280 allocRT(cull_callback);
283 //----------------------------------------------------------------------------
284 void ODGauge::clear()
286 if( camera.valid() && Canvas::getSystemAdapter() )
287 Canvas::getSystemAdapter()->removeCamera(camera.get());
291 _flags &= ~AVAILABLE;
294 //----------------------------------------------------------------------------
295 bool ODGauge::updateFlag(Flags flag, bool enable)
297 if( bool(_flags & flag) == enable )
304 //----------------------------------------------------------------------------
305 void ODGauge::updateCoordinateFrame()
309 if( _view_width < 0 )
310 _view_width = _size_x;
311 if( _view_height < 0 )
312 _view_height = _size_y;
314 camera->setViewport(0, 0, _size_x, _size_y);
316 if( _flags & USE_IMAGE_COORDS )
317 camera->setProjectionMatrix(
318 osg::Matrix::ortho2D(0, _view_width, _view_height, 0)
321 camera->setProjectionMatrix(
322 osg::Matrix::ortho2D( -_view_width/2., _view_width/2.,
323 -_view_height/2., _view_height/2. )
327 //----------------------------------------------------------------------------
328 void ODGauge::updateStencil()
332 GLbitfield mask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
334 if( _flags & USE_STENCIL )
336 camera->attach( osg::Camera::PACKED_DEPTH_STENCIL_BUFFER,
337 GL_DEPTH_STENCIL_EXT );
338 mask |= GL_STENCIL_BUFFER_BIT;
342 camera->detach(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER);
345 camera->setClearMask(mask);
348 //----------------------------------------------------------------------------
349 void ODGauge::updateSampling()
355 osg::Texture2D::MIN_FILTER,
356 (_flags & USE_MIPMAPPING) ? osg::Texture2D::LINEAR_MIPMAP_LINEAR
357 : osg::Texture2D::LINEAR
360 osg::Camera::COLOR_BUFFER,
363 _flags & USE_MIPMAPPING,
369 //----------------------------------------------------------------------------
370 void ODGauge::updateBlendMode()
374 camera->getOrCreateStateSet()
375 ->setAttributeAndModes
377 (_flags & USE_ADDITIVE_BLEND)
378 ? new osg::BlendFunc( osg::BlendFunc::SRC_ALPHA,
379 osg::BlendFunc::ONE_MINUS_SRC_ALPHA,
381 osg::BlendFunc::ONE )
382 : new osg::BlendFunc( osg::BlendFunc::SRC_ALPHA,
383 osg::BlendFunc::ONE_MINUS_SRC_ALPHA )
387 } // namespace canvas
388 } // namespace simgear