@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
98 lines • 8.37 kB
JavaScript
/* eslint-disable unicorn/prefer-single-call */
import { TgdMat4, TgdVec3 } from "./../math/index.js";
import { mat4 } from "gl-matrix";
import { TgdCamera } from "./camera.js";
export class TgdCameraPerspective extends TgdCamera {
constructor(options = {}) {
super(options);
this._matrixProjection = new TgdMat4();
this._fovy = Math.PI / 4;
this._ray = {
origin: new TgdVec3(),
direction: new TgdVec3(),
};
this._fovy = options.fovy ?? Math.PI / 4;
}
clone() {
const camera = new TgdCameraPerspective({
transfo: this.transfo.clone(),
});
camera.screenWidth = this.screenWidth;
camera.screenHeight = this.screenHeight;
camera.near = this.near;
camera.far = this.far;
camera.fovy = this.fovy;
return camera;
}
copyProjectionFrom(camera) {
this.fovy = camera.fovy;
this.near = camera.near;
this.far = camera.far;
return this;
}
castRay(screenX, screenY) {
const { transfo } = this;
const { origin, direction } = this._ray;
origin.from(transfo.actualPosition);
const h = Math.atan(this.fovy * 0.5);
const w = h * this.screenAspectRatio;
direction
.fromOpposite(transfo.axisZ)
.addWithScale(transfo.axisX, w * screenX)
.addWithScale(transfo.axisY, h * screenY)
.normalize();
return this._ray;
}
/**
* Vertical field of view in radians.
*
* The revealed space at a distance of 1 from the camera
* will have a height of `2 * tan(fovy / 2)`.
*/
get fovy() {
return this._fovy;
}
set fovy(v) {
if (v === this._fovy)
return;
this._fovy = v;
this.dirtyProjection = true;
}
get matrixProjection() {
this.updateProjectionIfNeeded();
return this._matrixProjection;
}
getSpaceHeightAtTarget() {
return 2 * Math.tan(this.fovy * 0.5) * this.transfo.distance;
}
setSpaceHeightAtTarget(v) {
this.transfo.setDistance(v / (2 * Math.tan(this.fovy * 0.5)));
}
updateProjectionIfNeeded() {
if (!this.dirtyProjection)
return;
const fovy = this._fovy;
const aspect = this.screenAspectRatio;
const near = this._near;
const far = this._far;
const out = this._matrixProjection;
mat4.perspective(out, fovy, aspect, near, far);
out[0] *= this.zoom;
out[5] *= this.zoom;
this.dirtyProjection = true;
}
toCode(caption) {
const code = [];
if (caption)
code.push(`// ${caption}`);
code.push("const camera = new TgdCameraPerspective({");
if (this.name)
code.push(` name: ${JSON.stringify(this.name)},`);
code.push(` fovy: ${this._fovy},`, ` near: ${this._near},`, ` far: ${this._far},`, ` zoom: ${this.zoom},`, " transfo: {", ` distance: ${this.transfo.distance},`);
code.push(` position: ${JSON.stringify([...this.transfo.position])},`);
code.push(` orientation: ${JSON.stringify([...this.transfo.orientation])},`);
code.push(` scale: ${JSON.stringify([...this.transfo.scale])},`, " }", "}");
return code.join("\n");
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FtZXJhLXBlcnNwZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NhbWVyYS9jYW1lcmEtcGVyc3BlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFBO0FBQzVDLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxXQUFXLENBQUE7QUFDaEMsT0FBTyxFQUFFLFNBQVMsRUFBeUIsTUFBTSxVQUFVLENBQUE7QUFZM0QsTUFBTSxPQUFPLG9CQUFxQixTQUFRLFNBQVM7SUFRL0MsWUFBWSxVQUF1QyxFQUFFO1FBQ2pELEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQVJELHNCQUFpQixHQUFHLElBQUksT0FBTyxFQUFFLENBQUE7UUFDMUMsVUFBSyxHQUFHLElBQUksQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFBO1FBQ1YsU0FBSSxHQUFHO1lBQ3BCLE1BQU0sRUFBRSxJQUFJLE9BQU8sRUFBRTtZQUNyQixTQUFTLEVBQUUsSUFBSSxPQUFPLEVBQUU7U0FDM0IsQ0FBQTtRQUlHLElBQUksQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQTtJQUM1QyxDQUFDO0lBRUQsS0FBSztRQUNELE1BQU0sTUFBTSxHQUFHLElBQUksb0JBQW9CLENBQUM7WUFDcEMsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFO1NBQ2hDLENBQUMsQ0FBQTtRQUNGLE1BQU0sQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQTtRQUNyQyxNQUFNLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUE7UUFDdkMsTUFBTSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFBO1FBQ3ZCLE1BQU0sQ0FBQyxHQUFHLEdBQUcsSUFB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