|
<!doctype html>
<html>
<head>
<title>.thrixl</title>
<meta charset="utf-8" />
<style>
canvas {
position: absolute;
top: 0;
left: 0;
}
</style>
</head>
<body>
<script src="three.js"></script>
<script src="three.flycontrols.js"></script>
<script src="geometry.js"></script>
<script>
window.trixl = {};
trixl.chunks = {};
trixl.chunkSize = 32;
trixl.bits = 5;
trixl.toChunk = function(pos) {
var b = trixl.bits;
return [pos[1] >> b, pos[2] >> b, pos[3] >> b];
}
trixl.toIndex = function(pos) {
var b = trixl.bits;
var mask = (1 << b) - 1;
return (pos[0] & mask) + ((pos[1] & mask) << b) + ((pos[2] & mask) << b * 2);
}
trixl.set = function(pos, data) {
var chunkIndex = trixl.toChunk(pos).join(',');
var chunk = trixl.chunks[chunkIndex];
if (!chunk) {
chunk = trixl.chunks[chunkIndex] = { voxels: [] };
}
data.pos = pos;
chunk.voxels[trixl.toIndex(pos)] = data;
chunk.dirty = true;
}
trixl.get = function(pos) {
var chunk = trixl.chunks[trixl.toChunk(pos).join(',')];
return chunk ? (chunk.voxels[trixl.toIndex(pos)] || null) : null;
}
var cube = new THREE.CubeGeometry(1, 1, 1);
trixl.toGeometry = function(chunk) {
var chunkGeometry = new THREE.Object3D();
for (var i = 0; i < chunk.voxels.length; i++) {
var voxel = chunk.voxels[i];
if (!voxel) {
continue;
}
var mesh = new THREE.Mesh(cube, new THREE.MeshBasicMaterial({color: voxel.color}));
mesh.position.x = voxel.pos[0];
mesh.position.y = voxel.pos[1];
mesh.position.z = voxel.pos[2];
mesh.frustumCulled = false;
mesh.matrixAutoUpdate = false;
mesh.updateMatrix();
chunkGeometry.add(mesh);
}
return chunkGeometry;
}
trixl.toBufferGeometry = function(chunk) {
var n = 0;
for (var i = 0; i < chunk.voxels.length; i++) {
n += chunk.voxels[i] ? 1 : 0;
}
var chunkGeometry = new THREE.BufferGeometry();
// 6 sides * 2 triangles
var m = 6 * 2;
var vs = n * m * 3 * 3;
chunkGeometry.addAttribute('position', Float32Array, vs, 3);
chunkGeometry.addAttribute('normal', Float32Array, vs, 3);
chunkGeometry.addAttribute('color', Float32Array, vs, 3);
var positions = chunkGeometry.attributes.position.array;
var normals = chunkGeometry.attributes.normal.array;
var colors = chunkGeometry.attributes.color.array;
var cube = geometry.cube();
cube.normals = geometry.cube.normals();
var c = -1;
for (var i = 0; i < chunk.voxels.length; i++) {
var voxel = chunk.voxels[i];
if (!voxel) continue;
c += 1;
var x = voxel.pos[0], y = voxel.pos[1], z = voxel.pos[2];
for (var j = 0; j < cube.length; j += 3) {
positions[c * m * 9 + j + 0] = x + cube[j + 0]
positions[c * m * 9 + j + 1] = y + cube[j + 1]
positions[c * m * 9 + j + 2] = z + cube[j + 2]
normals[c * m * 9 + j + 0] = cube.normals[j + 0];
normals[c * m * 9 + j + 1] = cube.normals[j + 1];
normals[c * m * 9 + j + 2] = cube.normals[j + 2];
colors[c * m * 9 + j + 0] = voxel.color[0];
colors[c * m * 9 + j + 1] = voxel.color[1];
colors[c * m * 9 + j + 2] = voxel.color[2];
}
}
var material = new THREE.MeshLambertMaterial({
vertexColors: true,
side: THREE.DoubleSide
});
return new THREE.Mesh(chunkGeometry, material);
}
trixl.generate = {}
trixl.generate.many = function(n, lo, hi) {
for (var i = 0; i < n; i++) {
var pos = [
lo + Math.random() * (hi - lo),
lo + Math.random() * (hi - lo),
lo + Math.random() * (hi - lo)
];
var color = [Math.random(), Math.random(), Math.random()];
trixl.set(pos, {color: color});
}
}
var scene = new THREE.Scene();
var aspect = window.innerWidth / window.innerHeight;
var camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 1000);
camera.position.z = 10;
var controls = new THREE.FlyControls(camera);
controls.movementSpeed = 5.0;
controls.rollSpeed = 0.75;
var ambient = new THREE.AmbientLight(0x606060);
scene.add(ambient);
var light = new THREE.PointLight(0xffffff, 1, 10000);
scene.add(light);
var renderer = new THREE.WebGLRenderer();
renderer.physicallyBasedShading = true;
renderer.sortObjects = false;
renderer.setClearColor(0xffffff);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var group = new THREE.Object3D();
group.frustumCulled = false;
scene.add(group);
var clock = new THREE.Clock();
var render = function() {
requestAnimationFrame(render);
for (var key in trixl.chunks) {
var chunk = trixl.chunks[key];
if (chunk.dirty) {
group.remove(chunk.geometry);
chunk.geometry = trixl.toBufferGeometry(chunk);
chunk.dirty = false;
group.add(chunk.geometry);
}
}
controls.update(clock.getDelta());
light.position.copy(camera.position);
light.rotation.copy(camera.rotation);
renderer.render(scene, camera);
}
render();
trixl.generate.many(100, -25, 25);
</script>
</body>
</html>
|