import OpenSimplexNoise from 'open-simplex-noise' import { vec3 } from 'gl-matrix' import Resource from '../../resource' class HeightMap { constructor (size) { this.size = size } static async fromFile (file, amplitude) { let img = await Resource.loadImage(file) if (img.width / img.height !== 1) throw new Error('Height Map needs to be of 1:1 aspect ratio.') let hmap = new HeightMap(img.width) let sampler = Resource.imageToSampler(img) for (let x = 0; x < img.width; x++) { for (let y = 0; y < img.width; y++) { hmap['h' + x + ';' + y] = (sampler(x, y)[0] / 255 * 2 - 1) * amplitude } } sampler = null return hmap } getHeight (x, y) { if (x > this.size || y > this.size || x < 0 || y < 0) return 0 if (!this['h' + x + ';' + y]) return 0 return this['h' + x + ';' + y] } getNormal (x, y) { let hL = this.getHeight(x - 1, y) let hR = this.getHeight(x + 1, y) let hD = this.getHeight(x, y - 1) let hU = this.getHeight(x, y + 1) let normal = vec3.fromValues(hL - hR, 2.0, hD - hU) vec3.normalize(normal, normal) return normal } } class SimplexHeightMap extends HeightMap { constructor (offsetX, offsetY, size, seed) { super(size) this.ix = offsetX this.iy = offsetY this.seed = seed this.osn = new OpenSimplexNoise(seed) } getNoise (relX, relY) { let x = ((this.ix * this.size) + relX) / this.size - 0.5 let y = ((this.iy * this.size) + relY) / this.size - 0.5 let total = this.osn.noise2D(2 * x, 2 * y) + 0.5 * this.osn.noise2D(4 * x, 4 * y) + 0.25 * this.osn.noise2D(2 * x, 2 * y) total *= 10 return total } getHeight (x, y) { return this.getNoise(x, y) } } export { HeightMap, SimplexHeightMap }