3 #include "raytracer/optimum_reflection_number.h" 4 #include "raytracer/reflector.h" 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" 15 #include "raytracer/reflection_processor/image_source.h" 16 #include "raytracer/reflection_processor/stochastic_histogram.h" 17 #include "raytracer/reflection_processor/visual.h" 19 #include "utilities/apply.h" 20 #include "utilities/map.h" 22 #include <experimental/optional> 28 #define FUNCTOR_ADAPTER(name) \ 29 template <typename T> \ 30 class name##_functor_adapter { \ 32 explicit name##_functor_adapter(T& t) \ 35 template <typename... Ts> \ 36 constexpr auto operator()(Ts&&... ts) { \ 37 return t_.name(std::forward<Ts>(ts)...); \ 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}; \ 51 FUNCTOR_ADAPTER(process)
52 FUNCTOR_ADAPTER(get_processor)
53 FUNCTOR_ADAPTER(get_results)
54 FUNCTOR_ADAPTER(accumulate)
55 FUNCTOR_ADAPTER(get_group_processor)
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)...};
65 template <
typename A,
typename B>
66 void zip_apply(A&& a, B&& b) {
67 zip_apply(std::forward<A>(a),
69 std::make_index_sequence<std::tuple_size<A>{}>{});
76 template <
typename Engine>
83 using value_type = glm::vec3;
84 using difference_type = std::ptrdiff_t;
85 using pointer = glm::vec3*;
86 using reference = glm::vec3&;
102 value_type operator*()
const {
return core::random_unit_vector(*engine_); }
123 difference_type n)
const {
129 difference_type n)
const {
146 constexpr difference_type operator-(
148 return pos_ - rhs.pos_;
152 return pos_ == rhs.pos_;
156 return !operator==(rhs);
160 return pos_ < rhs.pos_;
163 return pos_ <= rhs.pos_;
166 return pos_ > rhs.pos_;
169 return pos_ >= rhs.pos_;
174 Engine* engine_ =
nullptr;
175 difference_type pos_ = 0;
178 template <
typename Engine>
179 constexpr
auto make_random_direction_generator_iterator(
180 typename random_direction_generator_iterator<Engine>::difference_type
188 template <
typename It,
typename PerStepCallback,
typename Callbacks>
196 const glm::vec3& source,
197 const glm::vec3& receiver,
199 const std::atomic_bool& keep_going,
200 PerStepCallback&& per_step_callback,
201 Callbacks&& callbacks) {
204 const auto make_ray_iterator = [&](
auto it) {
205 return util::make_mapping_iterator_adapter(
206 std::move(it), [&](
const auto& i) {
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));
216 using return_type = decltype(util::apply_each(
217 util::map(make_get_results_functor_adapter{}, processors)));
219 constexpr
auto segment_size = 1 << 14;
220 const auto reflection_depth =
221 compute_optimum_reflection_number(voxelised.get_scene_data());
223 const auto run_segment = [&](
auto b,
auto e) {
224 const auto num_directions = std::distance(b, e);
226 reflector ref{cc, receiver, make_ray_iterator(b), make_ray_iterator(e)};
228 auto group_processors = util::apply_each(
229 util::map(make_get_group_processor_functor_adapter{},
231 std::make_tuple(num_directions));
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);
238 util::map(make_process_functor_adapter{}, group_processors),
239 std::tie(b, e, buffers, i, reflection_depth));
242 zip_apply(util::map(make_accumulate_functor_adapter{}, processors),
246 const auto groups = std::distance(b_direction, e_direction) / segment_size;
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);
253 per_step_callback(group, groups);
256 return std::experimental::optional<return_type>{};
260 if (it != e_direction) {
261 run_segment(it, e_direction);
264 return std::experimental::make_optional(util::apply_each(
265 util::map(make_get_results_functor_adapter{}, processors)));
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: raytracer.h:77
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