OpenWalnut  1.4.0
WGEUtils.cpp
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 <algorithm>
00026 #include <vector>
00027 
00028 #include <osg/Array>
00029 #include <osg/MatrixTransform>
00030 
00031 #include "../common/math/linearAlgebra/WPosition.h"
00032 #include "core/common/WLogger.h"
00033 
00034 #include "WGETexture.h"
00035 #include "shaders/WGEShader.h"
00036 #include "WGEGeodeUtils.h"
00037 
00038 #include "WGEUtils.h"
00039 
00040 osg::ref_ptr< osg::Vec3Array > wge::osgVec3Array( const std::vector< WPosition >& posArray )
00041 {
00042     osg::ref_ptr< osg::Vec3Array > result = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
00043     result->reserve( posArray.size() );
00044     std::vector< WPosition >::const_iterator cit;
00045     for( cit = posArray.begin(); cit != posArray.end(); ++cit )
00046     {
00047         result->push_back( *cit );
00048     }
00049     return result;
00050 }
00051 
00052 osg::Vec3 wge::unprojectFromScreen( const osg::Vec3 screen, osg::ref_ptr< WGECamera > camera )
00053 {
00054     return screen * osg::Matrix::inverse( camera->getViewMatrix() * camera->getProjectionMatrix() * camera->getViewport()->computeWindowMatrix() );
00055 }
00056 
00057 osg::Vec4 wge::unprojectFromScreen( const osg::Vec4 screen, osg::ref_ptr< WGECamera > camera )
00058 {
00059     return screen * osg::Matrix::inverse( camera->getViewMatrix() * camera->getProjectionMatrix() * camera->getViewport()->computeWindowMatrix() );
00060 }
00061 
00062 WColor wge::createColorFromIndex( int index )
00063 {
00064     float r = 0.0;
00065     float g = 0.0;
00066     float b = 0.0;
00067     float mult = 1.0;
00068 
00069     if( index == 0 )
00070     {
00071         return WColor( 0.0, 0.0, 0.0, 1.0 );
00072     }
00073 
00074     if( ( index & 1 ) == 1 )
00075     {
00076         b = 1.0;
00077     }
00078     if( ( index & 2 ) == 2 )
00079     {
00080         g = 1.0;
00081     }
00082     if( ( index & 4 ) == 4 )
00083     {
00084         r = 1.0;
00085     }
00086     if( ( index & 8 ) == 8 )
00087     {
00088         mult -= 0.15;
00089         if( r < 1.0 && g < 1.0 && b < 1.0 )
00090         {
00091             r = 1.0;
00092             g = 1.0;
00093         }
00094     }
00095     if( ( index & 16 ) == 16 )
00096     {
00097         mult -= 0.15;
00098         if( r < 1.0 && g < 1.0 && b < 1.0 )
00099         {
00100             b = 1.0;
00101             g = 1.0;
00102         }
00103     }
00104     if( ( index & 32 ) == 32 )
00105     {
00106         mult -= 0.15;
00107         if( r < 1.0 && g < 1.0 && b < 1.0 )
00108         {
00109             r = 1.0;
00110             b = 1.0;
00111         }
00112     }
00113     if( ( index & 64 ) == 64 )
00114     {
00115         mult -= 0.15;
00116         if( r < 1.0 && g < 1.0 && b < 1.0 )
00117         {
00118             g = 1.0;
00119         }
00120     }
00121     if( ( index & 128 ) == 128 )
00122     {
00123         mult -= 0.15;
00124         if( r < 1.0 && g < 1.0 && b < 1.0 )
00125         {
00126             r = 1.0;
00127         }
00128     }
00129     r *= mult;
00130     g *= mult;
00131     b *= mult;
00132 
00133     return WColor( r, g, b, 1.0 );
00134 }
00135 
00136 WColor wge::createColorFromHSV( int h, float s, float v )
00137 {
00138     h = h % 360;
00139 
00140     int hi = h / 60;
00141     float f =  ( static_cast<float>( h ) / 60.0 ) - hi;
00142 
00143     float p = v * ( 1.0 - s );
00144     float q = v * ( 1.0 - s * f );
00145     float t = v * ( 1.0 - s * ( 1.0 - f ) );
00146 
00147     switch( hi )
00148     {
00149         case 0:
00150             return WColor( v, t, p, 1.0 );
00151         case 1:
00152             return WColor( q, v, p, 1.0 );
00153         case 2:
00154             return WColor( p, v, t, 1.0 );
00155         case 3:
00156             return WColor( p, q, v, 1.0 );
00157         case 4:
00158             return WColor( t, p, v, 1.0 );
00159         case 5:
00160             return WColor( v, p, q, 1.0 );
00161         case 6:
00162             return WColor( v, t, p, 1.0 );
00163         default:
00164             return WColor( v, t, p, 1.0 );
00165     }
00166 }
00167 
00168 WColor wge::getNthHSVColor( int n )
00169 {
00170     int h = 0;
00171     float s = 1.0;
00172     float v = 1.0;
00173 
00174     if( ( n & 1 ) == 1 )
00175     {
00176         h += 180;
00177     }
00178     if( ( n & 2 ) == 2 )
00179     {
00180         h += 90;
00181     }
00182     if( ( n & 4 ) == 4 )
00183     {
00184         h += 45;
00185     }
00186     if( ( n & 8 ) == 8 )
00187     {
00188         h += 202;
00189         h = h % 360;
00190     }
00191     if( ( n & 16 ) == 16 )
00192     {
00193         v -= .25;
00194     }
00195     if( ( n & 32 ) == 32 )
00196     {
00197         s -= .25;
00198     }
00199     if( ( n & 64 ) == 64 )
00200     {
00201         v -= .25;
00202     }
00203     if( ( n & 128 ) == 128 )
00204     {
00205         s -= 0.25;
00206     }
00207     if( ( n & 256 ) == 256 )
00208     {
00209         v -= 0.25;
00210     }
00211 
00212     return createColorFromHSV( h, s, v );
00213 }
00214 
00215 void wge::enableTransparency( osg::ref_ptr< osg::Node > node )
00216 {
00217     osg::StateSet* state = node->getOrCreateStateSet();
00218 
00219     // NOTE: this does not en/disable blending. This is always on.
00220     state->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
00221 
00222     // Enable depth test so that an opaque polygon will occlude a transparent one behind it.
00223     state->setMode( GL_DEPTH_TEST, osg::StateAttribute::ON );
00224 
00225     // Conversely, disable writing to depth buffer so that a transparent polygon will allow polygons behind it to shine through.
00226     // OSG renders transparent polygons after opaque ones.
00227     // NOTE: USEFUL?
00228     // osg::Depth* depth = new osg::Depth;
00229     // depth->setWriteMask( false );
00230     // state->setAttributeAndModes( depth, osg::StateAttribute::ON );
00231 
00232     // blending. Without this, setting alpha does not cause anything
00233     state->setMode( GL_BLEND, osg::StateAttribute::ON );
00234 }
00235 
00236 osg::ref_ptr< osg::Node > wge::generateCullProxy( const WBoundingBox& bbox )
00237 {
00238     // Create some cube. Color is uninteresting.
00239     osg::ref_ptr< osg::Node > cullProxy = wge::generateSolidBoundingBoxNode( bbox, defaultColor::WHITE );
00240 
00241     // Avoid picking the proxy
00242     cullProxy->asTransform()->getChild( 0 )->setName( "_Cull Proxy Cube" ); // Be aware that this name is used in the pick handler.
00243                                                                            // because of the underscore in front it won't be picked
00244 
00245     // Add a shader which visually removes the proxy cube.
00246     osg::ref_ptr< WGEShader > cullProxyShader = new WGEShader( "WGECullProxyShader" );
00247     cullProxyShader->apply( cullProxy );
00248 
00249     return cullProxy;
00250 }
00251 
00252 /**
00253  * Update matrix transform according to bounds of some node
00254  */
00255 class BoundsCallback: public osg::NodeCallback
00256 {
00257 public:
00258     /**
00259      * Create and init.
00260      *
00261      * \param node the node
00262      */
00263     explicit BoundsCallback( osg::ref_ptr< osg::Node > node ):
00264         m_node( node )
00265     {
00266     }
00267 
00268     /**
00269      *  Callback method called by the NodeVisitor when visiting a node
00270      *
00271      * \param node the node handled
00272      * \param nv the visitor
00273      */
00274     virtual void operator()( osg::Node* node, osg::NodeVisitor* nv )
00275     {
00276         osg::MatrixTransform* m = static_cast< osg::MatrixTransform* >( node );
00277 
00278         osg::BoundingSphere s = m_node->getBound();
00279 
00280         // this will not be the bounding box which is embedded into the sphere as we do not know how the sphere was calculated. Create a BBox
00281         // around the sphere.
00282         osg::Matrix matrix = osg::Matrix::scale( osg::Vec3d( s.radius(), s.radius(), s.radius() ) ) * osg::Matrix::translate( s.center() );
00283 
00284         m->setMatrix( matrix );
00285 
00286         traverse( node, nv );
00287     }
00288 private:
00289     /**
00290      * The node to use as template for the resulting bbox
00291      */
00292     osg::ref_ptr< osg::Node > m_node;
00293 };
00294 
00295 osg::ref_ptr< osg::Node > wge::generateDynamicCullProxy( osg::ref_ptr< osg::Node > node )
00296 {
00297     // create a unit size proxy cube
00298     osg::ref_ptr< osg::Node > proxyUnitCube = generateCullProxy(
00299         WBoundingBox( WBoundingBox::vec_type( -1.0, -1.0, -1.0 ), WBoundingBox::vec_type( 1.0, 1.0, 1.0 ) )
00300     );
00301 
00302     // setComputeBoundingSphereCallback does not work -> we need a transform node which scales the cube using an update callback
00303     osg::ref_ptr< osg::MatrixTransform > mt( new osg::MatrixTransform() );
00304 
00305     mt->setUpdateCallback( new BoundsCallback( node ) );
00306     mt->addChild( proxyUnitCube );
00307 
00308     return mt;
00309 }
00310