|
@@ -806,6 +806,87 @@ float Curve2D::get_bake_interval() const {
|
|
|
return bake_interval;
|
|
|
}
|
|
|
|
|
|
+Vector2 Curve2D::get_closest_point(const Vector2 &p_to_point) const {
|
|
|
+ // Brute force method
|
|
|
+
|
|
|
+ if (baked_cache_dirty)
|
|
|
+ _bake();
|
|
|
+
|
|
|
+ //validate//
|
|
|
+ int pc = baked_point_cache.size();
|
|
|
+ if (pc == 0) {
|
|
|
+ ERR_EXPLAIN("No points in Curve2D");
|
|
|
+ ERR_FAIL_COND_V(pc == 0, Vector2());
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pc == 1)
|
|
|
+ return baked_point_cache.get(0);
|
|
|
+
|
|
|
+ PoolVector2Array::Read r = baked_point_cache.read();
|
|
|
+
|
|
|
+ Vector2 nearest;
|
|
|
+ float nearest_dist = -1.0f;
|
|
|
+
|
|
|
+ for (int i = 0; i < pc - 1; i++) {
|
|
|
+ Vector2 origin = r[i];
|
|
|
+ Vector2 direction = (r[i + 1] - origin) / bake_interval;
|
|
|
+
|
|
|
+ float d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
|
|
|
+ Vector2 proj = origin + direction * d;
|
|
|
+
|
|
|
+ float dist = proj.distance_squared_to(p_to_point);
|
|
|
+
|
|
|
+ if (nearest_dist < 0.0f || dist < nearest_dist) {
|
|
|
+ nearest = proj;
|
|
|
+ nearest_dist = dist;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return nearest;
|
|
|
+}
|
|
|
+
|
|
|
+float Curve2D::get_closest_offset(const Vector2 &p_to_point) const {
|
|
|
+ // Brute force method
|
|
|
+
|
|
|
+ if (baked_cache_dirty)
|
|
|
+ _bake();
|
|
|
+
|
|
|
+ //validate//
|
|
|
+ int pc = baked_point_cache.size();
|
|
|
+ if (pc == 0) {
|
|
|
+ ERR_EXPLAIN("No points in Curve2D");
|
|
|
+ ERR_FAIL_COND_V(pc == 0, 0.0f);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pc == 1)
|
|
|
+ return 0.0f;
|
|
|
+
|
|
|
+ PoolVector2Array::Read r = baked_point_cache.read();
|
|
|
+
|
|
|
+ float nearest = 0.0f;
|
|
|
+ float nearest_dist = -1.0f;
|
|
|
+ float offset = 0.0f;
|
|
|
+
|
|
|
+ for (int i = 0; i < pc - 1; i++) {
|
|
|
+ Vector2 origin = r[i];
|
|
|
+ Vector2 direction = (r[i + 1] - origin) / bake_interval;
|
|
|
+
|
|
|
+ float d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
|
|
|
+ Vector2 proj = origin + direction * d;
|
|
|
+
|
|
|
+ float dist = proj.distance_squared_to(p_to_point);
|
|
|
+
|
|
|
+ if (nearest_dist < 0.0f || dist < nearest_dist) {
|
|
|
+ nearest = offset + d;
|
|
|
+ nearest_dist = dist;
|
|
|
+ }
|
|
|
+
|
|
|
+ offset += bake_interval;
|
|
|
+ }
|
|
|
+
|
|
|
+ return nearest;
|
|
|
+}
|
|
|
+
|
|
|
Dictionary Curve2D::_get_data() const {
|
|
|
|
|
|
Dictionary dc;
|
|
@@ -909,6 +990,8 @@ void Curve2D::_bind_methods() {
|
|
|
ClassDB::bind_method(D_METHOD("get_baked_length"), &Curve2D::get_baked_length);
|
|
|
ClassDB::bind_method(D_METHOD("interpolate_baked", "offset", "cubic"), &Curve2D::interpolate_baked, DEFVAL(false));
|
|
|
ClassDB::bind_method(D_METHOD("get_baked_points"), &Curve2D::get_baked_points);
|
|
|
+ ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Curve2D::get_closest_point);
|
|
|
+ ClassDB::bind_method(D_METHOD("get_closest_offset", "to_point"), &Curve2D::get_closest_offset);
|
|
|
ClassDB::bind_method(D_METHOD("tessellate", "max_stages", "tolerance_degrees"), &Curve2D::tessellate, DEFVAL(5), DEFVAL(4));
|
|
|
|
|
|
ClassDB::bind_method(D_METHOD("_get_data"), &Curve2D::_get_data);
|
|
@@ -1276,6 +1359,87 @@ PoolRealArray Curve3D::get_baked_tilts() const {
|
|
|
return baked_tilt_cache;
|
|
|
}
|
|
|
|
|
|
+Vector3 Curve3D::get_closest_point(const Vector3 &p_to_point) const {
|
|
|
+ // Brute force method
|
|
|
+
|
|
|
+ if (baked_cache_dirty)
|
|
|
+ _bake();
|
|
|
+
|
|
|
+ //validate//
|
|
|
+ int pc = baked_point_cache.size();
|
|
|
+ if (pc == 0) {
|
|
|
+ ERR_EXPLAIN("No points in Curve3D");
|
|
|
+ ERR_FAIL_COND_V(pc == 0, Vector3());
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pc == 1)
|
|
|
+ return baked_point_cache.get(0);
|
|
|
+
|
|
|
+ PoolVector3Array::Read r = baked_point_cache.read();
|
|
|
+
|
|
|
+ Vector3 nearest;
|
|
|
+ float nearest_dist = -1.0f;
|
|
|
+
|
|
|
+ for (int i = 0; i < pc - 1; i++) {
|
|
|
+ Vector3 origin = r[i];
|
|
|
+ Vector3 direction = (r[i + 1] - origin) / bake_interval;
|
|
|
+
|
|
|
+ float d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
|
|
|
+ Vector3 proj = origin + direction * d;
|
|
|
+
|
|
|
+ float dist = proj.distance_squared_to(p_to_point);
|
|
|
+
|
|
|
+ if (nearest_dist < 0.0f || dist < nearest_dist) {
|
|
|
+ nearest = proj;
|
|
|
+ nearest_dist = dist;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return nearest;
|
|
|
+}
|
|
|
+
|
|
|
+float Curve3D::get_closest_offset(const Vector3 &p_to_point) const {
|
|
|
+ // Brute force method
|
|
|
+
|
|
|
+ if (baked_cache_dirty)
|
|
|
+ _bake();
|
|
|
+
|
|
|
+ //validate//
|
|
|
+ int pc = baked_point_cache.size();
|
|
|
+ if (pc == 0) {
|
|
|
+ ERR_EXPLAIN("No points in Curve3D");
|
|
|
+ ERR_FAIL_COND_V(pc == 0, 0.0f);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pc == 1)
|
|
|
+ return 0.0f;
|
|
|
+
|
|
|
+ PoolVector3Array::Read r = baked_point_cache.read();
|
|
|
+
|
|
|
+ float nearest = 0.0f;
|
|
|
+ float nearest_dist = -1.0f;
|
|
|
+ float offset = 0.0f;
|
|
|
+
|
|
|
+ for (int i = 0; i < pc - 1; i++) {
|
|
|
+ Vector3 origin = r[i];
|
|
|
+ Vector3 direction = (r[i + 1] - origin) / bake_interval;
|
|
|
+
|
|
|
+ float d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
|
|
|
+ Vector3 proj = origin + direction * d;
|
|
|
+
|
|
|
+ float dist = proj.distance_squared_to(p_to_point);
|
|
|
+
|
|
|
+ if (nearest_dist < 0.0f || dist < nearest_dist) {
|
|
|
+ nearest = offset + d;
|
|
|
+ nearest_dist = dist;
|
|
|
+ }
|
|
|
+
|
|
|
+ offset += bake_interval;
|
|
|
+ }
|
|
|
+
|
|
|
+ return nearest;
|
|
|
+}
|
|
|
+
|
|
|
void Curve3D::set_bake_interval(float p_tolerance) {
|
|
|
|
|
|
bake_interval = p_tolerance;
|
|
@@ -1404,6 +1568,8 @@ void Curve3D::_bind_methods() {
|
|
|
ClassDB::bind_method(D_METHOD("interpolate_baked", "offset", "cubic"), &Curve3D::interpolate_baked, DEFVAL(false));
|
|
|
ClassDB::bind_method(D_METHOD("get_baked_points"), &Curve3D::get_baked_points);
|
|
|
ClassDB::bind_method(D_METHOD("get_baked_tilts"), &Curve3D::get_baked_tilts);
|
|
|
+ ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Curve3D::get_closest_point);
|
|
|
+ ClassDB::bind_method(D_METHOD("get_closest_offset", "to_point"), &Curve3D::get_closest_offset);
|
|
|
ClassDB::bind_method(D_METHOD("tessellate", "max_stages", "tolerance_degrees"), &Curve3D::tessellate, DEFVAL(5), DEFVAL(4));
|
|
|
|
|
|
ClassDB::bind_method(D_METHOD("_get_data"), &Curve3D::_get_data);
|