summaryrefslogtreecommitdiffstats
path: root/core/math
diff options
context:
space:
mode:
Diffstat (limited to 'core/math')
-rw-r--r--core/math/a_star.cpp56
-rw-r--r--core/math/a_star_grid_2d.cpp39
-rw-r--r--core/math/a_star_grid_2d.h12
-rw-r--r--core/math/aabb.cpp5
-rw-r--r--core/math/basis.cpp23
-rw-r--r--core/math/basis.h15
-rw-r--r--core/math/dynamic_bvh.h18
-rw-r--r--core/math/geometry_3d.h16
-rw-r--r--core/math/math_funcs.h16
-rw-r--r--core/math/rect2.h4
-rw-r--r--core/math/transform_2d.cpp12
-rw-r--r--core/math/transform_2d.h2
-rw-r--r--core/math/transform_3d.cpp11
-rw-r--r--core/math/transform_3d.h2
-rw-r--r--core/math/vector2i.h8
-rw-r--r--core/math/vector3i.h11
-rw-r--r--core/math/vector4i.h11
17 files changed, 222 insertions, 39 deletions
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
index f0f160940d..fb54058bd9 100644
--- a/core/math/a_star.cpp
+++ b/core/math/a_star.cpp
@@ -69,7 +69,7 @@ void AStar3D::add_point(int64_t p_id, const Vector3 &p_pos, real_t p_weight_scal
}
Vector3 AStar3D::get_point_position(int64_t p_id) const {
- Point *p;
+ Point *p = nullptr;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_V_MSG(!p_exists, Vector3(), vformat("Can't get point's position. Point with id: %d doesn't exist.", p_id));
@@ -77,7 +77,7 @@ Vector3 AStar3D::get_point_position(int64_t p_id) const {
}
void AStar3D::set_point_position(int64_t p_id, const Vector3 &p_pos) {
- Point *p;
+ Point *p = nullptr;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_MSG(!p_exists, vformat("Can't set point's position. Point with id: %d doesn't exist.", p_id));
@@ -85,7 +85,7 @@ void AStar3D::set_point_position(int64_t p_id, const Vector3 &p_pos) {
}
real_t AStar3D::get_point_weight_scale(int64_t p_id) const {
- Point *p;
+ Point *p = nullptr;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_V_MSG(!p_exists, 0, vformat("Can't get point's weight scale. Point with id: %d doesn't exist.", p_id));
@@ -93,7 +93,7 @@ real_t AStar3D::get_point_weight_scale(int64_t p_id) const {
}
void AStar3D::set_point_weight_scale(int64_t p_id, real_t p_weight_scale) {
- Point *p;
+ Point *p = nullptr;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_MSG(!p_exists, vformat("Can't set point's weight scale. Point with id: %d doesn't exist.", p_id));
ERR_FAIL_COND_MSG(p_weight_scale < 0.0, vformat("Can't set point's weight scale less than 0.0: %f.", p_weight_scale));
@@ -102,7 +102,7 @@ void AStar3D::set_point_weight_scale(int64_t p_id, real_t p_weight_scale) {
}
void AStar3D::remove_point(int64_t p_id) {
- Point *p;
+ Point *p = nullptr;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_MSG(!p_exists, vformat("Can't remove point. Point with id: %d doesn't exist.", p_id));
@@ -130,11 +130,11 @@ void AStar3D::remove_point(int64_t p_id) {
void AStar3D::connect_points(int64_t p_id, int64_t p_with_id, bool bidirectional) {
ERR_FAIL_COND_MSG(p_id == p_with_id, vformat("Can't connect point with id: %d to itself.", p_id));
- Point *a;
+ Point *a = nullptr;
bool from_exists = points.lookup(p_id, a);
ERR_FAIL_COND_MSG(!from_exists, vformat("Can't connect points. Point with id: %d doesn't exist.", p_id));
- Point *b;
+ Point *b = nullptr;
bool to_exists = points.lookup(p_with_id, b);
ERR_FAIL_COND_MSG(!to_exists, vformat("Can't connect points. Point with id: %d doesn't exist.", p_with_id));
@@ -166,11 +166,11 @@ void AStar3D::connect_points(int64_t p_id, int64_t p_with_id, bool bidirectional
}
void AStar3D::disconnect_points(int64_t p_id, int64_t p_with_id, bool bidirectional) {
- Point *a;
+ Point *a = nullptr;
bool a_exists = points.lookup(p_id, a);
ERR_FAIL_COND_MSG(!a_exists, vformat("Can't disconnect points. Point with id: %d doesn't exist.", p_id));
- Point *b;
+ Point *b = nullptr;
bool b_exists = points.lookup(p_with_id, b);
ERR_FAIL_COND_MSG(!b_exists, vformat("Can't disconnect points. Point with id: %d doesn't exist.", p_with_id));
@@ -220,7 +220,7 @@ PackedInt64Array AStar3D::get_point_ids() {
}
Vector<int64_t> AStar3D::get_point_connections(int64_t p_id) {
- Point *p;
+ Point *p = nullptr;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_V_MSG(!p_exists, Vector<int64_t>(), vformat("Can't get point's connections. Point with id: %d doesn't exist.", p_id));
@@ -386,11 +386,11 @@ real_t AStar3D::_estimate_cost(int64_t p_from_id, int64_t p_to_id) {
return scost;
}
- Point *from_point;
+ Point *from_point = nullptr;
bool from_exists = points.lookup(p_from_id, from_point);
ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_from_id));
- Point *to_point;
+ Point *to_point = nullptr;
bool to_exists = points.lookup(p_to_id, to_point);
ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_to_id));
@@ -403,11 +403,11 @@ real_t AStar3D::_compute_cost(int64_t p_from_id, int64_t p_to_id) {
return scost;
}
- Point *from_point;
+ Point *from_point = nullptr;
bool from_exists = points.lookup(p_from_id, from_point);
ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_from_id));
- Point *to_point;
+ Point *to_point = nullptr;
bool to_exists = points.lookup(p_to_id, to_point);
ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_to_id));
@@ -415,11 +415,11 @@ real_t AStar3D::_compute_cost(int64_t p_from_id, int64_t p_to_id) {
}
Vector<Vector3> AStar3D::get_point_path(int64_t p_from_id, int64_t p_to_id) {
- Point *a;
+ Point *a = nullptr;
bool from_exists = points.lookup(p_from_id, a);
ERR_FAIL_COND_V_MSG(!from_exists, Vector<Vector3>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_from_id));
- Point *b;
+ Point *b = nullptr;
bool to_exists = points.lookup(p_to_id, b);
ERR_FAIL_COND_V_MSG(!to_exists, Vector<Vector3>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_to_id));
@@ -464,11 +464,11 @@ Vector<Vector3> AStar3D::get_point_path(int64_t p_from_id, int64_t p_to_id) {
}
Vector<int64_t> AStar3D::get_id_path(int64_t p_from_id, int64_t p_to_id) {
- Point *a;
+ Point *a = nullptr;
bool from_exists = points.lookup(p_from_id, a);
ERR_FAIL_COND_V_MSG(!from_exists, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_from_id));
- Point *b;
+ Point *b = nullptr;
bool to_exists = points.lookup(p_to_id, b);
ERR_FAIL_COND_V_MSG(!to_exists, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_to_id));
@@ -513,7 +513,7 @@ Vector<int64_t> AStar3D::get_id_path(int64_t p_from_id, int64_t p_to_id) {
}
void AStar3D::set_point_disabled(int64_t p_id, bool p_disabled) {
- Point *p;
+ Point *p = nullptr;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_MSG(!p_exists, vformat("Can't set if point is disabled. Point with id: %d doesn't exist.", p_id));
@@ -521,7 +521,7 @@ void AStar3D::set_point_disabled(int64_t p_id, bool p_disabled) {
}
bool AStar3D::is_point_disabled(int64_t p_id) const {
- Point *p;
+ Point *p = nullptr;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_V_MSG(!p_exists, false, vformat("Can't get if point is disabled. Point with id: %d doesn't exist.", p_id));
@@ -660,11 +660,11 @@ real_t AStar2D::_estimate_cost(int64_t p_from_id, int64_t p_to_id) {
return scost;
}
- AStar3D::Point *from_point;
+ AStar3D::Point *from_point = nullptr;
bool from_exists = astar.points.lookup(p_from_id, from_point);
ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_from_id));
- AStar3D::Point *to_point;
+ AStar3D::Point *to_point = nullptr;
bool to_exists = astar.points.lookup(p_to_id, to_point);
ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_to_id));
@@ -677,11 +677,11 @@ real_t AStar2D::_compute_cost(int64_t p_from_id, int64_t p_to_id) {
return scost;
}
- AStar3D::Point *from_point;
+ AStar3D::Point *from_point = nullptr;
bool from_exists = astar.points.lookup(p_from_id, from_point);
ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_from_id));
- AStar3D::Point *to_point;
+ AStar3D::Point *to_point = nullptr;
bool to_exists = astar.points.lookup(p_to_id, to_point);
ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_to_id));
@@ -689,11 +689,11 @@ real_t AStar2D::_compute_cost(int64_t p_from_id, int64_t p_to_id) {
}
Vector<Vector2> AStar2D::get_point_path(int64_t p_from_id, int64_t p_to_id) {
- AStar3D::Point *a;
+ AStar3D::Point *a = nullptr;
bool from_exists = astar.points.lookup(p_from_id, a);
ERR_FAIL_COND_V_MSG(!from_exists, Vector<Vector2>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_from_id));
- AStar3D::Point *b;
+ AStar3D::Point *b = nullptr;
bool to_exists = astar.points.lookup(p_to_id, b);
ERR_FAIL_COND_V_MSG(!to_exists, Vector<Vector2>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_to_id));
@@ -737,11 +737,11 @@ Vector<Vector2> AStar2D::get_point_path(int64_t p_from_id, int64_t p_to_id) {
}
Vector<int64_t> AStar2D::get_id_path(int64_t p_from_id, int64_t p_to_id) {
- AStar3D::Point *a;
+ AStar3D::Point *a = nullptr;
bool from_exists = astar.points.lookup(p_from_id, a);
ERR_FAIL_COND_V_MSG(!from_exists, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_from_id));
- AStar3D::Point *b;
+ AStar3D::Point *b = nullptr;
bool to_exists = astar.points.lookup(p_to_id, b);
ERR_FAIL_COND_V_MSG(!to_exists, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_to_id));
diff --git a/core/math/a_star_grid_2d.cpp b/core/math/a_star_grid_2d.cpp
index 379d34aa2a..d17f465ab8 100644
--- a/core/math/a_star_grid_2d.cpp
+++ b/core/math/a_star_grid_2d.cpp
@@ -106,16 +106,45 @@ Size2 AStarGrid2D::get_cell_size() const {
return cell_size;
}
+void AStarGrid2D::set_cell_shape(CellShape p_cell_shape) {
+ if (cell_shape == p_cell_shape) {
+ return;
+ }
+
+ ERR_FAIL_INDEX(p_cell_shape, CellShape::CELL_SHAPE_MAX);
+ cell_shape = p_cell_shape;
+ dirty = true;
+}
+
+AStarGrid2D::CellShape AStarGrid2D::get_cell_shape() const {
+ return cell_shape;
+}
+
void AStarGrid2D::update() {
points.clear();
const int32_t end_x = region.get_end().x;
const int32_t end_y = region.get_end().y;
+ const Vector2 half_cell_size = cell_size / 2;
for (int32_t y = region.position.y; y < end_y; y++) {
LocalVector<Point> line;
for (int32_t x = region.position.x; x < end_x; x++) {
- line.push_back(Point(Vector2i(x, y), offset + Vector2(x, y) * cell_size));
+ Vector2 v = offset;
+ switch (cell_shape) {
+ case CELL_SHAPE_ISOMETRIC_RIGHT:
+ v += half_cell_size + Vector2(x + y, y - x) * half_cell_size;
+ break;
+ case CELL_SHAPE_ISOMETRIC_DOWN:
+ v += half_cell_size + Vector2(x - y, x + y) * half_cell_size;
+ break;
+ case CELL_SHAPE_SQUARE:
+ v += Vector2(x, y) * cell_size;
+ break;
+ default:
+ break;
+ }
+ line.push_back(Point(Vector2i(x, y), v));
}
points.push_back(line);
}
@@ -620,6 +649,8 @@ void AStarGrid2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_offset"), &AStarGrid2D::get_offset);
ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &AStarGrid2D::set_cell_size);
ClassDB::bind_method(D_METHOD("get_cell_size"), &AStarGrid2D::get_cell_size);
+ ClassDB::bind_method(D_METHOD("set_cell_shape", "cell_shape"), &AStarGrid2D::set_cell_shape);
+ ClassDB::bind_method(D_METHOD("get_cell_shape"), &AStarGrid2D::get_cell_shape);
ClassDB::bind_method(D_METHOD("is_in_bounds", "x", "y"), &AStarGrid2D::is_in_bounds);
ClassDB::bind_method(D_METHOD("is_in_boundsv", "id"), &AStarGrid2D::is_in_boundsv);
ClassDB::bind_method(D_METHOD("is_dirty"), &AStarGrid2D::is_dirty);
@@ -651,6 +682,7 @@ void AStarGrid2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size"), "set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "cell_size"), "set_cell_size", "get_cell_size");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_shape", PROPERTY_HINT_ENUM, "Square,IsometricRight,IsometricDown"), "set_cell_shape", "get_cell_shape");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "jumping_enabled"), "set_jumping_enabled", "is_jumping_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "default_compute_heuristic", PROPERTY_HINT_ENUM, "Euclidean,Manhattan,Octile,Chebyshev"), "set_default_compute_heuristic", "get_default_compute_heuristic");
@@ -668,4 +700,9 @@ void AStarGrid2D::_bind_methods() {
BIND_ENUM_CONSTANT(DIAGONAL_MODE_AT_LEAST_ONE_WALKABLE);
BIND_ENUM_CONSTANT(DIAGONAL_MODE_ONLY_IF_NO_OBSTACLES);
BIND_ENUM_CONSTANT(DIAGONAL_MODE_MAX);
+
+ BIND_ENUM_CONSTANT(CELL_SHAPE_SQUARE);
+ BIND_ENUM_CONSTANT(CELL_SHAPE_ISOMETRIC_RIGHT);
+ BIND_ENUM_CONSTANT(CELL_SHAPE_ISOMETRIC_DOWN);
+ BIND_ENUM_CONSTANT(CELL_SHAPE_MAX);
}
diff --git a/core/math/a_star_grid_2d.h b/core/math/a_star_grid_2d.h
index 619551b754..69cb77dd3e 100644
--- a/core/math/a_star_grid_2d.h
+++ b/core/math/a_star_grid_2d.h
@@ -56,11 +56,19 @@ public:
HEURISTIC_MAX,
};
+ enum CellShape {
+ CELL_SHAPE_SQUARE,
+ CELL_SHAPE_ISOMETRIC_RIGHT,
+ CELL_SHAPE_ISOMETRIC_DOWN,
+ CELL_SHAPE_MAX,
+ };
+
private:
Rect2i region;
Vector2 offset;
Size2 cell_size = Size2(1, 1);
bool dirty = false;
+ CellShape cell_shape = CELL_SHAPE_SQUARE;
bool jumping_enabled = false;
DiagonalMode diagonal_mode = DIAGONAL_MODE_ALWAYS;
@@ -157,6 +165,9 @@ public:
void set_cell_size(const Size2 &p_cell_size);
Size2 get_cell_size() const;
+ void set_cell_shape(CellShape p_cell_shape);
+ CellShape get_cell_shape() const;
+
void update();
bool is_in_bounds(int32_t p_x, int32_t p_y) const;
@@ -193,5 +204,6 @@ public:
VARIANT_ENUM_CAST(AStarGrid2D::DiagonalMode);
VARIANT_ENUM_CAST(AStarGrid2D::Heuristic);
+VARIANT_ENUM_CAST(AStarGrid2D::CellShape)
#endif // A_STAR_GRID_2D_H
diff --git a/core/math/aabb.cpp b/core/math/aabb.cpp
index 1071df0979..e1d49dacc0 100644
--- a/core/math/aabb.cpp
+++ b/core/math/aabb.cpp
@@ -117,6 +117,11 @@ AABB AABB::intersection(const AABB &p_aabb) const {
return AABB(min, max - min);
}
+#ifdef MINGW_ENABLED
+#undef near
+#undef far
+#endif
+
bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip, Vector3 *r_normal) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
diff --git a/core/math/basis.cpp b/core/math/basis.cpp
index 9796ac59c2..cd8c87b158 100644
--- a/core/math/basis.cpp
+++ b/core/math/basis.cpp
@@ -89,13 +89,26 @@ Basis Basis::orthogonalized() const {
return c;
}
+// Returns true if the basis vectors are orthogonal (perpendicular), so it has no skew or shear, and can be decomposed into rotation and scale.
+// See https://en.wikipedia.org/wiki/Orthogonal_basis
bool Basis::is_orthogonal() const {
- Basis identity;
- Basis m = (*this) * transposed();
+ const Vector3 x = get_column(0);
+ const Vector3 y = get_column(1);
+ const Vector3 z = get_column(2);
+ return Math::is_zero_approx(x.dot(y)) && Math::is_zero_approx(x.dot(z)) && Math::is_zero_approx(y.dot(z));
+}
- return m.is_equal_approx(identity);
+// Returns true if the basis vectors are orthonormal (orthogonal and normalized), so it has no scale, skew, or shear.
+// See https://en.wikipedia.org/wiki/Orthonormal_basis
+bool Basis::is_orthonormal() const {
+ const Vector3 x = get_column(0);
+ const Vector3 y = get_column(1);
+ const Vector3 z = get_column(2);
+ return Math::is_equal_approx(x.length_squared(), 1) && Math::is_equal_approx(y.length_squared(), 1) && Math::is_equal_approx(z.length_squared(), 1) && Math::is_zero_approx(x.dot(y)) && Math::is_zero_approx(x.dot(z)) && Math::is_zero_approx(y.dot(z));
}
+// Returns true if the basis is conformal (orthogonal, uniform scale, preserves angles and distance ratios).
+// See https://en.wikipedia.org/wiki/Conformal_linear_transformation
bool Basis::is_conformal() const {
const Vector3 x = get_column(0);
const Vector3 y = get_column(1);
@@ -104,6 +117,7 @@ bool Basis::is_conformal() const {
return Math::is_equal_approx(x_len_sq, y.length_squared()) && Math::is_equal_approx(x_len_sq, z.length_squared()) && Math::is_zero_approx(x.dot(y)) && Math::is_zero_approx(x.dot(z)) && Math::is_zero_approx(y.dot(z));
}
+// Returns true if the basis only has diagonal elements, so it may only have scale or flip, but no rotation, skew, or shear.
bool Basis::is_diagonal() const {
return (
Math::is_zero_approx(rows[0][1]) && Math::is_zero_approx(rows[0][2]) &&
@@ -111,8 +125,9 @@ bool Basis::is_diagonal() const {
Math::is_zero_approx(rows[2][0]) && Math::is_zero_approx(rows[2][1]));
}
+// Returns true if the basis is a pure rotation matrix, so it has no scale, skew, shear, or flip.
bool Basis::is_rotation() const {
- return Math::is_equal_approx(determinant(), 1, (real_t)UNIT_EPSILON) && is_orthogonal();
+ return is_conformal() && Math::is_equal_approx(determinant(), 1, (real_t)UNIT_EPSILON);
}
#ifdef MATH_CHECKS
diff --git a/core/math/basis.h b/core/math/basis.h
index adacd1c216..e3094114e8 100644
--- a/core/math/basis.h
+++ b/core/math/basis.h
@@ -136,8 +136,11 @@ struct _NO_DISCARD_ Basis {
_FORCE_INLINE_ Basis operator-(const Basis &p_matrix) const;
_FORCE_INLINE_ void operator*=(const real_t p_val);
_FORCE_INLINE_ Basis operator*(const real_t p_val) const;
+ _FORCE_INLINE_ void operator/=(const real_t p_val);
+ _FORCE_INLINE_ Basis operator/(const real_t p_val) const;
bool is_orthogonal() const;
+ bool is_orthonormal() const;
bool is_conformal() const;
bool is_diagonal() const;
bool is_rotation() const;
@@ -288,6 +291,18 @@ _FORCE_INLINE_ Basis Basis::operator*(const real_t p_val) const {
return ret;
}
+_FORCE_INLINE_ void Basis::operator/=(const real_t p_val) {
+ rows[0] /= p_val;
+ rows[1] /= p_val;
+ rows[2] /= p_val;
+}
+
+_FORCE_INLINE_ Basis Basis::operator/(const real_t p_val) const {
+ Basis ret(*this);
+ ret /= p_val;
+ return ret;
+}
+
Vector3 Basis::xform(const Vector3 &p_vector) const {
return Vector3(
rows[0].dot(p_vector),
diff --git a/core/math/dynamic_bvh.h b/core/math/dynamic_bvh.h
index dbc1cb31de..9b49fcc3c8 100644
--- a/core/math/dynamic_bvh.h
+++ b/core/math/dynamic_bvh.h
@@ -328,7 +328,8 @@ void DynamicBVH::aabb_query(const AABB &p_box, QueryResult &r_result) {
volume.min = p_box.position;
volume.max = p_box.position + p_box.size;
- const Node **stack = (const Node **)alloca(ALLOCA_STACK_SIZE * sizeof(const Node *));
+ const Node **alloca_stack = (const Node **)alloca(ALLOCA_STACK_SIZE * sizeof(const Node *));
+ const Node **stack = alloca_stack;
stack[0] = bvh_root;
int32_t depth = 1;
int32_t threshold = ALLOCA_STACK_SIZE - 2;
@@ -343,7 +344,8 @@ void DynamicBVH::aabb_query(const AABB &p_box, QueryResult &r_result) {
if (depth > threshold) {
if (aux_stack.is_empty()) {
aux_stack.resize(ALLOCA_STACK_SIZE * 2);
- memcpy(aux_stack.ptr(), stack, ALLOCA_STACK_SIZE * sizeof(const Node *));
+ memcpy(aux_stack.ptr(), alloca_stack, ALLOCA_STACK_SIZE * sizeof(const Node *));
+ alloca_stack = nullptr;
} else {
aux_stack.resize(aux_stack.size() * 2);
}
@@ -384,7 +386,8 @@ void DynamicBVH::convex_query(const Plane *p_planes, int p_plane_count, const Ve
}
}
- const Node **stack = (const Node **)alloca(ALLOCA_STACK_SIZE * sizeof(const Node *));
+ const Node **alloca_stack = (const Node **)alloca(ALLOCA_STACK_SIZE * sizeof(const Node *));
+ const Node **stack = alloca_stack;
stack[0] = bvh_root;
int32_t depth = 1;
int32_t threshold = ALLOCA_STACK_SIZE - 2;
@@ -399,7 +402,8 @@ void DynamicBVH::convex_query(const Plane *p_planes, int p_plane_count, const Ve
if (depth > threshold) {
if (aux_stack.is_empty()) {
aux_stack.resize(ALLOCA_STACK_SIZE * 2);
- memcpy(aux_stack.ptr(), stack, ALLOCA_STACK_SIZE * sizeof(const Node *));
+ memcpy(aux_stack.ptr(), alloca_stack, ALLOCA_STACK_SIZE * sizeof(const Node *));
+ alloca_stack = nullptr;
} else {
aux_stack.resize(aux_stack.size() * 2);
}
@@ -436,7 +440,8 @@ void DynamicBVH::ray_query(const Vector3 &p_from, const Vector3 &p_to, QueryResu
Vector3 bounds[2];
- const Node **stack = (const Node **)alloca(ALLOCA_STACK_SIZE * sizeof(const Node *));
+ const Node **alloca_stack = (const Node **)alloca(ALLOCA_STACK_SIZE * sizeof(const Node *));
+ const Node **stack = alloca_stack;
stack[0] = bvh_root;
int32_t depth = 1;
int32_t threshold = ALLOCA_STACK_SIZE - 2;
@@ -456,7 +461,8 @@ void DynamicBVH::ray_query(const Vector3 &p_from, const Vector3 &p_to, QueryResu
if (depth > threshold) {
if (aux_stack.is_empty()) {
aux_stack.resize(ALLOCA_STACK_SIZE * 2);
- memcpy(aux_stack.ptr(), stack, ALLOCA_STACK_SIZE * sizeof(const Node *));
+ memcpy(aux_stack.ptr(), alloca_stack, ALLOCA_STACK_SIZE * sizeof(const Node *));
+ alloca_stack = nullptr;
} else {
aux_stack.resize(aux_stack.size() * 2);
}
diff --git a/core/math/geometry_3d.h b/core/math/geometry_3d.h
index 99c554fe05..305a64e39c 100644
--- a/core/math/geometry_3d.h
+++ b/core/math/geometry_3d.h
@@ -31,6 +31,7 @@
#ifndef GEOMETRY_3D_H
#define GEOMETRY_3D_H
+#include "core/math/delaunay_3d.h"
#include "core/math/face3.h"
#include "core/object/object.h"
#include "core/templates/local_vector.h"
@@ -532,6 +533,21 @@ public:
return clipped;
}
+ static Vector<int32_t> tetrahedralize_delaunay(const Vector<Vector3> &p_points) {
+ Vector<Delaunay3D::OutputSimplex> tetr = Delaunay3D::tetrahedralize(p_points);
+ Vector<int32_t> tetrahedrons;
+
+ tetrahedrons.resize(4 * tetr.size());
+ int32_t *ptr = tetrahedrons.ptrw();
+ for (int i = 0; i < tetr.size(); i++) {
+ *ptr++ = tetr[i].points[0];
+ *ptr++ = tetr[i].points[1];
+ *ptr++ = tetr[i].points[2];
+ *ptr++ = tetr[i].points[3];
+ }
+ return tetrahedrons;
+ }
+
// Create a "wrap" that encloses the given geometry.
static Vector<Face3> wrap_geometry(Vector<Face3> p_array, real_t *p_error = nullptr);
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index 366ccca4cb..3060f31970 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -198,6 +198,22 @@ public:
#endif
}
+ // These methods assume (p_num + p_den) doesn't overflow.
+ static _ALWAYS_INLINE_ int32_t division_round_up(int32_t p_num, int32_t p_den) {
+ int32_t offset = (p_num < 0 && p_den < 0) ? 1 : -1;
+ return (p_num + p_den + offset) / p_den;
+ }
+ static _ALWAYS_INLINE_ uint32_t division_round_up(uint32_t p_num, uint32_t p_den) {
+ return (p_num + p_den - 1) / p_den;
+ }
+ static _ALWAYS_INLINE_ int64_t division_round_up(int64_t p_num, int64_t p_den) {
+ int32_t offset = (p_num < 0 && p_den < 0) ? 1 : -1;
+ return (p_num + p_den + offset) / p_den;
+ }
+ static _ALWAYS_INLINE_ uint64_t division_round_up(uint64_t p_num, uint64_t p_den) {
+ return (p_num + p_den - 1) / p_den;
+ }
+
static _ALWAYS_INLINE_ bool is_finite(double p_val) { return isfinite(p_val); }
static _ALWAYS_INLINE_ bool is_finite(float p_val) { return isfinite(p_val); }
diff --git a/core/math/rect2.h b/core/math/rect2.h
index 6ccb76cd10..5f403458fd 100644
--- a/core/math/rect2.h
+++ b/core/math/rect2.h
@@ -285,6 +285,10 @@ struct _NO_DISCARD_ Rect2 {
return Rect2(Point2(position.x + MIN(size.x, (real_t)0), position.y + MIN(size.y, (real_t)0)), size.abs());
}
+ _FORCE_INLINE_ Rect2 round() const {
+ return Rect2(position.round(), size.round());
+ }
+
Vector2 get_support(const Vector2 &p_normal) const {
Vector2 half_extents = size * 0.5f;
Vector2 ofs = position + half_extents;
diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp
index bc4682fd90..a22d075b64 100644
--- a/core/math/transform_2d.cpp
+++ b/core/math/transform_2d.cpp
@@ -295,6 +295,18 @@ Transform2D Transform2D::operator*(const real_t p_val) const {
return ret;
}
+void Transform2D::operator/=(const real_t p_val) {
+ columns[0] /= p_val;
+ columns[1] /= p_val;
+ columns[2] /= p_val;
+}
+
+Transform2D Transform2D::operator/(const real_t p_val) const {
+ Transform2D ret(*this);
+ ret /= p_val;
+ return ret;
+}
+
Transform2D::operator String() const {
return "[X: " + columns[0].operator String() +
", Y: " + columns[1].operator String() +
diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h
index dd1a33c5d5..9ff925f66f 100644
--- a/core/math/transform_2d.h
+++ b/core/math/transform_2d.h
@@ -109,6 +109,8 @@ struct _NO_DISCARD_ Transform2D {
Transform2D operator*(const Transform2D &p_transform) const;
void operator*=(const real_t p_val);
Transform2D operator*(const real_t p_val) const;
+ void operator/=(const real_t p_val);
+ Transform2D operator/(const real_t p_val) const;
Transform2D interpolate_with(const Transform2D &p_transform, const real_t p_c) const;
diff --git a/core/math/transform_3d.cpp b/core/math/transform_3d.cpp
index cdc94676c9..20713349d7 100644
--- a/core/math/transform_3d.cpp
+++ b/core/math/transform_3d.cpp
@@ -208,6 +208,17 @@ Transform3D Transform3D::operator*(const real_t p_val) const {
return ret;
}
+void Transform3D::operator/=(const real_t p_val) {
+ basis /= p_val;
+ origin /= p_val;
+}
+
+Transform3D Transform3D::operator/(const real_t p_val) const {
+ Transform3D ret(*this);
+ ret /= p_val;
+ return ret;
+}
+
Transform3D::operator String() const {
return "[X: " + basis.get_column(0).operator String() +
", Y: " + basis.get_column(1).operator String() +
diff --git a/core/math/transform_3d.h b/core/math/transform_3d.h
index 70141a3dbe..d1ec34d53f 100644
--- a/core/math/transform_3d.h
+++ b/core/math/transform_3d.h
@@ -104,6 +104,8 @@ struct _NO_DISCARD_ Transform3D {
Transform3D operator*(const Transform3D &p_transform) const;
void operator*=(const real_t p_val);
Transform3D operator*(const real_t p_val) const;
+ void operator/=(const real_t p_val);
+ Transform3D operator/(const real_t p_val) const;
Transform3D interpolate_with(const Transform3D &p_transform, real_t p_c) const;
diff --git a/core/math/vector2i.h b/core/math/vector2i.h
index e6850347c3..b2c75beb4d 100644
--- a/core/math/vector2i.h
+++ b/core/math/vector2i.h
@@ -85,6 +85,14 @@ struct _NO_DISCARD_ Vector2i {
return Vector2i(MAX(x, p_vector2i.x), MAX(y, p_vector2i.y));
}
+ double distance_to(const Vector2i &p_to) const {
+ return (p_to - *this).length();
+ }
+
+ int64_t distance_squared_to(const Vector2i &p_to) const {
+ return (p_to - *this).length_squared();
+ }
+
Vector2i operator+(const Vector2i &p_v) const;
void operator+=(const Vector2i &p_v);
Vector2i operator-(const Vector2i &p_v) const;
diff --git a/core/math/vector3i.h b/core/math/vector3i.h
index 53d3829a99..5a5e9deda8 100644
--- a/core/math/vector3i.h
+++ b/core/math/vector3i.h
@@ -87,6 +87,9 @@ struct _NO_DISCARD_ Vector3i {
Vector3i clamp(const Vector3i &p_min, const Vector3i &p_max) const;
Vector3i snapped(const Vector3i &p_step) const;
+ _FORCE_INLINE_ double distance_to(const Vector3i &p_to) const;
+ _FORCE_INLINE_ int64_t distance_squared_to(const Vector3i &p_to) const;
+
/* Operators */
_FORCE_INLINE_ Vector3i &operator+=(const Vector3i &p_v);
@@ -143,6 +146,14 @@ Vector3i Vector3i::sign() const {
return Vector3i(SIGN(x), SIGN(y), SIGN(z));
}
+double Vector3i::distance_to(const Vector3i &p_to) const {
+ return (p_to - *this).length();
+}
+
+int64_t Vector3i::distance_squared_to(const Vector3i &p_to) const {
+ return (p_to - *this).length_squared();
+}
+
/* Operators */
Vector3i &Vector3i::operator+=(const Vector3i &p_v) {
diff --git a/core/math/vector4i.h b/core/math/vector4i.h
index b815aa8e76..7d85d473d9 100644
--- a/core/math/vector4i.h
+++ b/core/math/vector4i.h
@@ -84,6 +84,9 @@ struct _NO_DISCARD_ Vector4i {
_FORCE_INLINE_ void zero();
+ _FORCE_INLINE_ double distance_to(const Vector4i &p_to) const;
+ _FORCE_INLINE_ int64_t distance_squared_to(const Vector4i &p_to) const;
+
_FORCE_INLINE_ Vector4i abs() const;
_FORCE_INLINE_ Vector4i sign() const;
Vector4i clamp(const Vector4i &p_min, const Vector4i &p_max) const;
@@ -139,6 +142,14 @@ double Vector4i::length() const {
return Math::sqrt((double)length_squared());
}
+double Vector4i::distance_to(const Vector4i &p_to) const {
+ return (p_to - *this).length();
+}
+
+int64_t Vector4i::distance_squared_to(const Vector4i &p_to) const {
+ return (p_to - *this).length_squared();
+}
+
Vector4i Vector4i::abs() const {
return Vector4i(Math::abs(x), Math::abs(y), Math::abs(z), Math::abs(w));
}