# Remove Infinite-Distance Root Allocation in \`TransformNode.computeWorldMatrix\`

**URL:** <https://forum.babylonjs.com/t/remove-infinite-distance-root-allocation-in-transformnode-computeworldmatrix/63125>\
**Category:** Completed Features\
**Tags:** performance, transformnode, memory, matrix\
**Created:** [April 11, 2026, 5:47am UTC](https://forum.babylonjs.com/t/remove-infinite-distance-root-allocation-in-transformnode-computeworldmatrix/63125 "2026-04-11T05:47:42Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![kzhsw](https://avatars.discourse-cdn.com/v4/letter/k/848f3c/32.png) [@kzhsw](https://forum.babylonjs.com/u/kzhsw)\
**Post date:** [April 11, 2026, 5:47am UTC](https://forum.babylonjs.com/t/remove-infinite-distance-root-allocation-in-transformnode-computeworldmatrix/63125/1 "2026-04-11T05:47:42Z")

</div>

## Summary

Remove the per-call `new Vector3(...)` allocation in the root-node infinite-distance path of `TransformNode.computeWorldMatrix()` and replace it with a zero-allocation implementation based on direct matrix element reads or reusable temp storage.

This is a small, low-risk optimization that preserves public API and behavior while reducing work on a hot path that can run once per visible infinite-distance root node per frame.

## Current Code

Current implementation in [`packages/dev/core/src/Meshes/transformNode.ts#L1108`](https://github.com/BabylonJS/Babylon.js/blob/9.1.0/packages/dev/core/src/Meshes/transformNode.ts#L1108):

> <https://github.com/BabylonJS/Babylon.js/blob/9.1.0/packages/dev/core/src/Meshes/transformNode.ts#L1108-L1116>

The temporary `cameraGlobalPosition` object is allocated even though:

- only the translation components `m[12..14]` are needed
- the values are consumed immediately
- the vector is not exposed outside the function

## Motivation

This path is structurally more expensive than it needs to be:

- one heap allocation per recompute
- one constructor call
- one extra object read layer before `copyFromFloats`

The code is also avoidably indirect. The translation is already available in the matrix.

Even if the absolute gain is small, this is a good target because:

- it is isolated
- it does not affect semantics
- it composes well with other `computeWorldMatrix()` improvements

## Proposal

Replace:

```ts
const cameraGlobalPosition = new Vector3(cameraWorldMatrix.m[12], cameraWorldMatrix.m[13], cameraWorldMatrix.m[14]);

translation = TransformNode._TmpTranslation;
translation.copyFromFloats(this._position.x + cameraGlobalPosition.x, this._position.y + cameraGlobalPosition.y, this._position.z + cameraGlobalPosition.z);

```

With:

```ts
const cameraWorldMatrix = camera.getWorldMatrix();
const m = cameraWorldMatrix.m;

translation = TransformNode._TmpTranslation;
translation.copyFromFloats(this._position.x + m[12], this._position.y + m[13], this._position.z + m[14]);

```

## Why This Version

This is preferable to introducing another temp `Vector3` because:

- it avoids allocation completely
- it avoids another temp object write/read round-trip
- it keeps the code local and explicit
- it matches how the data is actually consumed

## Correctness

Behavior is unchanged:

- The only values read from `cameraGlobalPosition` are `x`, `y`, `z`.
- Those are exactly `cameraWorldMatrix.m[12]`, `m[13]`, `m[14]`.
- `translation` still ends up with the same final values.

This optimization does not change:

- parent handling
- camera selection
- matrix composition order
- any public return value

## Risk

Risk is low.

Potential concerns:

- If future code wants the camera position object for other reasons, this path would need to be revisited.
- If `camera.getWorldMatrix().m` ever stops exposing translation in `12/13/14`, the whole engine would already be broken in many places. This is standard Babylon matrix layout.

## Expected Impact

Per-call impact:

- lower allocation pressure
- lower GC pressure
- slightly less CPU work

Scene-level impact:

- most relevant in scenes with infinite-distance root nodes that recompute world matrices often
- likely modest on its own
- useful as part of a bundle of `computeWorldMatrix()` cleanups

## Suggested Patch Shape

Single-file change:

- [`packages/dev/core/src/Meshes/transformNode.ts`](https://github.com/BabylonJS/Babylon.js/blob/9.1.0/packages/dev/core/src/Meshes/transformNode.ts)

No public API change, no serialization change, no behavior change.

## Notes

Scanned the whole `_evaluateActiveMeshes` and `computeWorldMatrix` for performance, and that’s the one without breaking change or edge-case microbenchmark regression.

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [April 13, 2026, 8:39am UTC](https://forum.babylonjs.com/t/remove-infinite-distance-root-allocation-in-transformnode-computeworldmatrix/63125/2 "2026-04-13T08:39:47Z")

</div>

Looks good!

Do you want to create a PR for it?

---

<div class="post-metadata">

**Author:** ![kzhsw](https://avatars.discourse-cdn.com/v4/letter/k/848f3c/32.png) [@kzhsw](https://forum.babylonjs.com/u/kzhsw)\
**Post date:** [April 14, 2026, 1:36am UTC](https://forum.babylonjs.com/t/remove-infinite-distance-root-allocation-in-transformnode-computeworldmatrix/63125/3 "2026-04-14T01:36:12Z")

</div>

Yeah, here it is:

> <https://github.com/BabylonJS/Babylon.js/pull/18305>
>
> \## Summary
> 
> Remove the per-call \`new Vector3(...)\` allocation in the root-node… infinite-distance path of \`TransformNode.computeWorldMatrix()\` and replace it with a zero-allocation implementation based on direct matrix element reads or reusable temp storage.
> 
> This is a small, low-risk optimization that preserves public API and behavior while reducing work on a hot path that can run once per visible infinite-distance root node per frame.
> 
> \## Current Code
> 
> Current implementation in \`packages/dev/core/src/Meshes/transformNode.ts#L1108\`:
> 
> The temporary \`cameraGlobalPosition\` object is allocated even though:
> 
> \- only the translation components \`m\[12..14\]\` are needed
> \- the values are consumed immediately
> \- the vector is not exposed outside the function
> 
> \## Motivation
> 
> This path is structurally more expensive than it needs to be:
> 
> \- one heap allocation per recompute
> \- one constructor call
> \- one extra object read layer before \`copyFromFloats\`
> 
> The code is also avoidably indirect. The translation is already available in the matrix.
> 
> Even if the absolute gain is small, this is a good target because:
> 
> \- it is isolated
> \- it does not affect semantics
> \- it composes well with other \`computeWorldMatrix()\` improvements
> 
> \## Why This Version
> 
> This is preferable to introducing another temp \`Vector3\` because:
> 
> \- it avoids allocation completely
> \- it avoids another temp object write/read round-trip
> \- it keeps the code local and explicit
> \- it matches how the data is actually consumed
> 
> \## Correctness
> 
> Behavior is unchanged:
> 
> \- The only values read from \`cameraGlobalPosition\` are \`x\`, \`y\`, \`z\`.
> \- Those are exactly \`cameraWorldMatrix.m\[12\]\`, \`m\[13\]\`, \`m\[14\]\`.
> \- \`translation\` still ends up with the same final values.
> 
> This optimization does not change:
> 
> \- parent handling
> \- camera selection
> \- matrix composition order
> \- any public return value
> 
> \## Risk
> 
> Risk is low. No public API change, no serialization change, no behavior change.
> 
> Potential concerns:
> 
> \- If future code wants the camera position object for other reasons, this path would need to be revisited.
> \- If \`camera.getWorldMatrix().m\` ever stops exposing translation in \`12/13/14\`, the whole engine would already be broken in many places. This is standard Babylon matrix layout.
> 
> \## Expected Impact
> 
> Per-call impact:
> 
> \- lower allocation pressure
> \- lower GC pressure
> \- slightly less CPU work
> 
> Scene-level impact:
> 
> \- most relevant in scenes with infinite-distance root nodes that recompute world matrices often
> \- likely modest on its own
> \- useful as part of a bundle of \`computeWorldMatrix()\` cleanups
