I think most of these questions resolve in one way or another back to questions about 3D math, which is definitely too large a topic to tackle all-up in a forum post. However, let me see what I can do to add some context about what the code you’re asking about does, if not exactly how those mechanics work.
First, a few terms: transform matrix, position vector, direction vector. (You may already be familiar with some or all of these terms, so please feel free to skip this section if it’s not helpful.) A transform matrix (in the context of 3D graphics) is a mathematical construct which encodes all the information relating one 3D space to another. For the purposes of this conversation, you can think of it as containing both the position and the orientation (less precisely, rotation)* of an object in 3D space, like one of the spheres. You can use a transform matrix to transform a 3D vector, which means to move it from one space to another; that is, if you have a vector “in front of” a thing in one space, you can use a transform matrix to move that vector to be “in front of” something else whose position/orientation are described by the transform matrix in question. A position vector, unlike a matrix, encodes only position, not orientation; a position vector can contain any 3D value. Contrastingly, a direction vector encodes neither position nor rotation, but direction; it is also not free to contain just any 3D value, for a direction vector by definition must have a magnitude (i.e., vector length) of 1.
With that out of the way, let’s look at the first block of code you asked about.
BABYLON.Vector3.TransformNormalToRef(BABYLON.Axis.Z, boxArray[i].getWorldMatrix(), boxArray[i].metadata.velocity);
The overarching purpose of these three lines is to update the position of a single box, which is exactly what the last line does: it takes the value currently stored in
velocity and adds it to the current box’s
position in an operation you might think of as
+=. The purpose of the other two lines is simply to ensure that the value in
velocity when it’s added is the correct value.
- The first line essentially says, “Set the velocity of the box to be the same as its forward direction (i.e., relative Z axis).” It does this by taking
BABYLON.Axis.Z, which is a direction vector representing the forward direction in absolute space or “world space,” then transforms that direction vector using the box’s world transform matrix so that it becomes the relative forward direction for that sphere. It then stores this transformed direction vector in the box’s
velocity variable; any time you see
- The second line essentially says, “Set the magnitude of the box’s velocity to be the same as its speed.”
velocity.normalize() sets the magnitude of the
velocity to 1 (which doesn’t actually do anything here because the prior line set
velocity to be a direction vector, which as mentioned above already has a magnitude of 1 by definition).
scaleInPlace() then simply scales the
velocity vector by the
speed, which isn’t a vector but is a scalar (i.e., ordinary number) representing (in this case) how far the box should travel per frame.
In combination, the two operations described above store in
velocity a 3D vector which represents the movement the box should make on this frame; this vector is then added to the position in the final line, performing the movement. It’s worth noting that a fair bit of this could be simplified. If you’re interested, I created a modified version of the Playground that reduces all this to one shorter line, omitting some unnecessary operations and using some provided values like the
forward property, which obviates the need to directly interact with the world matrix at all.
Now let’s take a look at the second block of code you asked about.
As before, this code is performing the per-frame movement of a 3D entity in the scene, in this case a sphere. Also as before, the actual movement is done in the third line, and the preceding two lines exist to store the correct value in an intermediate variable, in this case
directionVector. (Regarding your question about
- Here we have another
ToRef function, which again is being used to store a value on its last argument,
directionVector. The value being stored here is simply the difference between the position of the sphere and the position of the box in question. Note that, despite the fact that this is being stored in a variable called
directionVector, it isn’t actually a direction vector yet because its magnitude is (probably) not 1. That problem gets addressed in the next line.
- These are the same operations done in the second line of the first block of code you asked about, and they’re done for the same reasons. However, unlike in that case, the
normalize() call (which forces
directionVector to have a magnitude of 1) is necessary in this case because we don’t know what magnitude the vector in
directionVector has, and we need that magnitude to be 1 for the
scaleInPlace() to produce the correct result. Once the magnitude is 1,
scaleInPlace() changes it again to be a new length corresponding to the desired length of motion in a single frame. Confusingly, this once again makes
directionVector (which very briefly was a real direction vector after
normalize() was called) have a magnitude unequal to 1. The name is the only confusing part, though; the usage is simply to increment the position in the next line.
Hope some of that was helpful and/or interesting. Best of luck!