Lagrange
Loading...
Searching...
No Matches
embree_closest_point.h
1// Source: https://github.com/embree/embree/blob/master/tutorials/closest_point/closest_point.cpp
2// SPDX-License-Identifier: Apache-2.0
3//
4// This file has been modified by Adobe.
5//
6// All modifications are Copyright 2020 Adobe.
7
8#pragma once
9
10#include <lagrange/legacy/inline.h>
11#include <lagrange/raycasting/ClosestPointResult.h>
12
13#include <lagrange/utils/point_triangle_squared_distance.h>
14
15#ifdef LAGRANGE_WITH_EMBREE_3
16 #include <embree3/rtcore.h>
17 #include <embree3/rtcore_geometry.h>
18 #include <embree3/rtcore_ray.h>
19#else
20 #include <embree4/rtcore.h>
21 #include <embree4/rtcore_geometry.h>
22 #include <embree4/rtcore_ray.h>
23#endif
24
25#include <Eigen/Geometry>
26
27RTC_NAMESPACE_USE
28
29namespace lagrange {
30namespace raycasting {
31LAGRANGE_LEGACY_INLINE
32namespace legacy {
33
34template <typename Scalar>
35bool embree_closest_point(RTCPointQueryFunctionArguments* args)
36{
37 using Point = typename ClosestPointResult<Scalar>::Point;
38 using MapType = Eigen::Map<Eigen::Matrix4f, Eigen::Aligned16>;
39 using AffineMat = Eigen::Transform<Scalar, 3, Eigen::Affine>;
40
41 assert(args->userPtr);
42 auto result = reinterpret_cast<ClosestPointResult<Scalar>*>(args->userPtr);
43
44 const unsigned int geomID = args->geomID;
45 const unsigned int primID = args->primID;
46
47 RTCPointQueryContext* context = args->context;
48 const unsigned int stack_size = args->context->instStackSize;
49 const unsigned int stack_ptr = stack_size - 1;
50
51 AffineMat inst2world =
52 (stack_size > 0 ? AffineMat(MapType(context->inst2world[stack_ptr]).template cast<Scalar>())
53 : AffineMat::Identity());
54
55 // Query position in world space
56 Point q(args->query->x, args->query->y, args->query->z);
57
58 // Get triangle information in local space
59 Point v0, v1, v2;
60 assert(result->populate_triangle);
61 result->populate_triangle(geomID, primID, v0, v1, v2);
62
63 // Bring query and primitive data in the same space if necessary.
64 if (stack_size > 0 && args->similarityScale > 0) {
65 // Instance transform is a similarity transform, therefore we
66 // can compute distance information in instance space. Therefore,
67 // transform query position into local instance space.
68 AffineMat world2inst(MapType(context->world2inst[stack_ptr]).template cast<Scalar>());
69 q = world2inst * q;
70 } else if (stack_size > 0) {
71 // Instance transform is not a similarity tranform. We have to transform the
72 // primitive data into world space and perform distance computations in
73 // world space to ensure correctness.
74 v0 = inst2world * v0;
75 v1 = inst2world * v1;
76 v2 = inst2world * v2;
77 } else {
78 // Primitive is not instanced, therefore point query and primitive are
79 // already in the same space.
80 }
81
82 // Determine distance to closest point on triangle, and transform in
83 // world space if necessary.
84 Point p;
85 Scalar l1, l2, l3;
86 Scalar d2 = point_triangle_squared_distance(q, v0, v1, v2, p, l1, l2, l3);
87 float d = std::sqrt(static_cast<float>(d2));
88 if (args->similarityScale > 0) {
89 d = d / args->similarityScale;
90 }
91
92 // Store result in userPtr and update the query radius if we found a point
93 // closer to the query position. This is optional but allows for faster
94 // traversal (due to better culling).
95 if (d < args->query->radius) {
96 args->query->radius = d;
97 result->closest_point = (args->similarityScale > 0 ? (inst2world * p).eval() : p);
98 result->mesh_index = geomID;
99 result->facet_index = primID;
100 result->barycentric_coord = Point(l1, l2, l3);
101 return true; // Return true to indicate that the query radius changed.
102 }
103
104 return false;
105}
106
107} // namespace legacy
108} // namespace raycasting
109} // namespace lagrange
@ Scalar
Mesh attribute must have exactly 1 channel.
Definition AttributeFwd.h:56
SurfaceMesh< ToScalar, ToIndex > cast(const SurfaceMesh< FromScalar, FromIndex > &source_mesh, const AttributeFilter &convertible_attributes={}, std::vector< std::string > *converted_attributes_names=nullptr)
Cast a mesh to a mesh of different scalar and/or index type.
Raycasting operations.
Definition ClosestPointResult.h:22
Main namespace for Lagrange.
auto point_triangle_squared_distance(const Eigen::MatrixBase< PointType > &point, const Eigen::MatrixBase< PointType2 > &V0, const Eigen::MatrixBase< PointType2 > &V1, const Eigen::MatrixBase< PointType2 > &V2, Eigen::PlainObjectBase< PointType > &closest_point, ScalarOf< PointType > &lambda0, ScalarOf< PointType > &lambda1, ScalarOf< PointType > &lambda2) -> ScalarOf< PointType >
Computes the point closest to a given point in a nd triangle.
Definition point_triangle_squared_distance.h:77
Definition ClosestPointResult.h:28