OpenWalnut
1.4.0
|
00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #include <iostream> 00026 #include <string> 00027 00028 #include <boost/bind.hpp> 00029 #include <boost/function.hpp> 00030 00031 #include <osg/Camera> 00032 #include <osg/Geode> 00033 #include <osg/Geometry> 00034 #include <osg/MatrixTransform> 00035 #include <osg/Node> 00036 #include <osg/TexEnv> 00037 00038 #include "../common/WPathHelper.h" 00039 00040 #include "WGETextureHud.h" 00041 00042 WGETextureHud::WGETextureHud(): 00043 osg::Projection(), 00044 m_group( new WGEGroupNode() ), 00045 m_maxElementWidth( 256 ), 00046 m_renderBin( 10000 ), 00047 m_viewport( new osg::Viewport() ), 00048 m_coupleTexViewport( false ) 00049 { 00050 getOrCreateStateSet()->setRenderBinDetails( m_renderBin, "RenderBin" ); 00051 m_group->addUpdateCallback( new SafeUpdateCallback( this ) ); 00052 addChild( m_group ); 00053 } 00054 00055 WGETextureHud::~WGETextureHud() 00056 { 00057 // cleanup 00058 } 00059 00060 void WGETextureHud::SafeUpdateCallback::operator()( osg::Node* node, osg::NodeVisitor* nv ) 00061 { 00062 // set the new size of the widget (how can we get this data?) 00063 unsigned int screenWidth = m_hud->m_viewport->width(); 00064 unsigned int screenHeight = m_hud->m_viewport->height(); 00065 m_hud->setMatrix( osg::Matrix::ortho2D( 0, screenWidth, 0, screenHeight ) ); 00066 00067 // border around each element 00068 unsigned int border = 5; 00069 00070 // update all those 00071 osg::Group* group = static_cast< osg::Group* >( node ); 00072 00073 unsigned int nextX = border; 00074 unsigned int nextY = border; 00075 00076 // iterate all children 00077 for( size_t i = 0; i < group->getNumChildren(); ++i ) 00078 { 00079 // all children are WGETextureHudEntries. 00080 WGETextureHudEntry* tex = static_cast< WGETextureHudEntry* >( group->getChild( i ) ); 00081 tex->setMaxTextWidth( m_hud->getMaxElementWidth() ); // as this might change each frame, we set it here 00082 00083 // scale the height of the quad (texture) to have proper aspect ratio 00084 float height = static_cast< float >( m_hud->getMaxElementWidth() * tex->getRealHeight() ) / static_cast< float >( tex->getRealWidth() ); 00085 00086 // scale texture if needed 00087 if( m_hud->m_coupleTexViewport ) 00088 { 00089 osg::ref_ptr< osg::TexMat > texMat = tex->getTextureMatrix(); 00090 texMat->setMatrix( osg::Matrixd::scale( static_cast< float >( screenWidth ) / static_cast< float >( tex->getRealWidth() ), 00091 static_cast< float >( screenHeight )/ static_cast< float >( tex->getRealHeight() ), 1.0 ) ); 00092 00093 // this also changes the aspect ratio in the texture: 00094 height = static_cast< float >( m_hud->getMaxElementWidth() * screenHeight ) / static_cast< float >( screenWidth ); 00095 } 00096 00097 // scale them to their final size 00098 osg::Matrixd scale = osg::Matrixd::scale( m_hud->getMaxElementWidth(), height, 1.0 ); 00099 00100 // need to add a "line-break"? 00101 if( nextY + height + border > screenHeight ) 00102 { 00103 nextX += m_hud->getMaxElementWidth() + border; 00104 nextY = border; 00105 } 00106 00107 // transform them to the right place 00108 osg::Matrixd translate = osg::Matrixd::translate( static_cast< double >( nextX ), static_cast< double >( nextY ), 0.0 ); 00109 tex->setMatrix( scale * translate ); 00110 00111 // calculate the y position of the next texture 00112 nextY += height + border; 00113 } 00114 00115 // update all the others 00116 traverse( node, nv ); 00117 } 00118 00119 void WGETextureHud::addTexture( osg::ref_ptr< WGETextureHudEntry > texture ) 00120 { 00121 m_group->insert( texture ); 00122 } 00123 00124 void WGETextureHud::removeTexture( osg::ref_ptr< WGETextureHudEntry > texture ) 00125 { 00126 m_group->remove( texture ); 00127 } 00128 00129 /** 00130 * This method compares a specified texture with the specified node. If the node is an WGETextureHudEntry instance, the containied textures 00131 * get compared. 00132 * 00133 * \param tex the texture to compare to 00134 * \param node the node 00135 * 00136 * \return true if node->m_texture == tex. 00137 */ 00138 bool hudEntryPredicate( osg::ref_ptr< osg::Texture > tex, osg::ref_ptr< osg::Node > const& node ) 00139 { 00140 // is the node an WGETextureHudEntry? 00141 WGETextureHud::WGETextureHudEntry const* e = dynamic_cast< WGETextureHud::WGETextureHudEntry const* >( node.get() ); 00142 if( !e ) 00143 { 00144 return false; 00145 } 00146 00147 // check if textures are equal 00148 return e->getTexture() == tex; 00149 } 00150 00151 void WGETextureHud::removeTexture( osg::ref_ptr< osg::Texture > texture ) 00152 { 00153 typedef WPredicateHelper::ArbitraryPredicate< osg::ref_ptr< osg::Node > const, 00154 boost::function< bool ( osg::ref_ptr< osg::Node > const& ) > > TexCheck; // NOLINT - if the 00155 // 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 00156 // boost::function. 00157 00158 m_group->remove_if( 00159 boost::shared_ptr< WGEGroupNode::NodePredicate >( 00160 new TexCheck( boost::bind( &hudEntryPredicate, texture, _1 ) ) 00161 ) 00162 ); 00163 } 00164 00165 void WGETextureHud::setViewport( osg::Viewport* viewport ) 00166 { 00167 m_viewport = viewport; 00168 } 00169 00170 void WGETextureHud::coupleViewportWithTextureViewport( bool couple ) 00171 { 00172 m_coupleTexViewport = couple; 00173 } 00174 00175 WGETextureHud::WGETextureHudEntry::WGETextureHudEntry( osg::ref_ptr< osg::Texture2D > texture, std::string name, bool transparency ): 00176 osg::MatrixTransform(), 00177 m_texture( texture ), 00178 m_name( name ), 00179 m_maxTextWidth( 256 ) 00180 { 00181 setMatrix( osg::Matrixd::identity() ); 00182 setReferenceFrame( osg::Transform::ABSOLUTE_RF ); 00183 00184 ////////////////////////////////////////////////// 00185 // Texture Quad 00186 00187 osg::Geode* geode = new osg::Geode(); 00188 00189 // Set up geometry for the HUD and add it to the HUD 00190 osg::ref_ptr< osg::Geometry > HUDBackgroundGeometry = new osg::Geometry(); 00191 00192 osg::ref_ptr< osg::Vec3Array > HUDBackgroundVertices = new osg::Vec3Array; 00193 HUDBackgroundVertices->push_back( osg::Vec3( 0, 0, -1 ) ); 00194 HUDBackgroundVertices->push_back( osg::Vec3( 1, 0, -1 ) ); 00195 HUDBackgroundVertices->push_back( osg::Vec3( 1, 1, -1 ) ); 00196 HUDBackgroundVertices->push_back( osg::Vec3( 0, 1, -1 ) ); 00197 00198 osg::ref_ptr< osg::Vec3Array > HUDBackgroundTex = new osg::Vec3Array; 00199 HUDBackgroundTex->push_back( osg::Vec3( 0, 0, 0 ) ); 00200 HUDBackgroundTex->push_back( osg::Vec3( 1, 0, 0 ) ); 00201 HUDBackgroundTex->push_back( osg::Vec3( 1, 1, 0 ) ); 00202 HUDBackgroundTex->push_back( osg::Vec3( 0, 1, 0 ) ); 00203 00204 osg::ref_ptr< osg::DrawElementsUInt > HUDBackgroundIndices = new osg::DrawElementsUInt( osg::PrimitiveSet::POLYGON, 0 ); 00205 HUDBackgroundIndices->push_back( 0 ); 00206 HUDBackgroundIndices->push_back( 1 ); 00207 HUDBackgroundIndices->push_back( 2 ); 00208 HUDBackgroundIndices->push_back( 3 ); 00209 00210 osg::ref_ptr< osg::Vec4Array > HUDcolors = new osg::Vec4Array; 00211 HUDcolors->push_back( osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) ); 00212 00213 osg::ref_ptr< osg::Vec3Array > HUDnormals = new osg::Vec3Array; 00214 HUDnormals->push_back( osg::Vec3( 0.0f, 0.0f, 1.0f ) ); 00215 HUDBackgroundGeometry->setNormalArray( HUDnormals ); 00216 HUDBackgroundGeometry->setNormalBinding( osg::Geometry::BIND_OVERALL ); 00217 HUDBackgroundGeometry->addPrimitiveSet( HUDBackgroundIndices ); 00218 HUDBackgroundGeometry->setVertexArray( HUDBackgroundVertices ); 00219 HUDBackgroundGeometry->setColorArray( HUDcolors ); 00220 HUDBackgroundGeometry->setColorBinding( osg::Geometry::BIND_OVERALL ); 00221 HUDBackgroundGeometry->setTexCoordArray( 0, HUDBackgroundTex ); 00222 00223 geode->addDrawable( HUDBackgroundGeometry ); 00224 00225 // Create and set up a state set using the texture from above 00226 osg::StateSet* state = geode->getOrCreateStateSet(); 00227 state->setTextureAttributeAndModes( 0, texture, osg::StateAttribute::ON ); 00228 state->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF ); 00229 state->setMode( GL_LIGHTING, osg::StateAttribute::PROTECTED ); 00230 state->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); 00231 00232 // enable texture coordinate manipulation via texture matrices 00233 m_texMat = new osg::TexMat; 00234 m_texMat->setMatrix( osg::Matrixd::identity() ); 00235 state->setTextureAttributeAndModes( 0, m_texMat, osg::StateAttribute::ON ); 00236 00237 // This disables colorblending of the texture with the underlying quad 00238 // osg::TexEnv* decalState = new osg::TexEnv(); 00239 // decalState->setMode( osg::TexEnv::DECAL ); 00240 // state->setTextureAttribute( 0, decalState, osg::StateAttribute::ON ); 00241 00242 // en/disable blending 00243 if( !transparency ) 00244 { 00245 state->setMode( GL_BLEND, osg::StateAttribute::PROTECTED ); 00246 state->setMode( GL_BLEND, osg::StateAttribute::OFF ); 00247 } 00248 else 00249 { 00250 state->setMode( GL_BLEND, osg::StateAttribute::PROTECTED ); 00251 state->setMode( GL_BLEND, osg::StateAttribute::ON ); 00252 state->setRenderingHint( osg::StateSet::TRANSPARENT_BIN ); 00253 } 00254 00255 // add the geode 00256 addChild( geode ); 00257 00258 ////////////////////////////////////////////////// 00259 // Text 00260 osg::ref_ptr< osg::Geode > textGeode = new osg::Geode(); 00261 state = textGeode->getOrCreateStateSet(); 00262 state->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF ); 00263 addChild( textGeode ); 00264 m_label = new osgText::Text(); 00265 m_label->setFont( WPathHelper::getAllFonts().Default.string() ); 00266 m_label->setBackdropType( osgText::Text::OUTLINE ); 00267 m_label->setCharacterSize( 15 ); 00268 m_label->setText( m_name ); 00269 m_label->setAxisAlignment( osgText::Text::SCREEN ); 00270 m_label->setPosition( osg::Vec3( 0.02, 0.925, -1.0 ) ); 00271 m_label->setColor( osg::Vec4( 1.0, 1.0, 1.0, 1.0 ) ); 00272 textGeode->addDrawable( m_label ); 00273 } 00274 00275 WGETextureHud::WGETextureHudEntry::~WGETextureHudEntry() 00276 { 00277 // cleanup 00278 } 00279 00280 void WGETextureHud::WGETextureHudEntry::setMaxTextWidth( float width ) 00281 { 00282 m_maxTextWidth = width; 00283 m_label->setMaximumWidth( width - 20 ); // 20? Ensure some space at the right side 00284 } 00285 00286 unsigned int WGETextureHud::WGETextureHudEntry::getRealWidth() const 00287 { 00288 return m_texture->getTextureWidth(); 00289 } 00290 00291 unsigned int WGETextureHud::WGETextureHudEntry::getRealHeight() const 00292 { 00293 return m_texture->getTextureHeight(); 00294 } 00295 00296 osg::ref_ptr< osg::TexMat > WGETextureHud::WGETextureHudEntry::getTextureMatrix() const 00297 { 00298 return m_texMat; 00299 } 00300 00301 std::string WGETextureHud::WGETextureHudEntry::getName() const 00302 { 00303 return m_name; 00304 } 00305 00306 unsigned int WGETextureHud::getMaxElementWidth() const 00307 { 00308 return m_maxElementWidth; 00309 } 00310 00311 void WGETextureHud::setMaxElementWidth( unsigned int width ) 00312 { 00313 m_maxElementWidth = width; 00314 } 00315 00316 osg::ref_ptr< osg::Texture2D > WGETextureHud::WGETextureHudEntry::getTexture() const 00317 { 00318 return m_texture; 00319 } 00320 00321 size_t WGETextureHud::getRenderBin() const 00322 { 00323 return m_renderBin; 00324 } 00325