Light serialization

has a list of light properties which are serialized.

Actually serializing a scene with a light discovers a few more:

  tags: null
  shadowFrustumSize: 0
  shadowOrthoScale: 0.1
  autoUpdateExtends: true
  autoCalcShadowZBounds: false
  orthoLeft: 1.7976931348623157e+308
  orthoRight: 5e-324
  orthoTop: 5e-324
  orthoBottom: 1.7976931348623157e+308
  diffuse: Array(3) [1, 1, 1]
  specular: Array(3) [1, 1, 1]
  falloffType: 0
  intensity: 1
  range: 1.7976931348623157e+308
  intensityMode: 0
  radius: 0.00001
  _renderPriority: 0
  shadowEnabled: true
  excludeWithLayerMask: 0
  includeOnlyWithLayerMask: 0
  lightmapMode: 0
  position: Array(3) [-0, -0, 1]
  direction: Array(3) [0, 0, -1]
  name: "HeadLight"
  id: "HeadLight"
  state: ""
  type: 1
  animations: Array(0) []
  ranges: Array(0) []

This list additionally includes “state” which I believe does not have an internal function. I was looking for an “enabled” flag, corresponding to the setEnabled() method.

Is there a way to automatically recover the setEnabled state of lights upon parsing ? Or is it necessary to do some additional work after parsing ?

1 Like

The enabled state is stored in _nodeDataStorage._isEnabled . _nodeDataStorage is an “internal” object to nodes, and does not seem to be serialized. All of the other stored data in it are more directly a result of internal processing and it is more difficult to see a use case for serialization of those. But enabled is directly exposed via setEnabled and is of a different nature I would suggest. A simple use case of enabled state serialization would be that initially in a scene a light is disabled and then through interaction or passage of time can be switched on.

As a workaround, I simply add _nodeDataStorage to metadata which lets the object become serialized, as much as possible. Then after scene loading, I process _nodeDataStorage for each light or node manually, for now just by node.setEnabled(metadata._nodeDataStorage._isEnabled)

It works and seems efficient but there may be good arguments for making isEnabled serializable for lights or perhaps all nodes. There may be also design arguments against which could be discovered. Perhaps there would be (unintended) consequences of some kind ?

2 Likes

I am not opposed to it but I wonder what @Deltakosh is thinking ?

1 Like

Yes, I feel I may be missing something. Perhaps just being careful to introduce only more important features since once introduced it will be difficult to deprecate. But perhaps the alpha version allows for some exploration ? That being said, support for serializing “enabled” could be popular.

One potential issue I can think of could arise if _isEnabled can be undefined, initially, and scenes somehow rely on that after loading. Seems farfetched ?

1 Like

I’m totally fine serializing isEnabled as long as it is on by default (if the field is absent from the serialized format)

4 Likes

Sounds like you have the go ahead! Do you want to try implementing it? We’d be more than happy to review a PR, or give you help if you have trouble anywhere.

Ideally it would work for all nodes, not just lights. Also, do you have a solution in mind that wouldn’t rely on metadata?

1 Like

Super. I definitely would need support as I am not familiar with the code base, coding style, build system or pitfalls. I will have a lot of reading to do starting with Start Contributing to Babylon.js | Babylon.js Documentation . Is there a recommended way to develop completely “in the cloud” ? Perhaps with vscode in the browser, Github workflows/actions ? I do not tend to have a single, main development machine. Ah, I see Dashboard — Gitpod looks like the way to go. Any tips for gitpod ?

seems like the main place to start. What does @serialize() do ? Which other files would be relevant ? Also then for parsing back ?

I was only relying on metadata because metadata is already serialized. The idea would be to serialize _nodeDataStorage._isEnabled, probably as node.isEnabled .

1 Like

Ok, I found that @serialize() is a decorater factory which appears to enable serialization of a member/field.

In node.ts

    private _nodeDataStorage = new _InternalNodeDataInfo();
/* specify source name and pull _isEnabled out from _nodeDataStorage */
    @serialize("isEnabled")
    private readonly _isEnabledRef = this._nodeDataStorage._isEnabled;

serializes now but does not update as the field is only initialized.

But it turns out one can also decorate a getter:

    @serialize("isEnabled") 
    //public readonly _isEnabledRef: boolean;

    /**
     * Gets a boolean used to define if the node is enabled
     */
    private get _isEnabledRef() {
        return this.isEnabled()
    }

And this seems to work fine. Does that approach seem like it is on the right track ?

I would not rely on the decorators for this one but rather manually update the serialize( function of node inherited classes to handle back compat and not expose unnecessary proxy properties.

That being said, anything inheriting from transformNode is already ok:

Serialization: Babylon.js/transformNode.ts at b556b96a004e77e2e141a210de819b931097867e · BabylonJS/Babylon.js · GitHub

and Deserialization: Babylon.js/transformNode.ts at b556b96a004e77e2e141a210de819b931097867e · BabylonJS/Babylon.js · GitHub

You could simply do the same in lights and camera which are the two missing ones :slight_smile:

2 Likes

Thanks, very helpful. It did seem off to have a getter proxy field just for serialization purposes. I did not realize transformNode.ts already has it. It seems straightforward enough to do lights and cameras in the same way.

On the other hand, as all node inheriting nodes are affected node.ts would seem to be the right level, and it may be desirable at some point to move all the isEnabled serialization there. Would _isEnabledRef (should be _isEnabledProxy) be exposed in Javascript if it is private and only has a getter ? Probably. It seems that there are plenty of exposed, more private _properties, just probably no proxy getters like this. It may mean to move ._isEnabled out of _nodeDataStorage but that seems like a larger change (unless _nodeDataStorage._isEnabled is never directly accessed outside of node.ts which may happen in user code).

What is there to consider with respect to back compat. ? Thanks for any feedback.

1 Like

If you do like transformNode, only thing to consider is to ensure that if isEnabled is not present, you are forcing it to true to not break previous .babylon

1 Like

Yes, light/camera.Parse() will check for ( "isEnabled" in parsedNode ) if that is the preferred way to determine if a property is present. transformNode.Parse does not seem to do that ?

Ah, it looks like if ( parsedNode.isEnabled ) is generally preferred.

Anyways, let me see how far I get. Thanks so much for the quick input.

2 Likes

Except if (parsedNode.isEnabled) will not work to test presence since isEnabled is boolean …

I am looking for examples to test setting camera.setEnabled(false). Does it have any effect ? It does not seem to disable rendering.

Here is a Playground:

https://playground.babylonjs.com/#4JXV32#40

Please see serialize isEnabled for lights and cameras by andreasplesch · Pull Request #11436 · BabylonJS/Babylon.js · GitHub for review.

Searching through the code base did not discover use of isEnabled() for cameras for me but I may have missed something. It could still be useful to serialize if somebody wants to use it for their own purposes which probably should not be encouraged.

The serialization is now functional on the Playground.

1 Like