A Babylon.js specialty camera targeted at ecommerce scenarios.



Showroom Camera

A Babylon.js specialty camera targeted at ecommerce scenarios.


The ShowroomCamera is specialized for ecommerce scenarios, specifically focusing on two "showroom" behaviors common to 3D product viewer/configurators: "matchmoving" and "arc-rotate inspection."

"Matchmoving" is a non-interactive behavior where the camera moves along a predetermined path, typically in order to showcase some aspect of a 3D model. For example, if a 3D product viewer for a watch wanted to showcase the watch band's clasp, this could be done by having the camera zoom in for a closeup of the clasp and then "matchmove" on an artist-defined trajectory to show the clasp from different angles.

Contrastingly, "arc-rotate inspection" is an interactive behavior where the camera focuses on a particular point in space, then gives the user (limited) control of the camera typically so that a 3D model can be inspected from different angles at will. For example, if a 3D product configurator allowed users to customize certain aspects of a 3D model, the users might want to be able to manipulate the 3D model interactively in order to view their changes. This behavior is classically encapsulated by Babylon.js's built-in ArcRotateCamera.

The ShowroomCamera makes it easy and seamless to combine these two behavior patterns in a single cohesive experience. This is done by specifying states -- IShowroomCameraMatchmoveState and IShowroomCameraArcRotateState -- representing the different behaviors a camera should undertake in a given experience. For example, a 3D viewer/configurator showcasing a watch might want to have multiple matchmoving states showcasing various aspects of the watch (the face, the clasp, etc.) as well as an arc-rotate state to be used during interactive configuration. To do this with a ShowroomCamera, all that's required is to create the appropriate IShowroomCameraMatchmoveState and IShowroomCameraArcRotateState objects and provide them to the ShowroomCamera at the appropriate times.

// From ShowroomCamera.Demo()
const matchmoveState: IShowroomCameraMatchmoveState = {
    matchmoveTarget: matchmove,
    focusDepth: 10

const arcRotateState: IShowroomCameraArcRotateState = {
    startingPosition: new Vector3(0, 5, -10),
    target: new Vector3(0, 1, 0)

const setStateFunction = async function() {
    while (true) {
        await Tools.DelayAsync(7000);
        await Tools.DelayAsync(7000);
        await camera.animateToArcRotateState(arcRotateState);
        await Tools.DelayAsync(7000);
        await camera.animateToMatchmoveState(matchmoveState);
        await Tools.DelayAsync(7000);

        camera.animateToArcRotateState(arcRotateState, 4);
        await Tools.DelayAsync(3000);
        camera.animateToMatchmoveState(matchmoveState, 4);
        await Tools.DelayAsync(2000);


Showcasing a particular part of a 3D model by "dollying" the camera along a predetermined path is a common objective, but defining that path and translating it into a 3D experience is often a challenge. ShowroomCamera's IShowroomCameraMatchmoveStates resolve this challenge by allowing 3D artists to define the trajectory in their own familiar Digital Content Creation (DCC) tools (Blender, 3ds Max, etc.) as an animated named "null" (empty 3D transform) which can be then exported in a common 3D format (such as glTF).

Say, for example, that the 3D artist making a model of a watch wanted to showcase the watch's clasp by having a camera "orbit" around the clasp in closeup. In the artist's chosen DCC tool -- potentially even in the same 3D file as the watch itself -- the artist can create a "null" named something like "clasp_camera_orbit" which is driven by an animation named "clasp_camera_animation" to follow the path the artist wants the camera to follow. (If the DCC tool allows it, the artist may even add a camera to this "null" to make it easy to see what a render from this animated orbit might look like.) This "null" and animation can then be exported -- again, potentially alongside the watch itself -- to a glTF (or equivalent) 3D file that can be imported into a Babylon.js experience.

When this glTF is imported into Babylon.js, the "null" will be represented in the Babylon scene by a TransformNode with the name specified in the DCC tool, in this case "clasp_camera_orbit." Similarly, the animation that moves this TransformNode will be represented as a Babylon AnimationGroup with the specified name -- "clasp_camera_animation." Using these imported resources, the artist's intended camera trajectory can be replicated in the Babylon experience by simply playing the "clasp_camera_animation" AnimationGroup, referencing the "clasp_camera_orbit" TransformNode in an IShowroomCameraMatchmoveState, then setting a showroom camera to use that IShowroomCameraMatchmoveState using setToMatchmoveState (which will teleport the camera instantly to the matchmove trajectory) or animateToMatchmoveState (which will smoothly move the camera to the matchmove directory using a procedural animation).

Using this approach, IShowroomCameraMatchmoveStates can give artists complete control of camera behavior in the matchmoving state of the 3D experience using only the DCC tools with which the artist is already comfortable. This is particularly powerful when it comes to updating the animation. Because the camera motion itself was completely specified in the artist's tools, any updates to or enhancements of the camera motion can be done entirely in those same tools: as long as the "null" and driving animation's names remain the same, any changes the artist makes to the motion and exports into a new glTF will be imported into the experience and hooked up by name automatically, without requiring any code changes at all.


Interactively inspecting a 3D model from different angles is another common objective, and it's one that is particularly well-served by Babylon.js's built-in ArcRotateCamera. Given that it already works extremely well, the ShowroomCamera does not seek to modify the ArcRotateCamera's behavior at all; instead, ShowroomCamera makes it easy to move into and out of arc-rotate states by specifying IShowroomCameraArcRotateStates to represent them.

Unlike IShowroomCameraMatchmoveStates, which are intended to follow artist-defined trajectories described by animated TransformNodes, IShowroomCameraArcRotateStates specify starting positions and settings for an interval of interaction during which the ShowroomCamera will enable an ArcRotateCamera. Over the interactive period, ArcRotateCamera will control its own position and rotation (and only a limited range of rotations are allowable even from the start) because it's interactive, so inherently less control can be given to the artist's DCC tool. This is reflected in the fact that IShowroomCameraArcRotateStates take Vector3s for position and target instead of a TransformNode: whereas a TransformNode specifies its own rotation, the ArcRotateCamera's rotation cannot be externally specified in this way and will be deduced by the ArcRotateCamera itself from its position and target, both of which are Vector3 values in world space. Note that these Vector3s can (and probably should) still be specified by the artist using "nulls" in the DCC tool; the difference is that the rotations of the resulting TransformNodes will be ignored and only the world space positions -- accessible using transformNode.absolutePosition -- will be used to create an IShowroomCameraArcRotateState.

Procedural Animations

Transitioning between various states can be either instantaneous (using setToMatchmoveState or setToArcRotateState) or animated (using animateToMatchmoveState or animateToArcRotateState). Instantaneous transitions are simple: the camera will just "teleport" to the new location immediately. (Note that the abruptness of such a transition can be mitigated by fade-in/fade-out techniques or other tricks that are not part of the ShowroomCamera.) The animated transitions, however, require procedural animation.

Procedural animation, in this case, means using code and math to animate an object instead of using predetermined motions created by an artist in a DCC tool. Generally speaking, procedural animations are less desirable than artist-specified animations because it's more difficult to control the procedural behavior precisely. In this case, however, procedural animation is unavoidable because of the interactive nature of the experience. The motion of the ArcRotateCamera itself is a form of procedural animation, and transitioning smoothly from such interactive procedural animation to non-interactive artist-specified animation requires an interval of non-interactive procedural animation.

Generally speaking, users shouldn't have to worry about how this procedural animation works as it is an implementation detail of the ShowroomCamera. The only place where this logic is somewhat exposed is in the focusDepth optional parameter of the IShowroomCameraMatchmoveState, which (if provided) approximates how far in front of the camera what the camera's "focused on" is. For example, if the IShowroomCameraMatchmoveState in question is orbiting the clasp of a watch, the focusDepth might be specified to the approximate distance between the camera and the clasp geometry it's orbiting.

This focusDepth parameter is not used at all during an IShowroomCameraMatchmoveState because, in that state, the motion of the camera is completely controlled by the TransformNode specified as the matchmoveTarget. focusDepth is only used during a procedural transition animation to control the rotation of the camera during its procedural animation -- specifically the direction it's looking. At a high level, every ShowroomCamera state has some notion of both where it is and what it's looking at, and the goal of the procedural transition animations is to derive a sequence of intermediate positions and look-at targets to allow the camera to smoothly move from one state to the next. In the case of IShowroomCameraArcRotateState, the look-at target is specified by the ArcRotateCamera itself: target. In the case of IShowroomCameraMatchmoveState, the look-at target is derived from the focusDepth of the state combined with the position and forward direction of the matchmoving camera at the start of the transition.

Questions? Comments? Concerns?

For help understanding, using, or fixing issues with the ShowroomCamera, please ping syntheticmagus on a question in the Questions section of the Babylon.js Community Forum. Thanks!

Monetize your
open-source work

Supercharge your OSS projects by selling npm packages. Get started in just 5 minutes.