wmc/geometry.js

138 lines
4.5 KiB
JavaScript
Raw Normal View History

2021-12-12 08:46:24 +00:00
function memoize(f) {
const memo = {};
function g(...args) {
if (!(args in memo)) {
memo[args] = f(...args);
}
return memo[args];
}
return g;
}
function _makeTextureFace(texture) {
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-12 08:46:24 +00:00
const textures = textuv.map(uv => uv.map((x, j) => textMul * x + textOff[j]));
2021-12-12 08:46:24 +00:00
return textures;
}
2021-12-12 08:46:24 +00:00
const makeTextureFace = memoize(_makeTextureFace);
2021-12-12 08:46:24 +00:00
function makePZFace(texture) {
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-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-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-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-12 08:46:24 +00:00
throw Error('unknown face');
}
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);
return {
2021-12-12 08:46:24 +00:00
glBuffer,
numVertices,
delete: () => gl.deleteBuffer(glBuffer),
};
}