ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ecvGenericMesh.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 "ecvGenericMesh.h"
9 
10 // local
11 #include "ecvChunk.h"
12 #include "ecvColorScalesManager.h"
13 #include "ecvDisplayTools.h"
14 #include "ecvGenericPointCloud.h"
15 #include "ecvHObjectCaster.h"
16 #include "ecvMaterialSet.h"
17 #include "ecvNormalVectors.h"
18 #include "ecvPointCloud.h"
19 #include "ecvScalarField.h"
20 
21 // cloudViewer
22 #include <CVPointCloud.h>
24 #include <GenericTriangle.h>
25 #include <MeshSamplingTools.h>
26 #include <ReferenceCloud.h>
27 
28 // system
29 #include <QFileInfo>
30 #include <cassert>
31 
32 ccGenericMesh::ccGenericMesh(QString name /*=QString()*/)
33  : GenericIndexedMesh(),
35  m_triNormsShown(false),
36  m_materialsShown(false),
37  m_showWired(false),
38  m_showPoints(false),
39  m_stippling(false) {
40  setVisible(true);
41  lockVisibility(false);
42 }
43 
44 void ccGenericMesh::showNormals(bool state) {
45  showTriNorms(state);
47 }
48 
49 // stipple mask (for semi-transparent display of meshes)
50 static const GLubyte s_byte0 = 1 | 4 | 16 | 64;
51 static const GLubyte s_byte1 = 2 | 8 | 32 | 128;
52 static const GLubyte s_stippleMask[4 * 32] = {
69 
70 // Vertex buffer
72  static CCVector3 s_xyzBuffer[ccChunk::SIZE * 3];
73  return s_xyzBuffer;
74 }
75 
76 // Normals buffer
78  static CCVector3 s_normBuffer[ccChunk::SIZE * 3];
79  return s_normBuffer;
80 }
81 
82 // Colors buffer
84  static ecvColor::Rgb s_rgbBuffer[ccChunk::SIZE * 3];
85  return s_rgbBuffer;
86 }
87 
88 // Vertex indexes buffer (for wired display)
89 static unsigned s_vertWireIndexes[ccChunk::SIZE * 6];
90 static bool s_vertIndexesInitialized = false;
92  // on first call, we init the array
94  unsigned* _vertWireIndexes = s_vertWireIndexes;
95  for (unsigned i = 0; i < ccChunk::SIZE * 3; ++i) {
96  *_vertWireIndexes++ = i;
97  *_vertWireIndexes++ = (((i + 1) % 3) == 0 ? i - 2 : i + 1);
98  }
100  }
101 
102  return s_vertWireIndexes;
103 }
104 
106  if (MACRO_Draw2D(context)) {
107  if (MACRO_Foreground(context) && !context.sfColorScaleToDisplay) {
108  if (sfShown()) {
110  if (!vertices || !vertices->isA(CV_TYPES::POINT_CLOUD)) return;
111 
112  ccPointCloud* cloud = static_cast<ccPointCloud*>(vertices);
113 
114  // we just need to 'display' the current SF scale if the
115  // vertices cloud is hidden (otherwise, it will be taken in
116  // charge by the cloud itself)
117  if (!cloud->sfColorScaleShown() ||
118  (cloud->sfShown() && cloud->isEnabled() &&
119  cloud->isVisible()))
120  return;
121 
122  // we must also check that the parent is not a mesh itself with
123  // the same vertices! (in which case it will also take that in
124  // charge)
125  ccHObject* parent = getParent();
126  if (parent && parent->isKindOf(CV_TYPES::MESH) &&
128  ->getAssociatedCloud() == vertices))
129  return;
130 
131  cloud->addColorRampInfo(context);
132  // cloud->drawScale(context);
133  }
134  }
135  }
136 }
137 
140  if (!vertices) return;
141 
143 
144  if (!ecvDisplayTools::GetMainWindow()) return;
145 
146  // 3D pass
147  if (MACRO_Draw3D(context)) {
148  // any triangle?
149  unsigned triNum = size();
150  if (triNum == 0) return;
151 
152  // L.O.D.
153  bool lodEnabled =
154  (triNum > context.minLODTriangleCount &&
155  context.decimateMeshOnMove && MACRO_LODActivated(context));
156  unsigned decimStep =
157  (lodEnabled ? static_cast<unsigned>(
158  ceil(static_cast<double>(triNum * 3) /
159  context.minLODTriangleCount))
160  : 1);
161  unsigned displayedTriNum = triNum / decimStep;
162 
163  // display parameters
164  glDrawParams glParams;
165  getDrawingParameters(glParams);
166  // no normals shading without light!
167  glParams.showNorms &= bool(MACRO_LightIsEnabled(context));
168 
169  // vertices visibility
170  const ccGenericPointCloud::VisibilityTableType& verticesVisibility =
171  vertices->getTheVisibilityArray();
172  bool visFiltering = (verticesVisibility.size() == vertices->size());
173  context.visFiltering = visFiltering;
174 
175  // wireframe ? (not compatible with LOD)
176  bool showWired = isShownAsWire() && !lodEnabled;
177  bool isShowPoints = isShownAsPoints() && !lodEnabled;
178  if (showWired) {
180  }
181 
182  if (isShowPoints) {
183  context.meshRenderingMode = MESH_RENDERING_MODE::ECV_POINTS_MODE;
184  }
185  if (!showWired && !isShowPoints) {
187  }
188 
189  // per-triangle normals?
190  bool showTriNormals = (hasTriNormals() && triNormsShown());
191  // fix 'showNorms'
192  glParams.showNorms = showTriNormals ||
193  (vertices->hasNormals() && m_normalsDisplayed);
194 
195  // materials & textures
196  bool applyMaterials = (hasMaterials() && materialsShown());
197  bool showTextures = (hasTextures() && materialsShown() && !lodEnabled);
198 
199  // GL name pushing
200  bool entityPickingMode = MACRO_EntityPicking(context);
201  if (entityPickingMode) {
202  // not fast at all!
203  if (MACRO_FastEntityPicking(context)) return;
204  // minimal display for picking mode!
205  glParams.showNorms = false;
206  glParams.showColors = false;
207  // glParams.showSF --> we keep it only if SF 'NaN' values are
208  // hidden
209  showTriNormals = false;
210  applyMaterials = false;
211  showTextures = false;
212  }
213 
214  // in the case we need to display scalar field colors
215  ccScalarField* currentDisplayedScalarField = nullptr;
216  bool greyForNanScalarValues = true;
217  // unsigned colorRampSteps = 0;
218  ccColorScale::Shared colorScale(nullptr);
219 
220  if (glParams.showSF) {
221  assert(vertices->isA(CV_TYPES::POINT_CLOUD));
222  ccPointCloud* cloud = static_cast<ccPointCloud*>(vertices);
223 
224  greyForNanScalarValues = (cloud->getCurrentDisplayedScalarField() &&
227  if (greyForNanScalarValues && entityPickingMode) {
228  // in picking mode, no need to take SF into account if we
229  // don't hide any points!
230  glParams.showSF = false;
231  }
232  }
233 
234  if (glParams.showColors) {
235  if (isColorOverridden()) {
236  context.defaultMeshColor = m_tempColor;
237  } else {
238  assert(vertices->isA(CV_TYPES::POINT_CLOUD));
239  context.defaultMeshColor = static_cast<ccPointCloud*>(vertices)
240  ->rgbColors()
241  ->getValue(0);
242  }
243  } else {
244  context.defaultMeshColor = ecvColor::lightGrey;
245  }
246 
247  context.drawParam = glParams;
248 
250  }
251 }
252 
253 bool ccGenericMesh::toFile_MeOnly(QFile& out, short dataVersion) const {
254  assert(out.isOpen() && (out.openMode() & QIODevice::WriteOnly));
255  if (dataVersion < 29) {
256  assert(false);
257  return false;
258  }
259 
260  if (!ccHObject::toFile_MeOnly(out, dataVersion)) return false;
261 
262  //'show wired' state (dataVersion>=20)
263  if (out.write(reinterpret_cast<const char*>(&m_showWired), sizeof(bool)) <
264  0)
265  return WriteError();
266 
267  // //'show points' state (dataVersion>=20)
268  // if (out.write(reinterpret_cast<const char*>(&m_showPoints),
269  // sizeof(bool)) < 0) return WriteError();
270 
271  //'per-triangle normals shown' state (dataVersion>=29))
272  if (out.write(reinterpret_cast<const char*>(&m_triNormsShown),
273  sizeof(bool)) < 0)
274  return WriteError();
275 
276  //'materials shown' state (dataVersion>=29))
277  if (out.write(reinterpret_cast<const char*>(&m_materialsShown),
278  sizeof(bool)) < 0)
279  return WriteError();
280 
281  //'polygon stippling' state (dataVersion>=29))
282  if (out.write(reinterpret_cast<const char*>(&m_stippling), sizeof(bool)) <
283  0)
284  return WriteError();
285 
286  return true;
287 }
288 
290  return std::max(static_cast<short>(29),
292 }
293 
295  short dataVersion,
296  int flags,
297  LoadedIDMap& oldToNewIDMap) {
298  if (!ccHObject::fromFile_MeOnly(in, dataVersion, flags, oldToNewIDMap))
299  return false;
300 
301  //'show wired' state (dataVersion>=20)
302  if (in.read(reinterpret_cast<char*>(&m_showWired), sizeof(bool)) < 0)
303  return ReadError();
304 
305  // //'show points' state (dataVersion>=20)
306  // if (in.read(reinterpret_cast<char*>(&m_showPoints), sizeof(bool)) < 0)
307  // return ReadError();
308 
309  //'per-triangle normals shown' state (dataVersion>=29))
310  if (dataVersion >= 29) {
311  if (in.read(reinterpret_cast<char*>(&m_triNormsShown), sizeof(bool)) <
312  0)
313  return ReadError();
314 
315  //'materials shown' state (dataVersion>=29))
316  if (in.read(reinterpret_cast<char*>(&m_materialsShown), sizeof(bool)) <
317  0)
318  return ReadError();
319 
320  //'polygon stippling' state (dataVersion>=29))
321  if (in.read(reinterpret_cast<char*>(&m_stippling), sizeof(bool)) < 0)
322  return ReadError();
323  }
324 
325  return true;
326 }
327 
329  bool densityBased,
330  double samplingParameter,
331  bool withNormals,
332  bool withRGB,
333  bool withTexture,
334  cloudViewer::GenericProgressCallback* pDlg /*=nullptr*/) {
335  if (samplingParameter <= 0) {
336  assert(false);
337  return nullptr;
338  }
339 
340  bool withFeatures = (withNormals || withRGB || withTexture);
341 
342  QScopedPointer<std::vector<unsigned>> triIndices;
343  if (withFeatures) {
344  triIndices.reset(new std::vector<unsigned>);
345  }
346 
347  cloudViewer::PointCloud* sampledCloud = nullptr;
348  if (densityBased) {
350  this, samplingParameter, pDlg, triIndices.data());
351  } else {
353  this, static_cast<unsigned>(samplingParameter), pDlg,
354  triIndices.data());
355  }
356 
357  // convert to real point cloud
358  ccPointCloud* cloud = nullptr;
359 
360  if (sampledCloud) {
361  if (sampledCloud->size() == 0) {
363  "[ccGenericMesh::samplePoints] No point was generated "
364  "(sampling density is too low?)");
365  } else {
366  cloud = ccPointCloud::From(sampledCloud);
367  if (!cloud) {
369  "[ccGenericMesh::samplePoints] Not enough memory!");
370  }
371  }
372 
373  delete sampledCloud;
374  sampledCloud = nullptr;
375  } else {
376  CVLog::Warning("[ccGenericMesh::samplePoints] Not enough memory!");
377  }
378 
379  if (!cloud) {
380  return nullptr;
381  }
382 
383  if (withFeatures && triIndices && triIndices->size() >= cloud->size()) {
384  // generate normals
385  if (withNormals && hasNormals()) {
386  if (cloud->reserveTheNormsTable()) {
387  for (unsigned i = 0; i < cloud->size(); ++i) {
388  unsigned triIndex = triIndices->at(i);
389  const CCVector3* P = cloud->getPoint(i);
390 
391  CCVector3 N(0, 0, 1);
392  interpolateNormals(triIndex, *P, N);
393  cloud->addNorm(N);
394  }
395 
396  cloud->showNormals(true);
397  } else {
399  "[ccGenericMesh::samplePoints] Failed to interpolate "
400  "normals (not enough memory?)");
401  }
402  }
403 
404  // generate colors
405  if (withTexture && hasMaterials()) {
406  if (cloud->reserveTheRGBTable()) {
407  for (unsigned i = 0; i < cloud->size(); ++i) {
408  unsigned triIndex = triIndices->at(i);
409  const CCVector3* P = cloud->getPoint(i);
410 
411  ecvColor::Rgb C;
412  getColorFromMaterial(triIndex, *P, C, withRGB);
413  cloud->addRGBColor(C);
414  }
415 
416  cloud->showColors(true);
417  } else {
419  "[ccGenericMesh::samplePoints] Failed to export "
420  "texture colors (not enough memory?)");
421  }
422  } else if (withRGB && hasColors()) {
423  if (cloud->reserveTheRGBTable()) {
424  for (unsigned i = 0; i < cloud->size(); ++i) {
425  unsigned triIndex = triIndices->at(i);
426  const CCVector3* P = cloud->getPoint(i);
427 
428  ecvColor::Rgb C;
429  interpolateColors(triIndex, *P, C);
430  cloud->addRGBColor(C);
431  }
432 
433  cloud->showColors(true);
434  } else {
436  "[ccGenericMesh::samplePoints] Failed to interpolate "
437  "colors (not enough memory?)");
438  }
439  }
440  }
441 
442  // we rename the resulting cloud
443  cloud->setName(getName() + QString(".sampled"));
444 
445  // import parameters from both the source vertices and the source mesh
446  cloud->copyGlobalShiftAndScale(*this);
448 
449  return cloud;
450 }
451 
453  if (!mesh) {
454  assert(false);
455  return;
456  }
457 
458  // original shift & scale
460 
461  // stippling
463 
464  // wired style
465  showWired(mesh->isShownAsWire());
466 
467  // points style
468  showPoints(mesh->isShownAsPoints());
469 
470  // keep the transformation history!
472  // and meta-data
473  setMetaData(mesh->metaData());
474 }
475 
477  const CCVector3& P,
478  CCVector3d& weights) const {
480  const_cast<ccGenericMesh*>(this)->_getTriangle(triIndex);
481  const CCVector3* A = tri->_getA();
482  const CCVector3* B = tri->_getB();
483  const CCVector3* C = tri->_getC();
484 
485  // barcyentric intepolation weights
486  weights.x = ((P - *B).cross(*C - *B)).normd() /*/2*/;
487  weights.y = ((P - *C).cross(*A - *C)).normd() /*/2*/;
488  weights.z = ((P - *A).cross(*B - *A)).normd() /*/2*/;
489 
490  // normalize weights
491  double sum = weights.x + weights.y + weights.z;
492  weights /= sum;
493 }
494 
496  unsigned triIndex,
497  const CCVector2d& clickPos,
498  const ccGLMatrix& trans,
499  bool noGLTrans,
500  const ccGenericPointCloud& vertices,
501  const ccGLCameraParameters& camera,
502  CCVector3d& point,
503  CCVector3d* barycentricCoords /*=nullptr*/) const {
504  assert(triIndex < size());
505 
506  CCVector3 A3D;
507  CCVector3 B3D;
508  CCVector3 C3D;
509  getTriangleVertices(triIndex, A3D, B3D, C3D);
510 
511  CCVector3d A2D;
512  CCVector3d B2D;
513  CCVector3d C2D;
514  bool inFrustum = true;
515  if (noGLTrans) {
516  // if none of its points fall into the frustrum the triangle is not
517  // visible...
518  // DGM: we need to project ALL the points in case at least one is
519  // visible
520  bool insideA = camera.project(A3D, A2D, &inFrustum);
521  bool insideB = camera.project(B3D, B2D, &inFrustum);
522  bool insideC = camera.project(C3D, C2D, &inFrustum);
523  if (!insideA && !insideB && !insideC) {
524  return false;
525  }
526  } else {
527  CCVector3 A3Dp = trans * A3D;
528  CCVector3 B3Dp = trans * B3D;
529  CCVector3 C3Dp = trans * C3D;
530  // if none of its points fall into the frustrum the triangle is not
531  // visible...
532  // DGM: we need to project ALL the points in case at least one is
533  // visible
534  bool insideA = camera.project(A3Dp, A2D, &inFrustum);
535  bool insideB = camera.project(B3Dp, B2D, &inFrustum);
536  bool insideC = camera.project(C3Dp, C2D, &inFrustum);
537  if (!insideA && !insideB && !insideC) {
538  return false;
539  }
540  }
541 
542  // barycentric coordinates
543  GLdouble detT = (B2D.y - C2D.y) * (A2D.x - C2D.x) +
544  (C2D.x - B2D.x) * (A2D.y - C2D.y);
545  if (cloudViewer::LessThanEpsilon(std::abs(detT))) {
546  return false;
547  }
548  GLdouble l1 = ((B2D.y - C2D.y) * (clickPos.x - C2D.x) +
549  (C2D.x - B2D.x) * (clickPos.y - C2D.y)) /
550  detT;
551  GLdouble l2 = ((C2D.y - A2D.y) * (clickPos.x - C2D.x) +
552  (A2D.x - C2D.x) * (clickPos.y - C2D.y)) /
553  detT;
554 
555  // does the point falls inside the triangle?
556  if (l1 >= 0 && l1 <= 1.0 && l2 >= 0.0 && l2 <= 1.0) {
557  double l1l2 = l1 + l2;
558  assert(l1l2 >= -1.0e-12);
559  if (l1l2 > 1.0) {
560  // we fall outside of the triangle!
561  return false;
562  }
563 
564  GLdouble l3 = 1.0 - l1 - l2;
565  assert(l3 >= -1.0e-12);
566 
567  // now deduce the 3D position
568  point = CCVector3d(l1 * A3D.x + l2 * B3D.x + l3 * C3D.x,
569  l1 * A3D.y + l2 * B3D.y + l3 * C3D.y,
570  l1 * A3D.z + l2 * B3D.z + l3 * C3D.z);
571 
572  if (barycentricCoords) {
573  *barycentricCoords = CCVector3d(l1, l2, l3);
574  }
575 
576  return true;
577  } else {
578  return false;
579  }
580 }
581 
583  const CCVector2d& clickPos,
584  const ccGLCameraParameters& camera,
585  int& nearestTriIndex,
586  double& nearestSquareDist,
587  CCVector3d& nearestPoint,
588  CCVector3d* barycentricCoords /*=nullptr*/) const {
589  ccGLMatrix trans;
590  bool noGLTrans = !getAbsoluteGLTransformation(trans);
591 
592  // back project the clicked point in 3D
593  CCVector3d clickPosd(clickPos.x, clickPos.y, 0);
594  CCVector3d X(0, 0, 0);
595  if (!camera.unproject(clickPosd, X)) {
596  return false;
597  }
598 
599  nearestTriIndex = -1;
600  nearestSquareDist = -1.0;
601  nearestPoint = CCVector3d(0, 0, 0);
602  if (barycentricCoords) *barycentricCoords = CCVector3d(0, 0, 0);
603 
605  if (!vertices) {
606  assert(false);
607  return false;
608  }
609 
610 #if defined(_OPENMP) && !defined(_DEBUG)
611 #pragma omp parallel for
612 #endif
613  for (int i = 0; i < static_cast<int>(size()); ++i) {
614  CCVector3d P;
615  CCVector3d BC;
616  if (!trianglePicking(i, clickPos, trans, noGLTrans, *vertices, camera,
617  P, barycentricCoords ? &BC : nullptr))
618  continue;
619 
620  double squareDist = (X - P).norm2d();
621  if (nearestTriIndex < 0 || squareDist < nearestSquareDist) {
622  nearestSquareDist = squareDist;
623  nearestTriIndex = static_cast<int>(i);
624  nearestPoint = P;
625  if (barycentricCoords) *barycentricCoords = BC;
626  }
627  }
628 
629  return (nearestTriIndex >= 0);
630 }
631 
633  unsigned triIndex,
634  const CCVector2d& clickPos,
635  const ccGLCameraParameters& camera,
636  CCVector3d& point,
637  CCVector3d* barycentricCoords /*=nullptr*/) const {
638  if (triIndex >= size()) {
639  assert(false);
640  return false;
641  }
642 
643  ccGLMatrix trans;
644  bool noGLTrans = !getAbsoluteGLTransformation(trans);
645 
647  if (!vertices) {
648  assert(false);
649  return false;
650  }
651 
652  return trianglePicking(triIndex, clickPos, trans, noGLTrans, *vertices,
653  camera, point, barycentricCoords);
654 }
655 
657  unsigned triIndex,
658  const CCVector2d& uv,
659  CCVector3& P,
660  bool warningIfOutside /*=true*/) const {
661  if (triIndex >= size()) {
662  assert(false);
663  CVLog::Warning("Index out of range");
664  return true;
665  }
666 
667  CCVector3 A;
668  CCVector3 B;
669  CCVector3 C;
670  getTriangleVertices(triIndex, A, B, C);
671 
672  double z = 1.0 - uv.x - uv.y;
673  if (warningIfOutside && ((z < -1.0e-6) || (z > 1.0 + 1.0e-6))) {
674  CVLog::Warning("Point falls outside of the triangle");
675  }
676 
677  P = CCVector3(
678  static_cast<PointCoordinateType>(uv.x * A.x + uv.y * B.x + z * C.x),
679  static_cast<PointCoordinateType>(uv.x * A.y + uv.y * B.y + z * C.y),
680  static_cast<PointCoordinateType>(uv.x * A.z + uv.y * B.z +
681  z * C.z));
682 
683  return true;
684 }
685 
687  if (getAssociatedCloud()) {
688  // auto transfer the global shift info to the vertices
690  } else {
691  // we normally don't want to store this information at
692  // the mesh level as it won't be saved.
693  assert(false);
695  }
696 }
697 
698 void ccGenericMesh::setGlobalScale(double scale) {
699  if (getAssociatedCloud()) {
700  // auto transfer the global scale info to the vertices
702  } else {
703  // we normally don't want to store this information at
704  // the mesh level as it won't be saved.
705  assert(false);
707  }
708 }
709 
713 }
714 
718 }
719 
720 bool ccGenericMesh::updateTextures(const std::string& texture_file) {
721  std::vector<std::string> texture_files = {texture_file};
722  return updateTextures(texture_files);
723 }
724 
726  const std::vector<std::string>& texture_files) {
727  if (texture_files.empty()) {
728  return false;
729  }
730 
731  // materials & textures
732  bool applyMaterials = (hasMaterials() && materialsShown());
733  bool showTextures = (hasTextures() && materialsShown());
734  if (applyMaterials || showTextures) {
735  auto* materials = const_cast<ccMaterialSet*>(getMaterialSet());
736  bool has_materials = true;
737  if (!materials) {
738  has_materials = false;
739  // try to create the materials
740  materials = new ccMaterialSet("materials");
741  materials->link();
742  }
743 
744  for (std::size_t ti = 0; ti < texture_files.size(); ++ti) {
745  QString textureFileName =
746  QFileInfo(texture_files[ti].c_str()).fileName();
747  QString textureFilePath = texture_files[ti].c_str();
748  if (ti >= materials->size()) {
749  ccMaterial::Shared material(new ccMaterial(textureFileName));
750  if (material->loadAndSetTexture(textureFilePath)) {
751  const QImage& texture = material->getTexture();
752  CVLog::Print(QString("[Texture] Successfully loaded "
753  "texture '%1' (%2x%3 pixels)")
754  .arg(textureFileName)
755  .arg(texture.width())
756  .arg(texture.height()));
757  material->setDiffuse(ecvColor::bright);
758  material->setSpecular(ecvColor::darker);
759  material->setAmbient(ecvColor::light);
760  materials->push_back(material);
761  } else {
762  CVLog::Warning(QString("[Texture] Failed to load "
763  "texture '%1'")
764  .arg(textureFilePath));
765  }
766  } else {
767  ccMaterial* material =
768  const_cast<ccMaterial*>(materials->at(ti).get());
769  assert(material);
770  // material->releaseTexture();
771  if (material->loadAndSetTexture(textureFilePath)) {
772  const QImage& texture = material->getTexture();
773  CVLog::Print(QString("[Texture] Update "
774  "texture '%1' (%2x%3 pixels)")
775  .arg(textureFileName)
776  .arg(texture.width())
777  .arg(texture.height()));
778  } else {
779  CVLog::Warning(QString("[Texture] Failed to load "
780  "texture '%1'")
781  .arg(textureFilePath));
782  }
783  }
784  }
785 
786  if (!has_materials) {
787  int childIndex = getChildIndex(materials);
788  if (childIndex < 0) addChild(materials);
789  }
790 
792  context.viewID = getViewId();
794  return true;
795  } else {
796  return false;
797  }
798 }
799 
801  ccGenericMesh** mesh /*=nullptr*/) {
802  if (!cloud) {
803  assert(false);
804  return false;
805  }
806 
807  // check whether the input point cloud acts as the vertices of a mesh
808  {
809  ccHObject* parent = cloud->getParent();
810  if (parent && parent->isKindOf(CV_TYPES::MESH) &&
811  static_cast<ccGenericMesh*>(parent)->getAssociatedCloud() ==
812  cloud) {
813  if (mesh) {
814  *mesh = static_cast<ccGenericMesh*>(parent);
815  }
816  return true;
817  }
818  }
819 
820  // now check the children
821  for (unsigned i = 0; i < cloud->getChildrenNumber(); ++i) {
822  ccHObject* child = cloud->getChild(i);
823  if (child && child->isKindOf(CV_TYPES::MESH) &&
824  static_cast<ccGenericMesh*>(child)->getAssociatedCloud() == cloud) {
825  if (mesh) {
826  *mesh = static_cast<ccGenericMesh*>(child);
827  }
828  return true;
829  }
830  }
831 
832  return false;
833 }
Vector3Tpl< double > CCVector3d
Double 3D Vector.
Definition: CVGeom.h:804
Vector3Tpl< PointCoordinateType > CCVector3
Default 3D Vector.
Definition: CVGeom.h:798
float PointCoordinateType
Type of the coordinates of a (N-D) point.
Definition: CVTypes.h:16
std::string name
math::float2 uv
void * X
Definition: SmallVector.cpp:45
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
Definition: CVLog.cpp:133
static bool Print(const char *format,...)
Prints out a formatted message in console.
Definition: CVLog.cpp:113
Type y
Definition: CVGeom.h:137
Type x
Definition: CVGeom.h:137
Type z
Definition: CVGeom.h:137
Type x
Definition: CVGeom.h:36
Type y
Definition: CVGeom.h:36
static const size_t SIZE
Definition: ecvChunk.h:17
QSharedPointer< ccColorScale > Shared
Shared pointer type.
Definition: ecvColorScale.h:74
virtual bool isVisible() const
Returns whether entity is visible or not.
virtual bool hasColors() const
Returns whether colors are enabled or not.
virtual void lockVisibility(bool state)
Locks/unlocks visibility.
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 bool isColorOverridden() const
virtual void showNormals(bool state)
Sets normals visibility.
virtual void showColors(bool state)
Sets colors visibility.
bool m_normalsDisplayed
Specifies whether normals should be displayed.
virtual void getDrawingParameters(glDrawParams &params) const
Returns main OpenGL parameters for this entity.
ecvColor::Rgb m_tempColor
Temporary (unique) color.
Float version of ccGLMatrixTpl.
Definition: ecvGLMatrix.h:19
Generic mesh interface.
virtual void showPoints(bool state)
bool updateTextures(const std::string &texture_file)
virtual bool materialsShown() const
Sets whether textures/material should be displayed or not.
void showNormals(bool state) override
Sets normals visibility.
virtual bool hasTextures() const =0
Returns whether textures are available for this mesh.
void importParametersFrom(const ccGenericMesh *mesh)
Imports the parameters from another mesh.
virtual void showWired(bool state)
Sets whether mesh should be displayed as a wire or with plain facets.
bool fromFile_MeOnly(QFile &in, short dataVersion, int flags, LoadedIDMap &oldToNewIDMap) override
Loads own object data.
virtual bool triNormsShown() const
Returns whether per-triangle normals are shown or not.
static CCVector3 * GetNormalsBuffer()
bool m_triNormsShown
Per-triangle normals display flag.
static ecvColor::Rgb * GetColorsBuffer()
virtual bool isShownAsWire() const
Returns whether the mesh is displayed as wired or with plain facets.
virtual const ccMaterialSet * getMaterialSet() const =0
bool m_stippling
Polygon stippling state.
virtual bool hasTriNormals() const =0
Returns whether the mesh has per-triangle normals.
const CCVector3d & getGlobalShift() const override
Returns the shift applied to original coordinates.
virtual void computeInterpolationWeights(unsigned triIndex, const CCVector3 &P, CCVector3d &weights) const
Returns the (barycentric) interpolation weights for a given triangle.
bool m_showWired
Wireframe display mode.
short minimumFileVersion_MeOnly() const override
ccPointCloud * samplePoints(bool densityBased, double samplingParameter, bool withNormals, bool withRGB, bool withTexture, cloudViewer::GenericProgressCallback *pDlg=nullptr)
Samples points on a mesh.
virtual ccGenericPointCloud * getAssociatedCloud() const =0
Returns the vertices cloud.
double getGlobalScale() const override
Returns the scale applied to original coordinates.
virtual bool interpolateColors(unsigned triIndex, const CCVector3 &P, ecvColor::Rgb &C)=0
Interpolates RGB colors inside a given triangle.
static bool IsCloudVerticesOfMesh(ccGenericPointCloud *cloud, ccGenericMesh **mesh=nullptr)
Helper to determine if the input cloud acts as vertices of a mesh.
void enableStippling(bool state)
Enables polygon stippling.
virtual bool trianglePicking(const CCVector2d &clickPos, const ccGLCameraParameters &camera, int &nearestTriIndex, double &nearestSquareDist, CCVector3d &nearestPoint, CCVector3d *barycentricCoords=nullptr) const
Brute force triangle picking.
void setGlobalShift(const CCVector3d &shift) override
Sets shift applied to original coordinates (information storage only)
bool m_materialsShown
Texture/material display flag.
bool computePointPosition(unsigned triIndex, const CCVector2d &uv, CCVector3 &P, bool warningIfOutside=true) const
static unsigned * GetWireVertexIndexes()
Returns a pre-initialized array of vertex indexes for wired display.
static CCVector3 * GetVertexBuffer()
virtual bool isShownAsPoints() const
Returns whether the mesh is displayed as wired or with plain facets.
void handleColorRamp(CC_DRAW_CONTEXT &context)
Handles the color ramp display.
ccGenericMesh(QString name=QString())
Default constructor.
bool toFile_MeOnly(QFile &out, short dataVersion) const override
Save own object data.
void drawMeOnly(CC_DRAW_CONTEXT &context) override
Enables (OpenGL) stipple mask.
virtual bool getColorFromMaterial(unsigned triIndex, const CCVector3 &P, ecvColor::Rgb &C, bool interpolateColorIfNoTexture)=0
void setGlobalScale(double scale) override
virtual bool stipplingEnabled() const
Returns whether polygon stippling is enabled or not.
virtual bool hasMaterials() const =0
virtual void showTriNorms(bool state)
Sets whether to show or not per-triangle normals.
A 3D cloud interface with associated features (color, normals, octree, etc.)
virtual VisibilityTableType & getTheVisibilityArray()
Returns associated visibility array.
std::vector< unsigned char > VisibilityTableType
Array of "visibility" information for each point.
static ccGenericMesh * ToGenericMesh(ccHObject *obj)
Converts current object to ccGenericMesh (if possible)
Hierarchical CLOUDVIEWER Object.
Definition: ecvHObject.h:25
virtual const ccGLMatrix & getGLTransformationHistory() const
Returns the transformation 'history' matrix.
Definition: ecvHObject.h:631
bool getAbsoluteGLTransformation(ccGLMatrix &trans) const
Definition: ecvHObject.cpp:740
virtual short minimumFileVersion_MeOnly() const
int getChildIndex(const ccHObject *aChild) const
Returns child index.
Definition: ecvHObject.cpp:639
virtual bool fromFile_MeOnly(QFile &in, short dataVersion, int flags, LoadedIDMap &oldToNewIDMap)
Loads own object data.
virtual bool toFile_MeOnly(QFile &out, short dataVersion) const
Save own object data.
QString getViewId() const
Definition: ecvHObject.h:225
unsigned getChildrenNumber() const
Returns the number of children.
Definition: ecvHObject.h:312
virtual void setGLTransformationHistory(const ccGLMatrix &mat)
Sets the transformation 'history' matrix (handle with care!)
Definition: ecvHObject.h:635
ccHObject * getParent() const
Returns parent object.
Definition: ecvHObject.h:245
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
Mesh (triangle) material.
Mesh (triangle) material.
Definition: ecvMaterial.h:28
QSharedPointer< ccMaterial > Shared
Shared type.
Definition: ecvMaterial.h:33
const QImage & getTexture() const
Returns the texture (if any)
bool loadAndSetTexture(const QString &absoluteFilename)
Loads texture from file (and set it if successful)
const QVariantMap & metaData() const
Returns meta-data map (const only)
Definition: ecvObject.h:184
virtual QString getName() const
Returns object name.
Definition: ecvObject.h:72
void setMetaData(const QString &key, const QVariant &data)
Sets a meta-data element.
Definition: ecvObject.cpp:216
bool isA(CV_CLASS_ENUM type) const
Definition: ecvObject.h:131
virtual void setName(const QString &name)
Sets object name.
Definition: ecvObject.h:75
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 addColorRampInfo(CC_DRAW_CONTEXT &context)
Adds associated SF color ramp info to current GL context.
bool sfColorScaleShown() const
Returns whether color scale should be displayed or not.
void addNorm(const CCVector3 &N)
Pushes a normal vector on stack (shortcut)
ccScalarField * getCurrentDisplayedScalarField() const
Returns the currently displayed scalar (or 0 if none)
static ccPointCloud * From(const cloudViewer::GenericIndexedCloud *cloud, const ccGenericPointCloud *sourceCloud=nullptr)
Creates a new point cloud object from a GenericIndexedCloud.
bool reserveTheNormsTable()
Reserves memory to store the compressed normals.
bool reserveTheRGBTable()
Reserves memory to store the RGB colors.
void addRGBColor(const ecvColor::Rgb &C)
Pushes an RGB color on stack.
A scalar field associated to display-related parameters.
bool areNaNValuesShownInGrey() const
Returns whether NaN values are displayed in gray or hidden.
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'.
Shifted entity interface.
virtual void setGlobalShift(double x, double y, double z)
Sets shift applied to original coordinates (information storage only)
virtual const CCVector3d & getGlobalShift() const
Returns the shift applied to original coordinates.
virtual void setGlobalScale(double scale)
virtual double getGlobalScale() const
Returns the scale applied to original coordinates.
void copyGlobalShiftAndScale(const ccShiftedObject &s)
Copies the Global Shift and Scale from another entity.
virtual unsigned size() const =0
Returns the number of points.
virtual bool interpolateNormals(unsigned triIndex, const CCVector3 &P, CCVector3 &N)
Interpolates normal(s) inside a given triangle.
virtual GenericTriangle * _getTriangle(unsigned triangleIndex)=0
Returns the ith triangle.
virtual void getTriangleVertices(unsigned triangleIndex, CCVector3 &A, CCVector3 &B, CCVector3 &C) const =0
Returns the vertices of a given triangle.
virtual unsigned size() const =0
Returns the number of triangles.
A generic triangle interface.
virtual const CCVector3 * _getA() const =0
Returns the first vertex (A)
virtual const CCVector3 * _getC() const =0
Returns the third vertex (C)
virtual const CCVector3 * _getB() const =0
Returns the second vertex (B)
static PointCloud * samplePointsOnMesh(GenericMesh *mesh, double samplingDensity, GenericProgressCallback *progressCb=nullptr, std::vector< unsigned > *triIndices=nullptr)
Samples points on a mesh.
unsigned size() const override
Definition: PointCloudTpl.h:38
const CCVector3 * getPoint(unsigned index) const override
RGB color structure.
Definition: ecvColorTypes.h:49
static void Draw(const CC_DRAW_CONTEXT &context, const ccHObject *obj)
static QMainWindow * GetMainWindow()
static void UpdateMeshTextures(const CC_DRAW_CONTEXT &context, const ccGenericMesh *mesh)
#define MACRO_Draw2D(context)
#define MACRO_Draw3D(context)
@ ECV_POINTS_MODE
@ ECV_SURFACE_MODE
@ ECV_WIREFRAME_MODE
#define MACRO_LightIsEnabled(context)
#define MACRO_Foreground(context)
#define MACRO_FastEntityPicking(context)
#define MACRO_EntityPicking(context)
#define MACRO_LODActivated(context)
static const GLubyte s_byte1
static const GLubyte s_stippleMask[4 *32]
static const GLubyte s_byte0
static bool s_vertIndexesInitialized
static unsigned s_vertWireIndexes[ccChunk::SIZE *6]
ImGuiContext * context
Definition: Window.cpp:76
normal_z z
@ MESH
Definition: CVTypes.h:105
@ POINT_CLOUD
Definition: CVTypes.h:104
MiniVec< float, N > ceil(const MiniVec< float, N > &a)
Definition: MiniVec.h:89
bool LessThanEpsilon(float x)
Test a floating point number against our epsilon (a very small number).
Definition: CVMath.h:23
constexpr Rgbaf light(0.66f, 0.66f, 0.66f, 1.00f)
constexpr Rgbaf bright(1.00f, 1.00f, 1.00f, 1.00f)
constexpr Rgb lightGrey(static_cast< ColorCompType >(MAX *0.8), static_cast< ColorCompType >(MAX *0.8), static_cast< ColorCompType >(MAX *0.8))
constexpr Rgbaf darker(0.17f, 0.17f, 0.17f, 1.00f)
OpenGL camera parameters.
bool unproject(const CCVector3d &input2D, CCVector3d &output3D) const
Unprojects a 2D point (+ normalized 'z' coordinate) in 3D.
bool project(const CCVector3d &input3D, CCVector3d &output2D, bool *inFrustum=nullptr) const
Projects a 3D point in 2D (+ normalized 'z' coordinate)
Display context.
Display parameters of a 3D entity.
bool showColors
Display colors.
bool showNorms
Display normals.
bool showSF
Display scalar field (prioritary on colors)