better (maybe) index generation

This commit is contained in:
Evert Prants 2020-04-01 21:52:45 +03:00
parent bdb2ad6697
commit 2cf2451b6f
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
1 changed files with 81 additions and 53 deletions

View File

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