Discourage usage of translateX/Y/Z and rotateX/Y/Z methods

Before reading - please keep in mind this is based entirely on my personal experience :pray: (Also want to have something to link when explaining questions sometimes :smiling_face_with_tear:)


When helping with projects and answering questions - sometimes it seems to me that at some point, either from old 3D tutorials, or from previous experiences with OpenGL, or just because for a new person it may be more intuitive to search docs for "translate" instead of "position.set" - newcomers fallback to using translateX / translateY / translateZ / rotateX / rotateY / rotateZ as if these were “the way” of moving things around the scene.

It seems like a similar issue to when people starting with 3D fallback to using .obj / .dae format - because “it’s the simplest, so it has to be the easiest to use for a beginner, right?”, while in practice these formats can be harder to work with than glTFs / GLBs.


To make my point a little more visual, say we have 4 boxes:

We apply the following transformations to them (in order from left to right):

// redBox
mesh.translateZ(1.0);
mesh.rotateX(-Math.PI / 2.0);
mesh.translateZ(1.0);
mesh.rotateY(Math.PI / 4.0);
mesh.translateZ(1.0);

// greenBox
mesh.position.z += 1.0;
mesh.rotation.x += -Math.PI / 2.0;
mesh.position.z += 1.0;
mesh.rotation.y += Math.PI / 4.0;
mesh.position.z += 1.0;

// blueBox (Just swapping the order of operations from redBox)
mesh.rotateX(-Math.PI / 2.0);
mesh.translateZ(1.0);
mesh.rotateY(Math.PI / 4.0);
mesh.translateZ(1.0);
mesh.translateZ(1.0);

// pinkBox (Similarly, just swapping the order from blueBox)
mesh.rotation.x += -Math.PI / 2.0;
mesh.position.z += 1.0;
mesh.rotation.y += Math.PI / 4.0;
mesh.position.z += 1.0;
mesh.position.z += 1.0;

How easily can you predict where each of the boxes will be? And how easily could you predict if these were run inside the animation loop, incrementally building up the changes - for frame 2, frame 3, etc.?

Answer & Codepen

redBox and blueBox fly places, while greenBox and pinkBox appear exactly where expected - regardless of order in which we move them on axes.

Moreover, were you to run these in a loop, you can easily simplify the mutation of position and rotation vectors to just:

// Each frame the object rotates on X axis, on Y axis a little slower, and moves `3.0` on Z axis
mesh.rotation.x += -Math.PI / 2.0;
mesh.rotation.y += Math.PI / 4.0;

mesh.position.z += 3.0;

Object-space transforms cannot be intuitively simplified as their result depends on the object transformation from the previous frame.

Codepen


A person learning 3D and three’s API could easily just assume that position.set and translateX are the same thing, not giving position.set even a try - after all, it’s longer to type :see_no_evil: And as in the example above - modifying the position directly is in practice more predictable and better in nearly all scenarios (if not straight up “in all scenarios”.)

Would any actual value be lost if translate / rotate methods were someway openly discouraged in the documentation :thinking: ? Is there any practical use-case that makes them even a viable alternative to modifying position / rotation with vector operations? Would it maybe make sense to rename object-space translation methods to translateLocalX/Y/Z and make translateX/Y/Z work in parent-space?

1 Like

The confusions for beginners is that there are many ways to do things. Failing to pick the most appropriate way is because:

  • they do not know what happens under the hood;
  • they are aware of only one way and have no idea there are other ways.

For example, rotation around X can be implemented in amazingly many ways:

  • mesh.rotation.x
  • mesh.rotateX()
  • mesh.rotateOnAxis()
  • mesh.rotateOnWorldAxis()
  • geometry.rotateX() ← yes, I’ve seen this used in an animation loop too
  • and a bunch of all other ways involving quaternions and matrix manipulations

I’m not sure that discouraging (as the title suggest) is good, as all different ways of doing the same thing exist for a reason. Sometimes I also use rotateX instead of rotation.x, for example, when I need to make ZXZ-rotation.

Maybe a better approach is to do like WIkipedia does for words with several meanings (example with DOF). All PoCs (points of confussions) may have a short note with a link to alternatives. Here is an example with rotation and rotateX.

I’m not sure whether this is the best way to resolve the confusion, because it shifts the documentation from being a reference into a tutorial.

2 Likes

Hey, as a new user, I thought my perspective might be valuable here. Intuitively, it seemed to me that geometry.rotateX() and mesh.rotation.x were synonyms but I eventually discovered that, while geometry.rotateX() effects the underlying geometry (which way is up) mesh.rotation.x does not. Hence mesh.rotation.x should be the choice for me. The docs were not helpful for this discovery (even after having found the reference to both of these, which took some doing). The docs could be much more helpful. How about a keyword search, so “rotat” got some results? Perhaps an inheritance hierarchy so I can see, for example, if something is an Object3D? Short usage examples for everything would be great! And yes, common trips and traps still work in a reference document.

1 Like