Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/core/math/face3.h
9896 views
1
/**************************************************************************/
2
/* face3.h */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#pragma once
32
33
#include "core/math/aabb.h"
34
#include "core/math/plane.h"
35
#include "core/math/transform_3d.h"
36
#include "core/math/vector3.h"
37
38
struct [[nodiscard]] Face3 {
39
enum Side {
40
SIDE_OVER,
41
SIDE_UNDER,
42
SIDE_SPANNING,
43
SIDE_COPLANAR
44
};
45
46
Vector3 vertex[3];
47
48
/**
49
* @param p_plane plane used to split the face
50
* @param p_res array of at least 3 faces, amount used in function return
51
* @param p_is_point_over array of at least 3 booleans, determining which face is over the plane, amount used in function return
52
* @return amount of faces generated by the split, either 0 (means no split possible), 2 or 3
53
*/
54
int split_by_plane(const Plane &p_plane, Face3 *p_res, bool *p_is_point_over) const;
55
56
Plane get_plane(ClockDirection p_dir = CLOCKWISE) const;
57
Vector3 get_random_point_inside() const;
58
59
bool is_degenerate() const;
60
real_t get_area() const;
61
62
Vector3 get_closest_point_to(const Vector3 &p_point) const;
63
64
bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection = nullptr) const;
65
bool intersects_segment(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection = nullptr) const;
66
67
void get_support(const Vector3 &p_normal, const Transform3D &p_transform, Vector3 *p_vertices, int *p_count, int p_max) const;
68
void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const;
69
70
AABB get_aabb() const {
71
AABB aabb(vertex[0], Vector3());
72
aabb.expand_to(vertex[1]);
73
aabb.expand_to(vertex[2]);
74
return aabb;
75
}
76
77
bool intersects_aabb(const AABB &p_aabb) const;
78
_FORCE_INLINE_ bool intersects_aabb2(const AABB &p_aabb) const;
79
explicit operator String() const;
80
81
Face3() = default;
82
constexpr Face3(const Vector3 &p_v1, const Vector3 &p_v2, const Vector3 &p_v3) :
83
vertex{ p_v1, p_v2, p_v3 } {}
84
};
85
86
bool Face3::intersects_aabb2(const AABB &p_aabb) const {
87
Vector3 perp = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]);
88
89
Vector3 half_extents = p_aabb.size * 0.5f;
90
Vector3 ofs = p_aabb.position + half_extents;
91
92
Vector3 sup = Vector3(
93
(perp.x > 0) ? -half_extents.x : half_extents.x,
94
(perp.y > 0) ? -half_extents.y : half_extents.y,
95
(perp.z > 0) ? -half_extents.z : half_extents.z);
96
97
real_t d = perp.dot(vertex[0]);
98
real_t dist_a = perp.dot(ofs + sup) - d;
99
real_t dist_b = perp.dot(ofs - sup) - d;
100
101
if (dist_a * dist_b > 0) {
102
return false; //does not intersect the plane
103
}
104
105
#define TEST_AXIS(m_ax) \
106
{ \
107
real_t aabb_min = p_aabb.position.m_ax; \
108
real_t aabb_max = p_aabb.position.m_ax + p_aabb.size.m_ax; \
109
real_t tri_min, tri_max; \
110
for (int i = 0; i < 3; i++) { \
111
if (i == 0 || vertex[i].m_ax > tri_max) \
112
tri_max = vertex[i].m_ax; \
113
if (i == 0 || vertex[i].m_ax < tri_min) \
114
tri_min = vertex[i].m_ax; \
115
} \
116
\
117
if (tri_max < aabb_min || aabb_max < tri_min) \
118
return false; \
119
}
120
121
TEST_AXIS(x);
122
TEST_AXIS(y);
123
TEST_AXIS(z);
124
125
#undef TEST_AXIS
126
127
const Vector3 edge_norms[3] = {
128
vertex[0] - vertex[1],
129
vertex[1] - vertex[2],
130
vertex[2] - vertex[0],
131
};
132
133
for (int i = 0; i < 12; i++) {
134
Vector3 from, to;
135
switch (i) {
136
case 0: {
137
from = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z);
138
to = Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z);
139
} break;
140
case 1: {
141
from = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z);
142
to = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z);
143
} break;
144
case 2: {
145
from = Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z);
146
to = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z);
147
148
} break;
149
case 3: {
150
from = Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z);
151
to = Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z);
152
153
} break;
154
case 4: {
155
from = Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z);
156
to = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z);
157
} break;
158
case 5: {
159
from = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z);
160
to = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z);
161
} break;
162
case 6: {
163
from = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z);
164
to = Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z);
165
166
} break;
167
case 7: {
168
from = Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z);
169
to = Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z);
170
171
} break;
172
case 8: {
173
from = Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z);
174
to = Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z);
175
176
} break;
177
case 9: {
178
from = Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z);
179
to = Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z);
180
181
} break;
182
case 10: {
183
from = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z);
184
to = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z);
185
186
} break;
187
case 11: {
188
from = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z);
189
to = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z);
190
191
} break;
192
}
193
194
Vector3 e1 = from - to;
195
for (int j = 0; j < 3; j++) {
196
Vector3 e2 = edge_norms[j];
197
198
Vector3 axis = vec3_cross(e1, e2);
199
200
if (axis.length_squared() < 0.0001f) {
201
continue; // coplanar
202
}
203
//axis.normalize();
204
205
Vector3 sup2 = Vector3(
206
(axis.x > 0) ? -half_extents.x : half_extents.x,
207
(axis.y > 0) ? -half_extents.y : half_extents.y,
208
(axis.z > 0) ? -half_extents.z : half_extents.z);
209
210
real_t maxB = axis.dot(ofs + sup2);
211
real_t minB = axis.dot(ofs - sup2);
212
if (minB > maxB) {
213
SWAP(maxB, minB);
214
}
215
216
real_t minT = 1e20, maxT = -1e20;
217
for (int k = 0; k < 3; k++) {
218
real_t vert_d = axis.dot(vertex[k]);
219
220
if (vert_d > maxT) {
221
maxT = vert_d;
222
}
223
224
if (vert_d < minT) {
225
minT = vert_d;
226
}
227
}
228
229
if (maxB < minT || maxT < minB) {
230
return false;
231
}
232
}
233
}
234
return true;
235
}
236
237
template <>
238
struct is_zero_constructible<Face3> : std::true_type {};
239
240