import { Mesh } from '../../mesh' import { mat4 } from 'gl-matrix' import { subv3, mulv3, addv3, normalv3, crossv3 } from '../../utility' class CubeFace { constructor (parent, level, pos, normal, resolution, radius, generator) { this.parent = parent this.children = [] this.position = pos this.normal = normal this.resolution = resolution this.radius = radius this.level = 0 this.generated = false // Calculate left and forward vectors from the normal this.left = [normal[1], normal[2], normal[0]] this.forward = crossv3(normal, this.left) this.transform = mat4.create() mat4.fromTranslation(this.transform, this.position) this.generate() } generate () { if (this.generated) return let cpoint = subv3(this.position, mulv3(this.left, this.radius / 2)) cpoint = subv3(cpoint, mulv3(this.forward, this.radius / 2)) let VERTICES = this.resolution let count = VERTICES * VERTICES let vertices = new Array(count * 3) // let normals = new Array(count * 3) let textureCoords = new Array(count * 2) let indices = new Array(6 * (VERTICES - 1) * (VERTICES - 1)) for (let i = 0, vertexPointer = 0; i < VERTICES; i++) { for (let j = 0; j < VERTICES; j++, vertexPointer++) { let isize = i / VERTICES * this.radius let jsize = j / VERTICES * this.radius // From the left and forward vectors, we can calculate an oriented vertex let iv = mulv3(this.left, isize) let jv = mulv3(this.forward, jsize) // Add the scaled left and forward to the centered origin let vertex = addv3(cpoint.slice(0), addv3(iv, jv)) // Normalize and multiply by radius to create a spherical mesh let pos = mulv3(normalv3(vertex), this.radius) vertices[vertexPointer * 3] = pos[0] vertices[vertexPointer * 3 + 1] = pos[1] vertices[vertexPointer * 3 + 2] = pos[2] // normals[vertexPointer * 3] = normal[0] // normals[vertexPointer * 3 + 1] = normal[1] // normals[vertexPointer * 3 + 2] = normal[2] textureCoords[vertexPointer * 2] = j / (VERTICES - 1) textureCoords[vertexPointer * 2 + 1] = i / (VERTICES - 1) } } for (let gz = 0, pointer = 0; gz < VERTICES - 1; gz++) { for (let gx = 0; gx < VERTICES - 1; gx++) { let topLeft = (gz * VERTICES) + gx let topRight = topLeft + 1 let bottomLeft = ((gz + 1) * VERTICES) + gx let bottomRight = bottomLeft + 1 indices[pointer++] = topLeft indices[pointer++] = bottomLeft indices[pointer++] = topRight indices[pointer++] = topRight indices[pointer++] = bottomLeft indices[pointer++] = bottomRight } } this.mesh = Mesh.construct(window.gl, vertices, indices, textureCoords) this.generated = true } draw (gl, shader) { // Set model transform matrix uniform const transformLocation = shader.getUniformLocation(gl, 'uModelMatrix') gl.uniformMatrix4fv(transformLocation, false, this.transform) this.mesh.prepare(gl, shader) this.mesh.draw(gl, shader) } } class CubePlanet { constructor (origin, resolution, radius, generator) { this.origin = origin this.resolution = resolution this.radius = radius let hs = resolution / 2 this.faces = [ new CubeFace(this, 0, [0, 0, -hs], [0, 0, -1], resolution, radius, generator), // front // new CubeFace(this, 0, [0, 0, hs], [0, 0, 1], resolution, radius, generator), // back new CubeFace(this, 0, [-hs, 0, 0], [-1, 0, 0], resolution, radius, generator), // left // new CubeFace(this, 0, [hs, 0, 0], [1, 0, 0], resolution, radius, generator), // right // new CubeFace(this, 0, [0, hs, 0], [0, 1, 0], resolution, radius, generator), // top // new CubeFace(this, 0, [0, -hs, 0], [0, -1, 0], resolution, radius, generator) // bottom ] } draw (gl, shader) { for (let i in this.faces) { this.faces[i].draw(gl, shader) } } } export { CubePlanet, CubeFace }