some voxel bs
This commit is contained in:
parent
f0a2eacd41
commit
ab35890f1b
@ -83,7 +83,7 @@ class SimplexHeightMap extends HeightMap {
|
|||||||
let amplitude = this.amplitude
|
let amplitude = this.amplitude
|
||||||
|
|
||||||
for (let i = 0; i < o; i++) {
|
for (let i = 0; i < o; i++) {
|
||||||
output += (amplitude * this.osn.noise3D(x * frequency, y * frequency))
|
output += (amplitude * this.osn.noise2D(x * frequency, y * frequency))
|
||||||
denom += amplitude
|
denom += amplitude
|
||||||
|
|
||||||
frequency *= this.lacunarity
|
frequency *= this.lacunarity
|
||||||
|
@ -8,6 +8,20 @@ export function clamp (num, min, max) {
|
|||||||
return Math.min(Math.max(num, min), max)
|
return Math.min(Math.max(num, min), max)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function dim3to1 (x, y, z, xMax, yMax) {
|
||||||
|
if (xMax && !yMax) yMax = xMax
|
||||||
|
return (z * xMax * yMax) + (y * xMax) + x
|
||||||
|
}
|
||||||
|
|
||||||
|
export function dim1to3 (idx, xMax, yMax) {
|
||||||
|
if (xMax && !yMax) yMax = xMax
|
||||||
|
const z = idx / (yMax * xMax)
|
||||||
|
idx -= (z * xMax * yMax)
|
||||||
|
const y = idx / xMax
|
||||||
|
const x = idx % xMax
|
||||||
|
return { x, y, z }
|
||||||
|
}
|
||||||
|
|
||||||
export function addv3 (one, two) {
|
export function addv3 (one, two) {
|
||||||
if (one.length !== 3) return null
|
if (one.length !== 3) return null
|
||||||
if (typeof two !== 'object') {
|
if (typeof two !== 'object') {
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import { Mesh } from '../mesh'
|
import { Mesh } from '../mesh'
|
||||||
import { Node, MeshInstance } from '../components'
|
import { Node, MeshInstance } from '../components'
|
||||||
import { addv3, mulv3 } from '../utility'
|
import { vec3 } from 'gl-matrix'
|
||||||
|
import { addv3, subv3, mulv3, dim3to1, dim1to3 } from '../utility'
|
||||||
|
import { BoundingBox } from '../mesh/aabb'
|
||||||
|
import VoxelData from './voxeldata'
|
||||||
|
|
||||||
const FACE_VERTEX = [
|
const FACE_VERTEX = [
|
||||||
// Bottom
|
// Bottom
|
||||||
@ -41,7 +44,7 @@ const FACE_VERTEX = [
|
|||||||
[1.0, 1.0, 1.0],
|
[1.0, 1.0, 1.0],
|
||||||
[0.0, 1.0, 1.0],
|
[0.0, 1.0, 1.0],
|
||||||
[0.0, 0.0, 1.0],
|
[0.0, 0.0, 1.0],
|
||||||
[0.0, 0.0, 1.0]
|
[0.0, 0.0, -1.0]
|
||||||
],
|
],
|
||||||
// Back
|
// Back
|
||||||
[
|
[
|
||||||
@ -49,7 +52,7 @@ const FACE_VERTEX = [
|
|||||||
[0.0, 1.0, 0.0],
|
[0.0, 1.0, 0.0],
|
||||||
[1.0, 1.0, 0.0],
|
[1.0, 1.0, 0.0],
|
||||||
[1.0, 0.0, 0.0],
|
[1.0, 0.0, 0.0],
|
||||||
[0.0, 0.0, -1.0]
|
[0.0, 0.0, 1.0]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -60,71 +63,65 @@ const FACE_RIGHT = 3
|
|||||||
const FACE_FRONT = 4
|
const FACE_FRONT = 4
|
||||||
const FACE_BACK = 5
|
const FACE_BACK = 5
|
||||||
|
|
||||||
class Voxel {
|
const AIR_VOXEL = VoxelData.register('air', { solid: false })
|
||||||
constructor (id) {
|
const GROUND_VOXEL = VoxelData.register('ground', { solid: true })
|
||||||
this.id = id
|
|
||||||
}
|
|
||||||
|
|
||||||
get solid () {
|
|
||||||
return this.id !== 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const AIR_VOXEL = new Voxel(0)
|
|
||||||
const GROUND_VOXEL = new Voxel(1)
|
|
||||||
|
|
||||||
class VoxelChunk extends MeshInstance {
|
class VoxelChunk extends MeshInstance {
|
||||||
constructor (origin, pos, size = 16) {
|
constructor (world, pos, size = 16) {
|
||||||
super(null, [origin[0] + pos[0] * size, origin[1] + pos[1] * size, origin[2] + pos[2] * size])
|
super(null, [pos[0] * size, pos[1] * size, pos[2] * size])
|
||||||
|
this.world = world
|
||||||
this.relativePos = pos
|
this.relativePos = pos
|
||||||
this.size = size
|
this.size = size
|
||||||
this.mesh = null
|
this.mesh = null
|
||||||
|
|
||||||
// Voxel data
|
// Voxel data
|
||||||
this.data = {}
|
this.data = []
|
||||||
|
|
||||||
// Set to true when this chunk mesh requires to be recreated
|
// Set to true when this chunk mesh requires to be recreated
|
||||||
this.dirty = true
|
this.dirty = true
|
||||||
|
|
||||||
// Set to true when the generation has been finished
|
// Set to true when the generation has been finished
|
||||||
this.generated = false
|
this.generated = false
|
||||||
|
|
||||||
|
// If the chunk is outside of the view, make it inactive
|
||||||
|
this.active = true
|
||||||
}
|
}
|
||||||
|
|
||||||
getVoxel (x, y, z) {
|
getVoxel (x, y, z) {
|
||||||
if (this.parent) {
|
if (this.world) {
|
||||||
let neighbor
|
let neighbor
|
||||||
if (x < 0) {
|
if (x < 0) {
|
||||||
neighbor = this.parent.getChunk(this.relativePos[0] - 1, this.relativePos[1], this.relativePos[2])
|
neighbor = this.world.getChunk(this.relativePos[0] - 1, this.relativePos[1], this.relativePos[2])
|
||||||
if (neighbor) {
|
if (neighbor) {
|
||||||
return neighbor.getVoxel(this.size + x, y, z)
|
return neighbor.getVoxel(this.size + x, y, z)
|
||||||
}
|
}
|
||||||
return AIR_VOXEL
|
return AIR_VOXEL
|
||||||
} else if (x >= this.size) {
|
} else if (x >= this.size) {
|
||||||
neighbor = this.parent.getChunk(this.relativePos[0] + 1, this.relativePos[1], this.relativePos[2])
|
neighbor = this.world.getChunk(this.relativePos[0] + 1, this.relativePos[1], this.relativePos[2])
|
||||||
if (neighbor) {
|
if (neighbor) {
|
||||||
return neighbor.getVoxel(x - this.size, y, z)
|
return neighbor.getVoxel(x - this.size, y, z)
|
||||||
}
|
}
|
||||||
return AIR_VOXEL
|
return AIR_VOXEL
|
||||||
} else if (y < 0) {
|
} else if (y < 0) {
|
||||||
neighbor = this.parent.getChunk(this.relativePos[0], this.relativePos[1] - 1, this.relativePos[2])
|
neighbor = this.world.getChunk(this.relativePos[0], this.relativePos[1] - 1, this.relativePos[2])
|
||||||
if (neighbor) {
|
if (neighbor) {
|
||||||
return neighbor.getVoxel(x, this.size + y, z)
|
return neighbor.getVoxel(x, this.size + y, z)
|
||||||
}
|
}
|
||||||
return AIR_VOXEL
|
return AIR_VOXEL
|
||||||
} else if (y >= this.size) {
|
} else if (y >= this.size) {
|
||||||
neighbor = this.parent.getChunk(this.relativePos[0], this.relativePos[1] + 1, this.relativePos[2])
|
neighbor = this.world.getChunk(this.relativePos[0], this.relativePos[1] + 1, this.relativePos[2])
|
||||||
if (neighbor) {
|
if (neighbor) {
|
||||||
return neighbor.getVoxel(x, y - this.size, z)
|
return neighbor.getVoxel(x, y - this.size, z)
|
||||||
}
|
}
|
||||||
return AIR_VOXEL
|
return AIR_VOXEL
|
||||||
} else if (z < 0) {
|
} else if (z < 0) {
|
||||||
neighbor = this.parent.getChunk(this.relativePos[0], this.relativePos[1], this.relativePos[2] - 1)
|
neighbor = this.world.getChunk(this.relativePos[0], this.relativePos[1], this.relativePos[2] - 1)
|
||||||
if (neighbor) {
|
if (neighbor) {
|
||||||
return neighbor.getVoxel(x, y, this.size + z)
|
return neighbor.getVoxel(x, y, this.size + z)
|
||||||
}
|
}
|
||||||
return AIR_VOXEL
|
return AIR_VOXEL
|
||||||
} else if (z >= this.size) {
|
} else if (z >= this.size) {
|
||||||
neighbor = this.parent.getChunk(this.relativePos[0], this.relativePos[1], this.relativePos[2] + 1)
|
neighbor = this.world.getChunk(this.relativePos[0], this.relativePos[1], this.relativePos[2] + 1)
|
||||||
if (neighbor) {
|
if (neighbor) {
|
||||||
return neighbor.getVoxel(x, y, z - this.size)
|
return neighbor.getVoxel(x, y, z - this.size)
|
||||||
}
|
}
|
||||||
@ -132,7 +129,7 @@ class VoxelChunk extends MeshInstance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.data[x][z][y]
|
return this.data[dim3to1(x, y, z, this.size)] || AIR_VOXEL
|
||||||
}
|
}
|
||||||
|
|
||||||
getVoxelv (v) {
|
getVoxelv (v) {
|
||||||
@ -140,33 +137,24 @@ class VoxelChunk extends MeshInstance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
generate (generator) {
|
generate (generator) {
|
||||||
this.data = {}
|
this.material = generator.material
|
||||||
for (let x = 0; x < this.size; x++) {
|
for (let x = 0; x < this.size; x++) {
|
||||||
if (!this.data[x]) this.data[x] = {}
|
|
||||||
for (let z = 0; z < this.size; z++) {
|
for (let z = 0; z < this.size; z++) {
|
||||||
if (!this.data[x][z]) this.data[x][z] = {}
|
|
||||||
const columnHeight = generator.getHeight(x + this.pos[0], z + this.pos[2])
|
const columnHeight = generator.getHeight(x + this.pos[0], z + this.pos[2])
|
||||||
for (let y = 0; y < this.size; y++) {
|
for (let y = 0; y < this.size; y++) {
|
||||||
const solid = this.pos[1] + y < columnHeight
|
const solid = this.pos[1] + y < columnHeight
|
||||||
this.data[x][z][y] = solid ? GROUND_VOXEL : AIR_VOXEL
|
this.data[dim3to1(x, y, z, this.size)] = solid ? GROUND_VOXEL : AIR_VOXEL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.generated = true
|
this.generated = true
|
||||||
|
return true
|
||||||
// Make sure the parent knows that we have generated everything
|
|
||||||
if (this.parent) {
|
|
||||||
this.parent.chunksLeft--
|
|
||||||
if (this.parent.chunksLeft <= 0) {
|
|
||||||
this.parent.generated = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Programmatically generate a voxel face
|
// Programmatically generate a voxel face
|
||||||
// Returns the position, normal and texture coordinates for each vertex in this face
|
// Returns the position, normal and texture coordinates for each vertex in this face
|
||||||
createFace (points, pos, face) {
|
createFace (indices, points, pos, face) {
|
||||||
// Add the corresponding offsets for this face to the position
|
// Add the corresponding offsets for this face to the position
|
||||||
const corners = [
|
const corners = [
|
||||||
addv3(pos, FACE_VERTEX[face][0]), addv3(pos, FACE_VERTEX[face][1]),
|
addv3(pos, FACE_VERTEX[face][0]), addv3(pos, FACE_VERTEX[face][1]),
|
||||||
@ -176,15 +164,22 @@ class VoxelChunk extends MeshInstance {
|
|||||||
// Select the normal for this face
|
// Select the normal for this face
|
||||||
const normal = FACE_VERTEX[face][4]
|
const normal = FACE_VERTEX[face][4]
|
||||||
|
|
||||||
// Return the 6 vertices that make up this face (two triangles)
|
// Create the 4 vertices that make up this face
|
||||||
// They're named points because this function returns not only vertices,
|
// They're named points because this function returns not only vertices,
|
||||||
// but corresponding texture coordinates and normals at the same time for convenience
|
// but corresponding texture coordinates and normals at the same time for convenience
|
||||||
points.push([corners[0], normal, [0.0, 1.0]])
|
points.push([corners[0], normal, [0.0, 1.0]])
|
||||||
points.push([corners[1], normal, [0.0, 0.0]])
|
points.push([corners[1], normal, [0.0, 0.0]])
|
||||||
points.push([corners[2], normal, [1.0, 0.0]])
|
points.push([corners[2], normal, [1.0, 0.0]])
|
||||||
points.push([corners[0], normal, [0.0, 1.0]])
|
|
||||||
points.push([corners[2], normal, [1.0, 0.0]])
|
|
||||||
points.push([corners[3], normal, [1.0, 1.0]])
|
points.push([corners[3], normal, [1.0, 1.0]])
|
||||||
|
|
||||||
|
// Create the face
|
||||||
|
const inx = points.length - 4
|
||||||
|
indices.push(inx)
|
||||||
|
indices.push(inx + 1)
|
||||||
|
indices.push(inx + 2)
|
||||||
|
indices.push(inx)
|
||||||
|
indices.push(inx + 2)
|
||||||
|
indices.push(inx + 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
createMesh (gl) {
|
createMesh (gl) {
|
||||||
@ -201,36 +196,37 @@ class VoxelChunk extends MeshInstance {
|
|||||||
|
|
||||||
// Array of vertices with texture positions and normals
|
// Array of vertices with texture positions and normals
|
||||||
const points = []
|
const points = []
|
||||||
|
const indices = []
|
||||||
|
|
||||||
// Generate face quads for each voxel in the chunk
|
// Generate face quads for each voxel in the chunk
|
||||||
for (let x = 0; x < this.size; x++) {
|
for (let x = 0; x < this.size; x++) {
|
||||||
for (let y = 0; y < this.size; y++) {
|
for (let y = 0; y < this.size; y++) {
|
||||||
for (let z = 0; z < this.size; z++) {
|
for (let z = 0; z < this.size; z++) {
|
||||||
const cellPos = [x, y, z]
|
const cellPos = [x, y, z]
|
||||||
if (!this.getVoxel(x, y, z).solid) continue
|
if (!VoxelData.isSolid(this.getVoxel(x, y, z))) continue
|
||||||
|
|
||||||
if (!this.getVoxel(x, y - 1, z).solid) {
|
if (!VoxelData.isSolid(this.getVoxel(x, y - 1, z))) {
|
||||||
this.createFace(points, cellPos, FACE_BOTTOM)
|
this.createFace(indices, points, cellPos, FACE_BOTTOM)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.getVoxel(x, y + 1, z).solid) {
|
if (!VoxelData.isSolid(this.getVoxel(x, y + 1, z))) {
|
||||||
this.createFace(points, cellPos, FACE_TOP)
|
this.createFace(indices, points, cellPos, FACE_TOP)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.getVoxel(x - 1, y, z).solid) {
|
if (!VoxelData.isSolid(this.getVoxel(x - 1, y, z))) {
|
||||||
this.createFace(points, cellPos, FACE_LEFT)
|
this.createFace(indices, points, cellPos, FACE_LEFT)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.getVoxel(x + 1, y, z).solid) {
|
if (!VoxelData.isSolid(this.getVoxel(x + 1, y, z))) {
|
||||||
this.createFace(points, cellPos, FACE_RIGHT)
|
this.createFace(indices, points, cellPos, FACE_RIGHT)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.getVoxel(x, y, z + 1).solid) {
|
if (!VoxelData.isSolid(this.getVoxel(x, y, z + 1))) {
|
||||||
this.createFace(points, cellPos, FACE_FRONT)
|
this.createFace(indices, points, cellPos, FACE_FRONT)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.getVoxel(x, y, z - 1).solid) {
|
if (!VoxelData.isSolid(this.getVoxel(x, y, z - 1))) {
|
||||||
this.createFace(points, cellPos, FACE_BACK)
|
this.createFace(indices, points, cellPos, FACE_BACK)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -257,15 +253,21 @@ class VoxelChunk extends MeshInstance {
|
|||||||
uvs.push(vert[2][1])
|
uvs.push(vert[2][1])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new mesh without an element array buffer (TODO maybe?)
|
// Create a new mesh with an element array buffer
|
||||||
this.mesh = Mesh.construct(gl, vertices, null, uvs, normals)
|
this.mesh = Mesh.construct(gl, vertices, indices, uvs, normals)
|
||||||
|
|
||||||
if (this.material) this.mesh.material = this.material
|
if (this.material) this.mesh.material = this.material
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
update (gl, dt) {
|
update (gl, dt, camera) {
|
||||||
|
this.active = camera.frustum.containsBox(
|
||||||
|
vec3.transformMat4([], [0.0, 0.0, 0.0], this.transform),
|
||||||
|
vec3.transformMat4([], [this.size, this.size, this.size], this.transform)
|
||||||
|
)
|
||||||
|
if (!this.active) return false
|
||||||
|
if (!this.generated) return this.generate(this.world.generator)
|
||||||
if (this.dirty) return this.createMesh(gl)
|
if (this.dirty) return this.createMesh(gl)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -275,132 +277,76 @@ class VoxelChunk extends MeshInstance {
|
|||||||
this.mesh && this.mesh.dispose(gl)
|
this.mesh && this.mesh.dispose(gl)
|
||||||
this.data = {}
|
this.data = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
draw (gl, shader, camera) {
|
||||||
|
if (this.active) super.draw(gl, shader)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class VoxelMapBlock extends Node {
|
class VoxelWorld {
|
||||||
constructor (pos, chunkSize = 16, size = 8) {
|
constructor (generator, origin, chunkSize = 16, renderDistance = 5) {
|
||||||
super(pos)
|
this.generator = generator
|
||||||
|
this.origin = origin
|
||||||
this.chunkSize = chunkSize
|
this.chunkSize = chunkSize
|
||||||
this.size = size
|
this.renderDistance = renderDistance
|
||||||
this.chunks = {}
|
this.chunks = []
|
||||||
this.generated = false
|
|
||||||
this.chunksLeft = size * size * size
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getChunk (x, y, z) {
|
getChunk (x, y, z) {
|
||||||
if (x < 0 || x >= this.size || y < 0 || y >= this.size || z < 0 || z >= this.size) return null
|
for (const i in this.chunks) {
|
||||||
return this.chunks[x][z][y]
|
const c = this.chunks[i]
|
||||||
|
if (c.relativePos[0] === x && c.relativePos[1] === y && c.relativePos[2] === z) return c
|
||||||
|
}
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
getChunkv (v) {
|
getChunkv (v) {
|
||||||
return this.getChunk(v[0], v[1], v[2])
|
return this.getChunk(v[0], v[1], v[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
generate (generator) {
|
|
||||||
this.chunks = {}
|
|
||||||
for (let x = 0; x < this.size; x++) {
|
|
||||||
if (!this.chunks[x]) this.chunks[x] = {}
|
|
||||||
for (let z = 0; z < this.size; z++) {
|
|
||||||
if (!this.chunks[x][z]) this.chunks[x][z] = {}
|
|
||||||
for (let y = 0; y < this.size; y++) {
|
|
||||||
if (this.chunks[x][z][y]) continue
|
|
||||||
const chunk = new VoxelChunk(this.pos, [x, y, z], this.chunkSize)
|
|
||||||
this.chunks[x][z][y] = chunk
|
|
||||||
this.addChild(chunk)
|
|
||||||
generator.pushChunk(chunk)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
destroy (gl) {
|
destroy (gl) {
|
||||||
this.generated = false
|
for (const i in this.chunks) {
|
||||||
for (const i in this.children) {
|
const ch = this.chunks[i]
|
||||||
const ch = this.children[i]
|
|
||||||
if (!(ch instanceof VoxelChunk)) continue
|
if (!(ch instanceof VoxelChunk)) continue
|
||||||
ch.destroy(gl)
|
ch.destroy(gl)
|
||||||
}
|
}
|
||||||
this.children = []
|
this.chunks = []
|
||||||
this.chunks = {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update (gl, dt) {
|
update (gl, dt, camera) {
|
||||||
if (!this.generated) return false
|
const slgrid = [
|
||||||
for (const i in this.children) {
|
Math.floor(camera.pos[0] / this.chunkSize),
|
||||||
const ch = this.children[i]
|
Math.floor(camera.pos[1] / this.chunkSize),
|
||||||
if (!(ch instanceof VoxelChunk)) continue
|
Math.floor(camera.pos[2] / this.chunkSize)
|
||||||
if (ch.update(gl, dt)) return true
|
]
|
||||||
|
|
||||||
|
for (let x = slgrid[0] - this.renderDistance; x < slgrid[0] + this.renderDistance; x++) {
|
||||||
|
for (let z = slgrid[2] - this.renderDistance; z < slgrid[2] + this.renderDistance; z++) {
|
||||||
|
for (let y = slgrid[1] + this.renderDistance / 2; y > slgrid[1] - this.renderDistance / 2; y--) {
|
||||||
|
if (this.getChunk(x, y, z)) continue
|
||||||
|
const chunk = new VoxelChunk(this, [x, y, z], this.chunkSize)
|
||||||
|
this.chunks.push(chunk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class VoxelWorld extends Node {
|
const resp = []
|
||||||
constructor (generator, renderDistance = 2, worldSize = 64, blockSize = 8, chunkSize = 16) {
|
for (const i in this.chunks) {
|
||||||
super([0.0, 0.0, 0.0])
|
const chunk = this.chunks[i]
|
||||||
this.generator = generator
|
const dist = vec3.length(subv3(chunk.relativePos, slgrid))
|
||||||
this.renderDistance = renderDistance
|
if (dist < this.renderDistance) resp.push(chunk)
|
||||||
this.generator = generator
|
|
||||||
this.worldSize = worldSize
|
|
||||||
this.blockSize = blockSize
|
|
||||||
this.chunkSize = chunkSize
|
|
||||||
this.blocks = {}
|
|
||||||
this.mapblockqueue = []
|
|
||||||
}
|
}
|
||||||
|
this.chunks = resp
|
||||||
|
|
||||||
queueMapblock (pos) {
|
for (const i in this.chunks) {
|
||||||
this.mapblockqueue.push(pos)
|
const ch = this.chunks[i]
|
||||||
}
|
if (ch.update(gl, dt, camera)) break
|
||||||
|
|
||||||
getBlock (x, y, z) {
|
|
||||||
if (!this.blocks[x] || !this.blocks[x][z] || !this.blocks[x][z][y]) return null
|
|
||||||
return this.blocks[x][z][y]
|
|
||||||
}
|
|
||||||
|
|
||||||
update (gl, cam, dt) {
|
|
||||||
// Generate queued mapblocks before adding new ones to queue
|
|
||||||
if (this.mapblockqueue.length) {
|
|
||||||
const leftover = []
|
|
||||||
let generated = false
|
|
||||||
for (const i in this.mapblockqueue) {
|
|
||||||
const pos = this.mapblockqueue[i]
|
|
||||||
const check = this.getBlock(pos[0], pos[1], pos[2])
|
|
||||||
|
|
||||||
if (generated || check) {
|
|
||||||
leftover.push(pos)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
const absPos = mulv3(pos, this.blockSize * this.chunkSize)
|
|
||||||
const block = new VoxelMapBlock(absPos, this.chunkSize, this.blockSize)
|
|
||||||
block.generate(this.generator)
|
|
||||||
|
|
||||||
if (!this.blocks[pos[0]]) this.blocks[pos[0]] = {}
|
|
||||||
if (!this.blocks[pos[0]][pos[2]]) this.blocks[pos[0]][pos[2]] = {}
|
|
||||||
if (!this.blocks[pos[0]][pos[2]][pos[1]]) this.blocks[pos[0]][pos[2]][pos[1]] = {}
|
|
||||||
|
|
||||||
this.blocks[pos[0]][pos[2]][pos[1]] = block
|
|
||||||
this.addChild(block)
|
|
||||||
generated = true
|
|
||||||
}
|
|
||||||
this.mapblockqueue = leftover
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate a fixed grid
|
|
||||||
const total = this.blockSize * this.chunkSize
|
|
||||||
const slgrid = [Math.floor(cam.pos[0] / total), Math.floor(cam.pos[1] / total), Math.floor(cam.pos[2] / total)]
|
|
||||||
|
|
||||||
for (let x = slgrid[0] - this.renderDistance / 2; x < slgrid[0] + this.renderDistance / 2; x++) {
|
|
||||||
for (let z = slgrid[2] - this.renderDistance / 2; z < slgrid[2] + this.renderDistance / 2; z++) {
|
|
||||||
for (let y = slgrid[1] - this.renderDistance / 2; y < slgrid[1] + this.renderDistance / 2; y++) {
|
|
||||||
if (this.getBlock(x, y, z)) continue
|
|
||||||
this.queueMapblock([x, y, z])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const i in this.children) {
|
draw (gl, shader) {
|
||||||
if (this.children[i].update(gl, dt)) break
|
for (const i in this.chunks) {
|
||||||
|
this.chunks[i].draw(gl, shader)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -410,29 +356,12 @@ class VoxelGenerator {
|
|||||||
this.material = material
|
this.material = material
|
||||||
this.noise = noise
|
this.noise = noise
|
||||||
this.groundHeight = groundHeight
|
this.groundHeight = groundHeight
|
||||||
this.generateQueue = []
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push a chunk into the generation queue
|
|
||||||
pushChunk (chunk) {
|
|
||||||
this.generateQueue.push(chunk)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get chunk height
|
// Get chunk height
|
||||||
getHeight (x, z) {
|
getHeight (x, z) {
|
||||||
return this.noise.getHeight(x, z) + this.groundHeight
|
return this.noise.getHeight(x / 100, z / 100) * this.noise.amplitude + this.groundHeight
|
||||||
}
|
|
||||||
|
|
||||||
// Generate chunks in the queue
|
|
||||||
update (dt) {
|
|
||||||
for (const i in this.generateQueue) {
|
|
||||||
const chunk = this.generateQueue[i]
|
|
||||||
if (chunk.generated) continue
|
|
||||||
|
|
||||||
chunk.material = this.material
|
|
||||||
chunk.generate(this)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { VoxelGenerator, Voxel, VoxelChunk, VoxelMapBlock, VoxelWorld }
|
export { VoxelGenerator, VoxelChunk, VoxelWorld }
|
||||||
|
27
src/engine/voxel/voxeldata.js
Normal file
27
src/engine/voxel/voxeldata.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
const VoxelData = {
|
||||||
|
index: 0,
|
||||||
|
registeredVoxels: {},
|
||||||
|
indexCache: [],
|
||||||
|
texture: null,
|
||||||
|
register: (name, def) => {
|
||||||
|
def.index = VoxelData.index++
|
||||||
|
VoxelData.registeredVoxels[name] = def
|
||||||
|
VoxelData.indexCache.push(def)
|
||||||
|
return def.index
|
||||||
|
},
|
||||||
|
get: (name) => {
|
||||||
|
return VoxelData.registeredVoxels[name]
|
||||||
|
},
|
||||||
|
afterRegistration: () => {
|
||||||
|
|
||||||
|
},
|
||||||
|
isSolid: (id) => {
|
||||||
|
return VoxelData.indexCache[id] ? VoxelData.indexCache[id].solid : false
|
||||||
|
},
|
||||||
|
textureIndex: (id, face) => {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default VoxelData
|
9
src/engine/voxel/voxeltexture.js
Normal file
9
src/engine/voxel/voxeltexture.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import Screen from '../screen'
|
||||||
|
|
||||||
|
function generateTextureMap (registeredVoxels) {
|
||||||
|
// body...
|
||||||
|
}
|
||||||
|
|
||||||
|
const VoxelTexture = {
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user