-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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
Transform mesh's AABB to skeleton's space when calculating mesh's bounds #84451
Conversation
ef5f774
to
c1790ad
Compare
c1790ad
to
61ce482
Compare
There's a notification for "move mesh's transform" on Node3D. NOTIFICATION_TRANSFORM_CHANGED NOTIFICATION_LOCAL_TRANSFORM_CHANGED you can consider if it's a rare operation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have some comments on a paper review. Godot uses snake_case for variable names. It looks ok.
Now to run the Godot Engine pull request in a compile.
Tempted to run 500 avatars moving to see what happens -- with the aabb calculations performance wise.
61ce482
to
041fe40
Compare
Pushed a new version to address this. I was intend to only do it in the editor, since I assumes the relative transform between mesh and skeleton won't change in runtime. |
Also hope @clayjohn @SlugFiller @lawnjelly can check this out, as this PR follows their previous work. |
041fe40
to
6424ba8
Compare
Added Engine::get_singleton()->is_editor_hint() to make sure only recreat mesh for transform change event in Editor. |
6424ba8
to
7d1a69d
Compare
Oops, looks like swich-case fall through triggered some warnning in linux. Changed the way how it does the editor check. |
As @fire suggested, I made a performance test project based on @Zoomulator's project at #74656 This is the profiler with this fix at 4.1.3. Frame time in range between 120ms - 140ms Looks like this fix do cause some frame time increase. But to be honest, I'm not sure which part causes this result. Because it costs more when culling working correctly: you got more drawcalls to cover. And godot's profiler looks quite rough to me, I can't see time in details. I'll try to do more test on this. |
So I made second performance test, make a new animation, but everything won't get culled in origin code. So both version will have same amount of meshes draw to the viewport. This is the fixed version test result, And this is the second test project I used |
@lawnjelly If you have some spare time, can you review this? |
scene/2d/polygon_2d.cpp
Outdated
|
||
const Transform2D meshTransform = this->get_global_transform(); | ||
const Transform2D skeletonTransform = skeleton_node->get_global_transform(); | ||
const Transform2D mesh_to_sk2d = meshTransform * skeletonTransform.inverse(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may be better to use affine_inverse()
here (that's what I used in 3.x). inverse()
just uses the transpose which is cheaper but doesn't work in some situations (I think transpose depends on being orthonormal but I forget).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ya, transpose is only valid if the matrix is orthonormal. I don't know if this transform is guaranteed to be orthonormal or not. So it's probably safest to use affine_inverse()
} else { | ||
laabb.merge_with(baabb); | ||
} | ||
} | ||
} | ||
|
||
if (found_bone_aabb) { | ||
// Transform skeleton bounds back to mesh's space if any animated AABB applied. | ||
laabb = surface.mesh_to_skeleton_xform.inverse().xform(laabb); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider pre-calculating affine inverse. Again affine_inverse
preferred over inverse, and as it is a little more expensive to calculate, it can just be stored.
This looks great! It turns out to be simpler than #75612 in 3.x, maybe the bone AABBs were unavailable there so it had to jump through some extra hoops. EDIT: Re: performance, as the author says if you compare scenes that are culling differently you are not comparing like with like. It should be pretty ok from what I can see, but have mentioned pre-calculating affine inverse which might be a tad quicker / more accurate. I don't know if @clayjohn might have opinions about storing the relative transform on each surface (even when not used), but maybe it can be reused for 3D skinning (no idea if the same problem exists there in 4.x). I haven't fully tested, but my old test project when I was looking at this seems to work ok and the debug bounds are correct. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approve in principle, see if author wants to make changes for affine inverse.
Also could do with a 4.x maintainer looking over to check they are happy with the housekeeping aspects (I'm not so familiar with rendering in 4.x).
Thanks @lawnjelly for the carefully review. About affine inverse(I dont know this before) and storing inverse matrix. I'm totally fine with these two change. I didn't code these just because I want this change as small as possible, and I don't think a inverse matrix calculation can make any differences per instance in performance wise :) I mean, there at least will be dozens matrix operation in cpu when you do a skeleton animation. Talking about performance, there actually is a more intense place than the inverse matrix. Like, is it correct and faster to mutliply the two matrix before apply to the bone AABB? I just haven't been very clear on the math correction with this. Futher more, can we just generate these AABBs in skeleton space, to save the matrix-aabb operation? Maybe, but there will be more related parts about these AABBs to be consider. I would like to leave these consideration in futher PRs, if we think the time worth it. And again, this PR is more focused on fixing this common issue than optimization as this is not usually the hotspot, I want to keep it as simple and small as possible. |
6ddeea0
to
f0940e7
Compare
Oops, Did I mess up anything? The compare looks so wrong to me |
You did not, you just updated your branch at the same time Now when applying the remaining changes you can do so with |
f0940e7
to
9966a7e
Compare
Looks good to me now. Thanks @AThousandShips |
Looks fine now. 👍 |
There was a problem hiding this 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. Great work! And thanks for your dedication in taking this the extra mile
Thanks for devs' excellent work 💗 |
Hi devs, by no means to push, but is there anything need to be down for this PR to be merged? |
This needs production team to merge, no need to poke reviewers (we generally don't merge). I'm sure they list the approved PRs during merging sprees, but just in case pinging @akien-mga . |
It's tracked for merging soon, but right now we focus on PRs that we want to cherrypick for 4.2.1 imminently, and this seems like one that should have some testing in 4.3-dev before we should consider a cherrypick. |
9966a7e
to
a0cd094
Compare
a0cd094
to
27f71c4
Compare
Thanks! And congrats for your first merged Godot contribution 🎉 |
Cherry-picked for 4.2.2. |
Cherry-picked for 4.1.4. |
Fixes #74656 fixes #81983 fixes #74132, and there maybe more duplicated reports I havent found, since this bug is quite common.
This PR is following @clayjohn 's pr #76184. Thanks to guys working in this threads, they have actually identified the cause of this issue:
It's because when resolving animated meshes AABBs with skeleton. The AABBs is actually in mesh instance's space. But skeleton animation assumes differently: all the meshes are in skeleton's space.
That's why the PR tried to solve it by introduce the mesh item's xform to mesh_get_aabb. But we quickly found item's xform is not enough. As it's a local transform, it means it will still has the bug when the Polygon2d in a different hierarchy with the skeleton.
So I come up with a solution:
Introduce a new transform stored in Mesh::Surface, which contains the transform differences between the Polygon2d and its skeleton. This transform is generated when polygon recreating the mesh. So that in run time, it can be used to transform the bones' AABBs back and forth.
I believe in 3d we have same issue, since the code is shared same logic. And I didn't address 3d part, because I believe this bug in 3d is quite rare, since people tends to have same root space for skinned meshes and skeletons in 3d. So I guess we can leave it for further PRs.
Plz NOTE that this PR is NOT tring to fix every edge cases, like if you move around polygon2d or skeleton's position in runtime, the AABBs will be incorrect until regenerating. And if people move around Polygon2ds in the editor when bones are not in their rest pos, there will be issues not just rect culling but also mesh rendering. I believe these cases are not really intentional usage. Since move mesh's transform after skinning in 3d is really weird practice.
This is my first PR to godot, so let me know if I messed up anything:)