Parents and Children
Overview of a Parent
Using a parent is an alternative to using a Babylon.js pivot to set the center of transformation for a mesh; that is, the point used as the center of rotation or the center of enlargement. To rotate or scale a mesh using a parent as the center of transformation, you apply the rotation or scaling vectors to the parent. This differs from using a Babylon.js pivot to rotate or scale a mesh.
Making mesh P a parent of mesh C changes the frame of reference for mesh C to the local axes of mesh P. Repositioning, rotating, or scaling mesh P will apply the same transformations to mesh C. The positioning, rotation, and scaling of mesh C will depend on the position and orientation of the local axes of C relative to those of P.
Please note that non-uniform scaling (scaling with different values on different axes) is not supported on parent nodes. Indeed, decomposition of such a Matrix would result in supporting shear mapping at the transform level. That has not been added out of concern for performance.
To parent mesh C to mesh P, you can use any of these three methods:
meshC.parent = meshP; // 1meshC.setParent(meshP); // 2meshP.addChild(meshC); // 3... however, the resulting behavior will not always match perfectly. Specifically, the order in which you set position and apply rotation to the parent mesh will affect the result if method 2 or 3 was used, but not if method 1 was used.
The following playgrounds show the different behaviors:
Transform C and P After Parenting Transform C Before and P After Parenting Transform P Before and C After Parenting Transform C and P Before ParentingTo remove a child (mesh C) from a parent (mesh P), use any of these methods:
meshC.parent = null; // 1meshC.setParent(null); // 2meshP.removeChild(meshC); // 3The following playground demonstrates how using method #1 does not just remove the parent from the child (mesh C, red in color), but also removes from the child any transformations applied via the parent and leaves only the transformations applied directly to the child mesh. The moment when the parent is removed from mesh C using method #1, position, rotation and scale of mesh C will visibly change in the scene view. Methods #2 and #3 do remove the parent-child relationship, but any transformations to mesh C applied via mesh P up to the point of removal will remain. Position, rotation and scale of mesh C will never visibly change when its parent is removed using method #2 or #3.
Removing a ParentHow To Use a Parent
The parent method used in these examples can be compared directly with transforming coordinates.
Satellite
Take a box that is rotating and translating from the top of which emerges a smaller box and travels in a direction always perpendicular to the top face of the box.
By parenting the smaller box to the box rotations, positions and scaling given to the parent are also applied to the child. Rotations, positions and scaling given to the child take place inside the frame of reference of the parent.
The following code gives the animation.
import { Axis, Space } from "@babylonjs/core/Maths/math.axis";import { Vector3 } from "@babylonjs/core/Maths/math.vector";scene.registerAfterRender(function () { box.rotate(Axis.Y, Math.PI / 150, Space.LOCAL); box.rotate(Axis.X, Math.PI / 200, Space.LOCAL); box.translate(new Vector3(-1, -1, -1).normalize(), 0.001, Space.WORLD); y += 0.001; small.translate(Axis.Y, 0.001, Space.LOCAL);});Disc World
Imagine a disc flying through space with buildings on it. In fact, the following example uses a thin cylinder as the disc, since the top circular face is horizontal, whereas the face of a disc in Babylon.js is vertical. (OK, it does not make any real difference, but it is more natural to start with a horizontal ground.)
The building will be an array of boxes with each box parented to the disc.
import { Axis, Space } from "@babylonjs/core/Maths/math.axis";import { Vector3 } from "@babylonjs/core/Maths/math.vector";var phi = 0;scene.registerAfterRender(function () { matrix = disc.getWorldMatrix(); disc.rotate(Axis.Y, Math.PI / 150, Space.LOCAL); disc.rotate(Axis.Z, Math.PI / 200, Space.LOCAL); disc.position = new Vector3(15 * Math.cos(phi), 16 * Math.sin(phi), 5); phi += 0.01;});Negative scaling and local transformation
When parenting a node with negative scaling values, some axes might change sign. When computing the child's local transform, all axes are assumed to be positive. This is the default behavior for legacy reasons. However, it is possible to keep the scaling axis sign. When calling addChild and removeChild, a second optional boolean parameter will preserve the sign when set to true. Both functions recompute the scaling value, so set the parameter to true when adding or removing a child.
