OpenWalnut 1.2.5
|
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 #include <osgText/Text> 00038 00039 #include "../common/WPathHelper.h" 00040 00041 #include "WGETextureHud.h" 00042 00043 WGETextureHud::WGETextureHud(): 00044 osg::Projection(), 00045 m_group( new WGEGroupNode() ), 00046 m_maxElementWidth( 256 ), 00047 m_renderBin( 10000 ), 00048 m_viewport( new osg::Viewport() ), 00049 m_coupleTexViewport( false ) 00050 { 00051 getOrCreateStateSet()->setRenderBinDetails( m_renderBin, "RenderBin" ); 00052 m_group->addUpdateCallback( new SafeUpdateCallback( this ) ); 00053 addChild( m_group ); 00054 } 00055 00056 WGETextureHud::~WGETextureHud() 00057 { 00058 // cleanup 00059 } 00060 00061 void WGETextureHud::SafeUpdateCallback::operator()( osg::Node* node, osg::NodeVisitor* nv ) 00062 { 00063 // set the new size of the widget (how can we get this data?) 00064 unsigned int screenWidth = m_hud->m_viewport->width(); 00065 unsigned int screenHeight = m_hud->m_viewport->height(); 00066 m_hud->setMatrix( osg::Matrix::ortho2D( 0, screenWidth, 0, screenHeight ) ); 00067 00068 // border around each element 00069 unsigned int border = 5; 00070 00071 // update all those 00072 osg::Group* group = static_cast< osg::Group* >( node ); 00073 00074 unsigned int nextX = border; 00075 unsigned int nextY = border; 00076 00077 // iterate all children 00078 for( size_t i = 0; i < group->getNumChildren(); ++i ) 00079 { 00080 // all children are WGETextureHudEntries. 00081 WGETextureHudEntry* tex = static_cast< WGETextureHudEntry* >( group->getChild( i ) ); 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 { 00180 setMatrix( osg::Matrixd::identity() ); 00181 setReferenceFrame( osg::Transform::ABSOLUTE_RF ); 00182 00183 ////////////////////////////////////////////////// 00184 // Texture Quad 00185 00186 osg::Geode* geode = new osg::Geode(); 00187 00188 // Set up geometry for the HUD and add it to the HUD 00189 osg::ref_ptr< osg::Geometry > HUDBackgroundGeometry = new osg::Geometry(); 00190 00191 osg::ref_ptr< osg::Vec3Array > HUDBackgroundVertices = new osg::Vec3Array; 00192 HUDBackgroundVertices->push_back( osg::Vec3( 0, 0, -1 ) ); 00193 HUDBackgroundVertices->push_back( osg::Vec3( 1, 0, -1 ) ); 00194 HUDBackgroundVertices->push_back( osg::Vec3( 1, 1, -1 ) ); 00195 HUDBackgroundVertices->push_back( osg::Vec3( 0, 1, -1 ) ); 00196 00197 osg::ref_ptr< osg::Vec3Array > HUDBackgroundTex = new osg::Vec3Array; 00198 HUDBackgroundTex->push_back( osg::Vec3( 0, 0, 0 ) ); 00199 HUDBackgroundTex->push_back( osg::Vec3( 1, 0, 0 ) ); 00200 HUDBackgroundTex->push_back( osg::Vec3( 1, 1, 0 ) ); 00201 HUDBackgroundTex->push_back( osg::Vec3( 0, 1, 0 ) ); 00202 00203 osg::ref_ptr< osg::DrawElementsUInt > HUDBackgroundIndices = new osg::DrawElementsUInt( osg::PrimitiveSet::POLYGON, 0 ); 00204 HUDBackgroundIndices->push_back( 0 ); 00205 HUDBackgroundIndices->push_back( 1 ); 00206 HUDBackgroundIndices->push_back( 2 ); 00207 HUDBackgroundIndices->push_back( 3 ); 00208 00209 osg::ref_ptr< osg::Vec4Array > HUDcolors = new osg::Vec4Array; 00210 HUDcolors->push_back( osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) ); 00211 00212 osg::ref_ptr< osg::Vec3Array > HUDnormals = new osg::Vec3Array; 00213 HUDnormals->push_back( osg::Vec3( 0.0f, 0.0f, 1.0f ) ); 00214 HUDBackgroundGeometry->setNormalArray( HUDnormals ); 00215 HUDBackgroundGeometry->setNormalBinding( osg::Geometry::BIND_OVERALL ); 00216 HUDBackgroundGeometry->addPrimitiveSet( HUDBackgroundIndices ); 00217 HUDBackgroundGeometry->setVertexArray( HUDBackgroundVertices ); 00218 HUDBackgroundGeometry->setColorArray( HUDcolors ); 00219 HUDBackgroundGeometry->setTexCoordArray( 0, HUDBackgroundTex ); 00220 HUDBackgroundGeometry->setColorBinding( osg::Geometry::BIND_OVERALL ); 00221 00222 geode->addDrawable( HUDBackgroundGeometry ); 00223 00224 // Create and set up a state set using the texture from above 00225 osg::StateSet* state = geode->getOrCreateStateSet(); 00226 state->setTextureAttributeAndModes( 0, texture, osg::StateAttribute::ON ); 00227 state->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF ); 00228 state->setMode( GL_LIGHTING, osg::StateAttribute::PROTECTED ); 00229 state->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); 00230 00231 // enable texture coordinate manipulation via texture matrices 00232 m_texMat = new osg::TexMat; 00233 m_texMat->setMatrix( osg::Matrixd::identity() ); 00234 state->setTextureAttributeAndModes( 0, m_texMat, osg::StateAttribute::ON ); 00235 00236 // This disables colorblending of the texture with the underlying quad 00237 // osg::TexEnv* decalState = new osg::TexEnv(); 00238 // decalState->setMode( osg::TexEnv::DECAL ); 00239 // state->setTextureAttribute( 0, decalState, osg::StateAttribute::ON ); 00240 00241 // en/disable blending 00242 if( !transparency ) 00243 { 00244 state->setMode( GL_BLEND, osg::StateAttribute::PROTECTED ); 00245 state->setMode( GL_BLEND, osg::StateAttribute::OFF ); 00246 } 00247 else 00248 { 00249 state->setMode( GL_BLEND, osg::StateAttribute::PROTECTED ); 00250 state->setMode( GL_BLEND, osg::StateAttribute::ON ); 00251 state->setRenderingHint( osg::StateSet::TRANSPARENT_BIN ); 00252 } 00253 00254 // add the geode 00255 addChild( geode ); 00256 00257 ////////////////////////////////////////////////// 00258 // Text 00259 osg::ref_ptr< osg::Geode > textGeode = new osg::Geode(); 00260 state = textGeode->getOrCreateStateSet(); 00261 state->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF ); 00262 addChild( textGeode ); 00263 osgText::Text* label = new osgText::Text(); 00264 label->setFont( WPathHelper::getAllFonts().Default.file_string() ); 00265 label->setBackdropType( osgText::Text::OUTLINE ); 00266 label->setCharacterSize( 15 ); 00267 label->setText( m_name ); 00268 label->setAxisAlignment( osgText::Text::SCREEN ); 00269 label->setPosition( osg::Vec3( 0.01, 0.01, -1.0 ) ); 00270 label->setColor( osg::Vec4( 1.0, 1.0, 1.0, 1.0 ) ); 00271 textGeode->addDrawable( label ); 00272 } 00273 00274 WGETextureHud::WGETextureHudEntry::~WGETextureHudEntry() 00275 { 00276 // cleanup 00277 } 00278 00279 unsigned int WGETextureHud::WGETextureHudEntry::getRealWidth() const 00280 { 00281 return m_texture->getTextureWidth(); 00282 } 00283 00284 unsigned int WGETextureHud::WGETextureHudEntry::getRealHeight() const 00285 { 00286 return m_texture->getTextureHeight(); 00287 } 00288 00289 osg::ref_ptr< osg::TexMat > WGETextureHud::WGETextureHudEntry::getTextureMatrix() const 00290 { 00291 return m_texMat; 00292 } 00293 00294 std::string WGETextureHud::WGETextureHudEntry::getName() const 00295 { 00296 return m_name; 00297 } 00298 00299 unsigned int WGETextureHud::getMaxElementWidth() const 00300 { 00301 return m_maxElementWidth; 00302 } 00303 00304 void WGETextureHud::setMaxElementWidth( unsigned int width ) 00305 { 00306 m_maxElementWidth = width; 00307 } 00308 00309 osg::ref_ptr< osg::Texture2D > WGETextureHud::WGETextureHudEntry::getTexture() const 00310 { 00311 return m_texture; 00312 } 00313 00314 size_t WGETextureHud::getRenderBin() const 00315 { 00316 return m_renderBin; 00317 } 00318