ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ecvGenericPrimitive.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include "ecvGenericPrimitive.h"
9 
10 #include "ecvDisplayTools.h"
11 #include "ecvPointCloud.h"
12 
14  const ccGLMatrix* transMat /*=0*/)
15  : ccMesh(new ccPointCloud("vertices")), m_drawPrecision(0) {
16  setName(name);
17  showNormals(true);
18 
19  ccPointCloud* vert = vertices();
20  assert(vert);
21  addChild(vert);
22  vert->setEnabled(false);
23  // we don't want the user to transform the vertices for instance (as they
24  // are only temporary)
25  vert->setLocked(true);
26 
27  if (transMat) m_transformation = *transMat;
28 }
29 
32  static_cast<ccPointCloud*>(m_associatedCloud)->setRGBColor(col);
33 }
34 
36  return static_cast<ccPointCloud*>(m_associatedCloud);
37 }
38 
40  const ccGenericPrimitive& prim) {
41  ccPointCloud* verts = vertices();
42  unsigned vertCount = verts->size();
43  unsigned facesCount = size();
44  unsigned triFacesNormCount =
46 
47  // count new number of vertices & faces
48  unsigned newVertCount = vertCount + prim.getAssociatedCloud()->size();
49  unsigned newFacesCount = facesCount + prim.size();
50  bool primHasVertNorms = prim.getAssociatedCloud()->hasNormals();
51  bool primHasFaceNorms = prim.hasTriNormals();
52  bool primHasColors = prim.getAssociatedCloud()->hasColors();
53 
54  if (primHasColors && !verts->hasColors()) {
55  if (verts->size() > 0 && !verts->setRGBColor(ecvColor::white)) {
56  CVLog::Error("[ccGenericPrimitive::operator +] Not enough memory!");
57  return *this;
58  }
59  }
60 
61  // reserve memory
62  if (verts->reserve(newVertCount) &&
63  (!primHasVertNorms || verts->reserveTheNormsTable()) &&
64  reserve(newFacesCount) &&
65  (!primHasFaceNorms || m_triNormalIndexes ||
67  if (primHasColors && !verts->hasColors()) {
68  if (!verts->reserveTheRGBTable()) {
70  "[ccGenericPrimitive::operator +] Not enough memory!");
71  return *this;
72  }
73  }
74 
75  // copy vertices & normals & colors
77  for (unsigned i = 0; i < cloud->size(); ++i) {
78  verts->addPoint(*cloud->getPoint(i));
79  if (primHasVertNorms) {
80  verts->addNormIndex(cloud->getPointNormalIndex(i));
81  }
82  if (primHasColors) {
83  verts->addRGBColor(cloud->getPointColor(i));
84  } else if (verts->hasColors()) {
86  }
87  }
88 
89  // copy face normals
90  if (primHasFaceNorms) {
91  const NormsIndexesTableType* primNorms = prim.getTriNormsTable();
92  assert(primNorms);
93  unsigned primTriNormCount = primNorms->currentSize();
94 
95  NormsIndexesTableType* normsTable =
97  if (!normsTable || !normsTable->reserveSafe(triFacesNormCount +
98  primTriNormCount)) {
100  "[ccGenericPrimitive::operator +] Not enough memory!");
101  return *this;
102  }
103 
104  // attach table if not done already
105  if (!m_triNormals) {
106  setTriNormsTable(normsTable);
107  assert(m_triNormals);
108  }
109 
110  for (unsigned i = 0; i < primTriNormCount; ++i) {
111  normsTable->addElement(primNorms->getValue(i));
112  }
113  }
114 
115  // copy faces
116  for (unsigned i = 0; i < prim.size(); ++i) {
117  const cloudViewer::VerticesIndexes* tsi =
118  prim.getTriangleVertIndexes(i);
119  addTriangle(vertCount + tsi->i1, vertCount + tsi->i2,
120  vertCount + tsi->i3);
121  if (primHasFaceNorms) {
122  const Tuple3i& normIndexes = prim.m_triNormalIndexes->at(i);
123  addTriangleNormalIndexes(triFacesNormCount + normIndexes.u[0],
124  triFacesNormCount + normIndexes.u[1],
125  triFacesNormCount + normIndexes.u[2]);
126  }
127  }
128  } else {
129  CVLog::Error("[ccGenericPrimitive::operator +] Not enough memory!");
130  }
131 
132  return *this;
133 }
134 
135 bool ccGenericPrimitive::toFile_MeOnly(QFile& out, short dataVersion) const {
136  assert(out.isOpen() && (out.openMode() & QIODevice::WriteOnly));
137  if (dataVersion < 21) {
138  assert(false);
139  return false;
140  }
141 
142  if (!ccMesh::toFile_MeOnly(out, dataVersion)) return false;
143 
144  // Transformation matrix backup (dataVersion>=21)
145  if (!m_transformation.toFile(out, dataVersion)) return false;
146 
147  //'drawing precision' (dataVersion>=21))
148  if (out.write((const char*)&m_drawPrecision, sizeof(unsigned)) < 0)
149  return WriteError();
150 
151  return true;
152 }
153 
155  short minVersion = std::max(static_cast<short>(21),
157  return std::max(minVersion, ccMesh::minimumFileVersion_MeOnly());
158 }
159 
161  short dataVersion,
162  int flags,
163  LoadedIDMap& oldToNewIDMap) {
164  if (!ccMesh::fromFile_MeOnly(in, dataVersion, flags, oldToNewIDMap))
165  return false;
166 
167  // HACK: first, we have to remove any 'wrongly' associated vertices cloud!
168  //(this is in fact the default one - automatically created on construction)
169  // while the true vertices come as a child (at least it should;)
172  removeChild(0);
173 
174  // Transformation matrix backup (dataVersion>=21)
175  if (!m_transformation.fromFile(in, dataVersion, flags, oldToNewIDMap))
176  return false;
177 
178  //'drawing precision' (dataVersion>=21))
179  if (in.read((char*)&m_drawPrecision, sizeof(unsigned)) < 0)
180  return ReadError();
181 
182  return true;
183 }
184 
186  if (m_drawPrecision == steps) return true;
187  if (steps < MIN_DRAWING_PRECISION) return false;
188 
189  m_drawPrecision = steps;
190 
191  return updateRepresentation();
192 }
193 
195  bool success = buildUp();
196  if (success) {
198  }
199 
200  return success;
201 }
202 
204  // transparent call
206 
207  // we update the vertices transformation
209 }
210 
212  return m_transformation;
213 }
214 
217 }
218 
221 }
222 
224  // we apply associated transformation but as a call
225  // to 'applyGLTransformation_recursive' will multiply
226  // this matrix by the new one, we must set the
227  // m_transformation matrix to identity first! (tricky, isn't it?)
228  ccGLMatrix oldTrans = m_transformation;
230  setGLTransformation(oldTrans);
232 }
233 
234 bool ccGenericPrimitive::init(unsigned vertCount,
235  bool vertNormals,
236  unsigned faceCounts,
237  unsigned faceNormCounts) {
238  ccPointCloud* verts = vertices();
239  assert(verts);
240  if (!verts) return false;
241 
242  /*** clear existing structures ***/
243 
244  // clear vertices & normals
245  bool keepOtherProps = (vertCount == verts->size());
246  if (keepOtherProps) {
247  verts->unalloactePoints();
248  verts->unallocateNorms();
249  } else {
250  verts->clear();
251  }
252 
253  // clear triangles indexes
254  assert(m_triVertIndexes);
256 
257  // clear per triangle normals
260  // DGM: if we do this we'll have issues with the DB tree depending on where
261  // when we call this method!
262  //{
263  // removeChild(m_triNormals);
264  // setTriNormsTable(0);
265  // assert(!m_triNormals);
266  // }
267 
268  /*** init necessary structures ***/
269 
270  if (vertCount && !verts->reserve(vertCount)) return false;
271 
272  if (vertNormals && !verts->reserveTheNormsTable()) {
273  verts->clear();
274  return false;
275  }
276 
277  if (faceCounts && !reserve(faceCounts)) {
278  verts->clear();
279  return false;
280  }
281 
282  if (faceNormCounts) {
283  NormsIndexesTableType* normsTable =
285  if (!normsTable || !normsTable->reserveSafe(faceNormCounts) ||
287  verts->clear();
289  delete normsTable;
290  return false;
291  }
292 
293  // attach table if not done already
294  if (!m_triNormals) {
295  setTriNormsTable(normsTable);
296  assert(m_triNormals);
297  }
298  }
299 
300  return true;
301 }
302 
304  ccGenericPrimitive* primitive) const {
305  if (primitive) {
306  //'clone' vertices (everything but the points that are already here)
307  if (primitive->m_associatedCloud && m_associatedCloud &&
308  m_associatedCloud->size() == primitive->m_associatedCloud->size()) {
309  primitive->m_associatedCloud =
312  }
313 
314  primitive->showNormals(normalsShown());
315  primitive->showColors(colorsShown());
316  primitive->showSF(sfShown());
317  // primitive->showMaterials(materialsShown());
318  // primitive->setName(getName()+QString(".clone"));
319  primitive->setVisible(isVisible());
320  primitive->setEnabled(isEnabled());
321  primitive->importParametersFrom(this);
322  } else {
323  // if the calling primitive provide a null pointer, it means that the
324  // cloned version creation failed!
325  CVLog::Warning("[ccGenericPrimitive::clone] Not enough memory!");
326  }
327 
328  return primitive;
329 }
std::string name
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
Definition: CVLog.cpp:133
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Definition: CVLog.cpp:143
Array of compressed 3D normals (single index)
Type u[3]
Definition: CVGeom.h:139
Type & getValue(size_t index)
Definition: ecvArray.h:100
bool reserveSafe(size_t count)
Reserves memory (no exception thrown)
Definition: ecvArray.h:56
unsigned currentSize() const
Definition: ecvArray.h:112
void addElement(const Type &value)
Definition: ecvArray.h:105
void clear(bool releaseMemory=false)
Definition: ecvArray.h:115
virtual bool colorsShown() const
Returns whether colors are shown or not.
virtual void setGLTransformation(const ccGLMatrix &trans)
Associates entity with a GL transformation (rotation + translation)
virtual bool isVisible() const
Returns whether entity is visible or not.
virtual bool hasColors() const
Returns whether colors are enabled or not.
virtual void setVisible(bool state)
Sets entity visibility.
virtual bool sfShown() const
Returns whether active scalar field is visible.
virtual bool hasNormals() const
Returns whether normals are enabled or not.
virtual void showColors(bool state)
Sets colors visibility.
virtual void showSF(bool state)
Sets active scalarfield visibility.
bool fromFile(QFile &in, short dataVersion, int flags, LoadedIDMap &oldToNewIDMap) override
Loads data from binary stream.
bool toFile(QFile &out, short dataVersion) const override
Saves data to binary stream.
short minimumFileVersion() const override
Returns the minimum file version required to save this instance.
virtual void toIdentity()
Sets matrix to identity.
Float version of ccGLMatrixTpl.
Definition: ecvGLMatrix.h:19
void showNormals(bool state) override
Sets normals visibility.
void importParametersFrom(const ccGenericMesh *mesh)
Imports the parameters from another mesh.
A 3D cloud interface with associated features (color, normals, octree, etc.)
virtual const ecvColor::Rgb & getPointColor(unsigned pointIndex) const =0
Returns color corresponding to a given point.
virtual ccGenericPointCloud * clone(ccGenericPointCloud *destCloud=nullptr, bool ignoreChildren=false)=0
Clones this entity.
virtual const CompressedNormType & getPointNormalIndex(unsigned pointIndex) const =0
Returns compressed normal corresponding to a given point.
Generic primitive interface.
void applyTransformationToVertices()
Applies associated transformation to vertices.
bool init(unsigned vertCount, bool vertNormals, unsigned faceCount, unsigned faceNormCount)
Inits internal structures.
virtual bool setDrawingPrecision(unsigned steps)
Sets drawing precision.
virtual void setColor(const ecvColor::Rgb &col)
Sets primitive color (shortcut)
virtual bool updateRepresentation()
Updates internal representation (as a mesh)
ccGenericPrimitive * finishCloneJob(ccGenericPrimitive *primitive) const
Finished 'clone' job (vertices color, etc.)
ccPointCloud * vertices()
Returns vertices.
const ccGLMatrix & getGLTransformationHistory() const override
inherited methods (ccHObject)
virtual void clearDrawings()
const ccGenericPrimitive & operator+=(const ccGenericPrimitive &prim)
Add operator.
unsigned m_drawPrecision
Drawing precision (for primitives that support this feature)
void applyGLTransformation(const ccGLMatrix &trans) override
Inherited from ccGenericMesh.
static const int MIN_DRAWING_PRECISION
Minimum drawing precision.
virtual void hideShowDrawings(CC_DRAW_CONTEXT &context)
ccGenericPrimitive(QString name=QString(), const ccGLMatrix *transMat=nullptr)
Default constructor.
bool toFile_MeOnly(QFile &out, short dataVersion) const override
Save own object data.
virtual bool buildUp()=0
Builds primitive.
bool fromFile_MeOnly(QFile &in, short dataVersion, int flags, LoadedIDMap &oldToNewIDMap) override
Loads own object data.
ccGLMatrix m_transformation
Associated transformation (applied to vertices)
short minimumFileVersion_MeOnly() const override
void applyGLTransformation_recursive(const ccGLMatrix *trans=nullptr)
Applies the active OpenGL transformation to the entity (recursive)
Definition: ecvHObject.cpp:948
unsigned getChildrenNumber() const
Returns the number of children.
Definition: ecvHObject.h:312
void removeChild(ccHObject *child)
virtual bool addChild(ccHObject *child, int dependencyFlags=DP_PARENT_OF_OTHER, int insertIndex=-1)
Adds a child.
Definition: ecvHObject.cpp:534
ccHObject * getChild(unsigned childPos) const
Returns the ith child.
Definition: ecvHObject.h:325
Triangular mesh.
Definition: ecvMesh.h:35
NormsIndexesTableType * getTriNormsTable() const override
Returns per-triangle normals shared array.
Definition: ecvMesh.h:344
void applyGLTransformation(const ccGLMatrix &trans) override
Applies a GL transformation to the entity.
Definition: ecvMesh.cpp:514
bool normalsShown() const override
Returns whether normals are shown or not.
Definition: ecvMesh.cpp:388
ccGenericPointCloud * m_associatedCloud
associated cloud (vertices)
Definition: ecvMesh.h:1490
void removePerTriangleNormalIndexes()
Removes any per-triangle triplets of normal indexes.
Definition: ecvMesh.cpp:3323
short minimumFileVersion_MeOnly() const override
Definition: ecvMesh.cpp:3870
bool toFile_MeOnly(QFile &out, short dataVersion) const override
Save own object data.
Definition: ecvMesh.cpp:3766
virtual unsigned size() const override
Returns the number of triangles.
Definition: ecvMesh.cpp:2143
void setTriNormsTable(NormsIndexesTableType *triNormsTable, bool autoReleaseOldTable=true)
Sets per-triangle normals array (may be shared)
Definition: ecvMesh.cpp:470
bool reserve(std::size_t n)
Reserves the memory to store the vertex indexes (3 per triangle)
Definition: ecvMesh.cpp:2475
ccGenericPointCloud * getAssociatedCloud() const override
Returns the vertices cloud.
Definition: ecvMesh.h:143
NormsIndexesTableType * m_triNormals
Per-triangle normals.
Definition: ecvMesh.h:1493
triangleNormalsIndexesSet * m_triNormalIndexes
Mesh normals indexes (per-triangle)
Definition: ecvMesh.h:1523
bool fromFile_MeOnly(QFile &in, short dataVersion, int flags, LoadedIDMap &oldToNewIDMap) override
Loads own object data.
Definition: ecvMesh.cpp:3877
void addTriangle(unsigned i1, unsigned i2, unsigned i3)
Adds a triangle to the mesh.
Definition: ecvMesh.cpp:2428
bool reservePerTriangleNormalIndexes()
Reserves memory to store per-triangle triplets of normal indexes.
Definition: ecvMesh.cpp:3328
void addTriangleNormalIndexes(int i1, int i2, int i3)
Adds a triplet of normal indexes for next triangle.
Definition: ecvMesh.cpp:3340
bool hasTriNormals() const override
Returns whether the mesh has per-triangle normals.
Definition: ecvMesh.cpp:3589
cloudViewer::VerticesIndexes * getTriangleVertIndexes(unsigned triangleIndex) override
Returns the indexes of the vertices of a given triangle.
Definition: ecvMesh.cpp:2599
triangleIndexesContainer * m_triVertIndexes
Triangles' vertices indexes (3 per triangle)
Definition: ecvMesh.h:1502
virtual void setLocked(bool state)
Sets the "enabled" property.
Definition: ecvObject.h:117
virtual QString getName() const
Returns object name.
Definition: ecvObject.h:72
virtual void setName(const QString &name)
Sets object name.
Definition: ecvObject.h:75
virtual void setEnabled(bool state)
Sets the "enabled" property.
Definition: ecvObject.h:102
virtual bool isEnabled() const
Returns whether the object is enabled or not.
Definition: ecvObject.h:97
bool isKindOf(CV_CLASS_ENUM type) const
Definition: ecvObject.h:128
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
void unalloactePoints()
Erases the cloud points.
bool reserve(unsigned numberOfPoints) override
Reserves memory for all the active features.
bool reserveTheNormsTable()
Reserves memory to store the compressed normals.
bool reserveTheRGBTable()
Reserves memory to store the RGB colors.
void clear() override
Clears the entity from all its points and features.
void unallocateNorms()
Erases the cloud normals.
bool hasColors() const override
Returns whether colors are enabled or not.
void addRGBColor(const ecvColor::Rgb &C)
Pushes an RGB color on stack.
bool setRGBColor(ColorCompType r, ColorCompType g, ColorCompType b)
Set a unique color for the whole cloud (shortcut)
void addNormIndex(CompressedNormType index)
Pushes a compressed normal vector.
QMultiMap< unsigned, unsigned > LoadedIDMap
Map of loaded unique IDs (old ID --> new ID)
static bool ReadError()
Sends a custom error message (read error) and returns 'false'.
static bool WriteError()
Sends a custom error message (write error) and returns 'false'.
virtual unsigned size() const =0
Returns the number of points.
virtual const CCVector3 * getPoint(unsigned index) const =0
Returns the ith point.
void addPoint(const CCVector3 &P)
Adds a 3D point to the database.
unsigned size() const override
Definition: PointCloudTpl.h:38
RGB color structure.
Definition: ecvColorTypes.h:49
static void RemoveEntities(const ccHObject *obj)
static bool HideShowEntities(const ccHObject *obj, bool visible)
ImGuiContext * context
Definition: Window.cpp:76
@ POINT_CLOUD
Definition: CVTypes.h:104
constexpr Rgb white(MAX, MAX, MAX)
Display context.
Triangle described by the indexes of its 3 vertices.