File: ccMesh.h

package info (click to toggle)
cloudcompare 2.10.1-2
  • links: PTS
  • area: main
  • in suites: buster
  • size: 55,916 kB
  • sloc: cpp: 219,837; ansic: 29,944; makefile: 67; sh: 45
file content (465 lines) | stat: -rw-r--r-- 19,555 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
//##########################################################################
//#                                                                        #
//#                              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

//CCLib
#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
	**/
	explicit ccMesh(ccGenericPointCloud* vertices);

	//! ccMesh constructor (from a CCLib::GenericIndexedMesh)
	/** The GenericIndexedMesh should refer to a known ccGenericPointCloud.
		\param giMesh the GenericIndexedMesh
		\param giVertices giMesh vertices
	**/
	explicit ccMesh(CCLib::GenericIndexedMesh* giMesh, ccGenericPointCloud* giVertices);

	//! Default destructor
	~ccMesh() override;
	
	//! Returns class ID
	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 0)
		\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 CCLib::PointProjectionTools::computeTriangulation.
	**/
	static ccMesh* Triangulate( ccGenericPointCloud* cloud,
								CC_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)
	unsigned getUniqueIDForDisplay() const override;
	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 interpolateNormals(unsigned triIndex, const CCVector3& P, CCVector3& N) override;
	bool interpolateColors(unsigned triIndex, const CCVector3& P, ccColor::Rgb& C) override;
	void computeInterpolationWeights(unsigned triIndex, const CCVector3& P, CCVector3d& weights) const override;
	bool getColorFromMaterial(unsigned triIndex, const CCVector3& P, ccColor::Rgb& C, bool interpolateColorIfNoTexture) override;
	bool getVertexColorFromMaterial(unsigned triIndex, unsigned char vertIndex, ccColor::Rgb& C, bool returnColorIfNoTexture) override;
	unsigned capacity() const override;

	//inherited methods (GenericIndexedMesh)
	void forEach(genericTriangleAction action) override;
	void placeIteratorAtBeginning() override;
	CCLib::GenericTriangle* _getNextTriangle() override; //temporary
	CCLib::GenericTriangle* _getTriangle(unsigned triangleIndex) override; //temporary
	CCLib::VerticesIndexes* getNextTriangleVertIndexes() override;
	CCLib::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;

	//const version of getTriangleVertIndexes
	const virtual CCLib::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()); }

	//! Shifts all triangles indexes
	/** \param shift index shift (positive)
	**/
	void shiftTriangleIndexes(unsigned shift);

	//! 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 (effictively 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();

	/********************************************************/
	/************    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 (effictively 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 (effictively 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 removeSelectedFaces specifies if the faces composed only of 'selected' vertices should be removed or not
	**/
	ccMesh* createNewMeshFromSelection(bool removeSelectedFaces);

	//! 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);

protected:

	//inherited from ccHObject
	void drawMeOnly(CC_DRAW_CONTEXT& context) override;
	bool toFile_MeOnly(QFile& out) const override;
	bool fromFile_MeOnly(QFile& in, short dataVersion, int flags) 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 CCLib::VerticesIndexes& vertIndexes, const CCVector3& P, CCVector3d& weights) const;
	//! Same as other 'interpolateNormals' method with a set of 3 vertices indexes
	bool interpolateNormals(const CCLib::VerticesIndexes& vertIndexes, const CCVector3& P, CCVector3& N, const Tuple3i* triNormIndexes = nullptr);
	//! Same as other 'interpolateColors' method with a set of 3 vertices indexes
	bool interpolateColors(const CCLib::VerticesIndexes& vertIndexes, const CCVector3& P, ccColor::Rgb& 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)

	//! 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<CCLib::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
	CCLib::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;
};

#endif //CC_MESH_HEADER