Skip to main content

PlayCanvas Lite Runner

The lite runner requires you to load PlayCanvas separately before loading the runner. This results in a smaller Bitbybit bundle size and allows you to use your own version of PlayCanvas.

Live Example

Bitbybit Platform

StackBlitz - PlayCanvas Lite Runner Example

Complete Example

Below is a complete example that creates a parametric lofted surface with rectangle holes using OCCT:

<!doctype html>
<html lang="en">

<head>
<title>Bitbybit Runner PlayCanvas Lite Example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

<!-- Load PlayCanvas separately first -->
<script src='https://code.playcanvas.com/playcanvas-stable.min.js'></script>
<script type="module">
window.PLAYCANVAS = pc;
</script>

<!-- Load the lite runner (requires PlayCanvas to be loaded) -->
<script defer
src="https://cdn.jsdelivr.net/gh/bitbybit-dev/bitbybit-assets@latest/runner/bitbybit-runner-lite-playcanvas.js"></script>
<script type="module">

const runnerOptions = {
canvasId: 'myCanvas',
canvasZoneClass: 'myCanvasZone',
enableOCCT: true,
enableJSCAD: false,
enableManifold: false,
cameraPosition: [20, 10, 20],
cameraTarget: [10, 5, 0],
backgroundColor: "#1a1c1f",
loadFonts: ['Roboto'],
};

const runner = window.bitbybitRunner.getRunnerInstance();
const { bitbybit, Bit, camera, scene, app, pc } = await runner.run(
runnerOptions
);

// Create additional directional light
const dirLight = new pc.Entity("additionalLight");
dirLight.addComponent("light", {
type: "directional",
color: new pc.Color(1, 1, 1),
intensity: 2,
castShadows: true,
shadowBias: 0.2,
normalOffsetBias: 0.05,
shadowResolution: 2048
});
dirLight.setPosition(60, 70, -30);
dirLight.lookAt(0, 0, 0);
scene.addChild(dirLight);

// Model parameters
const model = {
uRec: 16,
vRec: 16,
rounding: 0.5,
drawEdges: true,
drawFaces: true,
color: '#6600ff'
}

// Create curve points for lofting
const curvePts = [
[[-10, 0, -10], [0, 3, -10], [10, -1, -10], [20, 2, -10]],
[[-10, -5, 0], [0, -3, 0], [10, 1, 0], [20, -2, 0]],
[[-10, 0, 10], [0, 3, 10], [10, -1, 10], [20, 2, 10]]
];

// Create wires from interpolated points
const wirePromises = curvePts.map((pts) => {
return bitbybit.occt.shapes.wire.interpolatePoints({
points: pts, periodic: false, tolerance: 1e-7
});
});

const wires = await Promise.all(wirePromises);
const loft = await bitbybit.occt.operations.loft({ shapes: wires, makeSolid: false });
const translated = await bitbybit.occt.transforms.translate({ shape: loft, translation: [0, 10, 0] });
const faces = await bitbybit.occt.shapes.face.getFaces({ shape: translated });

// Subdivide face with rectangle holes
const subdivideOptions = new Bit.Inputs.OCCT.FaceSubdivideToRectangleHolesDto(faces[0]);
subdivideOptions.nrRectanglesU = model.vRec;
subdivideOptions.nrRectanglesV = model.uRec;
subdivideOptions.scalePatternU = [0.9, 0.5, 0.7];
subdivideOptions.scalePatternV = [0.9, 0.5, 0.7];
subdivideOptions.filletPattern = [model.rounding];
subdivideOptions.inclusionPattern = [false, true, true, true, true];
subdivideOptions.offsetFromBorderU = 0.01;
subdivideOptions.offsetFromBorderV = 0.01;

const withHoles = await bitbybit.occt.shapes.face.subdivideToRectangleHoles(subdivideOptions);
const finalShape = await bitbybit.occt.operations.makeThickSolidSimple({
shape: withHoles[0], offset: 0.5
});

// Draw options
const options = new Bit.Inputs.Draw.DrawOcctShapeOptions();
options.precision = 0.02;
options.drawEdges = model.drawEdges;
options.drawFaces = model.drawFaces;
options.drawVertices = false;
options.edgeWidth = 20;
options.edgeColour = "#000000";
options.faceColour = model.color;
options.drawTwoSided = false;

const group = await bitbybit.draw.drawAnyAsync({ entity: finalShape, options });

</script>
<style>
body {
margin: 0;
background-color: #1a1c1f;
}
#myCanvas {
display: block;
width: 100%;
height: 100vh;
}
.myCanvasZone {
width: 100%;
height: 100vh;
}
</style>
</head>

<body>
<div class="myCanvasZone">
<canvas id="myCanvas"></canvas>
</div>
</body>

</html>

Key Points

Loading PlayCanvas First

<script src='https://code.playcanvas.com/playcanvas-stable.min.js'></script>
<script type="module">
window.PLAYCANVAS = pc;
</script>

Important: You must expose PlayCanvas to the window object as window.PLAYCANVAS before loading the lite runner.

Lite Runner Script

<script defer src="https://cdn.jsdelivr.net/gh/bitbybit-dev/bitbybit-assets@latest/runner/bitbybit-runner-lite-playcanvas.js"></script>

Note the defer attribute - this ensures the script loads after PlayCanvas is available.

Initialization

const runner = window.bitbybitRunner.getRunnerInstance();
const { bitbybit, Bit, camera, scene, app, pc } = await runner.run(runnerOptions);

The returned objects are the same as the full runner.

When to Use Lite vs Full

Use CaseRecommended
Quick prototypingFull Runner
Need specific PlayCanvas versionLite Runner
Smallest possible bundleLite Runner
Using other PlayCanvas modulesLite Runner
Simple single-page demosFull Runner

Runner Options

The options are the same as the full runner:

OptionTypeDescription
canvasIdstringThe ID of your canvas element
canvasZoneClassstringCSS class for the canvas container
enableOCCTbooleanEnable OpenCASCADE kernel
enableJSCADbooleanEnable JSCAD kernel
enableManifoldbooleanEnable Manifold kernel
cameraPositionnumber[]Initial camera position [x, y, z]
cameraTargetnumber[]Camera look-at target [x, y, z]
backgroundColorstringScene background color (hex)
loadFontsstring[]Fonts to load for text operations

GitHub Source

View the full source code on GitHub: PlayCanvas Lite Runner Examples