Visual Computing Library
Loading...
Searching...
No Matches
export_buffer.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2025 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_ALGORITHMS_MESH_IMPORT_EXPORT_EXPORT_BUFFER_H
24#define VCL_ALGORITHMS_MESH_IMPORT_EXPORT_EXPORT_BUFFER_H
25
26#include <vclib/algorithms/core/polygon/ear_cut.h>
27#include <vclib/mesh/requirements.h>
28#include <vclib/space/complex/tri_poly_index_bimap.h>
29#include <vclib/views/mesh.h>
30
44namespace vcl {
45
46namespace detail {
47
48// returns a non-empty vector if the vertex container is not compact and the
49// user wants compact indices
50std::vector<uint> vertCompactIndices(const auto& mesh, bool wantCompact)
51{
52 std::vector<uint> vertCompIndices;
53
54 bool isCompact = mesh.vertexNumber() == mesh.vertexContainerSize();
55
56 if (wantCompact && !isCompact)
57 vertCompIndices = mesh.vertexCompactIndices();
58 return vertCompIndices;
59}
60
61// lambda to get the vertex index of a face (considering compact vertex indices)
62auto vIndexLambda(const auto& mesh, const std::vector<uint>& vertCompIndices)
63{
64 // lambda to get the vertex index of a face (considering compact indices)
65 auto vIndex = [&vertCompIndices](const auto& f, uint i) {
66 if (vertCompIndices.size() > 0)
67 return vertCompIndices[f.vertexIndex(i)];
68 else
69 return f.vertexIndex(i);
70 };
71
72 return vIndex;
73}
74
75inline TriPolyIndexBiMap indexMap;
76
77} // namespace detail
78
100template<MeshConcept MeshType>
102 const MeshType& mesh,
103 auto* buffer,
104 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
105 uint rowNumber = UINT_NULL)
106{
107 const uint VERT_NUM =
108 rowNumber == UINT_NULL ? mesh.vertexNumber() : rowNumber;
109 for (uint i = 0; const auto& c : mesh.vertices() | views::coords) {
110 if (storage == MatrixStorageType::ROW_MAJOR) {
111 buffer[i * 3 + 0] = c.x();
112 buffer[i * 3 + 1] = c.y();
113 buffer[i * 3 + 2] = c.z();
114 }
115 else {
116 buffer[0 * VERT_NUM + i] = c.x();
117 buffer[1 * VERT_NUM + i] = c.y();
118 buffer[2 * VERT_NUM + i] = c.z();
119 }
120 ++i;
121 }
122}
123
148template<FaceMeshConcept MeshType>
149uint faceSizesToBuffer(const MeshType& mesh, auto* buffer)
150{
151 uint sum = 0;
152 for (uint i = 0; const auto& f : mesh.faces()) {
153 buffer[i] = f.vertexNumber();
154 sum += f.vertexNumber();
155 ++i;
156 }
157 return sum;
158}
159
210template<FaceMeshConcept MeshType>
212 const MeshType& mesh,
213 auto* buffer,
215{
216 const std::vector<uint> vertCompIndices =
217 detail::vertCompactIndices(mesh, getIndicesAsIfContainerCompact);
218
219 // lambda to get the vertex index of a face (considering compact indices)
220 auto vIndex = detail::vIndexLambda(mesh, vertCompIndices);
221
222 for (uint i = 0; const auto& f : mesh.faces()) {
223 for (uint j = 0; j < f.vertexNumber(); ++j) {
224 buffer[i] = vIndex(f, j);
225 ++i;
226 }
227 }
228}
229
276template<FaceMeshConcept MeshType>
278 const MeshType& mesh,
279 auto* buffer,
280 uint largestFaceSize,
281 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
283 uint rowNumber = UINT_NULL)
284{
285 const std::vector<uint> vertCompIndices =
286 detail::vertCompactIndices(mesh, getIndicesAsIfContainerCompact);
287
288 // lambda to get the vertex index of a face (considering compact indices)
289 auto vIndex = detail::vIndexLambda(mesh, vertCompIndices);
290
291 const uint FACE_NUM =
292 rowNumber == UINT_NULL ? mesh.faceNumber() : rowNumber;
293
294 for (uint i = 0; const auto& f : mesh.faces()) {
295 for (uint j = 0; j < largestFaceSize; ++j) {
296 uint index = i * largestFaceSize + j;
297 if (storage == MatrixStorageType::COLUMN_MAJOR)
298 index = j * FACE_NUM + i;
299 if (j < f.vertexNumber()) {
300 buffer[index] = vIndex(f, j);
301 }
302 else {
303 buffer[index] = -1;
304 }
305 }
306 ++i;
307 }
308}
309
356template<FaceMeshConcept MeshType>
358 const MeshType& mesh,
359 auto* buffer,
360 TriPolyIndexBiMap& indexMap = detail::indexMap,
361 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
362 uint numTriangles = UINT_NULL,
364{
365 const std::vector<uint> vertCompIndices =
366 detail::vertCompactIndices(mesh, getIndicesAsIfContainerCompact);
367
368 // lambda to get the vertex index of a face (considering compact indices)
369 auto vIndex = detail::vIndexLambda(mesh, vertCompIndices);
370
371 // there will be at least a triangle for each polygon
372 indexMap.clear();
373 indexMap.reserve(mesh.faceNumber(), mesh.faceContainerSize());
374
375 if constexpr (TriangleMeshConcept<MeshType>) {
376 // construct the indexMap, which maps each triangle to the face index
377 for (uint t = 0; const auto& f : mesh.faces()) {
378 // map the ith triangle to the f face
379 indexMap.insert(t, f.index());
380 ++t;
381 }
382
383 return faceIndicesToBuffer(
384 mesh, buffer, 3, storage, getIndicesAsIfContainerCompact);
385 }
386 else {
387 // if the user did not give the number of triangles, and the buffer
388 // storage is column major, we need to compute the number of resulting
389 // triangles
390 if (numTriangles == UINT_NULL &&
391 storage == MatrixStorageType::COLUMN_MAJOR &&
392 mesh.faceNumber() > 0) {
393 numTriangles = countTriangulatedTriangles(mesh);
394 }
395 for (uint t = 0; const auto& f : mesh.faces()) {
396 std::vector<uint> vind = vcl::earCut(f);
397
398 // for each triangle of the triangulation (t is the triangle index)
399 for (uint vi = 0; vi < vind.size(); vi += 3) {
400 // map the t-th triangle to the f polygonal face
401 indexMap.insert(t, f.index());
402
403 if (storage == MatrixStorageType::ROW_MAJOR) {
404 buffer[t * 3 + 0] = vIndex(f, vind[vi + 0]);
405 buffer[t * 3 + 1] = vIndex(f, vind[vi + 1]);
406 buffer[t * 3 + 2] = vIndex(f, vind[vi + 2]);
407 }
408 else {
409 buffer[0 * numTriangles + t] = vIndex(f, vind[vi + 0]);
410 buffer[1 * numTriangles + t] = vIndex(f, vind[vi + 1]);
411 buffer[2 * numTriangles + t] = vIndex(f, vind[vi + 2]);
412 }
413 ++t;
414 }
415 }
416 }
417}
418
450template<EdgeMeshConcept MeshType>
452 const MeshType& mesh,
453 auto* buffer,
454 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
456 uint rowNumber = UINT_NULL)
457{
458 const std::vector<uint> vertCompIndices =
459 detail::vertCompactIndices(mesh, getIndicesAsIfContainerCompact);
460
461 // lambda to get the vertex index of a edge (considering compact indices)
462 auto vIndex = detail::vIndexLambda(mesh, vertCompIndices);
463
464 const uint EDGE_NUM =
465 rowNumber == UINT_NULL ? mesh.edgeNumber() : rowNumber;
466
467 for (uint i = 0; const auto& e : mesh.edges()) {
468 if (storage == MatrixStorageType::ROW_MAJOR) {
469 buffer[i * 2 + 0] = vIndex(e, 0);
470 buffer[i * 2 + 1] = vIndex(e, 1);
471 }
472 else {
473 buffer[0 * EDGE_NUM + i] = vIndex(e, 0);
474 buffer[1 * EDGE_NUM + i] = vIndex(e, 1);
475 }
476 ++i;
477 }
478}
479
509template<FaceMeshConcept MeshType>
511 const MeshType& mesh,
512 auto* buffer,
513 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
515 uint rowNumber = UINT_NULL)
516{
517 const std::vector<uint> vertCompIndices =
518 detail::vertCompactIndices(mesh, getIndicesAsIfContainerCompact);
519
520 // lambda to get the vertex index of a edge (considering compact indices)
521 auto vIndex = detail::vIndexLambda(mesh, vertCompIndices);
522
523 const uint EDGE_NUM =
524 rowNumber == UINT_NULL ? countPerFaceVertexReferences(mesh) : rowNumber;
525
526 for (uint i = 0; const auto& f : mesh.faces()) {
527 for (uint j = 0; j < f.vertexNumber(); ++j) {
528 uint v0 = vIndex(f, j);
529 uint v1 = vIndex(f, (j + 1) % f.vertexNumber());
530 if (storage == MatrixStorageType::ROW_MAJOR) {
531 buffer[i * 2 + 0] = v0;
532 buffer[i * 2 + 1] = v1;
533 }
534 else {
535 buffer[0 * EDGE_NUM + i] = v0;
536 buffer[1 * EDGE_NUM + i] = v1;
537 }
538 ++i;
539 }
540 }
541}
542
570template<uint ELEM_ID, MeshConcept MeshType>
571void elementSelectionToBuffer(const MeshType& mesh, auto* buffer)
572{
573 for (uint i = 0; const auto& e : mesh.template elements<ELEM_ID>()) {
574 buffer[i] = e.selected();
575 ++i;
576 }
577}
578
604template<MeshConcept MeshType>
605void vertexSelectionToBuffer(const MeshType& mesh, auto* buffer)
606{
607 elementSelectionToBuffer<ElemId::VERTEX>(mesh, buffer);
608}
609
635template<FaceMeshConcept MeshType>
636void faceSelectionToBuffer(const MeshType& mesh, auto* buffer)
637{
638 elementSelectionToBuffer<ElemId::FACE>(mesh, buffer);
639}
640
666template<EdgeMeshConcept MeshType>
667void edgeSelectionToBuffer(const MeshType& mesh, auto* buffer)
668{
669 elementSelectionToBuffer<ElemId::EDGE>(mesh, buffer);
670}
671
694template<uint ELEM_ID, MeshConcept MeshType>
695void elementNormalsToBuffer(
696 const MeshType& mesh,
697 auto* buffer,
698 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
699 uint rowNumber = UINT_NULL)
700{
701 requirePerElementComponent<ELEM_ID, CompId::NORMAL>(mesh);
702
703 const uint ELEM_NUM =
704 rowNumber == UINT_NULL ? mesh.template number<ELEM_ID>() : rowNumber;
705
706 for (uint i = 0;
707 const auto& n : mesh.template elements<ELEM_ID>() | views::normals) {
708 if (storage == MatrixStorageType::ROW_MAJOR) {
709 buffer[i * 3 + 0] = n.x();
710 buffer[i * 3 + 1] = n.y();
711 buffer[i * 3 + 2] = n.z();
712 }
713 else {
714 buffer[0 * ELEM_NUM + i] = n.x();
715 buffer[1 * ELEM_NUM + i] = n.y();
716 buffer[2 * ELEM_NUM + i] = n.z();
717 }
718 ++i;
719 }
720}
721
743template<MeshConcept MeshType>
744void vertexNormalsToBuffer(
745 const MeshType& mesh,
746 auto* buffer,
747 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
748 uint rowNumber = UINT_NULL)
749{
750 elementNormalsToBuffer<ElemId::VERTEX>(mesh, buffer, storage, rowNumber);
751}
752
773template<FaceMeshConcept MeshType>
774void faceNormalsToBuffer(
775 const MeshType& mesh,
776 auto* buffer,
777 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
778 uint rowNumber = UINT_NULL)
779{
780 elementNormalsToBuffer<ElemId::FACE>(mesh, buffer, storage, rowNumber);
781}
782
807template<FaceMeshConcept MeshType>
808void triangulatedFaceNormalsToBuffer(
809 const MeshType& mesh,
810 auto* buffer,
811 const TriPolyIndexBiMap& indexMap,
812 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
813 uint rowNumber = UINT_NULL)
814{
816
817 const uint FACE_NUM =
818 rowNumber == UINT_NULL ? indexMap.triangleNumber() : rowNumber;
819
820 for (const auto& f : mesh.faces()) {
821 const auto& n = f.normal();
822 uint first = indexMap.triangleBegin(f.index());
823 uint last = first + indexMap.triangleNumber(f.index());
824 for (uint t = first; t < last; ++t) {
825 if (storage == MatrixStorageType::ROW_MAJOR) {
826 buffer[t * 3 + 0] = n.x();
827 buffer[t * 3 + 1] = n.y();
828 buffer[t * 3 + 2] = n.z();
829 }
830 else {
831 buffer[0 * FACE_NUM + t] = n.x();
832 buffer[1 * FACE_NUM + t] = n.y();
833 buffer[2 * FACE_NUM + t] = n.z();
834 }
835 }
836 }
837}
838
859template<EdgeMeshConcept MeshType>
860void edgeNormalsToBuffer(
861 const MeshType& mesh,
862 auto* buffer,
863 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
864 uint rowNumber = UINT_NULL)
865{
866 elementNormalsToBuffer<ElemId::EDGE>(mesh, buffer, storage, rowNumber);
867}
868
893template<uint ELEM_ID, MeshConcept MeshType>
894void elementColorsToBuffer(
895 const MeshType& mesh,
896 auto* buffer,
897 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
898 Color::Representation representation = Color::Representation::INT_0_255,
899 uint rowNumber = UINT_NULL)
900{
901 requirePerElementComponent<ELEM_ID, CompId::COLOR>(mesh);
902
903 const bool R_INT = representation == Color::Representation::INT_0_255;
904
905 const uint ELEM_NUM =
906 rowNumber == UINT_NULL ? mesh.template number<ELEM_ID>() : rowNumber;
907
908 for (uint i = 0;
909 const auto& c : mesh.template elements<ELEM_ID>() | views::colors) {
910 if (storage == MatrixStorageType::ROW_MAJOR) {
911 buffer[i * 4 + 0] = R_INT ? c.red() : c.redF();
912 buffer[i * 4 + 1] = R_INT ? c.green() : c.greenF();
913 buffer[i * 4 + 2] = R_INT ? c.blue() : c.blueF();
914 buffer[i * 4 + 3] = R_INT ? c.alpha() : c.alphaF();
915 }
916 else {
917 buffer[0 * ELEM_NUM + i] = R_INT ? c.red() : c.redF();
918 buffer[1 * ELEM_NUM + i] = R_INT ? c.green() : c.greenF();
919 buffer[2 * ELEM_NUM + i] = R_INT ? c.blue() : c.blueF();
920 buffer[3 * ELEM_NUM + i] = R_INT ? c.alpha() : c.alphaF();
921 }
922 ++i;
923 }
924}
925
947template<uint ELEM_ID, MeshConcept MeshType>
948void elementColorsToBuffer(
949 const MeshType& mesh,
950 auto* buffer,
951 Color::Format colorFormat)
952{
953 requirePerElementComponent<ELEM_ID, CompId::COLOR>(mesh);
954
955 for (uint i = 0;
956 const auto& c : mesh.template elements<ELEM_ID>() | views::colors) {
957 switch (colorFormat) {
958 using enum Color::Format;
959 case ABGR: buffer[i] = c.abgr(); break;
960 case ARGB: buffer[i] = c.argb(); break;
961 case RGBA: buffer[i] = c.rgba(); break;
962 case BGRA: buffer[i] = c.bgra(); break;
963 }
964 ++i;
965 }
966}
967
992template<MeshConcept MeshType>
993void vertexColorsToBuffer(
994 const MeshType& mesh,
995 auto* buffer,
996 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
997 Color::Representation representation = Color::Representation::INT_0_255,
998 uint rowNumber = UINT_NULL)
999{
1000 elementColorsToBuffer<ElemId::VERTEX>(
1001 mesh, buffer, storage, representation, rowNumber);
1002}
1003
1024template<MeshConcept MeshType>
1025void vertexColorsToBuffer(
1026 const MeshType& mesh,
1027 auto* buffer,
1028 Color::Format colorFormat)
1029{
1030 elementColorsToBuffer<ElemId::VERTEX>(mesh, buffer, colorFormat);
1031}
1032
1056template<FaceMeshConcept MeshType>
1057void faceColorsToBuffer(
1058 const MeshType& mesh,
1059 auto* buffer,
1060 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
1061 Color::Representation representation = Color::Representation::INT_0_255,
1062 uint rowNumber = UINT_NULL)
1063{
1064 elementColorsToBuffer<ElemId::FACE>(
1065 mesh, buffer, storage, representation, rowNumber);
1066}
1067
1094template<FaceMeshConcept MeshType>
1095void triangulatedFaceColorsToBuffer(
1096 const MeshType& mesh,
1097 auto* buffer,
1098 const TriPolyIndexBiMap& indexMap,
1099 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
1100 Color::Representation representation = Color::Representation::INT_0_255,
1101 uint rowNumber = UINT_NULL)
1102{
1103 requirePerFaceColor(mesh);
1104
1105 const bool R_INT = representation == Color::Representation::INT_0_255;
1106
1107 const uint FACE_NUM =
1108 rowNumber == UINT_NULL ? indexMap.triangleNumber() : rowNumber;
1109
1110 for (const auto& f : mesh.faces()) {
1111 const auto& c = f.color();
1112 uint first = indexMap.triangleBegin(f.index());
1113 uint last = first + indexMap.triangleNumber(f.index());
1114 for (uint t = first; t < last; ++t) {
1115 if (storage == MatrixStorageType::ROW_MAJOR) {
1116 buffer[t * 4 + 0] = R_INT ? c.red() : c.redF();
1117 buffer[t * 4 + 1] = R_INT ? c.green() : c.greenF();
1118 buffer[t * 4 + 2] = R_INT ? c.blue() : c.blueF();
1119 buffer[t * 4 + 3] = R_INT ? c.alpha() : c.alphaF();
1120 }
1121 else {
1122 buffer[0 * FACE_NUM + t] = R_INT ? c.red() : c.redF();
1123 buffer[1 * FACE_NUM + t] = R_INT ? c.green() : c.greenF();
1124 buffer[2 * FACE_NUM + t] = R_INT ? c.blue() : c.blueF();
1125 buffer[3 * FACE_NUM + t] = R_INT ? c.alpha() : c.alphaF();
1126 }
1127 }
1128 }
1129}
1130
1151template<FaceMeshConcept MeshType>
1152void faceColorsToBuffer(
1153 const MeshType& mesh,
1154 auto* buffer,
1155 Color::Format colorFormat)
1156{
1157 elementColorsToBuffer<ElemId::FACE>(mesh, buffer, colorFormat);
1158}
1159
1183template<FaceMeshConcept MeshType>
1184void triangulatedFaceColorsToBuffer(
1185 const MeshType& mesh,
1186 auto* buffer,
1187 const TriPolyIndexBiMap& indexMap,
1188 Color::Format colorFormat)
1189{
1190 requirePerElementComponent<ElemId::FACE, CompId::COLOR>(mesh);
1191
1192 for (const auto& f : mesh.faces()) {
1193 const auto& c = f.color();
1194 uint first = indexMap.triangleBegin(f.index());
1195 uint last = first + indexMap.triangleNumber(f.index());
1196 for (uint t = first; t < last; ++t) {
1197 switch (colorFormat) {
1198 using enum Color::Format;
1199 case ABGR: buffer[t] = c.abgr(); break;
1200 case ARGB: buffer[t] = c.argb(); break;
1201 case RGBA: buffer[t] = c.rgba(); break;
1202 case BGRA: buffer[t] = c.bgra(); break;
1203 }
1204 }
1205 }
1206}
1207
1231template<EdgeMeshConcept MeshType>
1232void edgeColorsToBuffer(
1233 const MeshType& mesh,
1234 auto* buffer,
1235 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
1236 Color::Representation representation = Color::Representation::INT_0_255,
1237 uint rowNumber = UINT_NULL)
1238{
1239 elementColorsToBuffer<ElemId::EDGE>(
1240 mesh, buffer, storage, representation, rowNumber);
1241}
1242
1263template<EdgeMeshConcept MeshType>
1264void edgeColorsToBuffer(
1265 const MeshType& mesh,
1266 auto* buffer,
1267 Color::Format colorFormat)
1268{
1269 elementColorsToBuffer<ElemId::EDGE>(mesh, buffer, colorFormat);
1270}
1271
1291template<uint ELEM_ID, MeshConcept MeshType>
1292void elementQualityToBuffer(const MeshType& mesh, auto* buffer)
1293{
1294 requirePerElementComponent<ELEM_ID, CompId::QUALITY>(mesh);
1295
1296 for (uint i = 0;
1297 const auto& q : mesh.template elements<ELEM_ID>() | views::quality) {
1298 buffer[i] = q;
1299 ++i;
1300 }
1301}
1302
1321template<MeshConcept MeshType>
1322void vertexQualityToBuffer(const MeshType& mesh, auto* buffer)
1323{
1324 elementQualityToBuffer<ElemId::VERTEX>(mesh, buffer);
1325}
1326
1344template<MeshConcept MeshType>
1345void faceQualityToBuffer(const MeshType& mesh, auto* buffer)
1346{
1347 elementQualityToBuffer<ElemId::FACE>(mesh, buffer);
1348}
1349
1367template<MeshConcept MeshType>
1368void edgeQualityToBuffer(const MeshType& mesh, auto* buffer)
1369{
1370 elementQualityToBuffer<ElemId::FACE>(mesh, buffer);
1371}
1372
1394template<MeshConcept MeshType>
1395void vertexTexCoordsToBuffer(
1396 const MeshType& mesh,
1397 auto* buffer,
1398 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
1399 uint rowNumber = UINT_NULL)
1400{
1401 requirePerVertexTexCoord(mesh);
1402
1403 const uint VERT_NUM =
1404 rowNumber == UINT_NULL ? mesh.vertexNumber() : rowNumber;
1405
1406 for (uint i = 0; const auto& t : mesh.vertices() | views::texCoords) {
1407 if (storage == MatrixStorageType::ROW_MAJOR) {
1408 buffer[i * 2 + 0] = t.u();
1409 buffer[i * 2 + 1] = t.v();
1410 }
1411 else {
1412 buffer[0 * VERT_NUM + i] = t.u();
1413 buffer[1 * VERT_NUM + i] = t.v();
1414 }
1415 ++i;
1416 }
1417}
1418
1437template<MeshConcept MeshType>
1438void vertexTexCoordIndicesToBuffer(const MeshType& mesh, auto* buffer)
1439{
1440 requirePerVertexTexCoord(mesh);
1441
1442 for (uint i = 0; const auto& t : mesh.vertices() | views::texCoords) {
1443 buffer[i] = t.index();
1444 ++i;
1445 }
1446}
1447
1471template<FaceMeshConcept MeshType>
1472void vertexTexCoordIndicesAsFaceTexCoordIndicesToBuffer(
1473 const MeshType& mesh,
1474 auto* buffer)
1475{
1476 requirePerVertexTexCoord(mesh);
1477
1478 for (uint i = 0; const auto& f : mesh.faces()) {
1479 ushort ti = f.vertex(0)->texCoord()->index();
1480 buffer[i] = ti;
1481 ++i;
1482 }
1483}
1484
1509template<FaceMeshConcept MeshType>
1510void vertexTexCoordIndicesAsTriangulatedFaceTexCoordIndicesToBuffer(
1511 const MeshType& mesh,
1512 auto* buffer,
1513 const TriPolyIndexBiMap& indexMap)
1514{
1515 requirePerVertexTexCoord(mesh);
1516
1517 for (const auto& f : mesh.faces()) {
1518 ushort ti = f.vertex(0)->texCoord().index();
1519 uint first = indexMap.triangleBegin(f.index());
1520 uint last = first + indexMap.triangleNumber(f.index());
1521 for (uint t = first; t < last; ++t) {
1522 buffer[t] = ti;
1523 }
1524 }
1525}
1526
1564template<FaceMeshConcept MeshType>
1566 const MeshType& mesh,
1567 auto* buffer,
1568 uint largestFaceSize = 3,
1569 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
1570 uint rowNumber = UINT_NULL)
1571{
1573
1574 const uint FACE_NUM =
1575 rowNumber == UINT_NULL ? mesh.faceNumber() : rowNumber;
1576
1577 for (uint i = 0; const auto& f : mesh.faces()) {
1578 for (uint j = 0; j < largestFaceSize * 2; ++j) {
1579 uint fi = j / 2;
1580 uint index = i * largestFaceSize * 2 + j;
1581 if (storage == MatrixStorageType::COLUMN_MAJOR)
1582 index = j * FACE_NUM + i;
1583 if (fi < f.wedgeTexCoordsNumber()) {
1584 const auto& w = f.wedgeTexCoord(fi);
1585 if (j % 2 == 0)
1586 buffer[index] = w.u();
1587 else
1588 buffer[index] = w.v();
1589 }
1590 else {
1591 buffer[index] = 0;
1592 }
1593 }
1594 ++i;
1595 }
1596}
1597
1616template<FaceMeshConcept MeshType>
1617void faceWedgeTexCoordIndicesToBuffer(const MeshType& mesh, auto* buffer)
1618{
1620
1621 for (uint i = 0; const auto& f : mesh.faces()) {
1622 buffer[i] = f.textureIndex();
1623 ++i;
1624 }
1625}
1626
1648template<FaceMeshConcept MeshType>
1650 const MeshType& mesh,
1651 auto* buffer,
1652 const TriPolyIndexBiMap& indexMap)
1653{
1655
1656 for (const auto& f : mesh.faces()) {
1657 uint first = indexMap.triangleBegin(f.index());
1658 uint last = first + indexMap.triangleNumber(f.index());
1659 for (uint t = first; t < last; ++t) {
1660 buffer[t] = f.textureIndex();
1661 }
1662 }
1663}
1664
1709template<FaceMeshConcept MeshType>
1711 const MeshType& mesh,
1712 const std::vector<std::pair<vcl::uint, vcl::uint>>& vertWedgeMap,
1713 const std::list<std::list<std::pair<vcl::uint, vcl::uint>>>&
1715 auto* buffer,
1716 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR)
1717{
1718 using TexCoordType = typename MeshType::FaceType::WedgeTexCoordType;
1719
1721
1722 const uint VERT_NUM = mesh.vertexNumber() + facesToReassign.size();
1723
1724 // first export the texcoords of the non-duplicated vertices, using the
1725 // vertWedgeMap to get the texcoord index in the face
1726 uint vi = 0; // current vertex (or current row in the matrix)
1727 for (const auto& v : mesh.vertices()) {
1728 TexCoordType w;
1729 uint fInd = vertWedgeMap[vi].first;
1730 uint wInd = vertWedgeMap[vi].second;
1731
1732 // check if the vi is referenced
1733 if (fInd != UINT_NULL && wInd != UINT_NULL) {
1734 w = mesh.face(fInd).wedgeTexCoord(wInd);
1735 }
1736 if (storage == MatrixStorageType::ROW_MAJOR) {
1737 buffer[vi * 2 + 0] = w.u();
1738 buffer[vi * 2 + 1] = w.v();
1739 }
1740 else {
1741 buffer[0 * VERT_NUM + vi] = w.u();
1742 buffer[1 * VERT_NUM + vi] = w.v();
1743 }
1744 ++vi;
1745 }
1746
1747 // then append the texcoords of the duplicated vertices, that can be found
1748 // by looking into the any of the facesToReassign element lists
1749 for (const auto& list : facesToReassign) {
1750 assert(list.begin() != list.end());
1751 const auto& p = list.front();
1752 uint fInd = p.first;
1753 uint wInd = p.second;
1754
1755 const auto& w = mesh.face(fInd).wedgeTexCoord(wInd);
1756 if (storage == MatrixStorageType::ROW_MAJOR) {
1757 buffer[vi * 2 + 0] = w.u();
1758 buffer[vi * 2 + 1] = w.v();
1759 }
1760 else {
1761 buffer[0 * VERT_NUM + vi] = w.u();
1762 buffer[1 * VERT_NUM + vi] = w.v();
1763 }
1764 ++vi;
1765 }
1766}
1767
1812template<FaceMeshConcept MeshType>
1814 const MeshType& mesh,
1815 const std::vector<std::pair<vcl::uint, vcl::uint>>& vertWedgeMap,
1816 const std::list<std::list<std::pair<vcl::uint, vcl::uint>>>&
1818 auto* buffer)
1819{
1821
1822 const uint VERT_NUM = mesh.vertexNumber() + facesToReassign.size();
1823
1824 // first export the tex indices of the non-duplicated vertices, using the
1825 // vertWedgeMap to get the texcoord index in the face
1826 uint vi = 0; // current vertex (or current row in the matrix)
1827 for (const auto& v : mesh.vertices()) {
1828 uint fInd = vertWedgeMap[vi].first;
1829 ushort ti = mesh.face(fInd).textureIndex();
1830 buffer[vi] = ti;
1831 ++vi;
1832 }
1833
1834 // then append the tex indices of the duplicated vertices, that can be found
1835 // by looking into the any of the facesToReassign element lists
1836 for (const auto& list : facesToReassign) {
1837 assert(list.begin() != list.end());
1838 const auto& p = list.front();
1839 uint fInd = p.first;
1840
1841 ushort ti = mesh.face(fInd).textureIndex();
1842 buffer[vi] = ti;
1843 ++vi;
1844 }
1845}
1846
1847} // namespace vcl
1848
1849#endif // VCL_ALGORITHMS_MESH_IMPORT_EXPORT_EXPORT_BUFFER_H
Format
Color format enumeration.
Definition color.h:77
Representation
Color representation enumeration.
Definition color.h:64
A class representing a line segment in n-dimensional space. The class is parameterized by a PointConc...
Definition segment.h:43
The TriPolyIndexBiMap class allows to store a bidirectional mapping between a Polygon Mesh and a Tria...
Definition tri_poly_index_bimap.h:50
void reserve(uint nTriangles, uint nPolygons)
Reserves enogh memory for the BiMap. Allows fast insertions.
Definition tri_poly_index_bimap.h:155
void insert(uint triangleIndex, uint polygonIndex)
Performs an insertion into the BiMap, and associates:
Definition tri_poly_index_bimap.h:175
void clear()
Clears the BiMap.
Definition tri_poly_index_bimap.h:142
uint triangleBegin(uint polygonIndex) const
Returns the smallest index of set of triangles mapped to the polygon having the index given as input ...
Definition tri_poly_index_bimap.h:83
uint triangleNumber(uint polygonIndex) const
Returns the number of (consecutive index) triangles mapped to a polygon.
Definition tri_poly_index_bimap.h:112
Definition mesh_concept.h:221
void wedgeTexCoordsAsDuplicatedVertexTexCoordsToBuffer(const MeshType &mesh, const std::vector< std::pair< vcl::uint, vcl::uint > > &vertWedgeMap, const std::list< std::list< std::pair< vcl::uint, vcl::uint > > > &facesToReassign, auto *buffer, MatrixStorageType storage=MatrixStorageType::ROW_MAJOR)
Export wedge texture coordinates to a buffer of the duplicated vertex texture coordinates.
Definition export_buffer.h:1710
void wedgeTexCoordIndicesAsDuplicatedVertexTexCoordIndicesToBuffer(const MeshType &mesh, const std::vector< std::pair< vcl::uint, vcl::uint > > &vertWedgeMap, const std::list< std::list< std::pair< vcl::uint, vcl::uint > > > &facesToReassign, auto *buffer)
Export wedge texture coordinate indices to a buffer of the duplicated vertex texture coordinate indic...
Definition export_buffer.h:1813
std::vector< uint > earCut(Iterator begin, Iterator end)
Triangulates a simple polygon with no holes using the ear-cutting algorithm.
Definition ear_cut.h:92
void triangulatedFaceIndicesToBuffer(const MeshType &mesh, auto *buffer, TriPolyIndexBiMap &indexMap=detail::indexMap, MatrixStorageType storage=MatrixStorageType::ROW_MAJOR, uint numTriangles=UINT_NULL, bool getIndicesAsIfContainerCompact=true)
Export into a buffer the vertex indices for each triangle computed by triangulating the faces of a Me...
Definition export_buffer.h:357
void triangulatedFaceWedgeTexCoordIndicesToBuffer(const MeshType &mesh, auto *buffer, const TriPolyIndexBiMap &indexMap)
Export into a buffer the per triangle wedge texture indices of a mesh. Triangles are computed by tria...
Definition export_buffer.h:1649
void edgeIndicesToBuffer(const MeshType &mesh, auto *buffer, MatrixStorageType storage=MatrixStorageType::ROW_MAJOR, bool getIndicesAsIfContainerCompact=true, uint rowNumber=UINT_NULL)
Export into a buffer the vertex indices for each edge of a Mesh.
Definition export_buffer.h:451
void vertexCoordsToBuffer(const MeshType &mesh, auto *buffer, MatrixStorageType storage=MatrixStorageType::ROW_MAJOR, uint rowNumber=UINT_NULL)
Export the vertex coordinates of a mesh to a buffer.
Definition export_buffer.h:101
void faceIndicesToBuffer(const MeshType &mesh, auto *buffer, bool getIndicesAsIfContainerCompact=true)
Export into a buffer the vertex indices for each face of a Mesh. Faces can be polygons.
Definition export_buffer.h:211
void faceWedgeTexCoordIndicesToBuffer(const MeshType &mesh, auto *buffer)
Export into a buffer the per face wedge texture indices of a mesh.
Definition export_buffer.h:1617
void faceWedgeTexCoordsToBuffer(const MeshType &mesh, auto *buffer, uint largestFaceSize=3, MatrixStorageType storage=MatrixStorageType::ROW_MAJOR, uint rowNumber=UINT_NULL)
Export the selection status of the elements identified by ELEM_ID of a mesh to a buffer.
Definition export_buffer.h:1565
uint faceSizesToBuffer(const MeshType &mesh, auto *buffer)
Export into a buffer the sizes of the faces of a Mesh, and return the sum of the sizes.
Definition export_buffer.h:149
void wireframeIndicesToBuffer(const MeshType &mesh, auto *buffer, MatrixStorageType storage=MatrixStorageType::ROW_MAJOR, bool getIndicesAsIfContainerCompact=true, uint rowNumber=UINT_NULL)
Export into a buffer the vertex indices for each edge that composes the wireframe of the Mesh (i....
Definition export_buffer.h:510
void requirePerFaceWedgeTexCoords(const MeshType &m)
This function asserts that a Mesh has a FaceContainer, the Face has a WedgeTexCoords Component,...
Definition face_requirements.h:947
void requirePerFaceNormal(const MeshType &m)
This function asserts that a Mesh has a FaceContainer, the Face has a Normal Component,...
Definition face_requirements.h:804
void requirePerFaceColor(const MeshType &m)
This function asserts that a Mesh has a FaceContainer, the Face has a Color Component,...
Definition face_requirements.h:734
bool isCompact(const MeshType &m)
Checks if a Mesh is compact, that is if it does not contains deleted elements.
Definition mesh_requirements.h:118
MatrixStorageType
A simple type that enumerates the main storage types for matrices (row or column major).
Definition base.h:76
constexpr uint UINT_NULL
The UINT_NULL value represent a null value of uint that is the maximum value that can be represented ...
Definition base.h:48
constexpr detail::FacesView faces
A view that allows to iterate overt the Face elements of an object.
Definition face.h:52