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