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

Don't try to merge unused bone AABBs in the rendering server #64416

Merged
merged 1 commit into from
Aug 18, 2022

Conversation

aaronfranke
Copy link
Member

This PR fixes #56458. With this PR, the test project works, I can import the beetle car GLB without any errors.

I had investigated this half a year ago and was hoping that someone from rendering could confirm this was the correct fix. However, after thinking it over, I am fairly confident that this is indeed the correct fix.

@lawnjelly
Copy link
Member

Partly I hadn't commented because I'm not familiar with the pipeline for bones in 3d in godot, especially in 4.x.

Ideally it would probably be nice to mark bones as unused in another way (like passing some bitflags or something), but I suspect the original author thought this might be an easy way of stopping some problem at the time (just making size negative). They are probably essentially hacking in this bool into the AABB, either to make the API smaller and simpler, save typing etc, which might be okay to continue this approach, or might not.

There are two potential downsides that jump out:

  1. Could there be legit negative AABBs as a result of bones being mirrored in the skeleton (I don't know, no idea where the AABB calculation code is)
  2. Checking no volume is not as cheap as say, checking a bool or bitflag. But then again it's not super expensive, and unless it appears on a profile probably isn't worth worrying out

So I guess providing (1) doesn't seem to occur (I would check this code rigorously) this might not be bad just to fix the current bug, then see if any more appear. If there are knock bugs you could consider something else.

@YuriSizov
Copy link
Contributor

cc @clayjohn

@reduz
Copy link
Member

reduz commented Aug 16, 2022

This makes sense to me (I will approve)

Copy link
Member

@clayjohn clayjohn left a comment

Choose a reason for hiding this comment

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

Looks good to me too

@clayjohn clayjohn merged commit 982ff7d into godotengine:master Aug 18, 2022
AABB bone = p_surface.bone_aabbs[i];
if (!bone.has_no_volume()) {
mesh->bone_aabbs.write[i].merge_with(p_surface.bone_aabbs[i]);
}
Copy link
Member

@lawnjelly lawnjelly Aug 18, 2022

Choose a reason for hiding this comment

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

Sorry to only notice this just after merging, but should it be:

const AABB &bone = p_surface.bones_aabbs[i];

for a const reference rather than copying the AABB?

And then using bone directly in the next line:

mesh->bone_aabbs.write[i].merge_with(bone);

It is possible the optimizer might optimize this out, but there seems to be little point in copying by value here.

And same in the 2nd section below.

EDIT:
It looks like the name for this optimization is copy elision:
https://en.wikipedia.org/wiki/Copy_elision
But the compiler can't always do it, depending on what jiggery pokery e.g. the accessors do. So it is usually better practice to not depend on this and be explicit about it.

Copy link
Member

@Calinou Calinou Aug 18, 2022

Choose a reason for hiding this comment

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

It looks like the name for this optimization is copy elision:

I remember one of C++17's features being guaranteed copy elision. Since Godot uses C++17 in master, does this address the issue?

Copy link
Member

Choose a reason for hiding this comment

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

I wouldn't rely on anything like that, especially in hot loops. 😁

Be explicit in what you are asking the compiler to do, and you won't go far wrong. If you are vague, be prepared to examine the assembly. Which will take 10x as long as just writing it correctly in the first place.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, I completely forgot about using bone on the next line. And yeah, I'll update the code to have the AABB a const ref.

@permelin
Copy link
Contributor

I have models that still get "AABB size is negative". The problem is that the object that merge_with() is called on is (-1, -1, -1) while this fix only checks if the the argument has no size. Is this a different bug?

I can try to create a minimal GLB if it helps.

@aaronfranke
Copy link
Member Author

@permelin Yes, a new test GLB would be helpful. The test project in the linked issue was fixed with this PR.

@permelin
Copy link
Contributor

@aaronfranke Here it is. It admittedly looks a bit weird, but I started with a humanoid character and reduced it down as much as I could while keeping the error.

Let me know if I should create a new issue.

godot_negative_aabb_minimal.zip

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.

Warnings "AABB size is negative" when importing glTF file with zero-weight bones
7 participants