OpenWalnut  1.4.0
WGEGeodeUtils.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 <map>
00026 #include <string>
00027 #include <vector>
00028 
00029 #include <osg/Array>
00030 #include <osg/Geode>
00031 #include <osg/Geometry>
00032 #include <osg/LightModel>
00033 #include <osg/LineWidth>
00034 #include <osg/Material>
00035 #include <osg/MatrixTransform>
00036 #include <osg/ShapeDrawable>
00037 #include <osg/Vec3>
00038 
00039 #include "../common/math/WMath.h"
00040 #include "../common/WPathHelper.h"
00041 #include "../common/WStringUtils.h"
00042 
00043 #include "shaders/WGEShader.h"
00044 #include "WGEGeodeUtils.h"
00045 #include "WGEGeometryUtils.h"
00046 #include "WGEGroupNode.h"
00047 #include "WGESubdividedPlane.h"
00048 #include "WGEUtils.h"
00049 #include "widgets/labeling/WGELabel.h"
00050 
00051 osg::ref_ptr< osg::Geode > wge::generateBoundingBoxGeode( const WBoundingBox& bb, const WColor& color )
00052 {
00053     const WBoundingBox::vec_type& pos1 = bb.getMin();
00054     const WBoundingBox::vec_type& pos2 = bb.getMax();
00055 
00056     WAssert( pos1[0] <= pos2[0] && pos1[1] <= pos2[1] && pos1[2] <= pos2[2], "pos1 does not seem to be the frontLowerLeft corner of the BB!" );
00057     using osg::ref_ptr;
00058     ref_ptr< osg::Vec3Array > vertices = ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
00059     ref_ptr< osg::Vec4Array > colors = ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
00060     ref_ptr< osg::Geometry > geometry = ref_ptr< osg::Geometry >( new osg::Geometry );
00061 
00062     vertices->push_back( osg::Vec3( pos1[0], pos1[1], pos1[2] ) );
00063     vertices->push_back( osg::Vec3( pos2[0], pos1[1], pos1[2] ) );
00064     vertices->push_back( osg::Vec3( pos2[0], pos2[1], pos1[2] ) );
00065     vertices->push_back( osg::Vec3( pos1[0], pos2[1], pos1[2] ) );
00066     vertices->push_back( osg::Vec3( pos1[0], pos1[1], pos1[2] ) );
00067     vertices->push_back( osg::Vec3( pos1[0], pos1[1], pos2[2] ) );
00068     vertices->push_back( osg::Vec3( pos2[0], pos1[1], pos2[2] ) );
00069     vertices->push_back( osg::Vec3( pos2[0], pos2[1], pos2[2] ) );
00070     vertices->push_back( osg::Vec3( pos1[0], pos2[1], pos2[2] ) );
00071     vertices->push_back( osg::Vec3( pos1[0], pos1[1], pos2[2] ) );
00072 
00073     geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_STRIP, 0, vertices->size() ) );
00074 
00075     vertices->push_back( osg::Vec3( pos1[0], pos2[1], pos1[2] ) );
00076     vertices->push_back( osg::Vec3( pos1[0], pos2[1], pos2[2] ) );
00077     vertices->push_back( osg::Vec3( pos2[0], pos2[1], pos1[2] ) );
00078     vertices->push_back( osg::Vec3( pos2[0], pos2[1], pos2[2] ) );
00079     vertices->push_back( osg::Vec3( pos2[0], pos1[1], pos1[2] ) );
00080     vertices->push_back( osg::Vec3( pos2[0], pos1[1], pos2[2] ) );
00081 
00082     geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINES, vertices->size() - 6, 6 ) );
00083 
00084     geometry->setVertexArray( vertices );
00085     colors->push_back( color );
00086     geometry->setColorArray( colors );
00087     geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
00088     osg::ref_ptr< osg::Geode > geode = osg::ref_ptr< osg::Geode >( new osg::Geode );
00089     geode->addDrawable( geometry );
00090 
00091     // disable light for this geode as lines can't be lit properly
00092     osg::StateSet* state = geode->getOrCreateStateSet();
00093     state->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
00094 
00095     return geode;
00096 }
00097 
00098 void wge::createCube( osg::ref_ptr< osg::Geometry > geometry, const WPosition& position, const WPosition& size, const WColor& color )
00099 {
00100     // the geometry might be empty: ensure we have arrays properly set. If they cannot be casted, they get overwritten later. Users own fault if
00101     // he does not read the doc
00102     osg::ref_ptr< osg::Vec3Array > vertices = dynamic_cast< osg::Vec3Array* >( geometry->getVertexArray() );
00103     osg::ref_ptr< osg::Vec3Array > tex = dynamic_cast< osg::Vec3Array* >( geometry->getTexCoordArray( 0 ) );
00104     osg::ref_ptr< osg::Vec3Array > normals = dynamic_cast< osg::Vec3Array* >( geometry->getNormalArray() );
00105     osg::ref_ptr< osg::Vec4Array > colors = dynamic_cast< osg::Vec4Array* >( geometry->getColorArray() );
00106 
00107     // get some mem if not already done
00108     if( !vertices )
00109     {
00110         vertices = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
00111     }
00112     if( !tex )
00113     {
00114         tex = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
00115     }
00116     if( !normals )
00117     {
00118         normals = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
00119     }
00120     if( !colors )
00121     {
00122         colors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
00123     }
00124 
00125     size_t first = vertices->getNumElements();
00126 
00127     // NOTE: as the OSG 3.2 does not allow binding normals/colors and other arrays on a per-primitive basis, we bind the normals per vertex
00128     // This means we add four normals per face
00129 
00130     // front face
00131     vertices->push_back( position + WPosition( 0.0,      0.0,      0.0 ) );
00132     vertices->push_back( position + WPosition( size.x(), 0.0,      0.0 ) );
00133     vertices->push_back( position + WPosition( size.x(), size.y(), 0.0 ) );
00134     vertices->push_back( position + WPosition( 0.0,      size.y(), 0.0 ) );
00135     tex->push_back( osg::Vec3( 0.0, 0.0, 0.0 ) );
00136     tex->push_back( osg::Vec3( 1.0, 0.0, 0.0 ) );
00137     tex->push_back( osg::Vec3( 1.0, 1.0, 0.0 ) );
00138     tex->push_back( osg::Vec3( 0.0, 1.0, 0.0 ) );
00139     normals->push_back( osg::Vec3( 0.0, 0.0, -1.0 ) );
00140     normals->push_back( osg::Vec3( 0.0, 0.0, -1.0 ) );
00141     normals->push_back( osg::Vec3( 0.0, 0.0, -1.0 ) );
00142     normals->push_back( osg::Vec3( 0.0, 0.0, -1.0 ) );
00143 
00144     // back face
00145     vertices->push_back( position + WPosition( 0.0,      0.0,      size.z() ) );
00146     vertices->push_back( position + WPosition( size.x(), 0.0,      size.z() ) );
00147     vertices->push_back( position + WPosition( size.x(), size.y(), size.z() ) );
00148     vertices->push_back( position + WPosition( 0.0,      size.y(), size.z() ) );
00149     tex->push_back( osg::Vec3( 0.0, 0.0, 1.0 ) );
00150     tex->push_back( osg::Vec3( 1.0, 0.0, 1.0 ) );
00151     tex->push_back( osg::Vec3( 1.0, 1.0, 1.0 ) );
00152     tex->push_back( osg::Vec3( 0.0, 1.0, 1.0 ) );
00153     normals->push_back( osg::Vec3( 0.0, 0.0, 1.0 ) );
00154     normals->push_back( osg::Vec3( 0.0, 0.0, 1.0 ) );
00155     normals->push_back( osg::Vec3( 0.0, 0.0, 1.0 ) );
00156     normals->push_back( osg::Vec3( 0.0, 0.0, 1.0 ) );
00157 
00158     // left
00159     vertices->push_back( position + WPosition( 0.0, 0.0,      0.0 ) );
00160     vertices->push_back( position + WPosition( 0.0, size.y(), 0.0 ) );
00161     vertices->push_back( position + WPosition( 0.0, size.y(), size.z() ) );
00162     vertices->push_back( position + WPosition( 0.0, 0.0,      size.z() ) );
00163     tex->push_back( osg::Vec3( 0.0, 0.0, 0.0 ) );
00164     tex->push_back( osg::Vec3( 0.0, 1.0, 0.0 ) );
00165     tex->push_back( osg::Vec3( 0.0, 1.0, 1.0 ) );
00166     tex->push_back( osg::Vec3( 0.0, 0.0, 1.0 ) );
00167     normals->push_back( osg::Vec3( -1.0, 0.0, 0.0 ) );
00168     normals->push_back( osg::Vec3( -1.0, 0.0, 0.0 ) );
00169     normals->push_back( osg::Vec3( -1.0, 0.0, 0.0 ) );
00170     normals->push_back( osg::Vec3( -1.0, 0.0, 0.0 ) );
00171 
00172     // right
00173     vertices->push_back( position + WPosition( size.x(), 0.0,      0.0 ) );
00174     vertices->push_back( position + WPosition( size.x(), size.y(), 0.0 ) );
00175     vertices->push_back( position + WPosition( size.x(), size.y(), size.z() ) );
00176     vertices->push_back( position + WPosition( size.x(), 0.0,      size.z() ) );
00177     tex->push_back( osg::Vec3( 1.0, 0.0, 0.0 ) );
00178     tex->push_back( osg::Vec3( 1.0, 1.0, 0.0 ) );
00179     tex->push_back( osg::Vec3( 1.0, 1.0, 1.0 ) );
00180     tex->push_back( osg::Vec3( 1.0, 0.0, 1.0 ) );
00181     normals->push_back( osg::Vec3( 1.0, 0.0, 0.0 ) );
00182     normals->push_back( osg::Vec3( 1.0, 0.0, 0.0 ) );
00183     normals->push_back( osg::Vec3( 1.0, 0.0, 0.0 ) );
00184     normals->push_back( osg::Vec3( 1.0, 0.0, 0.0 ) );
00185 
00186     // bottom
00187     vertices->push_back( position + WPosition( 0.0,      0.0, 0.0 ) );
00188     vertices->push_back( position + WPosition( size.x(), 0.0, 0.0 ) );
00189     vertices->push_back( position + WPosition( size.x(), 0.0, size.z() ) );
00190     vertices->push_back( position + WPosition( 0.0,      0.0, size.z() ) );
00191     tex->push_back( osg::Vec3( 0.0, 0.0, 0.0 ) );
00192     tex->push_back( osg::Vec3( 1.0, 0.0, 0.0 ) );
00193     tex->push_back( osg::Vec3( 1.0, 0.0, 1.0 ) );
00194     tex->push_back( osg::Vec3( 0.0, 0.0, 1.0 ) );
00195     normals->push_back( osg::Vec3( 0.0, -1.0, 0.0 ) );
00196     normals->push_back( osg::Vec3( 0.0, -1.0, 0.0 ) );
00197     normals->push_back( osg::Vec3( 0.0, -1.0, 0.0 ) );
00198     normals->push_back( osg::Vec3( 0.0, -1.0, 0.0 ) );
00199 
00200     // top
00201     vertices->push_back( position + WPosition( 0.0,      size.y(), 0.0 ) );
00202     vertices->push_back( position + WPosition( size.x(), size.y(), 0.0 ) );
00203     vertices->push_back( position + WPosition( size.x(), size.y(), size.z() ) );
00204     vertices->push_back( position + WPosition( 0.0,      size.y(), size.z() ) );
00205     tex->push_back( osg::Vec3( 0.0, 1.0, 0.0 ) );
00206     tex->push_back( osg::Vec3( 1.0, 1.0, 0.0 ) );
00207     tex->push_back( osg::Vec3( 1.0, 1.0, 1.0 ) );
00208     tex->push_back( osg::Vec3( 0.0, 1.0, 1.0 ) );
00209     normals->push_back( osg::Vec3( 0.0, 1.0, 0.0 ) );
00210     normals->push_back( osg::Vec3( 0.0, 1.0, 0.0 ) );
00211     normals->push_back( osg::Vec3( 0.0, 1.0, 0.0 ) );
00212     normals->push_back( osg::Vec3( 0.0, 1.0, 0.0 ) );
00213 
00214     // set it up and set arrays
00215     geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::QUADS, first, 6 * 4 ) ); // 6 faces, 4 vertices per face
00216     geometry->setVertexArray( vertices );
00217 
00218     // set 3D texture coordinates here.
00219     geometry->setTexCoordArray( 0, tex );
00220 
00221     // set normals
00222     geometry->setNormalArray( normals );
00223     geometry->setNormalBinding( osg::Geometry::BIND_PER_VERTEX );
00224 
00225     // finally, the colors
00226     colors->push_back( color );
00227     geometry->setColorArray( colors );
00228     geometry->setColorBinding( osg::Geometry::BIND_PER_PRIMITIVE_SET );
00229 }
00230 
00231 osg::ref_ptr< osg::Geometry > wge::createCube( const WPosition& position, const WPosition& size, const WColor& color )
00232 {
00233     // create the unit cube manually as the ShapeDrawable and osg::Box does not provide 3D texture coordinates
00234     osg::ref_ptr< osg::Geometry > cube = new osg::Geometry();
00235     createCube( cube, position, size, color );
00236     return cube;
00237 }
00238 
00239 osg::ref_ptr< osg::Geometry > wge::createUnitCube( const WColor& color )
00240 {
00241     // create the unit cube manually as the ShapeDrawable and osg::Box does not provide 3D texture coordinates
00242     return createCube( WPosition( 0.0, 0.0, 0.0 ), WPosition( 1.0, 1.0, 1.0 ), color );
00243 }
00244 
00245 osg::ref_ptr< osg::Geometry > wge::createUnitCubeAsLines( const WColor& color )
00246 {
00247     // create the unit cube manually as the ShapeDrawable and osg::Box does not provide 3D texture coordinates
00248     osg::ref_ptr< osg::Geometry > cube = new osg::Geometry();
00249     osg::ref_ptr< osg::Vec3Array > vertices = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
00250     osg::ref_ptr< osg::Vec4Array > colors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
00251 
00252     vertices->push_back( osg::Vec3( 0.0, 0.0, 0.0 ) );
00253     vertices->push_back( osg::Vec3( 1.0, 0.0, 0.0 ) );
00254     vertices->push_back( osg::Vec3( 1.0, 1.0, 0.0 ) );
00255     vertices->push_back( osg::Vec3( 0.0, 1.0, 0.0 ) );
00256     vertices->push_back( osg::Vec3( 0.0, 0.0, 0.0 ) );
00257     vertices->push_back( osg::Vec3( 0.0, 0.0, 1.0 ) );
00258     vertices->push_back( osg::Vec3( 1.0, 0.0, 1.0 ) );
00259     vertices->push_back( osg::Vec3( 1.0, 1.0, 1.0 ) );
00260     vertices->push_back( osg::Vec3( 0.0, 1.0, 1.0 ) );
00261     vertices->push_back( osg::Vec3( 0.0, 0.0, 1.0 ) );
00262 
00263     cube->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_STRIP, 0, vertices->size() ) );
00264 
00265     vertices->push_back( osg::Vec3( 0.0, 1.0, 0.0 ) );
00266     vertices->push_back( osg::Vec3( 0.0, 1.0, 1.0 ) );
00267     vertices->push_back( osg::Vec3( 1.0, 0.0, 0.0 ) );
00268     vertices->push_back( osg::Vec3( 1.0, 0.0, 1.0 ) );
00269     vertices->push_back( osg::Vec3( 1.0, 1.0, 0.0 ) );
00270     vertices->push_back( osg::Vec3( 1.0, 1.0, 1.0 ) );
00271 
00272     cube->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINES, vertices->size() - 6, 6 ) );
00273 
00274     // set it up and set arrays
00275     cube->setVertexArray( vertices );
00276 
00277     // set 3D texture coordinates here.
00278     cube->setTexCoordArray( 0, vertices );
00279 
00280     // finally, the colors
00281     colors->push_back( color );
00282     cube->setColorArray( colors );
00283     cube->setColorBinding( osg::Geometry::BIND_OVERALL );
00284 
00285     return cube;
00286 }
00287 
00288 osg::ref_ptr< osg::Node > wge::generateSolidBoundingBoxNode( const WBoundingBox& bb, const WColor& color, bool threeDTexCoords )
00289 {
00290     WAssert( bb.valid(), "Invalid bounding box!" );
00291 
00292     // create a uni cube
00293     osg::ref_ptr< osg::Geode > cube = new osg::Geode();
00294     cube->setName( "Solid Bounding Box" );
00295     if( threeDTexCoords )
00296     {
00297         cube->addDrawable( createUnitCube( color ) );
00298     }
00299     else
00300     {
00301         osg::ref_ptr< osg::ShapeDrawable > cubeDrawable = new osg::ShapeDrawable( new osg::Box( osg::Vec3( 0.5, 0.5, 0.5 ), 1.0 ) );
00302         cubeDrawable->setColor( color );
00303         cube->addDrawable( cubeDrawable );
00304     }
00305 
00306     // transform the cube to match the bbox
00307     osg::Matrixd transformM;
00308     osg::Matrixd scaleM;
00309     transformM.makeTranslate( bb.getMin() );
00310     scaleM.makeScale( bb.getMax() - bb.getMin() );
00311 
00312     // apply transformation to bbox
00313     osg::ref_ptr< osg::MatrixTransform > transform = new osg::MatrixTransform();
00314     transform->setMatrix( scaleM * transformM );
00315     transform->addChild( cube );
00316 
00317     // we do not need light
00318     osg::StateSet* state = cube->getOrCreateStateSet();
00319     state->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
00320 
00321     return transform;
00322 }
00323 
00324 osg::ref_ptr< osg::Geometry > wge::convertToOsgGeometry( WTriangleMesh::SPtr mesh,
00325                                                           const WColor& defaultColor,
00326                                                           bool includeNormals,
00327                                                           bool lighting,
00328                                                           bool useMeshColor )
00329 {
00330     osg::ref_ptr< osg::Geometry> geometry( new osg::Geometry );
00331     geometry->setVertexArray( mesh->getVertexArray() );
00332 
00333     osg::DrawElementsUInt* surfaceElement;
00334 
00335     surfaceElement = new osg::DrawElementsUInt( osg::PrimitiveSet::TRIANGLES, 0 );
00336 
00337     std::vector< size_t > tris = mesh->getTriangles();
00338     surfaceElement->reserve( tris.size() );
00339 
00340     for( unsigned int vertId = 0; vertId < tris.size(); ++vertId )
00341     {
00342         surfaceElement->push_back( tris[vertId] );
00343     }
00344     geometry->addPrimitiveSet( surfaceElement );
00345 
00346     // add the mesh colors
00347     if( mesh->getVertexColorArray() && useMeshColor )
00348     {
00349         geometry->setColorArray( mesh->getVertexColorArray() );
00350         geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
00351     }
00352     else
00353     {
00354         osg::ref_ptr< osg::Vec4Array > colors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
00355         colors->push_back( defaultColor );
00356         geometry->setColorArray( colors );
00357         geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
00358     }
00359 
00360     // ------------------------------------------------
00361     // normals
00362     if( includeNormals )
00363     {
00364         geometry->setNormalArray( mesh->getVertexNormalArray() );
00365         geometry->setNormalBinding( osg::Geometry::BIND_PER_VERTEX );
00366 
00367         if( lighting )
00368         {
00369             // if normals are specified, we also setup a default lighting.
00370             osg::StateSet* state = geometry->getOrCreateStateSet();
00371             osg::ref_ptr<osg::LightModel> lightModel = new osg::LightModel();
00372             lightModel->setTwoSided( true );
00373             state->setAttributeAndModes( lightModel.get(), osg::StateAttribute::ON );
00374             state->setMode( GL_BLEND, osg::StateAttribute::ON  );
00375             {
00376                 osg::ref_ptr< osg::Material > material = new osg::Material();
00377                 material->setDiffuse(   osg::Material::FRONT, osg::Vec4( 1.0, 1.0, 1.0, 1.0 ) );
00378                 material->setSpecular(  osg::Material::FRONT, osg::Vec4( 0.0, 0.0, 0.0, 1.0 ) );
00379                 material->setAmbient(   osg::Material::FRONT, osg::Vec4( 0.1, 0.1, 0.1, 1.0 ) );
00380                 material->setEmission(  osg::Material::FRONT, osg::Vec4( 0.0, 0.0, 0.0, 1.0 ) );
00381                 material->setShininess( osg::Material::FRONT, 25.0 );
00382                 state->setAttribute( material );
00383             }
00384         }
00385     }
00386 
00387     // enable VBO
00388     geometry->setUseDisplayList( false );
00389     geometry->setUseVertexBufferObjects( true );
00390 
00391     return geometry;
00392 }
00393 
00394 osg::ref_ptr< osg::Geometry > wge::convertToOsgGeometryFlatShaded( WTriangleMesh::SPtr mesh,
00395                                                                     const WColor& defaultColor,
00396                                                                     bool includeNormals,
00397                                                                     bool lighting,
00398                                                                     bool useMeshColor )
00399 {
00400     osg::DrawElementsUInt* surfaceElement;
00401     surfaceElement = new osg::DrawElementsUInt( osg::PrimitiveSet::TRIANGLES, 0 );
00402     std::vector< size_t > tris = mesh->getTriangles();
00403 
00404     osg::ref_ptr< osg::Geometry> geometry( new osg::Geometry );
00405     osg::ref_ptr< osg::Vec3Array > oldVertexArray( mesh->getVertexArray() );
00406     osg::ref_ptr< osg::Vec3Array > newVertexArray( new osg::Vec3Array );
00407 
00408     // Make separate vertices for all triangle corners
00409     for( size_t index = 0; index < tris.size(); ++index )
00410     {
00411         newVertexArray->push_back( (*oldVertexArray)[tris[index]] );
00412         surfaceElement->push_back( index );
00413     }
00414     geometry->setVertexArray( newVertexArray );
00415     geometry->addPrimitiveSet( surfaceElement );
00416 
00417     // add the mesh colors
00418     if( mesh->getVertexColorArray() && useMeshColor )
00419     {
00420         geometry->setColorArray( mesh->getVertexColorArray() );
00421         geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
00422     }
00423     else
00424     {
00425         osg::ref_ptr< osg::Vec4Array > colors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
00426         colors->push_back( defaultColor );
00427         geometry->setColorArray( colors );
00428         geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
00429     }
00430 
00431     // ------------------------------------------------
00432     // normals
00433     if( includeNormals )
00434     {
00435         // Set all vertex normals to the normals of the corresponding
00436         // triangles causing uniform shading in a triangle
00437         osg::ref_ptr< osg::Vec3Array > oldTriNormals = mesh->getTriangleNormalArray( true );
00438         osg::ref_ptr< osg::Vec3Array > newVertNormals( new osg::Vec3Array );
00439         for( size_t index = 0; index < tris.size(); ++index )
00440         {
00441             newVertNormals->push_back( (*oldTriNormals)[index/3] );
00442         }
00443         geometry->setNormalArray( newVertNormals );
00444         geometry->setNormalBinding( osg::Geometry::BIND_PER_VERTEX );
00445 
00446         if( lighting )
00447         {
00448             // if normals are specified, we also setup a default lighting.
00449             osg::StateSet* state = geometry->getOrCreateStateSet();
00450             osg::ref_ptr<osg::LightModel> lightModel = new osg::LightModel();
00451             lightModel->setTwoSided( true );
00452             state->setAttributeAndModes( lightModel.get(), osg::StateAttribute::ON );
00453             state->setMode( GL_BLEND, osg::StateAttribute::ON  );
00454             {
00455                 osg::ref_ptr< osg::Material > material = new osg::Material();
00456                 material->setDiffuse(   osg::Material::FRONT, osg::Vec4( 1.0, 1.0, 1.0, 1.0 ) );
00457                 material->setSpecular(  osg::Material::FRONT, osg::Vec4( 0.0, 0.0, 0.0, 1.0 ) );
00458                 material->setAmbient(   osg::Material::FRONT, osg::Vec4( 0.1, 0.1, 0.1, 1.0 ) );
00459                 material->setEmission(  osg::Material::FRONT, osg::Vec4( 0.0, 0.0, 0.0, 1.0 ) );
00460                 material->setShininess( osg::Material::FRONT, 25.0 );
00461                 state->setAttribute( material );
00462             }
00463         }
00464     }
00465 
00466     // enable VBO
00467     geometry->setUseDisplayList( false );
00468     geometry->setUseVertexBufferObjects( true );
00469 
00470     return geometry;
00471 }
00472 
00473 osg::ref_ptr< osg::Geometry > wge::convertToOsgGeometry( WTriangleMesh::SPtr mesh,
00474                                                           const WColoredVertices& colorMap,
00475                                                           const WColor& defaultColor,
00476                                                           bool includeNormals, bool lighting )
00477 {
00478     osg::ref_ptr< osg::Geometry >  geometry = convertToOsgGeometry( mesh, defaultColor, includeNormals, lighting, false );
00479 
00480     // ------------------------------------------------
00481     // colors
00482     osg::ref_ptr< osg::Vec4Array > colors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
00483     for( size_t i = 0; i < mesh->vertSize(); ++i )
00484     {
00485         colors->push_back( defaultColor );
00486     }
00487     for( std::map< size_t, WColor >::const_iterator vc = colorMap.getData().begin(); vc != colorMap.getData().end(); ++vc )
00488     {
00489         // ATTENTION: the colormap might not be available and hence an old one, but the new mesh might have triggered the update
00490         if( vc->first < colors->size() )
00491         {
00492             colors->at( vc->first ) = vc->second;
00493         }
00494     }
00495 
00496     geometry->setColorArray( colors );
00497     geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
00498 
00499     return geometry;
00500 }
00501 
00502 osg::ref_ptr< osg::Geometry > wge::convertToOsgGeometryLines( WTriangleMesh::SPtr mesh,
00503                                                               const WColor& defaultColor,
00504                                                               bool useMeshColor )
00505 {
00506     osg::ref_ptr< osg::Geometry > geometry( new osg::Geometry );
00507     geometry->setVertexArray( mesh->getVertexArray() );
00508 
00509     osg::DrawElementsUInt* meshElement;
00510 
00511     meshElement = new osg::DrawElementsUInt( osg::PrimitiveSet::LINES, 0 );
00512 
00513     std::vector< size_t > tris = mesh->getTriangles();
00514     meshElement->reserve( tris.size() * 3 );
00515 
00516     for( unsigned int triId = 0; triId < tris.size() / 3.; ++triId )
00517     {
00518         for( size_t edgeId = 0; edgeId < 3; ++edgeId )
00519         {
00520             meshElement->push_back( tris[triId*3 + edgeId] );
00521             meshElement->push_back( tris[triId*3 + ( edgeId + 1 ) % 3] );
00522         }
00523     }
00524     geometry->addPrimitiveSet( meshElement );
00525 
00526     // add the mesh colors
00527     if( mesh->getVertexColorArray() && useMeshColor )
00528     {
00529         geometry->setColorArray( mesh->getVertexColorArray() );
00530         geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
00531     }
00532     else
00533     {
00534         osg::ref_ptr< osg::Vec4Array > colors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
00535         colors->push_back( defaultColor );
00536         geometry->setColorArray( colors );
00537         geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
00538     }
00539 
00540     osg::StateSet* stateset = geometry->getOrCreateStateSet();
00541     stateset->setAttributeAndModes( new osg::LineWidth( 1 ), osg::StateAttribute::ON );
00542     stateset->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
00543     stateset->setMode( GL_BLEND, osg::StateAttribute::ON );
00544 
00545     return geometry;
00546 }
00547 
00548 osg::ref_ptr< osg::PositionAttitudeTransform > wge::addLabel( osg::Vec3 position, std::string text )
00549 {
00550     osg::ref_ptr< osgText::Text > label = osg::ref_ptr< osgText::Text >( new osgText::Text() );
00551     osg::ref_ptr< osg::Geode > labelGeode = osg::ref_ptr< osg::Geode >( new osg::Geode() );
00552 
00553     labelGeode->addDrawable( label );
00554 
00555     // setup font
00556     label->setFont( WPathHelper::getAllFonts().Default.string() );
00557     label->setBackdropType( osgText::Text::OUTLINE );
00558     label->setCharacterSize( 6 );
00559 
00560     label->setText( text );
00561     label->setAxisAlignment( osgText::Text::SCREEN );
00562     label->setDrawMode( osgText::Text::TEXT );
00563     label->setAlignment( osgText::Text::CENTER_TOP );
00564     label->setPosition( osg::Vec3( 0.0, 0.0, 0.0 ) );
00565     label->setColor( osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) );
00566 
00567     osg::ref_ptr< osg::PositionAttitudeTransform > labelXform =
00568         osg::ref_ptr< osg::PositionAttitudeTransform >( new osg::PositionAttitudeTransform() );
00569     labelXform->setPosition( position );
00570 
00571     labelXform->addChild( labelGeode );
00572 
00573     return labelXform;
00574 }
00575 
00576 osg::ref_ptr< osg::PositionAttitudeTransform > wge::vector2label( osg::Vec3 position )
00577 {
00578     std::string label = "(" + string_utils::toString( position[0] ) + "," +
00579     string_utils::toString( position[1] ) + "," + string_utils::toString( position[2] ) + ")";
00580     return ( addLabel( position, label ) );
00581 }
00582 
00583 osg::ref_ptr< osg::Geode > wge::genFinitePlane( double xSize, double ySize, const WPlane& p, const WColor& color, bool border )
00584 {
00585     using osg::ref_ptr;
00586     ref_ptr< osg::Vec3Array > vertices = ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
00587     ref_ptr< osg::Vec4Array > colors   = ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
00588     ref_ptr< osg::Geometry >  geometry = ref_ptr< osg::Geometry >( new osg::Geometry );
00589 
00590     colors->push_back( color );
00591 
00592     vertices->push_back( p.getPointInPlane(  xSize,  ySize ) );
00593     vertices->push_back( p.getPointInPlane( -xSize,  ySize ) );
00594     vertices->push_back( p.getPointInPlane( -xSize, -ySize ) );
00595     vertices->push_back( p.getPointInPlane(  xSize, -ySize ) );
00596 
00597     geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, 4 ) );
00598     geometry->setVertexArray( vertices );
00599     geometry->setColorArray( colors );
00600     geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
00601 
00602     osg::StateSet* stateset = new osg::StateSet;
00603     stateset->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
00604     geometry->setStateSet( stateset );
00605 
00606     osg::ref_ptr< osg::Geode > geode = osg::ref_ptr< osg::Geode >( new osg::Geode );
00607     geode->addDrawable( geometry );
00608 
00609     if( border )
00610     {
00611         vertices->push_back( vertices->front() );
00612         ref_ptr< osg::Geometry >  borderGeom = ref_ptr< osg::Geometry >( new osg::Geometry );
00613         borderGeom->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_STRIP, 0, 4 ) );
00614         borderGeom->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_STRIP, 3, 2 ) );
00615         ref_ptr< osg::Vec4Array > colors   = ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
00616         colors->push_back( inverseColor( color ) );
00617         borderGeom->setColorArray( colors );
00618         borderGeom->setColorBinding( osg::Geometry::BIND_OVERALL );
00619         borderGeom->setVertexArray( vertices );
00620         geode->addDrawable( borderGeom );
00621     }
00622     return geode;
00623 }
00624 
00625 osg::ref_ptr< osg::Geode > wge::genFinitePlane( osg::Vec3 const& base, osg::Vec3 const& a, osg::Vec3 const& b, const WColor& color )
00626 {
00627     // the stuff needed by the OSG to create a geometry instance
00628     osg::ref_ptr< osg::Vec3Array > vertices = new osg::Vec3Array;
00629     osg::ref_ptr< osg::Vec3Array > texcoords0 = new osg::Vec3Array;
00630     osg::ref_ptr< osg::Vec3Array > normals = new osg::Vec3Array;
00631     osg::ref_ptr< osg::Vec4Array > colors = new osg::Vec4Array;
00632 
00633     osg::Vec3 aPlusB = a + b;
00634 
00635     vertices->push_back( base );
00636     vertices->push_back( base + a );
00637     vertices->push_back( base + aPlusB );
00638     vertices->push_back( base + b );
00639 
00640     osg::Vec3 aCrossB = a ^ b;
00641     aCrossB.normalize();
00642     osg::Vec3 aNorm = a;
00643     aNorm.normalize();
00644     osg::Vec3 bNorm = b;
00645     bNorm.normalize();
00646 
00647     normals->push_back( aCrossB );
00648     colors->push_back( color );
00649     texcoords0->push_back( osg::Vec3( 0.0, 0.0, 0.0 ) );
00650     texcoords0->push_back( aNorm );
00651     texcoords0->push_back( aNorm + bNorm );
00652     texcoords0->push_back( bNorm );
00653 
00654     // put it all together
00655     osg::ref_ptr< osg::Geometry > geometry = new osg::Geometry();
00656     geometry->setVertexArray( vertices );
00657     geometry->setTexCoordArray( 0, texcoords0 );
00658     geometry->setNormalArray( normals );
00659     geometry->setNormalBinding( osg::Geometry::BIND_OVERALL );
00660     geometry->setColorArray( colors );
00661     geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
00662     geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, 4 ) );
00663 
00664     osg::ref_ptr< osg::Geode > geode = new osg::Geode();
00665     geode->addDrawable( geometry );
00666     return geode;
00667 }
00668 
00669 osg::ref_ptr< osg::Group > wge::creatCoordinateSystem(
00670     osg::Vec3 middle,
00671     double sizeX,
00672     double sizeY,
00673     double sizeZ
00674 )
00675 {
00676     osg::ref_ptr< WGEGroupNode >groupNode = new WGEGroupNode();
00677     osg::ref_ptr< WGEShader > shaderCoordinateSystem( new WGEShader( "WGECoordinateSystem" ) );
00678 
00679     osg::ref_ptr< osg::Geode > graphX( new osg::Geode );
00680     osg::ref_ptr< osg::Geode > graphY( new osg::Geode );
00681     osg::ref_ptr< osg::Geode > graphZ( new osg::Geode );
00682 
00683     osg::ref_ptr< osg::Geode > graphXCylinder( new osg::Geode );
00684     osg::ref_ptr< osg::Geode > graphYCylinder( new osg::Geode );
00685     osg::ref_ptr< osg::Geode > graphZCylinder( new osg::Geode );
00686 
00687     // X
00688     osg::ref_ptr< osg::ShapeDrawable > cylinderX = new osg::ShapeDrawable( new osg::Cylinder(
00689         middle, 1, sizeX + ( sizeX * 0.5 )
00690     ) );
00691     osg::ref_ptr< osg::ShapeDrawable > cylinderXEnd = new osg::ShapeDrawable( new osg::Cylinder(
00692         osg::Vec3( middle.x(), middle.y(), middle.z() - ( sizeX + ( sizeX * 0.5 ) ) / 2.0 ), 1.0, 1.0
00693     ) );
00694     osg::ref_ptr< osg::ShapeDrawable > coneX = new osg::ShapeDrawable( new osg::Cone(
00695         osg::Vec3( middle.x(), middle.y(), middle.z() + ( sizeX + ( sizeX * 0.5 ) ) / 2.0 ), 2.0, 5.0
00696     ) );
00697     cylinderXEnd->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
00698     graphXCylinder->addDrawable( cylinderX );
00699     graphX->addDrawable( coneX );
00700     graphX->addDrawable( cylinderXEnd );
00701 
00702     osg::ref_ptr< osg::Material > matX = new osg::Material();
00703     matX->setDiffuse( osg::Material::FRONT, WColor( 1.0, 0.0, 0.0, 1.0 ) );
00704     cylinderX->getOrCreateStateSet()->setAttribute( matX, osg::StateAttribute::ON );
00705     coneX->getOrCreateStateSet()->setAttribute( matX, osg::StateAttribute::ON );
00706 
00707     // Y
00708     osg::ref_ptr< osg::ShapeDrawable > cylinderY = new osg::ShapeDrawable( new osg::Cylinder(
00709         middle, 1, sizeY + ( sizeY * 0.5 )
00710     ) );
00711     osg::ref_ptr< osg::ShapeDrawable > cylinderYEnd = new osg::ShapeDrawable( new osg::Cylinder(
00712         osg::Vec3( middle.x(), middle.y(), middle.z() - ( sizeY + ( sizeY * 0.5 ) ) / 2.0 ), 1.0, 1.0
00713     ) );
00714     osg::ref_ptr< osg::ShapeDrawable > coneY = new osg::ShapeDrawable( new osg::Cone(
00715         osg::Vec3( middle.x(), middle.y(), middle.z() + ( sizeY + ( sizeY * 0.5 ) ) / 2.0 ), 2.0, 5.0
00716     ) );
00717     cylinderYEnd->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
00718 
00719     graphYCylinder->addDrawable( cylinderY );
00720     graphY->addDrawable( coneY );
00721     graphY->addDrawable( cylinderYEnd );
00722 
00723     osg::ref_ptr< osg::Material > matY = new osg::Material();
00724     matY->setDiffuse( osg::Material::FRONT, WColor( 0.0, 1.0, 0.0, 1.0 ) );
00725     cylinderY->getOrCreateStateSet()->setAttribute( matY, osg::StateAttribute::ON );
00726     coneY->getOrCreateStateSet()->setAttribute( matY, osg::StateAttribute::ON );
00727 
00728 
00729     // Z
00730     osg::ref_ptr< osg::ShapeDrawable > cylinderZ = new osg::ShapeDrawable( new osg::Cylinder(
00731         middle, 1, sizeZ + ( sizeZ * 0.5 )
00732     ) );
00733     osg::ref_ptr< osg::ShapeDrawable > cylinderZEnd = new osg::ShapeDrawable( new osg::Cylinder(
00734         osg::Vec3( middle.x(), middle.y(), middle.z() - ( sizeZ + ( sizeZ * 0.5 ) ) / 2.0 ), 1.0, 1.0
00735     ) );
00736     osg::ref_ptr< osg::ShapeDrawable > coneZ = new osg::ShapeDrawable( new osg::Cone(
00737         osg::Vec3( middle.x(), middle.y(), middle.z() + ( sizeZ + ( sizeZ * 0.5 ) ) / 2.0 ), 2.0, 5.0
00738     ) );
00739     cylinderZEnd->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
00740 
00741     graphZCylinder->addDrawable( cylinderZ );
00742     graphZ->addDrawable( coneZ );
00743     graphZ->addDrawable( cylinderZEnd );
00744 
00745     osg::ref_ptr< osg::Material > matZ = new osg::Material();
00746     matZ->setDiffuse( osg::Material::FRONT, WColor( 0.0, 0.0, 1.0, 1.0 ) );
00747     cylinderZ->getOrCreateStateSet()->setAttribute( matZ, osg::StateAttribute::ON );
00748     coneZ->getOrCreateStateSet()->setAttribute( matZ, osg::StateAttribute::ON );
00749 
00750     shaderCoordinateSystem->apply( graphXCylinder );
00751     shaderCoordinateSystem->apply( graphYCylinder );
00752     shaderCoordinateSystem->apply( graphZCylinder );
00753 
00754     osg::ref_ptr< WGELabel > graphXLabel = new WGELabel();
00755     graphXLabel->setText( "X" );
00756     graphXLabel->setCharacterSize( 10 );
00757     graphXLabel->setPosition( osg::Vec3( middle.x(), middle.y(), middle.z() + ( sizeX + ( sizeX * 0.5 ) ) / 2.0 + 5.0 ) );
00758     graphXLabel->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
00759     graphX->addDrawable( graphXLabel );
00760 
00761     osg::ref_ptr< WGELabel > graphYLabel = new WGELabel();
00762     graphYLabel->setText( "Y" );
00763     graphYLabel->setCharacterSize( 10 );
00764     graphYLabel->setPosition( osg::Vec3( middle.x(), middle.y(), middle.z() + ( sizeY + ( sizeY * 0.5 ) ) / 2.0 + 5.0 ) );
00765     graphYLabel->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
00766     graphY->addDrawable( graphYLabel );
00767 
00768     osg::ref_ptr< WGELabel > graphZLabel = new WGELabel();
00769     graphZLabel->setText( "Z" );
00770     graphZLabel->setCharacterSize( 10 );
00771     graphZLabel->setPosition( osg::Vec3( middle.x(), middle.y(), middle.z() + ( sizeZ + ( sizeZ * 0.5 ) ) / 2.0 + 5.0 ) );
00772     graphZLabel->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
00773     graphZ->addDrawable( graphZLabel );
00774 
00775 
00776     osg::ref_ptr< osg::MatrixTransform > graphXTransform = new osg::MatrixTransform();
00777     graphXTransform->addChild( graphX );
00778     graphXTransform->addChild( graphXCylinder );
00779     osg::ref_ptr< osg::MatrixTransform > graphYTransform = new osg::MatrixTransform();
00780     graphYTransform->addChild( graphY );
00781     graphYTransform->addChild( graphYCylinder );
00782     osg::ref_ptr< osg::MatrixTransform > graphZTransform = new osg::MatrixTransform();
00783     graphZTransform->addChild( graphZ );
00784     graphZTransform->addChild( graphZCylinder );
00785 
00786     osg::Matrixd matrixTranslateTo0 = osg::Matrixd::translate( -middle.x(), -middle.y(), -middle.z() );
00787     osg::Matrixd matrixTranslateFrom0 = osg::Matrixd::translate( middle.x(), middle.y(), middle.z() );
00788 
00789     graphXTransform->setMatrix( matrixTranslateTo0 * osg::Matrixd::rotate(
00790         90.0 * piDouble / 180.0,
00791         osg::Vec3f( 0.0, 1.0, 0.0 ) ) * matrixTranslateFrom0
00792     );
00793     graphYTransform->setMatrix( matrixTranslateTo0 * osg::Matrixd::rotate(
00794         -90.0 * piDouble / 180.0,
00795         osg::Vec3f( 1.0, 0.0, 0.0 ) ) * matrixTranslateFrom0
00796     );
00797 
00798     groupNode->insert( graphXTransform );
00799     groupNode->insert( graphYTransform );
00800     groupNode->insert( graphZTransform );
00801 
00802     return groupNode;
00803 }