Created
November 5, 2023 22:18
-
-
Save GRAYgoose124/7ff0a85728ff3acda8fac81075af15c4 to your computer and use it in GitHub Desktop.
3d gol experiment w/ three.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>3D Game of Life</title> | |
<style> | |
body { margin: 0; } | |
canvas { display: block; } | |
</style> | |
</head> | |
<body> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js"></script> | |
<script> | |
// Set up the scene, camera, and renderer as usual | |
const scene = new THREE.Scene(); | |
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); | |
camera.position.z = 20; | |
const renderer = new THREE.WebGLRenderer(); | |
renderer.setSize(window.innerWidth, window.innerHeight); | |
document.body.appendChild(renderer.domElement); | |
// GoL constants | |
const gridSize = 20; | |
const GENERATION_DELAY = 250; | |
// init grid with rand states | |
const cells = new Array(gridSize); | |
const cellDistances = new Array(gridSize); | |
const geometry = new THREE.BoxGeometry(); | |
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00, transparent: true, opacity: 0.25 }); | |
const cube = new THREE.InstancedMesh(geometry, material, gridSize * gridSize * gridSize); | |
scene.add(cube); | |
function initScene() { | |
for (let x = 0; x < gridSize; x++) { | |
cells[x] = new Array(gridSize); | |
for (let y = 0; y < gridSize; y++) { | |
cells[x][y] = new Array(gridSize); | |
for (let z = 0; z < gridSize; z++) { | |
cells[x][y][z] = Math.floor(Math.random() * 2) === 0 ? 1 : 0; | |
} | |
} | |
} | |
} | |
function updateScene() { | |
let instanceId = 0; | |
const dummy = new THREE.Object3D(); | |
for (let x = 0; x < gridSize; x++) { | |
for (let y = 0; y < gridSize; y++) { | |
for (let z = 0; z < gridSize; z++) { | |
if (cells[x][y][z] === 1) { | |
dummy.position.set(x - gridSize / 2, y - gridSize / 2, z - gridSize / 2); | |
dummy.updateMatrix(); | |
cube.setMatrixAt(instanceId++, dummy.matrix); | |
} | |
} | |
} | |
} | |
cube.instanceMatrix.needsUpdate = true; | |
} | |
function cloneCells(cells) { | |
const clonedCells = new Array(cells.length); | |
for (let x = 0; x < cells.length; x++) { | |
clonedCells[x] = new Array(cells[x].length); | |
for (let y = 0; y < cells[x].length; y++) { | |
clonedCells[x][y] = cells[x][y].slice(); | |
} | |
} | |
return clonedCells; | |
} | |
function computeNextGeneration() { | |
const newCells = cloneCells(cells); | |
for (let x = 0; x < gridSize; x++) { | |
for (let y = 0; y < gridSize; y++) { | |
for (let z = 0; z < gridSize; z++) { | |
let liveNeighbors = 0; | |
// neighborhood of 3x3x3 | |
for (let i = -1; i <= 1; i++) { | |
for (let j = -1; j <= 1; j++) { | |
for (let k = -1; k <= 1; k++) { | |
if (i === 0 && j === 0 && k === 0) continue; // Skip the current cell | |
const nx = x + i; | |
const ny = y + j; | |
const nz = z + k; | |
if (nx >= 0 && nx < gridSize && ny >= 0 && ny < gridSize && nz >= 0 && nz < gridSize) { | |
liveNeighbors += cells[nx][ny][nz]; | |
} | |
} | |
} | |
} | |
if (cells[x][y][z] === 1) { // If the cell is alive | |
if (liveNeighbors < 4 || liveNeighbors > 8) { | |
newCells[x][y][z] = 0; // Cell dies | |
} | |
} else { // If the cell is dead | |
if (liveNeighbors === 5 || liveNeighbors === 6) { | |
newCells[x][y][z] = 1; // Cell becomes alive | |
} | |
} | |
} | |
} | |
} | |
for (let x = 0; x < gridSize; x++) { | |
for (let y = 0; y < gridSize; y++) { | |
for (let z = 0; z < gridSize; z++) { | |
cells[x][y][z] = newCells[x][y][z]; | |
} | |
} | |
} | |
setTimeout(computeNextGeneration, GENERATION_DELAY); | |
} | |
function animate() { | |
requestAnimationFrame(animate); | |
scene.rotation.x += 0.005; | |
scene.rotation.y += 0.005; | |
updateScene(); | |
renderer.render(scene, camera); | |
} | |
initScene(); | |
animate(); | |
computeNextGeneration(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment