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 <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