What is a scene object?

A scene object is a collection of scene nodes and components that are instantiated and executed together to exhibit complex behaviors.

Why use scene objects?

  • Scene objects manage the life cycle of their scene nodes, components, and bindings making it easy to start and stop the collection of scene nodes.
  • Scene objects support bindings between components of different scene nodes (version 2.0). Previously, bindings were only supported between components of the same scene node.
  • Scene objects support serialization making it possible to persist node/component/binding configurations and restore their behaviors at runtime. Scene objects are serialized to JSON making them easy to manually edit.
  • Scene objects remove creation and initialization steps, configure scene nodes, and components reducing the amount of code that needs to be maintained.

Example: A simple fbx loader

Manual construction and initialization

const [sceneObject] = await sdk.Scene.createObjects(1);

// add a scene node for the fbx model
const gltfNode = sceneObject.addNode();

// adjust the position of the scene node
gltfNode.obj3D.position.set(0, -0.68, 0);

// add the gltf loader component that loads a parrot model. Adjust the model's scale to make it fit inside the model.
const gltfComponent = gltfNode.addComponent('mp.gltfLoader', {
  url: 'https://cdn.jsdelivr.net/gh/mrdoob/three.js@dev/examples/models/gltf/Parrot.glb',
  localScale: {
      x: 0.03,
      y: 0.03,
      z: 0.03,
  },
});

// Add a path id 'gltfUrl' to the gltf component url property (not used in the this example).
sceneObject.addInputPath(gltfComponent, 'url', 'gltfUrl');

// add another scene node to contain the light objects.
const lightsNode = sceneObject.addNode();

// Add directional and ambient lights
const directionalLightComponet = lightsNode.addComponent('mp.directionalLight', {
  color: { r: 0.7, g: 0.7, b: 0.7 },
});
lightsNode.addComponent('mp.ambientLight', {
  intensity: 0.5,
  color: { r: 1.0, g: 1.0, b: 1.0 },
});

// Add a path id 'ambientIntensity' to the intensity property of the directional light component.
// The path will be used to set the value later.
const ambientIntensityPath = sceneObject.addInputPath(directionalLightComponet, 'intensity', 'ambientIntensity');

// Start the scene object and its nodes.
sceneObject.start();

Here is an example of an update function that animates the intensity of the directional light component using the path id.

let intensity = 1;
const intensityMax = 3;
const intensityMin = 0.5;
const intensityDelta = 0.02;
let intensityDirection = 1;
setInterval(() => {
  intensity += (intensityDelta * intensityDirection);

  if (intensity >= intensityMax) {
    intensity = intensityMax;
    intensityDirection = intensityDirection * -1;
  }
  else if (intensity <= intensityMin) {
    intensity = intensityMin;
    intensityDirection = intensityDirection * -1;
  }

  // The path can be used as the public interface to the component behaviors contained within the scene object.
  ambientIntensityPath.set(intensity);
}, 15);

You can serialize the contents of the scene object to reduce the amount of code required to construct and initialize the scene objects and components as follows:

// Starting from the previous example, serialize the scene object to a json string
// after having started it. All nodes, components, bindings and paths are preserved.
const serializedString = await sdk.Scene.serialize(sceneObject);

// To restore the scene object, deserialize and start it.
const deserializedSceneObject = await mpSdk.Scene.deserialize(serializedString);
deserializedSceneObject.start();

// iterate over the paths to find  the ones that we previously set by using their ids
let ambientIntensityPath: MpSdk.Scene.InputPath;
let gltfUrlPath: MpSdk.Scene.InputPath;
for (const { desc, path } of sceneObject.pathIterator()) {
  if (desc.id === 'ambientIntensity') {
    ambientIntensityPath = path;
  }
  if (desc.id === 'gltfUrl') {
    gltfUrlPath = path;
  }
}

// You can now set the previously defined path.
ambientIntensityPath.set(1.5);

// or set the url
gltfUrlPath.set('https://cdn.jsdelivr.net/gh/mrdoob/three.js@dev/examples/models/gltf/Stork.glb');