diff --git a/public/grass.png b/public/grass.png new file mode 100644 index 0000000..f453309 Binary files /dev/null and b/public/grass.png differ diff --git a/src/block.ts b/src/block.ts index 7ff66d8..75bc471 100644 --- a/src/block.ts +++ b/src/block.ts @@ -1,5 +1,12 @@ import { Object3D, Vector3 } from "three" import Face from "./face" +import { degToRad } from "three/src/math/MathUtils.js" + +function randInt(min: number, max: number): number { + const minCeiled = Math.ceil(min) + const maxFloored = Math.floor(max) + return Math.floor(Math.random() * (maxFloored - minCeiled + 1) + minCeiled) +} export default class Block { faces: Face[] @@ -13,6 +20,9 @@ export default class Block { this.faces.forEach((face) => { const dummy = new Object3D() dummy.position.add(coordinates) + if (face.orientation === "Up" || face.orientation === "Down") { + dummy.rotateOnAxis(new Vector3(0, 1, 0), degToRad(90 * randInt(0, 4))) + } dummy.updateMatrix() face.instancedMesh?.setMatrixAt(face.instaceIndex, dummy.matrix) this.facesIndexes.push(face.instaceIndex) diff --git a/src/face.ts b/src/face.ts index 7591af5..62d4ddd 100644 --- a/src/face.ts +++ b/src/face.ts @@ -1,8 +1,8 @@ import { - Color, InstancedMesh, - MeshLambertMaterial, + MeshBasicMaterial, PlaneGeometry, + Texture, Vector3 } from "three" @@ -43,14 +43,20 @@ export const FACE_ORIENTATION = [ ] export default class Face { - material: MeshLambertMaterial + material: MeshBasicMaterial orientation: Orientation geometry: PlaneGeometry instancedMesh: InstancedMesh | undefined instaceIndex: number = 0 - constructor(color: Color, orientation: Orientation, instancesCount: number) { - this.material = new MeshLambertMaterial({ color }) + constructor( + orientation: Orientation, + instancesCount: number, + texture: Texture + ) { + this.material = new MeshBasicMaterial({ + map: texture + }) this.orientation = orientation diff --git a/src/main.ts b/src/main.ts index 5f14aaf..f6dcd02 100644 --- a/src/main.ts +++ b/src/main.ts @@ -19,39 +19,62 @@ const controls = new OrbitControls(camera, renderer.domElement) controls.update() document.body.appendChild(renderer.domElement) -const ambientLight = new THREE.AmbientLight(new THREE.Color("white"), 5) -scene.add(ambientLight) +const image = document.createElement("img") +image.src = "/grass.png" +image.addEventListener("load", onImageLoaded, false) -const chunk = [] as THREE.Vector3[] -for (let i = -16; i < 16; i++) { - for (let j = -16; j < 16; j++) { - chunk.push( - new THREE.Vector3( - i, - Math.floor(Math.sin(i / 12) * 4 + Math.cos(j / 12) * 4), - j - ) - ) +function onImageLoaded() { + const textures = [] as THREE.Texture[] + + for (let i = 0; i < 6; i++) { + const canvas = document.createElement("canvas") + canvas.width = 16 + canvas.height = 16 + + const context = canvas.getContext("2d") + context?.drawImage(image, 0, 16 * i, 16, 16, 0, 0, 16, 16) + + const texture = new THREE.Texture(canvas) + texture.needsUpdate = true + texture.magFilter = THREE.NearestFilter + textures.push(texture) } + + onTextureLoaded(textures) } -const faces = [ - new Face(new THREE.Color("white"), "Up", chunk.length), - new Face(new THREE.Color("red"), "Down", chunk.length), - new Face(new THREE.Color("blue"), "North", chunk.length), - new Face(new THREE.Color("green"), "East", chunk.length), - new Face(new THREE.Color("yellow"), "West", chunk.length), - new Face(new THREE.Color("purple"), "South", chunk.length) -] +function onTextureLoaded(textures: THREE.Texture[]) { + const chunk = [] as THREE.Vector3[] + for (let i = -16; i < 16; i++) { + for (let j = -16; j < 16; j++) { + chunk.push( + new THREE.Vector3( + i, + Math.ceil(Math.sin(i / 25) * 8 + Math.cos(j / 25) * 8), + j + ) + ) + } + } -const cubes = [] as Block[] -chunk.forEach((block) => { - cubes.push(new Block(faces, block)) -}) + const faces = [ + new Face("Up", chunk.length, textures[0]), + new Face("North", chunk.length, textures[1]), + new Face("South", chunk.length, textures[2]), + new Face("East", chunk.length, textures[3]), + new Face("West", chunk.length, textures[4]), + new Face("Down", chunk.length, textures[5]) + ] -faces.forEach((face) => { - if (face.instancedMesh) scene.add(face.instancedMesh) -}) + const cubes = [] as Block[] + chunk.forEach((block) => { + cubes.push(new Block(faces, block)) + }) + + faces.forEach((face) => { + if (face.instancedMesh) scene.add(face.instancedMesh) + }) +} camera.position.x = 20 camera.position.y = 20