diff options
Diffstat (limited to 'core/math')
-rw-r--r-- | core/math/a_star.cpp | 56 | ||||
-rw-r--r-- | core/math/a_star_grid_2d.cpp | 39 | ||||
-rw-r--r-- | core/math/a_star_grid_2d.h | 12 | ||||
-rw-r--r-- | core/math/aabb.cpp | 5 | ||||
-rw-r--r-- | core/math/basis.cpp | 23 | ||||
-rw-r--r-- | core/math/basis.h | 15 | ||||
-rw-r--r-- | core/math/dynamic_bvh.h | 18 | ||||
-rw-r--r-- | core/math/geometry_3d.h | 16 | ||||
-rw-r--r-- | core/math/math_funcs.h | 16 | ||||
-rw-r--r-- | core/math/rect2.h | 4 | ||||
-rw-r--r-- | core/math/transform_2d.cpp | 12 | ||||
-rw-r--r-- | core/math/transform_2d.h | 2 | ||||
-rw-r--r-- | core/math/transform_3d.cpp | 11 | ||||
-rw-r--r-- | core/math/transform_3d.h | 2 | ||||
-rw-r--r-- | core/math/vector2i.h | 8 | ||||
-rw-r--r-- | core/math/vector3i.h | 11 | ||||
-rw-r--r-- | core/math/vector4i.h | 11 |
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)); } |