Wayverb
fast_pressure_calculator.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "raytracer/cl/structs.h"
4 
5 #include "core/conversions.h"
6 #include "core/scene_data.h"
7 #include "core/surfaces.h"
8 #include "core/unit_constructor.h"
9 
10 #include "utilities/aligned/vector.h"
11 #include "utilities/map_to_vector.h"
12 
19 
20 namespace wayverb {
21 namespace raytracer {
22 namespace image_source {
23 
24 struct reflection_metadata final {
25  cl_uint surface_index;
26  float cos_angle;
27 };
28 
30 
31 template <typename Channels, typename It>
32 auto compute_fast_pressure(const glm::vec3& receiver,
33  const util::aligned::vector<Channels>& impedance,
34  const util::aligned::vector<Channels>& scattering,
35  bool flip_phase,
36  const glm::vec3& image_source,
37  It begin,
38  It end) {
39  constexpr auto channels = ::detail::components_v<Channels>;
40 
41  const auto surface_attenuation = std::accumulate(
42  begin,
43  end,
44  core::unit_constructor_v<
45  ::detail::cl_vector_constructor_t<float, channels>>,
46  [&](auto i, auto j) {
47  const auto surface_impedance = impedance[j.surface_index];
48  const auto surface_scattering = scattering[j.surface_index];
49 
50  const auto reflectance =
51  core::average_wall_impedance_to_pressure_reflectance(
52  surface_impedance, j.cos_angle);
53  const auto outgoing = core::specular_pressure(
54  i * reflectance, surface_scattering);
55 
56  return outgoing * (flip_phase ? -1 : 1);
57  });
58 
59  return impulse<channels>{surface_attenuation,
60  core::to_cl_float3{}(image_source),
61  glm::distance(image_source, receiver)};
62 }
63 
68 template <typename multichannel_type>
70 public:
71  template <typename It>
72  fast_pressure_calculator(It b_surfaces,
73  It e_surfaces,
74  const glm::vec3& receiver,
75  bool flip_phase)
76  : receiver_{receiver}
77  , surface_impedances_{util::map_to_vector(
78  b_surfaces,
79  e_surfaces,
80  [](const auto& surface) {
81  return core::
82  pressure_reflectance_to_average_wall_impedance(
83  core::absorption_to_pressure_reflectance(
84  surface.absorption));
85  })}
86  , surface_scattering_{util::map_to_vector(
87  b_surfaces,
88  e_surfaces,
89  [](const auto& surface) { return surface.scattering; })}
90  , flip_phase_{flip_phase} {}
91 
92  using return_type = decltype(compute_fast_pressure(
93  std::declval<glm::vec3>(),
94  std::declval<util::aligned::vector<multichannel_type>>(),
95  std::declval<util::aligned::vector<multichannel_type>>(),
96  std::declval<bool>(),
97  std::declval<glm::vec3>(),
98  std::declval<const reflection_metadata*>(),
99  std::declval<const reflection_metadata*>()));
100 
101  template <typename It>
102  return_type operator()(const glm::vec3& image_source,
103  It begin,
104  It end) const {
105  return compute_fast_pressure(receiver_,
106  surface_impedances_,
107  surface_scattering_,
108  flip_phase_,
109  image_source,
110  begin,
111  end);
112  }
113 
114 private:
115  glm::vec3 receiver_;
116  util::aligned::vector<multichannel_type> surface_impedances_;
117  util::aligned::vector<multichannel_type> surface_scattering_;
118  bool flip_phase_;
119 };
120 
121 template <typename It>
122 constexpr auto make_fast_pressure_calculator(It b_surfaces,
123  It e_surfaces,
124  const glm::vec3& receiver,
125  bool flip_phase) {
126  using multichannel_type =
127  std::decay_t<decltype(std::declval<It>()->absorption)>;
129  std::move(b_surfaces), std::move(e_surfaces), receiver, flip_phase};
130 }
131 
132 } // namespace image_source
133 } // namespace raytracer
134 } // namespace wayverb
Definition: fast_pressure_calculator.h:69
Definition: conversions.h:10
float cos_angle
The index of the triangle that was intersected.
Definition: fast_pressure_calculator.h:26
Definition: structs.h:38
Definition: pressure.h:22
Definition: capsule_base.h:9
Definition: fast_pressure_calculator.h:24