2021-12-28 16:45:31 +00:00
|
|
|
import { memoize } from "./memoize";
|
2021-12-12 08:46:24 +00:00
|
|
|
|
|
|
|
function _makeTextureFace(texture) {
|
2021-12-08 17:24:19 +00:00
|
|
|
const textMul = 0.0625;
|
|
|
|
const textOff = texture.map(x => x * textMul);
|
2021-12-12 08:46:24 +00:00
|
|
|
const textuv = [
|
|
|
|
[0.99, 0.99],
|
|
|
|
[0.01, 0.99],
|
|
|
|
[0.01, 0.01],
|
|
|
|
[0.99, 0.99],
|
|
|
|
[0.01, 0.01],
|
|
|
|
[0.99, 0.01],
|
|
|
|
];
|
2021-12-08 17:24:19 +00:00
|
|
|
|
2021-12-12 08:46:24 +00:00
|
|
|
const textures = textuv.map(uv => uv.map((x, j) => textMul * x + textOff[j]));
|
2021-12-08 17:24:19 +00:00
|
|
|
|
2021-12-12 08:46:24 +00:00
|
|
|
return textures;
|
|
|
|
}
|
2021-12-08 17:24:19 +00:00
|
|
|
|
2021-12-12 08:46:24 +00:00
|
|
|
const makeTextureFace = memoize(_makeTextureFace);
|
2021-12-08 17:24:19 +00:00
|
|
|
|
2021-12-12 08:46:24 +00:00
|
|
|
function makePZFace(texture) {
|
2021-12-08 17:24:19 +00:00
|
|
|
return {
|
2021-12-12 08:46:24 +00:00
|
|
|
vertices: [[0.5, 0.5, 0], [-0.5, 0.5, 0], [-0.5, -0.5, 0], [0.5, 0.5, 0], [-0.5, -0.5, 0], [0.5, -0.5, 0]],
|
|
|
|
normals: Array(6).fill([0.0, 0.0, 1.0]),
|
|
|
|
textures: makeTextureFace(texture),
|
2021-12-08 17:24:19 +00:00
|
|
|
};
|
|
|
|
}
|
2021-12-12 08:46:24 +00:00
|
|
|
function makeNZFace(texture) {
|
|
|
|
return {
|
|
|
|
vertices: [[-0.5, 0.5, 0.0], [0.5, 0.5, 0.0], [0.5, -0.5, 0.0], [-0.5, 0.5, 0.0], [0.5, -0.5, 0.0], [-0.5, -0.5, 0.0]],
|
|
|
|
normals: Array(6).fill([0.0, 0.0, -1.0]),
|
|
|
|
textures: makeTextureFace(texture),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
function makePXFace(texture) {
|
|
|
|
return {
|
|
|
|
vertices: [[0, 0.5, -0.5], [0, 0.5, 0.5], [0, -0.5, 0.5], [0, 0.5, -0.5], [0, -0.5, 0.5], [0, -0.5, -0.5]],
|
|
|
|
normals: Array(6).fill([1.0, 0.0, 0.0]),
|
|
|
|
textures: makeTextureFace(texture),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
function makeNXFace(texture) {
|
|
|
|
return {
|
|
|
|
vertices: [[0, 0.5, 0.5], [0, 0.5, -0.5], [0, -0.5, -0.5], [0, 0.5, 0.5], [0, -0.5, -0.5], [0, -0.5, 0.5]],
|
|
|
|
normals: Array(6).fill([-1.0, 0.0, 0.0]),
|
|
|
|
textures: makeTextureFace(texture),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
function makePYFace(texture) {
|
|
|
|
return {
|
|
|
|
vertices: [[0.5, 0, -0.5], [-0.5, 0, -0.5], [-0.5, 0, 0.5], [0.5, 0, -0.5], [-0.5, 0, 0.5], [0.5, 0, 0.5]],
|
|
|
|
normals: Array(6).fill([0.0, 1.0, 0.0]),
|
|
|
|
textures: makeTextureFace(texture),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
function makeNYFace(texture) {
|
|
|
|
return {
|
|
|
|
vertices: [[0.5, 0, 0.5], [-0.5, 0, 0.5], [-0.5, 0, -0.5], [0.5, 0, 0.5], [-0.5, 0, -0.5], [0.5, 0, -0.5]],
|
|
|
|
normals: Array(6).fill([0.0, -1.0, 0.0]),
|
|
|
|
textures: makeTextureFace(texture),
|
|
|
|
};
|
2021-12-08 17:24:19 +00:00
|
|
|
}
|
|
|
|
|
2021-12-12 08:46:24 +00:00
|
|
|
function translateFace(face, x, y, z) {
|
|
|
|
return {
|
|
|
|
normals: face.normals,
|
|
|
|
textures: face.textures,
|
|
|
|
vertices: face.vertices.map(([vx, vy, vz]) => [vx + x, vy + y, vz + z]),
|
|
|
|
};
|
|
|
|
}
|
2021-12-08 17:24:19 +00:00
|
|
|
|
2021-12-12 08:46:24 +00:00
|
|
|
export function makeFace(which, texture, centerPos) {
|
|
|
|
switch(which) {
|
|
|
|
case '-x': return translateFace(makeNXFace(texture), ...centerPos);
|
|
|
|
case '+x': return translateFace(makePXFace(texture), ...centerPos);
|
|
|
|
case '-y': return translateFace(makeNYFace(texture), ...centerPos);
|
|
|
|
case '+y': return translateFace(makePYFace(texture), ...centerPos);
|
|
|
|
case '-z': return translateFace(makeNZFace(texture), ...centerPos);
|
|
|
|
case '+z': return translateFace(makePZFace(texture), ...centerPos);
|
|
|
|
}
|
2021-12-08 17:24:19 +00:00
|
|
|
|
2021-12-12 08:46:24 +00:00
|
|
|
throw Error('unknown face');
|
|
|
|
}
|
2021-12-08 17:24:19 +00:00
|
|
|
|
2021-12-12 08:46:24 +00:00
|
|
|
/** Packs all those faces into one big buffer. */
|
|
|
|
export function makeBufferFromFaces(gl, faces) {
|
|
|
|
const numVertices = faces.map(f => f.vertices).reduce((count, vertices) => count + vertices.length, 0);
|
|
|
|
|
|
|
|
// 3 * float32 + 3 * byte (padded to 4) + 2 * short
|
|
|
|
// see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/vertexAttribPointer#examples
|
|
|
|
const vertexSize = 3 * 4 + 4 + 4;
|
|
|
|
|
|
|
|
const glBuffer = gl.createBuffer();
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, glBuffer);
|
|
|
|
|
|
|
|
const buffer = new Uint8Array(numVertices * vertexSize);
|
|
|
|
const dv = new DataView(buffer.buffer);
|
|
|
|
let offset = 0;
|
|
|
|
|
|
|
|
faces.forEach(face => {
|
|
|
|
for (let i = 0; i < face.vertices.length; i++) {
|
|
|
|
const position = face.vertices[i];
|
|
|
|
dv.setFloat32(offset + 0, position[0], true);
|
|
|
|
dv.setFloat32(offset + 4, position[1], true);
|
|
|
|
dv.setFloat32(offset + 8, position[2], true);
|
|
|
|
offset += 12;
|
|
|
|
const normal = face.normals[i];
|
|
|
|
dv.setInt8(offset + 0, normal[0] * 0x7f);
|
|
|
|
dv.setInt8(offset + 1, normal[1] * 0x7f);
|
|
|
|
dv.setInt8(offset + 2, normal[2] * 0x7f);
|
|
|
|
offset += 4;
|
|
|
|
const texture = face.textures[i];
|
|
|
|
dv.setUint16(offset + 0, texture[0] * 0xffff, true);
|
|
|
|
dv.setUint16(offset + 2, texture[1] * 0xffff, true);
|
|
|
|
offset += 4;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
gl.bufferData(gl.ARRAY_BUFFER, buffer, gl.STATIC_DRAW);
|
2021-12-08 17:24:19 +00:00
|
|
|
|
|
|
|
return {
|
2021-12-12 08:46:24 +00:00
|
|
|
glBuffer,
|
|
|
|
numVertices,
|
|
|
|
delete: () => gl.deleteBuffer(glBuffer),
|
2021-12-08 17:24:19 +00:00
|
|
|
};
|
|
|
|
}
|