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 #ifndef WTRIANGLEMESH_H 00026 #define WTRIANGLEMESH_H 00027 00028 #include <list> 00029 #include <string> 00030 #include <vector> 00031 00032 #include <osg/Geode> 00033 00034 #include "../common/math/linearAlgebra/WLinearAlgebra.h" 00035 #include "../common/WAssert.h" 00036 #include "../common/WColor.h" 00037 #include "../common/WTransferable.h" 00038 #include "WExportWGE.h" 00039 00040 /** 00041 * Triangle mesh data structure allowing for convenient access of the elements. 00042 */ 00043 class WGE_EXPORT WTriangleMesh : public WTransferable 00044 { 00045 friend class WTriangleMeshTest; 00046 public: 00047 00048 /** 00049 * Shared pointer 00050 */ 00051 typedef boost::shared_ptr< WTriangleMesh > SPtr; 00052 00053 /** 00054 * Const shared pointer 00055 */ 00056 typedef boost::shared_ptr< const WTriangleMesh > ConstSPtr; 00057 00058 /** 00059 * constructor that already reserves space for a given number of triangles and vertexes 00060 * 00061 * \param vertNum 00062 * \param triangleNum 00063 */ 00064 WTriangleMesh( size_t vertNum, size_t triangleNum ); 00065 00066 /** 00067 * Constructs a new mesh out of the given vertices and triangles. 00068 * 00069 * \param vertices Vec3Array storing all vertices 00070 * \param triangles Vector of consecutive vertex indices where each 3 IDs are a triangle starting at 0,1,2 for first triangle 3,4,5 for the second 00071 */ 00072 WTriangleMesh( osg::ref_ptr< osg::Vec3Array > vertices, const std::vector< size_t >& triangles ); 00073 00074 /** 00075 * destructor 00076 */ 00077 virtual ~WTriangleMesh(); 00078 00079 /** 00080 * Returns a prototype instantiated with the true type of the deriving class. 00081 * 00082 * \return the prototype. 00083 */ 00084 static boost::shared_ptr< WPrototyped > getPrototype(); 00085 00086 /** 00087 * Gets the name of this prototype. 00088 * 00089 * \return the name. 00090 */ 00091 virtual const std::string getName() const; 00092 00093 /** 00094 * Gets the description for this prototype. 00095 * 00096 * \return the description 00097 */ 00098 virtual const std::string getDescription() const; 00099 00100 /** 00101 * adds a vertex position to the mesh 00102 * 00103 * \param vert 00104 */ 00105 void addVertex( osg::Vec3 vert ); 00106 00107 /** 00108 * adds a vertex position to the mesh 00109 * 00110 * \param x 00111 * \param y 00112 * \param z 00113 */ 00114 void addVertex( float x, float y, float z ); 00115 00116 /** 00117 * adds a vertex position to the mesh 00118 * 00119 * \param vert 00120 */ 00121 void addVertex( WPosition vert ); 00122 00123 /** 00124 * Adds a texture coordinate for the vertex. 00125 * 00126 * \param texCoord the texture coordinate 00127 */ 00128 void addTextureCoordinate( osg::Vec3 texCoord ); 00129 00130 /** 00131 * Adds a texture coordinate for the vertex. 00132 * 00133 * \param x texture coordinate X 00134 * \param y texture coordinate Y 00135 * \param z texture coordinate Z 00136 */ 00137 void addTextureCoordinate( float x, float y, float z ); 00138 00139 /** 00140 * adds a tringle to the mesh 00141 * 00142 * \param vert0 index of the first vertex 00143 * \param vert1 index of the second vertex 00144 * \param vert2 index of the third vertex 00145 */ 00146 void addTriangle( size_t vert0, size_t vert1, size_t vert2 ); 00147 00148 /** 00149 * adds a tringle and its 3 vertexes to the mesh 00150 * 00151 * \param vert0 position of the first vertex 00152 * \param vert1 position of the second vertex 00153 * \param vert2 position of the third vertex 00154 */ 00155 void addTriangle( osg::Vec3 vert0, osg::Vec3 vert1, osg::Vec3 vert2 ); 00156 00157 /** 00158 * sets a vertex to a new position 00159 * 00160 * \param index 00161 * \param vert 00162 */ 00163 void setVertex( size_t index, osg::Vec3 vert ); 00164 00165 /** 00166 * sets the normal for a given vertex 00167 * 00168 * \param index 00169 * \param normal 00170 */ 00171 void setVertexNormal( size_t index, osg::Vec3 normal ); 00172 00173 /** 00174 * sets the normal for a given vertex 00175 * 00176 * \param index 00177 * \param normal 00178 */ 00179 void setVertexNormal( size_t index, WPosition normal ); 00180 00181 /** 00182 * sets the color for a given vertex 00183 * 00184 * \param index 00185 * \param color 00186 */ 00187 void setVertexColor( size_t index, osg::Vec4 color ); 00188 00189 /** 00190 * sets the color for a given triangle 00191 * 00192 * \param index 00193 * \param color 00194 */ 00195 void setTriangleColor( size_t index, osg::Vec4 color ); 00196 00197 /** 00198 * Return triangle colors 00199 * 00200 * \return OSG Vec4 Array of triangle colors 00201 */ 00202 osg::ref_ptr< osg::Vec4Array > getTriangleColors() const; 00203 00204 /** 00205 * getter 00206 * 00207 * \return pointer to the vertex array 00208 */ 00209 osg::ref_ptr< osg::Vec3Array > getVertexArray(); 00210 00211 /** 00212 * Returns a const reference pointer to the vertex array. 00213 * 00214 * \return vertex array 00215 */ 00216 osg::ref_ptr< const osg::Vec3Array > getVertexArray() const; 00217 00218 /** 00219 * Returns a reference pointer to the texture coordinate array. 00220 * 00221 * \return texture coordinate array 00222 */ 00223 osg::ref_ptr< osg::Vec3Array > getTextureCoordinateArray(); 00224 00225 /** 00226 * Returns a const reference pointer to the texture coordinate array. 00227 * 00228 * \return texture coordinate array 00229 */ 00230 osg::ref_ptr< const osg::Vec3Array > getTextureCoordinateArray() const; 00231 00232 /** 00233 * getter 00234 * 00235 * \param forceRecalc 00236 * \return pointer to the vertex normal array 00237 */ 00238 osg::ref_ptr< osg::Vec3Array > getVertexNormalArray( bool forceRecalc = false ); 00239 00240 /** 00241 * getter 00242 * 00243 * \return pointer to the vertex color array 00244 */ 00245 osg::ref_ptr< osg::Vec4Array > getVertexColorArray(); 00246 00247 /** 00248 * Returns a const reference to the vertex ids of the triangles. 00249 * 00250 * \return The triangle vertex id list 00251 */ 00252 const std::vector< size_t >& getTriangles() const; 00253 00254 /** 00255 * getter 00256 * 00257 * \param forceRecalc 00258 * \return pointer to the triangle normal array 00259 */ 00260 osg::ref_ptr< osg::Vec3Array > getTriangleNormalArray( bool forceRecalc = false ); 00261 00262 00263 /** 00264 * getter 00265 * 00266 * \param index 00267 * \return vertex 00268 */ 00269 osg::Vec3 getVertex( size_t index ) const; 00270 00271 /** 00272 * getter 00273 * 00274 * \param index 00275 * \return color 00276 */ 00277 osg::Vec4 getVertColor( size_t index ) const; 00278 00279 /** 00280 * getter 00281 * 00282 * \param triId 00283 * \param vertNum 00284 * \return vertex 00285 */ 00286 osg::Vec3 getTriVert( size_t triId, size_t vertNum ); 00287 00288 /** 00289 * getter 00290 * 00291 * \param index 00292 * \return normal 00293 */ 00294 WVector3d getNormal( size_t index ) const; 00295 00296 /** 00297 * getter 00298 * 00299 * \return number of vertices in the mesh 00300 */ 00301 size_t vertSize() const; 00302 00303 /** 00304 * getter 00305 * 00306 * \return number of triangles in the mesh 00307 */ 00308 size_t triangleSize() const; 00309 00310 /** 00311 * performs a loop subdivision on the triangle mesh 00312 */ 00313 void doLoopSubD(); 00314 00315 /** 00316 * returns the id of the first vertex of a triangle 00317 * 00318 * \param triId id of the triangle 00319 * \return id of the vertex 00320 */ 00321 size_t getTriVertId0( size_t triId ) const; 00322 00323 /** 00324 * returns the id of the second vertex of a triangle 00325 * 00326 * \param triId id of the triangle 00327 * \return id of the vertex 00328 */ 00329 size_t getTriVertId1( size_t triId ) const; 00330 00331 /** 00332 * return the id of the third vertex of a triangle 00333 * 00334 * \param triId id of the triangle 00335 * \return id of the vertex 00336 */ 00337 size_t getTriVertId2( size_t triId ) const; 00338 00339 /** 00340 * adds a mesh to the existing, no check for duplicate vertexes is performed, an additional 00341 * vector may be specified to move the mesh to add 00342 * 00343 * \param mesh 00344 * \param xOff 00345 * \param yOff 00346 * \param zOff 00347 */ 00348 void addMesh( boost::shared_ptr<WTriangleMesh> mesh, float xOff = 0., float yOff = 0., float zOff = 0. ); 00349 00350 /** 00351 * moves the entire mesh to a new postion 00352 * 00353 * \param xOff 00354 * \param yOff 00355 * \param zOff 00356 */ 00357 void translateMesh( float xOff, float yOff, float zOff ); 00358 00359 /** 00360 * multiplies the vertex vectors of the mesh with a given number 00361 * 00362 * \param zoom 00363 */ 00364 void zoomMesh( float zoom ); 00365 00366 /** 00367 * Checks if two meshes are exactly the same. Same number of triangles, and 00368 * points, and indices as well as same ordering. Keep in mind different 00369 * ordering might result in the same structure but is considered different 00370 * here. 00371 * 00372 * \param rhs The other mesh to compare with 00373 * 00374 * \return True if and only if both: vertices and triangles are exactly the same. 00375 */ 00376 bool operator==( const WTriangleMesh& rhs ) const; 00377 00378 protected: 00379 static boost::shared_ptr< WPrototyped > m_prototype; //!< The prototype as singleton. 00380 private: 00381 /** 00382 * we don't allow the standard constructor 00383 */ 00384 WTriangleMesh(); 00385 00386 /** 00387 * removes a vertex from the vertex array, if any triangles still index that vertex they will be 00388 * removed if forceRemoveTriangle is true 00389 * 00390 * \param index the index of the vertex to remove 00391 */ 00392 void removeVertex( size_t index ); 00393 00394 /** 00395 * removes a triangle from the mesh 00396 * 00397 * \param index the triangle to remove 00398 */ 00399 void removeTriangle( size_t index ); 00400 00401 /** 00402 * recalculates the vertex normals 00403 */ 00404 void recalcVertNormals(); 00405 00406 /** 00407 * calculates a normal from the 3 points in space defining a triangle 00408 * 00409 * \param triangle 00410 * 00411 * \return the normal of the triangle 00412 */ 00413 osg::Vec3 calcTriangleNormal( size_t triangle ); 00414 00415 /** 00416 * calculates a normal from the 3 points in space 00417 * 00418 * \param vert0 vertex 1 00419 * \param vert1 vertex 2 00420 * \param vert2 vertex 3 00421 * 00422 * \return the normal of the plane defined by these three points 00423 */ 00424 osg::Vec3 calcNormal( osg::Vec3 vert0, osg::Vec3 vert1, osg::Vec3 vert2 ); 00425 00426 /** 00427 * updates the list for which vertexes appear in which triangle 00428 */ 00429 void updateVertsInTriangles(); 00430 00431 /** 00432 * calculates neighbor information for triangles 00433 */ 00434 void calcNeighbors(); 00435 00436 /** 00437 * returns the triangle index of a triangle neighboring a given edge of a vertex 00438 * 00439 * \param coVert1 00440 * \param coVert2 00441 * \param triangleNum 00442 * 00443 * \return the number of the neighboring triangle. 00444 */ 00445 size_t getNeighbor( const size_t coVert1, const size_t coVert2, const size_t triangleNum ); 00446 00447 /** 00448 * higher level access function to the triangle vector, sets the first vertex of a triangle to 00449 * a given vertex id 00450 * 00451 * \param triId the id of the triangle to modify 00452 * \param vertId new id of the first vertex 00453 */ 00454 void setTriVert0( size_t triId, size_t vertId ); 00455 00456 /** 00457 * higher level access function to the triangle vector, sets the second vertex of a triangle to 00458 * a given vertex id 00459 * 00460 * \param triId the id of the triangle to modify 00461 * \param vertId new id of the second vertex 00462 */ 00463 void setTriVert1( size_t triId, size_t vertId ); 00464 00465 /** 00466 * higher level access function to the triangle vector, sets the third vertex of a triangle to 00467 * a given vertex id 00468 * 00469 * \param triId the id of the triangle to modify 00470 * \param vertId new id of the third vertex 00471 */ 00472 void setTriVert2( size_t triId, size_t vertId ); 00473 00474 00475 // the next functions are helper functions for the loop subdivision algorithm and exist only for that 00476 // purpose, for more information read http://research.microsoft.com/en-us/um/people/cloop/thesis.pdf 00477 00478 00479 /** 00480 * changes the vertex ids of a triangle 00481 * 00482 * \param triId 00483 * \param vertId1 00484 * \param vertId2 00485 * \param vertId3 00486 */ 00487 void loopSetTriangle( size_t triId, size_t vertId1, size_t vertId2, size_t vertId3 ); 00488 00489 /** 00490 * erases a triangle from the vertexe's list of triangles it is part of 00491 * 00492 * \param triId 00493 * \param vertId 00494 */ 00495 void loopEraseTriangleFromVertex( size_t triId, size_t vertId ); 00496 00497 /** 00498 * calculates the new position of a vertex depending on it's location in the grid and number of neighbors 00499 * 00500 * \param vertId the vertex id 00501 * \return new position in 3D space 00502 */ 00503 osg::Vec3 loopCalcNewPosition( size_t vertId ); 00504 00505 /** 00506 * inserts the center triangle in a given triangle, 00507 * 00508 * \param triId the triangle id 00509 */ 00510 void loopInsertCenterTriangle( size_t triId ); 00511 00512 /** 00513 * inserts the 3 corner triangles in a given triangle 00514 * 00515 * \param triId the triangle id 00516 */ 00517 void loopInsertCornerTriangles( size_t triId ); 00518 00519 /** 00520 * calculates the vertex id for a given edge, inserts a new vertex of none exists yet 00521 * 00522 * \param triId the triangle id 00523 * \param edgeV1 00524 * \param edgeV2 00525 * \param V3 00526 * \return index of the vertex 00527 */ 00528 size_t loopCalcEdgeVert( size_t triId, size_t edgeV1, size_t edgeV2, size_t V3 ); 00529 00530 /** 00531 * loop helper function 00532 * \param n 00533 * \return alpha 00534 */ 00535 double loopGetAlpha( int n ); 00536 00537 /** 00538 * returns the id of the next vertex int he triangle 00539 * 00540 * \param triNum id of the triangle 00541 * \param vertNum id of the vertex 00542 * \return id of the next vertex 00543 */ 00544 size_t loopGetNextVertex( size_t triNum, size_t vertNum ); 00545 00546 /** 00547 * returns the id of the third vertex of a triangle for two given vertexes 00548 * 00549 * \param coVert1 00550 * \param coVert2 00551 * \param triangleNum 00552 * \return id of the third vertex 00553 */ 00554 size_t loopGetThirdVert( size_t coVert1, size_t coVert2, size_t triangleNum ); 00555 00556 00557 size_t m_countVerts; //!< number of vertexes in the mesh 00558 00559 size_t m_countTriangles; //!< number of triangles in the mesh 00560 00561 bool m_meshDirty; //!< flag indicating a change took place which requires a recalculation of components 00562 00563 bool m_neighborsCalculated; //!< flag indicating whether the neighbor information has been calculated yet 00564 00565 osg::ref_ptr< osg::Vec3Array > m_verts; //!< array containing the vertices 00566 00567 osg::ref_ptr< osg::Vec3Array > m_textureCoordinates; //!< array containing the texture coordinates 00568 00569 osg::ref_ptr< osg::Vec3Array > m_vertNormals; //!< array containing the vertex normals 00570 00571 osg::ref_ptr< osg::Vec4Array > m_vertColors; //!< array containing vertex colors 00572 00573 std::vector< size_t > m_triangles; //!< array containing the triangles 00574 00575 osg::ref_ptr< osg::Vec3Array > m_triangleNormals; //!< array containing the triangle normals 00576 00577 osg::ref_ptr< osg::Vec4Array > m_triangleColors; //!< array containing the triangle colors 00578 00579 // helper structures 00580 std::vector < std::vector< size_t > > m_vertexIsInTriangle; //!< for each vertex, list of triangles it is part of 00581 00582 std::vector< std::vector< size_t > > m_triangleNeighbors; //!< edge neighbors for each triangle 00583 00584 size_t m_numTriVerts; //!< stores the number of vertexes before the loop subdivion is run, needed by the loop algorithm 00585 00586 size_t m_numTriFaces; //!< stores the number of triangles before the loop subdivion is run, needed by the loop algorithm 00587 }; 00588 00589 /** 00590 * TriangleMesh utils 00591 */ 00592 namespace tm_utils 00593 { 00594 /** 00595 * Decompose the given mesh into connected components. 00596 * 00597 * \param mesh The triangle mesh to decompose 00598 * 00599 * \return List of components where each of them is a WTriangleMesh again. 00600 */ 00601 WGE_EXPORT boost::shared_ptr< std::list< boost::shared_ptr< WTriangleMesh > > > componentDecomposition( const WTriangleMesh& mesh ); 00602 00603 /** 00604 * Prints for each mesh \#vertices and \#triangles, as well as each triangle with its positions. No point IDs are printed. 00605 * 00606 * \param os Output stream to print on. 00607 * \param rhs The mesh instance. 00608 * 00609 * \return The output stream again for further usage. 00610 */ 00611 WGE_EXPORT std::ostream& operator<<( std::ostream& os, const WTriangleMesh& rhs ); 00612 } 00613 00614 inline bool WTriangleMesh::operator==( const WTriangleMesh& rhs ) const 00615 { 00616 return std::equal( m_verts->begin(), m_verts->end(), rhs.m_verts->begin() ) && 00617 std::equal( m_triangles.begin(), m_triangles.end(), rhs.m_triangles.begin() ); 00618 } 00619 00620 inline void WTriangleMesh::addTextureCoordinate( osg::Vec3 texCoord ) 00621 { 00622 ( *m_textureCoordinates )[m_countVerts-1] = texCoord; 00623 } 00624 00625 inline void WTriangleMesh::addTextureCoordinate( float x, float y, float z ) 00626 { 00627 addTextureCoordinate( osg::Vec3( x, y, z ) ); 00628 } 00629 00630 inline void WTriangleMesh::addVertex( osg::Vec3 vert ) 00631 { 00632 if( ( *m_verts ).size() == m_countVerts ) 00633 { 00634 ( *m_verts ).resize( m_countVerts + 1 ); 00635 } 00636 if( ( *m_textureCoordinates ).size() == m_countVerts ) 00637 { 00638 ( *m_textureCoordinates ).resize( m_countVerts + 1 ); 00639 } 00640 00641 ( *m_verts )[m_countVerts] = vert; 00642 ++m_countVerts; 00643 } 00644 00645 inline const std::string WTriangleMesh::getName() const 00646 { 00647 return "WTriangleMesh"; 00648 } 00649 00650 inline const std::string WTriangleMesh::getDescription() const 00651 { 00652 return "Triangle mesh data structure allowing for convenient access of the elements."; 00653 } 00654 00655 inline void WTriangleMesh::setTriVert0( size_t triId, size_t vertId ) 00656 { 00657 WAssert( triId < m_countTriangles, "set tri vert 0: triangle id out of range" ); 00658 WAssert( vertId < m_countVerts, "vertex id out of range" ); 00659 m_triangles[ triId * 3 ] = vertId; 00660 } 00661 00662 inline void WTriangleMesh::setTriVert1( size_t triId, size_t vertId ) 00663 { 00664 WAssert( triId < m_countTriangles, "set tri vert 1: triangle id out of range" ); 00665 WAssert( vertId < m_countVerts, "vertex id out of range" ); 00666 m_triangles[ triId * 3 + 1] = vertId; 00667 } 00668 00669 inline void WTriangleMesh::setTriVert2( size_t triId, size_t vertId ) 00670 { 00671 WAssert( triId < m_countTriangles, "set tri vert 2: triangle id out of range" ); 00672 WAssert( vertId < m_countVerts, "vertex id out of range" ); 00673 m_triangles[ triId * 3 + 2] = vertId; 00674 } 00675 00676 inline osg::Vec3 WTriangleMesh::getTriVert( size_t triId, size_t vertNum ) 00677 { 00678 WAssert( triId < m_countTriangles, "triangle id out of range" ); 00679 return ( *m_verts )[ m_triangles[ triId * 3 + vertNum] ]; 00680 } 00681 00682 inline size_t WTriangleMesh::getTriVertId0( size_t triId ) const 00683 { 00684 WAssert( triId < m_countTriangles, "get tri vert id 0: triangle id out of range" ); 00685 return m_triangles[triId * 3]; 00686 } 00687 00688 inline size_t WTriangleMesh::getTriVertId1( size_t triId ) const 00689 { 00690 WAssert( triId < m_countTriangles, "get tri vert id 1: triangle id out of range" ); 00691 return m_triangles[triId * 3 + 1]; 00692 } 00693 00694 inline size_t WTriangleMesh::getTriVertId2( size_t triId ) const 00695 { 00696 WAssert( triId < m_countTriangles, "get tri vert id 2: triangle id out of range" ); 00697 return m_triangles[triId * 3 + 2]; 00698 } 00699 00700 inline void WTriangleMesh::setVertex( size_t index, osg::Vec3 vert ) 00701 { 00702 ( *m_verts )[index] = vert; 00703 } 00704 00705 #endif // WTRIANGLEMESH_H