| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505 |
- //##########################################################################
- //# #
- //# CLOUDCOMPARE #
- //# #
- //# This program is free software; you can redistribute it and/or modify #
- //# it under the terms of the GNU General Public License as published by #
- //# the Free Software Foundation; version 2 or later of the License. #
- //# #
- //# This program 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 General Public License for more details. #
- //# #
- //# COPYRIGHT: EDF R&D / TELECOM ParisTech (ENST-TSI) #
- //# #
- //##########################################################################
- #ifndef CC_MESH_HEADER
- #define CC_MESH_HEADER
- //CCCoreLib
- #include <PointProjectionTools.h>
- #include <SimpleTriangle.h>
- //Local
- #include "ccGenericMesh.h"
- class ccProgressDialog;
- class ccPolyline;
- //! Triangular mesh
- class QCC_DB_LIB_API ccMesh : public ccGenericMesh
- {
- public:
- //! Default ccMesh constructor
- /** \param vertices the vertices cloud
- \param uniqueID unique ID (handle with care)
- **/
- explicit ccMesh(ccGenericPointCloud* vertices, unsigned uniqueID = ccUniqueIDGenerator::InvalidUniqueID);
- //! ccMesh constructor (from a CCCoreLib::GenericIndexedMesh)
- /** The GenericIndexedMesh must be associated to a valid ccGenericPointCloud instance.
- \param giMesh the mesh to 'copy'
- \param giVertices associated vertices (can technically be different from the input mesh vertices, but should have at least as many points)
- **/
- explicit ccMesh(CCCoreLib::GenericIndexedMesh* giMesh, ccGenericPointCloud* giVertices);
- //! Default destructor
- ~ccMesh() override;
-
- //! Returns class ID
- inline CC_CLASS_ENUM getClassID() const override { return CC_TYPES::MESH; }
- //! Sets the associated vertices cloud (warning)
- void setAssociatedCloud(ccGenericPointCloud* cloud);
- //! Clones this entity
- /** All the main features of the entity are cloned, except from the octree
- \param vertices vertices set to use (will be automatically - AND OPTIMALLY - cloned if nullptr)
- \param clonedMaterials for internal use
- \param clonedNormsTable for internal use
- \param cloneTexCoords for internal use
- \return a copy of this entity
- **/
- ccMesh* cloneMesh( ccGenericPointCloud* vertices = nullptr,
- ccMaterialSet* clonedMaterials = nullptr,
- NormsIndexesTableType* clonedNormsTable = nullptr,
- TextureCoordsContainer* cloneTexCoords = nullptr);
- //! Creates a Delaunay 2.5D mesh from a point cloud
- /** See CCCoreLib::PointProjectionTools::computeTriangulation.
- **/
- static ccMesh* Triangulate( ccGenericPointCloud* cloud,
- CCCoreLib::TRIANGULATION_TYPES type,
- bool updateNormals = false,
- PointCoordinateType maxEdgeLength = 0,
- unsigned char dim = 2);
- //! Creates a Delaunay 2.5D mesh from two polylines
- static ccMesh* TriangulateTwoPolylines(ccPolyline* p1, ccPolyline* p2, CCVector3* projectionDir = nullptr);
- //! Merges another mesh into this one
- /** \param mesh mesh to be merged in this one
- \param createSubMesh whether to create a submesh entity corresponding to the added mesh
- \return success
- **/
- bool merge(const ccMesh* mesh, bool createSubMesh);
- //inherited methods (ccHObject)
- ccBBox getOwnBB(bool withGLFeatures = false) override;
- bool isSerializable() const override { return true; }
- const ccGLMatrix& getGLTransformationHistory() const override;
- //inherited methods (ccGenericMesh)
- inline ccGenericPointCloud* getAssociatedCloud() const override { return m_associatedCloud; }
- void refreshBB() override;
- bool interpolateNormalsBC(unsigned triIndex, const CCVector3d& w, CCVector3& N) override;
- bool interpolateColors(unsigned triIndex, const CCVector3& P, ccColor::Rgb& C) override;
- bool interpolateColorsBC(unsigned triIndex, const CCVector3d& w, ccColor::Rgb& C) override;
- bool interpolateColors(unsigned triIndex, const CCVector3& P, ccColor::Rgba& C) override;
- bool interpolateColorsBC(unsigned triIndex, const CCVector3d& w, ccColor::Rgba& C) override;
- void computeInterpolationWeights(unsigned triIndex, const CCVector3& P, CCVector3d& weights) const override;
- bool getColorFromMaterial(unsigned triIndex, const CCVector3& P, ccColor::Rgba& C, bool interpolateColorIfNoTexture) override;
- bool getVertexColorFromMaterial(unsigned triIndex, unsigned char vertIndex, ccColor::Rgba& color, bool returnColorIfNoTexture) override;
- unsigned capacity() const override;
- //inherited methods (GenericIndexedMesh)
- void forEach(genericTriangleAction action) override;
- void placeIteratorAtBeginning() override;
- CCCoreLib::GenericTriangle* _getNextTriangle() override; //temporary
- CCCoreLib::GenericTriangle* _getTriangle(unsigned triangleIndex) override; //temporary
- CCCoreLib::VerticesIndexes* getNextTriangleVertIndexes() override;
- CCCoreLib::VerticesIndexes* getTriangleVertIndexes(unsigned triangleIndex) override;
- void getTriangleVertices(unsigned triangleIndex, CCVector3& A, CCVector3& B, CCVector3& C) const override;
- unsigned size() const override;
- void getBoundingBox(CCVector3& bbMin, CCVector3& bbMax) override;
- bool normalsAvailable() const override { return hasNormals(); }
- bool interpolateNormals(unsigned triIndex, const CCVector3& P, CCVector3& N) override;
- //const version of getTriangleVertIndexes
- const virtual CCCoreLib::VerticesIndexes* getTriangleVertIndexes(unsigned triangleIndex) const;
- //inherited methods (ccDrawableObject)
- bool hasColors() const override;
- bool hasNormals() const override;
- bool hasScalarFields() const override;
- bool hasDisplayedScalarField() const override;
- bool normalsShown() const override;
- void toggleMaterials() override { showMaterials(!materialsShown()); }
- //! Inverts normals (if any)
- /** Either the per-triangle normals, or the per-vertex ones
- **/
- void invertNormals();
- //! Shifts all triangles indexes
- /** \param shift index shift (positive)
- **/
- void shiftTriangleIndexes(unsigned shift);
- //! Flips the triangle
- /** Swaps the second and third vertices indexes
- **/
- void flipTriangles();
- //! Adds a triangle to the mesh
- /** \warning Bounding-box validity is broken after a call to this method.
- However, for the sake of performance, no call to notifyGeometryUpdate
- is made automatically. Make sure to do so when all modifications are done!
- \param i1 first vertex index (relatively to the vertex cloud)
- \param i2 second vertex index (relatively to the vertex cloud)
- \param i3 third vertex index (relatively to the vertex cloud)
- **/
- void addTriangle(unsigned i1, unsigned i2, unsigned i3);
- //! Reserves the memory to store the vertex indexes (3 per triangle)
- /** \param n the number of triangles to reserve
- \return true if the method succeeds, false otherwise
- **/
- bool reserve(size_t n);
- //! Resizes the array of vertex indexes (3 per triangle)
- /** If the new number of elements is smaller than the actual size,
- the overflooding elements will be deleted.
- \param n the new number of triangles
- \return true if the method succeeds, false otherwise
- **/
- bool resize(size_t n);
- //! Removes unused capacity
- inline void shrinkToFit() { if (size() < capacity()) resize(size()); }
- /*********************************************************/
- /************** PER-TRIANGLE NORMALS ***************/
- /*********************************************************/
- //inherited from ccGenericMesh
- bool hasTriNormals() const override;
- void getTriangleNormalIndexes(unsigned triangleIndex, int& i1, int& i2, int& i3) const override;
- bool getTriangleNormals(unsigned triangleIndex, CCVector3& Na, CCVector3& Nb, CCVector3& Nc) const override;
- NormsIndexesTableType* getTriNormsTable() const override { return m_triNormals; }
- //! Sets per-triangle normals array (may be shared)
- void setTriNormsTable(NormsIndexesTableType* triNormsTable, bool autoReleaseOldTable = true);
- //! Removes per-triangle normals
- void clearTriNormals() { setTriNormsTable(nullptr); }
- //! Returns whether per triangle normals are enabled
- /** To enable per triangle normals, you should:
- - first, reserve memory for triangles (this is always the first thing to do)
- - associate this mesh to a triangle normals array (see ccMesh::setTriNormsTable)
- - reserve memory to store per-triangle normal indexes with ccMesh::reservePerTriangleNormalIndexes
- - add for each triangle a triplet of indexes (referring to stored normals)
- **/
- bool arePerTriangleNormalsEnabled() const;
- //! Reserves memory to store per-triangle triplets of normal indexes
- /** Before adding per-triangle normal indexes triplets to
- the mesh (with ccMesh::addTriangleNormalsIndexes()) be
- sure to reserve the necessary amount of memory with
- this method. This method reserves memory for as many
- normals indexes triplets as the number of triangles
- in the mesh (effectively stored or reserved - a call to
- ccMesh::reserve prior to this one is mandatory).
- \return true if ok, false if there's not enough memory
- **/
- bool reservePerTriangleNormalIndexes();
- //! Adds a triplet of normal indexes for next triangle
- /** Make sure per-triangle normal indexes array is allocated
- (see reservePerTriangleNormalIndexes)
- \param i1 first vertex normal index
- \param i2 second vertex normal index
- \param i3 third vertex normal index
- **/
- void addTriangleNormalIndexes(int i1, int i2, int i3);
- //! Sets a triplet of normal indexes for a given triangle
- /** \param triangleIndex triangle index
- \param i1 first vertex normal index
- \param i2 second vertex normal index
- \param i3 third vertex normal index
- **/
- void setTriangleNormalIndexes(unsigned triangleIndex, int i1, int i2, int i3);
- //! Removes any per-triangle triplets of normal indexes
- void removePerTriangleNormalIndexes();
- //! Invert per-triangle normals
- void invertPerTriangleNormals();
- /********************************************************/
- /************ PER-TRIANGLE MATERIAL ***************/
- /********************************************************/
- //inherited from ccGenericMesh
- bool hasMaterials() const override;
- const ccMaterialSet* getMaterialSet() const override { return m_materials; }
- int getTriangleMtlIndex(unsigned triangleIndex) const override;
- //! Converts materials to vertex colors
- /** Warning: this method will overwrite colors (if any)
- **/
- bool convertMaterialsToVertexColors();
- //! Returns whether this mesh as per-triangle material index
- bool hasPerTriangleMtlIndexes() const { return m_triMtlIndexes && m_triMtlIndexes->isAllocated(); }
- //! Reserves memory to store per-triangle material index
- /** Before adding per-triangle material index to
- the mesh (with ccMesh::addTriangleMtlIndex()) be sure
- to reserve the necessary amount of memory with this
- method. This method reserves memory for as many
- material descriptors as the number of triangles in
- the mesh (effectively stored or reserved - a call to
- ccMesh::reserve prior to this one is mandatory).
- \return true if ok, false if there's not enough memory
- **/
- bool reservePerTriangleMtlIndexes();
- //! Removes any per-triangle material indexes
- void removePerTriangleMtlIndexes();
- //! Adds triangle material index for next triangle
- /** Cf. ccMesh::reservePerTriangleMtlIndexes.
- \param mtlIndex triangle material index
- **/
- void addTriangleMtlIndex(int mtlIndex);
- //! Container of per-triangle material descriptors
- using triangleMaterialIndexesSet = ccArray<int, 1, int>;
- //! Sets per-triangle material indexes array
- void setTriangleMtlIndexesTable(triangleMaterialIndexesSet* matIndexesTable, bool autoReleaseOldTable = true);
- //! Returns the per-triangle material indexes array
- inline const triangleMaterialIndexesSet* getTriangleMtlIndexesTable() const { return m_triMtlIndexes; }
- //! Sets triangle material indexes
- /** Cf. ccMesh::reservePerTriangleMtlIndexes.
- \param triangleIndex triangle index
- \param mtlIndex triangle material index
- **/
- void setTriangleMtlIndex(unsigned triangleIndex, int mtlIndex);
- //! Sets associated material set (may be shared)
- void setMaterialSet(ccMaterialSet* materialSet, bool autoReleaseOldMaterialSet = true);
- /******************************************************************/
- /************ PER-TRIANGLE TEXTURE COORDINATE ***************/
- /******************************************************************/
- //inherited from ccGenericMesh
- bool hasTextures() const override;
- TextureCoordsContainer* getTexCoordinatesTable() const override { return m_texCoords; }
- void getTriangleTexCoordinates(unsigned triIndex, TexCoords2D* &tx1, TexCoords2D* &tx2, TexCoords2D* &tx3) const override;
- bool hasPerTriangleTexCoordIndexes() const override { return m_texCoordIndexes && m_texCoordIndexes->isAllocated(); }
- void getTriangleTexCoordinatesIndexes(unsigned triangleIndex, int& i1, int& i2, int& i3) const override;
- //! Sets per-triangle texture coordinates array (may be shared)
- void setTexCoordinatesTable(TextureCoordsContainer* texCoordsTable, bool autoReleaseOldTable = true);
- //! Reserves memory to store per-triangle triplets of tex coords indexes
- /** Before adding per-triangle tex coords indexes triplets to
- the mesh (with ccMesh::addTriangleTexCoordIndexes()) be
- sure to reserve the necessary amount of memory with
- this method. This method reserves memory for as many
- tex coords indexes triplets as the number of triangles
- in the mesh (effectively stored or reserved - a call to
- ccMesh::reserve prior to this one is mandatory).
- \return true if ok, false if there's not enough memory
- **/
- bool reservePerTriangleTexCoordIndexes();
- //! Remove per-triangle tex coords indexes
- void removePerTriangleTexCoordIndexes();
- //! Adds a triplet of tex coords indexes for next triangle
- /** Make sure per-triangle tex coords indexes array is allocated
- (see reservePerTriangleTexCoordIndexes)
- \param i1 first vertex tex coords index
- \param i2 second vertex tex coords index
- \param i3 third vertex tex coords index
- **/
- void addTriangleTexCoordIndexes(int i1, int i2, int i3);
- //! Sets a triplet of tex coords indexes for a given triangle
- /** \param triangleIndex triangle index
- \param i1 first vertex tex coords index
- \param i2 second vertex tex coords index
- \param i3 third vertex tex coords index
- **/
- void setTriangleTexCoordIndexes(unsigned triangleIndex, int i1, int i2, int i3);
- //! Computes normals
- /** \param perVertex whether normals should be computed per-vertex or per-triangle
- \return success
- **/
- bool computeNormals(bool perVertex);
- //! Computes per-vertex normals
- bool computePerVertexNormals();
- //! Computes per-triangle normals
- bool computePerTriangleNormals();
- //! Laplacian smoothing
- /** \param nbIteration smoothing iterations
- \param factor smoothing 'force'
- \param progressCb progress dialog callback
- **/
- bool laplacianSmooth( unsigned nbIteration = 100,
- PointCoordinateType factor = static_cast<PointCoordinateType>(0.01),
- ccProgressDialog* progressCb = nullptr);
- //! Mesh scalar field processes
- enum MESH_SCALAR_FIELD_PROCESS { SMOOTH_MESH_SF, /**< Smooth **/
- ENHANCE_MESH_SF, /**< Enhance **/
- };
- //! Applies process to the mesh scalar field (the one associated to its vertices in fact)
- /** A very simple smoothing/enhancement algorithm based on
- each vertex direct neighbours. Prior to calling this method,
- one should check first that the vertices are associated to a
- scalar field.
- Warning: the processed scalar field must be enabled for both
- INPUT & OUTPUT! (see ccGenericCloud::setCurrentScalarField)
- \param process either 'smooth' or 'enhance'
- **/
- bool processScalarField(MESH_SCALAR_FIELD_PROCESS process);
- //! Subdivides mesh (so as to ensure that all triangles are falls below 'maxArea')
- /** \return subdivided mesh (if successful)
- **/
- ccMesh* subdivide(PointCoordinateType maxArea) const;
- //! Creates a new mesh with the selected vertices only
- /** This method is called after a graphical segmentation. It creates
- a new mesh structure with the vertices that are tagged as "visible"
- (see ccGenericPointCloud::visibilityArray).
- This method will also update this mesh if removeSelectedFaces is true.
- In this case, all "selected" triangles will be removed from this mesh's instance.
- \param removeSelectedTriangles specifies if the faces composed only of 'selected' vertices should be removed or not.
- If true, the visibility array will be automatically unallocated on completion
- \param newIndexesOfRemainingTriangles the new indexes of the remaining triangles (if removeSelectedTriangles is true - optional).
- Must be initially empty or have the same size as the original mesh.
- \param withChildEntities whether child entities should be transferred as well (see ccHObjectCaster::CloneChildren)
- \return the new mesh (if successful) or itself if all vertices were visible/selected
- **/
- ccMesh* createNewMeshFromSelection( bool removeSelectedTriangles,
- std::vector<int>* newIndexesOfRemainingTriangles = nullptr,
- bool withChildEntities = false );
- //! Swaps two triangles
- /** Automatically updates internal structures (i.e. lookup tables for
- material, normals, etc.).
- **/
- void swapTriangles(unsigned index1, unsigned index2);
- //! Transforms the mesh per-triangle normals
- void transformTriNormals(const ccGLMatrix& trans);
- //! Default octree level for the 'mergeDuplicatedVertices' algorithm
- static const unsigned char DefaultMergeDuplicateVerticesLevel = 10;
- //! Merges duplicated vertices
- bool mergeDuplicatedVertices(unsigned char octreeLevel = DefaultMergeDuplicateVerticesLevel, QWidget* parentWidget = nullptr);
- protected: //methods
- //inherited from ccHObject
- void drawMeOnly(CC_DRAW_CONTEXT& context) override;
- bool toFile_MeOnly(QFile& out, short dataVersion) const override;
- bool fromFile_MeOnly(QFile& in, short dataVersion, int flags, LoadedIDMap& oldToNewIDMap) override;
- short minimumFileVersion_MeOnly() const override;
- void applyGLTransformation(const ccGLMatrix& trans) override;
- void onUpdateOf(ccHObject* obj) override;
- void onDeletionOf(const ccHObject* obj) override;
- //! Same as other 'computeInterpolationWeights' method with a set of 3 vertices indexes
- void computeInterpolationWeights(const CCCoreLib::VerticesIndexes& vertIndexes, const CCVector3& P, CCVector3d& weights) const;
- //! Same as other 'interpolateNormals' method with a set of 3 vertices indexes
- bool interpolateNormals(const CCCoreLib::VerticesIndexes& vertIndexes, const CCVector3d& w, CCVector3& N, const Tuple3i* triNormIndexes = nullptr);
- //! Same as other 'interpolateColors' method with a set of 3 vertices indexes
- bool interpolateColors(const CCCoreLib::VerticesIndexes& vertIndexes, const CCVector3d& w, ccColor::Rgb& C);
- //! Same as other 'interpolateColors' method with a set of 3 vertices indexes
- bool interpolateColors(const CCCoreLib::VerticesIndexes& vertIndexes, const CCVector3d& w, ccColor::Rgba& C);
- //! Used internally by 'subdivide'
- bool pushSubdivide(/*PointCoordinateType maxArea, */unsigned indexA, unsigned indexB, unsigned indexC);
- /*** EXTENDED CALL SCRIPTS (FOR CC_SUB_MESHES) ***/
-
- //0 parameter
- #define ccMesh_extended_call0(baseName,recursiveName) \
- inline virtual void recursiveName() \
- { \
- baseName(); \
- for (Container::iterator it = m_children.begin(); it != m_children.end(); ++it) \
- if ((*it)->isA(CC_TYPES::SUB_MESH)) \
- static_cast<ccGenericMesh*>(*it)->baseName(); \
- } \
- //1 parameter
- #define ccMesh_extended_call1(baseName,param1Type,recursiveName) \
- inline virtual void recursiveName(param1Type p) \
- { \
- baseName(p); \
- for (Container::iterator it = m_children.begin(); it != m_children.end(); ++it) \
- if ((*it)->isA(CC_TYPES::SUB_MESH)) \
- static_cast<ccGenericMesh*>(*it)->baseName(p); \
- } \
- //recursive equivalents of some of ccGenericMesh methods (applied to sub-meshes as well)
- ccMesh_extended_call1(showNormals, bool, showNormals_extended)
- protected: //members
- //! associated cloud (vertices)
- ccGenericPointCloud* m_associatedCloud;
- //! Per-triangle normals
- NormsIndexesTableType* m_triNormals;
- //! Texture coordinates
- TextureCoordsContainer* m_texCoords;
- //! Materials
- ccMaterialSet* m_materials;
- //! Container of per-triangle vertices indexes (3)
- using triangleIndexesContainer = ccArray<CCCoreLib::VerticesIndexes, 3, unsigned>;
- //! Triangles' vertices indexes (3 per triangle)
- triangleIndexesContainer* m_triVertIndexes;
- //! Iterator on the list of triangles
- unsigned m_globalIterator;
- //! Dump triangle structure to transmit temporary data
- CCCoreLib::SimpleRefTriangle m_currentTriangle;
- //! Bounding-box
- ccBBox m_bBox;
- //! Per-triangle material indexes
- triangleMaterialIndexesSet* m_triMtlIndexes;
- //! Set of triplets of indexes referring to mesh texture coordinates
- using triangleTexCoordIndexesSet = ccArray<Tuple3i, 3, int>;
- //! Mesh tex coords indexes (per-triangle)
- triangleTexCoordIndexesSet* m_texCoordIndexes;
- //! Set of triplets of indexes referring to mesh normals
- using triangleNormalsIndexesSet = ccArray<Tuple3i, 3, int>;
- //! Mesh normals indexes (per-triangle)
- triangleNormalsIndexesSet* m_triNormalIndexes;
- private:
- //! Copy of a ccMesh instance is not supported (because of all the pointers to the members)
- ccMesh(const ccMesh&) {}
- };
- #endif //CC_MESH_HEADER
|