refactor project structure, implement tessellator
This commit is contained in:
+2
-1
@@ -47,7 +47,8 @@ window.Player = class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resetPos() {
|
resetPos() {
|
||||||
this.setPos(0, 15, 0);
|
this.setPos(0, 2, 0);
|
||||||
|
this.pitch = -90;
|
||||||
}
|
}
|
||||||
|
|
||||||
setPos(x, y, z) {
|
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
|
antialias: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Settings
|
||||||
this.webRenderer.shadowMap.enabled = true;
|
this.webRenderer.shadowMap.enabled = true;
|
||||||
this.webRenderer.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap
|
this.webRenderer.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap
|
||||||
this.webRenderer.autoClear = false;
|
this.webRenderer.autoClear = false;
|
||||||
this.webRenderer.setClearColor(0x000000, 0);
|
this.webRenderer.setClearColor(0x000000, 0);
|
||||||
this.webRenderer.clear();
|
this.webRenderer.clear();
|
||||||
|
|
||||||
|
// Add lights
|
||||||
const nightLight = new THREE.AmbientLight(0x888888, 1.0);
|
const nightLight = new THREE.AmbientLight(0x888888, 1.0);
|
||||||
this.scene.add(nightLight);
|
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) {
|
render(partialTicks) {
|
||||||
@@ -40,7 +50,7 @@ window.WorldRenderer = class {
|
|||||||
this.orientCamera(partialTicks);
|
this.orientCamera(partialTicks);
|
||||||
|
|
||||||
// Render chunks
|
// Render chunks
|
||||||
this.renderChunks(partialTicks);
|
this.renderChunks(this, partialTicks);
|
||||||
|
|
||||||
// Render window
|
// Render window
|
||||||
this.webRenderer.render(this.scene, this.camera);
|
this.webRenderer.render(this.scene, this.camera);
|
||||||
@@ -64,7 +74,7 @@ window.WorldRenderer = class {
|
|||||||
this.camera.updateProjectionMatrix();
|
this.camera.updateProjectionMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderChunks(partialTicks) {
|
renderChunks(renderer, partialTicks) {
|
||||||
let world = this.minecraft.world;
|
let world = this.minecraft.world;
|
||||||
|
|
||||||
const xKeys = Object.keys(world.chunks)
|
const xKeys = Object.keys(world.chunks)
|
||||||
@@ -80,7 +90,7 @@ window.WorldRenderer = class {
|
|||||||
let section = chunk.sections[y];
|
let section = chunk.sections[y];
|
||||||
|
|
||||||
if (section.dirty) {
|
if (section.dirty) {
|
||||||
section.rebuild();
|
section.rebuild(renderer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-6
@@ -1,15 +1,16 @@
|
|||||||
window.Chunk = class {
|
window.Chunk = class {
|
||||||
|
|
||||||
constructor(x, z) {
|
constructor(world, x, z) {
|
||||||
this.group = new THREE.Object3D();
|
this.world = world;
|
||||||
|
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.z = z;
|
this.z = z;
|
||||||
|
|
||||||
|
this.group = new THREE.Object3D();
|
||||||
|
|
||||||
// Initialize sections
|
// Initialize sections
|
||||||
this.sections = [];
|
this.sections = [];
|
||||||
for (let y = 0; y < 16; y++) {
|
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.sections[y] = section;
|
||||||
this.group.add(section.group);
|
this.group.add(section.group);
|
||||||
@@ -20,9 +21,9 @@ window.Chunk = class {
|
|||||||
return this.sections[y];
|
return this.sections[y];
|
||||||
}
|
}
|
||||||
|
|
||||||
rebuild() {
|
rebuild(renderer) {
|
||||||
for (let y = 0; y < this.sections.length; y++) {
|
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;
|
return 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(x, y, z) {
|
constructor(world, x, y, z) {
|
||||||
|
this.world = world;
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
this.z = z;
|
this.z = z;
|
||||||
@@ -22,10 +23,11 @@ window.ChunkSection = class {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rebuild() {
|
rebuild(renderer) {
|
||||||
this.dirty = false;
|
this.dirty = false;
|
||||||
this.group.clear();
|
this.group.clear();
|
||||||
|
|
||||||
|
|
||||||
for (let x = 0; x < ChunkSection.SIZE; x++) {
|
for (let x = 0; x < ChunkSection.SIZE; x++) {
|
||||||
for (let y = 0; y < ChunkSection.SIZE; y++) {
|
for (let y = 0; y < ChunkSection.SIZE; y++) {
|
||||||
for (let z = 0; z < ChunkSection.SIZE; z++) {
|
for (let z = 0; z < ChunkSection.SIZE; z++) {
|
||||||
@@ -36,18 +38,7 @@ window.ChunkSection = class {
|
|||||||
let absoluteY = this.y * ChunkSection.SIZE + y;
|
let absoluteY = this.y * ChunkSection.SIZE + y;
|
||||||
let absoluteZ = this.z * ChunkSection.SIZE + z;
|
let absoluteZ = this.z * ChunkSection.SIZE + z;
|
||||||
|
|
||||||
// Debug stuff
|
renderer.blockRenderer.renderBlock(this.world, this.group, typeId, absoluteX, absoluteY, absoluteZ);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -70,7 +70,7 @@ window.World = class {
|
|||||||
|
|
||||||
let chunk = zArray[z];
|
let chunk = zArray[z];
|
||||||
if (typeof chunk === 'undefined') {
|
if (typeof chunk === 'undefined') {
|
||||||
chunk = new Chunk(x, z);
|
chunk = new Chunk(this, x, z);
|
||||||
this.chunks[x][z] = chunk;
|
this.chunks[x][z] = chunk;
|
||||||
this.group.add(chunk.group);
|
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",
|
"libraries/three.min.js",
|
||||||
|
|
||||||
// Minecraft Source
|
// Minecraft Source
|
||||||
"src/net/minecraft/util/Timer.js",
|
"src/js/net/minecraft/util/Timer.js",
|
||||||
"src/net/minecraft/util/MathHelper.js",
|
"src/js/net/minecraft/util/MathHelper.js",
|
||||||
"src/net/minecraft/util/BoundingBox.js",
|
"src/js/net/minecraft/util/BoundingBox.js",
|
||||||
"src/net/minecraft/util/Keyboard.js",
|
"src/js/net/minecraft/util/Keyboard.js",
|
||||||
"src/net/minecraft/client/GameWindow.js",
|
"src/js/net/minecraft/client/GameWindow.js",
|
||||||
"src/net/minecraft/client/world/ChunkSection.js",
|
"src/js/net/minecraft/client/world/ChunkSection.js",
|
||||||
"src/net/minecraft/client/world/Chunk.js",
|
"src/js/net/minecraft/client/world/Chunk.js",
|
||||||
"src/net/minecraft/client/world/World.js",
|
"src/js/net/minecraft/client/world/World.js",
|
||||||
"src/net/minecraft/client/entity/Player.js",
|
"src/js/net/minecraft/client/entity/Player.js",
|
||||||
"src/net/minecraft/client/Minecraft.js",
|
"src/js/net/minecraft/client/Minecraft.js",
|
||||||
"src/net/minecraft/client/render/WorldRenderer.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(() => {
|
]).then(() => {
|
||||||
// Remove pre status
|
// Remove pre status
|
||||||
document.getElementById("pre-status").remove();
|
document.getElementById("pre-status").remove();
|
||||||
|
|||||||
Reference in New Issue
Block a user