127 lines
3.2 KiB
JavaScript
127 lines
3.2 KiB
JavaScript
|
import * as se3 from './se3';
|
||
|
|
||
|
/** Makes a square with constant z = 0.
|
||
|
*
|
||
|
* Face is oriented towards z+.
|
||
|
*/
|
||
|
function makeSquare() {
|
||
|
const vertices = [
|
||
|
// triangle 0
|
||
|
0.5, 0.5 , 0.0,
|
||
|
-0.5, 0.5, 0.0,
|
||
|
-0.5, -0.5, 0.0,
|
||
|
|
||
|
// triangle 1
|
||
|
0.5, 0.5, 0.0,
|
||
|
-0.5, -0.5, 0.0,
|
||
|
0.5, -0.5, 0.0,
|
||
|
];
|
||
|
|
||
|
// normals toward z+
|
||
|
const normals = [].concat(...Array(6).fill([0.0, 0.0, 1.0]));
|
||
|
|
||
|
const textures = [
|
||
|
0.99, 0.99,
|
||
|
0.01, 0.99,
|
||
|
0.01, 0.01,
|
||
|
|
||
|
0.99, 0.99,
|
||
|
0.01, 0.01,
|
||
|
0.99, 0.01,
|
||
|
];
|
||
|
|
||
|
return {
|
||
|
vertices,
|
||
|
normals,
|
||
|
textures,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function makeZFace(normal, texture, transform) {
|
||
|
const textMul = 0.0625;
|
||
|
const textOff = texture.map(x => x * textMul);
|
||
|
|
||
|
const vertices = [];
|
||
|
const textures = [];
|
||
|
|
||
|
const sq = makeSquare();
|
||
|
|
||
|
for (let i = 0; i < 6; i++) {
|
||
|
vertices.push(
|
||
|
se3.product(
|
||
|
transform,
|
||
|
sq.vertices.slice(3 * i, 3 * (i + 1)).concat([1.0])
|
||
|
).slice(0, 3));
|
||
|
textures.push(sq.textures.slice(2 * i, 2 * (i + 1)).map((v, j) => textMul * v + textOff[j]));
|
||
|
}
|
||
|
|
||
|
const normals = [].concat(...Array(6).fill(normal));
|
||
|
|
||
|
return {
|
||
|
vertices: [].concat(...vertices),
|
||
|
normals,
|
||
|
textures: [].concat(...textures),
|
||
|
};
|
||
|
|
||
|
}
|
||
|
|
||
|
export function makeFace(which, texture, centerPos) {
|
||
|
const rot = {
|
||
|
'-x': se3.roty(-Math.PI / 2),
|
||
|
'+x': se3.roty(Math.PI / 2),
|
||
|
'-y': se3.rotx(Math.PI / 2),
|
||
|
'+y': se3.rotx(-Math.PI / 2),
|
||
|
'-z': se3.roty(Math.PI),
|
||
|
'+z': se3.identity(),
|
||
|
}[which];
|
||
|
|
||
|
const normal = {
|
||
|
'+x': [1.0, 0.0, 0.0],
|
||
|
'-x': [-1.0, 0.0, 0.0],
|
||
|
'+y': [0.0, 1.0, 0.0],
|
||
|
'-y': [0.0, -1.0, 0.0],
|
||
|
'+z': [0.0, 0.0, 1.0],
|
||
|
'-z': [0.0, 0.0, -1.0],
|
||
|
}[which];
|
||
|
|
||
|
const tf = se3.product(se3.translation(...centerPos), rot);
|
||
|
return makeZFace(normal, texture, tf);
|
||
|
}
|
||
|
|
||
|
export function makeBuffersFromFraces(gl, faces) {
|
||
|
vertices = [].concat(...faces.map(f => f.vertices));
|
||
|
normals = [].concat(...faces.map(f => f.normals));
|
||
|
textures = [].concat(...faces.map(f => f.textures));
|
||
|
|
||
|
const vertexBuffer = gl.createBuffer();
|
||
|
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
|
||
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
|
||
|
|
||
|
const normalBuffer = gl.createBuffer();
|
||
|
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
|
||
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normals), gl.STATIC_DRAW);
|
||
|
|
||
|
const textureBuffer = gl.createBuffer();
|
||
|
gl.bindBuffer(gl.ARRAY_BUFFER, textureBuffer);
|
||
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textures), gl.STATIC_DRAW);
|
||
|
|
||
|
return {
|
||
|
vertexBuffer,
|
||
|
normalBuffer,
|
||
|
textureBuffer,
|
||
|
numVertices: vertices.length / 3,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
export function makeGrassCube(gl) {
|
||
|
faces = [
|
||
|
makeFace('+y', [0, 15], [0.0, 0.5, 0.0]),
|
||
|
makeFace('-y', [2, 15], [0.0, -0.5, 0.0]),
|
||
|
makeFace('-x', [1, 15], [-0.5, 0.0, 0.0]),
|
||
|
makeFace('+x', [1, 15], [0.5, 0.0, 0.0]),
|
||
|
makeFace('-z', [1, 15], [0.0, 0.0, -0.5]),
|
||
|
makeFace('+z', [1, 15], [0.0, 0.0, 0.5]),
|
||
|
];
|
||
|
|
||
|
return makeBuffersFromFraces(gl, faces);
|
||
|
}
|