API

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; // 1
meshC.setParent(meshP); // 2
meshP.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 Parenting

To remove a child (mesh C) from a parent (mesh P), use any of these methods:

meshC.parent = null; // 1
meshC.setParent(null); // 2
meshP.removeChild(meshC); // 3

The 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 Parent

How 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);
});
Animation Parent

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;
});
Disc World

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.

Further reading

Introduction To Coordinate Transformation
Learn all about coordinate transformation in Babylon.js.
Introduction To Coordinate Transformation