14#include <lagrange/MeshTrait.h>
15#include <lagrange/create_mesh.h>
16#include <lagrange/legacy/inline.h>
17#include <lagrange/raycasting/Options.h>
18#include <lagrange/raycasting/create_ray_caster.h>
19#include <lagrange/utils/safe_cast.h>
22#include <lagrange/utils/warnoff.h>
23#include <igl/bounding_box_diagonal.h>
24#include <lagrange/utils/warnon.h>
27#include <tbb/parallel_for.h>
77 typename ParticleDataType,
79 typename DefaultScalar =
typename ParticleDataType::value_type::Scalar,
80 typename MatrixType =
typename Eigen::Matrix<DefaultScalar, 4, 4>,
81 typename VectorType =
typename Eigen::Matrix<DefaultScalar, 3, 1>>
82void project_particles_directional(
83 const ParticleDataType& origins,
84 const MeshType& mesh_proj_on,
85 const VectorType& direction,
86 ParticleDataType& out_origins,
87 ParticleDataType& out_normals,
88 const MatrixType& parent_transforms = MatrixType::Identity(),
90 bool has_normals =
true)
92 static_assert(MeshTrait<MeshType>::is_mesh(),
"Mesh type is wrong");
95 using Scalar = DefaultScalar;
96 using Index =
typename MeshType::Index;
97 using Point =
typename EmbreeRayCaster<Scalar>::Point;
98 using Direction =
typename EmbreeRayCaster<Scalar>::Direction;
99 using Scalar4 =
typename EmbreeRayCaster<Scalar>::Scalar4;
100 using Index4 =
typename EmbreeRayCaster<Scalar>::Index4;
101 using Point4 =
typename EmbreeRayCaster<Scalar>::Point4;
102 using Direction4 =
typename EmbreeRayCaster<Scalar>::Direction4;
103 using Mask4 =
typename EmbreeRayCaster<Scalar>::Mask4;
106 std::unique_ptr<EmbreeRayCaster<Scalar>> engine;
111 engine = create_ray_caster<Scalar>(EMBREE_ROBUST, BUILD_QUALITY_HIGH);
114 engine->add_mesh(mesh, Eigen::Matrix<Scalar, 4, 4>::Identity());
118 engine->cast(Point(0, 0, 0), Direction(0, 0, 1));
119 ray_caster = engine.get();
121 logger().debug(
"Using provided ray-caster");
127 MatrixType parent_transforms_inv = parent_transforms.inverse();
128 bool use_parent_transforms = !parent_transforms.isIdentity();
130 VectorType dir = direction.normalized();
131 Index num_ray_packets = (num_particles + 3) / 4;
133 dirs.row(0) = dir.transpose();
134 for (
int i = 1; i < 4; ++i) {
135 dirs.row(i) = dirs.row(0);
140 ParticleDataType projected_origins;
141 ParticleDataType projected_normals;
143 out_origins.resize(num_particles);
144 if (has_normals) out_normals.resize(num_particles);
146 tbb::parallel_for(Index(0), num_ray_packets, [&](Index packet_index) {
149 Mask4 mask = Mask4::Constant(-1);
152 for (uint32_t b = 0; b < batchsize; ++b) {
153 Index i = (packet_index << 2) + b;
156 if (use_parent_transforms) {
158 (parent_transforms * origins[i].homogeneous()).hnormalized().transpose();
160 ray_origins.row(b) = origins[i].transpose();
164 for (Index b = batchsize; b < 4; ++b) {
169 Index4 instance_indices;
170 Index4 facet_indices;
174 uint8_t hits = ray_caster->cast4(
188 vector_hits[packet_index] = hits;
190 for (uint32_t b = 0; b < batchsize; ++b) {
191 bool hit = hits & (1 << b);
193 Index i = (packet_index << 2) + b;
196 (ray_caster->get_transform(mesh_indices[b], instance_indices[b])
197 .
template topLeftCorner<3, 3>() *
198 normals.row(b).transpose())
200 if (use_parent_transforms) {
201 norm = parent_transforms_inv.template topLeftCorner<3, 3>() * norm;
203 out_normals[i] = norm;
206 VectorType old_pos = ray_origins.row(b).transpose();
207 out_origins[i] = old_pos + dir * ray_depths(b);
208 if (use_parent_transforms) {
210 (parent_transforms_inv * out_origins[i].homogeneous()).hnormalized();
218 auto remove_func = [&](
const VectorType&) ->
bool {
219 Index packet_index = i >> 2;
220 Index b = i++ - (packet_index << 2);
221 return !(vector_hits[packet_index] & (1 << b));
225 std::remove_if(out_origins.begin(), out_origins.end(), remove_func),
231 std::remove_if(out_normals.begin(), out_normals.end(), remove_func),
A wrapper for Embree's raycasting API to compute ray intersections with (instances of) meshes.
Definition EmbreeRayCaster.h:59
LA_CORE_API spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:40
@ Scalar
Mesh attribute must have exactly 1 channel.
Definition AttributeFwd.h:56
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
Main namespace for Lagrange.
auto create_mesh(const Eigen::MatrixBase< DerivedV > &vertices, const Eigen::MatrixBase< DerivedF > &facets)
This function create a new mesh given the vertex and facet arrays by copying data into the Mesh objec...
Definition create_mesh.h:39
std::shared_ptr< T > to_shared_ptr(std::unique_ptr< T > &&ptr)
Helper for automatic type deduction for unique_ptr to shared_ptr conversion.
Definition common.h:88