bitbybit.dev runner example - code javascript - 3D slide with physics

This example shows how you can write actual bitbybit javascript code by using the bitbybit-runner. Example creates 3D CAD model of the slide, enables physics and creates basic UI. Users can run the Havok physics simulation.

by matas_bitbybitdev

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>3D Slide With Physics - Bit By Bit Developers</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/[email protected]/runner/bitbybit-runner.js"></script>
    <script type="module" src="script.js"></script>
  </head>
  <body>
    <div class="example">
      <a
        class="logo"
        href="https://bitbybit.dev"
        target="_blank"
        rel="noopener noreferrer"
      >
        <img
          alt="Logo of Bit by bit developers company"
          src="https://bitbybit.dev/assets/logo-gold-small.png"
        />
        <div>bitbybit.dev</div>
      </a>
      <h1>Runner Example - Actual Code</h1>
      <div class="myCanvasZone">
        <canvas id="myCanvas"></canvas>
      </div>
      <a
        href="https://bitbybit.dev/projects/public/UwnghvO89ocgFv5U3P4m/script/sWwcLOMIjUpdigPv315i/script-3d-slide-with-physics-in-project-3d-slide-from-wire-offsets-by-author-matas"
        target="_blank"
        rel="noopener noreferrer"
      >
        This example is based on the project that was coded in TypeScript on bitbybit.dev Monaco editor.
      </a>
    </div>
  </body>
</html>

CSS

body {
  margin: 0;
  background-color: #1a1c1f;
  color: white;
  font-weight: 400;
  font-family: 'IBM Plex Sans', sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  width: 100%;
  height: 100%;
}

.example {
  margin-top: 50px;
  margin-bottom: 50px;
  margin-left: 300px;
  margin-right: 300px;
}

@media(max-width:1400px) {
  .example {
      margin-left: 100px;
      margin-right: 100px;
  }
}

@media(max-width:769px) {
  .example {
      margin-left: 20px;
      margin-right: 20px;
  }
}

#myCanvas {
  display: block;
  outline: none;
  border: 1px solid white;
  border-radius: 5px;
  width: 100%;
}

.logo {
  margin-bottom: 20px;
}

.logo img {
  width: 50px;
  height: 50px;
}

.myCanvasZone {
  margin-top: 20px;
  margin-bottom: 10px;
}

a {
  color: white;
  vertical-align: middle;
}

JavaScript

// Timeout is needed for HTML to have time to finish rendering. This also makes sure that myCanvas actually can be found
setTimeout(async () => {
  const runnerOptions = {
    canvasId: 'myCanvas',
    canvasZoneClass: 'myCanvasZone',
    enablePhysics: true,
    enableOCCT: true,
    enableJSCAD: false,
    enableKeyEventListeners: false,
    loadFonts: ['Roboto'],
  };

  const { bitbybit, Bit, BABYLON, GUI } = await window.bitbybitRunner.run(
    runnerOptions
  );

  BABYLON.GUI = GUI;

  const points = [
    [0, 42, -20],
    [-10, 40, -10],
    [0, 35, 0],
    [0, 32, 10],
    [20, 30, 16],
    [40, 27, 40],
    [-20, 24, 16],
    [-20, 20, -16],
    [10, 15, 16],
    [-10, 10, 16],
    [-10, 5, -16],
    [-25, 0, -26],
  ];
  const scene = bitbybit.babylon.scene.getScene();
  const cam = scene.activeCamera;
  cam.position = new BABYLON.Vector3(20, 50, 50);
  cam.target = new BABYLON.Vector3(0, 20, 0);
  cam.panningSensibility = 40;
  const model = {
    dashboard: undefined,
    nrBalls: 25,
    sphereMeshes: [],
    sphereAggregates: [],
    pointsForSpheres: undefined,
    sphereBase: undefined,
    wireForSpherePositions: undefined,
  };
  const guiControlNames = {
    button: 'RunSimButton',
    nrBallsHeader: 'NrBallsHeader',
    nrBallsSlider: 'NrBallsSlider',
    loadingIndicator: 'LoadingHeader',
  };
  const start = async () => {
    createGUI();
    showLoadingIndicator();
    const bawlMesh = await createBawl(50, 4, [0, 10, 0]);
    const bawlMeshCollision = bawlMesh.getChildMeshes()[0];
    const res = await createSlide(points);
    const slideMeshCollision = res.slide.getChildMeshes()[0];
    model.sphereBase = await createCompleteSphereMesh();
    bitbybit.babylon.scene.enablePhysics({
      vector: [0, -9.81, 0],
    });
    new BABYLON.PhysicsAggregate(
      slideMeshCollision,
      BABYLON.PhysicsShapeType.MESH,
      { mesh: slideMeshCollision, mass: 0, restitution: 0.75 }
    );
    new BABYLON.PhysicsAggregate(
     ...