Radium Engine  1.5.0
IndexedGeometry.hpp
1 #pragma once
2 
3 #include <Core/Containers/VectorArray.hpp>
4 #include <Core/Geometry/TriangleMesh.hpp>
5 #include <Core/Utils/ContainerIntrospectionInterface.hpp>
6 #include <Core/Utils/ObjectWithSemantic.hpp>
8 
9 #include <memory>
10 #include <unordered_map>
11 
12 namespace Ra {
13 namespace Core {
14 namespace Geometry {
15 
17 class RA_CORE_API GeometryIndexLayerBase : public Utils::ObservableVoid,
20 {
21  public:
24  inline explicit GeometryIndexLayerBase( const GeometryIndexLayerBase& other );
27  inline GeometryIndexLayerBase& operator=( const GeometryIndexLayerBase& other );
30  inline GeometryIndexLayerBase& operator=( GeometryIndexLayerBase&& other );
31  virtual ~GeometryIndexLayerBase();
32 
34  virtual std::unique_ptr<GeometryIndexLayerBase> clone() = 0;
35 
38  virtual bool append( const GeometryIndexLayerBase& other ) = 0;
39 
41  virtual inline bool operator==( const GeometryIndexLayerBase& other ) const;
42 
43  protected:
46  template <class... SemanticNames>
47  inline GeometryIndexLayerBase( SemanticNames... names ) : ObjectWithSemantic( names... ) {}
48 };
49 
51 template <typename T>
53  using IndexType = T;
55 
56  inline IndexContainerType& collection();
57  const IndexContainerType& collection() const;
58 
59  inline bool append( const GeometryIndexLayerBase& other ) final;
60 
62  inline bool operator==( const GeometryIndexLayerBase& other ) const final;
63 
64  inline size_t getSize() const override final;
65 
66  inline std::unique_ptr<GeometryIndexLayerBase> clone() override final;
67 
68  inline size_t getNumberOfComponents() const override final;
69 
70  inline size_t getBufferSize() const override final;
71 
74  inline int getStride() const override final;
75 
76  inline const void* dataPtr() const override final;
77 
78  protected:
79  template <class... SemanticNames>
80  inline GeometryIndexLayer( SemanticNames... names ) : GeometryIndexLayerBase( names... ) {}
81 
82  private:
83  IndexContainerType m_collection;
84 };
85 
131 class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Utils::ObservableVoid
132 {
133  public:
134  using LayerSemanticCollection = Utils::ObjectWithSemantic::SemanticNameCollection;
135  using LayerSemantic = Utils::ObjectWithSemantic::SemanticName;
136  using LayerKeyType = std::pair<LayerSemanticCollection, std::string>;
137 
144 
145  inline MultiIndexedGeometry() = default;
146  explicit MultiIndexedGeometry( const MultiIndexedGeometry& other );
147  explicit MultiIndexedGeometry( MultiIndexedGeometry&& other );
148  explicit MultiIndexedGeometry( const AttribArrayGeometry& other );
149  explicit MultiIndexedGeometry( AttribArrayGeometry&& other );
150  MultiIndexedGeometry& operator=( const MultiIndexedGeometry& other );
151  MultiIndexedGeometry& operator=( MultiIndexedGeometry&& other );
152 
153  virtual inline ~MultiIndexedGeometry();
154  void clear() override;
155 
158  void copy( const MultiIndexedGeometry& other );
159 
162  void checkConsistency() const;
163 
167  bool append( const MultiIndexedGeometry& other );
168 
171 
175  inline bool containsLayer( const LayerKeyType& layerKey ) const;
176 
183  inline bool containsLayer( const LayerSemanticCollection& semantics,
184  const std::string& layerName ) const;
185 
191  bool containsLayer( const LayerSemanticCollection& semantics ) const;
192 
198  bool containsLayer( const LayerSemantic& semanticName ) const;
199 
202 
206  inline size_t countLayers( const LayerKeyType& layerKey ) const;
207 
214  inline size_t countLayers( const LayerSemanticCollection& semantics,
215  const std::string& layerName ) const;
216 
222  size_t countLayers( const LayerSemanticCollection& semantics ) const;
223 
229  size_t countLayers( const LayerSemantic& semanticName ) const;
230 
233 
238  inline const GeometryIndexLayerBase& getLayer( const LayerKeyType& layerKey ) const;
239 
247  inline const GeometryIndexLayerBase& getLayer( const LayerSemanticCollection& semantics,
248  const std::string& layerName ) const;
256  std::pair<LayerKeyType, const GeometryIndexLayerBase&>
257  getFirstLayerOccurrence( const LayerSemanticCollection& semantics ) const;
258 
266  std::pair<LayerKeyType, const GeometryIndexLayerBase&>
267  getFirstLayerOccurrence( const LayerSemantic& semanticName ) const;
268 
271 
280  GeometryIndexLayerBase& getLayerWithLock( const LayerKeyType& layerKey );
281 
290  inline GeometryIndexLayerBase& getLayerWithLock( const LayerSemanticCollection& semantics,
291  const std::string& layerName );
292 
301  std::pair<LayerKeyType, GeometryIndexLayerBase&>
302  getFirstLayerOccurrenceWithLock( const LayerSemanticCollection& semantics );
303 
312  std::pair<LayerKeyType, GeometryIndexLayerBase&>
313  getFirstLayerOccurrenceWithLock( const LayerSemantic& semanticName );
314 
317 
324  void unlockLayer( const LayerKeyType& layerKey );
325 
334  inline void unlockLayer( const LayerSemanticCollection& semantics,
335  const std::string& layerName );
336 
337  // The following methods are only mean to be used by PredifinedIndexGeometry and should not be
338  // part of the final API
339  protected:
347  void unlockFirstLayerOccurrence( const LayerSemanticCollection& semantics );
348 
356  void unlockFirstLayerOccurrence( const LayerSemantic& semanticName );
357 
360  public:
368  std::pair<bool, GeometryIndexLayerBase&>
369  addLayer( std::unique_ptr<GeometryIndexLayerBase>&& layer,
370  const bool withLock = false,
371  const std::string& layerName = "" );
372 
377  [[nodiscard]] inline auto layerKeys() const;
378 
379  private:
381  void deepCopy( const MultiIndexedGeometry& other );
382 
384  void deepClear();
385 
386  using EntryType = std::pair<bool, std::unique_ptr<GeometryIndexLayerBase>>;
387 
388  struct RA_CORE_API KeyHash {
389  std::size_t operator()( const LayerKeyType& k ) const;
390  };
391 
397  std::unordered_map<LayerKeyType, EntryType, KeyHash> m_indices;
398 };
399 
403 
405 struct RA_CORE_API PointCloudIndexLayer : public GeometryIndexLayer<Vector1ui> {
407  inline PointCloudIndexLayer();
408 
411  inline explicit PointCloudIndexLayer( size_t n );
412 
414  void linearIndices( const AttribArrayGeometry& attr );
415 
416  static constexpr const char* staticSemanticName = "PointCloud";
417 
418  protected:
419  template <class... SemanticNames>
420  inline PointCloudIndexLayer( SemanticNames... names );
421 };
422 
425 struct RA_CORE_API TriangleIndexLayer : public GeometryIndexLayer<Vector3ui> {
426  inline TriangleIndexLayer();
427  static constexpr const char* staticSemanticName = "TriangleMesh";
428 
429  protected:
430  template <class... SemanticNames>
431  inline explicit TriangleIndexLayer( SemanticNames... names );
432 };
433 
436 struct RA_CORE_API QuadIndexLayer : public GeometryIndexLayer<Vector4ui> {
437  inline QuadIndexLayer();
438  static constexpr const char* staticSemanticName = "QuadMesh";
439 
440  protected:
441  template <class... SemanticNames>
442  inline explicit QuadIndexLayer( SemanticNames... names );
443 };
444 
448 struct RA_CORE_API PolyIndexLayer : public GeometryIndexLayer<VectorNui> {
449  inline PolyIndexLayer();
450  static constexpr const char* staticSemanticName = "PolyMesh";
451 
452  protected:
453  template <class... SemanticNames>
454  inline explicit PolyIndexLayer( SemanticNames... names );
455 };
456 
459 struct RA_CORE_API LineIndexLayer : public GeometryIndexLayer<Vector2ui> {
460  inline LineIndexLayer();
461  static constexpr const char* staticSemanticName = "LineMesh";
462 
463  protected:
464  template <class... SemanticNames>
465  inline explicit LineIndexLayer( SemanticNames... names );
466 };
467 
469 
472 namespace IndexLayerType {
473 template <class IndexT>
474 struct getType {};
475 
476 template <>
477 struct getType<Vector2ui> {
479 };
480 
481 template <>
482 struct getType<Vector3ui> {
484 };
485 
486 template <>
487 struct getType<Vector4ui> {
489 };
490 
491 template <>
492 struct getType<VectorNui> {
494 };
495 
496 template <>
497 struct getType<Vector1ui> {
499 };
500 
501 } // namespace IndexLayerType
502 
513 template <typename T>
515 {
516  public:
517  using IndexType = T;
519 
520  private:
521  using DefaultLayerType = typename IndexLayerType::getType<IndexType>::Type;
522 
523  public:
524  inline IndexedGeometry();
525 
526  inline const IndexContainerType& getIndices() const;
531 
533  inline void indicesUnlock();
537  inline void setIndices( IndexContainerType&& indices );
538  inline void setIndices( const IndexContainerType& indices );
539  inline const LayerKeyType& getLayerKey() const;
540 
541  private:
542  LayerKeyType m_mainIndexLayerKey;
543 };
544 
545 class RA_CORE_API IndexedPointCloud : public IndexedGeometry<Vector1ui>
546 {};
547 
548 class RA_CORE_API TriangleMesh : public IndexedGeometry<Vector3ui>
549 {};
550 
551 class RA_CORE_API QuadMesh : public IndexedGeometry<Vector4ui>
552 {};
553 
554 class RA_CORE_API PolyMesh : public IndexedGeometry<VectorNui>
555 {};
556 
557 class RA_CORE_API LineMesh : public IndexedGeometry<Vector2ui>
558 {};
559 
560 // GeometryIndexLayerBase
562  ObjectWithSemantic( other.semantics() ) {}
563 
566  CORE_UNUSED( other );
567  CORE_ASSERT( semantics() == other.semantics(),
568  "Try to assign object with different semantics" );
569  return *this;
570 }
571 
573  CORE_UNUSED( other );
574  CORE_ASSERT( semantics() == other.semantics(),
575  "Try to assign GeometryIndexLayer of different type" );
576  return *this;
577 }
578 
579 inline GeometryIndexLayerBase::~GeometryIndexLayerBase() {}
580 
582  return false;
583 }
584 
585 // GeometryIndexLayer
586 
587 template <typename T>
589  return m_collection;
590 }
591 
592 template <typename T>
595  return m_collection;
596 }
597 
598 template <typename T>
600  if ( shareSemantic( other ) ) {
601  const auto& othercasted = static_cast<const GeometryIndexLayer<T>&>( other );
602  m_collection.insert(
603  m_collection.end(), othercasted.collection().begin(), othercasted.collection().end() );
604  return true;
605  }
606  return false;
607 }
608 
609 template <typename T>
611  if ( shareSemantic( other ) ) {
612  const auto& othercasted = static_cast<const GeometryIndexLayer<T>&>( other );
613  return othercasted.collection() == m_collection;
614  }
615  return false;
616 }
617 
618 template <typename T>
619 inline size_t GeometryIndexLayer<T>::getSize() const {
620  return m_collection.size();
621 }
622 
623 template <typename T>
625  return IndexType::RowsAtCompileTime;
626 }
627 
628 template <typename T>
630  return m_collection.size() * sizeof( IndexType );
631 }
632 
633 template <typename T>
635  return sizeof( IndexType );
636 }
637 
638 template <typename T>
639 inline const void* GeometryIndexLayer<T>::dataPtr() const {
640  return m_collection.data();
641 }
642 
643 template <typename T>
644 inline std::unique_ptr<GeometryIndexLayerBase> GeometryIndexLayer<T>::clone() {
645  auto copy = std::make_unique<GeometryIndexLayer<T>>( *this );
646  copy->m_collection = m_collection;
647  return copy;
648 }
649 
650 // MultiIndexedGeometry
651 inline MultiIndexedGeometry::~MultiIndexedGeometry() {
652  detachAll();
653  clear();
654 }
655 
656 inline bool
657 MultiIndexedGeometry::containsLayer( const MultiIndexedGeometry::LayerKeyType& layerKey ) const {
658  return m_indices.find( layerKey ) != m_indices.end();
659 }
660 
661 inline bool
662 MultiIndexedGeometry::containsLayer( const MultiIndexedGeometry::LayerSemanticCollection& semantics,
663  const std::string& layerName ) const {
664  return containsLayer( { semantics, layerName } );
665 }
666 
667 inline size_t
668 MultiIndexedGeometry::countLayers( const MultiIndexedGeometry::LayerKeyType& layerKey ) const {
669  return m_indices.count( layerKey );
670 }
671 
672 inline size_t
673 MultiIndexedGeometry::countLayers( const MultiIndexedGeometry::LayerSemanticCollection& semantics,
674  const std::string& layerName ) const {
675  return countLayers( { semantics, layerName } );
676 }
677 
678 inline const GeometryIndexLayerBase&
679 MultiIndexedGeometry::getLayer( const MultiIndexedGeometry::LayerKeyType& layerKey ) const {
680  return *( m_indices.at( layerKey ).second.get() );
681 }
682 
684  const MultiIndexedGeometry::LayerSemanticCollection& semantics,
685  const std::string& layerName ) {
686  return getLayerWithLock( { semantics, layerName } );
687 }
688 
689 inline void
690 MultiIndexedGeometry::unlockLayer( const MultiIndexedGeometry::LayerSemanticCollection& semantics,
691  const std::string& layerName ) {
692  unlockLayer( { semantics, layerName } );
693 }
694 
695 [[nodiscard]] inline auto MultiIndexedGeometry::layerKeys() const {
696  return Utils::map_keys( m_indices );
697 }
698 
699 // PointCloudIndexLayer
701  GeometryIndexLayer( PointCloudIndexLayer::staticSemanticName ) {}
703  GeometryIndexLayer( PointCloudIndexLayer::staticSemanticName ) {
704  collection().resize( n );
705  collection().getMap() = IndexContainerType::Matrix::LinSpaced( n, 0, n - 1 );
706 }
707 template <class... SemanticNames>
708 inline PointCloudIndexLayer::PointCloudIndexLayer( SemanticNames... names ) :
709  GeometryIndexLayer( PointCloudIndexLayer::staticSemanticName, names... ) {}
710 // TriangleIndexLayer
711 inline TriangleIndexLayer::TriangleIndexLayer() :
712  GeometryIndexLayer( TriangleIndexLayer::staticSemanticName ) {}
713 template <class... SemanticNames>
714 inline TriangleIndexLayer::TriangleIndexLayer( SemanticNames... names ) :
715  GeometryIndexLayer( TriangleIndexLayer::staticSemanticName, names... ) {}
716 // QuadIndexLayer
717 inline QuadIndexLayer::QuadIndexLayer() :
718  GeometryIndexLayer( QuadIndexLayer::staticSemanticName ) {}
719 template <class... SemanticNames>
720 inline QuadIndexLayer::QuadIndexLayer( SemanticNames... names ) :
721  GeometryIndexLayer( QuadIndexLayer::staticSemanticName, names... ) {}
722 // PolyIndexLayer
723 inline PolyIndexLayer::PolyIndexLayer() :
724  GeometryIndexLayer( PolyIndexLayer::staticSemanticName ) {}
725 template <class... SemanticNames>
726 inline PolyIndexLayer::PolyIndexLayer( SemanticNames... names ) :
727  GeometryIndexLayer( PolyIndexLayer::staticSemanticName, names... ) {}
728 // LineIndexLayer
729 inline LineIndexLayer::LineIndexLayer() :
730  GeometryIndexLayer( LineIndexLayer::staticSemanticName ) {}
731 template <class... SemanticNames>
732 inline LineIndexLayer::LineIndexLayer( SemanticNames... names ) :
733  GeometryIndexLayer( LineIndexLayer::staticSemanticName, names... ) {}
734 // IndexedGeometry
735 template <typename T>
736 inline IndexedGeometry<T>::IndexedGeometry() {
737  auto layer = std::make_unique<DefaultLayerType>();
738  m_mainIndexLayerKey = { layer->semantics(), "" };
739  addLayer( std::move( layer ) );
740 }
741 
742 template <typename T>
743 
744 inline const typename IndexedGeometry<T>::IndexContainerType&
745 IndexedGeometry<T>::getIndices() const {
746  const auto& abstractLayer = getLayer( m_mainIndexLayerKey );
747  return static_cast<const IndexedGeometry<T>::DefaultLayerType&>( abstractLayer ).collection();
748 }
749 template <typename T>
751  auto& abstractLayer = getLayerWithLock( m_mainIndexLayerKey );
752  return static_cast<IndexedGeometry<T>::DefaultLayerType&>( abstractLayer ).collection();
753 }
754 
755 template <typename T>
757  unlockLayer( m_mainIndexLayerKey );
758 }
759 
760 template <typename T>
762  auto& abstractLayer = getLayerWithLock( m_mainIndexLayerKey );
763  static_cast<IndexedGeometry<T>::DefaultLayerType&>( abstractLayer ).collection() =
764  std::move( indices );
765  notify();
766 }
767 
768 template <typename T>
769 inline void IndexedGeometry<T>::setIndices( const IndexContainerType& indices ) {
770  auto& abstractLayer = getLayerWithLock( m_mainIndexLayerKey );
771  static_cast<IndexedGeometry<T>::DefaultLayerType&>( abstractLayer ).collection() = indices;
772  notify();
773 }
774 
775 template <typename T>
777  return m_mainIndexLayerKey;
778 }
779 
780 } // namespace Geometry
781 } // namespace Core
782 } // namespace Ra
This class represents vertex + attributes per vertex. Toplogy is handled in MultiIndexedGeometry subc...
Base class for index collections stored in MultiIndexedGeometry.
GeometryIndexLayerBase(SemanticNames... names)
Hidden constructor that must be called by inheriting classes to define the object semantics.
virtual std::unique_ptr< GeometryIndexLayerBase > clone()=0
Create new layer with duplicated content.
virtual bool append(const GeometryIndexLayerBase &other)=0
Append content from another layer.
virtual bool operator==(const GeometryIndexLayerBase &other) const
Compare if two layers have the same content.
GeometryIndexLayerBase(const GeometryIndexLayerBase &other)
Copy constructor.
GeometryIndexLayerBase & operator=(const GeometryIndexLayerBase &other)
Assignment operator.
A single layer MultiIndexedGeometry.
IndexContainerType & getIndicesWithLock()
void indicesUnlock()
unlock previously read write acces, notify observers of the update.
void setIndices(IndexContainerType &&indices)
AbstractGeometry with per-vertex attributes and layers of indices. Each layer represents a different ...
const GeometryIndexLayerBase & getLayer(const LayerKeyType &layerKey) const
Read-only access to a layer.
auto layerKeys() const
Range on layer keys (read-only)
size_t countLayers(const LayerKeyType &layerKey) const
Count the number of layer matching the input parameters.
bool containsLayer(const LayerKeyType &layerKey) const
Check if at least one layer with such properties exists.
GeometryIndexLayerBase & getLayerWithLock(const LayerKeyType &layerKey)
Write access to a layer.
void clear() override
Erases all data, making the geometry empty.
void unlockLayer(const LayerKeyType &layerKey)
Unlock layer with write acces, notify observers of the update.
const GeometryIndexLayerBase & getLayer(const LayerSemanticCollection &semantics, const std::string &layerName) const
Read-only access to a layer.
This class defines the introspection interface a container need to implement.
Object associated with one or multiple semantic names.
std::set< SemanticName > SemanticNameCollection
Store in set to allow for logarithmic search.
void detachAll()
Detach all observers.
Definition: Observable.hpp:73
std::enable_if_t<(N > 0), MatrixMap > getMap()
Definition: VectorArray.hpp:70
Definition: Cage.cpp:3
bool append(const GeometryIndexLayerBase &other) final
Append content from another layer.
size_t getSize() const override final
const void * dataPtr() const override final
size_t getBufferSize() const override final
int getStride() const override final
size_t getNumberOfComponents() const override final
bool operator==(const GeometryIndexLayerBase &other) const final
std::unique_ptr< GeometryIndexLayerBase > clone() override final
Create new layer with duplicated content.
Index layer for line mesh.
Index layer for a point cloud.
PointCloudIndexLayer()
Constructor of an empty layer.
Index layer for polygonal mesh.
Index layer for quadrilateral mesh.
Index layer for triangle mesh.
Generate a range to iterate over the keys of a map.