Parenting and Bounds

Parenting, Pivots and Bounding Info

child.parent = node makes a transform relative (Scene Graph); setParent(node) does so while keeping the child's world position. Meshes rotate about their local origin, the center for builder shapes, so a door that should swing on its hinge needs its pivot moved with setPivotPoint:

Hinging a door on its left edge with setPivotPointJavaScript
const size = { width: 0.6, height: 1.8, depth: 0.03 };
const door = BABYLON.MeshBuilder.CreateBox('door', size, scene);
door.position.set(1, 0.9, 0);                         // hinge edge at x = 0.7
door.setPivotPoint(new BABYLON.Vector3(-0.3, 0, 0));  // local left edge
door.rotation.y = Math.PI / 2;                        // swing open a quarter turn
door.computeWorldMatrix(true);
const box = door.getBoundingInfo().boundingBox;
const r = (v) => v.asArray().map((c) => +c.toFixed(3) || 0);   // || 0 turns -0 into 0
console.log('min', r(box.minimumWorld), 'max', r(box.maximumWorld));
Output
BJS - [16:03:30]: Babylon.js v9.28.0 - WebGL2 - Parallel shader compilation
min [0.685, 0, -0.6] max [0.715, 1.8, 0]

The door now runs from z = -0.6 to 0 at x = 0.7: it turned about its hinge. getBoundingInfo() holds the local and world box and sphere that culling, picking and collisions test first; call refreshBoundingInfo() after editing vertices, and getHierarchyBoundingVectors() measures a whole group.

A shelf door swinging about its hinge with setPivotPoint, its world bounding box updatingHTMLLive
<!doctype html>
<style>
  body { margin: 0; background: #f7f3ec; font: 13px system-ui, sans-serif; color: #333; }
  canvas { width: 100%; max-width: 600px; height: 330px; display: block; touch-action: none; }
  #info { max-width: 600px; padding: 4px 8px; font-family: monospace; white-space: pre; }
</style>
<canvas id="view"></canvas>
<div id="info"></div>
<script src="https://cdn.jsdelivr.net/npm/babylonjs@9.28.0/babylon.js"></script>
<script>
const canvas = document.getElementById('view');
const engine = new BABYLON.Engine(canvas, true);
const scene = new BABYLON.Scene(engine);
scene.clearColor = BABYLON.Color4.FromHexString('#f7f3ecff');
const camera = new BABYLON.ArcRotateCamera('cam', -Math.PI / 2 - 0.9, 1.0, 3.1, new BABYLON.Vector3(0.8, 0.9, -0.1), scene);
camera.attachControl(canvas, true);
new BABYLON.HemisphericLight('sky', new BABYLON.Vector3(0.3, 1, -0.4), scene);
const paint = (mesh, hex) => {
  mesh.material = new BABYLON.StandardMaterial(hex, scene);
  mesh.material.diffuseColor = BABYLON.Color3.FromHexString(hex);
  return mesh;
};
paint(BABYLON.MeshBuilder.CreateGround('floor', { width: 4, height: 4 }, scene), '#e6ddd0');

// A small cabinet the door belongs to, with books inside
const cabinet = paint(BABYLON.MeshBuilder.CreateBox('cabinet', { width: 0.62, height: 1.8, depth: 0.4 }, scene), '#6d4c33');
cabinet.position.set(1, 0.9, 0.22);
['#1f5f8b', '#e09a10', '#3f7d3a', '#b5452f'].forEach((hex, i) => {
  const book = paint(BABYLON.MeshBuilder.CreateBox('book', { width: 0.1, height: 0.32, depth: 0.25 }, scene), hex);
  book.position.set(0.8 + i * 0.12, 1.2, 0.05);
});

const size = { width: 0.6, height: 1.8, depth: 0.03 };
const door = paint(BABYLON.MeshBuilder.CreateBox('door', size, scene), '#a1887f');
door.position.set(1, 0.9, 0);                         // hinge edge at x = 0.7
door.setPivotPoint(new BABYLON.Vector3(-0.3, 0, 0));  // local left edge
door.showBoundingBox = true;                          // draw the box culling and picking test first
const hinge = paint(BABYLON.MeshBuilder.CreateCylinder('hinge', { height: 1.9, diameter: 0.03 }, scene), '#e09a10');
hinge.position.set(0.7, 0.95, 0);

const info = document.getElementById('info');
const r = (v) => v.asArray().map((c) => (+c.toFixed(2) || 0).toFixed(2)).join(', ');   // no -0
let t = 0;
scene.onBeforeRenderObservable.add(() => {
  t += engine.getDeltaTime() / 1000;
  door.rotation.y = (0.5 - 0.5 * Math.cos(t * 1.2)) * Math.PI / 2;   // 0 to a quarter turn
  door.computeWorldMatrix(true);
  const box = door.getBoundingInfo().boundingBox;
  info.textContent = `rotation.y ${(door.rotation.y * 180 / Math.PI).toFixed(0).padStart(2)}°\n` +
    `minimumWorld (${r(box.minimumWorld)})\nmaximumWorld (${r(box.maximumWorld)})`;
});
engine.runRenderLoop(() => scene.render());
addEventListener('resize', () => engine.resize());
</script>