14#ifdef LAGRANGE_WITH_EMBREE_3
15 #include <embree3/rtcore.h>
16 #include <embree3/rtcore_geometry.h>
17 #include <embree3/rtcore_ray.h>
19 #include <embree4/rtcore.h>
20 #include <embree4/rtcore_geometry.h>
21 #include <embree4/rtcore_ray.h>
24#include <lagrange/common.h>
25#include <lagrange/legacy/inline.h>
26#include <lagrange/raycasting/ClosestPointResult.h>
27#include <lagrange/raycasting/EmbreeHelper.h>
28#include <lagrange/raycasting/RayCasterMesh.h>
29#include <lagrange/raycasting/embree_closest_point.h>
30#include <lagrange/utils/safe_cast.h>
57template <
typename ScalarType>
61 using Scalar = ScalarType;
62 using Transform = Eigen::Matrix<Scalar, 4, 4>;
63 using Point = Eigen::Matrix<Scalar, 3, 1>;
64 using Direction = Eigen::Matrix<Scalar, 3, 1>;
67 using TransformVector = std::vector<Transform>;
69 using Point4 = Eigen::Matrix<Scalar, 4, 3>;
70 using Direction4 = Eigen::Matrix<Scalar, 4, 3>;
71 using Index4 = Eigen::Matrix<size_t, 4, 1>;
72 using Scalar4 = Eigen::Matrix<Scalar, 4, 1>;
73 using Mask4 = Eigen::Matrix<std::int32_t, 4, 1>;
75 using FloatData = std::vector<float>;
76 using IntData = std::vector<unsigned>;
94 const Index* mesh_index,
95 const Index* instance_index,
96 const RTCFilterFunctionNArguments* args)>;
100 enum { FILTER_INTERSECT = 0, FILTER_OCCLUDED = 1 };
105 RTCSceneFlags scene_flags = RTC_SCENE_FLAG_DYNAMIC,
106 RTCBuildQuality build_quality = RTC_BUILD_QUALITY_LOW)
112#ifdef _MM_SET_FLUSH_ZERO_MODE
113 _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
115#ifdef _MM_SET_DENORMALS_ZERO_MODE
116 _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
119 m_scene_flags = scene_flags;
120 m_build_quality = build_quality;
121 m_device = rtcNewDevice(NULL);
122 ensure_no_errors_internal();
123 m_embree_world_scene = rtcNewScene(m_device);
124 ensure_no_errors_internal();
127 m_need_rebuild =
true;
128 m_need_commit =
false;
135 rtcReleaseDevice(m_device);
153 m_instance_index_ranges[mesh_index + 1] - m_instance_index_ranges[mesh_index]);
160 template <
typename MeshType>
161 std::shared_ptr<MeshType>
get_mesh(Index index)
const
179 return m_instance_to_user_mesh[cumulative_instance_index];
188 template <
typename MeshType>
190 std::shared_ptr<MeshType> mesh,
191 const Transform& trans = Transform::Identity(),
192 RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM)
206 template <
typename MeshType>
208 std::shared_ptr<MeshType> mesh,
209 const TransformVector& trans_vector,
210 RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM)
213 m_transforms.insert(m_transforms.end(), trans_vector.begin(), trans_vector.end());
214 m_mesh_build_qualities.push_back(build_quality);
215 m_visibility.resize(m_visibility.size() + trans_vector.size(),
true);
216 for (
auto& f : m_filters) {
217 f.push_back(
nullptr);
221 Index instance_index = m_instance_index_ranges.back();
223 Index new_instance_size = instance_index + trans_vector.size();
224 m_instance_index_ranges.push_back(new_instance_size);
225 m_instance_to_user_mesh.resize(new_instance_size, mesh_index);
226 m_need_rebuild =
true;
236 template <
typename MeshType>
239 std::shared_ptr<MeshType> mesh,
240 RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM)
242 update_raycasting_mesh(
256 if (m_need_rebuild)
return;
259 auto geom = rtcGetGeometry(m_embree_mesh_scenes[index], 0);
262 auto const& mesh = m_meshes[index];
267 reinterpret_cast<float*
>(rtcGetGeometryBufferData(geom, RTC_BUFFER_TYPE_VERTEX, 0));
269 mesh->vertices_to_float(vbuf);
270 rtcUpdateGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, 0);
273 rtcCommitGeometry(geom);
274 rtcCommitScene(m_embree_mesh_scenes[index]);
277 for (Index instance_index = m_instance_index_ranges[index];
278 instance_index < m_instance_index_ranges[index + 1];
280 Index rtc_inst_id = m_instance_index_ranges[index] + instance_index;
282 rtcGetGeometry(m_embree_world_scene,
static_cast<unsigned>(rtc_inst_id));
283 rtcCommitGeometry(geom_inst);
287 m_need_commit =
true;
294 Index index = m_instance_index_ranges[mesh_index] + instance_index;
297 return m_transforms[index];
304 Index index = m_instance_index_ranges[mesh_index] + instance_index;
307 m_transforms[index] = trans;
308 if (!m_need_rebuild) {
309 auto geom = rtcGetGeometry(m_embree_world_scene,
static_cast<unsigned>(index));
310 Eigen::Matrix<float, 4, 4> T = trans.template
cast<float>();
311 rtcSetGeometryTransform(geom, 0, RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR, T.eval().data());
312 rtcCommitGeometry(geom);
313 m_need_commit =
true;
321 Index index = m_instance_index_ranges[mesh_index] + instance_index;
324 return m_visibility[index];
331 Index index = m_instance_index_ranges[mesh_index] + instance_index;
334 m_visibility[index] = visible;
335 if (!m_need_rebuild &&
336 rtcGetDeviceProperty(m_device, RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED)) {
339 auto geom = rtcGetGeometry(m_embree_world_scene,
static_cast<unsigned>(index));
340 rtcSetGeometryMask(geom, visible ? 0xFFFFFFFF : 0x00000000);
341 rtcCommitGeometry(geom);
342 m_need_commit =
true;
365 m_filters[FILTER_INTERSECT][mesh_index] = filter;
366 m_need_rebuild =
true;
378 return m_filters[FILTER_INTERSECT][mesh_index];
400 m_filters[FILTER_OCCLUDED][mesh_index] = filter;
401 m_need_rebuild =
true;
413 return m_filters[FILTER_OCCLUDED][mesh_index];
425 if (!m_need_commit)
return;
427 rtcCommitScene(m_embree_world_scene);
428 m_need_commit =
false;
440 const Point4& origin,
441 const Direction4& direction,
444 Index4& instance_index,
447 Point4& barycentric_coord,
449 const Scalar4& tmin = Scalar4::Zero(),
450 const Scalar4& tmax = Scalar4::Constant(std::numeric_limits<Scalar>::infinity()))
456 RTCRayHit4 embree_raypacket;
457 for (
int i = 0; i < static_cast<int>(batch_size); ++i) {
459 embree_raypacket.ray.org_x[i] =
static_cast<float>(origin(i, 0));
460 embree_raypacket.ray.org_y[i] =
static_cast<float>(origin(i, 1));
461 embree_raypacket.ray.org_z[i] =
static_cast<float>(origin(i, 2));
464 embree_raypacket.ray.dir_x[i] =
static_cast<float>(direction(i, 0));
465 embree_raypacket.ray.dir_y[i] =
static_cast<float>(direction(i, 1));
466 embree_raypacket.ray.dir_z[i] =
static_cast<float>(direction(i, 2));
469 embree_raypacket.ray.tnear[i] =
static_cast<float>(tmin[i]);
470 embree_raypacket.ray.tfar[i] = std::isinf(tmax[i]) ? std::numeric_limits<float>::max()
471 :
static_cast<float>(tmax[i]);
472 embree_raypacket.ray.mask[i] = 0xFFFFFFFF;
473 embree_raypacket.ray.id[i] =
static_cast<unsigned>(i);
474 embree_raypacket.ray.flags[i] = 0;
477 embree_raypacket.hit.geomID[i] = RTC_INVALID_GEOMETRY_ID;
478 embree_raypacket.hit.primID[i] = RTC_INVALID_GEOMETRY_ID;
479 embree_raypacket.hit.instID[0][i] = RTC_INVALID_GEOMETRY_ID;
483 auto packet_mask = mask;
484 for (
int i =
static_cast<int>(batch_size); i < 4; ++i) packet_mask[i] = 0;
486 ensure_no_errors_internal();
487#ifdef LAGRANGE_WITH_EMBREE_3
488 RTCIntersectContext context;
489 rtcInitIntersectContext(&context);
490 rtcIntersect4(packet_mask.data(), m_embree_world_scene, &context, &embree_raypacket);
492 rtcIntersect4(packet_mask.data(), m_embree_world_scene, &embree_raypacket);
494 ensure_no_errors_internal();
496 uint32_t is_hits = 0;
497 for (
int i = 0; i < static_cast<int>(batch_size); ++i) {
498 if (embree_raypacket.hit.geomID[i] != RTC_INVALID_GEOMETRY_ID) {
499 Index rtc_inst_id = embree_raypacket.hit.instID[0][i];
500 Index rtc_mesh_id = (rtc_inst_id == RTC_INVALID_GEOMETRY_ID)
501 ? embree_raypacket.hit.geomID[i]
503 assert(rtc_mesh_id < m_instance_to_user_mesh.size());
504 assert(m_visibility[rtc_mesh_id]);
505 mesh_index[i] = m_instance_to_user_mesh[rtc_mesh_id];
506 assert(mesh_index[i] + 1 < m_instance_index_ranges.size());
508 instance_index[i] = rtc_mesh_id - m_instance_index_ranges[mesh_index[i]];
509 facet_index[i] = embree_raypacket.hit.primID[i];
510 ray_depth[i] = embree_raypacket.ray.tfar[i];
511 barycentric_coord(i, 0) =
512 1.0f - embree_raypacket.hit.u[i] - embree_raypacket.hit.v[i];
513 barycentric_coord(i, 1) = embree_raypacket.hit.u[i];
514 barycentric_coord(i, 2) = embree_raypacket.hit.v[i];
515 normal(i, 0) = embree_raypacket.hit.Ng_x[i];
516 normal(i, 1) = embree_raypacket.hit.Ng_y[i];
517 normal(i, 2) = embree_raypacket.hit.Ng_z[i];
518 is_hits = is_hits | (1 << i);
531 const Point4& origin,
532 const Direction4& direction,
537 Point4& barycentric_coord,
538 const Scalar4& tmin = Scalar4::Zero(),
539 const Scalar4& tmax = Scalar4::Constant(std::numeric_limits<Scalar>::infinity()))
541 Index4 instance_index;
563 const Point4& origin,
564 const Direction4& direction,
566 const Scalar4& tmin = Scalar4::Zero(),
567 const Scalar4& tmax = Scalar4::Constant(std::numeric_limits<Scalar>::infinity()))
573 RTCRay4 embree_raypacket;
574 for (
int i = 0; i < static_cast<int>(batch_size); ++i) {
576 embree_raypacket.org_x[i] =
static_cast<float>(origin(i, 0));
577 embree_raypacket.org_y[i] =
static_cast<float>(origin(i, 1));
578 embree_raypacket.org_z[i] =
static_cast<float>(origin(i, 2));
581 embree_raypacket.dir_x[i] =
static_cast<float>(direction(i, 0));
582 embree_raypacket.dir_y[i] =
static_cast<float>(direction(i, 1));
583 embree_raypacket.dir_z[i] =
static_cast<float>(direction(i, 2));
586 embree_raypacket.tnear[i] =
static_cast<float>(tmin[i]);
587 embree_raypacket.tfar[i] = std::isinf(tmax[i]) ? std::numeric_limits<float>::max()
588 :
static_cast<float>(tmax[i]);
589 embree_raypacket.mask[i] = 0xFFFFFFFF;
590 embree_raypacket.id[i] =
static_cast<unsigned>(i);
591 embree_raypacket.flags[i] = 0;
595 auto packet_mask = mask;
596 for (
int i =
static_cast<int>(batch_size); i < 4; ++i) packet_mask[i] = 0;
598 ensure_no_errors_internal();
599#ifdef LAGRANGE_WITH_EMBREE_3
600 RTCIntersectContext context;
601 rtcInitIntersectContext(&context);
602 rtcOccluded4(packet_mask.data(), m_embree_world_scene, &context, &embree_raypacket);
604 rtcOccluded4(packet_mask.data(), m_embree_world_scene, &embree_raypacket);
606 ensure_no_errors_internal();
609 uint32_t is_hits = 0;
610 for (uint32_t i = 0; i < batch_size; ++i)
611 if (!std::isfinite(embree_raypacket.tfar[i])) is_hits = is_hits | (1 << i);
622 const Direction& direction,
624 Index& instance_index,
627 Point& barycentric_coord,
630 Scalar tmax = std::numeric_limits<Scalar>::infinity())
636 RTCRayHit embree_rayhit;
637 embree_rayhit.ray.org_x =
static_cast<float>(origin.x());
638 embree_rayhit.ray.org_y =
static_cast<float>(origin.y());
639 embree_rayhit.ray.org_z =
static_cast<float>(origin.z());
640 embree_rayhit.ray.dir_x =
static_cast<float>(direction.x());
641 embree_rayhit.ray.dir_y =
static_cast<float>(direction.y());
642 embree_rayhit.ray.dir_z =
static_cast<float>(direction.z());
643 embree_rayhit.ray.tnear =
static_cast<float>(tmin);
644 embree_rayhit.ray.tfar =
645 std::isinf(tmax) ? std::numeric_limits<float>::max() :
static_cast<float>(tmax);
646 embree_rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID;
647 embree_rayhit.hit.primID = RTC_INVALID_GEOMETRY_ID;
648 embree_rayhit.hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
649 embree_rayhit.ray.mask = 0xFFFFFFFF;
650 embree_rayhit.ray.id = 0;
651 embree_rayhit.ray.flags = 0;
652 ensure_no_errors_internal();
653#ifdef LAGRANGE_WITH_EMBREE_3
654 RTCIntersectContext context;
655 rtcInitIntersectContext(&context);
656 rtcIntersect1(m_embree_world_scene, &context, &embree_rayhit);
658 rtcIntersect1(m_embree_world_scene, &embree_rayhit);
660 ensure_no_errors_internal();
662 if (embree_rayhit.hit.geomID != RTC_INVALID_GEOMETRY_ID) {
663 Index rtc_inst_id = embree_rayhit.hit.instID[0];
665 (rtc_inst_id == RTC_INVALID_GEOMETRY_ID) ? embree_rayhit.hit.geomID : rtc_inst_id;
666 assert(rtc_mesh_id < m_instance_to_user_mesh.size());
667 assert(m_visibility[rtc_mesh_id]);
668 mesh_index = m_instance_to_user_mesh[rtc_mesh_id];
669 assert(mesh_index + 1 < m_instance_index_ranges.size());
671 instance_index = rtc_mesh_id - m_instance_index_ranges[mesh_index];
672 facet_index = embree_rayhit.hit.primID;
673 ray_depth = embree_rayhit.ray.tfar;
674 barycentric_coord[0] = 1.0f - embree_rayhit.hit.u - embree_rayhit.hit.v;
675 barycentric_coord[1] = embree_rayhit.hit.u;
676 barycentric_coord[2] = embree_rayhit.hit.v;
677 normal[0] = embree_rayhit.hit.Ng_x;
678 normal[1] = embree_rayhit.hit.Ng_y;
679 normal[2] = embree_rayhit.hit.Ng_z;
696 const Direction& direction,
700 Point& barycentric_coord,
702 Scalar tmax = std::numeric_limits<Scalar>::infinity())
704 Index instance_index;
722 const Direction& direction,
724 Scalar tmax = std::numeric_limits<Scalar>::infinity())
729 embree_ray.org_x =
static_cast<float>(origin.x());
730 embree_ray.org_y =
static_cast<float>(origin.y());
731 embree_ray.org_z =
static_cast<float>(origin.z());
732 embree_ray.dir_x =
static_cast<float>(direction.x());
733 embree_ray.dir_y =
static_cast<float>(direction.y());
734 embree_ray.dir_z =
static_cast<float>(direction.z());
735 embree_ray.tnear =
static_cast<float>(tmin);
737 std::isinf(tmax) ? std::numeric_limits<float>::max() :
static_cast<float>(tmax);
738 embree_ray.mask = 0xFFFFFFFF;
740 embree_ray.flags = 0;
742 ensure_no_errors_internal();
743#ifdef LAGRANGE_WITH_EMBREE_3
744 RTCIntersectContext context;
745 rtcInitIntersectContext(&context);
746 rtcOccluded1(m_embree_world_scene, &context, &embree_ray);
748 rtcOccluded1(m_embree_world_scene, &embree_ray);
750 ensure_no_errors_internal();
753 return !std::isfinite(embree_ray.tfar);
761 std::unique_ptr<RaycasterMesh> mesh,
762 const Transform& trans = Transform::Identity(),
763 RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM)
765 m_meshes.push_back(std::move(mesh));
766 m_transforms.push_back(trans);
767 m_mesh_build_qualities.push_back(build_quality);
768 m_visibility.push_back(
true);
769 for (
auto& f : m_filters) {
770 f.push_back(
nullptr);
774 Index instance_index = m_instance_index_ranges.back();
776 m_instance_index_ranges.push_back(instance_index + 1);
777 m_instance_to_user_mesh.resize(instance_index + 1, mesh_index);
778 m_need_rebuild =
true;
782 void update_raycasting_mesh(
784 std::unique_ptr<RaycasterMesh> mesh,
785 RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM)
790 m_meshes[index] = std::move(mesh);
791 m_mesh_build_qualities[index] = build_quality;
792 m_need_rebuild =
true;
800 for (
auto& s : m_embree_mesh_scenes) {
803 rtcReleaseScene(m_embree_world_scene);
817 else if (m_need_commit)
829 if (!m_need_rebuild)
return;
833 m_embree_world_scene = rtcNewScene(m_device);
837 m_embree_world_scene,
839 rtcSetSceneBuildQuality(m_embree_world_scene, scene_build_quality);
840 m_float_data.clear();
842 const auto num_meshes = m_meshes.size();
844 m_embree_mesh_scenes.resize(num_meshes);
845 m_mesh_vertex_counts.resize(num_meshes);
846 ensure_no_errors_internal();
848 bool is_mask_supported =
849 rtcGetDeviceProperty(m_device, RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED);
850 for (
size_t i = 0; i < num_meshes; i++) {
852 const auto& mesh = m_meshes[i];
855 const Index num_vertices = m_mesh_vertex_counts[i] =
859 auto& embree_mesh_scene = m_embree_mesh_scenes[i];
860 embree_mesh_scene = rtcNewScene(m_device);
862 rtcSetSceneFlags(embree_mesh_scene, scene_flags);
863 rtcSetSceneBuildQuality(embree_mesh_scene, scene_build_quality);
864 ensure_no_errors_internal();
866 RTCGeometry geom = rtcNewGeometry(
868 RTC_GEOMETRY_TYPE_TRIANGLE);
870 rtcSetGeometryBuildQuality(geom, m_mesh_build_qualities[i]);
876 rtcSetSharedGeometryBuffer(
878 RTC_BUFFER_TYPE_VERTEX,
885 rtcSetSharedGeometryBuffer(
887 RTC_BUFFER_TYPE_INDEX,
898 rtcCommitGeometry(geom);
899 rtcAttachGeometry(embree_mesh_scene, geom);
900 rtcReleaseGeometry(geom);
901 ensure_no_errors_internal();
904 for (Index instance_index = m_instance_index_ranges[i];
905 instance_index < m_instance_index_ranges[i + 1];
907 const auto& trans = m_transforms[instance_index];
909 RTCGeometry geom_inst = rtcNewGeometry(
911 RTC_GEOMETRY_TYPE_INSTANCE);
913 rtcSetGeometryInstancedScene(geom_inst, embree_mesh_scene);
914 rtcSetGeometryTimeStepCount(geom_inst, 1);
916 Eigen::Matrix<float, 4, 4> T = trans.template
cast<float>();
917 rtcSetGeometryTransform(geom_inst, 0, RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR, T.data());
918 ensure_no_errors_internal();
920 if (is_mask_supported) {
923 m_visibility[instance_index] ? 0xFFFFFFFF : 0x00000000);
925 ensure_no_errors_internal();
927 rtcCommitGeometry(geom_inst);
928 unsigned rtc_instance_id = rtcAttachGeometry(m_embree_world_scene, geom_inst);
929 rtcReleaseGeometry(geom_inst);
931 ensure_no_errors_internal();
934 rtcCommitScene(embree_mesh_scene);
935 ensure_no_errors_internal();
937 rtcCommitScene(m_embree_world_scene);
938 ensure_no_errors_internal();
940 m_need_rebuild = m_need_commit =
false;
946 auto float_data = mesh.vertices_to_float();
950 float_data.push_back(0.0);
951 m_float_data.emplace_back(std::move(float_data));
952 return m_float_data.back().data();
958 auto int_data = mesh.indices_to_int();
962 int_data.push_back(0);
963 m_int_data.emplace_back(std::move(int_data));
964 return m_int_data.back().data();
974 if (is_mask_supported) {
976 rtcSetGeometryUserData(geom,
this);
977 rtcSetGeometryIntersectFilterFunction(geom, &wrap_filter<FILTER_INTERSECT>);
979 rtcSetGeometryIntersectFilterFunction(geom,
nullptr);
982 rtcSetGeometryUserData(geom,
this);
983 rtcSetGeometryIntersectFilterFunction(geom, &wrap_filter_and_mask<FILTER_INTERSECT>);
993 if (is_mask_supported) {
995 rtcSetGeometryUserData(geom,
this);
996 rtcSetGeometryOccludedFilterFunction(geom, &wrap_filter<FILTER_OCCLUDED>);
998 rtcSetGeometryOccludedFilterFunction(geom,
nullptr);
1001 rtcSetGeometryUserData(geom,
this);
1002 rtcSetGeometryOccludedFilterFunction(geom, &wrap_filter_and_mask<FILTER_OCCLUDED>);
1010 template <
int IntersectionOrOcclusion>
1011 static void wrap_filter(
const RTCFilterFunctionNArguments* args)
1016 const auto* obj =
reinterpret_cast<EmbreeRayCaster*
>(args->geometryUserPtr);
1017 auto rtc_inst_id = RTCHitN_instID(args->hit, args->N, 0, 0);
1018 assert(rtc_inst_id < obj->m_instance_to_user_mesh.size());
1020 auto filter = obj->m_filters[IntersectionOrOcclusion][rtc_inst_id];
1025 Index mesh_index = obj->m_instance_to_user_mesh[rtc_inst_id];
1026 assert(mesh_index + 1 < obj->m_instance_index_ranges.size());
1028 Index instance_index = rtc_inst_id - obj->m_instance_index_ranges[mesh_index];
1033 mesh_index4.fill(mesh_index);
1034 Index4 instance_index4;
1035 instance_index4.fill(instance_index);
1038 filter(obj, mesh_index4.data(), instance_index4.data(), args);
1046 template <
int IntersectionOrOcclusion>
1047 static void wrap_filter_and_mask(
const RTCFilterFunctionNArguments* args)
1052 const auto* obj =
reinterpret_cast<EmbreeRayCaster*
>(args->geometryUserPtr);
1053 auto rtc_inst_id = RTCHitN_instID(args->hit, args->N, 0, 0);
1054 if (!obj->m_visibility[rtc_inst_id]) {
1056 std::fill(args->valid, args->valid + args->N, 0);
1061 wrap_filter<IntersectionOrOcclusion>(args);
1065 RTCSceneFlags m_scene_flags;
1066 RTCBuildQuality m_build_quality;
1068 RTCScene m_embree_world_scene;
1069 bool m_need_rebuild;
1074 std::vector<FloatData> m_float_data;
1075 std::vector<IntData> m_int_data;
1076 std::vector<std::unique_ptr<RaycasterMesh>> m_meshes;
1077 std::vector<RTCBuildQuality> m_mesh_build_qualities;
1078 std::vector<RTCScene> m_embree_mesh_scenes;
1079 std::vector<Index> m_mesh_vertex_counts;
1080 std::vector<FilterFunction> m_filters[2];
1087 std::vector<Index> m_instance_index_ranges;
1097 std::vector<Index> m_instance_to_user_mesh;
1101 std::vector<Transform> m_transforms;
1102 std::vector<bool> m_visibility;
1105 void ensure_no_errors_internal()
const
1107#ifdef LAGRANGE_EMBREE_DEBUG
1108 EmbreeHelper::ensure_no_errors(m_device);
1117template <
typename Scalar>
1120 RTCPointQuery query;
1121 query.x = (float)(p.x());
1122 query.y = (float)(p.y());
1123 query.z = (float)(p.z());
1124 query.radius = std::numeric_limits<float>::max();
1126 ensure_no_errors_internal();
1128 ClosestPoint result;
1131 result.populate_triangle =
1132 [&](
unsigned mesh_index,
unsigned facet_index, Point& v0, Point& v1, Point& v2) {
1138 const unsigned* face = m_int_data[mesh_index].data() + 3 * facet_index;
1139 const float* vertices = m_float_data[mesh_index].data();
1140 v0 = Point(vertices[3 * face[0]], vertices[3 * face[0] + 1], vertices[3 * face[0] + 2]);
1141 v1 = Point(vertices[3 * face[1]], vertices[3 * face[1] + 1], vertices[3 * face[1] + 2]);
1142 v2 = Point(vertices[3 * face[2]], vertices[3 * face[2] + 1], vertices[3 * face[2] + 2]);
1146 RTCPointQueryContext context;
1147 rtcInitPointQueryContext(&context);
1149 m_embree_world_scene,
1152 &embree_closest_point<Scalar>,
1153 reinterpret_cast<void*
>(&result));
1155 result.mesh_index != RTC_INVALID_GEOMETRY_ID ||
1156 result.facet_index != RTC_INVALID_GEOMETRY_ID);
1160 ensure_no_errors_internal();
A wrapper for Embree's raycasting API to compute ray intersections with (instances of) meshes.
Definition EmbreeRayCaster.h:59
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:207
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:760
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:189
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:561
FilterFunction get_intersection_filter(Index mesh_index) const
Get the intersection filter function currently bound to a given mesh.
Definition EmbreeRayCaster.h:375
Index get_num_instances(Index mesh_index) const
Get the number of instances of a particular mesh.
Definition EmbreeRayCaster.h:149
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:237
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:362
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:620
virtual ~EmbreeRayCaster()
Destructor.
Definition EmbreeRayCaster.h:132
void generate_scene()
Build the whole Embree scene from the specified meshes, instances, etc.
Definition EmbreeRayCaster.h:827
bool get_visibility(Index mesh_index, Index instance_index) const
Get the visibility flag of a given mesh instance.
Definition EmbreeRayCaster.h:318
virtual RTCSceneFlags get_scene_flags() const
Get the Embree scene flags.
Definition EmbreeRayCaster.h:807
const float * extract_float_data(const RaycasterMesh &mesh)
Get the vertex data of a mesh as an array of floats.
Definition EmbreeRayCaster.h:944
void update_transformation(Index mesh_index, Index instance_index, const Transform &trans)
Update the transform applied to a given mesh instance.
Definition EmbreeRayCaster.h:301
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:253
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:438
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:694
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:529
Index get_num_instances() const
Get the total number of mesh instances.
Definition EmbreeRayCaster.h:146
void update_internal()
Update all internal structures based on the current dirty flags.
Definition EmbreeRayCaster.h:813
FilterFunction get_occlusion_filter(Index mesh_index) const
Get the occlusion filter function currently bound to a given mesh.
Definition EmbreeRayCaster.h:410
virtual RTCBuildQuality get_scene_build_quality() const
Get the Embree geometry build quality.
Definition EmbreeRayCaster.h:810
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:92
void ensure_no_errors() const
Throw an exception if an Embree error has occurred.
Definition EmbreeRayCaster.h:432
std::shared_ptr< MeshType > get_mesh(Index index) const
Get the mesh with a given index.
Definition EmbreeRayCaster.h:161
EmbreeRayCaster(RTCSceneFlags scene_flags=RTC_SCENE_FLAG_DYNAMIC, RTCBuildQuality build_quality=RTC_BUILD_QUALITY_LOW)
Constructor.
Definition EmbreeRayCaster.h:104
void commit_scene_changes()
Call rtcCommitScene() on the overall scene, if it has been marked as modified.
Definition EmbreeRayCaster.h:423
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:720
ClosestPoint query_closest_point(const Point &p) const
Use the underlying BVH to find the point closest to a query point.
Definition EmbreeRayCaster.h:1118
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:328
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:397
Index get_num_meshes() const
Get the total number of meshes (not instances).
Definition EmbreeRayCaster.h:143
void release_scenes()
Release internal Embree scenes.
Definition EmbreeRayCaster.h:798
Transform get_transform(Index mesh_index, Index instance_index) const
Get the transform applied to a given mesh instance.
Definition EmbreeRayCaster.h:291
const unsigned * extract_int_data(const RaycasterMesh &mesh)
Get the index data of a mesh as an array of integers.
Definition EmbreeRayCaster.h:956
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:176
Definition RayCasterMesh.h:46
Definition RayCasterMesh.h:25
#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:22
@ ClosestPoint
Interpolate attribute from the closest point on the source mesh.
Definition Options.h:35
Main namespace for Lagrange.
Definition ClosestPointResult.h:28