Radium Engine  1.5.0
VectorArray.hpp
1 #pragma once
2 
3 #include <Core/Containers/AlignedStdVector.hpp>
4 #include <Core/RaCore.hpp>
5 #include <Core/Utils/ContainerIntrospectionInterface.hpp>
6 
7 #include <type_traits> // std::is_integral
8 
9 namespace Ra {
10 namespace Core {
11 
15 template <typename V, bool isArithmetic, bool isEigen>
17 
22 template <typename V>
24  V,
25  std::is_arithmetic<V>::value || std::is_enum<V>::value,
26  std::is_base_of<typename Eigen::MatrixBase<V>, V>::value> {};
27 
33 template <typename V>
34 class VectorArray : public AlignedStdVector<V>, public Utils::ContainerIntrospectionInterface
35 {
36  private:
38 
39  public:
40  static constexpr int NumberOfComponents = TypeHelper::NumberOfComponents;
46  using component_type = typename TypeHelper::component_type;
47  using Matrix = Eigen::Matrix<component_type, TypeHelper::NumberOfComponents, Eigen::Dynamic>;
48  using MatrixMap = Eigen::Map<Matrix>;
49  using ConstMatrixMap = Eigen::Map<const Matrix>;
50 
52  using AlignedStdVector<V>::AlignedStdVector;
53 
56  size_t getSize() const override { return this->size(); }
57  size_t getNumberOfComponents() const override { return std::max( 0, NumberOfComponents ); }
58  size_t getBufferSize() const override { return getSize() * sizeof( V ); }
59  int getStride() const override { return sizeof( V ); }
60  const void* dataPtr() const override { return this->data(); }
62 
68 
69  template <int N = NumberOfComponents>
70  std::enable_if_t<( N > 0 ), MatrixMap> getMap() {
71  CORE_ASSERT( !this->empty(), "Cannot map an empty vector " );
72  return MatrixMap( TypeHelper::getData( this ),
73  TypeHelper::NumberOfComponents,
74  Eigen::Index( this->size() ) );
75  }
76 
78  template <int N = NumberOfComponents>
79  std::enable_if_t<( N > 0 ), ConstMatrixMap> getMap() const {
80  CORE_ASSERT( !this->empty(), "Cannot map an empty vector " );
81  return ConstMatrixMap( TypeHelper::getConstData( this ),
82  TypeHelper::NumberOfComponents,
83  Eigen::Index( this->size() ) );
84  }
86 };
87 
88 template <typename V>
89 struct VectorArrayTypeHelperInternal<V, true, false> {
90  using component_type = V; // arithmetic types are component types
91  static constexpr int NumberOfComponents = 1;
92  static inline component_type* getData( VectorArray<V>* v ) { return v->data(); }
93  static inline const component_type* getConstData( const VectorArray<V>* v ) {
94  return v->data();
95  }
96 };
97 
98 template <typename V>
99 struct VectorArrayTypeHelperInternal<V, false, true> {
100  using component_type = typename V::Scalar; // use eigen scalar as component
101  static constexpr int NumberOfComponents = V::RowsAtCompileTime; // i.e. -1 for dynamic size
102  static inline component_type* getData( VectorArray<V>* v ) { return v->data()->data(); }
103  static inline const component_type* getConstData( const VectorArray<V>* v ) {
104  return v->data()->data();
105  }
106 };
107 
108 template <typename V>
109 struct VectorArrayTypeHelperInternal<V, false, false> {
110  using component_type = V;
111  static constexpr int NumberOfComponents = 0; // no component for other types, i.e. not mappable
112  static inline component_type* getData( VectorArray<V>* v ) { return v->data(); }
113  static inline const component_type* getConstData( const VectorArray<V>* v ) {
114  return v->data();
115  }
116 };
117 
118 // Convenience aliases
119 using Vector1Array = VectorArray<Scalar>;
120 #define DEFINE_CONVENIENCE_MATRIX_ALIAS( NAME, TYPE, DIM ) \
121  using NAME = VectorArray<Eigen::Matrix<TYPE, DIM, 1>>;
122 DEFINE_CONVENIENCE_MATRIX_ALIAS( Vector2Array, Scalar, 2 )
123 DEFINE_CONVENIENCE_MATRIX_ALIAS( Vector3Array, Scalar, 3 )
124 DEFINE_CONVENIENCE_MATRIX_ALIAS( Vector4Array, Scalar, 4 )
125 DEFINE_CONVENIENCE_MATRIX_ALIAS( VectorNArray, Scalar, Eigen::Dynamic )
126 DEFINE_CONVENIENCE_MATRIX_ALIAS( Vector1iArray, int, 1 )
127 DEFINE_CONVENIENCE_MATRIX_ALIAS( Vector2iArray, int, 2 )
128 DEFINE_CONVENIENCE_MATRIX_ALIAS( Vector3iArray, int, 3 )
129 DEFINE_CONVENIENCE_MATRIX_ALIAS( Vector4iArray, int, 4 )
130 DEFINE_CONVENIENCE_MATRIX_ALIAS( VectorNiArray, int, Eigen::Dynamic )
131 DEFINE_CONVENIENCE_MATRIX_ALIAS( Vector1uArray, uint, 1 )
132 DEFINE_CONVENIENCE_MATRIX_ALIAS( Vector2uArray, uint, 2 )
133 DEFINE_CONVENIENCE_MATRIX_ALIAS( Vector3uArray, uint, 3 )
134 DEFINE_CONVENIENCE_MATRIX_ALIAS( Vector4uArray, uint, 4 )
135 DEFINE_CONVENIENCE_MATRIX_ALIAS( VectorNuArray, uint, Eigen::Dynamic )
136 #undef DEFINE_CONVENIENCE_MATRIX_ALIAS
137 
138 // Notes :
139 // Using a map for eigen integration was recommended by [1].
140 // According to this document [2], it is necessary to use a special allocator to enforce
141 // alignment...
142 // But actually it is not necessary to do so in C++11 [3] (it is actually harmful
143 // as it removes some vector features such as initializer lists).
144 // Finally we use our own aligned allocator.
145 
146 // [1] https://forum.kde.org/viewtopic.php?f=74&t=126959
147 // [2] http://eigen.tuxfamily.org/dox-devel/group__TopicStlContainers.html
148 // [3] http://eigen.tuxfamily.org/bz/show_bug.cgi?id=829
149 
150 } // namespace Core
151 } // namespace Ra
This class defines the introspection interface a container need to implement.
This class implements ContainerIntrospectionInterface for AlignedStdVector.
Definition: VectorArray.hpp:35
std::enable_if_t<(N > 0), ConstMatrixMap > getMap() const
Definition: VectorArray.hpp:79
const void * dataPtr() const override
Definition: VectorArray.hpp:60
std::enable_if_t<(N > 0), MatrixMap > getMap()
Definition: VectorArray.hpp:70
typename TypeHelper::component_type component_type
Definition: VectorArray.hpp:46
size_t getNumberOfComponents() const override
Definition: VectorArray.hpp:57
int getStride() const override
Definition: VectorArray.hpp:59
size_t getSize() const override
Definition: VectorArray.hpp:56
size_t getBufferSize() const override
Definition: VectorArray.hpp:58
Definition: Cage.cpp:3