Script: GLTF file manipulation

GLTF file manipulation picture
Type
Typescript logo indicatortypescript
Date Created
Jan 14, 2025, 8:49:36 AM
Last Edit Date
Jan 29, 2025, 2:04:58 PM

Project Information

Test loading GLB into the 3D Bits app and change the color via product variant without disturbing the model

View Full Project

Script Code

enum picturesEnum {
    bucket = "Bucket",
    vases = "Vases",
    woman = "Woman",
}

enum sizeEnum {
    s = "S",
    m = "M",
    l = "L",
}

Bit.mockBitbybitRunnerInputs({
    bitsContext: {
        iterationCount: 0,
    },
    "Picture": picturesEnum.vases,
    "Size": "S",
});

interface Inputs {
    bitsContext: {
        iterationCount: number,
    },
    Picture: picturesEnum,
    Size: sizeEnum,
}

interface SceneMetadata {
    sceneLoaderRes?: BABYLON.ISceneLoaderAsyncResult,
    materialToApply?: BABYLON.PBRMetallicRoughnessMaterial,
    texturesLoaded?: BABYLON.Texture[],
    previousInputs?: Inputs,
}

const inputs = Bit.getBitbybitRunnerInputs<Inputs>();

async function start() {
    const scene = bitbybit.babylon.scene.getScene();
    const sceneMetadata: SceneMetadata = scene.metadata;
    if (inputs.bitsContext.iterationCount === 0) {

        const glbContent = await BABYLON.SceneLoader.ImportMeshAsync("", "https://cdn.shopify.com/3d/models/55f9034057081157/", "frame.glb", scene);
        sceneMetadata.sceneLoaderRes = glbContent;
        const bucketTexture = new BABYLON.Texture("https://cdn.shopify.com/s/files/1/0700/3350/6556/files/bucket.webp?v=1737984516");
        const vasesTexture = new BABYLON.Texture("https://cdn.shopify.com/s/files/1/0700/3350/6556/files/vases.png?v=1737984516");
        const womanTexture = new BABYLON.Texture("https://cdn.shopify.com/s/files/1/0700/3350/6556/files/3dgirl.png?v=1737984516");

        sceneMetadata.texturesLoaded = [bucketTexture, vasesTexture, womanTexture];
        sceneMetadata.texturesLoaded.forEach(t => {
            t.uScale = 1;
            t.vScale = 1;
            t.vOffset = 1;
            t.uOffset = 1;
            t.wAng = Math.PI;
            t.level = 2;
        });
        const material = new BABYLON.PBRMetallicRoughnessMaterial("mainMaterial");
        material.baseTexture = bucketTexture;

        sceneMetadata.materialToApply = material;

        const pictureMesh = glbContent.meshes.find(m => m.name === "Picture");
        pictureMesh.material = material;

        const lightOpt = new Bit.Inputs.BabylonScene.DirectionalLightDto();
        lightOpt.intensity = 1;
        await bitbybit.babylon.scene.drawDirectionalLight(lightOpt);

        applyAppropriateTextureAndSize();
    } else {
        applyAppropriateTextureAndSize();
    }

    function applyAppropriateTextureAndSize() {
        if ((sceneMetadata.previousInputs && sceneMetadata.previousInputs.Picture !== inputs.Picture) || !sceneMetadata.previousInputs) {
            switch (inputs.Picture) {
                case picturesEnum.bucket:
                    sceneMetadata.materialToApply.baseTexture = sceneMetadata.texturesLoaded[0];
                    break;
                case picturesEnum.vases:
                    sceneMetadata.materialToApply.baseTexture = sceneMetadata.texturesLoaded[1];
                    break;
                case picturesEnum.woman:
                    sceneMetadata.materialToApply.baseTexture = sceneMetadata.texturesLoaded[2];
                    break;
                default:
                    break;
            }
        }

        if ((sceneMetadata.previousInputs && sceneMetadata.previousInputs.Size !== inputs.Size) || !sceneMetadata.previousInputs) {
            const rootMesh = sceneMetadata.sceneLoaderRes.meshes.find(m => m.name === "__root__");
            switch (inputs.Size) {
                case sizeEnum.s:
                    rootMesh.scaling = new BABYLON.Vector3(1, 1, -1);
                    break;
                case sizeEnum.m:
                    rootMesh.scaling = new BABYLON.Vector3(1.5, 1.5, -1.5);
                    break;
                case sizeEnum.l:
                    rootMesh.scaling = new BABYLON.Vector3(2, 2, -2);
                    break;
                default:
                    break;
            }
        }

        sceneMetadata.previousInputs = inputs;
    }

    const meshes = []
    return { meshes };
}

Bit.setBitbybitRunnerResult(start());