import { Node } from '../' import { Mesh } from '../../mesh' import { vec3 } from 'gl-matrix' import { subv3, mulv3, addv3, normalv3 } from '../../utility' class Terrain extends Node { constructor (pos, sWidth, sHeight, face = [0.0, -1.0, 0.0]) { super(pos) this.width = sWidth this.height = sHeight this.mesh = null // Calculate left and forward vectors this.left = [face[1], face[2], face[0]] || [1.0, 0.0, 0.0] this.forward = [0.0, 0.0, -1.0] vec3.cross(this.forward, face, this.left) } createMesh (gl, heightMap) { // Center the mesh let cpoint = [0.0, 0.0, 0.0] cpoint = subv3(cpoint, mulv3(this.left, heightMap.size / 2)) cpoint = subv3(cpoint, mulv3(this.forward, heightMap.size / 2)) let VERTICES = heightMap.size 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)) let vertexPointer = 0 for (let i = 0; i < VERTICES; i++) { for (let j = 0; j < VERTICES; j++) { let isize = j / (VERTICES - 1) * this.width / 2 let jsize = i / (VERTICES - 1) * this.height / 2 // 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 pos = addv3(cpoint.slice(0), addv3(iv, jv)) vertices[vertexPointer * 3] = pos[0] vertices[vertexPointer * 3 + 1] = pos[1] vertices[vertexPointer * 3 + 2] = pos[2] let normal = [0.0, 1.0, 0.0] // heightMap.getNormal(j, i) 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) vertexPointer++ } } let pointer = 0 for (let gz = 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(gl, vertices, indices, textureCoords, normals) } setMaterial (mat) { this.mesh.material = mat } draw (gl, shader) { if (!this.mesh) return // 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) super.draw(gl, shader) } } export { Terrain }