diff --git a/src/engine/components/planet/index.js b/src/engine/components/planet/index.js index 6b4847a..fa0cb44 100644 --- a/src/engine/components/planet/index.js +++ b/src/engine/components/planet/index.js @@ -1,4 +1,5 @@ import { Mesh } from '../../mesh' +import { BoundingBox } from '../../mesh/aabb' import { mat4, vec3 } from 'gl-matrix' import { subv3, mulv3, addv3, divv3, normalv3, crossv3 } from '../../utility' import Screen from '../../screen' @@ -11,16 +12,16 @@ class PlanetGenerator { this.radius = radius this.noise = noise - if (resolution <= 1 || resolution % 2 === 0) { - throw new Error('Resolution must be higher than 1 and an odd number.') - } - PlanetIndexBuffers.generate(resolution) } } const PlanetIndexBuffers = { generate (sideResolution) { + if (sideResolution <= 1 || sideResolution % 2 === 0) { + throw new Error('Resolution must be higher than 1 and an odd number.') + } + PlanetIndexBuffers.base = PlanetIndexBuffers.generateBuffer(sideResolution) PlanetIndexBuffers.fixT = PlanetIndexBuffers.generateBuffer(sideResolution, true, false, false, false) PlanetIndexBuffers.fixTR = PlanetIndexBuffers.generateBuffer(sideResolution, true, true, false, false) @@ -93,7 +94,7 @@ const PlanetIndexBuffers = { } class CubeFace { - constructor (index, parent, level, pos, normal, generator) { + constructor (index, parent, level, pos, normal, planet) { this.index = index this.parent = parent this.children = [] @@ -103,7 +104,8 @@ class CubeFace { this.level = level this.generated = false - this.generator = generator + this.planet = planet + this.generator = planet.generator // Calculate left (x) and forward (z) vectors from the normal (y) this.left = [normal[1], normal[2], normal[0]] @@ -113,8 +115,8 @@ class CubeFace { // Center the face if (level === 0) { - this.position = subv3(this.position, mulv3(this.left, generator.radius / 2)) - this.position = subv3(this.position, mulv3(this.forward, generator.radius / 2)) + this.position = subv3(this.position, mulv3(this.left, this.generator.radius / 2)) + this.position = subv3(this.position, mulv3(this.forward, this.generator.radius / 2)) } this.generate() @@ -155,8 +157,8 @@ class CubeFace { normals[vertexPointer * 3] = normal[0] normals[vertexPointer * 3 + 1] = normal[1] normals[vertexPointer * 3 + 2] = normal[2] - textureCoords[vertexPointer * 2] = j * (1 / sideResolution) - textureCoords[vertexPointer * 2 + 1] = i * (1 / sideResolution) + textureCoords[vertexPointer * 2] = i * (1 / sideResolution) + textureCoords[vertexPointer * 2 + 1] = j * (1 / sideResolution) if (i === Math.floor(sideResolution / 2) && j === Math.floor(sideResolution / 2)) { this.center = pos @@ -164,17 +166,11 @@ class CubeFace { } } - // TODO: neighbor detection - const indexBuffer = PlanetIndexBuffers.base - // Generate normals for this mesh Mesh.generateNormals(normals, PlanetIndexBuffers.base.indices, vertices) this.mesh = Mesh.construct(Screen.gl, vertices, null, textureCoords, normals) - - // Set the index buffer for this mesh to use - PlanetIndexBuffers.setBuffer(this.mesh, indexBuffer) - + this.bounds = BoundingBox.fromMesh(this.mesh) this.generated = true } @@ -202,6 +198,7 @@ class CubeFace { this.children = [] this.generate() + this.updateNeighbors() } subdivide () { @@ -213,15 +210,16 @@ class CubeFace { this.children = [ // Top left corner - new CubeFace(0, this, lv, addv3(this.position, addv3(stepLeft, stepForward)), this.normal, this.generator), + new CubeFace(0, this, lv, this.position, this.normal, this.planet), // Top right corner - new CubeFace(1, this, lv, addv3(this.position, stepForward), this.normal, this.generator), + new CubeFace(1, this, lv, addv3(this.position, stepForward), this.normal, this.planet), // Bottom right corner - new CubeFace(2, this, lv, this.position, this.normal, this.generator), + new CubeFace(2, this, lv, addv3(this.position, addv3(stepLeft, stepForward)), this.normal, this.planet), // Bottom left corner - new CubeFace(3, this, lv, addv3(this.position, stepLeft), this.normal, this.generator) + new CubeFace(3, this, lv, addv3(this.position, stepLeft), this.normal, this.planet) ] + this.updateNeighbors() this.dispose() } @@ -253,18 +251,72 @@ class CubeFace { return } + this.updateNeighbors() + if (this.children.length > 0) { for (const i in this.children) { this.children[i].update(camera, dt) } } + } - this.updateNeighbors() + get root () { + if (this.level === 0) return this + if (this.parent.level === 0) return this.parent + return this.parent.root } updateNeighbors () { - // TODO: planet face traversal - if (this.level === 0) return + if (this.level === 0) { + // The neighbors of root nodes never change + if (this.neighborTop) return + switch (this.index) { + // Front face + case 0: + this.neighborTop = this.parent.faces[4] + this.neighborLeft = this.parent.faces[2] + this.neighborRight = this.parent.faces[3] + this.neighborBottom = this.parent.faces[5] + break + // Back face + case 1: + this.neighborTop = this.parent.faces[4] + this.neighborLeft = this.parent.faces[3] + this.neighborRight = this.parent.faces[2] + this.neighborBottom = this.parent.faces[5] + break + // Left face + case 2: + this.neighborTop = this.parent.faces[4] + this.neighborLeft = this.parent.faces[1] + this.neighborRight = this.parent.faces[0] + this.neighborBottom = this.parent.faces[5] + break + // Right face + case 3: + this.neighborTop = this.parent.faces[4] + this.neighborLeft = this.parent.faces[0] + this.neighborRight = this.parent.faces[1] + this.neighborBottom = this.parent.faces[5] + break + // Top face + case 4: + this.neighborTop = this.parent.faces[1] + this.neighborLeft = this.parent.faces[2] + this.neighborRight = this.parent.faces[3] + this.neighborBottom = this.parent.faces[0] + break + // Bottom face + case 5: + this.neighborTop = this.parent.faces[0] + this.neighborLeft = this.parent.faces[2] + this.neighborRight = this.parent.faces[3] + this.neighborBottom = this.parent.faces[1] + break + } + return + } + switch (this.index) { // Top left corner case 0: @@ -315,7 +367,7 @@ class CubeFace { static determineIndexBuffer (face) { let buffer = PlanetIndexBuffers.base - if (face.level === 0) return PlanetIndexBuffers.setBuffer(face.mesh, buffer) + if (face.level <= 1) return PlanetIndexBuffers.setBuffer(face.mesh, buffer) switch (face.index) { // Top left corner case 0: @@ -373,14 +425,14 @@ class CubePlanet { const hs = generator.radius / 2 this.faces = [ - new CubeFace(0, this, 0, [0, 0, -hs], [0, 0, -1], generator), // front - new CubeFace(0, this, 0, [0, 0, hs], [0, 0, 1], generator), // back + new CubeFace(0, this, 0, [0, 0, -hs], [0, 0, -1], this), // front + new CubeFace(1, this, 0, [0, 0, hs], [0, 0, 1], this), // back - new CubeFace(0, this, 0, [-hs, 0, 0], [-1, 0, 0], generator), // left - new CubeFace(0, this, 0, [hs, 0, 0], [1, 0, 0], generator), // right + new CubeFace(2, this, 0, [-hs, 0, 0], [-1, 0, 0], this), // left + new CubeFace(3, this, 0, [hs, 0, 0], [1, 0, 0], this), // right - new CubeFace(0, this, 0, [0, hs, 0], [0, 1, 0], generator), // top - new CubeFace(0, this, 0, [0, -hs, 0], [0, -1, 0], generator) // bottom + new CubeFace(4, this, 0, [0, hs, 0], [0, 1, 0], this), // top + new CubeFace(5, this, 0, [0, -hs, 0], [0, -1, 0], this) // bottom ] }