cleanup, comments

This commit is contained in:
Evert Prants 2020-01-05 21:11:05 +02:00
parent 1bad7e46ab
commit 4de4de419c
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
2 changed files with 72 additions and 67 deletions

View File

@ -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)
} }
} }

View File

@ -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) {