Radium Engine  1.5.0
Volume.hpp
1 #pragma once
2 
3 #include <Core/Geometry/AbstractGeometry.hpp>
4 #include <Core/RaCore.hpp>
5 #include <Core/Types.hpp>
6 
7 #define RA_REQUIRE_OPTIONAL
8 #include <Core/Utils/StdOptional.hpp> // trigger an error if optional is not found
9 #undef RA_REQUIRE_OPTIONAL
10 
11 #include <algorithm> // find_if
12 
13 namespace Ra {
14 namespace Core {
15 namespace Geometry {
16 
30 class RA_CORE_API AbstractVolume : public AbstractGeometry
31 {
32 
33  public:
36  UNKNOWN = 1 << 0,
37  PARAMETRIC = 1 << 1,
38  DISCRETE_DENSE = 1 << 2,
39  DISCRETE_SPARSE = 1 << 3
41  };
42 
44  using ValueType = Scalar;
45 
46  protected:
47  AbstractVolume( const VolumeStorageType& type );
48 
49  public:
50  AbstractVolume( const AbstractVolume& data ) = default;
51  AbstractVolume& operator=( const AbstractVolume& ) = default;
52  ~AbstractVolume() = default;
53 
55  inline VolumeStorageType getType() const { return m_type; }
56 
57  protected:
59  inline void setType( const VolumeStorageType& type ) { m_type = type; }
60 
61  public:
66  virtual Utils::optional<ValueType> getValue( Eigen::Ref<const Vector3> p ) const = 0;
67 
71  bool isParametric() const;
73  bool isDiscrete() const;
75  bool isDense() const;
77  bool isSparse() const;
79 
81  void displayInfo() const;
82 
83  protected:
86 };
92 class RA_CORE_API AbstractDiscreteVolume : public AbstractVolume
93 {
94 
95  public:
97  using IndexType = Vector3i;
98 
99  protected:
100  inline AbstractDiscreteVolume( const VolumeStorageType& type ) :
101  AbstractVolume( type ), m_size( IndexType::Zero() ), m_binSize { 1_ra, 1_ra, 1_ra } {}
102 
103  public:
104  AbstractDiscreteVolume( const AbstractDiscreteVolume& data ) = default;
105  AbstractDiscreteVolume& operator=( const AbstractDiscreteVolume& ) = default;
106  ~AbstractDiscreteVolume() override = default;
107 
109  void clear() override;
110 
112  Aabb computeAabb() const override;
113 
115  const Vector3i& size() const { return m_size; }
117  void setSize( Eigen::Ref<const Vector3i> size ) {
118  m_size = size;
119  updateStorage();
120  invalidateAabb();
121  }
123  const Vector3& binSize() const { return m_binSize; }
124 
126  void setBinSize( Eigen::Ref<const Vector3> binSize ) {
127  CORE_ASSERT( binSize != Vector3::Zero(), "Volume bin size can't be zero." );
128  m_binSize = binSize;
129  invalidateAabb();
130  }
131 
133  inline Utils::optional<ValueType> getBinValue( Eigen::Ref<const IndexType> p ) const {
134  if ( auto res = linearIndex( p ) ) return getBinValue( *res );
135  return {};
136  }
137 
142  inline Utils::optional<ValueType> getValue( Eigen::Ref<const Vector3> p ) const override final {
143  return getBinValue( ( p.cwiseQuotient( m_binSize ) ).cast<typename IndexType::Scalar>() );
144  }
145 
150  inline bool addToBin( const ValueType& value, Eigen::Ref<const IndexType> p ) {
151  if ( auto res = linearIndex( p ) ) {
152  addToBin( value, *res );
153  invalidateAabb();
154  return true;
155  }
156  return false;
157  }
158 
159  protected:
161  inline Utils::optional<typename IndexType::Scalar>
162  linearIndex( Eigen::Ref<const IndexType> p ) const {
163  using Integer = typename IndexType::Scalar;
164  if ( ( p.array() >= m_size.array() ).any() ) return {};
165  return p.dot( IndexType( Integer( 1 ), m_size( 0 ), m_size( 0 ) * m_size( 1 ) ) );
166  }
168  virtual Utils::optional<ValueType> getBinValue( typename IndexType::Scalar idx ) const = 0;
170  virtual void addToBin( const ValueType& value, typename IndexType::Scalar idx ) = 0;
171 
173  virtual void updateStorage() = 0;
174 
175  private:
176  IndexType m_size;
177  Vector3 m_binSize;
178 };
179 
181 class RA_CORE_API VolumeGrid : public AbstractDiscreteVolume
182 {
183  public:
184  using ValueType = AbstractDiscreteVolume::ValueType;
185  using IndexType = AbstractDiscreteVolume::IndexType;
186  // Stores the 3 partial derivatives of the density if the 3 first components and the density as
187  // fourth component.
188  using GradientType = Eigen::Matrix<ValueType, 4, 1>;
189 
190  using Container = std::vector<ValueType>;
191  using GradientContainer = std::vector<GradientType>;
192 
193  public:
194  inline VolumeGrid( const ValueType& defaultValue = ValueType( 0. ) ) :
195  AbstractDiscreteVolume( DISCRETE_DENSE ), m_defaultValue( defaultValue ) {}
196  VolumeGrid( const VolumeGrid& data ) = default;
197  VolumeGrid& operator=( const VolumeGrid& ) = default;
198  ~VolumeGrid() override = default;
199 
202 
204  inline const Container& data() const { return m_data; }
206  inline Container& data() { return m_data; }
207 
209  inline void addToAllBins( const ValueType& value ) {
210  for ( auto& v : m_data ) {
211  v += value;
212  }
213  }
214 
216  bool hasGradients() const { return m_data.size() == m_gradient.size(); }
217 
219  void computeGradients();
220 
222  inline const GradientContainer& gradient() const { return m_gradient; }
224  inline GradientContainer& gradient() { return m_gradient; }
225 
226  protected:
229  inline Utils::optional<ValueType> getBinValue( typename IndexType::Scalar idx ) const override {
230  return m_data[size_t( idx )];
231  }
232 
235  inline void addToBin( const ValueType& value, typename IndexType::Scalar idx ) override {
236  m_data[size_t( idx )] += value;
237  }
238 
240  inline void updateStorage() override {
241  m_data.resize( size_t( size().prod() ), m_defaultValue );
242  }
243 
244  private:
246  ValueType sample( const IndexType& i );
247 
248  ValueType m_defaultValue;
249  Container m_data;
250  GradientContainer m_gradient;
251 }; // class VolumeGrid
252 
258 class RA_CORE_API VolumeSparse : public AbstractDiscreteVolume
259 {
260  public:
261  using ValueType = AbstractDiscreteVolume::ValueType;
262  using IndexType = AbstractDiscreteVolume::IndexType;
263  struct SampleType {
264  int index;
265  ValueType value;
266 
267  inline SampleType( int idx, const ValueType& v ) : index( idx ), value( v ) {}
268  };
269  using Container = std::vector<SampleType>;
270 
271  public:
272  inline VolumeSparse() : AbstractDiscreteVolume( DISCRETE_SPARSE ) {}
273  VolumeSparse( const VolumeSparse& data ) = default;
274  VolumeSparse& operator=( const VolumeSparse& ) = default;
275  ~VolumeSparse() override = default;
276 
279 
280  protected:
288  inline Utils::optional<ValueType> getBinValue( typename IndexType::Scalar idx ) const override {
289  auto res = findBin( idx );
290  if ( res != std::end( m_data ) ) return res->value;
291  return {};
292  }
293 
300  inline void addToBin( const ValueType& value, typename IndexType::Scalar idx ) override {
301  auto res = findBin( idx );
302  if ( res != std::end( m_data ) )
303  res->value += value;
304  else
305  m_data.emplace_back( idx, value );
306  }
307 
308  inline void updateStorage() override { m_data.clear(); }
309 
310  private:
311  inline Container::iterator findBin( typename IndexType::Scalar idx ) {
312  return std::find_if( std::begin( m_data ),
313  std::end( m_data ),
314  [&idx]( const SampleType& s ) { return s.index == idx; } );
315  }
316  inline Container::const_iterator findBin( typename IndexType::Scalar idx ) const {
317  return std::find_if( std::begin( m_data ),
318  std::end( m_data ),
319  [&idx]( const SampleType& s ) { return s.index == idx; } );
320  }
321 
322  private:
323  Container m_data;
324 
325 }; // class VolumeSparse
326 
327 } // namespace Geometry
328 } // namespace Core
329 } // namespace Ra
virtual Utils::optional< ValueType > getBinValue(typename IndexType::Scalar idx) const =0
Get the bin value.
Utils::optional< ValueType > getBinValue(Eigen::Ref< const IndexType > p) const
Get the value of the given bin.
Definition: Volume.hpp:133
void setBinSize(Eigen::Ref< const Vector3 > binSize)
Set the bin size.
Definition: Volume.hpp:126
Utils::optional< typename IndexType::Scalar > linearIndex(Eigen::Ref< const IndexType > p) const
Convert the 3D position into a linear index on the bin set.
Definition: Volume.hpp:162
virtual void updateStorage()=0
Method called when size as been updated.
void setSize(Eigen::Ref< const Vector3i > size)
Definition: Volume.hpp:117
virtual void addToBin(const ValueType &value, typename IndexType::Scalar idx)=0
Add a value to the bin.
const Vector3i & size() const
return the size (number of bins ni each dimension) of the volume
Definition: Volume.hpp:115
Utils::optional< ValueType > getValue(Eigen::Ref< const Vector3 > p) const override final
Definition: Volume.hpp:142
const Vector3 & binSize() const
return the bin size
Definition: Volume.hpp:123
bool addToBin(const ValueType &value, Eigen::Ref< const IndexType > p)
Definition: Volume.hpp:150
Scalar ValueType
Type of value encoded in the volume.
Definition: Volume.hpp:44
virtual Utils::optional< ValueType > getValue(Eigen::Ref< const Vector3 > p) const =0
VolumeStorageType m_type
The type of geometry for the object.
Definition: Volume.hpp:85
void setType(const VolumeStorageType &type)
Set the type of geometry.
Definition: Volume.hpp:59
VolumeStorageType getType() const
Return the type of geometry.
Definition: Volume.hpp:55
VolumeStorageType
The type of geometry.
Definition: Volume.hpp:35
Discrete volume data storing values in a regular grid.
Definition: Volume.hpp:182
const GradientContainer & gradient() const
Direct access to the managed gradients.
Definition: Volume.hpp:222
const Container & data() const
Direct access to the managed data.
Definition: Volume.hpp:204
bool hasGradients() const
Test if gradients are defined.
Definition: Volume.hpp:216
Container & data()
Direct access, with modification allowed to the managed data.
Definition: Volume.hpp:206
void addToAllBins(const ValueType &value)
Add a value to all bins.
Definition: Volume.hpp:209
void updateStorage() override
Definition: Volume.hpp:240
Utils::optional< ValueType > getBinValue(typename IndexType::Scalar idx) const override
Definition: Volume.hpp:229
void addToBin(const ValueType &value, typename IndexType::Scalar idx) override
Definition: Volume.hpp:235
GradientContainer & gradient()
Direct access, with modification allowed to the managed gradients.
Definition: Volume.hpp:224
Utils::optional< ValueType > getBinValue(typename IndexType::Scalar idx) const override
Definition: Volume.hpp:288
void updateStorage() override
Method called when size as been updated.
Definition: Volume.hpp:308
void addToBin(const ValueType &value, typename IndexType::Scalar idx) override
Definition: Volume.hpp:300
Definition: Cage.cpp:3