Lagrange
Loading...
Searching...
No Matches
RayCaster.h
1/*
2 * Copyright 2017 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12#pragma once
13
14#include <lagrange/SurfaceMesh.h>
15#include <lagrange/raycasting/api.h>
16#include <lagrange/scene/SimpleScene.h>
17#include <lagrange/utils/BitField.h>
18#include <lagrange/utils/value_ptr.h>
19
20#include <Eigen/Core>
21
22#include <cstdint>
23#include <functional>
24#include <limits>
25#include <memory>
26#include <optional>
27#include <variant>
28
29namespace lagrange::raycasting {
30
34struct HitBase
35{
38
41
44
48 Eigen::Vector2f barycentric_coord = Eigen::Vector2f::Zero();
49
51 Eigen::Vector3f position = Eigen::Vector3f::Zero();
52};
53
57struct ClosestPointHit : public HitBase
58{
60 float distance = std::numeric_limits<float>::infinity();
61};
62
66struct RayHit : public HitBase
67{
69 float ray_depth = 0;
70
72 Eigen::Vector3f normal = Eigen::Vector3f::Zero();
73};
74
80template <size_t N>
82{
84 uint32_t valid_mask = 0;
85
87 Eigen::Vector<uint32_t, N> mesh_indices =
88 Eigen::Vector<uint32_t, N>::Constant(invalid<uint32_t>());
89
91 Eigen::Vector<uint32_t, N> instance_indices =
92 Eigen::Vector<uint32_t, N>::Constant(invalid<uint32_t>());
93
95 Eigen::Vector<uint32_t, N> facet_indices =
96 Eigen::Vector<uint32_t, N>::Constant(invalid<uint32_t>());
97
101 Eigen::Matrix<float, 2, N> barycentric_coords = Eigen::Matrix<float, 2, N>::Zero();
102
104 Eigen::Matrix<float, 3, N> positions = Eigen::Matrix<float, 3, N>::Zero();
105
106 bool is_valid(size_t i) const { return (valid_mask & (1u << i)) != 0; }
107};
108
114template <size_t N>
115struct ClosestPointHitN : public HitBaseN<N>
116{
118 Eigen::Vector<float, N> distances =
119 Eigen::Vector<float, N>::Constant(std::numeric_limits<float>::infinity());
120};
121
127template <size_t N>
128struct RayHitN : public HitBaseN<N>
129{
131 Eigen::Vector<float, N> ray_depths = Eigen::Vector<float, N>::Zero();
132
134 Eigen::Matrix<float, 3, N> normals = Eigen::Matrix<float, 3, N>::Zero();
135};
136
139enum class SceneFlags {
141 None = 0,
142
144 Dynamic = 1 << 0,
145
147 Compact = 1 << 1,
148
151 Robust = 1 << 2,
152
154 Filter = 1 << 3,
155};
156
161enum class BuildQuality {
163 Low = 0,
164
167
169 High = 2,
170};
171
190{
191public:
193 using Pointf = Eigen::Vector3f;
194
196 using Directionf = Eigen::Vector3f;
197
199 template <typename Scalar>
200 using Affine = Eigen::Transform<Scalar, 3, Eigen::Affine>;
201
203 using Hit = RayHit;
204
207 using Point4f = Eigen::Matrix<float, 4, 3, Eigen::RowMajor>;
208 using Direction4f = Eigen::Matrix<float, 4, 3, Eigen::RowMajor>;
209 using Float4 = Eigen::Vector<float, 4>;
210 using Mask4 = Eigen::Vector<bool, 4>;
211 using RayHit4 = RayHitN<4>;
212 using ClosestPointHit4 = ClosestPointHitN<4>;
214
217 using Point8f = Eigen::Matrix<float, 8, 3, Eigen::RowMajor>;
218 using Direction8f = Eigen::Matrix<float, 8, 3, Eigen::RowMajor>;
219 using Float8 = Eigen::Vector<float, 8>;
220 using Mask8 = Eigen::Vector<bool, 8>;
221 using RayHit8 = RayHitN<8>;
222 using ClosestPointHit8 = ClosestPointHitN<8>;
224
227 using Point16f = Eigen::Matrix<float, 16, 3, Eigen::RowMajor>;
228 using Direction16f = Eigen::Matrix<float, 16, 3, Eigen::RowMajor>;
229 using Float16 = Eigen::Vector<float, 16>;
230 using Mask16 = Eigen::Vector<bool, 16>;
231 using RayHit16 = RayHitN<16>;
232 using ClosestPointHit16 = ClosestPointHitN<16>;
234
235public:
238
245 explicit RayCaster(
247 BuildQuality build_quality = BuildQuality::Medium);
248
251
253 RayCaster(RayCaster&& other) noexcept;
254
256 RayCaster& operator=(RayCaster&& other) noexcept;
257
259 RayCaster(const RayCaster&) = delete;
260
262 RayCaster& operator=(const RayCaster&) = delete;
263
265
268
289 template <typename Scalar, typename Index>
290 uint32_t add_mesh(
292 const std::optional<Affine<Scalar>>& transform = Affine<Scalar>::Identity());
293
308 uint32_t add_instance(uint32_t mesh_index, const Eigen::Affine3f& transform);
309
320 template <typename Scalar, typename Index>
322
328 void commit_updates();
329
331
334
345 template <typename Scalar, typename Index>
346 void update_mesh(uint32_t mesh_index, const SurfaceMesh<Scalar, Index>& mesh);
347
363 template <typename Scalar, typename Index>
364 void update_vertices(uint32_t mesh_index, const SurfaceMesh<Scalar, Index>& mesh);
365
375 template <typename Scalar>
376 void update_vertices(uint32_t mesh_index, span<const Scalar> vertices);
377
387 Eigen::Affine3f get_transform(uint32_t mesh_index, uint32_t instance_index) const;
388
397 void update_transform(
398 uint32_t mesh_index,
399 uint32_t instance_index,
400 const Eigen::Affine3f& transform);
401
410 bool get_visibility(uint32_t mesh_index, uint32_t instance_index);
411
419 void update_visibility(uint32_t mesh_index, uint32_t instance_index, bool visible);
420
422
425
433 auto get_intersection_filter(uint32_t mesh_index) const
434 -> std::function<bool(uint32_t instance_index, uint32_t facet_index)>;
435
444 uint32_t mesh_index,
445 std::function<bool(uint32_t instance_index, uint32_t facet_index)>&& filter);
446
454 auto get_occlusion_filter(uint32_t mesh_index) const
455 -> std::function<bool(uint32_t instance_index, uint32_t facet_index)>;
456
465 uint32_t mesh_index,
466 std::function<bool(uint32_t instance_index, uint32_t facet_index)>&& filter);
467
469
472
480 std::optional<ClosestPointHit> closest_point(const Pointf& query_point) const;
481
494 ClosestPointHit4 closest_point4(
495 const Point4f& query_points,
496 const std::variant<Mask4, size_t>& active) const;
497
510 ClosestPointHit8 closest_point8(
511 const Point8f& query_points,
512 const std::variant<Mask8, size_t>& active) const;
513
526 ClosestPointHit16 closest_point16(
527 const Point16f& query_points,
528 const std::variant<Mask16, size_t>& active) const;
529
531
534
545 std::optional<ClosestPointHit> closest_vertex(const Pointf& query_point) const;
546
559 ClosestPointHit4 closest_vertex4(
560 const Point4f& query_points,
561 const std::variant<Mask4, size_t>& active) const;
562
575 ClosestPointHit8 closest_vertex8(
576 const Point8f& query_points,
577 const std::variant<Mask8, size_t>& active) const;
578
591 ClosestPointHit16 closest_vertex16(
592 const Point16f& query_points,
593 const std::variant<Mask16, size_t>& active) const;
594
596
597
600
611 std::optional<RayHit> cast(
612 const Pointf& origin,
613 const Directionf& direction,
614 float tmin = 0,
615 float tmax = std::numeric_limits<float>::infinity()) const;
616
627 bool occluded(
628 const Pointf& origin,
629 const Directionf& direction,
630 float tmin = 0,
631 float tmax = std::numeric_limits<float>::infinity()) const;
632
634
637
651 RayHit4 cast4(
652 const Point4f& origins,
653 const Direction4f& directions,
654 const std::variant<Mask4, size_t>& active = size_t(4),
655 const Float4& tmin = Float4::Zero(),
656 const Float4& tmax = Float4::Constant(std::numeric_limits<float>::infinity())) const;
657
671 uint32_t occluded4(
672 const Point4f& origins,
673 const Direction4f& directions,
674 const std::variant<Mask4, size_t>& active = size_t(4),
675 const Float4& tmin = Float4::Zero(),
676 const Float4& tmax = Float4::Constant(std::numeric_limits<float>::infinity())) const;
677
679
682
696 RayHit8 cast8(
697 const Point8f& origins,
698 const Direction8f& directions,
699 const std::variant<Mask8, size_t>& active = size_t(8),
700 const Float8& tmin = Float8::Zero(),
701 const Float8& tmax = Float8::Constant(std::numeric_limits<float>::infinity())) const;
702
716 uint32_t occluded8(
717 const Point8f& origins,
718 const Direction8f& directions,
719 const std::variant<Mask8, size_t>& active = size_t(8),
720 const Float8& tmin = Float8::Zero(),
721 const Float8& tmax = Float8::Constant(std::numeric_limits<float>::infinity())) const;
722
724
727
741 RayHit16 cast16(
742 const Point16f& origins,
743 const Direction16f& directions,
744 const std::variant<Mask16, size_t>& active = size_t(16),
745 const Float16& tmin = Float16::Zero(),
746 const Float16& tmax = Float16::Constant(std::numeric_limits<float>::infinity())) const;
747
761 uint32_t occluded16(
762 const Point16f& origins,
763 const Direction16f& directions,
764 const std::variant<Mask16, size_t>& active = size_t(16),
765 const Float16& tmin = Float16::Zero(),
766 const Float16& tmax = Float16::Constant(std::numeric_limits<float>::infinity())) const;
767
769
770private:
771 struct Impl;
772 value_ptr<Impl> m_impl;
773};
774
775} // namespace lagrange::raycasting
Bit field utility class.
Definition BitField.h:33
A general purpose polygonal mesh class.
Definition SurfaceMesh.h:66
uint32_t occluded4(const Point4f &origins, const Direction4f &directions, const std::variant< Mask4, size_t > &active=size_t(4), const Float4 &tmin=Float4::Zero(), const Float4 &tmax=Float4::Constant(std::numeric_limits< float >::infinity())) const
Test a packet of up to 4 rays for occlusion.
Definition RayCaster.cpp:1475
std::optional< RayHit > cast(const Pointf &origin, const Directionf &direction, float tmin=0, float tmax=std::numeric_limits< float >::infinity()) const
Cast a single ray and find the closest intersection.
Definition RayCaster.cpp:1118
bool occluded(const Pointf &origin, const Directionf &direction, float tmin=0, float tmax=std::numeric_limits< float >::infinity()) const
Test whether a single ray hits anything in the scene (occlusion query).
Definition RayCaster.cpp:1183
void update_vertices(uint32_t mesh_index, const SurfaceMesh< Scalar, Index > &mesh)
Notify the raycaster that vertices of a mesh have been modified externally.
Definition RayCaster.cpp:782
void add_scene(scene::SimpleScene< Scalar, Index, 3 > simple_scene)
Add all meshes and instances from a SimpleScene.
Definition RayCaster.cpp:738
ClosestPointHit8 closest_vertex8(const Point8f &query_points, const std::variant< Mask8, size_t > &active) const
Find the closest vertex on the scene for a packet of up to 8 query points.
Definition RayCaster.cpp:1099
RayCaster(const RayCaster &)=delete
Non-copyable.
ClosestPointHit16 closest_point16(const Point16f &query_points, const std::variant< Mask16, size_t > &active) const
Find the closest point on the scene for a packet of up to 16 query points.
Definition RayCaster.cpp:1080
Eigen::Vector3f Pointf
3D point type.
Definition RayCaster.h:193
RayCaster & operator=(const RayCaster &)=delete
Non-copyable.
uint32_t add_mesh(SurfaceMesh< Scalar, Index > mesh, const std::optional< Affine< Scalar > > &transform=Affine< Scalar >::Identity())
Add a single mesh to the scene.
Definition RayCaster.cpp:710
uint32_t occluded16(const Point16f &origins, const Direction16f &directions, const std::variant< Mask16, size_t > &active=size_t(16), const Float16 &tmin=Float16::Zero(), const Float16 &tmax=Float16::Constant(std::numeric_limits< float >::infinity())) const
Test a packet of up to 16 rays for occlusion.
Definition RayCaster.cpp:1523
ClosestPointHit8 closest_point8(const Point8f &query_points, const std::variant< Mask8, size_t > &active) const
Find the closest point on the scene for a packet of up to 8 query points.
Definition RayCaster.cpp:1073
uint32_t occluded8(const Point8f &origins, const Direction8f &directions, const std::variant< Mask8, size_t > &active=size_t(8), const Float8 &tmin=Float8::Zero(), const Float8 &tmax=Float8::Constant(std::numeric_limits< float >::infinity())) const
Test a packet of up to 8 rays for occlusion.
Definition RayCaster.cpp:1499
auto get_intersection_filter(uint32_t mesh_index) const -> std::function< bool(uint32_t instance_index, uint32_t facet_index)>
Get the intersection filter function currently bound to a given mesh.
Definition RayCaster.cpp:897
RayHit4 cast4(const Point4f &origins, const Direction4f &directions, const std::variant< Mask4, size_t > &active=size_t(4), const Float4 &tmin=Float4::Zero(), const Float4 &tmax=Float4::Constant(std::numeric_limits< float >::infinity())) const
Cast a packet of up to 4 rays and find the closest intersections.
Definition RayCaster.cpp:1465
Eigen::Transform< Scalar, 3, Eigen::Affine > Affine
4x4 affine transform type (column-major).
Definition RayCaster.h:200
RayHit16 cast16(const Point16f &origins, const Direction16f &directions, const std::variant< Mask16, size_t > &active=size_t(16), const Float16 &tmin=Float16::Zero(), const Float16 &tmax=Float16::Constant(std::numeric_limits< float >::infinity())) const
Cast a packet of up to 16 rays and find the closest intersections.
Definition RayCaster.cpp:1513
std::optional< ClosestPointHit > closest_vertex(const Pointf &query_point) const
Find the closest vertex on the scene to a query point.
Definition RayCaster.cpp:1087
std::optional< ClosestPointHit > closest_point(const Pointf &query_point) const
Find the closest point on the scene to a query point.
Definition RayCaster.cpp:1061
RayHit Hit
Hit result type.
Definition RayCaster.h:203
ClosestPointHit4 closest_vertex4(const Point4f &query_points, const std::variant< Mask4, size_t > &active) const
Find the closest vertex on the scene for a packet of up to 4 query points.
Definition RayCaster.cpp:1092
RayCaster & operator=(RayCaster &&other) noexcept
Move assignment.
void update_transform(uint32_t mesh_index, uint32_t instance_index, const Eigen::Affine3f &transform)
Update the affine transform of a given mesh instance.
Definition RayCaster.cpp:829
RayHit8 cast8(const Point8f &origins, const Direction8f &directions, const std::variant< Mask8, size_t > &active=size_t(8), const Float8 &tmin=Float8::Zero(), const Float8 &tmax=Float8::Constant(std::numeric_limits< float >::infinity())) const
Cast a packet of up to 8 rays and find the closest intersections.
Definition RayCaster.cpp:1489
RayCaster(RayCaster &&other) noexcept
Move constructor.
RayCaster(BitField< SceneFlags > scene_flags=SceneFlags::Robust, BuildQuality build_quality=BuildQuality::Medium)
Construct a RayCaster with the given Embree scene configuration.
Definition RayCaster.cpp:692
Eigen::Affine3f get_transform(uint32_t mesh_index, uint32_t instance_index) const
Get the affine transform of a given mesh instance.
Definition RayCaster.cpp:818
void set_occlusion_filter(uint32_t mesh_index, std::function< bool(uint32_t instance_index, uint32_t facet_index)> &&filter)
Set an occlusion filter that is called for every hit on (every instance of) a mesh during an occlusio...
Definition RayCaster.cpp:929
void commit_updates()
Notify the raycaster that all pending updates have been made and the BVH can be rebuilt.
Definition RayCaster.cpp:747
auto get_occlusion_filter(uint32_t mesh_index) const -> std::function< bool(uint32_t instance_index, uint32_t facet_index)>
Get the occlusion filter function currently bound to a given mesh.
Definition RayCaster.cpp:920
uint32_t add_instance(uint32_t mesh_index, const Eigen::Affine3f &transform)
Add a single instance of an existing source mesh to the scene with a given affine transform.
Definition RayCaster.cpp:725
ClosestPointHit4 closest_point4(const Point4f &query_points, const std::variant< Mask4, size_t > &active) const
Find the closest point on the scene for a packet of up to 4 query points.
Definition RayCaster.cpp:1066
bool get_visibility(uint32_t mesh_index, uint32_t instance_index)
Get the visibility flag of a given mesh instance.
Definition RayCaster.cpp:857
void update_mesh(uint32_t mesh_index, const SurfaceMesh< Scalar, Index > &mesh)
Replace a mesh in the scene.
Definition RayCaster.cpp:757
Eigen::Vector3f Directionf
3D direction type.
Definition RayCaster.h:196
ClosestPointHit16 closest_vertex16(const Point16f &query_points, const std::variant< Mask16, size_t > &active) const
Find the closest vertex on the scene for a packet of up to 16 query points.
Definition RayCaster.cpp:1106
void update_visibility(uint32_t mesh_index, uint32_t instance_index, bool visible)
Update the visibility of a given mesh instance.
Definition RayCaster.cpp:868
void set_intersection_filter(uint32_t mesh_index, std::function< bool(uint32_t instance_index, uint32_t facet_index)> &&filter)
Set an intersection filter that is called for every hit on (every instance of) a mesh during an inter...
Definition RayCaster.cpp:906
Simple scene container for instanced meshes.
Definition SimpleScene.h:62
Smart pointer with value semantics.
Definition value_ptr.h:134
::nonstd::span< T, Extent > span
A bounds-safe view for sequences of objects.
Definition span.h:27
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
Raycasting operations.
Definition ClosestPointResult.h:22
SceneFlags
Flags for configuring the ray caster and the underlying Embree scene.
Definition RayCaster.h:139
@ None
No special behavior.
Definition RayCaster.h:141
@ Dynamic
Indicates that the scene will be updated frequently.
Definition RayCaster.h:144
@ Compact
Use a more compact BVH layout that may be faster to build but slower to traverse.
Definition RayCaster.h:147
@ Robust
Use a more robust BVH traversal algorithm that is slower but less likely to miss hits due to numerica...
Definition RayCaster.h:151
@ Filter
Enable user-defined intersection and occlusion filters.
Definition RayCaster.h:154
BuildQuality
Quality levels for BVH construction.
Definition RayCaster.h:161
@ Low
Fastest build time, lowest BVH quality.
Definition RayCaster.h:163
@ High
Slowest build time, highest BVH quality.
Definition RayCaster.h:169
@ Medium
Moderate build time and BVH quality.
Definition RayCaster.h:166
Result of a single closest point query.
Definition RayCaster.h:58
float distance
Distance from the query point to the closest point on the surface.
Definition RayCaster.h:60
Result of a multi-point closest point query.
Definition RayCaster.h:116
Eigen::Vector< float, N > distances
Definition RayCaster.h:118
Shared base struct for ray and closest point hits.
Definition RayCaster.h:35
Eigen::Vector2f barycentric_coord
Barycentric coordinates of the hit point within the hit facet.
Definition RayCaster.h:48
uint32_t facet_index
Index of the facet that was hit.
Definition RayCaster.h:43
Eigen::Vector3f position
World-space position of the hit point.
Definition RayCaster.h:51
uint32_t mesh_index
Index of the mesh that was hit.
Definition RayCaster.h:37
uint32_t instance_index
Index of the instance that was hit (relative to the source mesh).
Definition RayCaster.h:40
Shared base struct for multi-ray and multi-point hits.
Definition RayCaster.h:82
Eigen::Vector< uint32_t, N > mesh_indices
Index of the mesh that was hit.
Definition RayCaster.h:87
uint32_t valid_mask
Bitmask indicating which rays in the packet hit something (1 bit per ray).
Definition RayCaster.h:84
Eigen::Matrix< float, 3, N > positions
World-space position of the hit point.
Definition RayCaster.h:104
Eigen::Vector< uint32_t, N > instance_indices
Index of the instance that was hit (relative to the source mesh).
Definition RayCaster.h:91
Eigen::Matrix< float, 2, N > barycentric_coords
Barycentric coordinates of the hit points within the hit facets.
Definition RayCaster.h:101
Eigen::Vector< uint32_t, N > facet_indices
Index of the facet that was hit.
Definition RayCaster.h:95
Definition RayCaster.cpp:685
Result of a single-ray intersection query.
Definition RayCaster.h:67
Eigen::Vector3f normal
Unnormalized geometric normal at the hit point.
Definition RayCaster.h:72
float ray_depth
Parametric distance along the ray (t value).
Definition RayCaster.h:69
Result of a multi-ray intersection query.
Definition RayCaster.h:129
Eigen::Matrix< float, 3, N > normals
Definition RayCaster.h:134
Eigen::Vector< float, N > ray_depths
Definition RayCaster.h:131