joshmarinacci / voxeljs-next

The next generation of Voxel JS
https://vr.josh.earth/voxeljs-next/examples/ecsy.html
BSD 3-Clause "New" or "Revised" License
147 stars 20 forks source link

clean up block access api #21

Closed joshmarinacci closed 5 years ago

joshmarinacci commented 5 years ago

other modules should Never know about chunks. Just get and set blocks

joshmarinacci commented 5 years ago

From the outside chunks should be fairly opaque. The chunk manager will handle all location and de-allocation. It can optionally handle caching the data. It should be given a callback to fill a chunk in with data. The function should not have to create it’s own structure, but instead fill in the structure of the chunk. Since the most common case is to fill a chunk entirely from either a saved state or a function, the block setting api should be fast and support setting Lotts of blocks at the same time.

Proposal:

Create a chunk manager with parameters. The texture manager is internal to the chunk manager, but can be overridden if desired. Caching is internal to the chunk manager. the mesher is internal to the chunk manager. Draw distance is internal as well.

When a new chunk must be allocated it calls the generate function to fill in the chunk. It will first create an empty chunk at the desired location. Then call the function to fill in the chunk. Then it will run the mesher. Then it will convert the mesh data into an actually threeJS mesh. Then it will add the mesh to the threeJS scene. It will also place the mesh data into a cache to be used when

The outside should provide a threeJS group for the chunk manager to put meshes into. Alternatively you could pass in a callback for when a mesh should be added or removed from the scene. These could also be events.

The chunk api now looks like this:

Chunk {
    isEmpty() // returns if chunk is completely empty. true by default.
    getRawData() // returns a flat array of block values
    setBlockAtLocalCoords(x,y,z,value) //set using raw integer coords
    setBlockAtLocalPosition(pos, value) //set using Position object
    setBlockRange(start,dim,array)
    // set a rectangular range of block values
  // starting position
  // size of the range in x, y, z dimensions (a Position used a w,h,d)
  // flat array of values to be copied in.
  getChunkCoordId()
  //gets the string used for caching
    getChunkSize() 
    // gets the size of the chunk in blocks. assumes cube shaped chunks.
}

The chunk manager has the following init parameters

new ChunkManager({
    chunkSize: 16, // size of the chunks. assumes cube shaped
    blockSize: 1, //size of a single block in meters
        chunkDistance: 3, 
           // draws chunks within a particular radius of the camera, 
           // in chunks. uses manhattan distance.
    generateChunkData: (chunk) => {
        //a callback function. should fill the chunk with data.
        },
        textureManager: new TextureManager(), 
             //replace tm with one preloaded with the textures you want,
    mesher: new CulledMesher(), //replace with the custom mesher
    container: new Three.Group(),  // a threejs object that all meshes will be placed in
})

cm.setBlockAtWorldPosition(pos,value) 
     // sets block value at the global position. will look up the correct chunk then set it there.
cm.textureManager 
    // reference to the texture manager
cm.updateCenterPosition(pos) 
    // used to update the center of the world and trigger loading new chunks and removing old chunks.
cm.rebuildAllChunks() 
    // marks all chunks as dirty, rebuilds them.

Internally the chunk manager will re-mesh and rebuild chunks when their data changes. The outside code never has to mess with this (since it’s 99% always the same)

joshmarinacci commented 5 years ago

fixed with 5f86d040786681dd8c9e93b2cdfd380207100483