Question about Object3D.updateMatrixWorld()

Because updateMatrixWorld is called on the scene object itself during the render loop, I’ve found that since matrixAutoUpdate is defaulted to true on the scene object, updateMatrix is called. That call will flag scene.matrixWorldNeedsUpdate as true. Because matrixWorldNeedsUpdate is now true on the scene, the force variable is now set to true, which means every scene child will run this code from updateMatrixWorld:

if ( this.parent === null ) {

	this.matrixWorld.copy( this.matrix );

} else {

	this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );

}

Correct me if I’m wrong but this seems like an opportunity for optimization yea?

It’s a known issue that the update of world matrices can be a CPU hotspot. This was already discussed at github and there are some WIP PRs in order to verify different approaches to mitigate the issue e.g. here and here.

But yes, if you call scene.updateMatrixWorld( true ), the world matrices of the entire scene graph are recomputed. However, if the property Object3D.matrixAutoUpdate is set to false on a 3D object, its local matrix is not recomputed. Hence, users can control with this flag a part of the update process and avoid unneeded overhead.

That said, more performance optimizations will probably require changes to the library that are not backwards compatible. The API of three.js was designed to provide good flexibility, not necessarily the best performance. It might be necessary to make the local matrix of a 3D object private (or at least read-only) so stuff like matrix caching or dirty flags work reliably. I’m not sure such breaking changes are doable considering the maturity level of the engine.

Another example of the focus on flexibility is how rotations are handled. Normally, you want to represent Object3D.rotation as a quaternion (like Babylon.js or Unity) since that’s the representation you need for many internal computations. However, it’s of type Euler and it’s now necessary to sync between Object3D.quaternion so both properties represent the same angular displacement if one is changed. Using euler angles like so mesh.rotation.y += 0.01; is more convenient and flexible for the user, however there is now an additional overhead in the library which is hard to eliminate. Making Object3D.rotation to a quaternion would break a lot of code.

1 Like

Hmm, guess that’s up to you guys. Personally, if I find a problem in one of my projects, I just fix it regardless. Three.js has breaking changes all the time so I don’t see much of a break of pattern there.

Anyway, I’ve found that simply setting scene.matrixAutoUpdate = false; solves this for me. Maybe a note in the docs or something could help people.

I’m afraid the mentioned changes above would have a higher impact than anything else in the last (at least) three years…

Ha, this is no doubt true =]

I still find it weird that the world matrices of every object in the scene are forced to be updated simply because scene.matrixAutoUpdate is defaulted to true (like all Object3D’s).

I have a pretty well populated scene on average so setting matrixAutoUpdate to false on the scene itself helped out quite a bit.

I’m hoping I’m being clear on this exact situation. I may not be describing it well.

IMO matrixAutoUpdate should be false on the scene itself as this saves to the nth degree of world matrix updates that one would “believe” were not happening if they have matrixAutoUpdate set to false on their in-scene meshes (as I do).

I was honestly quite surprised to see that all of my static meshes were having their world matrices updated. Setting my scene.matrixAutoUpdate = false resolved this.

1 Like

I have your problem, too. I used three.js in an FPS game and I was surprised that Three recalculated the world matrix on every frame. So I have to do the cache stuff on my owns.
Maybe different libraries have their own design philosophy. For world matrix caching, you can take a look of babylon.

The problem here is that three.js provides great flexibility in how users can change the transformation of 3D objects. Unfortunately, this flexibility makes it almost impossible to introduce optimizations in the world matrix update process.

Important steps for improving the performance of world matrix updates are making the model matrix private and removing flags like matrixAutoUpdate so dirty flags and caches can be introduced. This was discussed at GitHub but there are objections against such changes. Right now, there is no enough support to change the established system (and remove parts of its flexibility) so something more performant can be introduced.