Importing multiple meshes per model with AssetsManager

I found a solution. Not sure it’s the best but it works. In blender, I reverted to the previous pattern, with a top level object with an empty mesh and several child objects with their mesh and materials e.g.:

Then for the import I use:


const parent_mesh_names = new Set([
    mesh_name_low_poly_tree_1,
    mesh_name_low_poly_house_2,  // === "low_poly_house_2" same as in blender
])
function load_assets (assets_manager: BABYLON.AssetsManager)
{
    assets_manager.addMeshTask("load low_poly_tree_1", null, "public/models/low_poly_tree/", "low_poly_tree_1.obj")
    assets_manager.addMeshTask("load low_poly_house_2", null, "public/models/low_poly_house/", "low_poly_house_2.obj")

    assets_manager.onTaskSuccess = task =>
    {
        if (is_MeshAssetTask(task))
        {
            const parent_mesh = task.loadedMeshes.find(mesh => parent_mesh_names.has(mesh.name))
            if (!parent_mesh)
            {
                console.error("No parent mesh found whilst loading ", task.name)
                return
            }

            task.loadedMeshes.forEach(mesh =>
            {
                if (mesh.name !== parent_mesh.name) parent_mesh.addChild(mesh)
                mesh.visibility = 0
            })
        }
    }
}

function is_MeshAssetTask (task: BABYLON.AbstractAssetTask): task is BABYLON.MeshAssetTask
{
    return (task as BABYLON.MeshAssetTask).loadedMeshes !== undefined
}

And then when I come to use them I use the following utility functions:

interface GetMeshOptions
{
    parent_node?: Node | null
    position?: Vector3
    receive_shadows?: boolean
    shadow_generator?: ShadowGenerator
    visibility?: number
}

export function get_mesh (scene: Scene, mesh_name: string, new_mesh_name: string, options: GetMeshOptions = {})
{
    const mesh = scene.getMeshByName(mesh_name)?.clone(new_mesh_name, options.parent_node || null)!

    const { position, receive_shadows, shadow_generator, visibility } = options

    if (position) mesh.position = position


    mesh.getChildMeshes().forEach(mesh =>
    {
        if (receive_shadows) mesh.receiveShadows = true
        if (shadow_generator) shadow_generator.addShadowCaster(mesh)
    })


    if (visibility !== undefined) set_mesh_visiblilty(mesh, visibility)


    return mesh
}


function set_mesh_visiblilty (mesh: AbstractMesh | Node, visibility: number)
{
    if (is_mesh(mesh)) mesh.visibility = visibility
    mesh.getChildMeshes().forEach(mesh => mesh.visibility = visibility)
}

Which I am using like:

// create_house.ts

export const mesh_name_low_poly_house_2 = "low_poly_house_2"

export function create_house (scene: Scene, shadow_generator: ShadowGenerator, position: Vector3, name: string)
{
    const house = get_mesh(scene, mesh_name_low_poly_house_2, "house_" + name, {
        position,
        receive_shadows: true,
        shadow_generator,
        visibility: 1,
    })
}

Full code here: Fix importing nested models · AJamesPhillips/3d_sandbox@6266318 · GitHub

1 Like