OpenWalnut
1.2.5
|
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 <osgUtil/DelaunayTriangulator> 00031 00032 #include "../common/math/linearAlgebra/WLinearAlgebra.h" 00033 #include "WGEGeometryUtils.h" 00034 #include "WGEUtils.h" 00035 #include "WTriangleMesh.h" 00036 #include "exceptions/WGEException.h" 00037 00038 osg::ref_ptr< osg::Vec3Array > wge::generateCuboidQuads( const std::vector< WPosition >& corners ) 00039 { 00040 osg::ref_ptr< osg::Vec3Array > vertices = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array ); 00041 00042 // Surfaces 00043 vertices->push_back( corners[0] ); 00044 vertices->push_back( corners[1] ); 00045 vertices->push_back( corners[2] ); 00046 vertices->push_back( corners[3] ); 00047 00048 vertices->push_back( corners[1] ); 00049 vertices->push_back( corners[5] ); 00050 vertices->push_back( corners[6] ); 00051 vertices->push_back( corners[2] ); 00052 00053 vertices->push_back( corners[5] ); 00054 vertices->push_back( corners[4] ); 00055 vertices->push_back( corners[7] ); 00056 vertices->push_back( corners[6] ); 00057 00058 vertices->push_back( corners[4] ); 00059 vertices->push_back( corners[0] ); 00060 vertices->push_back( corners[3] ); 00061 vertices->push_back( corners[7] ); 00062 00063 vertices->push_back( corners[3] ); 00064 vertices->push_back( corners[2] ); 00065 vertices->push_back( corners[6] ); 00066 vertices->push_back( corners[7] ); 00067 00068 vertices->push_back( corners[0] ); 00069 vertices->push_back( corners[1] ); 00070 vertices->push_back( corners[5] ); 00071 vertices->push_back( corners[4] ); 00072 return vertices; 00073 } 00074 00075 osg::Vec3 wge::getQuadNormal( const WPosition& a, 00076 const WPosition& b, 00077 const WPosition& c ) 00078 { 00079 WVector3d vec1 = a - b; 00080 WVector3d vec2 = c - b; 00081 WVector3d normal = cross( vec2, vec1 ); 00082 return normalize( normal ); 00083 } 00084 00085 osg::ref_ptr< osg::Vec3Array > wge::generateCuboidQuadNormals( const std::vector< WPosition >& corners ) 00086 { 00087 osg::ref_ptr< osg::Vec3Array > vertices = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array ); 00088 00089 vertices->push_back( getQuadNormal( corners[0], corners[1], corners[2] ) ); 00090 vertices->push_back( getQuadNormal( corners[1], corners[5], corners[6] ) ); 00091 vertices->push_back( getQuadNormal( corners[5], corners[4], corners[7] ) ); 00092 vertices->push_back( getQuadNormal( corners[4], corners[0], corners[3] ) ); 00093 vertices->push_back( getQuadNormal( corners[3], corners[2], corners[6] ) ); 00094 vertices->push_back( getQuadNormal( corners[0], corners[1], corners[5] ) ); 00095 return vertices; 00096 } 00097 00098 WTriangleMesh::SPtr wge::triangulate( const std::vector< WPosition >& points, double transformationFactor ) 00099 { 00100 WAssert( points.size() > 2, "The Delaunay triangulation needs at least 3 vertices!" ); 00101 00102 osg::ref_ptr< osg::Vec3Array > osgPoints = wge::osgVec3Array( points ); 00103 00104 if( transformationFactor != 0.0 ) 00105 { 00106 // Transform the points as described in the Doxygen description of 00107 // this function. 00108 osg::Vec3 centroid; 00109 for( std::size_t pointID = 0; pointID < osgPoints->size(); ++pointID ) 00110 { 00111 centroid += (*osgPoints)[pointID]; 00112 } 00113 centroid /= osgPoints->size(); 00114 00115 for( std::size_t pointID = 0; pointID < osgPoints->size(); ++pointID ) 00116 { 00117 const double factor = ( (*osgPoints)[pointID].z() - centroid.z() ) * transformationFactor + 1.0; 00118 (*osgPoints)[pointID].x() = ( (*osgPoints)[pointID].x() - centroid.x() ) * factor + centroid.x(); 00119 (*osgPoints)[pointID].y() = ( (*osgPoints)[pointID].y() - centroid.y() ) * factor + centroid.y(); 00120 } 00121 } 00122 00123 // The osg triangulator sorts the points and returns the triangles with 00124 // the indizes of the sorted points. Since we don't want to change the 00125 // sequence of the points, we have to save the original index of each 00126 // point. 00127 std::map< osg::Vec3, size_t > map; 00128 for( size_t index = 0; index < osgPoints->size(); ++index ) 00129 { 00130 map[ (*osgPoints)[index] ] = index; 00131 } 00132 00133 osg::ref_ptr< osgUtil::DelaunayTriangulator > triangulator( new osgUtil::DelaunayTriangulator( osgPoints ) ); 00134 00135 bool triangulationResult = triangulator->triangulate(); 00136 00137 WAssert( triangulationResult, "Something went wrong in triangulation." ); 00138 00139 osg::ref_ptr< const osg::DrawElementsUInt > osgTriangles( triangulator->getTriangles() ); 00140 size_t nbTriangles = osgTriangles->size() / 3; 00141 std::vector< size_t > triangles( osgTriangles->size() ); 00142 for( size_t triangleID = 0; triangleID < nbTriangles; ++triangleID ) 00143 { 00144 // Convert the new index of the osgTriangle to the original 00145 // index stored in map. 00146 size_t vertID = triangleID * 3; 00147 triangles[vertID + 0] = map[ (*osgPoints)[ (*osgTriangles)[vertID + 0] ] ]; 00148 triangles[vertID + 1] = map[ (*osgPoints)[ (*osgTriangles)[vertID + 1] ] ]; 00149 triangles[vertID + 2] = map[ (*osgPoints)[ (*osgTriangles)[vertID + 2] ] ]; 00150 } 00151 00152 // I needed this reconversion using osgVec3Array because the triangulator changed my positions somehow. 00153 return WTriangleMesh::SPtr( new WTriangleMesh( wge::osgVec3Array( points ), triangles ) ); 00154 }