2
0
Эх сурвалжийг харах

Split `Geometry` singleton into `Geometry2D` and `Geometry3D`

Extra `_2d` suffixes are removed from 2D methods accoringly.
Andrii Doroshenko (Xrayez) 5 жил өмнө
parent
commit
69d5de632e
70 өөрчлөгдсөн 1503 нэмэгдсэн , 1379 устгасан
  1. 198 182
      core/bind/core_bind.cpp
  2. 52 36
      core/bind/core_bind.h
  3. 2 2
      core/math/a_star.cpp
  4. 3 3
      core/math/face3.cpp
  5. 384 0
      core/math/geometry_2d.cpp
  6. 398 0
      core/math/geometry_2d.h
  7. 12 376
      core/math/geometry_3d.cpp
  8. 7 367
      core/math/geometry_3d.h
  9. 2 2
      core/math/octree.h
  10. 9 9
      core/math/quick_hull.cpp
  11. 3 3
      core/math/quick_hull.h
  12. 12 6
      core/register_core_types.cpp
  13. 5 2
      doc/classes/@GlobalScope.xml
  14. 1 1
      doc/classes/ConvexPolygonShape2D.xml
  15. 19 213
      doc/classes/Geometry2D.xml
  16. 194 0
      doc/classes/Geometry3D.xml
  17. 2 1
      editor/import/resource_importer_texture_atlas.cpp
  18. 22 21
      editor/node_3d_editor_gizmos.cpp
  19. 2 1
      editor/plugins/abstract_polygon_2d_editor.cpp
  20. 2 2
      editor/plugins/animation_blend_space_2d_editor.cpp
  21. 2 2
      editor/plugins/animation_state_machine_editor.cpp
  22. 2 1
      editor/plugins/canvas_item_editor_plugin.cpp
  23. 2 1
      editor/plugins/collision_polygon_3d_editor_plugin.cpp
  24. 2 2
      editor/plugins/node_3d_editor_plugin.cpp
  25. 4 2
      editor/plugins/path_3d_editor_plugin.cpp
  26. 2 1
      editor/plugins/polygon_2d_editor_plugin.cpp
  27. 2 1
      editor/plugins/sprite_2d_editor_plugin.cpp
  28. 2 1
      main/tests/test_math.cpp
  29. 8 8
      main/tests/test_physics_3d.cpp
  30. 3 3
      main/tests/test_render.cpp
  31. 1 1
      modules/bullet/shape_bullet.h
  32. 7 7
      modules/csg/csg.cpp
  33. 4 4
      modules/csg/csg_gizmos.cpp
  34. 2 1
      modules/csg/csg_shape.cpp
  35. 2 2
      modules/gdnavigation/nav_map.cpp
  36. 2 2
      modules/gdnavigation/navigation_mesh_generator.cpp
  37. 0 1
      modules/gridmap/grid_map_editor_plugin.cpp
  38. 6 6
      modules/lightmapper_rd/lightmapper_rd.cpp
  39. 3 2
      scene/2d/collision_polygon_2d.cpp
  40. 3 2
      scene/2d/light_occluder_2d.cpp
  41. 2 1
      scene/2d/line_2d.cpp
  42. 2 1
      scene/2d/navigation_agent_2d.cpp
  43. 3 2
      scene/2d/navigation_region_2d.cpp
  44. 2 1
      scene/2d/path_2d.cpp
  45. 4 4
      scene/2d/polygon_2d.cpp
  46. 1 1
      scene/3d/baked_lightmap.cpp
  47. 2 1
      scene/3d/collision_polygon_3d.cpp
  48. 1 1
      scene/3d/navigation_agent_3d.cpp
  49. 5 5
      scene/3d/voxelizer.cpp
  50. 5 5
      scene/animation/animation_blend_space_2d.cpp
  51. 3 2
      scene/gui/control.cpp
  52. 3 3
      scene/resources/animation.cpp
  53. 2 1
      scene/resources/capsule_shape_2d.cpp
  54. 2 1
      scene/resources/concave_polygon_shape_2d.cpp
  55. 4 4
      scene/resources/convex_polygon_shape_2d.cpp
  56. 1 1
      scene/resources/convex_polygon_shape_3d.cpp
  57. 2 1
      scene/resources/line_shape_2d.cpp
  58. 10 10
      scene/resources/polygon_path_finder.cpp
  59. 2 1
      scene/resources/segment_shape_2d.cpp
  60. 3 1
      scene/resources/tile_set.cpp
  61. 2 2
      servers/physics_2d/collision_solver_2d_sat.cpp
  62. 4 4
      servers/physics_2d/shape_2d_sw.cpp
  63. 21 21
      servers/physics_3d/collision_solver_3d_sat.cpp
  64. 17 17
      servers/physics_3d/shape_3d_sw.cpp
  65. 3 3
      servers/physics_3d/shape_3d_sw.h
  66. 1 1
      servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp
  67. 3 1
      servers/rendering/rendering_server_canvas.cpp
  68. 0 1
      servers/rendering/rendering_server_scene.h
  69. 3 3
      servers/rendering_server.cpp
  70. 2 2
      servers/rendering_server.h

+ 198 - 182
core/bind/core_bind.cpp

@@ -35,7 +35,8 @@
 #include "core/io/file_access_encrypted.h"
 #include "core/io/json.h"
 #include "core/io/marshalls.h"
-#include "core/math/geometry.h"
+#include "core/math/geometry_2d.h"
+#include "core/math/geometry_3d.h"
 #include "core/os/keyboard.h"
 #include "core/os/os.h"
 #include "core/project_settings.h"
@@ -828,55 +829,43 @@ void _OS::_bind_methods() {
 	BIND_ENUM_CONSTANT(SYSTEM_DIR_RINGTONES);
 }
 
-////// _Geometry //////
+////// _Geometry2D //////
 
-_Geometry *_Geometry::singleton = nullptr;
+_Geometry2D *_Geometry2D::singleton = nullptr;
 
-_Geometry *_Geometry::get_singleton() {
+_Geometry2D *_Geometry2D::get_singleton() {
 	return singleton;
 }
 
-Vector<Plane> _Geometry::build_box_planes(const Vector3 &p_extents) {
-	return Geometry::build_box_planes(p_extents);
+bool _Geometry2D::is_point_in_circle(const Vector2 &p_point, const Vector2 &p_circle_pos, real_t p_circle_radius) {
+	return Geometry2D::is_point_in_circle(p_point, p_circle_pos, p_circle_radius);
 }
 
-Vector<Plane> _Geometry::build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis) {
-	return Geometry::build_cylinder_planes(p_radius, p_height, p_sides, p_axis);
+real_t _Geometry2D::segment_intersects_circle(const Vector2 &p_from, const Vector2 &p_to, const Vector2 &p_circle_pos, real_t p_circle_radius) {
+	return Geometry2D::segment_intersects_circle(p_from, p_to, p_circle_pos, p_circle_radius);
 }
 
-Vector<Plane> _Geometry::build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis) {
-	return Geometry::build_capsule_planes(p_radius, p_height, p_sides, p_lats, p_axis);
-}
-
-bool _Geometry::is_point_in_circle(const Vector2 &p_point, const Vector2 &p_circle_pos, real_t p_circle_radius) {
-	return Geometry::is_point_in_circle(p_point, p_circle_pos, p_circle_radius);
-}
-
-real_t _Geometry::segment_intersects_circle(const Vector2 &p_from, const Vector2 &p_to, const Vector2 &p_circle_pos, real_t p_circle_radius) {
-	return Geometry::segment_intersects_circle(p_from, p_to, p_circle_pos, p_circle_radius);
-}
-
-Variant _Geometry::segment_intersects_segment_2d(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b) {
+Variant _Geometry2D::segment_intersects_segment(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b) {
 	Vector2 result;
-	if (Geometry::segment_intersects_segment_2d(p_from_a, p_to_a, p_from_b, p_to_b, &result)) {
+	if (Geometry2D::segment_intersects_segment(p_from_a, p_to_a, p_from_b, p_to_b, &result)) {
 		return result;
 	} else {
 		return Variant();
 	}
 }
 
-Variant _Geometry::line_intersects_line_2d(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b) {
+Variant _Geometry2D::line_intersects_line(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b) {
 	Vector2 result;
-	if (Geometry::line_intersects_line_2d(p_from_a, p_dir_a, p_from_b, p_dir_b, result)) {
+	if (Geometry2D::line_intersects_line(p_from_a, p_dir_a, p_from_b, p_dir_b, result)) {
 		return result;
 	} else {
 		return Variant();
 	}
 }
 
-Vector<Vector2> _Geometry::get_closest_points_between_segments_2d(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2) {
+Vector<Vector2> _Geometry2D::get_closest_points_between_segments(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2) {
 	Vector2 r1, r2;
-	Geometry::get_closest_points_between_segments(p1, q1, p2, q2, r1, r2);
+	Geometry2D::get_closest_points_between_segments(p1, q1, p2, q2, r1, r2);
 	Vector<Vector2> r;
 	r.resize(2);
 	r.set(0, r1);
@@ -884,123 +873,42 @@ Vector<Vector2> _Geometry::get_closest_points_between_segments_2d(const Vector2
 	return r;
 }
 
-Vector<Vector3> _Geometry::get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2) {
-	Vector3 r1, r2;
-	Geometry::get_closest_points_between_segments(p1, p2, q1, q2, r1, r2);
-	Vector<Vector3> r;
-	r.resize(2);
-	r.set(0, r1);
-	r.set(1, r2);
-	return r;
-}
-
-Vector2 _Geometry::get_closest_point_to_segment_2d(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b) {
+Vector2 _Geometry2D::get_closest_point_to_segment(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b) {
 	Vector2 s[2] = { p_a, p_b };
-	return Geometry::get_closest_point_to_segment_2d(p_point, s);
-}
-
-Vector3 _Geometry::get_closest_point_to_segment(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b) {
-	Vector3 s[2] = { p_a, p_b };
-	return Geometry::get_closest_point_to_segment(p_point, s);
+	return Geometry2D::get_closest_point_to_segment(p_point, s);
 }
 
-Vector2 _Geometry::get_closest_point_to_segment_uncapped_2d(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b) {
+Vector2 _Geometry2D::get_closest_point_to_segment_uncapped(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b) {
 	Vector2 s[2] = { p_a, p_b };
-	return Geometry::get_closest_point_to_segment_uncapped_2d(p_point, s);
-}
-
-Vector3 _Geometry::get_closest_point_to_segment_uncapped(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b) {
-	Vector3 s[2] = { p_a, p_b };
-	return Geometry::get_closest_point_to_segment_uncapped(p_point, s);
-}
-
-Variant _Geometry::ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2) {
-	Vector3 res;
-	if (Geometry::ray_intersects_triangle(p_from, p_dir, p_v0, p_v1, p_v2, &res)) {
-		return res;
-	} else {
-		return Variant();
-	}
-}
-
-Variant _Geometry::segment_intersects_triangle(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2) {
-	Vector3 res;
-	if (Geometry::segment_intersects_triangle(p_from, p_to, p_v0, p_v1, p_v2, &res)) {
-		return res;
-	} else {
-		return Variant();
-	}
-}
-
-bool _Geometry::point_is_inside_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) const {
-	return Geometry::is_point_in_triangle(s, a, b, c);
-}
-
-Vector<Vector3> _Geometry::segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius) {
-	Vector<Vector3> r;
-	Vector3 res, norm;
-	if (!Geometry::segment_intersects_sphere(p_from, p_to, p_sphere_pos, p_sphere_radius, &res, &norm)) {
-		return r;
-	}
-
-	r.resize(2);
-	r.set(0, res);
-	r.set(1, norm);
-	return r;
+	return Geometry2D::get_closest_point_to_segment_uncapped(p_point, s);
 }
 
-Vector<Vector3> _Geometry::segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, float p_height, float p_radius) {
-	Vector<Vector3> r;
-	Vector3 res, norm;
-	if (!Geometry::segment_intersects_cylinder(p_from, p_to, p_height, p_radius, &res, &norm)) {
-		return r;
-	}
-
-	r.resize(2);
-	r.set(0, res);
-	r.set(1, norm);
-	return r;
+bool _Geometry2D::point_is_inside_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) const {
+	return Geometry2D::is_point_in_triangle(s, a, b, c);
 }
 
-Vector<Vector3> _Geometry::segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const Vector<Plane> &p_planes) {
-	Vector<Vector3> r;
-	Vector3 res, norm;
-	if (!Geometry::segment_intersects_convex(p_from, p_to, p_planes.ptr(), p_planes.size(), &res, &norm)) {
-		return r;
-	}
-
-	r.resize(2);
-	r.set(0, res);
-	r.set(1, norm);
-	return r;
-}
-
-bool _Geometry::is_polygon_clockwise(const Vector<Vector2> &p_polygon) {
-	return Geometry::is_polygon_clockwise(p_polygon);
-}
-
-bool _Geometry::is_point_in_polygon(const Point2 &p_point, const Vector<Vector2> &p_polygon) {
-	return Geometry::is_point_in_polygon(p_point, p_polygon);
+bool _Geometry2D::is_polygon_clockwise(const Vector<Vector2> &p_polygon) {
+	return Geometry2D::is_polygon_clockwise(p_polygon);
 }
 
-Vector<int> _Geometry::triangulate_polygon(const Vector<Vector2> &p_polygon) {
-	return Geometry::triangulate_polygon(p_polygon);
+bool _Geometry2D::is_point_in_polygon(const Point2 &p_point, const Vector<Vector2> &p_polygon) {
+	return Geometry2D::is_point_in_polygon(p_point, p_polygon);
 }
 
-Vector<int> _Geometry::triangulate_delaunay_2d(const Vector<Vector2> &p_points) {
-	return Geometry::triangulate_delaunay_2d(p_points);
+Vector<int> _Geometry2D::triangulate_polygon(const Vector<Vector2> &p_polygon) {
+	return Geometry2D::triangulate_polygon(p_polygon);
 }
 
-Vector<Point2> _Geometry::convex_hull_2d(const Vector<Point2> &p_points) {
-	return Geometry::convex_hull_2d(p_points);
+Vector<int> _Geometry2D::triangulate_delaunay(const Vector<Vector2> &p_points) {
+	return Geometry2D::triangulate_delaunay(p_points);
 }
 
-Vector<Vector3> _Geometry::clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane) {
-	return Geometry::clip_polygon(p_points, p_plane);
+Vector<Point2> _Geometry2D::convex_hull(const Vector<Point2> &p_points) {
+	return Geometry2D::convex_hull(p_points);
 }
 
-Array _Geometry::merge_polygons_2d(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) {
-	Vector<Vector<Point2>> polys = Geometry::merge_polygons_2d(p_polygon_a, p_polygon_b);
+Array _Geometry2D::merge_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) {
+	Vector<Vector<Point2>> polys = Geometry2D::merge_polygons(p_polygon_a, p_polygon_b);
 
 	Array ret;
 
@@ -1010,8 +918,8 @@ Array _Geometry::merge_polygons_2d(const Vector<Vector2> &p_polygon_a, const Vec
 	return ret;
 }
 
-Array _Geometry::clip_polygons_2d(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) {
-	Vector<Vector<Point2>> polys = Geometry::clip_polygons_2d(p_polygon_a, p_polygon_b);
+Array _Geometry2D::clip_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) {
+	Vector<Vector<Point2>> polys = Geometry2D::clip_polygons(p_polygon_a, p_polygon_b);
 
 	Array ret;
 
@@ -1021,8 +929,8 @@ Array _Geometry::clip_polygons_2d(const Vector<Vector2> &p_polygon_a, const Vect
 	return ret;
 }
 
-Array _Geometry::intersect_polygons_2d(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) {
-	Vector<Vector<Point2>> polys = Geometry::intersect_polygons_2d(p_polygon_a, p_polygon_b);
+Array _Geometry2D::intersect_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) {
+	Vector<Vector<Point2>> polys = Geometry2D::intersect_polygons(p_polygon_a, p_polygon_b);
 
 	Array ret;
 
@@ -1032,8 +940,8 @@ Array _Geometry::intersect_polygons_2d(const Vector<Vector2> &p_polygon_a, const
 	return ret;
 }
 
-Array _Geometry::exclude_polygons_2d(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) {
-	Vector<Vector<Point2>> polys = Geometry::exclude_polygons_2d(p_polygon_a, p_polygon_b);
+Array _Geometry2D::exclude_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) {
+	Vector<Vector<Point2>> polys = Geometry2D::exclude_polygons(p_polygon_a, p_polygon_b);
 
 	Array ret;
 
@@ -1043,8 +951,8 @@ Array _Geometry::exclude_polygons_2d(const Vector<Vector2> &p_polygon_a, const V
 	return ret;
 }
 
-Array _Geometry::clip_polyline_with_polygon_2d(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) {
-	Vector<Vector<Point2>> polys = Geometry::clip_polyline_with_polygon_2d(p_polyline, p_polygon);
+Array _Geometry2D::clip_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) {
+	Vector<Vector<Point2>> polys = Geometry2D::clip_polyline_with_polygon(p_polyline, p_polygon);
 
 	Array ret;
 
@@ -1054,8 +962,8 @@ Array _Geometry::clip_polyline_with_polygon_2d(const Vector<Vector2> &p_polyline
 	return ret;
 }
 
-Array _Geometry::intersect_polyline_with_polygon_2d(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) {
-	Vector<Vector<Point2>> polys = Geometry::intersect_polyline_with_polygon_2d(p_polyline, p_polygon);
+Array _Geometry2D::intersect_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) {
+	Vector<Vector<Point2>> polys = Geometry2D::intersect_polyline_with_polygon(p_polyline, p_polygon);
 
 	Array ret;
 
@@ -1065,8 +973,8 @@ Array _Geometry::intersect_polyline_with_polygon_2d(const Vector<Vector2> &p_pol
 	return ret;
 }
 
-Array _Geometry::offset_polygon_2d(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type) {
-	Vector<Vector<Point2>> polys = Geometry::offset_polygon_2d(p_polygon, p_delta, Geometry::PolyJoinType(p_join_type));
+Array _Geometry2D::offset_polygon(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type) {
+	Vector<Vector<Point2>> polys = Geometry2D::offset_polygon(p_polygon, p_delta, Geometry2D::PolyJoinType(p_join_type));
 
 	Array ret;
 
@@ -1076,8 +984,8 @@ Array _Geometry::offset_polygon_2d(const Vector<Vector2> &p_polygon, real_t p_de
 	return ret;
 }
 
-Array _Geometry::offset_polyline_2d(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) {
-	Vector<Vector<Point2>> polys = Geometry::offset_polyline_2d(p_polygon, p_delta, Geometry::PolyJoinType(p_join_type), Geometry::PolyEndType(p_end_type));
+Array _Geometry2D::offset_polyline(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) {
+	Vector<Vector<Point2>> polys = Geometry2D::offset_polyline(p_polygon, p_delta, Geometry2D::PolyJoinType(p_join_type), Geometry2D::PolyEndType(p_end_type));
 
 	Array ret;
 
@@ -1087,7 +995,7 @@ Array _Geometry::offset_polyline_2d(const Vector<Vector2> &p_polygon, real_t p_d
 	return ret;
 }
 
-Dictionary _Geometry::make_atlas(const Vector<Size2> &p_rects) {
+Dictionary _Geometry2D::make_atlas(const Vector<Size2> &p_rects) {
 	Dictionary ret;
 
 	Vector<Size2i> rects;
@@ -1098,7 +1006,7 @@ Dictionary _Geometry::make_atlas(const Vector<Size2> &p_rects) {
 	Vector<Point2i> result;
 	Size2i size;
 
-	Geometry::make_atlas(rects, result, size);
+	Geometry2D::make_atlas(rects, result, size);
 
 	Size2 r_size = size;
 	Vector<Point2> r_result;
@@ -1112,56 +1020,37 @@ Dictionary _Geometry::make_atlas(const Vector<Size2> &p_rects) {
 	return ret;
 }
 
-int _Geometry::get_uv84_normal_bit(const Vector3 &p_vector) {
-	return Geometry::get_uv84_normal_bit(p_vector);
-}
-
-void _Geometry::_bind_methods() {
-	ClassDB::bind_method(D_METHOD("build_box_planes", "extents"), &_Geometry::build_box_planes);
-	ClassDB::bind_method(D_METHOD("build_cylinder_planes", "radius", "height", "sides", "axis"), &_Geometry::build_cylinder_planes, DEFVAL(Vector3::AXIS_Z));
-	ClassDB::bind_method(D_METHOD("build_capsule_planes", "radius", "height", "sides", "lats", "axis"), &_Geometry::build_capsule_planes, DEFVAL(Vector3::AXIS_Z));
-	ClassDB::bind_method(D_METHOD("is_point_in_circle", "point", "circle_position", "circle_radius"), &_Geometry::is_point_in_circle);
-	ClassDB::bind_method(D_METHOD("segment_intersects_circle", "segment_from", "segment_to", "circle_position", "circle_radius"), &_Geometry::segment_intersects_circle);
-	ClassDB::bind_method(D_METHOD("segment_intersects_segment_2d", "from_a", "to_a", "from_b", "to_b"), &_Geometry::segment_intersects_segment_2d);
-	ClassDB::bind_method(D_METHOD("line_intersects_line_2d", "from_a", "dir_a", "from_b", "dir_b"), &_Geometry::line_intersects_line_2d);
-
-	ClassDB::bind_method(D_METHOD("get_closest_points_between_segments_2d", "p1", "q1", "p2", "q2"), &_Geometry::get_closest_points_between_segments_2d);
-	ClassDB::bind_method(D_METHOD("get_closest_points_between_segments", "p1", "p2", "q1", "q2"), &_Geometry::get_closest_points_between_segments);
+void _Geometry2D::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("is_point_in_circle", "point", "circle_position", "circle_radius"), &_Geometry2D::is_point_in_circle);
+	ClassDB::bind_method(D_METHOD("segment_intersects_segment", "from_a", "to_a", "from_b", "to_b"), &_Geometry2D::segment_intersects_segment);
+	ClassDB::bind_method(D_METHOD("line_intersects_line", "from_a", "dir_a", "from_b", "dir_b"), &_Geometry2D::line_intersects_line);
 
-	ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_2d", "point", "s1", "s2"), &_Geometry::get_closest_point_to_segment_2d);
-	ClassDB::bind_method(D_METHOD("get_closest_point_to_segment", "point", "s1", "s2"), &_Geometry::get_closest_point_to_segment);
+	ClassDB::bind_method(D_METHOD("get_closest_points_between_segments", "p1", "q1", "p2", "q2"), &_Geometry2D::get_closest_points_between_segments);
 
-	ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_uncapped_2d", "point", "s1", "s2"), &_Geometry::get_closest_point_to_segment_uncapped_2d);
-	ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_uncapped", "point", "s1", "s2"), &_Geometry::get_closest_point_to_segment_uncapped);
+	ClassDB::bind_method(D_METHOD("get_closest_point_to_segment", "point", "s1", "s2"), &_Geometry2D::get_closest_point_to_segment);
 
-	ClassDB::bind_method(D_METHOD("get_uv84_normal_bit", "normal"), &_Geometry::get_uv84_normal_bit);
+	ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_uncapped", "point", "s1", "s2"), &_Geometry2D::get_closest_point_to_segment_uncapped);
 
-	ClassDB::bind_method(D_METHOD("ray_intersects_triangle", "from", "dir", "a", "b", "c"), &_Geometry::ray_intersects_triangle);
-	ClassDB::bind_method(D_METHOD("segment_intersects_triangle", "from", "to", "a", "b", "c"), &_Geometry::segment_intersects_triangle);
-	ClassDB::bind_method(D_METHOD("segment_intersects_sphere", "from", "to", "sphere_position", "sphere_radius"), &_Geometry::segment_intersects_sphere);
-	ClassDB::bind_method(D_METHOD("segment_intersects_cylinder", "from", "to", "height", "radius"), &_Geometry::segment_intersects_cylinder);
-	ClassDB::bind_method(D_METHOD("segment_intersects_convex", "from", "to", "planes"), &_Geometry::segment_intersects_convex);
-	ClassDB::bind_method(D_METHOD("point_is_inside_triangle", "point", "a", "b", "c"), &_Geometry::point_is_inside_triangle);
+	ClassDB::bind_method(D_METHOD("point_is_inside_triangle", "point", "a", "b", "c"), &_Geometry2D::point_is_inside_triangle);
 
-	ClassDB::bind_method(D_METHOD("is_polygon_clockwise", "polygon"), &_Geometry::is_polygon_clockwise);
-	ClassDB::bind_method(D_METHOD("is_point_in_polygon", "point", "polygon"), &_Geometry::is_point_in_polygon);
-	ClassDB::bind_method(D_METHOD("triangulate_polygon", "polygon"), &_Geometry::triangulate_polygon);
-	ClassDB::bind_method(D_METHOD("triangulate_delaunay_2d", "points"), &_Geometry::triangulate_delaunay_2d);
-	ClassDB::bind_method(D_METHOD("convex_hull_2d", "points"), &_Geometry::convex_hull_2d);
-	ClassDB::bind_method(D_METHOD("clip_polygon", "points", "plane"), &_Geometry::clip_polygon);
+	ClassDB::bind_method(D_METHOD("is_polygon_clockwise", "polygon"), &_Geometry2D::is_polygon_clockwise);
+	ClassDB::bind_method(D_METHOD("is_point_in_polygon", "point", "polygon"), &_Geometry2D::is_point_in_polygon);
+	ClassDB::bind_method(D_METHOD("triangulate_polygon", "polygon"), &_Geometry2D::triangulate_polygon);
+	ClassDB::bind_method(D_METHOD("triangulate_delaunay", "points"), &_Geometry2D::triangulate_delaunay);
+	ClassDB::bind_method(D_METHOD("convex_hull", "points"), &_Geometry2D::convex_hull);
 
-	ClassDB::bind_method(D_METHOD("merge_polygons_2d", "polygon_a", "polygon_b"), &_Geometry::merge_polygons_2d);
-	ClassDB::bind_method(D_METHOD("clip_polygons_2d", "polygon_a", "polygon_b"), &_Geometry::clip_polygons_2d);
-	ClassDB::bind_method(D_METHOD("intersect_polygons_2d", "polygon_a", "polygon_b"), &_Geometry::intersect_polygons_2d);
-	ClassDB::bind_method(D_METHOD("exclude_polygons_2d", "polygon_a", "polygon_b"), &_Geometry::exclude_polygons_2d);
+	ClassDB::bind_method(D_METHOD("merge_polygons", "polygon_a", "polygon_b"), &_Geometry2D::merge_polygons);
+	ClassDB::bind_method(D_METHOD("clip_polygons", "polygon_a", "polygon_b"), &_Geometry2D::clip_polygons);
+	ClassDB::bind_method(D_METHOD("intersect_polygons", "polygon_a", "polygon_b"), &_Geometry2D::intersect_polygons);
+	ClassDB::bind_method(D_METHOD("exclude_polygons", "polygon_a", "polygon_b"), &_Geometry2D::exclude_polygons);
 
-	ClassDB::bind_method(D_METHOD("clip_polyline_with_polygon_2d", "polyline", "polygon"), &_Geometry::clip_polyline_with_polygon_2d);
-	ClassDB::bind_method(D_METHOD("intersect_polyline_with_polygon_2d", "polyline", "polygon"), &_Geometry::intersect_polyline_with_polygon_2d);
+	ClassDB::bind_method(D_METHOD("clip_polyline_with_polygon", "polyline", "polygon"), &_Geometry2D::clip_polyline_with_polygon);
+	ClassDB::bind_method(D_METHOD("intersect_polyline_with_polygon", "polyline", "polygon"), &_Geometry2D::intersect_polyline_with_polygon);
 
-	ClassDB::bind_method(D_METHOD("offset_polygon_2d", "polygon", "delta", "join_type"), &_Geometry::offset_polygon_2d, DEFVAL(JOIN_SQUARE));
-	ClassDB::bind_method(D_METHOD("offset_polyline_2d", "polyline", "delta", "join_type", "end_type"), &_Geometry::offset_polyline_2d, DEFVAL(JOIN_SQUARE), DEFVAL(END_SQUARE));
+	ClassDB::bind_method(D_METHOD("offset_polygon", "polygon", "delta", "join_type"), &_Geometry2D::offset_polygon, DEFVAL(JOIN_SQUARE));
+	ClassDB::bind_method(D_METHOD("offset_polyline", "polyline", "delta", "join_type", "end_type"), &_Geometry2D::offset_polyline, DEFVAL(JOIN_SQUARE), DEFVAL(END_SQUARE));
 
-	ClassDB::bind_method(D_METHOD("make_atlas", "sizes"), &_Geometry::make_atlas);
+	ClassDB::bind_method(D_METHOD("make_atlas", "sizes"), &_Geometry2D::make_atlas);
 
 	BIND_ENUM_CONSTANT(OPERATION_UNION);
 	BIND_ENUM_CONSTANT(OPERATION_DIFFERENCE);
@@ -1179,6 +1068,133 @@ void _Geometry::_bind_methods() {
 	BIND_ENUM_CONSTANT(END_ROUND);
 }
 
+////// _Geometry3D //////
+
+_Geometry3D *_Geometry3D::singleton = nullptr;
+
+_Geometry3D *_Geometry3D::get_singleton() {
+	return singleton;
+}
+
+Vector<Plane> _Geometry3D::build_box_planes(const Vector3 &p_extents) {
+	return Geometry3D::build_box_planes(p_extents);
+}
+
+Vector<Plane> _Geometry3D::build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis) {
+	return Geometry3D::build_cylinder_planes(p_radius, p_height, p_sides, p_axis);
+}
+
+Vector<Plane> _Geometry3D::build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis) {
+	return Geometry3D::build_capsule_planes(p_radius, p_height, p_sides, p_lats, p_axis);
+}
+
+Vector<Vector3> _Geometry3D::get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2) {
+	Vector3 r1, r2;
+	Geometry3D::get_closest_points_between_segments(p1, p2, q1, q2, r1, r2);
+	Vector<Vector3> r;
+	r.resize(2);
+	r.set(0, r1);
+	r.set(1, r2);
+	return r;
+}
+
+Vector3 _Geometry3D::get_closest_point_to_segment(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b) {
+	Vector3 s[2] = { p_a, p_b };
+	return Geometry3D::get_closest_point_to_segment(p_point, s);
+}
+
+Vector3 _Geometry3D::get_closest_point_to_segment_uncapped(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b) {
+	Vector3 s[2] = { p_a, p_b };
+	return Geometry3D::get_closest_point_to_segment_uncapped(p_point, s);
+}
+
+Variant _Geometry3D::ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2) {
+	Vector3 res;
+	if (Geometry3D::ray_intersects_triangle(p_from, p_dir, p_v0, p_v1, p_v2, &res)) {
+		return res;
+	} else {
+		return Variant();
+	}
+}
+
+Variant _Geometry3D::segment_intersects_triangle(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2) {
+	Vector3 res;
+	if (Geometry3D::segment_intersects_triangle(p_from, p_to, p_v0, p_v1, p_v2, &res)) {
+		return res;
+	} else {
+		return Variant();
+	}
+}
+
+Vector<Vector3> _Geometry3D::segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius) {
+	Vector<Vector3> r;
+	Vector3 res, norm;
+	if (!Geometry3D::segment_intersects_sphere(p_from, p_to, p_sphere_pos, p_sphere_radius, &res, &norm)) {
+		return r;
+	}
+
+	r.resize(2);
+	r.set(0, res);
+	r.set(1, norm);
+	return r;
+}
+
+Vector<Vector3> _Geometry3D::segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, float p_height, float p_radius) {
+	Vector<Vector3> r;
+	Vector3 res, norm;
+	if (!Geometry3D::segment_intersects_cylinder(p_from, p_to, p_height, p_radius, &res, &norm)) {
+		return r;
+	}
+
+	r.resize(2);
+	r.set(0, res);
+	r.set(1, norm);
+	return r;
+}
+
+Vector<Vector3> _Geometry3D::segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const Vector<Plane> &p_planes) {
+	Vector<Vector3> r;
+	Vector3 res, norm;
+	if (!Geometry3D::segment_intersects_convex(p_from, p_to, p_planes.ptr(), p_planes.size(), &res, &norm)) {
+		return r;
+	}
+
+	r.resize(2);
+	r.set(0, res);
+	r.set(1, norm);
+	return r;
+}
+
+Vector<Vector3> _Geometry3D::clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane) {
+	return Geometry3D::clip_polygon(p_points, p_plane);
+}
+
+int _Geometry3D::get_uv84_normal_bit(const Vector3 &p_vector) {
+	return Geometry3D::get_uv84_normal_bit(p_vector);
+}
+
+void _Geometry3D::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("build_box_planes", "extents"), &_Geometry3D::build_box_planes);
+	ClassDB::bind_method(D_METHOD("build_cylinder_planes", "radius", "height", "sides", "axis"), &_Geometry3D::build_cylinder_planes, DEFVAL(Vector3::AXIS_Z));
+	ClassDB::bind_method(D_METHOD("build_capsule_planes", "radius", "height", "sides", "lats", "axis"), &_Geometry3D::build_capsule_planes, DEFVAL(Vector3::AXIS_Z));
+
+	ClassDB::bind_method(D_METHOD("get_closest_points_between_segments", "p1", "p2", "q1", "q2"), &_Geometry3D::get_closest_points_between_segments);
+
+	ClassDB::bind_method(D_METHOD("get_closest_point_to_segment", "point", "s1", "s2"), &_Geometry3D::get_closest_point_to_segment);
+
+	ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_uncapped", "point", "s1", "s2"), &_Geometry3D::get_closest_point_to_segment_uncapped);
+
+	ClassDB::bind_method(D_METHOD("get_uv84_normal_bit", "normal"), &_Geometry3D::get_uv84_normal_bit);
+
+	ClassDB::bind_method(D_METHOD("ray_intersects_triangle", "from", "dir", "a", "b", "c"), &_Geometry3D::ray_intersects_triangle);
+	ClassDB::bind_method(D_METHOD("segment_intersects_triangle", "from", "to", "a", "b", "c"), &_Geometry3D::segment_intersects_triangle);
+	ClassDB::bind_method(D_METHOD("segment_intersects_sphere", "from", "to", "sphere_position", "sphere_radius"), &_Geometry3D::segment_intersects_sphere);
+	ClassDB::bind_method(D_METHOD("segment_intersects_cylinder", "from", "to", "height", "radius"), &_Geometry3D::segment_intersects_cylinder);
+	ClassDB::bind_method(D_METHOD("segment_intersects_convex", "from", "to", "planes"), &_Geometry3D::segment_intersects_convex);
+
+	ClassDB::bind_method(D_METHOD("clip_polygon", "points", "plane"), &_Geometry3D::clip_polygon);
+}
+
 ////// _File //////
 
 Error _File::open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key) {

+ 52 - 36
core/bind/core_bind.h

@@ -258,44 +258,31 @@ VARIANT_ENUM_CAST(_OS::Weekday);
 VARIANT_ENUM_CAST(_OS::Month);
 VARIANT_ENUM_CAST(_OS::SystemDir);
 
-class _Geometry : public Object {
-	GDCLASS(_Geometry, Object);
+class _Geometry2D : public Object {
+	GDCLASS(_Geometry2D, Object);
 
-	static _Geometry *singleton;
+	static _Geometry2D *singleton;
 
 protected:
 	static void _bind_methods();
 
 public:
-	static _Geometry *get_singleton();
-	Vector<Plane> build_box_planes(const Vector3 &p_extents);
-	Vector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis = Vector3::AXIS_Z);
-	Vector<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis = Vector3::AXIS_Z);
-	Variant segment_intersects_segment_2d(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b);
-	Variant line_intersects_line_2d(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b);
-	Vector<Vector2> get_closest_points_between_segments_2d(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2);
-	Vector<Vector3> get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2);
-	Vector2 get_closest_point_to_segment_2d(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b);
-	Vector3 get_closest_point_to_segment(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b);
-	Vector2 get_closest_point_to_segment_uncapped_2d(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b);
-	Vector3 get_closest_point_to_segment_uncapped(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b);
-	Variant ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2);
-	Variant segment_intersects_triangle(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2);
+	static _Geometry2D *get_singleton();
+	Variant segment_intersects_segment(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b);
+	Variant line_intersects_line(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b);
+	Vector<Vector2> get_closest_points_between_segments(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2);
+	Vector2 get_closest_point_to_segment(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b);
+	Vector2 get_closest_point_to_segment_uncapped(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b);
 	bool point_is_inside_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) const;
 
-	Vector<Vector3> segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius);
-	Vector<Vector3> segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, float p_height, float p_radius);
-	Vector<Vector3> segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const Vector<Plane> &p_planes);
 	bool is_point_in_circle(const Vector2 &p_point, const Vector2 &p_circle_pos, real_t p_circle_radius);
 	real_t segment_intersects_circle(const Vector2 &p_from, const Vector2 &p_to, const Vector2 &p_circle_pos, real_t p_circle_radius);
-	int get_uv84_normal_bit(const Vector3 &p_vector);
 
 	bool is_polygon_clockwise(const Vector<Vector2> &p_polygon);
 	bool is_point_in_polygon(const Point2 &p_point, const Vector<Vector2> &p_polygon);
 	Vector<int> triangulate_polygon(const Vector<Vector2> &p_polygon);
-	Vector<int> triangulate_delaunay_2d(const Vector<Vector2> &p_points);
-	Vector<Point2> convex_hull_2d(const Vector<Point2> &p_points);
-	Vector<Vector3> clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane);
+	Vector<int> triangulate_delaunay(const Vector<Vector2> &p_points);
+	Vector<Point2> convex_hull(const Vector<Point2> &p_points);
 
 	enum PolyBooleanOperation {
 		OPERATION_UNION,
@@ -304,14 +291,14 @@ public:
 		OPERATION_XOR
 	};
 	// 2D polygon boolean operations.
-	Array merge_polygons_2d(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b); // Union (add).
-	Array clip_polygons_2d(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b); // Difference (subtract).
-	Array intersect_polygons_2d(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b); // Common area (multiply).
-	Array exclude_polygons_2d(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b); // All but common area (xor).
+	Array merge_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b); // Union (add).
+	Array clip_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b); // Difference (subtract).
+	Array intersect_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b); // Common area (multiply).
+	Array exclude_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b); // All but common area (xor).
 
 	// 2D polyline vs polygon operations.
-	Array clip_polyline_with_polygon_2d(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon); // Cut.
-	Array intersect_polyline_with_polygon_2d(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon); // Chop.
+	Array clip_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon); // Cut.
+	Array intersect_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon); // Chop.
 
 	// 2D offset polygons/polylines.
 	enum PolyJoinType {
@@ -326,17 +313,46 @@ public:
 		END_SQUARE,
 		END_ROUND
 	};
-	Array offset_polygon_2d(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type = JOIN_SQUARE);
-	Array offset_polyline_2d(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type = JOIN_SQUARE, PolyEndType p_end_type = END_SQUARE);
+	Array offset_polygon(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type = JOIN_SQUARE);
+	Array offset_polyline(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type = JOIN_SQUARE, PolyEndType p_end_type = END_SQUARE);
 
 	Dictionary make_atlas(const Vector<Size2> &p_rects);
 
-	_Geometry() { singleton = this; }
+	_Geometry2D() { singleton = this; }
 };
 
-VARIANT_ENUM_CAST(_Geometry::PolyBooleanOperation);
-VARIANT_ENUM_CAST(_Geometry::PolyJoinType);
-VARIANT_ENUM_CAST(_Geometry::PolyEndType);
+VARIANT_ENUM_CAST(_Geometry2D::PolyBooleanOperation);
+VARIANT_ENUM_CAST(_Geometry2D::PolyJoinType);
+VARIANT_ENUM_CAST(_Geometry2D::PolyEndType);
+
+class _Geometry3D : public Object {
+	GDCLASS(_Geometry3D, Object);
+
+	static _Geometry3D *singleton;
+
+protected:
+	static void _bind_methods();
+
+public:
+	static _Geometry3D *get_singleton();
+	Vector<Plane> build_box_planes(const Vector3 &p_extents);
+	Vector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis = Vector3::AXIS_Z);
+	Vector<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis = Vector3::AXIS_Z);
+	Vector<Vector3> get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2);
+	Vector3 get_closest_point_to_segment(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b);
+	Vector3 get_closest_point_to_segment_uncapped(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b);
+	Variant ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2);
+	Variant segment_intersects_triangle(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2);
+
+	Vector<Vector3> segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius);
+	Vector<Vector3> segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, float p_height, float p_radius);
+	Vector<Vector3> segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const Vector<Plane> &p_planes);
+	int get_uv84_normal_bit(const Vector3 &p_vector);
+
+	Vector<Vector3> clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane);
+
+	_Geometry3D() { singleton = this; }
+};
 
 class _File : public Reference {
 	GDCLASS(_File, Reference);

+ 2 - 2
core/math/a_star.cpp

@@ -30,7 +30,7 @@
 
 #include "a_star.h"
 
-#include "core/math/geometry.h"
+#include "core/math/geometry_3d.h"
 #include "core/script_language.h"
 #include "scene/scene_string_names.h"
 
@@ -309,7 +309,7 @@ Vector3 AStar::get_closest_position_in_segment(const Vector3 &p_point) const {
 			to_point->pos,
 		};
 
-		Vector3 p = Geometry::get_closest_point_to_segment(p_point, segment);
+		Vector3 p = Geometry3D::get_closest_point_to_segment(p_point, segment);
 		real_t d = p_point.distance_squared_to(p);
 		if (!found || d < closest_dist) {
 			closest_point = p;

+ 3 - 3
core/math/face3.cpp

@@ -30,7 +30,7 @@
 
 #include "face3.h"
 
-#include "core/math/geometry.h"
+#include "core/math/geometry_3d.h"
 
 int Face3::split_by_plane(const Plane &p_plane, Face3 p_res[3], bool p_is_point_over[3]) const {
 	ERR_FAIL_COND_V(is_degenerate(), 0);
@@ -108,11 +108,11 @@ int Face3::split_by_plane(const Plane &p_plane, Face3 p_res[3], bool p_is_point_
 }
 
 bool Face3::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection) const {
-	return Geometry::ray_intersects_triangle(p_from, p_dir, vertex[0], vertex[1], vertex[2], p_intersection);
+	return Geometry3D::ray_intersects_triangle(p_from, p_dir, vertex[0], vertex[1], vertex[2], p_intersection);
 }
 
 bool Face3::intersects_segment(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection) const {
-	return Geometry::segment_intersects_triangle(p_from, p_dir, vertex[0], vertex[1], vertex[2], p_intersection);
+	return Geometry3D::segment_intersects_triangle(p_from, p_dir, vertex[0], vertex[1], vertex[2], p_intersection);
 }
 
 bool Face3::is_degenerate() const {

+ 384 - 0
core/math/geometry_2d.cpp

@@ -0,0 +1,384 @@
+/*************************************************************************/
+/*  geometry.cpp                                                         */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#include "geometry_2d.h"
+
+#include "thirdparty/misc/clipper.hpp"
+#include "thirdparty/misc/triangulator.h"
+#define STB_RECT_PACK_IMPLEMENTATION
+#include "thirdparty/misc/stb_rect_pack.h"
+
+#define SCALE_FACTOR 100000.0 // Based on CMP_EPSILON.
+
+Vector<Vector<Vector2>> Geometry2D::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 (int64_t i = 0; i < tp.GetNumPoints(); i++) {
+			decomp.write[idx].write[i] = tp.GetPoint(i);
+		}
+
+		idx++;
+	}
+
+	return decomp;
+}
+
+struct _AtlasWorkRect {
+	Size2i s;
+	Point2i p;
+	int idx;
+	_FORCE_INLINE_ bool operator<(const _AtlasWorkRect &p_r) const { return s.width > p_r.s.width; };
+};
+
+struct _AtlasWorkRectResult {
+	Vector<_AtlasWorkRect> result;
+	int max_w;
+	int max_h;
+};
+
+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.
+	// 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);
+
+	Vector<_AtlasWorkRect> wrects;
+	wrects.resize(p_rects.size());
+	for (int i = 0; i < p_rects.size(); i++) {
+		wrects.write[i].s = p_rects[i];
+		wrects.write[i].idx = i;
+	}
+	wrects.sort();
+	int widest = wrects[0].s.width;
+
+	Vector<_AtlasWorkRectResult> results;
+
+	for (int i = 0; i <= 12; i++) {
+		int w = 1 << i;
+		int max_h = 0;
+		int max_w = 0;
+		if (w < widest) {
+			continue;
+		}
+
+		Vector<int> hmax;
+		hmax.resize(w);
+		for (int j = 0; j < w; j++) {
+			hmax.write[j] = 0;
+		}
+
+		// Place them.
+		int ofs = 0;
+		int limit_h = 0;
+		for (int j = 0; j < wrects.size(); j++) {
+			if (ofs + wrects[j].s.width > w) {
+				ofs = 0;
+			}
+
+			int from_y = 0;
+			for (int k = 0; k < wrects[j].s.width; k++) {
+				if (hmax[ofs + k] > from_y) {
+					from_y = hmax[ofs + k];
+				}
+			}
+
+			wrects.write[j].p.x = ofs;
+			wrects.write[j].p.y = from_y;
+			int end_h = from_y + wrects[j].s.height;
+			int end_w = ofs + wrects[j].s.width;
+			if (ofs == 0) {
+				limit_h = end_h;
+			}
+
+			for (int k = 0; k < wrects[j].s.width; k++) {
+				hmax.write[ofs + k] = end_h;
+			}
+
+			if (end_h > max_h) {
+				max_h = end_h;
+			}
+
+			if (end_w > max_w) {
+				max_w = end_w;
+			}
+
+			if (ofs == 0 || end_h > limit_h) { // While h limit not reached, keep stacking.
+				ofs += wrects[j].s.width;
+			}
+		}
+
+		_AtlasWorkRectResult result;
+		result.result = wrects;
+		result.max_h = max_h;
+		result.max_w = max_w;
+		results.push_back(result);
+	}
+
+	// Find the result with the best aspect ratio.
+
+	int best = -1;
+	real_t best_aspect = 1e20;
+
+	for (int i = 0; i < results.size(); i++) {
+		real_t h = next_power_of_2(results[i].max_h);
+		real_t w = next_power_of_2(results[i].max_w);
+		real_t aspect = h > w ? h / w : w / h;
+		if (aspect < best_aspect) {
+			best = i;
+			best_aspect = aspect;
+		}
+	}
+
+	r_result.resize(p_rects.size());
+
+	for (int i = 0; i < p_rects.size(); i++) {
+		r_result.write[results[best].result[i].idx] = results[best].result[i].p;
+	}
+
+	r_size = Size2(results[best].max_w, results[best].max_h);
+}
+
+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;
+
+	ClipType op = ctUnion;
+
+	switch (p_op) {
+		case OPERATION_UNION:
+			op = ctUnion;
+			break;
+		case OPERATION_DIFFERENCE:
+			op = ctDifference;
+			break;
+		case OPERATION_INTERSECTION:
+			op = ctIntersection;
+			break;
+		case OPERATION_XOR:
+			op = ctXor;
+			break;
+	}
+	Path path_a, path_b;
+
+	// Need to scale points (Clipper's requirement for robust computation).
+	for (int i = 0; i != p_polypath_a.size(); ++i) {
+		path_a << IntPoint(p_polypath_a[i].x * SCALE_FACTOR, p_polypath_a[i].y * SCALE_FACTOR);
+	}
+	for (int i = 0; i != p_polypath_b.size(); ++i) {
+		path_b << IntPoint(p_polypath_b[i].x * SCALE_FACTOR, p_polypath_b[i].y * SCALE_FACTOR);
+	}
+	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;
+
+	if (is_a_open) {
+		PolyTree tree; // Needed to populate polylines.
+		clp.Execute(op, tree);
+		OpenPathsFromPolyTree(tree, paths);
+	} else {
+		clp.Execute(op, paths); // Works on closed polygons only.
+	}
+	// Have to scale points down now.
+	Vector<Vector<Point2>> polypaths;
+
+	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) / SCALE_FACTOR,
+					static_cast<real_t>(scaled_path[j].Y) / SCALE_FACTOR));
+		}
+		polypaths.push_back(polypath);
+	}
+	return polypaths;
+}
+
+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;
+
+	JoinType jt = jtSquare;
+
+	switch (p_join_type) {
+		case JOIN_SQUARE:
+			jt = jtSquare;
+			break;
+		case JOIN_ROUND:
+			jt = jtRound;
+			break;
+		case JOIN_MITER:
+			jt = jtMiter;
+			break;
+	}
+
+	EndType et = etClosedPolygon;
+
+	switch (p_end_type) {
+		case END_POLYGON:
+			et = etClosedPolygon;
+			break;
+		case END_JOINED:
+			et = etClosedLine;
+			break;
+		case END_BUTT:
+			et = etOpenButt;
+			break;
+		case END_SQUARE:
+			et = etOpenSquare;
+			break;
+		case END_ROUND:
+			et = etOpenRound;
+			break;
+	}
+	ClipperOffset co(2.0, 0.25 * SCALE_FACTOR); // Defaults from ClipperOffset.
+	Path path;
+
+	// Need to scale points (Clipper's requirement for robust computation).
+	for (int i = 0; i != p_polypath.size(); ++i) {
+		path << IntPoint(p_polypath[i].x * SCALE_FACTOR, p_polypath[i].y * SCALE_FACTOR);
+	}
+	co.AddPath(path, jt, et);
+
+	Paths paths;
+	co.Execute(paths, p_delta * SCALE_FACTOR); // Inflate/deflate.
+
+	// Have to scale points down now.
+	Vector<Vector<Point2>> polypaths;
+
+	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) / SCALE_FACTOR,
+					static_cast<real_t>(scaled_path[j].Y) / SCALE_FACTOR));
+		}
+		polypaths.push_back(polypath);
+	}
+	return polypaths;
+}
+
+Vector<Point2i> Geometry2D::pack_rects(const Vector<Size2i> &p_sizes, const Size2i &p_atlas_size) {
+	Vector<stbrp_node> nodes;
+	nodes.resize(p_atlas_size.width);
+
+	stbrp_context context;
+	stbrp_init_target(&context, p_atlas_size.width, p_atlas_size.height, nodes.ptrw(), p_atlas_size.width);
+
+	Vector<stbrp_rect> rects;
+	rects.resize(p_sizes.size());
+
+	for (int i = 0; i < p_sizes.size(); i++) {
+		rects.write[i].id = 0;
+		rects.write[i].w = p_sizes[i].width;
+		rects.write[i].h = p_sizes[i].height;
+		rects.write[i].x = 0;
+		rects.write[i].y = 0;
+		rects.write[i].was_packed = 0;
+	}
+
+	int res = stbrp_pack_rects(&context, rects.ptrw(), rects.size());
+	if (res == 0) { //pack failed
+		return Vector<Point2i>();
+	}
+
+	Vector<Point2i> ret;
+	ret.resize(p_sizes.size());
+
+	for (int i = 0; i < p_sizes.size(); i++) {
+		Point2i r(rects[i].x, rects[i].y);
+		ret.write[i] = r;
+	}
+
+	return ret;
+}
+
+Vector<Vector3i> Geometry2D::partial_pack_rects(const Vector<Vector2i> &p_sizes, const Size2i &p_atlas_size) {
+	Vector<stbrp_node> nodes;
+	nodes.resize(p_atlas_size.width);
+	zeromem(nodes.ptrw(), sizeof(stbrp_node) * nodes.size());
+
+	stbrp_context context;
+	stbrp_init_target(&context, p_atlas_size.width, p_atlas_size.height, nodes.ptrw(), p_atlas_size.width);
+
+	Vector<stbrp_rect> rects;
+	rects.resize(p_sizes.size());
+
+	for (int i = 0; i < p_sizes.size(); i++) {
+		rects.write[i].id = i;
+		rects.write[i].w = p_sizes[i].width;
+		rects.write[i].h = p_sizes[i].height;
+		rects.write[i].x = 0;
+		rects.write[i].y = 0;
+		rects.write[i].was_packed = 0;
+	}
+
+	stbrp_pack_rects(&context, rects.ptrw(), rects.size());
+
+	Vector<Vector3i> ret;
+	ret.resize(p_sizes.size());
+
+	for (int i = 0; i < p_sizes.size(); i++) {
+		ret.write[rects[i].id] = Vector3i(rects[i].x, rects[i].y, rects[i].was_packed != 0 ? 1 : 0);
+	}
+
+	return ret;
+}

+ 398 - 0
core/math/geometry_2d.h

@@ -0,0 +1,398 @@
+/*************************************************************************/
+/*  geometry_2d.h                                                        */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef GEOMETRY_2D_H
+#define GEOMETRY_2D_H
+
+#include "core/math/delaunay_2d.h"
+#include "core/math/rect2.h"
+#include "core/math/triangulate.h"
+#include "core/object.h"
+#include "core/vector.h"
+
+class Geometry2D {
+	Geometry2D();
+
+public:
+	static real_t get_closest_points_between_segments(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2, Vector2 &c1, Vector2 &c2) {
+		Vector2 d1 = q1 - p1; // Direction vector of segment S1.
+		Vector2 d2 = q2 - p2; // Direction vector of segment S2.
+		Vector2 r = p1 - p2;
+		real_t a = d1.dot(d1); // Squared length of segment S1, always nonnegative.
+		real_t e = d2.dot(d2); // Squared length of segment S2, always nonnegative.
+		real_t f = d2.dot(r);
+		real_t s, t;
+		// Check if either or both segments degenerate into points.
+		if (a <= CMP_EPSILON && e <= CMP_EPSILON) {
+			// Both segments degenerate into points.
+			c1 = p1;
+			c2 = p2;
+			return Math::sqrt((c1 - c2).dot(c1 - c2));
+		}
+		if (a <= CMP_EPSILON) {
+			// First segment degenerates into a point.
+			s = 0.0;
+			t = f / e; // s = 0 => t = (b*s + f) / e = f / e
+			t = CLAMP(t, 0.0, 1.0);
+		} else {
+			real_t c = d1.dot(r);
+			if (e <= CMP_EPSILON) {
+				// Second segment degenerates into a point.
+				t = 0.0;
+				s = CLAMP(-c / a, 0.0, 1.0); // t = 0 => s = (b*t - c) / a = -c / a
+			} else {
+				// The general nondegenerate case starts here.
+				real_t b = d1.dot(d2);
+				real_t denom = a * e - b * b; // Always nonnegative.
+				// If segments not parallel, compute closest point on L1 to L2 and
+				// clamp to segment S1. Else pick arbitrary s (here 0).
+				if (denom != 0.0) {
+					s = CLAMP((b * f - c * e) / denom, 0.0, 1.0);
+				} else {
+					s = 0.0;
+				}
+				// Compute point on L2 closest to S1(s) using
+				// t = Dot((P1 + D1*s) - P2,D2) / Dot(D2,D2) = (b*s + f) / e
+				t = (b * s + f) / e;
+
+				//If t in [0,1] done. Else clamp t, recompute s for the new value
+				// of t using s = Dot((P2 + D2*t) - P1,D1) / Dot(D1,D1)= (t*b - c) / a
+				// and clamp s to [0, 1].
+				if (t < 0.0) {
+					t = 0.0;
+					s = CLAMP(-c / a, 0.0, 1.0);
+				} else if (t > 1.0) {
+					t = 1.0;
+					s = CLAMP((b - c) / a, 0.0, 1.0);
+				}
+			}
+		}
+		c1 = p1 + d1 * s;
+		c2 = p2 + d2 * t;
+		return Math::sqrt((c1 - c2).dot(c1 - c2));
+	}
+
+	static Vector2 get_closest_point_to_segment(const Vector2 &p_point, const Vector2 *p_segment) {
+		Vector2 p = p_point - p_segment[0];
+		Vector2 n = p_segment[1] - p_segment[0];
+		real_t l2 = n.length_squared();
+		if (l2 < 1e-20) {
+			return p_segment[0]; // Both points are the same, just give any.
+		}
+
+		real_t d = n.dot(p) / l2;
+
+		if (d <= 0.0) {
+			return p_segment[0]; // Before first point.
+		} else if (d >= 1.0) {
+			return p_segment[1]; // After first point.
+		} else {
+			return p_segment[0] + n * d; // Inside.
+		}
+	}
+
+	static bool is_point_in_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) {
+		Vector2 an = a - s;
+		Vector2 bn = b - s;
+		Vector2 cn = c - s;
+
+		bool orientation = an.cross(bn) > 0;
+
+		if ((bn.cross(cn) > 0) != orientation) {
+			return false;
+		}
+
+		return (cn.cross(an) > 0) == orientation;
+	}
+
+	static Vector2 get_closest_point_to_segment_uncapped(const Vector2 &p_point, const Vector2 *p_segment) {
+		Vector2 p = p_point - p_segment[0];
+		Vector2 n = p_segment[1] - p_segment[0];
+		real_t l2 = n.length_squared();
+		if (l2 < 1e-20) {
+			return p_segment[0]; // Both points are the same, just give any.
+		}
+
+		real_t d = n.dot(p) / l2;
+
+		return p_segment[0] + n * d; // Inside.
+	}
+
+	static bool line_intersects_line(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b, Vector2 &r_result) {
+		// See http://paulbourke.net/geometry/pointlineplane/
+
+		const real_t denom = p_dir_b.y * p_dir_a.x - p_dir_b.x * p_dir_a.y;
+		if (Math::is_zero_approx(denom)) { // Parallel?
+			return false;
+		}
+
+		const Vector2 v = p_from_a - p_from_b;
+		const real_t t = (p_dir_b.x * v.y - p_dir_b.y * v.x) / denom;
+		r_result = p_from_a + t * p_dir_a;
+		return true;
+	}
+
+	static bool segment_intersects_segment(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b, Vector2 *r_result) {
+		Vector2 B = p_to_a - p_from_a;
+		Vector2 C = p_from_b - p_from_a;
+		Vector2 D = p_to_b - p_from_a;
+
+		real_t ABlen = B.dot(B);
+		if (ABlen <= 0) {
+			return false;
+		}
+		Vector2 Bn = B / ABlen;
+		C = Vector2(C.x * Bn.x + C.y * Bn.y, C.y * Bn.x - C.x * Bn.y);
+		D = Vector2(D.x * Bn.x + D.y * Bn.y, D.y * Bn.x - D.x * Bn.y);
+
+		if ((C.y < 0 && D.y < 0) || (C.y >= 0 && D.y >= 0)) {
+			return false;
+		}
+
+		real_t ABpos = D.x + (C.x - D.x) * D.y / (D.y - C.y);
+
+		// Fail if segment C-D crosses line A-B outside of segment A-B.
+		if (ABpos < 0 || ABpos > 1.0) {
+			return false;
+		}
+
+		// (4) Apply the discovered position to line A-B in the original coordinate system.
+		if (r_result) {
+			*r_result = p_from_a + B * ABpos;
+		}
+
+		return true;
+	}
+
+	static inline bool is_point_in_circle(const Vector2 &p_point, const Vector2 &p_circle_pos, real_t p_circle_radius) {
+		return p_point.distance_squared_to(p_circle_pos) <= p_circle_radius * p_circle_radius;
+	}
+
+	static real_t segment_intersects_circle(const Vector2 &p_from, const Vector2 &p_to, const Vector2 &p_circle_pos, real_t p_circle_radius) {
+		Vector2 line_vec = p_to - p_from;
+		Vector2 vec_to_line = p_from - p_circle_pos;
+
+		// Create a quadratic formula of the form ax^2 + bx + c = 0
+		real_t a, b, c;
+
+		a = line_vec.dot(line_vec);
+		b = 2 * vec_to_line.dot(line_vec);
+		c = vec_to_line.dot(vec_to_line) - p_circle_radius * p_circle_radius;
+
+		// Solve for t.
+		real_t sqrtterm = b * b - 4 * a * c;
+
+		// If the term we intend to square root is less than 0 then the answer won't be real,
+		// so it definitely won't be t in the range 0 to 1.
+		if (sqrtterm < 0) {
+			return -1;
+		}
+
+		// If we can assume that the line segment starts outside the circle (e.g. for continuous time collision detection)
+		// then the following can be skipped and we can just return the equivalent of res1.
+		sqrtterm = Math::sqrt(sqrtterm);
+		real_t res1 = (-b - sqrtterm) / (2 * a);
+		real_t res2 = (-b + sqrtterm) / (2 * a);
+
+		if (res1 >= 0 && res1 <= 1) {
+			return res1;
+		}
+		if (res2 >= 0 && res2 <= 1) {
+			return res2;
+		}
+		return -1;
+	}
+
+	enum PolyBooleanOperation {
+		OPERATION_UNION,
+		OPERATION_DIFFERENCE,
+		OPERATION_INTERSECTION,
+		OPERATION_XOR
+	};
+	enum PolyJoinType {
+		JOIN_SQUARE,
+		JOIN_ROUND,
+		JOIN_MITER
+	};
+	enum PolyEndType {
+		END_POLYGON,
+		END_JOINED,
+		END_BUTT,
+		END_SQUARE,
+		END_ROUND
+	};
+
+	static Vector<Vector<Point2>> merge_polygons(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) {
+		return _polypaths_do_operation(OPERATION_UNION, p_polygon_a, p_polygon_b);
+	}
+
+	static Vector<Vector<Point2>> clip_polygons(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) {
+		return _polypaths_do_operation(OPERATION_DIFFERENCE, p_polygon_a, p_polygon_b);
+	}
+
+	static Vector<Vector<Point2>> intersect_polygons(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) {
+		return _polypaths_do_operation(OPERATION_INTERSECTION, p_polygon_a, p_polygon_b);
+	}
+
+	static Vector<Vector<Point2>> exclude_polygons(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) {
+		return _polypaths_do_operation(OPERATION_XOR, p_polygon_a, p_polygon_b);
+	}
+
+	static Vector<Vector<Point2>> clip_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) {
+		return _polypaths_do_operation(OPERATION_DIFFERENCE, p_polyline, p_polygon, true);
+	}
+
+	static Vector<Vector<Point2>> intersect_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) {
+		return _polypaths_do_operation(OPERATION_INTERSECTION, p_polyline, p_polygon, true);
+	}
+
+	static Vector<Vector<Point2>> offset_polygon(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type) {
+		return _polypath_offset(p_polygon, p_delta, p_join_type, END_POLYGON);
+	}
+
+	static Vector<Vector<Point2>> offset_polyline(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) {
+		ERR_FAIL_COND_V_MSG(p_end_type == END_POLYGON, Vector<Vector<Point2>>(), "Attempt to offset a polyline like a polygon (use offset_polygon instead).");
+
+		return _polypath_offset(p_polygon, p_delta, p_join_type, p_end_type);
+	}
+
+	static Vector<int> triangulate_delaunay(const Vector<Vector2> &p_points) {
+		Vector<Delaunay2D::Triangle> tr = Delaunay2D::triangulate(p_points);
+		Vector<int> triangles;
+
+		for (int i = 0; i < tr.size(); i++) {
+			triangles.push_back(tr[i].points[0]);
+			triangles.push_back(tr[i].points[1]);
+			triangles.push_back(tr[i].points[2]);
+		}
+		return triangles;
+	}
+
+	static Vector<int> triangulate_polygon(const Vector<Vector2> &p_polygon) {
+		Vector<int> triangles;
+		if (!Triangulate::triangulate(p_polygon, triangles)) {
+			return Vector<int>(); //fail
+		}
+		return triangles;
+	}
+
+	static bool is_polygon_clockwise(const Vector<Vector2> &p_polygon) {
+		int c = p_polygon.size();
+		if (c < 3) {
+			return false;
+		}
+		const Vector2 *p = p_polygon.ptr();
+		real_t sum = 0;
+		for (int i = 0; i < c; i++) {
+			const Vector2 &v1 = p[i];
+			const Vector2 &v2 = p[(i + 1) % c];
+			sum += (v2.x - v1.x) * (v2.y + v1.y);
+		}
+
+		return sum > 0.0f;
+	}
+
+	// Alternate implementation that should be faster.
+	static bool is_point_in_polygon(const Vector2 &p_point, const Vector<Vector2> &p_polygon) {
+		int c = p_polygon.size();
+		if (c < 3) {
+			return false;
+		}
+		const Vector2 *p = p_polygon.ptr();
+		Vector2 further_away(-1e20, -1e20);
+		Vector2 further_away_opposite(1e20, 1e20);
+
+		for (int i = 0; i < c; i++) {
+			further_away.x = MAX(p[i].x, further_away.x);
+			further_away.y = MAX(p[i].y, further_away.y);
+			further_away_opposite.x = MIN(p[i].x, further_away_opposite.x);
+			further_away_opposite.y = MIN(p[i].y, further_away_opposite.y);
+		}
+
+		// Make point outside that won't intersect with points in segment from p_point.
+		further_away += (further_away - further_away_opposite) * Vector2(1.221313, 1.512312);
+
+		int intersections = 0;
+		for (int i = 0; i < c; i++) {
+			const Vector2 &v1 = p[i];
+			const Vector2 &v2 = p[(i + 1) % c];
+			if (segment_intersects_segment(v1, v2, p_point, further_away, nullptr)) {
+				intersections++;
+			}
+		}
+
+		return (intersections & 1);
+	}
+
+	static real_t vec2_cross(const Point2 &O, const Point2 &A, const Point2 &B) {
+		return (real_t)(A.x - O.x) * (B.y - O.y) - (real_t)(A.y - O.y) * (B.x - O.x);
+	}
+
+	// Returns a list of points on the convex hull in counter-clockwise order.
+	// Note: the last point in the returned list is the same as the first one.
+	static Vector<Point2> convex_hull(Vector<Point2> P) {
+		int n = P.size(), k = 0;
+		Vector<Point2> H;
+		H.resize(2 * n);
+
+		// Sort points lexicographically.
+		P.sort();
+
+		// Build lower hull.
+		for (int i = 0; i < n; ++i) {
+			while (k >= 2 && vec2_cross(H[k - 2], H[k - 1], P[i]) <= 0) {
+				k--;
+			}
+			H.write[k++] = P[i];
+		}
+
+		// Build upper hull.
+		for (int i = n - 2, t = k + 1; i >= 0; i--) {
+			while (k >= t && vec2_cross(H[k - 2], H[k - 1], P[i]) <= 0) {
+				k--;
+			}
+			H.write[k++] = P[i];
+		}
+
+		H.resize(k);
+		return H;
+	}
+	static Vector<Vector<Vector2>> decompose_polygon_in_convex(Vector<Point2> polygon);
+
+	static void make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_result, Size2i &r_size);
+	static Vector<Point2i> pack_rects(const Vector<Size2i> &p_sizes, const Size2i &p_atlas_size);
+	static Vector<Vector3i> partial_pack_rects(const Vector<Vector2i> &p_sizes, const Size2i &p_atlas_size);
+
+private:
+	static Vector<Vector<Point2>> _polypaths_do_operation(PolyBooleanOperation p_op, const Vector<Point2> &p_polypath_a, const Vector<Point2> &p_polypath_b, bool is_a_open = false);
+	static Vector<Vector<Point2>> _polypath_offset(const Vector<Point2> &p_polypath, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type);
+};
+
+#endif // GEOMETRY_2D_H

+ 12 - 376
core/math/geometry.cpp → core/math/geometry_3d.cpp

@@ -28,32 +28,14 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#include "geometry.h"
+#include "geometry_3d.h"
 
 #include "core/print_string.h"
 
 #include "thirdparty/misc/clipper.hpp"
 #include "thirdparty/misc/triangulator.h"
-#define STB_RECT_PACK_IMPLEMENTATION
-#include "thirdparty/misc/stb_rect_pack.h"
-
-#define SCALE_FACTOR 100000.0 // Based on CMP_EPSILON.
-
-// 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) {
-	Vector<int> indices = Geometry::triangulate_polygon(p_polygon);
-	for (int j = 0; j + 3 <= indices.size(); j += 3) {
-		int i1 = indices[j], i2 = indices[j + 1], i3 = indices[j + 2];
-		if (Geometry::is_point_in_triangle(p_point, p_polygon[i1], p_polygon[i2], p_polygon[i3])) {
-			return true;
-		}
-	}
-	return false;
-}
-*/
 
-void Geometry::MeshData::optimize_vertices() {
+void Geometry3D::MeshData::optimize_vertices() {
 	Map<int, int> vtx_remap;
 
 	for (int i = 0; i < faces.size(); i++) {
@@ -200,7 +182,7 @@ static bool _group_face(_FaceClassify *p_faces, int len, int p_index, int p_grou
 	return true;
 }
 
-Vector<Vector<Face3>> Geometry::separate_objects(Vector<Face3> p_array) {
+Vector<Vector<Face3>> Geometry3D::separate_objects(Vector<Face3> p_array) {
 	Vector<Vector<Face3>> objects;
 
 	int len = p_array.size();
@@ -510,7 +492,7 @@ static inline void _build_faces(uint8_t ***p_cell_status, int x, int y, int z, i
 	}
 }
 
-Vector<Face3> Geometry::wrap_geometry(Vector<Face3> p_array, real_t *p_error) {
+Vector<Face3> Geometry3D::wrap_geometry(Vector<Face3> p_array, real_t *p_error) {
 #define _MIN_SIZE 1.0
 #define _MAX_LENGTH 20
 
@@ -646,41 +628,7 @@ Vector<Face3> Geometry::wrap_geometry(Vector<Face3> p_array, real_t *p_error) {
 	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 (int64_t i = 0; i < tp.GetNumPoints(); i++) {
-			decomp.write[idx].write[i] = tp.GetPoint(i);
-		}
-
-		idx++;
-	}
-
-	return decomp;
-}
-
-Geometry::MeshData Geometry::build_convex_mesh(const Vector<Plane> &p_planes) {
+Geometry3D::MeshData Geometry3D::build_convex_mesh(const Vector<Plane> &p_planes) {
 	MeshData mesh;
 
 #define SUBPLANE_SIZE 1024.0
@@ -815,7 +763,7 @@ Geometry::MeshData Geometry::build_convex_mesh(const Vector<Plane> &p_planes) {
 	return mesh;
 }
 
-Vector<Plane> Geometry::build_box_planes(const Vector3 &p_extents) {
+Vector<Plane> Geometry3D::build_box_planes(const Vector3 &p_extents) {
 	Vector<Plane> planes;
 
 	planes.push_back(Plane(Vector3(1, 0, 0), p_extents.x));
@@ -828,7 +776,7 @@ Vector<Plane> Geometry::build_box_planes(const Vector3 &p_extents) {
 	return planes;
 }
 
-Vector<Plane> Geometry::build_cylinder_planes(real_t p_radius, real_t p_height, int p_sides, Vector3::Axis p_axis) {
+Vector<Plane> Geometry3D::build_cylinder_planes(real_t p_radius, real_t p_height, int p_sides, Vector3::Axis p_axis) {
 	Vector<Plane> planes;
 
 	for (int i = 0; i < p_sides; i++) {
@@ -848,7 +796,7 @@ Vector<Plane> Geometry::build_cylinder_planes(real_t p_radius, real_t p_height,
 	return planes;
 }
 
-Vector<Plane> Geometry::build_sphere_planes(real_t p_radius, int p_lats, int p_lons, Vector3::Axis p_axis) {
+Vector<Plane> Geometry3D::build_sphere_planes(real_t p_radius, int p_lats, int p_lons, Vector3::Axis p_axis) {
 	Vector<Plane> planes;
 
 	Vector3 axis;
@@ -878,7 +826,7 @@ Vector<Plane> Geometry::build_sphere_planes(real_t p_radius, int p_lats, int p_l
 	return planes;
 }
 
-Vector<Plane> Geometry::build_capsule_planes(real_t p_radius, real_t p_height, int p_sides, int p_lats, Vector3::Axis p_axis) {
+Vector<Plane> Geometry3D::build_capsule_planes(real_t p_radius, real_t p_height, int p_sides, int p_lats, Vector3::Axis p_axis) {
 	Vector<Plane> planes;
 
 	Vector3 axis;
@@ -907,252 +855,7 @@ Vector<Plane> Geometry::build_capsule_planes(real_t p_radius, real_t p_height, i
 	return planes;
 }
 
-struct _AtlasWorkRect {
-	Size2i s;
-	Point2i p;
-	int idx;
-	_FORCE_INLINE_ bool operator<(const _AtlasWorkRect &p_r) const { return s.width > p_r.s.width; };
-};
-
-struct _AtlasWorkRectResult {
-	Vector<_AtlasWorkRect> result;
-	int max_w;
-	int max_h;
-};
-
-void Geometry::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.
-	// 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);
-
-	Vector<_AtlasWorkRect> wrects;
-	wrects.resize(p_rects.size());
-	for (int i = 0; i < p_rects.size(); i++) {
-		wrects.write[i].s = p_rects[i];
-		wrects.write[i].idx = i;
-	}
-	wrects.sort();
-	int widest = wrects[0].s.width;
-
-	Vector<_AtlasWorkRectResult> results;
-
-	for (int i = 0; i <= 12; i++) {
-		int w = 1 << i;
-		int max_h = 0;
-		int max_w = 0;
-		if (w < widest) {
-			continue;
-		}
-
-		Vector<int> hmax;
-		hmax.resize(w);
-		for (int j = 0; j < w; j++) {
-			hmax.write[j] = 0;
-		}
-
-		// Place them.
-		int ofs = 0;
-		int limit_h = 0;
-		for (int j = 0; j < wrects.size(); j++) {
-			if (ofs + wrects[j].s.width > w) {
-				ofs = 0;
-			}
-
-			int from_y = 0;
-			for (int k = 0; k < wrects[j].s.width; k++) {
-				if (hmax[ofs + k] > from_y) {
-					from_y = hmax[ofs + k];
-				}
-			}
-
-			wrects.write[j].p.x = ofs;
-			wrects.write[j].p.y = from_y;
-			int end_h = from_y + wrects[j].s.height;
-			int end_w = ofs + wrects[j].s.width;
-			if (ofs == 0) {
-				limit_h = end_h;
-			}
-
-			for (int k = 0; k < wrects[j].s.width; k++) {
-				hmax.write[ofs + k] = end_h;
-			}
-
-			if (end_h > max_h) {
-				max_h = end_h;
-			}
-
-			if (end_w > max_w) {
-				max_w = end_w;
-			}
-
-			if (ofs == 0 || end_h > limit_h) { // While h limit not reached, keep stacking.
-				ofs += wrects[j].s.width;
-			}
-		}
-
-		_AtlasWorkRectResult result;
-		result.result = wrects;
-		result.max_h = max_h;
-		result.max_w = max_w;
-		results.push_back(result);
-	}
-
-	// Find the result with the best aspect ratio.
-
-	int best = -1;
-	real_t best_aspect = 1e20;
-
-	for (int i = 0; i < results.size(); i++) {
-		real_t h = next_power_of_2(results[i].max_h);
-		real_t w = next_power_of_2(results[i].max_w);
-		real_t aspect = h > w ? h / w : w / h;
-		if (aspect < best_aspect) {
-			best = i;
-			best_aspect = aspect;
-		}
-	}
-
-	r_result.resize(p_rects.size());
-
-	for (int i = 0; i < p_rects.size(); i++) {
-		r_result.write[results[best].result[i].idx] = results[best].result[i].p;
-	}
-
-	r_size = Size2(results[best].max_w, results[best].max_h);
-}
-
-Vector<Vector<Point2>> Geometry::_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;
-
-	ClipType op = ctUnion;
-
-	switch (p_op) {
-		case OPERATION_UNION:
-			op = ctUnion;
-			break;
-		case OPERATION_DIFFERENCE:
-			op = ctDifference;
-			break;
-		case OPERATION_INTERSECTION:
-			op = ctIntersection;
-			break;
-		case OPERATION_XOR:
-			op = ctXor;
-			break;
-	}
-	Path path_a, path_b;
-
-	// Need to scale points (Clipper's requirement for robust computation).
-	for (int i = 0; i != p_polypath_a.size(); ++i) {
-		path_a << IntPoint(p_polypath_a[i].x * SCALE_FACTOR, p_polypath_a[i].y * SCALE_FACTOR);
-	}
-	for (int i = 0; i != p_polypath_b.size(); ++i) {
-		path_b << IntPoint(p_polypath_b[i].x * SCALE_FACTOR, p_polypath_b[i].y * SCALE_FACTOR);
-	}
-	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;
-
-	if (is_a_open) {
-		PolyTree tree; // Needed to populate polylines.
-		clp.Execute(op, tree);
-		OpenPathsFromPolyTree(tree, paths);
-	} else {
-		clp.Execute(op, paths); // Works on closed polygons only.
-	}
-	// Have to scale points down now.
-	Vector<Vector<Point2>> polypaths;
-
-	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) / SCALE_FACTOR,
-					static_cast<real_t>(scaled_path[j].Y) / SCALE_FACTOR));
-		}
-		polypaths.push_back(polypath);
-	}
-	return polypaths;
-}
-
-Vector<Vector<Point2>> Geometry::_polypath_offset(const Vector<Point2> &p_polypath, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) {
-	using namespace ClipperLib;
-
-	JoinType jt = jtSquare;
-
-	switch (p_join_type) {
-		case JOIN_SQUARE:
-			jt = jtSquare;
-			break;
-		case JOIN_ROUND:
-			jt = jtRound;
-			break;
-		case JOIN_MITER:
-			jt = jtMiter;
-			break;
-	}
-
-	EndType et = etClosedPolygon;
-
-	switch (p_end_type) {
-		case END_POLYGON:
-			et = etClosedPolygon;
-			break;
-		case END_JOINED:
-			et = etClosedLine;
-			break;
-		case END_BUTT:
-			et = etOpenButt;
-			break;
-		case END_SQUARE:
-			et = etOpenSquare;
-			break;
-		case END_ROUND:
-			et = etOpenRound;
-			break;
-	}
-	ClipperOffset co(2.0, 0.25 * SCALE_FACTOR); // Defaults from ClipperOffset.
-	Path path;
-
-	// Need to scale points (Clipper's requirement for robust computation).
-	for (int i = 0; i != p_polypath.size(); ++i) {
-		path << IntPoint(p_polypath[i].x * SCALE_FACTOR, p_polypath[i].y * SCALE_FACTOR);
-	}
-	co.AddPath(path, jt, et);
-
-	Paths paths;
-	co.Execute(paths, p_delta * SCALE_FACTOR); // Inflate/deflate.
-
-	// Have to scale points down now.
-	Vector<Vector<Point2>> polypaths;
-
-	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) / SCALE_FACTOR,
-					static_cast<real_t>(scaled_path[j].Y) / SCALE_FACTOR));
-		}
-		polypaths.push_back(polypath);
-	}
-	return polypaths;
-}
-
-Vector<Vector3> Geometry::compute_convex_mesh_points(const Plane *p_planes, int p_plane_count) {
+Vector<Vector3> Geometry3D::compute_convex_mesh_points(const Plane *p_planes, int p_plane_count) {
 	Vector<Vector3> points;
 
 	// Iterate through every unique combination of any three planes.
@@ -1188,73 +891,6 @@ Vector<Vector3> Geometry::compute_convex_mesh_points(const Plane *p_planes, int
 	return points;
 }
 
-Vector<Point2i> Geometry::pack_rects(const Vector<Size2i> &p_sizes, const Size2i &p_atlas_size) {
-	Vector<stbrp_node> nodes;
-	nodes.resize(p_atlas_size.width);
-
-	stbrp_context context;
-	stbrp_init_target(&context, p_atlas_size.width, p_atlas_size.height, nodes.ptrw(), p_atlas_size.width);
-
-	Vector<stbrp_rect> rects;
-	rects.resize(p_sizes.size());
-
-	for (int i = 0; i < p_sizes.size(); i++) {
-		rects.write[i].id = 0;
-		rects.write[i].w = p_sizes[i].width;
-		rects.write[i].h = p_sizes[i].height;
-		rects.write[i].x = 0;
-		rects.write[i].y = 0;
-		rects.write[i].was_packed = 0;
-	}
-
-	int res = stbrp_pack_rects(&context, rects.ptrw(), rects.size());
-	if (res == 0) { //pack failed
-		return Vector<Point2i>();
-	}
-
-	Vector<Point2i> ret;
-	ret.resize(p_sizes.size());
-
-	for (int i = 0; i < p_sizes.size(); i++) {
-		Point2i r(rects[i].x, rects[i].y);
-		ret.write[i] = r;
-	}
-
-	return ret;
-}
-
-Vector<Vector3i> Geometry::partial_pack_rects(const Vector<Vector2i> &p_sizes, const Size2i &p_atlas_size) {
-	Vector<stbrp_node> nodes;
-	nodes.resize(p_atlas_size.width);
-	zeromem(nodes.ptrw(), sizeof(stbrp_node) * nodes.size());
-
-	stbrp_context context;
-	stbrp_init_target(&context, p_atlas_size.width, p_atlas_size.height, nodes.ptrw(), p_atlas_size.width);
-
-	Vector<stbrp_rect> rects;
-	rects.resize(p_sizes.size());
-
-	for (int i = 0; i < p_sizes.size(); i++) {
-		rects.write[i].id = i;
-		rects.write[i].w = p_sizes[i].width;
-		rects.write[i].h = p_sizes[i].height;
-		rects.write[i].x = 0;
-		rects.write[i].y = 0;
-		rects.write[i].was_packed = 0;
-	}
-
-	stbrp_pack_rects(&context, rects.ptrw(), rects.size());
-
-	Vector<Vector3i> ret;
-	ret.resize(p_sizes.size());
-
-	for (int i = 0; i < p_sizes.size(); i++) {
-		ret.write[rects[i].id] = Vector3i(rects[i].x, rects[i].y, rects[i].was_packed != 0 ? 1 : 0);
-	}
-
-	return ret;
-}
-
 #define square(m_s) ((m_s) * (m_s))
 #define INF 1e20
 
@@ -1296,7 +932,7 @@ static void edt(float *f, int stride, int n) {
 
 #undef square
 
-Vector<uint32_t> Geometry::generate_edf(const Vector<bool> &p_voxels, const Vector3i &p_size, bool p_negative) {
+Vector<uint32_t> Geometry3D::generate_edf(const Vector<bool> &p_voxels, const Vector3i &p_size, bool p_negative) {
 	uint32_t float_count = p_size.x * p_size.y * p_size.z;
 
 	ERR_FAIL_COND_V((uint32_t)p_voxels.size() != float_count, Vector<uint32_t>());
@@ -1360,7 +996,7 @@ Vector<uint32_t> Geometry::generate_edf(const Vector<bool> &p_voxels, const Vect
 	return ret;
 }
 
-Vector<int8_t> Geometry::generate_sdf8(const Vector<uint32_t> &p_positive, const Vector<uint32_t> &p_negative) {
+Vector<int8_t> Geometry3D::generate_sdf8(const Vector<uint32_t> &p_positive, const Vector<uint32_t> &p_negative) {
 	ERR_FAIL_COND_V(p_positive.size() != p_negative.size(), Vector<int8_t>());
 	Vector<int8_t> sdf8;
 	int s = p_positive.size();

+ 7 - 367
core/math/geometry.h → core/math/geometry_3d.h

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  geometry.h                                                           */
+/*  geometry_3d.h                                                        */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,80 +28,17 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#ifndef GEOMETRY_H
-#define GEOMETRY_H
+#ifndef GEOMETRY_3D_H
+#define GEOMETRY_3D_H
 
-#include "core/math/delaunay_2d.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/print_string.h"
 #include "core/vector.h"
 
-class Geometry {
-	Geometry();
+class Geometry3D {
+	Geometry3D();
 
 public:
-	static real_t get_closest_points_between_segments(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2, Vector2 &c1, Vector2 &c2) {
-		Vector2 d1 = q1 - p1; // Direction vector of segment S1.
-		Vector2 d2 = q2 - p2; // Direction vector of segment S2.
-		Vector2 r = p1 - p2;
-		real_t a = d1.dot(d1); // Squared length of segment S1, always nonnegative.
-		real_t e = d2.dot(d2); // Squared length of segment S2, always nonnegative.
-		real_t f = d2.dot(r);
-		real_t s, t;
-		// Check if either or both segments degenerate into points.
-		if (a <= CMP_EPSILON && e <= CMP_EPSILON) {
-			// Both segments degenerate into points.
-			c1 = p1;
-			c2 = p2;
-			return Math::sqrt((c1 - c2).dot(c1 - c2));
-		}
-		if (a <= CMP_EPSILON) {
-			// First segment degenerates into a point.
-			s = 0.0;
-			t = f / e; // s = 0 => t = (b*s + f) / e = f / e
-			t = CLAMP(t, 0.0, 1.0);
-		} else {
-			real_t c = d1.dot(r);
-			if (e <= CMP_EPSILON) {
-				// Second segment degenerates into a point.
-				t = 0.0;
-				s = CLAMP(-c / a, 0.0, 1.0); // t = 0 => s = (b*t - c) / a = -c / a
-			} else {
-				// The general nondegenerate case starts here.
-				real_t b = d1.dot(d2);
-				real_t denom = a * e - b * b; // Always nonnegative.
-				// If segments not parallel, compute closest point on L1 to L2 and
-				// clamp to segment S1. Else pick arbitrary s (here 0).
-				if (denom != 0.0) {
-					s = CLAMP((b * f - c * e) / denom, 0.0, 1.0);
-				} else {
-					s = 0.0;
-				}
-				// Compute point on L2 closest to S1(s) using
-				// t = Dot((P1 + D1*s) - P2,D2) / Dot(D2,D2) = (b*s + f) / e
-				t = (b * s + f) / e;
-
-				//If t in [0,1] done. Else clamp t, recompute s for the new value
-				// of t using s = Dot((P2 + D2*t) - P1,D1) / Dot(D1,D1)= (t*b - c) / a
-				// and clamp s to [0, 1].
-				if (t < 0.0) {
-					t = 0.0;
-					s = CLAMP(-c / a, 0.0, 1.0);
-				} else if (t > 1.0) {
-					t = 1.0;
-					s = CLAMP((b - c) / a, 0.0, 1.0);
-				}
-			}
-		}
-		c1 = p1 + d1 * s;
-		c2 = p2 + d2 * t;
-		return Math::sqrt((c1 - c2).dot(c1 - c2));
-	}
-
 	static void get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2, Vector3 &c1, Vector3 &c2) {
 // Do the function 'd' as defined by pb. I think is is dot product of some sort.
 #define d_of(m, n, o, p) ((m.x - n.x) * (o.x - p.x) + (m.y - n.y) * (o.y - p.y) + (m.z - n.z) * (o.z - p.z))
@@ -501,98 +438,6 @@ public:
 		return p_segment[0] + n * d; // Inside.
 	}
 
-	static Vector2 get_closest_point_to_segment_2d(const Vector2 &p_point, const Vector2 *p_segment) {
-		Vector2 p = p_point - p_segment[0];
-		Vector2 n = p_segment[1] - p_segment[0];
-		real_t l2 = n.length_squared();
-		if (l2 < 1e-20) {
-			return p_segment[0]; // Both points are the same, just give any.
-		}
-
-		real_t d = n.dot(p) / l2;
-
-		if (d <= 0.0) {
-			return p_segment[0]; // Before first point.
-		} else if (d >= 1.0) {
-			return p_segment[1]; // After first point.
-		} else {
-			return p_segment[0] + n * d; // Inside.
-		}
-	}
-
-	static bool is_point_in_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) {
-		Vector2 an = a - s;
-		Vector2 bn = b - s;
-		Vector2 cn = c - s;
-
-		bool orientation = an.cross(bn) > 0;
-
-		if ((bn.cross(cn) > 0) != orientation) {
-			return false;
-		}
-
-		return (cn.cross(an) > 0) == orientation;
-	}
-
-	static Vector2 get_closest_point_to_segment_uncapped_2d(const Vector2 &p_point, const Vector2 *p_segment) {
-		Vector2 p = p_point - p_segment[0];
-		Vector2 n = p_segment[1] - p_segment[0];
-		real_t l2 = n.length_squared();
-		if (l2 < 1e-20) {
-			return p_segment[0]; // Both points are the same, just give any.
-		}
-
-		real_t d = n.dot(p) / l2;
-
-		return p_segment[0] + n * d; // Inside.
-	}
-
-	static bool line_intersects_line_2d(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b, Vector2 &r_result) {
-		// See http://paulbourke.net/geometry/pointlineplane/
-
-		const real_t denom = p_dir_b.y * p_dir_a.x - p_dir_b.x * p_dir_a.y;
-		if (Math::is_zero_approx(denom)) { // Parallel?
-			return false;
-		}
-
-		const Vector2 v = p_from_a - p_from_b;
-		const real_t t = (p_dir_b.x * v.y - p_dir_b.y * v.x) / denom;
-		r_result = p_from_a + t * p_dir_a;
-		return true;
-	}
-
-	static bool segment_intersects_segment_2d(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b, Vector2 *r_result) {
-		Vector2 B = p_to_a - p_from_a;
-		Vector2 C = p_from_b - p_from_a;
-		Vector2 D = p_to_b - p_from_a;
-
-		real_t ABlen = B.dot(B);
-		if (ABlen <= 0) {
-			return false;
-		}
-		Vector2 Bn = B / ABlen;
-		C = Vector2(C.x * Bn.x + C.y * Bn.y, C.y * Bn.x - C.x * Bn.y);
-		D = Vector2(D.x * Bn.x + D.y * Bn.y, D.y * Bn.x - D.x * Bn.y);
-
-		if ((C.y < 0 && D.y < 0) || (C.y >= 0 && D.y >= 0)) {
-			return false;
-		}
-
-		real_t ABpos = D.x + (C.x - D.x) * D.y / (D.y - C.y);
-
-		// Fail if segment C-D crosses line A-B outside of segment A-B.
-		if (ABpos < 0 || ABpos > 1.0) {
-			return false;
-		}
-
-		// (4) Apply the discovered position to line A-B in the original coordinate system.
-		if (r_result) {
-			*r_result = p_from_a + B * ABpos;
-		}
-
-		return true;
-	}
-
 	static inline bool point_in_projected_triangle(const Vector3 &p_point, const Vector3 &p_v1, const Vector3 &p_v2, const Vector3 &p_v3) {
 		Vector3 face_n = (p_v1 - p_v3).cross(p_v1 - p_v2);
 
@@ -629,7 +474,7 @@ public:
 
 		/** 2nd) TEST INSIDE TRIANGLE **/
 
-		if (Geometry::point_in_projected_triangle(contact, p_triangle[0], p_triangle[1], p_triangle[2])) {
+		if (Geometry3D::point_in_projected_triangle(contact, p_triangle[0], p_triangle[1], p_triangle[2])) {
 			r_triangle_contact = contact;
 			r_sphere_contact = p_sphere_pos - p_normal * p_sphere_radius;
 			//printf("solved inside triangle\n");
@@ -695,45 +540,6 @@ public:
 		return false;
 	}
 
-	static inline bool is_point_in_circle(const Vector2 &p_point, const Vector2 &p_circle_pos, real_t p_circle_radius) {
-		return p_point.distance_squared_to(p_circle_pos) <= p_circle_radius * p_circle_radius;
-	}
-
-	static real_t segment_intersects_circle(const Vector2 &p_from, const Vector2 &p_to, const Vector2 &p_circle_pos, real_t p_circle_radius) {
-		Vector2 line_vec = p_to - p_from;
-		Vector2 vec_to_line = p_from - p_circle_pos;
-
-		// Create a quadratic formula of the form ax^2 + bx + c = 0
-		real_t a, b, c;
-
-		a = line_vec.dot(line_vec);
-		b = 2 * vec_to_line.dot(line_vec);
-		c = vec_to_line.dot(vec_to_line) - p_circle_radius * p_circle_radius;
-
-		// Solve for t.
-		real_t sqrtterm = b * b - 4 * a * c;
-
-		// If the term we intend to square root is less than 0 then the answer won't be real,
-		// so it definitely won't be t in the range 0 to 1.
-		if (sqrtterm < 0) {
-			return -1;
-		}
-
-		// If we can assume that the line segment starts outside the circle (e.g. for continuous time collision detection)
-		// then the following can be skipped and we can just return the equivalent of res1.
-		sqrtterm = Math::sqrt(sqrtterm);
-		real_t res1 = (-b - sqrtterm) / (2 * a);
-		real_t res2 = (-b + sqrtterm) / (2 * a);
-
-		if (res1 >= 0 && res1 <= 1) {
-			return res1;
-		}
-		if (res2 >= 0 && res2 <= 1) {
-			return res2;
-		}
-		return -1;
-	}
-
 	static inline Vector<Vector3> clip_polygon(const Vector<Vector3> &polygon, const Plane &p_plane) {
 		enum LocationCache {
 			LOC_INSIDE = 1,
@@ -806,127 +612,6 @@ public:
 		return clipped;
 	}
 
-	enum PolyBooleanOperation {
-		OPERATION_UNION,
-		OPERATION_DIFFERENCE,
-		OPERATION_INTERSECTION,
-		OPERATION_XOR
-	};
-	enum PolyJoinType {
-		JOIN_SQUARE,
-		JOIN_ROUND,
-		JOIN_MITER
-	};
-	enum PolyEndType {
-		END_POLYGON,
-		END_JOINED,
-		END_BUTT,
-		END_SQUARE,
-		END_ROUND
-	};
-
-	static Vector<Vector<Point2>> merge_polygons_2d(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) {
-		return _polypaths_do_operation(OPERATION_UNION, p_polygon_a, p_polygon_b);
-	}
-
-	static Vector<Vector<Point2>> clip_polygons_2d(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) {
-		return _polypaths_do_operation(OPERATION_DIFFERENCE, p_polygon_a, p_polygon_b);
-	}
-
-	static Vector<Vector<Point2>> intersect_polygons_2d(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) {
-		return _polypaths_do_operation(OPERATION_INTERSECTION, p_polygon_a, p_polygon_b);
-	}
-
-	static Vector<Vector<Point2>> exclude_polygons_2d(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) {
-		return _polypaths_do_operation(OPERATION_XOR, p_polygon_a, p_polygon_b);
-	}
-
-	static Vector<Vector<Point2>> clip_polyline_with_polygon_2d(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) {
-		return _polypaths_do_operation(OPERATION_DIFFERENCE, p_polyline, p_polygon, true);
-	}
-
-	static Vector<Vector<Point2>> intersect_polyline_with_polygon_2d(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) {
-		return _polypaths_do_operation(OPERATION_INTERSECTION, p_polyline, p_polygon, true);
-	}
-
-	static Vector<Vector<Point2>> offset_polygon_2d(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type) {
-		return _polypath_offset(p_polygon, p_delta, p_join_type, END_POLYGON);
-	}
-
-	static Vector<Vector<Point2>> offset_polyline_2d(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) {
-		ERR_FAIL_COND_V_MSG(p_end_type == END_POLYGON, Vector<Vector<Point2>>(), "Attempt to offset a polyline like a polygon (use offset_polygon_2d instead).");
-
-		return _polypath_offset(p_polygon, p_delta, p_join_type, p_end_type);
-	}
-
-	static Vector<int> triangulate_delaunay_2d(const Vector<Vector2> &p_points) {
-		Vector<Delaunay2D::Triangle> tr = Delaunay2D::triangulate(p_points);
-		Vector<int> triangles;
-
-		for (int i = 0; i < tr.size(); i++) {
-			triangles.push_back(tr[i].points[0]);
-			triangles.push_back(tr[i].points[1]);
-			triangles.push_back(tr[i].points[2]);
-		}
-		return triangles;
-	}
-
-	static Vector<int> triangulate_polygon(const Vector<Vector2> &p_polygon) {
-		Vector<int> triangles;
-		if (!Triangulate::triangulate(p_polygon, triangles)) {
-			return Vector<int>(); //fail
-		}
-		return triangles;
-	}
-
-	static bool is_polygon_clockwise(const Vector<Vector2> &p_polygon) {
-		int c = p_polygon.size();
-		if (c < 3) {
-			return false;
-		}
-		const Vector2 *p = p_polygon.ptr();
-		real_t sum = 0;
-		for (int i = 0; i < c; i++) {
-			const Vector2 &v1 = p[i];
-			const Vector2 &v2 = p[(i + 1) % c];
-			sum += (v2.x - v1.x) * (v2.y + v1.y);
-		}
-
-		return sum > 0.0f;
-	}
-
-	// Alternate implementation that should be faster.
-	static bool is_point_in_polygon(const Vector2 &p_point, const Vector<Vector2> &p_polygon) {
-		int c = p_polygon.size();
-		if (c < 3) {
-			return false;
-		}
-		const Vector2 *p = p_polygon.ptr();
-		Vector2 further_away(-1e20, -1e20);
-		Vector2 further_away_opposite(1e20, 1e20);
-
-		for (int i = 0; i < c; i++) {
-			further_away.x = MAX(p[i].x, further_away.x);
-			further_away.y = MAX(p[i].y, further_away.y);
-			further_away_opposite.x = MIN(p[i].x, further_away_opposite.x);
-			further_away_opposite.y = MIN(p[i].y, further_away_opposite.y);
-		}
-
-		// Make point outside that won't intersect with points in segment from p_point.
-		further_away += (further_away - further_away_opposite) * Vector2(1.221313, 1.512312);
-
-		int intersections = 0;
-		for (int i = 0; i < c; i++) {
-			const Vector2 &v1 = p[i];
-			const Vector2 &v2 = p[(i + 1) % c];
-			if (segment_intersects_segment_2d(v1, v2, p_point, further_away, nullptr)) {
-				intersections++;
-			}
-		}
-
-		return (intersections & 1);
-	}
-
 	static Vector<Vector<Face3>> separate_objects(Vector<Face3> p_array);
 
 	// Create a "wrap" that encloses the given geometry.
@@ -999,50 +684,12 @@ public:
 			return ret;
 		}
 	}
-
-	static real_t vec2_cross(const Point2 &O, const Point2 &A, const Point2 &B) {
-		return (real_t)(A.x - O.x) * (B.y - O.y) - (real_t)(A.y - O.y) * (B.x - O.x);
-	}
-
-	// Returns a list of points on the convex hull in counter-clockwise order.
-	// Note: the last point in the returned list is the same as the first one.
-	static Vector<Point2> convex_hull_2d(Vector<Point2> P) {
-		int n = P.size(), k = 0;
-		Vector<Point2> H;
-		H.resize(2 * n);
-
-		// Sort points lexicographically.
-		P.sort();
-
-		// Build lower hull.
-		for (int i = 0; i < n; ++i) {
-			while (k >= 2 && vec2_cross(H[k - 2], H[k - 1], P[i]) <= 0) {
-				k--;
-			}
-			H.write[k++] = P[i];
-		}
-
-		// Build upper hull.
-		for (int i = n - 2, t = k + 1; i >= 0; i--) {
-			while (k >= t && vec2_cross(H[k - 2], H[k - 1], P[i]) <= 0) {
-				k--;
-			}
-			H.write[k++] = P[i];
-		}
-
-		H.resize(k);
-		return H;
-	}
-	static Vector<Vector<Vector2>> decompose_polygon_in_convex(Vector<Point2> polygon);
-
 	static MeshData build_convex_mesh(const Vector<Plane> &p_planes);
 	static Vector<Plane> build_sphere_planes(real_t p_radius, int p_lats, int p_lons, Vector3::Axis p_axis = Vector3::AXIS_Z);
 	static Vector<Plane> build_box_planes(const Vector3 &p_extents);
 	static Vector<Plane> build_cylinder_planes(real_t p_radius, real_t p_height, int p_sides, Vector3::Axis p_axis = Vector3::AXIS_Z);
 	static Vector<Plane> build_capsule_planes(real_t p_radius, real_t p_height, int p_sides, int p_lats, Vector3::Axis p_axis = Vector3::AXIS_Z);
 
-	static void make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_result, Size2i &r_size);
-
 	static Vector<Vector3> compute_convex_mesh_points(const Plane *p_planes, int p_plane_count);
 
 #define FINDMINMAX(x0, x1, x2, min, max) \
@@ -1255,9 +902,6 @@ public:
 		return planeBoxOverlap(normal, d, boxhalfsize); /* if true, box and triangle overlaps */
 	}
 
-	static Vector<Point2i> pack_rects(const Vector<Size2i> &p_sizes, const Size2i &p_atlas_size);
-	static Vector<Vector3i> partial_pack_rects(const Vector<Vector2i> &p_sizes, const Size2i &p_atlas_size);
-
 	static Vector<uint32_t> generate_edf(const Vector<bool> &p_voxels, const Vector3i &p_size, bool p_negative);
 	static Vector<int8_t> generate_sdf8(const Vector<uint32_t> &p_positive, const Vector<uint32_t> &p_negative);
 
@@ -1301,10 +945,6 @@ public:
 		return Color(va6 * v6, vb6 * v6, vc6 * v6, vd6 * v6);
 #undef STP
 	}
-
-private:
-	static Vector<Vector<Point2>> _polypaths_do_operation(PolyBooleanOperation p_op, const Vector<Point2> &p_polypath_a, const Vector<Point2> &p_polypath_b, bool is_a_open = false);
-	static Vector<Vector<Point2>> _polypath_offset(const Vector<Point2> &p_polypath, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type);
 };
 
-#endif // GEOMETRY_H
+#endif // GEOMETRY_3D_H

+ 2 - 2
core/math/octree.h

@@ -34,7 +34,7 @@
 #include "core/list.h"
 #include "core/map.h"
 #include "core/math/aabb.h"
-#include "core/math/geometry.h"
+#include "core/math/geometry_3d.h"
 #include "core/math/vector3.h"
 #include "core/print_string.h"
 #include "core/variant.h"
@@ -1201,7 +1201,7 @@ int Octree<T, use_pairs, AL>::cull_convex(const Vector<Plane> &p_convex, T **p_r
 		return 0;
 	}
 
-	Vector<Vector3> convex_points = Geometry::compute_convex_mesh_points(&p_convex[0], p_convex.size());
+	Vector<Vector3> convex_points = Geometry3D::compute_convex_mesh_points(&p_convex[0], p_convex.size());
 	if (convex_points.size() == 0) {
 		return 0;
 	}

+ 9 - 9
core/math/quick_hull.cpp

@@ -34,7 +34,7 @@
 
 uint32_t QuickHull::debug_stop_after = 0xFFFFFFFF;
 
-Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_mesh) {
+Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_mesh) {
 	/* CREATE AABB VOLUME */
 
 	AABB aabb;
@@ -334,17 +334,17 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
 
 	//make a map of edges again
 	Map<Edge, RetFaceConnect> ret_edges;
-	List<Geometry::MeshData::Face> ret_faces;
+	List<Geometry3D::MeshData::Face> ret_faces;
 
 	for (List<Face>::Element *E = faces.front(); E; E = E->next()) {
-		Geometry::MeshData::Face f;
+		Geometry3D::MeshData::Face f;
 		f.plane = E->get().plane;
 
 		for (int i = 0; i < 3; i++) {
 			f.indices.push_back(E->get().vertices[i]);
 		}
 
-		List<Geometry::MeshData::Face>::Element *F = ret_faces.push_back(f);
+		List<Geometry3D::MeshData::Face>::Element *F = ret_faces.push_back(f);
 
 		for (int i = 0; i < 3; i++) {
 			uint32_t a = E->get().vertices[i];
@@ -366,8 +366,8 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
 
 	//fill faces
 
-	for (List<Geometry::MeshData::Face>::Element *E = ret_faces.front(); E; E = E->next()) {
-		Geometry::MeshData::Face &f = E->get();
+	for (List<Geometry3D::MeshData::Face>::Element *E = ret_faces.front(); E; E = E->next()) {
+		Geometry3D::MeshData::Face &f = E->get();
 
 		for (int i = 0; i < f.indices.size(); i++) {
 			int a = E->get().indices[i];
@@ -377,7 +377,7 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
 			Map<Edge, RetFaceConnect>::Element *F = ret_edges.find(e);
 
 			ERR_CONTINUE(!F);
-			List<Geometry::MeshData::Face>::Element *O = F->get().left == E ? F->get().right : F->get().left;
+			List<Geometry3D::MeshData::Face>::Element *O = F->get().left == E ? F->get().right : F->get().left;
 			ERR_CONTINUE(O == E);
 			ERR_CONTINUE(O == nullptr);
 
@@ -439,13 +439,13 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
 	r_mesh.faces.resize(ret_faces.size());
 
 	int idx = 0;
-	for (List<Geometry::MeshData::Face>::Element *E = ret_faces.front(); E; E = E->next()) {
+	for (List<Geometry3D::MeshData::Face>::Element *E = ret_faces.front(); E; E = E->next()) {
 		r_mesh.faces.write[idx++] = E->get();
 	}
 	r_mesh.edges.resize(ret_edges.size());
 	idx = 0;
 	for (Map<Edge, RetFaceConnect>::Element *E = ret_edges.front(); E; E = E->next()) {
-		Geometry::MeshData::Edge e;
+		Geometry3D::MeshData::Edge e;
 		e.a = E->key().vertices[0];
 		e.b = E->key().vertices[1];
 		r_mesh.edges.write[idx++] = e;

+ 3 - 3
core/math/quick_hull.h

@@ -33,7 +33,7 @@
 
 #include "core/list.h"
 #include "core/math/aabb.h"
-#include "core/math/geometry.h"
+#include "core/math/geometry_3d.h"
 #include "core/set.h"
 
 class QuickHull {
@@ -74,13 +74,13 @@ private:
 		FaceConnect() {}
 	};
 	struct RetFaceConnect {
-		List<Geometry::MeshData::Face>::Element *left, *right = nullptr;
+		List<Geometry3D::MeshData::Face>::Element *left, *right = nullptr;
 		RetFaceConnect() {}
 	};
 
 public:
 	static uint32_t debug_stop_after;
-	static Error build(const Vector<Vector3> &p_points, Geometry::MeshData &r_mesh);
+	static Error build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_mesh);
 };
 
 #endif // QUICK_HULL_H

+ 12 - 6
core/register_core_types.cpp

@@ -60,7 +60,8 @@
 #include "core/io/xml_parser.h"
 #include "core/math/a_star.h"
 #include "core/math/expression.h"
-#include "core/math/geometry.h"
+#include "core/math/geometry_2d.h"
+#include "core/math/geometry_3d.h"
 #include "core/math/random_number_generator.h"
 #include "core/math/triangle_mesh.h"
 #include "core/os/main_loop.h"
@@ -87,7 +88,8 @@ static _JSON *_json = nullptr;
 
 static IP *ip = nullptr;
 
-static _Geometry *_geometry = nullptr;
+static _Geometry2D *_geometry_2d = nullptr;
+static _Geometry3D *_geometry_3d = nullptr;
 
 extern Mutex _global_mutex;
 
@@ -213,7 +215,8 @@ void register_core_types() {
 
 	ip = IP::create();
 
-	_geometry = memnew(_Geometry);
+	_geometry_2d = memnew(_Geometry2D);
+	_geometry_3d = memnew(_Geometry3D);
 
 	_resource_loader = memnew(_ResourceLoader);
 	_resource_saver = memnew(_ResourceSaver);
@@ -238,7 +241,8 @@ void register_core_settings() {
 void register_core_singletons() {
 	ClassDB::register_class<ProjectSettings>();
 	ClassDB::register_virtual_class<IP>();
-	ClassDB::register_class<_Geometry>();
+	ClassDB::register_class<_Geometry2D>();
+	ClassDB::register_class<_Geometry3D>();
 	ClassDB::register_class<_ResourceLoader>();
 	ClassDB::register_class<_ResourceSaver>();
 	ClassDB::register_class<_OS>();
@@ -253,7 +257,8 @@ void register_core_singletons() {
 
 	Engine::get_singleton()->add_singleton(Engine::Singleton("ProjectSettings", ProjectSettings::get_singleton()));
 	Engine::get_singleton()->add_singleton(Engine::Singleton("IP", IP::get_singleton()));
-	Engine::get_singleton()->add_singleton(Engine::Singleton("Geometry", _Geometry::get_singleton()));
+	Engine::get_singleton()->add_singleton(Engine::Singleton("Geometry2D", _Geometry2D::get_singleton()));
+	Engine::get_singleton()->add_singleton(Engine::Singleton("Geometry3D", _Geometry3D::get_singleton()));
 	Engine::get_singleton()->add_singleton(Engine::Singleton("ResourceLoader", _ResourceLoader::get_singleton()));
 	Engine::get_singleton()->add_singleton(Engine::Singleton("ResourceSaver", _ResourceSaver::get_singleton()));
 	Engine::get_singleton()->add_singleton(Engine::Singleton("OS", _OS::get_singleton()));
@@ -275,7 +280,8 @@ void unregister_core_types() {
 	memdelete(_marshalls);
 	memdelete(_json);
 
-	memdelete(_geometry);
+	memdelete(_geometry_2d);
+	memdelete(_geometry_3d);
 
 	ResourceLoader::remove_resource_format_loader(resource_format_image);
 	resource_format_image.unref();

+ 5 - 2
doc/classes/@GlobalScope.xml

@@ -27,8 +27,11 @@
 		<member name="Engine" type="Engine" setter="" getter="">
 			The [Engine] singleton.
 		</member>
-		<member name="Geometry" type="Geometry" setter="" getter="">
-			The [Geometry] singleton.
+		<member name="Geometry2D" type="Geometry2D" setter="" getter="">
+			The [Geometry2D] singleton.
+		</member>
+		<member name="Geometry3D" type="Geometry3D" setter="" getter="">
+			The [Geometry3D] singleton.
 		</member>
 		<member name="IP" type="IP" setter="" getter="">
 			The [IP] singleton.

+ 1 - 1
doc/classes/ConvexPolygonShape2D.xml

@@ -16,7 +16,7 @@
 			<argument index="0" name="point_cloud" type="PackedVector2Array">
 			</argument>
 			<description>
-				Based on the set of points provided, this creates and assigns the [member points] property using the convex hull algorithm. Removing all unneeded points. See [method Geometry.convex_hull_2d] for details.
+				Based on the set of points provided, this creates and assigns the [member points] property using the convex hull algorithm. Removing all unneeded points. See [method Geometry2D.convex_hull] for details.
 			</description>
 		</method>
 	</methods>

+ 19 - 213
doc/classes/Geometry.xml → doc/classes/Geometry2D.xml

@@ -1,67 +1,15 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<class name="Geometry" inherits="Object" version="4.0">
+<class name="Geometry2D" inherits="Object" version="4.0">
 	<brief_description>
-		Helper node to calculate generic geometry operations.
+		Helper node to calculate generic geometry operations in 2D space.
 	</brief_description>
 	<description>
-		Geometry provides users with a set of helper functions to create geometric shapes, compute intersections between shapes, and process various other geometric operations.
+		Geometry2D provides users with a set of helper functions to create geometric shapes, compute intersections between shapes, and process various other geometric operations.
 	</description>
 	<tutorials>
 	</tutorials>
 	<methods>
-		<method name="build_box_planes">
-			<return type="Array">
-			</return>
-			<argument index="0" name="extents" type="Vector3">
-			</argument>
-			<description>
-				Returns an array with 6 [Plane]s that describe the sides of a box centered at the origin. The box size is defined by [code]extents[/code], which represents one (positive) corner of the box (i.e. half its actual size).
-			</description>
-		</method>
-		<method name="build_capsule_planes">
-			<return type="Array">
-			</return>
-			<argument index="0" name="radius" type="float">
-			</argument>
-			<argument index="1" name="height" type="float">
-			</argument>
-			<argument index="2" name="sides" type="int">
-			</argument>
-			<argument index="3" name="lats" type="int">
-			</argument>
-			<argument index="4" name="axis" type="int" enum="Vector3.Axis" default="2">
-			</argument>
-			<description>
-				Returns an array of [Plane]s closely bounding a faceted capsule centered at the origin with radius [code]radius[/code] and height [code]height[/code]. The parameter [code]sides[/code] defines how many planes will be generated for the side part of the capsule, whereas [code]lats[/code] gives the number of latitudinal steps at the bottom and top of the capsule. The parameter [code]axis[/code] describes the axis along which the capsule is oriented (0 for X, 1 for Y, 2 for Z).
-			</description>
-		</method>
-		<method name="build_cylinder_planes">
-			<return type="Array">
-			</return>
-			<argument index="0" name="radius" type="float">
-			</argument>
-			<argument index="1" name="height" type="float">
-			</argument>
-			<argument index="2" name="sides" type="int">
-			</argument>
-			<argument index="3" name="axis" type="int" enum="Vector3.Axis" default="2">
-			</argument>
-			<description>
-				Returns an array of [Plane]s closely bounding a faceted cylinder centered at the origin with radius [code]radius[/code] and height [code]height[/code]. The parameter [code]sides[/code] defines how many planes will be generated for the round part of the cylinder. The parameter [code]axis[/code] describes the axis along which the cylinder is oriented (0 for X, 1 for Y, 2 for Z).
-			</description>
-		</method>
-		<method name="clip_polygon">
-			<return type="PackedVector3Array">
-			</return>
-			<argument index="0" name="points" type="PackedVector3Array">
-			</argument>
-			<argument index="1" name="plane" type="Plane">
-			</argument>
-			<description>
-				Clips the polygon defined by the points in [code]points[/code] against the [code]plane[/code] and returns the points of the clipped polygon.
-			</description>
-		</method>
-		<method name="clip_polygons_2d">
+		<method name="clip_polygons">
 			<return type="Array">
 			</return>
 			<argument index="0" name="polygon_a" type="PackedVector2Array">
@@ -73,7 +21,7 @@
 				If [code]polygon_b[/code] is enclosed by [code]polygon_a[/code], returns an outer polygon (boundary) and inner polygon (hole) which could be distinguished by calling [method is_polygon_clockwise].
 			</description>
 		</method>
-		<method name="clip_polyline_with_polygon_2d">
+		<method name="clip_polyline_with_polygon">
 			<return type="Array">
 			</return>
 			<argument index="0" name="polyline" type="PackedVector2Array">
@@ -84,7 +32,7 @@
 				Clips [code]polyline[/code] against [code]polygon[/code] and returns an array of clipped polylines. This performs [constant OPERATION_DIFFERENCE] between the polyline and the polygon. This operation can be thought of as cutting a line with a closed shape.
 			</description>
 		</method>
-		<method name="convex_hull_2d">
+		<method name="convex_hull">
 			<return type="PackedVector2Array">
 			</return>
 			<argument index="0" name="points" type="PackedVector2Array">
@@ -93,7 +41,7 @@
 				Given an array of [Vector2]s, returns the convex hull as a list of points in counterclockwise order. The last point is the same as the first one.
 			</description>
 		</method>
-		<method name="exclude_polygons_2d">
+		<method name="exclude_polygons">
 			<return type="Array">
 			</return>
 			<argument index="0" name="polygon_a" type="PackedVector2Array">
@@ -101,24 +49,11 @@
 			<argument index="1" name="polygon_b" type="PackedVector2Array">
 			</argument>
 			<description>
-				Mutually excludes common area defined by intersection of [code]polygon_a[/code] and [code]polygon_b[/code] (see [method intersect_polygons_2d]) and returns an array of excluded polygons. This performs [constant OPERATION_XOR] between polygons. In other words, returns all but common area between polygons.
+				Mutually excludes common area defined by intersection of [code]polygon_a[/code] and [code]polygon_b[/code] (see [method intersect_polygons]) and returns an array of excluded polygons. This performs [constant OPERATION_XOR] between polygons. In other words, returns all but common area between polygons.
 				The operation may result in an outer polygon (boundary) and inner polygon (hole) produced which could be distinguished by calling [method is_polygon_clockwise].
 			</description>
 		</method>
 		<method name="get_closest_point_to_segment">
-			<return type="Vector3">
-			</return>
-			<argument index="0" name="point" type="Vector3">
-			</argument>
-			<argument index="1" name="s1" type="Vector3">
-			</argument>
-			<argument index="2" name="s2" type="Vector3">
-			</argument>
-			<description>
-				Returns the 3D point on the 3D segment ([code]s1[/code], [code]s2[/code]) that is closest to [code]point[/code]. The returned point will always be inside the specified segment.
-			</description>
-		</method>
-		<method name="get_closest_point_to_segment_2d">
 			<return type="Vector2">
 			</return>
 			<argument index="0" name="point" type="Vector2">
@@ -132,19 +67,6 @@
 			</description>
 		</method>
 		<method name="get_closest_point_to_segment_uncapped">
-			<return type="Vector3">
-			</return>
-			<argument index="0" name="point" type="Vector3">
-			</argument>
-			<argument index="1" name="s1" type="Vector3">
-			</argument>
-			<argument index="2" name="s2" type="Vector3">
-			</argument>
-			<description>
-				Returns the 3D point on the 3D line defined by ([code]s1[/code], [code]s2[/code]) that is closest to [code]point[/code]. The returned point can be inside the segment ([code]s1[/code], [code]s2[/code]) or outside of it, i.e. somewhere on the line extending from the segment.
-			</description>
-		</method>
-		<method name="get_closest_point_to_segment_uncapped_2d">
 			<return type="Vector2">
 			</return>
 			<argument index="0" name="point" type="Vector2">
@@ -158,21 +80,6 @@
 			</description>
 		</method>
 		<method name="get_closest_points_between_segments">
-			<return type="PackedVector3Array">
-			</return>
-			<argument index="0" name="p1" type="Vector3">
-			</argument>
-			<argument index="1" name="p2" type="Vector3">
-			</argument>
-			<argument index="2" name="q1" type="Vector3">
-			</argument>
-			<argument index="3" name="q2" type="Vector3">
-			</argument>
-			<description>
-				Given the two 3D segments ([code]p1[/code], [code]p2[/code]) and ([code]q1[/code], [code]q2[/code]), finds those two points on the two segments that are closest to each other. Returns a [PackedVector3Array] that contains this point on ([code]p1[/code], [code]p2[/code]) as well the accompanying point on ([code]q1[/code], [code]q2[/code]).
-			</description>
-		</method>
-		<method name="get_closest_points_between_segments_2d">
 			<return type="PackedVector2Array">
 			</return>
 			<argument index="0" name="p1" type="Vector2">
@@ -187,16 +94,7 @@
 				Given the two 2D segments ([code]p1[/code], [code]p2[/code]) and ([code]q1[/code], [code]q2[/code]), finds those two points on the two segments that are closest to each other. Returns a [PackedVector2Array] that contains this point on ([code]p1[/code], [code]p2[/code]) as well the accompanying point on ([code]q1[/code], [code]q2[/code]).
 			</description>
 		</method>
-		<method name="get_uv84_normal_bit">
-			<return type="int">
-			</return>
-			<argument index="0" name="normal" type="Vector3">
-			</argument>
-			<description>
-				Used internally by the engine.
-			</description>
-		</method>
-		<method name="intersect_polygons_2d">
+		<method name="intersect_polygons">
 			<return type="Array">
 			</return>
 			<argument index="0" name="polygon_a" type="PackedVector2Array">
@@ -208,7 +106,7 @@
 				The operation may result in an outer polygon (boundary) and inner polygon (hole) produced which could be distinguished by calling [method is_polygon_clockwise].
 			</description>
 		</method>
-		<method name="intersect_polyline_with_polygon_2d">
+		<method name="intersect_polyline_with_polygon">
 			<return type="Array">
 			</return>
 			<argument index="0" name="polyline" type="PackedVector2Array">
@@ -252,7 +150,7 @@
 				Returns [code]true[/code] if [code]polygon[/code]'s vertices are ordered in clockwise order, otherwise returns [code]false[/code].
 			</description>
 		</method>
-		<method name="line_intersects_line_2d">
+		<method name="line_intersects_line">
 			<return type="Variant">
 			</return>
 			<argument index="0" name="from_a" type="Vector2">
@@ -277,7 +175,7 @@
 				Given an array of [Vector2]s representing tiles, builds an atlas. The returned dictionary has two keys: [code]points[/code] is a vector of [Vector2] that specifies the positions of each tile, [code]size[/code] contains the overall size of the whole atlas as [Vector2].
 			</description>
 		</method>
-		<method name="merge_polygons_2d">
+		<method name="merge_polygons">
 			<return type="Array">
 			</return>
 			<argument index="0" name="polygon_a" type="PackedVector2Array">
@@ -289,14 +187,14 @@
 				The operation may result in an outer polygon (boundary) and inner polygon (hole) produced which could be distinguished by calling [method is_polygon_clockwise].
 			</description>
 		</method>
-		<method name="offset_polygon_2d">
+		<method name="offset_polygon">
 			<return type="Array">
 			</return>
 			<argument index="0" name="polygon" type="PackedVector2Array">
 			</argument>
 			<argument index="1" name="delta" type="float">
 			</argument>
-			<argument index="2" name="join_type" type="int" enum="Geometry.PolyJoinType" default="0">
+			<argument index="2" name="join_type" type="int" enum="Geometry2D.PolyJoinType" default="0">
 			</argument>
 			<description>
 				Inflates or deflates [code]polygon[/code] by [code]delta[/code] units (pixels). If [code]delta[/code] is positive, makes the polygon grow outward. If [code]delta[/code] is negative, shrinks the polygon inward. Returns an array of polygons because inflating/deflating may result in multiple discrete polygons. Returns an empty array if [code]delta[/code] is negative and the absolute value of it approximately exceeds the minimum bounding rectangle dimensions of the polygon.
@@ -304,16 +202,16 @@
 				The operation may result in an outer polygon (boundary) and inner polygon (hole) produced which could be distinguished by calling [method is_polygon_clockwise].
 			</description>
 		</method>
-		<method name="offset_polyline_2d">
+		<method name="offset_polyline">
 			<return type="Array">
 			</return>
 			<argument index="0" name="polyline" type="PackedVector2Array">
 			</argument>
 			<argument index="1" name="delta" type="float">
 			</argument>
-			<argument index="2" name="join_type" type="int" enum="Geometry.PolyJoinType" default="0">
+			<argument index="2" name="join_type" type="int" enum="Geometry2D.PolyJoinType" default="0">
 			</argument>
-			<argument index="3" name="end_type" type="int" enum="Geometry.PolyEndType" default="3">
+			<argument index="3" name="end_type" type="int" enum="Geometry2D.PolyEndType" default="3">
 			</argument>
 			<description>
 				Inflates or deflates [code]polyline[/code] by [code]delta[/code] units (pixels), producing polygons. If [code]delta[/code] is positive, makes the polyline grow outward. Returns an array of polygons because inflating/deflating may result in multiple discrete polygons. If [code]delta[/code] is negative, returns an empty array.
@@ -337,67 +235,7 @@
 				Returns if [code]point[/code] is inside the triangle specified by [code]a[/code], [code]b[/code] and [code]c[/code].
 			</description>
 		</method>
-		<method name="ray_intersects_triangle">
-			<return type="Variant">
-			</return>
-			<argument index="0" name="from" type="Vector3">
-			</argument>
-			<argument index="1" name="dir" type="Vector3">
-			</argument>
-			<argument index="2" name="a" type="Vector3">
-			</argument>
-			<argument index="3" name="b" type="Vector3">
-			</argument>
-			<argument index="4" name="c" type="Vector3">
-			</argument>
-			<description>
-				Tests if the 3D ray starting at [code]from[/code] with the direction of [code]dir[/code] intersects the triangle specified by [code]a[/code], [code]b[/code] and [code]c[/code]. If yes, returns the point of intersection as [Vector3]. If no intersection takes place, an empty [Variant] is returned.
-			</description>
-		</method>
-		<method name="segment_intersects_circle">
-			<return type="float">
-			</return>
-			<argument index="0" name="segment_from" type="Vector2">
-			</argument>
-			<argument index="1" name="segment_to" type="Vector2">
-			</argument>
-			<argument index="2" name="circle_position" type="Vector2">
-			</argument>
-			<argument index="3" name="circle_radius" type="float">
-			</argument>
-			<description>
-				Given the 2D segment ([code]segment_from[/code], [code]segment_to[/code]), returns the position on the segment (as a number between 0 and 1) at which the segment hits the circle that is located at position [code]circle_position[/code] and has radius [code]circle_radius[/code]. If the segment does not intersect the circle, -1 is returned (this is also the case if the line extending the segment would intersect the circle, but the segment does not).
-			</description>
-		</method>
-		<method name="segment_intersects_convex">
-			<return type="PackedVector3Array">
-			</return>
-			<argument index="0" name="from" type="Vector3">
-			</argument>
-			<argument index="1" name="to" type="Vector3">
-			</argument>
-			<argument index="2" name="planes" type="Array">
-			</argument>
-			<description>
-				Given a convex hull defined though the [Plane]s in the array [code]planes[/code], tests if the segment ([code]from[/code], [code]to[/code]) intersects with that hull. If an intersection is found, returns a [PackedVector3Array] containing the point the intersection and the hull's normal. If no intersecion is found, an the returned array is empty.
-			</description>
-		</method>
-		<method name="segment_intersects_cylinder">
-			<return type="PackedVector3Array">
-			</return>
-			<argument index="0" name="from" type="Vector3">
-			</argument>
-			<argument index="1" name="to" type="Vector3">
-			</argument>
-			<argument index="2" name="height" type="float">
-			</argument>
-			<argument index="3" name="radius" type="float">
-			</argument>
-			<description>
-				Checks if the segment ([code]from[/code], [code]to[/code]) intersects the cylinder with height [code]height[/code] that is centered at the origin and has radius [code]radius[/code]. If no, returns an empty [PackedVector3Array]. If an intersection takes place, the returned array contains the point of intersection and the cylinder's normal at the point of intersection.
-			</description>
-		</method>
-		<method name="segment_intersects_segment_2d">
+		<method name="segment_intersects_segment">
 			<return type="Variant">
 			</return>
 			<argument index="0" name="from_a" type="Vector2">
@@ -412,39 +250,7 @@
 				Checks if the two segments ([code]from_a[/code], [code]to_a[/code]) and ([code]from_b[/code], [code]to_b[/code]) intersect. If yes, return the point of intersection as [Vector2]. If no intersection takes place, returns an empty [Variant].
 			</description>
 		</method>
-		<method name="segment_intersects_sphere">
-			<return type="PackedVector3Array">
-			</return>
-			<argument index="0" name="from" type="Vector3">
-			</argument>
-			<argument index="1" name="to" type="Vector3">
-			</argument>
-			<argument index="2" name="sphere_position" type="Vector3">
-			</argument>
-			<argument index="3" name="sphere_radius" type="float">
-			</argument>
-			<description>
-				Checks if the segment ([code]from[/code], [code]to[/code]) intersects the sphere that is located at [code]sphere_position[/code] and has radius [code]sphere_radius[/code]. If no, returns an empty [PackedVector3Array]. If yes, returns a [PackedVector3Array] containing the point of intersection and the sphere's normal at the point of intersection.
-			</description>
-		</method>
-		<method name="segment_intersects_triangle">
-			<return type="Variant">
-			</return>
-			<argument index="0" name="from" type="Vector3">
-			</argument>
-			<argument index="1" name="to" type="Vector3">
-			</argument>
-			<argument index="2" name="a" type="Vector3">
-			</argument>
-			<argument index="3" name="b" type="Vector3">
-			</argument>
-			<argument index="4" name="c" type="Vector3">
-			</argument>
-			<description>
-				Tests if the segment ([code]from[/code], [code]to[/code]) intersects the triangle [code]a[/code], [code]b[/code], [code]c[/code]. If yes, returns the point of intersection as [Vector3]. If no intersection takes place, an empty [Variant] is returned.
-			</description>
-		</method>
-		<method name="triangulate_delaunay_2d">
+		<method name="triangulate_delaunay">
 			<return type="PackedInt32Array">
 			</return>
 			<argument index="0" name="points" type="PackedVector2Array">

+ 194 - 0
doc/classes/Geometry3D.xml

@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="Geometry3D" inherits="Object" version="4.0">
+	<brief_description>
+		Helper node to calculate generic geometry operations in 3D space.
+	</brief_description>
+	<description>
+		Geometry3D provides users with a set of helper functions to create geometric shapes, compute intersections between shapes, and process various other geometric operations.
+	</description>
+	<tutorials>
+	</tutorials>
+	<methods>
+		<method name="build_box_planes">
+			<return type="Array">
+			</return>
+			<argument index="0" name="extents" type="Vector3">
+			</argument>
+			<description>
+				Returns an array with 6 [Plane]s that describe the sides of a box centered at the origin. The box size is defined by [code]extents[/code], which represents one (positive) corner of the box (i.e. half its actual size).
+			</description>
+		</method>
+		<method name="build_capsule_planes">
+			<return type="Array">
+			</return>
+			<argument index="0" name="radius" type="float">
+			</argument>
+			<argument index="1" name="height" type="float">
+			</argument>
+			<argument index="2" name="sides" type="int">
+			</argument>
+			<argument index="3" name="lats" type="int">
+			</argument>
+			<argument index="4" name="axis" type="int" enum="Vector3.Axis" default="2">
+			</argument>
+			<description>
+				Returns an array of [Plane]s closely bounding a faceted capsule centered at the origin with radius [code]radius[/code] and height [code]height[/code]. The parameter [code]sides[/code] defines how many planes will be generated for the side part of the capsule, whereas [code]lats[/code] gives the number of latitudinal steps at the bottom and top of the capsule. The parameter [code]axis[/code] describes the axis along which the capsule is oriented (0 for X, 1 for Y, 2 for Z).
+			</description>
+		</method>
+		<method name="build_cylinder_planes">
+			<return type="Array">
+			</return>
+			<argument index="0" name="radius" type="float">
+			</argument>
+			<argument index="1" name="height" type="float">
+			</argument>
+			<argument index="2" name="sides" type="int">
+			</argument>
+			<argument index="3" name="axis" type="int" enum="Vector3.Axis" default="2">
+			</argument>
+			<description>
+				Returns an array of [Plane]s closely bounding a faceted cylinder centered at the origin with radius [code]radius[/code] and height [code]height[/code]. The parameter [code]sides[/code] defines how many planes will be generated for the round part of the cylinder. The parameter [code]axis[/code] describes the axis along which the cylinder is oriented (0 for X, 1 for Y, 2 for Z).
+			</description>
+		</method>
+		<method name="clip_polygon">
+			<return type="PackedVector3Array">
+			</return>
+			<argument index="0" name="points" type="PackedVector3Array">
+			</argument>
+			<argument index="1" name="plane" type="Plane">
+			</argument>
+			<description>
+				Clips the polygon defined by the points in [code]points[/code] against the [code]plane[/code] and returns the points of the clipped polygon.
+			</description>
+		</method>
+		<method name="get_closest_point_to_segment">
+			<return type="Vector3">
+			</return>
+			<argument index="0" name="point" type="Vector3">
+			</argument>
+			<argument index="1" name="s1" type="Vector3">
+			</argument>
+			<argument index="2" name="s2" type="Vector3">
+			</argument>
+			<description>
+				Returns the 3D point on the 3D segment ([code]s1[/code], [code]s2[/code]) that is closest to [code]point[/code]. The returned point will always be inside the specified segment.
+			</description>
+		</method>
+		<method name="get_closest_point_to_segment_uncapped">
+			<return type="Vector3">
+			</return>
+			<argument index="0" name="point" type="Vector3">
+			</argument>
+			<argument index="1" name="s1" type="Vector3">
+			</argument>
+			<argument index="2" name="s2" type="Vector3">
+			</argument>
+			<description>
+				Returns the 3D point on the 3D line defined by ([code]s1[/code], [code]s2[/code]) that is closest to [code]point[/code]. The returned point can be inside the segment ([code]s1[/code], [code]s2[/code]) or outside of it, i.e. somewhere on the line extending from the segment.
+			</description>
+		</method>
+		<method name="get_closest_points_between_segments">
+			<return type="PackedVector3Array">
+			</return>
+			<argument index="0" name="p1" type="Vector3">
+			</argument>
+			<argument index="1" name="p2" type="Vector3">
+			</argument>
+			<argument index="2" name="q1" type="Vector3">
+			</argument>
+			<argument index="3" name="q2" type="Vector3">
+			</argument>
+			<description>
+				Given the two 3D segments ([code]p1[/code], [code]p2[/code]) and ([code]q1[/code], [code]q2[/code]), finds those two points on the two segments that are closest to each other. Returns a [PackedVector3Array] that contains this point on ([code]p1[/code], [code]p2[/code]) as well the accompanying point on ([code]q1[/code], [code]q2[/code]).
+			</description>
+		</method>
+		<method name="get_uv84_normal_bit">
+			<return type="int">
+			</return>
+			<argument index="0" name="normal" type="Vector3">
+			</argument>
+			<description>
+				Used internally by the engine.
+			</description>
+		</method>
+		<method name="ray_intersects_triangle">
+			<return type="Variant">
+			</return>
+			<argument index="0" name="from" type="Vector3">
+			</argument>
+			<argument index="1" name="dir" type="Vector3">
+			</argument>
+			<argument index="2" name="a" type="Vector3">
+			</argument>
+			<argument index="3" name="b" type="Vector3">
+			</argument>
+			<argument index="4" name="c" type="Vector3">
+			</argument>
+			<description>
+				Tests if the 3D ray starting at [code]from[/code] with the direction of [code]dir[/code] intersects the triangle specified by [code]a[/code], [code]b[/code] and [code]c[/code]. If yes, returns the point of intersection as [Vector3]. If no intersection takes place, an empty [Variant] is returned.
+			</description>
+		</method>
+		<method name="segment_intersects_convex">
+			<return type="PackedVector3Array">
+			</return>
+			<argument index="0" name="from" type="Vector3">
+			</argument>
+			<argument index="1" name="to" type="Vector3">
+			</argument>
+			<argument index="2" name="planes" type="Array">
+			</argument>
+			<description>
+				Given a convex hull defined though the [Plane]s in the array [code]planes[/code], tests if the segment ([code]from[/code], [code]to[/code]) intersects with that hull. If an intersection is found, returns a [PackedVector3Array] containing the point the intersection and the hull's normal. If no intersecion is found, an the returned array is empty.
+			</description>
+		</method>
+		<method name="segment_intersects_cylinder">
+			<return type="PackedVector3Array">
+			</return>
+			<argument index="0" name="from" type="Vector3">
+			</argument>
+			<argument index="1" name="to" type="Vector3">
+			</argument>
+			<argument index="2" name="height" type="float">
+			</argument>
+			<argument index="3" name="radius" type="float">
+			</argument>
+			<description>
+				Checks if the segment ([code]from[/code], [code]to[/code]) intersects the cylinder with height [code]height[/code] that is centered at the origin and has radius [code]radius[/code]. If no, returns an empty [PackedVector3Array]. If an intersection takes place, the returned array contains the point of intersection and the cylinder's normal at the point of intersection.
+			</description>
+		</method>
+		<method name="segment_intersects_sphere">
+			<return type="PackedVector3Array">
+			</return>
+			<argument index="0" name="from" type="Vector3">
+			</argument>
+			<argument index="1" name="to" type="Vector3">
+			</argument>
+			<argument index="2" name="sphere_position" type="Vector3">
+			</argument>
+			<argument index="3" name="sphere_radius" type="float">
+			</argument>
+			<description>
+				Checks if the segment ([code]from[/code], [code]to[/code]) intersects the sphere that is located at [code]sphere_position[/code] and has radius [code]sphere_radius[/code]. If no, returns an empty [PackedVector3Array]. If yes, returns a [PackedVector3Array] containing the point of intersection and the sphere's normal at the point of intersection.
+			</description>
+		</method>
+		<method name="segment_intersects_triangle">
+			<return type="Variant">
+			</return>
+			<argument index="0" name="from" type="Vector3">
+			</argument>
+			<argument index="1" name="to" type="Vector3">
+			</argument>
+			<argument index="2" name="a" type="Vector3">
+			</argument>
+			<argument index="3" name="b" type="Vector3">
+			</argument>
+			<argument index="4" name="c" type="Vector3">
+			</argument>
+			<description>
+				Tests if the segment ([code]from[/code], [code]to[/code]) intersects the triangle [code]a[/code], [code]b[/code], [code]c[/code]. If yes, returns the point of intersection as [Vector3]. If no intersection takes place, an empty [Variant] is returned.
+			</description>
+		</method>
+	</methods>
+	<constants>
+	</constants>
+</class>

+ 2 - 1
editor/import/resource_importer_texture_atlas.cpp

@@ -33,6 +33,7 @@
 #include "atlas_import_failed.xpm"
 #include "core/io/image_loader.h"
 #include "core/io/resource_saver.h"
+#include "core/math/geometry_2d.h"
 #include "core/os/file_access.h"
 #include "editor/editor_atlas_packer.h"
 #include "scene/resources/mesh.h"
@@ -247,7 +248,7 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file
 				chart.vertices = polygons[j];
 				chart.can_transpose = true;
 
-				Vector<int> poly = Geometry::triangulate_polygon(polygons[j]);
+				Vector<int> poly = Geometry2D::triangulate_polygon(polygons[j]);
 				for (int i = 0; i < poly.size(); i += 3) {
 					EditorAtlasPacker::Chart::Face f;
 					f.vertex[0] = poly[i + 0];

+ 22 - 21
editor/node_3d_editor_gizmos.cpp

@@ -30,7 +30,8 @@
 
 #include "node_3d_editor_gizmos.h"
 
-#include "core/math/geometry.h"
+#include "core/math/geometry_2d.h"
+#include "core/math/geometry_3d.h"
 #include "core/math/quick_hull.h"
 #include "scene/3d/audio_stream_player_3d.h"
 #include "scene/3d/baked_lightmap.h"
@@ -482,7 +483,7 @@ bool EditorNode3DGizmo::intersect_frustum(const Camera3D *p_camera, const Vector
 			transformed_frustum.push_back(it.xform(p_frustum[i]));
 		}
 
-		Vector<Vector3> convex_points = Geometry::compute_convex_mesh_points(p_frustum.ptr(), p_frustum.size());
+		Vector<Vector3> convex_points = Geometry3D::compute_convex_mesh_points(p_frustum.ptr(), p_frustum.size());
 		if (collision_mesh->inside_convex_shape(transformed_frustum.ptr(), transformed_frustum.size(), convex_points.ptr(), convex_points.size(), mesh_scale)) {
 			return true;
 		}
@@ -616,7 +617,7 @@ bool EditorNode3DGizmo::intersect_ray(Camera3D *p_camera, const Point2 &p_point,
 			s[0] = p_camera->unproject_position(a);
 			s[1] = p_camera->unproject_position(b);
 
-			Vector2 p = Geometry::get_closest_point_to_segment_2d(p_point, s);
+			Vector2 p = Geometry2D::get_closest_point_to_segment(p_point, s);
 
 			float pd = p.distance_to(p_point);
 
@@ -831,7 +832,7 @@ static float _find_closest_angle_to_half_pi_arc(const Vector3 &p_from, const Vec
 		Vector3 n = Vector3(Math::cos(an), 0, -Math::sin(an)) * p_arc_radius;
 
 		Vector3 ra, rb;
-		Geometry::get_closest_points_between_segments(p, n, p_from, p_to, ra, rb);
+		Geometry3D::get_closest_points_between_segments(p, n, p_from, p_to, ra, rb);
 
 		float d = ra.distance_to(rb);
 		if (d < min_d) {
@@ -857,7 +858,7 @@ void Light3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camer
 	if (p_idx == 0) {
 		if (Object::cast_to<SpotLight3D>(light)) {
 			Vector3 ra, rb;
-			Geometry::get_closest_points_between_segments(Vector3(), Vector3(0, 0, -4096), s[0], s[1], ra, rb);
+			Geometry3D::get_closest_points_between_segments(Vector3(), Vector3(0, 0, -4096), s[0], s[1], ra, rb);
 
 			float d = -ra.z;
 			if (Node3DEditor::get_singleton()->is_snap_enabled()) {
@@ -1100,7 +1101,7 @@ void AudioStreamPlayer3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int
 		Vector3 to(Math::sin(an), 0, -Math::cos(an));
 
 		Vector3 r1, r2;
-		Geometry::get_closest_points_between_segments(from, to, ray_from, ray_to, r1, r2);
+		Geometry3D::get_closest_points_between_segments(from, to, ray_from, ray_to, r1, r2);
 		float d = r1.distance_to(r2);
 		if (d < closest_dist) {
 			closest_dist = d;
@@ -1238,7 +1239,7 @@ void Camera3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Came
 		camera->set("fov", CLAMP(a * 2.0, 1, 179));
 	} else {
 		Vector3 ra, rb;
-		Geometry::get_closest_points_between_segments(Vector3(0, 0, -1), Vector3(4096, 0, -1), s[0], s[1], ra, rb);
+		Geometry3D::get_closest_points_between_segments(Vector3(0, 0, -1), Vector3(4096, 0, -1), s[0], s[1], ra, rb);
 		float d = ra.x * 2.0;
 		if (Node3DEditor::get_singleton()->is_snap_enabled()) {
 			d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap());
@@ -2169,7 +2170,7 @@ void VisibilityNotifier3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int
 
 	if (move) {
 		Vector3 ra, rb;
-		Geometry::get_closest_points_between_segments(ofs - axis * 4096, ofs + axis * 4096, sg[0], sg[1], ra, rb);
+		Geometry3D::get_closest_points_between_segments(ofs - axis * 4096, ofs + axis * 4096, sg[0], sg[1], ra, rb);
 
 		float d = ra[p_idx];
 		if (Node3DEditor::get_singleton()->is_snap_enabled()) {
@@ -2181,7 +2182,7 @@ void VisibilityNotifier3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int
 
 	} else {
 		Vector3 ra, rb;
-		Geometry::get_closest_points_between_segments(ofs, ofs + axis * 4096, sg[0], sg[1], ra, rb);
+		Geometry3D::get_closest_points_between_segments(ofs, ofs + axis * 4096, sg[0], sg[1], ra, rb);
 
 		float d = ra[p_idx] - ofs[p_idx];
 		if (Node3DEditor::get_singleton()->is_snap_enabled()) {
@@ -2360,7 +2361,7 @@ void GPUParticles3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx
 
 	if (move) {
 		Vector3 ra, rb;
-		Geometry::get_closest_points_between_segments(ofs - axis * 4096, ofs + axis * 4096, sg[0], sg[1], ra, rb);
+		Geometry3D::get_closest_points_between_segments(ofs - axis * 4096, ofs + axis * 4096, sg[0], sg[1], ra, rb);
 
 		float d = ra[p_idx];
 		if (Node3DEditor::get_singleton()->is_snap_enabled()) {
@@ -2372,7 +2373,7 @@ void GPUParticles3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx
 
 	} else {
 		Vector3 ra, rb;
-		Geometry::get_closest_points_between_segments(ofs, ofs + axis * 4096, sg[0], sg[1], ra, rb);
+		Geometry3D::get_closest_points_between_segments(ofs, ofs + axis * 4096, sg[0], sg[1], ra, rb);
 
 		float d = ra[p_idx] - ofs[p_idx];
 		if (Node3DEditor::get_singleton()->is_snap_enabled()) {
@@ -2523,7 +2524,7 @@ void ReflectionProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_id
 		axis[p_idx] = 1.0;
 
 		Vector3 ra, rb;
-		Geometry::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb);
+		Geometry3D::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb);
 		float d = ra[p_idx];
 		if (Node3DEditor::get_singleton()->is_snap_enabled()) {
 			d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap());
@@ -2550,7 +2551,7 @@ void ReflectionProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_id
 		axis[p_idx] = 1.0;
 
 		Vector3 ra, rb;
-		Geometry::get_closest_points_between_segments(origin - axis * 16384, origin + axis * 16384, sg[0], sg[1], ra, rb);
+		Geometry3D::get_closest_points_between_segments(origin - axis * 16384, origin + axis * 16384, sg[0], sg[1], ra, rb);
 		// Adjust the actual position to account for the gizmo handle position
 		float d = ra[p_idx] + 0.25;
 		if (Node3DEditor::get_singleton()->is_snap_enabled()) {
@@ -2701,7 +2702,7 @@ void DecalGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3
 	axis[p_idx] = 1.0;
 
 	Vector3 ra, rb;
-	Geometry::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb);
+	Geometry3D::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb);
 	float d = ra[p_idx];
 	if (Node3DEditor::get_singleton()->is_snap_enabled()) {
 		d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap());
@@ -2842,7 +2843,7 @@ void GIProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camer
 	axis[p_idx] = 1.0;
 
 	Vector3 ra, rb;
-	Geometry::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb);
+	Geometry3D::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb);
 	float d = ra[p_idx];
 	if (Node3DEditor::get_singleton()->is_snap_enabled()) {
 		d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap());
@@ -3354,7 +3355,7 @@ void CollisionShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_i
 	if (Object::cast_to<SphereShape3D>(*s)) {
 		Ref<SphereShape3D> ss = s;
 		Vector3 ra, rb;
-		Geometry::get_closest_points_between_segments(Vector3(), Vector3(4096, 0, 0), sg[0], sg[1], ra, rb);
+		Geometry3D::get_closest_points_between_segments(Vector3(), Vector3(4096, 0, 0), sg[0], sg[1], ra, rb);
 		float d = ra.x;
 		if (Node3DEditor::get_singleton()->is_snap_enabled()) {
 			d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap());
@@ -3370,7 +3371,7 @@ void CollisionShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_i
 	if (Object::cast_to<RayShape3D>(*s)) {
 		Ref<RayShape3D> rs = s;
 		Vector3 ra, rb;
-		Geometry::get_closest_points_between_segments(Vector3(), Vector3(0, 0, 4096), sg[0], sg[1], ra, rb);
+		Geometry3D::get_closest_points_between_segments(Vector3(), Vector3(0, 0, 4096), sg[0], sg[1], ra, rb);
 		float d = ra.z;
 		if (Node3DEditor::get_singleton()->is_snap_enabled()) {
 			d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap());
@@ -3388,7 +3389,7 @@ void CollisionShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_i
 		axis[p_idx] = 1.0;
 		Ref<BoxShape3D> bs = s;
 		Vector3 ra, rb;
-		Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
+		Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
 		float d = ra[p_idx];
 		if (Node3DEditor::get_singleton()->is_snap_enabled()) {
 			d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap());
@@ -3408,7 +3409,7 @@ void CollisionShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_i
 		axis[p_idx == 0 ? 0 : 2] = 1.0;
 		Ref<CapsuleShape3D> cs2 = s;
 		Vector3 ra, rb;
-		Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
+		Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
 		float d = axis.dot(ra);
 		if (p_idx == 1) {
 			d -= cs2->get_radius();
@@ -3434,7 +3435,7 @@ void CollisionShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_i
 		axis[p_idx == 0 ? 0 : 1] = 1.0;
 		Ref<CylinderShape3D> cs2 = s;
 		Vector3 ra, rb;
-		Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
+		Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
 		float d = axis.dot(ra);
 		if (Node3DEditor::get_singleton()->is_snap_enabled()) {
 			d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap());
@@ -3802,7 +3803,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 
 		if (points.size() > 3) {
 			Vector<Vector3> varr = Variant(points);
-			Geometry::MeshData md;
+			Geometry3D::MeshData md;
 			Error err = QuickHull::build(varr, md);
 			if (err == OK) {
 				Vector<Vector3> points2;

+ 2 - 1
editor/plugins/abstract_polygon_2d_editor.cpp

@@ -31,6 +31,7 @@
 #include "abstract_polygon_2d_editor.h"
 
 #include "canvas_item_editor_plugin.h"
+#include "core/math/geometry_2d.h"
 #include "core/os/keyboard.h"
 #include "editor/editor_scale.h"
 
@@ -671,7 +672,7 @@ AbstractPolygon2DEditor::PosVertex AbstractPolygon2DEditor::closest_edge_point(c
 			Vector2 segment[2] = { xform.xform(points[i] + offset),
 				xform.xform(points[(i + 1) % n_points] + offset) };
 
-			Vector2 cp = Geometry::get_closest_point_to_segment_2d(p_pos, segment);
+			Vector2 cp = Geometry2D::get_closest_point_to_segment(p_pos, segment);
 
 			if (cp.distance_squared_to(segment[0]) < eps2 || cp.distance_squared_to(segment[1]) < eps2) {
 				continue; //not valid to reuse point

+ 2 - 2
editor/plugins/animation_blend_space_2d_editor.cpp

@@ -32,7 +32,7 @@
 
 #include "core/input/input.h"
 #include "core/io/resource_loader.h"
-#include "core/math/delaunay_2d.h"
+#include "core/math/geometry_2d.h"
 #include "core/os/keyboard.h"
 #include "core/project_settings.h"
 #include "editor/editor_scale.h"
@@ -165,7 +165,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
 					triangle.push_back(points[idx]);
 				}
 
-				if (Geometry::is_point_in_triangle(mb->get_position(), triangle[0], triangle[1], triangle[2])) {
+				if (Geometry2D::is_point_in_triangle(mb->get_position(), triangle[0], triangle[1], triangle[2])) {
 					selected_triangle = i;
 					_update_tool_erase();
 					return;

+ 2 - 2
editor/plugins/animation_state_machine_editor.cpp

@@ -32,7 +32,7 @@
 
 #include "core/input/input.h"
 #include "core/io/resource_loader.h"
-#include "core/math/delaunay_2d.h"
+#include "core/math/geometry_2d.h"
 #include "core/os/keyboard.h"
 #include "core/project_settings.h"
 #include "editor/editor_scale.h"
@@ -191,7 +191,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
 				transition_lines[i].from,
 				transition_lines[i].to
 			};
-			Vector2 cpoint = Geometry::get_closest_point_to_segment_2d(mb->get_position(), s);
+			Vector2 cpoint = Geometry2D::get_closest_point_to_segment(mb->get_position(), s);
 			float d = cpoint.distance_to(mb->get_position());
 			if (d > transition_lines[i].width) {
 				continue;

+ 2 - 1
editor/plugins/canvas_item_editor_plugin.cpp

@@ -31,6 +31,7 @@
 #include "canvas_item_editor_plugin.h"
 
 #include "core/input/input.h"
+#include "core/math/geometry_2d.h"
 #include "core/os/keyboard.h"
 #include "core/print_string.h"
 #include "core/project_settings.h"
@@ -672,7 +673,7 @@ void CanvasItemEditor::_get_bones_at_pos(const Point2 &p_pos, Vector<_SelectResu
 		}
 
 		// Check if the point is inside the Polygon2D
-		if (Geometry::is_point_in_polygon(screen_pos, bone_shape)) {
+		if (Geometry2D::is_point_in_polygon(screen_pos, bone_shape)) {
 			// Check if the item is already in the list
 			bool duplicate = false;
 			for (int i = 0; i < r_items.size(); i++) {

+ 2 - 1
editor/plugins/collision_polygon_3d_editor_plugin.cpp

@@ -32,6 +32,7 @@
 
 #include "canvas_item_editor_plugin.h"
 #include "core/input/input.h"
+#include "core/math/geometry_2d.h"
 #include "core/os/file_access.h"
 #include "core/os/keyboard.h"
 #include "editor/editor_settings.h"
@@ -196,7 +197,7 @@ bool CollisionPolygon3DEditor::forward_spatial_gui_input(Camera3D *p_camera, con
 									p_camera->unproject_position(gt.xform(Vector3(poly[(i + 1) % poly.size()].x, poly[(i + 1) % poly.size()].y, depth)))
 								};
 
-								Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, points);
+								Vector2 cp = Geometry2D::get_closest_point_to_segment(gpoint, points);
 								if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2) {
 									continue; //not valid to reuse point
 								}

+ 2 - 2
editor/plugins/node_3d_editor_plugin.cpp

@@ -835,7 +835,7 @@ bool Node3DEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_high
 
 			Vector3 r;
 
-			if (Geometry::segment_intersects_sphere(ray_pos, ray_pos + ray * MAX_Z, grabber_pos, grabber_radius, &r)) {
+			if (Geometry3D::segment_intersects_sphere(ray_pos, ray_pos + ray * MAX_Z, grabber_pos, grabber_radius, &r)) {
 				float d = r.distance_to(ray_pos);
 				if (d < col_d) {
 					col_d = d;
@@ -932,7 +932,7 @@ bool Node3DEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_high
 
 			Vector3 r;
 
-			if (Geometry::segment_intersects_sphere(ray_pos, ray_pos + ray * MAX_Z, grabber_pos, grabber_radius, &r)) {
+			if (Geometry3D::segment_intersects_sphere(ray_pos, ray_pos + ray * MAX_Z, grabber_pos, grabber_radius, &r)) {
 				float d = r.distance_to(ray_pos);
 				if (d < col_d) {
 					col_d = d;

+ 4 - 2
editor/plugins/path_3d_editor_plugin.cpp

@@ -30,6 +30,8 @@
 
 #include "path_3d_editor_plugin.h"
 
+#include "core/math/geometry_2d.h"
+#include "core/math/geometry_3d.h"
 #include "core/os/keyboard.h"
 #include "node_3d_editor_plugin.h"
 #include "scene/resources/curve.h"
@@ -344,7 +346,7 @@ bool Path3DEditorPlugin::forward_spatial_gui_input(Camera3D *p_camera, const Ref
 							Vector2 s[2];
 							s[0] = p_camera->unproject_position(from);
 							s[1] = p_camera->unproject_position(to);
-							Vector2 inters = Geometry::get_closest_point_to_segment_2d(mbpos, s);
+							Vector2 inters = Geometry2D::get_closest_point_to_segment(mbpos, s);
 							float d = inters.distance_to(mbpos);
 
 							if (d < 10 && d < closest_d) {
@@ -354,7 +356,7 @@ bool Path3DEditorPlugin::forward_spatial_gui_input(Camera3D *p_camera, const Ref
 								Vector3 ray_dir = p_camera->project_ray_normal(mbpos);
 
 								Vector3 ra, rb;
-								Geometry::get_closest_points_between_segments(ray_from, ray_from + ray_dir * 4096, from, to, ra, rb);
+								Geometry3D::get_closest_points_between_segments(ray_from, ray_from + ray_dir * 4096, from, to, ra, rb);
 
 								closest_seg_point = it.xform(rb);
 							}

+ 2 - 1
editor/plugins/polygon_2d_editor_plugin.cpp

@@ -32,6 +32,7 @@
 
 #include "canvas_item_editor_plugin.h"
 #include "core/input/input.h"
+#include "core/math/geometry_2d.h"
 #include "core/os/file_access.h"
 #include "core/os/keyboard.h"
 #include "editor/editor_scale.h"
@@ -693,7 +694,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
 							polys.write[j] = mtx.xform(points_prev[idx]);
 						}
 
-						if (Geometry::is_point_in_polygon(Vector2(mb->get_position().x, mb->get_position().y), polys)) {
+						if (Geometry2D::is_point_in_polygon(Vector2(mb->get_position().x, mb->get_position().y), polys)) {
 							erase_index = i;
 							break;
 						}

+ 2 - 1
editor/plugins/sprite_2d_editor_plugin.cpp

@@ -31,6 +31,7 @@
 #include "sprite_2d_editor_plugin.h"
 
 #include "canvas_item_editor_plugin.h"
+#include "core/math/geometry_2d.h"
 #include "editor/editor_scale.h"
 #include "scene/2d/collision_polygon_2d.h"
 #include "scene/2d/light_occluder_2d.h"
@@ -233,7 +234,7 @@ void Sprite2DEditor::_update_mesh_data() {
 				computed_vertices.push_back(vtx);
 			}
 
-			Vector<int> poly = Geometry::triangulate_polygon(lines[j]);
+			Vector<int> poly = Geometry2D::triangulate_polygon(lines[j]);
 
 			for (int i = 0; i < poly.size(); i += 3) {
 				for (int k = 0; k < 3; k++) {

+ 2 - 1
main/tests/test_math.cpp

@@ -33,6 +33,7 @@
 #include "core/math/basis.h"
 #include "core/math/camera_matrix.h"
 #include "core/math/delaunay_3d.h"
+#include "core/math/geometry_2d.h"
 #include "core/math/math_funcs.h"
 #include "core/math/transform.h"
 #include "core/method_ptrcall.h"
@@ -635,7 +636,7 @@ MainLoop *test() {
 		b["44"] = 4;
 	}
 
-	print_line("inters: " + rtos(Geometry::segment_intersects_circle(Vector2(-5, 0), Vector2(-2, 0), Vector2(), 1.0)));
+	print_line("inters: " + rtos(Geometry2D::segment_intersects_circle(Vector2(-5, 0), Vector2(-2, 0), Vector2(), 1.0)));
 
 	print_line("cross: " + Vector3(1, 2, 3).cross(Vector3(4, 5, 7)));
 	print_line("dot: " + rtos(Vector3(1, 2, 3).dot(Vector3(4, 5, 7))));

+ 8 - 8
main/tests/test_physics_3d.cpp

@@ -136,9 +136,9 @@ protected:
 
 		/* BOX SHAPE */
 
-		Vector<Plane> box_planes = Geometry::build_box_planes(Vector3(0.5, 0.5, 0.5));
+		Vector<Plane> box_planes = Geometry3D::build_box_planes(Vector3(0.5, 0.5, 0.5));
 		RID box_mesh = vs->mesh_create();
-		Geometry::MeshData box_data = Geometry::build_convex_mesh(box_planes);
+		Geometry3D::MeshData box_data = Geometry3D::build_convex_mesh(box_planes);
 		vs->mesh_add_surface_from_mesh_data(box_mesh, box_data);
 		type_mesh_map[PhysicsServer3D::SHAPE_BOX] = box_mesh;
 
@@ -148,10 +148,10 @@ protected:
 
 		/* CAPSULE SHAPE */
 
-		Vector<Plane> capsule_planes = Geometry::build_capsule_planes(0.5, 0.7, 12, Vector3::AXIS_Z);
+		Vector<Plane> capsule_planes = Geometry3D::build_capsule_planes(0.5, 0.7, 12, Vector3::AXIS_Z);
 
 		RID capsule_mesh = vs->mesh_create();
-		Geometry::MeshData capsule_data = Geometry::build_convex_mesh(capsule_planes);
+		Geometry3D::MeshData capsule_data = Geometry3D::build_convex_mesh(capsule_planes);
 		vs->mesh_add_surface_from_mesh_data(capsule_mesh, capsule_data);
 
 		type_mesh_map[PhysicsServer3D::SHAPE_CAPSULE] = capsule_mesh;
@@ -165,10 +165,10 @@ protected:
 
 		/* CONVEX SHAPE */
 
-		Vector<Plane> convex_planes = Geometry::build_cylinder_planes(0.5, 0.7, 5, Vector3::AXIS_Z);
+		Vector<Plane> convex_planes = Geometry3D::build_cylinder_planes(0.5, 0.7, 5, Vector3::AXIS_Z);
 
 		RID convex_mesh = vs->mesh_create();
-		Geometry::MeshData convex_data = Geometry::build_convex_mesh(convex_planes);
+		Geometry3D::MeshData convex_data = Geometry3D::build_convex_mesh(convex_planes);
 		QuickHull::build(convex_data.vertices, convex_data);
 		vs->mesh_add_surface_from_mesh_data(convex_mesh, convex_data);
 
@@ -341,10 +341,10 @@ public:
 		RenderingServer *vs = RenderingServer::get_singleton();
 		PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
 
-		Vector<Plane> capsule_planes = Geometry::build_capsule_planes(0.5, 1, 12, 5, Vector3::AXIS_Y);
+		Vector<Plane> capsule_planes = Geometry3D::build_capsule_planes(0.5, 1, 12, 5, Vector3::AXIS_Y);
 
 		RID capsule_mesh = vs->mesh_create();
-		Geometry::MeshData capsule_data = Geometry::build_convex_mesh(capsule_planes);
+		Geometry3D::MeshData capsule_data = Geometry3D::build_convex_mesh(capsule_planes);
 		vs->mesh_add_surface_from_mesh_data(capsule_mesh, capsule_data);
 		type_mesh_map[PhysicsServer3D::SHAPE_CAPSULE] = capsule_mesh;
 

+ 3 - 3
main/tests/test_render.cpp

@@ -79,8 +79,8 @@ public:
 		Vector<Vector3> vts;
 
 		/*
-		Vector<Plane> sp = Geometry::build_sphere_planes(2,5,5);
-		Geometry::MeshData md2 = Geometry::build_convex_mesh(sp);
+		Vector<Plane> sp = Geometry3D::build_sphere_planes(2,5,5);
+		Geometry3D::MeshData md2 = Geometry3D::build_convex_mesh(sp);
 		vts=md2.vertices;
 */
 		/*
@@ -118,7 +118,7 @@ public:
 		vts.push_back(Vector3(-1, 1, -1));
 		vts.push_back(Vector3(-1, -1, -1));
 
-		Geometry::MeshData md;
+		Geometry3D::MeshData md;
 		Error err = QuickHull::build(vts, md);
 		print_line("ERR: " + itos(err));
 		test_cube = vs->mesh_create();

+ 1 - 1
modules/bullet/shape_bullet.h

@@ -31,7 +31,7 @@
 #ifndef SHAPE_BULLET_H
 #define SHAPE_BULLET_H
 
-#include "core/math/geometry.h"
+#include "core/math/geometry_3d.h"
 #include "core/variant.h"
 #include "rid_bullet.h"
 #include "servers/physics_server_3d.h"

+ 7 - 7
modules/csg/csg.cpp

@@ -30,7 +30,7 @@
 
 #include "csg.h"
 
-#include "core/math/geometry.h"
+#include "core/math/geometry_2d.h"
 #include "core/math/math_funcs.h"
 #include "core/sort_array.h"
 
@@ -964,7 +964,7 @@ void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_
 						face_points[face_edge_idx],
 						face_points[(face_edge_idx + 1) % 3]
 					};
-					Vector2 closest_point = Geometry::get_closest_point_to_segment_2d(point_2D, edge_points);
+					Vector2 closest_point = Geometry2D::get_closest_point_to_segment(point_2D, edge_points);
 
 					if ((closest_point - point_2D).length_squared() < vertex_snap2) {
 						int opposite_vertex_idx = face.vertex_idx[(face_edge_idx + 2) % 3];
@@ -1028,7 +1028,7 @@ void CSGBrushOperation::Build2DFaces::_find_edge_intersections(const Vector2 p_s
 			// First check if the ends of the segment are on the edge.
 			bool on_edge = false;
 			for (int edge_point_idx = 0; edge_point_idx < 2; ++edge_point_idx) {
-				intersection_point = Geometry::get_closest_point_to_segment_2d(p_segment_points[edge_point_idx], edge_points);
+				intersection_point = Geometry2D::get_closest_point_to_segment(p_segment_points[edge_point_idx], edge_points);
 				if ((intersection_point - p_segment_points[edge_point_idx]).length_squared() < vertex_snap2) {
 					on_edge = true;
 					break;
@@ -1036,7 +1036,7 @@ void CSGBrushOperation::Build2DFaces::_find_edge_intersections(const Vector2 p_s
 			}
 
 			// Else check if the segment intersects the edge.
-			if (on_edge || Geometry::segment_intersects_segment_2d(p_segment_points[0], p_segment_points[1], edge_points[0], edge_points[1], &intersection_point)) {
+			if (on_edge || Geometry2D::segment_intersects_segment(p_segment_points[0], p_segment_points[1], edge_points[0], edge_points[1], &intersection_point)) {
 				// Check if intersection point is an edge point.
 				if ((intersection_point - edge_points[0]).length_squared() < vertex_snap2 ||
 						(intersection_point - edge_points[1]).length_squared() < vertex_snap2) {
@@ -1074,7 +1074,7 @@ void CSGBrushOperation::Build2DFaces::_find_edge_intersections(const Vector2 p_s
 				}
 
 				// If opposite point is on the segemnt, add its index to segment indices too.
-				Vector2 closest_point = Geometry::get_closest_point_to_segment_2d(vertices[opposite_vertex_idx].point, p_segment_points);
+				Vector2 closest_point = Geometry2D::get_closest_point_to_segment(vertices[opposite_vertex_idx].point, p_segment_points);
 				if ((closest_point - vertices[opposite_vertex_idx].point).length_squared() < vertex_snap2) {
 					_add_vertex_idx_sorted(r_segment_indices, opposite_vertex_idx);
 				}
@@ -1141,7 +1141,7 @@ int CSGBrushOperation::Build2DFaces::_insert_point(const Vector2 &p_point) {
 				uvs[(face_edge_idx + 1) % 3]
 			};
 
-			Vector2 closest_point = Geometry::get_closest_point_to_segment_2d(p_point, edge_points);
+			Vector2 closest_point = Geometry2D::get_closest_point_to_segment(p_point, edge_points);
 			if ((closest_point - p_point).length_squared() < vertex_snap2) {
 				on_edge = true;
 
@@ -1192,7 +1192,7 @@ int CSGBrushOperation::Build2DFaces::_insert_point(const Vector2 &p_point) {
 		}
 
 		// If not on an edge, check if the point is inside the face.
-		if (!on_edge && Geometry::is_point_in_triangle(p_point, face_vertices[0].point, face_vertices[1].point, face_vertices[2].point)) {
+		if (!on_edge && Geometry2D::is_point_in_triangle(p_point, face_vertices[0].point, face_vertices[1].point, face_vertices[2].point)) {
 			// Add the point as a new vertex.
 			Vertex2D new_vertex;
 			new_vertex.point = p_point;

+ 4 - 4
modules/csg/csg_gizmos.cpp

@@ -120,7 +120,7 @@ void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Ca
 		CSGSphere3D *s = Object::cast_to<CSGSphere3D>(cs);
 
 		Vector3 ra, rb;
-		Geometry::get_closest_points_between_segments(Vector3(), Vector3(4096, 0, 0), sg[0], sg[1], ra, rb);
+		Geometry3D::get_closest_points_between_segments(Vector3(), Vector3(4096, 0, 0), sg[0], sg[1], ra, rb);
 		float d = ra.x;
 		if (Node3DEditor::get_singleton()->is_snap_enabled()) {
 			d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap());
@@ -139,7 +139,7 @@ void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Ca
 		Vector3 axis;
 		axis[p_idx] = 1.0;
 		Vector3 ra, rb;
-		Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
+		Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
 		float d = ra[p_idx];
 		if (Node3DEditor::get_singleton()->is_snap_enabled()) {
 			d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap());
@@ -168,7 +168,7 @@ void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Ca
 		Vector3 axis;
 		axis[p_idx == 0 ? 0 : 1] = 1.0;
 		Vector3 ra, rb;
-		Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
+		Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
 		float d = axis.dot(ra);
 		if (Node3DEditor::get_singleton()->is_snap_enabled()) {
 			d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap());
@@ -191,7 +191,7 @@ void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Ca
 		Vector3 axis;
 		axis[0] = 1.0;
 		Vector3 ra, rb;
-		Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
+		Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
 		float d = axis.dot(ra);
 		if (Node3DEditor::get_singleton()->is_snap_enabled()) {
 			d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap());

+ 2 - 1
modules/csg/csg_shape.cpp

@@ -29,6 +29,7 @@
 /*************************************************************************/
 
 #include "csg_shape.h"
+#include "core/math/geometry_2d.h"
 #include "scene/3d/path_3d.h"
 
 void CSGShape3D::set_use_collision(bool p_enable) {
@@ -1728,7 +1729,7 @@ CSGBrush *CSGPolygon3D::_build_brush() {
 		final_polygon.invert();
 	}
 
-	Vector<int> triangles = Geometry::triangulate_polygon(final_polygon);
+	Vector<int> triangles = Geometry2D::triangulate_polygon(final_polygon);
 
 	if (triangles.size() < 3) {
 		return nullptr;

+ 2 - 2
modules/gdnavigation/nav_map.cpp

@@ -155,7 +155,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
 					least_cost_poly->poly->points[(i + 1) % least_cost_poly->poly->points.size()].pos
 				};
 
-				const Vector3 new_entry = Geometry::get_closest_point_to_segment(least_cost_poly->entry, edge_line);
+				const Vector3 new_entry = Geometry3D::get_closest_point_to_segment(least_cost_poly->entry, edge_line);
 				const float new_distance = least_cost_poly->entry.distance_to(new_entry) + least_cost_poly->traveled_distance;
 #else
 				const float new_distance = least_cost_poly->poly->center.distance_to(edge.other_polygon->center) + least_cost_poly->traveled_distance;
@@ -413,7 +413,7 @@ Vector3 NavMap::get_closest_point_to_segment(const Vector3 &p_from, const Vector
 			for (size_t point_id = 0; point_id < p.points.size(); point_id += 1) {
 				Vector3 a, b;
 
-				Geometry::get_closest_points_between_segments(
+				Geometry3D::get_closest_points_between_segments(
 						p_from,
 						p_to,
 						p.points[point_id].pos,

+ 2 - 2
modules/gdnavigation/navigation_mesh_generator.cpp

@@ -218,7 +218,7 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform,
 					ConvexPolygonShape3D *convex_polygon = Object::cast_to<ConvexPolygonShape3D>(*s);
 					if (convex_polygon) {
 						Vector<Vector3> varr = Variant(convex_polygon->get_points());
-						Geometry::MeshData md;
+						Geometry3D::MeshData md;
 
 						Error err = QuickHull::build(varr, md);
 
@@ -226,7 +226,7 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform,
 							PackedVector3Array faces;
 
 							for (int j = 0; j < md.faces.size(); ++j) {
-								Geometry::MeshData::Face face = md.faces[j];
+								Geometry3D::MeshData::Face face = md.faces[j];
 
 								for (int k = 2; k < face.indices.size(); ++k) {
 									faces.push_back(md.vertices[face.indices[0]]);

+ 0 - 1
modules/gridmap/grid_map_editor_plugin.cpp

@@ -35,7 +35,6 @@
 #include "editor/plugins/node_3d_editor_plugin.h"
 #include "scene/3d/camera_3d.h"
 
-#include "core/math/geometry.h"
 #include "core/os/keyboard.h"
 #include "scene/main/window.h"
 

+ 6 - 6
modules/lightmapper_rd/lightmapper_rd.cpp

@@ -29,7 +29,7 @@
 /*************************************************************************/
 
 #include "lightmapper_rd.h"
-#include "core/math/geometry.h"
+#include "core/math/geometry_2d.h"
 #include "core/project_settings.h"
 #include "lm_blendseams.glsl.gen.h"
 #include "lm_compute.glsl.gen.h"
@@ -137,7 +137,7 @@ void LightmapperRD::_plot_triangle_into_triangle_index_list(int p_size, const Ve
 		{
 			Vector3 qsize = aabb.size * 0.5; //quarter size, for fast aabb test
 
-			if (!Geometry::triangle_box_overlap(aabb.position + qsize, qsize, p_points)) {
+			if (!Geometry3D::triangle_box_overlap(aabb.position + qsize, qsize, p_points)) {
 				//does not fit in child, go on
 				continue;
 			}
@@ -198,7 +198,7 @@ Lightmapper::BakeError LightmapperRD::_blit_meshes_into_atlas(int p_max_texture_
 		int slices = 0;
 
 		while (source_sizes.size() > 0) {
-			Vector<Vector3i> offsets = Geometry::partial_pack_rects(source_sizes, atlas_size);
+			Vector<Vector3i> offsets = Geometry2D::partial_pack_rects(source_sizes, atlas_size);
 			Vector<int> new_indices;
 			Vector<Vector2i> new_sources;
 			for (int i = 0; i < offsets.size(); i++) {
@@ -488,9 +488,9 @@ void LightmapperRD::_create_acceleration_structures(RenderingDevice *rd, Size2i
 	}
 
 	//generate SDF for raytracing
-	Vector<uint32_t> euclidean_pos = Geometry::generate_edf(solid, Vector3i(grid_size, grid_size, grid_size), false);
-	Vector<uint32_t> euclidean_neg = Geometry::generate_edf(solid, Vector3i(grid_size, grid_size, grid_size), true);
-	Vector<int8_t> sdf8 = Geometry::generate_sdf8(euclidean_pos, euclidean_neg);
+	Vector<uint32_t> euclidean_pos = Geometry3D::generate_edf(solid, Vector3i(grid_size, grid_size, grid_size), false);
+	Vector<uint32_t> euclidean_neg = Geometry3D::generate_edf(solid, Vector3i(grid_size, grid_size, grid_size), true);
+	Vector<int8_t> sdf8 = Geometry3D::generate_sdf8(euclidean_pos, euclidean_neg);
 
 	/*****************************/
 	/*** CREATE GPU STRUCTURES ***/

+ 3 - 2
scene/2d/collision_polygon_2d.cpp

@@ -32,6 +32,7 @@
 
 #include "collision_object_2d.h"
 #include "core/engine.h"
+#include "core/math/geometry_2d.h"
 #include "scene/resources/concave_polygon_shape_2d.h"
 #include "scene/resources/convex_polygon_shape_2d.h"
 
@@ -75,7 +76,7 @@ void CollisionPolygon2D::_build_polygon() {
 }
 
 Vector<Vector<Vector2>> CollisionPolygon2D::_decompose_in_convex() {
-	Vector<Vector<Vector2>> decomp = Geometry::decompose_polygon_in_convex(polygon);
+	Vector<Vector<Vector2>> decomp = Geometry2D::decompose_polygon_in_convex(polygon);
 	return decomp;
 }
 
@@ -224,7 +225,7 @@ bool CollisionPolygon2D::_edit_use_rect() const {
 }
 
 bool CollisionPolygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
-	return Geometry::is_point_in_polygon(p_point, Variant(polygon));
+	return Geometry2D::is_point_in_polygon(p_point, Variant(polygon));
 }
 #endif
 

+ 3 - 2
scene/2d/light_occluder_2d.cpp

@@ -29,6 +29,7 @@
 /*************************************************************************/
 
 #include "light_occluder_2d.h"
+#include "core/math/geometry_2d.h"
 
 #include "core/engine.h"
 
@@ -68,12 +69,12 @@ Rect2 OccluderPolygon2D::_edit_get_rect() const {
 
 bool OccluderPolygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
 	if (closed) {
-		return Geometry::is_point_in_polygon(p_point, Variant(polygon));
+		return Geometry2D::is_point_in_polygon(p_point, Variant(polygon));
 	} else {
 		const real_t d = LINE_GRAB_WIDTH / 2 + p_tolerance;
 		const Vector2 *points = polygon.ptr();
 		for (int i = 0; i < polygon.size() - 1; i++) {
-			Vector2 p = Geometry::get_closest_point_to_segment_2d(p_point, &points[i]);
+			Vector2 p = Geometry2D::get_closest_point_to_segment(p_point, &points[i]);
 			if (p.distance_to(p_point) <= d) {
 				return true;
 			}

+ 2 - 1
scene/2d/line_2d.cpp

@@ -31,6 +31,7 @@
 #include "line_2d.h"
 
 #include "core/core_string_names.h"
+#include "core/math/geometry_2d.h"
 #include "line_builder.h"
 
 // Needed so we can bind functions
@@ -72,7 +73,7 @@ bool Line2D::_edit_is_selected_on_click(const Point2 &p_point, double p_toleranc
 	const real_t d = _width / 2 + p_tolerance;
 	const Vector2 *points = _points.ptr();
 	for (int i = 0; i < _points.size() - 1; i++) {
-		Vector2 p = Geometry::get_closest_point_to_segment_2d(p_point, &points[i]);
+		Vector2 p = Geometry2D::get_closest_point_to_segment(p_point, &points[i]);
 		if (p.distance_to(p_point) <= d) {
 			return true;
 		}

+ 2 - 1
scene/2d/navigation_agent_2d.cpp

@@ -31,6 +31,7 @@
 #include "navigation_agent_2d.h"
 
 #include "core/engine.h"
+#include "core/math/geometry_2d.h"
 #include "scene/2d/navigation_2d.h"
 #include "servers/navigation_server_2d.h"
 
@@ -304,7 +305,7 @@ void NavigationAgent2D::update_navigation() {
 			Vector2 segment[2];
 			segment[0] = navigation_path[nav_path_index - 1];
 			segment[1] = navigation_path[nav_path_index];
-			Vector2 p = Geometry::get_closest_point_to_segment_2d(o, segment);
+			Vector2 p = Geometry2D::get_closest_point_to_segment(o, segment);
 			if (o.distance_to(p) >= path_max_distance) {
 				// To faraway, reload path
 				reload_path = true;

+ 3 - 2
scene/2d/navigation_region_2d.cpp

@@ -32,6 +32,7 @@
 
 #include "core/core_string_names.h"
 #include "core/engine.h"
+#include "core/math/geometry_2d.h"
 #include "core/os/mutex.h"
 #include "navigation_2d.h"
 #include "servers/navigation_server_2d.h"
@@ -73,7 +74,7 @@ bool NavigationPolygon::_edit_is_selected_on_click(const Point2 &p_point, double
 		if (outline_size < 3) {
 			continue;
 		}
-		if (Geometry::is_point_in_polygon(p_point, Variant(outline))) {
+		if (Geometry2D::is_point_in_polygon(p_point, Variant(outline))) {
 			return true;
 		}
 	}
@@ -269,7 +270,7 @@ void NavigationPolygon::make_polygons_from_outlines() {
 			const Vector2 *r2 = ol2.ptr();
 
 			for (int l = 0; l < olsize2; l++) {
-				if (Geometry::segment_intersects_segment_2d(r[0], outside_point, r2[l], r2[(l + 1) % olsize2], nullptr)) {
+				if (Geometry2D::segment_intersects_segment(r[0], outside_point, r2[l], r2[(l + 1) % olsize2], nullptr)) {
 					interscount++;
 				}
 			}

+ 2 - 1
scene/2d/path_2d.cpp

@@ -31,6 +31,7 @@
 #include "path_2d.h"
 
 #include "core/engine.h"
+#include "core/math/geometry_2d.h"
 #include "scene/scene_string_names.h"
 
 #ifdef TOOLS_ENABLED
@@ -73,7 +74,7 @@ bool Path2D::_edit_is_selected_on_click(const Point2 &p_point, double p_toleranc
 			real_t frac = j / 8.0;
 			s[1] = curve->interpolate(i, frac);
 
-			Vector2 p = Geometry::get_closest_point_to_segment_2d(p_point, s);
+			Vector2 p = Geometry2D::get_closest_point_to_segment(p_point, s);
 			if (p.distance_to(p_point) <= p_tolerance) {
 				return true;
 			}

+ 4 - 4
scene/2d/polygon_2d.cpp

@@ -30,7 +30,7 @@
 
 #include "polygon_2d.h"
 
-#include "core/math/geometry.h"
+#include "core/math/geometry_2d.h"
 #include "skeleton_2d.h"
 
 #ifdef TOOLS_ENABLED
@@ -86,7 +86,7 @@ bool Polygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_toler
 	if (internal_vertices > 0) {
 		polygon2d.resize(polygon2d.size() - internal_vertices);
 	}
-	return Geometry::is_point_in_polygon(p_point - get_offset(), polygon2d);
+	return Geometry2D::is_point_in_polygon(p_point - get_offset(), polygon2d);
 }
 #endif
 
@@ -300,7 +300,7 @@ void Polygon2D::_notification(int p_what) {
 			}
 
 			if (invert || polygons.size() == 0) {
-				Vector<int> indices = Geometry::triangulate_polygon(points);
+				Vector<int> indices = Geometry2D::triangulate_polygon(points);
 				if (indices.size()) {
 					RS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID(), -1, normal_map.is_valid() ? normal_map->get_rid() : RID(), specular_map.is_valid() ? specular_map->get_rid() : RID(), Color(specular_color.r, specular_color.g, specular_color.b, shininess));
 				}
@@ -323,7 +323,7 @@ void Polygon2D::_notification(int p_what) {
 						ERR_CONTINUE(idx < 0 || idx >= points.size());
 						tmp_points.write[j] = points[r[j]];
 					}
-					Vector<int> indices = Geometry::triangulate_polygon(tmp_points);
+					Vector<int> indices = Geometry2D::triangulate_polygon(tmp_points);
 					int ic2 = indices.size();
 					const int *r2 = indices.ptr();
 

+ 1 - 1
scene/3d/baked_lightmap.cpp

@@ -559,7 +559,7 @@ void BakedLightmap::_plot_triangle_into_octree(GenProbesOctree *p_cell, float p_
 		subcell.position = Vector3(pos) * p_cell_size;
 		subcell.size = Vector3(half_size, half_size, half_size) * p_cell_size;
 
-		if (!Geometry::triangle_box_overlap(subcell.position + subcell.size * 0.5, subcell.size * 0.5, p_triangle)) {
+		if (!Geometry3D::triangle_box_overlap(subcell.position + subcell.size * 0.5, subcell.size * 0.5, p_triangle)) {
 			continue;
 		}
 

+ 2 - 1
scene/3d/collision_polygon_3d.cpp

@@ -31,6 +31,7 @@
 #include "collision_polygon_3d.h"
 
 #include "collision_object_3d.h"
+#include "core/math/geometry_2d.h"
 #include "scene/resources/concave_polygon_shape_3d.h"
 #include "scene/resources/convex_polygon_shape_3d.h"
 
@@ -45,7 +46,7 @@ void CollisionPolygon3D::_build_polygon() {
 		return;
 	}
 
-	Vector<Vector<Vector2>> decomp = Geometry::decompose_polygon_in_convex(polygon);
+	Vector<Vector<Vector2>> decomp = Geometry2D::decompose_polygon_in_convex(polygon);
 	if (decomp.size() == 0) {
 		return;
 	}

+ 1 - 1
scene/3d/navigation_agent_3d.cpp

@@ -323,7 +323,7 @@ void NavigationAgent3D::update_navigation() {
 			segment[1] = navigation_path[nav_path_index];
 			segment[0].y -= navigation_height_offset;
 			segment[1].y -= navigation_height_offset;
-			Vector3 p = Geometry::get_closest_point_to_segment(o, segment);
+			Vector3 p = Geometry3D::get_closest_point_to_segment(o, segment);
 			if (o.distance_to(p) >= path_max_distance) {
 				// To faraway, reload path
 				reload_path = true;

+ 5 - 5
scene/3d/voxelizer.cpp

@@ -29,7 +29,7 @@
 /*************************************************************************/
 
 #include "voxelizer.h"
-#include "core/math/geometry.h"
+#include "core/math/geometry_3d.h"
 #include "core/os/os.h"
 #include "core/os/threaded_array_processor.h"
 
@@ -124,7 +124,7 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
 				Vector3 half = (to - from) * 0.5;
 
 				//is in this cell?
-				if (!Geometry::triangle_box_overlap(from + half, half, p_vtx)) {
+				if (!Geometry3D::triangle_box_overlap(from + half, half, p_vtx)) {
 					continue; //face does not span this cell
 				}
 
@@ -267,7 +267,7 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
 				//test_aabb.grow_by(test_aabb.get_longest_axis_size()*0.05); //grow a bit to avoid numerical error in real-time
 				Vector3 qsize = test_aabb.size * 0.5; //quarter size, for fast aabb test
 
-				if (!Geometry::triangle_box_overlap(test_aabb.position + qsize, qsize, p_vtx)) {
+				if (!Geometry3D::triangle_box_overlap(test_aabb.position + qsize, qsize, p_vtx)) {
 					//if (!Face3(p_vtx[0],p_vtx[1],p_vtx[2]).intersects_aabb2(aabb)) {
 					//does not fit in child, go on
 					continue;
@@ -439,7 +439,7 @@ void Voxelizer::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vec
 				}
 
 				//test against original bounds
-				if (!Geometry::triangle_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs)) {
+				if (!Geometry3D::triangle_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs)) {
 					continue;
 				}
 				//plot
@@ -471,7 +471,7 @@ void Voxelizer::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vec
 				}
 
 				//test against original bounds
-				if (!Geometry::triangle_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs)) {
+				if (!Geometry3D::triangle_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs)) {
 					continue;
 				}
 				//plot face

+ 5 - 5
scene/animation/animation_blend_space_2d.cpp

@@ -30,7 +30,7 @@
 
 #include "animation_blend_space_2d.h"
 
-#include "core/math/delaunay_2d.h"
+#include "core/math/geometry_2d.h"
 
 void AnimationNodeBlendSpace2D::get_parameter_list(List<PropertyInfo> *r_list) const {
 	r_list->push_back(PropertyInfo(Variant::VECTOR2, blend_position));
@@ -366,7 +366,7 @@ Vector2 AnimationNodeBlendSpace2D::get_closest_point(const Vector2 &p_point) {
 			points[j] = get_blend_point_position(get_triangle_point(i, j));
 		}
 
-		if (Geometry::is_point_in_triangle(p_point, points[0], points[1], points[2])) {
+		if (Geometry2D::is_point_in_triangle(p_point, points[0], points[1], points[2])) {
 			return p_point;
 		}
 
@@ -375,7 +375,7 @@ Vector2 AnimationNodeBlendSpace2D::get_closest_point(const Vector2 &p_point) {
 				points[j],
 				points[(j + 1) % 3]
 			};
-			Vector2 closest = Geometry::get_closest_point_to_segment_2d(p_point, s);
+			Vector2 closest = Geometry2D::get_closest_point_to_segment(p_point, s);
 			if (first || closest.distance_to(p_point) < best_point.distance_to(p_point)) {
 				best_point = closest;
 				first = false;
@@ -455,7 +455,7 @@ float AnimationNodeBlendSpace2D::process(float p_time, bool p_seek) {
 				points[j] = get_blend_point_position(get_triangle_point(i, j));
 			}
 
-			if (Geometry::is_point_in_triangle(blend_pos, points[0], points[1], points[2])) {
+			if (Geometry2D::is_point_in_triangle(blend_pos, points[0], points[1], points[2])) {
 				blend_triangle = i;
 				_blend_triangle(blend_pos, points, blend_weights);
 				break;
@@ -466,7 +466,7 @@ float AnimationNodeBlendSpace2D::process(float p_time, bool p_seek) {
 					points[j],
 					points[(j + 1) % 3]
 				};
-				Vector2 closest2 = Geometry::get_closest_point_to_segment_2d(blend_pos, s);
+				Vector2 closest2 = Geometry2D::get_closest_point_to_segment(blend_pos, s);
 				if (first || closest2.distance_to(blend_pos) < best_point.distance_to(blend_pos)) {
 					best_point = closest2;
 					blend_triangle = i;

+ 3 - 2
scene/gui/control.cpp

@@ -30,6 +30,7 @@
 
 #include "control.h"
 
+#include "core/math/geometry_2d.h"
 #include "core/message_queue.h"
 #include "core/os/keyboard.h"
 #include "core/os/os.h"
@@ -2293,8 +2294,8 @@ void Control::_window_find_focus_neighbour(const Vector2 &p_dir, Node *p_at, con
 					Vector2 fb = points[(j + 1) % 4];
 
 					Vector2 pa, pb;
-					float d = Geometry::get_closest_points_between_segments(la, lb, fa, fb, pa, pb);
-					//float d = Geometry::get_closest_distance_between_segments(Vector3(la.x,la.y,0),Vector3(lb.x,lb.y,0),Vector3(fa.x,fa.y,0),Vector3(fb.x,fb.y,0));
+					float d = Geometry2D::get_closest_points_between_segments(la, lb, fa, fb, pa, pb);
+					//float d = Geometry2D::get_closest_distance_between_segments(Vector3(la.x,la.y,0),Vector3(lb.x,lb.y,0),Vector3(fa.x,fa.y,0),Vector3(fb.x,fb.y,0));
 					if (d < r_closest_dist) {
 						r_closest_dist = d;
 						*r_closest = c;

+ 3 - 3
scene/resources/animation.cpp

@@ -31,7 +31,7 @@
 #include "animation.h"
 #include "scene/scene_string_names.h"
 
-#include "core/math/geometry.h"
+#include "core/math/geometry_3d.h"
 
 #define ANIM_MIN_LENGTH 0.001
 
@@ -2730,7 +2730,7 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons
 			}
 
 			Vector3 s[2] = { v0, v2 };
-			real_t d = Geometry::get_closest_point_to_segment(v1, s).distance_to(v1);
+			real_t d = Geometry3D::get_closest_point_to_segment(v1, s).distance_to(v1);
 
 			if (d > pd.length() * p_alowed_linear_err) {
 				return false; //beyond allowed error for colinearity
@@ -2820,7 +2820,7 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons
 			}
 
 			Vector3 s[2] = { v0, v2 };
-			real_t d = Geometry::get_closest_point_to_segment(v1, s).distance_to(v1);
+			real_t d = Geometry3D::get_closest_point_to_segment(v1, s).distance_to(v1);
 
 			if (d > pd.length() * p_alowed_linear_err) {
 				return false; //beyond allowed error for colinearity

+ 2 - 1
scene/resources/capsule_shape_2d.cpp

@@ -30,6 +30,7 @@
 
 #include "capsule_shape_2d.h"
 
+#include "core/math/geometry_2d.h"
 #include "servers/physics_server_2d.h"
 #include "servers/rendering_server.h"
 
@@ -48,7 +49,7 @@ Vector<Vector2> CapsuleShape2D::_get_points() const {
 }
 
 bool CapsuleShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
-	return Geometry::is_point_in_polygon(p_point, _get_points());
+	return Geometry2D::is_point_in_polygon(p_point, _get_points());
 }
 
 void CapsuleShape2D::_update_shape() {

+ 2 - 1
scene/resources/concave_polygon_shape_2d.cpp

@@ -30,6 +30,7 @@
 
 #include "concave_polygon_shape_2d.h"
 
+#include "core/math/geometry_2d.h"
 #include "servers/physics_server_2d.h"
 #include "servers/rendering_server.h"
 
@@ -42,7 +43,7 @@ bool ConcavePolygonShape2D::_edit_is_selected_on_click(const Point2 &p_point, do
 
 	const Vector2 *r = s.ptr();
 	for (int i = 0; i < len; i += 2) {
-		Vector2 closest = Geometry::get_closest_point_to_segment_2d(p_point, &r[i]);
+		Vector2 closest = Geometry2D::get_closest_point_to_segment(p_point, &r[i]);
 		if (p_point.distance_to(closest) < p_tolerance) {
 			return true;
 		}

+ 4 - 4
scene/resources/convex_polygon_shape_2d.cpp

@@ -30,17 +30,17 @@
 
 #include "convex_polygon_shape_2d.h"
 
-#include "core/math/geometry.h"
+#include "core/math/geometry_2d.h"
 #include "servers/physics_server_2d.h"
 #include "servers/rendering_server.h"
 
 bool ConvexPolygonShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
-	return Geometry::is_point_in_polygon(p_point, points);
+	return Geometry2D::is_point_in_polygon(p_point, points);
 }
 
 void ConvexPolygonShape2D::_update_shape() {
 	Vector<Vector2> final_points = points;
-	if (Geometry::is_polygon_clockwise(final_points)) { //needs to be counter clockwise
+	if (Geometry2D::is_polygon_clockwise(final_points)) { //needs to be counter clockwise
 		final_points.invert();
 	}
 	PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), final_points);
@@ -48,7 +48,7 @@ void ConvexPolygonShape2D::_update_shape() {
 }
 
 void ConvexPolygonShape2D::set_point_cloud(const Vector<Vector2> &p_points) {
-	Vector<Point2> hull = Geometry::convex_hull_2d(p_points);
+	Vector<Point2> hull = Geometry2D::convex_hull(p_points);
 	ERR_FAIL_COND(hull.size() < 3);
 	set_points(hull);
 }

+ 1 - 1
scene/resources/convex_polygon_shape_3d.cpp

@@ -37,7 +37,7 @@ Vector<Vector3> ConvexPolygonShape3D::get_debug_mesh_lines() {
 
 	if (points.size() > 3) {
 		Vector<Vector3> varr = Variant(points);
-		Geometry::MeshData md;
+		Geometry3D::MeshData md;
 		Error err = QuickHull::build(varr, md);
 		if (err == OK) {
 			Vector<Vector3> lines;

+ 2 - 1
scene/resources/line_shape_2d.cpp

@@ -30,6 +30,7 @@
 
 #include "line_shape_2d.h"
 
+#include "core/math/geometry_2d.h"
 #include "servers/physics_server_2d.h"
 #include "servers/rendering_server.h"
 
@@ -38,7 +39,7 @@ bool LineShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tol
 	Vector2 l[2][2] = { { point - get_normal().tangent() * 100, point + get_normal().tangent() * 100 }, { point, point + get_normal() * 30 } };
 
 	for (int i = 0; i < 2; i++) {
-		Vector2 closest = Geometry::get_closest_point_to_segment_2d(p_point, l[i]);
+		Vector2 closest = Geometry2D::get_closest_point_to_segment(p_point, l[i]);
 		if (p_point.distance_to(closest) < p_tolerance) {
 			return true;
 		}

+ 10 - 10
scene/resources/polygon_path_finder.cpp

@@ -29,7 +29,7 @@
 /*************************************************************************/
 
 #include "polygon_path_finder.h"
-#include "core/math/geometry.h"
+#include "core/math/geometry_2d.h"
 
 bool PolygonPathFinder::_is_point_inside(const Vector2 &p_point) const {
 	int crosses = 0;
@@ -40,7 +40,7 @@ bool PolygonPathFinder::_is_point_inside(const Vector2 &p_point) const {
 		Vector2 a = points[e.points[0]].pos;
 		Vector2 b = points[e.points[1]].pos;
 
-		if (Geometry::segment_intersects_segment_2d(a, b, p_point, outside_point, nullptr)) {
+		if (Geometry2D::segment_intersects_segment(a, b, p_point, outside_point, nullptr)) {
 			crosses++;
 		}
 	}
@@ -114,7 +114,7 @@ void PolygonPathFinder::setup(const Vector<Vector2> &p_points, const Vector<int>
 				Vector2 a = points[e.points[0]].pos;
 				Vector2 b = points[e.points[1]].pos;
 
-				if (Geometry::segment_intersects_segment_2d(a, b, from, to, nullptr)) {
+				if (Geometry2D::segment_intersects_segment(a, b, from, to, nullptr)) {
 					valid = false;
 					break;
 				}
@@ -147,7 +147,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector
 				points[e.points[1]].pos
 			};
 
-			Vector2 closest = Geometry::get_closest_point_to_segment_2d(from, seg);
+			Vector2 closest = Geometry2D::get_closest_point_to_segment(from, seg);
 			float d = from.distance_squared_to(closest);
 
 			if (d < closest_dist) {
@@ -171,7 +171,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector
 				points[e.points[1]].pos
 			};
 
-			Vector2 closest = Geometry::get_closest_point_to_segment_2d(to, seg);
+			Vector2 closest = Geometry2D::get_closest_point_to_segment(to, seg);
 			float d = to.distance_squared_to(closest);
 
 			if (d < closest_dist) {
@@ -200,7 +200,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector
 			Vector2 a = points[e.points[0]].pos;
 			Vector2 b = points[e.points[1]].pos;
 
-			if (Geometry::segment_intersects_segment_2d(a, b, from, to, nullptr)) {
+			if (Geometry2D::segment_intersects_segment(a, b, from, to, nullptr)) {
 				can_see_eachother = false;
 				break;
 			}
@@ -255,7 +255,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector
 						e.points[1] != ignore_from_edge.points[1] &&
 						e.points[0] != ignore_from_edge.points[0] &&
 						e.points[1] != ignore_from_edge.points[0]) {
-					if (Geometry::segment_intersects_segment_2d(a, b, from, points[i].pos, nullptr)) {
+					if (Geometry2D::segment_intersects_segment(a, b, from, points[i].pos, nullptr)) {
 						valid_a = false;
 					}
 				}
@@ -266,7 +266,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector
 						e.points[1] != ignore_to_edge.points[1] &&
 						e.points[0] != ignore_to_edge.points[0] &&
 						e.points[1] != ignore_to_edge.points[0]) {
-					if (Geometry::segment_intersects_segment_2d(a, b, to, points[i].pos, nullptr)) {
+					if (Geometry2D::segment_intersects_segment(a, b, to, points[i].pos, nullptr)) {
 						valid_b = false;
 					}
 				}
@@ -499,7 +499,7 @@ Vector2 PolygonPathFinder::get_closest_point(const Vector2 &p_point) const {
 			points[e.points[1]].pos
 		};
 
-		Vector2 closest = Geometry::get_closest_point_to_segment_2d(p_point, seg);
+		Vector2 closest = Geometry2D::get_closest_point_to_segment(p_point, seg);
 		float d = p_point.distance_squared_to(closest);
 
 		if (d < closest_dist) {
@@ -521,7 +521,7 @@ Vector<Vector2> PolygonPathFinder::get_intersections(const Vector2 &p_from, cons
 		Vector2 b = points[E->get().points[1]].pos;
 
 		Vector2 res;
-		if (Geometry::segment_intersects_segment_2d(a, b, p_from, p_to, &res)) {
+		if (Geometry2D::segment_intersects_segment(a, b, p_from, p_to, &res)) {
 			inters.push_back(res);
 		}
 	}

+ 2 - 1
scene/resources/segment_shape_2d.cpp

@@ -30,12 +30,13 @@
 
 #include "segment_shape_2d.h"
 
+#include "core/math/geometry_2d.h"
 #include "servers/physics_server_2d.h"
 #include "servers/rendering_server.h"
 
 bool SegmentShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
 	Vector2 l[2] = { a, b };
-	Vector2 closest = Geometry::get_closest_point_to_segment_2d(p_point, l);
+	Vector2 closest = Geometry2D::get_closest_point_to_segment(p_point, l);
 	return p_point.distance_to(closest) < p_tolerance;
 }
 

+ 3 - 1
scene/resources/tile_set.cpp

@@ -29,8 +29,10 @@
 /*************************************************************************/
 
 #include "tile_set.h"
+
 #include "core/array.h"
 #include "core/engine.h"
+#include "core/math/geometry_2d.h"
 
 bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
 	String n = p_name;
@@ -1033,7 +1035,7 @@ void TileSet::_decompose_convex_shape(Ref<Shape2D> p_shape) {
 	if (!convex.is_valid()) {
 		return;
 	}
-	Vector<Vector<Vector2>> decomp = Geometry::decompose_polygon_in_convex(convex->get_points());
+	Vector<Vector<Vector2>> decomp = Geometry2D::decompose_polygon_in_convex(convex->get_points());
 	if (decomp.size() > 1) {
 		Array sub_shapes;
 		for (int i = 0; i < decomp.size(); i++) {

+ 2 - 2
servers/physics_2d/collision_solver_2d_sat.cpp

@@ -30,7 +30,7 @@
 
 #include "collision_solver_2d_sat.h"
 
-#include "core/math/geometry.h"
+#include "core/math/geometry_2d.h"
 
 struct _CollectorCallback2D {
 	CollisionSolver2DSW::CallbackResult callback;
@@ -70,7 +70,7 @@ _FORCE_INLINE_ static void _generate_contacts_point_edge(const Vector2 *p_points
 	ERR_FAIL_COND(p_point_count_B != 2);
 #endif
 
-	Vector2 closest_B = Geometry::get_closest_point_to_segment_uncapped_2d(*p_points_A, p_points_B);
+	Vector2 closest_B = Geometry2D::get_closest_point_to_segment_uncapped(*p_points_A, p_points_B);
 	p_collector->call(*p_points_A, closest_B);
 }
 

+ 4 - 4
servers/physics_2d/shape_2d_sw.cpp

@@ -30,7 +30,7 @@
 
 #include "shape_2d_sw.h"
 
-#include "core/math/geometry.h"
+#include "core/math/geometry_2d.h"
 #include "core/sort_array.h"
 
 void Shape2DSW::configure(const Rect2 &p_aabb) {
@@ -205,7 +205,7 @@ bool SegmentShape2DSW::contains_point(const Vector2 &p_point) const {
 }
 
 bool SegmentShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
-	if (!Geometry::segment_intersects_segment_2d(p_begin, p_end, a, b, &r_point)) {
+	if (!Geometry2D::segment_intersects_segment(p_begin, p_end, a, b, &r_point)) {
 		return false;
 	}
 
@@ -556,7 +556,7 @@ bool ConvexPolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Vec
 
 		Vector2 res;
 
-		if (!Geometry::segment_intersects_segment_2d(p_begin, p_end, points[i].pos, points[(i + 1) % point_count].pos, &res)) {
+		if (!Geometry2D::segment_intersects_segment(p_begin, p_end, points[i].pos, points[(i + 1) % point_count].pos, &res)) {
 			continue;
 		}
 
@@ -735,7 +735,7 @@ bool ConcavePolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Ve
 
 						Vector2 res;
 
-						if (Geometry::segment_intersects_segment_2d(p_begin, p_end, a, b, &res)) {
+						if (Geometry2D::segment_intersects_segment(p_begin, p_end, a, b, &res)) {
 							real_t nd = n.dot(res);
 							if (nd < d) {
 								d = nd;

+ 21 - 21
servers/physics_3d/collision_solver_3d_sat.cpp

@@ -29,7 +29,7 @@
 /*************************************************************************/
 
 #include "collision_solver_3d_sat.h"
-#include "core/math/geometry.h"
+#include "core/math/geometry_3d.h"
 
 #define _EDGE_IS_VALID_SUPPORT_THRESHOLD 0.02
 
@@ -67,7 +67,7 @@ static void _generate_contacts_point_edge(const Vector3 *p_points_A, int p_point
 	ERR_FAIL_COND(p_point_count_B != 2);
 #endif
 
-	Vector3 closest_B = Geometry::get_closest_point_to_segment_uncapped(*p_points_A, p_points_B);
+	Vector3 closest_B = Geometry3D::get_closest_point_to_segment_uncapped(*p_points_A, p_points_B);
 	p_callback->call(*p_points_A, closest_B);
 }
 
@@ -124,7 +124,7 @@ static void _generate_contacts_edge_edge(const Vector3 *p_points_A, int p_point_
 	}
 
 	Vector3 closest_A = p_points_A[0] + rel_A * d;
-	Vector3 closest_B = Geometry::get_closest_point_to_segment_uncapped(closest_A, p_points_B);
+	Vector3 closest_B = Geometry3D::get_closest_point_to_segment_uncapped(closest_A, p_points_B);
 	p_callback->call(closest_A, closest_B);
 }
 
@@ -542,11 +542,11 @@ static void _collision_sphere_convex_polygon(const Shape3DSW *p_a, const Transfo
 		return;
 	}
 
-	const Geometry::MeshData &mesh = convex_polygon_B->get_mesh();
+	const Geometry3D::MeshData &mesh = convex_polygon_B->get_mesh();
 
-	const Geometry::MeshData::Face *faces = mesh.faces.ptr();
+	const Geometry3D::MeshData::Face *faces = mesh.faces.ptr();
 	int face_count = mesh.faces.size();
-	const Geometry::MeshData::Edge *edges = mesh.edges.ptr();
+	const Geometry3D::MeshData::Edge *edges = mesh.edges.ptr();
 	int edge_count = mesh.edges.size();
 	const Vector3 *vertices = mesh.vertices.ptr();
 	int vertex_count = mesh.vertices.size();
@@ -839,11 +839,11 @@ static void _collision_box_convex_polygon(const Shape3DSW *p_a, const Transform
 		return;
 	}
 
-	const Geometry::MeshData &mesh = convex_polygon_B->get_mesh();
+	const Geometry3D::MeshData &mesh = convex_polygon_B->get_mesh();
 
-	const Geometry::MeshData::Face *faces = mesh.faces.ptr();
+	const Geometry3D::MeshData::Face *faces = mesh.faces.ptr();
 	int face_count = mesh.faces.size();
-	const Geometry::MeshData::Edge *edges = mesh.edges.ptr();
+	const Geometry3D::MeshData::Edge *edges = mesh.edges.ptr();
 	int edge_count = mesh.edges.size();
 	const Vector3 *vertices = mesh.vertices.ptr();
 	int vertex_count = mesh.vertices.size();
@@ -1124,11 +1124,11 @@ static void _collision_capsule_convex_polygon(const Shape3DSW *p_a, const Transf
 		return;
 	}
 
-	const Geometry::MeshData &mesh = convex_polygon_B->get_mesh();
+	const Geometry3D::MeshData &mesh = convex_polygon_B->get_mesh();
 
-	const Geometry::MeshData::Face *faces = mesh.faces.ptr();
+	const Geometry3D::MeshData::Face *faces = mesh.faces.ptr();
 	int face_count = mesh.faces.size();
-	const Geometry::MeshData::Edge *edges = mesh.edges.ptr();
+	const Geometry3D::MeshData::Edge *edges = mesh.edges.ptr();
 	int edge_count = mesh.edges.size();
 	const Vector3 *vertices = mesh.vertices.ptr();
 
@@ -1257,20 +1257,20 @@ static void _collision_convex_polygon_convex_polygon(const Shape3DSW *p_a, const
 		return;
 	}
 
-	const Geometry::MeshData &mesh_A = convex_polygon_A->get_mesh();
+	const Geometry3D::MeshData &mesh_A = convex_polygon_A->get_mesh();
 
-	const Geometry::MeshData::Face *faces_A = mesh_A.faces.ptr();
+	const Geometry3D::MeshData::Face *faces_A = mesh_A.faces.ptr();
 	int face_count_A = mesh_A.faces.size();
-	const Geometry::MeshData::Edge *edges_A = mesh_A.edges.ptr();
+	const Geometry3D::MeshData::Edge *edges_A = mesh_A.edges.ptr();
 	int edge_count_A = mesh_A.edges.size();
 	const Vector3 *vertices_A = mesh_A.vertices.ptr();
 	int vertex_count_A = mesh_A.vertices.size();
 
-	const Geometry::MeshData &mesh_B = convex_polygon_B->get_mesh();
+	const Geometry3D::MeshData &mesh_B = convex_polygon_B->get_mesh();
 
-	const Geometry::MeshData::Face *faces_B = mesh_B.faces.ptr();
+	const Geometry3D::MeshData::Face *faces_B = mesh_B.faces.ptr();
 	int face_count_B = mesh_B.faces.size();
-	const Geometry::MeshData::Edge *edges_B = mesh_B.edges.ptr();
+	const Geometry3D::MeshData::Edge *edges_B = mesh_B.edges.ptr();
 	int edge_count_B = mesh_B.edges.size();
 	const Vector3 *vertices_B = mesh_B.vertices.ptr();
 	int vertex_count_B = mesh_B.vertices.size();
@@ -1362,11 +1362,11 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
 
 	SeparatorAxisTest<ConvexPolygonShape3DSW, FaceShape3DSW, withMargin> separator(convex_polygon_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
 
-	const Geometry::MeshData &mesh = convex_polygon_A->get_mesh();
+	const Geometry3D::MeshData &mesh = convex_polygon_A->get_mesh();
 
-	const Geometry::MeshData::Face *faces = mesh.faces.ptr();
+	const Geometry3D::MeshData::Face *faces = mesh.faces.ptr();
 	int face_count = mesh.faces.size();
-	const Geometry::MeshData::Edge *edges = mesh.edges.ptr();
+	const Geometry3D::MeshData::Edge *edges = mesh.edges.ptr();
 	int edge_count = mesh.edges.size();
 	const Vector3 *vertices = mesh.vertices.ptr();
 	int vertex_count = mesh.vertices.size();

+ 17 - 17
servers/physics_3d/shape_3d_sw.cpp

@@ -30,7 +30,7 @@
 
 #include "shape_3d_sw.h"
 
-#include "core/math/geometry.h"
+#include "core/math/geometry_3d.h"
 #include "core/math/quick_hull.h"
 #include "core/sort_array.h"
 
@@ -195,7 +195,7 @@ Vector3 RayShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
 		Vector3(0, 0, length)
 	};
 
-	return Geometry::get_closest_point_to_segment(p_point, s);
+	return Geometry3D::get_closest_point_to_segment(p_point, s);
 }
 
 Vector3 RayShape3DSW::get_moment_of_inertia(real_t p_mass) const {
@@ -252,7 +252,7 @@ void SphereShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *
 }
 
 bool SphereShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
-	return Geometry::segment_intersects_sphere(p_begin, p_end, Vector3(), radius, &r_result, &r_normal);
+	return Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(), radius, &r_result, &r_normal);
 }
 
 bool SphereShape3DSW::intersect_point(const Vector3 &p_point) const {
@@ -441,7 +441,7 @@ Vector3 BoxShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
 		s[1] = closest_vertex;
 		s[1][i] = -s[1][i]; //edge
 
-		Vector3 closest_edge = Geometry::get_closest_point_to_segment(p_point, s);
+		Vector3 closest_edge = Geometry3D::get_closest_point_to_segment(p_point, s);
 
 		float d = p_point.distance_to(closest_edge);
 		if (d < min_distance) {
@@ -540,7 +540,7 @@ bool CapsuleShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &
 
 	// test against cylinder and spheres :-|
 
-	collided = Geometry::segment_intersects_cylinder(p_begin, p_end, height, radius, &auxres, &auxn);
+	collided = Geometry3D::segment_intersects_cylinder(p_begin, p_end, height, radius, &auxres, &auxn);
 
 	if (collided) {
 		real_t d = norm.dot(auxres);
@@ -552,7 +552,7 @@ bool CapsuleShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &
 		}
 	}
 
-	collided = Geometry::segment_intersects_sphere(p_begin, p_end, Vector3(0, 0, height * 0.5), radius, &auxres, &auxn);
+	collided = Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(0, 0, height * 0.5), radius, &auxres, &auxn);
 
 	if (collided) {
 		real_t d = norm.dot(auxres);
@@ -564,7 +564,7 @@ bool CapsuleShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &
 		}
 	}
 
-	collided = Geometry::segment_intersects_sphere(p_begin, p_end, Vector3(0, 0, height * -0.5), radius, &auxres, &auxn);
+	collided = Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(0, 0, height * -0.5), radius, &auxres, &auxn);
 
 	if (collided) {
 		real_t d = norm.dot(auxres);
@@ -600,7 +600,7 @@ Vector3 CapsuleShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
 		Vector3(0, 0, height * 0.5),
 	};
 
-	Vector3 p = Geometry::get_closest_point_to_segment(p_point, s);
+	Vector3 p = Geometry3D::get_closest_point_to_segment(p_point, s);
 
 	if (p.distance_to(p_point) < radius) {
 		return p_point;
@@ -691,10 +691,10 @@ Vector3 ConvexPolygonShape3DSW::get_support(const Vector3 &p_normal) const {
 }
 
 void ConvexPolygonShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const {
-	const Geometry::MeshData::Face *faces = mesh.faces.ptr();
+	const Geometry3D::MeshData::Face *faces = mesh.faces.ptr();
 	int fc = mesh.faces.size();
 
-	const Geometry::MeshData::Edge *edges = mesh.edges.ptr();
+	const Geometry3D::MeshData::Edge *edges = mesh.edges.ptr();
 	int ec = mesh.edges.size();
 
 	const Vector3 *vertices = mesh.vertices.ptr();
@@ -755,7 +755,7 @@ void ConvexPolygonShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Ve
 }
 
 bool ConvexPolygonShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
-	const Geometry::MeshData::Face *faces = mesh.faces.ptr();
+	const Geometry3D::MeshData::Face *faces = mesh.faces.ptr();
 	int fc = mesh.faces.size();
 
 	const Vector3 *vertices = mesh.vertices.ptr();
@@ -793,7 +793,7 @@ bool ConvexPolygonShape3DSW::intersect_segment(const Vector3 &p_begin, const Vec
 }
 
 bool ConvexPolygonShape3DSW::intersect_point(const Vector3 &p_point) const {
-	const Geometry::MeshData::Face *faces = mesh.faces.ptr();
+	const Geometry3D::MeshData::Face *faces = mesh.faces.ptr();
 	int fc = mesh.faces.size();
 
 	for (int i = 0; i < fc; i++) {
@@ -806,7 +806,7 @@ bool ConvexPolygonShape3DSW::intersect_point(const Vector3 &p_point) const {
 }
 
 Vector3 ConvexPolygonShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
-	const Geometry::MeshData::Face *faces = mesh.faces.ptr();
+	const Geometry3D::MeshData::Face *faces = mesh.faces.ptr();
 	int fc = mesh.faces.size();
 	const Vector3 *vertices = mesh.vertices.ptr();
 
@@ -844,7 +844,7 @@ Vector3 ConvexPolygonShape3DSW::get_closest_point_to(const Vector3 &p_point) con
 	Vector3 min_point;
 
 	//check edges
-	const Geometry::MeshData::Edge *edges = mesh.edges.ptr();
+	const Geometry3D::MeshData::Edge *edges = mesh.edges.ptr();
 	int ec = mesh.edges.size();
 	for (int i = 0; i < ec; i++) {
 		Vector3 s[2] = {
@@ -852,7 +852,7 @@ Vector3 ConvexPolygonShape3DSW::get_closest_point_to(const Vector3 &p_point) con
 			vertices[edges[i].b]
 		};
 
-		Vector3 closest = Geometry::get_closest_point_to_segment(p_point, s);
+		Vector3 closest = Geometry3D::get_closest_point_to_segment(p_point, s);
 		float d = closest.distance_to(p_point);
 		if (d < min_distance) {
 			min_distance = d;
@@ -986,7 +986,7 @@ void FaceShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_
 }
 
 bool FaceShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
-	bool c = Geometry::segment_intersects_triangle(p_begin, p_end, vertex[0], vertex[1], vertex[2], &r_result);
+	bool c = Geometry3D::segment_intersects_triangle(p_begin, p_end, vertex[0], vertex[1], vertex[2], &r_result);
 	if (c) {
 		r_normal = Plane(vertex[0], vertex[1], vertex[2]).normal;
 		if (r_normal.dot(p_end - p_begin) > 0) {
@@ -1095,7 +1095,7 @@ void ConcavePolygonShape3DSW::_cull_segment(int p_idx, _SegmentCullParams *p_par
 			p_params->vertices[p_params->faces[bvh->face_index].indices[2]]
 		};
 
-		if (Geometry::segment_intersects_triangle(
+		if (Geometry3D::segment_intersects_triangle(
 					p_params->from,
 					p_params->to,
 					vertices[0],

+ 3 - 3
servers/physics_3d/shape_3d_sw.h

@@ -31,7 +31,7 @@
 #ifndef SHAPE_SW_H
 #define SHAPE_SW_H
 
-#include "core/math/geometry.h"
+#include "core/math/geometry_3d.h"
 #include "servers/physics_server_3d.h"
 /*
 
@@ -252,12 +252,12 @@ public:
 };
 
 struct ConvexPolygonShape3DSW : public Shape3DSW {
-	Geometry::MeshData mesh;
+	Geometry3D::MeshData mesh;
 
 	void _setup(const Vector<Vector3> &p_vertices);
 
 public:
-	const Geometry::MeshData &get_mesh() const { return mesh; }
+	const Geometry3D::MeshData &get_mesh() const { return mesh; }
 
 	virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_CONVEX_POLYGON; }
 

+ 1 - 1
servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp

@@ -4295,7 +4295,7 @@ void RasterizerStorageRD::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p
 	uint32_t *tetrahedron = (uint32_t *)&lm->tetrahedra[node * 4];
 	Vector3 points[4] = { lm->points[tetrahedron[0]], lm->points[tetrahedron[1]], lm->points[tetrahedron[2]], lm->points[tetrahedron[3]] };
 	const Color *sh_colors[4]{ &lm->point_sh[tetrahedron[0] * 9], &lm->point_sh[tetrahedron[1] * 9], &lm->point_sh[tetrahedron[2] * 9], &lm->point_sh[tetrahedron[3] * 9] };
-	Color barycentric = Geometry::tetrahedron_get_barycentric_coords(points[0], points[1], points[2], points[3], p_point);
+	Color barycentric = Geometry3D::tetrahedron_get_barycentric_coords(points[0], points[1], points[2], points[3], p_point);
 
 	for (int i = 0; i < 4; i++) {
 		float c = CLAMP(barycentric[i], 0.0, 1.0);

+ 3 - 1
servers/rendering/rendering_server_canvas.cpp

@@ -29,6 +29,8 @@
 /*************************************************************************/
 
 #include "rendering_server_canvas.h"
+
+#include "core/math/geometry_2d.h"
 #include "rendering_server_globals.h"
 #include "rendering_server_raster.h"
 #include "rendering_server_viewport.h"
@@ -774,7 +776,7 @@ void RenderingServerCanvas::canvas_item_add_polygon(RID p_item, const Vector<Poi
 	ERR_FAIL_COND(color_size != 0 && color_size != 1 && color_size != pointcount);
 	ERR_FAIL_COND(uv_size != 0 && (uv_size != pointcount));
 #endif
-	Vector<int> indices = Geometry::triangulate_polygon(p_points);
+	Vector<int> indices = Geometry2D::triangulate_polygon(p_points);
 	ERR_FAIL_COND_MSG(indices.empty(), "Invalid polygon data, triangulation failed.");
 
 	Item::CommandPolygon *polygon = canvas_item->alloc_command<Item::CommandPolygon>();

+ 0 - 1
servers/rendering/rendering_server_scene.h

@@ -33,7 +33,6 @@
 
 #include "servers/rendering/rasterizer.h"
 
-#include "core/math/geometry.h"
 #include "core/math/octree.h"
 #include "core/os/semaphore.h"
 #include "core/os/thread.h"

+ 3 - 3
servers/rendering_server.cpp

@@ -2245,12 +2245,12 @@ void RenderingServer::_camera_set_orthogonal(RID p_camera, float p_size, float p
 	camera_set_orthogonal(p_camera, p_size, p_z_near, p_z_far);
 }
 
-void RenderingServer::mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry::MeshData &p_mesh_data) {
+void RenderingServer::mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry3D::MeshData &p_mesh_data) {
 	Vector<Vector3> vertices;
 	Vector<Vector3> normals;
 
 	for (int i = 0; i < p_mesh_data.faces.size(); i++) {
-		const Geometry::MeshData::Face &f = p_mesh_data.faces[i];
+		const Geometry3D::MeshData::Face &f = p_mesh_data.faces[i];
 
 		for (int j = 2; j < f.indices.size(); j++) {
 #define _ADD_VERTEX(m_idx)                                      \
@@ -2271,7 +2271,7 @@ void RenderingServer::mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry
 }
 
 void RenderingServer::mesh_add_surface_from_planes(RID p_mesh, const Vector<Plane> &p_planes) {
-	Geometry::MeshData mdata = Geometry::build_convex_mesh(p_planes);
+	Geometry3D::MeshData mdata = Geometry3D::build_convex_mesh(p_planes);
 	mesh_add_surface_from_mesh_data(p_mesh, mdata);
 }
 

+ 2 - 2
servers/rendering_server.h

@@ -32,7 +32,7 @@
 #define RENDERING_SERVER_H
 
 #include "core/image.h"
-#include "core/math/geometry.h"
+#include "core/math/geometry_3d.h"
 #include "core/math/transform_2d.h"
 #include "core/object.h"
 #include "core/rid.h"
@@ -1208,7 +1208,7 @@ public:
 
 	virtual RID make_sphere_mesh(int p_lats, int p_lons, float p_radius);
 
-	virtual void mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry::MeshData &p_mesh_data);
+	virtual void mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry3D::MeshData &p_mesh_data);
 	virtual void mesh_add_surface_from_planes(RID p_mesh, const Vector<Plane> &p_planes);
 
 	virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) = 0;