javascriptthree.js

Chunking using planes in THREE.js


I'm trying to make an infinitely generating world, the same way Minecraft does it, by using chunks that disappear and reappear depending on where the player is. I'm using a plane that generates points from a combination of Perlin and Simplex noise.

Anyway, When I load the points into the world all the chunks are the same. It's because I'm using the same geometry for everyone. I've tried using object.matrixAutoUpdate = false; and object.updateMatrix(); but it doesn't do anything. I've tried making each chunk a different geometry but the performance drops when it loads a new set of chunks.

Here's the full code:

function updateChunk() {
    // Clear chunks
    while(ground.children.length > 0){ 
        ground.children[0].geometry.dispose()
        ground.remove(ground.children[0]); 
    }

    let size = (game.chunk.render * 2) + 1
    let sX = (Math.floor(plane.position.x / 1000) * 1000) - Math.floor((size / 2) * 1000)
    let sY = (Math.floor(plane.position.z / 1000) * 1000) - Math.floor((size / 2) * 1000)

    ground.position.set(sX, 0, sY)

    for(let y = 0; y < size; y++) {
        for(let x = 0; x < size; x++) {
            let g = new THREE.Mesh(geometry.clone(), material);
            let startX = ((sX / 1000) + x) * 100
            let startY = ((sY / 1000) + y) * 100
            let currentChunk = createChunk(startX, startY)

            //Setup Terrain
            for(let y2 = 0; y2 < 101;y2++) {
                for(let x2 = 0; x2 < 101; x2++) {
                    g.geometry.vertices[(y2 * 101) + x2].z = currentChunk[x2 + ',' + y2]
                }
            }

            g.rotation.x = Math.PI / -2
            g.position.set(x * 1000, 0, y * 1000)
            g.matrixAutoUpdate = false;
            g.updateMatrix();
            ground.add( g );
        }
    }
}
function createChunk(startX, startY) {
    let chunk = []
    for(let y = 0; y < 101; y++) {
        for(let x = 0; x < 101; x++) {
            chunk[x + ',' + y] = Math.abs(noise.perlin2((x + startX) / 100, (y + startY) / 100)) * 200;
        }
    }
    return chunk
}

Solution

  • It was a simple answer I should have thought of a while ago. The solution was I pre-generated the 25 geometries (5x5 chunks) and set an ID to them. When the player moved between chunks, the geometry vertices would reset, and add it to a list of geometries that have been untaken. When it was time for the new chunk to be loaded in, a function would spit out the ID to an untaken geometry