Wayverb
raytracer.h
1 #pragma once
2 
3 #include "raytracer/optimum_reflection_number.h"
4 #include "raytracer/reflector.h"
5 
6 #include "core/azimuth_elevation.h"
7 #include "core/cl/common.h"
8 #include "core/cl/geometry.h"
9 #include "core/environment.h"
10 #include "core/nan_checking.h"
11 #include "core/pressure_intensity.h"
12 #include "core/spatial_division/scene_buffers.h"
13 #include "core/spatial_division/voxelised_scene_data.h"
14 
15 #include "raytracer/reflection_processor/image_source.h"
16 #include "raytracer/reflection_processor/stochastic_histogram.h"
17 #include "raytracer/reflection_processor/visual.h"
18 
19 #include "utilities/apply.h"
20 #include "utilities/map.h"
21 
22 #include <experimental/optional>
23 #include <iostream>
24 
25 namespace wayverb {
26 namespace raytracer {
27 
28 #define FUNCTOR_ADAPTER(name) \
29  template <typename T> \
30  class name##_functor_adapter { \
31  public: \
32  explicit name##_functor_adapter(T& t) \
33  : t_{t} {} \
34  \
35  template <typename... Ts> \
36  constexpr auto operator()(Ts&&... ts) { \
37  return t_.name(std::forward<Ts>(ts)...); \
38  } \
39  \
40  private: \
41  T& t_; \
42  }; \
43  \
44  struct make_##name##_functor_adapter final { \
45  template <typename T> \
46  constexpr auto operator()(T& t) const { \
47  return name##_functor_adapter<T>{t}; \
48  } \
49  };
50 
51 FUNCTOR_ADAPTER(process)
52 FUNCTOR_ADAPTER(get_processor)
53 FUNCTOR_ADAPTER(get_results)
54 FUNCTOR_ADAPTER(accumulate)
55 FUNCTOR_ADAPTER(get_group_processor)
56 
58 
59 template <typename A, typename B, size_t... Ix>
60 void zip_apply(A&& a, B&& b, std::index_sequence<Ix...>) {
61  (void)std::initializer_list<int>{
62  ((void)(std::get<Ix>(a)(std::get<Ix>(b))), 0)...};
63 }
64 
65 template <typename A, typename B>
66 void zip_apply(A&& a, B&& b) {
67  zip_apply(std::forward<A>(a),
68  std::forward<B>(b),
69  std::make_index_sequence<std::tuple_size<A>{}>{});
70 }
71 
73 
76 template <typename Engine>
78 public:
82  using iterator_category = std::random_access_iterator_tag;
83  using value_type = glm::vec3;
84  using difference_type = std::ptrdiff_t;
85  using pointer = glm::vec3*;
86  using reference = glm::vec3&;
87 
88  constexpr explicit random_direction_generator_iterator(difference_type pos,
89  Engine& engine)
90  : engine_{&engine}
91  , pos_{pos} {}
92 
94  const random_direction_generator_iterator&) = default;
96  random_direction_generator_iterator&&) noexcept = default;
97  constexpr random_direction_generator_iterator& operator=(
98  const random_direction_generator_iterator&) = default;
99  constexpr random_direction_generator_iterator& operator=(
100  random_direction_generator_iterator&&) noexcept = default;
101 
102  value_type operator*() const { return core::random_unit_vector(*engine_); }
103 
104  constexpr random_direction_generator_iterator& operator++() {
105  ++pos_;
106  return *this;
107  }
108 
109  constexpr random_direction_generator_iterator& operator--() {
110  --pos_;
111  return *this;
112  }
113 
114  constexpr random_direction_generator_iterator operator++(int) {
116  }
117 
118  constexpr random_direction_generator_iterator operator--(int) {
120  }
121 
122  constexpr random_direction_generator_iterator operator+(
123  difference_type n) const {
124  auto ret = *this;
125  return ret += n;
126  }
127 
128  constexpr random_direction_generator_iterator operator-(
129  difference_type n) const {
130  auto ret = *this;
131  return ret -= n;
132  }
133 
134  constexpr random_direction_generator_iterator& operator+=(
135  difference_type n) {
136  pos_ += n;
137  return *this;
138  }
139 
140  constexpr random_direction_generator_iterator& operator-=(
141  difference_type n) {
142  pos_ -= n;
143  return *this;
144  }
145 
146  constexpr difference_type operator-(
148  return pos_ - rhs.pos_;
149  }
150 
151  constexpr bool operator==(const random_direction_generator_iterator& rhs) {
152  return pos_ == rhs.pos_;
153  }
154 
155  constexpr bool operator!=(const random_direction_generator_iterator& rhs) {
156  return !operator==(rhs);
157  }
158 
159  constexpr bool operator<(const random_direction_generator_iterator& rhs) {
160  return pos_ < rhs.pos_;
161  }
162  constexpr bool operator<=(const random_direction_generator_iterator& rhs) {
163  return pos_ <= rhs.pos_;
164  }
165  constexpr bool operator>(const random_direction_generator_iterator& rhs) {
166  return pos_ > rhs.pos_;
167  }
168  constexpr bool operator>=(const random_direction_generator_iterator& rhs) {
169  return pos_ >= rhs.pos_;
170  }
171 
172 private:
174  Engine* engine_ = nullptr;
175  difference_type pos_ = 0;
176 };
177 
178 template <typename Engine>
179 constexpr auto make_random_direction_generator_iterator(
180  typename random_direction_generator_iterator<Engine>::difference_type
181  pos,
182  Engine& engine) {
184 }
185 
187 
188 template <typename It, typename PerStepCallback, typename Callbacks>
189 auto run(
190  It b_direction,
191  It e_direction,
192  const core::compute_context& cc,
193  const core::voxelised_scene_data<cl_float3,
195  voxelised,
196  const glm::vec3& source,
197  const glm::vec3& receiver,
198  const core::environment& environment,
199  const std::atomic_bool& keep_going,
200  PerStepCallback&& per_step_callback,
201  Callbacks&& callbacks) {
202  const core::scene_buffers buffers{cc.context, voxelised};
203 
204  const auto make_ray_iterator = [&](auto it) {
205  return util::make_mapping_iterator_adapter(
206  std::move(it), [&](const auto& i) {
207  return core::geo::ray{source, i};
208  });
209  };
210 
211  auto processors = util::apply_each(
212  util::map(make_get_processor_functor_adapter{},
213  std::forward<Callbacks>(callbacks)),
214  std::tie(cc, source, receiver, environment, voxelised));
215 
216  using return_type = decltype(util::apply_each(
217  util::map(make_get_results_functor_adapter{}, processors)));
218 
219  constexpr auto segment_size = 1 << 14;
220  const auto reflection_depth =
221  compute_optimum_reflection_number(voxelised.get_scene_data());
222 
223  const auto run_segment = [&](auto b, auto e) {
224  const auto num_directions = std::distance(b, e);
225 
226  reflector ref{cc, receiver, make_ray_iterator(b), make_ray_iterator(e)};
227 
228  auto group_processors = util::apply_each(
229  util::map(make_get_group_processor_functor_adapter{},
230  processors),
231  std::make_tuple(num_directions));
232 
233  for (auto i = 0ul; i != reflection_depth; ++i) {
234  const auto reflections = ref.run_step(buffers);
235  const auto b = begin(reflections);
236  const auto e = end(reflections);
237  util::call_each(
238  util::map(make_process_functor_adapter{}, group_processors),
239  std::tie(b, e, buffers, i, reflection_depth));
240  }
241 
242  zip_apply(util::map(make_accumulate_functor_adapter{}, processors),
243  group_processors);
244  };
245 
246  const auto groups = std::distance(b_direction, e_direction) / segment_size;
247 
248  auto it = b_direction;
249  for (auto group = 0; it + segment_size <= e_direction;
250  it += segment_size, ++group) {
251  run_segment(it, it + segment_size);
252 
253  per_step_callback(group, groups);
254 
255  if (!keep_going) {
256  return std::experimental::optional<return_type>{};
257  }
258  }
259 
260  if (it != e_direction) {
261  run_segment(it, e_direction);
262  }
263 
264  return std::experimental::make_optional(util::apply_each(
265  util::map(make_get_results_functor_adapter{}, processors)));
266 }
267 
268 } // namespace raytracer
269 } // namespace wayverb
I would do this with a struct, but rays have an invariant:
Definition: geometric.h:19
Definition: reflector.h:25
Definition: scene_buffers.h:12
Definition: pressure.h:22
Definition: environment.h:6
Definition: capsule_base.h:9
std::random_access_iterator_tag iterator_category
Definition: raytracer.h:82
invariant: device is a valid device for the context
Definition: common.h:13
Definition: voxelised_scene_data.h:14