|
24 | 24 | * If not, see <https://opensource.org/licenses/MIT>. |
25 | 25 | */ |
26 | 26 |
|
27 | | - |
28 | | -#include <cmath> |
29 | | -#include <algorithm> |
30 | | -#include "constants.hpp" |
31 | 27 | #include "room.hpp" |
| 28 | +#include "constants.hpp" |
| 29 | +#include <algorithm> |
| 30 | +#include <cmath> |
32 | 31 |
|
33 | 32 | size_t number_image_sources_2(size_t max_order) { |
34 | 33 | /* |
@@ -104,6 +103,29 @@ Room<D>::Room(const Vectorf<D> &_room_size, |
104 | 103 | init(); |
105 | 104 | } |
106 | 105 |
|
| 106 | +template <size_t D> |
| 107 | +Room<D>::Room(const std::vector<Wall<D>> &_walls, |
| 108 | + const std::vector<int> &_obstructing_walls, |
| 109 | + const Eigen::MatrixXf &_V, const Eigen::MatrixXi &_F, |
| 110 | + const std::vector<int> &_face_to_wall, |
| 111 | + const std::vector<Microphone<D>> &_microphones, |
| 112 | + float _sound_speed, int _ism_order, float _energy_thres, |
| 113 | + float _time_thres, float _mic_radius, float _mic_hist_res, |
| 114 | + bool _is_hybrid_sim) |
| 115 | + : walls(_walls), obstructing_walls(_obstructing_walls), |
| 116 | + microphones(_microphones), V_mesh(_V), F_mesh(_F), |
| 117 | + face_to_wall(_face_to_wall), sound_speed(_sound_speed), |
| 118 | + ism_order(_ism_order), energy_thres(_energy_thres), |
| 119 | + time_thres(_time_thres), mic_radius(_mic_radius), |
| 120 | + mic_radius_sq(_mic_radius * _mic_radius), mic_hist_res(_mic_hist_res), |
| 121 | + is_hybrid_sim(_is_hybrid_sim), is_shoebox(false) { |
| 122 | + init(); |
| 123 | + // Initialize AABB tree if mesh is provided |
| 124 | + if (F_mesh.rows() > 0) { |
| 125 | + mesh_aabb.init(V_mesh, F_mesh); |
| 126 | + } |
| 127 | +} |
| 128 | + |
107 | 129 | template <> |
108 | 130 | void Room<2>::make_shoebox_walls( |
109 | 131 | const Vectorf<2> &rs, // room_size |
@@ -669,6 +691,28 @@ std::tuple<Vectorf<D>, int, float> Room<D>::next_wall_hit( |
669 | 691 | (void)0; // no op |
670 | 692 | } |
671 | 693 | } else { |
| 694 | + if constexpr (D == 3) { |
| 695 | + if (F_mesh.rows() > 0 && !scattered_ray) { |
| 696 | + // Use libigl AABB tree for 3D ray tracing (non-scattered) |
| 697 | + igl::Hit<float> hit; |
| 698 | + Vectorf<3> _start = start.template cast<float>(); |
| 699 | + Vectorf<3> _end = end.template cast<float>(); |
| 700 | + Vectorf<3> _dir = (_end - _start).normalized(); |
| 701 | + // Offset start to avoid hitting the same wall |
| 702 | + Vectorf<3> _start_offset = _start + 1e-4f * _dir; |
| 703 | + if (mesh_aabb.intersect_ray(V_mesh, F_mesh, _start_offset, _dir, hit)) { |
| 704 | + // hit.t is the distance to the hit point from _start_offset |
| 705 | + float actual_t = hit.t + 1e-4f; |
| 706 | + if (actual_t < hit_dist) { |
| 707 | + hit_dist = actual_t; |
| 708 | + result = start + actual_t * _dir.template cast<float>(); |
| 709 | + next_wall_index = face_to_wall[hit.id]; |
| 710 | + } |
| 711 | + } |
| 712 | + return std::make_tuple(result, next_wall_index, hit_dist); |
| 713 | + } |
| 714 | + } |
| 715 | + |
672 | 716 | // For case 1) in non-convex rooms, the segment might intersect several |
673 | 717 | // walls. In this case, we are only interested on the closest wall to |
674 | 718 | // 'start'. That's why we need a min_dist variable |
@@ -696,7 +740,7 @@ std::tuple<Vectorf<D>, int, float> Room<D>::next_wall_hit( |
696 | 740 | if (temp_dist > libroom_eps && temp_dist < hit_dist) { |
697 | 741 | hit_dist = temp_dist; |
698 | 742 | result = temp_hit; |
699 | | - next_wall_index = i; |
| 743 | + next_wall_index = scattered_ray ? obstructing_walls[i] : i; |
700 | 744 | } |
701 | 745 | } |
702 | 746 | } |
@@ -1131,4 +1175,3 @@ bool Room<D>::contains(const Vectorf<D> point) { |
1131 | 1175 | // then the point is in the room => return true |
1132 | 1176 | return ((n_intersections % 2) == 1); |
1133 | 1177 | } |
1134 | | - |
|
0 commit comments