Script: 3D Bike Animation Gaussian Splatting

3D Bike Animation Gaussian Splatting picture
Type
Typescript logo indicatortypescript
Date Created
Jun 6, 2024, 8:55:09 PM
Last Edit Date
Oct 2, 2025, 4:00:09 PM

Project Information

The scanned 3D bike on the grass, displayed by using gaussian splatting technique

View Full Project

Script Code

const { occt } = bitbybit;

enum cameraAnimationEnum {
    ellipse,
    spiral,
    line,
};

let activeAnimation = cameraAnimationEnum.spiral;

const start = async () => {
    const assetPalm = await bitbybit.asset.getFile({ fileName: "bike.splat" });
    const objectUrl = bitbybit.asset.createObjectURL({ file: assetPalm });
    const gs = await bitbybit.babylon.gaussianSplatting.create({
        url: objectUrl
    });

    // gs.position = new BABYLON.Vector3(-0.6, 0.1, -0.1);

    const box = await occt.shapes.solid.createBox({
        width: 5,
        height: 0.3,
        length: 5,
        center: [-0.2, -0.2, 0],
    });

    const drawopt = new Bit.Inputs.Draw.DrawOcctShapeOptions();
    drawopt.drawEdges = false;
    drawopt.faceColour = "#444444";
    await bitbybit.draw.drawAnyAsync({
        entity: box,
        options: drawopt,
    });

    const skyboxDto = new Bit.Inputs.BabylonScene.SkyboxDto();
    skyboxDto.blur = 0.5;
    skyboxDto.skybox = Bit.Inputs.Base.skyboxEnum.city;
    bitbybit.babylon.scene.enableSkybox(skyboxDto);

    const gridOpt = new Bit.Inputs.Draw.SceneDrawGridMeshDto();
    bitbybit.draw.drawGridMesh(gridOpt);

    setupCameraAndAnimations();
}


async function setupCameraAndAnimations() {

    let wire;
    if (activeAnimation === cameraAnimationEnum.ellipse) {
        wire = await occt.shapes.wire.createEllipseWire({
            center: [0, 3, 0],
            radiusMinor: 4,
            radiusMajor: 5,
            direction: [0, 1, -0.1]
        });
    } else if (activeAnimation === cameraAnimationEnum.line) {
        wire = await occt.shapes.wire.createLineWire({
            start: [10, 2, 10],
            end: [-6, 2, -9],
        });
    } else if (activeAnimation === cameraAnimationEnum.spiral) {
        const radius = 4;
        const step = 0.5;


        const ptsSpiralBase: Bit.Inputs.Base.Point3[] = [
            [radius, step * 4, 0],
            [0, step * 5, radius],
            [-radius, step * 6, 0],
            [0, step * 7, -radius],
            [radius, step * 8, 0],
            [0, step * 9, radius],
            [-radius, step * 10, 0],
            [0, step * 11, -radius],
        ];
        wire = await occt.shapes.wire.interpolatePoints({ points: ptsSpiralBase, periodic: false, tolerance: 0.01 });
    }
    const points = await occt.shapes.wire.divideWireByEqualDistanceToPoints({ shape: wire, nrOfDivisions: 10000, removeStartPoint: false, removeEndPoint: true });

    const ptsLooped = [...points, ...points.reverse()]

    const camera = bitbybit.babylon.scene.getActiveCamera() as BABYLON.ArcRotateCamera;
    camera.target = new BABYLON.Vector3(0, 1, 0);
    let index = 0;
    bitbybit.time.registerRenderFunction(() => {
        if (index < ptsLooped.length) {
            const pt = ptsLooped[index];
            camera.setPosition(new BABYLON.Vector3(pt[0], pt[1], pt[2]))
            index++;
        } else {
            index = 0;
        }
    });
}

start();