Visual Computing Library  devel
Loading...
Searching...
No Matches
export_buffer.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2026 *
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 "detail.h"
27
28#include <vclib/algorithms/mesh/utility.h>
29
30#include <vclib/algorithms/core.h>
31#include <vclib/mesh.h>
32#include <vclib/space/complex.h>
33
44namespace vcl {
45
46namespace detail {
47
48inline TriPolyIndexBiMap indexMap;
49
50} // namespace detail
51
73template<MeshConcept MeshType>
75 const MeshType& mesh,
76 auto* buffer,
77 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
78 uint numRows = UINT_NULL)
79{
80 using namespace detail;
81
82 const uint NUM_ROWS = numRows == UINT_NULL ? mesh.vertexCount() : numRows;
83 for (uint i = 0; const auto& p : mesh.vertices() | views::positions) {
84 at(buffer, i, 0, NUM_ROWS, 3, storage) = p.x();
85 at(buffer, i, 1, NUM_ROWS, 3, storage) = p.y();
86 at(buffer, i, 2, NUM_ROWS, 3, storage) = p.z();
87 ++i;
88 }
89}
90
109template<MeshConcept MeshType>
110void vertexQuadIndicesToBuffer(const MeshType& mesh, auto* buffer)
111{
112 // creates indices for two triangles (quad) for each vertex
113 //
114 // 2-------3
115 // | \ |
116 // | \ |
117 // | \ |
118 // | \ |
119 // | \ |
120 // 0-------1
121 //
122 // - Triangle 1: [0, 1, 2]
123 // - Triangle 2: [1, 3, 2]
124 //
125 for (uint i = 0; const auto& v : mesh.vertices()) {
126 const uint baseIdx = i * 6;
127 const uint quadIdx = i * 4;
128 buffer[baseIdx + 0] = quadIdx + 0;
129 buffer[baseIdx + 1] = quadIdx + 1;
130 buffer[baseIdx + 2] = quadIdx + 2;
131 buffer[baseIdx + 3] = quadIdx + 1;
132 buffer[baseIdx + 4] = quadIdx + 3;
133 buffer[baseIdx + 5] = quadIdx + 2;
134 ++i;
135 }
136}
137
162template<FaceMeshConcept MeshType>
163uint faceSizesToBuffer(const MeshType& mesh, auto* buffer)
164{
165 uint sum = 0;
166 for (uint i = 0; const auto& f : mesh.faces()) {
167 buffer[i] = f.vertexCount();
168 sum += f.vertexCount();
169 ++i;
170 }
171 return sum;
172}
173
224template<FaceMeshConcept MeshType>
226 const MeshType& mesh,
227 auto* buffer,
229{
230 const std::vector<uint> vertCompIndices =
231 detail::vertCompactIndices(mesh, getIndicesAsIfContainerCompact);
232
233 // lambda to get the vertex index of a face (considering compact indices)
234 auto vIndex = detail::vIndexLambda(mesh, vertCompIndices);
235
236 for (uint i = 0; const auto& f : mesh.faces()) {
237 for (uint j = 0; j < f.vertexCount(); ++j) {
238 buffer[i] = vIndex(f, j);
239 ++i;
240 }
241 }
242}
243
290template<FaceMeshConcept MeshType>
292 const MeshType& mesh,
293 auto* buffer,
294 uint largestFaceSize,
295 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
297 uint numRows = UINT_NULL)
298{
299 using namespace detail;
300
301 const std::vector<uint> vertCompIndices =
302 detail::vertCompactIndices(mesh, getIndicesAsIfContainerCompact);
303
304 // lambda to get the vertex index of a face (considering compact indices)
305 auto vIndex = detail::vIndexLambda(mesh, vertCompIndices);
306
307 const uint NUM_ROWS = numRows == UINT_NULL ? mesh.faceCount() : numRows;
308
309 for (uint i = 0; const auto& f : mesh.faces()) {
310 for (uint j = 0; j < largestFaceSize; ++j) {
311 at(buffer, i, j, NUM_ROWS, largestFaceSize, storage) =
312 j < f.vertexCount() ? vIndex(f, j) : -1;
313 }
314 ++i;
315 }
316}
317
364template<FaceMeshConcept MeshType>
366 const MeshType& mesh,
367 auto* buffer,
368 TriPolyIndexBiMap& indexMap = detail::indexMap,
369 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
370 uint numTriangles = UINT_NULL,
372{
373 using namespace detail;
374
375 const std::vector<uint> vertCompIndices =
376 detail::vertCompactIndices(mesh, getIndicesAsIfContainerCompact);
377
378 // lambda to get the vertex index of a face (considering compact indices)
379 auto vIndex = detail::vIndexLambda(mesh, vertCompIndices);
380
381 // there will be at least a triangle for each polygon
382 indexMap.clear();
383 indexMap.reserve(mesh.faceCount(), mesh.faceContainerSize());
384
385 if constexpr (TriangleMeshConcept<MeshType>) {
386 // construct the indexMap, which maps each triangle to the face index
387 for (uint t = 0; const auto& f : mesh.faces()) {
388 // map the ith triangle to the f face
389 indexMap.insert(t, f.index());
390 ++t;
391 }
392
394 mesh, buffer, 3, storage, getIndicesAsIfContainerCompact);
395 }
396 else {
397 // if the user did not give the number of triangles, and the buffer
398 // storage is column major, we need to compute the number of resulting
399 // triangles
400 if (numTriangles == UINT_NULL &&
401 storage == MatrixStorageType::COLUMN_MAJOR &&
402 mesh.faceCount() > 0) {
404 }
405 for (uint t = 0; const auto& f : mesh.faces()) {
406 std::vector<uint> vind = vcl::earCut(f);
407
408 // for each triangle of the triangulation (t is the triangle index)
409 for (uint vi = 0; vi < vind.size(); vi += 3) {
410 // map the t-th triangle to the f polygonal face
411 indexMap.insert(t, f.index());
412
413 for (uint k = 0; k < 3; ++k)
414 at(buffer, t, k, numTriangles, 3, storage) =
415 vIndex(f, vind[vi + k]);
416
417 ++t;
418 }
419 }
420 }
421}
422
454template<EdgeMeshConcept MeshType>
456 const MeshType& mesh,
457 auto* buffer,
458 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
460 uint numRows = UINT_NULL)
461{
462 using namespace detail;
463
464 const std::vector<uint> vertCompIndices =
465 detail::vertCompactIndices(mesh, getIndicesAsIfContainerCompact);
466
467 // lambda to get the vertex index of a edge (considering compact indices)
468 auto vIndex = detail::vIndexLambda(mesh, vertCompIndices);
469
470 const uint NUM_ROWS = numRows == UINT_NULL ? mesh.edgeCount() : numRows;
471
472 for (uint i = 0; const auto& e : mesh.edges()) {
473 at(buffer, i, 0, NUM_ROWS, 2, storage) = vIndex(e, 0);
474 at(buffer, i, 1, NUM_ROWS, 2, storage) = 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 numRows = UINT_NULL)
516{
517 using namespace detail;
518
519 const std::vector<uint> vertCompIndices =
520 detail::vertCompactIndices(mesh, getIndicesAsIfContainerCompact);
521
522 // lambda to get the vertex index of a edge (considering compact indices)
523 auto vIndex = detail::vIndexLambda(mesh, vertCompIndices);
524
525 const uint NUM_ROWS =
527
528 for (uint i = 0; const auto& f : mesh.faces()) {
529 for (uint j = 0; j < f.vertexCount(); ++j) {
530 uint v0 = vIndex(f, j);
531 uint v1 = vIndex(f, (j + 1) % f.vertexCount());
532
533 at(buffer, i, 0, NUM_ROWS, 2, storage) = v0;
534 at(buffer, i, 1, NUM_ROWS, 2, storage) = v1;
535
536 ++i;
537 }
538 }
539}
540
568template<uint ELEM_ID, MeshConcept MeshType>
569void elementSelectionToBuffer(const MeshType& mesh, auto* buffer)
570{
571 for (uint i = 0; const auto& e : mesh.template elements<ELEM_ID>()) {
572 buffer[i] = e.selected();
573 ++i;
574 }
575}
576
602template<MeshConcept MeshType>
603void vertexSelectionToBuffer(const MeshType& mesh, auto* buffer)
604{
605 elementSelectionToBuffer<ElemId::VERTEX>(mesh, buffer);
606}
607
633template<FaceMeshConcept MeshType>
634void faceSelectionToBuffer(const MeshType& mesh, auto* buffer)
635{
636 elementSelectionToBuffer<ElemId::FACE>(mesh, buffer);
637}
638
664template<EdgeMeshConcept MeshType>
665void edgeSelectionToBuffer(const MeshType& mesh, auto* buffer)
666{
667 elementSelectionToBuffer<ElemId::EDGE>(mesh, buffer);
668}
669
692template<uint ELEM_ID, MeshConcept MeshType>
693void elementNormalsToBuffer(
694 const MeshType& mesh,
695 auto* buffer,
696 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
697 uint numRows = UINT_NULL)
698{
699 using namespace detail;
700
701 requirePerElementComponent<ELEM_ID, CompId::NORMAL>(mesh);
702
703 const uint NUM_ROWS =
704 numRows == UINT_NULL ? mesh.template count<ELEM_ID>() : numRows;
705
706 for (uint i = 0;
707 const auto& n : mesh.template elements<ELEM_ID>() | views::normals) {
708 at(buffer, i, 0, NUM_ROWS, 3, storage) = n.x();
709 at(buffer, i, 1, NUM_ROWS, 3, storage) = n.y();
710 at(buffer, i, 2, NUM_ROWS, 3, storage) = n.z();
711
712 ++i;
713 }
714}
715
737template<MeshConcept MeshType>
738void vertexNormalsToBuffer(
739 const MeshType& mesh,
740 auto* buffer,
741 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
742 uint numRows = UINT_NULL)
743{
744 elementNormalsToBuffer<ElemId::VERTEX>(mesh, buffer, storage, numRows);
745}
746
767template<FaceMeshConcept MeshType>
768void faceNormalsToBuffer(
769 const MeshType& mesh,
770 auto* buffer,
771 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
772 uint numRows = UINT_NULL)
773{
774 elementNormalsToBuffer<ElemId::FACE>(mesh, buffer, storage, numRows);
775}
776
801template<FaceMeshConcept MeshType>
802void triangulatedFaceNormalsToBuffer(
803 const MeshType& mesh,
804 auto* buffer,
805 const TriPolyIndexBiMap& indexMap,
806 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
807 uint numRows = UINT_NULL)
808{
809 using namespace detail;
810
812
813 const uint NUM_ROWS =
814 numRows == UINT_NULL ? indexMap.triangleCount() : numRows;
815
816 for (const auto& f : mesh.faces()) {
817 const auto& n = f.normal();
818 uint first = indexMap.triangleBegin(f.index());
819 uint last = first + indexMap.triangleCount(f.index());
820 for (uint t = first; t < last; ++t) {
821 at(buffer, t, 0, NUM_ROWS, 3, storage) = n.x();
822 at(buffer, t, 1, NUM_ROWS, 3, storage) = n.y();
823 at(buffer, t, 2, NUM_ROWS, 3, storage) = n.z();
824 }
825 }
826}
827
848template<EdgeMeshConcept MeshType>
849void edgeNormalsToBuffer(
850 const MeshType& mesh,
851 auto* buffer,
852 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
853 uint numRows = UINT_NULL)
854{
855 elementNormalsToBuffer<ElemId::EDGE>(mesh, buffer, storage, numRows);
856}
857
882template<uint ELEM_ID, MeshConcept MeshType>
883void elementColorsToBuffer(
884 const MeshType& mesh,
885 auto* buffer,
886 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
887 Color::Representation representation = Color::Representation::INT_0_255,
888 uint numRows = UINT_NULL)
889{
890 using namespace detail;
891
892 requirePerElementComponent<ELEM_ID, CompId::COLOR>(mesh);
893
894 const bool R_INT = representation == Color::Representation::INT_0_255;
895
896 const uint NUM_ROWS =
897 numRows == UINT_NULL ? mesh.template count<ELEM_ID>() : numRows;
898
899 for (uint i = 0;
900 const auto& c : mesh.template elements<ELEM_ID>() | views::colors) {
901 at(buffer, i, 0, NUM_ROWS, 4, storage) = R_INT ? c.red() : c.redF();
902 at(buffer, i, 1, NUM_ROWS, 4, storage) = R_INT ? c.green() : c.greenF();
903 at(buffer, i, 2, NUM_ROWS, 4, storage) = R_INT ? c.blue() : c.blueF();
904 at(buffer, i, 3, NUM_ROWS, 4, storage) = R_INT ? c.alpha() : c.alphaF();
905
906 ++i;
907 }
908}
909
931template<uint ELEM_ID, MeshConcept MeshType>
932void elementColorsToBuffer(
933 const MeshType& mesh,
934 auto* buffer,
935 Color::Format colorFormat)
936{
937 requirePerElementComponent<ELEM_ID, CompId::COLOR>(mesh);
938
939 for (uint i = 0;
940 const auto& c : mesh.template elements<ELEM_ID>() | views::colors) {
941 switch (colorFormat) {
942 using enum Color::Format;
943 case ABGR: buffer[i] = c.abgr(); break;
944 case ARGB: buffer[i] = c.argb(); break;
945 case RGBA: buffer[i] = c.rgba(); break;
946 case BGRA: buffer[i] = c.bgra(); break;
947 }
948 ++i;
949 }
950}
951
976template<MeshConcept MeshType>
977void vertexColorsToBuffer(
978 const MeshType& mesh,
979 auto* buffer,
980 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
981 Color::Representation representation = Color::Representation::INT_0_255,
982 uint numRows = UINT_NULL)
983{
984 elementColorsToBuffer<ElemId::VERTEX>(
985 mesh, buffer, storage, representation, numRows);
986}
987
1008template<MeshConcept MeshType>
1009void vertexColorsToBuffer(
1010 const MeshType& mesh,
1011 auto* buffer,
1012 Color::Format colorFormat)
1013{
1014 elementColorsToBuffer<ElemId::VERTEX>(mesh, buffer, colorFormat);
1015}
1016
1040template<FaceMeshConcept MeshType>
1041void faceColorsToBuffer(
1042 const MeshType& mesh,
1043 auto* buffer,
1044 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
1045 Color::Representation representation = Color::Representation::INT_0_255,
1046 uint numRows = UINT_NULL)
1047{
1048 elementColorsToBuffer<ElemId::FACE>(
1049 mesh, buffer, storage, representation, numRows);
1050}
1051
1078template<FaceMeshConcept MeshType>
1079void triangulatedFaceColorsToBuffer(
1080 const MeshType& mesh,
1081 auto* buffer,
1082 const TriPolyIndexBiMap& indexMap,
1083 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
1084 Color::Representation representation = Color::Representation::INT_0_255,
1085 uint numRows = UINT_NULL)
1086{
1087 using namespace detail;
1088
1089 requirePerFaceColor(mesh);
1090
1091 const bool R_INT = representation == Color::Representation::INT_0_255;
1092
1093 const uint NUM_ROWS =
1094 numRows == UINT_NULL ? indexMap.triangleCount() : numRows;
1095
1096 for (const auto& f : mesh.faces()) {
1097 const auto& c = f.color();
1098 uint first = indexMap.triangleBegin(f.index());
1099 uint last = first + indexMap.triangleCount(f.index());
1100 for (uint t = first; t < last; ++t) {
1101 at(buffer, t, 0, NUM_ROWS, 4, storage) = R_INT ? c.red() : c.redF();
1102 at(buffer, t, 1, NUM_ROWS, 4, storage) =
1103 R_INT ? c.green() : c.greenF();
1104 at(buffer, t, 2, NUM_ROWS, 4, storage) =
1105 R_INT ? c.blue() : c.blueF();
1106 at(buffer, t, 3, NUM_ROWS, 4, storage) =
1107 R_INT ? c.alpha() : c.alphaF();
1108 }
1109 }
1110}
1111
1132template<FaceMeshConcept MeshType>
1133void faceColorsToBuffer(
1134 const MeshType& mesh,
1135 auto* buffer,
1136 Color::Format colorFormat)
1137{
1138 elementColorsToBuffer<ElemId::FACE>(mesh, buffer, colorFormat);
1139}
1140
1164template<FaceMeshConcept MeshType>
1165void triangulatedFaceColorsToBuffer(
1166 const MeshType& mesh,
1167 auto* buffer,
1168 const TriPolyIndexBiMap& indexMap,
1169 Color::Format colorFormat)
1170{
1171 requirePerElementComponent<ElemId::FACE, CompId::COLOR>(mesh);
1172
1173 for (const auto& f : mesh.faces()) {
1174 const auto& c = f.color();
1175 uint first = indexMap.triangleBegin(f.index());
1176 uint last = first + indexMap.triangleCount(f.index());
1177 for (uint t = first; t < last; ++t) {
1178 switch (colorFormat) {
1179 using enum Color::Format;
1180 case ABGR: buffer[t] = c.abgr(); break;
1181 case ARGB: buffer[t] = c.argb(); break;
1182 case RGBA: buffer[t] = c.rgba(); break;
1183 case BGRA: buffer[t] = c.bgra(); break;
1184 }
1185 }
1186 }
1187}
1188
1212template<EdgeMeshConcept MeshType>
1213void edgeColorsToBuffer(
1214 const MeshType& mesh,
1215 auto* buffer,
1216 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
1217 Color::Representation representation = Color::Representation::INT_0_255,
1218 uint numRows = UINT_NULL)
1219{
1220 elementColorsToBuffer<ElemId::EDGE>(
1221 mesh, buffer, storage, representation, numRows);
1222}
1223
1244template<EdgeMeshConcept MeshType>
1245void edgeColorsToBuffer(
1246 const MeshType& mesh,
1247 auto* buffer,
1248 Color::Format colorFormat)
1249{
1250 elementColorsToBuffer<ElemId::EDGE>(mesh, buffer, colorFormat);
1251}
1252
1272template<uint ELEM_ID, MeshConcept MeshType>
1273void elementQualityToBuffer(const MeshType& mesh, auto* buffer)
1274{
1275 requirePerElementComponent<ELEM_ID, CompId::QUALITY>(mesh);
1276
1277 for (uint i = 0;
1278 const auto& q : mesh.template elements<ELEM_ID>() | views::quality) {
1279 buffer[i] = q;
1280 ++i;
1281 }
1282}
1283
1302template<MeshConcept MeshType>
1303void vertexQualityToBuffer(const MeshType& mesh, auto* buffer)
1304{
1305 elementQualityToBuffer<ElemId::VERTEX>(mesh, buffer);
1306}
1307
1325template<MeshConcept MeshType>
1326void faceQualityToBuffer(const MeshType& mesh, auto* buffer)
1327{
1328 elementQualityToBuffer<ElemId::FACE>(mesh, buffer);
1329}
1330
1348template<MeshConcept MeshType>
1349void edgeQualityToBuffer(const MeshType& mesh, auto* buffer)
1350{
1351 elementQualityToBuffer<ElemId::FACE>(mesh, buffer);
1352}
1353
1380template<MeshConcept MeshType>
1381void vertexTangentsToBuffer(
1382 const MeshType& mesh,
1383 auto* buffer,
1384 bool storeHandednessAsW = true,
1385 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
1386 uint numRows = UINT_NULL)
1387{
1388 using namespace detail;
1389
1390 requirePerVertexTangent(mesh);
1391
1392 const uint NUM_ROWS = numRows == UINT_NULL ? mesh.vertexCount() : numRows;
1393 const uint NUM_COLS = storeHandednessAsW ? 4 : 3;
1394
1395 for (uint i = 0; const auto& v : mesh.vertices()) {
1396 at(buffer, i, 0, NUM_ROWS, NUM_COLS, storage) = v.tangent().x();
1397 at(buffer, i, 1, NUM_ROWS, NUM_COLS, storage) = v.tangent().y();
1398 at(buffer, i, 2, NUM_ROWS, NUM_COLS, storage) = v.tangent().z();
1399 if (storeHandednessAsW) {
1400 at(buffer, i, 3, NUM_ROWS, NUM_COLS, storage) =
1401 v.tangentRightHanded() ? 1.0 : -1.0;
1402 }
1403
1404 ++i;
1405 }
1406}
1407
1429template<MeshConcept MeshType>
1430void vertexTexCoordsToBuffer(
1431 const MeshType& mesh,
1432 auto* buffer,
1433 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
1434 uint numRows = UINT_NULL)
1435{
1436 using namespace detail;
1437
1438 requirePerVertexTexCoord(mesh);
1439
1440 const uint NUM_ROWS = numRows == UINT_NULL ? mesh.vertexCount() : numRows;
1441
1442 for (uint i = 0; const auto& t : mesh.vertices() | views::texCoords) {
1443 at(buffer, i, 0, NUM_ROWS, 2, storage) = t.u();
1444 at(buffer, i, 1, NUM_ROWS, 2, storage) = t.v();
1445
1446 ++i;
1447 }
1448}
1449
1468template<MeshConcept MeshType>
1469void vertexMaterialIndicesToBuffer(const MeshType& mesh, auto* buffer)
1470{
1471 requirePerVertexMaterialIndex(mesh);
1472
1473 for (uint i = 0; const auto& v : mesh.vertices()) {
1474 buffer[i] = v.materialIndex();
1475 ++i;
1476 }
1477}
1478
1502template<FaceMeshConcept MeshType>
1503void vertexMaterialIndicesAsFaceMaterialIndicesToBuffer(
1504 const MeshType& mesh,
1505 auto* buffer)
1506{
1507 requirePerVertexMaterialIndex(mesh);
1508
1509 for (uint i = 0; const auto& f : mesh.faces()) {
1510 ushort ti = f.vertex(0)->materialIndex();
1511 buffer[i] = ti;
1512 ++i;
1513 }
1514}
1515
1540template<FaceMeshConcept MeshType>
1541void vertexMaterialIndicesAsTriangulatedFaceMaterialIndicesToBuffer(
1542 const MeshType& mesh,
1543 auto* buffer,
1544 const TriPolyIndexBiMap& indexMap)
1545{
1546 requirePerVertexMaterialIndex(mesh);
1547
1548 for (const auto& f : mesh.faces()) {
1549 ushort ti = f.vertex(0)->materialIndex();
1550 uint first = indexMap.triangleBegin(f.index());
1551 uint last = first + indexMap.triangleCount(f.index());
1552 for (uint t = first; t < last; ++t) {
1553 buffer[t] = ti;
1554 }
1555 }
1556}
1557
1595template<FaceMeshConcept MeshType>
1597 const MeshType& mesh,
1598 auto* buffer,
1599 uint largestFaceSize = 3,
1600 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
1601 uint numRows = UINT_NULL)
1602{
1604
1605 const uint NUM_ROWS = numRows == UINT_NULL ? mesh.faceCount() : numRows;
1606
1607 for (uint i = 0; const auto& f : mesh.faces()) {
1608 for (uint j = 0; j < largestFaceSize * 2; ++j) {
1609 uint fi = j / 2;
1610 uint index = i * largestFaceSize * 2 + j;
1611 if (storage == MatrixStorageType::COLUMN_MAJOR)
1612 index = j * NUM_ROWS + i;
1613 if (fi < f.vertexCount()) {
1614 const auto& w = f.wedgeTexCoord(fi);
1615 if (j % 2 == 0)
1616 buffer[index] = w.u();
1617 else
1618 buffer[index] = w.v();
1619 }
1620 else {
1621 buffer[index] = 0;
1622 }
1623 }
1624 ++i;
1625 }
1626}
1627
1646template<FaceMeshConcept MeshType>
1647void faceMaterialIndicesToBuffer(const MeshType& mesh, auto* buffer)
1648{
1650
1651 for (uint i = 0; const auto& f : mesh.faces()) {
1652 buffer[i] = f.materialIndex();
1653 ++i;
1654 }
1655}
1656
1678template<FaceMeshConcept MeshType>
1680 const MeshType& mesh,
1681 auto* buffer,
1682 const TriPolyIndexBiMap& indexMap)
1683{
1685
1686 for (const auto& f : mesh.faces()) {
1687 uint first = indexMap.triangleBegin(f.index());
1688 uint last = first + indexMap.triangleCount(f.index());
1689 for (uint t = first; t < last; ++t) {
1690 buffer[t] = f.materialIndex();
1691 }
1692 }
1693}
1694
1739template<FaceMeshConcept MeshType>
1741 const MeshType& mesh,
1742 const std::vector<std::pair<vcl::uint, vcl::uint>>& vertWedgeMap,
1743 const std::list<std::list<std::pair<vcl::uint, vcl::uint>>>&
1745 auto* buffer,
1746 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR)
1747{
1748 using namespace detail;
1749 using TexCoordType = typename MeshType::FaceType::WedgeTexCoordType;
1750
1752
1753 const uint NUM_ROWS = mesh.vertexCount() + facesToReassign.size();
1754
1755 // first export the texcoords of the non-duplicated vertices, using the
1756 // vertWedgeMap to get the texcoord index in the face
1757 uint vi = 0; // current vertex (or current row in the matrix)
1758 for (const auto& v : mesh.vertices()) {
1759 TexCoordType w;
1760 uint fInd = vertWedgeMap[vi].first;
1761 uint wInd = vertWedgeMap[vi].second;
1762
1763 // check if the vi is referenced
1764 if (fInd != UINT_NULL && wInd != UINT_NULL) {
1765 w = mesh.face(fInd).wedgeTexCoord(wInd);
1766 }
1767 at(buffer, vi, 0, NUM_ROWS, 2, storage) = w.u();
1768 at(buffer, vi, 1, NUM_ROWS, 2, storage) = w.v();
1769
1770 ++vi;
1771 }
1772
1773 // then append the texcoords of the duplicated vertices, that can be found
1774 // by looking into the any of the facesToReassign element lists
1775 for (const auto& list : facesToReassign) {
1776 assert(list.begin() != list.end());
1777 const auto& p = list.front();
1778 uint fInd = p.first;
1779 uint wInd = p.second;
1780
1781 const auto& w = mesh.face(fInd).wedgeTexCoord(wInd);
1782 at(buffer, vi, 0, NUM_ROWS, 2, storage) = w.u();
1783 at(buffer, vi, 1, NUM_ROWS, 2, storage) = w.v();
1784
1785 ++vi;
1786 }
1787}
1788
1831template<FaceMeshConcept MeshType>
1833 const MeshType& mesh,
1834 const std::vector<std::pair<vcl::uint, vcl::uint>>& vertWedgeMap,
1835 const std::list<std::list<std::pair<vcl::uint, vcl::uint>>>&
1837 auto* buffer)
1838{
1840
1841 const uint VERT_NUM = mesh.vertexCount() + facesToReassign.size();
1842
1843 // first export the material indices of the non-duplicated vertices, using
1844 // the vertWedgeMap to get the material index in the face
1845 uint vi = 0; // current vertex (or current row in the matrix)
1846 for (const auto& v : mesh.vertices()) {
1847 uint fInd = vertWedgeMap[vi].first;
1848 ushort ti = mesh.face(fInd).materialIndex();
1849 buffer[vi] = ti;
1850 ++vi;
1851 }
1852
1853 // then append the material indices of the duplicated vertices, that can be
1854 // found by looking into the any of the facesToReassign element lists
1855 for (const auto& list : facesToReassign) {
1856 assert(list.begin() != list.end());
1857 const auto& p = list.front();
1858 uint fInd = p.first;
1859
1860 ushort ti = mesh.face(fInd).materialIndex();
1861 buffer[vi] = ti;
1862 ++vi;
1863 }
1864}
1865
1895template<MeshConcept MeshType>
1897 const MeshType& mesh,
1898 auto* buffer,
1900 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
1901 uint numRows = UINT_NULL)
1902{
1903 using namespace detail;
1904
1905 requireVertexContainerCompactness(mesh);
1906 requirePerVertexAdjacentVertices(mesh);
1907
1908 const uint NUM_ROWS = numRows == UINT_NULL ? mesh.vertexCount() : numRows;
1909
1911
1912 for (uint i = 0; const auto& v : mesh.vertices()) {
1913 uint adjIndex = 0;
1914 for (const auto* a : v.adjVertices()) {
1915 uint idx = a ? a->index() : UINT_NULL;
1916 at(buffer, i, adjIndex, NUM_ROWS, NUM_COLS, storage) = idx;
1917 ++adjIndex;
1918 }
1919 // fill the remaining entries with UINT_NULL
1920 for (; adjIndex < NUM_COLS; ++adjIndex) {
1921 at(buffer, i, adjIndex, NUM_ROWS, NUM_COLS, storage) = UINT_NULL;
1922 }
1923 ++i;
1924 }
1925}
1926
1955template<uint ELEM_ID, FaceMeshConcept MeshType>
1957 const MeshType& mesh,
1958 auto* buffer,
1960 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
1961 uint numRows = UINT_NULL)
1962{
1963 using namespace detail;
1964
1967
1968 const uint NUM_ROWS =
1969 numRows == UINT_NULL ? mesh.template count<ELEM_ID>() : numRows;
1970
1972
1973 for (uint i = 0; const auto& v : mesh.template elements<ELEM_ID>()) {
1974 uint adjIndex = 0;
1975 for (const auto* a : v.adjFaces()) {
1976 uint idx = a ? a->index() : UINT_NULL;
1977 at(buffer, i, adjIndex, NUM_ROWS, NUM_COLS, storage) = idx;
1978 ++adjIndex;
1979 }
1980 // fill the remaining entries with UINT_NULL
1981 for (; adjIndex < NUM_COLS; ++adjIndex) {
1982 at(buffer, i, adjIndex, NUM_ROWS, NUM_COLS, storage) = UINT_NULL;
1983 }
1984 ++i;
1985 }
1986}
1987
2016template<FaceMeshConcept MeshType>
2018 const MeshType& mesh,
2019 auto* buffer,
2021 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
2022 uint numRows = UINT_NULL)
2023{
2025 mesh, buffer, largestAdjacentFacesSize, storage, numRows);
2026}
2027
2049template<FaceMeshConcept MeshType>
2051 const MeshType& mesh,
2052 auto* buffer,
2053 uint largestFacesSize,
2054 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
2055 uint numRows = UINT_NULL)
2056{
2058 mesh, buffer, largestFacesSize, storage, numRows);
2059}
2060
2089template<FaceMeshConcept MeshType>
2091 const MeshType& mesh,
2092 auto* buffer,
2094 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
2096{
2098 mesh, buffer, largestAdjacentFacesSize, storage, numRows);
2099}
2100
2129template<uint ELEM_ID, EdgeMeshConcept MeshType>
2131 const MeshType& mesh,
2132 auto* buffer,
2134 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
2135 uint numRows = UINT_NULL)
2136{
2137 using namespace detail;
2138
2141
2142 const uint NUM_ROWS =
2143 numRows == UINT_NULL ? mesh.template count<ELEM_ID>() : numRows;
2144
2146
2147 for (uint i = 0; const auto& v : mesh.template elements<ELEM_ID>()) {
2148 uint adjIndex = 0;
2149 for (const auto* a : v.adjEdges()) {
2150 uint idx = a ? a->index() : UINT_NULL;
2151 at(buffer, i, adjIndex, NUM_ROWS, NUM_COLS, storage) = idx;
2152 ++adjIndex;
2153 }
2154 // fill the remaining entries with UINT_NULL
2155 for (; adjIndex < NUM_COLS; ++adjIndex) {
2156 at(buffer, i, adjIndex, NUM_ROWS, NUM_COLS, storage) = UINT_NULL;
2157 }
2158 ++i;
2159 }
2160}
2161
2190template<EdgeMeshConcept MeshType>
2192 const MeshType& mesh,
2193 auto* buffer,
2195 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
2196 uint numRows = UINT_NULL)
2197{
2199 mesh, buffer, largestAdjacentEdgesSize, storage, numRows);
2200}
2201
2230template<EdgeMeshConcept MeshType>
2232 const MeshType& mesh,
2233 auto* buffer,
2235 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
2237{
2239 mesh, buffer, largestAdjacentEdgesSize, storage, numRows);
2240}
2241
2270template<EdgeMeshConcept MeshType>
2272 const MeshType& mesh,
2273 auto* buffer,
2275 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
2276 uint numRows = UINT_NULL)
2277{
2279 mesh, buffer, largestAdjacentEdgesSize, storage, numRows);
2280}
2281
2282} // namespace vcl
2283
2284#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:41
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:141
void insert(uint triangleIndex, uint polygonIndex)
Performs an insertion into the BiMap, and associates:
Definition tri_poly_index_bimap.h:162
void clear()
Clears the BiMap.
Definition tri_poly_index_bimap.h:127
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:84
uint triangleCount(uint polygonIndex) const
Returns the number of (consecutive index) triangles mapped to a polygon.
Definition tri_poly_index_bimap.h:113
The EdgeMeshConcept is evaluated true if the type T is a Mesh (it satisfies the vcl::MeshConcept) and...
Definition edge_requirements.h:58
The FaceMeshConcept is evaluated true if the type T is a Mesh (it satisfies the vcl::MeshConcept) and...
Definition face_requirements.h:70
Definition face_requirements.h:73
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:1740
void faceMaterialIndicesAsDuplicatedVertexMaterialIndicesToBuffer(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 face material indices to a buffer of the duplicated vertex material indices.
Definition export_buffer.h:1832
MatrixStorageType
A simple type that enumerates the main storage types for matrices (row or column major).
Definition base.h:89
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:49
std::vector< uint > earCut(Iterator begin, Iterator end)
Triangulates a simple polygon with no holes using the ear-cutting algorithm.
Definition ear_cut.h:90
void requireEdgeContainerCompactness(const MeshType &m)
This function asserts that a Mesh has the EdgeContainer compact (no elements flagged as deleted).
Definition edge_requirements.h:597
void edgeAdjacentFacesToBuffer(const MeshType &mesh, auto *buffer, uint largestAdjacentFacesSize, MatrixStorageType storage=MatrixStorageType::ROW_MAJOR, uint numRows=UINT_NULL)
Export into a buffer the adjacent faces indices for each edge of a Mesh. The number of adjacent faces...
Definition export_buffer.h:2090
void wireframeVertexIndicesToBuffer(const MeshType &mesh, auto *buffer, MatrixStorageType storage=MatrixStorageType::ROW_MAJOR, bool getIndicesAsIfContainerCompact=true, uint numRows=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 triangulatedFaceVertexIndicesToBuffer(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:365
void elementAdjacentEdgesToBuffer(const MeshType &mesh, auto *buffer, uint largestAdjacentEdgesSize, MatrixStorageType storage=MatrixStorageType::ROW_MAJOR, uint numRows=UINT_NULL)
Export into a buffer the adjacent edges indices for each ELEM_ID element of a Mesh....
Definition export_buffer.h:2130
void edgeAdjacentEdgesToBuffer(const MeshType &mesh, auto *buffer, uint largestAdjacentEdgesSize, MatrixStorageType storage=MatrixStorageType::ROW_MAJOR, uint numRows=UINT_NULL)
Export into a buffer the adjacent edges indices for each edge of a Mesh. The number of adjacent edges...
Definition export_buffer.h:2271
void edgeVertexIndicesToBuffer(const MeshType &mesh, auto *buffer, MatrixStorageType storage=MatrixStorageType::ROW_MAJOR, bool getIndicesAsIfContainerCompact=true, uint numRows=UINT_NULL)
Export into a buffer the vertex indices for each edge of a Mesh.
Definition export_buffer.h:455
void triangulatedFaceMaterialIndicesToBuffer(const MeshType &mesh, auto *buffer, const TriPolyIndexBiMap &indexMap)
Export into a buffer the per triangle material indices of a mesh. Triangles are computed by triangula...
Definition export_buffer.h:1679
void faceAdjacentEdgesToBuffer(const MeshType &mesh, auto *buffer, uint largestAdjacentEdgesSize, MatrixStorageType storage=MatrixStorageType::ROW_MAJOR, uint numRows=UINT_NULL)
Export into a buffer the adjacent edges indices for each face of a Mesh. The number of adjacent edges...
Definition export_buffer.h:2231
void faceVertexIndicesToBuffer(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:225
void vertexPositionsToBuffer(const MeshType &mesh, auto *buffer, MatrixStorageType storage=MatrixStorageType::ROW_MAJOR, uint numRows=UINT_NULL)
Export the vertex positions of a mesh to a buffer.
Definition export_buffer.h:74
void faceWedgeTexCoordsToBuffer(const MeshType &mesh, auto *buffer, uint largestFaceSize=3, MatrixStorageType storage=MatrixStorageType::ROW_MAJOR, uint numRows=UINT_NULL)
Export the selection status of the elements identified by ELEM_ID of a mesh to a buffer.
Definition export_buffer.h:1596
void elementAdjacentFacesToBuffer(const MeshType &mesh, auto *buffer, uint largestAdjacentFacesSize, MatrixStorageType storage=MatrixStorageType::ROW_MAJOR, uint numRows=UINT_NULL)
Export into a buffer the adjacent faces indices for each ELEM_ID element of a Mesh....
Definition export_buffer.h:1956
void vertexAdjacentVerticesToBuffer(const MeshType &mesh, auto *buffer, uint largestAdjacentVerticesSize, MatrixStorageType storage=MatrixStorageType::ROW_MAJOR, uint numRows=UINT_NULL)
Export into a buffer the adjacent vertex indices for each vertex of a Mesh. The number of adjacent ve...
Definition export_buffer.h:1896
void vertexQuadIndicesToBuffer(const MeshType &mesh, auto *buffer)
Export the indices of a quad per vertex to a buffer.
Definition export_buffer.h:110
void vertexAdjacentEdgesToBuffer(const MeshType &mesh, auto *buffer, uint largestAdjacentEdgesSize, MatrixStorageType storage=MatrixStorageType::ROW_MAJOR, uint numRows=UINT_NULL)
Export into a buffer the adjacent edges indices for each vertex of a Mesh. The number of adjacent edg...
Definition export_buffer.h:2191
void vertexAdjacentFacesToBuffer(const MeshType &mesh, auto *buffer, uint largestAdjacentFacesSize, MatrixStorageType storage=MatrixStorageType::ROW_MAJOR, uint numRows=UINT_NULL)
Export into a buffer the adjacent faces indices for each vertex of a Mesh. The number of adjacent fac...
Definition export_buffer.h:2017
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:163
void faceAdjacentFacesToBuffer(const MeshType &mesh, auto *buffer, uint largestFacesSize, MatrixStorageType storage=MatrixStorageType::ROW_MAJOR, uint numRows=UINT_NULL)
Export into a buffer the adjacent faces indices for each face of a Mesh. The number of adjacent faces...
Definition export_buffer.h:2050
void faceMaterialIndicesToBuffer(const MeshType &mesh, auto *buffer)
Export into a buffer the per face material indices of a mesh.
Definition export_buffer.h:1647
void requirePerFaceWedgeTexCoords(const MeshType &m)
This function asserts that a Mesh has a FaceContainer, the Face has a WedgeTexCoords Component,...
Definition face_requirements.h:1322
void requirePerFaceMaterialIndex(const MeshType &m)
This function asserts that a Mesh has a FaceContainer, the Face has a MaterialIndex Component,...
Definition face_requirements.h:1143
void requireFaceContainerCompactness(const MeshType &m)
This function asserts that a Mesh has the FaceContainer compact (no elements flagged as deleted).
Definition face_requirements.h:966
void requirePerFaceNormal(const MeshType &m)
This function asserts that a Mesh has a FaceContainer, the Face has a Normal Component,...
Definition face_requirements.h:1179
void requirePerFaceColor(const MeshType &m)
This function asserts that a Mesh has a FaceContainer, the Face has a Color Component,...
Definition face_requirements.h:1073
uint faceVertexReferencesCount(const FaceMeshConcept auto &mesh)
Count the total number of vertex references in the mesh faces.
Definition topology.h:182
uint triangulatedFaceCount(const FaceMeshConcept auto &mesh)
Counts the number of resulting triangles if the input mesh would be triangulated by splitting each fa...
Definition topology.h:240
uint largestFaceSize(const FaceMeshConcept auto &mesh)
Returns the largest face size in the mesh.
Definition topology.h:212
constexpr detail::FacesView faces
A view that allows to iterate overt the Face elements of an object.
Definition face.h:84