Hello !
I’m currently working on a 3D version of John Conway’s life game on three.js.
Here’s the code I’ve done so far:
import * as THREE from 'three';
const scene = new THREE.Scene();
const createCube = (newCube, scene) => {
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial( { color: 0xffffff } );
const cube = new THREE.Mesh( geometry, material );
cube.position.set(newCube.x, newCube.y, newCube.z);
scene.add( cube );
}
const deleteCubes = (scene) => {
return new Promise((resolve) => {
while (scene.children.length > 0) {
scene.remove(scene.children[0]);
}
resolve();
});
}
const updateDisplay = async (cubes, scene) => {
// clear
await deleteCubes(scene)
// create cubes
cubes.map((cube) => createCube(cube, scene));
// replacing lights
scene.add(new THREE.AmbientLight(0xffffff, .5))
const dir = new THREE.DirectionalLight(0xff0000, 1)
dir.position.set(-1, 1, 1)
scene.add(dir)
console.log(scene.children)
}
const isEqual = (a, b) => a.x === b.x && a.y === b.y && a.z === b.z;
const offsets = [-1, 0, 1];
const lookNeighbors = (cube, cubes) => {
// code that look to all the cubes around and counts the "living" ones
};
const generateNextCubes = (cubes) => {
// code that generates the cube array to be displayed in the next frame
}
let cubes = [
{x:0, y:0, z:0},
{x:0, y:0, z:1},
{x:0, y:0, z:-1},
{x:0, y:1, z:0},
{x:0, y:1, z:1},
{x:0, y:1, z:-1},
{x:0, y:-1, z:1},
{x:0, y:-1, z:-1},
{x:0, y:-1, z:0},
] // initial situation
let nextCubes = []
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
scene.add(new THREE.AmbientLight(0xffffff, .5))
const dir = new THREE.DirectionalLight(0xffffff, 1)
dir.position.set(-1, 1, 1)
scene.add(dir)
camera.position.z = 25;
let lastUpdateTime = 0;
const updateTimeInterval = 5000;
function animate(currentTime) {
requestAnimationFrame(animate);
const deltaTime = currentTime - lastUpdateTime;
if (deltaTime >= updateTimeInterval) {
lastUpdateTime = currentTime;
updateDisplay(cubes, scene)
nextCubes = generateNextCubes(cubes);
cubes = nextCubes;
renderer.render(scene, camera);
console.log("frame");
}
}
animate(0);
I have a real problem with the way to erase the content of the 3D render. The basic idea is: at each “frame” of the animation, the scene content is erased and then recreated.
Currently there are 4 functions that seem important to me for this problem.
-
createCube(newCube, scene) takes a cube as parameter, creates it and adds it to the scene. I call it using cubes.map, cubes being an array of cubes (with coordinates).
-
deleteCubes(scene) deletes all children in the scene, i.e. all cubes and lights.
-
updateDisplay(cubes, scene) calls the first two functions, then recreates the lights.
-
animate() contains a deltaTime so that the animation generates a frame every 5 seconds. and calls updateDisplay before calculating the next frame.
When I run it in its current state, the canvas remains black and nothing is displayed. But if I comment on the deleteCubes in updateDisplay, then it works correctly, if we omit the fact that the cubes in the previous frames are not deleted.
My first thought was that the cube creation code ended before the delete function, which explains the use of a promise, but that wasn’t it. Then I realized that the delete function also deletes the lights, so I said to myself that I couldn’t see anything because there were no more lights, so I added the lights in updateDisplay and it’s still the same.
I don’t know what to do now, I can’t see what the problem is and I hope you can help me - thanks in advance!