Hi, I’m building a React web app with THREEjs driving a ‘Viewport’ component that contains the current 3D scene. The user might do something with the geometry, or else abandon that page (and the Viewport) to come back later with a fresh scene. There is no case where I want the scene data to live on after the viewport unmounts, so ideally on Viewport.componentWillUnmount() the scene would be purged entirely.
The scene is held as an element of Viewport’s state ( = this.state.scene
in the code). I actually half expected this issue would take care of itself, since the state.scene resets itself to a new THREE.Scene each time the component mounts.
The core creation of the face geometry occurs within a method, like this:
// for each face in the face list:
for (let i = 0; i < fl.length; i++) {
let F = fl[i];
let geometry = new THREE.BufferGeometry();
let pt0 = new THREE.Vector3(F.pt0[0], F.pt0[1], F.pt0[2]);
let pt1 = new THREE.Vector3(F.pt1[0], F.pt1[1], F.pt1[2]);
let pt2 = new THREE.Vector3(F.pt2[0], F.pt2[1], F.pt2[2]);
let pt3 = new THREE.Vector3(F.pt3[0], F.pt3[1], F.pt3[2]);
if (pt2.x !== pt3.x || pt2.y !== pt3.y || pt2.z !== pt3.z) {
const vertices = new Float32Array([
// 1st triangle
pt0.x, pt0.y, pt0.z,
pt1.x, pt1.y, pt1.z,
pt3.x, pt3.y, pt3.z,
// 2nd triangle
pt1.x, pt1.y, pt1.z,
pt2.x, pt2.y, pt2.z,
pt3.x, pt3.y, pt3.z
]);
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
} else {
// 3-vert triangle
const vertices = new Float32Array([
pt0.x, pt0.y, pt0.z,
pt1.x, pt1.y, pt1.z,
pt2.x, pt2.y, pt2.z
]);
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
}
const mesh = new THREE.Mesh(geometry, material);
this.state.scene.add(mesh);
let wf_mesh = new THREE.Mesh(geometry, wireframe_material);
this.state.scene.add(wf_mesh);
}
} // i loop
I have tried to remove and dispose of this geometry in several ways. My most recent attempt was to try to eliminate it during React’s componentWillUnmount. (I threw in the dispose line out of desperation)…
componentWillUnmount() {
console.log("---> 1 Viewport.componentWillUnmount scene:", this.state.scene)
// empty the scene of geometry
while (this.state.scene.children.length > 0) {
this.state.scene.remove(this.state.scene.children[0]);
this.state.scene.dispose(this.state.scene.children[0]);
}
console.log("---> 2 Viewport.componentWillUnmount scene:", this.state.scene)
this.state.scene = null; //also tried " = new THREE.Scene()" here
console.log("---> 3 Viewport.componentWillUnmount scene:", this.state.scene)
}
When I look at the console log, things look correct: the children have been reduced from 5852 elements to zero, and then the state.scene shows itself null. (When I tried the " = new THREE.Scene()" statement instead of the null statement above, there was an empty scene with a new uuid, just as I expected.)
BUT… when I come back to the web page containing Viewport later with another fresh data set, I can tell from the console and from looking in the Viewport that the faces from the previous instance of Viewport are still there. See how the Array value below continues to keep going up.
I’m still a little new to THREEjs and I’ve never taken the time to zero out scene geometry before- what am I missing? thanks in advance for any guidance.
–Noah