Question about Babylon Lite API

I have several questions when trying to port to Babylon Lite:

1. How to show / hide node of skinned model in Lite?

In Babylon.js, I use the trick: set scaling 0 & revert original scaling to show / hide a node and its descendants of a skinned model. Like the playground below:

I have tried in Lite:

  • setSubtreeVisible(node, false)
  • node.scaling.set(0, 0, 0)
  • recursively set node and node.children scaling to zero

but none of these worked.

2. Is AnimationMask supported?
Some of my model animations can be applied to upper / lower / whole body depending on situations. Previously I use AnimationMask to control it. I could not find a workaround in Lite or maybe I am missing something?

3. What is the expected way to set parent child relationship between two TransformNodes?
I have seen in Lite scenes doing this:

childNode.parent = parentNode
parentNode.children.push(childNode)

Is it necessary to push into children array?

On the other hand, there is also

setParent(child: Mesh, parent: IWorldMatrixProvider | null): void

Will setParent() accepts TransformNode or SceneNode as child too?

4. Will quaternion math functions be ported to Lite?
Specifically Quaternion.FromLookDirectionRH(forward, up) and Quaternion.FromRotationMatrix. I use these 2 functions quite a lot to apply rotation on nodes.

5. setDracoBaseUrl and setMeshoptBaseUrl seems to be not exported

Any help? :thinking:

Sorry with the release your question felt through the cracks. Checking right now!

Sorry again for the miss!

1. Show / hide a node of a skinned model

Two cases:

  • Regular (non-skinned) nodes: use setMeshVisible(node, false) (it cascades to the node’s children). The Babylon trick of zeroing scaling does not translate, because Lite’s render path keys off a single visible flag, not a degenerate transform.
  • Skinned models: a skinned mesh is one GPU-skinned draw whose pose comes from a bone texture, so writing scaling/visible on a joint node has no visual effect. For this there is now a PR for an opt-in bone API. Call enableBoneControl() once before loading, then:
enableBoneControl();
const character = await loadGltf(engine, "character.glb");
addToScene(scene, character);

const skel = character.skeletons[0];
const head = getBoneByName(skel, "Head");
if (head) setBoneVisible(skel, head, false); // hides the head and everything under it

setBoneVisible(skel, bone, false) scales the bone to zero (collapsing its sub-tree), exactly like the Babylon workflow. You also get setBonePosition, setBoneRotationQuaternion, setBoneScaling, and clearBoneOverride. It is opt-in so projects that don’t use it pay no bundle cost. Overrides re-apply every frame, so a playing clip still wins on any bone it animates, while bones the clip doesn’t touch keep your override.

2. Is AnimationMask supported?

Not yet. There is no per-bone mask (yet but we will asap, please create an issue for it so we can prioritize). What exists for combining clips is weight-based and additive blending: setAnimationWeight, enableAnimationBlending, setAnimationAdditive,
crossFadeAnimationGroups, fadeAnimationWeight, enablePropertyAnimationBlending. For upper/lower-body splits today, the bone API above (overriding the bones a given clip should not drive) is the closest workaround.

3. Parent / child between two TransformNodes

child.parent = parentNode is what actually drives the transform (the world-matrix system tracks children off the parent setter). The children array is a separate traversal list used by helpers (setMeshVisible cascade, cloning, camera bounds). So setting parent is enough for the math; push into children if you want those helpers to see the child.

setParent(child, parent) (the Babylon-style “reparent but keep world position” helper) will be improved by a PR coming today: it will keep the children arrays in sync automatically, and it accepts any node (SceneNode: mesh, transform node, camera, light), not just Mesh. The parent can be any world-matrix provider.

4. Quaternion.FromLookDirectionRH / FromRotationMatrix

Both will also be available as standalone functions on the core Quat data type: quatFromRotationMatrix(matrix) and quatFromLookDirectionRH(forward, up). They match the Babylon.js implementations. (The core package keeps rotations as plain { x, y, z, w } data plus functions rather than a Quaternion class, so these are functions, not statics.)

5. setDracoBaseUrl and setMeshoptBaseUrl

same, both will be exported from babylon-lite.

I’ll link the PR here as they go :slight_smile:

feat(skeleton): opt-in bone control + quaternion helpers + setParent fixes by deltakosh · Pull Request #268 · BabylonJS/Babylon-Lite

AnimationMask: feat(animation): add AnimationGroupMask (include/exclude target masking) + scene 251 by deltakosh · Pull Request #269 · BabylonJS/Babylon-Lite

Thanks for the PRs!

As I’m continuing on porting, I have more questions about Lite (and probably more in the future, sorry in advance :sweat_smile:)

About missing features:
1. AnimationGroup.blendingSpeed is missing in Lite. Will it be supported?

2. In Babylon.js, we can iterate AnimationGroup.targetedAnimations to get what nodes are affected. It is quite useful for reverting animations. Will it be supported?

3. I see animation event is not supported in the feature comparison doc. I assume the workaround would be manually comparing AnimationGroup.currentFrame and AnimatrionGroup.duration and wait for this PR to land?

4. Will accessing gltf extras be supported? I currently rely on extras to setup custom alpha mode on meshes and setting up StandardMaterial props.


About API design:
1. Is there any reason why AnimationGroup.currentFrame and AnimatrionGroup.duration are in seconds instead of keyframe (just like Babylon.js AnimationGroup.from, AnimationGroup.to)?

2. Vector maths in Babylon.js have apis xxxToRef and xxxInPlace to avoid creating and destroying temp objects. Will these be added in Lite as well or we will have to wait for the lite-compat package?

Thanks, these are all good points.

For targetedAnimations , yes, we should expose a lightweight readonly list on AnimationGroup . It will not be a full Babylon.js Animation object graph, but it should give you the target node, target name, node index, and animated path so you can inspect or revert affected nodes.

For animation events, your workaround is the right one for now: compare the group time with its duration. PR #254 should make the animation time reliable during the render loop. A real event API should come later as a separate feature.

For extras , yes, we should support this. The plan is to mirror Babylon.js ExtrasAsMetadata and expose glTF extras as metadata.gltf.extras on the relevant Lite objects.

About currentFrame : you are right, the name is confusing because Lite stores glTF animation playback in seconds. We will rename it to currentTime . goToFrame() will remain available for frame-based seeking.

For vector math, we should add ToRef and InPlace style helpers, but as tree-shakable free functions instead of methods on Vec3 .

PR is coming :wink:

feat!: expose glTF metadata and animation time API by deltakosh · Pull Request #275 · BabylonJS/Babylon-Lite

Does tree shaking happen per individual function such that including addInPlace doesn’t also include subtractInPlace?

From what I can tell, InPlace is slightly redundant to ToRef when you are using InPlace standalone e.g. result.addToRef(b,result). InPlace is most useful when chaining multiple functions in one JavaScript statement and not wanting to create temporary storage for intermediate variables. That said, if choosing only one of the three forms (returning new stored value versus InPlace versus ToRef) the “ToRef” form can easily be transformed to the others.

Is this logic different with Vec3 compared to Babylon-Full’s Vector3?

I’ve thought for a while that there’s redundancy in Vector, Color, and Matrix in the various sizes (2, 3, 4, 2x3, 3x3, 4x4) even given that (I think) only Vec4 and Matrix 4x4 are useful in shaders. I’ve found some utility in abstracting to a Matrix that stores its number of rows and columns. A Vector4 is Matrix 1x4 under the hood. Not sure how useful it is to others, though.

Yup it is per function:)