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 center of transformation is always at its local origin. To illustrate how to set and use a pivot the diagrams will use a small red box to show the pivot point, a grey box shows the intially created box and the green box is a copy of the grey one.
Rotations of a mesh always take place around its local origin. In other words the local origin of the mesh is the pivot of the mesh.
As can be seen in the above diagrams before setting a pivot the green box and the grey box have the same local origin and rotate about the same pivot.
A pivot an be set with a translation matrix or directly with the setPivotPoint method.
You can set a pivot using a matrix that when applied to the mesh translates by the x, y and z values given.
The method needed is
mesh.setPivotMatrix(BABYLON.Matrix.Translation(x, y, z));
The first thing to note when setting the pivot is that the mesh is translated by (-x, -y, -z).
For example, the green and grey boxes have the following dimensions, 8, 4, and 2 in the x, y, and z directions respectively. The lower front right corner, therefore, has coordinates (4, -2, -1) and to place the pivot at the lower front right corner the translation needed is (-4, 2, 1). This is done using
greenBox.setPivotMatrix(BABYLON.Matrix.Translation(-4, 2, 1));
If you now want the box back in its starting position you will need to place the local origin, or pivot, of the box at (4, -2, -1) to take into account the translation of the box relative to the pivot. This is done with
greenBox.position(4, -2, -1);
Now when you apply a rotation to the green box it will be about the pivot, which is of course its new local origin.
Ordinarily it is easy enough to align the centres of meshes because the position of each of their local origins can be set relative to the world origin. However when a pivot has been applied to the meshes each mesh will already have been translated and their local origins are no longer at their centres.
If the centre of a pivoted mesh is to be positioned at (xc, yc, zc) and the pivot was positioned using the translation (-xt, -yt, -zt) then the centre of the mesh can be placed using
var centreAt = new BABYLON.Vector3(xc, yc, zc); var pivotAt = new BABYLON.Vector3(xt, yt, zt); mesh.position = centreAt.add(pivotAt);
When you want to position a mesh with its centre at (xc, yc, zc) and a pivot at (xp, yp, zp) just follow these steps
var centreAt = new BABYLON.Vector3(xc, yc, zc); var pivotAt = new BABYLON.Vector3(xp, yp, zp); mesh.position = pivotAt; var pivotTranslate = centreAt.substract(pivotAt); mesh.setPivotMatrix(BABYLON.Matrix.Translation(pivotTranslate.x, pivotTranslate.y, pivotTranslate.z));
The mesh will now be positioned with its centre at (xc, yc, zc) and all rotations and scaling will take place with reference to the pivot at (xp, yp, zp).
In the above playgrounds the sphere(s) show that rotation and scaling do take place with reference to the pivot.
When you want the mesh to stay in the same place but move the pivot to a new position (xp, yp, zp) you need to have stored and kept the current centre of the mesh.
Then the steps are as above.
pivotAt = new BABYLON.Vector3(xp, yp, zp); mesh.position = pivotAt; pivotTranslate = centreAt.substract(pivotAt); //centreAt retained from previous pivot setting mesh.setPivotMatrix(BABYLON.Matrix.Translation(pivotTranslate.x, pivotTranslate.y, pivotTranslate.z));
The following sequence of playgrounds goes from setting the first pivot position to scaling about the second pivot position
NOTE: Restting the pivot this way resets it relative to the unrotated mesh. That is if the mesh has been rotated before resetting the pivot the actual order remains reset pivot do rotation.
The following sequence of playgrounds shows setting the first pivot, rotating the pivot then resetting the pivot.
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
The following sequence of playgrounds goes from setting the first pivot point to scaling about the 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.