summaryrefslogtreecommitdiff
path: root/core/math
diff options
context:
space:
mode:
Diffstat (limited to 'core/math')
-rw-r--r--core/math/aabb.h8
-rw-r--r--core/math/audio_frame.h3
-rw-r--r--core/math/basis.cpp10
-rw-r--r--core/math/camera_matrix.cpp13
-rw-r--r--core/math/camera_matrix.h1
-rw-r--r--core/math/color.cpp135
-rw-r--r--core/math/color.h28
-rw-r--r--core/math/color_names.inc2
-rw-r--r--core/math/expression.cpp2
-rw-r--r--core/math/geometry_2d.cpp24
-rw-r--r--core/math/geometry_3d.cpp23
-rw-r--r--core/math/geometry_3d.h33
-rw-r--r--core/math/math_funcs.h8
-rw-r--r--core/math/quat.cpp110
-rw-r--r--core/math/quat.h19
-rw-r--r--core/math/quick_hull.cpp2
-rw-r--r--core/math/transform.h4
-rw-r--r--core/math/triangulate.cpp2
-rw-r--r--core/math/vector2.cpp12
-rw-r--r--core/math/vector2.h30
-rw-r--r--core/math/vector3.h32
21 files changed, 249 insertions, 252 deletions
diff --git a/core/math/aabb.h b/core/math/aabb.h
index 2861358e32..e16246902a 100644
--- a/core/math/aabb.h
+++ b/core/math/aabb.h
@@ -107,8 +107,8 @@ public:
Variant intersects_segment_bind(const Vector3 &p_from, const Vector3 &p_to) const;
Variant intersects_ray_bind(const Vector3 &p_from, const Vector3 &p_dir) const;
- _FORCE_INLINE_ void quantize(float p_unit);
- _FORCE_INLINE_ AABB quantized(float p_unit) const;
+ _FORCE_INLINE_ void quantize(real_t p_unit);
+ _FORCE_INLINE_ AABB quantized(real_t p_unit) const;
_FORCE_INLINE_ void set_end(const Vector3 &p_end) {
size = p_end - position;
@@ -430,7 +430,7 @@ void AABB::grow_by(real_t p_amount) {
size.z += 2.0 * p_amount;
}
-void AABB::quantize(float p_unit) {
+void AABB::quantize(real_t p_unit) {
size += position;
position.x -= Math::fposmodp(position.x, p_unit);
@@ -448,7 +448,7 @@ void AABB::quantize(float p_unit) {
size -= position;
}
-AABB AABB::quantized(float p_unit) const {
+AABB AABB::quantized(real_t p_unit) const {
AABB ret = *this;
ret.quantize(p_unit);
return ret;
diff --git a/core/math/audio_frame.h b/core/math/audio_frame.h
index 5773da9211..a5616b8d79 100644
--- a/core/math/audio_frame.h
+++ b/core/math/audio_frame.h
@@ -47,6 +47,9 @@ static inline float undenormalise(volatile float f) {
return (v.i & 0x7f800000) < 0x08000000 ? 0.0f : f;
}
+static const float AUDIO_PEAK_OFFSET = 0.0000000001f;
+static const float AUDIO_MIN_PEAK_DB = -200.0f; // linear2db(AUDIO_PEAK_OFFSET)
+
struct AudioFrame {
//left and right samples
float l, r;
diff --git a/core/math/basis.cpp b/core/math/basis.cpp
index 26b4caba39..cc2b7c6611 100644
--- a/core/math/basis.cpp
+++ b/core/math/basis.cpp
@@ -132,7 +132,7 @@ bool Basis::is_symmetric() const {
Basis Basis::diagonalize() {
//NOTE: only implemented for symmetric matrices
-//with the Jacobi iterative method method
+//with the Jacobi iterative method
#ifdef MATH_CHECKS
ERR_FAIL_COND_V(!is_symmetric(), Basis());
#endif
@@ -317,7 +317,7 @@ Vector3 Basis::rotref_posscale_decomposition(Basis &rotref) const {
// Multiplies the matrix from left by the rotation matrix: M -> R.M
// Note that this does *not* rotate the matrix itself.
//
-// The main use of Basis is as Transform.basis, which is used a the transformation matrix
+// The main use of Basis is as Transform.basis, which is used by the transformation matrix
// of 3D object. Rotate here refers to rotation of the object (which is R * (*this)),
// not the matrix itself (which is R * (*this) * R.transposed()).
Basis Basis::rotated(const Vector3 &p_axis, real_t p_phi) const {
@@ -790,8 +790,8 @@ Quat Basis::get_quat() const {
temp[2] = ((m.elements[1][0] - m.elements[0][1]) * s);
} else {
int i = m.elements[0][0] < m.elements[1][1] ?
- (m.elements[1][1] < m.elements[2][2] ? 2 : 1) :
- (m.elements[0][0] < m.elements[2][2] ? 2 : 0);
+ (m.elements[1][1] < m.elements[2][2] ? 2 : 1) :
+ (m.elements[0][0] < m.elements[2][2] ? 2 : 0);
int j = (i + 1) % 3;
int k = (i + 2) % 3;
@@ -881,7 +881,7 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
if ((Math::abs(elements[1][0] - elements[0][1]) < epsilon) && (Math::abs(elements[2][0] - elements[0][2]) < epsilon) && (Math::abs(elements[2][1] - elements[1][2]) < epsilon)) {
// singularity found
// first check for identity matrix which must have +1 for all terms
- // in leading diagonaland zero in other terms
+ // in leading diagonal and zero in other terms
if ((Math::abs(elements[1][0] + elements[0][1]) < epsilon2) && (Math::abs(elements[2][0] + elements[0][2]) < epsilon2) && (Math::abs(elements[2][1] + elements[1][2]) < epsilon2) && (Math::abs(elements[0][0] + elements[1][1] + elements[2][2] - 3) < epsilon2)) {
// this singularity is identity matrix so angle = 0
r_axis = Vector3(0, 1, 0);
diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp
index 9ec71af57f..1066cf5e30 100644
--- a/core/math/camera_matrix.cpp
+++ b/core/math/camera_matrix.cpp
@@ -74,13 +74,22 @@ Plane CameraMatrix::xform4(const Plane &p_vec4) const {
return ret;
}
+void CameraMatrix::adjust_perspective_znear(real_t p_new_znear) {
+ real_t zfar = get_z_far();
+ real_t znear = p_new_znear;
+
+ real_t deltaZ = zfar - znear;
+ matrix[2][2] = -(zfar + znear) / deltaZ;
+ matrix[3][2] = -2 * znear * zfar / deltaZ;
+}
+
void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov) {
if (p_flip_fov) {
p_fovy_degrees = get_fovy(p_fovy_degrees, 1.0 / p_aspect);
}
real_t sine, cotangent, deltaZ;
- real_t radians = p_fovy_degrees / 2.0 * Math_PI / 180.0;
+ real_t radians = Math::deg2rad(p_fovy_degrees / 2.0);
deltaZ = p_z_far - p_z_near;
sine = Math::sin(radians);
@@ -107,7 +116,7 @@ void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_
real_t left, right, modeltranslation, ymax, xmax, frustumshift;
- ymax = p_z_near * tan(p_fovy_degrees * Math_PI / 360.0f);
+ ymax = p_z_near * tan(Math::deg2rad(p_fovy_degrees / 2.0));
xmax = ymax * p_aspect;
frustumshift = (p_intraocular_dist / 2.0) * p_z_near / p_convergence_dist;
diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h
index 03068bc7ea..3f327d3bc4 100644
--- a/core/math/camera_matrix.h
+++ b/core/math/camera_matrix.h
@@ -59,6 +59,7 @@ struct CameraMatrix {
void set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov = false);
void set_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far);
void set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov = false);
+ void adjust_perspective_znear(real_t p_new_znear);
static real_t get_fovy(real_t p_fovx, real_t p_aspect) {
return Math::rad2deg(Math::atan(p_aspect * Math::tan(Math::deg2rad(p_fovx) * 0.5)) * 2.0);
diff --git a/core/math/color.cpp b/core/math/color.cpp
index 4d58c8c84a..8affb07e8c 100644
--- a/core/math/color.cpp
+++ b/core/math/color.cpp
@@ -355,6 +355,23 @@ bool Color::html_is_valid(const String &p_color) {
}
Color Color::named(const String &p_name) {
+ int idx = find_named_color(p_name);
+ if (idx == -1) {
+ ERR_FAIL_V_MSG(Color(), "Invalid color name: " + p_name + ".");
+ return Color();
+ }
+ return get_named_color(idx);
+}
+
+Color Color::named(const String &p_name, const Color &p_default) {
+ int idx = find_named_color(p_name);
+ if (idx == -1) {
+ return p_default;
+ }
+ return get_named_color(idx);
+}
+
+int Color::find_named_color(const String &p_name) {
String name = p_name;
// Normalize name
name = name.replace(" ", "");
@@ -367,14 +384,12 @@ Color Color::named(const String &p_name) {
int idx = 0;
while (named_colors[idx].name != nullptr) {
if (name == named_colors[idx].name) {
- return named_colors[idx].color;
+ return idx;
}
idx++;
}
- ERR_FAIL_V_MSG(Color(), "Invalid color name: " + p_name + ".");
-
- return Color();
+ return -1;
}
int Color::get_named_color_count() {
@@ -384,13 +399,25 @@ int Color::get_named_color_count() {
}
return idx;
}
+
String Color::get_named_color_name(int p_idx) {
return named_colors[p_idx].name;
}
+
Color Color::get_named_color(int p_idx) {
return named_colors[p_idx].color;
}
+// For a version that errors on invalid values instead of returning
+// a default color, use the Color(String) constructor instead.
+Color Color::from_string(const String &p_string, const Color &p_default) {
+ if (html_is_valid(p_string)) {
+ return html(p_string);
+ } else {
+ return named(p_string, p_default);
+ }
+}
+
String _to_hex(float p_val) {
int v = Math::round(p_val * 255);
v = CLAMP(v, 0, 255);
@@ -425,56 +452,9 @@ String Color::to_html(bool p_alpha) const {
}
Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) const {
- p_h = Math::fmod(p_h * 360.0f, 360.0f);
- if (p_h < 0.0) {
- p_h += 360.0f;
- }
-
- const float h_ = p_h / 60.0f;
- const float c = p_v * p_s;
- const float x = c * (1.0f - Math::abs(Math::fmod(h_, 2.0f) - 1.0f));
- float r, g, b;
-
- switch ((int)h_) {
- case 0: {
- r = c;
- g = x;
- b = 0;
- } break;
- case 1: {
- r = x;
- g = c;
- b = 0;
- } break;
- case 2: {
- r = 0;
- g = c;
- b = x;
- } break;
- case 3: {
- r = 0;
- g = x;
- b = c;
- } break;
- case 4: {
- r = x;
- g = 0;
- b = c;
- } break;
- case 5: {
- r = c;
- g = 0;
- b = x;
- } break;
- default: {
- r = 0;
- g = 0;
- b = 0;
- } break;
- }
-
- const float m = p_v - c;
- return Color(m + r, m + g, m + b, p_a);
+ Color c;
+ c.set_hsv(p_h, p_s, p_v, p_a);
+ return c;
}
Color::operator String() const {
@@ -519,12 +499,12 @@ Color Color::operator*(const Color &p_color) const {
a * p_color.a);
}
-Color Color::operator*(real_t p_rvalue) const {
+Color Color::operator*(float p_scalar) const {
return Color(
- r * p_rvalue,
- g * p_rvalue,
- b * p_rvalue,
- a * p_rvalue);
+ r * p_scalar,
+ g * p_scalar,
+ b * p_scalar,
+ a * p_scalar);
}
void Color::operator*=(const Color &p_color) {
@@ -534,11 +514,11 @@ void Color::operator*=(const Color &p_color) {
a = a * p_color.a;
}
-void Color::operator*=(real_t p_rvalue) {
- r = r * p_rvalue;
- g = g * p_rvalue;
- b = b * p_rvalue;
- a = a * p_rvalue;
+void Color::operator*=(float p_scalar) {
+ r = r * p_scalar;
+ g = g * p_scalar;
+ b = b * p_scalar;
+ a = a * p_scalar;
}
Color Color::operator/(const Color &p_color) const {
@@ -549,12 +529,12 @@ Color Color::operator/(const Color &p_color) const {
a / p_color.a);
}
-Color Color::operator/(real_t p_rvalue) const {
+Color Color::operator/(float p_scalar) const {
return Color(
- r / p_rvalue,
- g / p_rvalue,
- b / p_rvalue,
- a / p_rvalue);
+ r / p_scalar,
+ g / p_scalar,
+ b / p_scalar,
+ a / p_scalar);
}
void Color::operator/=(const Color &p_color) {
@@ -564,18 +544,11 @@ void Color::operator/=(const Color &p_color) {
a = a / p_color.a;
}
-void Color::operator/=(real_t p_rvalue) {
- if (p_rvalue == 0) {
- r = 1.0;
- g = 1.0;
- b = 1.0;
- a = 1.0;
- } else {
- r = r / p_rvalue;
- g = g / p_rvalue;
- b = b / p_rvalue;
- a = a / p_rvalue;
- }
+void Color::operator/=(float p_scalar) {
+ r = r / p_scalar;
+ g = g / p_scalar;
+ b = b / p_scalar;
+ a = a / p_scalar;
}
Color Color::operator-() const {
diff --git a/core/math/color.h b/core/math/color.h
index c7b5ceca3d..5eb8b1119a 100644
--- a/core/math/color.h
+++ b/core/math/color.h
@@ -78,14 +78,14 @@ struct Color {
void operator-=(const Color &p_color);
Color operator*(const Color &p_color) const;
- Color operator*(real_t p_rvalue) const;
+ Color operator*(float p_scalar) const;
void operator*=(const Color &p_color);
- void operator*=(real_t p_rvalue);
+ void operator*=(float p_scalar);
Color operator/(const Color &p_color) const;
- Color operator/(real_t p_rvalue) const;
+ Color operator/(float p_scalar) const;
void operator/=(const Color &p_color);
- void operator/=(real_t p_rvalue);
+ void operator/=(float p_scalar);
bool is_equal_approx(const Color &p_color) const;
@@ -182,9 +182,12 @@ struct Color {
static Color html(const String &p_rgba);
static bool html_is_valid(const String &p_color);
static Color named(const String &p_name);
+ static Color named(const String &p_name, const Color &p_default);
+ static int find_named_color(const String &p_name);
static int get_named_color_count();
static String get_named_color_name(int p_idx);
static Color get_named_color(int p_idx);
+ static Color from_string(const String &p_string, const Color &p_default);
String to_html(bool p_alpha = true) const;
Color from_hsv(float p_h, float p_s, float p_v, float p_a) const;
static Color from_rgbe9995(uint32_t p_rgbe);
@@ -238,6 +241,19 @@ struct Color {
b = p_c.b;
a = p_a;
}
+
+ Color(const String &p_code) {
+ if (html_is_valid(p_code)) {
+ *this = html(p_code);
+ } else {
+ *this = named(p_code);
+ }
+ }
+
+ Color(const String &p_code, float p_a) {
+ *this = Color(p_code);
+ a = p_a;
+ }
};
bool Color::operator<(const Color &p_color) const {
@@ -256,8 +272,8 @@ bool Color::operator<(const Color &p_color) const {
}
}
-_FORCE_INLINE_ Color operator*(real_t p_real, const Color &p_color) {
- return p_color * p_real;
+_FORCE_INLINE_ Color operator*(float p_scalar, const Color &p_color) {
+ return p_color * p_scalar;
}
#endif // COLOR_H
diff --git a/core/math/color_names.inc b/core/math/color_names.inc
index 523c7e3c59..e5b935ea9c 100644
--- a/core/math/color_names.inc
+++ b/core/math/color_names.inc
@@ -156,5 +156,5 @@ static NamedColor named_colors[] = {
{ "whitesmoke", Color(0.96, 0.96, 0.96) },
{ "yellow", Color(1.00, 1.00, 0.00) },
{ "yellowgreen", Color(0.60, 0.80, 0.20) },
- { nullptr, Color(0.60, 0.80, 0.20) },
+ { nullptr, Color() },
};
diff --git a/core/math/expression.cpp b/core/math/expression.cpp
index 636ea601c7..f7ac44d321 100644
--- a/core/math/expression.cpp
+++ b/core/math/expression.cpp
@@ -978,7 +978,7 @@ Expression::ENode *Expression::_parse_expression() {
}
}
- /* Reduce the set set of expressions and place them in an operator tree, respecting precedence */
+ /* Reduce the set of expressions and place them in an operator tree, respecting precedence */
while (expression.size() > 1) {
int next_op = -1;
diff --git a/core/math/geometry_2d.cpp b/core/math/geometry_2d.cpp
index 5d4c31088b..feb1fb2fb8 100644
--- a/core/math/geometry_2d.cpp
+++ b/core/math/geometry_2d.cpp
@@ -31,7 +31,7 @@
#include "geometry_2d.h"
#include "thirdparty/misc/clipper.hpp"
-#include "thirdparty/misc/triangulator.h"
+#include "thirdparty/misc/polypartition.h"
#define STB_RECT_PACK_IMPLEMENTATION
#include "thirdparty/misc/stb_rect_pack.h"
@@ -39,16 +39,16 @@
Vector<Vector<Vector2>> Geometry2D::decompose_polygon_in_convex(Vector<Point2> polygon) {
Vector<Vector<Vector2>> decomp;
- List<TriangulatorPoly> in_poly, out_poly;
+ List<TPPLPoly> in_poly, out_poly;
- TriangulatorPoly inp;
+ TPPLPoly inp;
inp.Init(polygon.size());
for (int i = 0; i < polygon.size(); i++) {
inp.GetPoint(i) = polygon[i];
}
- inp.SetOrientation(TRIANGULATOR_CCW);
+ inp.SetOrientation(TPPL_ORIENTATION_CCW);
in_poly.push_back(inp);
- TriangulatorPartition tpart;
+ TPPLPartition tpart;
if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { // Failed.
ERR_PRINT("Convex decomposing failed!");
return decomp;
@@ -56,8 +56,8 @@ Vector<Vector<Vector2>> Geometry2D::decompose_polygon_in_convex(Vector<Point2> p
decomp.resize(out_poly.size());
int idx = 0;
- for (List<TriangulatorPoly>::Element *I = out_poly.front(); I; I = I->next()) {
- TriangulatorPoly &tp = I->get();
+ for (List<TPPLPoly>::Element *I = out_poly.front(); I; I = I->next()) {
+ TPPLPoly &tp = I->get();
decomp.write[idx].resize(tp.GetNumPoints());
@@ -87,13 +87,17 @@ struct _AtlasWorkRectResult {
void Geometry2D::make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_result, Size2i &r_size) {
// Super simple, almost brute force scanline stacking fitter.
// It's pretty basic for now, but it tries to make sure that the aspect ratio of the
- // resulting atlas is somehow square. This is necessary because video cards have limits.
- // On texture size (usually 2048 or 4096), so the more square a texture, the more chances.
- // It will work in every hardware.
+ // resulting atlas is somehow square. This is necessary because video cards have limits
+ // on texture size (usually 2048 or 4096), so the squarer a texture, the more the chances
+ // that it will work in every hardware.
// 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);
+ 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);
+ }
Vector<_AtlasWorkRect> wrects;
wrects.resize(p_rects.size());
diff --git a/core/math/geometry_3d.cpp b/core/math/geometry_3d.cpp
index a918d1de0d..6628b760e0 100644
--- a/core/math/geometry_3d.cpp
+++ b/core/math/geometry_3d.cpp
@@ -33,7 +33,7 @@
#include "core/string/print_string.h"
#include "thirdparty/misc/clipper.hpp"
-#include "thirdparty/misc/triangulator.h"
+#include "thirdparty/misc/polypartition.h"
void Geometry3D::MeshData::optimize_vertices() {
Map<int, int> vtx_remap;
@@ -775,12 +775,15 @@ Vector<Plane> Geometry3D::build_box_planes(const Vector3 &p_extents) {
}
Vector<Plane> Geometry3D::build_cylinder_planes(real_t p_radius, real_t p_height, int p_sides, Vector3::Axis p_axis) {
+ ERR_FAIL_INDEX_V(p_axis, 3, Vector<Plane>());
+
Vector<Plane> planes;
+ const double sides_step = Math_TAU / p_sides;
for (int i = 0; i < p_sides; i++) {
Vector3 normal;
- normal[(p_axis + 1) % 3] = Math::cos(i * (2.0 * Math_PI) / p_sides);
- normal[(p_axis + 2) % 3] = Math::sin(i * (2.0 * Math_PI) / p_sides);
+ normal[(p_axis + 1) % 3] = Math::cos(i * sides_step);
+ normal[(p_axis + 2) % 3] = Math::sin(i * sides_step);
planes.push_back(Plane(normal, p_radius));
}
@@ -795,6 +798,8 @@ Vector<Plane> Geometry3D::build_cylinder_planes(real_t p_radius, real_t p_height
}
Vector<Plane> Geometry3D::build_sphere_planes(real_t p_radius, int p_lats, int p_lons, Vector3::Axis p_axis) {
+ ERR_FAIL_INDEX_V(p_axis, 3, Vector<Plane>());
+
Vector<Plane> planes;
Vector3 axis;
@@ -805,10 +810,11 @@ Vector<Plane> Geometry3D::build_sphere_planes(real_t p_radius, int p_lats, int p
axis_neg[(p_axis + 2) % 3] = 1.0;
axis_neg[p_axis] = -1.0;
+ const double lon_step = Math_TAU / p_lons;
for (int i = 0; i < p_lons; i++) {
Vector3 normal;
- normal[(p_axis + 1) % 3] = Math::cos(i * (2.0 * Math_PI) / p_lons);
- normal[(p_axis + 2) % 3] = Math::sin(i * (2.0 * Math_PI) / p_lons);
+ normal[(p_axis + 1) % 3] = Math::cos(i * lon_step);
+ normal[(p_axis + 2) % 3] = Math::sin(i * lon_step);
planes.push_back(Plane(normal, p_radius));
@@ -825,6 +831,8 @@ Vector<Plane> Geometry3D::build_sphere_planes(real_t p_radius, int p_lats, int p
}
Vector<Plane> Geometry3D::build_capsule_planes(real_t p_radius, real_t p_height, int p_sides, int p_lats, Vector3::Axis p_axis) {
+ ERR_FAIL_INDEX_V(p_axis, 3, Vector<Plane>());
+
Vector<Plane> planes;
Vector3 axis;
@@ -835,10 +843,11 @@ Vector<Plane> Geometry3D::build_capsule_planes(real_t p_radius, real_t p_height,
axis_neg[(p_axis + 2) % 3] = 1.0;
axis_neg[p_axis] = -1.0;
+ const double sides_step = Math_TAU / p_sides;
for (int i = 0; i < p_sides; i++) {
Vector3 normal;
- normal[(p_axis + 1) % 3] = Math::cos(i * (2.0 * Math_PI) / p_sides);
- normal[(p_axis + 2) % 3] = Math::sin(i * (2.0 * Math_PI) / p_sides);
+ normal[(p_axis + 1) % 3] = Math::cos(i * sides_step);
+ normal[(p_axis + 2) % 3] = Math::sin(i * sides_step);
planes.push_back(Plane(normal, p_radius));
diff --git a/core/math/geometry_3d.h b/core/math/geometry_3d.h
index 825817af5e..4ef9b4dbe6 100644
--- a/core/math/geometry_3d.h
+++ b/core/math/geometry_3d.h
@@ -252,27 +252,34 @@ public:
return true;
}
- static inline bool segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, real_t p_height, real_t p_radius, Vector3 *r_res = nullptr, Vector3 *r_norm = nullptr) {
+ static inline bool segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, real_t p_height, real_t p_radius, Vector3 *r_res = nullptr, Vector3 *r_norm = nullptr, int p_cylinder_axis = 2) {
Vector3 rel = (p_to - p_from);
real_t rel_l = rel.length();
if (rel_l < CMP_EPSILON) {
return false; // Both points are the same.
}
+ ERR_FAIL_COND_V(p_cylinder_axis < 0, false);
+ ERR_FAIL_COND_V(p_cylinder_axis > 2, false);
+ Vector3 cylinder_axis;
+ cylinder_axis[p_cylinder_axis] = 1.0;
+
// First check if they are parallel.
Vector3 normal = (rel / rel_l);
- Vector3 crs = normal.cross(Vector3(0, 0, 1));
+ Vector3 crs = normal.cross(cylinder_axis);
real_t crs_l = crs.length();
- Vector3 z_dir;
+ Vector3 axis_dir;
if (crs_l < CMP_EPSILON) {
- z_dir = Vector3(1, 0, 0); // Any x/y vector OK.
+ Vector3 side_axis;
+ side_axis[(p_cylinder_axis + 1) % 3] = 1.0; // Any side axis OK.
+ axis_dir = side_axis;
} else {
- z_dir = crs / crs_l;
+ axis_dir = crs / crs_l;
}
- real_t dist = z_dir.dot(p_from);
+ real_t dist = axis_dir.dot(p_from);
if (dist >= p_radius) {
return false; // Too far away.
@@ -285,10 +292,10 @@ public:
}
Size2 size(Math::sqrt(w2), p_height * 0.5);
- Vector3 x_dir = z_dir.cross(Vector3(0, 0, 1)).normalized();
+ Vector3 side_dir = axis_dir.cross(cylinder_axis).normalized();
- Vector2 from2D(x_dir.dot(p_from), p_from.z);
- Vector2 to2D(x_dir.dot(p_to), p_to.z);
+ Vector2 from2D(side_dir.dot(p_from), p_from[p_cylinder_axis]);
+ Vector2 to2D(side_dir.dot(p_to), p_to[p_cylinder_axis]);
real_t min = 0, max = 1;
@@ -335,10 +342,12 @@ public:
Vector3 res_normal = result;
if (axis == 0) {
- res_normal.z = 0;
+ res_normal[p_cylinder_axis] = 0;
} else {
- res_normal.x = 0;
- res_normal.y = 0;
+ int axis_side = (p_cylinder_axis + 1) % 3;
+ res_normal[axis_side] = 0;
+ axis_side = (axis_side + 1) % 3;
+ res_normal[axis_side] = 0;
}
res_normal.normalize();
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index c7d24e9c58..267f6a4fe2 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -223,11 +223,11 @@ public:
return value;
}
- static _ALWAYS_INLINE_ double deg2rad(double p_y) { return p_y * Math_PI / 180.0; }
- static _ALWAYS_INLINE_ float deg2rad(float p_y) { return p_y * Math_PI / 180.0; }
+ static _ALWAYS_INLINE_ double deg2rad(double p_y) { return p_y * (Math_PI / 180.0); }
+ static _ALWAYS_INLINE_ float deg2rad(float p_y) { return p_y * (Math_PI / 180.0); }
- static _ALWAYS_INLINE_ double rad2deg(double p_y) { return p_y * 180.0 / Math_PI; }
- static _ALWAYS_INLINE_ float rad2deg(float p_y) { return p_y * 180.0 / Math_PI; }
+ static _ALWAYS_INLINE_ double rad2deg(double p_y) { return p_y * (180.0 / Math_PI); }
+ static _ALWAYS_INLINE_ float rad2deg(float p_y) { return p_y * (180.0 / Math_PI); }
static _ALWAYS_INLINE_ double lerp(double p_from, double p_to, double p_weight) { return p_from + (p_to - p_from) * p_weight; }
static _ALWAYS_INLINE_ float lerp(float p_from, float p_to, float p_weight) { return p_from + (p_to - p_from) * p_weight; }
diff --git a/core/math/quat.cpp b/core/math/quat.cpp
index 4cecc20fef..6f13e04027 100644
--- a/core/math/quat.cpp
+++ b/core/math/quat.cpp
@@ -33,32 +33,6 @@
#include "core/math/basis.h"
#include "core/string/print_string.h"
-// set_euler_xyz expects a vector containing the Euler angles in the format
-// (ax,ay,az), where ax is the angle of rotation around x axis,
-// and similar for other axes.
-// This implementation uses XYZ convention (Z is the first rotation).
-void Quat::set_euler_xyz(const Vector3 &p_euler) {
- real_t half_a1 = p_euler.x * 0.5;
- real_t half_a2 = p_euler.y * 0.5;
- real_t half_a3 = p_euler.z * 0.5;
-
- // R = X(a1).Y(a2).Z(a3) convention for Euler angles.
- // Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-2)
- // a3 is the angle of the first rotation, following the notation in this reference.
-
- real_t cos_a1 = Math::cos(half_a1);
- real_t sin_a1 = Math::sin(half_a1);
- real_t cos_a2 = Math::cos(half_a2);
- real_t sin_a2 = Math::sin(half_a2);
- real_t cos_a3 = Math::cos(half_a3);
- real_t sin_a3 = Math::sin(half_a3);
-
- set(sin_a1 * cos_a2 * cos_a3 + sin_a2 * sin_a3 * cos_a1,
- -sin_a1 * sin_a3 * cos_a2 + sin_a2 * cos_a1 * cos_a3,
- sin_a1 * sin_a2 * cos_a3 + sin_a3 * cos_a1 * cos_a2,
- -sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3);
-}
-
// get_euler_xyz returns a vector containing the Euler angles in the format
// (ax,ay,az), where ax is the angle of rotation around x axis,
// and similar for other axes.
@@ -68,32 +42,6 @@ Vector3 Quat::get_euler_xyz() const {
return m.get_euler_xyz();
}
-// set_euler_yxz expects a vector containing the Euler angles in the format
-// (ax,ay,az), where ax is the angle of rotation around x axis,
-// and similar for other axes.
-// This implementation uses YXZ convention (Z is the first rotation).
-void Quat::set_euler_yxz(const Vector3 &p_euler) {
- real_t half_a1 = p_euler.y * 0.5;
- real_t half_a2 = p_euler.x * 0.5;
- real_t half_a3 = p_euler.z * 0.5;
-
- // R = Y(a1).X(a2).Z(a3) convention for Euler angles.
- // Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-6)
- // a3 is the angle of the first rotation, following the notation in this reference.
-
- real_t cos_a1 = Math::cos(half_a1);
- real_t sin_a1 = Math::sin(half_a1);
- real_t cos_a2 = Math::cos(half_a2);
- real_t sin_a2 = Math::sin(half_a2);
- real_t cos_a3 = Math::cos(half_a3);
- real_t sin_a3 = Math::sin(half_a3);
-
- set(sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3,
- sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3,
- -sin_a1 * sin_a2 * cos_a3 + cos_a1 * cos_a2 * sin_a3,
- sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3);
-}
-
// get_euler_yxz returns a vector containing the Euler angles in the format
// (ax,ay,az), where ax is the angle of rotation around x axis,
// and similar for other axes.
@@ -107,10 +55,13 @@ Vector3 Quat::get_euler_yxz() const {
}
void Quat::operator*=(const Quat &p_q) {
- set(w * p_q.x + x * p_q.w + y * p_q.z - z * p_q.y,
- w * p_q.y + y * p_q.w + z * p_q.x - x * p_q.z,
- w * p_q.z + z * p_q.w + x * p_q.y - y * p_q.x,
- w * p_q.w - x * p_q.x - y * p_q.y - z * p_q.z);
+ real_t xx = w * p_q.x + x * p_q.w + y * p_q.z - z * p_q.y;
+ real_t yy = w * p_q.y + y * p_q.w + z * p_q.x - x * p_q.z;
+ real_t zz = w * p_q.z + z * p_q.w + x * p_q.y - y * p_q.x;
+ w = w * p_q.w - x * p_q.x - y * p_q.y - z * p_q.z;
+ x = xx;
+ y = yy;
+ z = zz;
}
Quat Quat::operator*(const Quat &p_q) const {
@@ -233,18 +184,49 @@ Quat::operator String() const {
return String::num(x) + ", " + String::num(y) + ", " + String::num(z) + ", " + String::num(w);
}
-void Quat::set_axis_angle(const Vector3 &axis, const real_t &angle) {
+Quat::Quat(const Vector3 &p_axis, real_t p_angle) {
#ifdef MATH_CHECKS
- ERR_FAIL_COND_MSG(!axis.is_normalized(), "The axis Vector3 must be normalized.");
+ ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 must be normalized.");
#endif
- real_t d = axis.length();
+ real_t d = p_axis.length();
if (d == 0) {
- set(0, 0, 0, 0);
+ x = 0;
+ y = 0;
+ z = 0;
+ w = 0;
} else {
- real_t sin_angle = Math::sin(angle * 0.5);
- real_t cos_angle = Math::cos(angle * 0.5);
+ real_t sin_angle = Math::sin(p_angle * 0.5);
+ real_t cos_angle = Math::cos(p_angle * 0.5);
real_t s = sin_angle / d;
- set(axis.x * s, axis.y * s, axis.z * s,
- cos_angle);
+ x = p_axis.x * s;
+ y = p_axis.y * s;
+ z = p_axis.z * s;
+ w = cos_angle;
}
}
+
+// Euler constructor expects a vector containing the Euler angles in the format
+// (ax, ay, az), where ax is the angle of rotation around x axis,
+// and similar for other axes.
+// This implementation uses YXZ convention (Z is the first rotation).
+Quat::Quat(const Vector3 &p_euler) {
+ real_t half_a1 = p_euler.y * 0.5;
+ real_t half_a2 = p_euler.x * 0.5;
+ real_t half_a3 = p_euler.z * 0.5;
+
+ // R = Y(a1).X(a2).Z(a3) convention for Euler angles.
+ // Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-6)
+ // a3 is the angle of the first rotation, following the notation in this reference.
+
+ real_t cos_a1 = Math::cos(half_a1);
+ real_t sin_a1 = Math::sin(half_a1);
+ real_t cos_a2 = Math::cos(half_a2);
+ real_t sin_a2 = Math::sin(half_a2);
+ real_t cos_a3 = Math::cos(half_a3);
+ real_t sin_a3 = Math::sin(half_a3);
+
+ x = sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3;
+ y = sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3;
+ z = -sin_a1 * sin_a2 * cos_a3 + cos_a1 * cos_a2 * sin_a3;
+ w = sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3;
+}
diff --git a/core/math/quat.h b/core/math/quat.h
index 423a7f8dfe..9db914fe52 100644
--- a/core/math/quat.h
+++ b/core/math/quat.h
@@ -65,19 +65,14 @@ public:
Quat inverse() const;
_FORCE_INLINE_ real_t dot(const Quat &p_q) const;
- void set_euler_xyz(const Vector3 &p_euler);
Vector3 get_euler_xyz() const;
- void set_euler_yxz(const Vector3 &p_euler);
Vector3 get_euler_yxz() const;
-
- void set_euler(const Vector3 &p_euler) { set_euler_yxz(p_euler); };
Vector3 get_euler() const { return get_euler_yxz(); };
Quat slerp(const Quat &p_to, const real_t &p_weight) const;
Quat slerpni(const Quat &p_to, const real_t &p_weight) const;
Quat cubic_slerp(const Quat &p_b, const Quat &p_pre_a, const Quat &p_post_b, const real_t &p_weight) const;
- void set_axis_angle(const Vector3 &axis, const real_t &angle);
_FORCE_INLINE_ void get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
r_angle = 2 * Math::acos(w);
real_t r = ((real_t)1) / Math::sqrt(1 - w * w);
@@ -124,23 +119,19 @@ public:
operator String() const;
- inline void set(real_t p_x, real_t p_y, real_t p_z, real_t p_w) {
- x = p_x;
- y = p_y;
- z = p_z;
- w = p_w;
- }
-
_FORCE_INLINE_ Quat() {}
+
_FORCE_INLINE_ Quat(real_t p_x, real_t p_y, real_t p_z, real_t p_w) :
x(p_x),
y(p_y),
z(p_z),
w(p_w) {
}
- Quat(const Vector3 &axis, const real_t &angle) { set_axis_angle(axis, angle); }
- Quat(const Vector3 &euler) { set_euler(euler); }
+ Quat(const Vector3 &p_axis, real_t p_angle);
+
+ Quat(const Vector3 &p_euler);
+
Quat(const Quat &p_q) :
x(p_q.x),
y(p_q.y),
diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp
index ad28967d7a..fe18cc3d41 100644
--- a/core/math/quick_hull.cpp
+++ b/core/math/quick_hull.cpp
@@ -268,7 +268,7 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_
for (Map<Edge, FaceConnect>::Element *E = lit_edges.front(); E; E = E->next()) {
FaceConnect &fc = E->get();
if (fc.left && fc.right) {
- continue; //edge is uninteresting, not on horizont
+ continue; //edge is uninteresting, not on horizon
}
//create new face!
diff --git a/core/math/transform.h b/core/math/transform.h
index 60da6f5593..1c05dbe554 100644
--- a/core/math/transform.h
+++ b/core/math/transform.h
@@ -51,8 +51,8 @@ public:
void rotate(const Vector3 &p_axis, real_t p_phi);
void rotate_basis(const Vector3 &p_axis, real_t p_phi);
- void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up);
- Transform looking_at(const Vector3 &p_target, const Vector3 &p_up) const;
+ void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0));
+ Transform looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)) const;
void scale(const Vector3 &p_scale);
Transform scaled(const Vector3 &p_scale) const;
diff --git a/core/math/triangulate.cpp b/core/math/triangulate.cpp
index 0047c0705d..fa1588dbc5 100644
--- a/core/math/triangulate.cpp
+++ b/core/math/triangulate.cpp
@@ -97,7 +97,7 @@ bool Triangulate::snip(const Vector<Vector2> &p_contour, int u, int v, int w, in
// It can happen that the triangulation ends up with three aligned vertices to deal with.
// In this scenario, making the check below strict may reject the possibility of
- // forming a last triangle with these aligned vertices, preventing the triangulatiom
+ // forming a last triangle with these aligned vertices, preventing the triangulation
// from completing.
// To avoid that we allow zero-area triangles if all else failed.
float threshold = relaxed ? -CMP_EPSILON : CMP_EPSILON;
diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp
index 496e29ebe4..5129ed336e 100644
--- a/core/math/vector2.cpp
+++ b/core/math/vector2.cpp
@@ -211,11 +211,11 @@ Vector2i Vector2i::operator*(const Vector2i &p_v1) const {
return Vector2i(x * p_v1.x, y * p_v1.y);
}
-Vector2i Vector2i::operator*(const int &rvalue) const {
+Vector2i Vector2i::operator*(const int32_t &rvalue) const {
return Vector2i(x * rvalue, y * rvalue);
}
-void Vector2i::operator*=(const int &rvalue) {
+void Vector2i::operator*=(const int32_t &rvalue) {
x *= rvalue;
y *= rvalue;
}
@@ -224,11 +224,11 @@ Vector2i Vector2i::operator/(const Vector2i &p_v1) const {
return Vector2i(x / p_v1.x, y / p_v1.y);
}
-Vector2i Vector2i::operator/(const int &rvalue) const {
+Vector2i Vector2i::operator/(const int32_t &rvalue) const {
return Vector2i(x / rvalue, y / rvalue);
}
-void Vector2i::operator/=(const int &rvalue) {
+void Vector2i::operator/=(const int32_t &rvalue) {
x /= rvalue;
y /= rvalue;
}
@@ -237,11 +237,11 @@ Vector2i Vector2i::operator%(const Vector2i &p_v1) const {
return Vector2i(x % p_v1.x, y % p_v1.y);
}
-Vector2i Vector2i::operator%(const int &rvalue) const {
+Vector2i Vector2i::operator%(const int32_t &rvalue) const {
return Vector2i(x % rvalue, y % rvalue);
}
-void Vector2i::operator%=(const int &rvalue) {
+void Vector2i::operator%=(const int32_t &rvalue) {
x %= rvalue;
y %= rvalue;
}
diff --git a/core/math/vector2.h b/core/math/vector2.h
index 24795857a3..81bc71d590 100644
--- a/core/math/vector2.h
+++ b/core/math/vector2.h
@@ -265,18 +265,18 @@ struct Vector2i {
};
union {
- int x = 0;
- int width;
+ int32_t x = 0;
+ int32_t width;
};
union {
- int y = 0;
- int height;
+ int32_t y = 0;
+ int32_t height;
};
- _FORCE_INLINE_ int &operator[](int p_idx) {
+ _FORCE_INLINE_ int32_t &operator[](int p_idx) {
return p_idx ? y : x;
}
- _FORCE_INLINE_ const int &operator[](int p_idx) const {
+ _FORCE_INLINE_ const int32_t &operator[](int p_idx) const {
return p_idx ? y : x;
}
@@ -286,16 +286,16 @@ struct Vector2i {
void operator-=(const Vector2i &p_v);
Vector2i operator*(const Vector2i &p_v1) const;
- Vector2i operator*(const int &rvalue) const;
- void operator*=(const int &rvalue);
+ Vector2i operator*(const int32_t &rvalue) const;
+ void operator*=(const int32_t &rvalue);
Vector2i operator/(const Vector2i &p_v1) const;
- Vector2i operator/(const int &rvalue) const;
- void operator/=(const int &rvalue);
+ Vector2i operator/(const int32_t &rvalue) const;
+ void operator/=(const int32_t &rvalue);
Vector2i operator%(const Vector2i &p_v1) const;
- Vector2i operator%(const int &rvalue) const;
- void operator%=(const int &rvalue);
+ Vector2i operator%(const int32_t &rvalue) const;
+ void operator%=(const int32_t &rvalue);
Vector2i operator-() const;
bool operator<(const Vector2i &p_vec2) const { return (x == p_vec2.x) ? (y < p_vec2.y) : (x < p_vec2.x); }
@@ -317,10 +317,10 @@ struct Vector2i {
inline Vector2i() {}
inline Vector2i(const Vector2 &p_vec2) {
- x = (int)p_vec2.x;
- y = (int)p_vec2.y;
+ x = (int32_t)p_vec2.x;
+ y = (int32_t)p_vec2.y;
}
- inline Vector2i(int p_x, int p_y) {
+ inline Vector2i(int32_t p_x, int32_t p_y) {
x = p_x;
y = p_y;
}
diff --git a/core/math/vector3.h b/core/math/vector3.h
index 3fdb944729..377581bb45 100644
--- a/core/math/vector3.h
+++ b/core/math/vector3.h
@@ -110,6 +110,7 @@ struct Vector3 {
_FORCE_INLINE_ Vector3 project(const Vector3 &p_to) const;
_FORCE_INLINE_ real_t angle_to(const Vector3 &p_to) const;
+ _FORCE_INLINE_ real_t signed_angle_to(const Vector3 &p_to, const Vector3 &p_axis) const;
_FORCE_INLINE_ Vector3 direction_to(const Vector3 &p_to) const;
_FORCE_INLINE_ Vector3 slide(const Vector3 &p_normal) const;
@@ -230,6 +231,13 @@ real_t Vector3::angle_to(const Vector3 &p_to) const {
return Math::atan2(cross(p_to).length(), dot(p_to));
}
+real_t Vector3::signed_angle_to(const Vector3 &p_to, const Vector3 &p_axis) const {
+ Vector3 cross_to = cross(p_to);
+ real_t unsigned_angle = Math::atan2(cross_to.length(), dot(p_to));
+ real_t sign = cross_to.dot(p_axis);
+ return (sign < 0) ? -unsigned_angle : unsigned_angle;
+}
+
Vector3 Vector3::direction_to(const Vector3 &p_to) const {
Vector3 ret(p_to.x - x, p_to.y - y, p_to.z - z);
ret.normalize();
@@ -324,48 +332,40 @@ bool Vector3::operator<(const Vector3 &p_v) const {
if (x == p_v.x) {
if (y == p_v.y) {
return z < p_v.z;
- } else {
- return y < p_v.y;
}
- } else {
- return x < p_v.x;
+ return y < p_v.y;
}
+ return x < p_v.x;
}
bool Vector3::operator>(const Vector3 &p_v) const {
if (x == p_v.x) {
if (y == p_v.y) {
return z > p_v.z;
- } else {
- return y > p_v.y;
}
- } else {
- return x > p_v.x;
+ return y > p_v.y;
}
+ return x > p_v.x;
}
bool Vector3::operator<=(const Vector3 &p_v) const {
if (x == p_v.x) {
if (y == p_v.y) {
return z <= p_v.z;
- } else {
- return y < p_v.y;
}
- } else {
- return x < p_v.x;
+ return y < p_v.y;
}
+ return x < p_v.x;
}
bool Vector3::operator>=(const Vector3 &p_v) const {
if (x == p_v.x) {
if (y == p_v.y) {
return z >= p_v.z;
- } else {
- return y > p_v.y;
}
- } else {
- return x > p_v.x;
+ return y > p_v.y;
}
+ return x > p_v.x;
}
_FORCE_INLINE_ Vector3 vec3_cross(const Vector3 &p_a, const Vector3 &p_b) {