709 lines
22 KiB
JavaScript
709 lines
22 KiB
JavaScript
"use strict";
|
|
|
|
class Animation {
|
|
constructor() {
|
|
this.time = 0.0;
|
|
}
|
|
|
|
interpolation(i) {
|
|
if (i > this.time) {
|
|
return 0.0;
|
|
}
|
|
if (i+1 > this.time) {
|
|
return this.time - Math.floor(this.time);
|
|
}
|
|
return 1.0;
|
|
}
|
|
|
|
isZAxisInverted() {
|
|
return (this.time <= 5.0);
|
|
}
|
|
|
|
isCameraDrawn() {
|
|
return (this.time <= 2.0);
|
|
}
|
|
|
|
isOriginCubeDrawn() {
|
|
return (this.time != 0.0 && this.time < 5.0);
|
|
}
|
|
|
|
}
|
|
|
|
let cv, gl;
|
|
|
|
let program;
|
|
let floorProgram;
|
|
|
|
let hVertices;
|
|
let hVertexBuffer;
|
|
|
|
let cubeVertices;
|
|
let cubeVertexBuffer;
|
|
|
|
let lineCubeVertices;
|
|
let lineCubeVertexBuffer;
|
|
|
|
let originVertices;
|
|
let originVertexBuffer;
|
|
|
|
let floorVertices;
|
|
let floorVertexBuffer;
|
|
|
|
let cameraVertices;
|
|
let cameraVertexBuffer;
|
|
|
|
let lastFrame = Date.now();
|
|
|
|
let animation = new Animation();
|
|
|
|
let displayMatricesVirtually = true;
|
|
let virtualRealInterpolation = 1;
|
|
|
|
let cameraPitch = 0.565;
|
|
let cameraYaw = 0.375;
|
|
let cameraDistance = 4;
|
|
let smoothCameraDistance = 4;
|
|
|
|
let mouseDragging = false;
|
|
|
|
let frameTimes = [];
|
|
|
|
function resizeCanvas() {
|
|
const dpr = window.devicePixelRatio;
|
|
cv.width = cv.parentElement.clientWidth * dpr;
|
|
cv.height = cv.parentElement.clientHeight * dpr;
|
|
gl.viewport(0, 0, cv.width, cv.height);
|
|
}
|
|
|
|
async function init() {
|
|
cv = document.getElementById("cv");
|
|
|
|
gl = cv.getContext("webgl");
|
|
|
|
if (!gl) {
|
|
window.alert("WebGL not supported");
|
|
}
|
|
|
|
const resizeObserver = new ResizeObserver(resizeCanvas);
|
|
resizeObserver.observe(cv.parentElement);
|
|
resizeCanvas();
|
|
|
|
|
|
// input handling
|
|
document.getElementById("interpolate").addEventListener("input", (e) => {
|
|
animation.time = 6.0 - e.target.value;
|
|
for (let i = 0; i < 6; ++i) {
|
|
document.getElementById("matrices").children[5-i].style.setProperty("--fill-percentage", (animation.interpolation(i) * 100) + "%");
|
|
}
|
|
});
|
|
document.getElementById("displayMatricesVirtually").addEventListener("input", (e) => {
|
|
displayMatricesVirtually = e.target.checked;
|
|
});
|
|
document.getElementById("backfaceCulling").addEventListener("input", (e) => {
|
|
if (e.target.checked) {
|
|
gl.enable(gl.CULL_FACE);
|
|
} else {
|
|
gl.disable(gl.CULL_FACE);
|
|
}
|
|
});
|
|
|
|
cv.addEventListener("mousedown", (e) => {
|
|
if (e.button == 0) {
|
|
mouseDragging = true;
|
|
}
|
|
});
|
|
document.addEventListener("mouseup", (e) => {
|
|
if (e.button == 0) {
|
|
mouseDragging = false;
|
|
}
|
|
});
|
|
document.addEventListener("mouseleave", (e) => {
|
|
mouseDragging = false;
|
|
});
|
|
|
|
document.addEventListener("mousemove", (e) => {
|
|
if (mouseDragging && displayMatricesVirtually) {
|
|
cameraYaw += e.movementX / 100;
|
|
cameraPitch += e.movementY / 100;
|
|
|
|
if (cameraPitch < -Math.PI / 2) cameraPitch = -Math.PI / 2;
|
|
if (cameraPitch > Math.PI / 2) cameraPitch = Math.PI / 2;
|
|
}
|
|
});
|
|
cv.addEventListener("wheel", (e) => {
|
|
cameraDistance += e.deltaY / 100;
|
|
if (cameraDistance < 1) cameraDistance = 1;
|
|
if (cameraDistance > 15) cameraDistance = 15;
|
|
e.preventDefault();
|
|
});
|
|
|
|
|
|
// end input handling
|
|
|
|
console.log("compiling shaders...");
|
|
program = await buildShaderProgram(gl, "shaders/vertex.glsl", "shaders/fragment.glsl");
|
|
floorProgram = await buildShaderProgram(gl, "shaders/floor-vertex.glsl", "shaders/floor-fragment.glsl");
|
|
|
|
console.log("creating vertex buffer");
|
|
|
|
hVertices = [
|
|
// X // Y
|
|
|
|
// left vertical bar
|
|
-0.35, 0.6, 0.0, 1.0, 0.3, 0.3,
|
|
-0.35, -0.6, 0.0, 1.0, 0.3, 0.3,
|
|
-0.2, 0.6, 0.0, 1.0, 0.3, 0.3,
|
|
|
|
-0.2, 0.6, 0.0, 1.0, 0.3, 0.3,
|
|
-0.35, -0.6, 0.0, 1.0, 0.3, 0.3,
|
|
-0.2, -0.6, 0.0, 1.0, 0.3, 0.3,
|
|
|
|
// right vertical bar
|
|
0.35, -0.6, 0.0, 1.0, 0.3, 0.3,
|
|
0.35, 0.6, 0.0, 1.0, 0.3, 0.3,
|
|
0.2, 0.6, 0.0, 1.0, 0.3, 0.3,
|
|
|
|
0.35, -0.6, 0.0, 1.0, 0.3, 0.3,
|
|
0.2, 0.6, 0.0, 1.0, 0.3, 0.3,
|
|
0.2, -0.6, 0.0, 1.0, 0.3, 0.3,
|
|
|
|
// middle bar
|
|
-0.2, 0.1, 0.0, 1.0, 0.3, 0.3,
|
|
-0.2, -0.1, 0.0, 1.0, 0.3, 0.3,
|
|
0.2, 0.1, 0.0, 1.0, 0.3, 0.3,
|
|
|
|
0.2, 0.1, 0.0, 1.0, 0.3, 0.3,
|
|
-0.2, -0.1, 0.0, 1.0, 0.3, 0.3,
|
|
0.2, -0.1, 0.0, 1.0, 0.3, 0.3,
|
|
|
|
// bottom bar
|
|
-0.35, -0.7, 0.0, 1.0, 0.3, 0.3,
|
|
-0.35, -0.9, 0.0, 1.0, 0.3, 0.3,
|
|
0.35, -0.9, 0.0, 1.0, 0.3, 0.3,
|
|
|
|
-0.35, -0.7, 0.0, 1.0, 0.3, 0.3,
|
|
0.35, -0.9, 0.0, 1.0, 0.3, 0.3,
|
|
0.35, -0.7, 0.0, 1.0, 0.3, 0.3,
|
|
];
|
|
|
|
cubeVertices = [
|
|
// Back face (red)
|
|
-1, -1, -1, 1, 0.5, 0.5,
|
|
-1, 1, -1, 1, 0.5, 0.5,
|
|
1, 1, -1, 1, 0.5, 0.5,
|
|
-1, -1, -1, 1, 0.5, 0.5,
|
|
1, 1, -1, 1, 0.5, 0.5,
|
|
1, -1, -1, 1, 0.5, 0.5,
|
|
|
|
// Front face (green)
|
|
-1, -1, 1, 0.5, 1, 0.5,
|
|
1, -1, 1, 0.5, 1, 0.5,
|
|
1, 1, 1, 0.5, 1, 0.5,
|
|
-1, -1, 1, 0.5, 1, 0.5,
|
|
1, 1, 1, 0.5, 1, 0.5,
|
|
-1, 1, 1, 0.5, 1, 0.5,
|
|
|
|
// Left face (blue)
|
|
-1, 1, -1, 0.5, 0.5, 1,
|
|
-1, -1, -1, 0.5, 0.5, 1,
|
|
-1, 1, 1, 0.5, 0.5, 1,
|
|
-1, 1, 1, 0.5, 0.5, 1,
|
|
-1, -1, -1, 0.5, 0.5, 1,
|
|
-1, -1, 1, 0.5, 0.5, 1,
|
|
|
|
// Right face (yellow)
|
|
1, -1, -1, 1, 1, 0.5,
|
|
1, 1, -1, 1, 1, 0.5,
|
|
1, 1, 1, 1, 1, 0.5,
|
|
1, -1, -1, 1, 1, 0.5,
|
|
1, 1, 1, 1, 1, 0.5,
|
|
1, -1, 1, 1, 1, 0.5,
|
|
|
|
// Top face (magenta)
|
|
-1, 1, -1, 1, 0.5, 1,
|
|
-1, 1, 1, 1, 0.5, 1,
|
|
1, 1, 1, 1, 0.5, 1,
|
|
-1, 1, -1, 1, 0.5, 1,
|
|
1, 1, 1, 1, 0.5, 1,
|
|
1, 1, -1, 1, 0.5, 1,
|
|
|
|
// Bottom face (cyan)
|
|
-1, -1, 1, 0.5, 1, 1,
|
|
-1, -1, -1, 0.5, 1, 1,
|
|
1, -1, 1, 0.5, 1, 1,
|
|
1, -1, 1, 0.5, 1, 1,
|
|
-1, -1, -1, 0.5, 1, 1,
|
|
1, -1, -1, 0.5, 1, 1
|
|
];
|
|
|
|
lineCubeVertices = [
|
|
1, 1, 1, 1, 0, 0,
|
|
1, 1, -1, 1, 0, 0,
|
|
1, 1, 1, 1, 0, 0,
|
|
1, -1, 1, 1, 0, 0,
|
|
1, 1, 1, 1, 0, 0,
|
|
-1, 1, 1, 1, 0, 0,
|
|
1, 1, -1, 1, 0, 0,
|
|
1, -1, -1, 1, 0, 0,
|
|
1, 1, -1, 1, 0, 0,
|
|
-1, 1, -1, 1, 0, 0,
|
|
1, -1, 1, 1, 0, 0,
|
|
1, -1, -1, 1, 0, 0,
|
|
1, -1, 1, 1, 0, 0,
|
|
-1, -1, 1, 1, 0, 0,
|
|
-1, 1, 1, 1, 0, 0,
|
|
-1, 1, -1, 1, 0, 0,
|
|
-1, 1, 1, 1, 0, 0,
|
|
-1, -1, 1, 1, 0, 0,
|
|
1, -1, -1, 1, 0, 0,
|
|
-1, -1, -1, 1, 0, 0,
|
|
-1, -1, 1, 1, 0, 0,
|
|
-1, -1, -1, 1, 0, 0,
|
|
-1, 1, -1, 1, 0, 0,
|
|
-1, -1, -1, 1, 0, 0,
|
|
];
|
|
|
|
originVertices = [
|
|
0, 0, 0, 1, 0, 0,
|
|
1, 0, 0, 1, 0, 0,
|
|
0, 0, 0, 0, 1, 0,
|
|
0, 1, 0, 0, 1, 0,
|
|
0, 0, 0, 0, 0, 1,
|
|
0, 0, 1, 0, 0, 1,
|
|
];
|
|
|
|
floorVertices = [
|
|
1, 0, 1, 0, 0, 0,
|
|
-1, 0, -1, 0, 0, 0,
|
|
-1, 0, 1, 0, 0, 0,
|
|
-1, 0, -1, 0, 0, 0,
|
|
1, 0, 1, 0, 0, 0,
|
|
1, 0, -1, 0, 0, 0,
|
|
];
|
|
|
|
cameraVertices = [
|
|
// Cube Body (dark gray)
|
|
// Front face
|
|
-1, -1, 1, 0.196, 0.196, 0.196,
|
|
1, -1, 1, 0.196, 0.196, 0.196,
|
|
1, 1, 1, 0.196, 0.196, 0.196,
|
|
-1, -1, 1, 0.196, 0.196, 0.196,
|
|
1, 1, 1, 0.196, 0.196, 0.196,
|
|
-1, 1, 1, 0.196, 0.196, 0.196,
|
|
|
|
// Back face
|
|
-1, -1, -1, 0.196, 0.196, 0.196,
|
|
1, 1, -1, 0.196, 0.196, 0.196,
|
|
1, -1, -1, 0.196, 0.196, 0.196,
|
|
-1, -1, -1, 0.196, 0.196, 0.196,
|
|
-1, 1, -1, 0.196, 0.196, 0.196,
|
|
1, 1, -1, 0.196, 0.196, 0.196,
|
|
|
|
// Left face
|
|
-1, -1, -1, 0.196, 0.196, 0.196,
|
|
-1, -1, 1, 0.196, 0.196, 0.196,
|
|
-1, 1, 1, 0.196, 0.196, 0.196,
|
|
-1, -1, -1, 0.196, 0.196, 0.196,
|
|
-1, 1, 1, 0.196, 0.196, 0.196,
|
|
-1, 1, -1, 0.196, 0.196, 0.196,
|
|
|
|
// Right face
|
|
1, -1, -1, 0.196, 0.196, 0.196,
|
|
1, 1, 1, 0.196, 0.196, 0.196,
|
|
1, -1, 1, 0.196, 0.196, 0.196,
|
|
1, -1, -1, 0.196, 0.196, 0.196,
|
|
1, 1, -1, 0.196, 0.196, 0.196,
|
|
1, 1, 1, 0.196, 0.196, 0.196,
|
|
|
|
// Top face
|
|
-1, 1, -1, 0.196, 0.196, 0.196,
|
|
-1, 1, 1, 0.196, 0.196, 0.196,
|
|
1, 1, 1, 0.196, 0.196, 0.196,
|
|
-1, 1, -1, 0.196, 0.196, 0.196,
|
|
1, 1, 1, 0.196, 0.196, 0.196,
|
|
1, 1, -1, 0.196, 0.196, 0.196,
|
|
|
|
// Bottom face
|
|
-1, -1, -1, 0.196, 0.196, 0.196,
|
|
1, -1, 1, 0.196, 0.196, 0.196,
|
|
-1, -1, 1, 0.196, 0.196, 0.196,
|
|
-1, -1, -1, 0.196, 0.196, 0.196,
|
|
1, -1, -1, 0.196, 0.196, 0.196,
|
|
1, -1, 1, 0.196, 0.196, 0.196,
|
|
|
|
// Lens (light gray)
|
|
// Front face
|
|
-0.5, -0.5, -1.6, 0.706, 0.706, 0.706,
|
|
0.5, 0.5, -1.6, 0.706, 0.706, 0.706,
|
|
0.5, -0.5, -1.6, 0.706, 0.706, 0.706,
|
|
-0.5, -0.5, -1.6, 0.706, 0.706, 0.706,
|
|
-0.5, 0.5, -1.6, 0.706, 0.706, 0.706,
|
|
0.5, 0.5, -1.6, 0.706, 0.706, 0.706,
|
|
|
|
// Back face
|
|
-0.5, -0.5, -1.0, 0.706, 0.706, 0.706,
|
|
0.5, -0.5, -1.0, 0.706, 0.706, 0.706,
|
|
0.5, 0.5, -1.0, 0.706, 0.706, 0.706,
|
|
-0.5, -0.5, -1.0, 0.706, 0.706, 0.706,
|
|
0.5, 0.5, -1.0, 0.706, 0.706, 0.706,
|
|
-0.5, 0.5, -1.0, 0.706, 0.706, 0.706,
|
|
|
|
// Left face
|
|
-0.5, 0.5, -1.6, 0.706, 0.706, 0.706,
|
|
-0.5, -0.5, -1.0, 0.706, 0.706, 0.706,
|
|
-0.5, 0.5, -1.0, 0.706, 0.706, 0.706,
|
|
-0.5, -0.5, -1.6, 0.706, 0.706, 0.706,
|
|
-0.5, -0.5, -1.0, 0.706, 0.706, 0.706,
|
|
-0.5, 0.5, -1.6, 0.706, 0.706, 0.706,
|
|
|
|
// Right face
|
|
0.5, 0.5, -1.0, 0.706, 0.706, 0.706,
|
|
0.5, -0.5, -1.0, 0.706, 0.706, 0.706,
|
|
0.5, 0.5, -1.6, 0.706, 0.706, 0.706,
|
|
0.5, 0.5, -1.6, 0.706, 0.706, 0.706,
|
|
0.5, -0.5, -1.0, 0.706, 0.706, 0.706,
|
|
0.5, -0.5, -1.6, 0.706, 0.706, 0.706,
|
|
|
|
// Top face
|
|
0.5, 0.5, -1.6, 0.706, 0.706, 0.706,
|
|
-0.5, 0.5, -1.0, 0.706, 0.706, 0.706,
|
|
0.5, 0.5, -1.0, 0.706, 0.706, 0.706,
|
|
-0.5, 0.5, -1.6, 0.706, 0.706, 0.706,
|
|
-0.5, 0.5, -1.0, 0.706, 0.706, 0.706,
|
|
0.5, 0.5, -1.6, 0.706, 0.706, 0.706,
|
|
|
|
// Bottom face
|
|
-0.5, -0.5, -1.0, 0.706, 0.706, 0.706,
|
|
0.5, -0.5, -1.0, 0.706, 0.706, 0.706,
|
|
0.5, -0.5, -1.6, 0.706, 0.706, 0.706,
|
|
-0.5, -0.5, -1.0, 0.706, 0.706, 0.706,
|
|
0.5, -0.5, -1.6, 0.706, 0.706, 0.706,
|
|
-0.5, -0.5, -1.6, 0.706, 0.706, 0.706
|
|
];
|
|
|
|
hVertexBuffer = gl.createBuffer();
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, hVertexBuffer);
|
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(hVertices), gl.STATIC_DRAW);
|
|
|
|
cubeVertexBuffer = gl.createBuffer();
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexBuffer);
|
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(cubeVertices), gl.STATIC_DRAW);
|
|
|
|
lineCubeVertexBuffer = gl.createBuffer();
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, lineCubeVertexBuffer);
|
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(lineCubeVertices), gl.STATIC_DRAW);
|
|
|
|
originVertexBuffer = gl.createBuffer();
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, originVertexBuffer);
|
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(originVertices), gl.STATIC_DRAW);
|
|
|
|
floorVertexBuffer = gl.createBuffer();
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, floorVertexBuffer);
|
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(floorVertices), gl.STATIC_DRAW);
|
|
|
|
cameraVertexBuffer = gl.createBuffer();
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, cameraVertexBuffer);
|
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(cameraVertices), gl.STATIC_DRAW);
|
|
|
|
// unbind buffer
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
|
|
// set clear colour
|
|
gl.clearColor(...hexToRgb("181825"), 1.0);
|
|
|
|
gl.enable(gl.DEPTH_TEST);
|
|
gl.enable(gl.BLEND);
|
|
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
|
|
|
gl.enable( gl.LINE_SMOOTH );
|
|
gl.enable( gl.POLYGON_SMOOTH );
|
|
gl.hint( gl.LINE_SMOOTH_HINT, gl.NICEST );
|
|
gl.hint( gl.POLYGON_SMOOTH_HINT, gl.NICEST )
|
|
gl.lineWidth(3.0);
|
|
|
|
// start drawing
|
|
requestAnimationFrame(draw);
|
|
}
|
|
|
|
function setAttribPointers() {
|
|
let positionAttribLocation = gl.getAttribLocation(program, "vertPosition");
|
|
let colorAttribLocation = gl.getAttribLocation(program, "vertColor");
|
|
|
|
gl.vertexAttribPointer(positionAttribLocation, 3, gl.FLOAT, gl.FALSE, 6 * Float32Array.BYTES_PER_ELEMENT, 0);
|
|
gl.vertexAttribPointer(colorAttribLocation, 3, gl.FLOAT, gl.FALSE, 6 * Float32Array.BYTES_PER_ELEMENT, 3 * Float32Array.BYTES_PER_ELEMENT);
|
|
|
|
gl.enableVertexAttribArray(positionAttribLocation);
|
|
gl.enableVertexAttribArray(colorAttribLocation);
|
|
}
|
|
|
|
let frameCount = 0;
|
|
let lastStatUpdate = Date.now();
|
|
|
|
function updateStats(deltaTime) {
|
|
frameCount++;
|
|
|
|
let now = Date.now();
|
|
let timeSinceLastUpdate = (now - lastStatUpdate) / 1000;
|
|
|
|
if (timeSinceLastUpdate < 0.5) return;
|
|
|
|
lastStatUpdate = now;
|
|
|
|
let fpsDisplay = document.getElementById("fps");
|
|
fpsDisplay.innerText = Math.round(frameCount / timeSinceLastUpdate)
|
|
|
|
let msDisplay = document.getElementById("ms");
|
|
if (frameTimes.length > 0) {
|
|
msDisplay.innerText = (Math.round(frameTimes.reduce((prev, curr) => prev + curr) / frameTimes.length * 100) / 100) + "ms";
|
|
}
|
|
|
|
frameTimes = [];
|
|
frameCount = 0;
|
|
}
|
|
|
|
async function draw() {
|
|
let now = Date.now();
|
|
let deltaTime = (now - lastFrame) / 1000;
|
|
let frameStart = performance.now();
|
|
|
|
if (displayMatricesVirtually) {
|
|
virtualRealInterpolation = Math.min(virtualRealInterpolation + deltaTime * 2, 1);
|
|
} else {
|
|
virtualRealInterpolation = Math.max(virtualRealInterpolation - deltaTime * 2, 0);
|
|
}
|
|
|
|
smoothCameraDistance += (cameraDistance - smoothCameraDistance) / 8;
|
|
|
|
updateStats(deltaTime);
|
|
|
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
|
|
|
|
|
|
let identity = [];
|
|
mat4Identity(identity);
|
|
|
|
// Real Matrices
|
|
let realProjectionMatrix = [];
|
|
mat4BuildPerspective(realProjectionMatrix, 60.0 / 180.0 * Math.PI, cv.width / cv.height, 0.1, 30);
|
|
|
|
let realViewMatrix = [];
|
|
let realCameraPosition = [Math.cos(cameraYaw) * smoothCameraDistance * Math.cos(cameraPitch), Math.sin(cameraPitch) * smoothCameraDistance, Math.sin(cameraYaw) * smoothCameraDistance * Math.cos(cameraPitch)];
|
|
let realCameraLookAt = [0, 0, 0];
|
|
let realCameraUp = [0, 1, 0];
|
|
mat4BuildLookAt(realViewMatrix, realCameraPosition, realCameraLookAt, realCameraUp);
|
|
|
|
mat4Interpolate(realProjectionMatrix, identity, realProjectionMatrix, virtualRealInterpolation * virtualRealInterpolation);
|
|
mat4Interpolate(realViewMatrix, identity, realViewMatrix, virtualRealInterpolation);
|
|
|
|
gl.useProgram(program);
|
|
gl.uniformMatrix4fv(gl.getUniformLocation(program, "realProjectionMatrix"), gl.FALSE, new Float32Array(realProjectionMatrix));
|
|
gl.uniformMatrix4fv(gl.getUniformLocation(program, "realViewMatrix"), gl.FALSE, new Float32Array(realViewMatrix));
|
|
|
|
gl.useProgram(floorProgram);
|
|
gl.uniformMatrix4fv(gl.getUniformLocation(floorProgram, "realProjectionMatrix"), gl.FALSE, new Float32Array(realProjectionMatrix));
|
|
|
|
// Virtual Matrices
|
|
gl.useProgram(program);
|
|
let virtualModelViewLocation = gl.getUniformLocation(program, "virtualModelViewMatrix");
|
|
let virtualProjectionLocation = gl.getUniformLocation(program, "virtualProjectionMatrix");
|
|
let colorOverrideLocation = gl.getUniformLocation(program, "colorOverride");
|
|
|
|
|
|
let virtualProjectionMatrix = [];
|
|
mat4BuildPerspective(virtualProjectionMatrix, 60.0 / 180.0 * Math.PI, cv.width / cv.height, 0.9, 5);
|
|
|
|
if (animation.isZAxisInverted()) {
|
|
let zAxisFlipMatrix = [];
|
|
mat4Identity(zAxisFlipMatrix);
|
|
zAxisFlipMatrix[10] = -1;
|
|
mat4Interpolate(zAxisFlipMatrix, identity, zAxisFlipMatrix, virtualRealInterpolation);
|
|
mat4Multiply(virtualProjectionMatrix, zAxisFlipMatrix, virtualProjectionMatrix);
|
|
}
|
|
|
|
let inverseVirtualProjectionMatrix = [];
|
|
mat4Inverse(inverseVirtualProjectionMatrix, virtualProjectionMatrix);
|
|
|
|
let virtualViewMatrix = [];
|
|
let virtualCameraPosition = [1.2, 1.2, 2];
|
|
let virtualCameraLookAt = [0, 0, -1];
|
|
let virtualCameraUp = [0, 1, 0];
|
|
mat4BuildLookAt(virtualViewMatrix, virtualCameraPosition, virtualCameraLookAt, virtualCameraUp);
|
|
|
|
let inverseVirtualViewMatrix = [];
|
|
mat4Inverse(inverseVirtualViewMatrix, virtualViewMatrix);
|
|
|
|
// interpolated view matrix
|
|
let virtualViewMatrix1 = [];
|
|
mat4BuildLookAt1(virtualViewMatrix1, virtualCameraPosition, virtualCameraLookAt, virtualCameraUp);
|
|
mat4Interpolate(virtualViewMatrix1, identity, virtualViewMatrix1, animation.interpolation(0));
|
|
|
|
let virtualViewMatrix2 = [];
|
|
mat4BuildLookAt2(virtualViewMatrix2, virtualCameraPosition, virtualCameraLookAt, virtualCameraUp);
|
|
mat4Interpolate(virtualViewMatrix2, identity, virtualViewMatrix2, animation.interpolation(1));
|
|
|
|
mat4Multiply(virtualViewMatrix, virtualViewMatrix2, virtualViewMatrix1);
|
|
|
|
// interpolated projection matrix
|
|
mat4Identity(virtualProjectionMatrix);
|
|
|
|
let virtualProjectionMatrix1 = [];
|
|
mat4BuildPerspective1(virtualProjectionMatrix1, 60.0 / 180.0 * Math.PI, cv.width / cv.height, 0.9, 5);
|
|
mat4Interpolate(virtualProjectionMatrix1, identity, virtualProjectionMatrix1, animation.interpolation(2));
|
|
mat4Multiply(virtualProjectionMatrix, virtualProjectionMatrix1, virtualProjectionMatrix);
|
|
|
|
let virtualProjectionMatrix2 = [];
|
|
mat4BuildPerspective2(virtualProjectionMatrix2, 60.0 / 180.0 * Math.PI, cv.width / cv.height, 0.9, 5);
|
|
mat4Interpolate(virtualProjectionMatrix2, identity, virtualProjectionMatrix2, animation.interpolation(3));
|
|
mat4Multiply(virtualProjectionMatrix, virtualProjectionMatrix2, virtualProjectionMatrix);
|
|
|
|
let virtualProjectionMatrix3 = [];
|
|
mat4BuildPerspective3(virtualProjectionMatrix3, 60.0 / 180.0 * Math.PI, cv.width / cv.height, 0.9, 5);
|
|
mat4Interpolate(virtualProjectionMatrix3, identity, virtualProjectionMatrix3, animation.interpolation(4));
|
|
mat4Multiply(virtualProjectionMatrix, virtualProjectionMatrix3, virtualProjectionMatrix);
|
|
|
|
if (!displayMatricesVirtually) {
|
|
let virtualProjectionMatrix4 = [];
|
|
mat4BuildPerspective4(virtualProjectionMatrix4, 60.0 / 180.0 * Math.PI, cv.width / cv.height, 0.9, 5);
|
|
mat4Interpolate(virtualProjectionMatrix4, identity, virtualProjectionMatrix4, animation.interpolation(5));
|
|
mat4Multiply(virtualProjectionMatrix, virtualProjectionMatrix4, virtualProjectionMatrix);
|
|
|
|
}
|
|
|
|
gl.uniformMatrix4fv(virtualProjectionLocation, gl.FALSE, new Float32Array(virtualProjectionMatrix));
|
|
|
|
|
|
let modelMatrix = [];
|
|
mat4Identity(modelMatrix);
|
|
|
|
let modelViewMatrix = [];
|
|
mat4Multiply(modelViewMatrix, virtualViewMatrix, modelMatrix);
|
|
|
|
gl.uniformMatrix4fv(virtualModelViewLocation, gl.FALSE, new Float32Array(modelViewMatrix));
|
|
|
|
|
|
// draw scene
|
|
|
|
// draw H
|
|
gl.useProgram(program);
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, hVertexBuffer);
|
|
setAttribPointers();
|
|
gl.drawArrays(gl.TRIANGLES, 0, hVertices.length / 6);
|
|
|
|
// draw line cube
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, lineCubeVertexBuffer);
|
|
setAttribPointers();
|
|
gl.uniform3fv(colorOverrideLocation, [1, 1, 0.5]);
|
|
gl.drawArrays(gl.LINES, 0, lineCubeVertices.length / 6);
|
|
gl.uniform3fv(colorOverrideLocation, [0, 0, 0]);
|
|
|
|
// draw solid cube 1
|
|
let cube1ModelView = [];
|
|
mat4Identity(cube1ModelView);
|
|
mat4Scale(cube1ModelView, cube1ModelView, [0.3, 0.3, 0.3]);
|
|
mat4RotateY(cube1ModelView, cube1ModelView, 0.3);
|
|
mat4Translate(cube1ModelView, cube1ModelView, [-0.5, 0.3, -0.7]);
|
|
mat4Multiply(cube1ModelView, virtualViewMatrix, cube1ModelView);
|
|
|
|
gl.uniformMatrix4fv(virtualModelViewLocation, gl.FALSE, new Float32Array(cube1ModelView));
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexBuffer);
|
|
setAttribPointers();
|
|
gl.drawArrays(gl.TRIANGLES, 0, cubeVertices.length / 6);
|
|
|
|
// draw solid cube 2
|
|
let cube2ModelView = [];
|
|
mat4Identity(cube2ModelView);
|
|
mat4Scale(cube2ModelView, cube2ModelView, [0.4, 0.4, 0.4]);
|
|
mat4RotateY(cube2ModelView, cube2ModelView, 2.6);
|
|
mat4Translate(cube2ModelView, cube2ModelView, [1.6, 0.3, -1]);
|
|
mat4Multiply(cube2ModelView, virtualViewMatrix, cube2ModelView);
|
|
|
|
gl.uniformMatrix4fv(virtualModelViewLocation, gl.FALSE, new Float32Array(cube2ModelView));
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexBuffer);
|
|
setAttribPointers();
|
|
gl.drawArrays(gl.TRIANGLES, 0, cubeVertices.length / 6);
|
|
|
|
// draw virtual camera
|
|
if (displayMatricesVirtually && animation.isCameraDrawn()) {
|
|
let virtualCameraModelView = [];
|
|
mat4Identity(virtualCameraModelView);
|
|
mat4Scale(virtualCameraModelView, virtualCameraModelView, [0.1, 0.1, 0.1]);
|
|
mat4Translate(virtualCameraModelView, virtualCameraModelView, [0, 0, 0.16]);
|
|
|
|
mat4Multiply(virtualCameraModelView, inverseVirtualViewMatrix, virtualCameraModelView);
|
|
mat4Multiply(virtualCameraModelView, virtualViewMatrix, virtualCameraModelView);
|
|
|
|
gl.uniformMatrix4fv(virtualModelViewLocation, gl.FALSE, new Float32Array(virtualCameraModelView));
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, cameraVertexBuffer);
|
|
setAttribPointers();
|
|
|
|
gl.drawArrays(gl.TRIANGLES, 0, cameraVertices.length / 6);
|
|
}
|
|
|
|
let frustomModelMatrix = [];
|
|
mat4Multiply(frustomModelMatrix, inverseVirtualViewMatrix, inverseVirtualProjectionMatrix);
|
|
mat4Multiply(frustomModelMatrix, virtualViewMatrix, frustomModelMatrix);
|
|
// mat4Copy(inverseVirtualProjectionMatrix, frustomModelMatrix);
|
|
|
|
gl.uniformMatrix4fv(virtualModelViewLocation, gl.FALSE, new Float32Array(frustomModelMatrix));
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, lineCubeVertexBuffer);
|
|
setAttribPointers();
|
|
gl.uniform3fv(colorOverrideLocation, [1, 0, 1]);
|
|
gl.drawArrays(gl.LINES, 0, lineCubeVertices.length / 6);
|
|
gl.uniform3fv(colorOverrideLocation, [0, 0, 0]);
|
|
|
|
|
|
|
|
// draw origin
|
|
let originMatrix = [];
|
|
mat4BuildPerspective4(originMatrix, 60.0 / 180.0 * Math.PI, cv.width / cv.height, 0.9, 5);
|
|
mat4Interpolate(originMatrix, identity, originMatrix, animation.interpolation(5));
|
|
|
|
gl.uniformMatrix4fv(virtualModelViewLocation, gl.FALSE, new Float32Array(originMatrix));
|
|
gl.uniformMatrix4fv(virtualProjectionLocation, gl.FALSE, new Float32Array(identity));
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, originVertexBuffer);
|
|
setAttribPointers();
|
|
gl.drawArrays(gl.LINES, 0, originVertices.length / 6);
|
|
|
|
// draw origin cube
|
|
|
|
if (animation.isOriginCubeDrawn()) {
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, lineCubeVertexBuffer);
|
|
setAttribPointers();
|
|
gl.uniform3fv(colorOverrideLocation, [1, 0, 0]);
|
|
gl.drawArrays(gl.LINES, 0, lineCubeVertices.length / 6);
|
|
gl.uniform3fv(colorOverrideLocation, [0, 0, 0]);
|
|
}
|
|
|
|
// draw floor
|
|
|
|
gl.useProgram(floorProgram);
|
|
|
|
let floorModelView = [];
|
|
mat4Identity(floorModelView);
|
|
mat4Scale(floorModelView, floorModelView, [10, 0, 10]);
|
|
mat4Multiply(floorModelView, realViewMatrix, floorModelView);
|
|
gl.uniformMatrix4fv(gl.getUniformLocation(floorProgram, "realModelViewMatrix"), gl.FALSE, new Float32Array(floorModelView));
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, floorVertexBuffer);
|
|
setAttribPointers();
|
|
gl.drawArrays(gl.TRIANGLES, 0, floorVertices.length / 6);
|
|
|
|
|
|
frameTimes.push(performance.now() - frameStart);
|
|
lastFrame = now;
|
|
requestAnimationFrame(draw);
|
|
}
|
|
|
|
function hexToRgb(hex) {
|
|
let r = parseInt(hex.substring(0, 2), 16) / 255;
|
|
let g = parseInt(hex.substring(2, 4), 16) / 255;
|
|
let b = parseInt(hex.substring(4, 6), 16) / 255;
|
|
|
|
return [r, g, b];
|
|
}
|
|
|
|
|
|
window.addEventListener("DOMContentLoaded", init); |