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();
115 m_need_rebuild =
true;
116 m_need_commit =
false;
123 rtcReleaseDevice(m_device);
141 m_instance_index_ranges[mesh_index + 1] - m_instance_index_ranges[mesh_index]);
148 template <
typename MeshType>
149 std::shared_ptr<MeshType>
get_mesh(Index index)
const
167 return m_instance_to_user_mesh[cumulative_instance_index];
176 template <
typename MeshType>
178 std::shared_ptr<MeshType> mesh,
179 const Transform& trans = Transform::Identity(),
180 RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM)
194 template <
typename MeshType>
196 std::shared_ptr<MeshType> mesh,
197 const TransformVector& trans_vector,
198 RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM)
201 m_transforms.insert(m_transforms.end(), trans_vector.begin(), trans_vector.end());
202 m_mesh_build_qualities.push_back(build_quality);
203 m_visibility.resize(m_visibility.size() + trans_vector.size(),
true);
204 for (
auto& f : m_filters) {
205 f.push_back(
nullptr);
209 Index instance_index = m_instance_index_ranges.back();
211 Index new_instance_size = instance_index + trans_vector.size();
212 m_instance_index_ranges.push_back(new_instance_size);
213 m_instance_to_user_mesh.resize(new_instance_size, mesh_index);
214 m_need_rebuild =
true;
224 template <
typename MeshType>
227 std::shared_ptr<MeshType> mesh,
228 RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM)
230 update_raycasting_mesh(
244 if (m_need_rebuild)
return;
247 auto geom = rtcGetGeometry(m_embree_mesh_scenes[index], 0);
250 auto const& mesh = m_meshes[index];
255 reinterpret_cast<float*
>(rtcGetGeometryBufferData(geom, RTC_BUFFER_TYPE_VERTEX, 0));
257 mesh->vertices_to_float(vbuf);
258 rtcUpdateGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, 0);
261 rtcCommitGeometry(geom);
262 rtcCommitScene(m_embree_mesh_scenes[index]);
265 for (Index instance_index = m_instance_index_ranges[index];
266 instance_index < m_instance_index_ranges[index + 1];
268 Index rtc_inst_id = m_instance_index_ranges[index] + instance_index;
270 rtcGetGeometry(m_embree_world_scene,
static_cast<unsigned>(rtc_inst_id));
271 rtcCommitGeometry(geom_inst);
275 m_need_commit =
true;
282 Index index = m_instance_index_ranges[mesh_index] + instance_index;
285 return m_transforms[index];
292 Index index = m_instance_index_ranges[mesh_index] + instance_index;
295 m_transforms[index] = trans;
296 if (!m_need_rebuild) {
297 auto geom = rtcGetGeometry(m_embree_world_scene,
static_cast<unsigned>(index));
298 Eigen::Matrix<float, 4, 4> T = trans.template
cast<float>();
299 rtcSetGeometryTransform(geom, 0, RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR, T.eval().data());
300 rtcCommitGeometry(geom);
301 m_need_commit =
true;
309 Index index = m_instance_index_ranges[mesh_index] + instance_index;
312 return m_visibility[index];
319 Index index = m_instance_index_ranges[mesh_index] + instance_index;
322 m_visibility[index] = visible;
323 if (!m_need_rebuild &&
324 rtcGetDeviceProperty(m_device, RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED)) {
327 auto geom = rtcGetGeometry(m_embree_world_scene,
static_cast<unsigned>(index));
328 rtcSetGeometryMask(geom, visible ? 0xFFFFFFFF : 0x00000000);
329 rtcCommitGeometry(geom);
330 m_need_commit =
true;
353 m_filters[FILTER_INTERSECT][mesh_index] = filter;
354 m_need_rebuild =
true;
366 return m_filters[FILTER_INTERSECT][mesh_index];
388 m_filters[FILTER_OCCLUDED][mesh_index] = filter;
389 m_need_rebuild =
true;
401 return m_filters[FILTER_OCCLUDED][mesh_index];
413 if (!m_need_commit)
return;
415 rtcCommitScene(m_embree_world_scene);
416 m_need_commit =
false;
428 const Point4& origin,
429 const Direction4& direction,
432 Index4& instance_index,
435 Point4& barycentric_coord,
437 const Scalar4& tmin = Scalar4::Zero(),
438 const Scalar4& tmax = Scalar4::Constant(std::numeric_limits<Scalar>::infinity()))
444 RTCRayHit4 embree_raypacket;
445 for (
int i = 0; i < static_cast<int>(batch_size); ++i) {
447 embree_raypacket.ray.org_x[i] =
static_cast<float>(origin(i, 0));
448 embree_raypacket.ray.org_y[i] =
static_cast<float>(origin(i, 1));
449 embree_raypacket.ray.org_z[i] =
static_cast<float>(origin(i, 2));
452 embree_raypacket.ray.dir_x[i] =
static_cast<float>(direction(i, 0));
453 embree_raypacket.ray.dir_y[i] =
static_cast<float>(direction(i, 1));
454 embree_raypacket.ray.dir_z[i] =
static_cast<float>(direction(i, 2));
457 embree_raypacket.ray.tnear[i] =
static_cast<float>(tmin[i]);
458 embree_raypacket.ray.tfar[i] = std::isinf(tmax[i]) ? std::numeric_limits<float>::max()
459 :
static_cast<float>(tmax[i]);
460 embree_raypacket.ray.mask[i] = 0xFFFFFFFF;
461 embree_raypacket.ray.id[i] =
static_cast<unsigned>(i);
462 embree_raypacket.ray.flags[i] = 0;
465 embree_raypacket.hit.geomID[i] = RTC_INVALID_GEOMETRY_ID;
466 embree_raypacket.hit.primID[i] = RTC_INVALID_GEOMETRY_ID;
467 embree_raypacket.hit.instID[0][i] = RTC_INVALID_GEOMETRY_ID;
471 auto packet_mask = mask;
472 for (
int i =
static_cast<int>(batch_size); i < 4; ++i) packet_mask[i] = 0;
474 ensure_no_errors_internal();
476 RTCIntersectContext context;
477 rtcInitIntersectContext(&context);
478 rtcIntersect4(packet_mask.data(), m_embree_world_scene, &context, &embree_raypacket);
480 ensure_no_errors_internal();
482 uint32_t is_hits = 0;
483 for (
int i = 0; i < static_cast<int>(batch_size); ++i) {
484 if (embree_raypacket.hit.geomID[i] != RTC_INVALID_GEOMETRY_ID) {
485 Index rtc_inst_id = embree_raypacket.hit.instID[0][i];
486 Index rtc_mesh_id = (rtc_inst_id == RTC_INVALID_GEOMETRY_ID)
487 ? embree_raypacket.hit.geomID[i]
489 assert(rtc_mesh_id < m_instance_to_user_mesh.size());
490 assert(m_visibility[rtc_mesh_id]);
491 mesh_index[i] = m_instance_to_user_mesh[rtc_mesh_id];
492 assert(mesh_index[i] + 1 < m_instance_index_ranges.size());
494 instance_index[i] = rtc_mesh_id - m_instance_index_ranges[mesh_index[i]];
495 facet_index[i] = embree_raypacket.hit.primID[i];
496 ray_depth[i] = embree_raypacket.ray.tfar[i];
497 barycentric_coord(i, 0) =
498 1.0f - embree_raypacket.hit.u[i] - embree_raypacket.hit.v[i];
499 barycentric_coord(i, 1) = embree_raypacket.hit.u[i];
500 barycentric_coord(i, 2) = embree_raypacket.hit.v[i];
501 normal(i, 0) = embree_raypacket.hit.Ng_x[i];
502 normal(i, 1) = embree_raypacket.hit.Ng_y[i];
503 normal(i, 2) = embree_raypacket.hit.Ng_z[i];
504 is_hits = is_hits | (1 << i);
517 const Point4& origin,
518 const Direction4& direction,
523 Point4& barycentric_coord,
524 const Scalar4& tmin = Scalar4::Zero(),
525 const Scalar4& tmax = Scalar4::Constant(std::numeric_limits<Scalar>::infinity()))
527 Index4 instance_index;
549 const Point4& origin,
550 const Direction4& direction,
552 const Scalar4& tmin = Scalar4::Zero(),
553 const Scalar4& tmax = Scalar4::Constant(std::numeric_limits<Scalar>::infinity()))
559 RTCRay4 embree_raypacket;
560 for (
int i = 0; i < static_cast<int>(batch_size); ++i) {
562 embree_raypacket.org_x[i] =
static_cast<float>(origin(i, 0));
563 embree_raypacket.org_y[i] =
static_cast<float>(origin(i, 1));
564 embree_raypacket.org_z[i] =
static_cast<float>(origin(i, 2));
567 embree_raypacket.dir_x[i] =
static_cast<float>(direction(i, 0));
568 embree_raypacket.dir_y[i] =
static_cast<float>(direction(i, 1));
569 embree_raypacket.dir_z[i] =
static_cast<float>(direction(i, 2));
572 embree_raypacket.tnear[i] =
static_cast<float>(tmin[i]);
573 embree_raypacket.tfar[i] = std::isinf(tmax[i]) ? std::numeric_limits<float>::max()
574 :
static_cast<float>(tmax[i]);
575 embree_raypacket.mask[i] = 0xFFFFFFFF;
576 embree_raypacket.id[i] =
static_cast<unsigned>(i);
577 embree_raypacket.flags[i] = 0;
581 auto packet_mask = mask;
582 for (
int i =
static_cast<int>(batch_size); i < 4; ++i) packet_mask[i] = 0;
584 ensure_no_errors_internal();
586 RTCIntersectContext context;
587 rtcInitIntersectContext(&context);
588 rtcOccluded4(packet_mask.data(), m_embree_world_scene, &context, &embree_raypacket);
590 ensure_no_errors_internal();
593 uint32_t is_hits = 0;
594 for (uint32_t i = 0; i < batch_size; ++i)
595 if (!std::isfinite(embree_raypacket.tfar[i])) is_hits = is_hits | (1 << i);
606 const Direction& direction,
608 Index& instance_index,
611 Point& barycentric_coord,
614 Scalar tmax = std::numeric_limits<Scalar>::infinity())
620 RTCRayHit embree_rayhit;
621 embree_rayhit.ray.org_x =
static_cast<float>(origin.x());
622 embree_rayhit.ray.org_y =
static_cast<float>(origin.y());
623 embree_rayhit.ray.org_z =
static_cast<float>(origin.z());
624 embree_rayhit.ray.dir_x =
static_cast<float>(direction.x());
625 embree_rayhit.ray.dir_y =
static_cast<float>(direction.y());
626 embree_rayhit.ray.dir_z =
static_cast<float>(direction.z());
627 embree_rayhit.ray.tnear =
static_cast<float>(tmin);
628 embree_rayhit.ray.tfar =
629 std::isinf(tmax) ? std::numeric_limits<float>::max() :
static_cast<float>(tmax);
630 embree_rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID;
631 embree_rayhit.hit.primID = RTC_INVALID_GEOMETRY_ID;
632 embree_rayhit.hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
633 embree_rayhit.ray.mask = 0xFFFFFFFF;
634 embree_rayhit.ray.id = 0;
635 embree_rayhit.ray.flags = 0;
636 ensure_no_errors_internal();
638 RTCIntersectContext context;
639 rtcInitIntersectContext(&context);
640 rtcIntersect1(m_embree_world_scene, &context, &embree_rayhit);
642 ensure_no_errors_internal();
644 if (embree_rayhit.hit.geomID != RTC_INVALID_GEOMETRY_ID) {
645 Index rtc_inst_id = embree_rayhit.hit.instID[0];
647 (rtc_inst_id == RTC_INVALID_GEOMETRY_ID) ? embree_rayhit.hit.geomID : rtc_inst_id;
648 assert(rtc_mesh_id < m_instance_to_user_mesh.size());
649 assert(m_visibility[rtc_mesh_id]);
650 mesh_index = m_instance_to_user_mesh[rtc_mesh_id];
651 assert(mesh_index + 1 < m_instance_index_ranges.size());
653 instance_index = rtc_mesh_id - m_instance_index_ranges[mesh_index];
654 facet_index = embree_rayhit.hit.primID;
655 ray_depth = embree_rayhit.ray.tfar;
656 barycentric_coord[0] = 1.0f - embree_rayhit.hit.u - embree_rayhit.hit.v;
657 barycentric_coord[1] = embree_rayhit.hit.u;
658 barycentric_coord[2] = embree_rayhit.hit.v;
659 normal[0] = embree_rayhit.hit.Ng_x;
660 normal[1] = embree_rayhit.hit.Ng_y;
661 normal[2] = embree_rayhit.hit.Ng_z;
678 const Direction& direction,
682 Point& barycentric_coord,
684 Scalar tmax = std::numeric_limits<Scalar>::infinity())
686 Index instance_index;
704 const Direction& direction,
706 Scalar tmax = std::numeric_limits<Scalar>::infinity())
711 embree_ray.org_x =
static_cast<float>(origin.x());
712 embree_ray.org_y =
static_cast<float>(origin.y());
713 embree_ray.org_z =
static_cast<float>(origin.z());
714 embree_ray.dir_x =
static_cast<float>(direction.x());
715 embree_ray.dir_y =
static_cast<float>(direction.y());
716 embree_ray.dir_z =
static_cast<float>(direction.z());
717 embree_ray.tnear =
static_cast<float>(tmin);
719 std::isinf(tmax) ? std::numeric_limits<float>::max() :
static_cast<float>(tmax);
720 embree_ray.mask = 0xFFFFFFFF;
722 embree_ray.flags = 0;
724 ensure_no_errors_internal();
726 RTCIntersectContext context;
727 rtcInitIntersectContext(&context);
728 rtcOccluded1(m_embree_world_scene, &context, &embree_ray);
730 ensure_no_errors_internal();
733 return !std::isfinite(embree_ray.tfar);
741 std::unique_ptr<RaycasterMesh> mesh,
742 const Transform& trans = Transform::Identity(),
743 RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM)
745 m_meshes.push_back(std::move(mesh));
746 m_transforms.push_back(trans);
747 m_mesh_build_qualities.push_back(build_quality);
748 m_visibility.push_back(
true);
749 for (
auto& f : m_filters) {
750 f.push_back(
nullptr);
754 Index instance_index = m_instance_index_ranges.back();
756 m_instance_index_ranges.push_back(instance_index + 1);
757 m_instance_to_user_mesh.resize(instance_index + 1, mesh_index);
758 m_need_rebuild =
true;
762 void update_raycasting_mesh(
764 std::unique_ptr<RaycasterMesh> mesh,
765 RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM)
770 m_meshes[index] = std::move(mesh);
771 m_mesh_build_qualities[index] = build_quality;
772 m_need_rebuild =
true;
780 for (
auto& s : m_embree_mesh_scenes) {
783 rtcReleaseScene(m_embree_world_scene);
797 else if (m_need_commit)
809 if (!m_need_rebuild)
return;
813 m_embree_world_scene = rtcNewScene(m_device);
817 m_embree_world_scene,
819 rtcSetSceneBuildQuality(m_embree_world_scene, scene_build_quality);
820 m_float_data.clear();
822 const auto num_meshes = m_meshes.size();
824 m_embree_mesh_scenes.resize(num_meshes);
825 m_mesh_vertex_counts.resize(num_meshes);
826 ensure_no_errors_internal();
828 bool is_mask_supported =
829 rtcGetDeviceProperty(m_device, RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED);
830 for (
size_t i = 0; i < num_meshes; i++) {
832 const auto& mesh = m_meshes[i];
835 const Index num_vertices = m_mesh_vertex_counts[i] =
839 auto& embree_mesh_scene = m_embree_mesh_scenes[i];
840 embree_mesh_scene = rtcNewScene(m_device);
842 rtcSetSceneFlags(embree_mesh_scene, scene_flags);
843 rtcSetSceneBuildQuality(embree_mesh_scene, scene_build_quality);
844 ensure_no_errors_internal();
846 RTCGeometry geom = rtcNewGeometry(
848 RTC_GEOMETRY_TYPE_TRIANGLE);
850 rtcSetGeometryBuildQuality(geom, m_mesh_build_qualities[i]);
856 rtcSetSharedGeometryBuffer(
858 RTC_BUFFER_TYPE_VERTEX,
865 rtcSetSharedGeometryBuffer(
867 RTC_BUFFER_TYPE_INDEX,
878 rtcCommitGeometry(geom);
879 rtcAttachGeometry(embree_mesh_scene, geom);
880 rtcReleaseGeometry(geom);
881 ensure_no_errors_internal();
884 for (Index instance_index = m_instance_index_ranges[i];
885 instance_index < m_instance_index_ranges[i + 1];
887 const auto& trans = m_transforms[instance_index];
889 RTCGeometry geom_inst = rtcNewGeometry(
891 RTC_GEOMETRY_TYPE_INSTANCE);
893 rtcSetGeometryInstancedScene(geom_inst, embree_mesh_scene);
894 rtcSetGeometryTimeStepCount(geom_inst, 1);
896 Eigen::Matrix<float, 4, 4> T = trans.template
cast<float>();
897 rtcSetGeometryTransform(geom_inst, 0, RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR, T.data());
898 ensure_no_errors_internal();
900 if (is_mask_supported) {
903 m_visibility[instance_index] ? 0xFFFFFFFF : 0x00000000);
905 ensure_no_errors_internal();
907 rtcCommitGeometry(geom_inst);
908 unsigned rtc_instance_id = rtcAttachGeometry(m_embree_world_scene, geom_inst);
909 rtcReleaseGeometry(geom_inst);
911 ensure_no_errors_internal();
914 rtcCommitScene(embree_mesh_scene);
915 ensure_no_errors_internal();
917 rtcCommitScene(m_embree_world_scene);
918 ensure_no_errors_internal();
920 m_need_rebuild = m_need_commit =
false;
926 auto float_data = mesh.vertices_to_float();
930 float_data.push_back(0.0);
931 m_float_data.emplace_back(std::move(float_data));
932 return m_float_data.back().data();
938 auto int_data = mesh.indices_to_int();
942 int_data.push_back(0);
943 m_int_data.emplace_back(std::move(int_data));
944 return m_int_data.back().data();
954 if (is_mask_supported) {
956 rtcSetGeometryUserData(geom,
this);
957 rtcSetGeometryIntersectFilterFunction(geom, &wrap_filter<FILTER_INTERSECT>);
959 rtcSetGeometryIntersectFilterFunction(geom,
nullptr);
962 rtcSetGeometryUserData(geom,
this);
963 rtcSetGeometryIntersectFilterFunction(geom, &wrap_filter_and_mask<FILTER_INTERSECT>);
973 if (is_mask_supported) {
975 rtcSetGeometryUserData(geom,
this);
976 rtcSetGeometryOccludedFilterFunction(geom, &wrap_filter<FILTER_OCCLUDED>);
978 rtcSetGeometryOccludedFilterFunction(geom,
nullptr);
981 rtcSetGeometryUserData(geom,
this);
982 rtcSetGeometryOccludedFilterFunction(geom, &wrap_filter_and_mask<FILTER_OCCLUDED>);
990 template <
int IntersectionOrOcclusion>
991 static void wrap_filter(
const RTCFilterFunctionNArguments* args)
996 const auto* obj =
reinterpret_cast<EmbreeRayCaster*
>(args->geometryUserPtr);
997 auto rtc_inst_id = RTCHitN_instID(args->hit, args->N, 0, 0);
998 assert(rtc_inst_id < obj->m_instance_to_user_mesh.size());
1000 auto filter = obj->m_filters[IntersectionOrOcclusion][rtc_inst_id];
1005 Index mesh_index = obj->m_instance_to_user_mesh[rtc_inst_id];
1006 assert(mesh_index + 1 < obj->m_instance_index_ranges.size());
1008 Index instance_index = rtc_inst_id - obj->m_instance_index_ranges[mesh_index];
1013 mesh_index4.fill(mesh_index);
1014 Index4 instance_index4;
1015 instance_index4.fill(instance_index);
1018 filter(obj, mesh_index4.data(), instance_index4.data(), args);
1026 template <
int IntersectionOrOcclusion>
1027 static void wrap_filter_and_mask(
const RTCFilterFunctionNArguments* args)
1032 const auto* obj =
reinterpret_cast<EmbreeRayCaster*
>(args->geometryUserPtr);
1033 auto rtc_inst_id = RTCHitN_instID(args->hit, args->N, 0, 0);
1034 if (!obj->m_visibility[rtc_inst_id]) {
1036 std::fill(args->valid, args->valid + args->N, 0);
1041 wrap_filter<IntersectionOrOcclusion>(args);
1045 RTCSceneFlags m_scene_flags;
1046 RTCBuildQuality m_build_quality;
1048 RTCScene m_embree_world_scene;
1049 bool m_need_rebuild;
1054 std::vector<FloatData> m_float_data;
1055 std::vector<IntData> m_int_data;
1056 std::vector<std::unique_ptr<RaycasterMesh>> m_meshes;
1057 std::vector<RTCBuildQuality> m_mesh_build_qualities;
1058 std::vector<RTCScene> m_embree_mesh_scenes;
1059 std::vector<Index> m_mesh_vertex_counts;
1060 std::vector<FilterFunction> m_filters[2];
1067 std::vector<Index> m_instance_index_ranges;
1077 std::vector<Index> m_instance_to_user_mesh;
1081 std::vector<Transform> m_transforms;
1082 std::vector<bool> m_visibility;
1085 void ensure_no_errors_internal()
const
1087#ifdef LAGRANGE_EMBREE_DEBUG
1088 EmbreeHelper::ensure_no_errors(m_device);
1097template <
typename Scalar>
1100 RTCPointQuery query;
1101 query.x = (float)(p.x());
1102 query.y = (float)(p.y());
1103 query.z = (float)(p.z());
1104 query.radius = std::numeric_limits<float>::max();
1106 ensure_no_errors_internal();
1108 ClosestPoint result;
1111 result.populate_triangle =
1112 [&](
unsigned mesh_index,
unsigned facet_index, Point& v0, Point& v1, Point& v2) {
1118 const unsigned* face = m_int_data[mesh_index].data() + 3 * facet_index;
1119 const float* vertices = m_float_data[mesh_index].data();
1120 v0 = Point(vertices[3 * face[0]], vertices[3 * face[0] + 1], vertices[3 * face[0] + 2]);
1121 v1 = Point(vertices[3 * face[1]], vertices[3 * face[1] + 1], vertices[3 * face[1] + 2]);
1122 v2 = Point(vertices[3 * face[2]], vertices[3 * face[2] + 1], vertices[3 * face[2] + 2]);
1126 RTCPointQueryContext context;
1127 rtcInitPointQueryContext(&context);
1129 m_embree_world_scene,
1132 &embree_closest_point<Scalar>,
1133 reinterpret_cast<void*
>(&result));
1135 result.mesh_index != RTC_INVALID_GEOMETRY_ID ||
1136 result.facet_index != RTC_INVALID_GEOMETRY_ID);
1140 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:195
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:740
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:177
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:547
FilterFunction get_intersection_filter(Index mesh_index) const
Get the intersection filter function currently bound to a given mesh.
Definition EmbreeRayCaster.h:363
Index get_num_instances(Index mesh_index) const
Get the number of instances of a particular mesh.
Definition EmbreeRayCaster.h:137
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:225
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:350
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:604
virtual ~EmbreeRayCaster()
Destructor.
Definition EmbreeRayCaster.h:120
void generate_scene()
Build the whole Embree scene from the specified meshes, instances, etc.
Definition EmbreeRayCaster.h:807
bool get_visibility(Index mesh_index, Index instance_index) const
Get the visibility flag of a given mesh instance.
Definition EmbreeRayCaster.h:306
virtual RTCSceneFlags get_scene_flags() const
Get the Embree scene flags.
Definition EmbreeRayCaster.h:787
const float * extract_float_data(const RaycasterMesh &mesh)
Get the vertex data of a mesh as an array of floats.
Definition EmbreeRayCaster.h:924
void update_transformation(Index mesh_index, Index instance_index, const Transform &trans)
Update the transform applied to a given mesh instance.
Definition EmbreeRayCaster.h:289
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:241
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:426
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:676
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:515
Index get_num_instances() const
Get the total number of mesh instances.
Definition EmbreeRayCaster.h:134
void update_internal()
Update all internal structures based on the current dirty flags.
Definition EmbreeRayCaster.h:793
FilterFunction get_occlusion_filter(Index mesh_index) const
Get the occlusion filter function currently bound to a given mesh.
Definition EmbreeRayCaster.h:398
virtual RTCBuildQuality get_scene_build_quality() const
Get the Embree geometry build quality.
Definition EmbreeRayCaster.h:790
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:80
void ensure_no_errors() const
Throw an exception if an Embree error has occurred.
Definition EmbreeRayCaster.h:420
std::shared_ptr< MeshType > get_mesh(Index index) const
Get the mesh with a given index.
Definition EmbreeRayCaster.h:149
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:411
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:702
ClosestPoint query_closest_point(const Point &p) const
Use the underlying BVH to find the point closest to a query point.
Definition EmbreeRayCaster.h:1098
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:316
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:385
Index get_num_meshes() const
Get the total number of meshes (not instances).
Definition EmbreeRayCaster.h:131
void release_scenes()
Release internal Embree scenes.
Definition EmbreeRayCaster.h:778
Transform get_transform(Index mesh_index, Index instance_index) const
Get the transform applied to a given mesh instance.
Definition EmbreeRayCaster.h:279
const unsigned * extract_int_data(const RaycasterMesh &mesh)
Get the index data of a mesh as an array of integers.
Definition EmbreeRayCaster.h:936
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:164
Definition RayCasterMesh.h:43
Definition RayCasterMesh.h:22
#define la_runtime_assert(...)
Runtime assertion check.
Definition assert.h:174
#define la_debug_assert(...)
Debug assertion check.
Definition assert.h:194
constexpr T invalid()
You can use invalid<T>() to get a value that can represent "invalid" values, such as invalid indices ...
Definition invalid.h:40
constexpr auto safe_cast(SourceType value) -> std::enable_if_t<!std::is_same< SourceType, TargetType >::value, TargetType >
Perform safe cast from SourceType to TargetType, where "safe" means:
Definition safe_cast.h:50
Raycasting operations.
Definition ClosestPointResult.h:21
Main namespace for Lagrange.
Definition ClosestPointResult.h:25