pex-cam
Version:
Cameras models and controllers for 3D rendering in PEX.
108 lines (94 loc) • 2.6 kB
JavaScript
import { mat4, vec3 } from "pex-math";
import Camera from "./camera.js";
/**
* A class to create an orthographic camera
* @augments Camera
*/
class OrthographicCamera extends Camera {
static get DEFAULT_OPTIONS() {
return {
left: -1,
right: 1,
bottom: -1,
top: 1,
zoom: 1,
};
}
/**
* Create an instance of PerspectiveCamera
* @param {import("./types.js").CameraOptions & import("./types.js").OrthographicCameraOptions} opts
*/
constructor(opts = {}) {
super();
this.set({
...Camera.DEFAULT_OPTIONS,
...OrthographicCamera.DEFAULT_OPTIONS,
...opts,
});
}
/**
* Update the camera
* @param {import("./types.js").CameraOptions & import("./types.js").OrthographicCameraOptions} opts
*/
set(opts) {
super.set(opts);
if (
opts.left ||
opts.right ||
opts.bottom ||
opts.top ||
opts.zoom ||
opts.near ||
opts.far ||
opts.view
) {
const dx = (this.right - this.left) / (2 / this.zoom);
const dy = (this.top - this.bottom) / (2 / this.zoom);
const cx = (this.right + this.left) / 2;
const cy = (this.top + this.bottom) / 2;
let left = cx - dx;
let right = cx + dx;
let top = cy + dy;
let bottom = cy - dy;
if (this.view) {
const zoomW =
1 / this.zoom / (this.view.size[0] / this.view.totalSize[0]);
const zoomH =
1 / this.zoom / (this.view.size[1] / this.view.totalSize[1]);
const scaleW = (this.right - this.left) / this.view.size[0];
const scaleH = (this.top - this.bottom) / this.view.size[1];
left += scaleW * (this.view.offset[0] / zoomW);
right = left + scaleW * (this.view.size[0] / zoomW);
top -= scaleH * (this.view.offset[1] / zoomH);
bottom = top - scaleH * (this.view.size[1] / zoomH);
}
mat4.ortho(
this.projectionMatrix,
left,
right,
bottom,
top,
this.near,
this.far,
);
}
}
getViewRay(x, y, windowWidth, windowHeight) {
if (this.view) {
x += this.view.offset[0];
y += this.view.offset[1];
windowWidth = this.view.totalSize[0];
windowHeight = this.view.totalSize[1];
}
// [origin, direction]
return [
[0, 0, 0],
vec3.normalize([
(x * (this.right - this.left)) / this.zoom / windowWidth,
((1 - y) * (this.top - this.bottom)) / this.zoom / windowHeight,
-this.near,
]),
];
}
}
export default OrthographicCamera;