Radium Engine  1.5.20
Loading...
Searching...
No Matches
Tex.hpp
1#pragma once
2
3#include <Core/Containers/Grid.hpp>
4#include <Core/Math/LinearAlgebra.hpp>
5#include <Core/RaCore.hpp>
6#include <Core/Types.hpp>
7
8#include <Eigen/Core>
9
10namespace Ra {
11namespace Core {
15template <typename T, uint N>
16class Tex : public Grid<T, N>
17{
18
19 public:
20 using IdxVector = typename Grid<T, N>::IdxVector;
21 using Vector = Eigen::Matrix<Scalar, N, 1>;
22 using AabbND = Eigen::AlignedBox<Scalar, N>;
23
25 Tex( const IdxVector& resolution, const Vector& start, const Vector& end );
26
28 Tex( const IdxVector& resolution, const AabbND& aabb );
29
31 Tex( const Tex& other ) = default;
32 Tex& operator=( const Tex& other ) = default;
33
34 inline const AabbND& getAabb() const;
35
37 T fetch( const Vector& v ) const;
38
39 private:
41 AabbND m_aabb;
44 Vector m_cellSize;
45};
46
47template <typename T>
48using Tex2D = Tex<T, 2>;
49
50template <typename T>
51using Tex3D = Tex<T, 3>;
52
53// Helper functions
54namespace {
55// This is a helper class for the texture fetch implementation. This interpolate linear
56// interpolation from values at a corner of a grid.
57template <uint N>
58struct NLinearInterpolator {
59 template <typename T>
60 static T interpolate(
61 const Grid<T, N>& grid, // grid from which values are read
62 const typename Tex<T, N>::Vector& fact, // factors of the interpolation (between 0 and 1)
63 const typename Tex<T, N>::IdxVector& size, // size of the dual grid
64 const typename Tex<T, N>::IdxVector& clamped_nearest ) // base indices of the cell
65 {
66 CORE_ERROR( "N-linear interpolation not implemented for N= " << N );
67 return T();
68 }
69};
70
71template <>
72struct NLinearInterpolator<2> {
73 // bilinear interpolation in a quad cell
74 template <typename T>
75 static T interpolate( const Grid<T, 2>& grid,
76 const Vector2& fact,
77 const Vector2ui& size,
78 const Vector2ui& clamped_nearest ) {
79 const uint i0 = clamped_nearest[0];
80 const uint j0 = clamped_nearest[1];
81
82 const uint i1 = i0 < size[0] ? i0 + 1 : i0;
83 const uint j1 = j0 < size[1] ? j0 + 1 : j0;
84
85 const T v00 = grid.at( { i0, j0 } );
86 const T v01 = grid.at( { i0, j1 } );
87 const T v10 = grid.at( { i1, j0 } );
88 const T v11 = grid.at( { i1, j1 } );
89
90 const T c0 = v00 * ( 1.0 - fact[0] ) + v10 * fact[0];
91 const T c1 = v01 * ( 1.0 - fact[0] ) + v11 * fact[0];
92
93 return c0 * ( 1.0 - fact[1] ) + c1 * fact[1];
94 }
95};
96
97template <>
98struct NLinearInterpolator<3> {
99 // tri-linear interpolation in a cubic cell
100 template <typename T>
101 static T interpolate( const Grid<T, 3>& grid,
102 const Vector3& fact,
103 const Vector3ui& size,
104 const Vector3ui& clamped_nearest ) {
105 const uint i0 = clamped_nearest[0];
106 const uint j0 = clamped_nearest[1];
107 const uint k0 = clamped_nearest[2];
108 const uint i1 = i0 < size[0] ? i0 + 1 : i0;
109 const uint j1 = j0 < size[1] ? j0 + 1 : j0;
110 const uint k1 = k0 < size[2] ? k0 + 1 : k0;
111
112 const T v000 = grid.at( { i0, j0, k0 } );
113 const T v001 = grid.at( { i0, j0, k1 } );
114 const T v010 = grid.at( { i0, j1, k0 } );
115 const T v011 = grid.at( { i0, j1, k1 } );
116 const T v100 = grid.at( { i1, j0, k0 } );
117 const T v101 = grid.at( { i1, j0, k1 } );
118 const T v110 = grid.at( { i1, j1, k0 } );
119 const T v111 = grid.at( { i1, j1, k1 } );
120
121 const T c00 = v000 * ( 1.0 - fact[0] ) + v100 * fact[0];
122 const T c10 = v010 * ( 1.0 - fact[0] ) + v110 * fact[0];
123 const T c01 = v001 * ( 1.0 - fact[0] ) + v101 * fact[0];
124 const T c11 = v011 * ( 1.0 - fact[0] ) + v111 * fact[0];
125
126 const T c0 = c00 * ( 1.0 - fact[1] ) + c10 * fact[1];
127 const T c1 = c01 * ( 1.0 - fact[1] ) + c11 * fact[1];
128
129 return c0 * ( 1.0 - fact[2] ) + c1 * fact[2];
130 }
131};
132} // namespace
133
134template <typename T, uint N>
135Tex<T, N>::Tex( const IdxVector& resolution, const Vector& start, const Vector& end ) :
136 Grid<T, N>( resolution ), m_aabb( start, end ) {
137 const Vector quotient = ( resolution - IdxVector::Ones() ).template cast<Scalar>();
138 m_cellSize = m_aabb.sizes().cwiseQuotient( quotient );
139}
140
141template <typename T, uint N>
142Tex<T, N>::Tex( const IdxVector& resolution, const AabbND& aabb ) :
143 Grid<T, N>( resolution ), m_aabb( aabb ) {
144 const Vector quotient = ( resolution - IdxVector::Ones() ).template cast<Scalar>();
145 m_cellSize = m_aabb.sizes().cwiseQuotient( quotient );
146}
147
148template <typename T, uint N>
149inline const typename Tex<T, N>::AabbND& Tex<T, N>::getAabb() const {
150 return m_aabb;
151}
152
153template <typename T, uint N>
154inline T Tex<T, N>::fetch( const Vector& v ) const {
155 Vector scaled_coords( ( v - m_aabb.min() ).cwiseQuotient( m_cellSize ) );
156 // Sometimes due to float imprecision, a value of 0 is passed as -1e7
157 // which floors incorrectly rounds down to -1, hence the use of trunc().
158 Vector tmp = Ra::Core::Math::trunc( scaled_coords );
159 CORE_ASSERT( !( ( tmp.array() < Vector::Zero().array() ).any() ), "Cannot cast to uint" );
160 IdxVector nearest = tmp.template cast<uint>();
161 Vector fact = scaled_coords - tmp;
162
163 // TODO: Give other texture behaviour (such as wrapping) ?
164
165 IdxVector size =
166 this->sizeVector() - IdxVector::Ones(); // TODO check this code on borders of the grid
167 IdxVector clamped_nearest =
168 Ra::Core::Math::clamp<IdxVector>( nearest, IdxVector::Zero(), size );
169
170 return NLinearInterpolator<N>::interpolate( *this, fact, size, clamped_nearest );
171}
172} // namespace Core
173} // namespace Ra
Eigen::Matrix< uint, D, 1 > IdxVector
Dimension of our grid.
Definition Grid.hpp:23
Tex(const IdxVector &resolution, const Vector &start, const Vector &end)
Construct a Tex with the given resolution in the box given by two points.
Definition Tex.hpp:135
T fetch(const Vector &v) const
Tri-linear interpolation of the grid values at position v.
Definition Tex.hpp:154
Tex(const Tex &other)=default
Copy constructor and assignment operator perform a deep copy.
Vector trunc(const Vector &v)
Component-wise trunc() function on a floating-point vector.
Derived::PlainMatrix clamp(const Eigen::MatrixBase< Derived > &v, const Eigen::MatrixBase< DerivedA > &min, const Eigen::MatrixBase< DerivedB > &max)
Component-wise clamp() function on a floating-point vector.
hepler function to manage enum as underlying types in VariableSet
Definition Cage.cpp:3