diff --git a/examples/jsm/controls/OrbitControls.js b/examples/jsm/controls/OrbitControls.js index 10bf8437214498..ff9c1b2f22cd95 100644 --- a/examples/jsm/controls/OrbitControls.js +++ b/examples/jsm/controls/OrbitControls.js @@ -594,6 +594,67 @@ class OrbitControls extends Controls { } + /** + * Programmatically pan the camera. + * + * @param {number} deltaX - The horizontal pan amount in pixels. + * @param {number} deltaY - The vertical pan amount in pixels. + */ + pan( deltaX, deltaY ) { + + this._pan( deltaX, deltaY ); + this.update(); + + } + + /** + * Programmatically dolly in (zoom in for perspective camera). + * + * @param {number} dollyScale - The dolly scale factor. + */ + dollyIn( dollyScale ) { + + this._dollyIn( dollyScale ); + this.update(); + + } + + /** + * Programmatically dolly out (zoom out for perspective camera). + * + * @param {number} dollyScale - The dolly scale factor. + */ + dollyOut( dollyScale ) { + + this._dollyOut( dollyScale ); + this.update(); + + } + + /** + * Programmatically rotate the camera left (around the vertical axis). + * + * @param {number} angle - The rotation angle in radians. + */ + rotateLeft( angle ) { + + this._rotateLeft( angle ); + this.update(); + + } + + /** + * Programmatically rotate the camera up (around the horizontal axis). + * + * @param {number} angle - The rotation angle in radians. + */ + rotateUp( angle ) { + + this._rotateUp( angle ); + this.update(); + + } + update( deltaTime = null ) { const position = this.object.position; diff --git a/package-lock.json b/package-lock.json index 08197fa153f329..e80edf7908f772 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2599,9 +2599,9 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "dev": true, "license": "MIT" }, diff --git a/src/cameras/Camera.js b/src/cameras/Camera.js index 333b0b40ec65e2..2c2569639c4476 100644 --- a/src/cameras/Camera.js +++ b/src/cameras/Camera.js @@ -1,6 +1,12 @@ import { WebGLCoordinateSystem } from '../constants.js'; import { Matrix4 } from '../math/Matrix4.js'; import { Object3D } from '../core/Object3D.js'; +import { Vector3 } from '../math/Vector3.js'; +import { Quaternion } from '../math/Quaternion.js'; + +const _position = /*@__PURE__*/ new Vector3(); +const _quaternion = /*@__PURE__*/ new Quaternion(); +const _scale = /*@__PURE__*/ new Vector3(); /** * Abstract base class for cameras. This class should always be inherited @@ -107,7 +113,19 @@ class Camera extends Object3D { super.updateMatrixWorld( force ); - this.matrixWorldInverse.copy( this.matrixWorld ).invert(); + // exclude scale from view matrix to be glTF conform + + this.matrixWorld.decompose( _position, _quaternion, _scale ); + + if ( _scale.x === 1 && _scale.y === 1 && _scale.z === 1 ) { + + this.matrixWorldInverse.copy( this.matrixWorld ).invert(); + + } else { + + this.matrixWorldInverse.compose( _position, _quaternion, _scale.set( 1, 1, 1 ) ).invert(); + + } } @@ -115,7 +133,19 @@ class Camera extends Object3D { super.updateWorldMatrix( updateParents, updateChildren ); - this.matrixWorldInverse.copy( this.matrixWorld ).invert(); + // exclude scale from view matrix to be glTF conform + + this.matrixWorld.decompose( _position, _quaternion, _scale ); + + if ( _scale.x === 1 && _scale.y === 1 && _scale.z === 1 ) { + + this.matrixWorldInverse.copy( this.matrixWorld ).invert(); + + } else { + + this.matrixWorldInverse.compose( _position, _quaternion, _scale.set( 1, 1, 1 ) ).invert(); + + } } diff --git a/src/materials/nodes/MeshPhysicalNodeMaterial.js b/src/materials/nodes/MeshPhysicalNodeMaterial.js index 83d676698f6162..fd5a11f5978744 100644 --- a/src/materials/nodes/MeshPhysicalNodeMaterial.js +++ b/src/materials/nodes/MeshPhysicalNodeMaterial.js @@ -502,6 +502,8 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { this.specularIntensityNode = source.specularIntensityNode; this.specularColorNode = source.specularColorNode; + this.iorNode = source.iorNode; + this.transmissionNode = source.transmissionNode; this.thicknessNode = source.thicknessNode; this.attenuationDistanceNode = source.attenuationDistanceNode; diff --git a/src/math/MathUtils.js b/src/math/MathUtils.js index 3800f4160e6b5f..25a898cd2fa39e 100644 --- a/src/math/MathUtils.js +++ b/src/math/MathUtils.js @@ -64,7 +64,7 @@ function euclideanModulo( n, m ) { /** * Performs a linear mapping from range `` to range `` - * for the given value. + * for the given value. `a2` must be greater than `a1`. * * @param {number} x - The value to be mapped. * @param {number} a1 - Minimum value for range A. @@ -159,9 +159,9 @@ function pingpong( x, length = 1 ) { * * See [Smoothstep](http://en.wikipedia.org/wiki/Smoothstep) for more details. * - * @param {number} x - The value to evaluate based on its position between min and max. - * @param {number} min - The min value. Any x value below min will be `0`. - * @param {number} max - The max value. Any x value above max will be `1`. + * @param {number} x - The value to evaluate based on its position between `min` and `max`. + * @param {number} min - The min value. Any `x` value below `min` will be `0`. `min` must be lower than `max`. + * @param {number} max - The max value. Any `x` value above `max` will be `1`. `max` must be greater than `min`. * @return {number} The alternated value. */ function smoothstep( x, min, max ) { @@ -177,11 +177,11 @@ function smoothstep( x, min, max ) { /** * A [variation on smoothstep](https://en.wikipedia.org/wiki/Smoothstep#Variations) - * that has zero 1st and 2nd order derivatives at x=0 and x=1. + * that has zero 1st and 2nd order derivatives at `x=0` and `x=1`. * - * @param {number} x - The value to evaluate based on its position between min and max. - * @param {number} min - The min value. Any x value below min will be `0`. - * @param {number} max - The max value. Any x value above max will be `1`. + * @param {number} x - The value to evaluate based on its position between `min` and `max`. + * @param {number} min - The min value. Any `x` value below `min` will be `0`. `min` must be lower than `max`. + * @param {number} max - The max value. Any `x` value above `max` will be `1`. `max` must be greater than `min`. * @return {number} The alternated value. */ function smootherstep( x, min, max ) { @@ -294,7 +294,7 @@ function isPowerOfTwo( value ) { /** * Returns the smallest power of two that is greater than or equal to the given number. * - * @param {number} value - The value to find a POT for. + * @param {number} value - The value to find a POT for. Must be greater than `0`. * @return {number} The smallest power of two that is greater than or equal to the given number. */ function ceilPowerOfTwo( value ) { @@ -306,7 +306,7 @@ function ceilPowerOfTwo( value ) { /** * Returns the largest power of two that is less than or equal to the given number. * - * @param {number} value - The value to find a POT for. + * @param {number} value - The value to find a POT for. Must be greater than `0`. * @return {number} The largest power of two that is less than or equal to the given number. */ function floorPowerOfTwo( value ) {