gpu-curtains
Version:
gpu-curtains is a 3D WebGPU rendering engine. It can be used as a standalone 3D engine, but also includes extra classes focused on mapping 3d objects to DOM elements; It allows users to synchronize values such as position, sizing, or scale between them.
206 lines (205 loc) • 5.6 kB
JavaScript
import { generateUUID } from "../../utils/utils.mjs";
import { Vec3 } from "../../math/Vec3.mjs";
import { Mat4 } from "../../math/Mat4.mjs";
import { Object3D } from "../objects3D/Object3D.mjs";
//#region src/core/cameras/Camera.ts
/**
* Used as a base class to create a {@link Camera}.
*
* This class is not made to be used directly, you should use the {@link core/cameras/PerspectiveCamera.PerspectiveCamera | PerspectiveCamera} or {@link core/cameras/OrthographicCamera.OrthographicCamera | OrthographicCamera} classes instead.
*/
var Camera = class extends Object3D {
/** @ignore */
#near;
/** @ignore */
#far;
/** @ignore */
#pixelRatio;
/**
* Camera constructor
* @param parameters - {@link CameraParams} used to create our {@link Camera}.
*/
constructor({ label = "Camera", near = .1, far = 150, pixelRatio = 1, onMatricesChanged = () => {} } = {}) {
super();
this.label = label;
this.uuid = generateUUID();
this.onMatricesChanged = onMatricesChanged;
}
/**
* Set our transform and projection matrices.
*/
setMatrices() {
super.setMatrices();
this.matrices = {
...this.matrices,
view: {
matrix: new Mat4(),
shouldUpdate: true,
onUpdate: () => {
this.viewMatrix.copy(this.worldMatrix).invert();
}
},
projection: {
matrix: new Mat4(),
shouldUpdate: true,
onUpdate: () => this.updateProjectionMatrix()
},
viewProjection: {
matrix: new Mat4(),
shouldUpdate: true,
onUpdate: () => this.viewProjectionMatrix.multiplyMatrices(this.projectionMatrix, this.viewMatrix)
}
};
}
/**
* Get our view matrix.
* @readonly
*/
get viewMatrix() {
return this.matrices.view.matrix;
}
set viewMatrix(value) {
this.matrices.view.matrix = value;
this.shouldUpdateViewMatrices();
}
/**
* Get our projection matrix.
* @readonly
*/
get projectionMatrix() {
return this.matrices.projection.matrix;
}
set projectionMatrix(value) {
this.matrices.projection.matrix = value;
this.shouldUpdateProjectionMatrices();
}
/**
* Get our view projection matrix.
* @readonly
*/
get viewProjectionMatrix() {
return this.matrices.viewProjection.matrix;
}
/**
* Set our view dependent matrices shouldUpdate flag to `true` (tell it to update).
*/
shouldUpdateViewMatrices() {
this.matrices.view.shouldUpdate = true;
this.matrices.viewProjection.shouldUpdate = true;
}
/**
* Set our projection dependent matrices shouldUpdate flag to `true` (tell it to update).
*/
shouldUpdateProjectionMatrices() {
this.matrices.projection.shouldUpdate = true;
this.matrices.viewProjection.shouldUpdate = true;
}
/**
* Update our model matrix and tell our view matrix to update as well.
*/
updateModelMatrix() {
super.updateModelMatrix();
this.setVisibleSize();
this.shouldUpdateViewMatrices();
}
/**
* Update our view matrix whenever we need to update the world matrix.
*/
shouldUpdateWorldMatrix() {
super.shouldUpdateWorldMatrix();
this.shouldUpdateViewMatrices();
}
/**
* Callback to run when the camera {@link modelMatrix | model matrix} has been updated.
*/
updateMatrixStack() {
super.updateMatrixStack();
if (this.matricesNeedUpdate) this.onMatricesChanged();
}
/**
* Get the {@link Camera.near | near} plane value.
*/
get near() {
return this.#near;
}
/**
* Set the {@link Camera.near | near} plane value. Update the {@link projectionMatrix} only if the near plane actually changed.
* @param near - New near plane value.
*/
set near(near) {
near = Math.max(near ?? this.near, 1e-4);
if (near !== this.near) {
this.#near = near;
this.shouldUpdateProjectionMatrices();
}
}
/**
* Get the {@link Camera.far | far} plane value.
*/
get far() {
return this.#far;
}
/**
* Set the {@link Camera.far | far} plane value. Update {@link projectionMatrix} only if the far plane actually changed.
* @param far - New far plane value.
*/
set far(far) {
far = Math.max(far ?? this.far, this.near + 1);
if (far !== this.far) {
this.#far = far;
this.shouldUpdateProjectionMatrices();
}
}
/**
* Get the {@link Camera.pixelRatio | pixelRatio} value.
*/
get pixelRatio() {
return this.#pixelRatio;
}
/**
* Set the {@link Camera.pixelRatio | pixelRatio} value. Update the {@link CSSPerspective} only if the pixel ratio actually changed.
* @param pixelRatio - New pixel ratio value.
*/
set pixelRatio(pixelRatio) {
this.#pixelRatio = pixelRatio ?? this.pixelRatio;
this.setCSSPerspective();
}
/** @ignore */
setCSSPerspective() {
this.CSSPerspective = 0;
}
/**
* Get visible width / height at a given z-depth from our {@link Camera} parameters. Useless for this base class, but will be overriden by children classes.
* @param depth - Depth to use for calculations.
* @returns - Visible width and height at given depth.
*/
getVisibleSizeAtDepth(depth = 0) {
return {
width: 0,
height: 0
};
}
/**
* Sets visible width / height at a depth of 0.
*/
setVisibleSize() {
this.visibleSize = this.getVisibleSizeAtDepth();
}
/**
* Rotate this {@link Camera} so it looks at the {@link Vec3 | target}.
* @param target - {@link Vec3} to look at. Default to `new Vec3()`.
*/
lookAt(target = new Vec3()) {
this.updateModelMatrix();
this.updateWorldMatrix(true, false);
if (this.actualPosition.x === 0 && this.actualPosition.y !== 0 && this.actualPosition.z === 0) this.up.set(0, 0, 1);
else this.up.set(0, 1, 0);
this.applyLookAt(this.actualPosition, target);
}
/**
* Updates the {@link Camera} {@link projectionMatrix}.
*/
updateProjectionMatrix() {}
};
//#endregion
export { Camera };