refactor project structure, implement tessellator
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
window.Chunk = class {
|
||||
|
||||
constructor(world, x, z) {
|
||||
this.world = world;
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
|
||||
this.group = new THREE.Object3D();
|
||||
|
||||
// Initialize sections
|
||||
this.sections = [];
|
||||
for (let y = 0; y < 16; y++) {
|
||||
let section = new ChunkSection(world, x, y, z);
|
||||
|
||||
this.sections[y] = section;
|
||||
this.group.add(section.group);
|
||||
}
|
||||
}
|
||||
|
||||
getSection(y) {
|
||||
return this.sections[y];
|
||||
}
|
||||
|
||||
rebuild(renderer) {
|
||||
for (let y = 0; y < this.sections.length; y++) {
|
||||
this.sections[y].rebuild(renderer);
|
||||
}
|
||||
}
|
||||
|
||||
queueForRebuild() {
|
||||
for (let y = 0; y < this.sections.length; y++) {
|
||||
this.sections[y].queueForRebuild();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
window.ChunkSection = class {
|
||||
|
||||
static get SIZE() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
constructor(world, x, y, z) {
|
||||
this.world = world;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
|
||||
this.group = new THREE.Object3D();
|
||||
this.dirty = true;
|
||||
|
||||
this.blocks = [];
|
||||
for (let x = 0; x < ChunkSection.SIZE; x++) {
|
||||
for (let y = 0; y < ChunkSection.SIZE; y++) {
|
||||
for (let z = 0; z < ChunkSection.SIZE; z++) {
|
||||
this.setBlockAt(x, y, z, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rebuild(renderer) {
|
||||
this.dirty = false;
|
||||
this.group.clear();
|
||||
|
||||
|
||||
for (let x = 0; x < ChunkSection.SIZE; x++) {
|
||||
for (let y = 0; y < ChunkSection.SIZE; y++) {
|
||||
for (let z = 0; z < ChunkSection.SIZE; z++) {
|
||||
let typeId = this.getBlockAt(x, y, z);
|
||||
|
||||
if (typeId !== 0) {
|
||||
let absoluteX = this.x * ChunkSection.SIZE + x;
|
||||
let absoluteY = this.y * ChunkSection.SIZE + y;
|
||||
let absoluteZ = this.z * ChunkSection.SIZE + z;
|
||||
|
||||
renderer.blockRenderer.renderBlock(this.world, this.group, typeId, absoluteX, absoluteY, absoluteZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getBlockAt(x, y, z) {
|
||||
let index = y << 8 | z << 4 | x;
|
||||
return this.blocks[index];
|
||||
}
|
||||
|
||||
setBlockAt(x, y, z, typeId) {
|
||||
let index = y << 8 | z << 4 | x;
|
||||
this.blocks[index] = typeId;
|
||||
}
|
||||
|
||||
queueForRebuild() {
|
||||
this.dirty = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
window.World = class {
|
||||
|
||||
static get TOTAL_HEIGHT() {
|
||||
return ChunkSection.SIZE * 16 - 1;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this.group = new THREE.Object3D();
|
||||
this.chunks = [];
|
||||
|
||||
for (let x = -16; x < 16; x++) {
|
||||
for (let z = -16; z < 16; z++) {
|
||||
this.setBlockAt(x, 0, z, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getChunkAtBlock(x, y, z) {
|
||||
let chunk = this.getChunkAt(x >> 4, z >> 4);
|
||||
return y < 0 || y > World.TOTAL_HEIGHT ? null : chunk.getSection(y >> 4);
|
||||
}
|
||||
|
||||
getCollisionBoxes(aabb) {
|
||||
let boundingBoxList = [];
|
||||
|
||||
let minX = MathHelper.floor_double(aabb.minX);
|
||||
let maxX = MathHelper.floor_double(aabb.maxX + 1.0);
|
||||
let minY = MathHelper.floor_double(aabb.minY);
|
||||
let maxY = MathHelper.floor_double(aabb.maxY + 1.0);
|
||||
let minZ = MathHelper.floor_double(aabb.minZ);
|
||||
let maxZ = MathHelper.floor_double(aabb.maxZ + 1.0);
|
||||
|
||||
for (let x = minX; x < maxX; x++) {
|
||||
for (let y = minY; y < maxY; y++) {
|
||||
for (let z = minZ; z < maxZ; z++) {
|
||||
if (this.isSolidBlockAt(x, y, z)) {
|
||||
boundingBoxList.push(new BoundingBox(x, y, z, x + 1, y + 1, z + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return boundingBoxList;
|
||||
}
|
||||
|
||||
isSolidBlockAt(x, y, z) {
|
||||
let typeId = this.getBlockAt(x, y, z);
|
||||
return typeId !== 0; /* && Block.getById(typeId).isSolid();*/
|
||||
}
|
||||
|
||||
setBlockAt(x, y, z, type) {
|
||||
let chunkSection = this.getChunkAtBlock(x, y, z);
|
||||
if (chunkSection != null) {
|
||||
chunkSection.setBlockAt(x & 15, y & 15, z & 15, type);
|
||||
}
|
||||
|
||||
this.blockChanged(x, y, z);
|
||||
}
|
||||
|
||||
|
||||
getBlockAt(x, y, z) {
|
||||
let chunkSection = this.getChunkAtBlock(x, y, z);
|
||||
return chunkSection == null ? 0 : chunkSection.getBlockAt(x & 15, y & 15, z & 15);
|
||||
}
|
||||
|
||||
getChunkAt(x, z) {
|
||||
let zArray = this.chunks[x];
|
||||
if (typeof zArray === 'undefined') {
|
||||
zArray = this.chunks[x] = [];
|
||||
}
|
||||
|
||||
let chunk = zArray[z];
|
||||
if (typeof chunk === 'undefined') {
|
||||
chunk = new Chunk(this, x, z);
|
||||
this.chunks[x][z] = chunk;
|
||||
this.group.add(chunk.group);
|
||||
}
|
||||
return chunk;
|
||||
}
|
||||
|
||||
blockChanged(x, y, z) {
|
||||
this.setDirty(x - 1, y - 1, z - 1, x + 1, y + 1, z + 1);
|
||||
}
|
||||
|
||||
setDirty(minX, minY, minZ, maxX, maxY, maxZ) {
|
||||
// To chunk coordinates
|
||||
minX = minX >> 4;
|
||||
maxX = maxX >> 4;
|
||||
minY = minY >> 4;
|
||||
maxY = maxY >> 4;
|
||||
minZ = minZ >> 4;
|
||||
maxZ = maxZ >> 4;
|
||||
|
||||
// Minimum and maximum y
|
||||
minY = Math.max(0, minY);
|
||||
maxY = Math.min(15, maxY);
|
||||
|
||||
for (let x = minX; x <= maxX; x++) {
|
||||
for (let y = minY; y <= maxY; y++) {
|
||||
for (let z = minZ; z <= maxZ; z++) {
|
||||
this.getChunkAt(x, y, z).queueForRebuild();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user