refactor project structure, implement tessellator

This commit is contained in:
LabyStudio
2022-01-31 20:15:27 +01:00
parent 192417f626
commit 293a6d9553
15 changed files with 160 additions and 36 deletions
@@ -47,7 +47,8 @@ window.Player = class {
}
resetPos() {
this.setPos(0, 15, 0);
this.setPos(0, 2, 0);
this.pitch = -90;
}
setPos(x, y, z) {
@@ -0,0 +1,81 @@
window.BlockRenderer = class {
constructor(worldRenderer) {
this.worldRenderer = worldRenderer;
this.tessellator = new Tessellator();
this.tessellator.bindTexture(worldRenderer.terrainTexture);
}
renderBlock(world, group, typeId, x, y, z) {
let boundingBox = new BoundingBox(0.0, 0.0, 0.0, 1.0, 1.0, 1.0);
for (let face = 0; face < 6; face++) {
this.tessellator.startDrawing();
this.renderFace(world, typeId, boundingBox, face, x, y, z);
this.tessellator.draw(group);
}
}
renderFace(world, typeId, boundingBox, face, x, y, z) {
// Vertex mappings
let minX = x + boundingBox.minX;
let minY = y + boundingBox.minY;
let minZ = z + boundingBox.minZ;
let maxX = x + boundingBox.maxX;
let maxY = y + boundingBox.maxY;
let maxZ = z + boundingBox.maxZ;
// UV Mapping
let textureIndex = typeId;
let minU = (textureIndex % 16) / 16.0;
let maxU = minU + (16 / 256);
let minV = parseInt(textureIndex / 16); // TODO Math.round
let maxV = minV + (16 / 256);
// Flip V
minV = 1 - minV;
maxV = 1 - maxV;
if (face === 0) {
this.addBlockCorner(world, face, minX, minY, maxZ, minU, maxV);
this.addBlockCorner(world, face, minX, minY, minZ, minU, minV);
this.addBlockCorner(world, face, maxX, minY, minZ, maxU, minV);
this.addBlockCorner(world, face, maxX, minY, maxZ, maxU, maxV);
}
if (face === 1) {
this.addBlockCorner(world, face, maxX, maxY, maxZ, maxU, maxV);
this.addBlockCorner(world, face, maxX, maxY, minZ, maxU, minV);
this.addBlockCorner(world, face, minX, maxY, minZ, minU, minV);
this.addBlockCorner(world, face, minX, maxY, maxZ, minU, maxV);
}
if (face === 2) {
this.addBlockCorner(world, face, minX, maxY, minZ, maxU, minV);
this.addBlockCorner(world, face, maxX, maxY, minZ, minU, minV);
this.addBlockCorner(world, face, maxX, minY, minZ, minU, maxV);
this.addBlockCorner(world, face, minX, minY, minZ, maxU, maxV);
}
if (face === 3) {
this.addBlockCorner(world, face, minX, maxY, maxZ, minU, minV);
this.addBlockCorner(world, face, minX, minY, maxZ, minU, maxV);
this.addBlockCorner(world, face, maxX, minY, maxZ, maxU, maxV);
this.addBlockCorner(world, face, maxX, maxY, maxZ, maxU, minV);
}
if (face === 4) {
this.addBlockCorner(world, face, minX, maxY, maxZ, maxU, minV);
this.addBlockCorner(world, face, minX, maxY, minZ, minU, minV);
this.addBlockCorner(world, face, minX, minY, minZ, minU, maxV);
this.addBlockCorner(world, face, minX, minY, maxZ, maxU, maxV);
}
if (face === 5) {
this.addBlockCorner(world, face, maxX, minY, maxZ, minU, maxV);
this.addBlockCorner(world, face, maxX, minY, minZ, maxU, maxV);
this.addBlockCorner(world, face, maxX, maxY, minZ, maxU, minV);
this.addBlockCorner(world, face, maxX, maxY, maxZ, minU, minV);
}
}
addBlockCorner(world, face, x, y, z, u, v) {
this.tessellator.addVertexWithUV(x, y, z, u, v);
}
}
@@ -0,0 +1,38 @@
window.Tessellator = class {
constructor() {
this.material = new THREE.MeshBasicMaterial({
color: 0xffffff,
side: THREE.BackSide
});
}
bindTexture(texture) {
this.material.map = texture;
}
startDrawing() {
this.verticies = [];
this.uv = [];
}
addVertexWithUV(x, y, z, u, v) {
this.verticies.push(x);
this.verticies.push(y);
this.verticies.push(z);
this.uv.push(u);
this.uv.push(v);
}
draw(group) {
let geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(this.verticies), 3));
geometry.setAttribute('uv', new THREE.BufferAttribute(new Float32Array(this.uv), 2));
geometry.setIndex(new THREE.BufferAttribute(new Uint32Array([0, 2, 1, 0, 3, 2]), 1));
let mesh = new THREE.Mesh(geometry, this.material);
group.add(mesh);
}
}
@@ -25,14 +25,24 @@ window.WorldRenderer = class {
antialias: true
});
// Settings
this.webRenderer.shadowMap.enabled = true;
this.webRenderer.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap
this.webRenderer.autoClear = false;
this.webRenderer.setClearColor(0x000000, 0);
this.webRenderer.clear();
// Add lights
const nightLight = new THREE.AmbientLight(0x888888, 1.0);
this.scene.add(nightLight);
// Load terrain
this.terrainTexture = new THREE.TextureLoader().load( 'src/resources/terrain.png' );
this.terrainTexture.magFilter = THREE.NearestFilter;
this.terrainTexture.minFilter = THREE.LinearFilter;
// Block Renderer
this.blockRenderer = new BlockRenderer(this);
}
render(partialTicks) {
@@ -40,7 +50,7 @@ window.WorldRenderer = class {
this.orientCamera(partialTicks);
// Render chunks
this.renderChunks(partialTicks);
this.renderChunks(this, partialTicks);
// Render window
this.webRenderer.render(this.scene, this.camera);
@@ -64,7 +74,7 @@ window.WorldRenderer = class {
this.camera.updateProjectionMatrix();
}
renderChunks(partialTicks) {
renderChunks(renderer, partialTicks) {
let world = this.minecraft.world;
const xKeys = Object.keys(world.chunks)
@@ -80,7 +90,7 @@ window.WorldRenderer = class {
let section = chunk.sections[y];
if (section.dirty) {
section.rebuild();
section.rebuild(renderer);
}
}
}
@@ -1,15 +1,16 @@
window.Chunk = class {
constructor(x, z) {
this.group = new THREE.Object3D();
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(x, y, z);
let section = new ChunkSection(world, x, y, z);
this.sections[y] = section;
this.group.add(section.group);
@@ -20,9 +21,9 @@ window.Chunk = class {
return this.sections[y];
}
rebuild() {
rebuild(renderer) {
for (let y = 0; y < this.sections.length; y++) {
this.sections[y].rebuild();
this.sections[y].rebuild(renderer);
}
}
@@ -4,7 +4,8 @@ window.ChunkSection = class {
return 16;
}
constructor(x, y, z) {
constructor(world, x, y, z) {
this.world = world;
this.x = x;
this.y = y;
this.z = z;
@@ -22,10 +23,11 @@ window.ChunkSection = class {
}
}
rebuild() {
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++) {
@@ -36,18 +38,7 @@ window.ChunkSection = class {
let absoluteY = this.y * ChunkSection.SIZE + y;
let absoluteZ = this.z * ChunkSection.SIZE + z;
// Debug stuff
let color = 0x888888 | (Math.random() * 223);
let geometry = new THREE.BoxGeometry(1, 1, 1);
let material = new THREE.MeshBasicMaterial({
color: color
});
let cube = new THREE.Mesh(geometry, material);
cube.position.set(absoluteX + 0.5, absoluteY + 0.5, absoluteZ + 0.5);
this.group.add(cube);
renderer.blockRenderer.renderBlock(this.world, this.group, typeId, absoluteX, absoluteY, absoluteZ);
}
}
}
@@ -70,7 +70,7 @@ window.World = class {
let chunk = zArray[z];
if (typeof chunk === 'undefined') {
chunk = new Chunk(x, z);
chunk = new Chunk(this, x, z);
this.chunks[x][z] = chunk;
this.group.add(chunk.group);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

+13 -11
View File
@@ -47,17 +47,19 @@ loadScripts([
"libraries/three.min.js",
// Minecraft Source
"src/net/minecraft/util/Timer.js",
"src/net/minecraft/util/MathHelper.js",
"src/net/minecraft/util/BoundingBox.js",
"src/net/minecraft/util/Keyboard.js",
"src/net/minecraft/client/GameWindow.js",
"src/net/minecraft/client/world/ChunkSection.js",
"src/net/minecraft/client/world/Chunk.js",
"src/net/minecraft/client/world/World.js",
"src/net/minecraft/client/entity/Player.js",
"src/net/minecraft/client/Minecraft.js",
"src/net/minecraft/client/render/WorldRenderer.js"
"src/js/net/minecraft/util/Timer.js",
"src/js/net/minecraft/util/MathHelper.js",
"src/js/net/minecraft/util/BoundingBox.js",
"src/js/net/minecraft/util/Keyboard.js",
"src/js/net/minecraft/client/GameWindow.js",
"src/js/net/minecraft/client/world/ChunkSection.js",
"src/js/net/minecraft/client/world/Chunk.js",
"src/js/net/minecraft/client/world/World.js",
"src/js/net/minecraft/client/entity/Player.js",
"src/js/net/minecraft/client/Minecraft.js",
"src/js/net/minecraft/client/render/Tessellator.js",
"src/js/net/minecraft/client/render/WorldRenderer.js",
"src/js/net/minecraft/client/render/BlockRenderer.js"
]).then(() => {
// Remove pre status
document.getElementById("pre-status").remove();