agargaro/three.ez

Troubleshooting InstancedMesh2 in R3F: culling issues / manual instance creation

Closed this issue · 5 comments

I am trying to use component InstancedMesh2 in my R3F based project. I am manually creating instances and adding to the scene. Before rendering I call updateCulling however nothing happens, i.e. the number of rendered objects remains the same despite, for example, a different camera placement. What am I doing wrong ? Can I use InstancedMesh2 in this way (e.g. without initializing the “main” object from the library) ?

chrome_rwGQt6rrN5

const GridPureJSIM2: React.FC<GridProps> = ({ grid, size = 200 }) => {
    const { scene, camera } = useThree();
    const gridHalfSize = size / 2;
    const countX = grid.length;
    const countY = grid[0].length;

    const visibleSquares = useMemo(() => {
        const squares = [];
        for (let x = 0; x < countX; x++) {
            for (let y = 0; y < countY; y++) {
                if (grid[x][y].visible) {
                    squares.push([x - gridHalfSize, y - gridHalfSize]);
                }
            }
        }
        return squares;
    }, []);

    const geometry = new THREE.BoxGeometry(1, 1, 0.1);
    const material = new THREE.MeshBasicMaterial({ color: 'darkblue' });


// MAIN PART :

    const trees = new InstancedMesh2(geometry, material, visibleSquares.length, {
        behaviour: CullingStatic,
        onInstanceCreation: (obj, i) => {
            // const [x, y, z] = visibleSquares[i];
            // obj.applyMatrix4(new THREE.Matrix4().makeRotationX(Math.PI / 2).setPosition(x + 0.5, 0.01, y + 0.5));
        }
    });

    React.useEffect(() => {
        for (let i = 0; i < visibleSquares.length; i++) {
            const [x, y, z] = visibleSquares[i];
            trees.setMatrixAt(i, new THREE.Matrix4().makeRotationX(Math.PI / 2).setPosition(x + 0.5, 0.01, y + 0.5));
        }

        trees.updateMatrix();
        camera.updateMatrixWorld(true);
        scene.add(trees);

        return () => {
            scene.remove(trees);
            trees.dispose();
            geometry.dispose();
            material.dispose();
        };
    }, [visibleSquares, scene]);

    useFrame(() => {
        trees.updateCulling(camera);
    }, -1); //before render**

    return null;
};

export default GridPureJSIM2;

When using CullingStatic it's necessary to initialize the matrices of all instances inside the onInstanceCreation callback, because this creates a BVH that can no longer be modified (that's why it's static).

However, I will soon release a new library, completely rewritten, with better performance and more features, including sorting, dynamic BVH, and no more need to call updateCulling manually.

Repository of new library: https://github.com/three-ez/instanced-mesh

I am glad to see my library also used with r3f, if you want we can write each other on discord so I can let you try the new library too.

I have prepared an example for you with the new library:

https://stackblitz.com/edit/three-ez-instancedmesh2-test?file=src%2Fmain.ts

What do you think? :)

Thanks for the quick response and the prepared example! It looks very promising! Despite the large number of objects fps are at maximum level. Everything works as it should.

However, I will soon release a new library, completely rewritten, with better performance and more features, including sorting, dynamic BVH, and no more need to call updateCulling manually.

So far I have been using the https://www.npmjs.com/package/@three.ez/instanced-mesh version.
I searched the npm repository by name and found https://www.npmjs.com/package/@three.ez/instanced-mesh-test/v/0.0.4 - is this the current "beta" version I should use ?

is this the current "beta" version I should use ?

Yes. It's a test package which I will remove later (be sure to use the latest version). Once I'm done I will post again on the '@three.ez/instanced-mesh' package.

I am not very convinced about how to initialize BVH, so I will definitely change the API a bit.

I am open to advice on how to simplify the use of the library 😄

New package for InstancedMesh2 released here: https://www.npmjs.com/package/@three.ez/instanced-mesh