summaryrefslogtreecommitdiff
path: root/core/math
diff options
context:
space:
mode:
Diffstat (limited to 'core/math')
-rw-r--r--core/math/a_star.cpp3
-rw-r--r--core/math/a_star.h4
-rw-r--r--core/math/aabb.h2
-rw-r--r--core/math/basis.cpp39
-rw-r--r--core/math/basis.h9
-rw-r--r--core/math/camera_matrix.cpp13
-rw-r--r--core/math/color.h2
-rw-r--r--core/math/disjoint_set.h4
-rw-r--r--core/math/face3.cpp8
-rw-r--r--core/math/face3.h2
-rw-r--r--core/math/geometry_3d.cpp80
-rw-r--r--core/math/octree.h2
-rw-r--r--core/math/plane.h2
-rw-r--r--core/math/quaternion.h2
-rw-r--r--core/math/rect2.h24
-rw-r--r--core/math/transform_2d.h2
-rw-r--r--core/math/transform_3d.cpp24
-rw-r--r--core/math/transform_3d.h5
-rw-r--r--core/math/vector2.cpp8
-rw-r--r--core/math/vector2.h22
-rw-r--r--core/math/vector3.h14
-rw-r--r--core/math/vector3i.h14
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));
}