Visual Computing Library  devel
Loading...
Searching...
No Matches
mesh.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_MESH_MESH_H
24#define VCL_MESH_MESH_H
25
26#include "mesh_components.h"
27#include "mesh_containers.h"
28
29#include <vclib/algorithms/core.h>
30
31namespace vcl {
32
66template<typename... Args>
67class Mesh : public Args...
68{
69 static_assert(HasVertices<Args...>, "A Mesh must have a VertexContainer.");
70
71 template<typename El, bool b>
72 friend struct comp::detail::CustomComponentsData;
73
74 template<typename El, bool b>
75 friend struct comp::detail::ComponentData;
76
77 template<ElementConcept T>
78 friend class mesh::ElementContainer;
79
80 template<uint ELEM_ID, typename MeshType, comp::ComponentConcept... Comps>
81 friend class Element;
82
83 // Predicate structures
84
85 template<uint ELEM_ID>
87 public mesh::ContainerOfElement<ELEM_ID, Mesh<Args...>>
88 {
89 };
90
101 template<ElementConcept El>
102 struct ContainerOf : public ContainerOfElement<El::ELEMENT_ID>
103 {
104 };
105
106public:
114 TypeWrapper<Args...>>::type;
115
122 FilterTypesByCondition<comp::IsComponentPred, TypeWrapper<Args...>>::
123 type;
124
136 template<uint ELEM_ID>
138
150 template<uint ELEM_ID>
152
153 /* Constexpr static member functions */
154
179 template<ElementConcept El>
180 static constexpr bool hasContainerOf()
181 {
182 return mesh::HasContainerOfPred<El, Mesh<Args...>>::value;
183 }
184
202 template<uint ELEM_ID>
203 static constexpr bool hasContainerOf()
204 {
205 return mesh::HasContainerOfElementPred<ELEM_ID, Mesh<Args...>>::value;
206 }
207
226 template<uint ELEM_ID, uint COMP_ID>
227 static constexpr bool hasPerElementComponent()
228 {
229 return mesh::HasPerElementComponent<Mesh<Args...>, ELEM_ID, COMP_ID>;
230 }
231
251 template<uint ELEM_ID, uint COMP_ID>
252 static constexpr bool hasPerElementOptionalComponent()
253 {
254 return mesh::
255 HasPerElementOptionalComponent<Mesh<Args...>, ELEM_ID, COMP_ID>;
256 }
257
258 /* Constructors */
259
264 {
265 // Set to all element containers their parent mesh (this)
266 updateAllParentMeshPointers();
267 }
268
276 Mesh(const Mesh& oth) :
277 Args(oth)... // call auto copy constructors for all the container
278 // elements and components
279 {
280 // Set to all element containers their parent mesh (this)
281 updateAllParentMeshPointers();
282
283 // for each container of oth, save its base pointer
284 // will need it to update all the pointers of this mesh
285 constexpr uint N_CONTAINERS =
286 NumberOfTypes<typename Mesh<Args...>::Containers>::value;
287 std::array<const void*, N_CONTAINERS> othBases =
289
290 // update all the pointers contained on each container
291 // use the base pointer of each container of oth to update all the
292 // pointers in this mesh. Each pointer of oth that was copied in this
293 // mesh, will be updated computing its offset wrt the base of oth, and
294 // then adding that offset to the new base pointer of this mesh
296 }
297
305 {
306 swap(oth); // use copy and swap idiom: this (empty) mesh is swapped with
307 // the input one
308 }
309
310 /* Member functions */
311
318 bool isCompact() const
319 {
320 bool isCompact = true;
322 return isCompact;
323 }
324
329 void clear() { (clearContainer<Args>(), ...); }
330
337 void compact() { (compactContainer<Args>(), ...); }
338
347
356
386 template<typename OtherMeshType>
388 {
389 // enable all optional components of this Mesh depending on what's
390 // available in the OtherMeshType
391
393 }
394
408 void append(const Mesh& m)
409 {
410 // for each container of this mesh, save its size
411 // will need it to update all the pointers/indices of this mesh
412 constexpr uint N_CONTAINERS =
413 NumberOfTypes<typename Mesh<Args...>::Containers>::value;
414 std::array<std::size_t, N_CONTAINERS> sizes =
416
417 // for each container of the other mesh m, save its bases
418 // will need it to update all the pointers of this mesh
419 std::array<const void*, N_CONTAINERS> bases =
421
422 // call the append function for each container
423 (appendContainer<Args>(m), ...);
424
425 // update all the pointers/indices contained on each container
427 ...);
428
429 // manage transform matrix
430 if constexpr (mesh::HasTransformMatrix<Mesh<Args...>>) {
431 using Matrixtype = typename Mesh<Args...>::TransformMatrixType;
432
433 Matrixtype matrix = this->transformMatrix();
434 matrix = matrix.inverse().eval();
435 matrix *= m.transformMatrix();
436
437 if (matrix != Matrixtype::Identity()) {
439 *this, sizes, matrix),
440 ...);
441 }
442 }
443
444 if constexpr (mesh::HasTexturePaths<Mesh<Args...>>) {
445 uint nTextures = this->textureNumber();
446
447 std::vector<uint> mapping(m.textureNumber());
448
449 for (uint i = 0; i < m.textureNumber(); ++i) {
450 uint tpi = this->indexOfTexturePath(m.texturePath(i));
451
452 if (tpi == UINT_NULL) {
453 if constexpr (mesh::HasTextureImages<Mesh<Args...>>) {
454 this->pushTexture(m.texture(i));
455 }
456 else {
457 this->pushTexturePath(m.texturePath(i));
458 }
459 mapping[i] = nTextures++;
460 }
461 else {
462 mapping[i] = tpi;
463 }
464 }
465
466 if (nTextures > 0 || mapping.size() > 0) {
468 *this, sizes, mapping),
469 ...);
470 }
471 }
472 }
473
488 template<typename OtherMeshType>
490 {
491 // This function will first:
492 // Call, for each Container and Component of the mesh, its importFrom
493 // function. In case of containers, it first creates the same number of
494 // elements in the container, and then calls the importFrom function for
495 // each new element.
496
497 (Args::importFrom(m), ...);
498
499 // Set to all element containers their parent mesh (this)
500 updateAllParentMeshPointers();
501
502 if constexpr (mesh::HasFaceContainer<Mesh<Args...>>) {
503 // Now I need to manage imports between different types of meshes
504 // (same type of meshes are already managed from importFrom member
505 // function).
506 //
507 // Generally speaking, Polygon meshes can import from any other type
508 // of mesh. We need to take care when this mesh has static vertex
509 // references number in the face container (VERTEX_NUMBER >= 3).
510 //
511 // The follwing case don't need to be managed:
512 // - import polygon mesh from triangle mesh
513 //
514 // I can manage the following cases:
515 // - import triangle mesh from polygon mesh: need triangulation
516 //
517 // I cannot manage the follwing cases:
518 // - import static non-triangle mesh from polygon mesh or from a
519 // mesh with different VERTEX_NUMBER
520
521 // in case of import from poly to triangle mesh, I need to manage
522 // triangulation of polygons and create additional triangle faces
523 // for each of the imported polygons. This function statically
524 // asserts that the import can be done.
526 using FaceContainer = typename Mesh<Args...>::FaceContainer;
527 FaceContainer::manageImportTriFromPoly(m);
528 }
529 }
530 }
531
536 void swap(Mesh& m2)
537 {
538 Mesh<Args...>& m1 = *this;
539
540 constexpr uint N_CONTAINERS =
541 NumberOfTypes<typename Mesh<Args...>::Containers>::value;
542 static_assert(N_CONTAINERS != 0);
543
544 // container bases of each container for m1 and m2
545 // we save the bases of the containers before swap
546 std::array<const void*, N_CONTAINERS> m1Bases =
548 std::array<const void*, N_CONTAINERS> m2Bases =
550
551 // actual swap of all the containers and the components of the mesh
552 // using pack expansion: swap will be called for each of the containers
553 // (or components!) that compose the Mesh
554 using std::swap;
555 (swap((Args&) m1, (Args&) m2), ...);
556
557 // Set to all elements their parent mesh
558 m1.updateAllParentMeshPointers();
559 m2.updateAllParentMeshPointers();
560
561 // update all the refs to m1 and m2: old base of m1 is now "old
562 // base" of m2, and viceversa
565 }
566
575 friend void swap(Mesh& a, Mesh& b) { a.swap(b); }
576
584 {
585 swap(oth);
586 return *this;
587 }
588
589 /*** Generic Element functions ***/
590
602 template<ElementConcept El>
603 uint index(const El& e) const requires (hasContainerOf<El>())
604 {
605 using Container = ContainerOf<El>::type;
606 return Container::index(&e);
607 }
608
620 template<ElementConcept El>
621 uint index(const El* e) const requires (hasContainerOf<El>())
622 {
623 using Container = ContainerOf<El>::type;
624 return Container::index(e);
625 }
626
641 template<uint ELEM_ID>
642 const auto& element(uint i) const requires (hasContainerOf<ELEM_ID>())
643 {
645
646 return Cont::element(i);
647 }
648
663 template<uint ELEM_ID>
665 {
667
668 return Cont::element(i);
669 }
670
680 template<uint ELEM_ID>
682 {
684
685 return Cont::elementNumber();
686 }
687
702 template<uint ELEM_ID>
704 {
706
707 return Cont::elementContainerSize();
708 }
709
720 template<uint ELEM_ID>
722 {
724
725 return Cont::deletedElementNumber();
726 }
727
742 template<uint ELEM_ID>
744 {
746
747 return Cont::addElement();
748 }
749
765 template<uint ELEM_ID>
767 {
769
770 return Cont::addElements(n); // add the number elements
771 }
772
793 template<uint ELEM_ID>
795 {
797
798 Cont::clearElements();
799 }
800
834 template<uint ELEM_ID>
836 {
838
839 Cont::resizeElements(n);
840 }
841
862 template<uint ELEM_ID>
864 {
866
867 Cont::reserveElements(n);
868 }
869
876 template<uint ELEM_ID>
878 {
880
881 Cont::compactElements();
882 }
883
901 template<uint ELEM_ID>
903 {
905
906 Cont::deleteElement(i);
907 }
908
926 template<ElementConcept El>
927 void deleteElement(const El* e) const requires (hasContainerOf<El>())
928 {
930 return Cont::deleteElement(e);
931 }
932
950 template<ElementConcept El>
951 void deleteElement(const El& e) const requires (hasContainerOf<El>())
952 {
954 return Cont::deleteElement(&e);
955 }
956
974 template<uint ELEM_ID>
975 std::vector<uint> compactIndices() const
976 requires (hasContainerOf<ELEM_ID>())
977 {
979
980 return Cont::elementConpactIndices();
981 }
982
1009 template<uint ELEM_ID>
1010 void updateIndices(const std::vector<uint>& newIndices)
1011 requires (hasContainerOf<ELEM_ID>())
1012 {
1014
1015 return Cont::updateElementIndices(newIndices);
1016 }
1017
1018 void serialize(std::ostream& os) const
1019 {
1020 (preSerialization<Args>(os), ...);
1021
1023 }
1024
1025 void deserialize(std::istream& is)
1026 {
1027 (preDeserialization<Args>(is), ...);
1028
1029 (postDeserialization<Args>(is), ...);
1030 }
1031
1049 template<uint ELEM_ID>
1050 auto begin(bool jumpDeleted = true) requires (hasContainerOf<ELEM_ID>())
1051 {
1053
1054 return Cont::elementBegin(jumpDeleted);
1055 }
1056
1068 template<uint ELEM_ID>
1069 auto end() requires (hasContainerOf<ELEM_ID>())
1070 {
1072
1073 return Cont::elementEnd();
1074 }
1075
1093 template<uint ELEM_ID>
1094 auto begin(bool jumpDeleted = true) const
1095 requires (hasContainerOf<ELEM_ID>())
1096 {
1098
1099 return Cont::elementBegin(jumpDeleted);
1100 }
1101
1113 template<uint ELEM_ID>
1114 auto end() const requires (hasContainerOf<ELEM_ID>())
1115 {
1117
1118 return Cont::elementEnd();
1119 }
1120
1143 template<uint ELEM_ID>
1144 auto elements(bool jumpDeleted = true) requires (hasContainerOf<ELEM_ID>())
1145 {
1147
1148 return Cont::elements(jumpDeleted);
1149 }
1150
1180 template<uint ELEM_ID>
1182 requires (hasContainerOf<ELEM_ID>())
1183 {
1185
1186 return Cont::elements(begin, end);
1187 }
1188
1211 template<uint ELEM_ID>
1212 auto elements(bool jumpDeleted = true) const
1213 requires (hasContainerOf<ELEM_ID>())
1214 {
1216
1217 return Cont::elements(jumpDeleted);
1218 }
1219
1249 template<uint ELEM_ID>
1251 requires (hasContainerOf<ELEM_ID>())
1252 {
1254
1255 return Cont::elements(begin, end);
1256 }
1257
1271 template<uint ELEM_ID, uint COMP_ID>
1279
1291 template<uint ELEM_ID, uint COMP_ID>
1299
1311 template<uint ELEM_ID, uint COMP_ID>
1319
1336 template<uint ELEM_ID>
1337 bool hasPerElementCustomComponent(const std::string& name) const
1339 {
1341
1342 return Cont::hasElemCustomComponent(name);
1343 }
1344
1357 template<uint ELEM_ID>
1358 std::vector<std::string> perElementCustomComponentNames() const
1359 requires (hasPerElementComponent<ELEM_ID, CompId::CUSTOM_COMPONENTS>())
1360 {
1362
1363 return Cont::elemCustomComponentNames();
1364 }
1365
1380 template<uint ELEM_ID, typename K>
1381 bool isPerElementCustomComponentOfType(const std::string& name) const
1383 {
1385
1386 return Cont::template isElemCustomComponentOfType<K>(name);
1387 }
1388
1402 template<uint ELEM_ID>
1403 std::type_index perElementCustomComponentType(const std::string& name) const
1405 {
1407
1408 return Cont::elemCustomComponentType(name);
1409 }
1410
1424 template<uint ELEM_ID, typename K>
1426 requires (hasPerElementComponent<ELEM_ID, CompId::CUSTOM_COMPONENTS>())
1427 {
1429
1430 return Cont::template elemCustomComponentNamesOfType<K>();
1431 }
1432
1445 template<uint ELEM_ID, typename K>
1446 void addPerElementCustomComponent(const std::string& name)
1448 {
1450
1451 Cont::template addElemCustomComponent<K>(name);
1452 }
1453
1465 template<uint ELEM_ID>
1466 void deletePerElementCustomComponent(const std::string& name)
1468 {
1470
1471 Cont::deleteElemCustomComponent(name);
1472 }
1473
1515 template<uint ELEM_ID, typename K>
1524
1566 template<uint ELEM_ID, typename K>
1575
1601 template<uint ELEM_ID, typename K>
1603 {
1605
1607 }
1608
1621 template<uint ELEM_ID, typename K>
1628
1629protected:
1630 template<typename Cont>
1631 bool isContainerCompact() const
1632 {
1633 if constexpr (mesh::ElementContainerConcept<Cont>) {
1634 return Cont::elementNumber() == Cont::elementContainerSize();
1635 }
1636 else {
1637 return true; // does not count as a container
1638 }
1639 }
1640
1650 template<typename Cont>
1652 {
1653 if constexpr (mesh::ElementContainerConcept<Cont>) {
1654 if (Cont::elementNumber() != Cont::elementContainerSize()) {
1655 Cont::compactElements();
1656 }
1657 }
1658 }
1659
1669 template<typename Cont>
1671 {
1672 if constexpr (mesh::ElementContainerConcept<Cont>) {
1673 Cont::enableAllOptionalComponents();
1674 }
1675 }
1676
1686 template<typename Cont>
1688 {
1689 if constexpr (mesh::ElementContainerConcept<Cont>) {
1690 Cont::disableAllOptionalComponents();
1691 }
1692 }
1693
1703 template<typename Cont>
1705 {
1706 if constexpr (mesh::ElementContainerConcept<Cont>) {
1707 Cont::clearElements();
1708 }
1709 }
1710
1711 template<ElementConcept Element>
1712 void updateAllReferences(const Element* oldBase)
1713 {
1714 if (oldBase != nullptr)
1716 }
1717
1718 // this function is required in order to get msvc compile
1719 template<typename Element, typename... A>
1720 void updateReferences(const Element* oldBase, TypeWrapper<A...>)
1721 {
1722 updateReferences(
1723 oldBase, TypeWrapper<A...>(), std::array<std::size_t, 0>(), 0);
1724 }
1725
1726 // this function is required in order to get msvc compile
1727 template<typename Cont, typename Element>
1728 void updateReferences(const Element* oldBase)
1729 {
1730 updateReferences<Cont>(oldBase, std::array<std::size_t, 0>(), 0);
1731 }
1732
1733 // this additional function is necessary because otherwise msvc jumps
1734 // totally the pack expansion if called directly in the function
1735 // updateReferencesOfContainerTypeAfterAppend
1736 template<typename Element, std::size_t N, typename... A>
1737 void updateReferences(
1738 const Element* oldBase,
1739 TypeWrapper<A...>,
1740 const std::array<std::size_t, N>& sizes = std::array<std::size_t, 0>(),
1741 uint offset = 0)
1742 {
1743 (updateReferences<A>(oldBase, sizes, offset), ...);
1744 }
1745
1746 template<typename Cont, typename Element, std::size_t N>
1747 void updateReferences(
1748 const Element* oldBase,
1749 const std::array<std::size_t, N>& sizes = std::array<std::size_t, 0>(),
1750 uint offset = 0)
1751 {
1752 if constexpr (mesh::ElementContainerConcept<Cont>) {
1753 if constexpr (N > 0) {
1754 using Containers = Mesh<Args...>::Containers;
1755 constexpr uint I = IndexInTypes<Cont, Containers>::value;
1756 static_assert(I >= 0 && I != UINT_NULL);
1757 Cont::updateReferences(oldBase, sizes[I], offset);
1758 }
1759 else {
1760 Cont::updateReferences(oldBase);
1761 }
1762 }
1763 }
1764
1765 template<ElementConcept Element>
1766 void updateAllReferences(const std::vector<uint>& newIndices)
1767 {
1768 (updateReferences<Args, Element>(newIndices), ...);
1769 }
1770
1771 template<typename Cont, typename Element>
1772 void updateReferences(const std::vector<uint>& newIndices)
1773 {
1774 if constexpr (mesh::ElementContainerConcept<Cont>) {
1775 Cont::template updateReferences<Element>(newIndices);
1776 }
1777 }
1778
1779private:
1780 // hide init and isAvailable members
1781 void init() {};
1782
1783 bool isAvailable() const { return true; }
1784
1785 // enable optional components
1786
1787 template<typename Cont, typename OtherMeshType>
1788 void enableSameOptionalComponentsOf(const OtherMeshType& m)
1789 {
1790 if constexpr (mesh::ElementContainerConcept<Cont>) {
1791 Cont::enableOptionalComponentsOf(m);
1792 }
1793 }
1794
1795 // private parent mesh pointers functions
1796
1797 void updateAllParentMeshPointers() { (setParentMeshPointers<Args>(), ...); }
1798
1799 template<typename Cont>
1800 void setParentMeshPointers()
1801 {
1802 if constexpr (mesh::ElementContainerConcept<Cont>) {
1803 Cont::setParentMeshPointers(this);
1804 }
1805 }
1806
1807 template<typename Cont>
1808 void appendContainer(const Mesh& m)
1809 {
1810 if constexpr (mesh::ElementContainerConcept<Cont>) {
1811 Cont::append((const Cont&) m);
1812 }
1813 }
1814
1815 // private copy and swap member functions
1816
1824 template<uint I, typename Cont, typename Array, typename... A>
1826 {
1827 // since this function is called using pack expansion, it means that
1828 // Cont could be a mesh component and not a cointainer. We check if Cont
1829 // is a container
1830 if constexpr (mesh::ElementContainerConcept<Cont>) {
1831 static_assert(I >= 0 && I != UINT_NULL);
1832 bases[I] = m.Cont::mElemVec.data();
1833 }
1834 }
1835
1836 template<typename... A>
1837 static auto getContainerBases(const Mesh<A...>& m)
1838 {
1839 using Containers = Mesh<A...>::Containers;
1840
1841 // the number of containers in Mesh<A...>
1843 // each element of this array will contain the base pointer of the
1844 // vector of elements contained in each container of Mesh<A...>
1845 std::array<const void*, N_CONTAINERS> bases;
1846
1847 // for each container/component of Mesh<A...>, we call the function
1848 // that sets the base of the container in its index
1850 ...);
1851
1852 return bases;
1853 }
1854
1862 template<uint I, typename Cont, typename Array, typename... A>
1864 {
1865 // since this function is called using pack expansion, it means that
1866 // Cont could be a mesh component and not a cointainer. We check if Cont
1867 // is a container
1868 if constexpr (mesh::ElementContainerConcept<Cont>) {
1869 static_assert(I >= 0 && I != UINT_NULL);
1870 sizes[I] = m.Cont::mElemVec.size();
1871 }
1872 }
1873
1874 template<typename... A>
1875 static auto getContainerSizes(const Mesh<A...>& m)
1876 {
1877 using Containers = Mesh<A...>::Containers;
1878
1879 // the number of containers in Mesh<A...>
1881 // each element of this array will contain the size of the
1882 // vector of elements contained in each container of Mesh<A...>
1883 std::array<std::size_t, N_CONTAINERS> sizes;
1884
1885 // for each container/component of Mesh<A...>, we set call the function
1886 // that sets the size of the container in its index
1888 ...);
1889
1890 return sizes;
1891 }
1892
1917 template<typename Cont, typename Array, typename... A>
1919 Mesh<A...>& m,
1920 const Array& bases)
1921 {
1922 // since this function is called using pack expansion, it means that
1923 // Cont could be a mesh component and not a cointainer. We check if Cont
1924 // is a container
1925 if constexpr (mesh::ElementContainerConcept<Cont>) {
1926 // The element type contained in the container
1927 // We need it to get back the actual type of the element from the
1928 // old bases
1929 using ElType = Cont::ElementType;
1930
1931 using Containers = Mesh<A...>::Containers;
1933 static_assert(I >= 0 && I != UINT_NULL);
1934
1935 using ContainerWrapper = TypeWrapper<A...>;
1936
1937 // for each Container A in m, we update the references of ElType.
1938 // old base is contained in the array bases, the new base is the
1939 // base of the container
1940 m.updateReferences(
1941 reinterpret_cast<const ElType*>(bases[I]), ContainerWrapper());
1942 }
1943 }
1944
1945 template<typename Cont, typename ArrayB, typename ArrayS, typename... A>
1946 static void updateReferencesOfContainerTypeAfterAppend(
1947 Mesh<A...>& m,
1948 const ArrayB& bases,
1949 const ArrayS& sizes)
1950 {
1951 // since this function is called using pack expansion, it means that
1952 // Cont could be a mesh component and not a cointainer. We check if Cont
1953 // is a container
1954 if constexpr (mesh::ElementContainerConcept<Cont>) {
1955 // The element type contained in the container
1956 // We need it to get back the actual type of the element from the
1957 // old bases
1958 using ElType = Cont::ElementType;
1959
1960 using Containers = Mesh<A...>::Containers;
1961 constexpr uint I = IndexInTypes<Cont, Containers>::value;
1962 static_assert(I >= 0 && I != UINT_NULL);
1963
1964 using ContainerWrapper = TypeWrapper<A...>;
1965
1966 // for each Container A in m, we update the references of ElType.
1967 // old base is contained in the array bases
1968 m.updateReferences(
1969 reinterpret_cast<const ElType*>(bases[I]),
1971 sizes,
1972 sizes[I]);
1973 }
1974 }
1975
1976 template<
1977 typename Cont,
1978 typename ArrayS,
1979 Matrix44Concept MatrixType,
1980 typename... A>
1981 static void updatePosAndNormalsOfContainerTypeAfterAppend(
1982 Mesh<A...>& m,
1983 const ArrayS& sizes,
1984 const MatrixType& matrix)
1985 {
1986 // since this function is called using pack expansion, it means that
1987 // Cont could be a mesh component and not a cointainer. We check if Cont
1988 // is a container
1989 if constexpr (mesh::ElementContainerConcept<Cont>) {
1990 // The element type contained in the container
1991 // We need it to get back the actual type of the element from the
1992 // old bases
1993 using ElType = Cont::ElementType;
1994 static constexpr uint ELEM_ID = ElType::ELEMENT_ID;
1995
1996 using Containers = Mesh<A...>::Containers;
1997 constexpr uint I = IndexInTypes<Cont, Containers>::value;
1998 static_assert(I >= 0 && I != UINT_NULL);
1999
2000 if constexpr (hasPerElementComponent<ELEM_ID, CompId::POSITION>()) {
2001 auto posview = m.template elements<ELEM_ID>((uint) sizes[I]) |
2002 vcl::views::positions;
2003
2004 multiplyPointsByMatrix(posview, matrix);
2005 }
2006
2007 if constexpr (hasPerElementComponent<ELEM_ID, CompId::NORMAL>()) {
2008 if (m.Cont::template isComponentAvailable<CompId::NORMAL>()) {
2009 auto norview =
2010 m.template elements<ELEM_ID>((uint) sizes[I]) |
2011 vcl::views::normals;
2012
2013 multiplyNormalsByMatrix(norview, matrix);
2014 }
2015 }
2016 }
2017 }
2018
2019 template<typename Cont, typename ArrayS, typename... A>
2020 static void updateTextureIndicesOfContainerTypeAfterAppend(
2021 Mesh<A...>& m,
2022 const ArrayS& sizes,
2023 const std::vector<uint>& mapping)
2024 {
2025 // since this function is called using pack expansion, it means that
2026 // Cont could be a mesh component and not a cointainer. We check if Cont
2027 // is a container
2028 if constexpr (mesh::ElementContainerConcept<Cont>) {
2029 // The element type contained in the container
2030 // We need it to get back the actual type of the element from the
2031 // old bases
2032 using ElType = Cont::ElementType;
2033 static constexpr uint ELEM_ID = ElType::ELEMENT_ID;
2034
2035 using Containers = Mesh<A...>::Containers;
2036 constexpr uint I = IndexInTypes<Cont, Containers>::value;
2037 static_assert(I >= 0 && I != UINT_NULL);
2038
2039 if constexpr (hasPerElementComponent<
2040 ELEM_ID,
2041 CompId::TEX_COORD>()) {
2042 if (m.Cont::template isComponentAvailable<
2043 CompId::TEX_COORD>()) {
2044 auto tcview =
2045 m.template elements<ELEM_ID>((uint) sizes[I]) |
2046 vcl::views::texCoords;
2047 for (auto& tc : tcview) {
2048 tc.index() = mapping[tc.index()];
2049 }
2050 }
2051 }
2052
2053 if constexpr (hasPerElementComponent<
2054 ELEM_ID,
2055 CompId::WEDGE_TEX_COORDS>()) {
2056 if (m.Cont::template isComponentAvailable<
2057 CompId::WEDGE_TEX_COORDS>()) {
2058 auto elview = m.template elements<ELEM_ID>((uint) sizes[I]);
2059 for (auto& e : elview) {
2060 e.textureIndex() = mapping[e.textureIndex()];
2061 }
2062 }
2063 }
2064 }
2065 }
2066
2067 // serialization/deserialization
2068
2069 template<typename Cont>
2070 void preSerialization(std::ostream& os) const
2071 {
2072 if constexpr (mesh::ElementContainerConcept<Cont>) {
2073 Cont::serializeOptionalComponentsAndElementsNumber(os);
2074 }
2075 }
2076
2077 template<typename Cont>
2078 void postSerialization(std::ostream& os) const
2079 {
2080 if constexpr (mesh::ElementContainerConcept<Cont>) {
2081 Cont::serializeElements(os);
2082 }
2083 else {
2084 // cont is a component...
2085 Cont::serialize(os);
2086 }
2087 }
2088
2089 template<typename Cont>
2090 void preDeserialization(std::istream& is)
2091 {
2092 if constexpr (mesh::ElementContainerConcept<Cont>) {
2093 Cont::deserializeOptionalComponentsAndElementsNumber(is);
2094 }
2095 }
2096
2097 template<typename Cont>
2098 void postDeserialization(std::istream& is)
2099 {
2100 if constexpr (mesh::ElementContainerConcept<Cont>) {
2101 Cont::deserializeElements(is);
2102 }
2103 else {
2104 // cont is a component...
2105 Cont::deserialize(is);
2106 }
2107 }
2108
2109 // member functions used by friends
2110
2111 template<uint ELEM_ID, typename T>
2112 uint elementIndex(const T* el) const
2113 {
2114 using Cont = ContainerOfElement<ELEM_ID>::type;
2115 using ElType = Cont::ElementType;
2116 return index(static_cast<const ElType*>(el));
2117 }
2118
2119 template<typename El>
2120 auto& customComponents()
2121 {
2122 using ElCont = ContainerOf<El>::type;
2123
2124 return ElCont::mCustomCompVecMap;
2125 }
2126
2127 template<typename El>
2128 const auto& customComponents() const
2129 {
2130 using ElCont = ContainerOf<El>::type;
2131
2132 return ElCont::mCustomCompVecMap;
2133 }
2134
2135 template<typename El>
2136 auto& verticalComponents()
2137 {
2138 using ElCont = ContainerOf<El>::type;
2139
2140 return ElCont::mVerticalCompVecTuple;
2141 }
2142
2143 template<typename El>
2144 const auto& verticalComponents() const
2145 {
2146 using ElCont = ContainerOf<El>::type;
2147
2148 return ElCont::mVerticalCompVecTuple;
2149 }
2150};
2151
2152/* Concepts */
2153
2166template<typename T>
2168 IsDerivedFromSpecializationOfV<T, Mesh> && mesh::HasVertexContainer<T>;
2169
2179template<typename T>
2181
2182} // namespace vcl
2183
2184#endif // VCL_MESH_MESH_H
The Array class is a dynamically allocated N-dimensional array stored in RowWise mode.
Definition array.h:60
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
The Element class.
Definition element.h:75
The Mesh class represents a generic 3D mesh. A mesh is composed of a generic number of containers of ...
Definition mesh.h:68
bool isCompact() const
Returns true if this mesh is compact, meaning that all its containers have no deleted elements (size ...
Definition mesh.h:318
auto elements(bool jumpDeleted=true) const
Definition mesh.h:1212
uint deletedNumber() const
Returns the number of deleted elements of the given type in this mesh.
Definition mesh.h:721
void deleteElement(uint i)
Marks as deleted the element at the given index from its container, deduced from the template index E...
Definition mesh.h:902
void deleteElement(const El &e) const
Marks as deleted the given element from its container.
Definition mesh.h:951
Mesh()
Empty constructor, constructs an empty mesh.
Definition mesh.h:263
Mesh(const Mesh &oth)
Copy constructor of the Mesh. Will create a deep copy of the given input mesh, taking care of copying...
Definition mesh.h:276
auto begin(bool jumpDeleted=true)
Returns an iterator to the begining of the container of the elements having ID ELEM_ID in the mesh.
Definition mesh.h:1050
CustomComponentVectorHandle< K > perElementCustomComponentVectorHandle(const std::string &name)
Returns a vector handle to the custom component of type K having the given name associated to the Ele...
Definition mesh.h:1516
std::type_index perElementCustomComponentType(const std::string &name) const
Returns the std::type_index of the custom component having the given name associated to the Element h...
Definition mesh.h:1403
void compactContainer()
Definition mesh.h:1651
auto elements(bool jumpDeleted=true)
Definition mesh.h:1144
void compactElements()
Compacts the Container of the given element, removing all the elements marked as deleted....
Definition mesh.h:877
void enableSameOptionalComponentsOf(const OtherMeshType &m)
Enables all the OptionalComponents of this mesh according to the Components available on the OtherMes...
Definition mesh.h:387
Mesh(Mesh &&oth)
Move constructor, moves the given mesh into this one, without any other resource acquisition.
Definition mesh.h:304
bool hasPerElementCustomComponent(const std::string &name) const
Returns true if the Element having ID ELEM_ID has a custom component with the given name.
Definition mesh.h:1337
std::vector< uint > compactIndices() const
Returns a vector that tells, for each element of the container of ELEM_ID in the mesh,...
Definition mesh.h:975
void deserializePerElementCustomComponentsOfType(std::istream &is)
Deserializes the custom components of type K of the element with ID ELEM_ID.
Definition mesh.h:1622
void deleteElement(const El *e) const
Marks as deleted the given element from its container.
Definition mesh.h:927
void disableAllOptionalComponents()
Disables all the optional components of the elements of the containers if the mesh.
Definition mesh.h:352
void addPerElementCustomComponent(const std::string &name)
Adds a custom component of type K having the given name to the Element having ID ELEM_ID.
Definition mesh.h:1446
void append(const Mesh &m)
Appends all the elements contained in the mesh m to this mesh.
Definition mesh.h:408
auto end()
Returns an iterator to the end of the container of the elements having ID ELEM_ID in the mesh.
Definition mesh.h:1069
void enableAllOptionalComponentsInContainer()
Definition mesh.h:1670
bool isPerElementCustomComponentOfType(const std::string &name) const
Returns true if the Element having ID ELEM_ID has a custom component of type K with the given name.
Definition mesh.h:1381
uint add()
Adds a new element of the given type into its container, returning the index of the added element in ...
Definition mesh.h:743
void clear()
Clears all the Elements contained in the mesh.
Definition mesh.h:329
uint add(uint n)
Adds n new elements of the given type into its container, returning the index of the first added elem...
Definition mesh.h:766
void swap(Mesh &m2)
Swaps this mesh with the other input Mesh m2.
Definition mesh.h:536
uint containerSize() const
Returns the size of the container of elements of the given type in this mesh.
Definition mesh.h:703
void clearElements()
Clears the container of ELEM_ID elements the Mesh, deleting all the Elements.
Definition mesh.h:794
void importFrom(const OtherMeshType &m)
Imports all the components that can be imported from another type of mesh.
Definition mesh.h:489
bool isPerElementComponentEnabled() const
Returns true if optional Component having ID COMP_ID is enabled for elements having ID ELEM_ID in the...
Definition mesh.h:1272
const auto & element(uint i) const
Returns the element of the given type at the given index inside its container of this mesh.
Definition mesh.h:642
auto elements(uint begin, uint end=UINT_NULL) const
Returns a lightweight const view object that stores the begin and end const iterators of the containe...
Definition mesh.h:1250
void compact()
Compacts all the containers of the mesh.
Definition mesh.h:337
void updateIndices(const std::vector< uint > &newIndices)
Updates all the indices and pointers of the elements of the container of ELEM_ID in the mesh,...
Definition mesh.h:1010
Mesh & operator=(Mesh oth)
Assignment operator of the Mesh.
Definition mesh.h:583
void clearContainer()
Definition mesh.h:1704
void deletePerElementCustomComponent(const std::string &name)
Deletes the custom component of the given name from the Element having ID ELEM_ID.
Definition mesh.h:1466
void reserve(uint n)
Reserves a number of elements of the given type in its container. The function does not add any eleme...
Definition mesh.h:863
void resize(uint n)
Resizes the Element container to contain n Elements of type ELEM_ID.
Definition mesh.h:835
static void updateReferencesOfContainerType(Mesh< A... > &m, const Array &bases)
Definition mesh.h:1918
auto end() const
Returns a const iterator to the end of the container of the elements having ID ELEM_ID in the mesh.
Definition mesh.h:1114
void enableAllOptionalComponents()
Enables all the optional components of the elements of the containers if the mesh.
Definition mesh.h:343
std::vector< std::string > perElementCustomComponentNames() const
Returns a vector containing all the names of the custom components of any type associated to the Elem...
Definition mesh.h:1358
void disableAllOptionalComponentsInContainer()
Definition mesh.h:1687
static constexpr bool hasPerElementComponent()
Returns true if this Mesh has a container of elements having the same Element ID of the template ELEM...
Definition mesh.h:227
static void setContainerBase(const Mesh< A... > &m, Array &bases)
Definition mesh.h:1825
friend void swap(Mesh &a, Mesh &b)
Specializes the swap function to allow the swapping of two Mesh objects.
Definition mesh.h:575
FilterTypesByCondition< mesh::IsElementContainerPred, TypeWrapper< Args... > >::type Containers
Containers is a vcl::TypeWrapper that wraps all the types from which the Mesh inherits (Args) that ar...
Definition mesh.h:114
auto & element(uint i)
Returns the element of the given type at the given index inside its container of this mesh.
Definition mesh.h:664
void enablePerElementComponent()
Enables the optional Component having ID COMP_ID for elements having ID ELEM_ID in the mesh.
Definition mesh.h:1292
uint index(const El *e) const
Returns the index of the given element in its Container of the Mesh.
Definition mesh.h:621
void disablePerElementComponent()
Disables the optional Component having ID COMP_ID for elements having ID ELEM_ID in the mesh.
Definition mesh.h:1312
ConstCustomComponentVectorHandle< K > perElementCustomComponentVectorHandle(const std::string &name) const
Returns a const vector handle to the custom component of type K having the given name associated to t...
Definition mesh.h:1567
uint number() const
Returns the number of elements of the given type in this mesh.
Definition mesh.h:681
ContainerType< ELEM_ID >::ElementType ElementType
ElementType is an alias that exposes the type of the Element identified by the template parameter ELE...
Definition mesh.h:151
uint index(const El &e) const
Returns the index of the given element in its Container of the Mesh.
Definition mesh.h:603
auto begin(bool jumpDeleted=true) const
Returns a const iterator to the begining of the container of the elements having ID ELEM_ID in the me...
Definition mesh.h:1094
auto elements(uint begin, uint end=UINT_NULL)
Definition mesh.h:1181
static constexpr bool hasPerElementOptionalComponent()
Returns true if this Mesh has a container of elements having the same Element ID of the template ELEM...
Definition mesh.h:252
static constexpr bool hasContainerOf()
Returns true if this Mesh has a container of elements having the same Element ID of the template Elem...
Definition mesh.h:180
std::vector< std::string > perElementCustomComponentNamesOfType() const
Returns a vector containing all the names of the custom components of type K associated to the Elemen...
Definition mesh.h:1425
void serializePerElementCustomComponentsOfType(std::ostream &os) const
Serializes the custom components of type K of the element with ID ELEM_ID.
Definition mesh.h:1602
static void setContainerSize(const Mesh< A... > &m, Array &sizes)
Definition mesh.h:1863
Definition element.h:64
Definition element.h:54
A concept that checks whether a class is a Mesh or an Element.
Definition mesh.h:2180
HasVertices concepts is satisfied when at least one of its types is (or inherits from) a vcl::mesh::V...
Definition vertex_container.h:1267
A concept that checks whether a class is (inherits from) a Mesh class.
Definition mesh.h:2167
The ComponentConcept is evaluated to true whenever the type T is a valid component,...
Definition component.h:46
A concept that checks whether a class has (inherits from) an FaceContainer class.
Definition face_container.h:1349
Definition mesh_components.h:58
Definition mesh_components.h:60
Definition mesh_components.h:62
A concept that checks whether a class has (inherits from) a VertexContainer class.
Definition vertex_container.h:1226
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
The CompId struct enumerates the components that can compose a element or a mesh.
Definition base.h:48
Removes all types that do not satisfy a condition, and get them as a TypeWrapper.
Definition filter_types.h:70
Get the index of a type T in a pack of types (variadic templates) or a TypeWrapper.
Definition variadic_templates.h:138
Definition mesh.h:88
The ContainerOf struct allows to get the Container of an Element on this Mesh.
Definition mesh.h:103
Get the number of types in a pack of types (variadic templates) or a TypeWrapper.
Definition variadic_templates.h:189
A simple structure that wraps a list of variadic templates, without instantiating anything....
Definition type_wrapper.h:39
The ContainerOfElement structure exposes the type of the container of the given MeshType having eleme...
Definition base.h:107
Definition base.h:138
The predicate IsElementContainerPred sets its bool value to true when the type T satisfies the Elemen...
Definition base.h:81