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