three.ez icon indicating copy to clipboard operation
three.ez copied to clipboard

Troubleshooting InstancedMesh2 in R3F: culling issues / manual instance creation

Open raptyk opened this issue 1 year ago • 4 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;

raptyk avatar Jul 30 '24 21:07 raptyk

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.

agargaro avatar Jul 31 '24 11:07 agargaro

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? :)

agargaro avatar Jul 31 '24 18:07 agargaro

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 ?

raptyk avatar Aug 01 '24 07:08 raptyk

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 😄

agargaro avatar Aug 01 '24 07:08 agargaro

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

agargaro avatar Oct 31 '24 17:10 agargaro