diff --git a/src/engine/components/planet/index.js b/src/engine/components/planet/index.js index cf6f4a5..9b1ea0f 100644 --- a/src/engine/components/planet/index.js +++ b/src/engine/components/planet/index.js @@ -10,11 +10,16 @@ class PlanetGenerator { this.resolution = resolution 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.') + } } } class CubeFace { - constructor (parent, level, pos, normal, generator) { + constructor (index, parent, level, pos, normal, generator) { + this.index = index this.parent = parent this.children = [] @@ -43,7 +48,7 @@ class CubeFace { generate () { if (this.generated) return - const VERTICES = this.generator.resolution + const sideResolution = this.generator.resolution const vertices = [] const normals = [] const textureCoords = [] @@ -52,11 +57,11 @@ class CubeFace { const radius = this.generator.radius const divisionLevel = Math.pow(2, this.level) - for (let i = 0, vertexPointer = 0; i < VERTICES; i++) { - for (let j = 0; j < VERTICES; j++, vertexPointer++) { + for (let i = 0, vertexPointer = 0; i < sideResolution; i++) { + for (let j = 0; j < sideResolution; j++, vertexPointer++) { // Vertex index (0 - 1) - const iindex = i / (VERTICES - 1) - const jindex = j / (VERTICES - 1) + const iindex = i / (sideResolution - 1) + const jindex = j / (sideResolution - 1) // From the left and forward vectors, we can calculate an oriented vertex const iv = divv3(mulv3(mulv3(this.left, iindex), radius), divisionLevel) @@ -76,50 +81,69 @@ class CubeFace { normals[vertexPointer * 3] = normal[0] normals[vertexPointer * 3 + 1] = normal[1] normals[vertexPointer * 3 + 2] = normal[2] - textureCoords[vertexPointer * 2] = j * (1 / VERTICES) - textureCoords[vertexPointer * 2 + 1] = i * (1 / VERTICES) + textureCoords[vertexPointer * 2] = j * (1 / sideResolution) + textureCoords[vertexPointer * 2 + 1] = i * (1 / sideResolution) - if (i === Math.floor(VERTICES / 2) && j === Math.floor(VERTICES / 2)) { + if (i === Math.floor(sideResolution / 2) && j === Math.floor(sideResolution / 2)) { this.center = pos } } } - for (let gz = 0; gz < VERTICES - 1; gz++) { - for (let gx = 0; gx < VERTICES - 1; gx++) { - const topLeft = (gz * VERTICES) + gx + // TODO: neighbor detection + let fanTop = false + let fanBottom = false + let fanLeft = false + let fanRight = false + + for (let y = 0; y < sideResolution - 1; y++) { + let slantLeft = (y % 2) === 0 + for (let x = 0; x < sideResolution - 1; x++) { + const topLeft = (y * sideResolution) + x const topRight = topLeft + 1 - const bottomLeft = ((gz + 1) * VERTICES) + gx + const bottomLeft = ((y + 1) * sideResolution) + x const bottomRight = bottomLeft + 1 - if (gx % 2 !== 0) { - if (gz % 2 === 0) { - // x-x - // |/ - // x x - indices.push(topRight, topLeft, bottomLeft) - indices.push(bottomLeft, bottomRight, topRight) + + let tri1 = slantLeft ? [topLeft, bottomLeft, bottomRight] : [topLeft, bottomLeft, topRight] + let tri2 = slantLeft ? [topLeft, bottomRight, topRight] : [bottomLeft, bottomRight, topRight] + + if (fanTop && y === 0) { + if (x % 2 === 0) { + tri2 = [topLeft, bottomRight, topRight + 1] } else { - // x-x - // \| - // x x - indices.push(bottomRight, topRight, topLeft) - indices.push(topLeft, bottomLeft, bottomRight) - } - } else { - if (gz % 2 === 0) { - // x x - // |\ - // x-x - indices.push(topLeft, bottomLeft, bottomRight) - indices.push(bottomRight, topRight, topLeft) - } else { - // x x - // /| - // x-x - indices.push(bottomLeft, bottomRight, topRight) - indices.push(topRight, topLeft, bottomLeft) + tri1 = null } } + + if (fanRight && x === sideResolution - 2) { + if (y % 2 === 0) { + tri2 = [topRight, bottomLeft, bottomRight + sideResolution] + } else { + tri2 = null + } + } + + if (fanBottom && y === sideResolution - 2) { + if (x % 2 === 0) { + tri2 = [bottomLeft, bottomRight + 1, topRight] + } else { + tri1 = null + } + } + + if (fanLeft && x === 0) { + if (y % 2 === 0) { + tri1 = [topLeft, bottomLeft + sideResolution, bottomRight] + } else { + tri1 = null + } + } + + // faster than concat :p + if (tri1) indices.push(tri1[0], tri1[1], tri1[2]) + if (tri2) indices.push(tri2[0], tri2[1], tri2[2]) + + slantLeft = !slantLeft } } @@ -137,8 +161,12 @@ class CubeFace { } } + isLeaf () { + return !this.children.length + } + merge () { - if (!this.children.length) return + if (this.isLeaf()) return for (const i in this.children) { const ch = this.children[i] @@ -159,14 +187,14 @@ class CubeFace { const stepForward = mulv3(this.forward, this.generator.radius / Math.pow(2, lv)) this.children = [ - // Bottom right corner - new CubeFace(this, lv, this.position, this.normal, this.generator), - // Top right corner - new CubeFace(this, lv, addv3(this.position, stepForward), this.normal, this.generator), - // Bottom left corner - new CubeFace(this, lv, addv3(this.position, stepLeft), this.normal, this.generator), // Top left corner - new CubeFace(this, lv, addv3(this.position, addv3(stepLeft, stepForward)), this.normal, this.generator) + new CubeFace(0, this, lv, addv3(this.position, addv3(stepLeft, stepForward)), this.normal, this.generator), + // Top right corner + new CubeFace(1, this, lv, addv3(this.position, stepForward), this.normal, this.generator), + // Bottom right corner + new CubeFace(2, this, lv, this.position, this.normal, this.generator), + // Bottom left corner + new CubeFace(3, this, lv, addv3(this.position, stepLeft), this.normal, this.generator) ] this.dispose() @@ -217,14 +245,14 @@ class CubePlanet { const hs = generator.radius / 2 this.faces = [ - new CubeFace(this, 0, [0, 0, -hs], [0, 0, -1], generator), // front - new CubeFace(this, 0, [0, 0, hs], [0, 0, 1], generator), // back + 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(this, 0, [-hs, 0, 0], [-1, 0, 0], generator), // left - new CubeFace(this, 0, [hs, 0, 0], [1, 0, 0], generator), // right + 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(this, 0, [0, hs, 0], [0, 1, 0], generator), // top - new CubeFace(this, 0, [0, -hs, 0], [0, -1, 0], generator) // bottom + 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 ] }