How to export GLB scene objects from Blender to InstancedMesh

I have a bunch objects like this in my Blender scene (2 materials, 2 objects for each pipe). Right now, they are just normal mesh that I copied over and over. I wonder what is the known practice to export them and use them as InstancedMesh in three.js/R3F?

Extra: Each of them have an animation, but just a simple rotation, and it would be nice if I can somehow access each instanced animations, but if it’s too complex, I can just animate them in code for each specific instances.

Try this:

const loader = new GLTFLoader();
loader.load('https://threejs.org/examples/models/gltf/Nefertiti/Nefertiti.glb', (gltf) => {
    const egypt = gltf.scene.children[0];
    const originalMaterial = egypt.material;
  
    const instanceEgypt = 100;
    const instancedMesh = new THREE.InstancedMesh(egypt.geometry, originalMaterial, instanceEgypt);

    const matrix = new THREE.Matrix4();
    const scale = 0.1;
    for (let i = 0; i < instanceEgypt; i++) {
        const x = (Math.random() - 0.5) * 40;
        const y = (Math.random() - 0.5) * 40;
        const z = (Math.random() - 0.5) * 40;
        matrix.makeScale(scale, scale, scale);
        matrix.setPosition(x, y, z);
        instancedMesh.setMatrixAt(i, matrix);
    }

    scene.add(instancedMesh);
});

If you have animations, like you mentioned, you can use classical AnimationMixer to them.

OfficialExample

In R3F logic remain the same.

R3F

In this code, you are placing the InstancedMesh randomly. I’m looking for a way to use mesh position that already set inside Blender .glb instead.
And since they are instanced, I wonder what the code would look like if I use AnimationMixer as you suggested?

I meant that you more talking about multiplying then positioning etc. But if you want original position of GLB from software, you need to retrieve that, and set to the scene, because that data is inside exported mesh.

const loader = new GLTFLoader();
loader.load('https://threejs.org/examples/models/gltf/Nefertiti/Nefertiti.glb', (gltf) => {
    const egypt = gltf.scene.children[0];
    const originalMaterial = egypt.material;

    const instanceCount = egypt.children.length;
    const instancedMesh = new THREE.InstancedMesh(egypt.geometry, originalMaterial, instanceCount);

    const matrix = new THREE.Matrix4();

    for (let i = 0; i < instanceCount; i++) {
        const childMesh = egypt.children[i];
        const position = childMesh.position;
        const rotation = childMesh.rotation;
        const scale = childMesh.scale;

        matrix.compose(position, new THREE.Quaternion().setFromEuler(rotation), scale);
        instancedMesh.setMatrixAt(i, matrix);
    }

    scene.add(instancedMesh);
});

If you talking about animations, well, I think all is inside example what I provided.

const animations = gltf.animations;
mixer = new THREE.AnimationMixer( // yourModel );
if (animations && animations.length > 0) {
    animations.forEach((clip) => {
        const action = mixer.clipAction(clip);
        action.play();
    });
}

//...

const clock = new THREE.Clock();
function animate() {
    requestAnimationFrame(animate);
    const delta = clock.getDelta();
    mixer.update(delta); 
    renderer.render(scene, camera); 
}
animate();

Keep in mind that, probably, your animations have names, if you want triggering only some of them…

For instanced meshes in blender to gltf i think only non animated meshes are supported.

And to create an instance in blender, instead of copying the object with Shift-D to duplicate, you use Alt-D to create an instance. If you do this, then the instances will export and load in threejs as an InstancedMesh.