import { Telemetry } from "../renderer/telemetry";
import { mat4 } from "gl-matrix";
export class App {
constructor(
config = {
fov: 45,
}
) {
this._now = 0;
this.registry = {
onStart: [],
onUpdate: [],
onBeforeUpdate: [],
onAfterUpdate: [],
};
this.config = config;
this.canvas = document.querySelector("canvas");
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.gl = this.canvas.getContext("webgl2");
if (this.gl === null) {
document.querySelector(
"main"
).innerHTML = `
your browser didn't let me set up webgl
`;
throw new Error(
"Unable to initialize WebGL. Your browser or machine may not support it."
);
}
const gl = this.gl;
const fieldOfView = (this.config.fov * Math.PI) / 180; // in radians
const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
const zNear = 0.1;
const zFar = 100.0;
const projectionMatrix = mat4.create();
mat4.perspective(projectionMatrix, fieldOfView, aspect, zNear, zFar);
const modelViewMatrix = mat4.create();
mat4.translate(modelViewMatrix, modelViewMatrix, [-0.0, 0.0, -6.0]);
this.projectionMatrix = projectionMatrix;
this.modelViewMatrix = modelViewMatrix;
this.clear();
this.onBeforeUpdate(() => this.clear());
this.telemetry = new Telemetry(this);
}
clear() {
const gl = this.gl;
gl.clearColor(0.0, 0.0, 0.0, 1.0); // Clear to black, fully opaque
gl.clearDepth(1.0); // Clear everything
gl.enable(gl.DEPTH_TEST); // Enable depth testing
gl.depthFunc(gl.LEQUAL); // Near things obscure far things
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
}
onStart(fn) {
this.registry.onStart.push(fn);
}
onUpdate(fn) {
this.registry.onUpdate.push(fn);
}
onBeforeUpdate(fn) {
this.registry.onBeforeUpdate.push(fn);
}
onAfterUpdate(fn) {
this.registry.onAfterUpdate.push(fn);
}
start() {
this.registry.onStart.forEach((fn) => fn(this));
}
update() {
this.registry.onBeforeUpdate.forEach((fn) => fn(this));
this.registry.onUpdate.forEach((fn) => fn(this));
this.registry.onAfterUpdate.forEach((fn) => fn(this));
}
oneShot() {
requestAnimationFrame((now) => {
this._now = now;
this.start();
this.update();
});
}
loop() {
const run = (now) => {
this._now = now;
this.update();
requestAnimationFrame(run);
};
requestAnimationFrame(run);
}
now() {
return this._now;
}
}