Loading...
Searching...
No Matches
spherical_linearizer.h
Go to the documentation of this file.
1#ifndef _BBM_SPHERICAL_LINEARIZER_H_
2#define _BBM_SPHERICAL_LINEARIZER_H_
3
4#include "concepts/macro.h"
6
7#include "core/spherical.h"
8
9#include "bbm/config.h"
10#include "bbm/vec3dpair.h"
11
12
13/***********************************************************************/
14/* \file spherical_linearizer.h
15
16 \brief Linearize the spherical coordinates by linearizing a regular
17 sampling of (theta,phi) coordinates for both in and out.
18
19 Follows concepts/inout_linearizer.h
20************************************************************************/
21
22namespace bbm {
23
24 template<typename CONF> requires concepts::config<CONF>
26 {
28
29 /******************************************************************/
30 /*! \brief Constructor
31
32 \param samplesIn = number vec2d<size_t>(phi, theta) samples for incident directions
33 \param samplesOut = number vec2d<size_t>(phi, theta) samples for outgoing directions
34 \param startIn = start Vec2d(phi,theta) for incident directions (default 0)
35 \param endIn = end Vec2d(phi,theta) for incident directions (default HEMISPHERE)
36 \param startOut = start Vec2d(phi,theta) for outgoing directions (default 0)
37 \param endOut = end Vec2d(phi,theta) for outgoing directions (default HEMISPHERE)
38 ********************************************************************/
39 inline spherical_linearizer(const vec2d<Size_t>& samplesIn,
40 const vec2d<Size_t>& samplesOut,
41 const Vec2d& startIn = 0,
42 const Vec2d& endIn = Constants::Hemisphere(),
43 const Vec2d& startOut = 0,
44 const Vec2d& endOut = Constants::Hemisphere())
45 : _samplesIn(samplesIn), _samplesOut(samplesOut), _startIn(startIn), _endIn(endIn), _startOut(startOut), _endOut(endOut), _sizeIn(endIn - startIn), _sizeOut(endOut - startOut) { }
46
47 /********************************************************************/
48 /*! \brief Copy Constructor
49 ********************************************************************/
51
52 /*******************************************************************/
53 /*! \brief Size of the linearized 'array' of direction pairs
54 ********************************************************************/
55 Size_t size(void) const
56 {
57 return _samplesIn[0] * _samplesIn[1] * _samplesOut[0] * _samplesOut[1];
58 }
59
60 /********************************************************************/
61 /*! \brief The in-out coordinate of the idx-th sample
62
63 \param idx = index of the sample (in [0, samples()-1]
64 \returns a Ve3dPair of the in and out direction of the
65 sample. Will return {0,0} if the index is not valid.
66
67 Note: the sample direction is placed at the center of the index's bin,
68 except for the top and bottom, where it is placed at the center of the
69 top and bottom edge respectively.
70 *********************************************************************/
71 Vec3dPair operator()(Size_t idx, Mask mask=true) const
72 {
73 Vec3dPair result = {0,0};
74
75 // check bounds
76 mask &= (idx < size());
77 if(bbm::none(mask)) return result;
78
79 // compute spherical indices
80 vec2d<Size_t> in_coord, out_coord;
81 Size_t temp_idx = idx;
82
83 out_coord[1] = temp_idx % _samplesOut[1];
84 temp_idx /= _samplesOut[1];
85
86 out_coord[0] = temp_idx % _samplesOut[0];
87 temp_idx /= _samplesOut[0];
88
89 in_coord[1] = temp_idx % _samplesIn[1];
90 temp_idx /= _samplesIn[1];
91
92 in_coord[0] = temp_idx;
93
94 // compute spherical angles (include equator/end samples)
95 vec2d<Size_t> sIn( _samplesIn[0], bbm::max( _samplesIn[1] - 1, Size_t(1)) );
96 vec2d<Size_t> sOut( _samplesOut[0], bbm::max( _samplesOut[1] - 1, Size_t(1)) );
97
98 Vec2d sph_in = bbm::cast<Vec2d>(in_coord * _sizeIn / sIn) + _startIn;
99 Vec2d sph_out = bbm::cast<Vec2d>(out_coord * _sizeOut / sOut) + _startOut;
100
101 // Create Vec3dPair
102 result.in = spherical::convert(sph_in);
103 result.out = spherical::convert(sph_out);
104
105 // handle round-off errors close to zero
106 result.in = bbm::select(bbm::abs(result.in) < Constants::Epsilon(), 0, result.in);
107 result.out = bbm::select(bbm::abs(result.out) < Constants::Epsilon(), 0, result.out);
108
109 // Done.
110 return bbm::select(mask, result, Vec3dPair{0,0});
111 }
112
113 /********************************************************************/
114 /*! \brief Map a coordinate to an linear index
115
116 \param in = incident direction
117 \param out = outgoing direction
118 \returns linearized index
119
120 Invalid querries are set to 'size()'.
121 *********************************************************************/
122 Size_t operator()(const Vec3d& in, const Vec3d& out, Mask mask=true) const
123 {
124 // get normalized spherical coordinates
125 Vec2d sph_in = spherical::convert(in);
126 Vec2d sph_out = spherical::convert(out);
127
128 // check bounds
129 mask &= bbm::all((sph_in > _startIn-Constants::Epsilon()) && (sph_in < _endIn+Constants::Epsilon()) && (sph_out > _startOut-Constants::Epsilon()) && (sph_out < _endOut - Constants::Epsilon()));
130
131 // quick bail out
132 if(bbm::none(mask)) return size();
133
134 // convert to local index and clamp
135 vec2d<Size_t> in_coord = bbm::cast<vec2d<Size_t>>(bbm::clamp((sph_in - _startIn) * _samplesIn / _sizeIn, 0, _samplesIn-1));
136 vec2d<Size_t> out_coord = bbm::cast<vec2d<Size_t>>(bbm::clamp((sph_out - _startOut) * _samplesOut / _sizeOut, 0, _samplesOut-1));
137
138 // Done.
139 return cast<Size_t>(bbm::select(mask, ((in_coord[0] * _samplesIn[1] + in_coord[1]) * _samplesOut[0] + out_coord[0]) * _samplesOut[1] + out_coord[1], size()));
140 }
141
142 private:
143 ///////////////////////
144 // Class Attributes
145 ///////////////////////
146 vec2d<Size_t> _samplesIn, _samplesOut;
150 };
151
153
154} // end bbm namespace
155
156#endif /* _BBM_SPHERICAL_LINEARIZER_H_ */
All BBM methods are defined to operate on a variety of value types and spectrum types....
inout_linearizer concept
Definition: inout_linearizer.h:28
inout_linearizer contract
Macros for checking if a class meets a concept.
#define BBM_CHECK_CONCEPT(CONCEPTNAME, CLASSNAME,...)
Check a class for a concept with bbm::concepts::archetypes in the namespace.
Definition: macro.h:35
vec2d< T > convert(const vec3d< T > &v)
Definition: spherical.h:53
Definition: aggregatebsdf.h:29
constexpr auto select(MASK &&mask, const A &a, const A &b)
Definition: backbone.h:255
Methods for handling spherical coordinates.
Definition: spherical_linearizer.h:26
Vec2d _sizeIn
Definition: spherical_linearizer.h:149
Size_t size(void) const
Size of the linearized 'array' of direction pairs.
Definition: spherical_linearizer.h:55
Size_t operator()(const Vec3d &in, const Vec3d &out, Mask mask=true) const
Map a coordinate to an linear index.
Definition: spherical_linearizer.h:122
Vec2d _startIn
Definition: spherical_linearizer.h:147
spherical_linearizer(const spherical_linearizer &src)
Copy Constructor.
Definition: spherical_linearizer.h:50
vec2d< Size_t > _samplesIn
Definition: spherical_linearizer.h:146
Vec2d _startOut
Definition: spherical_linearizer.h:148
spherical_linearizer(const vec2d< Size_t > &samplesIn, const vec2d< Size_t > &samplesOut, const Vec2d &startIn=0, const Vec2d &endIn=Constants::Hemisphere(), const Vec2d &startOut=0, const Vec2d &endOut=Constants::Hemisphere())
Constructor.
Definition: spherical_linearizer.h:39
Vec2d _sizeOut
Definition: spherical_linearizer.h:149
Vec3dPair operator()(Size_t idx, Mask mask=true) const
The in-out coordinate of the idx-th sample.
Definition: spherical_linearizer.h:71
vec2d< Size_t > _samplesOut
Definition: spherical_linearizer.h:146
Vec2d _endOut
Definition: spherical_linearizer.h:148
Vec2d _endIn
Definition: spherical_linearizer.h:147
Structure to hold a pair of directions.