OpenWalnut 1.3.1
|
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 <iostream> 00026 #include <list> 00027 #include <map> 00028 #include <sstream> 00029 #include <string> 00030 #include <utility> 00031 #include <vector> 00032 00033 #include <osg/io_utils> 00034 00035 #include "../common/datastructures/WUnionFind.h" 00036 #include "WTriangleMesh.h" 00037 00038 // init _static_ member variable and provide a linker reference to it 00039 boost::shared_ptr< WPrototyped > WTriangleMesh::m_prototype = boost::shared_ptr< WPrototyped >(); 00040 00041 boost::shared_ptr< WPrototyped > WTriangleMesh::getPrototype() 00042 { 00043 if( !m_prototype ) 00044 { 00045 m_prototype = boost::shared_ptr< WPrototyped >( new WTriangleMesh( 0, 0 ) ); 00046 } 00047 return m_prototype; 00048 } 00049 00050 /** 00051 * constructor that already reserves space for a given number of triangles and vertexes 00052 */ 00053 WTriangleMesh::WTriangleMesh( size_t vertNum, size_t triangleNum ) 00054 : m_countVerts( 0 ), 00055 m_countTriangles( 0 ), 00056 m_meshDirty( true ), 00057 m_neighborsCalculated( false ) 00058 { 00059 m_verts = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array( vertNum ) ); 00060 m_textureCoordinates = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array( vertNum ) ); 00061 m_vertNormals = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array( vertNum ) ); 00062 m_vertColors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array( vertNum ) ); 00063 00064 m_triangles.resize( triangleNum * 3 ); 00065 m_triangleNormals = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array( triangleNum ) ); 00066 m_triangleColors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array( triangleNum ) ); 00067 } 00068 00069 WTriangleMesh::WTriangleMesh( osg::ref_ptr< osg::Vec3Array > vertices, const std::vector< size_t >& triangles ) 00070 : m_countVerts( vertices->size() ), 00071 m_countTriangles( triangles.size() / 3 ), 00072 m_meshDirty( true ), 00073 m_neighborsCalculated( false ), 00074 m_verts( vertices ), 00075 m_textureCoordinates( new osg::Vec3Array( vertices->size() ) ), 00076 m_vertNormals( new osg::Vec3Array( vertices->size() ) ), 00077 m_vertColors( new osg::Vec4Array( vertices->size() ) ), 00078 m_triangles( triangles ), 00079 m_triangleNormals( new osg::Vec3Array( triangles.size() / 3 ) ), 00080 m_triangleColors( new osg::Vec4Array( triangles.size() / 3 ) ) 00081 { 00082 WAssert( triangles.size() % 3 == 0, "Invalid triangle vector, having an invalid size (not divideable by 3)" ); 00083 } 00084 00085 WTriangleMesh::~WTriangleMesh() 00086 { 00087 } 00088 00089 void WTriangleMesh::addVertex( float x, float y, float z ) 00090 { 00091 addVertex( osg::Vec3( x, y, z ) ); 00092 } 00093 00094 void WTriangleMesh::addVertex( WPosition vert ) 00095 { 00096 addVertex( osg::Vec3( vert[0], vert[1], vert[2] ) ); 00097 } 00098 00099 void WTriangleMesh::addTriangle( size_t vert0, size_t vert1, size_t vert2 ) 00100 { 00101 if( m_triangles.size() == m_countTriangles * 3 ) 00102 { 00103 m_triangles.resize( m_countTriangles * 3 + 3 ); 00104 } 00105 m_triangles[ m_countTriangles * 3 ] = vert0; 00106 m_triangles[ m_countTriangles * 3 + 1 ] = vert1; 00107 m_triangles[ m_countTriangles * 3 + 2 ] = vert2; 00108 ++m_countTriangles; 00109 } 00110 00111 void WTriangleMesh::addTriangle( osg::Vec3 vert0, osg::Vec3 vert1, osg::Vec3 vert2 ) 00112 { 00113 addVertex( vert0 ); 00114 addVertex( vert1 ); 00115 addVertex( vert2 ); 00116 addTriangle( m_countVerts - 3, m_countVerts - 2, m_countVerts - 1 ); 00117 } 00118 00119 void WTriangleMesh::setVertexNormal( size_t index, osg::Vec3 normal ) 00120 { 00121 WAssert( index < m_countVerts, "set vertex normal: index out of range" ); 00122 ( *m_vertNormals )[index] = normal; 00123 } 00124 00125 void WTriangleMesh::setVertexNormal( size_t index, WPosition normal ) 00126 { 00127 WAssert( index < m_countVerts, "set vertex normal: index out of range" ); 00128 setVertexNormal( index, osg::Vec3( normal[0], normal[1], normal[2] ) ); 00129 } 00130 00131 void WTriangleMesh::setVertexColor( size_t index, osg::Vec4 color ) 00132 { 00133 WAssert( index < m_countVerts, "set vertex color: index out of range" ); 00134 ( *m_vertColors )[index] = color; 00135 } 00136 00137 void WTriangleMesh::setTriangleColor( size_t index, osg::Vec4 color ) 00138 { 00139 WAssert( index < m_countTriangles, "set triangle color: index out of range" ); 00140 ( *m_triangleColors )[index] = color; 00141 } 00142 00143 osg::ref_ptr< osg::Vec3Array >WTriangleMesh::getVertexArray() 00144 { 00145 return m_verts; 00146 } 00147 00148 osg::ref_ptr< const osg::Vec3Array >WTriangleMesh::getVertexArray() const 00149 { 00150 return m_verts; 00151 } 00152 00153 osg::ref_ptr< osg::Vec3Array > WTriangleMesh::getTextureCoordinateArray() 00154 { 00155 return m_textureCoordinates; 00156 } 00157 00158 osg::ref_ptr< const osg::Vec3Array > WTriangleMesh::getTextureCoordinateArray() const 00159 { 00160 return m_textureCoordinates; 00161 } 00162 00163 osg::ref_ptr< osg::Vec3Array >WTriangleMesh::getVertexNormalArray( bool forceRecalc ) 00164 { 00165 if( forceRecalc || m_meshDirty ) 00166 { 00167 recalcVertNormals(); 00168 } 00169 return m_vertNormals; 00170 } 00171 00172 osg::ref_ptr< osg::Vec3Array >WTriangleMesh::getTriangleNormalArray( bool forceRecalc ) 00173 { 00174 if( forceRecalc || m_meshDirty ) 00175 { 00176 recalcVertNormals(); 00177 } 00178 return m_triangleNormals; 00179 } 00180 00181 00182 osg::ref_ptr< osg::Vec4Array >WTriangleMesh::getVertexColorArray() 00183 { 00184 return m_vertColors; 00185 } 00186 00187 const std::vector< size_t >& WTriangleMesh::getTriangles() const 00188 { 00189 return m_triangles; 00190 } 00191 00192 osg::Vec3 WTriangleMesh::getVertex( size_t index ) const 00193 { 00194 WAssert( index < m_countVerts, "get vertex: index out of range" ); 00195 return ( *m_verts )[index]; 00196 } 00197 00198 osg::Vec4 WTriangleMesh::getVertColor( size_t index ) const 00199 { 00200 WAssert( index < m_countVerts, "get vertex color: index out of range" ); 00201 return ( *m_vertColors )[index]; 00202 } 00203 00204 WVector3d WTriangleMesh::getNormal( size_t index ) 00205 { 00206 WAssert( index < m_countVerts, "get normal as position: index out of range" ); 00207 if( m_meshDirty ) 00208 { 00209 recalcVertNormals(); 00210 } 00211 return WPosition( ( *m_vertNormals )[index][0], ( *m_vertNormals )[index][1], ( *m_vertNormals )[index][2] ); 00212 } 00213 00214 void WTriangleMesh::removeVertex( size_t index ) 00215 { 00216 WAssert( index < m_countVerts, "remove vertex: index out of range" ); 00217 if( m_vertexIsInTriangle[ index ].size() > 0 ) 00218 { 00219 return; 00220 } 00221 ( *m_verts ).erase( ( *m_verts ).begin() + index ); 00222 00223 for( size_t i = 0; i < m_countTriangles * 3; ++i ) 00224 { 00225 if( m_triangles[ i ] > index ) 00226 { 00227 --m_triangles[ i ]; 00228 } 00229 } 00230 m_meshDirty = true; 00231 } 00232 00233 void WTriangleMesh::removeTriangle( size_t index ) 00234 { 00235 WAssert( index < m_countTriangles, "remove triangle: index out of range" ); 00236 m_triangles.erase( m_triangles.begin() + index * 3, m_triangles.begin() + index * 3 + 3 ); 00237 m_meshDirty = true; 00238 } 00239 00240 void WTriangleMesh::recalcVertNormals() 00241 { 00242 updateVertsInTriangles(); 00243 00244 ( *m_vertNormals ).resize( m_countVerts ); 00245 ( *m_triangleNormals ).resize( m_countTriangles ); 00246 00247 for( size_t i = 0; i < m_countTriangles; ++i ) 00248 { 00249 ( *m_triangleNormals )[i] = calcTriangleNormal( i ); 00250 } 00251 00252 for( size_t vertId = 0; vertId < m_countVerts; ++vertId ) 00253 { 00254 osg::Vec3 tempNormal( 0.0, 0.0, 0.0 ); 00255 for( size_t neighbour = 0; neighbour < m_vertexIsInTriangle[vertId].size(); ++neighbour ) 00256 { 00257 tempNormal += ( *m_triangleNormals )[ m_vertexIsInTriangle[vertId][neighbour] ]; 00258 } 00259 tempNormal *= 1./m_vertexIsInTriangle[vertId].size(); 00260 00261 tempNormal.normalize(); 00262 ( *m_vertNormals )[vertId] = tempNormal; 00263 } 00264 00265 m_meshDirty = false; 00266 } 00267 00268 void WTriangleMesh::updateVertsInTriangles() 00269 { 00270 m_vertexIsInTriangle.clear(); 00271 std::vector< size_t >v; 00272 m_vertexIsInTriangle.resize( ( *m_verts ).size(), v ); 00273 00274 for( size_t i = 0; i < m_countTriangles; ++i ) 00275 { 00276 m_vertexIsInTriangle[ getTriVertId0( i ) ].push_back( i ); 00277 m_vertexIsInTriangle[ getTriVertId1( i ) ].push_back( i ); 00278 m_vertexIsInTriangle[ getTriVertId2( i ) ].push_back( i ); 00279 } 00280 } 00281 00282 osg::Vec3 WTriangleMesh::calcTriangleNormal( size_t triangle ) 00283 { 00284 osg::Vec3 v1( getTriVert( triangle, 1 ) - getTriVert( triangle, 0 ) ); 00285 osg::Vec3 v2( getTriVert( triangle, 2 ) - getTriVert( triangle, 0 ) ); 00286 00287 osg::Vec3 tempNormal( 0, 0, 0 ); 00288 00289 tempNormal[0] = v1[1] * v2[2] - v1[2] * v2[1]; 00290 tempNormal[1] = v1[2] * v2[0] - v1[0] * v2[2]; 00291 tempNormal[2] = v1[0] * v2[1] - v1[1] * v2[0]; 00292 00293 tempNormal.normalize(); 00294 00295 return tempNormal; 00296 } 00297 00298 osg::Vec3 WTriangleMesh::calcNormal( osg::Vec3 vert0, osg::Vec3 vert1, osg::Vec3 vert2 ) 00299 { 00300 osg::Vec3 v1( vert1 - vert0 ); 00301 osg::Vec3 v2( vert2 - vert0 ); 00302 00303 osg::Vec3 tempNormal( 0, 0, 0 ); 00304 00305 tempNormal[0] = v1[1] * v2[2] - v1[2] * v2[1]; 00306 tempNormal[1] = v1[2] * v2[0] - v1[0] * v2[2]; 00307 tempNormal[2] = v1[0] * v2[1] - v1[1] * v2[0]; 00308 00309 tempNormal.normalize(); 00310 00311 return tempNormal; 00312 } 00313 00314 size_t WTriangleMesh::vertSize() const 00315 { 00316 return m_countVerts; 00317 } 00318 00319 size_t WTriangleMesh::triangleSize() const 00320 { 00321 return m_countTriangles; 00322 } 00323 00324 void WTriangleMesh::calcNeighbors() 00325 { 00326 std::vector<size_t> v( 3, -1 ); 00327 m_triangleNeighbors.resize( ( *m_triangleNormals ).size(), v ); 00328 00329 for( size_t triId = 0; triId < m_countTriangles; ++triId ) 00330 { 00331 size_t coVert0 = getTriVertId0( triId ); 00332 size_t coVert1 = getTriVertId1( triId ); 00333 size_t coVert2 = getTriVertId2( triId ); 00334 00335 m_triangleNeighbors[triId][0] = getNeighbor( coVert0, coVert1, triId ); 00336 m_triangleNeighbors[triId][1] = getNeighbor( coVert1, coVert2, triId ); 00337 m_triangleNeighbors[triId][2] = getNeighbor( coVert2, coVert0, triId ); 00338 } 00339 m_neighborsCalculated = true; 00340 } 00341 00342 size_t WTriangleMesh::getNeighbor( const size_t coVert1, const size_t coVert2, const size_t triangleNum ) 00343 { 00344 std::vector< size_t > candidates = m_vertexIsInTriangle[coVert1]; 00345 std::vector< size_t > compares = m_vertexIsInTriangle[coVert2]; 00346 00347 for( size_t i = 0; i < candidates.size(); ++i ) 00348 { 00349 for( size_t k = 0; k < compares.size(); ++k ) 00350 { 00351 if( ( candidates[i] != triangleNum ) && ( candidates[i] == compares[k] ) ) 00352 { 00353 return candidates[i]; 00354 } 00355 } 00356 } 00357 return triangleNum; 00358 } 00359 00360 void WTriangleMesh::doLoopSubD() 00361 { 00362 m_numTriVerts = m_countVerts; 00363 m_numTriFaces = m_countTriangles; 00364 00365 ( *m_verts ).resize( m_numTriVerts * 4 ); 00366 m_triangles.resize( m_numTriFaces * 4 * 3 ); 00367 00368 updateVertsInTriangles(); 00369 00370 osg::Vec3* newVertexPositions = new osg::Vec3[m_numTriVerts]; 00371 00372 //std::cout << "Loop subdivision pass 1" << std::endl; 00373 for( size_t i = 0; i < m_numTriVerts; ++i ) 00374 { 00375 newVertexPositions[i] = loopCalcNewPosition( i ); 00376 } 00377 00378 //std::cout << "Loop subdivision pass 2" << std::endl; 00379 for( size_t i = 0; i < m_numTriFaces; ++i ) 00380 { 00381 loopInsertCenterTriangle( i ); 00382 } 00383 ( *m_verts ).resize( m_countVerts ); 00384 std::vector< size_t >v; 00385 m_vertexIsInTriangle.resize( ( *m_verts ).size(), v ); 00386 00387 //std::cout << "Loop subdivision pass 3" << std::endl; 00388 for( size_t i = 0; i < m_numTriFaces; ++i ) 00389 { 00390 loopInsertCornerTriangles( i ); 00391 } 00392 00393 //std::cout << "Loop subdivision pass 4" << std::endl; 00394 for( size_t i = 0; i < m_numTriVerts; ++i ) 00395 { 00396 ( *m_verts )[i] = newVertexPositions[i]; 00397 } 00398 00399 delete[] newVertexPositions; 00400 00401 m_vertNormals->resize( m_verts->size() ); 00402 m_vertColors->resize( m_verts->size() ); 00403 m_triangleColors->resize( m_triangles.size() / 3 ); 00404 00405 m_meshDirty = true; 00406 } 00407 00408 00409 osg::Vec3 WTriangleMesh::loopCalcNewPosition( size_t vertId ) 00410 { 00411 std::vector< size_t > starP = m_vertexIsInTriangle[vertId]; 00412 int starSize = starP.size(); 00413 00414 osg::Vec3 oldPos = getVertex( vertId ); 00415 double alpha = loopGetAlpha( starSize ); 00416 00417 double scale = 1.0 - ( static_cast<double>( starSize ) * alpha ); 00418 oldPos *= scale; 00419 00420 osg::Vec3 newPos; 00421 int edgeV = 0; 00422 for( int i = 0; i < starSize; i++ ) 00423 { 00424 edgeV = loopGetNextVertex( starP[i], vertId ); 00425 osg::Vec3 translate = getVertex( edgeV ); 00426 newPos += translate; 00427 } 00428 newPos *= alpha; 00429 00430 return oldPos + newPos; 00431 } 00432 00433 void WTriangleMesh::loopInsertCenterTriangle( size_t triId ) 00434 { 00435 size_t edgeVerts[3]; 00436 00437 edgeVerts[0] = loopCalcEdgeVert( triId, getTriVertId0( triId ), getTriVertId1( triId ), getTriVertId2( triId ) ); 00438 edgeVerts[1] = loopCalcEdgeVert( triId, getTriVertId1( triId ), getTriVertId2( triId ), getTriVertId0( triId ) ); 00439 edgeVerts[2] = loopCalcEdgeVert( triId, getTriVertId2( triId ), getTriVertId0( triId ), getTriVertId1( triId ) ); 00440 00441 addTriangle( edgeVerts[0], edgeVerts[1], edgeVerts[2] ); 00442 } 00443 00444 00445 size_t WTriangleMesh::loopCalcEdgeVert( size_t triId, size_t edgeV1, size_t edgeV2, size_t V3 ) 00446 { 00447 size_t neighborVert = -1; 00448 size_t neighborFaceNum = -1; 00449 osg::Vec3 edgeVert; 00450 00451 neighborFaceNum = getNeighbor( edgeV1, edgeV2, triId ); 00452 00453 if( neighborFaceNum == triId ) 00454 { 00455 osg::Vec3 edgeVert = ( ( *m_verts )[edgeV1] + ( *m_verts )[edgeV2] ) / 2.0; 00456 size_t vertId = m_countVerts; 00457 addVertex( edgeVert ); 00458 return vertId; 00459 } 00460 00461 else if( neighborFaceNum > triId ) 00462 { 00463 neighborVert = loopGetThirdVert( edgeV1, edgeV2, neighborFaceNum ); 00464 00465 osg::Vec3 edgePart = ( *m_verts )[edgeV1] + ( *m_verts )[edgeV2]; 00466 osg::Vec3 neighborPart = ( *m_verts )[neighborVert] + ( *m_verts )[V3]; 00467 00468 edgeVert = ( ( edgePart * ( 3.0 / 8.0 ) ) + ( neighborPart * ( 1.0 / 8.0 ) ) ); 00469 size_t vertId = m_countVerts; 00470 addVertex( edgeVert ); 00471 return vertId; 00472 } 00473 else 00474 { 00475 size_t neighborCenterP = neighborFaceNum + m_numTriFaces; 00476 size_t neighborP = neighborFaceNum; 00477 00478 if( getTriVertId0( neighborP ) == edgeV2 ) 00479 { 00480 return getTriVertId0( neighborCenterP ); 00481 } 00482 else if( getTriVertId1( neighborP ) == edgeV2 ) 00483 { 00484 return getTriVertId1( neighborCenterP ); 00485 } 00486 else 00487 { 00488 return getTriVertId2( neighborCenterP ); 00489 } 00490 } 00491 return -1; 00492 } 00493 00494 void WTriangleMesh::loopInsertCornerTriangles( size_t triId ) 00495 { 00496 // comment: center are twisted from the orignal vertices. 00497 // original: 0, 1, 2 00498 // center: a, b, c 00499 // reAsgnOrig: 0, a, c 00500 // addTris: 1, b, a 00501 // addTris: 2, c, b 00502 // 00503 size_t originalTri0 = getTriVertId0( triId ); 00504 size_t originalTri1 = getTriVertId1( triId ); 00505 size_t originalTri2 = getTriVertId2( triId ); 00506 00507 size_t centerTri0 = getTriVertId0( triId + m_numTriFaces ); 00508 size_t centerTri1 = getTriVertId1( triId + m_numTriFaces ); 00509 size_t centerTri2 = getTriVertId2( triId + m_numTriFaces ); 00510 00511 addTriangle( originalTri1, centerTri1, centerTri0 ); 00512 addTriangle( originalTri2, centerTri2, centerTri1 ); 00513 loopSetTriangle( triId, originalTri0, centerTri0, centerTri2 ); 00514 } 00515 00516 void WTriangleMesh::loopSetTriangle( size_t triId, size_t vertId1, size_t vertId2, size_t vertId3 ) 00517 { 00518 loopEraseTriangleFromVertex( triId, getTriVertId1( triId ) ); 00519 loopEraseTriangleFromVertex( triId, getTriVertId2( triId ) ); 00520 00521 setTriVert0( triId, vertId1 ); 00522 setTriVert1( triId, vertId2 ); 00523 setTriVert2( triId, vertId3 ); 00524 00525 m_vertexIsInTriangle[vertId2].push_back( triId ); 00526 m_vertexIsInTriangle[vertId3].push_back( triId ); 00527 } 00528 00529 void WTriangleMesh::loopEraseTriangleFromVertex( size_t triId, size_t vertId ) 00530 { 00531 std::vector< size_t > temp; 00532 for( size_t i = 0; i < m_vertexIsInTriangle[vertId].size(); ++i ) 00533 { 00534 if( triId != m_vertexIsInTriangle[vertId][i] ) 00535 temp.push_back( m_vertexIsInTriangle[vertId][i] ); 00536 } 00537 m_vertexIsInTriangle[vertId] = temp; 00538 } 00539 00540 double WTriangleMesh::loopGetAlpha( int n ) 00541 { 00542 double answer; 00543 if( n > 3 ) 00544 { 00545 double center = ( 0.375 + ( 0.25 * cos( ( 2.0 * 3.14159265358979 ) / static_cast<double>( n ) ) ) ); 00546 answer = ( 0.625 - ( center * center ) ) / static_cast<double>( n ); 00547 } 00548 else 00549 { 00550 answer = 3.0 / 16.0; 00551 } 00552 return answer; 00553 } 00554 00555 size_t WTriangleMesh::loopGetNextVertex( size_t triNum, size_t vertNum ) 00556 { 00557 if( getTriVertId0( triNum ) == vertNum ) 00558 { 00559 return getTriVertId1( triNum ); 00560 } 00561 else if( getTriVertId1( triNum ) == vertNum ) 00562 { 00563 return getTriVertId2( triNum ); 00564 } 00565 return getTriVertId0( triNum ); 00566 } 00567 00568 size_t WTriangleMesh::loopGetThirdVert( size_t coVert1, size_t coVert2, size_t triangleNum ) 00569 { 00570 if( !( getTriVertId0( triangleNum ) == coVert1 ) && !( getTriVertId0( triangleNum ) == coVert2 ) ) 00571 { 00572 return getTriVertId0( triangleNum ); 00573 } 00574 else if( !( getTriVertId1( triangleNum ) == coVert1 ) && !( getTriVertId1( triangleNum ) == coVert2 ) ) 00575 { 00576 return getTriVertId1( triangleNum ); 00577 } 00578 return getTriVertId2( triangleNum ); 00579 } 00580 00581 void WTriangleMesh::addMesh( boost::shared_ptr<WTriangleMesh> mesh, float xOff, float yOff, float zOff ) 00582 { 00583 size_t oldVertSize = m_countVerts; 00584 00585 ( *m_vertColors ).resize( oldVertSize + mesh->vertSize() ); 00586 for( size_t i = 0; i < mesh->vertSize(); ++i ) 00587 { 00588 osg::Vec3 v( mesh->getVertex( i ) ); 00589 v[0] += xOff; 00590 v[1] += yOff; 00591 v[2] += zOff; 00592 addVertex( v ); 00593 setVertexColor( oldVertSize + i, mesh->getVertColor( i ) ); 00594 } 00595 for( size_t i = 0; i < mesh->triangleSize(); ++i ) 00596 { 00597 addTriangle( mesh->getTriVertId0( i ) + oldVertSize, mesh->getTriVertId1( i ) + oldVertSize, mesh->getTriVertId2( i ) + oldVertSize ); 00598 } 00599 m_meshDirty = true; 00600 } 00601 00602 void WTriangleMesh::translateMesh( float xOff, float yOff, float zOff ) 00603 { 00604 osg::Vec3 t( xOff, yOff, zOff ); 00605 for( size_t i = 0; i < ( *m_verts ).size(); ++i ) 00606 { 00607 ( *m_verts )[i] += t; 00608 } 00609 } 00610 00611 void WTriangleMesh::zoomMesh( float zoom ) 00612 { 00613 for( size_t i = 0; i < ( *m_verts ).size(); ++i ) 00614 { 00615 ( *m_verts )[i] *= zoom; 00616 } 00617 } 00618 00619 void WTriangleMesh::rescaleVertexColors() 00620 { 00621 float maxR = 0; 00622 float maxG = 0; 00623 float maxB = 0; 00624 for( size_t vertId = 0; vertId < m_vertColors->size(); ++vertId ) 00625 { 00626 if( ( *m_vertColors )[vertId][0] > maxR ) 00627 { 00628 maxR = ( *m_vertColors )[vertId][0]; 00629 } 00630 if( ( *m_vertColors )[vertId][1] > maxG ) 00631 { 00632 maxG = ( *m_vertColors )[vertId][1]; 00633 } 00634 if( ( *m_vertColors )[vertId][2] > maxB ) 00635 { 00636 maxB = ( *m_vertColors )[vertId][2]; 00637 } 00638 } 00639 for( size_t vertId = 0; vertId < m_vertColors->size(); ++vertId ) 00640 { 00641 ( *m_vertColors )[vertId][0] /= maxR; 00642 ( *m_vertColors )[vertId][1] /= maxG; 00643 ( *m_vertColors )[vertId][2] /= maxB; 00644 } 00645 } 00646 00647 std::ostream& tm_utils::operator<<( std::ostream& os, const WTriangleMesh& rhs ) 00648 { 00649 std::stringstream ss; 00650 ss << "WTriangleMesh( #vertices=" << rhs.vertSize() << " #triangles=" << rhs.triangleSize() << " )" << std::endl; 00651 using string_utils::operator<<; 00652 size_t count = 0; 00653 ss << std::endl; 00654 const std::vector< size_t >& triangles = rhs.getTriangles(); 00655 osg::ref_ptr< const osg::Vec3Array > vertices = rhs.getVertexArray(); 00656 for( size_t vID = 0 ; vID <= triangles.size() - 3; ++count ) 00657 { 00658 std::stringstream prefix; 00659 prefix << "triangle: " << count << "[ "; 00660 std::string indent( prefix.str().size(), ' ' ); 00661 using osg::operator<<; // using operator<< as defined in osg/io_utils 00662 ss << prefix.str() << vertices->at( triangles[ vID++ ] ) << std::endl; 00663 ss << indent << vertices->at( triangles[ vID++ ] ) << std::endl; 00664 ss << indent << vertices->at( triangles[ vID++ ] ) << std::endl; 00665 ss << std::string( indent.size() - 2, ' ' ) << "]" << std::endl; 00666 } 00667 return os << ss.str(); 00668 } 00669 00670 boost::shared_ptr< std::list< boost::shared_ptr< WTriangleMesh > > > tm_utils::componentDecomposition( const WTriangleMesh& mesh ) 00671 { 00672 boost::shared_ptr< std::list< boost::shared_ptr< WTriangleMesh > > > result( new std::list< boost::shared_ptr< WTriangleMesh > >() ); 00673 if( mesh.vertSize() <= 0 ) // no component possible 00674 { 00675 return result; 00676 } 00677 if( mesh.triangleSize() < 3 ) 00678 { 00679 if( mesh.vertSize() > 0 ) 00680 { 00681 // there are vertices but no triangles 00682 WAssert( false, "Not implemented the decomposition of a TriangleMesh without any triangles" ); 00683 } 00684 else // no component possible 00685 { 00686 return result; 00687 } 00688 } 00689 00690 WUnionFind uf( mesh.vertSize() ); // idea: every vertex in own component, then successivley join in accordance with the triangles 00691 00692 const std::vector< size_t >& triangles = mesh.getTriangles(); 00693 for( size_t vID = 0; vID <= triangles.size() - 3; vID += 3) 00694 { 00695 uf.merge( triangles[ vID ], triangles[ vID + 1 ] ); 00696 uf.merge( triangles[ vID ], triangles[ vID + 2 ] ); // uf.merge( triangles[ vID + 2 ], triangles[ vID + 1 ] ); they are already in same 00697 } 00698 00699 // ATTENTION: The reason for using the complex BucketType instead of pasting vertices directly into a new WTriangleMesh 00700 // is performance! For example: If there are many vertices reused inside the former WTriangleMesh mesh, then we want 00701 // to reuse them in the new components too. Hence we must determine if a certain vertex is already inside the new component. 00702 // Since the vertices are organized in a vector, we can use std::find( v.begin, v.end(), vertexToLookUp ) which results 00703 // in O(N^2) or we could use faster lookUp via key and value leading to the map and the somehow complicated BucketType. 00704 typedef std::map< osg::Vec3, size_t > VertexType; // look up fast if a vertex is already inside the new mesh! 00705 typedef std::vector< size_t > TriangleType; 00706 typedef std::pair< VertexType, TriangleType > BucketType; // Later on the Bucket will be transformed into the new WTriangleMesh component 00707 std::map< size_t, BucketType > buckets; // Key identify with the cannonical element from UnionFind the new connected component 00708 00709 osg::ref_ptr< const osg::Vec3Array > vertices = mesh.getVertexArray(); 00710 for( size_t vID = 0; vID <= triangles.size() - 3; vID += 3 ) 00711 { 00712 size_t component = uf.find( triangles[ vID ] ); 00713 if( buckets.find( component ) == buckets.end() ) 00714 { 00715 buckets[ component ] = BucketType( VertexType(), TriangleType() ); // create new bucket 00716 } 00717 00718 // Note: We discard the order of the points and indices, but semantically the structure remains the same 00719 VertexType& mapRef = buckets[ component ].first; // short hand alias 00720 for( int i = 0; i < 3; ++i ) 00721 { 00722 size_t id = 0; 00723 const osg::Vec3& vertex = ( *vertices )[ triangles[ vID + i ] ]; 00724 if( mapRef.find( vertex ) == mapRef.end() ) 00725 { 00726 id = mapRef.size(); // since size might change in next line 00727 mapRef[ vertex ] = id; 00728 } 00729 else 00730 { 00731 id = mapRef[ vertex ]; 00732 } 00733 buckets[ component ].second.push_back( id ); 00734 } 00735 } 00736 00737 for( std::map< size_t, BucketType >::const_iterator cit = buckets.begin(); cit != buckets.end(); ++cit ) 00738 { 00739 osg::ref_ptr< osg::Vec3Array > newVertices( new osg::Vec3Array ); 00740 newVertices->resize( cit->second.first.size() ); 00741 for( VertexType::const_iterator vit = cit->second.first.begin(); vit != cit->second.first.end(); ++vit ) 00742 { 00743 newVertices->at( vit->second ) = vit->first; // if you are sure that vit->second is always valid replace at() call with operator[] 00744 } 00745 boost::shared_ptr< WTriangleMesh > newMesh( new WTriangleMesh( newVertices, cit->second.second ) ); 00746 result->push_back( newMesh ); 00747 } 00748 00749 return result; 00750 } 00751 00752 osg::ref_ptr< osg::Vec4Array > WTriangleMesh::getTriangleColors() const 00753 { 00754 return m_triangleColors; 00755 }