3d viewer control with custom code
  • 27 Jun 2024
  • 2 Minutes to read
  • Contributors
  • Dark
    Light

3d viewer control with custom code

  • Dark
    Light

Article summary

If you need more functionality than the 3d viewer control provides out of the box in the configurator editor, you can use custom code to extend it by adding custom parameter observers, adjusting the viewer settings and much more.

Basic setup & usage

  • Set the 3d viewer control's viewer version property to Injected
  • Install the viewer in your custom code with npm i @combeenation/3d-viewer
  • Use the viewer control's injectViewer method to pass the viewer to the control:
    import { Viewer } from '@combeenation/3d-viewer';
    // ...
    CfgrUtils.onCfgrReady(() => {
      // ...
      CtrlUtils.getViewerCtrl('viewer3d').injectViewer(Viewer);
      // ...
    });
    
  • Use the viewer control's getViewer to get access to the viewer instance and the Babylon.js scene.
    const viewerCtrl = CtrlUtils.getViewerCtrl('viewer3d');
    const viewer = await viewerCtrl.getViewer();
    
    // E.g. create custom skybox from JPGs
    const scene = viewer.scene;
    const customReflection = new CubeTexture('', scene, null, null, files);
    const customSkybox = scene.createDefaultSkybox(customReflection, true, 10000);
    

Common use cases

When extending the viewer control's capabilities in custom code, there are almost no limits in what you can do. If you want to, you can have direct access to the underlying Combeenation 3d viewer & Babylon.js core which power the viewer control.

In the following chapters we'll explore some common use cases and explain how to best deal with them.

Add custom parameter observer

The viewer comes with some built in parameters which you can use with the control's set parameter values slot but you can also add your own, custom parameters using custom code.

These observers should be added before the initial viewer parameter update, as this update would not trigger the custom observers then.
Since getViewer is awaiting this initial parameter update, we have to access the observer in a different way.
For this case we can use the onAfterViewerCreated parameter of injectViewer.

This example shows, how to add a custom parameter named ShowBoundingBox with which you can show or hide a meshs bounding box:

CtrlUtils.getViewerCtrl('viewer3d').injectViewer(Viewer, {
  onAfterViewerCreated: (viewer: Viewer) => {
    viewer.tagManager.setParameterObserver('ShowBoundingBox', async ({ nodes, newValue }) => {
      nodes
        .filter(node => node instanceof AbstractMesh)
        .forEach(node => node.showBoundingBox = newValue)
    });        
  }
});

You can set & change the value of all custom parameters with the control's set parameter values slot like with all built in parameters.

Adjust viewer settings

The viewer control automatically creates a viewer instance which comes with a set of default values. You can customize these viewer settings before the viewer instance is created, using the onBeforeCreateViewer parameter of injectViewer.

CtrlUtils.getViewerCtrl('viewer3d').injectViewer(Viewer, {
  onBeforeCreateViewer: (viewerSettings: ViewerSettings) => {
    viewerSettings.useParallelShaderCompile = false;
    viewerSettings.engineOptions.useHighPrecisionMatrix = true;
  }
});

React on parameter application

There are cases where you want to execute code right after viewer parameters, set by the set parameter values slot, have been applied.
For example changing light setup or moving the camera to show the adjusted scene in a better way.
There is the onAfterParametersApplied parameter of injectViewer to achieve this.

CtrlUtils.getViewerCtrl('viewer3d').injectViewer(Viewer, {
  onAfterParametersApplied: (modelVisibility: ModelVisibilityEntry[], parameterValues: ParameterValues) => {
    // e.g. center camera if model has been changed
    if (modelVisibility.length) {
      await centerCamera();
    }
  }
});

Was this article helpful?

What's Next