diff options
Diffstat (limited to 'core/math')
-rw-r--r-- | core/math/a_star.cpp | 3 | ||||
-rw-r--r-- | core/math/a_star.h | 4 | ||||
-rw-r--r-- | core/math/aabb.h | 2 | ||||
-rw-r--r-- | core/math/basis.cpp | 39 | ||||
-rw-r--r-- | core/math/basis.h | 9 | ||||
-rw-r--r-- | core/math/camera_matrix.cpp | 13 | ||||
-rw-r--r-- | core/math/color.h | 2 | ||||
-rw-r--r-- | core/math/disjoint_set.h | 4 | ||||
-rw-r--r-- | core/math/face3.cpp | 8 | ||||
-rw-r--r-- | core/math/face3.h | 2 | ||||
-rw-r--r-- | core/math/geometry_3d.cpp | 80 | ||||
-rw-r--r-- | core/math/octree.h | 2 | ||||
-rw-r--r-- | core/math/plane.h | 2 | ||||
-rw-r--r-- | core/math/quaternion.h | 2 | ||||
-rw-r--r-- | core/math/rect2.h | 24 | ||||
-rw-r--r-- | core/math/transform_2d.h | 2 | ||||
-rw-r--r-- | core/math/transform_3d.cpp | 24 | ||||
-rw-r--r-- | core/math/transform_3d.h | 5 | ||||
-rw-r--r-- | core/math/vector2.cpp | 8 | ||||
-rw-r--r-- | core/math/vector2.h | 22 | ||||
-rw-r--r-- | core/math/vector3.h | 14 | ||||
-rw-r--r-- | core/math/vector3i.h | 14 |
22 files changed, 183 insertions, 102 deletions
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp index ebe88fcf66..ce2435216b 100644 --- a/core/math/a_star.cpp +++ b/core/math/a_star.cpp @@ -699,8 +699,7 @@ Vector<Vector2> AStar2D::get_point_path(int p_from_id, int p_to_id) { 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)); if (a == b) { - Vector<Vector2> ret; - ret.push_back(Vector2(a->pos.x, a->pos.y)); + Vector<Vector2> ret = { Vector2(a->pos.x, a->pos.y) }; return ret; } diff --git a/core/math/a_star.h b/core/math/a_star.h index 1839ec7e04..130c202a61 100644 --- a/core/math/a_star.h +++ b/core/math/a_star.h @@ -37,9 +37,7 @@ #include "core/templates/oa_hash_map.h" /** - A* pathfinding algorithm - - @author Juan Linietsky <reduzio@gmail.com> + A* pathfinding algorithm. */ class AStar : public RefCounted { diff --git a/core/math/aabb.h b/core/math/aabb.h index 2eaaafa27d..3d19410ddf 100644 --- a/core/math/aabb.h +++ b/core/math/aabb.h @@ -41,7 +41,7 @@ */ class Variant; -class AABB { +class _NO_DISCARD_ AABB { public: Vector3 position; Vector3 size; diff --git a/core/math/basis.cpp b/core/math/basis.cpp index 6159e78bab..a9b4651664 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -94,6 +94,18 @@ Basis Basis::orthonormalized() const { return c; } +void Basis::orthogonalize() { + Vector3 scl = get_scale(); + orthonormalize(); + scale_local(scl); +} + +Basis Basis::orthogonalized() const { + Basis c = *this; + c.orthogonalize(); + return c; +} + bool Basis::is_orthogonal() const { Basis identity; Basis m = (*this) * transposed(); @@ -237,6 +249,24 @@ void Basis::scale_local(const Vector3 &p_scale) { *this = scaled_local(p_scale); } +void Basis::scale_orthogonal(const Vector3 &p_scale) { + *this = scaled_orthogonal(p_scale); +} + +Basis Basis::scaled_orthogonal(const Vector3 &p_scale) const { + Basis m = *this; + Vector3 s = Vector3(-1, -1, -1) + p_scale; + Vector3 dots; + Basis b; + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + dots[j] += s[i] * abs(m.get_axis(i).normalized().dot(b.get_axis(j))); + } + } + m.scale_local(Vector3(1, 1, 1) + dots); + return m; +} + float Basis::get_uniform_scale() const { return (elements[0].length() + elements[1].length() + elements[2].length()) / 3.0; } @@ -931,6 +961,15 @@ void Basis::_set_diagonal(const Vector3 &p_diag) { elements[2][2] = p_diag.z; } +Basis Basis::lerp(const Basis &p_to, const real_t &p_weight) const { + Basis b; + b.elements[0] = elements[0].lerp(p_to.elements[0], p_weight); + b.elements[1] = elements[1].lerp(p_to.elements[1], p_weight); + b.elements[2] = elements[2].lerp(p_to.elements[2], p_weight); + + return b; +} + Basis Basis::slerp(const Basis &p_to, const real_t &p_weight) const { //consider scale Quaternion from(*this); diff --git a/core/math/basis.h b/core/math/basis.h index 48367631d5..802da82089 100644 --- a/core/math/basis.h +++ b/core/math/basis.h @@ -34,7 +34,7 @@ #include "core/math/quaternion.h" #include "core/math/vector3.h" -class Basis { +class _NO_DISCARD_ Basis { private: void _set_diagonal(const Vector3 &p_diag); @@ -123,6 +123,9 @@ public: void scale_local(const Vector3 &p_scale); Basis scaled_local(const Vector3 &p_scale) const; + void scale_orthogonal(const Vector3 &p_scale); + Basis scaled_orthogonal(const Vector3 &p_scale) const; + void make_scale_uniform(); float get_uniform_scale() const; @@ -168,6 +171,7 @@ public: bool is_diagonal() const; bool is_rotation() const; + Basis lerp(const Basis &p_to, const real_t &p_weight) const; Basis slerp(const Basis &p_to, const real_t &p_weight) const; void rotate_sh(real_t *p_values); @@ -233,6 +237,9 @@ public: void orthonormalize(); Basis orthonormalized() const; + void orthogonalize(); + Basis orthogonalized() const; + #ifdef MATH_CHECKS bool is_symmetric() const; #endif diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp index b968156887..2902ca59b9 100644 --- a/core/math/camera_matrix.cpp +++ b/core/math/camera_matrix.cpp @@ -346,6 +346,7 @@ Vector<Plane> CameraMatrix::get_projection_planes(const Transform3D &p_transform */ Vector<Plane> planes; + planes.resize(6); const real_t *matrix = (const real_t *)this->matrix; @@ -360,7 +361,7 @@ Vector<Plane> CameraMatrix::get_projection_planes(const Transform3D &p_transform new_plane.normal = -new_plane.normal; new_plane.normalize(); - planes.push_back(p_transform.xform(new_plane)); + planes.write[0] = p_transform.xform(new_plane); ///////--- Far Plane ---/////// new_plane = Plane(matrix[3] - matrix[2], @@ -371,7 +372,7 @@ Vector<Plane> CameraMatrix::get_projection_planes(const Transform3D &p_transform new_plane.normal = -new_plane.normal; new_plane.normalize(); - planes.push_back(p_transform.xform(new_plane)); + planes.write[1] = p_transform.xform(new_plane); ///////--- Left Plane ---/////// new_plane = Plane(matrix[3] + matrix[0], @@ -382,7 +383,7 @@ Vector<Plane> CameraMatrix::get_projection_planes(const Transform3D &p_transform new_plane.normal = -new_plane.normal; new_plane.normalize(); - planes.push_back(p_transform.xform(new_plane)); + planes.write[2] = p_transform.xform(new_plane); ///////--- Top Plane ---/////// new_plane = Plane(matrix[3] - matrix[1], @@ -393,7 +394,7 @@ Vector<Plane> CameraMatrix::get_projection_planes(const Transform3D &p_transform new_plane.normal = -new_plane.normal; new_plane.normalize(); - planes.push_back(p_transform.xform(new_plane)); + planes.write[3] = p_transform.xform(new_plane); ///////--- Right Plane ---/////// new_plane = Plane(matrix[3] - matrix[0], @@ -404,7 +405,7 @@ Vector<Plane> CameraMatrix::get_projection_planes(const Transform3D &p_transform new_plane.normal = -new_plane.normal; new_plane.normalize(); - planes.push_back(p_transform.xform(new_plane)); + planes.write[4] = p_transform.xform(new_plane); ///////--- Bottom Plane ---/////// new_plane = Plane(matrix[3] + matrix[1], @@ -415,7 +416,7 @@ Vector<Plane> CameraMatrix::get_projection_planes(const Transform3D &p_transform new_plane.normal = -new_plane.normal; new_plane.normalize(); - planes.push_back(p_transform.xform(new_plane)); + planes.write[5] = p_transform.xform(new_plane); return planes; } diff --git a/core/math/color.h b/core/math/color.h index 6c09f7941c..72a4a5f8be 100644 --- a/core/math/color.h +++ b/core/math/color.h @@ -34,7 +34,7 @@ #include "core/math/math_funcs.h" #include "core/string/ustring.h" -struct Color { +struct _NO_DISCARD_ Color { union { struct { float r; diff --git a/core/math/disjoint_set.h b/core/math/disjoint_set.h index d16c5d3d62..8657dc068e 100644 --- a/core/math/disjoint_set.h +++ b/core/math/disjoint_set.h @@ -34,10 +34,6 @@ #include "core/templates/map.h" #include "core/templates/vector.h" -/** - @author Marios Staikopoulos <marios@staik.net> -*/ - /* This DisjointSet class uses Find with path compression and Union by rank */ template <typename T, class C = Comparator<T>, class AL = DefaultAllocator> class DisjointSet { diff --git a/core/math/face3.cpp b/core/math/face3.cpp index ba10b50465..d588f34e5d 100644 --- a/core/math/face3.cpp +++ b/core/math/face3.cpp @@ -260,8 +260,8 @@ void Face3::project_range(const Vector3 &p_normal, const Transform3D &p_transfor } void Face3::get_support(const Vector3 &p_normal, const Transform3D &p_transform, Vector3 *p_vertices, int *p_count, int p_max) const { -#define _FACE_IS_VALID_SUPPORT_THRESHOLD 0.98 -#define _EDGE_IS_VALID_SUPPORT_THRESHOLD 0.05 + constexpr double face_support_threshold = 0.98; + constexpr double edge_support_threshold = 0.05; if (p_max <= 0) { return; @@ -270,7 +270,7 @@ void Face3::get_support(const Vector3 &p_normal, const Transform3D &p_transform, Vector3 n = p_transform.basis.xform_inv(p_normal); /** TEST FACE AS SUPPORT **/ - if (get_plane().normal.dot(n) > _FACE_IS_VALID_SUPPORT_THRESHOLD) { + if (get_plane().normal.dot(n) > face_support_threshold) { *p_count = MIN(3, p_max); for (int i = 0; i < *p_count; i++) { @@ -304,7 +304,7 @@ void Face3::get_support(const Vector3 &p_normal, const Transform3D &p_transform, // check if edge is valid as a support real_t dot = (vertex[i] - vertex[(i + 1) % 3]).normalized().dot(n); dot = ABS(dot); - if (dot < _EDGE_IS_VALID_SUPPORT_THRESHOLD) { + if (dot < edge_support_threshold) { *p_count = MIN(2, p_max); for (int j = 0; j < *p_count; j++) { diff --git a/core/math/face3.h b/core/math/face3.h index 5a34858ccb..3dbbca09e0 100644 --- a/core/math/face3.h +++ b/core/math/face3.h @@ -36,7 +36,7 @@ #include "core/math/transform_3d.h" #include "core/math/vector3.h" -class Face3 { +class _NO_DISCARD_ Face3 { public: enum Side { SIDE_OVER, diff --git a/core/math/geometry_3d.cpp b/core/math/geometry_3d.cpp index e1bce81b6b..a9ff46410e 100644 --- a/core/math/geometry_3d.cpp +++ b/core/math/geometry_3d.cpp @@ -281,16 +281,16 @@ static inline void _plot_face(uint8_t ***p_cell_status, int x, int y, int z, int int div_y = len_y > 1 ? 2 : 1; int div_z = len_z > 1 ? 2 : 1; -#define _SPLIT(m_i, m_div, m_v, m_len_v, m_new_v, m_new_len_v) \ - if (m_div == 1) { \ - m_new_v = m_v; \ - m_new_len_v = 1; \ - } else if (m_i == 0) { \ - m_new_v = m_v; \ - m_new_len_v = m_len_v / 2; \ - } else { \ - m_new_v = m_v + m_len_v / 2; \ - m_new_len_v = m_len_v - m_len_v / 2; \ +#define SPLIT_DIV(m_i, m_div, m_v, m_len_v, m_new_v, m_new_len_v) \ + if (m_div == 1) { \ + m_new_v = m_v; \ + m_new_len_v = 1; \ + } else if (m_i == 0) { \ + m_new_v = m_v; \ + m_new_len_v = m_len_v / 2; \ + } else { \ + m_new_v = m_v + m_len_v / 2; \ + m_new_len_v = m_len_v - m_len_v / 2; \ } int new_x; @@ -301,18 +301,20 @@ static inline void _plot_face(uint8_t ***p_cell_status, int x, int y, int z, int int new_len_z; for (int i = 0; i < div_x; i++) { - _SPLIT(i, div_x, x, len_x, new_x, new_len_x); + SPLIT_DIV(i, div_x, x, len_x, new_x, new_len_x); for (int j = 0; j < div_y; j++) { - _SPLIT(j, div_y, y, len_y, new_y, new_len_y); + SPLIT_DIV(j, div_y, y, len_y, new_y, new_len_y); for (int k = 0; k < div_z; k++) { - _SPLIT(k, div_z, z, len_z, new_z, new_len_z); + SPLIT_DIV(k, div_z, z, len_z, new_z, new_len_z); _plot_face(p_cell_status, new_x, new_y, new_z, new_len_x, new_len_y, new_len_z, voxelsize, p_face); } } } + +#undef SPLIT_DIV } static inline void _mark_outside(uint8_t ***p_cell_status, int x, int y, int z, int len_x, int len_y, int len_z) { @@ -491,11 +493,10 @@ static inline void _build_faces(uint8_t ***p_cell_status, int x, int y, int z, i } Vector<Face3> Geometry3D::wrap_geometry(Vector<Face3> p_array, real_t *p_error) { -#define _MIN_SIZE 1.0 -#define _MAX_LENGTH 20 - int face_count = p_array.size(); const Face3 *faces = p_array.ptr(); + constexpr double min_size = 1.0; + constexpr int max_length = 20; AABB global_aabb; @@ -512,22 +513,22 @@ Vector<Face3> Geometry3D::wrap_geometry(Vector<Face3> p_array, real_t *p_error) // Determine amount of cells in grid axis. int div_x, div_y, div_z; - if (global_aabb.size.x / _MIN_SIZE < _MAX_LENGTH) { - div_x = (int)(global_aabb.size.x / _MIN_SIZE) + 1; + if (global_aabb.size.x / min_size < max_length) { + div_x = (int)(global_aabb.size.x / min_size) + 1; } else { - div_x = _MAX_LENGTH; + div_x = max_length; } - if (global_aabb.size.y / _MIN_SIZE < _MAX_LENGTH) { - div_y = (int)(global_aabb.size.y / _MIN_SIZE) + 1; + if (global_aabb.size.y / min_size < max_length) { + div_y = (int)(global_aabb.size.y / min_size) + 1; } else { - div_y = _MAX_LENGTH; + div_y = max_length; } - if (global_aabb.size.z / _MIN_SIZE < _MAX_LENGTH) { - div_z = (int)(global_aabb.size.z / _MIN_SIZE) + 1; + if (global_aabb.size.z / min_size < max_length) { + div_z = (int)(global_aabb.size.z / min_size) + 1; } else { - div_z = _MAX_LENGTH; + div_z = max_length; } Vector3 voxelsize = global_aabb.size; @@ -644,14 +645,15 @@ Geometry3D::MeshData Geometry3D::build_convex_mesh(const Vector<Plane> &p_planes Vector3 right = p.normal.cross(ref).normalized(); Vector3 up = p.normal.cross(right).normalized(); - Vector<Vector3> vertices; - Vector3 center = p.center(); + // make a quad clockwise - vertices.push_back(center - up * subplane_size + right * subplane_size); - vertices.push_back(center - up * subplane_size - right * subplane_size); - vertices.push_back(center + up * subplane_size - right * subplane_size); - vertices.push_back(center + up * subplane_size + right * subplane_size); + Vector<Vector3> vertices = { + center - up * subplane_size + right * subplane_size, + center - up * subplane_size - right * subplane_size, + center + up * subplane_size - right * subplane_size, + center + up * subplane_size + right * subplane_size + }; for (int j = 0; j < p_planes.size(); j++) { if (j == i) { @@ -762,14 +764,14 @@ Geometry3D::MeshData Geometry3D::build_convex_mesh(const Vector<Plane> &p_planes } Vector<Plane> Geometry3D::build_box_planes(const Vector3 &p_extents) { - Vector<Plane> planes; - - planes.push_back(Plane(Vector3(1, 0, 0), p_extents.x)); - planes.push_back(Plane(Vector3(-1, 0, 0), p_extents.x)); - planes.push_back(Plane(Vector3(0, 1, 0), p_extents.y)); - planes.push_back(Plane(Vector3(0, -1, 0), p_extents.y)); - planes.push_back(Plane(Vector3(0, 0, 1), p_extents.z)); - planes.push_back(Plane(Vector3(0, 0, -1), p_extents.z)); + Vector<Plane> planes = { + Plane(Vector3(1, 0, 0), p_extents.x), + Plane(Vector3(-1, 0, 0), p_extents.x), + Plane(Vector3(0, 1, 0), p_extents.y), + Plane(Vector3(0, -1, 0), p_extents.y), + Plane(Vector3(0, 0, 1), p_extents.z), + Plane(Vector3(0, 0, -1), p_extents.z) + }; return planes; } diff --git a/core/math/octree.h b/core/math/octree.h index 7861c35e07..23ba4c1aa3 100644 --- a/core/math/octree.h +++ b/core/math/octree.h @@ -103,7 +103,7 @@ private: Octant *parent = nullptr; Octant *children[8] = { nullptr }; - int children_count = 0; // cache for amount of childrens (fast check for removal) + int children_count = 0; // cache for amount of children (fast check for removal) int parent_index = -1; // cache for parent index (fast check for removal) List<Element *, AL> pairable_elements; diff --git a/core/math/plane.h b/core/math/plane.h index bac946502b..8cb6f62b3b 100644 --- a/core/math/plane.h +++ b/core/math/plane.h @@ -35,7 +35,7 @@ class Variant; -class Plane { +class _NO_DISCARD_ Plane { public: Vector3 normal; real_t d = 0; diff --git a/core/math/quaternion.h b/core/math/quaternion.h index cf3762e090..2575d7d229 100644 --- a/core/math/quaternion.h +++ b/core/math/quaternion.h @@ -36,7 +36,7 @@ #include "core/math/vector3.h" #include "core/string/ustring.h" -class Quaternion { +class _NO_DISCARD_ Quaternion { public: union { struct { diff --git a/core/math/rect2.h b/core/math/rect2.h index 1f14a01103..4ea24e8f88 100644 --- a/core/math/rect2.h +++ b/core/math/rect2.h @@ -35,7 +35,7 @@ struct Transform2D; -struct Rect2 { +struct _NO_DISCARD_ Rect2 { Point2 position; Size2 size; @@ -207,11 +207,6 @@ struct Rect2 { bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; } inline Rect2 grow(real_t p_amount) const { -#ifdef MATH_CHECKS - if (unlikely(size.x < 0 || size.y < 0)) { - ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size."); - } -#endif Rect2 g = *this; g.grow_by(p_amount); return g; @@ -238,11 +233,6 @@ struct Rect2 { } inline Rect2 grow_individual(real_t p_left, real_t p_top, real_t p_right, real_t p_bottom) const { -#ifdef MATH_CHECKS - if (unlikely(size.x < 0 || size.y < 0)) { - ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size."); - } -#endif Rect2 g = *this; g.position.x -= p_left; g.position.y -= p_top; @@ -373,7 +363,7 @@ struct Rect2 { } }; -struct Rect2i { +struct _NO_DISCARD_ Rect2i { Point2i position; Size2i size; @@ -488,11 +478,6 @@ struct Rect2i { bool operator!=(const Rect2i &p_rect) const { return position != p_rect.position || size != p_rect.size; } Rect2i grow(int p_amount) const { -#ifdef MATH_CHECKS - if (unlikely(size.x < 0 || size.y < 0)) { - ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size."); - } -#endif Rect2i g = *this; g.position.x -= p_amount; g.position.y -= p_amount; @@ -515,11 +500,6 @@ struct Rect2i { } inline Rect2i grow_individual(int p_left, int p_top, int p_right, int p_bottom) const { -#ifdef MATH_CHECKS - if (unlikely(size.x < 0 || size.y < 0)) { - ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size."); - } -#endif Rect2i g = *this; g.position.x -= p_left; g.position.y -= p_top; diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h index 752a885eba..6c2d51bd9b 100644 --- a/core/math/transform_2d.h +++ b/core/math/transform_2d.h @@ -33,7 +33,7 @@ #include "core/math/rect2.h" // also includes vector2, math_funcs, and ustring -struct Transform2D { +struct _NO_DISCARD_ Transform2D { // Warning #1: basis of Transform2D is stored differently from Basis. In terms of elements array, the basis matrix looks like "on paper": // M = (elements[0][0] elements[1][0]) // (elements[0][1] elements[1][1]) diff --git a/core/math/transform_3d.cpp b/core/math/transform_3d.cpp index 1e0ee13504..e5374315e2 100644 --- a/core/math/transform_3d.cpp +++ b/core/math/transform_3d.cpp @@ -80,9 +80,11 @@ void Transform3D::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, con origin = p_eye; } -Transform3D Transform3D::interpolate_with(const Transform3D &p_transform, real_t p_c) const { +Transform3D Transform3D::sphere_interpolate_with(const Transform3D &p_transform, real_t p_c) const { /* not sure if very "efficient" but good enough? */ + Transform3D interp; + Vector3 src_scale = basis.get_scale(); Quaternion src_rot = basis.get_rotation_quaternion(); Vector3 src_loc = origin; @@ -91,13 +93,21 @@ Transform3D Transform3D::interpolate_with(const Transform3D &p_transform, real_t Quaternion dst_rot = p_transform.basis.get_rotation_quaternion(); Vector3 dst_loc = p_transform.origin; - Transform3D interp; interp.basis.set_quaternion_scale(src_rot.slerp(dst_rot, p_c).normalized(), src_scale.lerp(dst_scale, p_c)); interp.origin = src_loc.lerp(dst_loc, p_c); return interp; } +Transform3D Transform3D::interpolate_with(const Transform3D &p_transform, real_t p_c) const { + Transform3D interp; + + interp.basis = basis.lerp(p_transform.basis, p_c); + interp.origin = origin.lerp(p_transform.origin, p_c); + + return interp; +} + void Transform3D::scale(const Vector3 &p_scale) { basis.scale(p_scale); origin *= p_scale; @@ -139,6 +149,16 @@ Transform3D Transform3D::orthonormalized() const { return _copy; } +void Transform3D::orthogonalize() { + basis.orthogonalize(); +} + +Transform3D Transform3D::orthogonalized() const { + Transform3D _copy = *this; + _copy.orthogonalize(); + return _copy; +} + bool Transform3D::is_equal_approx(const Transform3D &p_transform) const { return basis.is_equal_approx(p_transform.basis) && origin.is_equal_approx(p_transform.origin); } diff --git a/core/math/transform_3d.h b/core/math/transform_3d.h index 4356aa4e79..c16c278e74 100644 --- a/core/math/transform_3d.h +++ b/core/math/transform_3d.h @@ -35,7 +35,7 @@ #include "core/math/basis.h" #include "core/math/plane.h" -class Transform3D { +class _NO_DISCARD_ Transform3D { public: Basis basis; Vector3 origin; @@ -69,6 +69,8 @@ public: void orthonormalize(); Transform3D orthonormalized() const; + void orthogonalize(); + Transform3D orthogonalized() const; bool is_equal_approx(const Transform3D &p_transform) const; bool operator==(const Transform3D &p_transform) const; @@ -99,6 +101,7 @@ public: void operator*=(const real_t p_val); Transform3D operator*(const real_t p_val) const; + Transform3D sphere_interpolate_with(const Transform3D &p_transform, real_t p_c) const; Transform3D interpolate_with(const Transform3D &p_transform, real_t p_c) const; _FORCE_INLINE_ Transform3D inverse_xform(const Transform3D &t) const { diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp index 38dad893f5..676a0004ea 100644 --- a/core/math/vector2.cpp +++ b/core/math/vector2.cpp @@ -210,6 +210,14 @@ Vector2i Vector2i::clamp(const Vector2i &p_min, const Vector2i &p_max) const { CLAMP(y, p_min.y, p_max.y)); } +int64_t Vector2i::length_squared() const { + return x * (int64_t)x + y * (int64_t)y; +} + +double Vector2i::length() const { + return Math::sqrt((double)length_squared()); +} + Vector2i Vector2i::operator+(const Vector2i &p_v) const { return Vector2i(x + p_v.x, y + p_v.y); } diff --git a/core/math/vector2.h b/core/math/vector2.h index 493e0af27d..af40b9e68d 100644 --- a/core/math/vector2.h +++ b/core/math/vector2.h @@ -36,7 +36,7 @@ struct Vector2i; -struct Vector2 { +struct _NO_DISCARD_ Vector2 { static const int AXIS_COUNT = 2; enum Axis { @@ -261,11 +261,16 @@ Vector2 Vector2::lerp(const Vector2 &p_to, const real_t p_weight) const { } Vector2 Vector2::slerp(const Vector2 &p_to, const real_t p_weight) const { -#ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!is_normalized(), Vector2(), "The start Vector2 must be normalized."); -#endif - real_t theta = angle_to(p_to); - return rotated(theta * p_weight); + real_t start_length_sq = length_squared(); + real_t end_length_sq = p_to.length_squared(); + if (unlikely(start_length_sq == 0.0 || end_length_sq == 0.0)) { + // Zero length vectors have no angle, so the best we can do is either lerp or throw an error. + return lerp(p_to, p_weight); + } + real_t start_length = Math::sqrt(start_length_sq); + real_t result_length = Math::lerp(start_length, Math::sqrt(end_length_sq), p_weight); + real_t angle = angle_to(p_to); + return rotated(angle * p_weight) * (result_length / start_length); } Vector2 Vector2::direction_to(const Vector2 &p_to) const { @@ -279,7 +284,7 @@ typedef Vector2 Point2; /* INTEGER STUFF */ -struct Vector2i { +struct _NO_DISCARD_ Vector2i { enum Axis { AXIS_X, AXIS_Y, @@ -344,6 +349,9 @@ struct Vector2i { bool operator==(const Vector2i &p_vec2) const; bool operator!=(const Vector2i &p_vec2) const; + int64_t length_squared() const; + double length() const; + real_t aspect() const { return width / (real_t)height; } Vector2i sign() const { return Vector2i(SIGN(x), SIGN(y)); } Vector2i abs() const { return Vector2i(ABS(x), ABS(y)); } diff --git a/core/math/vector3.h b/core/math/vector3.h index 1861627718..b62edef40f 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -37,7 +37,7 @@ #include "core/string/ustring.h" class Basis; -struct Vector3 { +struct _NO_DISCARD_ Vector3 { static const int AXIS_COUNT = 3; enum Axis { @@ -240,8 +240,16 @@ Vector3 Vector3::lerp(const Vector3 &p_to, const real_t p_weight) const { } Vector3 Vector3::slerp(const Vector3 &p_to, const real_t p_weight) const { - real_t theta = angle_to(p_to); - return rotated(cross(p_to).normalized(), theta * p_weight); + real_t start_length_sq = length_squared(); + real_t end_length_sq = p_to.length_squared(); + if (unlikely(start_length_sq == 0.0 || end_length_sq == 0.0)) { + // Zero length vectors have no angle, so the best we can do is either lerp or throw an error. + return lerp(p_to, p_weight); + } + real_t start_length = Math::sqrt(start_length_sq); + real_t result_length = Math::lerp(start_length, Math::sqrt(end_length_sq), p_weight); + real_t angle = angle_to(p_to); + return rotated(cross(p_to).normalized(), angle * p_weight) * (result_length / start_length); } real_t Vector3::distance_to(const Vector3 &p_to) const { diff --git a/core/math/vector3i.h b/core/math/vector3i.h index 0f9caa349b..1564ee9173 100644 --- a/core/math/vector3i.h +++ b/core/math/vector3i.h @@ -31,10 +31,11 @@ #ifndef VECTOR3I_H #define VECTOR3I_H +#include "core/math/math_funcs.h" #include "core/string/ustring.h" #include "core/typedefs.h" -struct Vector3i { +struct _NO_DISCARD_ Vector3i { enum Axis { AXIS_X, AXIS_Y, @@ -65,6 +66,9 @@ struct Vector3i { Vector3i::Axis min_axis_index() const; Vector3i::Axis max_axis_index() const; + _FORCE_INLINE_ int64_t length_squared() const; + _FORCE_INLINE_ double length() const; + _FORCE_INLINE_ void zero(); _FORCE_INLINE_ Vector3i abs() const; @@ -110,6 +114,14 @@ struct Vector3i { } }; +int64_t Vector3i::length_squared() const { + return x * (int64_t)x + y * (int64_t)y + z * (int64_t)z; +} + +double Vector3i::length() const { + return Math::sqrt((double)length_squared()); +} + Vector3i Vector3i::abs() const { return Vector3i(ABS(x), ABS(y), ABS(z)); } |