broken planet
This commit is contained in:
parent
c785db574c
commit
befbcc5480
@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<style type="text/css">*{margin:0;padding:0;}body{width:100%;height:100%;}body,html{overflow:hidden;}</style>
|
<style type="text/css">*{margin:0;padding:0;}body{width:100%;height:100%;}body,html{overflow:hidden;}</style>
|
||||||
<title>Trotland</title>
|
<title>3D Experiments</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
</body>
|
</body>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "trotland-game",
|
"name": "3dexperiments",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"description": "Trotland 3D MMORPG",
|
"description": "3D Experiments",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"serve": "node ./serve.js",
|
"serve": "node ./serve.js",
|
||||||
@ -9,7 +9,7 @@
|
|||||||
"watch": "webpack -w --mode=development"
|
"watch": "webpack -w --mode=development"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"game",
|
"experiment",
|
||||||
"webgl"
|
"webgl"
|
||||||
],
|
],
|
||||||
"private": true,
|
"private": true,
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { Node } from './components'
|
import { Node } from './components'
|
||||||
import { glMatrix, mat4, vec2, vec3 } from 'gl-matrix'
|
import { glMatrix, mat4, vec2, vec3 } from 'gl-matrix'
|
||||||
|
|
||||||
const SPEED = 10.0
|
const SPEED = 100.0
|
||||||
const SENSITIVTY = 100.0
|
const SENSITIVTY = 100.0
|
||||||
const FOV = 45.0
|
const FOV = 45.0
|
||||||
const ZNEAR = 0.1
|
const ZNEAR = 0.1
|
||||||
const ZFAR = 1000.0
|
const ZFAR = 10000.0
|
||||||
|
|
||||||
class Camera extends Node {
|
class Camera extends Node {
|
||||||
constructor (pos, rotation) {
|
constructor (pos, rotation) {
|
||||||
|
@ -47,6 +47,7 @@ class Node {
|
|||||||
this.rotation = rotation || [0.0, 0.0, 0.0]
|
this.rotation = rotation || [0.0, 0.0, 0.0]
|
||||||
|
|
||||||
this.transform = mat4.create()
|
this.transform = mat4.create()
|
||||||
|
|
||||||
this.updateTransform()
|
this.updateTransform()
|
||||||
|
|
||||||
this.parent = null
|
this.parent = null
|
||||||
@ -63,8 +64,8 @@ class Node {
|
|||||||
|
|
||||||
// Add local transform to the global transform, if present
|
// Add local transform to the global transform, if present
|
||||||
// Will be present in loaded models
|
// Will be present in loaded models
|
||||||
if (this._rootTransform) {
|
if (this.worldTransform) {
|
||||||
mat4.mul(matrix, matrix, this._rootTransform)
|
mat4.mul(matrix, matrix, this.worldTransform)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add parent's transform to this
|
// Add parent's transform to this
|
||||||
@ -158,13 +159,33 @@ class Node {
|
|||||||
|
|
||||||
// Draw base
|
// Draw base
|
||||||
draw (gl, shader) {
|
draw (gl, shader) {
|
||||||
// Set model transform matrix uniform
|
// Nothing to draw here, so just draw children
|
||||||
const transformLocation = shader.getUniformLocation(gl, 'uModelMatrix')
|
for (let i in this.children) {
|
||||||
gl.uniformMatrix4fv(transformLocation, false, this.transform)
|
let child = this.children[i]
|
||||||
|
if (!(child instanceof Node)) continue
|
||||||
|
child.draw(gl, shader)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update (dt) {
|
||||||
|
// Update children
|
||||||
|
for (let i in this.children) {
|
||||||
|
let child = this.children[i]
|
||||||
|
if (!(child instanceof Node)) continue
|
||||||
|
child.update(dt)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addChild (ch) {
|
addChild (ch) {
|
||||||
|
// Recursive add in case of table
|
||||||
|
if (ch && typeof ch === 'object' && ch.length) {
|
||||||
|
for (let i in ch) {
|
||||||
|
this.addChild(ch[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!(ch instanceof Node)) return
|
if (!(ch instanceof Node)) return
|
||||||
|
ch.setParent(this)
|
||||||
this.children.push(ch)
|
this.children.push(ch)
|
||||||
this.updateTransform()
|
this.updateTransform()
|
||||||
}
|
}
|
||||||
@ -184,41 +205,18 @@ class MeshInstance extends Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
draw (gl, shader) {
|
draw (gl, shader) {
|
||||||
// Set model transform uniform
|
if (!this.mesh) return super.draw(gl, shader)
|
||||||
super.draw(gl, shader)
|
// Set model transform matrix uniform
|
||||||
|
const transformLocation = shader.getUniformLocation(gl, 'uModelMatrix')
|
||||||
|
gl.uniformMatrix4fv(transformLocation, false, this.transform)
|
||||||
|
|
||||||
// Draw the mesh
|
// Draw the mesh
|
||||||
this.mesh.prepare(gl, shader)
|
this.mesh.prepare(gl, shader)
|
||||||
this.mesh.draw(gl, shader)
|
this.mesh.draw(gl, shader)
|
||||||
|
|
||||||
// Invoke children's draw methods
|
// Draw children
|
||||||
for (let i in this.children) {
|
super.draw(gl, shader)
|
||||||
let child = this.children[i]
|
|
||||||
if (!(child instanceof MeshInstance)) continue
|
|
||||||
child.draw(gl, shader)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A node that contains multiple meshes
|
|
||||||
class MultiMeshInstance extends Node {
|
|
||||||
constructor (meshes, pos) {
|
|
||||||
super(pos)
|
|
||||||
|
|
||||||
for (let i in meshes) {
|
|
||||||
meshes[i].parent = this
|
|
||||||
this.children.push(meshes[i])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
draw (gl, shader) {
|
export { Node, MeshInstance }
|
||||||
// Invoke children's draw methods
|
|
||||||
for (let i in this.children) {
|
|
||||||
let child = this.children[i]
|
|
||||||
if (!(child instanceof MeshInstance)) continue
|
|
||||||
child.draw(gl, shader)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { Node, MeshInstance, MultiMeshInstance }
|
|
||||||
|
124
src/engine/components/planet/index.js
Normal file
124
src/engine/components/planet/index.js
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
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 }
|
96
src/engine/components/terrain/experimental.js
Normal file
96
src/engine/components/terrain/experimental.js
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
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 }
|
@ -60,10 +60,14 @@ class Terrain extends Node {
|
|||||||
|
|
||||||
draw (gl, shader) {
|
draw (gl, shader) {
|
||||||
if (!this.mesh) return
|
if (!this.mesh) return
|
||||||
super.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.prepare(gl, shader)
|
||||||
this.mesh.draw(gl, shader)
|
this.mesh.draw(gl, shader)
|
||||||
|
|
||||||
|
super.draw(gl, shader)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
120
src/engine/gui/index.js
Normal file
120
src/engine/gui/index.js
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
import { clamp } from '../utility'
|
||||||
|
|
||||||
|
class Dim4 {
|
||||||
|
constructor (scX, ofX, scY, ofY) {
|
||||||
|
this.scX = scX
|
||||||
|
this.ofX = ofX
|
||||||
|
this.scY = scY
|
||||||
|
this.ofY = ofY
|
||||||
|
this._update()
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromTable (tbl) {
|
||||||
|
let sx = 0.0
|
||||||
|
let ox = 0.0
|
||||||
|
let sy = 0.0
|
||||||
|
let oy = 0.0
|
||||||
|
if (tbl.length === 2) {
|
||||||
|
let x = tbl[0]
|
||||||
|
let y = tbl[1]
|
||||||
|
|
||||||
|
if (typeof x === 'object' && x.length === 2) {
|
||||||
|
sx = x[0]
|
||||||
|
ox = x[1]
|
||||||
|
} else if (typeof x === 'number') {
|
||||||
|
sx = x
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof y === 'object' && y.length === 2) {
|
||||||
|
sx = y[0]
|
||||||
|
ox = y[1]
|
||||||
|
} else if (typeof y === 'number') {
|
||||||
|
sx = y
|
||||||
|
}
|
||||||
|
} else if (tbl.length === 4) {
|
||||||
|
sx = tbl[0]
|
||||||
|
ox = tbl[1]
|
||||||
|
sy = tbl[2]
|
||||||
|
oy = tbl[3]
|
||||||
|
}
|
||||||
|
return new Dim4(sx, ox, sy, oy)
|
||||||
|
}
|
||||||
|
|
||||||
|
toTable () {
|
||||||
|
return [this.scX, this.ofX, this.scY, this.ofY]
|
||||||
|
}
|
||||||
|
|
||||||
|
_update () {
|
||||||
|
this[0] = this.scX
|
||||||
|
this[1] = this.ofX
|
||||||
|
this[2] = this.scY
|
||||||
|
this[3] = this.ofY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Node2D {
|
||||||
|
constructor (pos, size, rotation) {
|
||||||
|
// Translation
|
||||||
|
this.gpos = [0.0, 0.0]
|
||||||
|
this.pos = pos || new Dim4(0.0, 0.0, 0.0, 0.0)
|
||||||
|
|
||||||
|
// Scaling
|
||||||
|
this.gscale = [1.0, 1.0]
|
||||||
|
this.size = size || new Dim4(0.0, 0.0, 0.0, 0.0)
|
||||||
|
|
||||||
|
// Rotation in degrees
|
||||||
|
this.rotation = rotation || 0.0
|
||||||
|
|
||||||
|
this.parent = null
|
||||||
|
this.children = []
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTransform () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getters
|
||||||
|
get position () {
|
||||||
|
return this.pos
|
||||||
|
}
|
||||||
|
|
||||||
|
get translation () {
|
||||||
|
return this.pos
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw base
|
||||||
|
draw (gl) {
|
||||||
|
// Nothing to draw here, so just draw children
|
||||||
|
for (let i in this.children) {
|
||||||
|
let child = this.children[i]
|
||||||
|
if (!(child instanceof Node2D)) continue
|
||||||
|
child.draw(gl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update (dt) {
|
||||||
|
// Update children
|
||||||
|
for (let i in this.children) {
|
||||||
|
let child = this.children[i]
|
||||||
|
if (!(child instanceof Node2D)) continue
|
||||||
|
child.update(dt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addChild (ch) {
|
||||||
|
// Recursive add in case of table
|
||||||
|
if (ch && typeof ch === 'object' && ch.length) {
|
||||||
|
for (let i in ch) {
|
||||||
|
this.addChild(ch[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(ch instanceof Node2D)) return
|
||||||
|
this.children.push(ch)
|
||||||
|
}
|
||||||
|
|
||||||
|
setParent (p) {
|
||||||
|
if (!(p instanceof Node2D)) return
|
||||||
|
this.parent = p
|
||||||
|
}
|
||||||
|
}
|
0
src/engine/gui/renderer.js
Normal file
0
src/engine/gui/renderer.js
Normal file
@ -17,6 +17,8 @@ class Engine {
|
|||||||
this.frameTime = 0
|
this.frameTime = 0
|
||||||
this.frameCount = 0
|
this.frameCount = 0
|
||||||
this.fps = 0
|
this.fps = 0
|
||||||
|
|
||||||
|
window.gl = this.screen.gl
|
||||||
}
|
}
|
||||||
|
|
||||||
get gl () {
|
get gl () {
|
||||||
|
@ -1,35 +1,36 @@
|
|||||||
|
|
||||||
class Mesh {
|
class Mesh {
|
||||||
|
static loadToBuffer (gl, type, data, drawtype = gl.STATIC_DRAW) {
|
||||||
|
let id = gl.createBuffer()
|
||||||
|
gl.bindBuffer(type, id)
|
||||||
|
gl.bufferData(type, data, drawtype)
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
static construct (gl, vertices, indices, uvs, normals) {
|
static construct (gl, vertices, indices, uvs, normals) {
|
||||||
// VBO for model vertices
|
// VBO for model vertices
|
||||||
let pos = gl.createBuffer()
|
let pos = Mesh.loadToBuffer(gl, gl.ARRAY_BUFFER, new Float32Array(vertices))
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, pos)
|
|
||||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW)
|
|
||||||
|
|
||||||
// Indices Buffer
|
// Indices Buffer
|
||||||
let ebo = gl.createBuffer()
|
let ebo = Mesh.loadToBuffer(gl, gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices))
|
||||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebo)
|
|
||||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW)
|
|
||||||
|
|
||||||
|
// Create the mesh, as we have the most important data already buffered
|
||||||
let mesh = new Mesh()
|
let mesh = new Mesh()
|
||||||
mesh.posBuffer = pos
|
mesh.posBuffer = pos
|
||||||
mesh.ebo = ebo
|
mesh.ebo = ebo
|
||||||
mesh.indices = indices.length
|
mesh.vertices = vertices
|
||||||
|
mesh.indices = indices
|
||||||
|
|
||||||
// VBO for model UVs
|
// VBO for model UVs
|
||||||
if (uvs) {
|
if (uvs) {
|
||||||
let uv = gl.createBuffer()
|
mesh.uv = uvs
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, uv)
|
mesh.uvs = Mesh.loadToBuffer(gl, gl.ARRAY_BUFFER, new Float32Array(uvs))
|
||||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(uvs), gl.STATIC_DRAW)
|
|
||||||
mesh.uvs = uv
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normals buffer
|
// Normals buffer
|
||||||
if (normals) {
|
if (normals) {
|
||||||
let nms = gl.createBuffer()
|
mesh.normals = normals
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, nms)
|
mesh.nms = Mesh.loadToBuffer(gl, gl.ARRAY_BUFFER, new Float32Array(normals))
|
||||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normals), gl.STATIC_DRAW)
|
|
||||||
mesh.nms = nms
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, null)
|
gl.bindBuffer(gl.ARRAY_BUFFER, null)
|
||||||
@ -64,8 +65,31 @@ class Mesh {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
draw (gl, shader) {
|
draw (gl, shader, mode = gl.TRIANGLES) {
|
||||||
gl.drawElements(gl.TRIANGLES, this.indices, gl.UNSIGNED_SHORT, 0)
|
if (this.indices) {
|
||||||
|
gl.drawElements(mode, this.indices.length, gl.UNSIGNED_SHORT, 0)
|
||||||
|
} else {
|
||||||
|
gl.drawArrays(mode, 0, this.vertices.length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure no data floats around in memory
|
||||||
|
dispose (gl) {
|
||||||
|
gl.deleteBuffer(this.posBuffer)
|
||||||
|
gl.deleteBuffer(this.ebo)
|
||||||
|
this.uvs && gl.deleteBuffer(this.uvs)
|
||||||
|
this.nms && gl.deleteBuffer(this.nms)
|
||||||
|
this.vertices = null
|
||||||
|
this.indices = null
|
||||||
|
this.uv = null
|
||||||
|
this.normals = null
|
||||||
|
}
|
||||||
|
|
||||||
|
recreate (gl) {
|
||||||
|
let msh = Mesh.construct(gl, this.vertices, this.indices, this.uv, this.normals)
|
||||||
|
if (!msh) return null
|
||||||
|
this.dispose(gl)
|
||||||
|
return msh
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Mesh } from './'
|
import { Mesh } from './'
|
||||||
import { MeshInstance, MultiMeshInstance } from '../components'
|
import { Node, MeshInstance } from '../components'
|
||||||
import { Material } from './material'
|
import { Material } from './material'
|
||||||
|
|
||||||
import { mat4 } from 'gl-matrix'
|
import { mat4 } from 'gl-matrix'
|
||||||
@ -122,7 +122,7 @@ async function assimp2json (gl, file, dat) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mat4.transpose(transform, transform)
|
mat4.transpose(transform, transform)
|
||||||
meshInstance._rootTransform = transform
|
meshInstance.worldTransform = transform
|
||||||
meshInstance.updateTransform()
|
meshInstance.updateTransform()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,9 +135,10 @@ async function assimp2json (gl, file, dat) {
|
|||||||
|
|
||||||
let returnType
|
let returnType
|
||||||
if (finished.length > 1) {
|
if (finished.length > 1) {
|
||||||
returnType = new MultiMeshInstance(finished)
|
returnType = new Node()
|
||||||
|
returnType.addChild(finished)
|
||||||
mat4.transpose(lastTransform, lastTransform)
|
mat4.transpose(lastTransform, lastTransform)
|
||||||
returnType._rootTransform = lastTransform
|
returnType.worldTransform = lastTransform
|
||||||
returnType.updateTransform()
|
returnType.updateTransform()
|
||||||
} else {
|
} else {
|
||||||
returnType = finished[0]
|
returnType = finished[0]
|
||||||
@ -155,7 +156,12 @@ async function loadMesh (gl, file) {
|
|||||||
file = '/assets/models/' + file + '.json'
|
file = '/assets/models/' + file + '.json'
|
||||||
|
|
||||||
// Ensure each mesh file is loaded only once
|
// Ensure each mesh file is loaded only once
|
||||||
if (meshCache[file]) return meshCache[file].length > 1 ? new MultiMeshInstance(meshCache[file]) : meshCache[file][0]
|
if (meshCache[file]) {
|
||||||
|
if (meshCache[file].length <= 1) return meshCache[file][0]
|
||||||
|
let cached = new Node()
|
||||||
|
cached.addChild(meshCache[file])
|
||||||
|
return cached
|
||||||
|
}
|
||||||
|
|
||||||
let dat = await Resource.GET({ type: 'json', url: file })
|
let dat = await Resource.GET({ type: 'json', url: file })
|
||||||
|
|
||||||
|
@ -40,8 +40,8 @@ class Material {
|
|||||||
for (let i in this.textures) {
|
for (let i in this.textures) {
|
||||||
let tex = this.textures[i]
|
let tex = this.textures[i]
|
||||||
if (tex && tex instanceof Texture) {
|
if (tex && tex instanceof Texture) {
|
||||||
gl.bindTexture(tex.type, tex.id)
|
|
||||||
gl.activeTexture(gl.TEXTURE0 + parseInt(i))
|
gl.activeTexture(gl.TEXTURE0 + parseInt(i))
|
||||||
|
gl.bindTexture(tex.type, tex.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
65
src/engine/utility.js
Normal file
65
src/engine/utility.js
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { vec3 } from 'gl-matrix'
|
||||||
|
|
||||||
|
export function clamp (num, min, max) {
|
||||||
|
return Math.min(Math.max(num, min), max)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addv3 (one, two) {
|
||||||
|
if (one.length !== 3) return null
|
||||||
|
if (typeof two !== 'object') {
|
||||||
|
return [
|
||||||
|
one[0] + two, one[1] + two, one[2] + two
|
||||||
|
]
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
one[0] + two[0], one[1] + two[1], one[2] + two[2]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export function subv3 (one, two) {
|
||||||
|
if (one.length !== 3) return null
|
||||||
|
if (typeof two !== 'object') {
|
||||||
|
return [
|
||||||
|
one[0] - two, one[1] - two, one[2] - two
|
||||||
|
]
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
one[0] - two[0], one[1] - two[1], one[2] - two[2]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mulv3 (one, two) {
|
||||||
|
if (one.length !== 3) return null
|
||||||
|
if (typeof two !== 'object') {
|
||||||
|
return [
|
||||||
|
one[0] * two, one[1] * two, one[2] * two
|
||||||
|
]
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
one[0] * two[0], one[1] * two[1], one[2] * two[2]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export function divv3 (one, two) {
|
||||||
|
if (one.length !== 3) return null
|
||||||
|
if (typeof two !== 'object') {
|
||||||
|
return [
|
||||||
|
one[0] / two, one[1] / two, one[2] / two
|
||||||
|
]
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
one[0] / two[0], one[1] / two[1], one[2] / two[2]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalv3 (vec) {
|
||||||
|
let res = []
|
||||||
|
vec3.normalize(res, vec)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
export function crossv3 (vec1, vec2) {
|
||||||
|
let res = []
|
||||||
|
vec3.cross(res, vec1, vec2)
|
||||||
|
return res
|
||||||
|
}
|
14
src/index.js
14
src/index.js
@ -7,10 +7,12 @@ import { Terrain } from './engine/components/terrain'
|
|||||||
import { SimplexHeightMap } from './engine/components/terrain/heightmap'
|
import { SimplexHeightMap } from './engine/components/terrain/heightmap'
|
||||||
import { Material } from './engine/mesh/material'
|
import { Material } from './engine/mesh/material'
|
||||||
|
|
||||||
|
import { CubePlanet } from './engine/components/planet'
|
||||||
|
|
||||||
let game = new Engine()
|
let game = new Engine()
|
||||||
let env = new Environment()
|
let env = new Environment()
|
||||||
|
|
||||||
let t = 0
|
// let t = 0
|
||||||
async function pipeline () {
|
async function pipeline () {
|
||||||
let entity = await loadMesh(game.gl, 'test')
|
let entity = await loadMesh(game.gl, 'test')
|
||||||
let shader = await game.shaders.createShaderFromFiles(game.gl, 'basic', false)
|
let shader = await game.shaders.createShaderFromFiles(game.gl, 'basic', false)
|
||||||
@ -32,9 +34,12 @@ async function pipeline () {
|
|||||||
terrain.setMaterial(material)
|
terrain.setMaterial(material)
|
||||||
|
|
||||||
// Create and initialize the camera
|
// Create and initialize the camera
|
||||||
let cam = new Camera([0.0, 1.0, 2.0])
|
let cam = new Camera([-100.0, 1.0, 0.0])
|
||||||
cam.updateProjection(game.gl)
|
cam.updateProjection(game.gl)
|
||||||
|
|
||||||
|
// Planet test
|
||||||
|
let planet = new CubePlanet([0.0, 0.0, 0.0], 16, 32)
|
||||||
|
|
||||||
// Update function for camera
|
// Update function for camera
|
||||||
game.addUpdateFunction(function (dt) {
|
game.addUpdateFunction(function (dt) {
|
||||||
if (game.input.isDown('w')) {
|
if (game.input.isDown('w')) {
|
||||||
@ -54,8 +59,8 @@ async function pipeline () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TESTING: Move model forward
|
// TESTING: Move model forward
|
||||||
t = t + 0.1
|
// t = t + 0.1
|
||||||
entity.setPosition([t, 0.0, 0.0])
|
// entity.setPosition([t, 0.0, 0.0])
|
||||||
})
|
})
|
||||||
|
|
||||||
// Render function for the triangle
|
// Render function for the triangle
|
||||||
@ -63,6 +68,7 @@ async function pipeline () {
|
|||||||
shader.use(gl)
|
shader.use(gl)
|
||||||
cam.draw(gl, shader)
|
cam.draw(gl, shader)
|
||||||
entity.draw(gl, shader)
|
entity.draw(gl, shader)
|
||||||
|
planet.draw(gl, shader)
|
||||||
|
|
||||||
// Use terrain shader
|
// Use terrain shader
|
||||||
terrainShader.use(gl)
|
terrainShader.use(gl)
|
||||||
|
Loading…
Reference in New Issue
Block a user