3dexperiments/src/engine/components/terrain/experimental.js

97 lines
3.0 KiB
JavaScript

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 }