//--------------------------------------------------------------------------- // // Project: OpenWalnut ( http://www.openwalnut.org ) // // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS // For more information see http://www.openwalnut.org/copying // // This file is part of OpenWalnut. // // OpenWalnut is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // OpenWalnut is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with OpenWalnut. If not, see . // //--------------------------------------------------------------------------- #ifndef WTRIANGLEMESH2_H #define WTRIANGLEMESH2_H #include #include #include #include "../common/WColor.h" #include "../common/WTransferable.h" #include "../common/math/WVector3D.h" #include "../common/WAssert.h" /** * Triangle mesh data structure allowing for convenient access of the elements. */ class WTriangleMesh2 : public WTransferable { public: /** * constructor that already reserves space for a given number of triangles and vertexes * * \param vertNum * \param triangleNum */ WTriangleMesh2( size_t vertNum, size_t triangleNum ); /** * destructor */ ~WTriangleMesh2(); /** * Returns a prototype instantiated with the true type of the deriving class. * * \return the prototype. */ static boost::shared_ptr< WPrototyped > getPrototype(); /** * Gets the name of this prototype. * * \return the name. */ virtual const std::string getName() const; /** * Gets the description for this prototype. * * \return the description */ virtual const std::string getDescription() const; /** * adds a vertex position to the mesh * * \param vert */ void addVertex( osg::Vec3 vert ); /** * adds a vertex position to the mesh * * \param x * \param y * \param z */ void addVertex( float x, float y, float z ); /** * adds a vertex position to the mesh * * \param vert */ void addVertex( wmath::WPosition vert ); /** * adds a tringle to the mesh * * \param vert0 index of the first vertex * \param vert1 index of the second vertex * \param vert2 index of the third vertex */ void addTriangle( size_t vert0, size_t vert1, size_t vert2 ); /** * adds a tringle and its 3 vertexes to the mesh * * \param vert0 position of the first vertex * \param vert1 position of the second vertex * \param vert2 position of the third vertex */ void addTriangle( osg::Vec3 vert0, osg::Vec3 vert1, osg::Vec3 vert2 ); /** * sets the normal for a given vertex * * \param index * \param normal */ void setVertexNormal( size_t index, osg::Vec3 normal ); /** * sets the normal for a given vertex * * \param index * \param normal */ void setVertexNormal( size_t index, wmath::WPosition normal ); /** * sets the color for a given vertex * * \param index * \param color */ void setVertexColor( size_t index, osg::Vec4 color ); /** * sets the color for a given vertex * * \param index * \param color */ void setVertexColor( size_t index, WColor color ); /** * sets the color for a given triangle * * \param index * \param color */ void setTriangleColor( size_t index, osg::Vec4 color ); /** * sets the color for a given triangle * * \param index * \param color */ void setTriangleColor( size_t index, WColor color ); /** * getter * * \return pointer to the vertex array */ osg::ref_ptr< osg::Vec3Array >getVertexArray(); /** * getter * * \param forceRecalc * \return pointer to the vertex normal array */ osg::ref_ptr< osg::Vec3Array >getVertexNormalArray( bool forceRecalc = false ); /** * getter * * \return pointer to the vertex color array */ osg::ref_ptr< osg::Vec4Array >getVertexColorArray(); /** * getter * * \return the triangle list */ std::vector< size_t >getTriangles(); /** * getter * * \param index * \return vertex */ osg::Vec3 getVertex( size_t index ); /** * getter * * \param triId * \param vertNum * \return vertex */ osg::Vec3 getTriVert( size_t triId, size_t vertNum ); /** * getter * * \param index * \return vertex */ wmath::WPosition getVertexAsPosition( size_t index ); /** * getter * * \param triangleIndex * \param vertNum * \return vertex */ wmath::WPosition getVertexAsPosition( size_t triangleIndex, size_t vertNum ); /** * getter * * \return number of vertexes in the mesh */ size_t vertSize(); /** * getter * * \return number of triangles in the mesh */ size_t triangleSize(); /** * performs a loop subdivision on the triangle mesh */ void doLoopSubD(); protected: static boost::shared_ptr< WPrototyped > m_prototype; //!< The prototype as singleton. private: /** * we don't allow the standard constructor */ WTriangleMesh2(); /** * removes a vertex from the vertex array, if any triangles still index that vertex they will be * removed if forceRemoveTriangle is true * * \param index the index of the vertex to remove */ void removeVertex( size_t index ); /** * removes a triangle from the mesh * * \param index the triangle to remove */ void removeTriangle( size_t index ); /** * removes any vertex that isn't indexed by a triangle */ void cleanUpMesh(); /** * recalculates the vertex normals */ void recalcVertNormals(); /** * calculates a normal from the 3 points in space defining a triangle * * \param triangle */ osg::Vec3 calcTriangleNormal( size_t triangle ); /** * calculates a normal from the 3 points in space * * \param vert0 * \param vert1 * \param vert2 */ osg::Vec3 calcNormal( osg::Vec3 vert0, osg::Vec3 vert1, osg::Vec3 vert2 ); /** * updates the list for which vertexes appear in which triangle */ void updateVertsInTriangles(); /** * calculates neighbor information for triangles */ void calcNeighbors(); /** * returns the triangle index of a triangle neighboring a given edge of a vertex * * \param coVert1 * \param coVert2 * \param triangleNum */ size_t getNeighbor( const size_t coVert1, const size_t coVert2, const size_t triangleNum ); /** * higher level access function to the triangle vector, sets the first vertex of a triangle to * a given vertex id * * \param triId the id of the triangle to modify * \param vertId new id of the first vertex */ void setTriVert0( size_t triId, size_t vertId ); /** * higher level access function to the triangle vector, sets the second vertex of a triangle to * a given vertex id * * \param triId the id of the triangle to modify * \param vertId new id of the second vertex */ void setTriVert1( size_t triId, size_t vertId ); /** * higher level access function to the triangle vector, sets the third vertex of a triangle to * a given vertex id * * \param triId the id of the triangle to modify * \param vertId new id of the third vertex */ void setTriVert2( size_t triId, size_t vertId ); /** * returns the id of the first vertex of a triangle * * \param triId id of the triangle * \return id of the vertex */ size_t getTriVertId0( size_t triId ); /** * returns the id of the second vertex of a triangle * * \param triId id of the triangle * \return id of the vertex */ size_t getTriVertId1( size_t triId ); /** * return the id of the third vertex of a triangle * * \param triId id of the triangle * \return id of the vertex */ size_t getTriVertId2( size_t triId ); // the next functions are helper functions for the loop subdivision algorithm and exist only for that // purpose, for more information read http://research.microsoft.com/en-us/um/people/cloop/thesis.pdf /** * changes the vertex ids of a triangle * * \param triId * \param vertId1 * \param vertId2 * \param vertId3 */ void loopSetTriangle( size_t triId, size_t vertId1, size_t vertId2, size_t vertId3 ); /** * erases a triangle from the vertexe's list of triangles it is part of * * \param triId * \param vertId */ void loopEraseTriangleFromVertex( size_t triId, size_t vertId ); /** * calculates the new position of a vertex depending on it's location in the grid and number of neighbors * * \param vertId the vertex id * \return new position in 3D space */ osg::Vec3 loopCalcNewPosition( size_t vertId ); /** * inserts the center triangle in a given triangle, * * \param triId the triangle id */ void loopInsertCenterTriangle( size_t triId ); /** * inserts the 3 corner triangles in a given triangle * * \param triId the triangle id */ void loopInsertCornerTriangles( size_t triId ); /** * calculates the vertex id for a given edge, inserts a new vertex of none exists yet * * \param triId the triangle id * \param edgeV1 * \param edgeV2 * \param V3 * \return index of the vertex */ size_t loopCalcEdgeVert( size_t triId, size_t edgeV1, size_t edgeV2, size_t V3 ); /** * loop helper function * \param n * \return alpha */ double loopGetAlpha( int n ); /** * returns the id of the next vertex int he triangle * * \param triNum id of the triangle * \param vertNum id of the vertex * \return id of the next vertex */ size_t loopGetNextVertex( size_t triNum, size_t vertNum ); /** * returns the id of the third vertex of a triangle for two given vertexes * * \param coVert1 * \param coVert2 * \param triangleNum * \return id of the third vertex */ size_t loopGetThirdVert( size_t coVert1, size_t coVert2, size_t triangleNum ); size_t m_countVerts; //!< number of vertexes in the mesh size_t m_countTriangles; //!< number of triangles in the mesh bool m_meshDirty; //!< flag indicating a change took place which requires a recalculation of components bool m_neighborsCalculated; //!< flag indicating whether the neighbor information has been calculated yet osg::ref_ptr< osg::Vec3Array >m_verts; //!< array containing the vertexes osg::ref_ptr< osg::Vec3Array >m_vertNormals; //!< array containing the vertex normals osg::ref_ptr< osg::Vec4Array >m_vertColors; //!< array containing vertex colors std::vector< size_t >m_triangles; //!< array containing the triangles osg::ref_ptr< osg::Vec3Array >m_triangleNormals; //!< array containing the triangle normals osg::ref_ptr< osg::Vec4Array >m_triangleColors; //!< array containing the triangle colors // helper structures std::vector < std::vector< size_t > >m_vertexIsInTriangle; //!< for each vertex, list of triangles it is part of std::vector< std::vector< size_t > > m_triangleNeighbors; //!< edge neighbors for each triangle size_t m_numTriVerts; //!< stores the number of vertexes before the loop subdivion is run, needed by the loop algorithm size_t m_numTriFaces; //!< stores the number of triangles before the loop subdivion is run, needed by the loop algorithm }; inline void WTriangleMesh2::addVertex( osg::Vec3 vert ) { if ( ( *m_verts ).size() == m_countVerts ) { ( *m_verts ).resize( m_countVerts + 1 ); } ( *m_verts )[m_countVerts] = vert; ++m_countVerts; } inline const std::string WTriangleMesh2::getName() const { return "WTriangleMesh"; } inline const std::string WTriangleMesh2::getDescription() const { return "Triangle mesh data structure allowing for convenient access of the elements."; } inline void WTriangleMesh2::setTriVert0( size_t triId, size_t vertId ) { WAssert( triId < m_countTriangles, "set tri vert 0: triangle id out of range" ); WAssert( vertId < m_countVerts, "vertex id out of range" ); m_triangles[ triId * 3 ] = vertId; } inline void WTriangleMesh2::setTriVert1( size_t triId, size_t vertId ) { WAssert( triId < m_countTriangles, "set tri vert 1: triangle id out of range" ); WAssert( vertId < m_countVerts, "vertex id out of range" ); m_triangles[ triId * 3 + 1] = vertId; } inline void WTriangleMesh2::setTriVert2( size_t triId, size_t vertId ) { WAssert( triId < m_countTriangles, "set tri vert 2: triangle id out of range" ); WAssert( vertId < m_countVerts, "vertex id out of range" ); m_triangles[ triId * 3 + 2] = vertId; } inline osg::Vec3 WTriangleMesh2::getTriVert( size_t triId, size_t vertNum ) { WAssert( triId < m_countTriangles, "triangle id out of range" ); return ( *m_verts )[ m_triangles[ triId * 3 + vertNum] ]; } inline size_t WTriangleMesh2::getTriVertId0( size_t triId ) { WAssert( triId < m_countTriangles, "get tri vert id 0: triangle id out of range" ); return m_triangles[triId * 3]; } inline size_t WTriangleMesh2::getTriVertId1( size_t triId ) { WAssert( triId < m_countTriangles, "get tri vert id 1: triangle id out of range" ); return m_triangles[triId * 3 + 1]; } inline size_t WTriangleMesh2::getTriVertId2( size_t triId ) { WAssert( triId < m_countTriangles, "get tri vert id 2: triangle id out of range" ); return m_triangles[triId * 3 + 2]; } #endif // WTRIANGLEMESH2_H