16 #include <pcl/common/io.h>
17 #include <pcl/io/vtk_io.h>
18 #include <pcl/io/vtk_lib_io.h>
20 #include <pcl/io/impl/vtk_lib_io.hpp>
23 #include <vtkCellArray.h>
24 #include <vtkFloatArray.h>
25 #include <vtkMatrix4x4.h>
26 #include <vtkPoints.h>
27 #include <vtkPolyData.h>
28 #include <vtkStringArray.h>
29 #include <vtkUnsignedCharArray.h>
32 #ifdef vtkGenericDataArray_h
33 #define SetTupleValue SetTypedTuple
34 #define InsertNextTupleValue InsertNextTypedTuple
55 : m_cc_cloud(nullptr),
57 m_partialVisibility(false),
62 : m_cc_cloud(cc_cloud),
64 m_partialVisibility(false),
74 for (
unsigned i = 0; i <
count; ++i) {
83 PCLCloud::Ptr sm_cloud;
85 if (field_name ==
"x") {
87 }
else if (field_name ==
"y") {
89 }
else if (field_name ==
"z") {
91 }
else if (field_name ==
"normal_x") {
93 }
else if (field_name ==
"normal_y") {
95 }
else if (field_name ==
"normal_z") {
97 }
else if (field_name ==
"xyz") {
99 }
else if (field_name ==
"normal_xyz") {
101 }
else if (field_name ==
"rgb") {
118 PCLCloud::Ptr sm_cloud;
121 unsigned char dim = 0;
159 PointCloud<FloatScalar>::Ptr pcl_cloud(
new PointCloud<FloatScalar>);
164 pcl_cloud->resize(realNum);
166 for (
unsigned i = 0; i < pointCount; ++i) {
175 pcl_cloud->at(index).S5c4laR =
176 static_cast<float>(P->
u[dim]);
181 pcl_cloud->at(i).S5c4laR =
182 static_cast<float>(P->
u[dim]);
192 pcl_cloud->at(i).S5c4laR =
193 static_cast<float>(N.
u[dim]);
198 pcl_cloud->at(i).S5c4laR =
static_cast<float>(N.
u[dim]);
208 sm_cloud = PCLCloud::Ptr(
new PCLCloud);
210 sm_cloud->fields[0].name =
name;
221 PointCloud<PointXYZ>::Ptr pcl_cloud(
new PointCloud<PointXYZ>);
226 pcl_cloud->resize(realNum);
229 for (
unsigned i = 0; i < pointCount; ++i) {
234 pcl_cloud->at(index).
x =
static_cast<float>(P->
x);
235 pcl_cloud->at(index).y =
static_cast<float>(P->
y);
236 pcl_cloud->at(index).z =
static_cast<float>(P->
z);
241 pcl_cloud->at(i).
x =
static_cast<float>(P->
x);
242 pcl_cloud->at(i).y =
static_cast<float>(P->
y);
243 pcl_cloud->at(i).z =
static_cast<float>(P->
z);
255 PCLCloud::Ptr sm_cloud;
257 PointCloud<PointXYZ>::Ptr pcl_cloud =
getXYZ2();
259 sm_cloud = PCLCloud::Ptr(
new PCLCloud);
268 return PCLCloud::Ptr(
static_cast<PCLCloud*
>(
nullptr));
270 PCLCloud::Ptr sm_cloud(
new PCLCloud);
272 PointCloud<OnlyNormals>::Ptr pcl_cloud(
new PointCloud<OnlyNormals>);
277 pcl_cloud->resize(realNum);
280 for (
unsigned i = 0; i < pointCount; ++i) {
285 pcl_cloud->at(index).normal_x = N.
x;
286 pcl_cloud->at(index).normal_y = N.
y;
287 pcl_cloud->at(index).normal_z = N.
z;
292 pcl_cloud->at(i).normal_x = N.
x;
293 pcl_cloud->at(i).normal_y = N.
y;
294 pcl_cloud->at(i).normal_z = N.
z;
312 PCLCloud::Ptr xyzCloud =
getXYZ();
315 pcl::concatenateFields(*
normals, *xyzCloud, *sm_tmp);
322 return PCLCloud::Ptr(
static_cast<PCLCloud*
>(0));
324 PCLCloud::Ptr sm_cloud(
new PCLCloud);
326 PointCloud<OnlyRGB>::Ptr pcl_cloud(
new PointCloud<OnlyRGB>);
331 pcl_cloud->resize(realNum);
334 for (
unsigned i = 0; i < pointCount; ++i) {
339 pcl_cloud->at(index).
r =
static_cast<uint8_t
>(
rgb.r);
340 pcl_cloud->at(index).g =
static_cast<uint8_t
>(
rgb.g);
341 pcl_cloud->at(index).b =
static_cast<uint8_t
>(
rgb.b);
346 pcl_cloud->at(i).
r =
static_cast<uint8_t
>(
rgb.r);
347 pcl_cloud->at(i).g =
static_cast<uint8_t
>(
rgb.g);
348 pcl_cloud->at(i).b =
static_cast<uint8_t
>(
rgb.b);
367 bool sfColors)
const {
371 scalars->SetNumberOfComponents(3);
374 reinterpret_cast<vtkUnsignedCharArray*
>(&(*scalars))
375 ->SetNumberOfTuples(
static_cast<vtkIdType
>(nr_points));
377 reinterpret_cast<vtkUnsignedCharArray*
>(&(*scalars))->GetPointer(0);
381 if (sfIdx < 0)
return false;
384 if (!scalar_field)
return false;
385 for (
unsigned cp = 0; cp < nr_points; ++cp) {
393 colors[j] =
static_cast<uint8_t
>(
rgb->r);
394 colors[j + 1] =
static_cast<uint8_t
>(
rgb->g);
395 colors[j + 2] =
static_cast<uint8_t
>(
rgb->b);
398 int idx =
static_cast<int>(cp) * 3;
399 colors[idx] =
static_cast<uint8_t
>(
rgb->r);
400 colors[idx + 1] =
static_cast<uint8_t
>(
rgb->g);
401 colors[idx + 2] =
static_cast<uint8_t
>(
rgb->b);
406 for (
unsigned cp = 0; cp < nr_points; ++cp) {
414 colors[j + 1] =
static_cast<uint8_t
>(
rgb.g);
415 colors[j + 2] =
static_cast<uint8_t
>(
rgb.b);
419 int idx =
static_cast<int>(cp) * 3;
420 colors[idx] =
static_cast<uint8_t
>(
rgb.r);
421 colors[idx + 1] =
static_cast<uint8_t
>(
rgb.g);
422 colors[idx + 2] =
static_cast<uint8_t
>(
rgb.b);
433 QString simplified = QString::fromStdString(ccSfName).simplified();
434 simplified.replace(
' ',
'_');
435 return simplified.toStdString();
441 inMaterial->getTexture();
442 std::string texFile =
447 auto allTextures = inMaterial->getAllTextureFilenames();
458 if (allTextures.size() > 1) {
459 texName +=
"_PBR_MULTITEX";
460 for (
const auto& tex : allTextures) {
462 texName +=
"|" +
std::to_string(
static_cast<int>(tex.first)) +
":" +
466 "[cc2smReader::ConVertToPCLMaterial] Encoded %zu textures "
467 "into material name for pcl::TexMaterial compatibility",
473 float shininess = inMaterial->getShininessFront();
475 outMaterial.tex_name = texName;
476 outMaterial.tex_file = texFile;
477 outMaterial.tex_Ka.
r = ambientColor.
r;
478 outMaterial.tex_Ka.g = ambientColor.
g;
479 outMaterial.tex_Ka.b = ambientColor.
b;
480 outMaterial.tex_Kd.r = diffuseColor.
r;
481 outMaterial.tex_Kd.g = diffuseColor.
g;
482 outMaterial.tex_Kd.b = diffuseColor.
b;
483 outMaterial.tex_Ks.r = specularColor.
r;
484 outMaterial.tex_Ks.g = specularColor.
g;
485 outMaterial.tex_Ks.b = specularColor.
b;
486 outMaterial.tex_d = ambientColor.
a;
487 outMaterial.tex_Ns = shininess;
488 outMaterial.tex_illum = inMaterial->getIllum();
489 if (outMaterial.tex_illum > 2)
491 outMaterial.tex_illum = 0;
496 const std::string& field_name)
const {
501 return PCLCloud::Ptr(
static_cast<PCLCloud*
>(
nullptr));
504 assert(scalar_field);
506 PCLCloud::Ptr sm_cloud(
new PCLCloud);
514 PointCloud<OnlyRGB>::Ptr pcl_cloud(
new PointCloud<OnlyRGB>);
519 pcl_cloud->resize(realNum);
522 for (
unsigned i = 0; i < pointCount; ++i) {
529 pcl_cloud->at(index).
r =
530 static_cast<uint8_t
>(col->
r);
531 pcl_cloud->at(index).g =
532 static_cast<uint8_t
>(col->
g);
533 pcl_cloud->at(index).b =
534 static_cast<uint8_t
>(col->
b);
541 pcl_cloud->at(i).
r =
static_cast<uint8_t
>(col->
r);
542 pcl_cloud->at(i).g =
static_cast<uint8_t
>(col->
g);
543 pcl_cloud->at(i).b =
static_cast<uint8_t
>(col->
b);
552 PointCloud<FloatScalar>::Ptr pcl_cloud(
new PointCloud<FloatScalar>);
556 pcl_cloud->resize(realNum);
559 for (
unsigned i = 0; i < pointCount; ++i) {
564 pcl_cloud->at(index).S5c4laR =
565 static_cast<float>(
scalar);
570 pcl_cloud->at(i).S5c4laR =
static_cast<float>(
scalar);
592 if ((field_name ==
"x") || (field_name ==
"y") || (field_name ==
"z") ||
593 (field_name ==
"xyz"))
596 else if ((field_name ==
"normal_x") || (field_name ==
"normal_y") ||
597 (field_name ==
"normal_z") || (field_name ==
"normal_xyz"))
600 else if (field_name ==
"rgb")
608 std::list<std::string>& requested_fields)
const {
611 for (std::list<std::string>::const_iterator it =
612 requested_fields.begin();
613 it != requested_fields.end(); ++it) {
616 return PCLCloud::Ptr(
static_cast<PCLCloud*
>(
nullptr));
622 bool got_xyz = (std::find(requested_fields.begin(), requested_fields.end(),
623 "xyz") != requested_fields.end());
627 requested_fields.erase(
628 std::remove(requested_fields.begin(), requested_fields.end(),
630 requested_fields.end());
631 requested_fields.erase(
632 std::remove(requested_fields.begin(), requested_fields.end(),
634 requested_fields.end());
635 requested_fields.erase(
636 std::remove(requested_fields.begin(), requested_fields.end(),
638 requested_fields.end());
642 bool got_normal_xyz =
643 (std::find(requested_fields.begin(), requested_fields.end(),
644 "normal_xyz") != requested_fields.end());
645 if (got_normal_xyz) {
646 requested_fields.erase(
647 std::remove(requested_fields.begin(), requested_fields.end(),
648 std::string(
"normal_x")),
649 requested_fields.end());
650 requested_fields.erase(
651 std::remove(requested_fields.begin(), requested_fields.end(),
652 std::string(
"normal_y")),
653 requested_fields.end());
654 requested_fields.erase(
655 std::remove(requested_fields.begin(), requested_fields.end(),
656 std::string(
"normal_z")),
657 requested_fields.end());
661 PCLCloud::Ptr firstCloud;
665 for (std::list<std::string>::const_iterator it =
666 requested_fields.begin();
667 it != requested_fields.end(); ++it) {
674 pcl::concatenateFields(*firstCloud, *otherCloud, *sm_tmp);
688 return PCLCloud::Ptr(
static_cast<PCLCloud*
>(
nullptr));
692 std::list<std::string>
fields;
699 if (!ignoreScalars) {
704 }
catch (
const std::bad_alloc&) {
706 return PCLCloud::Ptr(
static_cast<PCLCloud*
>(
nullptr));
712 static PCLCloud::Ptr
SetOrAdd(PCLCloud::Ptr firstCloud,
713 PCLCloud::Ptr secondCloud) {
721 PCLCloud::Ptr tempCloud(
new PCLCloud);
722 pcl::concatenateFields(*firstCloud, *secondCloud, *tempCloud);
724 }
catch (
const std::bad_alloc&) {
736 const QStringList& scalarFields)
const {
742 PCLCloud::Ptr outputCloud;
748 PCLCloud::Ptr xyzCloud =
getXYZ();
753 outputCloud =
SetOrAdd(outputCloud, xyzCloud);
761 outputCloud =
SetOrAdd(outputCloud, normalsCloud);
769 outputCloud =
SetOrAdd(outputCloud, rgbCloud);
772 for (
const QString& sfName : scalarFields) {
777 outputCloud =
SetOrAdd(outputCloud, sfCloud);
793 PointCloud<pcl::PointNormal>::Ptr pcl_cloud(
794 new PointCloud<pcl::PointNormal>);
799 pcl_cloud->resize(pointCount);
805 for (
unsigned i = 0; i < pointCount; ++i) {
807 pcl_cloud->at(i).
x =
static_cast<float>(P->
x);
808 pcl_cloud->at(i).y =
static_cast<float>(P->
y);
809 pcl_cloud->at(i).z =
static_cast<float>(P->
z);
813 for (
unsigned i = 0; i < pointCount; ++i) {
815 pcl_cloud->at(i).normal_x =
static_cast<float>(N->
x);
816 pcl_cloud->at(i).normal_y =
static_cast<float>(N->
y);
817 pcl_cloud->at(i).normal_z =
static_cast<float>(N->
z);
830 PointCloud<PointXYZ>::Ptr xyzCloud(
new PointCloud<PointXYZ>);
833 xyzCloud->resize(pointCount);
835 for (
unsigned i = 0; i < pointCount; ++i) {
837 xyzCloud->at(i).
x =
static_cast<float>(P->
x);
838 xyzCloud->at(i).y =
static_cast<float>(P->
y);
839 xyzCloud->at(i).z =
static_cast<float>(P->
z);
850 vtkPolyData*
const polydata)
const {
853 vtkUnsignedCharArray*
colors = vtkUnsignedCharArray::SafeDownCast(
854 polydata->GetPointData()->GetScalars());
859 vtkFloatArray::SafeDownCast(polydata->GetPointData()->GetNormals());
860 PCLCloud::Ptr smCloud(
new PCLCloud);
863 pcl::io::vtkPolyDataToPointCloud(polydata, *cloud);
867 pcl::io::vtkPolyDataToPointCloud(polydata, *cloud);
871 pcl::io::vtkPolyDataToPointCloud(polydata, *cloud);
875 pcl::io::vtkPolyDataToPointCloud(polydata, *cloud);
883 vtkPolyData*
const polydata)
const {
884 PCLMesh::Ptr plcMesh(
new PCLMesh);
885 vtkCellArray* mesh_polygons = polydata->GetPolys();
886 if (!mesh_polygons || mesh_polygons->GetNumberOfCells() == 0) {
890 pcl::io::vtk2mesh(polydata, *plcMesh);
895 if (!mesh)
return nullptr;
901 PCLMesh::Ptr pclMesh(
new PCLMesh);
905 "[cc2smReader::getPclMesh] Failed to get pcl::PCLPointCloud2!");
910 unsigned triNum = mesh->
size();
912 for (
unsigned n = 0; n < triNum; ++n) {
924 tri.vertices.push_back(n * 3 + 0);
925 tri.vertices.push_back(n * 3 + 1);
926 tri.vertices.push_back(n * 3 + 2);
927 pclMesh->polygons.push_back(tri);
934 unsigned int triNum = mesh->
size();
936 CVLog::Warning(
"[cc2smReader::getPclCloud2] No triangles found!");
940 std::size_t dimension =
static_cast<std::size_t
>(
957 pcl::PointCloud<pcl::PointXYZ>::Ptr xyz_cloud(
958 new pcl::PointCloud<pcl::PointXYZ>());
960 xyz_cloud->points.resize(
static_cast<std::size_t
>(triNum) * dimension);
961 xyz_cloud->width = xyz_cloud->size();
962 xyz_cloud->height = 1;
963 xyz_cloud->is_dense =
true;
966 pcl::PointCloud<pcl::RGB>::Ptr rgb_cloud =
nullptr;
968 rgb_cloud.reset(
new pcl::PointCloud<pcl::RGB>());
969 rgb_cloud->points.resize(
static_cast<std::size_t
>(triNum) * dimension);
970 rgb_cloud->width = rgb_cloud->size();
971 rgb_cloud->height = 1;
972 rgb_cloud->is_dense =
true;
975 pcl::PointCloud<pcl::Normal>::Ptr normal_cloud =
nullptr;
977 normal_cloud.reset(
new pcl::PointCloud<pcl::Normal>());
978 normal_cloud->resize(
static_cast<std::size_t
>(triNum) * dimension);
979 normal_cloud->width = xyz_cloud->size();
980 normal_cloud->height = 1;
981 normal_cloud->is_dense =
true;
1004 for (
unsigned n = 0; n < triNum; ++n) {
1016 for (std::size_t vertexIndex = 0; vertexIndex < dimension;
1018 (*xyz_cloud)[n * dimension + vertexIndex].x =
static_cast<float>(
1020 (*xyz_cloud)[n * dimension + vertexIndex].y =
static_cast<float>(
1022 (*xyz_cloud)[n * dimension + vertexIndex].z =
static_cast<float>(
1028 for (std::size_t vertexIndex = 0; vertexIndex < dimension;
1034 (*rgb_cloud)[n * dimension + vertexIndex].
r =
rgb->r;
1035 (*rgb_cloud)[n * dimension + vertexIndex].g =
rgb->g;
1036 (*rgb_cloud)[n * dimension + vertexIndex].b =
rgb->b;
1037 (*rgb_cloud)[n * dimension + vertexIndex].a = 255;
1039 }
else if (showColors) {
1040 for (std::size_t vertexIndex = 0; vertexIndex < dimension;
1045 (*rgb_cloud)[n * dimension + vertexIndex].r =
rgb->r;
1046 (*rgb_cloud)[n * dimension + vertexIndex].g =
rgb->g;
1047 (*rgb_cloud)[n * dimension + vertexIndex].b =
rgb->b;
1048 (*rgb_cloud)[n * dimension + vertexIndex].a = 255;
1054 if (showTriNormals) {
1071 N1 = compressedNormals
1074 N2 = compressedNormals
1077 N3 = compressedNormals
1082 (*normal_cloud)[n * dimension + 0].normal_x = N1[0];
1083 (*normal_cloud)[n * dimension + 0].normal_y = N1[1];
1084 (*normal_cloud)[n * dimension + 0].normal_z = N1[2];
1085 (*normal_cloud)[n * dimension + 1].normal_x = N2[0];
1086 (*normal_cloud)[n * dimension + 1].normal_y = N2[1];
1087 (*normal_cloud)[n * dimension + 1].normal_z = N2[2];
1088 (*normal_cloud)[n * dimension + 2].normal_x = N3[0];
1089 (*normal_cloud)[n * dimension + 2].normal_y = N3[1];
1090 (*normal_cloud)[n * dimension + 2].normal_z = N3[2];
1104 pcl::concatenateFields(rgb_cloud2, cloud, aux);
1113 pcl::concatenateFields(normal_cloud2, cloud, aux);
1129 unsigned int triNum = mesh->
size();
1132 "[cc2smReader::getVtkPolyDataFromMeshCloud] No triangles "
1137 std::size_t dimension =
static_cast<std::size_t
>(
1160 QString(
"[cc2smReader::getVtkPolyDataFromMeshCloud] "
1161 "hasTriNormals=%1, hasNormals=%2, hasNormalsForExport=%3")
1164 .arg(hasNormalsForExport));
1169 std::size_t totalPoints =
static_cast<std::size_t
>(triNum) * dimension;
1171 poly_points->SetNumberOfPoints(
static_cast<vtkIdType
>(totalPoints));
1176 colors->SetNumberOfComponents(3);
1177 colors->SetNumberOfTuples(
static_cast<vtkIdType
>(totalPoints));
1184 if (hasNormalsForExport) {
1186 normals->SetNumberOfComponents(3);
1187 normals->SetNumberOfTuples(
static_cast<vtkIdType
>(totalPoints));
1192 polys->AllocateEstimate(
static_cast<vtkIdType
>(triNum), 3);
1202 if (hasNormalsForExport) {
1213 for (
unsigned n = 0; n < triNum; ++n) {
1226 vtkIdType basePointIndex =
1227 static_cast<vtkIdType
>(n) *
static_cast<vtkIdType
>(dimension);
1230 for (std::size_t vertexIndex = 0; vertexIndex < dimension;
1232 vtkIdType pointIndex =
1233 basePointIndex +
static_cast<vtkIdType
>(vertexIndex);
1234 unsigned vertexIdx = tsi->
i[vertexIndex];
1238 poly_points->SetPoint(pointIndex, p->
x, p->
y, p->
z);
1249 unsigned char* colorPtr =
colors->GetPointer(
1250 static_cast<vtkIdType
>(pointIndex) * 3);
1251 colorPtr[0] =
rgb->r;
1252 colorPtr[1] =
rgb->g;
1253 colorPtr[2] =
rgb->b;
1259 if (hasNormalsForExport) {
1262 if (useTriNormals) {
1281 }
else if (normalsIndexesTable && compressedNormals) {
1282 N1 = compressedNormals
1285 N2 = compressedNormals
1288 N3 = compressedNormals
1294 if (vertexIndex == 0) {
1296 }
else if (vertexIndex == 1) {
1302 float* normalPtr =
normals->GetPointer(
1303 static_cast<vtkIdType
>(pointIndex) * 3);
1305 normalPtr[0] =
static_cast<float>(N[0]);
1306 normalPtr[1] =
static_cast<float>(N[1]);
1307 normalPtr[2] =
static_cast<float>(N[2]);
1309 normalPtr[0] = 0.0f;
1310 normalPtr[1] = 0.0f;
1311 normalPtr[2] = 0.0f;
1317 polys->InsertNextCell(3);
1318 polys->InsertCellPoint(basePointIndex + 0);
1319 polys->InsertCellPoint(basePointIndex + 1);
1320 polys->InsertCellPoint(basePointIndex + 2);
1325 polydata->SetPoints(poly_points);
1326 polydata->SetPolys(polys);
1340 colors->SetName(sfName.toStdString().c_str());
1342 "getVtkPolyDataFromMeshCloud] "
1343 "Set scalar array name: %1")
1354 polydata->GetPointData()->SetScalars(
colors);
1357 if (hasNormalsForExport &&
normals) {
1358 polydata->GetPointData()->SetNormals(
normals);
1362 QString meshName = mesh->
getName();
1363 if (meshName.length() > 0) {
1366 datasetNameArray->SetName(
"DatasetName");
1367 datasetNameArray->SetNumberOfTuples(1);
1368 datasetNameArray->SetValue(0, meshName.toStdString());
1369 polydata->GetFieldData()->AddArray(datasetNameArray);
1376 if (!mesh)
return nullptr;
1380 bool lodEnabled =
false;
1384 if (applyMaterials || showTextures) {
1385 unsigned int triNum = mesh->
size();
1388 "[cc2smReader::getPclTextureMesh] No triangles found!");
1395 "[cc2smReader::getPclTextureMesh] Failed to get "
1396 "pcl::PCLPointCloud2!");
1402 bool visFiltering = (verticesVisibility.size() >=
1409 int lasMtlIndex = -1;
1412 for (
unsigned n = 0; n < triNum; ++n) {
1426 if (lasMtlIndex != newMatlIndex) {
1427 assert(newMatlIndex <
static_cast<int>(materials->size()));
1429 if (newMatlIndex >= 0) {
1430 textureMesh->tex_polygons.push_back(
1431 std::vector<pcl::Vertices>());
1432 textureMesh->tex_materials.push_back(
PCLMaterial());
1433 textureMesh->tex_coordinates.push_back(
1434 std::vector<Eigen::Vector2f,
1435 Eigen::aligned_allocator<
1436 Eigen::Vector2f>>());
1438 textureMesh->tex_materials.back());
1441 textureMesh->tex_polygons.push_back(
1442 std::vector<pcl::Vertices>());
1443 textureMesh->tex_materials.push_back(
PCLMaterial());
1444 textureMesh->tex_coordinates.push_back(
1445 std::vector<Eigen::Vector2f,
1446 Eigen::aligned_allocator<
1447 Eigen::Vector2f>>());
1451 textureMesh->tex_materials.back());
1454 lasMtlIndex = newMatlIndex;
1458 if (showTextures && !textureMesh->tex_coordinates.empty()) {
1466 if (Tx1 && Tx2 && Tx3) {
1467 textureMesh->tex_coordinates.back().push_back(
1468 Eigen::Vector2f(Tx1->
tx, Tx1->
ty));
1469 textureMesh->tex_coordinates.back().push_back(
1470 Eigen::Vector2f(Tx2->
tx, Tx2->
ty));
1471 textureMesh->tex_coordinates.back().push_back(
1472 Eigen::Vector2f(Tx3->
tx, Tx3->
ty));
1475 "[cc2smReader::getPclTextureMesh] Null texture "
1476 "coordinates for triangle %d (Tx1=%p, Tx2=%p, "
1480 textureMesh->tex_coordinates.back().push_back(
1481 Eigen::Vector2f(0.0f, 0.0f));
1482 textureMesh->tex_coordinates.back().push_back(
1483 Eigen::Vector2f(0.0f, 0.0f));
1484 textureMesh->tex_coordinates.back().push_back(
1485 Eigen::Vector2f(0.0f, 0.0f));
1490 tri.vertices.push_back(n * 3 + 0);
1491 tri.vertices.push_back(n * 3 + 1);
1492 tri.vertices.push_back(n * 3 + 2);
1494 if (!textureMesh->tex_polygons.empty()) {
1495 textureMesh->tex_polygons.back().push_back(tri);
1502 if (textureMesh->tex_materials.size() == 0) {
1504 "[cc2smReader::getPclTextureMesh] No textures found!");
1508 if (textureMesh->tex_materials.size() !=
1509 textureMesh->tex_polygons.size()) {
1511 "[cc2smReader::getPclTextureMesh] Materials number %lu "
1512 "differs from polygons number %lu!",
1513 textureMesh->tex_materials.size(),
1514 textureMesh->tex_polygons.size());
1518 if (textureMesh->tex_materials.size() !=
1519 textureMesh->tex_coordinates.size()) {
1521 "[cc2smReader::getPclTextureMesh] Coordinates number "
1522 "%lu differs from materials number %lu!",
1523 textureMesh->tex_coordinates.size(),
1524 textureMesh->tex_materials.size());
1531 "[cc2smReader::getPclTextureMesh] this mesh has no material "
1532 "and texture and please try polygonMesh other than "
1540 pcl::PointCloud<PointT>::Ptr cloud_xyz(
new pcl::PointCloud<PointT>);
1541 if (polyline->
size() < 2) {
1545 cloud_xyz->resize(polyline->
size());
1547 for (
unsigned i = 0; i < polyline->
size(); ++i) {
1556 cloud_xyz->points[i].x = output3D.
x;
1557 cloud_xyz->points[i].y = output3D.
y;
1558 cloud_xyz->points[i].z = output3D.
z;
1561 pclPolygon->setContour(*cloud_xyz);
1570 std::vector<std::vector<Eigen::Vector2f>>& tex_coordinates) {
1580 "[cc2smReader::getVtkPolyDataWithTextures] Failed to get "
1588 bool lodEnabled =
false;
1592 if (!applyMaterials && !showTextures) {
1594 "[cc2smReader::getVtkPolyDataWithTextures] Mesh has no "
1595 "materials/textures!");
1599 unsigned int triNum = mesh->
size();
1602 "[cc2smReader::getVtkPolyDataWithTextures] No triangles "
1607 std::size_t dimension =
static_cast<std::size_t
>(
1620 std::vector<std::vector<Eigen::Vector2f>> materialTexCoords;
1623 triangleToMaterial.reserve(triNum);
1625 int lasMtlIndex = -1;
1626 int currentMaterialIndex = -1;
1630 for (
unsigned n = 0; n < triNum; ++n) {
1642 if (lasMtlIndex != newMatlIndex) {
1643 if (newMatlIndex >= 0) {
1644 assert(newMatlIndex <
static_cast<int>(materials->size()));
1645 currentMaterialIndex =
1646 static_cast<int>(materialTexCoords.size());
1647 materialTexCoords.push_back(std::vector<Eigen::Vector2f>());
1650 currentMaterialIndex =
1651 static_cast<int>(materialTexCoords.size());
1652 materialTexCoords.push_back(std::vector<Eigen::Vector2f>());
1654 lasMtlIndex = newMatlIndex;
1658 if (
static_cast<size_t>(n) >= triangleToMaterial.size()) {
1659 triangleToMaterial.resize(n + 1, -1);
1661 triangleToMaterial[n] = currentMaterialIndex;
1664 if (showTextures && currentMaterialIndex >= 0) {
1670 if (Tx1 && Tx2 && Tx3) {
1671 materialTexCoords[currentMaterialIndex].push_back(
1672 Eigen::Vector2f(Tx1->
tx, Tx1->
ty));
1673 materialTexCoords[currentMaterialIndex].push_back(
1674 Eigen::Vector2f(Tx2->
tx, Tx2->
ty));
1675 materialTexCoords[currentMaterialIndex].push_back(
1676 Eigen::Vector2f(Tx3->
tx, Tx3->
ty));
1679 materialTexCoords[currentMaterialIndex].push_back(
1680 Eigen::Vector2f(0.0f, 0.0f));
1681 materialTexCoords[currentMaterialIndex].push_back(
1682 Eigen::Vector2f(0.0f, 0.0f));
1683 materialTexCoords[currentMaterialIndex].push_back(
1684 Eigen::Vector2f(0.0f, 0.0f));
1686 }
else if (currentMaterialIndex >= 0) {
1688 materialTexCoords[currentMaterialIndex].push_back(
1689 Eigen::Vector2f(0.0f, 0.0f));
1690 materialTexCoords[currentMaterialIndex].push_back(
1691 Eigen::Vector2f(0.0f, 0.0f));
1692 materialTexCoords[currentMaterialIndex].push_back(
1693 Eigen::Vector2f(0.0f, 0.0f));
1700 vtkIdType numPoints = polydata->GetNumberOfPoints();
1701 tex_coordinates.clear();
1702 tex_coordinates.resize(materialTexCoords.size());
1705 std::vector<size_t> materialCoordIndex(materialTexCoords.size(), 0);
1709 for (vtkIdType pointIdx = 0; pointIdx < numPoints; ++pointIdx) {
1710 int triIdx =
static_cast<int>(pointIdx) /
static_cast<int>(dimension);
1711 int matIdx = (triIdx < static_cast<int>(triangleToMaterial.size()))
1712 ? triangleToMaterial[triIdx]
1716 for (
size_t mat = 0; mat < materialTexCoords.size(); ++mat) {
1717 if (
static_cast<int>(mat) == matIdx &&
1718 materialCoordIndex[mat] < materialTexCoords[mat].size()) {
1720 tex_coordinates[mat].push_back(
1721 materialTexCoords[mat][materialCoordIndex[mat]]);
1722 materialCoordIndex[mat]++;
1726 tex_coordinates[mat].push_back(Eigen::Vector2f(-1.0f, -1.0f));
1734 if (materials && materials->size() > 0) {
1737 QString mtlFilename;
1738 QVariant mtlData = mesh->
getMetaData(
"MTL_FILENAME");
1739 if (mtlData.isValid() && !mtlData.toString().isEmpty()) {
1740 mtlFilename = mtlData.toString();
1743 mtlFilename = materials->at(0)->
getName();
1748 materialLibArray->SetName(
"MaterialLibraries");
1749 materialLibArray->SetNumberOfTuples(1);
1750 materialLibArray->SetValue(0, mtlFilename.toStdString());
1751 polydata->GetFieldData()->AddArray(materialLibArray);
1757 materialNamesArray->SetName(
"MaterialNames");
1758 materialNamesArray->SetNumberOfComponents(1);
1759 materialNamesArray->SetNumberOfTuples(materials->size());
1760 for (
size_t i = 0; i < materials->size(); ++i) {
1761 QString matName = materials->at(i)->
getName();
1762 materialNamesArray->SetValue(i, matName.toStdString());
1764 polydata->GetFieldData()->AddArray(materialNamesArray);
1773 transformation->Identity();
constexpr unsigned char POINT_VISIBLE
float PointCoordinateType
Type of the coordinates of a (N-D) point.
std::vector< PCLPointField > fields
pcl::PointCloud< PointRGBNormal > PointCloudRGBNormal
pcl::TexMaterial PCLMaterial
pcl::PointCloud< PointNT > PointCloudNormal
pcl::PointCloud< PointT > PointCloudT
pcl::PCLPointCloud2 PCLCloud
pcl::PlanarPolygon< PointT > PCLPolygon
pcl::PointCloud< PointRGB > PointCloudRGB
pcl::TextureMesh PCLTextureMesh
static PCLCloud::Ptr SetOrAdd(PCLCloud::Ptr firstCloud, PCLCloud::Ptr secondCloud)
static bool PrintDebug(const char *format,...)
Same as Print, but works only in Debug mode.
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
Array of compressed 3D normals (single index)
static Vector3Tpl fromArray(const int a[3])
Constructor from an int array.
static void ConVertToPCLMaterial(ccMaterial::CShared inMaterial, PCLMaterial &outMaterial)
static std::string GetSimplifiedSFName(const std::string &ccSfName)
PCLCloud::Ptr getFloatScalarField(const std::string &field_name) const
PCLCloud::Ptr getPointNormals() const
PCLCloud::Ptr getOneOf(Fields field) const
pcl::PointCloud< pcl::PointNormal >::Ptr getAsPointNormal() const
Converts the ccPointCloud to a 'pcl::PointNormal' cloud.
PCLCloud::Ptr getVtkPolyDataAsSM(vtkPolyData *const polydata) const
PCLCloud::Ptr getColors() const
PCLCloud::Ptr getAsSM(std::list< std::string > &requested_fields) const
PCLPolygon::Ptr getPclPolygon(ccPolyline *polyline) const
const ccPointCloud * m_cc_cloud
Associated cloud.
unsigned getvisibilityNum() const
bool getVtkPolyDataWithTextures(ccGenericMesh *mesh, vtkSmartPointer< vtkPolyData > &polydata, vtkSmartPointer< vtkMatrix4x4 > &transformation, std::vector< std::vector< Eigen::Vector2f >> &tex_coordinates)
Convert ccGenericMesh to vtkPolyData with texture coordinates Reuses getPclTextureMesh logic to ensur...
PCLMesh::Ptr getVtkPolyDataAsPclMesh(vtkPolyData *const polydata) const
bool checkIfFieldExists(const std::string &field_name) const
PCLCloud::Ptr getXYZ() const
cc2smReader(bool showMode=false)
PCLMesh::Ptr getPclMesh(ccGenericMesh *mesh)
bool getPclCloud2(ccGenericMesh *mesh, PCLCloud &cloud) const
PCLCloud::Ptr getNormals() const
PCLTextureMesh::Ptr getPclTextureMesh(ccGenericMesh *mesh)
PCLCloud::Ptr getGenericField(std::string field_name) const
bool getvtkScalars(vtkSmartPointer< vtkDataArray > &scalars, bool sfColors) const
Obtain the actual color for the input dataset as vtk scalars.
bool getVtkPolyDataFromMeshCloud(ccGenericMesh *mesh, vtkSmartPointer< vtkPolyData > &polydata) const
Convert ccGenericMesh to vtkPolyData using same logic as getPclCloud2 Direct conversion without PCL i...
pcl::PointCloud< pcl::PointXYZ >::Ptr getXYZ2() const
pcl::PointCloud< pcl::PointXYZ >::Ptr getRawXYZ() const
Converts the ccPointCloud to a 'pcl::PointXYZ' cloud.
virtual bool colorsShown() const
Returns whether colors are shown or not.
virtual bool hasDisplayedScalarField() const
Returns whether an active scalar field is available or not.
virtual bool hasColors() const
Returns whether colors are enabled or not.
virtual bool sfShown() const
Returns whether active scalar field is visible.
virtual bool normalsShown() const
Returns whether normals are shown or not.
virtual bool hasNormals() const
Returns whether normals are enabled or not.
virtual bool materialsShown() const
Sets whether textures/material should be displayed or not.
virtual bool hasTextures() const =0
Returns whether textures are available for this mesh.
virtual bool triNormsShown() const
Returns whether per-triangle normals are shown or not.
virtual void getTriangleNormalIndexes(unsigned triangleIndex, int &i1, int &i2, int &i3) const =0
Returns a triplet of normal indexes for a given triangle (if any)
virtual const ccMaterialSet * getMaterialSet() const =0
virtual bool hasTriNormals() const =0
Returns whether the mesh has per-triangle normals.
virtual int getTriangleMtlIndex(unsigned triangleIndex) const =0
Returns a given triangle material indexes.
virtual ccGenericPointCloud * getAssociatedCloud() const =0
Returns the vertices cloud.
virtual void getTriangleTexCoordinates(unsigned triIndex, TexCoords2D *&tx1, TexCoords2D *&tx2, TexCoords2D *&tx3) const =0
Returns per-triangle texture coordinates (pointer to)
virtual NormsIndexesTableType * getTriNormsTable() const =0
Returns per-triangle normals shared array.
virtual bool hasMaterials() const =0
A 3D cloud interface with associated features (color, normals, octree, etc.)
virtual bool isVisibilityTableInstantiated() const
Returns whether the visibility array is allocated or not.
virtual VisibilityTableType & getTheVisibilityArray()
Returns associated visibility array.
std::vector< unsigned char > VisibilityTableType
Array of "visibility" information for each point.
static ccPointCloud * ToPointCloud(ccHObject *obj, bool *isLockedVertices=nullptr)
Converts current object to 'equivalent' ccPointCloud.
Mesh (triangle) material.
Mesh (triangle) material.
QSharedPointer< const ccMaterial > CShared
Const + Shared type.
QSharedPointer< ccMaterial > Shared
Shared type.
Compressed normal vectors handler.
const CCVector3 & getNormal(unsigned normIndex) const
Returns the precomputed normal corresponding to a given compressed index.
static const CCVector3 & GetNormal(unsigned normIndex)
Static access to ccNormalVectors::getNormal.
static ccNormalVectors * GetUniqueInstance()
Returns unique instance.
virtual QString getName() const
Returns object name.
QVariant getMetaData(const QString &key) const
Returns a given associated meta data.
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
ColorsTableType * rgbColors() const
Returns pointer on RGB colors table.
const ecvColor::Rgb * getScalarValueColor(ScalarType d) const override
Returns color corresponding to a given scalar value.
NormsIndexesTableType * normals() const
Returns pointer on compressed normals indexes table.
ccScalarField * getCurrentDisplayedScalarField() const
Returns the currently displayed scalar (or 0 if none)
bool hasNormals() const override
Returns whether normals are enabled or not.
int getCurrentDisplayedScalarFieldIndex() const
Returns the currently displayed scalar field index (or -1 if none)
bool hasColors() const override
Returns whether colors are enabled or not.
const CCVector3 * getNormal(unsigned pointIndex) const override
If per-point normals are available, returns the one at a specific index.
const CCVector3 & getPointNormal(unsigned pointIndex) const override
Returns normal corresponding to a given point.
bool hasScalarFields() const override
Returns whether one or more scalar fields are instantiated.
const ecvColor::Rgb & getPointColor(unsigned pointIndex) const override
Returns color corresponding to a given point.
bool is2DMode() const
Returns whether the polyline is considered as 2D or 3D.
const ecvColor::Rgb * getValueColor(unsigned index) const
Shortcut to getColor.
virtual unsigned size() const =0
Returns the number of points.
virtual VerticesIndexes * getTriangleVertIndexes(unsigned triangleIndex)=0
Returns the indexes of the vertices of a given triangle.
virtual unsigned size() const =0
Returns the number of triangles.
int getScalarFieldIndexByName(const char *name) const
Returns the index of a scalar field represented by its name.
ScalarField * getScalarField(int index) const
Returns a pointer to a specific scalar field.
unsigned getNumberOfScalarFields() const
Returns the number of associated (and active) scalar fields.
unsigned size() const override
const char * getScalarFieldName(int index) const
Returns the name of a specific scalar field.
const CCVector3 * getPoint(unsigned index) const override
unsigned size() const override
Returns the number of points.
const CCVector3 * getPoint(unsigned index) const override
Returns the ith point.
A simple scalar field (to be associated to a point cloud)
ScalarType & getValue(std::size_t index)
const char * getName() const
Returns scalar field name.
std::string to_string(const T &n)
Triangle described by the indexes of its 3 vertices.
unsigned int getDimension() const