broken transform
This commit is contained in:
parent
129e4b661a
commit
4ec5c6a045
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
/node_modules/
|
||||
/dist/
|
||||
/package-lock.json
|
||||
/**/dna.txt
|
||||
|
261696
assets/models/test.json
261696
assets/models/test.json
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
import { Node } from './components'
|
||||
import { glMatrix, mat4, vec2, vec3 } from 'gl-matrix'
|
||||
|
||||
const SPEED = 100.0
|
||||
const SPEED = 10.0
|
||||
const SENSITIVTY = 100.0
|
||||
const FOV = 45.0
|
||||
const ZNEAR = 0.1
|
||||
|
@ -61,6 +61,11 @@ class Node {
|
||||
updateTransform () {
|
||||
let matrix = mat4.create()
|
||||
|
||||
// Add parent node's transform
|
||||
if (this.parent) {
|
||||
mat4.mul(matrix, matrix, this.parent.transform)
|
||||
}
|
||||
|
||||
// Set translation
|
||||
mat4.translate(matrix, matrix, this.pos)
|
||||
|
||||
@ -80,11 +85,6 @@ class Node {
|
||||
// Set scale
|
||||
mat4.scale(matrix, matrix, this.scale)
|
||||
|
||||
// Add parent node's transform
|
||||
if (this.parent) {
|
||||
mat4.mul(matrix, this.parent.transform, matrix)
|
||||
}
|
||||
|
||||
// Set the matrix
|
||||
this.transform = matrix
|
||||
|
||||
@ -102,11 +102,9 @@ class Node {
|
||||
let rotation = vec3.create()
|
||||
let scale = vec3.create()
|
||||
|
||||
mat4.transpose(transform, transform)
|
||||
|
||||
mat4.getTranslation(translation, transform)
|
||||
mat4.getScaling(scale, transform)
|
||||
mat4.getRotation(quaternion, transform)
|
||||
mat4.getTranslation(translation, transform)
|
||||
|
||||
quat.getEuler(rotation, quaternion)
|
||||
|
||||
@ -195,127 +193,6 @@ class MeshInstance extends Node {
|
||||
this.mesh = mesh
|
||||
}
|
||||
|
||||
static async loadFile (gl, file, pos) {
|
||||
file = '/assets/models/' + file + '.json'
|
||||
|
||||
// Ensure each mesh file is loaded only once
|
||||
if (meshCache[file]) return meshCache[file].length > 1 ? meshCache[file] : meshCache[file][0]
|
||||
|
||||
let dat = await Resource.GET({ type: 'json', url: file })
|
||||
if (!dat.meshes) throw new Error('No meshes defined in file.')
|
||||
|
||||
let cleaned = []
|
||||
let materials = []
|
||||
for (let mi in dat.meshes) {
|
||||
let mesh = dat.meshes[mi]
|
||||
let material
|
||||
|
||||
if (mesh.materialindex != null && dat.materials && dat.materials.length) {
|
||||
// Ensure we don't re-create materials with the same index
|
||||
if (materials[mesh.materialindex]) {
|
||||
material = materials[mesh.materialindex]
|
||||
} else {
|
||||
// Load a new material
|
||||
material = new Material()
|
||||
let matdata = dat.materials[mesh.materialindex].properties
|
||||
|
||||
// Parse material information
|
||||
for (let pi in matdata) {
|
||||
let property = matdata[pi]
|
||||
if (!property || !property.key) continue
|
||||
if (property.key === '?mat.name') material.name = property.value
|
||||
else if (property.key.indexOf('$clr.') === 0) {
|
||||
let dproperty = property.key.substr(5)
|
||||
switch (dproperty) {
|
||||
case 'specular':
|
||||
case 'diffuse':
|
||||
case 'shininess':
|
||||
case 'ambient':
|
||||
case 'reflective':
|
||||
material[dproperty] = property.value
|
||||
break
|
||||
}
|
||||
} else if (property.key.indexOf('$tex.file') === 0) {
|
||||
if (!material.textures) {
|
||||
material.textures = []
|
||||
}
|
||||
|
||||
material.textures.push(property.value)
|
||||
}
|
||||
}
|
||||
|
||||
materials[mesh.materialindex] = material
|
||||
}
|
||||
}
|
||||
|
||||
cleaned.push({
|
||||
vertices: mesh.vertices,
|
||||
indices: [].concat.apply([], mesh.faces),
|
||||
uv: mesh.texturecoords ? mesh.texturecoords[0] : null,
|
||||
normals: mesh.normals ? mesh.normals : null,
|
||||
material
|
||||
})
|
||||
}
|
||||
|
||||
// Load everything
|
||||
let loadComplete = []
|
||||
for (let i in cleaned) {
|
||||
let meshdata = cleaned[i]
|
||||
let mesh = Mesh.construct(gl, meshdata.vertices, meshdata.indices,
|
||||
meshdata.uv, meshdata.normals)
|
||||
|
||||
// Initialize the material's texture if present
|
||||
if (meshdata.material) {
|
||||
mesh.material = meshdata.material
|
||||
|
||||
// Ensure all textures get loaded before finishing
|
||||
if (meshdata.material.textures) {
|
||||
await meshdata.material.loadTextures(gl)
|
||||
}
|
||||
}
|
||||
|
||||
loadComplete.push(mesh)
|
||||
}
|
||||
|
||||
// Now, we need to give the meshes the appropriate parents and transforms.
|
||||
let finished = []
|
||||
function setChildren (parent, chMeshes) {
|
||||
let meshIndex = chMeshes.meshes[0]
|
||||
let mesh = loadComplete[meshIndex]
|
||||
let meshInstance = new MeshInstance(mesh, parent == null ? pos : null)
|
||||
|
||||
meshInstance.mesh = mesh
|
||||
|
||||
if (chMeshes.children) {
|
||||
for (let i in chMeshes.children) {
|
||||
if (!chMeshes.children[i].meshes) continue
|
||||
setChildren(meshInstance, chMeshes.children[i])
|
||||
}
|
||||
}
|
||||
|
||||
meshInstance.name = chMeshes.name
|
||||
|
||||
if (parent == null) {
|
||||
finished.push(meshInstance)
|
||||
} else {
|
||||
parent.children.push(meshInstance)
|
||||
meshInstance.parent = parent
|
||||
meshInstance.setTransformation(chMeshes.transformation)
|
||||
}
|
||||
}
|
||||
|
||||
let rootchildren = dat.rootnode.children
|
||||
for (let j in rootchildren) {
|
||||
if (!rootchildren[j].meshes) continue
|
||||
setChildren(null, rootchildren[j])
|
||||
}
|
||||
|
||||
// Cache the mesh
|
||||
meshCache[file] = finished
|
||||
|
||||
return finished.length > 1 ? finished : finished[0]
|
||||
}
|
||||
|
||||
draw (gl, shader) {
|
||||
// Set model transform uniform
|
||||
super.draw(gl, shader)
|
||||
@ -333,4 +210,24 @@ class MeshInstance extends Node {
|
||||
}
|
||||
}
|
||||
|
||||
export { Node, MeshInstance }
|
||||
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) {
|
||||
// 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 }
|
||||
|
167
src/engine/mesh/loader.js
Normal file
167
src/engine/mesh/loader.js
Normal file
@ -0,0 +1,167 @@
|
||||
import { Mesh } from './'
|
||||
import { MeshInstance, MultiMeshInstance } from '../components'
|
||||
import { Material } from './material'
|
||||
|
||||
import { mat4 } from 'gl-matrix'
|
||||
|
||||
import Resource from '../resource'
|
||||
|
||||
let meshCache = {}
|
||||
|
||||
// Parse an assimp2json formatted mesh file
|
||||
// Supports multiple geometries
|
||||
async function assimp2json (gl, file, dat, pos) {
|
||||
let cleaned = []
|
||||
let materials = []
|
||||
for (let mi in dat.meshes) {
|
||||
let mesh = dat.meshes[mi]
|
||||
let material
|
||||
|
||||
if (mesh.materialindex != null && dat.materials && dat.materials.length) {
|
||||
// Ensure we don't re-create materials with the same index
|
||||
if (materials[mesh.materialindex]) {
|
||||
material = materials[mesh.materialindex]
|
||||
} else {
|
||||
// Load a new material
|
||||
material = new Material()
|
||||
let matdata = dat.materials[mesh.materialindex].properties
|
||||
|
||||
// Parse material information
|
||||
for (let pi in matdata) {
|
||||
let property = matdata[pi]
|
||||
if (!property || !property.key) continue
|
||||
if (property.key === '?mat.name') material.name = property.value
|
||||
else if (property.key.indexOf('$clr.') === 0) {
|
||||
let dproperty = property.key.substr(5)
|
||||
switch (dproperty) {
|
||||
case 'specular':
|
||||
case 'diffuse':
|
||||
case 'shininess':
|
||||
case 'ambient':
|
||||
case 'reflective':
|
||||
material[dproperty] = property.value
|
||||
break
|
||||
}
|
||||
} else if (property.key.indexOf('$tex.file') === 0) {
|
||||
if (!material.textures) {
|
||||
material.textures = []
|
||||
}
|
||||
|
||||
material.textures.push(property.value)
|
||||
}
|
||||
}
|
||||
|
||||
materials[mesh.materialindex] = material
|
||||
}
|
||||
}
|
||||
|
||||
cleaned.push({
|
||||
vertices: mesh.vertices,
|
||||
indices: [].concat.apply([], mesh.faces),
|
||||
uv: mesh.texturecoords ? mesh.texturecoords[0] : null,
|
||||
normals: mesh.normals ? mesh.normals : null,
|
||||
material
|
||||
})
|
||||
}
|
||||
|
||||
// Load everything
|
||||
let loadComplete = []
|
||||
for (let i in cleaned) {
|
||||
let meshdata = cleaned[i]
|
||||
let mesh = Mesh.construct(gl, meshdata.vertices, meshdata.indices,
|
||||
meshdata.uv, meshdata.normals)
|
||||
|
||||
// Initialize the material's texture if present
|
||||
if (meshdata.material) {
|
||||
mesh.material = meshdata.material
|
||||
|
||||
// Ensure all textures get loaded before finishing
|
||||
if (meshdata.material.textures) {
|
||||
await meshdata.material.loadTextures(gl)
|
||||
}
|
||||
}
|
||||
|
||||
loadComplete.push(mesh)
|
||||
}
|
||||
|
||||
let finished = []
|
||||
function setChildren (parent, chMeshes, last) {
|
||||
if (!chMeshes.meshes) {
|
||||
if (chMeshes.children) {
|
||||
for (let j in chMeshes.children) {
|
||||
setChildren(null, chMeshes.children[j], chMeshes)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Transpose the mesh's transform
|
||||
let transform = chMeshes.transformation
|
||||
|
||||
let meshIndex = chMeshes.meshes[0]
|
||||
let mesh = loadComplete[meshIndex]
|
||||
let meshInstance = new MeshInstance(mesh, parent == null ? pos : null)
|
||||
|
||||
meshInstance.mesh = mesh
|
||||
|
||||
if (chMeshes.children) {
|
||||
for (let i in chMeshes.children) {
|
||||
if (!chMeshes.children[i].meshes) continue
|
||||
setChildren(meshInstance, chMeshes.children[i], chMeshes)
|
||||
}
|
||||
}
|
||||
|
||||
meshInstance.name = chMeshes.name
|
||||
|
||||
if (parent == null) {
|
||||
// Multiply the last meshless node's transform in order to preserve it
|
||||
|
||||
finished.push(meshInstance)
|
||||
} else {
|
||||
parent.children.push(meshInstance)
|
||||
meshInstance.parent = parent
|
||||
}
|
||||
|
||||
meshInstance.setTransformation(transform)
|
||||
}
|
||||
|
||||
setChildren(null, dat.rootnode)
|
||||
|
||||
if (!finished.length) throw new Error('Failed to build mesh.')
|
||||
|
||||
// Cache the mesh
|
||||
meshCache[file] = finished
|
||||
|
||||
let returnType
|
||||
if (finished.length > 1) {
|
||||
returnType = new MultiMeshInstance(finished)
|
||||
} else {
|
||||
returnType = finished[0]
|
||||
}
|
||||
|
||||
return returnType
|
||||
}
|
||||
|
||||
// Parse a collada mesh
|
||||
async function collada (gl, file, dat, pos) {
|
||||
// TODO...
|
||||
}
|
||||
|
||||
async function loadMesh (gl, file, pos) {
|
||||
file = '/assets/models/' + file + '.json'
|
||||
|
||||
// Ensure each mesh file is loaded only once
|
||||
if (meshCache[file]) return meshCache[file].length > 1 ? new MultiMeshInstance(meshCache[file], pos) : meshCache[file][0]
|
||||
|
||||
let dat = await Resource.GET({ type: 'json', url: file })
|
||||
|
||||
// Recognize a assimp2json file format
|
||||
if (dat['__metadata__'] && dat['__metadata__'].format === 'assimp2json') {
|
||||
if (!dat.meshes) throw new Error('No geometries found in file ' + file)
|
||||
return assimp2json(gl, file, dat, pos)
|
||||
}
|
||||
|
||||
throw new Error('Unsupported mesh format.')
|
||||
}
|
||||
|
||||
export default loadMesh
|
10
src/index.js
10
src/index.js
@ -1,20 +1,26 @@
|
||||
import Engine from './engine'
|
||||
import Camera from './engine/camera'
|
||||
import { MeshInstance } from './engine/components'
|
||||
import loadMesh from './engine/mesh/loader'
|
||||
|
||||
import { Environment } from './engine/environment'
|
||||
import { Terrain } from './engine/components/terrain'
|
||||
import { SimplexHeightMap } from './engine/components/terrain/heightmap'
|
||||
import { Material } from './engine/mesh/material'
|
||||
|
||||
// import { glMatrix } from 'gl-matrix'
|
||||
|
||||
let game = new Engine()
|
||||
let env = new Environment()
|
||||
|
||||
async function pipeline () {
|
||||
let entity = await MeshInstance.loadFile(game.gl, 'test', [0.0, 0.0, 0.0])
|
||||
let entity = await loadMesh(game.gl, 'test', [0.0, 0.0, 0.0])
|
||||
let shader = await game.shaders.createShaderFromFiles(game.gl, 'basic', false)
|
||||
let terrainShader = await game.shaders.createShaderFromFiles(game.gl, 'terrain', false)
|
||||
|
||||
console.log(entity)
|
||||
|
||||
// entity.setRotation([glMatrix.toRadian(-90), 0.0, 0.0])
|
||||
|
||||
// Create a height map based on OpenSimplex noise
|
||||
let hmap = new SimplexHeightMap(1, 1, 256, 50)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user