diff options
Diffstat (limited to 'core/math')
-rw-r--r-- | core/math/aabb.h | 2 | ||||
-rw-r--r-- | core/math/basis.cpp | 2 | ||||
-rw-r--r-- | core/math/basis.h | 2 | ||||
-rw-r--r-- | core/math/delaunay_3d.h | 83 | ||||
-rw-r--r-- | core/math/geometry_2d.cpp | 111 | ||||
-rw-r--r-- | core/math/quick_hull.cpp | 2 | ||||
-rw-r--r-- | core/math/rect2.h | 2 | ||||
-rw-r--r-- | core/math/rect2i.h | 2 | ||||
-rw-r--r-- | core/math/triangle_mesh.cpp | 2 | ||||
-rw-r--r-- | core/math/vector2.cpp | 12 | ||||
-rw-r--r-- | core/math/vector2.h | 10 | ||||
-rw-r--r-- | core/math/vector2i.cpp | 12 | ||||
-rw-r--r-- | core/math/vector2i.h | 10 | ||||
-rw-r--r-- | core/math/vector3.cpp | 19 | ||||
-rw-r--r-- | core/math/vector3.h | 11 | ||||
-rw-r--r-- | core/math/vector3i.cpp | 14 | ||||
-rw-r--r-- | core/math/vector3i.h | 10 | ||||
-rw-r--r-- | core/math/vector4.cpp | 27 | ||||
-rw-r--r-- | core/math/vector4.h | 41 | ||||
-rw-r--r-- | core/math/vector4i.cpp | 16 | ||||
-rw-r--r-- | core/math/vector4i.h | 10 |
21 files changed, 272 insertions, 128 deletions
diff --git a/core/math/aabb.h b/core/math/aabb.h index 48a883e64c..c2945a3ef1 100644 --- a/core/math/aabb.h +++ b/core/math/aabb.h @@ -101,7 +101,7 @@ struct _NO_DISCARD_ AABB { _FORCE_INLINE_ void expand_to(const Vector3 &p_vector); /** expand to contain a point if necessary */ _FORCE_INLINE_ AABB abs() const { - return AABB(position + size.min(Vector3()), size.abs()); + return AABB(position + size.minf(0), size.abs()); } Variant intersects_segment_bind(const Vector3 &p_from, const Vector3 &p_to) const; diff --git a/core/math/basis.cpp b/core/math/basis.cpp index 84ac878172..34ed1c2d85 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -293,7 +293,7 @@ Vector3 Basis::get_scale_abs() const { Vector3(rows[0][2], rows[1][2], rows[2][2]).length()); } -Vector3 Basis::get_scale_local() const { +Vector3 Basis::get_scale_global() const { real_t det_sign = SIGN(determinant()); return det_sign * Vector3(rows[0].length(), rows[1].length(), rows[2].length()); } diff --git a/core/math/basis.h b/core/math/basis.h index 79f3bda8f8..918cbc18d4 100644 --- a/core/math/basis.h +++ b/core/math/basis.h @@ -103,7 +103,7 @@ struct _NO_DISCARD_ Basis { Vector3 get_scale() const; Vector3 get_scale_abs() const; - Vector3 get_scale_local() const; + Vector3 get_scale_global() const; void set_axis_angle_scale(const Vector3 &p_axis, real_t p_angle, const Vector3 &p_scale); void set_euler_scale(const Vector3 &p_euler, const Vector3 &p_scale, EulerOrder p_order = EulerOrder::YXZ); diff --git a/core/math/delaunay_3d.h b/core/math/delaunay_3d.h index 45571fb570..4f21a665de 100644 --- a/core/math/delaunay_3d.h +++ b/core/math/delaunay_3d.h @@ -46,7 +46,8 @@ class Delaunay3D { struct Simplex; enum { - ACCEL_GRID_SIZE = 16 + ACCEL_GRID_SIZE = 16, + QUANTIZATION_MAX = 1 << 16 // A power of two smaller than the 23 bit significand of a float. }; struct GridPos { Vector3i pos; @@ -173,38 +174,25 @@ class Delaunay3D { R128 radius2 = rel2_x * rel2_x + rel2_y * rel2_y + rel2_z * rel2_z; - return radius2 < (p_simplex.circum_r2 - R128(0.00001)); + return radius2 < (p_simplex.circum_r2 - R128(0.0000000001)); + // When this tolerance is too big, it can result in overlapping simplices. + // When it's too small, large amounts of planar simplices are created. } static bool simplex_is_coplanar(const Vector3 *p_points, const Simplex &p_simplex) { - Plane p(p_points[p_simplex.points[0]], p_points[p_simplex.points[1]], p_points[p_simplex.points[2]]); - if (ABS(p.distance_to(p_points[p_simplex.points[3]])) < CMP_EPSILON) { - return true; + // Checking every possible distance like this is overkill, but only checking + // one is not enough. If the simplex is almost planar then the vectors p1-p2 + // and p1-p3 can be practically collinear, which makes Plane unreliable. + for (uint32_t i = 0; i < 4; i++) { + Plane p(p_points[p_simplex.points[i]], p_points[p_simplex.points[(i + 1) % 4]], p_points[p_simplex.points[(i + 2) % 4]]); + // This tolerance should not be smaller than the one used with + // Plane::has_point() when creating the LightmapGI probe BSP tree. + if (ABS(p.distance_to(p_points[p_simplex.points[(i + 3) % 4]])) < 0.001) { + return true; + } } - Projection cm; - - cm.columns[0][0] = p_points[p_simplex.points[0]].x; - cm.columns[0][1] = p_points[p_simplex.points[1]].x; - cm.columns[0][2] = p_points[p_simplex.points[2]].x; - cm.columns[0][3] = p_points[p_simplex.points[3]].x; - - cm.columns[1][0] = p_points[p_simplex.points[0]].y; - cm.columns[1][1] = p_points[p_simplex.points[1]].y; - cm.columns[1][2] = p_points[p_simplex.points[2]].y; - cm.columns[1][3] = p_points[p_simplex.points[3]].y; - - cm.columns[2][0] = p_points[p_simplex.points[0]].z; - cm.columns[2][1] = p_points[p_simplex.points[1]].z; - cm.columns[2][2] = p_points[p_simplex.points[2]].z; - cm.columns[2][3] = p_points[p_simplex.points[3]].z; - - cm.columns[3][0] = 1.0; - cm.columns[3][1] = 1.0; - cm.columns[3][2] = 1.0; - cm.columns[3][3] = 1.0; - - return ABS(cm.determinant()) <= CMP_EPSILON; + return false; } public: @@ -215,9 +203,10 @@ public: static Vector<OutputSimplex> tetrahedralize(const Vector<Vector3> &p_points) { uint32_t point_count = p_points.size(); Vector3 *points = (Vector3 *)memalloc(sizeof(Vector3) * (point_count + 4)); + const Vector3 *src_points = p_points.ptr(); + Vector3 proportions; { - const Vector3 *src_points = p_points.ptr(); AABB rect; for (uint32_t i = 0; i < point_count; i++) { Vector3 point = src_points[i]; @@ -226,17 +215,25 @@ public: } else { rect.expand_to(point); } - points[i] = point; } + real_t longest_axis = rect.size[rect.get_longest_axis_index()]; + proportions = Vector3(longest_axis, longest_axis, longest_axis) / rect.size; + for (uint32_t i = 0; i < point_count; i++) { - points[i] = (points[i] - rect.position) / rect.size; + // Scale points to the unit cube to better utilize R128 precision + // and quantize to stabilize triangulation over a wide range of + // distances. + points[i] = Vector3(Vector3i((src_points[i] - rect.position) / longest_axis * QUANTIZATION_MAX)) / QUANTIZATION_MAX; } - const real_t delta_max = Math::sqrt(2.0) * 20.0; + const real_t delta_max = Math::sqrt(2.0) * 100.0; Vector3 center = Vector3(0.5, 0.5, 0.5); - // any simplex that contains everything is good + // The larger the root simplex is, the more likely it is that the + // triangulation is convex. If it's not absolutely huge, there can + // be missing simplices that are not created for the outermost faces + // of the point cloud if the point density is very low there. points[point_count + 0] = center + Vector3(0, 1, 0) * delta_max; points[point_count + 1] = center + Vector3(0, -1, 1) * delta_max; points[point_count + 2] = center + Vector3(1, -1, -1) * delta_max; @@ -271,7 +268,7 @@ public: for (uint32_t i = 0; i < point_count; i++) { bool unique = true; for (uint32_t j = i + 1; j < point_count; j++) { - if (points[i].is_equal_approx(points[j])) { + if (points[i] == points[j]) { unique = false; break; } @@ -280,8 +277,8 @@ public: continue; } - Vector3i grid_pos = Vector3i(points[i] * ACCEL_GRID_SIZE); - grid_pos = grid_pos.clamp(Vector3i(), Vector3i(ACCEL_GRID_SIZE - 1, ACCEL_GRID_SIZE - 1, ACCEL_GRID_SIZE - 1)); + Vector3i grid_pos = Vector3i(points[i] * proportions * ACCEL_GRID_SIZE); + grid_pos = grid_pos.clampi(0, ACCEL_GRID_SIZE - 1); for (List<Simplex *>::Element *E = acceleration_grid[grid_pos.x][grid_pos.y][grid_pos.z].front(); E;) { List<Simplex *>::Element *N = E->next(); //may be deleted @@ -300,6 +297,9 @@ public: Triangle t = Triangle(simplex->points[triangle_order[k][0]], simplex->points[triangle_order[k][1]], simplex->points[triangle_order[k][2]]); uint32_t *p = triangles_inserted.lookup_ptr(t); if (p) { + // This Delaunay implementation uses the Bowyer-Watson algorithm. + // The rule is that you don't reuse any triangles that were + // shared by any of the retriangulated simplices. triangles[*p].bad = true; } else { triangles_inserted.insert(t, triangles.size()); @@ -307,7 +307,6 @@ public: } } - //remove simplex and continue simplex_list.erase(simplex->SE); for (const GridPos &gp : simplex->grid_positions) { @@ -334,10 +333,10 @@ public: const real_t radius2 = Math::sqrt(double(new_simplex->circum_r2)) + 0.0001; Vector3 extents = Vector3(radius2, radius2, radius2); - Vector3i from = Vector3i((center - extents) * ACCEL_GRID_SIZE); - Vector3i to = Vector3i((center + extents) * ACCEL_GRID_SIZE); - from = from.clamp(Vector3i(), Vector3i(ACCEL_GRID_SIZE - 1, ACCEL_GRID_SIZE - 1, ACCEL_GRID_SIZE - 1)); - to = to.clamp(Vector3i(), Vector3i(ACCEL_GRID_SIZE - 1, ACCEL_GRID_SIZE - 1, ACCEL_GRID_SIZE - 1)); + Vector3i from = Vector3i((center - extents) * proportions * ACCEL_GRID_SIZE); + Vector3i to = Vector3i((center + extents) * proportions * ACCEL_GRID_SIZE); + from = from.clampi(0, ACCEL_GRID_SIZE - 1); + to = to.clampi(0, ACCEL_GRID_SIZE - 1); for (int32_t x = from.x; x <= to.x; x++) { for (int32_t y = from.y; y <= to.y; y++) { @@ -370,7 +369,7 @@ public: break; } } - if (invalid || simplex_is_coplanar(points, *simplex)) { + if (invalid || simplex_is_coplanar(src_points, *simplex)) { memdelete(simplex); continue; } diff --git a/core/math/geometry_2d.cpp b/core/math/geometry_2d.cpp index 602e95bc13..d60619b27f 100644 --- a/core/math/geometry_2d.cpp +++ b/core/math/geometry_2d.cpp @@ -30,12 +30,12 @@ #include "geometry_2d.h" -#include "thirdparty/misc/clipper.hpp" +#include "thirdparty/clipper2/include/clipper2/clipper.h" #include "thirdparty/misc/polypartition.h" #define STB_RECT_PACK_IMPLEMENTATION #include "thirdparty/misc/stb_rect_pack.h" -#define SCALE_FACTOR 100000.0 // Based on CMP_EPSILON. +#define PRECISION 5 // Based on CMP_EPSILON. Vector<Vector<Vector2>> Geometry2D::decompose_polygon_in_convex(const Vector<Point2> &polygon) { Vector<Vector<Vector2>> decomp; @@ -196,58 +196,59 @@ void Geometry2D::make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_re } Vector<Vector<Point2>> Geometry2D::_polypaths_do_operation(PolyBooleanOperation p_op, const Vector<Point2> &p_polypath_a, const Vector<Point2> &p_polypath_b, bool is_a_open) { - using namespace ClipperLib; + using namespace Clipper2Lib; - ClipType op = ctUnion; + ClipType op = ClipType::Union; switch (p_op) { case OPERATION_UNION: - op = ctUnion; + op = ClipType::Union; break; case OPERATION_DIFFERENCE: - op = ctDifference; + op = ClipType::Difference; break; case OPERATION_INTERSECTION: - op = ctIntersection; + op = ClipType::Intersection; break; case OPERATION_XOR: - op = ctXor; + op = ClipType::Xor; break; } - Path path_a, path_b; - // Need to scale points (Clipper's requirement for robust computation). + PathD path_a(p_polypath_a.size()); for (int i = 0; i != p_polypath_a.size(); ++i) { - path_a << IntPoint(p_polypath_a[i].x * (real_t)SCALE_FACTOR, p_polypath_a[i].y * (real_t)SCALE_FACTOR); + path_a[i] = PointD(p_polypath_a[i].x, p_polypath_a[i].y); } + PathD path_b(p_polypath_b.size()); for (int i = 0; i != p_polypath_b.size(); ++i) { - path_b << IntPoint(p_polypath_b[i].x * (real_t)SCALE_FACTOR, p_polypath_b[i].y * (real_t)SCALE_FACTOR); + path_b[i] = PointD(p_polypath_b[i].x, p_polypath_b[i].y); } - Clipper clp; - clp.AddPath(path_a, ptSubject, !is_a_open); // Forward compatible with Clipper 10.0.0. - clp.AddPath(path_b, ptClip, true); // Polylines cannot be set as clip. - Paths paths; + ClipperD clp(PRECISION); // Scale points up internally to attain the desired precision. + clp.PreserveCollinear(false); // Remove redundant vertices. + if (is_a_open) { + clp.AddOpenSubject({ path_a }); + } else { + clp.AddSubject({ path_a }); + } + clp.AddClip({ path_b }); + + PathsD paths; if (is_a_open) { - PolyTree tree; // Needed to populate polylines. - clp.Execute(op, tree); - OpenPathsFromPolyTree(tree, paths); + PolyTreeD tree; // Needed to populate polylines. + clp.Execute(op, FillRule::EvenOdd, tree, paths); } else { - clp.Execute(op, paths); // Works on closed polygons only. + clp.Execute(op, FillRule::EvenOdd, paths); // Works on closed polygons only. } - // Have to scale points down now. + Vector<Vector<Point2>> polypaths; + for (PathsD::size_type i = 0; i < paths.size(); ++i) { + const PathD &path = paths[i]; - for (Paths::size_type i = 0; i < paths.size(); ++i) { Vector<Vector2> polypath; - - const Path &scaled_path = paths[i]; - - for (Paths::size_type j = 0; j < scaled_path.size(); ++j) { - polypath.push_back(Point2( - static_cast<real_t>(scaled_path[j].X) / (real_t)SCALE_FACTOR, - static_cast<real_t>(scaled_path[j].Y) / (real_t)SCALE_FACTOR)); + for (PathsD::size_type j = 0; j < path.size(); ++j) { + polypath.push_back(Point2(static_cast<real_t>(path[j].x), static_cast<real_t>(path[j].y))); } polypaths.push_back(polypath); } @@ -255,67 +256,61 @@ Vector<Vector<Point2>> Geometry2D::_polypaths_do_operation(PolyBooleanOperation } Vector<Vector<Point2>> Geometry2D::_polypath_offset(const Vector<Point2> &p_polypath, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) { - using namespace ClipperLib; + using namespace Clipper2Lib; - JoinType jt = jtSquare; + JoinType jt = JoinType::Square; switch (p_join_type) { case JOIN_SQUARE: - jt = jtSquare; + jt = JoinType::Square; break; case JOIN_ROUND: - jt = jtRound; + jt = JoinType::Round; break; case JOIN_MITER: - jt = jtMiter; + jt = JoinType::Miter; break; } - EndType et = etClosedPolygon; + EndType et = EndType::Polygon; switch (p_end_type) { case END_POLYGON: - et = etClosedPolygon; + et = EndType::Polygon; break; case END_JOINED: - et = etClosedLine; + et = EndType::Joined; break; case END_BUTT: - et = etOpenButt; + et = EndType::Butt; break; case END_SQUARE: - et = etOpenSquare; + et = EndType::Square; break; case END_ROUND: - et = etOpenRound; + et = EndType::Round; break; } - ClipperOffset co(2.0, 0.25f * (real_t)SCALE_FACTOR); // Defaults from ClipperOffset. - Path path; - // Need to scale points (Clipper's requirement for robust computation). + PathD polypath(p_polypath.size()); for (int i = 0; i != p_polypath.size(); ++i) { - path << IntPoint(p_polypath[i].x * (real_t)SCALE_FACTOR, p_polypath[i].y * (real_t)SCALE_FACTOR); + polypath[i] = PointD(p_polypath[i].x, p_polypath[i].y); } - co.AddPath(path, jt, et); - Paths paths; - co.Execute(paths, p_delta * (real_t)SCALE_FACTOR); // Inflate/deflate. + // Inflate/deflate. + PathsD paths = InflatePaths({ polypath }, p_delta, jt, et, 2.0, PRECISION, 0.0); + // Here the miter_limit = 2.0 and arc_tolerance = 0.0 are Clipper2 defaults, + // and the PRECISION is used to scale points up internally, to attain the desired precision. - // Have to scale points down now. Vector<Vector<Point2>> polypaths; + for (PathsD::size_type i = 0; i < paths.size(); ++i) { + const PathD &path = paths[i]; - for (Paths::size_type i = 0; i < paths.size(); ++i) { - Vector<Vector2> polypath; - - const Path &scaled_path = paths[i]; - - for (Paths::size_type j = 0; j < scaled_path.size(); ++j) { - polypath.push_back(Point2( - static_cast<real_t>(scaled_path[j].X) / (real_t)SCALE_FACTOR, - static_cast<real_t>(scaled_path[j].Y) / (real_t)SCALE_FACTOR)); + Vector<Vector2> polypath2; + for (PathsD::size_type j = 0; j < path.size(); ++j) { + polypath2.push_back(Point2(static_cast<real_t>(path[j].x), static_cast<real_t>(path[j].y))); } - polypaths.push_back(polypath); + polypaths.push_back(polypath2); } return polypaths; } diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp index 4483f61bc4..6a60a5925d 100644 --- a/core/math/quick_hull.cpp +++ b/core/math/quick_hull.cpp @@ -55,7 +55,7 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_ HashSet<Vector3> valid_cache; for (int i = 0; i < p_points.size(); i++) { - Vector3 sp = p_points[i].snapped(Vector3(0.0001, 0.0001, 0.0001)); + Vector3 sp = p_points[i].snappedf(0.0001); if (valid_cache.has(sp)) { valid_points.write[i] = false; } else { diff --git a/core/math/rect2.h b/core/math/rect2.h index 7f410feb1c..b4069ae86a 100644 --- a/core/math/rect2.h +++ b/core/math/rect2.h @@ -278,7 +278,7 @@ struct _NO_DISCARD_ Rect2 { } _FORCE_INLINE_ Rect2 abs() const { - return Rect2(position + size.min(Point2()), size.abs()); + return Rect2(position + size.minf(0), size.abs()); } _FORCE_INLINE_ Rect2 round() const { diff --git a/core/math/rect2i.h b/core/math/rect2i.h index 64806414c7..a1338da0bb 100644 --- a/core/math/rect2i.h +++ b/core/math/rect2i.h @@ -213,7 +213,7 @@ struct _NO_DISCARD_ Rect2i { } _FORCE_INLINE_ Rect2i abs() const { - return Rect2i(position + size.min(Point2i()), size.abs()); + return Rect2i(position + size.mini(0), size.abs()); } _FORCE_INLINE_ void set_end(const Vector2i &p_end) { diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp index 0da1b8c7ad..01b733183d 100644 --- a/core/math/triangle_mesh.cpp +++ b/core/math/triangle_mesh.cpp @@ -133,7 +133,7 @@ void TriangleMesh::create(const Vector<Vector3> &p_faces, const Vector<int32_t> for (int j = 0; j < 3; j++) { int vidx = -1; - Vector3 vs = v[j].snapped(Vector3(0.0001, 0.0001, 0.0001)); + Vector3 vs = v[j].snappedf(0.0001); HashMap<Vector3, int>::Iterator E = db.find(vs); if (E) { vidx = E->value; diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp index 198fd85d20..e86b97d6a8 100644 --- a/core/math/vector2.cpp +++ b/core/math/vector2.cpp @@ -135,12 +135,24 @@ Vector2 Vector2::clamp(const Vector2 &p_min, const Vector2 &p_max) const { CLAMP(y, p_min.y, p_max.y)); } +Vector2 Vector2::clampf(real_t p_min, real_t p_max) const { + return Vector2( + CLAMP(x, p_min, p_max), + CLAMP(y, p_min, p_max)); +} + Vector2 Vector2::snapped(const Vector2 &p_step) const { return Vector2( Math::snapped(x, p_step.x), Math::snapped(y, p_step.y)); } +Vector2 Vector2::snappedf(real_t p_step) const { + return Vector2( + Math::snapped(x, p_step), + Math::snapped(y, p_step)); +} + Vector2 Vector2::limit_length(real_t p_len) const { const real_t l = length(); Vector2 v = *this; diff --git a/core/math/vector2.h b/core/math/vector2.h index 6ad003edd1..8851942cdd 100644 --- a/core/math/vector2.h +++ b/core/math/vector2.h @@ -89,10 +89,18 @@ struct _NO_DISCARD_ Vector2 { return Vector2(MIN(x, p_vector2.x), MIN(y, p_vector2.y)); } + Vector2 minf(real_t p_scalar) const { + return Vector2(MIN(x, p_scalar), MIN(y, p_scalar)); + } + Vector2 max(const Vector2 &p_vector2) const { return Vector2(MAX(x, p_vector2.x), MAX(y, p_vector2.y)); } + Vector2 maxf(real_t p_scalar) const { + return Vector2(MAX(x, p_scalar), MAX(y, p_scalar)); + } + real_t distance_to(const Vector2 &p_vector2) const; real_t distance_squared_to(const Vector2 &p_vector2) const; real_t angle_to(const Vector2 &p_vector2) const; @@ -168,7 +176,9 @@ struct _NO_DISCARD_ Vector2 { Vector2 ceil() const; Vector2 round() const; Vector2 snapped(const Vector2 &p_by) const; + Vector2 snappedf(real_t p_by) const; Vector2 clamp(const Vector2 &p_min, const Vector2 &p_max) const; + Vector2 clampf(real_t p_min, real_t p_max) const; real_t aspect() const { return width / height; } operator String() const; diff --git a/core/math/vector2i.cpp b/core/math/vector2i.cpp index ba79d439dd..790f564734 100644 --- a/core/math/vector2i.cpp +++ b/core/math/vector2i.cpp @@ -39,12 +39,24 @@ Vector2i Vector2i::clamp(const Vector2i &p_min, const Vector2i &p_max) const { CLAMP(y, p_min.y, p_max.y)); } +Vector2i Vector2i::clampi(int32_t p_min, int32_t p_max) const { + return Vector2i( + CLAMP(x, p_min, p_max), + CLAMP(y, p_min, p_max)); +} + Vector2i Vector2i::snapped(const Vector2i &p_step) const { return Vector2i( Math::snapped(x, p_step.x), Math::snapped(y, p_step.y)); } +Vector2i Vector2i::snappedi(int32_t p_step) const { + return Vector2i( + Math::snapped(x, p_step), + Math::snapped(y, p_step)); +} + int64_t Vector2i::length_squared() const { return x * (int64_t)x + y * (int64_t)y; } diff --git a/core/math/vector2i.h b/core/math/vector2i.h index aa29263a65..aca9ae8272 100644 --- a/core/math/vector2i.h +++ b/core/math/vector2i.h @@ -81,10 +81,18 @@ struct _NO_DISCARD_ Vector2i { return Vector2i(MIN(x, p_vector2i.x), MIN(y, p_vector2i.y)); } + Vector2i mini(int32_t p_scalar) const { + return Vector2i(MIN(x, p_scalar), MIN(y, p_scalar)); + } + Vector2i max(const Vector2i &p_vector2i) const { return Vector2i(MAX(x, p_vector2i.x), MAX(y, p_vector2i.y)); } + Vector2i maxi(int32_t p_scalar) const { + return Vector2i(MAX(x, p_scalar), MAX(y, p_scalar)); + } + double distance_to(const Vector2i &p_to) const { return (p_to - *this).length(); } @@ -127,7 +135,9 @@ struct _NO_DISCARD_ Vector2i { Vector2i sign() const { return Vector2i(SIGN(x), SIGN(y)); } Vector2i abs() const { return Vector2i(Math::abs(x), Math::abs(y)); } Vector2i clamp(const Vector2i &p_min, const Vector2i &p_max) const; + Vector2i clampi(int32_t p_min, int32_t p_max) const; Vector2i snapped(const Vector2i &p_step) const; + Vector2i snappedi(int32_t p_step) const; operator String() const; operator Vector2() const; diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp index fad5f2c0fb..1e90002665 100644 --- a/core/math/vector3.cpp +++ b/core/math/vector3.cpp @@ -52,6 +52,13 @@ Vector3 Vector3::clamp(const Vector3 &p_min, const Vector3 &p_max) const { CLAMP(z, p_min.z, p_max.z)); } +Vector3 Vector3::clampf(real_t p_min, real_t p_max) const { + return Vector3( + CLAMP(x, p_min, p_max), + CLAMP(y, p_min, p_max), + CLAMP(z, p_min, p_max)); +} + void Vector3::snap(const Vector3 &p_step) { x = Math::snapped(x, p_step.x); y = Math::snapped(y, p_step.y); @@ -64,6 +71,18 @@ Vector3 Vector3::snapped(const Vector3 &p_step) const { return v; } +void Vector3::snapf(real_t p_step) { + x = Math::snapped(x, p_step); + y = Math::snapped(y, p_step); + z = Math::snapped(z, p_step); +} + +Vector3 Vector3::snappedf(real_t p_step) const { + Vector3 v = *this; + v.snapf(p_step); + return v; +} + Vector3 Vector3::limit_length(real_t p_len) const { const real_t l = length(); Vector3 v = *this; diff --git a/core/math/vector3.h b/core/math/vector3.h index f5d16984d9..2313eb557a 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -80,10 +80,18 @@ struct _NO_DISCARD_ Vector3 { return Vector3(MIN(x, p_vector3.x), MIN(y, p_vector3.y), MIN(z, p_vector3.z)); } + Vector3 minf(real_t p_scalar) const { + return Vector3(MIN(x, p_scalar), MIN(y, p_scalar), MIN(z, p_scalar)); + } + Vector3 max(const Vector3 &p_vector3) const { return Vector3(MAX(x, p_vector3.x), MAX(y, p_vector3.y), MAX(z, p_vector3.z)); } + Vector3 maxf(real_t p_scalar) const { + return Vector3(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar)); + } + _FORCE_INLINE_ real_t length() const; _FORCE_INLINE_ real_t length_squared() const; @@ -96,7 +104,9 @@ struct _NO_DISCARD_ Vector3 { _FORCE_INLINE_ void zero(); void snap(const Vector3 &p_step); + void snapf(real_t p_step); Vector3 snapped(const Vector3 &p_step) const; + Vector3 snappedf(real_t p_step) const; void rotate(const Vector3 &p_axis, real_t p_angle); Vector3 rotated(const Vector3 &p_axis, real_t p_angle) const; @@ -127,6 +137,7 @@ struct _NO_DISCARD_ Vector3 { _FORCE_INLINE_ Vector3 ceil() const; _FORCE_INLINE_ Vector3 round() const; Vector3 clamp(const Vector3 &p_min, const Vector3 &p_max) const; + Vector3 clampf(real_t p_min, real_t p_max) const; _FORCE_INLINE_ real_t distance_to(const Vector3 &p_to) const; _FORCE_INLINE_ real_t distance_squared_to(const Vector3 &p_to) const; diff --git a/core/math/vector3i.cpp b/core/math/vector3i.cpp index f41460e623..93f9d15ac1 100644 --- a/core/math/vector3i.cpp +++ b/core/math/vector3i.cpp @@ -48,6 +48,13 @@ Vector3i Vector3i::clamp(const Vector3i &p_min, const Vector3i &p_max) const { CLAMP(z, p_min.z, p_max.z)); } +Vector3i Vector3i::clampi(int32_t p_min, int32_t p_max) const { + return Vector3i( + CLAMP(x, p_min, p_max), + CLAMP(y, p_min, p_max), + CLAMP(z, p_min, p_max)); +} + Vector3i Vector3i::snapped(const Vector3i &p_step) const { return Vector3i( Math::snapped(x, p_step.x), @@ -55,6 +62,13 @@ Vector3i Vector3i::snapped(const Vector3i &p_step) const { Math::snapped(z, p_step.z)); } +Vector3i Vector3i::snappedi(int32_t p_step) const { + return Vector3i( + Math::snapped(x, p_step), + Math::snapped(y, p_step), + Math::snapped(z, p_step)); +} + Vector3i::operator String() const { return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ")"; } diff --git a/core/math/vector3i.h b/core/math/vector3i.h index a9f298bff1..035cfcf9e2 100644 --- a/core/math/vector3i.h +++ b/core/math/vector3i.h @@ -73,10 +73,18 @@ struct _NO_DISCARD_ Vector3i { return Vector3i(MIN(x, p_vector3i.x), MIN(y, p_vector3i.y), MIN(z, p_vector3i.z)); } + Vector3i mini(int32_t p_scalar) const { + return Vector3i(MIN(x, p_scalar), MIN(y, p_scalar), MIN(z, p_scalar)); + } + Vector3i max(const Vector3i &p_vector3i) const { return Vector3i(MAX(x, p_vector3i.x), MAX(y, p_vector3i.y), MAX(z, p_vector3i.z)); } + Vector3i maxi(int32_t p_scalar) const { + return Vector3i(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar)); + } + _FORCE_INLINE_ int64_t length_squared() const; _FORCE_INLINE_ double length() const; @@ -85,7 +93,9 @@ struct _NO_DISCARD_ Vector3i { _FORCE_INLINE_ Vector3i abs() const; _FORCE_INLINE_ Vector3i sign() const; Vector3i clamp(const Vector3i &p_min, const Vector3i &p_max) const; + Vector3i clampi(int32_t p_min, int32_t p_max) const; Vector3i snapped(const Vector3i &p_step) const; + Vector3i snappedi(int32_t p_step) const; _FORCE_INLINE_ double distance_to(const Vector3i &p_to) const; _FORCE_INLINE_ int64_t distance_squared_to(const Vector3i &p_to) const; diff --git a/core/math/vector4.cpp b/core/math/vector4.cpp index e6f6dee42c..b6b914f36d 100644 --- a/core/math/vector4.cpp +++ b/core/math/vector4.cpp @@ -30,6 +30,8 @@ #include "vector4.h" +#include "core/math/math_funcs.h" +#include "core/math/vector4i.h" #include "core/string/ustring.h" Vector4::Axis Vector4::min_axis_index() const { @@ -171,12 +173,25 @@ void Vector4::snap(const Vector4 &p_step) { w = Math::snapped(w, p_step.w); } +void Vector4::snapf(real_t p_step) { + x = Math::snapped(x, p_step); + y = Math::snapped(y, p_step); + z = Math::snapped(z, p_step); + w = Math::snapped(w, p_step); +} + Vector4 Vector4::snapped(const Vector4 &p_step) const { Vector4 v = *this; v.snap(p_step); return v; } +Vector4 Vector4::snappedf(real_t p_step) const { + Vector4 v = *this; + v.snapf(p_step); + return v; +} + Vector4 Vector4::inverse() const { return Vector4(1.0f / x, 1.0f / y, 1.0f / z, 1.0f / w); } @@ -189,8 +204,20 @@ Vector4 Vector4::clamp(const Vector4 &p_min, const Vector4 &p_max) const { CLAMP(w, p_min.w, p_max.w)); } +Vector4 Vector4::clampf(real_t p_min, real_t p_max) const { + return Vector4( + CLAMP(x, p_min, p_max), + CLAMP(y, p_min, p_max), + CLAMP(z, p_min, p_max), + CLAMP(w, p_min, p_max)); +} + Vector4::operator String() const { return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ", " + String::num_real(w, false) + ")"; } static_assert(sizeof(Vector4) == 4 * sizeof(real_t)); + +Vector4::operator Vector4i() const { + return Vector4i(x, y, z, w); +} diff --git a/core/math/vector4.h b/core/math/vector4.h index 4dba3126cb..f69b4752bb 100644 --- a/core/math/vector4.h +++ b/core/math/vector4.h @@ -32,9 +32,11 @@ #define VECTOR4_H #include "core/error/error_macros.h" -#include "core/math/math_funcs.h" +#include "core/math/math_defs.h" +#include "core/typedefs.h" class String; +struct Vector4i; struct _NO_DISCARD_ Vector4 { static const int AXIS_COUNT = 4; @@ -72,10 +74,18 @@ struct _NO_DISCARD_ Vector4 { return Vector4(MIN(x, p_vector4.x), MIN(y, p_vector4.y), MIN(z, p_vector4.z), MIN(w, p_vector4.w)); } + Vector4 minf(real_t p_scalar) const { + return Vector4(MIN(x, p_scalar), MIN(y, p_scalar), MIN(z, p_scalar), MIN(w, p_scalar)); + } + Vector4 max(const Vector4 &p_vector4) const { return Vector4(MAX(x, p_vector4.x), MAX(y, p_vector4.y), MAX(z, p_vector4.z), MAX(w, p_vector4.w)); } + Vector4 maxf(real_t p_scalar) const { + return Vector4(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar), MAX(w, p_scalar)); + } + _FORCE_INLINE_ real_t length_squared() const; bool is_equal_approx(const Vector4 &p_vec4) const; bool is_zero_approx() const; @@ -101,8 +111,11 @@ struct _NO_DISCARD_ Vector4 { Vector4 posmod(real_t p_mod) const; Vector4 posmodv(const Vector4 &p_modv) const; void snap(const Vector4 &p_step); + void snapf(real_t p_step); Vector4 snapped(const Vector4 &p_step) const; + Vector4 snappedf(real_t p_step) const; Vector4 clamp(const Vector4 &p_min, const Vector4 &p_max) const; + Vector4 clampf(real_t p_min, real_t p_max) const; Vector4 inverse() const; _FORCE_INLINE_ real_t dot(const Vector4 &p_vec4) const; @@ -129,28 +142,14 @@ struct _NO_DISCARD_ Vector4 { _FORCE_INLINE_ bool operator<=(const Vector4 &p_vec4) const; operator String() const; + operator Vector4i() const; _FORCE_INLINE_ Vector4() {} - - _FORCE_INLINE_ Vector4(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) { - } - - Vector4(const Vector4 &p_vec4) : - x(p_vec4.x), - y(p_vec4.y), - z(p_vec4.z), - w(p_vec4.w) { - } - - void operator=(const Vector4 &p_vec4) { - x = p_vec4.x; - y = p_vec4.y; - z = p_vec4.z; - w = p_vec4.w; + _FORCE_INLINE_ Vector4(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; } }; diff --git a/core/math/vector4i.cpp b/core/math/vector4i.cpp index 8e36c6b534..afa77a4988 100644 --- a/core/math/vector4i.cpp +++ b/core/math/vector4i.cpp @@ -65,6 +65,14 @@ Vector4i Vector4i::clamp(const Vector4i &p_min, const Vector4i &p_max) const { CLAMP(w, p_min.w, p_max.w)); } +Vector4i Vector4i::clampi(int32_t p_min, int32_t p_max) const { + return Vector4i( + CLAMP(x, p_min, p_max), + CLAMP(y, p_min, p_max), + CLAMP(z, p_min, p_max), + CLAMP(w, p_min, p_max)); +} + Vector4i Vector4i::snapped(const Vector4i &p_step) const { return Vector4i( Math::snapped(x, p_step.x), @@ -73,6 +81,14 @@ Vector4i Vector4i::snapped(const Vector4i &p_step) const { Math::snapped(w, p_step.w)); } +Vector4i Vector4i::snappedi(int32_t p_step) const { + return Vector4i( + Math::snapped(x, p_step), + Math::snapped(y, p_step), + Math::snapped(z, p_step), + Math::snapped(w, p_step)); +} + Vector4i::operator String() const { return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ", " + itos(w) + ")"; } diff --git a/core/math/vector4i.h b/core/math/vector4i.h index 5a96d98d18..8a9c580bc1 100644 --- a/core/math/vector4i.h +++ b/core/math/vector4i.h @@ -75,10 +75,18 @@ struct _NO_DISCARD_ Vector4i { return Vector4i(MIN(x, p_vector4i.x), MIN(y, p_vector4i.y), MIN(z, p_vector4i.z), MIN(w, p_vector4i.w)); } + Vector4i mini(int32_t p_scalar) const { + return Vector4i(MIN(x, p_scalar), MIN(y, p_scalar), MIN(z, p_scalar), MIN(w, p_scalar)); + } + Vector4i max(const Vector4i &p_vector4i) const { return Vector4i(MAX(x, p_vector4i.x), MAX(y, p_vector4i.y), MAX(z, p_vector4i.z), MAX(w, p_vector4i.w)); } + Vector4i maxi(int32_t p_scalar) const { + return Vector4i(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar), MAX(w, p_scalar)); + } + _FORCE_INLINE_ int64_t length_squared() const; _FORCE_INLINE_ double length() const; @@ -90,7 +98,9 @@ struct _NO_DISCARD_ Vector4i { _FORCE_INLINE_ Vector4i abs() const; _FORCE_INLINE_ Vector4i sign() const; Vector4i clamp(const Vector4i &p_min, const Vector4i &p_max) const; + Vector4i clampi(int32_t p_min, int32_t p_max) const; Vector4i snapped(const Vector4i &p_step) const; + Vector4i snappedi(int32_t p_step) const; /* Operators */ |