Skip to content

Instantly share code, notes, and snippets.

@bnolan
Created January 18, 2019 23:34
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bnolan/7cc954de84ae0b88646899db5b6d1229 to your computer and use it in GitHub Desktop.
Save bnolan/7cc954de84ae0b88646899db5b6d1229 to your computer and use it in GitHub Desktop.
// 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