three.js
Integrate three.js rendering into ImFusion Web SDK views with a CustomGlObject.
Here we show a simplified version of three.js' lights / arealight demo, integrated with the SDK's views.
Loading demo…
Set up three.js so it does not interfere with the SDK: disable auto-clear so it never wipes the SDK's output, and reset the GL state after each frame.
ts
const renderer = new THREE.WebGLRenderer({
context: imf.canvas.getContext('webgl2')!,
preserveDrawingBuffer: true,
precision: 'mediump',
antialias: true,
});
renderer.autoClear = false;From these definitions, we can implement the render and bounds functions required by the CustomGlObject interface.
ts
// Here you would compute an axis aligned bounding box of your CustomGlObject in world space.
// This information is used by the ImFusion Web SDK to compute bounds for the whole rendered scene
// and corresponding clipping planes. For demo purposes we return invalid bounds, which tells the
// ImFusion Web SDK to ignore this CustomGlObject in those computations.
const bounds = new imf.bindings.AlignedBox();
const threejsGlObject = {
render: (viewState: GlViewState) => {
const imfViewport = viewState.viewport();
renderer.setViewport(imfViewport.x, imfViewport.y, imfViewport.width, imfViewport.height);
// Matrix4.set expects row-major order, which matches the ImFusion Web SDK convention
const imfProjectionMatrix = new THREE.Matrix4();
imfProjectionMatrix.set(...viewState.projectionMatrix());
// The SDK provides worldToView; invert it to get the camera transform
const imfModelViewMatrix = new THREE.Matrix4();
imfModelViewMatrix.set(...viewState.modelViewMatrix()).invert();
const position = new THREE.Vector3();
const rotationQuaternion = new THREE.Quaternion();
const scale = new THREE.Vector3();
imfModelViewMatrix.decompose(position, rotationQuaternion, scale);
camera.position.set(position.x, position.y, position.z);
camera.quaternion.set(rotationQuaternion.x, rotationQuaternion.y, rotationQuaternion.z, rotationQuaternion.w);
camera.scale.set(scale.x, scale.y, scale.z);
camera.projectionMatrix.copy(imfProjectionMatrix);
camera.projectionMatrixInverse.copy(imfProjectionMatrix).invert();
renderer.render(scene, camera);
renderer.resetState();
},
bounds: () => bounds,
};
const customGlObject = imf.createCustomGlObject(threejsGlObject, 'glObjectThreeJS');This defines our CustomGlObject that we can then add to the Display:
ts
imf.display.mainSagittalView().addObject(customGlObject);
imf.display.main3dView().addObject(customGlObject);