refactor project structure, implement tessellator
This commit is contained in:
+2
-1
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
+13
-3
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-6
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-14
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user