icy3dw/src/client/object/world/ClientWorldMesher.ts

78 lines
2.1 KiB
TypeScript

import {
BufferGeometry,
Float32BufferAttribute,
Material,
Mesh,
MeshLambertMaterial,
Vector3,
} from 'three';
import { to2D } from '../../../common/convert';
import { WorldChunk } from '../../../common/world/WorldChunk';
export class ClientWorldMesher {
public createGeometry(
chunk: WorldChunk,
getHeight: (x: number, y: number) => number,
getNormal: (x: number, y: number) => Vector3,
): BufferGeometry {
const geometry = new BufferGeometry();
const vertices = [];
const normals = [];
const indices = [];
const uvs = [];
for (let x = 0; x < chunk.size; x++) {
for (let y = 0; y < chunk.size; y++) {
const normal = getNormal(y, x);
vertices.push(
(y / chunk.size - 1) * chunk.size,
getHeight(y, x),
(x / chunk.size - 1) * chunk.size,
);
normals.push(normal.x, normal.y, normal.z);
uvs.push(y / (chunk.size - 1), x / (chunk.size - 1));
}
}
for (let x = 0; x < chunk.size - 1; x++) {
for (let y = 0; y < chunk.size - 1; y++) {
const topLeft = x * chunk.size + y;
const topRight = topLeft + 1;
const bottomLeft = (x + 1) * chunk.size + y;
const bottomRight = bottomLeft + 1;
indices.push(
topLeft,
bottomLeft,
topRight,
topRight,
bottomLeft,
bottomRight,
);
}
}
geometry.setIndex(indices);
geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3));
geometry.setAttribute('normal', new Float32BufferAttribute(normals, 3));
geometry.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
return geometry;
}
public createTerrainMesh(
chunk: WorldChunk,
material: Material,
getHeight: (x: number, y: number) => number,
getNormal: (x: number, y: number) => Vector3,
): Mesh {
const geometry = this.createGeometry(chunk, getHeight, getNormal);
const mesh = new Mesh(geometry, material);
mesh.position.set(
chunk.size * (chunk.x + 1),
0,
chunk.size * (chunk.y + 1),
);
return mesh;
}
}