14#include <embree3/rtcore.h>
15#include <embree3/rtcore_geometry.h>
16#include <embree3/rtcore_ray.h>
17#include <lagrange/common.h>
18#include <lagrange/raycasting/ClosestPointResult.h>
19#include <lagrange/raycasting/EmbreeHelper.h>
20#include <lagrange/raycasting/RayCasterMesh.h>
21#include <lagrange/raycasting/embree_closest_point.h>
22#include <lagrange/utils/safe_cast.h>
45template <
typename ScalarType>
49 using Scalar = ScalarType;
50 using Transform = Eigen::Matrix<Scalar, 4, 4>;
51 using Point = Eigen::Matrix<Scalar, 3, 1>;
52 using Direction = Eigen::Matrix<Scalar, 3, 1>;
55 using TransformVector = std::vector<Transform>;
57 using Point4 = Eigen::Matrix<Scalar, 4, 3>;
58 using Direction4 = Eigen::Matrix<Scalar, 4, 3>;
59 using Index4 = Eigen::Matrix<size_t, 4, 1>;
60 using Scalar4 = Eigen::Matrix<Scalar, 4, 1>;
61 using Mask4 = Eigen::Matrix<std::int32_t, 4, 1>;
63 using FloatData = std::vector<float>;
64 using IntData = std::vector<unsigned>;
82 const Index* mesh_index,
83 const Index* instance_index,
84 const RTCFilterFunctionNArguments* args)>;
88 enum { FILTER_INTERSECT = 0, FILTER_OCCLUDED = 1 };
93 RTCSceneFlags scene_flags = RTC_SCENE_FLAG_DYNAMIC,
94 RTCBuildQuality build_quality = RTC_BUILD_QUALITY_LOW)
100#ifdef _MM_SET_FLUSH_ZERO_MODE
101 _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
103#ifdef _MM_SET_DENORMALS_ZERO_MODE
104 _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
107 m_scene_flags = scene_flags;
108 m_build_quality = build_quality;
109 m_device = rtcNewDevice(NULL);
110 ensure_no_errors_internal();
111 m_embree_world_scene = rtcNewScene(m_device);
112 ensure_no_errors_internal();
113 m_instance_index_ranges.push_back(safe_cast<Index>(0));
115 m_need_rebuild =
true;
116 m_need_commit =
false;
123 rtcReleaseDevice(m_device);
133 return safe_cast<Index>(m_meshes.size());
139 return m_instance_index_ranges.back();
145 la_debug_assert(mesh_index + 1 < safe_cast<Index>(m_instance_index_ranges.size()));
146 return safe_cast<Index>(
147 m_instance_index_ranges[mesh_index + 1] - m_instance_index_ranges[mesh_index]);
154 template <
typename MeshType>
155 std::shared_ptr<MeshType>
get_mesh(Index index)
const
173 return m_instance_to_user_mesh[cumulative_instance_index];
182 template <
typename MeshType>
184 std::shared_ptr<MeshType> mesh,
185 const Transform& trans = Transform::Identity(),
186 RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM)
200 template <
typename MeshType>
202 std::shared_ptr<MeshType> mesh,
203 const TransformVector& trans_vector,
204 RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM)
207 m_transforms.insert(m_transforms.end(), trans_vector.begin(), trans_vector.end());
208 m_mesh_build_qualities.push_back(build_quality);
209 m_visibility.resize(m_visibility.size() + trans_vector.size(),
true);
210 for (
auto& f : m_filters) {
211 f.push_back(
nullptr);
213 Index mesh_index = safe_cast<Index>(m_meshes.size() - 1);
215 Index instance_index = m_instance_index_ranges.back();
216 la_runtime_assert(instance_index == safe_cast<Index>(m_instance_to_user_mesh.size()));
217 Index new_instance_size = instance_index + trans_vector.size();
218 m_instance_index_ranges.push_back(new_instance_size);
219 m_instance_to_user_mesh.resize(new_instance_size, mesh_index);
220 m_need_rebuild =
true;
230 template <
typename MeshType>
233 std::shared_ptr<MeshType> mesh,
234 RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM)
236 update_raycasting_mesh(
250 if (m_need_rebuild)
return;
253 auto geom = rtcGetGeometry(m_embree_mesh_scenes[index], 0);
256 auto const& mesh = m_meshes[index];
258 safe_cast<Index>(mesh->get_num_vertices()) == m_mesh_vertex_counts[index]);
261 reinterpret_cast<float*
>(rtcGetGeometryBufferData(geom, RTC_BUFFER_TYPE_VERTEX, 0));
263 mesh->vertices_to_float(vbuf);
264 rtcUpdateGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, 0);
267 rtcCommitGeometry(geom);
268 rtcCommitScene(m_embree_mesh_scenes[index]);
271 for (Index instance_index = m_instance_index_ranges[index];
272 instance_index < m_instance_index_ranges[index + 1];
274 Index rtc_inst_id = m_instance_index_ranges[index] + instance_index;
276 rtcGetGeometry(m_embree_world_scene,
static_cast<unsigned>(rtc_inst_id));
277 rtcCommitGeometry(geom_inst);
281 m_need_commit =
true;
287 la_runtime_assert(mesh_index + 1 < safe_cast<Index>(m_instance_index_ranges.size()));
288 Index index = m_instance_index_ranges[mesh_index] + instance_index;
291 return m_transforms[index];
297 la_runtime_assert(mesh_index + 1 < safe_cast<Index>(m_instance_index_ranges.size()));
298 Index index = m_instance_index_ranges[mesh_index] + instance_index;
301 m_transforms[index] = trans;
302 if (!m_need_rebuild) {
303 auto geom = rtcGetGeometry(m_embree_world_scene,
static_cast<unsigned>(index));
304 Eigen::Matrix<float, 4, 4> T = trans.template cast<float>();
305 rtcSetGeometryTransform(geom, 0, RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR, T.eval().data());
306 rtcCommitGeometry(geom);
307 m_need_commit =
true;
314 la_runtime_assert(mesh_index + 1 < safe_cast<Index>(m_instance_index_ranges.size()));
315 Index index = m_instance_index_ranges[mesh_index] + instance_index;
318 return m_visibility[index];
324 la_runtime_assert(mesh_index + 1 < safe_cast<Index>(m_instance_index_ranges.size()));
325 Index index = m_instance_index_ranges[mesh_index] + instance_index;
328 m_visibility[index] = visible;
329 if (!m_need_rebuild &&
330 rtcGetDeviceProperty(m_device, RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED)) {
333 auto geom = rtcGetGeometry(m_embree_world_scene,
static_cast<unsigned>(index));
334 rtcSetGeometryMask(geom, visible ? 0xFFFFFFFF : 0x00000000);
335 rtcCommitGeometry(geom);
336 m_need_commit =
true;
359 m_filters[FILTER_INTERSECT][mesh_index] = filter;
360 m_need_rebuild =
true;
372 return m_filters[FILTER_INTERSECT][mesh_index];
394 m_filters[FILTER_OCCLUDED][mesh_index] = filter;
395 m_need_rebuild =
true;
407 return m_filters[FILTER_OCCLUDED][mesh_index];
419 if (!m_need_commit)
return;
421 rtcCommitScene(m_embree_world_scene);
422 m_need_commit =
false;
428 EmbreeHelper::ensure_no_errors(m_device);
437 const Point4& origin,
438 const Direction4& direction,
441 Index4& instance_index,
444 Point4& barycentric_coord,
446 const Scalar4& tmin = Scalar4::Zero(),
447 const Scalar4& tmax = Scalar4::Constant(std::numeric_limits<Scalar>::infinity()))
453 RTCRayHit4 embree_raypacket;
454 for (
int i = 0; i < static_cast<int>(batch_size); ++i) {
456 embree_raypacket.ray.org_x[i] =
static_cast<float>(origin(i, 0));
457 embree_raypacket.ray.org_y[i] =
static_cast<float>(origin(i, 1));
458 embree_raypacket.ray.org_z[i] =
static_cast<float>(origin(i, 2));
461 embree_raypacket.ray.dir_x[i] =
static_cast<float>(direction(i, 0));
462 embree_raypacket.ray.dir_y[i] =
static_cast<float>(direction(i, 1));
463 embree_raypacket.ray.dir_z[i] =
static_cast<float>(direction(i, 2));
466 embree_raypacket.ray.tnear[i] =
static_cast<float>(tmin[i]);
467 embree_raypacket.ray.tfar[i] = std::isinf(tmax[i]) ? std::numeric_limits<float>::max()
468 :
static_cast<float>(tmax[i]);
469 embree_raypacket.ray.mask[i] = 0xFFFFFFFF;
470 embree_raypacket.ray.id[i] =
static_cast<unsigned>(i);
471 embree_raypacket.ray.flags[i] = 0;
474 embree_raypacket.hit.geomID[i] = RTC_INVALID_GEOMETRY_ID;
475 embree_raypacket.hit.primID[i] = RTC_INVALID_GEOMETRY_ID;
476 embree_raypacket.hit.instID[0][i] = RTC_INVALID_GEOMETRY_ID;
480 auto packet_mask = mask;
481 for (
int i =
static_cast<int>(batch_size); i < 4; ++i) packet_mask[i] = 0;
483 ensure_no_errors_internal();
485 RTCIntersectContext context;
486 rtcInitIntersectContext(&context);
487 rtcIntersect4(packet_mask.data(), m_embree_world_scene, &context, &embree_raypacket);
489 ensure_no_errors_internal();
491 uint32_t is_hits = 0;
492 for (
int i = 0; i < static_cast<int>(batch_size); ++i) {
493 if (embree_raypacket.hit.geomID[i] != RTC_INVALID_GEOMETRY_ID) {
494 Index rtc_inst_id = embree_raypacket.hit.instID[0][i];
495 Index rtc_mesh_id = (rtc_inst_id == RTC_INVALID_GEOMETRY_ID)
496 ? embree_raypacket.hit.geomID[i]
498 assert(rtc_mesh_id < m_instance_to_user_mesh.size());
499 assert(m_visibility[rtc_mesh_id]);
500 mesh_index[i] = m_instance_to_user_mesh[rtc_mesh_id];
501 assert(mesh_index[i] + 1 < m_instance_index_ranges.size());
502 assert(mesh_index[i] < safe_cast<Index>(m_meshes.size()));
503 instance_index[i] = rtc_mesh_id - m_instance_index_ranges[mesh_index[i]];
504 facet_index[i] = embree_raypacket.hit.primID[i];
505 ray_depth[i] = embree_raypacket.ray.tfar[i];
506 barycentric_coord(i, 0) =
507 1.0f - embree_raypacket.hit.u[i] - embree_raypacket.hit.v[i];
508 barycentric_coord(i, 1) = embree_raypacket.hit.u[i];
509 barycentric_coord(i, 2) = embree_raypacket.hit.v[i];
510 normal(i, 0) = embree_raypacket.hit.Ng_x[i];
511 normal(i, 1) = embree_raypacket.hit.Ng_y[i];
512 normal(i, 2) = embree_raypacket.hit.Ng_z[i];
513 is_hits = is_hits | (1 << i);
526 const Point4& origin,
527 const Direction4& direction,
532 Point4& barycentric_coord,
533 const Scalar4& tmin = Scalar4::Zero(),
534 const Scalar4& tmax = Scalar4::Constant(std::numeric_limits<Scalar>::infinity()))
536 Index4 instance_index;
558 const Point4& origin,
559 const Direction4& direction,
561 const Scalar4& tmin = Scalar4::Zero(),
562 const Scalar4& tmax = Scalar4::Constant(std::numeric_limits<Scalar>::infinity()))
568 RTCRay4 embree_raypacket;
569 for (
int i = 0; i < static_cast<int>(batch_size); ++i) {
571 embree_raypacket.org_x[i] =
static_cast<float>(origin(i, 0));
572 embree_raypacket.org_y[i] =
static_cast<float>(origin(i, 1));
573 embree_raypacket.org_z[i] =
static_cast<float>(origin(i, 2));
576 embree_raypacket.dir_x[i] =
static_cast<float>(direction(i, 0));
577 embree_raypacket.dir_y[i] =
static_cast<float>(direction(i, 1));
578 embree_raypacket.dir_z[i] =
static_cast<float>(direction(i, 2));
581 embree_raypacket.tnear[i] =
static_cast<float>(tmin[i]);
582 embree_raypacket.tfar[i] = std::isinf(tmax[i]) ? std::numeric_limits<float>::max()
583 :
static_cast<float>(tmax[i]);
584 embree_raypacket.mask[i] = 0xFFFFFFFF;
585 embree_raypacket.id[i] =
static_cast<unsigned>(i);
586 embree_raypacket.flags[i] = 0;
590 auto packet_mask = mask;
591 for (
int i =
static_cast<int>(batch_size); i < 4; ++i) packet_mask[i] = 0;
593 ensure_no_errors_internal();
595 RTCIntersectContext context;
596 rtcInitIntersectContext(&context);
597 rtcOccluded4(packet_mask.data(), m_embree_world_scene, &context, &embree_raypacket);
599 ensure_no_errors_internal();
602 uint32_t is_hits = 0;
603 for (uint32_t i = 0; i < batch_size; ++i)
604 if (!std::isfinite(embree_raypacket.tfar[i])) is_hits = is_hits | (1 << i);
615 const Direction& direction,
617 Index& instance_index,
620 Point& barycentric_coord,
623 Scalar tmax = std::numeric_limits<Scalar>::infinity())
629 RTCRayHit embree_rayhit;
630 embree_rayhit.ray.org_x =
static_cast<float>(origin.x());
631 embree_rayhit.ray.org_y =
static_cast<float>(origin.y());
632 embree_rayhit.ray.org_z =
static_cast<float>(origin.z());
633 embree_rayhit.ray.dir_x =
static_cast<float>(direction.x());
634 embree_rayhit.ray.dir_y =
static_cast<float>(direction.y());
635 embree_rayhit.ray.dir_z =
static_cast<float>(direction.z());
636 embree_rayhit.ray.tnear =
static_cast<float>(tmin);
637 embree_rayhit.ray.tfar =
638 std::isinf(tmax) ? std::numeric_limits<float>::max() :
static_cast<float>(tmax);
639 embree_rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID;
640 embree_rayhit.hit.primID = RTC_INVALID_GEOMETRY_ID;
641 embree_rayhit.hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
642 embree_rayhit.ray.mask = 0xFFFFFFFF;
643 embree_rayhit.ray.id = 0;
644 embree_rayhit.ray.flags = 0;
645 ensure_no_errors_internal();
647 RTCIntersectContext context;
648 rtcInitIntersectContext(&context);
649 rtcIntersect1(m_embree_world_scene, &context, &embree_rayhit);
651 ensure_no_errors_internal();
653 if (embree_rayhit.hit.geomID != RTC_INVALID_GEOMETRY_ID) {
654 Index rtc_inst_id = embree_rayhit.hit.instID[0];
656 (rtc_inst_id == RTC_INVALID_GEOMETRY_ID) ? embree_rayhit.hit.geomID : rtc_inst_id;
657 assert(rtc_mesh_id < m_instance_to_user_mesh.size());
658 assert(m_visibility[rtc_mesh_id]);
659 mesh_index = m_instance_to_user_mesh[rtc_mesh_id];
660 assert(mesh_index + 1 < m_instance_index_ranges.size());
661 assert(mesh_index < safe_cast<Index>(m_meshes.size()));
662 instance_index = rtc_mesh_id - m_instance_index_ranges[mesh_index];
663 facet_index = embree_rayhit.hit.primID;
664 ray_depth = embree_rayhit.ray.tfar;
665 barycentric_coord[0] = 1.0f - embree_rayhit.hit.u - embree_rayhit.hit.v;
666 barycentric_coord[1] = embree_rayhit.hit.u;
667 barycentric_coord[2] = embree_rayhit.hit.v;
668 normal[0] = embree_rayhit.hit.Ng_x;
669 normal[1] = embree_rayhit.hit.Ng_y;
670 normal[2] = embree_rayhit.hit.Ng_z;
674 mesh_index = invalid<Index>();
675 instance_index = invalid<Index>();
676 facet_index = invalid<Index>();
687 const Direction& direction,
691 Point& barycentric_coord,
693 Scalar tmax = std::numeric_limits<Scalar>::infinity())
695 Index instance_index;
713 const Direction& direction,
715 Scalar tmax = std::numeric_limits<Scalar>::infinity())
720 embree_ray.org_x =
static_cast<float>(origin.x());
721 embree_ray.org_y =
static_cast<float>(origin.y());
722 embree_ray.org_z =
static_cast<float>(origin.z());
723 embree_ray.dir_x =
static_cast<float>(direction.x());
724 embree_ray.dir_y =
static_cast<float>(direction.y());
725 embree_ray.dir_z =
static_cast<float>(direction.z());
726 embree_ray.tnear =
static_cast<float>(tmin);
728 std::isinf(tmax) ? std::numeric_limits<float>::max() :
static_cast<float>(tmax);
729 embree_ray.mask = 0xFFFFFFFF;
731 embree_ray.flags = 0;
733 ensure_no_errors_internal();
735 RTCIntersectContext context;
736 rtcInitIntersectContext(&context);
737 rtcOccluded1(m_embree_world_scene, &context, &embree_ray);
739 ensure_no_errors_internal();
742 return !std::isfinite(embree_ray.tfar);
750 std::unique_ptr<RaycasterMesh> mesh,
751 const Transform& trans = Transform::Identity(),
752 RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM)
754 m_meshes.push_back(std::move(mesh));
755 m_transforms.push_back(trans);
756 m_mesh_build_qualities.push_back(build_quality);
757 m_visibility.push_back(
true);
758 for (
auto& f : m_filters) {
759 f.push_back(
nullptr);
761 Index mesh_index = safe_cast<Index>(m_meshes.size() - 1);
763 Index instance_index = m_instance_index_ranges.back();
764 la_runtime_assert(instance_index == safe_cast<Index>(m_instance_to_user_mesh.size()));
765 m_instance_index_ranges.push_back(instance_index + 1);
766 m_instance_to_user_mesh.resize(instance_index + 1, mesh_index);
767 m_need_rebuild =
true;
771 void update_raycasting_mesh(
773 std::unique_ptr<RaycasterMesh> mesh,
774 RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM)
779 m_meshes[index] = std::move(mesh);
780 m_mesh_build_qualities[index] = build_quality;
781 m_need_rebuild =
true;
788 for (
auto& s : m_embree_mesh_scenes) {
791 rtcReleaseScene(m_embree_world_scene);
797 return m_scene_flags;
803 return m_build_quality;
811 else if (m_need_commit)
823 if (!m_need_rebuild)
return;
827 m_embree_world_scene = rtcNewScene(m_device);
831 m_embree_world_scene,
833 rtcSetSceneBuildQuality(m_embree_world_scene, scene_build_quality);
834 m_float_data.clear();
836 const auto num_meshes = m_meshes.size();
838 m_embree_mesh_scenes.resize(num_meshes);
839 m_mesh_vertex_counts.resize(num_meshes);
840 ensure_no_errors_internal();
842 bool is_mask_supported =
843 rtcGetDeviceProperty(m_device, RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED);
844 for (
size_t i = 0; i < num_meshes; i++) {
846 const auto& mesh = m_meshes[i];
849 const Index num_vertices = m_mesh_vertex_counts[i] =
850 safe_cast<Index>(mesh->get_num_vertices());
851 const Index num_facets = safe_cast<Index>(mesh->get_num_facets());
853 auto& embree_mesh_scene = m_embree_mesh_scenes[i];
854 embree_mesh_scene = rtcNewScene(m_device);
856 rtcSetSceneFlags(embree_mesh_scene, scene_flags);
857 rtcSetSceneBuildQuality(embree_mesh_scene, scene_build_quality);
858 ensure_no_errors_internal();
860 RTCGeometry geom = rtcNewGeometry(
862 RTC_GEOMETRY_TYPE_TRIANGLE);
864 rtcSetGeometryBuildQuality(geom, m_mesh_build_qualities[i]);
870 rtcSetSharedGeometryBuffer(
872 RTC_BUFFER_TYPE_VERTEX,
879 rtcSetSharedGeometryBuffer(
881 RTC_BUFFER_TYPE_INDEX,
892 rtcCommitGeometry(geom);
893 rtcAttachGeometry(embree_mesh_scene, geom);
894 rtcReleaseGeometry(geom);
895 ensure_no_errors_internal();
898 for (Index instance_index = m_instance_index_ranges[i];
899 instance_index < m_instance_index_ranges[i + 1];
901 const auto& trans = m_transforms[instance_index];
903 RTCGeometry geom_inst = rtcNewGeometry(
905 RTC_GEOMETRY_TYPE_INSTANCE);
907 rtcSetGeometryInstancedScene(geom_inst, embree_mesh_scene);
908 rtcSetGeometryTimeStepCount(geom_inst, 1);
910 Eigen::Matrix<float, 4, 4> T = trans.template cast<float>();
911 rtcSetGeometryTransform(geom_inst, 0, RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR, T.data());
912 ensure_no_errors_internal();
914 if (is_mask_supported) {
917 m_visibility[instance_index] ? 0xFFFFFFFF : 0x00000000);
919 ensure_no_errors_internal();
921 rtcCommitGeometry(geom_inst);
922 unsigned rtc_instance_id = rtcAttachGeometry(m_embree_world_scene, geom_inst);
923 rtcReleaseGeometry(geom_inst);
925 ensure_no_errors_internal();
928 rtcCommitScene(embree_mesh_scene);
929 ensure_no_errors_internal();
931 rtcCommitScene(m_embree_world_scene);
932 ensure_no_errors_internal();
934 m_need_rebuild = m_need_commit =
false;
940 auto float_data = mesh.vertices_to_float();
944 float_data.push_back(0.0);
945 m_float_data.emplace_back(std::move(float_data));
946 return m_float_data.back().data();
952 auto int_data = mesh.indices_to_int();
956 int_data.push_back(0);
957 m_int_data.emplace_back(std::move(int_data));
958 return m_int_data.back().data();
968 if (is_mask_supported) {
970 rtcSetGeometryUserData(geom,
this);
971 rtcSetGeometryIntersectFilterFunction(geom, &wrap_filter<FILTER_INTERSECT>);
973 rtcSetGeometryIntersectFilterFunction(geom,
nullptr);
976 rtcSetGeometryUserData(geom,
this);
977 rtcSetGeometryIntersectFilterFunction(geom, &wrap_filter_and_mask<FILTER_INTERSECT>);
987 if (is_mask_supported) {
989 rtcSetGeometryUserData(geom,
this);
990 rtcSetGeometryOccludedFilterFunction(geom, &wrap_filter<FILTER_OCCLUDED>);
992 rtcSetGeometryOccludedFilterFunction(geom,
nullptr);
995 rtcSetGeometryUserData(geom,
this);
996 rtcSetGeometryOccludedFilterFunction(geom, &wrap_filter_and_mask<FILTER_OCCLUDED>);
1004 template <
int IntersectionOrOcclusion>
1005 static void wrap_filter(
const RTCFilterFunctionNArguments* args)
1010 const auto* obj =
reinterpret_cast<EmbreeRayCaster*
>(args->geometryUserPtr);
1011 auto rtc_inst_id = RTCHitN_instID(args->hit, args->N, 0, 0);
1012 assert(rtc_inst_id < obj->m_instance_to_user_mesh.size());
1014 auto filter = obj->m_filters[IntersectionOrOcclusion][rtc_inst_id];
1019 Index mesh_index = obj->m_instance_to_user_mesh[rtc_inst_id];
1020 assert(mesh_index + 1 < obj->m_instance_index_ranges.size());
1021 assert(mesh_index < safe_cast<Index>(obj->m_meshes.size()));
1022 Index instance_index = rtc_inst_id - obj->m_instance_index_ranges[mesh_index];
1027 mesh_index4.fill(mesh_index);
1028 Index4 instance_index4;
1029 instance_index4.fill(instance_index);
1032 filter(obj, mesh_index4.data(), instance_index4.data(), args);
1040 template <
int IntersectionOrOcclusion>
1041 static void wrap_filter_and_mask(
const RTCFilterFunctionNArguments* args)
1046 const auto* obj =
reinterpret_cast<EmbreeRayCaster*
>(args->geometryUserPtr);
1047 auto rtc_inst_id = RTCHitN_instID(args->hit, args->N, 0, 0);
1048 if (!obj->m_visibility[rtc_inst_id]) {
1050 std::fill(args->valid, args->valid + args->N, 0);
1055 wrap_filter<IntersectionOrOcclusion>(args);
1059 RTCSceneFlags m_scene_flags;
1060 RTCBuildQuality m_build_quality;
1062 RTCScene m_embree_world_scene;
1063 bool m_need_rebuild;
1068 std::vector<FloatData> m_float_data;
1069 std::vector<IntData> m_int_data;
1070 std::vector<std::unique_ptr<RaycasterMesh>> m_meshes;
1071 std::vector<RTCBuildQuality> m_mesh_build_qualities;
1072 std::vector<RTCScene> m_embree_mesh_scenes;
1073 std::vector<Index> m_mesh_vertex_counts;
1074 std::vector<FilterFunction> m_filters[2];
1081 std::vector<Index> m_instance_index_ranges;
1091 std::vector<Index> m_instance_to_user_mesh;
1095 std::vector<Transform> m_transforms;
1096 std::vector<bool> m_visibility;
1099 void ensure_no_errors_internal()
const
1101#ifdef LAGRANGE_EMBREE_DEBUG
1102 EmbreeHelper::ensure_no_errors(m_device);
1111template <
typename Scalar>
1114 RTCPointQuery query;
1115 query.x = (float)(p.x());
1116 query.y = (float)(p.y());
1117 query.z = (float)(p.z());
1118 query.radius = std::numeric_limits<float>::max();
1120 ensure_no_errors_internal();
1125 result.populate_triangle =
1126 [&](
unsigned mesh_index,
unsigned facet_index, Point& v0, Point& v1, Point& v2) {
1132 const unsigned* face = m_int_data[mesh_index].data() + 3 * facet_index;
1133 const float* vertices = m_float_data[mesh_index].data();
1134 v0 = Point(vertices[3 * face[0]], vertices[3 * face[0] + 1], vertices[3 * face[0] + 2]);
1135 v1 = Point(vertices[3 * face[1]], vertices[3 * face[1] + 1], vertices[3 * face[1] + 2]);
1136 v2 = Point(vertices[3 * face[2]], vertices[3 * face[2] + 1], vertices[3 * face[2] + 2]);
1140 RTCPointQueryContext context;
1141 rtcInitPointQueryContext(&context);
1143 m_embree_world_scene,
1146 &embree_closest_point<Scalar>,
1147 reinterpret_cast<void*
>(&result));
1149 result.mesh_index != RTC_INVALID_GEOMETRY_ID ||
1150 result.facet_index != RTC_INVALID_GEOMETRY_ID);
1152 result.mesh_index != invalid<unsigned>() || result.facet_index != invalid<unsigned>());
1154 ensure_no_errors_internal();
A wrapper for Embree's raycasting API to compute ray intersections with (instances of) meshes.
Definition: EmbreeRayCaster.h:47
Index add_meshes(std::shared_ptr< MeshType > mesh, const TransformVector &trans_vector, RTCBuildQuality build_quality=RTC_BUILD_QUALITY_MEDIUM)
Add multiple instances of a single mesh to the scene, with given transformations.
Definition: EmbreeRayCaster.h:201
Index add_raycasting_mesh(std::unique_ptr< RaycasterMesh > mesh, const Transform &trans=Transform::Identity(), RTCBuildQuality build_quality=RTC_BUILD_QUALITY_MEDIUM)
Add raycasting utilities.
Definition: EmbreeRayCaster.h:749
Index add_mesh(std::shared_ptr< MeshType > mesh, const Transform &trans=Transform::Identity(), RTCBuildQuality build_quality=RTC_BUILD_QUALITY_MEDIUM)
Add an instance of a mesh to the scene, with a given transformation.
Definition: EmbreeRayCaster.h:183
uint32_t cast4(uint32_t batch_size, const Point4 &origin, const Direction4 &direction, const Mask4 &mask, const Scalar4 &tmin=Scalar4::Zero(), const Scalar4 &tmax=Scalar4::Constant(std::numeric_limits< Scalar >::infinity()))
Cast a packet of up to 4 rays through the scene and check whether they hit anything or not.
Definition: EmbreeRayCaster.h:556
FilterFunction get_intersection_filter(Index mesh_index) const
Get the intersection filter function currently bound to a given mesh.
Definition: EmbreeRayCaster.h:369
Index get_num_instances(Index mesh_index) const
Get the number of instances of a particular mesh.
Definition: EmbreeRayCaster.h:143
void update_mesh(Index index, std::shared_ptr< MeshType > mesh, RTCBuildQuality build_quality=RTC_BUILD_QUALITY_MEDIUM)
Update a particular mesh with a new mesh object.
Definition: EmbreeRayCaster.h:231
void set_intersection_filter(Index mesh_index, FilterFunction filter)
Set an intersection filter that is called for every hit on (every instance of) a mesh during an inter...
Definition: EmbreeRayCaster.h:356
bool cast(const Point &origin, const Direction &direction, Index &mesh_index, Index &instance_index, Index &facet_index, Scalar &ray_depth, Point &barycentric_coord, Point &normal, Scalar tmin=0, Scalar tmax=std::numeric_limits< Scalar >::infinity())
Cast a single ray through the scene, returning full data of the closest intersection including the no...
Definition: EmbreeRayCaster.h:613
virtual ~EmbreeRayCaster()
Destructor.
Definition: EmbreeRayCaster.h:120
void generate_scene()
Build the whole Embree scene from the specified meshes, instances, etc.
Definition: EmbreeRayCaster.h:821
bool get_visibility(Index mesh_index, Index instance_index) const
Get the visibility flag of a given mesh instance.
Definition: EmbreeRayCaster.h:312
virtual RTCSceneFlags get_scene_flags() const
Get the Embree scene flags.
Definition: EmbreeRayCaster.h:795
const float * extract_float_data(const RaycasterMesh &mesh)
Get the vertex data of a mesh as an array of floats.
Definition: EmbreeRayCaster.h:938
void update_transformation(Index mesh_index, Index instance_index, const Transform &trans)
Update the transform applied to a given mesh instance.
Definition: EmbreeRayCaster.h:295
void update_mesh_vertices(Index index)
Update the object to reflect external changes to the vertices of a particular mesh which is already i...
Definition: EmbreeRayCaster.h:247
uint32_t cast4(uint32_t batch_size, const Point4 &origin, const Direction4 &direction, const Mask4 &mask, Index4 &mesh_index, Index4 &instance_index, Index4 &facet_index, Scalar4 &ray_depth, Point4 &barycentric_coord, Point4 &normal, const Scalar4 &tmin=Scalar4::Zero(), const Scalar4 &tmax=Scalar4::Constant(std::numeric_limits< Scalar >::infinity()))
Cast a packet of up to 4 rays through the scene, returning full data of the closest intersections inc...
Definition: EmbreeRayCaster.h:435
bool cast(const Point &origin, const Direction &direction, Index &mesh_index, Index &facet_index, Scalar &ray_depth, Point &barycentric_coord, Scalar tmin=0, Scalar tmax=std::numeric_limits< Scalar >::infinity())
Cast a single ray through the scene, returning data of the closest intersection excluding the normal ...
Definition: EmbreeRayCaster.h:685
uint32_t cast4(uint32_t batch_size, const Point4 &origin, const Direction4 &direction, const Mask4 &mask, Index4 &mesh_index, Index4 &facet_index, Scalar4 &ray_depth, Point4 &barycentric_coord, const Scalar4 &tmin=Scalar4::Zero(), const Scalar4 &tmax=Scalar4::Constant(std::numeric_limits< Scalar >::infinity()))
Cast a packet of up to 4 rays through the scene, returning data of the closest intersections excludin...
Definition: EmbreeRayCaster.h:524
Index get_num_instances() const
Get the total number of mesh instances.
Definition: EmbreeRayCaster.h:137
void update_internal()
Update all internal structures based on the current dirty flags.
Definition: EmbreeRayCaster.h:807
FilterFunction get_occlusion_filter(Index mesh_index) const
Get the occlusion filter function currently bound to a given mesh.
Definition: EmbreeRayCaster.h:404
virtual RTCBuildQuality get_scene_build_quality() const
Get the Embree geometry build quality.
Definition: EmbreeRayCaster.h:801
void ensure_no_errors() const
Throw an exception if an Embree error has occurred.
Definition: EmbreeRayCaster.h:426
std::shared_ptr< MeshType > get_mesh(Index index) const
Get the mesh with a given index.
Definition: EmbreeRayCaster.h:155
EmbreeRayCaster(RTCSceneFlags scene_flags=RTC_SCENE_FLAG_DYNAMIC, RTCBuildQuality build_quality=RTC_BUILD_QUALITY_LOW)
Constructor.
Definition: EmbreeRayCaster.h:92
void commit_scene_changes()
Call rtcCommitScene() on the overall scene, if it has been marked as modified.
Definition: EmbreeRayCaster.h:417
bool cast(const Point &origin, const Direction &direction, Scalar tmin=0, Scalar tmax=std::numeric_limits< Scalar >::infinity())
Cast a single ray through the scene and check whether it hits anything or not.
Definition: EmbreeRayCaster.h:711
ClosestPoint query_closest_point(const Point &p) const
Use the underlying BVH to find the point closest to a query point.
Definition: EmbreeRayCaster.h:1112
void update_visibility(Index mesh_index, Index instance_index, bool visible)
Update the visibility of a given mesh index (true for visible, false for invisible).
Definition: EmbreeRayCaster.h:322
void set_occlusion_filter(Index mesh_index, FilterFunction filter)
Set an occlusion filter that is called for every hit on (every instance of) a mesh during an occlusio...
Definition: EmbreeRayCaster.h:391
Index get_num_meshes() const
Get the total number of meshes (not instances).
Definition: EmbreeRayCaster.h:131
std::function< void(const EmbreeRayCaster *obj, const Index *mesh_index, const Index *instance_index, const RTCFilterFunctionNArguments *args)> FilterFunction
Interface for a hit filter function.
Definition: EmbreeRayCaster.h:84
void release_scenes()
Release internal Embree scenes.
Definition: EmbreeRayCaster.h:787
Transform get_transform(Index mesh_index, Index instance_index) const
Get the transform applied to a given mesh instance.
Definition: EmbreeRayCaster.h:285
const unsigned * extract_int_data(const RaycasterMesh &mesh)
Get the index data of a mesh as an array of integers.
Definition: EmbreeRayCaster.h:950
Index get_mesh_for_instance(Index cumulative_instance_index) const
Get the index of the mesh corresponding to a given instance, where the instances are indexed sequenti...
Definition: EmbreeRayCaster.h:170
Definition: RayCasterMesh.h:43
Definition: RayCasterMesh.h:22
#define la_runtime_assert(...)
Runtime assertion check.
Definition: assert.h:169
#define la_debug_assert(...)
Debug assertion check.
Definition: assert.h:189
Main namespace for Lagrange.
Definition: AABBIGL.h:30
Definition: ClosestPointResult.h:25