UNPKG

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
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 };