ccMesh.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. //##########################################################################
  2. //# #
  3. //# CLOUDCOMPARE #
  4. //# #
  5. //# This program is free software; you can redistribute it and/or modify #
  6. //# it under the terms of the GNU General Public License as published by #
  7. //# the Free Software Foundation; version 2 or later of the License. #
  8. //# #
  9. //# This program is distributed in the hope that it will be useful, #
  10. //# but WITHOUT ANY WARRANTY; without even the implied warranty of #
  11. //# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
  12. //# GNU General Public License for more details. #
  13. //# #
  14. //# COPYRIGHT: EDF R&D / TELECOM ParisTech (ENST-TSI) #
  15. //# #
  16. //##########################################################################
  17. #ifndef CC_MESH_HEADER
  18. #define CC_MESH_HEADER
  19. //CCCoreLib
  20. #include <PointProjectionTools.h>
  21. #include <SimpleTriangle.h>
  22. //Local
  23. #include "ccGenericMesh.h"
  24. class ccProgressDialog;
  25. class ccPolyline;
  26. //! Triangular mesh
  27. class QCC_DB_LIB_API ccMesh : public ccGenericMesh
  28. {
  29. public:
  30. //! Default ccMesh constructor
  31. /** \param vertices the vertices cloud
  32. \param uniqueID unique ID (handle with care)
  33. **/
  34. explicit ccMesh(ccGenericPointCloud* vertices, unsigned uniqueID = ccUniqueIDGenerator::InvalidUniqueID);
  35. //! ccMesh constructor (from a CCCoreLib::GenericIndexedMesh)
  36. /** The GenericIndexedMesh must be associated to a valid ccGenericPointCloud instance.
  37. \param giMesh the mesh to 'copy'
  38. \param giVertices associated vertices (can technically be different from the input mesh vertices, but should have at least as many points)
  39. **/
  40. explicit ccMesh(CCCoreLib::GenericIndexedMesh* giMesh, ccGenericPointCloud* giVertices);
  41. //! Default destructor
  42. ~ccMesh() override;
  43. //! Returns class ID
  44. inline CC_CLASS_ENUM getClassID() const override { return CC_TYPES::MESH; }
  45. //! Sets the associated vertices cloud (warning)
  46. void setAssociatedCloud(ccGenericPointCloud* cloud);
  47. //! Clones this entity
  48. /** All the main features of the entity are cloned, except from the octree
  49. \param vertices vertices set to use (will be automatically - AND OPTIMALLY - cloned if nullptr)
  50. \param clonedMaterials for internal use
  51. \param clonedNormsTable for internal use
  52. \param cloneTexCoords for internal use
  53. \return a copy of this entity
  54. **/
  55. ccMesh* cloneMesh( ccGenericPointCloud* vertices = nullptr,
  56. ccMaterialSet* clonedMaterials = nullptr,
  57. NormsIndexesTableType* clonedNormsTable = nullptr,
  58. TextureCoordsContainer* cloneTexCoords = nullptr);
  59. //! Creates a Delaunay 2.5D mesh from a point cloud
  60. /** See CCCoreLib::PointProjectionTools::computeTriangulation.
  61. **/
  62. static ccMesh* Triangulate( ccGenericPointCloud* cloud,
  63. CCCoreLib::TRIANGULATION_TYPES type,
  64. bool updateNormals = false,
  65. PointCoordinateType maxEdgeLength = 0,
  66. unsigned char dim = 2);
  67. //! Creates a Delaunay 2.5D mesh from two polylines
  68. static ccMesh* TriangulateTwoPolylines(ccPolyline* p1, ccPolyline* p2, CCVector3* projectionDir = nullptr);
  69. //! Merges another mesh into this one
  70. /** \param mesh mesh to be merged in this one
  71. \param createSubMesh whether to create a submesh entity corresponding to the added mesh
  72. \return success
  73. **/
  74. bool merge(const ccMesh* mesh, bool createSubMesh);
  75. //inherited methods (ccHObject)
  76. ccBBox getOwnBB(bool withGLFeatures = false) override;
  77. bool isSerializable() const override { return true; }
  78. const ccGLMatrix& getGLTransformationHistory() const override;
  79. //inherited methods (ccGenericMesh)
  80. inline ccGenericPointCloud* getAssociatedCloud() const override { return m_associatedCloud; }
  81. void refreshBB() override;
  82. bool interpolateNormalsBC(unsigned triIndex, const CCVector3d& w, CCVector3& N) override;
  83. bool interpolateColors(unsigned triIndex, const CCVector3& P, ccColor::Rgb& C) override;
  84. bool interpolateColorsBC(unsigned triIndex, const CCVector3d& w, ccColor::Rgb& C) override;
  85. bool interpolateColors(unsigned triIndex, const CCVector3& P, ccColor::Rgba& C) override;
  86. bool interpolateColorsBC(unsigned triIndex, const CCVector3d& w, ccColor::Rgba& C) override;
  87. void computeInterpolationWeights(unsigned triIndex, const CCVector3& P, CCVector3d& weights) const override;
  88. bool getColorFromMaterial(unsigned triIndex, const CCVector3& P, ccColor::Rgba& C, bool interpolateColorIfNoTexture) override;
  89. bool getVertexColorFromMaterial(unsigned triIndex, unsigned char vertIndex, ccColor::Rgba& color, bool returnColorIfNoTexture) override;
  90. unsigned capacity() const override;
  91. //inherited methods (GenericIndexedMesh)
  92. void forEach(genericTriangleAction action) override;
  93. void placeIteratorAtBeginning() override;
  94. CCCoreLib::GenericTriangle* _getNextTriangle() override; //temporary
  95. CCCoreLib::GenericTriangle* _getTriangle(unsigned triangleIndex) override; //temporary
  96. CCCoreLib::VerticesIndexes* getNextTriangleVertIndexes() override;
  97. CCCoreLib::VerticesIndexes* getTriangleVertIndexes(unsigned triangleIndex) override;
  98. void getTriangleVertices(unsigned triangleIndex, CCVector3& A, CCVector3& B, CCVector3& C) const override;
  99. unsigned size() const override;
  100. void getBoundingBox(CCVector3& bbMin, CCVector3& bbMax) override;
  101. bool normalsAvailable() const override { return hasNormals(); }
  102. bool interpolateNormals(unsigned triIndex, const CCVector3& P, CCVector3& N) override;
  103. //const version of getTriangleVertIndexes
  104. const virtual CCCoreLib::VerticesIndexes* getTriangleVertIndexes(unsigned triangleIndex) const;
  105. //inherited methods (ccDrawableObject)
  106. bool hasColors() const override;
  107. bool hasNormals() const override;
  108. bool hasScalarFields() const override;
  109. bool hasDisplayedScalarField() const override;
  110. bool normalsShown() const override;
  111. void toggleMaterials() override { showMaterials(!materialsShown()); }
  112. //! Inverts normals (if any)
  113. /** Either the per-triangle normals, or the per-vertex ones
  114. **/
  115. void invertNormals();
  116. //! Shifts all triangles indexes
  117. /** \param shift index shift (positive)
  118. **/
  119. void shiftTriangleIndexes(unsigned shift);
  120. //! Flips the triangle
  121. /** Swaps the second and third vertices indexes
  122. **/
  123. void flipTriangles();
  124. //! Adds a triangle to the mesh
  125. /** \warning Bounding-box validity is broken after a call to this method.
  126. However, for the sake of performance, no call to notifyGeometryUpdate
  127. is made automatically. Make sure to do so when all modifications are done!
  128. \param i1 first vertex index (relatively to the vertex cloud)
  129. \param i2 second vertex index (relatively to the vertex cloud)
  130. \param i3 third vertex index (relatively to the vertex cloud)
  131. **/
  132. void addTriangle(unsigned i1, unsigned i2, unsigned i3);
  133. //! Reserves the memory to store the vertex indexes (3 per triangle)
  134. /** \param n the number of triangles to reserve
  135. \return true if the method succeeds, false otherwise
  136. **/
  137. bool reserve(size_t n);
  138. //! Resizes the array of vertex indexes (3 per triangle)
  139. /** If the new number of elements is smaller than the actual size,
  140. the overflooding elements will be deleted.
  141. \param n the new number of triangles
  142. \return true if the method succeeds, false otherwise
  143. **/
  144. bool resize(size_t n);
  145. //! Removes unused capacity
  146. inline void shrinkToFit() { if (size() < capacity()) resize(size()); }
  147. /*********************************************************/
  148. /************** PER-TRIANGLE NORMALS ***************/
  149. /*********************************************************/
  150. //inherited from ccGenericMesh
  151. bool hasTriNormals() const override;
  152. void getTriangleNormalIndexes(unsigned triangleIndex, int& i1, int& i2, int& i3) const override;
  153. bool getTriangleNormals(unsigned triangleIndex, CCVector3& Na, CCVector3& Nb, CCVector3& Nc) const override;
  154. NormsIndexesTableType* getTriNormsTable() const override { return m_triNormals; }
  155. //! Sets per-triangle normals array (may be shared)
  156. void setTriNormsTable(NormsIndexesTableType* triNormsTable, bool autoReleaseOldTable = true);
  157. //! Removes per-triangle normals
  158. void clearTriNormals() { setTriNormsTable(nullptr); }
  159. //! Returns whether per triangle normals are enabled
  160. /** To enable per triangle normals, you should:
  161. - first, reserve memory for triangles (this is always the first thing to do)
  162. - associate this mesh to a triangle normals array (see ccMesh::setTriNormsTable)
  163. - reserve memory to store per-triangle normal indexes with ccMesh::reservePerTriangleNormalIndexes
  164. - add for each triangle a triplet of indexes (referring to stored normals)
  165. **/
  166. bool arePerTriangleNormalsEnabled() const;
  167. //! Reserves memory to store per-triangle triplets of normal indexes
  168. /** Before adding per-triangle normal indexes triplets to
  169. the mesh (with ccMesh::addTriangleNormalsIndexes()) be
  170. sure to reserve the necessary amount of memory with
  171. this method. This method reserves memory for as many
  172. normals indexes triplets as the number of triangles
  173. in the mesh (effectively stored or reserved - a call to
  174. ccMesh::reserve prior to this one is mandatory).
  175. \return true if ok, false if there's not enough memory
  176. **/
  177. bool reservePerTriangleNormalIndexes();
  178. //! Adds a triplet of normal indexes for next triangle
  179. /** Make sure per-triangle normal indexes array is allocated
  180. (see reservePerTriangleNormalIndexes)
  181. \param i1 first vertex normal index
  182. \param i2 second vertex normal index
  183. \param i3 third vertex normal index
  184. **/
  185. void addTriangleNormalIndexes(int i1, int i2, int i3);
  186. //! Sets a triplet of normal indexes for a given triangle
  187. /** \param triangleIndex triangle index
  188. \param i1 first vertex normal index
  189. \param i2 second vertex normal index
  190. \param i3 third vertex normal index
  191. **/
  192. void setTriangleNormalIndexes(unsigned triangleIndex, int i1, int i2, int i3);
  193. //! Removes any per-triangle triplets of normal indexes
  194. void removePerTriangleNormalIndexes();
  195. //! Invert per-triangle normals
  196. void invertPerTriangleNormals();
  197. /********************************************************/
  198. /************ PER-TRIANGLE MATERIAL ***************/
  199. /********************************************************/
  200. //inherited from ccGenericMesh
  201. bool hasMaterials() const override;
  202. const ccMaterialSet* getMaterialSet() const override { return m_materials; }
  203. int getTriangleMtlIndex(unsigned triangleIndex) const override;
  204. //! Converts materials to vertex colors
  205. /** Warning: this method will overwrite colors (if any)
  206. **/
  207. bool convertMaterialsToVertexColors();
  208. //! Returns whether this mesh as per-triangle material index
  209. bool hasPerTriangleMtlIndexes() const { return m_triMtlIndexes && m_triMtlIndexes->isAllocated(); }
  210. //! Reserves memory to store per-triangle material index
  211. /** Before adding per-triangle material index to
  212. the mesh (with ccMesh::addTriangleMtlIndex()) be sure
  213. to reserve the necessary amount of memory with this
  214. method. This method reserves memory for as many
  215. material descriptors as the number of triangles in
  216. the mesh (effectively stored or reserved - a call to
  217. ccMesh::reserve prior to this one is mandatory).
  218. \return true if ok, false if there's not enough memory
  219. **/
  220. bool reservePerTriangleMtlIndexes();
  221. //! Removes any per-triangle material indexes
  222. void removePerTriangleMtlIndexes();
  223. //! Adds triangle material index for next triangle
  224. /** Cf. ccMesh::reservePerTriangleMtlIndexes.
  225. \param mtlIndex triangle material index
  226. **/
  227. void addTriangleMtlIndex(int mtlIndex);
  228. //! Container of per-triangle material descriptors
  229. using triangleMaterialIndexesSet = ccArray<int, 1, int>;
  230. //! Sets per-triangle material indexes array
  231. void setTriangleMtlIndexesTable(triangleMaterialIndexesSet* matIndexesTable, bool autoReleaseOldTable = true);
  232. //! Returns the per-triangle material indexes array
  233. inline const triangleMaterialIndexesSet* getTriangleMtlIndexesTable() const { return m_triMtlIndexes; }
  234. //! Sets triangle material indexes
  235. /** Cf. ccMesh::reservePerTriangleMtlIndexes.
  236. \param triangleIndex triangle index
  237. \param mtlIndex triangle material index
  238. **/
  239. void setTriangleMtlIndex(unsigned triangleIndex, int mtlIndex);
  240. //! Sets associated material set (may be shared)
  241. void setMaterialSet(ccMaterialSet* materialSet, bool autoReleaseOldMaterialSet = true);
  242. /******************************************************************/
  243. /************ PER-TRIANGLE TEXTURE COORDINATE ***************/
  244. /******************************************************************/
  245. //inherited from ccGenericMesh
  246. bool hasTextures() const override;
  247. TextureCoordsContainer* getTexCoordinatesTable() const override { return m_texCoords; }
  248. void getTriangleTexCoordinates(unsigned triIndex, TexCoords2D* &tx1, TexCoords2D* &tx2, TexCoords2D* &tx3) const override;
  249. bool hasPerTriangleTexCoordIndexes() const override { return m_texCoordIndexes && m_texCoordIndexes->isAllocated(); }
  250. void getTriangleTexCoordinatesIndexes(unsigned triangleIndex, int& i1, int& i2, int& i3) const override;
  251. //! Sets per-triangle texture coordinates array (may be shared)
  252. void setTexCoordinatesTable(TextureCoordsContainer* texCoordsTable, bool autoReleaseOldTable = true);
  253. //! Reserves memory to store per-triangle triplets of tex coords indexes
  254. /** Before adding per-triangle tex coords indexes triplets to
  255. the mesh (with ccMesh::addTriangleTexCoordIndexes()) be
  256. sure to reserve the necessary amount of memory with
  257. this method. This method reserves memory for as many
  258. tex coords indexes triplets as the number of triangles
  259. in the mesh (effectively stored or reserved - a call to
  260. ccMesh::reserve prior to this one is mandatory).
  261. \return true if ok, false if there's not enough memory
  262. **/
  263. bool reservePerTriangleTexCoordIndexes();
  264. //! Remove per-triangle tex coords indexes
  265. void removePerTriangleTexCoordIndexes();
  266. //! Adds a triplet of tex coords indexes for next triangle
  267. /** Make sure per-triangle tex coords indexes array is allocated
  268. (see reservePerTriangleTexCoordIndexes)
  269. \param i1 first vertex tex coords index
  270. \param i2 second vertex tex coords index
  271. \param i3 third vertex tex coords index
  272. **/
  273. void addTriangleTexCoordIndexes(int i1, int i2, int i3);
  274. //! Sets a triplet of tex coords indexes for a given triangle
  275. /** \param triangleIndex triangle index
  276. \param i1 first vertex tex coords index
  277. \param i2 second vertex tex coords index
  278. \param i3 third vertex tex coords index
  279. **/
  280. void setTriangleTexCoordIndexes(unsigned triangleIndex, int i1, int i2, int i3);
  281. //! Computes normals
  282. /** \param perVertex whether normals should be computed per-vertex or per-triangle
  283. \return success
  284. **/
  285. bool computeNormals(bool perVertex);
  286. //! Computes per-vertex normals
  287. bool computePerVertexNormals();
  288. //! Computes per-triangle normals
  289. bool computePerTriangleNormals();
  290. //! Laplacian smoothing
  291. /** \param nbIteration smoothing iterations
  292. \param factor smoothing 'force'
  293. \param progressCb progress dialog callback
  294. **/
  295. bool laplacianSmooth( unsigned nbIteration = 100,
  296. PointCoordinateType factor = static_cast<PointCoordinateType>(0.01),
  297. ccProgressDialog* progressCb = nullptr);
  298. //! Mesh scalar field processes
  299. enum MESH_SCALAR_FIELD_PROCESS { SMOOTH_MESH_SF, /**< Smooth **/
  300. ENHANCE_MESH_SF, /**< Enhance **/
  301. };
  302. //! Applies process to the mesh scalar field (the one associated to its vertices in fact)
  303. /** A very simple smoothing/enhancement algorithm based on
  304. each vertex direct neighbours. Prior to calling this method,
  305. one should check first that the vertices are associated to a
  306. scalar field.
  307. Warning: the processed scalar field must be enabled for both
  308. INPUT & OUTPUT! (see ccGenericCloud::setCurrentScalarField)
  309. \param process either 'smooth' or 'enhance'
  310. **/
  311. bool processScalarField(MESH_SCALAR_FIELD_PROCESS process);
  312. //! Subdivides mesh (so as to ensure that all triangles are falls below 'maxArea')
  313. /** \return subdivided mesh (if successful)
  314. **/
  315. ccMesh* subdivide(PointCoordinateType maxArea) const;
  316. //! Creates a new mesh with the selected vertices only
  317. /** This method is called after a graphical segmentation. It creates
  318. a new mesh structure with the vertices that are tagged as "visible"
  319. (see ccGenericPointCloud::visibilityArray).
  320. This method will also update this mesh if removeSelectedFaces is true.
  321. In this case, all "selected" triangles will be removed from this mesh's instance.
  322. \param removeSelectedTriangles specifies if the faces composed only of 'selected' vertices should be removed or not.
  323. If true, the visibility array will be automatically unallocated on completion
  324. \param newIndexesOfRemainingTriangles the new indexes of the remaining triangles (if removeSelectedTriangles is true - optional).
  325. Must be initially empty or have the same size as the original mesh.
  326. \param withChildEntities whether child entities should be transferred as well (see ccHObjectCaster::CloneChildren)
  327. \return the new mesh (if successful) or itself if all vertices were visible/selected
  328. **/
  329. ccMesh* createNewMeshFromSelection( bool removeSelectedTriangles,
  330. std::vector<int>* newIndexesOfRemainingTriangles = nullptr,
  331. bool withChildEntities = false );
  332. //! Swaps two triangles
  333. /** Automatically updates internal structures (i.e. lookup tables for
  334. material, normals, etc.).
  335. **/
  336. void swapTriangles(unsigned index1, unsigned index2);
  337. //! Transforms the mesh per-triangle normals
  338. void transformTriNormals(const ccGLMatrix& trans);
  339. //! Default octree level for the 'mergeDuplicatedVertices' algorithm
  340. static const unsigned char DefaultMergeDuplicateVerticesLevel = 10;
  341. //! Merges duplicated vertices
  342. bool mergeDuplicatedVertices(unsigned char octreeLevel = DefaultMergeDuplicateVerticesLevel, QWidget* parentWidget = nullptr);
  343. protected: //methods
  344. //inherited from ccHObject
  345. void drawMeOnly(CC_DRAW_CONTEXT& context) override;
  346. bool toFile_MeOnly(QFile& out, short dataVersion) const override;
  347. bool fromFile_MeOnly(QFile& in, short dataVersion, int flags, LoadedIDMap& oldToNewIDMap) override;
  348. short minimumFileVersion_MeOnly() const override;
  349. void applyGLTransformation(const ccGLMatrix& trans) override;
  350. void onUpdateOf(ccHObject* obj) override;
  351. void onDeletionOf(const ccHObject* obj) override;
  352. //! Same as other 'computeInterpolationWeights' method with a set of 3 vertices indexes
  353. void computeInterpolationWeights(const CCCoreLib::VerticesIndexes& vertIndexes, const CCVector3& P, CCVector3d& weights) const;
  354. //! Same as other 'interpolateNormals' method with a set of 3 vertices indexes
  355. bool interpolateNormals(const CCCoreLib::VerticesIndexes& vertIndexes, const CCVector3d& w, CCVector3& N, const Tuple3i* triNormIndexes = nullptr);
  356. //! Same as other 'interpolateColors' method with a set of 3 vertices indexes
  357. bool interpolateColors(const CCCoreLib::VerticesIndexes& vertIndexes, const CCVector3d& w, ccColor::Rgb& C);
  358. //! Same as other 'interpolateColors' method with a set of 3 vertices indexes
  359. bool interpolateColors(const CCCoreLib::VerticesIndexes& vertIndexes, const CCVector3d& w, ccColor::Rgba& C);
  360. //! Used internally by 'subdivide'
  361. bool pushSubdivide(/*PointCoordinateType maxArea, */unsigned indexA, unsigned indexB, unsigned indexC);
  362. /*** EXTENDED CALL SCRIPTS (FOR CC_SUB_MESHES) ***/
  363. //0 parameter
  364. #define ccMesh_extended_call0(baseName,recursiveName) \
  365. inline virtual void recursiveName() \
  366. { \
  367. baseName(); \
  368. for (Container::iterator it = m_children.begin(); it != m_children.end(); ++it) \
  369. if ((*it)->isA(CC_TYPES::SUB_MESH)) \
  370. static_cast<ccGenericMesh*>(*it)->baseName(); \
  371. } \
  372. //1 parameter
  373. #define ccMesh_extended_call1(baseName,param1Type,recursiveName) \
  374. inline virtual void recursiveName(param1Type p) \
  375. { \
  376. baseName(p); \
  377. for (Container::iterator it = m_children.begin(); it != m_children.end(); ++it) \
  378. if ((*it)->isA(CC_TYPES::SUB_MESH)) \
  379. static_cast<ccGenericMesh*>(*it)->baseName(p); \
  380. } \
  381. //recursive equivalents of some of ccGenericMesh methods (applied to sub-meshes as well)
  382. ccMesh_extended_call1(showNormals, bool, showNormals_extended)
  383. protected: //members
  384. //! associated cloud (vertices)
  385. ccGenericPointCloud* m_associatedCloud;
  386. //! Per-triangle normals
  387. NormsIndexesTableType* m_triNormals;
  388. //! Texture coordinates
  389. TextureCoordsContainer* m_texCoords;
  390. //! Materials
  391. ccMaterialSet* m_materials;
  392. //! Container of per-triangle vertices indexes (3)
  393. using triangleIndexesContainer = ccArray<CCCoreLib::VerticesIndexes, 3, unsigned>;
  394. //! Triangles' vertices indexes (3 per triangle)
  395. triangleIndexesContainer* m_triVertIndexes;
  396. //! Iterator on the list of triangles
  397. unsigned m_globalIterator;
  398. //! Dump triangle structure to transmit temporary data
  399. CCCoreLib::SimpleRefTriangle m_currentTriangle;
  400. //! Bounding-box
  401. ccBBox m_bBox;
  402. //! Per-triangle material indexes
  403. triangleMaterialIndexesSet* m_triMtlIndexes;
  404. //! Set of triplets of indexes referring to mesh texture coordinates
  405. using triangleTexCoordIndexesSet = ccArray<Tuple3i, 3, int>;
  406. //! Mesh tex coords indexes (per-triangle)
  407. triangleTexCoordIndexesSet* m_texCoordIndexes;
  408. //! Set of triplets of indexes referring to mesh normals
  409. using triangleNormalsIndexesSet = ccArray<Tuple3i, 3, int>;
  410. //! Mesh normals indexes (per-triangle)
  411. triangleNormalsIndexesSet* m_triNormalIndexes;
  412. private:
  413. //! Copy of a ccMesh instance is not supported (because of all the pointers to the members)
  414. ccMesh(const ccMesh&) {}
  415. };
  416. #endif //CC_MESH_HEADER