14#include <lagrange/MeshTrait.h>
15#include <lagrange/create_mesh.h>
16#include <lagrange/raycasting/create_ray_caster.h>
17#include <lagrange/raycasting/project_options.h>
18#include <lagrange/utils/safe_cast.h>
21#include <lagrange/utils/warnoff.h>
22#include <igl/bounding_box_diagonal.h>
23#include <lagrange/utils/warnon.h>
26#include <tbb/parallel_for.h>
74 typename ParticleDataType,
76 typename DefaultScalar =
typename ParticleDataType::value_type::Scalar,
77 typename MatrixType =
typename Eigen::Matrix<DefaultScalar, 4, 4>,
78 typename VectorType =
typename Eigen::Matrix<DefaultScalar, 3, 1>>
80 const ParticleDataType& origins,
82 const VectorType& direction,
83 ParticleDataType& out_origins,
84 ParticleDataType& out_normals,
85 const MatrixType& parent_transforms = MatrixType::Identity(),
87 bool has_normals =
true)
92 using Scalar = DefaultScalar;
93 using Index =
typename MeshType::Index;
94 using Point =
typename EmbreeRayCaster<Scalar>::Point;
95 using Direction =
typename EmbreeRayCaster<Scalar>::Direction;
96 using Scalar4 =
typename EmbreeRayCaster<Scalar>::Scalar4;
97 using Index4 =
typename EmbreeRayCaster<Scalar>::Index4;
98 using Point4 =
typename EmbreeRayCaster<Scalar>::Point4;
99 using Direction4 =
typename EmbreeRayCaster<Scalar>::Direction4;
100 using Mask4 =
typename EmbreeRayCaster<Scalar>::Mask4;
103 std::unique_ptr<EmbreeRayCaster<Scalar>> engine;
111 engine->add_mesh(mesh, Eigen::Matrix<Scalar, 4, 4>::Identity());
115 engine->cast(Point(0, 0, 0), Direction(0, 0, 1));
116 ray_caster = engine.get();
118 logger().debug(
"Using provided ray-caster");
121 Index num_particles = safe_cast<Index>(origins.size());
124 MatrixType parent_transforms_inv = parent_transforms.inverse();
125 bool use_parent_transforms = !parent_transforms.isIdentity();
127 VectorType dir = direction.normalized();
128 Index num_ray_packets = (num_particles + 3) / 4;
130 dirs.row(0) = dir.transpose();
131 for (
int i = 1; i < 4; ++i) {
132 dirs.row(i) = dirs.row(0);
135 std::vector<uint8_t> vector_hits(num_ray_packets, safe_cast<uint8_t>(0u));
137 ParticleDataType projected_origins;
138 ParticleDataType projected_normals;
140 out_origins.resize(num_particles);
141 if (has_normals) out_normals.resize(num_particles);
143 tbb::parallel_for(Index(0), num_ray_packets, [&](Index packet_index) {
145 safe_cast<uint32_t>(std::min(num_particles - (packet_index << 2), safe_cast<Index>(4)));
146 Mask4 mask = Mask4::Constant(-1);
149 for (uint32_t b = 0; b < batchsize; ++b) {
150 Index i = (packet_index << 2) + b;
153 if (use_parent_transforms) {
155 (parent_transforms * origins[i].homogeneous()).hnormalized().transpose();
157 ray_origins.row(b) = origins[i].transpose();
161 for (Index b = batchsize; b < 4; ++b) {
166 Index4 instance_indices;
167 Index4 facet_indices;
171 uint8_t hits = ray_caster->cast4(
185 vector_hits[packet_index] = hits;
187 for (uint32_t b = 0; b < batchsize; ++b) {
188 bool hit = hits & (1 << b);
190 Index i = (packet_index << 2) + b;
193 (ray_caster->get_transform(mesh_indices[b], instance_indices[b])
194 .template topLeftCorner<3, 3>() *
195 normals.row(b).transpose())
197 if (use_parent_transforms) {
198 norm = parent_transforms_inv.template topLeftCorner<3, 3>() * norm;
200 out_normals[i] = norm;
203 VectorType old_pos = ray_origins.row(b).transpose();
204 out_origins[i] = old_pos + dir * ray_depths(b);
205 if (use_parent_transforms) {
207 (parent_transforms_inv * out_origins[i].homogeneous()).hnormalized();
215 auto remove_func = [&](
const VectorType&) ->
bool {
216 Index packet_index = i >> 2;
217 Index b = i++ - (packet_index << 2);
218 return !(vector_hits[packet_index] & (1 << b));
222 std::remove_if(out_origins.begin(), out_origins.end(), remove_func),
228 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:47
LA_CORE_API spdlog::logger & logger()
Retrieves the current logger.
Definition: Logger.cpp:40
@ EMBREE_ROBUST
Corresponds to RTC_SCENE_FLAG_ROBUST.
Definition: create_ray_caster.h:25
void project_particles_directional(const ParticleDataType &origins, const MeshType &mesh_proj_on, const VectorType &direction, ParticleDataType &out_origins, ParticleDataType &out_normals, const MatrixType &parent_transforms=MatrixType::Identity(), EmbreeRayCaster< ScalarOf< MeshType > > *ray_caster=nullptr, bool has_normals=true)
Project particles (a particle contains origin and tangent info) to another mesh, by projecting their ...
Definition: project_particles_directional.h:79
@ BUILD_QUALITY_HIGH
Corresponds to RTC_BUILD_QUALITY_HIGH.
Definition: create_ray_caster.h:32
Main namespace for Lagrange.
Definition: AABBIGL.h:30
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:84
MeshTrait class provide compiler check for different mesh types.
Definition: MeshTrait.h:108