cleanup, comments
This commit is contained in:
parent
1bad7e46ab
commit
4de4de419c
@ -1,6 +1,6 @@
|
|||||||
import { Mesh } from '../mesh'
|
import { Mesh } from '../mesh'
|
||||||
import { MeshInstance } from '../components'
|
import { MeshInstance } from '../components'
|
||||||
import { addv3, crossv3, subv3 } from '../utility'
|
import { addv3 } from '../utility'
|
||||||
|
|
||||||
const FACE_VERTEX = [
|
const FACE_VERTEX = [
|
||||||
// Bottom
|
// Bottom
|
||||||
@ -8,34 +8,39 @@ const FACE_VERTEX = [
|
|||||||
[1.0, 0.0, 0.0],
|
[1.0, 0.0, 0.0],
|
||||||
[1.0, 0.0, 1.0],
|
[1.0, 0.0, 1.0],
|
||||||
[0.0, 0.0, 1.0],
|
[0.0, 0.0, 1.0],
|
||||||
[0.0, 0.0, 0.0]
|
[0.0, 0.0, 0.0],
|
||||||
|
[0.0, -1.0, 0.0]
|
||||||
],
|
],
|
||||||
// Top
|
// Top
|
||||||
[
|
[
|
||||||
[0.0, 1.0, 0.0],
|
[0.0, 1.0, 0.0],
|
||||||
[0.0, 1.0, 1.0],
|
[0.0, 1.0, 1.0],
|
||||||
[1.0, 1.0, 1.0],
|
[1.0, 1.0, 1.0],
|
||||||
[1.0, 1.0, 0.0]
|
[1.0, 1.0, 0.0],
|
||||||
|
[0.0, 1.0, 0.0]
|
||||||
],
|
],
|
||||||
// Left
|
// Left
|
||||||
[
|
[
|
||||||
[0.0, 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]
|
[0.0, 0.0, 0.0],
|
||||||
|
[-1.0, 0.0, 0.0]
|
||||||
],
|
],
|
||||||
// Right
|
// Right
|
||||||
[
|
[
|
||||||
[1.0, 0.0, 0.0],
|
[1.0, 0.0, 0.0],
|
||||||
[1.0, 1.0, 0.0],
|
[1.0, 1.0, 0.0],
|
||||||
[1.0, 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]
|
||||||
],
|
],
|
||||||
// Front
|
// Front
|
||||||
[
|
[
|
||||||
[1.0, 0.0, 1.0],
|
[1.0, 0.0, 1.0],
|
||||||
[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]
|
||||||
],
|
],
|
||||||
// Back
|
// Back
|
||||||
@ -43,7 +48,8 @@ const FACE_VERTEX = [
|
|||||||
[0.0, 0.0, 0.0],
|
[0.0, 0.0, 0.0],
|
||||||
[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]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -65,130 +71,123 @@ class Voxel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const AIR_VOXEL = new Voxel(0)
|
const AIR_VOXEL = new Voxel(0)
|
||||||
|
const GROUND_VOXEL = new Voxel(1)
|
||||||
|
|
||||||
class VoxelChunk extends MeshInstance {
|
class VoxelChunk extends MeshInstance {
|
||||||
constructor (pos, size = 16) {
|
constructor (pos, size = 16) {
|
||||||
super(null, pos)
|
super(null, pos)
|
||||||
this.size = size
|
this.size = size
|
||||||
this.array = {}
|
|
||||||
|
|
||||||
this.mesh = null
|
this.mesh = null
|
||||||
|
|
||||||
|
// Voxel data
|
||||||
|
this.data = {}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
this.generated = false
|
||||||
}
|
}
|
||||||
|
|
||||||
getVoxel (x, y, z) {
|
getVoxel (x, y, z) {
|
||||||
if (x < 0 || x >= this.size || y < 0 || y >= this.size || z < 0 || z >= this.size) return AIR_VOXEL
|
if (x < 0 || x >= this.size || y < 0 || y >= this.size || z < 0 || z >= this.size) return AIR_VOXEL
|
||||||
return this.array[x][y][z]
|
return this.data[x][y][z]
|
||||||
}
|
}
|
||||||
|
|
||||||
generate (noise) {
|
generate (generator) {
|
||||||
this.array = {}
|
this.data = {}
|
||||||
for (let x = 0; x < this.size; x++) {
|
for (let x = 0; x < this.size; x++) {
|
||||||
if (!this.array[x]) this.array[x] = {}
|
if (!this.data[x]) this.data[x] = {}
|
||||||
for (let y = 0; y < this.size; y++) {
|
for (let y = 0; y < this.size; y++) {
|
||||||
if (!this.array[x][y]) this.array[x][y] = {}
|
if (!this.data[x][y]) this.data[x][y] = {}
|
||||||
for (let z = 0; z < this.size; z++) {
|
for (let z = 0; z < this.size; z++) {
|
||||||
if (!this.array[x][y][z]) this.array[x][y][z] = {}
|
if (!this.data[x][y][z]) this.data[x][y][z] = {}
|
||||||
let solid = y < (noise.getHeight(x + this.pos[0], z + this.pos[2]) + 10)
|
let solid = y < (generator.getHeight(x + this.pos[0], z + this.pos[2]) + 10)
|
||||||
this.array[x][y][z] = new Voxel(solid ? 1 : 0)
|
this.data[x][y][z] = solid ? GROUND_VOXEL : AIR_VOXEL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.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 (verts, pos, face) {
|
createFace (points, pos, face) {
|
||||||
let posi = [
|
// Add the corresponding offsets for this face to the position
|
||||||
|
let 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]),
|
||||||
addv3(pos, FACE_VERTEX[face][2]), addv3(pos, FACE_VERTEX[face][3])
|
addv3(pos, FACE_VERTEX[face][2]), addv3(pos, FACE_VERTEX[face][3])
|
||||||
]
|
]
|
||||||
let normal = crossv3(subv3(posi[2], posi[0]), subv3(posi[3], posi[1]))
|
|
||||||
verts.push([posi[0], normal, [0.0, 1.0]])
|
// Select the normal for this face
|
||||||
verts.push([posi[1], normal, [0.0, 0.0]])
|
let normal = FACE_VERTEX[face][4]
|
||||||
verts.push([posi[2], normal, [1.0, 0.0]])
|
|
||||||
verts.push([posi[0], normal, [0.0, 1.0]])
|
// Return the 6 vertices that make up this face (two triangles)
|
||||||
verts.push([posi[2], normal, [1.0, 0.0]])
|
// They're named points because this function returns not only vertices,
|
||||||
verts.push([posi[3], normal, [1.0, 1.0]])
|
// but corresponding texture coordinates and normals at the same time for convenience
|
||||||
|
points.push([corners[0], normal, [0.0, 1.0]])
|
||||||
|
points.push([corners[1], normal, [0.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]])
|
||||||
}
|
}
|
||||||
|
|
||||||
createMesh (gl) {
|
createMesh (gl) {
|
||||||
|
// Makes sure the createMesh function is not called again while it is generating
|
||||||
this.dirty = false
|
this.dirty = false
|
||||||
|
|
||||||
|
// If there is no generated chunk, we have nothing to base a mesh off of
|
||||||
|
if (!this.generated) return
|
||||||
|
|
||||||
|
// If there already exists a mesh, dispose of it
|
||||||
if (this.mesh) {
|
if (this.mesh) {
|
||||||
this.mesh.dispose(gl)
|
this.mesh.dispose(gl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Array of vertices with texture positions and normals
|
||||||
let points = []
|
let points = []
|
||||||
|
|
||||||
|
// 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++) {
|
||||||
|
let cellPos = [x, y, z]
|
||||||
if (!this.getVoxel(x, y, z).solid) continue
|
if (!this.getVoxel(x, y, z).solid) continue
|
||||||
|
|
||||||
let faceLeft = true
|
if (!this.getVoxel(x, y - 1, z).solid) {
|
||||||
if (x > 0) {
|
|
||||||
faceLeft = !this.getVoxel(x - 1, y, z).solid
|
|
||||||
}
|
|
||||||
|
|
||||||
let faceRight = true
|
|
||||||
if (x < this.size - 1) {
|
|
||||||
faceRight = !this.getVoxel(x + 1, y, z).solid
|
|
||||||
}
|
|
||||||
|
|
||||||
let faceBottom = true
|
|
||||||
if (y > 0) {
|
|
||||||
faceBottom = !this.getVoxel(x, y - 1, z).solid
|
|
||||||
}
|
|
||||||
|
|
||||||
let faceTop = true
|
|
||||||
if (y < this.size - 1) {
|
|
||||||
faceTop = !this.getVoxel(x, y + 1, z).solid
|
|
||||||
}
|
|
||||||
|
|
||||||
let faceBack = true
|
|
||||||
if (z > 0) {
|
|
||||||
faceBack = !this.getVoxel(x, y, z - 1).solid
|
|
||||||
}
|
|
||||||
|
|
||||||
let faceFront = true
|
|
||||||
if (z < this.size - 1) {
|
|
||||||
faceFront = !this.getVoxel(x, y, z + 1).solid
|
|
||||||
}
|
|
||||||
|
|
||||||
let cellPos = [x, y, z]
|
|
||||||
|
|
||||||
if (faceBottom) {
|
|
||||||
this.createFace(points, cellPos, FACE_BOTTOM)
|
this.createFace(points, cellPos, FACE_BOTTOM)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (faceTop) {
|
if (!this.getVoxel(x, y + 1, z).solid) {
|
||||||
this.createFace(points, cellPos, FACE_TOP)
|
this.createFace(points, cellPos, FACE_TOP)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (faceLeft) {
|
if (!this.getVoxel(x - 1, y, z).solid) {
|
||||||
this.createFace(points, cellPos, FACE_LEFT)
|
this.createFace(points, cellPos, FACE_LEFT)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (faceRight) {
|
if (!this.getVoxel(x + 1, y, z).solid) {
|
||||||
this.createFace(points, cellPos, FACE_RIGHT)
|
this.createFace(points, cellPos, FACE_RIGHT)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (faceFront) {
|
if (!this.getVoxel(x, y, z + 1).solid) {
|
||||||
this.createFace(points, cellPos, FACE_FRONT)
|
this.createFace(points, cellPos, FACE_FRONT)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (faceBack) {
|
if (!this.getVoxel(x, y, z - 1).solid) {
|
||||||
this.createFace(points, cellPos, FACE_BACK)
|
this.createFace(points, cellPos, FACE_BACK)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do not create a mesh when there are no faces in this chunk
|
||||||
if (points.length === 0) {
|
if (points.length === 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Flatten the points array to three separate arrays
|
||||||
let vertices = []
|
let vertices = []
|
||||||
let normals = []
|
let normals = []
|
||||||
let uvs = []
|
let uvs = []
|
||||||
@ -204,11 +203,15 @@ 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?)
|
||||||
this.mesh = Mesh.construct(gl, vertices, null, uvs, normals)
|
this.mesh = Mesh.construct(gl, vertices, null, uvs, normals)
|
||||||
|
|
||||||
|
// TODO: Temporary..
|
||||||
|
if (this.material) this.mesh.material = this.material
|
||||||
}
|
}
|
||||||
|
|
||||||
update (dt) {
|
update (gl, dt) {
|
||||||
|
if (this.dirty) return this.createMesh(gl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,8 +89,7 @@ async function pipeline () {
|
|||||||
// Voxel test
|
// Voxel test
|
||||||
let chunk = new VoxelChunk([0.0, 0.0, 0.0])
|
let chunk = new VoxelChunk([0.0, 0.0, 0.0])
|
||||||
chunk.generate(hmap)
|
chunk.generate(hmap)
|
||||||
chunk.createMesh(game.gl)
|
chunk.material = material
|
||||||
chunk.mesh.material = material
|
|
||||||
|
|
||||||
// Update function for camera and terrain
|
// Update function for camera and terrain
|
||||||
let fpsTimer = 0
|
let fpsTimer = 0
|
||||||
@ -132,6 +131,9 @@ async function pipeline () {
|
|||||||
// Ripple water
|
// Ripple water
|
||||||
// waterRenderer.update(dt)
|
// waterRenderer.update(dt)
|
||||||
|
|
||||||
|
// Update voxel chunk
|
||||||
|
chunk.update(game.gl, dt)
|
||||||
|
|
||||||
// Set text to FPS
|
// Set text to FPS
|
||||||
fpsTimer++
|
fpsTimer++
|
||||||
if (fpsTimer === 10) {
|
if (fpsTimer === 10) {
|
||||||
|
Loading…
Reference in New Issue
Block a user