Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make is_equal_approx separate and make == exact again #32477

Merged
merged 3 commits into from
Nov 7, 2019

Conversation

aaronfranke
Copy link
Member

@aaronfranke aaronfranke commented Oct 2, 2019

This PR fixes the concerns @reduz has about #18992, and fixes #32604

My initial reasoning is that end-user code would almost always want to have equality checks be safe, so that would make sense to have as the default behavior of == for vectors. One concern about this is with performance, but if that was the only concern, performance-critical code could have a separate method for checking this (and some code could also switch to integer vectors later on, too).

This PR restores the old (3.1) functionality of == for vectors etc, and instead introduces some is_equal_approx methods for comparing them. The main reason I think this is the best course of action is that, as @reduz mentioned, we don't want to hide this functionality from the user. It makes sense to require users to be aware of approximate equality and consciously choose it, instead of it just being the default choice for ==. Aside from that, it does also have the advantage of allowing code to run as fast as before.

The first commit adds is_equal_approx internally (exposed in C#) to the types (so, nothing breaking). There is a pre-existing exposed is_equal_approx in Basis that should be replaced in 4.0, I've placed TODO notes in there. The second commit switches internal code that depends on approximate vector equality (such as the lines in #31395) to use the is_equal_approx methods (so, nothing breaking). The third commit exposes is_equal_approx methods and reverts == to check for exact equality again (same behavior as 3.1, so 3.1 projects will still work the same).

One thing I wasn't sure about is with > and >= etc. I think it's desirable to leave these as they currently are, but I could be wrong.

As a side note, this is my 100th pull request on GitHub (and my 51st to the Godot repo). 🎉

core/math/plane.cpp Outdated Show resolved Hide resolved
@akien-mga
Copy link
Member

I would really prefer a PR that only addresses the issues raised in #18992.

It's unclear whether many of the added approximation checks are necessary, and as mentioned by @reduz, they might impair the compiler's ability to perform optimizations.

AFAICT reverting the changes to operators in Plane, Vector2 and Vector3 should be enough for now. The rest can be added in a second step, in a PR that would likely not be merged for 3.2 as it's too late.

@@ -557,28 +557,9 @@ void Basis::set_euler_yxz(const Vector3 &p_euler) {
*this = ymat * xmat * zmat;
}

bool Basis::is_equal_approx(const Basis &a, const Basis &b, real_t p_epsilon) const {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The epsilon is needed afaik because it can be used with different values for different use cases, when matrix is not of unit size. Check those that use is_equal_approx_ratio and leave them alone.

Copy link
Member Author

@aaronfranke aaronfranke Oct 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the matrix is not of unit size, is_equal_approx now handles such cases, since is_equal_approx is called on each component Vector3.

The epsilon override for the pre-existing is_equal_approx is not actually used anywhere in the code base.

I undid changes to is_equal_approx_ratio for Basis, but it's also not actually used anywhere in the code base.

Copy link
Member

@reduz reduz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

leave == comparisons alone if they did not use is_equal_approx originally.

@@ -80,11 +80,11 @@ class Delaunay2D {
}

static bool edge_compare(const Vector<Vector2> &p_vertices, const Edge &p_a, const Edge &p_b) {
if (p_vertices[p_a.edge[0]] == p_vertices[p_b.edge[0]] && p_vertices[p_a.edge[1]] == p_vertices[p_b.edge[1]]) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In many cases there is a good reason for this to have equal signs. When dealing with geometry, vertices may be very close but not be the same one, or sometimes they may be hashed, and this will break it.

Please do not replace == comparisons by is_equal_approx if they did not originally do this.

Copy link
Member Author

@aaronfranke aaronfranke Oct 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -156,11 +153,6 @@ bool Plane::intersects_segment(const Vector3 &p_begin, const Vector3 &p_end, Vec

/* misc */

bool Plane::is_almost_like(const Plane &p_plane) const {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not break compatibility, leave the old function with a deprecate warning.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only used internally, @akien-mga told me to remove it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it's ok to remove this one.

@@ -242,7 +242,7 @@ void CSGBrushOperation::BuildPoly::_clip_segment(const CSGBrush *p_brush, int p_
//check if edge and poly share a vertex, of so, assign it to segment_idx
for (int i = 0; i < points.size(); i++) {
for (int j = 0; j < 2; j++) {
if (segment[j] == points[i].point) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, I dont remember how this was originally, but if it did not use is_equal_approx, then dont replace it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They were originally is_zero_approx(a.distance_to(b)) which is functionally identical to checking for approximate equality except that the old code doesn't work with large vectors. This is necessary to keep #22988 fixed.

@@ -310,7 +310,7 @@ void CSGBrushOperation::BuildPoly::_clip_segment(const CSGBrush *p_brush, int p_
Vector2 edgeseg[2] = { points[edges[i].points[0]].point, points[edges[i].points[1]].point };
Vector2 closest = Geometry::get_closest_point_to_segment_2d(segment[j], edgeseg);

if (closest == segment[j]) {
if (closest.is_equal_approx(segment[j])) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as always, check what this was originally.

@reduz
Copy link
Member

reduz commented Oct 8, 2019

ack stupid github, dont merge this, i only approved the last commit.

@akien-mga akien-mga requested a review from reduz October 8, 2019 14:52
This commit adds exposed behavior for C#
This commit changes behavior for GDScript and C#.

Also did some organizing of the order to logically group related methods, mostly for Rect2 and AABB.
@akien-mga
Copy link
Member

As mentioned, I would really have preferred a PR only addressing the necessary bug fixes, i.e. undoing approximate equality checks added where exact checks are meant to be used.

This PR does that, and adds more utility methods, some cleanup, some refactoring... it makes it big and quite inappropriate to merge at such a late stage in development.

Still, the bug fixes are important and I don't feel like doing a slimmed down version of the PR with only fixes myself. After the last revision and discussing it with @reduz, we agree that the extra enhancements should likely be fine, so let's merge.

@akien-mga akien-mga merged commit 77816fe into godotengine:master Nov 7, 2019
@akien-mga
Copy link
Member

Thanks!

@aaronfranke
Copy link
Member Author

@akien-mga For the record, having only the changes to the == operator would break other things, and I'm not keen on doing that, or creating workarounds in the affected code, just to minimize changes. I'd rather create a comprehensive solution, so I did.

If any further issues are discovered due to merging such a large PR I'll get on it immediately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Failure of mathematical analysis in 3D scene
4 participants