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

Spaces between circles in GDPaint #846

Open
michaldev opened this issue Feb 17, 2023 · 11 comments
Open

Spaces between circles in GDPaint #846

michaldev opened this issue Feb 17, 2023 · 11 comments

Comments

@michaldev
Copy link

michaldev commented Feb 17, 2023

Hi. Why in your demo I have spaces between circles? How can i fix it?

Nagranie.z.ekranu.2023-02-17.o.21.02.20.mov
@michaldev michaldev added the bug label Feb 17, 2023
@Calinou
Copy link
Member

Calinou commented Feb 17, 2023

This is because Bresenham's line algorithm needs to be implemented in the demo, placing a circle every pixel between the last two reported input events (or perhaps every 2 pixels to improve performance, at least with larger circle sizes).

Feel free to open a pull request for this 🙂

@Calinou Calinou added enhancement and removed bug labels Feb 17, 2023
@michaldev
Copy link
Author

Something like Line2D (points between mouse movement)?

@Calinou
Copy link
Member

Calinou commented Feb 17, 2023

Something like Line2D (points between mouse movement)?

No, the Bresenham algorithm is something you can implement with relative ease in GDScript. No high-level nodes should be used here.

See this implementation in C++ from Godot itself: https://github.com/godotengine/godot/blob/0c27edf3d971bd3accffbaee5c57da33d0549284/core/math/geometry_2d.h#L426-L462

The C++ implementation isn't exposed to the scripting API, but this could likely be done in a future 4.x release.

@michaldev
Copy link
Author

michaldev commented Feb 17, 2023

Why something like this is bad method (it works)?

func _draw():
	var index = 0
	for point in _points:
		if (len(_points) != index+1):
			var brush_size = 10
			draw_circle(point, brush_size, Color.NAVY_BLUE)
			draw_line(point, _points[index+1], Color.NAVY_BLUE, brush_size*2)
		index += 1

@Calinou
Copy link
Member

Calinou commented Feb 17, 2023

Why something like this is bad method (it works)?

Can you show a video/GIF of drawing lines with fast mouse motion with this method? While not ideal (and not applicable to all situations), it might be good enough for this particular demo.

@michaldev
Copy link
Author

michaldev commented Feb 17, 2023

Nagranie.z.ekranu.2023-02-18.o.00.14.32.mov

@Calinou
Copy link
Member

Calinou commented Feb 17, 2023

@michaldev Looks good! Please open a pull request 🙂

@michaldev
Copy link
Author

michaldev commented Feb 28, 2023

I tested this solution for a longer time and I think it's not very good - when there are more drawn lines, significant delays appear between the mouse cursor and the currently drawn line.

And technically, I think that a lot of unnecessary objects are created.

@Calinou
Copy link
Member

Calinou commented Mar 1, 2023

I tested this solution for a longer time and I think it's not very good - when there are more drawn lines, significant delays appear between the mouse cursor and the currently drawn line.

The way the demo is designed allows for more flexibility, but it was never intended to be as fast as possible. It's a proof of concept after all 🙂

@dalexeev
Copy link
Member

This is because Bresenham's line algorithm needs to be implemented in the demo

@Zylann
Copy link

Zylann commented Dec 14, 2023

Not familiar with this demo, but I wonder why bresenham's line algorithm would be so useful here? I mean, I guess it would work eventually, but it's a circular brush. Bresenham only gives you a series of jagged positions for a single-pixel line, allocating a long array as well. Using it repeatedly to fill a thicker line one by one (especially as shown earlier) doesn't seem great for performance when the GPU can draw the same thing with a few polygons. Using it to draw many circles every 2 pixels wouldn't be good either. Assuming this is painting on a Viewport, #846 (comment) would work better, although for opaque colors only. It won't do well with transparent, and wont scale well if every line and circular joint is drawn as separate calls. I think the algorithm Line2D uses would work better out of the box (draws all at once, with circular joints and no overlaps with transparent colors), but since it wasn't used in draw_polyline, to be used here it requires a few more code changes compared to a function call (need to instantiate a node). But it depends what the demo wants to show of course.
On the other hand, if the brush was a transparent image instead, drawing it many times alongside the path would be the only way to "smear" it (but would not need bresenham either I think). However that would be a different issue.

Regarding slowdown when many things are drawn, it can be brought down to zero by "printing" what's been drawn so far into a background image. Usually can be done if the canvas is a Viewport that doesn't clear. But again, maybe it's not the goal to have many fancy and optimized features in the demo.

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

No branches or pull requests

4 participants