OpenWalnut  1.4.0
WGEGridNode.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 <sstream>
00026 #include <string>
00027 
00028 #include <osg/LineWidth>
00029 
00030 #include "../callbacks/WGEFunctorCallback.h"
00031 #include "../WGEGeodeUtils.h"
00032 #include "WGEGridNode.h"
00033 
00034 WGEGridNode::WGEGridNode( WGridRegular3D::ConstSPtr grid ):
00035     m_boundaryGeode( new osg::Geode() ),
00036     m_innerGridGeode( new osg::Geode() ),
00037     m_labelGeode( new osg::Geode() ),
00038     m_gridUpdate( true ),
00039     m_gridGeometryUpdate( true ),
00040     m_showLabels( true ),
00041     m_bbColor( WColor( 0.3, 0.3, 0.3, 1.0 ) ),
00042     m_gridColor( WColor( 0.1, 0.1, 0.1, 1.0 ) )
00043 {
00044     m_grid.getWriteTicket()->get() = grid;
00045 
00046     // init the boundary geometry
00047     m_boundaryGeode->addDrawable( wge::createUnitCubeAsLines( m_bbColor ) );
00048 
00049     // init labels
00050     // Therefore: create prototype
00051     WGELabel::SPtr label = new WGELabel();
00052     label->setAlignment( osgText::Text::CENTER_TOP );
00053     label->setColor( osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) );
00054 
00055     // add several copies and set position accordingly
00056 
00057     // Front face ( z = 0 )
00058     // bottom left
00059     label->setPosition( osg::Vec3( 0.0, 0.0, 0.0 ) );
00060     label->setCharacterSize( 6 );
00061     m_labelGeode->addDrawable( label );
00062     m_borderLabels[0] = label;
00063 
00064     // bottom right
00065     label = new WGELabel( *label );
00066     label->setPosition( osg::Vec3( 1.0, 0.0, 0.0 ) );
00067     m_labelGeode->addDrawable( label );
00068     m_borderLabels[1] = label;
00069 
00070     // top right
00071     label = new WGELabel( *label );
00072     label->setPosition( osg::Vec3( 1.0, 1.0, 0.0 ) );
00073     m_labelGeode->addDrawable( label );
00074     m_borderLabels[2] = label;
00075 
00076     // top left
00077     label = new WGELabel( *label );
00078     label->setPosition( osg::Vec3( 0.0, 1.0, 0.0 ) );
00079     m_labelGeode->addDrawable( label );
00080     m_borderLabels[3] = label;
00081 
00082     // Back face ( z = 1 )
00083     // bottom left
00084     label = new WGELabel( *label );
00085     label->setPosition( osg::Vec3( 0.0, 0.0, 1.0 ) );
00086     m_labelGeode->addDrawable( label );
00087     m_borderLabels[4] = label;
00088 
00089     // bottom right
00090     label = new WGELabel( *label );
00091     label->setPosition( osg::Vec3( 1.0, 0.0, 1.0 ) );
00092     m_labelGeode->addDrawable( label );
00093     m_borderLabels[5] = label;
00094 
00095     // top right
00096     label = new WGELabel( *label );
00097     label->setPosition( osg::Vec3( 1.0, 1.0, 1.0 ) );
00098     m_labelGeode->addDrawable( label );
00099     m_borderLabels[6] = label;
00100 
00101     // top left
00102     label = new WGELabel( *label );
00103     label->setPosition( osg::Vec3( 0.0, 1.0, 1.0 ) );
00104     m_labelGeode->addDrawable( label );
00105     m_borderLabels[7] = label;
00106 
00107     // add the others too
00108     addChild( m_boundaryGeode );
00109     addChild( m_innerGridGeode );
00110     addChild( m_labelGeode );
00111 
00112     m_boundaryGeode->getOrCreateStateSet()->setAttributeAndModes( new osg::LineWidth( 4.0 ), osg::StateAttribute::ON );
00113 
00114     addUpdateCallback( new WGEFunctorCallback< osg::Node >( boost::bind( &WGEGridNode::callback, this, _1 ) ) );
00115 
00116     // no blending
00117     getOrCreateStateSet()->setMode( GL_BLEND, osg::StateAttribute::OFF );
00118     // disable light for this node
00119     getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
00120 }
00121 
00122 WGEGridNode::~WGEGridNode()
00123 {
00124     // cleanup
00125 }
00126 
00127 void WGEGridNode::setGrid( WGridRegular3D::ConstSPtr grid )
00128 {
00129     m_grid.getWriteTicket()->get() = grid;
00130     m_gridUpdate = true;
00131     m_gridGeometryUpdate = true;
00132 }
00133 
00134 WGridRegular3D::ConstSPtr WGEGridNode::getGrid() const
00135 {
00136     return m_grid.getReadTicket()->get();
00137 }
00138 
00139 bool WGEGridNode::getEnableLabels() const
00140 {
00141     return m_showLabels;
00142 }
00143 
00144 void WGEGridNode::setEnableLabels( bool enable )
00145 {
00146     m_showLabels = enable;
00147     m_gridUpdate = true;
00148 }
00149 
00150 bool WGEGridNode::getEnableBBox() const
00151 {
00152     return m_showBBox;
00153 }
00154 
00155 void WGEGridNode::setEnableBBox( bool enable )
00156 {
00157     m_showBBox = enable;
00158     m_gridUpdate = true;
00159 }
00160 
00161 bool WGEGridNode::getEnableGrid() const
00162 {
00163     return m_showGrid;
00164 }
00165 
00166 void WGEGridNode::setEnableGrid( bool enable )
00167 {
00168     m_showGrid = enable;
00169     m_gridUpdate = true;
00170 }
00171 
00172 const WColor& WGEGridNode::getBBoxColor() const
00173 {
00174     return m_bbColor;
00175 }
00176 
00177 void WGEGridNode::setBBoxColor( const WColor& color )
00178 {
00179     m_bbColor = color;
00180     m_gridUpdate = true;
00181 }
00182 
00183 const WColor& WGEGridNode::getGridColor() const
00184 {
00185     return m_gridColor;
00186 }
00187 
00188 void WGEGridNode::setGridColor( const WColor& color )
00189 {
00190     m_gridColor = color;
00191     m_gridUpdate = true;
00192 }
00193 
00194 /**
00195  * Simply converts the vector to an string.
00196  *
00197  * \param vec the vector
00198  *
00199  * \return string representation
00200  */
00201 std::string vec2str( osg::Vec3 vec )
00202 {
00203     std::ostringstream os;
00204     os.precision( 5 );
00205     os << "(" << vec[0] << "," << vec[1] << "," << vec[2] << ")";
00206     return os.str();
00207 }
00208 
00209 void WGEGridNode::callback( osg::Node* /*node*/ )
00210 {
00211     if( m_gridUpdate )
00212     {
00213         // grab the grid
00214         WGridRegular3D::ConstSPtr grid = m_grid.getReadTicket()->get();
00215 
00216         // apply the grid transformation
00217         osg::Matrix m = osg::Matrix::scale( grid->getNbCoordsX() - 1, grid->getNbCoordsY() - 1, grid->getNbCoordsZ() - 1 ) *
00218                         static_cast< osg::Matrixd >( static_cast< WMatrix4d >( grid->getTransform() ) );
00219         setMatrix( m );
00220 
00221         // set the labels correspondingly
00222         for( size_t i = 0; i < 8; ++i )
00223         {
00224             m_borderLabels[i]->setText( vec2str( m_borderLabels[i]->getPosition() * m ) );
00225         }
00226 
00227         // set node mask of labels, bbox and grid
00228         m_labelGeode->setNodeMask( 0xFFFFFFFF * m_showLabels );
00229         m_boundaryGeode->setNodeMask( 0xFFFFFFFF * m_showBBox );
00230         m_innerGridGeode->setNodeMask( 0xFFFFFFFF * m_showGrid );
00231 
00232         // color
00233         osg::ref_ptr< osg::Vec4Array > colors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
00234         colors->push_back( m_bbColor );
00235         m_boundaryGeode->getDrawable( 0 )->asGeometry()->setColorArray( colors );
00236         m_boundaryGeode->getDrawable( 0 )->asGeometry()->setColorBinding( osg::Geometry::BIND_OVERALL );
00237 
00238         // set color for grid too
00239         if( m_innerGridGeode->getNumDrawables() )
00240         {
00241             osg::ref_ptr< osg::Vec4Array > colors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
00242             colors->push_back( m_gridColor );
00243             m_innerGridGeode->getDrawable( 0 )->asGeometry()->setColorArray( colors );
00244             m_innerGridGeode->getDrawable( 0 )->asGeometry()->setColorBinding( osg::Geometry::BIND_OVERALL );
00245         }
00246 
00247         m_gridUpdate = false;
00248     }
00249 
00250     // recreate grid?
00251     if( m_gridGeometryUpdate && m_showGrid )
00252     {
00253         // grab the grid
00254         WGridRegular3D::ConstSPtr grid = m_grid.getReadTicket()->get();
00255 
00256         osg::Geometry* gridGeometry = new osg::Geometry();
00257         osg::ref_ptr< osg::Vec3Array > vertArray = new osg::Vec3Array( grid->size() );
00258 
00259         osg::DrawElementsUInt* gridElement = new osg::DrawElementsUInt( osg::PrimitiveSet::LINES, 0 );
00260         gridElement->reserve( grid->size() * 2 );
00261 
00262         size_t sx = grid->getNbCoordsX();
00263         size_t sy = grid->getNbCoordsY();
00264         size_t sz = grid->getNbCoordsZ();
00265         for( unsigned int vertIdX = 0; vertIdX < sx; ++vertIdX )
00266         {
00267             for( unsigned int vertIdY = 0; vertIdY < sy; ++vertIdY )
00268             {
00269                 for( unsigned int vertIdZ = 0; vertIdZ < sz; ++vertIdZ )
00270                 {
00271                     size_t id = vertIdX + vertIdY * sx + vertIdZ * sx * sy;
00272 
00273                     ( *vertArray )[id][0] = static_cast< float >( vertIdX ) / static_cast< float >( sx - 1 );
00274                     ( *vertArray )[id][1] = static_cast< float >( vertIdY ) / static_cast< float >( sy - 1 );
00275                     ( *vertArray )[id][2] = static_cast< float >( vertIdZ ) / static_cast< float >( sz - 1 );
00276 
00277                     if( vertIdX < sx - 1 )
00278                     {
00279                         gridElement->push_back( id );
00280                         gridElement->push_back( id + 1 );
00281                     }
00282 
00283                     if( vertIdY < sy - 1 )
00284                     {
00285                         gridElement->push_back( id );
00286                         gridElement->push_back( id + sx );
00287                     }
00288 
00289                     if( vertIdZ < sz - 1 )
00290                     {
00291                         gridElement->push_back( id );
00292                         gridElement->push_back( id + sx * sy );
00293                     }
00294                 }
00295             }
00296         }
00297 
00298         // done. Add it
00299         gridGeometry->setVertexArray( vertArray );
00300         gridGeometry->addPrimitiveSet( gridElement );
00301 
00302         osg::ref_ptr< osg::Vec4Array > colors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
00303         // finally, the colors
00304         colors->push_back( m_gridColor );
00305         gridGeometry->setColorArray( colors );
00306         gridGeometry->setColorBinding( osg::Geometry::BIND_OVERALL );
00307 
00308         if( m_innerGridGeode->getNumDrawables() )
00309         {
00310             m_innerGridGeode->setDrawable( 0, gridGeometry );
00311         }
00312         else
00313         {
00314             m_innerGridGeode->addDrawable( gridGeometry );
00315         }
00316 
00317         // we create a unit cube here as the transformation matrix already contains the proper scaling.
00318         m_gridGeometryUpdate = false;
00319     }
00320 }
00321