-
-
Notifications
You must be signed in to change notification settings - Fork 35.2k
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
Remove force flag and make Object3D.matrixWorldAutoUpdate
work properly again
#27261
Open
DolphinIQ
wants to merge
5
commits into
mrdoob:dev
Choose a base branch
from
DolphinIQ:remove-force-flag
base: dev
Could not load branches
Branch not found: {{ refName }}
Could not load tags
Nothing to show
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
772955d
Remove force flag set, which makes object3d.matrixWorldAutoUpdate red…
DolphinIQ 237a984
Add matrixWorldAutoUpdate condition to obj.updateMatrixWorld
DolphinIQ 16314fc
Restore tests
DolphinIQ cfb0516
restore volume stuff
DolphinIQ e49af41
fix tests
DolphinIQ File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 had some time now to study the PR more closely (and
matrixWorldAutoUpdate
in general) and I think this PR goes in the right direction!However, there is one thing that confuses me: The comment
update children
in this method is actually wrong. This should actually be calledupdate descendants
since when a world matrix changes, you want to update not just the world matrices of children but of all subsequent nodes in the hierarchy.Hence, I think it was wrong to add
child.matrixWorldAutoUpdate === true
to this code block because it prevents updates that might be wanted further down the hierarchy. This PR puts thematrixWorldAutoUpdate
check at the right place (further up in the method where the world matrix of a node is actually computed).So how about writing the code like so 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.
Hi @Mugen87 , thanks for having a look!
Have you tested your code? Your argument about descendants makes sense conceptually, however in the current configuration I believe it would cause world matrix updates regardless of
.matrixWorldAutoUpdate
, because:updateMatrixWorld()
on its descendantsdescendant.matrixAutoUpdate
and performsdescendant.updateMatrix()
updateMatrix()
setsdescendant.matrixWorldNeedsUpdate = true
if ( this.matrixWorldNeedsUpdate || this.matrixWorldAutoUpdate === true || force ) {
passes, once again regardless ofdescendant.matrixWorldAutoUpdate
In other words, as long as object has
object.matrixAutoUpdate
set totrue
, it will overrideobject.matrixWorldAutoUpdate
. If we wanted to go the way you propose and keepobject.matrixWorldNeedsUpdate
relevant, we would have to either:a) eliminate
descendant.matrixWorldNeedsUpdate = true
fromupdateMatrix()
or...b) in the second
if
statementif ( this.matrixWorldNeedsUpdate || this.matrixWorldAutoUpdate === true || force ) {
havethis.matrixWorldAutoUpdate
somehow override thethis.matrixWorldNeedsUpdate
flag if necessary.My use-case (which has led to discovery of this bug) was setting skinned mesh's
rootBone.matrixWorldAutoUpdate = false
(rootBone.matrixAutoUpdate
is left to defaulttrue
) to prevent skeleton matrices updates and perform it manually when needed. The current way is convenient because setting.matrixWorldAutoUpdate
on the root object automatically prevents world updates of its descendants. You might say it makes.matrixAutoUpdate
obsolete because the local matrix wont be updated either, but I think there is no reason to update local matrix if we dont update world matrix, since it is the latter that is sent to the shader anyway.Thus I believe it is the
object.matrixWorldAutoUpdate
that should take precedence overobject.matrixAutoUpdate
.It would be less convenient (although maybe more logical? 🤔) if traversal of descendants happens regardless (in the case of your change), as then in order to prevent all world matrix updates, you'd have to first traverse the entire object and set
.matrixWorldAutoUpdate
tofalse
on each and every descendant instead of just the root object.I am not sure if it even makes sense for descendant to update world matrix
if the
parent.matrixWorld
stayed the same. But maybe it makes sense for descendants deeper in the graph?What would be some use-cases for this?🤔
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 assumed
matrixAutoUpdate
andmatrixWorldAutoUpdate
are set tofalse
at the same time if an app wants to control the update matrix process.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.
Side note: This entire thread is another example of why the flag based approach is cumbersome and too complicated. At some point, we should revisit the entire world matrix update computation and implement a solution based on dirty flags and caches and remove the update flags altogether. Even if this means some breaking changes like making
Object3D.matrix
private.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 is cumbersome, but I've found this
force = true
flag removal to be a good workaround for now. How would that dirty flags and caches solution work?Then maybe it makes sense to merge these flags into one? Or maybe we could implement an enum-like option for matrices update to reduce the number of impossible states? Its generally better than having booleans for every option. Something like
Also I would avoid making
Object3D.matrix
private. I know in more advanced performance-focused projects people omitposition/rotation/scale
properties and just deal with matrices directly.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.
The first step would be to introduce dirty flags in
Vector3
andQuaternion
so you know whenposition
,quaternion
orscale
has been changed. Only then you recompute the local matrix which meansmatrixAutoUpdate
could be removed.You could still set a matrix with a new method called
Object3D.setMatrix()
. It's just important that thematrix
property itself isn't writable anymore otherwise we can't properly detect a state change.We have tried to implement something like this in #14138 but stopped because of
Object3D.matrix
is writable. Besides, at that time I wanted to explore caching first since it requires no changes to the math classes. Turned out that caching is slower than the dirty flag approach.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.
@mrdoob said:
Yes. For the previous decade the code was correct -- at least as it pertains to the 'force' flag.