diff options
Diffstat (limited to 'core/math')
-rw-r--r-- | core/math/a_star.cpp | 27 | ||||
-rw-r--r-- | core/math/basis.cpp (renamed from core/math/matrix3.cpp) | 76 | ||||
-rw-r--r-- | core/math/basis.h (renamed from core/math/matrix3.h) | 8 | ||||
-rw-r--r-- | core/math/bsp_tree.h | 2 | ||||
-rw-r--r-- | core/math/expression.cpp | 62 | ||||
-rw-r--r-- | core/math/face3.h | 10 | ||||
-rw-r--r-- | core/math/geometry.cpp | 35 | ||||
-rw-r--r-- | core/math/geometry.h | 4 | ||||
-rw-r--r-- | core/math/math_defs.h | 9 | ||||
-rw-r--r-- | core/math/math_funcs.h | 30 | ||||
-rw-r--r-- | core/math/octree.h | 20 | ||||
-rw-r--r-- | core/math/quat.cpp | 4 | ||||
-rw-r--r-- | core/math/quick_hull.cpp | 14 | ||||
-rw-r--r-- | core/math/quick_hull.h | 2 | ||||
-rw-r--r-- | core/math/random_pcg.cpp | 17 | ||||
-rw-r--r-- | core/math/random_pcg.h | 22 | ||||
-rw-r--r-- | core/math/transform.h | 2 | ||||
-rw-r--r-- | core/math/transform_2d.cpp | 12 | ||||
-rw-r--r-- | core/math/transform_2d.h | 1 | ||||
-rw-r--r-- | core/math/triangle_mesh.cpp | 2 | ||||
-rw-r--r-- | core/math/vector2.cpp | 2 | ||||
-rw-r--r-- | core/math/vector3.cpp | 2 | ||||
-rw-r--r-- | core/math/vector3.h | 4 |
23 files changed, 229 insertions, 138 deletions
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp index a0556ae839..6c3b84d49a 100644 --- a/core/math/a_star.cpp +++ b/core/math/a_star.cpp @@ -97,11 +97,14 @@ void AStar::remove_point(int p_id) { Point *p = points[p_id]; - for (Set<Point *>::Element *E = p->neighbours.front(); E; E = E->next()) { - - Segment s(p_id, E->get()->id); - segments.erase(s); - E->get()->neighbours.erase(p); + Map<int, Point *>::Element *PE = points.front(); + while (PE) { + for (Set<Point *>::Element *E = PE->get()->neighbours.front(); E; E = E->next()) { + Segment s(p_id, E->get()->id); + segments.erase(s); + E->get()->neighbours.erase(p); + } + PE = PE->next(); } memdelete(p); @@ -260,8 +263,8 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { } // Check open list - SelfList<Point> *least_cost_point = NULL; - real_t least_cost = 1e30; + SelfList<Point> *least_cost_point = open_list.first(); + real_t least_cost = Math_INF; // TODO: Cache previous results for (SelfList<Point> *E = open_list.first(); E; E = E->next()) { @@ -371,14 +374,14 @@ PoolVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { { PoolVector<Vector3>::Write w = path.write(); - Point *p = end_point; + Point *p2 = end_point; int idx = pc - 1; - while (p != begin_point) { - w[idx--] = p->pos; - p = p->prev_point; + while (p2 != begin_point) { + w[idx--] = p2->pos; + p2 = p2->prev_point; } - w[0] = p->pos; // Assign first + w[0] = p2->pos; // Assign first } return path; diff --git a/core/math/matrix3.cpp b/core/math/basis.cpp index 0aa67078fb..8816e3639a 100644 --- a/core/math/matrix3.cpp +++ b/core/math/basis.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* matrix3.cpp */ +/* basis.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "matrix3.h" +#include "basis.h" #include "core/math/math_funcs.h" #include "core/os/copymem.h" @@ -76,9 +76,11 @@ void Basis::invert() { } void Basis::orthonormalize() { + #ifdef MATH_CHECKS ERR_FAIL_COND(determinant() == 0); #endif + // Gram-Schmidt Process Vector3 x = get_axis(0); @@ -118,16 +120,16 @@ bool Basis::is_diagonal() const { } bool Basis::is_rotation() const { - return Math::is_equal_approx(determinant(), 1) && is_orthogonal(); + return Math::is_equal_approx(determinant(), 1, UNIT_EPSILON) && is_orthogonal(); } bool Basis::is_symmetric() const { - if (!Math::is_equal_approx(elements[0][1], elements[1][0])) + if (!Math::is_equal_approx_ratio(elements[0][1], elements[1][0], UNIT_EPSILON)) return false; - if (!Math::is_equal_approx(elements[0][2], elements[2][0])) + if (!Math::is_equal_approx_ratio(elements[0][2], elements[2][0], UNIT_EPSILON)) return false; - if (!Math::is_equal_approx(elements[1][2], elements[2][1])) + if (!Math::is_equal_approx_ratio(elements[1][2], elements[2][1], UNIT_EPSILON)) return false; return true; @@ -258,7 +260,7 @@ Vector3 Basis::get_scale_abs() const { } Vector3 Basis::get_scale_local() const { - real_t det_sign = determinant() > 0 ? 1 : -1; + real_t det_sign = SGN(determinant()); return det_sign * Vector3(elements[0].length(), elements[1].length(), elements[2].length()); } @@ -284,7 +286,7 @@ Vector3 Basis::get_scale() const { // matrix elements. // // The rotation part of this decomposition is returned by get_rotation* functions. - real_t det_sign = determinant() > 0 ? 1 : -1; + real_t det_sign = SGN(determinant()); return det_sign * Vector3( Vector3(elements[0][0], elements[1][0], elements[2][0]).length(), Vector3(elements[0][1], elements[1][1], elements[2][1]).length(), @@ -488,6 +490,11 @@ void Basis::set_euler_xyz(const Vector3 &p_euler) { // as the x, y, and z components of a Vector3 respectively. Vector3 Basis::get_euler_yxz() const { + /* checking this is a bad idea, because obtaining from scaled transform is a valid use case +#ifdef MATH_CHECKS + ERR_FAIL_COND(!is_rotation()); +#endif +*/ // Euler angles in YXZ convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix // @@ -496,9 +503,7 @@ Vector3 Basis::get_euler_yxz() const { // cy*sx*sz-cz*sy cy*cz*sx+sy*sz cy*cx Vector3 euler; -#ifdef MATH_CHECKS - ERR_FAIL_COND_V(!is_rotation(), euler); -#endif + real_t m12 = elements[1][2]; if (m12 < 1) { @@ -556,7 +561,7 @@ bool Basis::is_equal_approx(const Basis &a, const Basis &b) const { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - if (!Math::is_equal_approx(a.elements[i][j], b.elements[i][j])) + if (!Math::is_equal_approx_ratio(a.elements[i][j], b.elements[i][j], UNIT_EPSILON)) return false; } } @@ -599,10 +604,14 @@ Basis::operator String() const { } Quat Basis::get_quat() const { -#ifdef MATH_CHECKS - ERR_FAIL_COND_V(!is_rotation(), Quat()); -#endif - real_t trace = elements[0][0] + elements[1][1] + elements[2][2]; + + /* Allow getting a quaternion from an unnormalized transform */ + Basis m = *this; + m.elements[0].normalize(); + m.elements[1].normalize(); + m.elements[2].normalize(); + + real_t trace = m.elements[0][0] + m.elements[1][1] + m.elements[2][2]; real_t temp[4]; if (trace > 0.0) { @@ -610,23 +619,23 @@ Quat Basis::get_quat() const { temp[3] = (s * 0.5); s = 0.5 / s; - temp[0] = ((elements[2][1] - elements[1][2]) * s); - temp[1] = ((elements[0][2] - elements[2][0]) * s); - temp[2] = ((elements[1][0] - elements[0][1]) * s); + temp[0] = ((m.elements[2][1] - m.elements[1][2]) * s); + temp[1] = ((m.elements[0][2] - m.elements[2][0]) * s); + temp[2] = ((m.elements[1][0] - m.elements[0][1]) * s); } else { - int i = elements[0][0] < elements[1][1] ? - (elements[1][1] < elements[2][2] ? 2 : 1) : - (elements[0][0] < elements[2][2] ? 2 : 0); + 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); int j = (i + 1) % 3; int k = (i + 2) % 3; - real_t s = Math::sqrt(elements[i][i] - elements[j][j] - elements[k][k] + 1.0); + real_t s = Math::sqrt(m.elements[i][i] - m.elements[j][j] - m.elements[k][k] + 1.0); temp[i] = s * 0.5; s = 0.5 / s; - temp[3] = (elements[k][j] - elements[j][k]) * s; - temp[j] = (elements[j][i] + elements[i][j]) * s; - temp[k] = (elements[k][i] + elements[i][k]) * s; + temp[3] = (m.elements[k][j] - m.elements[j][k]) * s; + temp[j] = (m.elements[j][i] + m.elements[i][j]) * s; + temp[k] = (m.elements[k][i] + m.elements[i][k]) * s; } return Quat(temp[0], temp[1], temp[2], temp[3]); @@ -696,9 +705,11 @@ void Basis::set_orthogonal_index(int p_index) { } void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const { + /* checking this is a bad idea, because obtaining from scaled transform is a valid use case #ifdef MATH_CHECKS ERR_FAIL_COND(!is_rotation()); #endif +*/ real_t angle, x, y, z; // variables for result real_t epsilon = 0.01; // margin to allow for rounding errors real_t epsilon2 = 0.1; // margin to distinguish between 0 and 180 degrees @@ -835,14 +846,15 @@ void Basis::set_diagonal(const Vector3 p_diag) { } Basis Basis::slerp(const Basis &target, const real_t &t) const { -// TODO: implement this directly without using quaternions to make it more efficient -#ifdef MATH_CHECKS - ERR_FAIL_COND_V(!is_rotation(), Basis()); - ERR_FAIL_COND_V(!target.is_rotation(), Basis()); -#endif + //consider scale Quat from(*this); Quat to(target); - return Basis(from.slerp(to, t)); + Basis b(from.slerp(to, t)); + b.elements[0] *= Math::lerp(elements[0].length(), target.elements[0].length(), t); + b.elements[1] *= Math::lerp(elements[1].length(), target.elements[1].length(), t); + b.elements[2] *= Math::lerp(elements[2].length(), target.elements[2].length(), t); + + return b; } diff --git a/core/math/matrix3.h b/core/math/basis.h index e7d6ab4522..128e56b494 100644 --- a/core/math/matrix3.h +++ b/core/math/basis.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* matrix3.h */ +/* basis.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -31,8 +31,8 @@ // Circular dependency between Vector3 and Basis :/ #include "core/math/vector3.h" -#ifndef MATRIX3_H -#define MATRIX3_H +#ifndef BASIS_H +#define BASIS_H #include "core/math/quat.h" @@ -341,4 +341,4 @@ real_t Basis::determinant() const { elements[1][0] * (elements[0][1] * elements[2][2] - elements[2][1] * elements[0][2]) + elements[2][0] * (elements[0][1] * elements[1][2] - elements[1][1] * elements[0][2]); } -#endif +#endif // BASIS_H diff --git a/core/math/bsp_tree.h b/core/math/bsp_tree.h index 0af532a2d5..a7a3697990 100644 --- a/core/math/bsp_tree.h +++ b/core/math/bsp_tree.h @@ -31,11 +31,11 @@ #ifndef BSP_TREE_H #define BSP_TREE_H -#include "core/dvector.h" #include "core/math/aabb.h" #include "core/math/face3.h" #include "core/math/plane.h" #include "core/method_ptrcall.h" +#include "core/pool_vector.h" #include "core/variant.h" #include "core/vector.h" /** diff --git a/core/math/expression.cpp b/core/math/expression.cpp index 61e5154f44..99251d80e3 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -1264,10 +1264,10 @@ Expression::ENode *Expression::_parse_expression() { } str_ofs = cofs; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *subexpr = _parse_expression(); + if (!subexpr) return NULL; - dn->dict.push_back(expr); + dn->dict.push_back(subexpr); _get_token(tk); if (tk.type != TK_COLON) { @@ -1275,11 +1275,11 @@ Expression::ENode *Expression::_parse_expression() { return NULL; } - expr = _parse_expression(); - if (!expr) + subexpr = _parse_expression(); + if (!subexpr) return NULL; - dn->dict.push_back(expr); + dn->dict.push_back(subexpr); cofs = str_ofs; _get_token(tk); @@ -1308,10 +1308,10 @@ Expression::ENode *Expression::_parse_expression() { } str_ofs = cofs; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *subexpr = _parse_expression(); + if (!subexpr) return NULL; - an->array.push_back(expr); + an->array.push_back(subexpr); cofs = str_ofs; _get_token(tk); @@ -1355,25 +1355,25 @@ Expression::ENode *Expression::_parse_expression() { while (true) { - int cofs = str_ofs; + int cofs2 = str_ofs; _get_token(tk); if (tk.type == TK_PARENTHESIS_CLOSE) { break; } - str_ofs = cofs; //revert + str_ofs = cofs2; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *subexpr = _parse_expression(); + if (!subexpr) return NULL; - func_call->arguments.push_back(expr); + func_call->arguments.push_back(subexpr); - cofs = str_ofs; + cofs2 = str_ofs; _get_token(tk); if (tk.type == TK_COMMA) { //all good } else if (tk.type == TK_PARENTHESIS_CLOSE) { - str_ofs = cofs; + str_ofs = cofs2; } else { _set_error("Expected ',' or ')'"); } @@ -1444,11 +1444,11 @@ Expression::ENode *Expression::_parse_expression() { } str_ofs = cofs; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *subexpr = _parse_expression(); + if (!subexpr) return NULL; - constructor->arguments.push_back(expr); + constructor->arguments.push_back(subexpr); cofs = str_ofs; _get_token(tk); @@ -1485,11 +1485,11 @@ Expression::ENode *Expression::_parse_expression() { } str_ofs = cofs; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *subexpr = _parse_expression(); + if (!subexpr) return NULL; - bifunc->arguments.push_back(expr); + bifunc->arguments.push_back(subexpr); cofs = str_ofs; _get_token(tk); @@ -1584,25 +1584,25 @@ Expression::ENode *Expression::_parse_expression() { while (true) { - int cofs = str_ofs; + int cofs3 = str_ofs; _get_token(tk); if (tk.type == TK_PARENTHESIS_CLOSE) { break; } - str_ofs = cofs; //revert + str_ofs = cofs3; //revert //parse an expression - ENode *expr = _parse_expression(); - if (!expr) + ENode *subexpr = _parse_expression(); + if (!subexpr) return NULL; - func_call->arguments.push_back(expr); + func_call->arguments.push_back(subexpr); - cofs = str_ofs; + cofs3 = str_ofs; _get_token(tk); if (tk.type == TK_COMMA) { //all good } else if (tk.type == TK_PARENTHESIS_CLOSE) { - str_ofs = cofs; + str_ofs = cofs3; } else { _set_error("Expected ',' or ')'"); } @@ -1902,7 +1902,7 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: Variant b; if (op->nodes[1]) { - bool ret = _execute(p_inputs, p_instance, op->nodes[1], b, r_error_str); + ret = _execute(p_inputs, p_instance, op->nodes[1], b, r_error_str); if (ret) return true; } @@ -2070,7 +2070,7 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: for (int i = 0; i < call->arguments.size(); i++) { Variant value; - bool ret = _execute(p_inputs, p_instance, call->arguments[i], value, r_error_str); + ret = _execute(p_inputs, p_instance, call->arguments[i], value, r_error_str); if (ret) return true; diff --git a/core/math/face3.h b/core/math/face3.h index 1a00851eab..184e80ff77 100644 --- a/core/math/face3.h +++ b/core/math/face3.h @@ -241,13 +241,13 @@ bool Face3::intersects_aabb2(const AABB &p_aabb) const { real_t minT = 1e20, maxT = -1e20; for (int k = 0; k < 3; k++) { - real_t d = axis.dot(vertex[k]); + real_t vert_d = axis.dot(vertex[k]); - if (d > maxT) - maxT = d; + if (vert_d > maxT) + maxT = vert_d; - if (d < minT) - minT = d; + if (vert_d < minT) + minT = vert_d; } if (maxB < minT || maxT < minB) diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp index 12c88f43b3..194a6f6352 100644 --- a/core/math/geometry.cpp +++ b/core/math/geometry.cpp @@ -31,6 +31,7 @@ #include "geometry.h" #include "core/print_string.h" +#include "thirdparty/misc/triangulator.h" /* this implementation is very inefficient, commenting unless bugs happen. See the other one. bool Geometry::is_point_in_polygon(const Vector2 &p_point, const Vector<Vector2> &p_polygon) { @@ -737,6 +738,40 @@ PoolVector<Face3> Geometry::wrap_geometry(PoolVector<Face3> p_array, real_t *p_e return wrapped_faces; } +Vector<Vector<Vector2> > Geometry::decompose_polygon_in_convex(Vector<Point2> polygon) { + Vector<Vector<Vector2> > decomp; + List<TriangulatorPoly> in_poly, out_poly; + + TriangulatorPoly inp; + inp.Init(polygon.size()); + for (int i = 0; i < polygon.size(); i++) { + inp.GetPoint(i) = polygon[i]; + } + inp.SetOrientation(TRIANGULATOR_CCW); + in_poly.push_back(inp); + TriangulatorPartition tpart; + if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { //failed! + ERR_PRINT("Convex decomposing failed!"); + return decomp; + } + + decomp.resize(out_poly.size()); + int idx = 0; + for (List<TriangulatorPoly>::Element *I = out_poly.front(); I; I = I->next()) { + TriangulatorPoly &tp = I->get(); + + decomp.write[idx].resize(tp.GetNumPoints()); + + for (int i = 0; i < tp.GetNumPoints(); i++) { + decomp.write[idx].write[i] = tp.GetPoint(i); + } + + idx++; + } + + return decomp; +} + Geometry::MeshData Geometry::build_convex_mesh(const PoolVector<Plane> &p_planes) { MeshData mesh; diff --git a/core/math/geometry.h b/core/math/geometry.h index 29493516b8..4b478b6b16 100644 --- a/core/math/geometry.h +++ b/core/math/geometry.h @@ -31,12 +31,12 @@ #ifndef GEOMETRY_H #define GEOMETRY_H -#include "core/dvector.h" #include "core/math/face3.h" #include "core/math/rect2.h" #include "core/math/triangulate.h" #include "core/math/vector3.h" #include "core/object.h" +#include "core/pool_vector.h" #include "core/print_string.h" #include "core/vector.h" @@ -950,6 +950,8 @@ public: return H; } + static Vector<Vector<Vector2> > decompose_polygon_in_convex(Vector<Point2> polygon); + static MeshData build_convex_mesh(const PoolVector<Plane> &p_planes); static PoolVector<Plane> build_sphere_planes(real_t p_radius, int p_lats, int p_lons, Vector3::Axis p_axis = Vector3::AXIS_Z); static PoolVector<Plane> build_box_planes(const Vector3 &p_extents); diff --git a/core/math/math_defs.h b/core/math/math_defs.h index 48533ba659..c54d3cc96f 100644 --- a/core/math/math_defs.h +++ b/core/math/math_defs.h @@ -33,6 +33,7 @@ #define CMP_EPSILON 0.00001 #define CMP_EPSILON2 (CMP_EPSILON * CMP_EPSILON) + #define CMP_NORMALIZE_TOLERANCE 0.000001 #define CMP_POINT_IN_PLANE_EPSILON 0.00001 @@ -49,6 +50,14 @@ #define MATH_CHECKS #endif +//this epsilon is for values related to a unit size (scalar or vector len) +#ifdef PRECISE_MATH_CHECKS +#define UNIT_EPSILON 0.00001 +#else +//tolerate some more floating point error normally +#define UNIT_EPSILON 0.001 +#endif + #define USEC_TO_SEC(m_usec) ((m_usec) / 1000000.0) enum ClockDirection { diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index ea0bfd88cc..17112d8940 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -217,17 +217,17 @@ public: static _ALWAYS_INLINE_ double round(double p_val) { return (p_val >= 0) ? Math::floor(p_val + 0.5) : -Math::floor(-p_val + 0.5); } static _ALWAYS_INLINE_ float round(float p_val) { return (p_val >= 0) ? Math::floor(p_val + 0.5) : -Math::floor(-p_val + 0.5); } - static _ALWAYS_INLINE_ int wrapi(int value, int min, int max) { - int rng = max - min; - return min + ((((value - min) % rng) + rng) % rng); + static _ALWAYS_INLINE_ int64_t wrapi(int64_t value, int64_t min, int64_t max) { + int64_t rng = max - min; + return (rng != 0) ? min + ((((value - min) % rng) + rng) % rng) : min; } static _ALWAYS_INLINE_ double wrapf(double value, double min, double max) { double rng = max - min; - return value - (rng * Math::floor((value - min) / rng)); + return (!is_equal_approx(rng, 0.0)) ? value - (rng * Math::floor((value - min) / rng)) : min; } static _ALWAYS_INLINE_ float wrapf(float value, float min, float max) { float rng = max - min; - return value - (rng * Math::floor((value - min) / rng)); + return (!is_equal_approx(rng, 0.0f)) ? value - (rng * Math::floor((value - min) / rng)) : min; } // double only, as these functions are mainly used by the editor and not performance-critical, @@ -242,20 +242,32 @@ public: static void randomize(); static uint32_t rand_from_seed(uint64_t *seed); static uint32_t rand(); - static _ALWAYS_INLINE_ double randf() { return (double)rand() / (double)Math::RANDOM_MAX; } - static _ALWAYS_INLINE_ float randd() { return (float)rand() / (float)Math::RANDOM_MAX; } + static _ALWAYS_INLINE_ double randd() { return (double)rand() / (double)Math::RANDOM_MAX; } + static _ALWAYS_INLINE_ float randf() { return (float)rand() / (float)Math::RANDOM_MAX; } static double random(double from, double to); static float random(float from, float to); static real_t random(int from, int to) { return (real_t)random((real_t)from, (real_t)to); } - static _ALWAYS_INLINE_ bool is_equal_approx(real_t a, real_t b) { + static _ALWAYS_INLINE_ bool is_equal_approx_ratio(real_t a, real_t b, real_t epsilon = CMP_EPSILON) { + // this is an approximate way to check that numbers are close, as a ratio of their average size + // helps compare approximate numbers that may be very big or very small + real_t diff = abs(a - b); + if (diff == 0.0) { + return true; + } + real_t avg_size = (abs(a) + abs(b)) / 2.0; + diff /= avg_size; + return diff < epsilon; + } + + static _ALWAYS_INLINE_ bool is_equal_approx(real_t a, real_t b, real_t epsilon = CMP_EPSILON) { // TODO: Comparing floats for approximate-equality is non-trivial. // Using epsilon should cover the typical cases in Godot (where a == b is used to compare two reals), such as matrix and vector comparison operators. // A proper implementation in terms of ULPs should eventually replace the contents of this function. // See https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ for details. - return abs(a - b) < CMP_EPSILON; + return abs(a - b) < epsilon; } static _ALWAYS_INLINE_ float absf(float g) { diff --git a/core/math/octree.h b/core/math/octree.h index 36a77663f4..d6fc9776bc 100644 --- a/core/math/octree.h +++ b/core/math/octree.h @@ -916,34 +916,34 @@ void Octree<T, use_pairs, AL>::move(OctreeElementID p_id, const AABB &p_aabb) { pass++; - for (typename List<typename Element::OctantOwner, AL>::Element *E = owners.front(); E;) { + for (typename List<typename Element::OctantOwner, AL>::Element *F = owners.front(); F;) { - Octant *o = E->get().octant; - typename List<typename Element::OctantOwner, AL>::Element *N = E->next(); + Octant *o = F->get().octant; + typename List<typename Element::OctantOwner, AL>::Element *N = F->next(); /* if (!use_pairs) - o->elements.erase( E->get().E ); + o->elements.erase( F->get().E ); */ if (use_pairs && e.pairable) - o->pairable_elements.erase(E->get().E); + o->pairable_elements.erase(F->get().E); else - o->elements.erase(E->get().E); + o->elements.erase(F->get().E); if (_remove_element_from_octant(&e, o, common_parent->parent)) { - owners.erase(E); + owners.erase(F); } - E = N; + F = N; } if (use_pairs) { //unpair child elements in anything that survived - for (typename List<typename Element::OctantOwner, AL>::Element *E = owners.front(); E; E = E->next()) { + for (typename List<typename Element::OctantOwner, AL>::Element *F = owners.front(); F; F = F->next()) { - Octant *o = E->get().octant; + Octant *o = F->get().octant; // erase children pairs, unref ONCE pass++; diff --git a/core/math/quat.cpp b/core/math/quat.cpp index c1e45f36f0..1a67be7384 100644 --- a/core/math/quat.cpp +++ b/core/math/quat.cpp @@ -30,7 +30,7 @@ #include "quat.h" -#include "core/math/matrix3.h" +#include "core/math/basis.h" #include "core/print_string.h" // set_euler_xyz expects a vector containing the Euler angles in the format @@ -135,7 +135,7 @@ Quat Quat::normalized() const { } bool Quat::is_normalized() const { - return Math::is_equal_approx(length_squared(), 1.0); + return Math::is_equal_approx(length_squared(), 1.0, UNIT_EPSILON); //use less epsilon } Quat Quat::inverse() const { diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp index 1aa345db1f..fc2eb1454d 100644 --- a/core/math/quick_hull.cpp +++ b/core/math/quick_hull.cpp @@ -36,8 +36,6 @@ uint32_t QuickHull::debug_stop_after = 0xFFFFFFFF; Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_mesh) { - static const real_t over_tolerance = 0.0001; - /* CREATE AABB VOLUME */ AABB aabb; @@ -180,6 +178,8 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me faces.push_back(f); } + real_t over_tolerance = 3 * UNIT_EPSILON * (aabb.size.x + aabb.size.y + aabb.size.z); + /* COMPUTE AVAILABLE VERTICES */ for (int i = 0; i < p_points.size(); i++) { @@ -438,12 +438,12 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me } // remove all edge connections to this face - for (Map<Edge, RetFaceConnect>::Element *E = ret_edges.front(); E; E = E->next()) { - if (E->get().left == O) - E->get().left = NULL; + for (Map<Edge, RetFaceConnect>::Element *G = ret_edges.front(); G; G = G->next()) { + if (G->get().left == O) + G->get().left = NULL; - if (E->get().right == O) - E->get().right = NULL; + if (G->get().right == O) + G->get().right = NULL; } ret_edges.erase(F); //remove the edge diff --git a/core/math/quick_hull.h b/core/math/quick_hull.h index 2e659cab6e..a445a47cbe 100644 --- a/core/math/quick_hull.h +++ b/core/math/quick_hull.h @@ -64,7 +64,7 @@ public: struct Face { Plane plane; - int vertices[3]; + uint32_t vertices[3]; Vector<int> points_over; bool operator<(const Face &p_face) const { diff --git a/core/math/random_pcg.cpp b/core/math/random_pcg.cpp index 8bbcca88fe..45467b32b2 100644 --- a/core/math/random_pcg.cpp +++ b/core/math/random_pcg.cpp @@ -32,24 +32,25 @@ #include "core/os/os.h" -RandomPCG::RandomPCG(uint64_t seed, uint64_t inc) : - pcg() { - pcg.state = seed; - pcg.inc = inc; +RandomPCG::RandomPCG(uint64_t p_seed, uint64_t p_inc) : + pcg(), + current_seed(DEFAULT_SEED) { + pcg.inc = p_inc; + seed(p_seed); } void RandomPCG::randomize() { seed(OS::get_singleton()->get_ticks_usec() * pcg.state + PCG_DEFAULT_INC_64); } -double RandomPCG::random(double from, double to) { +double RandomPCG::random(double p_from, double p_to) { unsigned int r = rand(); double ret = (double)r / (double)RANDOM_MAX; - return (ret) * (to - from) + from; + return (ret) * (p_to - p_from) + p_from; } -float RandomPCG::random(float from, float to) { +float RandomPCG::random(float p_from, float p_to) { unsigned int r = rand(); float ret = (float)r / (float)RANDOM_MAX; - return (ret) * (to - from) + from; + return (ret) * (p_to - p_from) + p_from; } diff --git a/core/math/random_pcg.h b/core/math/random_pcg.h index ef69bf7120..230eb9a11b 100644 --- a/core/math/random_pcg.h +++ b/core/math/random_pcg.h @@ -37,25 +37,33 @@ class RandomPCG { pcg32_random_t pcg; + uint64_t current_seed; // seed with this to get the same state public: static const uint64_t DEFAULT_SEED = 12047754176567800795U; static const uint64_t DEFAULT_INC = PCG_DEFAULT_INC_64; static const uint64_t RANDOM_MAX = 0xFFFFFFFF; - RandomPCG(uint64_t seed = DEFAULT_SEED, uint64_t inc = PCG_DEFAULT_INC_64); + RandomPCG(uint64_t p_seed = DEFAULT_SEED, uint64_t p_inc = PCG_DEFAULT_INC_64); - _FORCE_INLINE_ void seed(uint64_t seed) { pcg.state = seed; } - _FORCE_INLINE_ uint64_t get_seed() { return pcg.state; } + _FORCE_INLINE_ void seed(uint64_t p_seed) { + current_seed = p_seed; + pcg.state = p_seed; + pcg32_random_r(&pcg); // Force changing internal state to avoid initial 0 + } + _FORCE_INLINE_ uint64_t get_seed() { return current_seed; } void randomize(); - _FORCE_INLINE_ uint32_t rand() { return pcg32_random_r(&pcg); } + _FORCE_INLINE_ uint32_t rand() { + current_seed = pcg.state; + return pcg32_random_r(&pcg); + } _FORCE_INLINE_ double randd() { return (double)rand() / (double)RANDOM_MAX; } _FORCE_INLINE_ float randf() { return (float)rand() / (float)RANDOM_MAX; } - double random(double from, double to); - float random(float from, float to); - real_t random(int from, int to) { return (real_t)random((real_t)from, (real_t)to); } + double random(double p_from, double p_to); + float random(float p_from, float p_to); + real_t random(int p_from, int p_to) { return (real_t)random((real_t)p_from, (real_t)p_to); } }; #endif // RANDOM_PCG_H diff --git a/core/math/transform.h b/core/math/transform.h index 9b323a6f0f..2f43f6b035 100644 --- a/core/math/transform.h +++ b/core/math/transform.h @@ -32,7 +32,7 @@ #define TRANSFORM_H #include "core/math/aabb.h" -#include "core/math/matrix3.h" +#include "core/math/basis.h" #include "core/math/plane.h" /** diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp index 295e60babb..7d00158f3d 100644 --- a/core/math/transform_2d.cpp +++ b/core/math/transform_2d.cpp @@ -80,13 +80,14 @@ real_t Transform2D::get_rotation() const { } void Transform2D::set_rotation(real_t p_rot) { - + Size2 scale = get_scale(); real_t cr = Math::cos(p_rot); real_t sr = Math::sin(p_rot); elements[0][0] = cr; elements[0][1] = sr; elements[1][0] = -sr; elements[1][1] = cr; + set_scale(scale); } Transform2D::Transform2D(real_t p_rot, const Vector2 &p_pos) { @@ -101,10 +102,17 @@ Transform2D::Transform2D(real_t p_rot, const Vector2 &p_pos) { } Size2 Transform2D::get_scale() const { - real_t det_sign = basis_determinant() > 0 ? 1 : -1; + real_t det_sign = SGN(basis_determinant()); return Size2(elements[0].length(), det_sign * elements[1].length()); } +void Transform2D::set_scale(Size2 &p_scale) { + elements[0].normalize(); + elements[1].normalize(); + elements[0] *= p_scale.x; + elements[1] *= p_scale.y; +} + void Transform2D::scale(const Size2 &p_scale) { scale_basis(p_scale); elements[2] *= p_scale; diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h index 507e6a16eb..b9e7a36fb3 100644 --- a/core/math/transform_2d.h +++ b/core/math/transform_2d.h @@ -81,6 +81,7 @@ struct Transform2D { real_t basis_determinant() const; Size2 get_scale() const; + void set_scale(Size2 &p_scale); _FORCE_INLINE_ const Vector2 &get_origin() const { return elements[2]; } _FORCE_INLINE_ void set_origin(const Vector2 &p_origin) { elements[2] = p_origin; } diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp index cdf3d16b72..83784a1fa7 100644 --- a/core/math/triangle_mesh.cpp +++ b/core/math/triangle_mesh.cpp @@ -30,7 +30,7 @@ #include "triangle_mesh.h" -#include "core/sort.h" +#include "core/sort_array.h" int TriangleMesh::_create_bvh(BVH *p_bvh, BVH **p_bb, int p_from, int p_size, int p_depth, int &max_depth, int &max_alloc) { diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp index e580057950..5c1ea5943d 100644 --- a/core/math/vector2.cpp +++ b/core/math/vector2.cpp @@ -65,7 +65,7 @@ Vector2 Vector2::normalized() const { bool Vector2::is_normalized() const { // use length_squared() instead of length() to avoid sqrt(), makes it more stringent. - return Math::is_equal_approx(length_squared(), 1.0); + return Math::is_equal_approx(length_squared(), 1.0, UNIT_EPSILON); } real_t Vector2::distance_to(const Vector2 &p_vector2) const { diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp index b2e89ac7b8..1c28934422 100644 --- a/core/math/vector3.cpp +++ b/core/math/vector3.cpp @@ -30,7 +30,7 @@ #include "vector3.h" -#include "core/math/matrix3.h" +#include "core/math/basis.h" void Vector3::rotate(const Vector3 &p_axis, real_t p_phi) { diff --git a/core/math/vector3.h b/core/math/vector3.h index b0eef35635..b11838d16e 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -151,7 +151,7 @@ struct Vector3 { }; // Should be included after class definition, otherwise we get circular refs -#include "core/math/matrix3.h" +#include "core/math/basis.h" Vector3 Vector3::cross(const Vector3 &p_b) const { @@ -414,7 +414,7 @@ Vector3 Vector3::normalized() const { bool Vector3::is_normalized() const { // use length_squared() instead of length() to avoid sqrt(), makes it more stringent. - return Math::is_equal_approx(length_squared(), 1.0); + return Math::is_equal_approx(length_squared(), 1.0, UNIT_EPSILON); } Vector3 Vector3::inverse() const { |