Merge pull request #39051 from Xrayez/geometry-split
Split `Geometry` singleton into `Geometry2D` and `Geometry3D`
This commit is contained in:
commit
1620669f4e
70 changed files with 1503 additions and 1379 deletions
|
@ -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);
|
||||
return Geometry2D::get_closest_point_to_segment(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);
|
||||
}
|
||||
|
||||
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);
|
||||
return Geometry2D::get_closest_point_to_segment_uncapped(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);
|
||||
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);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
bool _Geometry2D::is_polygon_clockwise(const Vector<Vector2> &p_polygon) {
|
||||
return Geometry2D::is_polygon_clockwise(p_polygon);
|
||||
}
|
||||
|
||||
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 _Geometry2D::is_point_in_polygon(const Point2 &p_point, const Vector<Vector2> &p_polygon) {
|
||||
return Geometry2D::is_point_in_polygon(p_point, p_polygon);
|
||||
}
|
||||
|
||||
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<int> _Geometry2D::triangulate_polygon(const Vector<Vector2> &p_polygon) {
|
||||
return Geometry2D::triangulate_polygon(p_polygon);
|
||||
}
|
||||
|
||||
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;
|
||||
Vector<int> _Geometry2D::triangulate_delaunay(const Vector<Vector2> &p_points) {
|
||||
return Geometry2D::triangulate_delaunay(p_points);
|
||||
}
|
||||
|
||||
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;
|
||||
Vector<Point2> _Geometry2D::convex_hull(const Vector<Point2> &p_points) {
|
||||
return Geometry2D::convex_hull(p_points);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Vector<int> _Geometry::triangulate_polygon(const Vector<Vector2> &p_polygon) {
|
||||
return Geometry::triangulate_polygon(p_polygon);
|
||||
}
|
||||
|
||||
Vector<int> _Geometry::triangulate_delaunay_2d(const Vector<Vector2> &p_points) {
|
||||
return Geometry::triangulate_delaunay_2d(p_points);
|
||||
}
|
||||
|
||||
Vector<Point2> _Geometry::convex_hull_2d(const Vector<Point2> &p_points) {
|
||||
return Geometry::convex_hull_2d(p_points);
|
||||
}
|
||||
|
||||
Vector<Vector3> _Geometry::clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane) {
|
||||
return Geometry::clip_polygon(p_points, p_plane);
|
||||
}
|
||||
|
||||
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 _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);
|
||||
|
||||
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", "p1", "q1", "p2", "q2"), &_Geometry2D::get_closest_points_between_segments);
|
||||
|
||||
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);
|
||||
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_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_point_to_segment_uncapped", "point", "s1", "s2"), &_Geometry2D::get_closest_point_to_segment_uncapped);
|
||||
|
||||
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("point_is_inside_triangle", "point", "a", "b", "c"), &_Geometry2D::point_is_inside_triangle);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_uv84_normal_bit", "normal"), &_Geometry::get_uv84_normal_bit);
|
||||
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("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("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("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("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("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("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("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("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("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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
core/math/geometry_2d.cpp
Normal file
384
core/math/geometry_2d.cpp
Normal file
|
@ -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
core/math/geometry_2d.h
Normal file
398
core/math/geometry_2d.h
Normal file
|
@ -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
|
|
@ -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();
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
doc/classes/Geometry3D.xml
Normal file
194
doc/classes/Geometry3D.xml
Normal file
|
@ -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>
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -832,7 +832,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;
|
||||
|
@ -929,7 +929,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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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))));
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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]]);
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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 ***/
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue