Visual Computing Library  devel
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.h>
27#include <vclib/mesh.h>
28#include <vclib/space/complex.h>
29
43namespace vcl {
44
45namespace detail {
46
47// returns a non-empty vector if the vertex container is not compact and the
48// user wants compact indices
49std::vector<uint> vertCompactIndices(const auto& mesh, bool wantCompact)
50{
51 std::vector<uint> vertCompIndices;
52
53 bool isCompact = mesh.vertexNumber() == mesh.vertexContainerSize();
54
55 if (wantCompact && !isCompact)
56 vertCompIndices = mesh.vertexCompactIndices();
57 return vertCompIndices;
58}
59
60// lambda to get the vertex index of a face (considering compact vertex indices)
61auto vIndexLambda(const auto& mesh, const std::vector<uint>& vertCompIndices)
62{
63 // lambda to get the vertex index of a face (considering compact indices)
64 auto vIndex = [&vertCompIndices](const auto& f, uint i) {
65 if (vertCompIndices.size() > 0)
66 return vertCompIndices[f.vertexIndex(i)];
67 else
68 return f.vertexIndex(i);
69 };
70
71 return vIndex;
72}
73
74inline TriPolyIndexBiMap indexMap;
75
76} // namespace detail
77
99template<MeshConcept MeshType>
101 const MeshType& mesh,
102 auto* buffer,
103 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
104 uint rowNumber = UINT_NULL)
105{
106 const uint VERT_NUM =
107 rowNumber == UINT_NULL ? mesh.vertexNumber() : rowNumber;
108 for (uint i = 0; const auto& c : mesh.vertices() | views::positions) {
109 if (storage == MatrixStorageType::ROW_MAJOR) {
110 buffer[i * 3 + 0] = c.x();
111 buffer[i * 3 + 1] = c.y();
112 buffer[i * 3 + 2] = c.z();
113 }
114 else {
115 buffer[0 * VERT_NUM + i] = c.x();
116 buffer[1 * VERT_NUM + i] = c.y();
117 buffer[2 * VERT_NUM + i] = c.z();
118 }
119 ++i;
120 }
121}
122
141template<MeshConcept MeshType>
142void vertexQuadIndicesToBuffer(const MeshType& mesh, auto* buffer)
143{
144 // creates indices for two triangles (quad) for each vertex
145 //
146 // 2-------3
147 // | \ |
148 // | \ |
149 // | \ |
150 // | \ |
151 // | \ |
152 // 0-------1
153 //
154 // - Triangle 1: [0, 1, 2]
155 // - Triangle 2: [1, 3, 2]
156 //
157 for (uint i = 0; const auto& v : mesh.vertices()) {
158 const uint baseIdx = i * 6;
159 const uint quadIdx = i * 4;
160 buffer[baseIdx + 0] = quadIdx + 0;
161 buffer[baseIdx + 1] = quadIdx + 1;
162 buffer[baseIdx + 2] = quadIdx + 2;
163 buffer[baseIdx + 3] = quadIdx + 1;
164 buffer[baseIdx + 4] = quadIdx + 3;
165 buffer[baseIdx + 5] = quadIdx + 2;
166 ++i;
167 }
168}
169
194template<FaceMeshConcept MeshType>
195uint faceSizesToBuffer(const MeshType& mesh, auto* buffer)
196{
197 uint sum = 0;
198 for (uint i = 0; const auto& f : mesh.faces()) {
199 buffer[i] = f.vertexNumber();
200 sum += f.vertexNumber();
201 ++i;
202 }
203 return sum;
204}
205
256template<FaceMeshConcept MeshType>
258 const MeshType& mesh,
259 auto* buffer,
261{
262 const std::vector<uint> vertCompIndices =
263 detail::vertCompactIndices(mesh, getIndicesAsIfContainerCompact);
264
265 // lambda to get the vertex index of a face (considering compact indices)
266 auto vIndex = detail::vIndexLambda(mesh, vertCompIndices);
267
268 for (uint i = 0; const auto& f : mesh.faces()) {
269 for (uint j = 0; j < f.vertexNumber(); ++j) {
270 buffer[i] = vIndex(f, j);
271 ++i;
272 }
273 }
274}
275
322template<FaceMeshConcept MeshType>
324 const MeshType& mesh,
325 auto* buffer,
326 uint largestFaceSize,
327 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
329 uint rowNumber = UINT_NULL)
330{
331 const std::vector<uint> vertCompIndices =
332 detail::vertCompactIndices(mesh, getIndicesAsIfContainerCompact);
333
334 // lambda to get the vertex index of a face (considering compact indices)
335 auto vIndex = detail::vIndexLambda(mesh, vertCompIndices);
336
337 const uint FACE_NUM =
338 rowNumber == UINT_NULL ? mesh.faceNumber() : rowNumber;
339
340 for (uint i = 0; const auto& f : mesh.faces()) {
341 for (uint j = 0; j < largestFaceSize; ++j) {
342 uint index = i * largestFaceSize + j;
343 if (storage == MatrixStorageType::COLUMN_MAJOR)
344 index = j * FACE_NUM + i;
345 if (j < f.vertexNumber()) {
346 buffer[index] = vIndex(f, j);
347 }
348 else {
349 buffer[index] = -1;
350 }
351 }
352 ++i;
353 }
354}
355
402template<FaceMeshConcept MeshType>
404 const MeshType& mesh,
405 auto* buffer,
406 TriPolyIndexBiMap& indexMap = detail::indexMap,
407 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
408 uint numTriangles = UINT_NULL,
410{
411 const std::vector<uint> vertCompIndices =
412 detail::vertCompactIndices(mesh, getIndicesAsIfContainerCompact);
413
414 // lambda to get the vertex index of a face (considering compact indices)
415 auto vIndex = detail::vIndexLambda(mesh, vertCompIndices);
416
417 // there will be at least a triangle for each polygon
418 indexMap.clear();
419 indexMap.reserve(mesh.faceNumber(), mesh.faceContainerSize());
420
421 if constexpr (TriangleMeshConcept<MeshType>) {
422 // construct the indexMap, which maps each triangle to the face index
423 for (uint t = 0; const auto& f : mesh.faces()) {
424 // map the ith triangle to the f face
425 indexMap.insert(t, f.index());
426 ++t;
427 }
428
429 return faceIndicesToBuffer(
430 mesh, buffer, 3, storage, getIndicesAsIfContainerCompact);
431 }
432 else {
433 // if the user did not give the number of triangles, and the buffer
434 // storage is column major, we need to compute the number of resulting
435 // triangles
436 if (numTriangles == UINT_NULL &&
437 storage == MatrixStorageType::COLUMN_MAJOR &&
438 mesh.faceNumber() > 0) {
440 }
441 for (uint t = 0; const auto& f : mesh.faces()) {
442 std::vector<uint> vind = vcl::earCut(f);
443
444 // for each triangle of the triangulation (t is the triangle index)
445 for (uint vi = 0; vi < vind.size(); vi += 3) {
446 // map the t-th triangle to the f polygonal face
447 indexMap.insert(t, f.index());
448
449 if (storage == MatrixStorageType::ROW_MAJOR) {
450 buffer[t * 3 + 0] = vIndex(f, vind[vi + 0]);
451 buffer[t * 3 + 1] = vIndex(f, vind[vi + 1]);
452 buffer[t * 3 + 2] = vIndex(f, vind[vi + 2]);
453 }
454 else {
455 buffer[0 * numTriangles + t] = vIndex(f, vind[vi + 0]);
456 buffer[1 * numTriangles + t] = vIndex(f, vind[vi + 1]);
457 buffer[2 * numTriangles + t] = vIndex(f, vind[vi + 2]);
458 }
459 ++t;
460 }
461 }
462 }
463}
464
496template<EdgeMeshConcept MeshType>
498 const MeshType& mesh,
499 auto* buffer,
500 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
502 uint rowNumber = UINT_NULL)
503{
504 const std::vector<uint> vertCompIndices =
505 detail::vertCompactIndices(mesh, getIndicesAsIfContainerCompact);
506
507 // lambda to get the vertex index of a edge (considering compact indices)
508 auto vIndex = detail::vIndexLambda(mesh, vertCompIndices);
509
510 const uint EDGE_NUM =
511 rowNumber == UINT_NULL ? mesh.edgeNumber() : rowNumber;
512
513 for (uint i = 0; const auto& e : mesh.edges()) {
514 if (storage == MatrixStorageType::ROW_MAJOR) {
515 buffer[i * 2 + 0] = vIndex(e, 0);
516 buffer[i * 2 + 1] = vIndex(e, 1);
517 }
518 else {
519 buffer[0 * EDGE_NUM + i] = vIndex(e, 0);
520 buffer[1 * EDGE_NUM + i] = vIndex(e, 1);
521 }
522 ++i;
523 }
524}
525
555template<FaceMeshConcept MeshType>
557 const MeshType& mesh,
558 auto* buffer,
559 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
561 uint rowNumber = UINT_NULL)
562{
563 const std::vector<uint> vertCompIndices =
564 detail::vertCompactIndices(mesh, getIndicesAsIfContainerCompact);
565
566 // lambda to get the vertex index of a edge (considering compact indices)
567 auto vIndex = detail::vIndexLambda(mesh, vertCompIndices);
568
569 const uint EDGE_NUM =
571
572 for (uint i = 0; const auto& f : mesh.faces()) {
573 for (uint j = 0; j < f.vertexNumber(); ++j) {
574 uint v0 = vIndex(f, j);
575 uint v1 = vIndex(f, (j + 1) % f.vertexNumber());
576 if (storage == MatrixStorageType::ROW_MAJOR) {
577 buffer[i * 2 + 0] = v0;
578 buffer[i * 2 + 1] = v1;
579 }
580 else {
581 buffer[0 * EDGE_NUM + i] = v0;
582 buffer[1 * EDGE_NUM + i] = v1;
583 }
584 ++i;
585 }
586 }
587}
588
616template<uint ELEM_ID, MeshConcept MeshType>
617void elementSelectionToBuffer(const MeshType& mesh, auto* buffer)
618{
619 for (uint i = 0; const auto& e : mesh.template elements<ELEM_ID>()) {
620 buffer[i] = e.selected();
621 ++i;
622 }
623}
624
650template<MeshConcept MeshType>
651void vertexSelectionToBuffer(const MeshType& mesh, auto* buffer)
652{
653 elementSelectionToBuffer<ElemId::VERTEX>(mesh, buffer);
654}
655
681template<FaceMeshConcept MeshType>
682void faceSelectionToBuffer(const MeshType& mesh, auto* buffer)
683{
684 elementSelectionToBuffer<ElemId::FACE>(mesh, buffer);
685}
686
712template<EdgeMeshConcept MeshType>
713void edgeSelectionToBuffer(const MeshType& mesh, auto* buffer)
714{
715 elementSelectionToBuffer<ElemId::EDGE>(mesh, buffer);
716}
717
740template<uint ELEM_ID, MeshConcept MeshType>
741void elementNormalsToBuffer(
742 const MeshType& mesh,
743 auto* buffer,
744 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
745 uint rowNumber = UINT_NULL)
746{
747 requirePerElementComponent<ELEM_ID, CompId::NORMAL>(mesh);
748
749 const uint ELEM_NUM =
750 rowNumber == UINT_NULL ? mesh.template number<ELEM_ID>() : rowNumber;
751
752 for (uint i = 0;
753 const auto& n : mesh.template elements<ELEM_ID>() | views::normals) {
754 if (storage == MatrixStorageType::ROW_MAJOR) {
755 buffer[i * 3 + 0] = n.x();
756 buffer[i * 3 + 1] = n.y();
757 buffer[i * 3 + 2] = n.z();
758 }
759 else {
760 buffer[0 * ELEM_NUM + i] = n.x();
761 buffer[1 * ELEM_NUM + i] = n.y();
762 buffer[2 * ELEM_NUM + i] = n.z();
763 }
764 ++i;
765 }
766}
767
789template<MeshConcept MeshType>
790void vertexNormalsToBuffer(
791 const MeshType& mesh,
792 auto* buffer,
793 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
794 uint rowNumber = UINT_NULL)
795{
796 elementNormalsToBuffer<ElemId::VERTEX>(mesh, buffer, storage, rowNumber);
797}
798
819template<FaceMeshConcept MeshType>
820void faceNormalsToBuffer(
821 const MeshType& mesh,
822 auto* buffer,
823 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
824 uint rowNumber = UINT_NULL)
825{
826 elementNormalsToBuffer<ElemId::FACE>(mesh, buffer, storage, rowNumber);
827}
828
853template<FaceMeshConcept MeshType>
854void triangulatedFaceNormalsToBuffer(
855 const MeshType& mesh,
856 auto* buffer,
857 const TriPolyIndexBiMap& indexMap,
858 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
859 uint rowNumber = UINT_NULL)
860{
862
863 const uint FACE_NUM =
864 rowNumber == UINT_NULL ? indexMap.triangleNumber() : rowNumber;
865
866 for (const auto& f : mesh.faces()) {
867 const auto& n = f.normal();
868 uint first = indexMap.triangleBegin(f.index());
869 uint last = first + indexMap.triangleNumber(f.index());
870 for (uint t = first; t < last; ++t) {
871 if (storage == MatrixStorageType::ROW_MAJOR) {
872 buffer[t * 3 + 0] = n.x();
873 buffer[t * 3 + 1] = n.y();
874 buffer[t * 3 + 2] = n.z();
875 }
876 else {
877 buffer[0 * FACE_NUM + t] = n.x();
878 buffer[1 * FACE_NUM + t] = n.y();
879 buffer[2 * FACE_NUM + t] = n.z();
880 }
881 }
882 }
883}
884
905template<EdgeMeshConcept MeshType>
906void edgeNormalsToBuffer(
907 const MeshType& mesh,
908 auto* buffer,
909 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
910 uint rowNumber = UINT_NULL)
911{
912 elementNormalsToBuffer<ElemId::EDGE>(mesh, buffer, storage, rowNumber);
913}
914
939template<uint ELEM_ID, MeshConcept MeshType>
940void elementColorsToBuffer(
941 const MeshType& mesh,
942 auto* buffer,
943 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
944 Color::Representation representation = Color::Representation::INT_0_255,
945 uint rowNumber = UINT_NULL)
946{
947 requirePerElementComponent<ELEM_ID, CompId::COLOR>(mesh);
948
949 const bool R_INT = representation == Color::Representation::INT_0_255;
950
951 const uint ELEM_NUM =
952 rowNumber == UINT_NULL ? mesh.template number<ELEM_ID>() : rowNumber;
953
954 for (uint i = 0;
955 const auto& c : mesh.template elements<ELEM_ID>() | views::colors) {
956 if (storage == MatrixStorageType::ROW_MAJOR) {
957 buffer[i * 4 + 0] = R_INT ? c.red() : c.redF();
958 buffer[i * 4 + 1] = R_INT ? c.green() : c.greenF();
959 buffer[i * 4 + 2] = R_INT ? c.blue() : c.blueF();
960 buffer[i * 4 + 3] = R_INT ? c.alpha() : c.alphaF();
961 }
962 else {
963 buffer[0 * ELEM_NUM + i] = R_INT ? c.red() : c.redF();
964 buffer[1 * ELEM_NUM + i] = R_INT ? c.green() : c.greenF();
965 buffer[2 * ELEM_NUM + i] = R_INT ? c.blue() : c.blueF();
966 buffer[3 * ELEM_NUM + i] = R_INT ? c.alpha() : c.alphaF();
967 }
968 ++i;
969 }
970}
971
993template<uint ELEM_ID, MeshConcept MeshType>
994void elementColorsToBuffer(
995 const MeshType& mesh,
996 auto* buffer,
997 Color::Format colorFormat)
998{
999 requirePerElementComponent<ELEM_ID, CompId::COLOR>(mesh);
1000
1001 for (uint i = 0;
1002 const auto& c : mesh.template elements<ELEM_ID>() | views::colors) {
1003 switch (colorFormat) {
1004 using enum Color::Format;
1005 case ABGR: buffer[i] = c.abgr(); break;
1006 case ARGB: buffer[i] = c.argb(); break;
1007 case RGBA: buffer[i] = c.rgba(); break;
1008 case BGRA: buffer[i] = c.bgra(); break;
1009 }
1010 ++i;
1011 }
1012}
1013
1038template<MeshConcept MeshType>
1039void vertexColorsToBuffer(
1040 const MeshType& mesh,
1041 auto* buffer,
1042 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
1043 Color::Representation representation = Color::Representation::INT_0_255,
1044 uint rowNumber = UINT_NULL)
1045{
1046 elementColorsToBuffer<ElemId::VERTEX>(
1047 mesh, buffer, storage, representation, rowNumber);
1048}
1049
1070template<MeshConcept MeshType>
1071void vertexColorsToBuffer(
1072 const MeshType& mesh,
1073 auto* buffer,
1074 Color::Format colorFormat)
1075{
1076 elementColorsToBuffer<ElemId::VERTEX>(mesh, buffer, colorFormat);
1077}
1078
1102template<FaceMeshConcept MeshType>
1103void faceColorsToBuffer(
1104 const MeshType& mesh,
1105 auto* buffer,
1106 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
1107 Color::Representation representation = Color::Representation::INT_0_255,
1108 uint rowNumber = UINT_NULL)
1109{
1110 elementColorsToBuffer<ElemId::FACE>(
1111 mesh, buffer, storage, representation, rowNumber);
1112}
1113
1140template<FaceMeshConcept MeshType>
1141void triangulatedFaceColorsToBuffer(
1142 const MeshType& mesh,
1143 auto* buffer,
1144 const TriPolyIndexBiMap& indexMap,
1145 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
1146 Color::Representation representation = Color::Representation::INT_0_255,
1147 uint rowNumber = UINT_NULL)
1148{
1149 requirePerFaceColor(mesh);
1150
1151 const bool R_INT = representation == Color::Representation::INT_0_255;
1152
1153 const uint FACE_NUM =
1154 rowNumber == UINT_NULL ? indexMap.triangleNumber() : rowNumber;
1155
1156 for (const auto& f : mesh.faces()) {
1157 const auto& c = f.color();
1158 uint first = indexMap.triangleBegin(f.index());
1159 uint last = first + indexMap.triangleNumber(f.index());
1160 for (uint t = first; t < last; ++t) {
1161 if (storage == MatrixStorageType::ROW_MAJOR) {
1162 buffer[t * 4 + 0] = R_INT ? c.red() : c.redF();
1163 buffer[t * 4 + 1] = R_INT ? c.green() : c.greenF();
1164 buffer[t * 4 + 2] = R_INT ? c.blue() : c.blueF();
1165 buffer[t * 4 + 3] = R_INT ? c.alpha() : c.alphaF();
1166 }
1167 else {
1168 buffer[0 * FACE_NUM + t] = R_INT ? c.red() : c.redF();
1169 buffer[1 * FACE_NUM + t] = R_INT ? c.green() : c.greenF();
1170 buffer[2 * FACE_NUM + t] = R_INT ? c.blue() : c.blueF();
1171 buffer[3 * FACE_NUM + t] = R_INT ? c.alpha() : c.alphaF();
1172 }
1173 }
1174 }
1175}
1176
1197template<FaceMeshConcept MeshType>
1198void faceColorsToBuffer(
1199 const MeshType& mesh,
1200 auto* buffer,
1201 Color::Format colorFormat)
1202{
1203 elementColorsToBuffer<ElemId::FACE>(mesh, buffer, colorFormat);
1204}
1205
1229template<FaceMeshConcept MeshType>
1230void triangulatedFaceColorsToBuffer(
1231 const MeshType& mesh,
1232 auto* buffer,
1233 const TriPolyIndexBiMap& indexMap,
1234 Color::Format colorFormat)
1235{
1236 requirePerElementComponent<ElemId::FACE, CompId::COLOR>(mesh);
1237
1238 for (const auto& f : mesh.faces()) {
1239 const auto& c = f.color();
1240 uint first = indexMap.triangleBegin(f.index());
1241 uint last = first + indexMap.triangleNumber(f.index());
1242 for (uint t = first; t < last; ++t) {
1243 switch (colorFormat) {
1244 using enum Color::Format;
1245 case ABGR: buffer[t] = c.abgr(); break;
1246 case ARGB: buffer[t] = c.argb(); break;
1247 case RGBA: buffer[t] = c.rgba(); break;
1248 case BGRA: buffer[t] = c.bgra(); break;
1249 }
1250 }
1251 }
1252}
1253
1277template<EdgeMeshConcept MeshType>
1278void edgeColorsToBuffer(
1279 const MeshType& mesh,
1280 auto* buffer,
1281 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
1282 Color::Representation representation = Color::Representation::INT_0_255,
1283 uint rowNumber = UINT_NULL)
1284{
1285 elementColorsToBuffer<ElemId::EDGE>(
1286 mesh, buffer, storage, representation, rowNumber);
1287}
1288
1309template<EdgeMeshConcept MeshType>
1310void edgeColorsToBuffer(
1311 const MeshType& mesh,
1312 auto* buffer,
1313 Color::Format colorFormat)
1314{
1315 elementColorsToBuffer<ElemId::EDGE>(mesh, buffer, colorFormat);
1316}
1317
1337template<uint ELEM_ID, MeshConcept MeshType>
1338void elementQualityToBuffer(const MeshType& mesh, auto* buffer)
1339{
1340 requirePerElementComponent<ELEM_ID, CompId::QUALITY>(mesh);
1341
1342 for (uint i = 0;
1343 const auto& q : mesh.template elements<ELEM_ID>() | views::quality) {
1344 buffer[i] = q;
1345 ++i;
1346 }
1347}
1348
1367template<MeshConcept MeshType>
1368void vertexQualityToBuffer(const MeshType& mesh, auto* buffer)
1369{
1370 elementQualityToBuffer<ElemId::VERTEX>(mesh, buffer);
1371}
1372
1390template<MeshConcept MeshType>
1391void faceQualityToBuffer(const MeshType& mesh, auto* buffer)
1392{
1393 elementQualityToBuffer<ElemId::FACE>(mesh, buffer);
1394}
1395
1413template<MeshConcept MeshType>
1414void edgeQualityToBuffer(const MeshType& mesh, auto* buffer)
1415{
1416 elementQualityToBuffer<ElemId::FACE>(mesh, buffer);
1417}
1418
1440template<MeshConcept MeshType>
1441void vertexTexCoordsToBuffer(
1442 const MeshType& mesh,
1443 auto* buffer,
1444 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
1445 uint rowNumber = UINT_NULL)
1446{
1447 requirePerVertexTexCoord(mesh);
1448
1449 const uint VERT_NUM =
1450 rowNumber == UINT_NULL ? mesh.vertexNumber() : rowNumber;
1451
1452 for (uint i = 0; const auto& t : mesh.vertices() | views::texCoords) {
1453 if (storage == MatrixStorageType::ROW_MAJOR) {
1454 buffer[i * 2 + 0] = t.u();
1455 buffer[i * 2 + 1] = t.v();
1456 }
1457 else {
1458 buffer[0 * VERT_NUM + i] = t.u();
1459 buffer[1 * VERT_NUM + i] = t.v();
1460 }
1461 ++i;
1462 }
1463}
1464
1483template<MeshConcept MeshType>
1484void vertexTexCoordIndicesToBuffer(const MeshType& mesh, auto* buffer)
1485{
1486 requirePerVertexTexCoord(mesh);
1487
1488 for (uint i = 0; const auto& t : mesh.vertices() | views::texCoords) {
1489 buffer[i] = t.index();
1490 ++i;
1491 }
1492}
1493
1517template<FaceMeshConcept MeshType>
1518void vertexTexCoordIndicesAsFaceTexCoordIndicesToBuffer(
1519 const MeshType& mesh,
1520 auto* buffer)
1521{
1522 requirePerVertexTexCoord(mesh);
1523
1524 for (uint i = 0; const auto& f : mesh.faces()) {
1525 ushort ti = f.vertex(0)->texCoord()->index();
1526 buffer[i] = ti;
1527 ++i;
1528 }
1529}
1530
1555template<FaceMeshConcept MeshType>
1556void vertexTexCoordIndicesAsTriangulatedFaceTexCoordIndicesToBuffer(
1557 const MeshType& mesh,
1558 auto* buffer,
1559 const TriPolyIndexBiMap& indexMap)
1560{
1561 requirePerVertexTexCoord(mesh);
1562
1563 for (const auto& f : mesh.faces()) {
1564 ushort ti = f.vertex(0)->texCoord().index();
1565 uint first = indexMap.triangleBegin(f.index());
1566 uint last = first + indexMap.triangleNumber(f.index());
1567 for (uint t = first; t < last; ++t) {
1568 buffer[t] = ti;
1569 }
1570 }
1571}
1572
1610template<FaceMeshConcept MeshType>
1612 const MeshType& mesh,
1613 auto* buffer,
1614 uint largestFaceSize = 3,
1615 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR,
1616 uint rowNumber = UINT_NULL)
1617{
1619
1620 const uint FACE_NUM =
1621 rowNumber == UINT_NULL ? mesh.faceNumber() : rowNumber;
1622
1623 for (uint i = 0; const auto& f : mesh.faces()) {
1624 for (uint j = 0; j < largestFaceSize * 2; ++j) {
1625 uint fi = j / 2;
1626 uint index = i * largestFaceSize * 2 + j;
1627 if (storage == MatrixStorageType::COLUMN_MAJOR)
1628 index = j * FACE_NUM + i;
1629 if (fi < f.wedgeTexCoordsNumber()) {
1630 const auto& w = f.wedgeTexCoord(fi);
1631 if (j % 2 == 0)
1632 buffer[index] = w.u();
1633 else
1634 buffer[index] = w.v();
1635 }
1636 else {
1637 buffer[index] = 0;
1638 }
1639 }
1640 ++i;
1641 }
1642}
1643
1662template<FaceMeshConcept MeshType>
1663void faceWedgeTexCoordIndicesToBuffer(const MeshType& mesh, auto* buffer)
1664{
1666
1667 for (uint i = 0; const auto& f : mesh.faces()) {
1668 buffer[i] = f.textureIndex();
1669 ++i;
1670 }
1671}
1672
1694template<FaceMeshConcept MeshType>
1696 const MeshType& mesh,
1697 auto* buffer,
1698 const TriPolyIndexBiMap& indexMap)
1699{
1701
1702 for (const auto& f : mesh.faces()) {
1703 uint first = indexMap.triangleBegin(f.index());
1704 uint last = first + indexMap.triangleNumber(f.index());
1705 for (uint t = first; t < last; ++t) {
1706 buffer[t] = f.textureIndex();
1707 }
1708 }
1709}
1710
1755template<FaceMeshConcept MeshType>
1757 const MeshType& mesh,
1758 const std::vector<std::pair<vcl::uint, vcl::uint>>& vertWedgeMap,
1759 const std::list<std::list<std::pair<vcl::uint, vcl::uint>>>&
1761 auto* buffer,
1762 MatrixStorageType storage = MatrixStorageType::ROW_MAJOR)
1763{
1764 using TexCoordType = typename MeshType::FaceType::WedgeTexCoordType;
1765
1767
1768 const uint VERT_NUM = mesh.vertexNumber() + facesToReassign.size();
1769
1770 // first export the texcoords of the non-duplicated vertices, using the
1771 // vertWedgeMap to get the texcoord index in the face
1772 uint vi = 0; // current vertex (or current row in the matrix)
1773 for (const auto& v : mesh.vertices()) {
1774 TexCoordType w;
1775 uint fInd = vertWedgeMap[vi].first;
1776 uint wInd = vertWedgeMap[vi].second;
1777
1778 // check if the vi is referenced
1779 if (fInd != UINT_NULL && wInd != UINT_NULL) {
1780 w = mesh.face(fInd).wedgeTexCoord(wInd);
1781 }
1782 if (storage == MatrixStorageType::ROW_MAJOR) {
1783 buffer[vi * 2 + 0] = w.u();
1784 buffer[vi * 2 + 1] = w.v();
1785 }
1786 else {
1787 buffer[0 * VERT_NUM + vi] = w.u();
1788 buffer[1 * VERT_NUM + vi] = w.v();
1789 }
1790 ++vi;
1791 }
1792
1793 // then append the texcoords of the duplicated vertices, that can be found
1794 // by looking into the any of the facesToReassign element lists
1795 for (const auto& list : facesToReassign) {
1796 assert(list.begin() != list.end());
1797 const auto& p = list.front();
1798 uint fInd = p.first;
1799 uint wInd = p.second;
1800
1801 const auto& w = mesh.face(fInd).wedgeTexCoord(wInd);
1802 if (storage == MatrixStorageType::ROW_MAJOR) {
1803 buffer[vi * 2 + 0] = w.u();
1804 buffer[vi * 2 + 1] = w.v();
1805 }
1806 else {
1807 buffer[0 * VERT_NUM + vi] = w.u();
1808 buffer[1 * VERT_NUM + vi] = w.v();
1809 }
1810 ++vi;
1811 }
1812}
1813
1858template<FaceMeshConcept MeshType>
1860 const MeshType& mesh,
1861 const std::vector<std::pair<vcl::uint, vcl::uint>>& vertWedgeMap,
1862 const std::list<std::list<std::pair<vcl::uint, vcl::uint>>>&
1864 auto* buffer)
1865{
1867
1868 const uint VERT_NUM = mesh.vertexNumber() + facesToReassign.size();
1869
1870 // first export the tex indices of the non-duplicated vertices, using the
1871 // vertWedgeMap to get the texcoord index in the face
1872 uint vi = 0; // current vertex (or current row in the matrix)
1873 for (const auto& v : mesh.vertices()) {
1874 uint fInd = vertWedgeMap[vi].first;
1875 ushort ti = mesh.face(fInd).textureIndex();
1876 buffer[vi] = ti;
1877 ++vi;
1878 }
1879
1880 // then append the tex indices of the duplicated vertices, that can be found
1881 // by looking into the any of the facesToReassign element lists
1882 for (const auto& list : facesToReassign) {
1883 assert(list.begin() != list.end());
1884 const auto& p = list.front();
1885 uint fInd = p.first;
1886
1887 ushort ti = mesh.face(fInd).textureIndex();
1888 buffer[vi] = ti;
1889 ++vi;
1890 }
1891}
1892
1893} // namespace vcl
1894
1895#endif // VCL_ALGORITHMS_MESH_IMPORT_EXPORT_EXPORT_BUFFER_H
A class representing a box in N-dimensional space.
Definition box.h:46
PointT size() const
Computes the size of the box.
Definition box.h:267
Format
Color format enumeration.
Definition color.h:77
Representation
Color representation enumeration.
Definition color.h:64
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 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:1756
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:1859
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
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 vertexPositionsToBuffer(const MeshType &mesh, auto *buffer, MatrixStorageType storage=MatrixStorageType::ROW_MAJOR, uint rowNumber=UINT_NULL)
Export the vertex positions of a mesh to a buffer.
Definition export_buffer.h:100
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:403
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:1695
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:497
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:257
void faceWedgeTexCoordIndicesToBuffer(const MeshType &mesh, auto *buffer)
Export into a buffer the per face wedge texture indices of a mesh.
Definition export_buffer.h:1663
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:1611
void vertexQuadIndicesToBuffer(const MeshType &mesh, auto *buffer)
Export the indices of a quad per vertex to a buffer.
Definition export_buffer.h:142
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:195
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:556
void requirePerFaceWedgeTexCoords(const MeshType &m)
This function asserts that a Mesh has a FaceContainer, the Face has a WedgeTexCoords Component,...
Definition face_requirements.h:1209
void requirePerFaceNormal(const MeshType &m)
This function asserts that a Mesh has a FaceContainer, the Face has a Normal Component,...
Definition face_requirements.h:1066
void requirePerFaceColor(const MeshType &m)
This function asserts that a Mesh has a FaceContainer, the Face has a Color Component,...
Definition face_requirements.h:996
bool isCompact(const MeshType &m)
Checks if a Mesh is compact, that is if it does not contains deleted elements.
Definition mesh_requirements.h:204
uint countPerFaceVertexReferences(const FaceMeshConcept auto &mesh)
Count the number of references to vertices in the mesh faces.
Definition topology.h:182
uint largestFaceSize(const FaceMeshConcept auto &mesh)
Returns the largest face size in the mesh.
Definition topology.h:211
uint countTriangulatedTriangles(const FaceMeshConcept auto &mesh)
Counts the number of resulting triangles if the input mesh would be triangulated by splitting each fa...
Definition topology.h:239
constexpr detail::FacesView faces
A view that allows to iterate overt the Face elements of an object.
Definition face.h:84