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));
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));
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 PivotNOTE: 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 PivotHow 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 Vector3mesh.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));
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));
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 PointIt 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 RotateGet 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.