-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathmpr.h
174 lines (154 loc) · 6.32 KB
/
mpr.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//
// Created by mech-mind_gw on 2/7/2022.
//
#pragma once
#include "minkowski_diff.h"
#include "vec_types.h"
namespace fcl {
namespace cvx_collide {
/// The Minkowski Portal Refinement Algorithm Described
/// in Game Programming Gem 7. This algorithm can be used
/// to computed binary intersection and DIRECTED penetration
template <typename T>
struct MPR {
MPR(int max_iterations_in, T tolerance_in);
~MPR() = default;
// The data for binary query
enum class IntersectStatus { Intersect, Separated, Failed };
struct IntersectData {
Vector3<T> v0_interior;
Vector3<T> v1;
Vector3<T> v2;
Vector3<T> v3;
// The direction that find v1-v3
Vector3<T> v1_dir_in_support;
Vector3<T> v2_dir_in_support;
Vector3<T> v3_dir_in_support;
};
// The evaluation interface with only binary flag output
static IntersectStatus RunIntersect(const MinkowskiDiff<T>& shape,
IntersectData& intersect_data,
int max_iterations, T tolerance);
IntersectStatus Intersect(const MinkowskiDiff<T>& shape,
IntersectData* intersect_data = nullptr) const;
bool IsOriginEnclosedDebug(const MinkowskiDiff<T>& shape,
const IntersectData& intersect_data) const;
// The data for penetration
enum class DirectedPenetrationStatus {
OK,
Failed,
FailedNoIntersect,
FailedRefinementIterationLimit
};
struct DirectedPenetrationData {
Vector3<T> v1;
Vector3<T> v2;
Vector3<T> v3;
// The direction that find v1-v3
Vector3<T> v1_dir_in_support;
Vector3<T> v2_dir_in_support;
Vector3<T> v3_dir_in_support;
// The output
Vector3<T> portal_normal;
T distance_on_direction;
Vector3<T> p0_in_shape0_frame;
Vector3<T> p1_in_shape0_frame;
};
static DirectedPenetrationStatus RunDirectedPenetration(
const MinkowskiDiff<T>& shape, const Vector3<T>& unit_direction,
DirectedPenetrationData& penetration_data, int max_iterations,
T tolerance);
DirectedPenetrationStatus DirectedPenetration(
const MinkowskiDiff<T>& shape, const Vector3<T>& unit_direction,
DirectedPenetrationData& penetration_data) const;
// The data for local refinement minimum penetration
enum class IncrementalPenetrationStatus {
OK,
Failed,
FailedNoIntersect,
DirectedPenetrationFailed,
IterationLimit
};
struct IncrementalMinimumPenetrationData {
// The output
T minimum_penetration;
Vector3<T> penetration_direction;
Vector3<T> p0_in_shape0_frame;
Vector3<T> p1_in_shape0_frame;
};
static IncrementalPenetrationStatus RunIncrementalMinimumPenetrationDistance(
const MinkowskiDiff<T>& shape, const Vector3<T>& init_direction,
IncrementalMinimumPenetrationData& refine_data, int max_iteration,
T tolerance, bool return_on_subroutine_converge = true);
IncrementalPenetrationStatus IncrementalMinimumPenetrationDistance(
const MinkowskiDiff<T>& shape, const Vector3<T>& init_direction,
IncrementalMinimumPenetrationData& refine_data,
bool return_on_subroutine_converge = true) const;
private:
// Termination
const int max_iterations;
const T tolerance;
static constexpr T dot_eps_ratio = std::numeric_limits<T>::epsilon();
// Helpers
// Sometimes we need to normalize the direction (sphere, capsule, cylinder)
// Sometimes we do not.
static Vector3<T> computeShapeSupport(const MinkowskiDiff<T>& shape,
Vector3<T>& direction);
static inline T computeAbsNorm(const Vector3<T>& v);
// Find the portal by finding v1/v2/v3 such that the origin ray from
// v0 to O intersects with the triangle formed by v1/v2/v3.
// v1/v2/v3 must be on the shape
enum class FindPortalStatus { IterationLimit, DetectSeperated, PortalFound };
static FindPortalStatus findPortal(
const MinkowskiDiff<T>& shape, const Vector3<T>& v0, Vector3<T>& v1,
Vector3<T>& v2, Vector3<T>& v3,
std::array<Vector3<T>*, 3> v1_v2_v3_dir_in_support, int max_iterations);
// Helpers for findPortal
static void updatePortal(const Vector3<T>& v0, const Vector3<T>& v4,
const Vector3<T>& v4_dir_in_support, Vector3<T>& v1,
Vector3<T>& v2, Vector3<T>& v3,
std::array<Vector3<T>*, 3> v1_v2_v3_dir_in_support);
static bool portalEncloseOrigin(const Vector3<T>& v0_interior,
const Vector3<T>& v1, const Vector3<T>& v2,
const Vector3<T>& v3);
// Suppose there is a ray from origin O along the direction ray_direction
// This ray intersects with the triangle v1v2v3, and the normal v123.dot(d)
// cannot be negative. ray_direction/v123_normal is a unit vector.
// Compute the distance from the origin to the intersecting point on v1v2v3.
static void finalizeDirectedPenetrationResult(
const MinkowskiDiff<T>& shape, const Vector3<T>& ray_direction,
const Vector3<T>& v123_normal_arg,
DirectedPenetrationData& penetration_data,
const Vector3<T>* v4_optional = nullptr);
static void finalizeIncrementalPenetrationResult(
const MinkowskiDiff<T>& shape, const Vector3<T>& ray_direction,
const Vector3<T>& v1, const Vector3<T>& v2, const Vector3<T>& v3,
const Vector3<T>& v1_dir, const Vector3<T>& v2_dir,
const Vector3<T>& v3_dir, const Vector3<T>& v123_normal_arg,
T distance_lb, T distance_ub,
IncrementalMinimumPenetrationData& penetration_data);
// Private sub-routine for refinement
enum class IncrementalMinDistanceSubroutineStatus {
NewDirection,
SubroutineConverge,
Degenerated,
Failed,
FailedNoIntersect
};
static IncrementalMinDistanceSubroutineStatus
incrementalMinimumDistanceExploreDirection(
const MinkowskiDiff<T>& shape, const Vector3<T>& direction_to_explore,
// Both input/output
Vector3<T>& v1, Vector3<T>& v2, Vector3<T>& v3, Vector3<T>& v1_dir,
Vector3<T>& v2_dir, Vector3<T>& v3_dir,
// Output
T& distance_on_direction_lb, T& distance_on_direction_ub,
Vector3<T>& new_direction,
// Parameters
bool v123_valid, int max_iterations, T tolerance);
};
} // namespace cvx_collide
} // namespace fcl
// Header only implementation
#include "mpr.hpp"
#include "mpr_incremental_penetration.hpp"