Skip to main content

Building a 3D Table Configurator with TypeScript & Bitbybit Runner

What You Will Learn

In this tutorial, you will learn how to create an interactive 3D website by leveraging JavaScript, HTML, CSS, and code exported from our TypeScript web CAD editor on Bitbybit.

We will guide you through setting up the logic for a 3D table model configurator, introducing some basic 3D programming concepts along the way. This project will utilize:

  • OpenCascade Technology (OCCT) geometry kernel algorithms for creating the table's parametric shapes.
  • BabylonJS game engine for rendering the 3D scene, all facilitated through the bitbybit-runner.js library.
  • We'll also set up a skybox and a directional light to cast shadows, enhancing the visual realism.

This free lecture is designed for a wide audience, from beginners looking to dive into parametric design and 3D web development, to experts wanting to integrate our open-source technologies into their own products and applications.

Final Result & Code

You can either check the live demo of StackBlitz project or use the code snippets below to recreate it on your own website.

Bitbybit Platform

StackBlitz - 3D Table Configurator TypeScript

TypeScript Code (The Program)

The following Bitbybit TypeScript script is the program that defines the logic for our 3D table configurator. The JavaScript code used in the StackBlitz example is what gets generated (or is very similar to what you'd write directly after transpilation) when you use the "Export to Runner" feature from this TypeScript script.

Bitbybit Platform

Bitbybit TypeScript Editor - 3D Table Configurator

typescript logoTypescript
Script Source (typescript)
type Inputs = {
width: number;
length: number;
height: number;
thickness: number;
};

const defaultValues: Inputs = {
width: 1,
length: 1,
height: 0.5,
thickness: 0.05,
};

Bit.mockBitbybitRunnerInputs(defaultValues);
const inputs: Inputs = Bit.getBitbybitRunnerInputs();

const { solid, compound, face } = bitbybit.occt.shapes;

const legHeight = inputs.height - inputs.thickness;
const halfLegHeight = legHeight / 2;
const halfThickness = inputs.thickness / 2;
const widthOffset = inputs.width / 2 - halfThickness;
const lengthOffset = inputs.length / 2 - halfThickness;


const start = async () => {

const skyboxOptions = new Bit.Inputs.BabylonScene.SkyboxDto();
skyboxOptions.skybox = Bit.Inputs.Base.skyboxEnum.clearSky;
bitbybit.babylon.scene.enableSkybox(skyboxOptions);

const lightOptions = new Bit.Inputs.BabylonScene.DirectionalLightDto();
lightOptions.intensity = 3;
bitbybit.babylon.scene.drawDirectionalLight(lightOptions);

const tableTopShape = await solid.createBox({
width: inputs.width,
length: inputs.length,
height: inputs.thickness,
center: [0, inputs.height - halfThickness, 0],
});

const leg1Shape = await solid.createBox({
width: inputs.thickness,
length: inputs.thickness,
height: legHeight,
center: [widthOffset, halfLegHeight, lengthOffset],
});
const leg2Shape = await solid.createBox({
width: inputs.thickness,
length: inputs.thickness,
height: legHeight,
center: [-widthOffset, halfLegHeight, lengthOffset],
});
const leg3Shape = await solid.createBox({
width: inputs.thickness,
length: inputs.thickness,
height: legHeight,
center: [widthOffset, halfLegHeight, -lengthOffset],
});
const leg4Shape = await solid.createBox({
width: inputs.thickness,
length: inputs.thickness,
height: legHeight,
center: [-widthOffset, halfLegHeight, -lengthOffset],
});

const groundShape = await face.createCircleFace({
radius: 2,
center: [0, 0, 0],
direction: [0, 1, 0]
});

const compoundShape = await compound.makeCompound({
shapes: [tableTopShape, leg1Shape, leg2Shape, leg3Shape, leg4Shape, groundShape],
});

const drawOptions = new Bit.Inputs.Draw.DrawOcctShapeSimpleOptions();
drawOptions.faceColour = "#555577";
drawOptions.edgeWidth = 1;
const table = await bitbybit.draw.drawAnyAsync({ entity: compoundShape, options: drawOptions });
return { table };
}

const runnerOutput = start();
Bit.setBitbybitRunnerResult(runnerOutput);

Complete Code for Your Website

Below are the index.html and script.js files you would use on StackBlitz or your own website to run the 3D table configurator. The index.html is identical to the previous table configurator examples, as the UI controls are the same. The primary difference lies in the script.js content, which will now execute the logic adapted from or exported from the TypeScript editor.

<!DOCTYPE html>
<html lang="en">
<head>
<title>Home</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="styles.css" />
<script src="https://cdn.jsdelivr.net/gh/bitbybit-dev/bitbybit-assets@0.15.14.1/runner/bitbybit-runner.js"></script>
<script type="module" src="script.js"></script>
</head>
<body>
<h1>3D Table Configurator</h1>
<div class="myCanvasZone">
<canvas id="myCanvas"></canvas>
</div>
<div>
<input
id="width"
type="range"
value="1"
min="0.3"
max="3"
step="0.1"
onchange="changeModel(+event.target.value, 'width')"
/>
<label for="width">Width</label>
</div>
<div>
<input
id="length"
type="range"
value="1"
min="0.3"
max="3"
step="0.1"
onchange="changeModel(+event.target.value, 'length')"
/>
<label for="length">Length</label>
</div>
<div>
<input
id="height"
type="range"
value="0.5"
min="0.3"
max="1.5"
step="0.1"
onchange="changeModel(+event.target.value, 'height')"
/>
<label for="height">Height</label>
</div>
<div>
<input
id="thickness"
type="range"
value="0.05"
min="0.01"
max="0.25"
step="0.01"
onchange="changeModel(+event.target.value, 'thickness')"
/>
<label for="thickness">Thickness</label>
</div>
</body>
</html>

Note: Remember to replace <version-number> in the bitbybit-runner-babylonjs.js script tag with an actual version number (e.g., 0.25.0). Check Bitbybit GitHub Releases for the latest version.


This tutorial highlights the capabilities of using TypeScript for creating complex 3D parametric models and interactive configurators. By leveraging Bitbybit's TypeScript environment and the Bitbybit Runner, developers can build sophisticated web applications that integrate advanced CAD functionalities with the rendering power of BabylonJS, all controlled through a familiar and powerful programming language.