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

Add closed property to Line2D #79182

Merged
merged 1 commit into from
Sep 16, 2023
Merged

Conversation

MewPurPur
Copy link
Contributor

@MewPurPur MewPurPur commented Jul 8, 2023

Closes godotengine/godot-proposals#4330

Also helps some of the use cases in godotengine/godot-proposals#1126

Simplified Line2D's codebase a bit, as it reinvents a bunch of wheels for no reason (or maybe Line2D is very old and the wheels were invented later). This could help in a potential future rework of these files, which have lots of TODOs comments.

Screenshot from 2023-07-08 06-25-18

(the fact it's not representing the gradient properly is unrelated to my PR)

Test project I'm using

PuttingLine2DThroughIntenseTrials.zip

@MewPurPur MewPurPur requested a review from a team as a code owner July 8, 2023 03:35
@MewPurPur MewPurPur force-pushed the polyline-close branch 2 times, most recently from f2e18ab to 77048f7 Compare July 8, 2023 03:44
@MewPurPur MewPurPur requested a review from a team as a code owner July 8, 2023 03:44
@arkology
Copy link
Contributor

arkology commented Jul 8, 2023

Looks like you referenced wrong issue👀

@MewPurPur
Copy link
Contributor Author

Ah, sorry, I put in an issue instead of a proposal. Bugsquad fixed it for me.

kleonc
kleonc previously requested changes Jul 8, 2023
Copy link
Member

@kleonc kleonc left a comment

Choose a reason for hiding this comment

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

Some previous behavior is broken, e.g.:

Before After
Wz3glunb0W godot windows editor x86_64_egbIL6KILb
Last segment broken uvs.
Broken end cap box.

scene/2d/line_builder.cpp Outdated Show resolved Hide resolved
scene/2d/line_2d.cpp Show resolved Hide resolved
scene/2d/line_builder.cpp Outdated Show resolved Hide resolved
@MewPurPur MewPurPur marked this pull request as draft July 8, 2023 12:14
@MewPurPur
Copy link
Contributor Author

MewPurPur commented Jul 8, 2023

Added a test project I made.

@MewPurPur
Copy link
Contributor Author

MewPurPur commented Jul 8, 2023

Addressed the concerns, but this feature is a tougher nut to track than I thought. Sorry, I think I misjudged and put it out way too undercooked. Putting as draft for now until I fix some bugs with the new feature.

p.s. Can I please combine the line_builder and line_2d files? I don't see a reason to not have LineBuilder as a member of line, it's created on every redraw. Or even just as private methods in the Line2D.

@kleonc
Copy link
Member

kleonc commented Jul 8, 2023

p.s. Can I please combine the line_builder and line_2d files? I don't see a reason to not have LineBuilder as a member of line, it's created on every redraw. Or even just as private methods in the Line2D.

Potentially a good idea but I'd suggest not complicating this PR and making it only add the new closed feature. Code refactoring could be done separately in another PR. Simpler for reviewing, tracking potential regressions, etc.

@MewPurPur MewPurPur force-pushed the polyline-close branch 2 times, most recently from 19be64f to c018faf Compare July 8, 2023 23:07
@MewPurPur MewPurPur marked this pull request as ready for review July 8, 2023 23:07
@MewPurPur
Copy link
Contributor Author

MewPurPur commented Jul 8, 2023

image

Well, aside from transparent closed curves being slightly messed up in Bevel and Round joint mode, it works. I changed the gradient to not flip around automatically. If the user wants a smooth transition of shape and color, they should set up the width curve and gradient in a way that achieves this.

Trying to fix those joint modes with transparent lines currently.

scene/2d/line_builder.cpp Outdated Show resolved Hide resolved
scene/2d/line_builder.cpp Outdated Show resolved Hide resolved
scene/2d/line_builder.cpp Outdated Show resolved Hide resolved
scene/2d/line_builder.cpp Outdated Show resolved Hide resolved
scene/2d/line_builder.cpp Outdated Show resolved Hide resolved
scene/2d/line_builder.cpp Outdated Show resolved Hide resolved
@MewPurPur
Copy link
Contributor Author

Huh, I don't think the check fails are on me. I guess I'll rebase then?

Copy link
Member

@kleonc kleonc left a comment

Choose a reason for hiding this comment

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

Note that for a closed line with bevel/round joint modes the joint at the first point is still being drawn twice (would be fine if only halves would be drawn). Visible when not fully opaque:
T0WqqkQEpW
RySuSwsTef
q408xxWoMp

@kleonc kleonc dismissed their stale review August 15, 2023 15:03

Outdated.

@MewPurPur
Copy link
Contributor Author

MewPurPur commented Aug 29, 2023

Unfortunately this behavior is the most reasonable possible way to do this :v

Copy link
Member

@kleonc kleonc left a comment

Choose a reason for hiding this comment

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

So the geometry of the line now indeed seems to be fine.

However, there are still issues with the bevel/round joint modes (for closed line).

  • For bevel/round joint modes the start/end seam goes through the joint's beginning instead of through the line's first point (like it does for the sharp joint mode).
sharp bevel round
9P64WmrVHH N1rJXw732y DQgeNaay4K
  • The UVs at the start/end are also incorrect (as already mentioned in Add closed property to Line2D #79182 (comment)). Specifically, I think V = 0.0 line should also go through the first point (just as the seam mentioned in the previous point). Currently for bevel/round modes the whole joint at the first point has V = 0.0.
sharp bevel round
5j8LEpdSf1 BPVDM6Dwl4 l2d8l5FvD5

If these are too hard to fix then I guess:

  • This PR could be merged, leaving the fixes for subsequent PRs.
  • Edit: it's already like that. 🤦‍♂️ Optionally (if simple enough), the "whole first joint with v = 0.0" issue could be "fixed" in this PR by making the v = 0.0 be at the first joint's start (so it will match e.g. the gradient seam):
    0PLi8i1ahY

@MewPurPur
Copy link
Contributor Author

MewPurPur commented Aug 30, 2023

Sharp joint mode is the absense of a joint; I think the first issue you've brought up surrounds something I basically threw a coin on how to implement: Whether the joint that connects the last line to the first should be the first thing drawn or the last. I made it the first, although I'm now thinking maybe it should be the last.

What you point out to be a broken UV, if I understand you correctly, are actually the leftmost pixels of Godot.svg, since it's the first joint and the line has not yet started (?)

@kleonc
Copy link
Member

kleonc commented Aug 30, 2023

Sharp joint mode is the absense of a joint; I think the first issue you've brought up surrounds something I basically threw a coin on how to implement: Whether the joint that connects the last line to the first should be the first thing drawn or the last. I made it the first, although I'm now thinking maybe it should be the last.

What I'm suggesting is that the joint at the first point should be handled as half-joints at the start/end, not as the whole joint either at the start or end. So the start/end seam would go thought the first point / middle of such joint:
mROHkuRnJV

What you point out to be a broken UV, if I understand you correctly, are actually the leftmost pixels of Godot.svg, since it's the first joint and the line has not yet started (?)

Oh, my bad! It's already like what I've suggested as a potential meh-fix (:man_facepalming::smile:):

0PLi8i1ahY

But what I'm suggesting with 2 half-joints is that the texture seem would go through the middle:
Zo2ChcgTZG

@MewPurPur
Copy link
Contributor Author

MewPurPur commented Aug 30, 2023

The half-joints idea looks quite interesting and should be possible. I'll need some extra logic, but at least no fake pass to only draw a single joint, instead it will be half a joint before the segments drawing logic, half a joint after. I'll also need to modify arc-drawing to be splittable in two.

@MewPurPur
Copy link
Contributor Author

MewPurPur commented Sep 2, 2023

Well, I added the following to the docs of the new property:

Note: The joint between the closing segment and the first segment is drawn first and it samples the [member gradient] and the [member width_curve] at the beginning. This is an implementation detail that might change in a future version.

I'll do some benchmarking now. I implemented a few safe little optimizations so I don't expect the performance with closed = false to be worse than before.

@MewPurPur
Copy link
Contributor Author

MewPurPur commented Sep 2, 2023

Performance is good, maybe even better, and there are no regressions.

@akien-mga akien-mga requested a review from kleonc September 4, 2023 07:01
@akien-mga akien-mga modified the milestones: 4.x, 4.2 Sep 4, 2023
Copy link
Member

@kleonc kleonc left a comment

Choose a reason for hiding this comment

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

I've skimmed through the code. Most things looks fine AFAICT. I'm gonna do some more in-action testing later.


Well, I added the following to the docs of the new property:

Note: The joint between the closing segment and the first segment is drawn first and it samples the [member gradient] and the [member width_curve] at the beginning. This is an implementation detail that might change in a future version.

@MewPurPur Looks like a solution to me! 😄 I'm absolutely fine with just documenting that quirk. 👍

scene/2d/line_builder.cpp Outdated Show resolved Hide resolved
@MewPurPur MewPurPur force-pushed the polyline-close branch 2 times, most recently from 2d9ddba to 6bfbdd2 Compare September 4, 2023 15:49
@MewPurPur
Copy link
Contributor Author

MewPurPur commented Sep 4, 2023

Nice catch, I haven't actually tested if my changes fixed the above but I can't see why they wouldn't

@MewPurPur MewPurPur force-pushed the polyline-close branch 2 times, most recently from a39cc3a to 9cb006f Compare September 11, 2023 06:47
Copy link
Member

@AThousandShips AThousandShips left a comment

Choose a reason for hiding this comment

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

Style and docs looks good!

Copy link
Member

@kleonc kleonc left a comment

Choose a reason for hiding this comment

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

So today I've finally done some procedural testing against potential regressions, by brute force comparing every rendered pixel for some specific configurations of line parameters (8748 images per tested build = 3 * 3 * 3 begin/end/joint types * 2 widths * 9 different width curves (including no curve) * 6 different line types (UV stretched/tiled, solid color + translucent, gradient + translucent) * 3 different point densities (default points + subdivided twice)). Stuff like:
ShBJCot64E

The results are that there are slight differences between this PR and other versions (which all produce the exact same results between themselves) like: v4.1.1.stable.official [bd6af8e], v4.2.dev1.official [0c2144d], v4.2.dev4.official [549fcce], or some random artifact downloaded from a recent GH action for master (v4.2.dev.custom_build [a79955c]).

However, the mentioned differences are AFAICT negligible. These are either:

  • a single pixel "missing" (non-background vs background),
  • or some pixels mismatched by approximately no more than 1.0 / 255.0.

Here's an example of a test case with the highest difference count, specifically 34 pixels mismatched where:

  • 1 pixel "missing" (pointed by the arrows),
  • 33 pixels off by approx no more than 1.0 / 255.0 (can you spot them?:smile::mag:).
Honeyview_c6PNOrANuY nvgL32nMaD

I've rechecked the code and the only change I suspect could have resulted in such small discrepancies is that segment intersection check is now done with Geometry2D::segment_intersects_segment instead of a custom method. But haven't verified it anyhow.

Anyway, I doubt anyone will notice anything has changed. 🙃


Overall LGTM and seems to be working fine. 👍
(@MewPurPur Thanks for all your patience! 🙂)

@MewPurPur
Copy link
Contributor Author

Thanks, this PR was lots of fun! Except for the part where width curves bullied me

@akien-mga akien-mga merged commit 4c01c62 into godotengine:master Sep 16, 2023
@akien-mga
Copy link
Member

Thanks!

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.

Add a closed property to Line2D
8 participants