godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
89.55k stars 20.69k forks source link

Ragdoll visibility is inconsistent due to culling box problems #73521

Closed henriquelalves closed 8 months ago

henriquelalves commented 1 year ago

Godot version

4.0 RC2

System information

Ubuntu 22.04, Vulkan

Issue description

I'm working on demos for Godot 4.0, and we're having problems with a flickering mesh on a ragdoll. The physical behavior of the ragdoll looks fine, but after rolling the ragdoll around a bit, the mesh suddenly disappears on certain camera angles.

The solution I found was the following:

1- throw "extra cull margin" to the maximum value (maybe max is not needed though, but it must be high enough) 2- disabling the mesh LOD so the extra cull margin won't trigger a lower resolution LOD.

After that, the ragdoll skeleton mesh stopped flickering.

Steps to reproduce

Rolling the Ragdolls around (before the workaround) would consistently trigger this problem, as shown in the video.

bug2.webm

Minimal reproduction project

https://github.com/gdquest-demos/godot-4.0-new-features

The specific demo in question is 3D Physics Nodes.

Calinou commented 1 year ago
eddieataberk commented 1 year ago

I am having the same issue. The solution I found is to call this code when starting ragdoll.

    for child in get_children():
        if child is MeshInstance3D:
            RenderingServer.instance_set_ignore_culling(child.get_instance(), true)

There might be a better solution utilizing Custom AABB but I couldn't make it work.

eddieataberk commented 1 year ago

Another related problem I'm having is when ragdoll starts sometimes characters that are not simulating physics but share the same skeleton name also disappear for no reason.

ruanrothmann commented 11 months ago

Additionally, likely related, even when calling RenderingServer.instance_set_ignore_culling, the shadow is not rendered (I assume at the same times when the object would be incorrectly culled).

unrelated - I'm new to godot and open source - what's the best way of checking whether a fix for an issue such as this is being worked on / has been incorporated into the next release?

ecmjohnson commented 9 months ago

unrelated - I'm new to godot and open source - what's the best way of checking whether a fix for an issue such as this is being worked on / has been incorporated into the next release?

@ruanrothmann Generally you can be pretty confident that if the issue is still open that a fix hasn't been implemented yet, although it's always a good idea to reproduce an issue with the latest code before working on a fix. As for if it's being worked on, that's more challenging to know. If you do make progress in understanding the root cause of an issue, it's a good idea to put a comment explaining what you learned. Even if you don't fix the issue, that can help someone else resolve it.

ecmjohnson commented 9 months ago

This issue is caused by all the ragdolls incorrectly getting the same AABB. This occurs because of the following check:

https://github.com/godotengine/godot/blob/2d0ee20ff30461b6b10f6fdfba87511a0ebc6642/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp#L660-L662

specifically, the mesh->skeleton_aabb_version == skeleton->version condition.

Since all the ragdolls share the same mesh instance, the first call to MeshStorage::mesh_get_aabb() notices that skeleton->version is one greater than mesh->skeleton_aabb_version and correctly computes the AABB. Then, the next skeleton to call MeshStorage::mesh_get_aabb() has a skeleton->version that already matches mesh->skeleton_aabb_version and returns the AABB of the first ragdoll. These AABBs are then transformed for each ragdoll, which is why they do not all cull at the same time.

I think the optimization of not computing the AABB again for an unchanged skeleton makes sense, so I propose adding the skeleton RID to MeshStorage alongside the skeleton_aab_version (say skeleton_aabb_rid), then extending the condition from above to: mesh->skeleton_aabb_rid == p_skeleton && mesh->skeleton_aabb_version == skeleton->version.