first app vibe
This commit is contained in:
54
app/node_modules/three/src/cameras/ArrayCamera.js
generated
vendored
Normal file
54
app/node_modules/three/src/cameras/ArrayCamera.js
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
import { PerspectiveCamera } from './PerspectiveCamera.js';
|
||||
|
||||
/**
|
||||
* This type of camera can be used in order to efficiently render a scene with a
|
||||
* predefined set of cameras. This is an important performance aspect for
|
||||
* rendering VR scenes.
|
||||
*
|
||||
* An instance of `ArrayCamera` always has an array of sub cameras. It's mandatory
|
||||
* to define for each sub camera the `viewport` property which determines the
|
||||
* part of the viewport that is rendered with this camera.
|
||||
*
|
||||
* @augments PerspectiveCamera
|
||||
*/
|
||||
class ArrayCamera extends PerspectiveCamera {
|
||||
|
||||
/**
|
||||
* Constructs a new array camera.
|
||||
*
|
||||
* @param {Array<PerspectiveCamera>} [array=[]] - An array of perspective sub cameras.
|
||||
*/
|
||||
constructor( array = [] ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isArrayCamera = true;
|
||||
|
||||
/**
|
||||
* Whether this camera is used with multiview rendering or not.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default false
|
||||
*/
|
||||
this.isMultiViewCamera = false;
|
||||
|
||||
/**
|
||||
* An array of perspective sub cameras.
|
||||
*
|
||||
* @type {Array<PerspectiveCamera>}
|
||||
*/
|
||||
this.cameras = array;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { ArrayCamera };
|
||||
116
app/node_modules/three/src/cameras/Camera.js
generated
vendored
Normal file
116
app/node_modules/three/src/cameras/Camera.js
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
import { WebGLCoordinateSystem } from '../constants.js';
|
||||
import { Matrix4 } from '../math/Matrix4.js';
|
||||
import { Object3D } from '../core/Object3D.js';
|
||||
|
||||
/**
|
||||
* Abstract base class for cameras. This class should always be inherited
|
||||
* when you build a new camera.
|
||||
*
|
||||
* @abstract
|
||||
* @augments Object3D
|
||||
*/
|
||||
class Camera extends Object3D {
|
||||
|
||||
/**
|
||||
* Constructs a new camera.
|
||||
*/
|
||||
constructor() {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isCamera = true;
|
||||
|
||||
this.type = 'Camera';
|
||||
|
||||
/**
|
||||
* The inverse of the camera's world matrix.
|
||||
*
|
||||
* @type {Matrix4}
|
||||
*/
|
||||
this.matrixWorldInverse = new Matrix4();
|
||||
|
||||
/**
|
||||
* The camera's projection matrix.
|
||||
*
|
||||
* @type {Matrix4}
|
||||
*/
|
||||
this.projectionMatrix = new Matrix4();
|
||||
|
||||
/**
|
||||
* The inverse of the camera's projection matrix.
|
||||
*
|
||||
* @type {Matrix4}
|
||||
*/
|
||||
this.projectionMatrixInverse = new Matrix4();
|
||||
|
||||
/**
|
||||
* The coordinate system in which the camera is used.
|
||||
*
|
||||
* @type {(WebGLCoordinateSystem|WebGPUCoordinateSystem)}
|
||||
*/
|
||||
this.coordinateSystem = WebGLCoordinateSystem;
|
||||
|
||||
}
|
||||
|
||||
copy( source, recursive ) {
|
||||
|
||||
super.copy( source, recursive );
|
||||
|
||||
this.matrixWorldInverse.copy( source.matrixWorldInverse );
|
||||
|
||||
this.projectionMatrix.copy( source.projectionMatrix );
|
||||
this.projectionMatrixInverse.copy( source.projectionMatrixInverse );
|
||||
|
||||
this.coordinateSystem = source.coordinateSystem;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a vector representing the ("look") direction of the 3D object in world space.
|
||||
*
|
||||
* This method is overwritten since cameras have a different forward vector compared to other
|
||||
* 3D objects. A camera looks down its local, negative z-axis by default.
|
||||
*
|
||||
* @param {Vector3} target - The target vector the result is stored to.
|
||||
* @return {Vector3} The 3D object's direction in world space.
|
||||
*/
|
||||
getWorldDirection( target ) {
|
||||
|
||||
return super.getWorldDirection( target ).negate();
|
||||
|
||||
}
|
||||
|
||||
updateMatrixWorld( force ) {
|
||||
|
||||
super.updateMatrixWorld( force );
|
||||
|
||||
this.matrixWorldInverse.copy( this.matrixWorld ).invert();
|
||||
|
||||
}
|
||||
|
||||
updateWorldMatrix( updateParents, updateChildren ) {
|
||||
|
||||
super.updateWorldMatrix( updateParents, updateChildren );
|
||||
|
||||
this.matrixWorldInverse.copy( this.matrixWorld ).invert();
|
||||
|
||||
}
|
||||
|
||||
clone() {
|
||||
|
||||
return new this.constructor().copy( this );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { Camera };
|
||||
239
app/node_modules/three/src/cameras/CubeCamera.js
generated
vendored
Normal file
239
app/node_modules/three/src/cameras/CubeCamera.js
generated
vendored
Normal file
@@ -0,0 +1,239 @@
|
||||
import { WebGLCoordinateSystem, WebGPUCoordinateSystem } from '../constants.js';
|
||||
import { Object3D } from '../core/Object3D.js';
|
||||
import { PerspectiveCamera } from './PerspectiveCamera.js';
|
||||
|
||||
const fov = - 90; // negative fov is not an error
|
||||
const aspect = 1;
|
||||
|
||||
/**
|
||||
* A special type of camera that is positioned in 3D space to render its surroundings into a
|
||||
* cube render target. The render target can then be used as an environment map for rendering
|
||||
* realtime reflections in your scene.
|
||||
*
|
||||
* ```js
|
||||
* // Create cube render target
|
||||
* const cubeRenderTarget = new THREE.WebGLCubeRenderTarget( 256, { generateMipmaps: true, minFilter: THREE.LinearMipmapLinearFilter } );
|
||||
*
|
||||
* // Create cube camera
|
||||
* const cubeCamera = new THREE.CubeCamera( 1, 100000, cubeRenderTarget );
|
||||
* scene.add( cubeCamera );
|
||||
*
|
||||
* // Create car
|
||||
* const chromeMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff, envMap: cubeRenderTarget.texture } );
|
||||
* const car = new THREE.Mesh( carGeometry, chromeMaterial );
|
||||
* scene.add( car );
|
||||
*
|
||||
* // Update the render target cube
|
||||
* car.visible = false;
|
||||
* cubeCamera.position.copy( car.position );
|
||||
* cubeCamera.update( renderer, scene );
|
||||
*
|
||||
* // Render the scene
|
||||
* car.visible = true;
|
||||
* renderer.render( scene, camera );
|
||||
* ```
|
||||
*
|
||||
* @augments Object3D
|
||||
*/
|
||||
class CubeCamera extends Object3D {
|
||||
|
||||
/**
|
||||
* Constructs a new cube camera.
|
||||
*
|
||||
* @param {number} near - The camera's near plane.
|
||||
* @param {number} far - The camera's far plane.
|
||||
* @param {WebGLCubeRenderTarget} renderTarget - The cube render target.
|
||||
*/
|
||||
constructor( near, far, renderTarget ) {
|
||||
|
||||
super();
|
||||
|
||||
this.type = 'CubeCamera';
|
||||
|
||||
/**
|
||||
* A reference to the cube render target.
|
||||
*
|
||||
* @type {WebGLCubeRenderTarget}
|
||||
*/
|
||||
this.renderTarget = renderTarget;
|
||||
|
||||
/**
|
||||
* The current active coordinate system.
|
||||
*
|
||||
* @type {?(WebGLCoordinateSystem|WebGPUCoordinateSystem)}
|
||||
* @default null
|
||||
*/
|
||||
this.coordinateSystem = null;
|
||||
|
||||
/**
|
||||
* The current active mipmap level
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0
|
||||
*/
|
||||
this.activeMipmapLevel = 0;
|
||||
|
||||
const cameraPX = new PerspectiveCamera( fov, aspect, near, far );
|
||||
cameraPX.layers = this.layers;
|
||||
this.add( cameraPX );
|
||||
|
||||
const cameraNX = new PerspectiveCamera( fov, aspect, near, far );
|
||||
cameraNX.layers = this.layers;
|
||||
this.add( cameraNX );
|
||||
|
||||
const cameraPY = new PerspectiveCamera( fov, aspect, near, far );
|
||||
cameraPY.layers = this.layers;
|
||||
this.add( cameraPY );
|
||||
|
||||
const cameraNY = new PerspectiveCamera( fov, aspect, near, far );
|
||||
cameraNY.layers = this.layers;
|
||||
this.add( cameraNY );
|
||||
|
||||
const cameraPZ = new PerspectiveCamera( fov, aspect, near, far );
|
||||
cameraPZ.layers = this.layers;
|
||||
this.add( cameraPZ );
|
||||
|
||||
const cameraNZ = new PerspectiveCamera( fov, aspect, near, far );
|
||||
cameraNZ.layers = this.layers;
|
||||
this.add( cameraNZ );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Must be called when the coordinate system of the cube camera is changed.
|
||||
*/
|
||||
updateCoordinateSystem() {
|
||||
|
||||
const coordinateSystem = this.coordinateSystem;
|
||||
|
||||
const cameras = this.children.concat();
|
||||
|
||||
const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = cameras;
|
||||
|
||||
for ( const camera of cameras ) this.remove( camera );
|
||||
|
||||
if ( coordinateSystem === WebGLCoordinateSystem ) {
|
||||
|
||||
cameraPX.up.set( 0, 1, 0 );
|
||||
cameraPX.lookAt( 1, 0, 0 );
|
||||
|
||||
cameraNX.up.set( 0, 1, 0 );
|
||||
cameraNX.lookAt( - 1, 0, 0 );
|
||||
|
||||
cameraPY.up.set( 0, 0, - 1 );
|
||||
cameraPY.lookAt( 0, 1, 0 );
|
||||
|
||||
cameraNY.up.set( 0, 0, 1 );
|
||||
cameraNY.lookAt( 0, - 1, 0 );
|
||||
|
||||
cameraPZ.up.set( 0, 1, 0 );
|
||||
cameraPZ.lookAt( 0, 0, 1 );
|
||||
|
||||
cameraNZ.up.set( 0, 1, 0 );
|
||||
cameraNZ.lookAt( 0, 0, - 1 );
|
||||
|
||||
} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
|
||||
|
||||
cameraPX.up.set( 0, - 1, 0 );
|
||||
cameraPX.lookAt( - 1, 0, 0 );
|
||||
|
||||
cameraNX.up.set( 0, - 1, 0 );
|
||||
cameraNX.lookAt( 1, 0, 0 );
|
||||
|
||||
cameraPY.up.set( 0, 0, 1 );
|
||||
cameraPY.lookAt( 0, 1, 0 );
|
||||
|
||||
cameraNY.up.set( 0, 0, - 1 );
|
||||
cameraNY.lookAt( 0, - 1, 0 );
|
||||
|
||||
cameraPZ.up.set( 0, - 1, 0 );
|
||||
cameraPZ.lookAt( 0, 0, 1 );
|
||||
|
||||
cameraNZ.up.set( 0, - 1, 0 );
|
||||
cameraNZ.lookAt( 0, 0, - 1 );
|
||||
|
||||
} else {
|
||||
|
||||
throw new Error( 'THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: ' + coordinateSystem );
|
||||
|
||||
}
|
||||
|
||||
for ( const camera of cameras ) {
|
||||
|
||||
this.add( camera );
|
||||
|
||||
camera.updateMatrixWorld();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Calling this method will render the given scene with the given renderer
|
||||
* into the cube render target of the camera.
|
||||
*
|
||||
* @param {(Renderer|WebGLRenderer)} renderer - The renderer.
|
||||
* @param {Scene} scene - The scene to render.
|
||||
*/
|
||||
update( renderer, scene ) {
|
||||
|
||||
if ( this.parent === null ) this.updateMatrixWorld();
|
||||
|
||||
const { renderTarget, activeMipmapLevel } = this;
|
||||
|
||||
if ( this.coordinateSystem !== renderer.coordinateSystem ) {
|
||||
|
||||
this.coordinateSystem = renderer.coordinateSystem;
|
||||
|
||||
this.updateCoordinateSystem();
|
||||
|
||||
}
|
||||
|
||||
const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = this.children;
|
||||
|
||||
const currentRenderTarget = renderer.getRenderTarget();
|
||||
const currentActiveCubeFace = renderer.getActiveCubeFace();
|
||||
const currentActiveMipmapLevel = renderer.getActiveMipmapLevel();
|
||||
|
||||
const currentXrEnabled = renderer.xr.enabled;
|
||||
|
||||
renderer.xr.enabled = false;
|
||||
|
||||
const generateMipmaps = renderTarget.texture.generateMipmaps;
|
||||
|
||||
renderTarget.texture.generateMipmaps = false;
|
||||
|
||||
renderer.setRenderTarget( renderTarget, 0, activeMipmapLevel );
|
||||
renderer.render( scene, cameraPX );
|
||||
|
||||
renderer.setRenderTarget( renderTarget, 1, activeMipmapLevel );
|
||||
renderer.render( scene, cameraNX );
|
||||
|
||||
renderer.setRenderTarget( renderTarget, 2, activeMipmapLevel );
|
||||
renderer.render( scene, cameraPY );
|
||||
|
||||
renderer.setRenderTarget( renderTarget, 3, activeMipmapLevel );
|
||||
renderer.render( scene, cameraNY );
|
||||
|
||||
renderer.setRenderTarget( renderTarget, 4, activeMipmapLevel );
|
||||
renderer.render( scene, cameraPZ );
|
||||
|
||||
// mipmaps are generated during the last call of render()
|
||||
// at this point, all sides of the cube render target are defined
|
||||
|
||||
renderTarget.texture.generateMipmaps = generateMipmaps;
|
||||
|
||||
renderer.setRenderTarget( renderTarget, 5, activeMipmapLevel );
|
||||
renderer.render( scene, cameraNZ );
|
||||
|
||||
renderer.setRenderTarget( currentRenderTarget, currentActiveCubeFace, currentActiveMipmapLevel );
|
||||
|
||||
renderer.xr.enabled = currentXrEnabled;
|
||||
|
||||
renderTarget.texture.needsPMREMUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { CubeCamera };
|
||||
245
app/node_modules/three/src/cameras/OrthographicCamera.js
generated
vendored
Executable file
245
app/node_modules/three/src/cameras/OrthographicCamera.js
generated
vendored
Executable file
@@ -0,0 +1,245 @@
|
||||
import { Camera } from './Camera.js';
|
||||
|
||||
/**
|
||||
* Camera that uses [orthographic projection]{@link https://en.wikipedia.org/wiki/Orthographic_projection}.
|
||||
*
|
||||
* In this projection mode, an object's size in the rendered image stays
|
||||
* constant regardless of its distance from the camera. This can be useful
|
||||
* for rendering 2D scenes and UI elements, amongst other things.
|
||||
*
|
||||
* ```js
|
||||
* const camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 1, 1000 );
|
||||
* scene.add( camera );
|
||||
* ```
|
||||
*
|
||||
* @augments Camera
|
||||
*/
|
||||
class OrthographicCamera extends Camera {
|
||||
|
||||
/**
|
||||
* Constructs a new orthographic camera.
|
||||
*
|
||||
* @param {number} [left=-1] - The left plane of the camera's frustum.
|
||||
* @param {number} [right=1] - The right plane of the camera's frustum.
|
||||
* @param {number} [top=1] - The top plane of the camera's frustum.
|
||||
* @param {number} [bottom=-1] - The bottom plane of the camera's frustum.
|
||||
* @param {number} [near=0.1] - The camera's near plane.
|
||||
* @param {number} [far=2000] - The camera's far plane.
|
||||
*/
|
||||
constructor( left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000 ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isOrthographicCamera = true;
|
||||
|
||||
this.type = 'OrthographicCamera';
|
||||
|
||||
/**
|
||||
* The zoom factor of the camera.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 1
|
||||
*/
|
||||
this.zoom = 1;
|
||||
|
||||
/**
|
||||
* Represents the frustum window specification. This property should not be edited
|
||||
* directly but via {@link PerspectiveCamera#setViewOffset} and {@link PerspectiveCamera#clearViewOffset}.
|
||||
*
|
||||
* @type {?Object}
|
||||
* @default null
|
||||
*/
|
||||
this.view = null;
|
||||
|
||||
/**
|
||||
* The left plane of the camera's frustum.
|
||||
*
|
||||
* @type {number}
|
||||
* @default -1
|
||||
*/
|
||||
this.left = left;
|
||||
|
||||
/**
|
||||
* The right plane of the camera's frustum.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 1
|
||||
*/
|
||||
this.right = right;
|
||||
|
||||
/**
|
||||
* The top plane of the camera's frustum.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 1
|
||||
*/
|
||||
this.top = top;
|
||||
|
||||
/**
|
||||
* The bottom plane of the camera's frustum.
|
||||
*
|
||||
* @type {number}
|
||||
* @default -1
|
||||
*/
|
||||
this.bottom = bottom;
|
||||
|
||||
/**
|
||||
* The camera's near plane. The valid range is greater than `0`
|
||||
* and less than the current value of {@link OrthographicCamera#far}.
|
||||
*
|
||||
* Note that, unlike for the {@link PerspectiveCamera}, `0` is a
|
||||
* valid value for an orthographic camera's near plane.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0.1
|
||||
*/
|
||||
this.near = near;
|
||||
|
||||
/**
|
||||
* The camera's far plane. Must be greater than the
|
||||
* current value of {@link OrthographicCamera#near}.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 2000
|
||||
*/
|
||||
this.far = far;
|
||||
|
||||
this.updateProjectionMatrix();
|
||||
|
||||
}
|
||||
|
||||
copy( source, recursive ) {
|
||||
|
||||
super.copy( source, recursive );
|
||||
|
||||
this.left = source.left;
|
||||
this.right = source.right;
|
||||
this.top = source.top;
|
||||
this.bottom = source.bottom;
|
||||
this.near = source.near;
|
||||
this.far = source.far;
|
||||
|
||||
this.zoom = source.zoom;
|
||||
this.view = source.view === null ? null : Object.assign( {}, source.view );
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an offset in a larger frustum. This is useful for multi-window or
|
||||
* multi-monitor/multi-machine setups.
|
||||
*
|
||||
* @param {number} fullWidth - The full width of multiview setup.
|
||||
* @param {number} fullHeight - The full height of multiview setup.
|
||||
* @param {number} x - The horizontal offset of the subcamera.
|
||||
* @param {number} y - The vertical offset of the subcamera.
|
||||
* @param {number} width - The width of subcamera.
|
||||
* @param {number} height - The height of subcamera.
|
||||
* @see {@link PerspectiveCamera#setViewOffset}
|
||||
*/
|
||||
setViewOffset( fullWidth, fullHeight, x, y, width, height ) {
|
||||
|
||||
if ( this.view === null ) {
|
||||
|
||||
this.view = {
|
||||
enabled: true,
|
||||
fullWidth: 1,
|
||||
fullHeight: 1,
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
width: 1,
|
||||
height: 1
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
this.view.enabled = true;
|
||||
this.view.fullWidth = fullWidth;
|
||||
this.view.fullHeight = fullHeight;
|
||||
this.view.offsetX = x;
|
||||
this.view.offsetY = y;
|
||||
this.view.width = width;
|
||||
this.view.height = height;
|
||||
|
||||
this.updateProjectionMatrix();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the view offset from the projection matrix.
|
||||
*/
|
||||
clearViewOffset() {
|
||||
|
||||
if ( this.view !== null ) {
|
||||
|
||||
this.view.enabled = false;
|
||||
|
||||
}
|
||||
|
||||
this.updateProjectionMatrix();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the camera's projection matrix. Must be called after any change of
|
||||
* camera properties.
|
||||
*/
|
||||
updateProjectionMatrix() {
|
||||
|
||||
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 !== null && this.view.enabled ) {
|
||||
|
||||
const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom;
|
||||
const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom;
|
||||
|
||||
left += scaleW * this.view.offsetX;
|
||||
right = left + scaleW * this.view.width;
|
||||
top -= scaleH * this.view.offsetY;
|
||||
bottom = top - scaleH * this.view.height;
|
||||
|
||||
}
|
||||
|
||||
this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, this.coordinateSystem );
|
||||
|
||||
this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
|
||||
|
||||
}
|
||||
|
||||
toJSON( meta ) {
|
||||
|
||||
const data = super.toJSON( meta );
|
||||
|
||||
data.object.zoom = this.zoom;
|
||||
data.object.left = this.left;
|
||||
data.object.right = this.right;
|
||||
data.object.top = this.top;
|
||||
data.object.bottom = this.bottom;
|
||||
data.object.near = this.near;
|
||||
data.object.far = this.far;
|
||||
|
||||
if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { OrthographicCamera };
|
||||
407
app/node_modules/three/src/cameras/PerspectiveCamera.js
generated
vendored
Normal file
407
app/node_modules/three/src/cameras/PerspectiveCamera.js
generated
vendored
Normal file
@@ -0,0 +1,407 @@
|
||||
import { Camera } from './Camera.js';
|
||||
import { RAD2DEG, DEG2RAD } from '../math/MathUtils.js';
|
||||
import { Vector2 } from '../math/Vector2.js';
|
||||
import { Vector3 } from '../math/Vector3.js';
|
||||
|
||||
const _v3 = /*@__PURE__*/ new Vector3();
|
||||
const _minTarget = /*@__PURE__*/ new Vector2();
|
||||
const _maxTarget = /*@__PURE__*/ new Vector2();
|
||||
|
||||
/**
|
||||
* Camera that uses [perspective projection]{@link https://en.wikipedia.org/wiki/Perspective_(graphical)}.
|
||||
*
|
||||
* This projection mode is designed to mimic the way the human eye sees. It
|
||||
* is the most common projection mode used for rendering a 3D scene.
|
||||
*
|
||||
* ```js
|
||||
* const camera = new THREE.PerspectiveCamera( 45, width / height, 1, 1000 );
|
||||
* scene.add( camera );
|
||||
* ```
|
||||
*
|
||||
* @augments Camera
|
||||
*/
|
||||
class PerspectiveCamera extends Camera {
|
||||
|
||||
/**
|
||||
* Constructs a new perspective camera.
|
||||
*
|
||||
* @param {number} [fov=50] - The vertical field of view.
|
||||
* @param {number} [aspect=1] - The aspect ratio.
|
||||
* @param {number} [near=0.1] - The camera's near plane.
|
||||
* @param {number} [far=2000] - The camera's far plane.
|
||||
*/
|
||||
constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isPerspectiveCamera = true;
|
||||
|
||||
this.type = 'PerspectiveCamera';
|
||||
|
||||
/**
|
||||
* The vertical field of view, from bottom to top of view,
|
||||
* in degrees.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 50
|
||||
*/
|
||||
this.fov = fov;
|
||||
|
||||
/**
|
||||
* The zoom factor of the camera.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 1
|
||||
*/
|
||||
this.zoom = 1;
|
||||
|
||||
/**
|
||||
* The camera's near plane. The valid range is greater than `0`
|
||||
* and less than the current value of {@link PerspectiveCamera#far}.
|
||||
*
|
||||
* Note that, unlike for the {@link OrthographicCamera}, `0` is <em>not</em> a
|
||||
* valid value for a perspective camera's near plane.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0.1
|
||||
*/
|
||||
this.near = near;
|
||||
|
||||
/**
|
||||
* The camera's far plane. Must be greater than the
|
||||
* current value of {@link PerspectiveCamera#near}.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 2000
|
||||
*/
|
||||
this.far = far;
|
||||
|
||||
/**
|
||||
* Object distance used for stereoscopy and depth-of-field effects. This
|
||||
* parameter does not influence the projection matrix unless a
|
||||
* {@link StereoCamera} is being used.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 10
|
||||
*/
|
||||
this.focus = 10;
|
||||
|
||||
/**
|
||||
* The aspect ratio, usually the canvas width / canvas height.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 1
|
||||
*/
|
||||
this.aspect = aspect;
|
||||
|
||||
/**
|
||||
* Represents the frustum window specification. This property should not be edited
|
||||
* directly but via {@link PerspectiveCamera#setViewOffset} and {@link PerspectiveCamera#clearViewOffset}.
|
||||
*
|
||||
* @type {?Object}
|
||||
* @default null
|
||||
*/
|
||||
this.view = null;
|
||||
|
||||
/**
|
||||
* Film size used for the larger axis. Default is `35` (millimeters). This
|
||||
* parameter does not influence the projection matrix unless {@link PerspectiveCamera#filmOffset}
|
||||
* is set to a nonzero value.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 35
|
||||
*/
|
||||
this.filmGauge = 35;
|
||||
|
||||
/**
|
||||
* Horizontal off-center offset in the same unit as {@link PerspectiveCamera#filmGauge}.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0
|
||||
*/
|
||||
this.filmOffset = 0;
|
||||
|
||||
this.updateProjectionMatrix();
|
||||
|
||||
}
|
||||
|
||||
copy( source, recursive ) {
|
||||
|
||||
super.copy( source, recursive );
|
||||
|
||||
this.fov = source.fov;
|
||||
this.zoom = source.zoom;
|
||||
|
||||
this.near = source.near;
|
||||
this.far = source.far;
|
||||
this.focus = source.focus;
|
||||
|
||||
this.aspect = source.aspect;
|
||||
this.view = source.view === null ? null : Object.assign( {}, source.view );
|
||||
|
||||
this.filmGauge = source.filmGauge;
|
||||
this.filmOffset = source.filmOffset;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the FOV by focal length in respect to the current {@link PerspectiveCamera#filmGauge}.
|
||||
*
|
||||
* The default film gauge is 35, so that the focal length can be specified for
|
||||
* a 35mm (full frame) camera.
|
||||
*
|
||||
* @param {number} focalLength - Values for focal length and film gauge must have the same unit.
|
||||
*/
|
||||
setFocalLength( focalLength ) {
|
||||
|
||||
/** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */
|
||||
const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
|
||||
|
||||
this.fov = RAD2DEG * 2 * Math.atan( vExtentSlope );
|
||||
this.updateProjectionMatrix();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the focal length from the current {@link PerspectiveCamera#fov} and
|
||||
* {@link PerspectiveCamera#filmGauge}.
|
||||
*
|
||||
* @return {number} The computed focal length.
|
||||
*/
|
||||
getFocalLength() {
|
||||
|
||||
const vExtentSlope = Math.tan( DEG2RAD * 0.5 * this.fov );
|
||||
|
||||
return 0.5 * this.getFilmHeight() / vExtentSlope;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current vertical field of view angle in degrees considering {@link PerspectiveCamera#zoom}.
|
||||
*
|
||||
* @return {number} The effective FOV.
|
||||
*/
|
||||
getEffectiveFOV() {
|
||||
|
||||
return RAD2DEG * 2 * Math.atan(
|
||||
Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the width of the image on the film. If {@link PerspectiveCamera#aspect} is greater than or
|
||||
* equal to one (landscape format), the result equals {@link PerspectiveCamera#filmGauge}.
|
||||
*
|
||||
* @return {number} The film width.
|
||||
*/
|
||||
getFilmWidth() {
|
||||
|
||||
// film not completely covered in portrait format (aspect < 1)
|
||||
return this.filmGauge * Math.min( this.aspect, 1 );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the height of the image on the film. If {@link PerspectiveCamera#aspect} is greater than or
|
||||
* equal to one (landscape format), the result equals {@link PerspectiveCamera#filmGauge}.
|
||||
*
|
||||
* @return {number} The film width.
|
||||
*/
|
||||
getFilmHeight() {
|
||||
|
||||
// film not completely covered in landscape format (aspect > 1)
|
||||
return this.filmGauge / Math.max( this.aspect, 1 );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the 2D bounds of the camera's viewable rectangle at a given distance along the viewing direction.
|
||||
* Sets `minTarget` and `maxTarget` to the coordinates of the lower-left and upper-right corners of the view rectangle.
|
||||
*
|
||||
* @param {number} distance - The viewing distance.
|
||||
* @param {Vector2} minTarget - The lower-left corner of the view rectangle is written into this vector.
|
||||
* @param {Vector2} maxTarget - The upper-right corner of the view rectangle is written into this vector.
|
||||
*/
|
||||
getViewBounds( distance, minTarget, maxTarget ) {
|
||||
|
||||
_v3.set( - 1, - 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse );
|
||||
|
||||
minTarget.set( _v3.x, _v3.y ).multiplyScalar( - distance / _v3.z );
|
||||
|
||||
_v3.set( 1, 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse );
|
||||
|
||||
maxTarget.set( _v3.x, _v3.y ).multiplyScalar( - distance / _v3.z );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the width and height of the camera's viewable rectangle at a given distance along the viewing direction.
|
||||
*
|
||||
* @param {number} distance - The viewing distance.
|
||||
* @param {Vector2} target - The target vector that is used to store result where x is width and y is height.
|
||||
* @returns {Vector2} The view size.
|
||||
*/
|
||||
getViewSize( distance, target ) {
|
||||
|
||||
this.getViewBounds( distance, _minTarget, _maxTarget );
|
||||
|
||||
return target.subVectors( _maxTarget, _minTarget );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an offset in a larger frustum. This is useful for multi-window or
|
||||
* multi-monitor/multi-machine setups.
|
||||
*
|
||||
* For example, if you have 3x2 monitors and each monitor is 1920x1080 and
|
||||
* the monitors are in grid like this
|
||||
*```
|
||||
* +---+---+---+
|
||||
* | A | B | C |
|
||||
* +---+---+---+
|
||||
* | D | E | F |
|
||||
* +---+---+---+
|
||||
*```
|
||||
* then for each monitor you would call it like this:
|
||||
*```js
|
||||
* const w = 1920;
|
||||
* const h = 1080;
|
||||
* const fullWidth = w * 3;
|
||||
* const fullHeight = h * 2;
|
||||
*
|
||||
* // --A--
|
||||
* camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
|
||||
* // --B--
|
||||
* camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
|
||||
* // --C--
|
||||
* camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
|
||||
* // --D--
|
||||
* camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
|
||||
* // --E--
|
||||
* camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
|
||||
* // --F--
|
||||
* camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
|
||||
* ```
|
||||
*
|
||||
* Note there is no reason monitors have to be the same size or in a grid.
|
||||
*
|
||||
* @param {number} fullWidth - The full width of multiview setup.
|
||||
* @param {number} fullHeight - The full height of multiview setup.
|
||||
* @param {number} x - The horizontal offset of the subcamera.
|
||||
* @param {number} y - The vertical offset of the subcamera.
|
||||
* @param {number} width - The width of subcamera.
|
||||
* @param {number} height - The height of subcamera.
|
||||
*/
|
||||
setViewOffset( fullWidth, fullHeight, x, y, width, height ) {
|
||||
|
||||
this.aspect = fullWidth / fullHeight;
|
||||
|
||||
if ( this.view === null ) {
|
||||
|
||||
this.view = {
|
||||
enabled: true,
|
||||
fullWidth: 1,
|
||||
fullHeight: 1,
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
width: 1,
|
||||
height: 1
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
this.view.enabled = true;
|
||||
this.view.fullWidth = fullWidth;
|
||||
this.view.fullHeight = fullHeight;
|
||||
this.view.offsetX = x;
|
||||
this.view.offsetY = y;
|
||||
this.view.width = width;
|
||||
this.view.height = height;
|
||||
|
||||
this.updateProjectionMatrix();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the view offset from the projection matrix.
|
||||
*/
|
||||
clearViewOffset() {
|
||||
|
||||
if ( this.view !== null ) {
|
||||
|
||||
this.view.enabled = false;
|
||||
|
||||
}
|
||||
|
||||
this.updateProjectionMatrix();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the camera's projection matrix. Must be called after any change of
|
||||
* camera properties.
|
||||
*/
|
||||
updateProjectionMatrix() {
|
||||
|
||||
const near = this.near;
|
||||
let top = near * Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom;
|
||||
let height = 2 * top;
|
||||
let width = this.aspect * height;
|
||||
let left = - 0.5 * width;
|
||||
const view = this.view;
|
||||
|
||||
if ( this.view !== null && this.view.enabled ) {
|
||||
|
||||
const fullWidth = view.fullWidth,
|
||||
fullHeight = view.fullHeight;
|
||||
|
||||
left += view.offsetX * width / fullWidth;
|
||||
top -= view.offsetY * height / fullHeight;
|
||||
width *= view.width / fullWidth;
|
||||
height *= view.height / fullHeight;
|
||||
|
||||
}
|
||||
|
||||
const skew = this.filmOffset;
|
||||
if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
|
||||
|
||||
this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far, this.coordinateSystem );
|
||||
|
||||
this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
|
||||
|
||||
}
|
||||
|
||||
toJSON( meta ) {
|
||||
|
||||
const data = super.toJSON( meta );
|
||||
|
||||
data.object.fov = this.fov;
|
||||
data.object.zoom = this.zoom;
|
||||
|
||||
data.object.near = this.near;
|
||||
data.object.far = this.far;
|
||||
data.object.focus = this.focus;
|
||||
|
||||
data.object.aspect = this.aspect;
|
||||
|
||||
if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
|
||||
|
||||
data.object.filmGauge = this.filmGauge;
|
||||
data.object.filmOffset = this.filmOffset;
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { PerspectiveCamera };
|
||||
146
app/node_modules/three/src/cameras/StereoCamera.js
generated
vendored
Normal file
146
app/node_modules/three/src/cameras/StereoCamera.js
generated
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
import { Matrix4 } from '../math/Matrix4.js';
|
||||
import { DEG2RAD } from '../math/MathUtils.js';
|
||||
import { PerspectiveCamera } from './PerspectiveCamera.js';
|
||||
|
||||
const _eyeRight = /*@__PURE__*/ new Matrix4();
|
||||
const _eyeLeft = /*@__PURE__*/ new Matrix4();
|
||||
const _projectionMatrix = /*@__PURE__*/ new Matrix4();
|
||||
|
||||
/**
|
||||
* A special type of camera that uses two perspective cameras with
|
||||
* stereoscopic projection. Can be used for rendering stereo effects
|
||||
* like [3D Anaglyph]{@link https://en.wikipedia.org/wiki/Anaglyph_3D} or
|
||||
* [Parallax Barrier]{@link https://en.wikipedia.org/wiki/parallax_barrier}.
|
||||
*/
|
||||
class StereoCamera {
|
||||
|
||||
/**
|
||||
* Constructs a new stereo camera.
|
||||
*/
|
||||
constructor() {
|
||||
|
||||
/**
|
||||
* The type property is used for detecting the object type
|
||||
* in context of serialization/deserialization.
|
||||
*
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
this.type = 'StereoCamera';
|
||||
|
||||
/**
|
||||
* The aspect.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 1
|
||||
*/
|
||||
this.aspect = 1;
|
||||
|
||||
/**
|
||||
* The eye separation which represents the distance
|
||||
* between the left and right camera.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0.064
|
||||
*/
|
||||
this.eyeSep = 0.064;
|
||||
|
||||
/**
|
||||
* The camera representing the left eye. This is added to layer `1` so objects to be
|
||||
* rendered by the left camera must also be added to this layer.
|
||||
*
|
||||
* @type {PerspectiveCamera}
|
||||
*/
|
||||
this.cameraL = new PerspectiveCamera();
|
||||
this.cameraL.layers.enable( 1 );
|
||||
this.cameraL.matrixAutoUpdate = false;
|
||||
|
||||
/**
|
||||
* The camera representing the right eye. This is added to layer `2` so objects to be
|
||||
* rendered by the right camera must also be added to this layer.
|
||||
*
|
||||
* @type {PerspectiveCamera}
|
||||
*/
|
||||
this.cameraR = new PerspectiveCamera();
|
||||
this.cameraR.layers.enable( 2 );
|
||||
this.cameraR.matrixAutoUpdate = false;
|
||||
|
||||
this._cache = {
|
||||
focus: null,
|
||||
fov: null,
|
||||
aspect: null,
|
||||
near: null,
|
||||
far: null,
|
||||
zoom: null,
|
||||
eyeSep: null
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the stereo camera based on the given perspective camera.
|
||||
*
|
||||
* @param {PerspectiveCamera} camera - The perspective camera.
|
||||
*/
|
||||
update( camera ) {
|
||||
|
||||
const cache = this._cache;
|
||||
|
||||
const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov ||
|
||||
cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near ||
|
||||
cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep;
|
||||
|
||||
if ( needsUpdate ) {
|
||||
|
||||
cache.focus = camera.focus;
|
||||
cache.fov = camera.fov;
|
||||
cache.aspect = camera.aspect * this.aspect;
|
||||
cache.near = camera.near;
|
||||
cache.far = camera.far;
|
||||
cache.zoom = camera.zoom;
|
||||
cache.eyeSep = this.eyeSep;
|
||||
|
||||
// Off-axis stereoscopic effect based on
|
||||
// http://paulbourke.net/stereographics/stereorender/
|
||||
|
||||
_projectionMatrix.copy( camera.projectionMatrix );
|
||||
const eyeSepHalf = cache.eyeSep / 2;
|
||||
const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus;
|
||||
const ymax = ( cache.near * Math.tan( DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom;
|
||||
let xmin, xmax;
|
||||
|
||||
// translate xOffset
|
||||
|
||||
_eyeLeft.elements[ 12 ] = - eyeSepHalf;
|
||||
_eyeRight.elements[ 12 ] = eyeSepHalf;
|
||||
|
||||
// for left eye
|
||||
|
||||
xmin = - ymax * cache.aspect + eyeSepOnProjection;
|
||||
xmax = ymax * cache.aspect + eyeSepOnProjection;
|
||||
|
||||
_projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
|
||||
_projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
|
||||
|
||||
this.cameraL.projectionMatrix.copy( _projectionMatrix );
|
||||
|
||||
// for right eye
|
||||
|
||||
xmin = - ymax * cache.aspect - eyeSepOnProjection;
|
||||
xmax = ymax * cache.aspect - eyeSepOnProjection;
|
||||
|
||||
_projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
|
||||
_projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
|
||||
|
||||
this.cameraR.projectionMatrix.copy( _projectionMatrix );
|
||||
|
||||
}
|
||||
|
||||
this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft );
|
||||
this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { StereoCamera };
|
||||
Reference in New Issue
Block a user