Automatically dispose of 3D models once out of view

Viewed 49

In order to save memory in my application I've decided to dispose of any 3D models that escape the view of the camera. To do this I used a method which detects if the camera is able to see the position of the model (using model.position). The below code is within my animate loop.

const frustum = new THREE.Frustum();
const matrix = new THREE.Matrix4().multiplyMatrices(test.camera.projectionMatrix, test.camera.matrixWorldInverse);
frustum.setFromProjectionMatrix(matrix);

let earthContainerPos = { ...earthContainer.position }; //spread syntax removes reference to container position
earthContainerPos.z += 10; //to ensure its only disposed once completely out of view (since .position is the center of the model)
if (!frustum.containsPoint(earthContainerPos)) { //check if container in view of camera
   console.log('Out of view')
   earthContainer.dispose(); //dispose of the model - I thought .dispose would work since its being rendered by a webGL renderer (from the docs) but it didnt
};

The method works for detecting when my model is out of view, but for some reason the dispose method for my container (which holds 2 3D Models) is not working. Do I have to dispose of everything or is there a more dynamic method of disposal?


Model Details:

  • GLTF models
  • 2 models in the container
1 Answers

earthContainer.dispose();

If earthContainer is an instance of Object3D, your code will produce a runtime error. dispose() methods only exist for selected classes like BufferGeometry, Material, Texture or WebGLRenderTarget.

Besides, I don't think your approach of calling dispose() when an 3D objects gets out of view makes sense. The engine automatically ensures to only render objects when they are inside the view frustum. That is more effective than what you do since it can lead to expensive ping-pong effects. Meaning you deallocate resources which could be allocated again in the next frames. And this back-and-forth can produce noticeably overhead. E.g. if you call dispose() on a material, its respective shader might be deleted. If you know have to render an object with this material again, a new compilation is required which is an expensive operation.

I suggest you only call dispose() if your application does not require a resource again. More information about dispose() in the following guide:

https://threejs.org/docs/index.html#manual/en/introduction/How-to-dispose-of-objects

Related