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.cpp14
-rw-r--r--core/math/aabb.h6
-rw-r--r--core/math/audio_frame.h110
-rw-r--r--core/math/basis.cpp27
-rw-r--r--core/math/basis.h15
-rw-r--r--core/math/convex_hull.cpp16
-rw-r--r--core/math/dynamic_bvh.h18
-rw-r--r--core/math/geometry_2d.cpp2
-rw-r--r--core/math/geometry_2d.h26
-rw-r--r--core/math/geometry_3d.h16
-rw-r--r--core/math/math_funcs.h16
-rw-r--r--core/math/quaternion.cpp22
-rw-r--r--core/math/quaternion.h5
-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/vector2.cpp8
-rw-r--r--core/math/vector2i.h8
-rw-r--r--core/math/vector3.cpp2
-rw-r--r--core/math/vector3.h10
-rw-r--r--core/math/vector3i.h11
-rw-r--r--core/math/vector4i.h11
26 files changed, 347 insertions, 130 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..76e9e74dea 100644
--- a/core/math/aabb.cpp
+++ b/core/math/aabb.cpp
@@ -125,8 +125,8 @@ bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *
#endif
Vector3 c1, c2;
Vector3 end = position + size;
- real_t near = -1e20;
- real_t far = 1e20;
+ real_t depth_near = -1e20;
+ real_t depth_far = 1e20;
int axis = 0;
for (int i = 0; i < 3; i++) {
@@ -141,14 +141,14 @@ bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *
if (c1[i] > c2[i]) {
SWAP(c1, c2);
}
- if (c1[i] > near) {
- near = c1[i];
+ if (c1[i] > depth_near) {
+ depth_near = c1[i];
axis = i;
}
- if (c2[i] < far) {
- far = c2[i];
+ if (c2[i] < depth_far) {
+ depth_far = c2[i];
}
- if ((near > far) || (far < 0)) {
+ if ((depth_near > depth_far) || (depth_far < 0)) {
return false;
}
}
diff --git a/core/math/aabb.h b/core/math/aabb.h
index 859810df37..cea845bf7c 100644
--- a/core/math/aabb.h
+++ b/core/math/aabb.h
@@ -200,11 +200,11 @@ inline bool AABB::encloses(const AABB &p_aabb) const {
return (
(src_min.x <= dst_min.x) &&
- (src_max.x > dst_max.x) &&
+ (src_max.x >= dst_max.x) &&
(src_min.y <= dst_min.y) &&
- (src_max.y > dst_max.y) &&
+ (src_max.y >= dst_max.y) &&
(src_min.z <= dst_min.z) &&
- (src_max.z > dst_max.z));
+ (src_max.z >= dst_max.z));
}
Vector3 AABB::get_support(const Vector3 &p_normal) const {
diff --git a/core/math/audio_frame.h b/core/math/audio_frame.h
index d26336e9a2..e205126cdf 100644
--- a/core/math/audio_frame.h
+++ b/core/math/audio_frame.h
@@ -51,105 +51,123 @@ static const float AUDIO_PEAK_OFFSET = 0.0000000001f;
static const float AUDIO_MIN_PEAK_DB = -200.0f; // linear_to_db(AUDIO_PEAK_OFFSET)
struct AudioFrame {
- //left and right samples
- float l = 0.f, r = 0.f;
-
- _ALWAYS_INLINE_ const float &operator[](int idx) const { return idx == 0 ? l : r; }
- _ALWAYS_INLINE_ float &operator[](int idx) { return idx == 0 ? l : r; }
+ // Left and right samples.
+ union {
+ struct {
+ float left;
+ float right;
+ };
+#ifndef DISABLE_DEPRECATED
+ struct {
+ float l;
+ float r;
+ };
+#endif
+ float levels[2] = { 0.0 };
+ };
+
+ _ALWAYS_INLINE_ const float &operator[](int p_idx) const {
+ DEV_ASSERT((unsigned int)p_idx < 2);
+ return levels[p_idx];
+ }
+ _ALWAYS_INLINE_ float &operator[](int p_idx) {
+ DEV_ASSERT((unsigned int)p_idx < 2);
+ return levels[p_idx];
+ }
- _ALWAYS_INLINE_ AudioFrame operator+(const AudioFrame &p_frame) const { return AudioFrame(l + p_frame.l, r + p_frame.r); }
- _ALWAYS_INLINE_ AudioFrame operator-(const AudioFrame &p_frame) const { return AudioFrame(l - p_frame.l, r - p_frame.r); }
- _ALWAYS_INLINE_ AudioFrame operator*(const AudioFrame &p_frame) const { return AudioFrame(l * p_frame.l, r * p_frame.r); }
- _ALWAYS_INLINE_ AudioFrame operator/(const AudioFrame &p_frame) const { return AudioFrame(l / p_frame.l, r / p_frame.r); }
+ _ALWAYS_INLINE_ AudioFrame operator+(const AudioFrame &p_frame) const { return AudioFrame(left + p_frame.left, right + p_frame.right); }
+ _ALWAYS_INLINE_ AudioFrame operator-(const AudioFrame &p_frame) const { return AudioFrame(left - p_frame.left, right - p_frame.right); }
+ _ALWAYS_INLINE_ AudioFrame operator*(const AudioFrame &p_frame) const { return AudioFrame(left * p_frame.left, right * p_frame.right); }
+ _ALWAYS_INLINE_ AudioFrame operator/(const AudioFrame &p_frame) const { return AudioFrame(left / p_frame.left, right / p_frame.right); }
- _ALWAYS_INLINE_ AudioFrame operator+(float p_sample) const { return AudioFrame(l + p_sample, r + p_sample); }
- _ALWAYS_INLINE_ AudioFrame operator-(float p_sample) const { return AudioFrame(l - p_sample, r - p_sample); }
- _ALWAYS_INLINE_ AudioFrame operator*(float p_sample) const { return AudioFrame(l * p_sample, r * p_sample); }
- _ALWAYS_INLINE_ AudioFrame operator/(float p_sample) const { return AudioFrame(l / p_sample, r / p_sample); }
+ _ALWAYS_INLINE_ AudioFrame operator+(float p_sample) const { return AudioFrame(left + p_sample, right + p_sample); }
+ _ALWAYS_INLINE_ AudioFrame operator-(float p_sample) const { return AudioFrame(left - p_sample, right - p_sample); }
+ _ALWAYS_INLINE_ AudioFrame operator*(float p_sample) const { return AudioFrame(left * p_sample, right * p_sample); }
+ _ALWAYS_INLINE_ AudioFrame operator/(float p_sample) const { return AudioFrame(left / p_sample, right / p_sample); }
_ALWAYS_INLINE_ void operator+=(const AudioFrame &p_frame) {
- l += p_frame.l;
- r += p_frame.r;
+ left += p_frame.left;
+ right += p_frame.right;
}
_ALWAYS_INLINE_ void operator-=(const AudioFrame &p_frame) {
- l -= p_frame.l;
- r -= p_frame.r;
+ left -= p_frame.left;
+ right -= p_frame.right;
}
_ALWAYS_INLINE_ void operator*=(const AudioFrame &p_frame) {
- l *= p_frame.l;
- r *= p_frame.r;
+ left *= p_frame.left;
+ right *= p_frame.right;
}
_ALWAYS_INLINE_ void operator/=(const AudioFrame &p_frame) {
- l /= p_frame.l;
- r /= p_frame.r;
+ left /= p_frame.left;
+ right /= p_frame.right;
}
_ALWAYS_INLINE_ void operator+=(float p_sample) {
- l += p_sample;
- r += p_sample;
+ left += p_sample;
+ right += p_sample;
}
_ALWAYS_INLINE_ void operator-=(float p_sample) {
- l -= p_sample;
- r -= p_sample;
+ left -= p_sample;
+ right -= p_sample;
}
_ALWAYS_INLINE_ void operator*=(float p_sample) {
- l *= p_sample;
- r *= p_sample;
+ left *= p_sample;
+ right *= p_sample;
}
_ALWAYS_INLINE_ void operator/=(float p_sample) {
- l /= p_sample;
- r /= p_sample;
+ left /= p_sample;
+ right /= p_sample;
}
_ALWAYS_INLINE_ void undenormalize() {
- l = ::undenormalize(l);
- r = ::undenormalize(r);
+ left = ::undenormalize(left);
+ right = ::undenormalize(right);
}
_FORCE_INLINE_ AudioFrame lerp(const AudioFrame &p_b, float p_t) const {
AudioFrame res = *this;
- res.l += (p_t * (p_b.l - l));
- res.r += (p_t * (p_b.r - r));
+ res.left += (p_t * (p_b.left - left));
+ res.right += (p_t * (p_b.right - right));
return res;
}
- _ALWAYS_INLINE_ AudioFrame(float p_l, float p_r) {
- l = p_l;
- r = p_r;
+ _ALWAYS_INLINE_ AudioFrame(float p_left, float p_right) {
+ left = p_left;
+ right = p_right;
}
_ALWAYS_INLINE_ AudioFrame(const AudioFrame &p_frame) {
- l = p_frame.l;
- r = p_frame.r;
+ left = p_frame.left;
+ right = p_frame.right;
}
_ALWAYS_INLINE_ void operator=(const AudioFrame &p_frame) {
- l = p_frame.l;
- r = p_frame.r;
+ left = p_frame.left;
+ right = p_frame.right;
}
_ALWAYS_INLINE_ operator Vector2() const {
- return Vector2(l, r);
+ return Vector2(left, right);
}
_ALWAYS_INLINE_ AudioFrame(const Vector2 &p_v2) {
- l = p_v2.x;
- r = p_v2.y;
+ left = p_v2.x;
+ right = p_v2.y;
}
_ALWAYS_INLINE_ AudioFrame() {}
};
_ALWAYS_INLINE_ AudioFrame operator*(float p_scalar, const AudioFrame &p_frame) {
- return AudioFrame(p_frame.l * p_scalar, p_frame.r * p_scalar);
+ return AudioFrame(p_frame.left * p_scalar, p_frame.right * p_scalar);
}
_ALWAYS_INLINE_ AudioFrame operator*(int32_t p_scalar, const AudioFrame &p_frame) {
- return AudioFrame(p_frame.l * p_scalar, p_frame.r * p_scalar);
+ return AudioFrame(p_frame.left * p_scalar, p_frame.right * p_scalar);
}
_ALWAYS_INLINE_ AudioFrame operator*(int64_t p_scalar, const AudioFrame &p_frame) {
- return AudioFrame(p_frame.l * p_scalar, p_frame.r * p_scalar);
+ return AudioFrame(p_frame.left * p_scalar, p_frame.right * p_scalar);
}
#endif // AUDIO_FRAME_H
diff --git a/core/math/basis.cpp b/core/math/basis.cpp
index 9796ac59c2..1ff6cdd588 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
@@ -707,7 +722,7 @@ Basis::operator String() const {
Quaternion Basis::get_quaternion() const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_rotation(), Quaternion(), "Basis must be normalized in order to be casted to a Quaternion. Use get_rotation_quaternion() or call orthonormalized() if the Basis contains linearly independent vectors.");
+ ERR_FAIL_COND_V_MSG(!is_rotation(), Quaternion(), "Basis " + operator String() + " must be normalized in order to be casted to a Quaternion. Use get_rotation_quaternion() or call orthonormalized() if the Basis contains linearly independent vectors.");
#endif
/* Allow getting a quaternion from an unnormalized transform */
Basis m = *this;
@@ -834,7 +849,7 @@ void Basis::set_quaternion(const Quaternion &p_quaternion) {
void Basis::set_axis_angle(const Vector3 &p_axis, real_t p_angle) {
// Rotation matrix from axis and angle, see https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_angle
#ifdef MATH_CHECKS
- ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 must be normalized.");
+ ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 " + p_axis.operator String() + " must be normalized.");
#endif
Vector3 axis_sq(p_axis.x * p_axis.x, p_axis.y * p_axis.y, p_axis.z * p_axis.z);
real_t cosine = Math::cos(p_angle);
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/convex_hull.cpp b/core/math/convex_hull.cpp
index 68d995fe67..478fde3a64 100644
--- a/core/math/convex_hull.cpp
+++ b/core/math/convex_hull.cpp
@@ -344,31 +344,31 @@ public:
Rational128(int64_t p_value) {
if (p_value > 0) {
sign = 1;
- this->numerator = p_value;
+ numerator = p_value;
} else if (p_value < 0) {
sign = -1;
- this->numerator = -p_value;
+ numerator = -p_value;
} else {
sign = 0;
- this->numerator = (uint64_t)0;
+ numerator = (uint64_t)0;
}
- this->denominator = (uint64_t)1;
+ denominator = (uint64_t)1;
is_int_64 = true;
}
Rational128(const Int128 &p_numerator, const Int128 &p_denominator) {
sign = p_numerator.get_sign();
if (sign >= 0) {
- this->numerator = p_numerator;
+ numerator = p_numerator;
} else {
- this->numerator = -p_numerator;
+ numerator = -p_numerator;
}
int32_t dsign = p_denominator.get_sign();
if (dsign >= 0) {
- this->denominator = p_denominator;
+ denominator = p_denominator;
} else {
sign = -sign;
- this->denominator = -p_denominator;
+ denominator = -p_denominator;
}
is_int_64 = false;
}
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_2d.cpp b/core/math/geometry_2d.cpp
index 74cb92539a..1e5f12bebf 100644
--- a/core/math/geometry_2d.cpp
+++ b/core/math/geometry_2d.cpp
@@ -93,7 +93,7 @@ void Geometry2D::make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_re
// For example, it will prioritize a 1024x1024 atlas (works everywhere) instead of a
// 256x8192 atlas (won't work anywhere).
- ERR_FAIL_COND(p_rects.size() == 0);
+ ERR_FAIL_COND(p_rects.is_empty());
for (int i = 0; i < p_rects.size(); i++) {
ERR_FAIL_COND(p_rects[i].width <= 0);
ERR_FAIL_COND(p_rects[i].height <= 0);
diff --git a/core/math/geometry_2d.h b/core/math/geometry_2d.h
index b37fce9e9c..9907d579a5 100644
--- a/core/math/geometry_2d.h
+++ b/core/math/geometry_2d.h
@@ -119,6 +119,10 @@ public:
}
}
+ static real_t get_distance_to_segment(const Vector2 &p_point, const Vector2 *p_segment) {
+ return p_point.distance_to(get_closest_point_to_segment(p_point, p_segment));
+ }
+
static bool is_point_in_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) {
Vector2 an = a - s;
Vector2 bn = b - s;
@@ -249,6 +253,28 @@ public:
return -1;
}
+ static bool segment_intersects_rect(const Vector2 &p_from, const Vector2 &p_to, const Rect2 &p_rect) {
+ if (p_rect.has_point(p_from) || p_rect.has_point(p_to)) {
+ return true;
+ }
+
+ const Vector2 rect_points[4] = {
+ p_rect.position,
+ p_rect.position + Vector2(p_rect.size.x, 0),
+ p_rect.position + p_rect.size,
+ p_rect.position + Vector2(0, p_rect.size.y)
+ };
+
+ // Check if any of the rect's edges intersect the segment.
+ for (int i = 0; i < 4; i++) {
+ if (segment_intersects_segment(p_from, p_to, rect_points[i], rect_points[(i + 1) % 4], nullptr)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
enum PolyBooleanOperation {
OPERATION_UNION,
OPERATION_DIFFERENCE,
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/quaternion.cpp b/core/math/quaternion.cpp
index e4ad17c8ef..cbaaa1371a 100644
--- a/core/math/quaternion.cpp
+++ b/core/math/quaternion.cpp
@@ -41,7 +41,7 @@ real_t Quaternion::angle_to(const Quaternion &p_to) const {
Vector3 Quaternion::get_euler(EulerOrder p_order) const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), Vector3(0, 0, 0), "The quaternion must be normalized.");
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Vector3(0, 0, 0), "The quaternion " + operator String() + " must be normalized.");
#endif
return Basis(*this).get_euler(p_order);
}
@@ -88,7 +88,7 @@ bool Quaternion::is_normalized() const {
Quaternion Quaternion::inverse() const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The quaternion must be normalized.");
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The quaternion " + operator String() + " must be normalized.");
#endif
return Quaternion(-x, -y, -z, w);
}
@@ -112,8 +112,8 @@ Quaternion Quaternion::exp() const {
Quaternion Quaternion::slerp(const Quaternion &p_to, const real_t &p_weight) const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
- ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized.");
+ ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion " + p_to.operator String() + " must be normalized.");
#endif
Quaternion to1;
real_t omega, cosom, sinom, scale0, scale1;
@@ -153,8 +153,8 @@ Quaternion Quaternion::slerp(const Quaternion &p_to, const real_t &p_weight) con
Quaternion Quaternion::slerpni(const Quaternion &p_to, const real_t &p_weight) const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
- ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized.");
+ ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion " + p_to.operator String() + " must be normalized.");
#endif
const Quaternion &from = *this;
@@ -177,8 +177,8 @@ Quaternion Quaternion::slerpni(const Quaternion &p_to, const real_t &p_weight) c
Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
- ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized.");
+ ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion " + p_b.operator String() + " must be normalized.");
#endif
Quaternion from_q = *this;
Quaternion pre_q = p_pre_a;
@@ -228,8 +228,8 @@ Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const
Quaternion Quaternion::spherical_cubic_interpolate_in_time(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight,
const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
- ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
+ ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized.");
+ ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion " + p_b.operator String() + " must be normalized.");
#endif
Quaternion from_q = *this;
Quaternion pre_q = p_pre_a;
@@ -294,7 +294,7 @@ real_t Quaternion::get_angle() const {
Quaternion::Quaternion(const Vector3 &p_axis, real_t p_angle) {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 must be normalized.");
+ ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 " + p_axis.operator String() + " must be normalized.");
#endif
real_t d = p_axis.length();
if (d == 0) {
diff --git a/core/math/quaternion.h b/core/math/quaternion.h
index ea952304a5..f8133df559 100644
--- a/core/math/quaternion.h
+++ b/core/math/quaternion.h
@@ -33,8 +33,7 @@
#include "core/math/math_funcs.h"
#include "core/math/vector3.h"
-
-class String;
+#include "core/string/ustring.h"
struct _NO_DISCARD_ Quaternion {
union {
@@ -90,7 +89,7 @@ struct _NO_DISCARD_ Quaternion {
_FORCE_INLINE_ Vector3 xform(const Vector3 &v) const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!is_normalized(), v, "The quaternion must be normalized.");
+ ERR_FAIL_COND_V_MSG(!is_normalized(), v, "The quaternion " + operator String() + " must be normalized.");
#endif
Vector3 u(x, y, z);
Vector3 uv = u.cross(v);
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/vector2.cpp b/core/math/vector2.cpp
index df8c804243..74631d3e29 100644
--- a/core/math/vector2.cpp
+++ b/core/math/vector2.cpp
@@ -162,9 +162,9 @@ Vector2 Vector2::move_toward(const Vector2 &p_to, const real_t p_delta) const {
// slide returns the component of the vector along the given plane, specified by its normal vector.
Vector2 Vector2::slide(const Vector2 &p_normal) const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 must be normalized.");
+ ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 " + p_normal.operator String() + "must be normalized.");
#endif
- return *this - p_normal * this->dot(p_normal);
+ return *this - p_normal * dot(p_normal);
}
Vector2 Vector2::bounce(const Vector2 &p_normal) const {
@@ -173,9 +173,9 @@ Vector2 Vector2::bounce(const Vector2 &p_normal) const {
Vector2 Vector2::reflect(const Vector2 &p_normal) const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 must be normalized.");
+ ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 " + p_normal.operator String() + "must be normalized.");
#endif
- return 2.0f * p_normal * this->dot(p_normal) - *this;
+ return 2.0f * p_normal * dot(p_normal) - *this;
}
bool Vector2::is_equal_approx(const Vector2 &p_v) 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/vector3.cpp b/core/math/vector3.cpp
index ae009fc4ef..c483d659a3 100644
--- a/core/math/vector3.cpp
+++ b/core/math/vector3.cpp
@@ -109,7 +109,7 @@ Vector3 Vector3::octahedron_decode(const Vector2 &p_oct) {
Vector2 Vector3::octahedron_tangent_encode(const float sign) const {
const float bias = 1.0f / 32767.0f;
- Vector2 res = this->octahedron_encode();
+ Vector2 res = octahedron_encode();
res.y = MAX(res.y, bias);
res.y = res.y * 0.5f + 0.5f;
res.y = sign >= 0.0f ? res.y : 1 - res.y;
diff --git a/core/math/vector3.h b/core/math/vector3.h
index 18943a820f..5d4e2c7d87 100644
--- a/core/math/vector3.h
+++ b/core/math/vector3.h
@@ -33,8 +33,8 @@
#include "core/error/error_macros.h"
#include "core/math/math_funcs.h"
+#include "core/string/ustring.h"
-class String;
struct Basis;
struct Vector2;
struct Vector3i;
@@ -512,9 +512,9 @@ void Vector3::zero() {
// slide returns the component of the vector along the given plane, specified by its normal vector.
Vector3 Vector3::slide(const Vector3 &p_normal) const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 must be normalized.");
+ ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 " + p_normal.operator String() + " must be normalized.");
#endif
- return *this - p_normal * this->dot(p_normal);
+ return *this - p_normal * dot(p_normal);
}
Vector3 Vector3::bounce(const Vector3 &p_normal) const {
@@ -523,9 +523,9 @@ Vector3 Vector3::bounce(const Vector3 &p_normal) const {
Vector3 Vector3::reflect(const Vector3 &p_normal) const {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 must be normalized.");
+ ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 " + p_normal.operator String() + " must be normalized.");
#endif
- return 2.0f * p_normal * this->dot(p_normal) - *this;
+ return 2.0f * p_normal * dot(p_normal) - *this;
}
#endif // VECTOR3_H
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));
}