Pivots

A Pivot

The latest pivot in Babylon (v3.2+) is a pre-transformation pivot and behaves differently than in tools like 3DS Max and Maya as the object's position will move if scale is applied prior to setting the pivot. To get pivot behavior that matches these tools it is recommended to set the object as a child of another transform node that will act as the pivot see: Simple Pivot Example

A pivot can be set with a translation matrix or directly with the setPivotPoint method.

A pivot in Babylon.js is the center of transformation for a mesh, that is the point used as the center of rotation or the center of enlargement. When a mesh is created the pivot (red sphere) is always at the local origin (yellow sphere) and the local origin always at the world origin, as in Fig 1. When the pivot and local origin are coincident they are shown as a red and yellow striped sphere.


    Fig 1

When positioning a mesh it is the local origin that is placed at the given position, for example

box.position.x = 2;

moves the box as in Fig 2


    Fig 2.

Now, mathematically, it is always more straight forward to rotate or enlarge about the local origin and any code to that does rotation and enlargement uses that principle.

When you want the pivot to be at a corner as in Fig 3 the way this is done is to translate the box corner to the local origin resulting as in Fig 4.


    Fig 3.                                    Fig 4.

Since it is the box that is translated the values used in the translation will be negative with regard to position. For example given a cube with sides of length 2 to set the pivot at position (-1, -1, -1) requires a translation of (1, 1, 1).

Prior to Babylon.js v3.2 setting a pivot meant that the mesh was translated as in Fig 4 and the local origin of the mesh was reset to the pivot point. This meant that after setting a pivot when you reset the the position of the mesh it was the pivot that was placed at this position. Compare Fig 2 with Fig 5 which shows the result of setting a pivot with the move mesh method followed by

box.position.x = 2;


    Fig 5.

From Babylon.js v3.2 there is a breaking change and setting the pivot no longer produces a change in position of the mesh unless the mesh has been scaled.


    Fig 6.

Fig 6 shows result of using setting a pivot with this method followed by

box.position.x = 2;

Compare this with Fig 5.

So there are two ways of setting a pivot, one that does not alter the position of the mesh (set pivot only) and one that does alter the mesh position (set pivot with move). The set pivot only method is much more straightforward and all playground examples on this page use this method. The setPivotPoint function, describe later, uses set pivot only.

In fact unless you have an older project coded for versions before 3.2 or want to change the local origin to that of the pivot do not use the set pivot with move method. It is usually better to set pivot only and then move the mesh as normal with mesh.position or mesh.translate When you do have an older project there is a simple way to update your project code to work with version 3.2 or later as described in the Breaking Change section below.

Breaking Change

You set a pivot at the point (x, y, z) with a translation matrix that using

mesh.setPivotMatrix(BABYLON.Matrix.Translation(-x, -y, -z));

Before v3.2 this would result in the mesh being moved and the local origin of the mesh being reset to the pivot point.

From v3.2 this results in the pivot point being set without the mesh being moved and the current local origin of the mesh is kept. Should you want to maintain the older behaviour of moving the mesh a second parameter, false is needed

mesh.setPivotMatrix(BABYLON.Matrix.Translation(-x, -y, -z), false);

STRESSED NOTE For those of you who wrote code using a pivot for versions of Babylon.js before v3.2 and who want to update the version of Babylon.js to a current one should change each occurrence, in their project code, of

mesh.setPivotMatrix(BABYLON.Matrix.Translation(-x, -y, -z));

to

mesh.setPivotMatrix(BABYLON.Matrix.Translation(-x, -y, -z), false);

How To Set the Pivot Matrix

To set a pivot at (x, y, z) relative to the local origin of a mesh requires the applied translation to be (-x, -y, -z).

mesh.setPivotMatrix(BABYLON.Matrix.Translation(-x, -y, -z));
Set Pivot Matrix

How To Set Pivot Position to World Space Coordinates

When there is a mesh at position (xc, yc, zc) you want to set a pivot at (xp, yp, zp) then you need to use (xc - xp, yc - yp, zc - zp) as the translation.

mesh.setPivotMatrix(BABYLON.Matrix.Translation(xc - xp, yc - yp, zc - zp));
Set Pivot With World Coordinates

How To Reset the Pivot

Simply recalculate the translation of the pivot to the local origin of the mesh as above.

The following sequence of playgrounds goes from setting the first pivot position to scaling about the second pivot position

Set First PivotSet Second PivotScaling From Second Pivot

NOTE: When a mesh has been rotated before resetting the pivot on resetting the pivot the mesh will move since the current rotation will be applied to the new pivot point.

The following sequence of playgrounds shows setting the first pivot, rotating around the pivot then resetting the pivot.

Set First PivotRotate About First PivotSet Second Pivot

How To Set and Get a Pivot Point

There are three useful functions to aid setting and getting a pivot point. These are

mesh.setPivotPoint(Vector3);
mesh.getPivotPoint(); // returns Vector3
mesh.getAbsolutePivotPoint(); // returns Vector3

Set Pivot Point

Using setPivotPoint you simply pass a Vector3 object that is the relative position of the pivot to the local origin of the mesh. To set a pivot at (x, y, z) relative to the local origin of a mesh requires

mesh.setPivotPoint(new BABYLON.Vector3(x, y, z));
Set Pivot Point

When there is a mesh at position (xc, yc, zc) you want to set a pivot at (xp, yp, zp) then the relative position is (xp - xc, yp - yc, zp - z) and use

mesh.setPivotPoint(BABYLON.Vector3(xp - xc, yp - yc, zp - z));
Set Pivot Point

The following sequence of playgrounds goes from setting the first pivot point to scaling about the second pivot point

Set First Pivot PointSet Second Pivot PointScaling From Second Pivot Point

It is possible to reset the pivot point and maintain the position and rotation of the mesh.

To do this the current rotation of the mesh has to be stored and then the mesh's rotation set to (0, 0, 0) before the pivot point is reset. The current rotation is then re-applied to the mesh.

The following sequence of playgrounds shows setting the first pivot point, rotating the pivot then resetting the pivot point and re-applying the rotation.

Set First Pivot PointRotate About First Pivot PointSet Second Pivot Point and Rotate

Get Pivot Point

When using getPivotPoint or getAbsolutePivotPoint the results obtained depend on whether you are using a set pivot only method, that is setPivotMatrix(translation) or setPivotPoint or the set pivot with move method, that is setPivotMatrix(translation).

In both of the following cases the box has then been rotated through 90 degrees, positioned at (6, 1, 2) and the pivot has been set to world position (5, 0, 1) which is (-1, -1, -1) relative to the current position of the local origin of the box.

Set Pivot Only Method

Getter Results       Explanation
Getter
box.position
 Results       
(6, 1, 2)
Explanation
Position as set
Getter
box.getAbsolutePosition()
 Results       
(6, 1, 0)
Explanation
Position of box (yellow sphere) as seen, in world coordinates
Getter
box.getPivotPoint()
 Results       
(-1, -1, -1)
Explanation
Position of pivot (red sphere) relative to local origin of box, as set
Getter
box.getAbsolutePivotPoint()
 Results       
(5, 0, 1)
Explanation
Position of pivot as seen, in world coordinates

Set Pivot Only Method

Getter Results       Explanation
Getter
box.position
 Results       
(6, 1, 2)
Explanation
Position as set
Getter
box.getAbsolutePosition()
 Results       
(7, 2, 1)
Explanation
World coordinate position of the created origin of box (green sphere)
Getter
box.getPivotPoint()
 Results       
(-1, -1, -1)
Explanation
Position of pivot (red/yellow sphere) relative to the created origin of box
Getter
box.getAbsolutePivotPoint()
 Results       
(6, 1, 2)
Explanation
Position of pivot which is the same as the position of the box due to the change in the box's local origin

This table alone shows one good reason not to use the set pivot with move method unless for amending old projects.

Further reading

Rotating Around Axis
Learn how to rotate around an axis in Babylon.js.
Rotating Around Axis