Remove force flag set from Object3D.updateMatrixWorld()
, which makes Object3D.matrixWorldAutoUpdate
useless
#27245
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.
Remove force flag set from
Object3D.updateMatrixWorld()
, which makesObject3D.matrixWorldAutoUpdate
uselessMotivation
I am setting
object.matrixWorldAutoUpdate = false;
in my app and updating the world matrices manually. However due to the issue,Object3D.matrixWorldAutoUpdate
simply doesn't work.Description
At the moment
Object3D.matrixWorldAutoUpdate
flag doesn't do anything. Itstrue
by default (which is why it hasnt been caught yet I assume), but if you set it tofalse
, the object will still have its world matrix recalculated every frame. Why? Because offorce = true
insideObject3D.updateMatrixWorld()
.The Problem
So what happens?
WebGLRenderer.render()
callsif ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld();
scene.updateMatrixWorld()
callsif ( this.matrixAutoUpdate ) this.updateMatrix();
scene.updateMatrix()
composes the local matrix and setsthis.matrixWorldNeedsUpdate = true;
scene.updateMatrixWorld
the condition is called:if ( this.matrixWorldNeedsUpdate || force ) {
, which will run because of point 3.force = true;
is called (for what reason, I do not know)if ( child.matrixWorldAutoUpdate === true || force === true ) {
- HERE WE SEEchild.matrixWorldAutoUpdate
DOES NOT MATTER! becauseforce
istrue
.child.updateMatrixWorld( force );
updating the entire scene graph, now withforce
flag set totrue
SO FROM NOW ON IT WILL ALWAYS BE TRUE FOR EVERY OBJECT IN THE SCENE GRAPH! And since it will always be passed down as true, the check from point 6.if ( child.matrixWorldAutoUpdate === true || force === true ) {
will always run, makingchild.matrixWorldAutoUpdate
not matter at all!Here is a rundown in the
Object3D
matrix updates code, with steps above pointed out in the comments:We see that in the current configuration as long as the root
Scene
object updates its local matrix, ALL of its descendants will have their world matrices updated, whether they like it or not (regardless ofchild.matrixWorldAutoUpdate
. Here is JSfiddle proof: https://jsfiddle.net/fpb09am8/Its very easy to test. Just do:
Here we see that even though child doesnt want to have its world matrix updated automatically (
child.matrixWorldAutoUpdate = false
) it still happens because thescene
will force it on all its descendants as shown in the 7 points above.Solution
Remove
force = true;
from insideObject3D.updateMatrixWorld
. It is setting itself to true by itself, making auto update checks ineffective. It is confusing if you setforce
tofalse
(or leaveundefined
) because it will turn totrue
in just 1 generation by itself anyway. It is not clear at all that its basically alwaystrue
.In my opinion
force
should be an external flag set by the users if they want it.Important tests note!
Running tests with
force = true;
removed, causes one failed test:The test in question:
This is caused because in previous tests (which are all inline so they risk mixing flags) there is
child.matrixAutoUpdate = false;
. This affects the failed test, by causing the child to not runchild.updateMatrix()
and thus not setchild.matrixWorldNeedsUpdate = true;
(point 3.). And now since theforce
flag just doesnt forcefully update everything by itself regardless of any user concerns, theif ( this.matrixWorldNeedsUpdate || force ) {
check (point 4.) will fail and not update the child's world matrix.This test only worked previously, because
force
was broken and is now fixed. I fixed the test by addingchild.matrixAutoUpdate = true;
which is the default anyway.Now we could argue that the
Object3D.matrixWorldNeedsUpdate
flag shouldn't rely solely onObject3D.updateMatrix()
and I kinda agree, but it is outside the scope of this PR. It works this way right now and I kept it working this way.