Skip to content

Commit 7d3a3cf

Browse files
author
sth-v
committed
Add GJK collision detection and UV12 class
Implemented the GJK (Gilbert-Johnson-Keerthi) algorithm for collision detection between convex shapes in _gjk.cpp. Added a UV12 class in _dqr.cpp to represent a pair of (u, v) coordinates. Updated the project version to 0.41.1 in pyproject.toml.
1 parent 60efdf9 commit 7d3a3cf

File tree

3 files changed

+233
-1
lines changed

3 files changed

+233
-1
lines changed

mmcore/numeric/algorithms/_gjk.cpp

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
#include <array>
2+
#include <cstdint>
3+
#include <vector>
4+
#include <limits>
5+
#include <cmath>
6+
#include <algorithm>
7+
8+
#if defined(__ARM_NEON)
9+
#include <arm_neon.h>
10+
#elif defined(__AVX__)
11+
#include <immintrin.h>
12+
#endif
13+
14+
15+
template<typename T>
16+
using Vec3 = std::array<T, 3>;
17+
18+
typedef Vec3<float> Vec3_f;
19+
typedef Vec3<double> Vec3_d;
20+
21+
22+
template<typename T>
23+
inline T dot(const Vec3<T>& a, const Vec3<T>& b) {
24+
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
25+
}
26+
27+
28+
template<typename T>
29+
inline Vec3<T> cross(const Vec3<T>& a, const Vec3<T>& b) {
30+
return {
31+
a[1] * b[2] - a[2] * b[1],
32+
a[2] * b[0] - a[0] * b[2],
33+
a[0] * b[1] - a[1] * b[0]
34+
};
35+
}
36+
37+
template<typename T>
38+
inline Vec3<T> operator-(const Vec3<T>& a, const Vec3<T>& b) {
39+
return {a[0] - b[0], a[1] - b[1], a[2] - b[2]};
40+
}
41+
42+
template<typename T>
43+
inline int support_vector(const std::vector<Vec3<T>>& vertices, const Vec3<T>& d, Vec3<T>& support) {
44+
T highest = -std::numeric_limits<T>::max();
45+
support[0]=0;
46+
support[1]=0;
47+
support[2]=0;
48+
int support_i = -1;
49+
50+
for (size_t i = 0; i < vertices.size(); ++i) {
51+
T dot_value = dot(vertices[i], d);
52+
if (dot_value > highest) {
53+
highest = dot_value;
54+
support[0] = vertices[i][0];
55+
support[1] = vertices[i][1];
56+
support[2] = vertices[i][2];
57+
support_i = i;
58+
}
59+
}
60+
61+
return support_i;
62+
}
63+
64+
template<typename T>
65+
bool handle_simplex(std::vector<Vec3<T>>& simplex, Vec3<T>& d, T tol) {
66+
switch (simplex.size()) {
67+
case 2: {
68+
const auto& a = simplex[1];
69+
const auto& b = simplex[0];
70+
Vec3<T> ab = b - a;
71+
Vec3<T> ao = {-a[0], -a[1], -a[2]};
72+
73+
if (dot(ab, ao) > tol) {
74+
d = cross(cross(ab, ao), ab);
75+
} else {
76+
simplex.erase(simplex.begin());
77+
d = ao;
78+
}
79+
break;
80+
}
81+
case 3: {
82+
const auto& a = simplex[2];
83+
const auto& b = simplex[1];
84+
const auto& c = simplex[0];
85+
Vec3<T> ab = b - a;
86+
Vec3<T> ac = c - a;
87+
Vec3<T> ao = {-a[0], -a[1], -a[2]};
88+
Vec3<T> abc = cross(ab, ac);
89+
90+
if (dot(cross(abc, ac), ao) > tol) {
91+
if (dot(ac, ao) > 0) {
92+
simplex.erase(simplex.begin() + 1);
93+
d = cross(cross(ac, ao), ac);
94+
} else {
95+
simplex.erase(simplex.begin());
96+
return handle_simplex<T>(simplex, d, tol);
97+
}
98+
} else {
99+
if (dot(cross(ab, abc), ao) > tol) {
100+
simplex.erase(simplex.begin());
101+
return handle_simplex<T>(simplex, d, tol);
102+
} else {
103+
if (dot(abc, ao) > tol) {
104+
d = abc;
105+
} else {
106+
std::swap(simplex[0], simplex[1]);
107+
d = {-abc[0], -abc[1], -abc[2]};
108+
}
109+
}
110+
}
111+
break;
112+
}
113+
case 4: {
114+
const auto& a = simplex[3];
115+
const auto& b = simplex[2];
116+
const auto& c = simplex[1];
117+
const auto& d_point = simplex[0];
118+
119+
Vec3<T> ab = b - a;
120+
Vec3<T> ac = c - a;
121+
Vec3<T> ad = d_point - a;
122+
Vec3<T> ao = {-a[0], -a[1], -a[2]};
123+
124+
Vec3<T> abc = cross<T>(ab, ac);
125+
Vec3<T> acd = cross<T>(ac, ad);
126+
Vec3<T> adb = cross<T>(ad, ab);
127+
128+
if (dot(abc, ao) > tol) {
129+
simplex.erase(simplex.begin());
130+
return handle_simplex<T>(simplex, d, tol);
131+
} else if (dot(acd, ao) > tol) {
132+
simplex.erase(simplex.begin() + 1);
133+
return handle_simplex<T>(simplex, d, tol);
134+
} else if (dot(adb, ao) > tol) {
135+
simplex.erase(simplex.begin() + 2);
136+
return handle_simplex<T>(simplex, d, tol);
137+
} else {
138+
return true;
139+
}
140+
}
141+
}
142+
return false;
143+
}
144+
145+
inline bool isVisited(bool* arr, const size_t cols, const size_t i, const size_t j) {
146+
return arr[i * cols + j];
147+
};
148+
inline Vec3_d& getVisited(Vec3_d* tt, const size_t cols, const size_t i, const size_t j) {
149+
return tt[i * cols + j];
150+
};
151+
inline void setVisited(bool* arr, Vec3<double>* tt, const size_t cols, const size_t i, const size_t j, const Vec3_d& val) {
152+
arr[i * cols + j]=true;
153+
tt[i*cols+j]=val;
154+
};
155+
bool gjk_collision_detection(const std::vector<Vec3<double>>& vertices1, const std::vector<Vec3<double>>& vertices2, double tol , size_t max_iter) {
156+
if (max_iter == 0) {
157+
max_iter = vertices1.size() * vertices2.size();
158+
}
159+
const size_t rows=vertices1.size();
160+
const size_t cols=vertices2.size();
161+
bool* arr= new bool[rows * cols];
162+
Vec3<double>* tt= new Vec3<double>[rows * cols];
163+
164+
std::vector<Vec3<double>> simplex;
165+
simplex.reserve(4); // Pre-allocate space for efficiency
166+
167+
auto support = [&](const Vec3<double>& d, size_t &i_index, size_t &j_index) -> Vec3<double> {
168+
Vec3<double> p1;
169+
Vec3<double> p2;
170+
i_index = support_vector<double>(vertices1, d, p1);
171+
j_index = support_vector<double>(vertices2, {-d[0], -d[1], -d[2]}, p2);
172+
173+
return p1 - p2;
174+
};
175+
size_t i,j;
176+
Vec3<double> d = {0, 0, 1};
177+
auto new_point=support(d, i,j);
178+
setVisited(arr,tt,cols,i,j, new_point);
179+
simplex.push_back(new_point);
180+
d = {-simplex[0][0], -simplex[0][1], -simplex[0][2]};
181+
182+
for (size_t iter = 0; iter < max_iter; ++iter) {
183+
new_point = support(d,i,j );
184+
if (isVisited(arr,cols, i,j)){
185+
auto vec=new_point-getVisited(tt, cols, i,j);
186+
187+
188+
if (dot(vec, vec)==0){
189+
delete tt;
190+
delete arr;
191+
return true;
192+
}
193+
} else{
194+
setVisited(arr,tt, cols,i,j, new_point);
195+
}
196+
197+
198+
if (dot(new_point, d) < 0) {
199+
delete tt;
200+
delete arr;
201+
return false;
202+
}
203+
204+
simplex.push_back(new_point);
205+
206+
if (handle_simplex<double>(simplex, d, tol)) {
207+
delete tt;
208+
delete arr;
209+
return true;
210+
}
211+
}
212+
213+
delete tt;
214+
delete arr;
215+
216+
return false;
217+
}
218+
219+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
class UV12
3+
{
4+
public:
5+
double u1,v1,u2,v2;
6+
UV12()=default;
7+
UV12(double u1,double v1,double u2,double v2): u1(u1), v1(v1), u2(v2),v2(v2) {};
8+
9+
10+
/* data */
11+
};
12+
13+

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
44

55
[tool.poetry]
66
name = "mmcore"
7-
version = "0.41.0"
7+
version = "0.41.1"
88
description = "mmcore"
99
authors = ["Andrew Astakhov <aa@contextmachine.ru>", ]
1010
license = "Apache License Version 2.0"

0 commit comments

Comments
 (0)