Three.js - Voxel Geometry - Textures
by Lazaro Contreras
HTML
<canvas id="c"></canvas>
CSS
body {
margin: 0;
}
#c {
width: 100vw;
height: 100vh;
display: block;
}
JavaScript
// Three.js - Voxel Geometry - Textures
// from https://threejsfundamentals.org/threejs/threejs-voxel-geometry-culled-faces-with-textures.html
import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r110/build/three.module.js';
import {OrbitControls} from 'https://threejsfundamentals.org/threejs/resources/threejs/r110/examples/jsm/controls/OrbitControls.js';
class VoxelWorld {
constructor(options) {
this.cellSizeX = options.cellSizeX;
this.cellSizeY = options.cellSizeY;
this.cellSizeZ = options.cellSizeZ;
this.tileSize = options.tileSize;
this.tileTextureWidth = options.tileTextureWidth;
this.tileTextureHeight = options.tileTextureHeight;
const {cellSizeX, cellSizeY, cellSizeZ} = this;
this.cellSliceSize = cellSizeX * cellSizeY;
this.cell = new Uint8Array(cellSizeX * cellSizeY * cellSizeZ);
}
computeVoxelOffset(x, y, z) {
const {cellSizeX, cellSizeY, cellSizeZ, cellSliceSize} = this;
const voxelX = THREE.Math.euclideanModulo(x, cellSizeX) | 0;
const voxelY = THREE.Math.euclideanModulo(y, cellSizeY) | 0;
const voxelZ = THREE.Math.euclideanModulo(z, cellSizeZ) | 0;
return voxelY * cellSliceSize +
voxelZ * cellSizeZ +
voxelX;
}
getCellForVoxel(x, y, z) {
const {cellSizeX, cellSizeY, cellSizeZ} = this;
const cellX = Math.floor(x / cellSizeX);
const cellY = Math.floor(y / cellSizeY);
const cellZ = Math.floor(z / cellSizeZ);
if (cellX !== 0 || cellY !== 0 || cellZ !== 0) {
return null;
}
return this.cell;
}
setVoxel(x, y, z, v) {
const cell = this.getCellForVoxel(x, y, z);
if (!cell) {
return; // TODO: add a new cell?
}
const voxelOffset = this.computeVoxelOffset(x, y, z);
cell[voxelOffset] = v;
}
getVoxel(x, y, z) {
const cell = this.getCellForVoxel(x, y, z);
if (!cell) {
return 0;
}
const voxelOffset = this.computeVoxelOffset(x, y, z);
return...