Created
January 18, 2019 23:34
-
-
Save bnolan/7cc954de84ae0b88646899db5b6d1229 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// budo boop.ts --live --dir . -- -p [ tsify --target es6 ] | |
import * as B from 'babylonjs' | |
import * as parseMagicaVoxel from 'parse-magica-voxel' | |
import * as createAOMesh from 'ao-mesher' | |
import * as fill from 'ndarray-fill' | |
import * as ndarray from 'ndarray' | |
let canvas : any = document.createElement( "canvas" ); | |
document.body.appendChild(canvas) | |
document.documentElement.style.cssText = | |
document.body.style.cssText = | |
'margin: 0; padding: 0; height: 100%' | |
canvas.style.cssText = 'width: 100%; height: 100%' | |
let engine = new B.Engine( canvas, true ); | |
let scene = new B.Scene( engine ); | |
// | |
// Camera | |
// | |
let camera = new B.UniversalCamera('camera1', new B.Vector3(0, 2, 2), scene); | |
camera.setTarget( BABYLON.Vector3.Zero() ); | |
camera.attachControl( canvas, true ); | |
// | |
// Lighting | |
// | |
let light1 = new B.HemisphericLight('light1', new B.Vector3(0,5,0), scene); | |
light1.intensity = 0.5 | |
var light2 = new BABYLON.DirectionalLight("dir01", new BABYLON.Vector3(-10, -20, -10), scene) | |
var shadowGenerator = new BABYLON.ShadowGenerator(2048, light2) | |
shadowGenerator.usePoissonSampling = true; | |
let mat = new B.StandardMaterial( "mat", scene ); | |
mat.diffuseColor = new B.Color3( 0.8, 0, 0 ); | |
// sphere.material = mat; | |
engine.runRenderLoop( () => { | |
scene.render(); | |
}) | |
window.addEventListener( 'resize', () => { | |
engine.resize(); | |
}) | |
fetch('./lab-02.vox') | |
.then(r => r.arrayBuffer()) | |
.then(buffer => { | |
let parsed = parseMagicaVoxel(buffer) | |
console.log(parsed) | |
let size = parsed.SIZE | |
// Oversize because ao-mesher doesn't create faces on the boundaries | |
size.x += 2 | |
size.y += 2 | |
size.z += 2 | |
// Construct an ndarray | |
let field = ndarray(new Uint16Array(size.x * size.y * size.z), [size.x, size.y, size.z]) | |
fill(field, (x, y, z) => 0) | |
parsed.XYZI.forEach(row => { | |
let { x, y, z, c } = row | |
field.set(x, y, z, c + (1 << 15)) | |
}) | |
const vertData = createAOMesh(field) | |
// Convert the vertData format into a babylon.js Mesh | |
let face = 0 | |
let i = 0 | |
let s = 1 | |
const hue = 0 | |
const positions = [] | |
const indices = [] | |
const normals = [] | |
const colors = [] | |
// Identity function, use these to nudge the mesh as needed | |
const fx = x => x | |
const fy = y => y | |
const fz = z => z | |
while (i < vertData.length) { | |
const textureIndex = vertData[i + 7] | |
// const color = new B.Color3(1, 1, 0) | |
var a = new B.Vector3(vertData[i + 0], vertData[i + 1], vertData[i + 2]) | |
positions.push(fx(vertData[i + 0] * s)) | |
positions.push(fy(vertData[i + 1] * s)) | |
positions.push(fz(vertData[i + 2] * s)) | |
i += 8 | |
var b = new B.Vector3(vertData[i + 0], vertData[i + 1], vertData[i + 2]) | |
positions.push(fx(vertData[i + 0] * s)) | |
positions.push(fy(vertData[i + 1] * s)) | |
positions.push(fz(vertData[i + 2] * s)) | |
i += 8 | |
var c = new B.Vector3(vertData[i + 0], vertData[i + 1], vertData[i + 2]) | |
positions.push(fx(vertData[i + 0] * s)) | |
positions.push(fy(vertData[i + 1] * s)) | |
positions.push(fz(vertData[i + 2] * s)) | |
i += 8 | |
// Face index | |
indices.push(face + 0, face + 2, face + 1) | |
const intensity = 0.5 | |
const offset = 0.4 | |
let color = new B.Color3(parsed.RGBA[textureIndex].r / 255, parsed.RGBA[textureIndex].g / 255, parsed.RGBA[textureIndex].b / 255) | |
colors.push(color.r * (vertData[i - 24 + 3] / 255 * intensity + offset)) | |
colors.push(color.g * (vertData[i - 24 + 3] / 255 * intensity + offset)) | |
colors.push(color.b * (vertData[i - 24 + 3] / 255 * intensity + offset)) | |
colors.push(1) | |
colors.push(color.r * (vertData[i - 16 + 3] / 255 * intensity + offset)) | |
colors.push(color.g * (vertData[i - 16 + 3] / 255 * intensity + offset)) | |
colors.push(color.b * (vertData[i - 16 + 3] / 255 * intensity + offset)) | |
colors.push(1) | |
colors.push(color.r * (vertData[i - 8 + 3] / 255 * intensity + offset)) | |
colors.push(color.g * (vertData[i - 8 + 3] / 255 * intensity + offset)) | |
colors.push(color.b * (vertData[i - 8 + 3] / 255 * intensity + offset)) | |
colors.push(1) | |
face += 3 | |
} | |
// Create transferrable objects | |
let positionsArray = new Float32Array(positions) | |
let indicesArray = new Float32Array(indices) | |
let colorsArray = new Float32Array(colors) | |
let mesh = new B.Mesh('voxel-mesh', scene) | |
mesh.scaling.set(0.25, 0.25, 0.25) | |
mesh.rotation.set(-Math.PI / 2, 0, 0) | |
mesh.position.set(-8, -2, 8) | |
mesh.receiveShadows = true | |
var mat = new BABYLON.StandardMaterial('voxel-material', scene); | |
mat.specularColor = new BABYLON.Color3(0, 0, 0) | |
mesh.material = mat | |
var vertexData = new B.VertexData() | |
B.VertexData.ComputeNormals(positions, indices, normals) | |
// Assign positions, indices and normals to vertexData | |
vertexData.positions = positions | |
vertexData.indices = indices | |
vertexData.normals = normals | |
vertexData.colors = colors | |
// Apply vertexData to custom mesh | |
vertexData.applyToMesh(mesh) | |
shadowGenerator.getShadowMap().renderList.push(mesh) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment