I haven't found any post that describes exactly this issue but I've noticed it's kinda hard to delete elements from the scene.
I'm making a house editor, it allows to draw a 2D house and then it generates a 3d version.
If I use the next line or scene.clear() to clear the scene, it won´t render anything else afterwards:
build(layers) {
let height = 0;
this.scene.remove.apply(this.scene, this.scene.children);
layers.forEach(layer => {
for (let y = 0; y < GRID_SIZE; y++) {
for (let x = 0; x < GRID_SIZE; x++) {
if (layer.grid[y][x] != null) {
this.scene.add(layer.grid[y][x].get3DVersion(x, y, height));
}
}
}
height += layer.getTotalHeight();
});
}
However, if I empty the scene like this, it continues rendering the scene but it won't remove all the elements that were deleted in the grid properlty, I have to call build(layers) several times for all of them to be gone:
this.scene.children.forEach((child) => {
if (child.isMesh && child !== this.plane) {
this.scene.remove(child);
child.geometry.dispose();
child.material.dispose();
}
});
This is all my Three.js related code:
class HouseBuilder {
constructor() {
const section = document.getElementById("threeSection");
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera(30, 400 / 300, 0.1, 5000);
this.camera.position.set(25, 25, 50);
this.camera.lookAt(0, 0, 2.5);
this.renderer = new THREE.WebGLRenderer();
this.renderer.setSize(400, 300);
section.appendChild(this.renderer.domElement);
const ambientLight = new THREE.AmbientLight(0x404040);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
this.scene.add(ambientLight);
directionalLight.position.set(5, 10, 5);
this.scene.add(directionalLight);
this.addFloor();
this.animate();
}
addFloor() {
const geometry = new THREE.PlaneGeometry(GRID_SIZE + 5, GRID_SIZE + 5);
const material = new THREE.MeshStandardMaterial({ color: 0x228b22, side: THREE.DoubleSide });
this.plane = new THREE.Mesh(geometry, material);
this.plane.rotation.x = -Math.PI / 2;
this.scene.add(this.plane);
}
animate() {
requestAnimationFrame(() => this.animate());
this.renderer.render(this.scene, this.camera);
}
build(layers) {
let height = 0;
// this.scene.children.forEach((child) => {
// if (child.isMesh && child !== this.plane) {
// this.scene.remove(child);
// child.geometry.dispose();
// child.material.dispose();
// }
// });
this.scene.remove.apply(this.scene, this.scene.children);
layers.forEach(layer => {
for (let y = 0; y < GRID_SIZE; y++) {
for (let x = 0; x < GRID_SIZE; x++) {
if (layer.grid[y][x] != null) {
this.scene.add(layer.grid[y][x].get3DVersion(x, y, height));
}
}
}
height += layer.getTotalHeight();
});
}
}
I haven't found any post that describes exactly this issue but I've noticed it's kinda hard to delete elements from the scene.
I'm making a house editor, it allows to draw a 2D house and then it generates a 3d version.
If I use the next line or scene.clear() to clear the scene, it won´t render anything else afterwards:
build(layers) {
let height = 0;
this.scene.remove.apply(this.scene, this.scene.children);
layers.forEach(layer => {
for (let y = 0; y < GRID_SIZE; y++) {
for (let x = 0; x < GRID_SIZE; x++) {
if (layer.grid[y][x] != null) {
this.scene.add(layer.grid[y][x].get3DVersion(x, y, height));
}
}
}
height += layer.getTotalHeight();
});
}
However, if I empty the scene like this, it continues rendering the scene but it won't remove all the elements that were deleted in the grid properlty, I have to call build(layers) several times for all of them to be gone:
this.scene.children.forEach((child) => {
if (child.isMesh && child !== this.plane) {
this.scene.remove(child);
child.geometry.dispose();
child.material.dispose();
}
});
This is all my Three.js related code:
class HouseBuilder {
constructor() {
const section = document.getElementById("threeSection");
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera(30, 400 / 300, 0.1, 5000);
this.camera.position.set(25, 25, 50);
this.camera.lookAt(0, 0, 2.5);
this.renderer = new THREE.WebGLRenderer();
this.renderer.setSize(400, 300);
section.appendChild(this.renderer.domElement);
const ambientLight = new THREE.AmbientLight(0x404040);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
this.scene.add(ambientLight);
directionalLight.position.set(5, 10, 5);
this.scene.add(directionalLight);
this.addFloor();
this.animate();
}
addFloor() {
const geometry = new THREE.PlaneGeometry(GRID_SIZE + 5, GRID_SIZE + 5);
const material = new THREE.MeshStandardMaterial({ color: 0x228b22, side: THREE.DoubleSide });
this.plane = new THREE.Mesh(geometry, material);
this.plane.rotation.x = -Math.PI / 2;
this.scene.add(this.plane);
}
animate() {
requestAnimationFrame(() => this.animate());
this.renderer.render(this.scene, this.camera);
}
build(layers) {
let height = 0;
// this.scene.children.forEach((child) => {
// if (child.isMesh && child !== this.plane) {
// this.scene.remove(child);
// child.geometry.dispose();
// child.material.dispose();
// }
// });
this.scene.remove.apply(this.scene, this.scene.children);
layers.forEach(layer => {
for (let y = 0; y < GRID_SIZE; y++) {
for (let x = 0; x < GRID_SIZE; x++) {
if (layer.grid[y][x] != null) {
this.scene.add(layer.grid[y][x].get3DVersion(x, y, height));
}
}
}
height += layer.getTotalHeight();
});
}
}
Share
Improve this question
edited Mar 26 at 12:55
Carmen Sirgo López
asked Mar 26 at 12:54
Carmen Sirgo LópezCarmen Sirgo López
213 bronze badges
1 Answer
Reset to default 1As @Don McCurdy said, the problem was due to modifying an array while iterating over it. Here's the solution:
const objectsToRemove = this.scene.children.filter((child) => child !== this.plane);
for (const child of objectsToRemove) {
if (child.isMesh && child !== this.plane) {
this.scene.remove(child);
child.geometry.dispose();
child.material.dispose();
}
}