OpenWalnut  1.5.0dev
WGETextureHud.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <iostream>
26 #include <memory>
27 #include <string>
28 
29 #include <boost/bind/bind.hpp>
30 #include <boost/function.hpp>
31 #include <osg/Camera>
32 #include <osg/Geode>
33 #include <osg/Geometry>
34 #include <osg/MatrixTransform>
35 #include <osg/Node>
36 #include <osg/TexEnv>
37 
38 #include "../common/WPathHelper.h"
39 #include "WGETextureHud.h"
40 
42  osg::Projection(),
43  m_group( new WGEGroupNode() ),
44  m_maxElementWidth( 256 ),
45  m_renderBin( 10000 ),
46  m_viewport( new osg::Viewport() ),
47  m_coupleTexViewport( false )
48 {
49  getOrCreateStateSet()->setRenderBinDetails( m_renderBin, "RenderBin" );
50  m_group->addUpdateCallback( new SafeUpdateCallback( this ) );
51  addChild( m_group );
52 }
53 
55 {
56  // cleanup
57 }
58 
59 void WGETextureHud::SafeUpdateCallback::operator()( osg::Node* node, osg::NodeVisitor* nv )
60 {
61  // set the new size of the widget (how can we get this data?)
62  unsigned int screenWidth = m_hud->m_viewport->width();
63  unsigned int screenHeight = m_hud->m_viewport->height();
64  m_hud->setMatrix( osg::Matrix::ortho2D( 0, screenWidth, 0, screenHeight ) );
65 
66  // border around each element
67  unsigned int border = 5;
68 
69  // update all those
70  osg::Group* group = static_cast< osg::Group* >( node );
71 
72  unsigned int nextX = border;
73  unsigned int nextY = border;
74 
75  // iterate all children
76  for( size_t i = 0; i < group->getNumChildren(); ++i )
77  {
78  // all children are WGETextureHudEntries.
79  WGETextureHudEntry* tex = static_cast< WGETextureHudEntry* >( group->getChild( i ) );
80  tex->setMaxTextWidth( m_hud->getMaxElementWidth() ); // as this might change each frame, we set it here
81 
82  // scale the height of the quad (texture) to have proper aspect ratio
83  float height = static_cast< float >( m_hud->getMaxElementWidth() * tex->getRealHeight() ) / static_cast< float >( tex->getRealWidth() );
84 
85  // scale texture if needed
87  {
88  osg::ref_ptr< osg::TexMat > texMat = tex->getTextureMatrix();
89  texMat->setMatrix( osg::Matrixd::scale( static_cast< float >( screenWidth ) / static_cast< float >( tex->getRealWidth() ),
90  static_cast< float >( screenHeight )/ static_cast< float >( tex->getRealHeight() ), 1.0 ) );
91 
92  // this also changes the aspect ratio in the texture:
93  height = static_cast< float >( m_hud->getMaxElementWidth() * screenHeight ) / static_cast< float >( screenWidth );
94  }
95 
96  // scale them to their final size
97  osg::Matrixd scale = osg::Matrixd::scale( m_hud->getMaxElementWidth(), height, 1.0 );
98 
99  // need to add a "line-break"?
100  if( nextY + height + border > screenHeight )
101  {
102  nextX += m_hud->getMaxElementWidth() + border;
103  nextY = border;
104  }
105 
106  // transform them to the right place
107  osg::Matrixd translate = osg::Matrixd::translate( static_cast< double >( nextX ), static_cast< double >( nextY ), 0.0 );
108  tex->setMatrix( scale * translate );
109 
110  // calculate the y position of the next texture
111  nextY += height + border;
112  }
113 
114  // update all the others
115  traverse( node, nv );
116 }
117 
118 void WGETextureHud::addTexture( osg::ref_ptr< WGETextureHudEntry > texture )
119 {
120  m_group->insert( texture );
121 }
122 
123 void WGETextureHud::removeTexture( osg::ref_ptr< WGETextureHudEntry > texture )
124 {
125  m_group->remove( texture );
126 }
127 
128 /**
129  * This method compares a specified texture with the specified node. If the node is an WGETextureHudEntry instance, the containied textures
130  * get compared.
131  *
132  * \param tex the texture to compare to
133  * \param node the node
134  *
135  * \return true if node->m_texture == tex.
136  */
137 bool hudEntryPredicate( osg::ref_ptr< osg::Texture > tex, osg::ref_ptr< osg::Node > const& node )
138 {
139  // is the node an WGETextureHudEntry?
140  WGETextureHud::WGETextureHudEntry const* e = dynamic_cast< WGETextureHud::WGETextureHudEntry const* >( node.get() );
141  if( !e )
142  {
143  return false;
144  }
145 
146  // check if textures are equal
147  return e->getTexture() == tex;
148 }
149 
150 void WGETextureHud::removeTexture( osg::ref_ptr< osg::Texture > texture )
151 {
153  boost::function< bool ( osg::ref_ptr< osg::Node > const& ) > > TexCheck; // NOLINT - if the
154  // space after bool is removed (as the stylechecker want) it interprets it as old-style cast and complains about it. This is valid syntax for
155  // boost::function.
156 
157  m_group->remove_if(
158  std::shared_ptr< WGEGroupNode::NodePredicate >(
159  new TexCheck( boost::bind( &hudEntryPredicate, texture, boost::placeholders::_1 ) )
160  )
161  );
162 }
163 
164 void WGETextureHud::setViewport( osg::Viewport* viewport )
165 {
166  m_viewport = viewport;
167 }
168 
170 {
171  m_coupleTexViewport = couple;
172 }
173 
174 WGETextureHud::WGETextureHudEntry::WGETextureHudEntry( osg::ref_ptr< osg::Texture2D > texture, std::string name, bool transparency ):
175  osg::MatrixTransform(),
176  m_texture( texture ),
177  m_name( name ),
178  m_maxTextWidth( 256 )
179 {
180  setMatrix( osg::Matrixd::identity() );
181  setReferenceFrame( osg::Transform::ABSOLUTE_RF );
182 
183  //////////////////////////////////////////////////
184  // Texture Quad
185 
186  osg::Geode* geode = new osg::Geode();
187 
188  // Set up geometry for the HUD and add it to the HUD
189  osg::ref_ptr< osg::Geometry > HUDBackgroundGeometry = new osg::Geometry();
190 
191  osg::ref_ptr< osg::Vec3Array > HUDBackgroundVertices = new osg::Vec3Array;
192  HUDBackgroundVertices->push_back( osg::Vec3( 0, 0, -1 ) );
193  HUDBackgroundVertices->push_back( osg::Vec3( 1, 0, -1 ) );
194  HUDBackgroundVertices->push_back( osg::Vec3( 1, 1, -1 ) );
195  HUDBackgroundVertices->push_back( osg::Vec3( 0, 1, -1 ) );
196 
197  osg::ref_ptr< osg::Vec3Array > HUDBackgroundTex = new osg::Vec3Array;
198  HUDBackgroundTex->push_back( osg::Vec3( 0, 0, 0 ) );
199  HUDBackgroundTex->push_back( osg::Vec3( 1, 0, 0 ) );
200  HUDBackgroundTex->push_back( osg::Vec3( 1, 1, 0 ) );
201  HUDBackgroundTex->push_back( osg::Vec3( 0, 1, 0 ) );
202 
203  osg::ref_ptr< osg::DrawElementsUInt > HUDBackgroundIndices = new osg::DrawElementsUInt( osg::PrimitiveSet::POLYGON, 0 );
204  HUDBackgroundIndices->push_back( 0 );
205  HUDBackgroundIndices->push_back( 1 );
206  HUDBackgroundIndices->push_back( 2 );
207  HUDBackgroundIndices->push_back( 3 );
208 
209  osg::ref_ptr< osg::Vec4Array > HUDcolors = new osg::Vec4Array;
210  HUDcolors->push_back( osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) );
211 
212  osg::ref_ptr< osg::Vec3Array > HUDnormals = new osg::Vec3Array;
213  HUDnormals->push_back( osg::Vec3( 0.0f, 0.0f, 1.0f ) );
214  HUDBackgroundGeometry->setNormalArray( HUDnormals );
215  HUDBackgroundGeometry->setNormalBinding( osg::Geometry::BIND_OVERALL );
216  HUDBackgroundGeometry->addPrimitiveSet( HUDBackgroundIndices );
217  HUDBackgroundGeometry->setVertexArray( HUDBackgroundVertices );
218  HUDBackgroundGeometry->setColorArray( HUDcolors );
219  HUDBackgroundGeometry->setColorBinding( osg::Geometry::BIND_OVERALL );
220  HUDBackgroundGeometry->setTexCoordArray( 0, HUDBackgroundTex );
221 
222  geode->addDrawable( HUDBackgroundGeometry );
223 
224  // Create and set up a state set using the texture from above
225  osg::StateSet* state = geode->getOrCreateStateSet();
226  state->setTextureAttributeAndModes( 0, texture, osg::StateAttribute::ON );
227  state->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
228  state->setMode( GL_LIGHTING, osg::StateAttribute::PROTECTED );
229  state->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
230 
231  // enable texture coordinate manipulation via texture matrices
232  m_texMat = new osg::TexMat;
233  m_texMat->setMatrix( osg::Matrixd::identity() );
234  state->setTextureAttributeAndModes( 0, m_texMat, osg::StateAttribute::ON );
235 
236  // This disables colorblending of the texture with the underlying quad
237  // osg::TexEnv* decalState = new osg::TexEnv();
238  // decalState->setMode( osg::TexEnv::DECAL );
239  // state->setTextureAttribute( 0, decalState, osg::StateAttribute::ON );
240 
241  // en/disable blending
242  if( !transparency )
243  {
244  state->setMode( GL_BLEND, osg::StateAttribute::PROTECTED );
245  state->setMode( GL_BLEND, osg::StateAttribute::OFF );
246  }
247  else
248  {
249  state->setMode( GL_BLEND, osg::StateAttribute::PROTECTED );
250  state->setMode( GL_BLEND, osg::StateAttribute::ON );
251  state->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
252  }
253 
254  // add the geode
255  addChild( geode );
256 
257  //////////////////////////////////////////////////
258  // Text
259  osg::ref_ptr< osg::Geode > textGeode = new osg::Geode();
260  state = textGeode->getOrCreateStateSet();
261  state->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
262  addChild( textGeode );
263  m_label = new osgText::Text();
264  m_label->setFont( WPathHelper::getAllFonts().Default.string() );
265  m_label->setBackdropType( osgText::Text::OUTLINE );
266  m_label->setCharacterSize( 15 );
267  m_label->setText( m_name );
268  m_label->setAxisAlignment( osgText::Text::SCREEN );
269  m_label->setPosition( osg::Vec3( 0.02, 0.925, -1.0 ) );
270  m_label->setColor( osg::Vec4( 1.0, 1.0, 1.0, 1.0 ) );
271  textGeode->addDrawable( m_label );
272 }
273 
275 {
276  // cleanup
277 }
278 
280 {
281  m_maxTextWidth = width;
282  m_label->setMaximumWidth( width - 20 ); // 20? Ensure some space at the right side
283 }
284 
286 {
287  return m_texture->getTextureWidth();
288 }
289 
291 {
292  return m_texture->getTextureHeight();
293 }
294 
295 osg::ref_ptr< osg::TexMat > WGETextureHud::WGETextureHudEntry::getTextureMatrix() const
296 {
297  return m_texMat;
298 }
299 
301 {
302  return m_name;
303 }
304 
306 {
307  return m_maxElementWidth;
308 }
309 
310 void WGETextureHud::setMaxElementWidth( unsigned int width )
311 {
312  m_maxElementWidth = width;
313 }
314 
315 osg::ref_ptr< osg::Texture2D > WGETextureHud::WGETextureHudEntry::getTexture() const
316 {
317  return m_texture;
318 }
319 
321 {
322  return m_renderBin;
323 }
324 
Class to wrap around the osg Group node and providing a thread safe add/removal mechanism.
Definition: WGEGroupNode.h:48
Callback which aligns and renders the textures.
WGETextureHud * m_hud
Pointer used to access members of the hud.
virtual void operator()(osg::Node *node, osg::NodeVisitor *nv)
operator () - called during the update traversal.
Class implementing one texture HUD entry representing a texture in the HUD.
Definition: WGETextureHud.h:63
osg::ref_ptr< osg::Texture2D > getTexture() const
Gets the texture associated with the entry.
std::string m_name
The name for this HUD entry.
osgText::Text * m_label
The label text.
std::string getName() const
Returns the name of the entry.
unsigned int getRealHeight() const
Returns the real height of the contained texture.
osg::ref_ptr< osg::TexMat > getTextureMatrix() const
Get the texture matrix state for this entry.
unsigned int getRealWidth() const
Returns the real width of the contained texture.
WGETextureHudEntry(osg::ref_ptr< osg::Texture2D > texture, std::string name, bool transparency=false)
Constructor.
void setMaxTextWidth(float width)
Set maximum text width.
osg::ref_ptr< osg::TexMat > m_texMat
The texture matrix for this entry.
virtual ~WGETextureHud()
Destructor.
void removeTexture(osg::ref_ptr< WGETextureHudEntry > texture)
Remove the texture from the HUD.
osg::Viewport * m_viewport
The current viewport of.
void setViewport(osg::Viewport *viewport)
Sets the viewport of the camera housing this HUD.
void coupleViewportWithTextureViewport(bool couple=true)
Set the viewport to be used for textures too.
size_t getRenderBin() const
Returns the render bin used by the HUD.
unsigned int getMaxElementWidth() const
Gets the maximum width of a tex element.
void addTexture(osg::ref_ptr< WGETextureHudEntry > texture)
Adds the specified HUD element to the HUD.
unsigned int m_maxElementWidth
The maximum element width.
void setMaxElementWidth(unsigned int width)
Sets the new maximum width of a texture column.
bool m_coupleTexViewport
The viewport in texture space to allow viewing parts of the texture.
osg::ref_ptr< WGEGroupNode > m_group
The group Node where all those texture reside in.
size_t m_renderBin
The render bin to use.
WGETextureHud()
Default constructor.
static Fonts getAllFonts()
The paths to all fonts supported.
The actual class implementing the predicate evaluation.