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

Path3D has editor performance issues when points are added over a long distance #81707

Open
sketchyfun opened this issue Sep 15, 2023 · 15 comments · May be fixed by #90357
Open

Path3D has editor performance issues when points are added over a long distance #81707

sketchyfun opened this issue Sep 15, 2023 · 15 comments · May be fixed by #90357

Comments

@sketchyfun
Copy link
Contributor

sketchyfun commented Sep 15, 2023

Godot version

v4.2.dev.custom_build [da81ca6]

System information

Godot v4.2.dev (da81ca6) - Windows 10.0.19045 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 3060 (NVIDIA; 31.0.15.3699) - AMD Ryzen 5 2600 Six-Core Processor (12 Threads)

Issue description

I noticed that when I loaded up one of my game's levels that uses a long Path3D, the editor was slow to respond when I initially selected the Path3D node, and then when I was panning around with the camera, there were intermittent hiccups in the performance and the editor would freeze for a second.

If you create a Path3D with a bunch of points while zoomed right in, the performance is okay, but if you zoom all the way out and start adding points, it takes longer and longer to process as you add each new point. I also found that after I'd added the points, if I panned the camera around I'd get random stutters/freezes like something is being re-calculated as the view changes.

Steps to reproduce

Create a Path3D node
Zoom all the way out and start adding a bunch of points
Notice the editor become less responsive as more points are added (not that many are needed to cause this, maybe 15 or so)
With the Path3D node still selected, pan the camera around continuously and you may notice some stutters (how long it takes to happen for me is a bit inconsistent, but usually after a few seconds it starts happening)

Minimal reproduction project

I don't think a minimal reproduction project is really needed

@AThousandShips
Copy link
Member

Can you try with a recent version of 4.2? Your build is about two months old

@sketchyfun
Copy link
Contributor Author

Can you try with a recent version of 4.2? Your build is about two months old

Sorry, I should have mentioned I've also tried it with a build from master that I built today

@Calinou
Copy link
Member

Calinou commented Sep 15, 2023

Can you reproduce this in 4.1.1? I wonder if this is a regression from #80329.

@sketchyfun
Copy link
Contributor Author

sketchyfun commented Sep 16, 2023

Can you reproduce this in 4.1.1? I wonder if this is a regression from #80329.

Yep, still happens in 4.1.1, and it even happens all the way back in the first stable release of 4.0 as well

I've just tried it in 3.3 (which is what I was using before moving to 4.x) and I can keep adding points while fully zoomed out and there's no drop in performance at all

@Calinou
Copy link
Member

Calinou commented Sep 16, 2023

Can you reproduce this in 3.5.2? If not, can you test 4.0 alphas and betas? This would help pinpoint the regression more accurately, as there are a lot of commits to cover before we should start bisecting.

@sketchyfun
Copy link
Contributor Author

Okay, I've just gone through some of the betas and I've found that it started with Beta 8, everything before that (including 3.5.2) is fine

@xiongyaohua
Copy link
Contributor

@sketchyfun Seems working on my computer. Could you provide a minimal reproduction project? I'd like to investigate if it is somehow caused by my curve baking code refactor.

@sketchyfun
Copy link
Contributor Author

@sketchyfun Seems working on my computer. Could you provide a minimal reproduction project? I'd like to investigate if it is somehow caused by my curve baking code refactor.

I didn't add a minimal project because part of the issue appears when actually adding the points, after several points have been added, it starts to get slower and slower to add new points. If I made a project, it would just be a path with some points already added, there's really nothing else to it. Maybe it's system specific, but I'm not sure why that would be..

@matheusmdx
Copy link
Contributor

I can confirm that happens in the master version, i also bisected between beta 7 and beta 9 and this started to happen after #68860

I did some test and what i found was:

  1. In both master and Draw fish bones for Path3D and Path2D in the Editor #68860 the freeze happens when you move the camera with Path3D selected, if you deselect the node, the freeze stops
  2. The freeze also happens if you change for another scene and click to go back for the scene with Path3D, even if Path3D node wasn't selected and to close the engine too
  3. The zoom per-se doesn't seems be the problem, but have points too far from each other is
  4. In Draw fish bones for Path3D and Path2D in the Editor #68860 you can easily trigger the freeze even with points close each other, also the console spams the error: "The target vector can't be zero."

I compiled both master and #68860 with scons default options

My specs:
Godot v4.2.dev unknown - Windows 10.0.19045 - Vulkan (Forward+) - dedicated AMD Radeon RX 580 2048SP (Advanced Micro Devices, Inc.; 31.0.21029.1006) - AMD Ryzen 5 3600 6-Core Processor (12 Threads)

Demonstrating the bug in master: https://www.youtube.com/watch?v=YouQkKOZaWY
Demonstrating the bug in #68860: https://www.youtube.com/watch?v=E48LaOw4_ps

@sketchyfun
Copy link
Contributor Author

sketchyfun commented Sep 19, 2023

Edit: Although the fish bones are contributing to the issue, I've found it's not the entire reason for the performance issues. I think the bigger problem is simply how subdivided the path is when it's drawn, especially since the same number of points used to draw the line are used to generate the collision segments (so the path can be clicked on).

I've done a bit of testing, and it's definitely the fish bones that are slowing it down. The issue is that there's just too many of them being drawn unnecessarily. You only have to be zoomed out slightly and they're barely visible, and yet with two points only 4 units apart, there's 50 fish bones being drawn. I checked how many were drawn when I was fully zoomed out (thus adding points large distances apart) and after I'd added around 45 points, there were almost 150,000 fish bones being drawn.

I think the code needs to be changed so that the amount of fish bones drawn takes the zoom level into account or the on-screen distance between each point, so that there isn't an excessive amount of them drawn. I'll look into this myself, but I can't promise anything.

xiongyaohua added a commit to xiongyaohua/godot that referenced this issue Nov 28, 2023
Path3D notify transform change to CSGPolygon.
@xiongyaohua
Copy link
Contributor

xiongyaohua commented Nov 28, 2023

Further investigate this problem a bit, find something interesting. I reported in previous comment that I cannot reproduce this problem . It turns out that's because I was rotating the camera with the "ball gizmo" at the upper-right corner of the viewport. If I rotate with middle mouse button, then there is the stutter.

So my hypothesis is that the stutter is not related with drawing at all, but with the mouse event handling, which somehow trigger the collision detection code path. Then I checked the code of EditorNode3DGizmo::intersect_ray, which strengthened the suspicion, as this method does a linear search for all line segment one-by-one.

So I think the solution should be optimizing the collision detection code. For example, substitute collision_segment with collision_mesh, as the latter has BVH acceleration structure. I will try this route when I have more time.

@Zireael07
Copy link
Contributor

@xiongyaohua This reminds me, someone else recently reported a stutter with mouse camera rotating....

@Calinou
Copy link
Member

Calinou commented Dec 7, 2023

@xiongyaohua This reminds me, someone else recently reported a stutter with mouse camera rotating....

There's #80941 but it's caused by an unrelated Vulkan issue (#84137).

There is also #52378 but it's not related to this issue either.

@AyyZerrAsa
Copy link

I'm not getting any stutters myself when rotating the camera, but dragging points over large distances is awfully laggy. Adding points over long distances can also cause hitches. Definitely related to how long the spline is in world-space.

@AyyZerrAsa
Copy link

Setting the interval value higher here helps to alleviate the issue, but only temporarily. You'll end up hitting a threshold where it starts to chug. The simplest solution is probably to match Blender's functionality. A resolution value that defines a fixed number of intervals between two spline points.

real_t interval = 0.1;
const real_t length = c->get_baked_length();
// 1. Draw curve and bones.
if (length > CMP_EPSILON) {
const int sample_count = int(length / interval) + 2;
interval = length / (sample_count - 1); // Recalculate real interval length.
Vector<Transform3D> frames;
frames.resize(sample_count);
{
Transform3D *w = frames.ptrw();
for (int i = 0; i < sample_count; i++) {
w[i] = c->sample_baked_with_rotation(i * interval, true, true);
}
}
const Transform3D *r = frames.ptr();
Vector<Vector3> _collision_segments;
_collision_segments.resize((sample_count - 1) * 2);
Vector3 *_collisions_ptr = _collision_segments.ptrw();
Vector<Vector3> bones;
bones.resize(sample_count * 4);
Vector3 *bones_ptr = bones.ptrw();
Vector<Vector3> ribbon;
ribbon.resize(sample_count);
Vector3 *ribbon_ptr = ribbon.ptrw();
for (int i = 0; i < sample_count; i++) {
const Vector3 p1 = r[i].origin;
const Vector3 side = r[i].basis.get_column(0);
const Vector3 up = r[i].basis.get_column(1);
const Vector3 forward = r[i].basis.get_column(2);
// Collision segments.
if (i != sample_count - 1) {
const Vector3 p2 = r[i + 1].origin;
_collisions_ptr[(i * 2)] = p1;
_collisions_ptr[(i * 2) + 1] = p2;
}
// Path3D as a ribbon.
ribbon_ptr[i] = p1;
// Fish Bone.
const Vector3 p_left = p1 + (side + forward - up * 0.3) * 0.06;
const Vector3 p_right = p1 + (-side + forward - up * 0.3) * 0.06;
const int bone_idx = i * 4;
bones_ptr[bone_idx] = p1;
bones_ptr[bone_idx + 1] = p_left;
bones_ptr[bone_idx + 2] = p1;
bones_ptr[bone_idx + 3] = p_right;
}
add_collision_segments(_collision_segments);
add_lines(bones, path_material);
add_vertices(ribbon, path_material, Mesh::PRIMITIVE_LINE_STRIP);
}

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

Successfully merging a pull request may close this issue.

7 participants