Obj.position.set(x,y,z) and obj.position = new Vector3(x,y,z) don't behave the same way

Babylon Version: Babylon.js v5.7.0 - WebGL2 - Parallel shader compilation

I’m not sure this is a bug or strange architectural decision but I’ve been building babylonjs apps in my spare time to become more fluent with the library and ran into a situation that is extremely unintuitive.

As an example, let’s say I create 6 meshes (which happen to be planes) and then do:

plane.position.set(0, 0.006, 0);
plane.rotation.y = ((Math.PI * 2) * this.sizeOfSlice) * offset;  // rotate to face various directions in a circle
plane.translate(Axis.X, -0.25, Space.LOCAL);

This rotates the meshes then moves them all in the same direction, which is strange and not what I want to do. I expected them to either move outwards in a circle (or inwards).

Now this code on the other hand, does what I expect:

plane.position = new Vector3(0, 0.006, 0);
plane.rotation.y = ((Math.PI * 2) * this.sizeOfSlice) * offset;
plane.translate(Axis.X, -0.25, Space.LOCAL);

This code does what I want: it rotates the meshes and they all move outwards in a circle. My question is why? Why don’t these two snippets of code do the same thing?

Are the planes in your first code snippet referencing the same Vector3 object?
They are clearly not in the second snippet, so I think in your first example you are using the same position object for all planes (and setting the x, y, z values again on it with each created plane).

Edit, nvm ‘set’ returns a new Vector3.

I would want to verify this in the BJS source code, but I think that using .set causes recalculation of world matrix, whereas assigning the value doesn’t.

You could test by adding a call to mesh.computeWorldMatrix(true) after changing position. It would behave the same then regardless of which means used to translate and rotate

3 Likes

The difference is that plane.position = marks the mesh dirty, but plane.position.set marks the vector dirty. If you call plane.markAsDirty() before calling plane.translate then it should work when using set as well. :slight_smile:

5 Likes

This was the solution, thank you. I guess it’s not a bug? This is kind of confusing though, as there is no indication anywhere that it will be necessary to markAsDirty. (at least that I remember reading)
It seems like we should add this to the docs and tutorials related to moving things around the scene.

2 Likes

AFAIK there’s a performance optimization where the vectors are only checked for dirtiness at most once per frame, but we can work around it by either marking the mesh dirty or by calling computeWorldMatrix(true) to force the update manually, like above…

And yep a note in the documentation of each function that calls or relies on computeWorldMatrix could be very helpful IMO, that and/or a list of those functions somewhere, so we could know without having to check the source of the functions (my usual go-to). :slight_smile:

1 Like