UNPKG

@google/model-viewer

Version:

Easily display interactive 3D models on the web and in AR!

1,736 lines (1,328 loc) 2.16 MB
/** * @license * Copyright 2019 Google LLC * SPDX-License-Identifier: BSD-3-Clause */ const t$2=globalThis,e$2=t$2.ShadowRoot&&(void 0===t$2.ShadyCSS||t$2.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,s$1=Symbol(),o$3=new WeakMap;let n$4 = class n{constructor(t,e,o){if(this._$cssResult$=true,o!==s$1)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e;}get styleSheet(){let t=this.o;const s=this.t;if(e$2&&void 0===t){const e=void 0!==s&&1===s.length;e&&(t=o$3.get(s)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&o$3.set(s,t));}return t}toString(){return this.cssText}};const r$4=t=>new n$4("string"==typeof t?t:t+"",void 0,s$1),S$1=(s,o)=>{if(e$2)s.adoptedStyleSheets=o.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet));else for(const e of o){const o=document.createElement("style"),n=t$2.litNonce;void 0!==n&&o.setAttribute("nonce",n),o.textContent=e.cssText,s.appendChild(o);}},c$3=e$2?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const s of t.cssRules)e+=s.cssText;return r$4(e)})(t):t; /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause */const{is:i$3,defineProperty:e$1,getOwnPropertyDescriptor:r$3,getOwnPropertyNames:h$1,getOwnPropertySymbols:o$2,getPrototypeOf:n$3}=Object,a$2=globalThis,c$2=a$2.trustedTypes,l$1=c$2?c$2.emptyScript:"",p$1=a$2.reactiveElementPolyfillSupport,d$1=(t,s)=>t,u$2={toAttribute(t,s){switch(s){case Boolean:t=t?l$1:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t);}return t},fromAttribute(t,s){let i=t;switch(s){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t);}catch(t){i=null;}}return i}},f$1=(t,s)=>!i$3(t,s),y$1={attribute:true,type:String,converter:u$2,reflect:false,hasChanged:f$1};Symbol.metadata??=Symbol("metadata"),a$2.litPropertyMetadata??=new WeakMap;let b$1 = class b extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t);}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,s=y$1){if(s.state&&(s.attribute=false),this._$Ei(),this.elementProperties.set(t,s),!s.noAccessor){const i=Symbol(),r=this.getPropertyDescriptor(t,i,s);void 0!==r&&e$1(this.prototype,t,r);}}static getPropertyDescriptor(t,s,i){const{get:e,set:h}=r$3(this.prototype,t)??{get(){return this[s]},set(t){this[s]=t;}};return {get(){return e?.call(this)},set(s){const r=e?.call(this);h.call(this,s),this.requestUpdate(t,r,i);},configurable:true,enumerable:true}}static getPropertyOptions(t){return this.elementProperties.get(t)??y$1}static _$Ei(){if(this.hasOwnProperty(d$1("elementProperties")))return;const t=n$3(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties);}static finalize(){if(this.hasOwnProperty(d$1("finalized")))return;if(this.finalized=true,this._$Ei(),this.hasOwnProperty(d$1("properties"))){const t=this.properties,s=[...h$1(t),...o$2(t)];for(const i of s)this.createProperty(i,t[i]);}const t=this[Symbol.metadata];if(null!==t){const s=litPropertyMetadata.get(t);if(void 0!==s)for(const[t,i]of s)this.elementProperties.set(t,i);}this._$Eh=new Map;for(const[t,s]of this.elementProperties){const i=this._$Eu(t,s);void 0!==i&&this._$Eh.set(i,t);}this.elementStyles=this.finalizeStyles(this.styles);}static finalizeStyles(s){const i=[];if(Array.isArray(s)){const e=new Set(s.flat(1/0).reverse());for(const s of e)i.unshift(c$3(s));}else void 0!==s&&i.push(c$3(s));return i}static _$Eu(t,s){const i=s.attribute;return false===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=false,this.hasUpdated=false,this._$Em=null,this._$Ev();}_$Ev(){this._$ES=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach((t=>t(this)));}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.();}removeController(t){this._$EO?.delete(t);}_$E_(){const t=new Map,s=this.constructor.elementProperties;for(const i of s.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t);}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return S$1(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(true),this._$EO?.forEach((t=>t.hostConnected?.()));}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach((t=>t.hostDisconnected?.()));}attributeChangedCallback(t,s,i){this._$AK(t,i);}_$EC(t,s){const i=this.constructor.elementProperties.get(t),e=this.constructor._$Eu(t,i);if(void 0!==e&&true===i.reflect){const r=(void 0!==i.converter?.toAttribute?i.converter:u$2).toAttribute(s,i.type);this._$Em=t,null==r?this.removeAttribute(e):this.setAttribute(e,r),this._$Em=null;}}_$AK(t,s){const i=this.constructor,e=i._$Eh.get(t);if(void 0!==e&&this._$Em!==e){const t=i.getPropertyOptions(e),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:u$2;this._$Em=e,this[e]=r.fromAttribute(s,t.type),this._$Em=null;}}requestUpdate(t,s,i){if(void 0!==t){if(i??=this.constructor.getPropertyOptions(t),!(i.hasChanged??f$1)(this[t],s))return;this.P(t,s,i);} false===this.isUpdatePending&&(this._$ES=this._$ET());}P(t,s,i){this._$AL.has(t)||this._$AL.set(t,s),true===i.reflect&&this._$Em!==t&&(this._$Ej??=new Set).add(t);}async _$ET(){this.isUpdatePending=true;try{await this._$ES;}catch(t){Promise.reject(t);}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[t,s]of this._$Ep)this[t]=s;this._$Ep=void 0;}const t=this.constructor.elementProperties;if(t.size>0)for(const[s,i]of t) true!==i.wrapped||this._$AL.has(s)||void 0===this[s]||this.P(s,this[s],i);}let t=false;const s=this._$AL;try{t=this.shouldUpdate(s),t?(this.willUpdate(s),this._$EO?.forEach((t=>t.hostUpdate?.())),this.update(s)):this._$EU();}catch(s){throw t=false,this._$EU(),s}t&&this._$AE(s);}willUpdate(t){}_$AE(t){this._$EO?.forEach((t=>t.hostUpdated?.())),this.hasUpdated||(this.hasUpdated=true,this.firstUpdated(t)),this.updated(t);}_$EU(){this._$AL=new Map,this.isUpdatePending=false;}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return true}update(t){this._$Ej&&=this._$Ej.forEach((t=>this._$EC(t,this[t]))),this._$EU();}updated(t){}firstUpdated(t){}};b$1.elementStyles=[],b$1.shadowRootOptions={mode:"open"},b$1[d$1("elementProperties")]=new Map,b$1[d$1("finalized")]=new Map,p$1?.({ReactiveElement:b$1}),(a$2.reactiveElementVersions??=[]).push("2.0.4"); /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause */const o$1={attribute:true,type:String,converter:u$2,reflect:false,hasChanged:f$1},r$2=(t=o$1,e,r)=>{const{kind:n,metadata:i}=r;let s=globalThis.litPropertyMetadata.get(i);if(void 0===s&&globalThis.litPropertyMetadata.set(i,s=new Map),s.set(r.name,t),"accessor"===n){const{name:o}=r;return {set(r){const n=e.get.call(this);e.set.call(this,r),this.requestUpdate(o,n,t);},init(e){return void 0!==e&&this.P(o,void 0,t),e}}}if("setter"===n){const{name:o}=r;return function(r){const n=this[o];e.call(this,r),this.requestUpdate(o,n,t);}}throw Error("Unsupported decorator location: "+n)};function n$2(t){return (e,o)=>"object"==typeof o?r$2(t,e,o):((t,e,o)=>{const r=e.hasOwnProperty(o);return e.constructor.createProperty(o,r?{...t,wrapped:true}:t),r?Object.getOwnPropertyDescriptor(e,o):void 0})(t,e,o)} /** * @license * Copyright 2010-2025 Three.js Authors * SPDX-License-Identifier: MIT */ const REVISION = '174'; const CullFaceNone = 0; const CullFaceBack = 1; const CullFaceFront = 2; const PCFShadowMap = 1; const PCFSoftShadowMap = 2; const VSMShadowMap = 3; const FrontSide = 0; const BackSide = 1; const DoubleSide = 2; const NoBlending = 0; const NormalBlending = 1; const AdditiveBlending = 2; const SubtractiveBlending = 3; const MultiplyBlending = 4; const CustomBlending = 5; const AddEquation = 100; const SubtractEquation = 101; const ReverseSubtractEquation = 102; const MinEquation = 103; const MaxEquation = 104; const ZeroFactor = 200; const OneFactor = 201; const SrcColorFactor = 202; const OneMinusSrcColorFactor = 203; const SrcAlphaFactor = 204; const OneMinusSrcAlphaFactor = 205; const DstAlphaFactor = 206; const OneMinusDstAlphaFactor = 207; const DstColorFactor = 208; const OneMinusDstColorFactor = 209; const SrcAlphaSaturateFactor = 210; const ConstantColorFactor = 211; const OneMinusConstantColorFactor = 212; const ConstantAlphaFactor = 213; const OneMinusConstantAlphaFactor = 214; const NeverDepth = 0; const AlwaysDepth = 1; const LessDepth = 2; const LessEqualDepth = 3; const EqualDepth = 4; const GreaterEqualDepth = 5; const GreaterDepth = 6; const NotEqualDepth = 7; const MultiplyOperation = 0; const MixOperation = 1; const AddOperation = 2; const NoToneMapping = 0; const LinearToneMapping = 1; const ReinhardToneMapping = 2; const CineonToneMapping = 3; const ACESFilmicToneMapping = 4; const CustomToneMapping = 5; const AgXToneMapping = 6; const NeutralToneMapping = 7; const AttachedBindMode = 'attached'; const DetachedBindMode = 'detached'; const UVMapping = 300; const CubeReflectionMapping = 301; const CubeRefractionMapping = 302; const EquirectangularReflectionMapping = 303; const EquirectangularRefractionMapping = 304; const CubeUVReflectionMapping = 306; const RepeatWrapping = 1000; const ClampToEdgeWrapping = 1001; const MirroredRepeatWrapping = 1002; const NearestFilter = 1003; const NearestMipmapNearestFilter = 1004; const NearestMipmapLinearFilter = 1005; const LinearFilter = 1006; const LinearMipmapNearestFilter = 1007; const LinearMipmapLinearFilter = 1008; const LinearMipMapLinearFilter = 1008; const UnsignedByteType = 1009; const ByteType = 1010; const ShortType = 1011; const UnsignedShortType = 1012; const IntType = 1013; const UnsignedIntType = 1014; const FloatType = 1015; const HalfFloatType = 1016; const UnsignedShort4444Type = 1017; const UnsignedShort5551Type = 1018; const UnsignedInt248Type = 1020; const UnsignedInt5999Type = 35902; const AlphaFormat = 1021; const RGBFormat = 1022; const RGBAFormat = 1023; const LuminanceFormat = 1024; const LuminanceAlphaFormat = 1025; const DepthFormat = 1026; const DepthStencilFormat = 1027; const RedFormat = 1028; const RedIntegerFormat = 1029; const RGFormat = 1030; const RGIntegerFormat = 1031; const RGBAIntegerFormat = 1033; const RGB_S3TC_DXT1_Format = 33776; const RGBA_S3TC_DXT1_Format = 33777; const RGBA_S3TC_DXT3_Format = 33778; const RGBA_S3TC_DXT5_Format = 33779; const RGB_PVRTC_4BPPV1_Format = 35840; const RGB_PVRTC_2BPPV1_Format = 35841; const RGBA_PVRTC_4BPPV1_Format = 35842; const RGBA_PVRTC_2BPPV1_Format = 35843; const RGB_ETC1_Format = 36196; const RGB_ETC2_Format = 37492; const RGBA_ETC2_EAC_Format = 37496; const RGBA_ASTC_4x4_Format = 37808; const RGBA_ASTC_5x4_Format = 37809; const RGBA_ASTC_5x5_Format = 37810; const RGBA_ASTC_6x5_Format = 37811; const RGBA_ASTC_6x6_Format = 37812; const RGBA_ASTC_8x5_Format = 37813; const RGBA_ASTC_8x6_Format = 37814; const RGBA_ASTC_8x8_Format = 37815; const RGBA_ASTC_10x5_Format = 37816; const RGBA_ASTC_10x6_Format = 37817; const RGBA_ASTC_10x8_Format = 37818; const RGBA_ASTC_10x10_Format = 37819; const RGBA_ASTC_12x10_Format = 37820; const RGBA_ASTC_12x12_Format = 37821; const RGBA_BPTC_Format = 36492; const RGB_BPTC_SIGNED_Format = 36494; const RGB_BPTC_UNSIGNED_Format = 36495; const RED_RGTC1_Format = 36283; const SIGNED_RED_RGTC1_Format = 36284; const RED_GREEN_RGTC2_Format = 36285; const SIGNED_RED_GREEN_RGTC2_Format = 36286; const LoopOnce = 2200; const LoopRepeat = 2201; const LoopPingPong = 2202; const InterpolateDiscrete = 2300; const InterpolateLinear = 2301; const InterpolateSmooth = 2302; const ZeroCurvatureEnding = 2400; const ZeroSlopeEnding = 2401; const WrapAroundEnding = 2402; const NormalAnimationBlendMode = 2500; const AdditiveAnimationBlendMode = 2501; const TrianglesDrawMode = 0; const TriangleStripDrawMode = 1; const TriangleFanDrawMode = 2; const BasicDepthPacking = 3200; const RGBADepthPacking = 3201; const TangentSpaceNormalMap = 0; const ObjectSpaceNormalMap = 1; // Color space string identifiers, matching CSS Color Module Level 4 and WebGPU names where available. const NoColorSpace = ''; const SRGBColorSpace = 'srgb'; const LinearSRGBColorSpace = 'srgb-linear'; const LinearTransfer = 'linear'; const SRGBTransfer = 'srgb'; const KeepStencilOp = 7680; const AlwaysStencilFunc = 519; const NeverCompare = 512; const LessCompare = 513; const EqualCompare = 514; const LessEqualCompare = 515; const GreaterCompare = 516; const NotEqualCompare = 517; const GreaterEqualCompare = 518; const AlwaysCompare = 519; const StaticDrawUsage = 35044; const GLSL3 = '300 es'; const WebGLCoordinateSystem = 2000; const WebGPUCoordinateSystem = 2001; /** * This modules allows to dispatch event objects on custom JavaScript objects. * * Main repository: [eventdispatcher.js]{@link https://github.com/mrdoob/eventdispatcher.js/} * * Code Example: * ```js * class Car extends EventDispatcher { * start() { * this.dispatchEvent( { type: 'start', message: 'vroom vroom!' } ); * } *}; * * // Using events with the custom object * const car = new Car(); * car.addEventListener( 'start', function ( event ) { * alert( event.message ); * } ); * * car.start(); * ``` */ class EventDispatcher { /** * Adds the given event listener to the given event type. * * @param {string} type - The type of event to listen to. * @param {Function} listener - The function that gets called when the event is fired. */ addEventListener( type, listener ) { if ( this._listeners === undefined ) this._listeners = {}; const listeners = this._listeners; if ( listeners[ type ] === undefined ) { listeners[ type ] = []; } if ( listeners[ type ].indexOf( listener ) === -1 ) { listeners[ type ].push( listener ); } } /** * Returns `true` if the given event listener has been added to the given event type. * * @param {string} type - The type of event. * @param {Function} listener - The listener to check. * @return {boolean} Whether the given event listener has been added to the given event type. */ hasEventListener( type, listener ) { const listeners = this._listeners; if ( listeners === undefined ) return false; return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== -1; } /** * Removes the given event listener from the given event type. * * @param {string} type - The type of event. * @param {Function} listener - The listener to remove. */ removeEventListener( type, listener ) { const listeners = this._listeners; if ( listeners === undefined ) return; const listenerArray = listeners[ type ]; if ( listenerArray !== undefined ) { const index = listenerArray.indexOf( listener ); if ( index !== -1 ) { listenerArray.splice( index, 1 ); } } } /** * Dispatches an event object. * * @param {Object} event - The event that gets fired. */ dispatchEvent( event ) { const listeners = this._listeners; if ( listeners === undefined ) return; const listenerArray = listeners[ event.type ]; if ( listenerArray !== undefined ) { event.target = this; // Make a copy, in case listeners are removed while iterating. const array = listenerArray.slice( 0 ); for ( let i = 0, l = array.length; i < l; i ++ ) { array[ i ].call( this, event ); } event.target = null; } } } const _lut = [ '00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0a', '0b', '0c', '0d', '0e', '0f', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '1a', '1b', '1c', '1d', '1e', '1f', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '2a', '2b', '2c', '2d', '2e', '2f', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '3a', '3b', '3c', '3d', '3e', '3f', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '4a', '4b', '4c', '4d', '4e', '4f', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '5a', '5b', '5c', '5d', '5e', '5f', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '6a', '6b', '6c', '6d', '6e', '6f', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '7a', '7b', '7c', '7d', '7e', '7f', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '8a', '8b', '8c', '8d', '8e', '8f', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '9a', '9b', '9c', '9d', '9e', '9f', 'a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9', 'aa', 'ab', 'ac', 'ad', 'ae', 'af', 'b0', 'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'b9', 'ba', 'bb', 'bc', 'bd', 'be', 'bf', 'c0', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'ca', 'cb', 'cc', 'cd', 'ce', 'cf', 'd0', 'd1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'd9', 'da', 'db', 'dc', 'dd', 'de', 'df', 'e0', 'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7', 'e8', 'e9', 'ea', 'eb', 'ec', 'ed', 'ee', 'ef', 'f0', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'fa', 'fb', 'fc', 'fd', 'fe', 'ff' ]; let _seed = 1234567; const DEG2RAD = Math.PI / 180; const RAD2DEG = 180 / Math.PI; /** * Generate a [UUID]{@link https://en.wikipedia.org/wiki/Universally_unique_identifier} * (universally unique identifier). * * @return {string} The UUID. */ function generateUUID() { // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136 const d0 = Math.random() * 0xffffffff | 0; const d1 = Math.random() * 0xffffffff | 0; const d2 = Math.random() * 0xffffffff | 0; const d3 = Math.random() * 0xffffffff | 0; const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' + _lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' + _lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] + _lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ]; // .toLowerCase() here flattens concatenated strings to save heap memory space. return uuid.toLowerCase(); } /** * Clamps the given value between min and max. * * @param {number} value - The value to clamp. * @param {number} min - The min value. * @param {number} max - The max value. * @return {number} The clamped value. */ function clamp$1( value, min, max ) { return Math.max( min, Math.min( max, value ) ); } /** * Computes the Euclidean modulo of the given parameters that * is `( ( n % m ) + m ) % m`. * * @param {number} n - The first parameter. * @param {number} m - The second parameter. * @return {number} The Euclidean modulo. */ function euclideanModulo( n, m ) { // https://en.wikipedia.org/wiki/Modulo_operation return ( ( n % m ) + m ) % m; } /** * Performs a linear mapping from range `<a1, a2>` to range `<b1, b2>` * for the given value. * * @param {number} x - The value to be mapped. * @param {number} a1 - Minimum value for range A. * @param {number} a2 - Maximum value for range A. * @param {number} b1 - Minimum value for range B. * @param {number} b2 - Maximum value for range B. * @return {number} The mapped value. */ function mapLinear( x, a1, a2, b1, b2 ) { return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); } /** * Returns the percentage in the closed interval `[0, 1]` of the given value * between the start and end point. * * @param {number} x - The start point * @param {number} y - The end point. * @param {number} value - A value between start and end. * @return {number} The interpolation factor. */ function inverseLerp( x, y, value ) { // https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/ if ( x !== y ) { return ( value - x ) / ( y - x ); } else { return 0; } } /** * Returns a value linearly interpolated from two known points based on the given interval - * `t = 0` will return `x` and `t = 1` will return `y`. * * @param {number} x - The start point * @param {number} y - The end point. * @param {number} t - The interpolation factor in the closed interval `[0, 1]`. * @return {number} The interpolated value. */ function lerp$1( x, y, t ) { return ( 1 - t ) * x + t * y; } /** * Smoothly interpolate a number from `x` to `y` in a spring-like manner using a delta * time to maintain frame rate independent movement. For details, see * [Frame rate independent damping using lerp]{@link http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/}. * * @param {number} x - The current point. * @param {number} y - The target point. * @param {number} lambda - A higher lambda value will make the movement more sudden, * and a lower value will make the movement more gradual. * @param {number} dt - Delta time in seconds. * @return {number} The interpolated value. */ function damp( x, y, lambda, dt ) { return lerp$1( x, y, 1 - Math.exp( - lambda * dt ) ); } /** * Returns a value that alternates between `0` and the given `length` parameter. * * @param {number} x - The value to pingpong. * @param {number} [length=1] - The positive value the function will pingpong to. * @return {number} The alternated value. */ function pingpong( x, length = 1 ) { // https://www.desmos.com/calculator/vcsjnyz7x4 return length - Math.abs( euclideanModulo( x, length * 2 ) - length ); } /** * Returns a value in the range `[0,1]` that represents the percentage that `x` has * moved between `min` and `max`, but smoothed or slowed down the closer `x` is to * the `min` and `max`. * * See [Smoothstep]{@link 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`. * @return {number} The alternated value. */ function smoothstep( x, min, max ) { if ( x <= min ) return 0; if ( x >= max ) return 1; x = ( x - min ) / ( max - min ); return x * x * ( 3 - 2 * x ); } /** * A [variation on smoothstep]{@link https://en.wikipedia.org/wiki/Smoothstep#Variations} * 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`. * @return {number} The alternated value. */ function smootherstep( x, min, max ) { if ( x <= min ) return 0; if ( x >= max ) return 1; x = ( x - min ) / ( max - min ); return x * x * x * ( x * ( x * 6 - 15 ) + 10 ); } /** * Returns a random integer from `<low, high>` interval. * * @param {number} low - The lower value boundary. * @param {number} high - The upper value boundary * @return {number} A random integer. */ function randInt( low, high ) { return low + Math.floor( Math.random() * ( high - low + 1 ) ); } /** * Returns a random float from `<low, high>` interval. * * @param {number} low - The lower value boundary. * @param {number} high - The upper value boundary * @return {number} A random float. */ function randFloat( low, high ) { return low + Math.random() * ( high - low ); } /** * Returns a random integer from `<-range/2, range/2>` interval. * * @param {number} range - Defines the value range. * @return {number} A random float. */ function randFloatSpread( range ) { return range * ( 0.5 - Math.random() ); } /** * Returns a deterministic pseudo-random float in the interval `[0, 1]`. * * @param {number} [s] - The integer seed. * @return {number} A random float. */ function seededRandom( s ) { if ( s !== undefined ) _seed = s; // Mulberry32 generator let t = _seed += 0x6D2B79F5; t = Math.imul( t ^ t >>> 15, t | 1 ); t ^= t + Math.imul( t ^ t >>> 7, t | 61 ); return ( ( t ^ t >>> 14 ) >>> 0 ) / 4294967296; } /** * Converts degrees to radians. * * @param {number} degrees - A value in degrees. * @return {number} The converted value in radians. */ function degToRad( degrees ) { return degrees * DEG2RAD; } /** * Converts radians to degrees. * * @param {number} radians - A value in radians. * @return {number} The converted value in degrees. */ function radToDeg( radians ) { return radians * RAD2DEG; } /** * Returns `true` if the given number is a power of two. * * @param {number} value - The value to check. * @return {boolean} Whether the given number is a power of two or not. */ function isPowerOfTwo( value ) { return ( value & ( value - 1 ) ) === 0 && value !== 0; } /** * 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. * @return {number} The smallest power of two that is greater than or equal to the given number. */ function ceilPowerOfTwo( value ) { return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) ); } /** * 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. * @return {number} The largest power of two that is less than or equal to the given number. */ function floorPowerOfTwo( value ) { return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) ); } /** * Sets the given quaternion from the [Intrinsic Proper Euler Angles]{@link https://en.wikipedia.org/wiki/Euler_angles} * defined by the given angles and order. * * Rotations are applied to the axes in the order specified by order: * rotation by angle `a` is applied first, then by angle `b`, then by angle `c`. * * @param {Quaternion} q - The quaternion to set. * @param {number} a - The rotation applied to the first axis, in radians. * @param {number} b - The rotation applied to the second axis, in radians. * @param {number} c - The rotation applied to the third axis, in radians. * @param {('XYX'|'XZX'|'YXY'|'YZY'|'ZXZ'|'ZYZ')} order - A string specifying the axes order. */ function setQuaternionFromProperEuler( q, a, b, c, order ) { const cos = Math.cos; const sin = Math.sin; const c2 = cos( b / 2 ); const s2 = sin( b / 2 ); const c13 = cos( ( a + c ) / 2 ); const s13 = sin( ( a + c ) / 2 ); const c1_3 = cos( ( a - c ) / 2 ); const s1_3 = sin( ( a - c ) / 2 ); const c3_1 = cos( ( c - a ) / 2 ); const s3_1 = sin( ( c - a ) / 2 ); switch ( order ) { case 'XYX': q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 ); break; case 'YZY': q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 ); break; case 'ZXZ': q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 ); break; case 'XZX': q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 ); break; case 'YXY': q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 ); break; case 'ZYZ': q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 ); break; default: console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order ); } } /** * Denormalizes the given value according to the given typed array. * * @param {number} value - The value to denormalize. * @param {TypedArray} array - The typed array that defines the data type of the value. * @return {number} The denormalize (float) value in the range `[0,1]`. */ function denormalize( value, array ) { switch ( array.constructor ) { case Float32Array: return value; case Uint32Array: return value / 4294967295.0; case Uint16Array: return value / 65535.0; case Uint8Array: return value / 255.0; case Int32Array: return Math.max( value / 2147483647.0, -1 ); case Int16Array: return Math.max( value / 32767.0, -1 ); case Int8Array: return Math.max( value / 127.0, -1 ); default: throw new Error( 'Invalid component type.' ); } } /** * Normalizes the given value according to the given typed array. * * @param {number} value - The float value in the range `[0,1]` to normalize. * @param {TypedArray} array - The typed array that defines the data type of the value. * @return {number} The normalize value. */ function normalize( value, array ) { switch ( array.constructor ) { case Float32Array: return value; case Uint32Array: return Math.round( value * 4294967295.0 ); case Uint16Array: return Math.round( value * 65535.0 ); case Uint8Array: return Math.round( value * 255.0 ); case Int32Array: return Math.round( value * 2147483647.0 ); case Int16Array: return Math.round( value * 32767.0 ); case Int8Array: return Math.round( value * 127.0 ); default: throw new Error( 'Invalid component type.' ); } } const MathUtils = { DEG2RAD: DEG2RAD, RAD2DEG: RAD2DEG, generateUUID: generateUUID, clamp: clamp$1, euclideanModulo: euclideanModulo, mapLinear: mapLinear, inverseLerp: inverseLerp, lerp: lerp$1, damp: damp, pingpong: pingpong, smoothstep: smoothstep, smootherstep: smootherstep, randInt: randInt, randFloat: randFloat, randFloatSpread: randFloatSpread, seededRandom: seededRandom, degToRad: degToRad, radToDeg: radToDeg, isPowerOfTwo: isPowerOfTwo, ceilPowerOfTwo: ceilPowerOfTwo, floorPowerOfTwo: floorPowerOfTwo, setQuaternionFromProperEuler: setQuaternionFromProperEuler, normalize: normalize, denormalize: denormalize }; /** * Class representing a 2D vector. A 2D vector is an ordered pair of numbers * (labeled x and y), which can be used to represent a number of things, such as: * * - A point in 2D space (i.e. a position on a plane). * - A direction and length across a plane. In three.js the length will * always be the Euclidean distance(straight-line distance) from `(0, 0)` to `(x, y)` * and the direction is also measured from `(0, 0)` towards `(x, y)`. * - Any arbitrary ordered pair of numbers. * * There are other things a 2D vector can be used to represent, such as * momentum vectors, complex numbers and so on, however these are the most * common uses in three.js. * * Iterating through a vector instance will yield its components `(x, y)` in * the corresponding order. * ```js * const a = new THREE.Vector2( 0, 1 ); * * //no arguments; will be initialised to (0, 0) * const b = new THREE.Vector2( ); * * const d = a.distanceTo( b ); * ``` */ class Vector2 { /** * Constructs a new 2D vector. * * @param {number} [x=0] - The x value of this vector. * @param {number} [y=0] - The y value of this vector. */ constructor( x = 0, y = 0 ) { /** * This flag can be used for type testing. * * @type {boolean} * @readonly * @default true */ Vector2.prototype.isVector2 = true; /** * The x value of this vector. * * @type {number} */ this.x = x; /** * The y value of this vector. * * @type {number} */ this.y = y; } /** * Alias for {@link Vector2#x}. * * @type {number} */ get width() { return this.x; } set width( value ) { this.x = value; } /** * Alias for {@link Vector2#y}. * * @type {number} */ get height() { return this.y; } set height( value ) { this.y = value; } /** * Sets the vector components. * * @param {number} x - The value of the x component. * @param {number} y - The value of the y component. * @return {Vector2} A reference to this vector. */ set( x, y ) { this.x = x; this.y = y; return this; } /** * Sets the vector components to the same value. * * @param {number} scalar - The value to set for all vector components. * @return {Vector2} A reference to this vector. */ setScalar( scalar ) { this.x = scalar; this.y = scalar; return this; } /** * Sets the vector's x component to the given value * * @param {number} x - The value to set. * @return {Vector2} A reference to this vector. */ setX( x ) { this.x = x; return this; } /** * Sets the vector's y component to the given value * * @param {number} y - The value to set. * @return {Vector2} A reference to this vector. */ setY( y ) { this.y = y; return this; } /** * Allows to set a vector component with an index. * * @param {number} index - The component index. `0` equals to x, `1` equals to y. * @param {number} value - The value to set. * @return {Vector2} A reference to this vector. */ setComponent( index, value ) { switch ( index ) { case 0: this.x = value; break; case 1: this.y = value; break; default: throw new Error( 'index is out of range: ' + index ); } return this; } /** * Returns the value of the vector component which matches the given index. * * @param {number} index - The component index. `0` equals to x, `1` equals to y. * @return {number} A vector component value. */ getComponent( index ) { switch ( index ) { case 0: return this.x; case 1: return this.y; default: throw new Error( 'index is out of range: ' + index ); } } /** * Returns a new vector with copied values from this instance. * * @return {Vector2} A clone of this instance. */ clone() { return new this.constructor( this.x, this.y ); } /** * Copies the values of the given vector to this instance. * * @param {Vector2} v - The vector to copy. * @return {Vector2} A reference to this vector. */ copy( v ) { this.x = v.x; this.y = v.y; return this; } /** * Adds the given vector to this instance. * * @param {Vector2} v - The vector to add. * @return {Vector2} A reference to this vector. */ add( v ) { this.x += v.x; this.y += v.y; return this; } /** * Adds the given scalar value to all components of this instance. * * @param {number} s - The scalar to add. * @return {Vector2} A reference to this vector. */ addScalar( s ) { this.x += s; this.y += s; return this; } /** * Adds the given vectors and stores the result in this instance. * * @param {Vector2} a - The first vector. * @param {Vector2} b - The second vector. * @return {Vector2} A reference to this vector. */ addVectors( a, b ) { this.x = a.x + b.x; this.y = a.y + b.y; return this; } /** * Adds the given vector scaled by the given factor to this instance. * * @param {Vector2} v - The vector. * @param {number} s - The factor that scales `v`. * @return {Vector2} A reference to this vector. */ addScaledVector( v, s ) { this.x += v.x * s; this.y += v.y * s; return this; } /** * Subtracts the given vector from this instance. * * @param {Vector2} v - The vector to subtract. * @return {Vector2} A reference to this vector. */ sub( v ) { this.x -= v.x; this.y -= v.y; return this; } /** * Subtracts the given scalar value from all components of this instance. * * @param {number} s - The scalar to subtract. * @return {Vector2} A reference to this vector. */ subScalar( s ) { this.x -= s; this.y -= s; return this; } /** * Subtracts the given vectors and stores the result in this instance. * * @param {Vector2} a - The first vector. * @param {Vector2} b - The second vector. * @return {Vector2} A reference to this vector. */ subVectors( a, b ) { this.x = a.x - b.x; this.y = a.y - b.y; return this; } /** * Multiplies the given vector with this instance. * * @param {Vector2} v - The vector to multiply. * @return {Vector2} A reference to this vector. */ multiply( v ) { this.x *= v.x; this.y *= v.y; return this; } /** * Multiplies the given scalar value with all components of this instance. * * @param {number} scalar - The scalar to multiply. * @return {Vector2} A reference to this vector. */ multiplyScalar( scalar ) { this.x *= scalar; this.y *= scalar; return this; } /** * Divides this instance by the given vector. * * @param {Vector2} v - The vector to divide. * @return {Vector2} A reference to this vector. */ divide( v ) { this.x /= v.x; this.y /= v.y; return this; } /** * Divides this vector by the given scalar. * * @param {number} scalar - The scalar to divide. * @return {Vector2} A reference to this vector. */ divideScalar( scalar ) { return this.multiplyScalar( 1 / scalar ); } /** * Multiplies this vector (with an implicit 1 as the 3rd component) by * the given 3x3 matrix. * * @param {Matrix3} m - The matrix to apply. * @return {Vector2} A reference to this vector. */ applyMatrix3( m ) { const x = this.x, y = this.y; const e = m.elements; this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ]; this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ]; return this; } /** * If this vector's x or y value is greater than the given vector's x or y * value, replace that value with the corresponding min value. * * @param {Vector2} v - The vector. * @return {Vector2} A reference to this vector. */ min( v ) { this.x = Math.min( this.x, v.x ); this.y = Math.min( this.y, v.y ); return this; } /** * If this vector's x or y value is less than the given vector's x or y * value, replace that value with the corresponding max value. * * @param {Vector2} v - The vector. * @return {Vector2} A reference to this vector. */ max( v ) { this.x = Math.max( this.x, v.x ); this.y = Math.max( this.y, v.y ); return this; } /** * If this vector's x or y value is greater than the max vector's x or y * value, it is replaced by the corresponding value. * If this vector's x or y value is less than the min vector's x or y value, * it is replaced by the corresponding value. * * @param {Vector2} min - The minimum x and y values. * @param {Vector2} max - The maximum x and y values in the desired range. * @return {Vector2} A reference to this vector. */ clamp( min, max ) { // assumes min < max, componentwise this.x = clamp$1( this.x, min.x, max.x ); this.y = clamp$1( this.y, min.y, max.y ); return this; } /** * If this vector's x or y values are greater than the max value, they are * replaced by the max value. * If this vector's x or y values are less than the min value, they are * replaced by the min value. * * @param {number} minVal - The minimum value the components will be clamped to. * @param {number} maxVal - The maximum value the components will be clamped to. * @return {Vector2} A reference to this vector. */ clampScalar( minVal, maxVal ) { this.x = clamp$1( this.x, minVal, maxVal ); this.y = clamp$1( this.y, minVal, maxVal ); return this; } /** * If this vector's length is greater than the max value, it is replaced by * the max value. * If this vector's length is less than the min value, it is replaced by the * min value. * * @param {number} min - The minimum value the vector length will be clamped to. * @param {number} max - The maximum value the vector length will be clamped to. * @return {Vector2} A reference to this vector. */ clampLength( min, max ) { const length = this.length(); return this.divideScalar( length || 1 ).multiplyScalar( clamp$1( length, min, max ) ); } /** * The components of this vector are rounded down to the nearest integer value. * * @return {Vector2} A reference to this vector. */ floor() { this.x = Math.floor( this.x ); this.y = Math.floor( this.y ); return this; } /** * The components of this vector are rounded up to the nearest integer value. * * @return {Vector2} A reference to this vector. */ ceil() { this.x = Math.ceil( this.x ); this.y = Math.ceil( this.y ); return this; } /** * The components of this vector are rounded to the nearest integer value * * @return {Vector2} A reference to this vector. */ round() { this.x = Math.round( this.x ); this.y = Math.round( this.y ); return this; } /** * The components of this vector are rounded towards zero (up if negative, * down if positive) to an integer value. * * @return {Vector2} A reference to this vector. */ roundToZero() { this.x = Math.trunc( this.x ); this.y = Math.trunc( this.y ); return this; } /** * Inverts this vector - i.e. sets x = -x and y = -y. * * @return {Vector2} A reference to this vector. */ negate() { this.x = - this.x; this.y = - this.y; return this; } /** * Calculates the dot product of the given vector with this instance. * * @param {Vector2} v - The vector to compute the dot product with. * @return {number} The result of the dot product. */ dot( v ) { return this.x * v.x + this.y * v.y; } /** * Calculates the cross product of the given vector with this instance. * * @param {Vector2} v - The vector to compute the cross product with. * @return {number} The result of the cross product. */ cross( v ) { return this.x * v.y - this.y * v.x; } /** * Computes the square of the Euclidean length (straight-line length) from * (0, 0) to (x, y). If you are comparing the lengths of vectors, you should * compare the length squared instead as it is slightly more efficient to calculate. * * @return {number} The square length of this vector. */ lengthSq() { return this.x * this.x + this.y * this.y; } /** * Computes the Euclidean length (straight-line length) from (0, 0) to (x, y). * * @return {number} The length of this vector. */ length() { return Math.sqrt( this.x * this.x + this.y * this.y ); } /** * Computes the Manhattan length of this vector. * * @return {number} The length of this vector. */ manhattanLength() { return Math.abs( this.x ) + Math.abs( this.y ); } /** * Converts this vector to a unit vector - that is, sets it equal to a vector * with the same direction as this one, but with a vector length of `1`. * * @return {Vector2} A reference to this vector. */ normalize() { return this.divideScalar( this.length() || 1 ); } /** * Computes the angle in radians of this vector with respect to the positive x-axis. * * @return {number} The angle in radians. */ angle() { const angle = Math.atan2( - this.y, - this.x ) + Math.PI; return angle; } /** * Returns the angle between the given vector and this instance in radians. * * @param {Vector2} v - The vector to compute the angle with. * @return {number} The angle in radians. */ angleTo( v ) { const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); if ( denominator === 0 ) return Math.PI / 2; const theta = this.dot( v ) / denominator; // clamp, to handle numerical problems return Math.acos( clamp$1( theta, -1, 1 ) ); } /** * Computes the distance from the given vector to this instance. * * @param {Vector2} v - The vector to compute the distance to. * @return {number} The distance. */ distanceTo( v ) { return Math.sqrt( this.distanceToSquared( v ) ); } /** * Computes the squared distance from the given vector to this instance. * If you are just comparing the distance with another distance, you should compare * the distance squared instead as it is slightly more efficient to calculate. * * @param {Vector2} v - The vector to compute the squared distance to. * @return {number} The squared distance. */ distanceToSquared( v ) { const dx = this.x - v.x, dy = this.y - v.y; return dx * dx + dy * dy; } /** * Computes the Manhattan distance from the given vector to this instance. * * @param {Vector2} v - The vector to compute the Manhattan distance to. * @return {number} The Manhattan distance. */ manhattanDistanceTo( v ) { return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ); } /** * Sets this vector to a vector with the same direction as this one, but * with the specified length. * * @param {number} length - The new length of this vector. * @return {Vector2} A reference to this vector. */ setLength( length ) { return this.normalize().multiplyScalar( length ); } /** * Linearly interpolates between the given vector and this instance, where * alpha is the percent distance along the line - alpha = 0 will be this * vector, and alpha = 1 will be the given one. * * @param {Vector2} v - The vector to interpolate towards. * @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`. * @return {Vector2} A reference to this vector. */ lerp( v, alpha ) { this.x += ( v.x - this.x ) * alpha; this.y += ( v.y - this.y ) * alpha; return this; } /** * Linearly interpolates between the given vectors, where alpha is the percent * distance along the line - alpha = 0 will be first vector, and alpha = 1 will * be the second one. The result is stored in this instance. * * @param {Vector2} v1 - The first vector. * @param {Vector2} v2 - The second vector. * @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`. * @return {Vector2} A reference to this vector. */ lerpVectors( v1, v2, alpha ) { this.x = v1.x + ( v2.x - v1.x ) * alpha; this.y = v1.y + ( v2.y - v1.y ) * alpha; return this; } /** * Returns `true` if this vector is equal with the given one. * * @param {Vector2} v - The vector to test for equality. * @return {boolean} Whether this vector is equal with the given one. */ equals( v ) { return ( ( v.x === this.x ) && ( v.y === this.y ) ); } /** * Sets this vector's x value to be `array[ offset ]` and y * value to be `array[ offset + 1 ]`. * * @param {Array<number>} array - An array holding the vector component values. * @param {number} [offset=0] - The offset into the array. * @return {Vector2} A reference to this vector. */ fromArray( array, offset = 0 ) { this.x = array[ offset ]; this.y = array[ offset + 1 ]; return this; } /** * Writes the components of this vector to the given array. If no array is provided, * the method returns a new instance. * * @param {Array<number>} [array=[]] - The target array holding the vector components. * @param {number} [offset=0] - Index of the first element in the array. * @return {Array<number>} The vector components. */ toArray( array = [], offset = 0 ) { array[ offset ] = this.x; array[ offset + 1 ] = this.y; return array; } /** * Sets the components of this vector from the given buffer attribute. * * @param {BufferAttribute} attribute - The buffer attribute holding vector data. * @param {number} index - The index into the attribute. * @return {Vector2} A reference to this vector. */ fromBufferAttribute( attribute, index ) { this.x = attribute.getX( index ); this.y = attribute.getY( index ); return this; } /** * Rotates this vector around the given center by the given angle. * * @param {Vector2} center - The point around which to rotate. * @param {number} angle - The angle to rotate, in radians. * @return {Vector2} A reference to this vector. */ rotateAround( center, angle ) { const c = Math.cos( angle ), s = Math.sin( angle ); const x = this.x - center.x; const y = this.y - center.y; this.x = x * c - y * s + center.x; this.y = x * s + y * c + center.y; return this; } /** * Sets each component of this vector to a pseudo-random value between `0` and * `1`, excluding `1`. * * @return {Vector2} A reference to this vector. */ random() { this.x = Math.random(); this.y = Math.random(); return this; } *[ Symbol.iterator ]() { yield this.x; yield this.y; } } /** * Represents a 3x3 matrix. * * A Note on Row-Major and Column-Major Ordering: * * The constructor and {@link Matrix3#set} method take arguments in * [row-major]{@link https://en.wikipedia.org/wiki/Row-_and_column-major_order#Column-major_order} * order, while internally they are stored in the {@link Matrix3#elements} array in column-major order. * This means that calling: * ```js * const m = new THREE.Matrix(); * m.set( 11, 12, 13, * 21, 22, 23, * 31, 32, 33 ); * ``` * will result in the elements array containing: * ```js * m.elements = [ 11, 21, 31, * 12, 22, 32, * 13, 23, 33 ]; * ``` * and internally all calculations are performed using column-major ordering. * However, as the actual ordering makes no difference mathematically and * most people are used to thinking about matrices in row-major order, the * three.js documentation shows matrices in row-major order. Just bear in * mind that if you are reading the source code, you'll have to take the * transpose of any matrices outlined here to make sense of the calculations. */ class Matrix3 { /** * Constructs a new 3x3 matrix. The arguments are supposed to be * in row-major order. If no arguments are provided, the constructor * initializes the matrix as an identity matrix. * * @param {number} [n11] - 1-1 matrix element. * @param {number} [n12] - 1-2 matrix element. * @param {number} [n13] - 1-3 matrix element. * @param {number} [n21] - 2-1 matrix element. * @param {number} [n22] - 2-2 matrix element. * @param {number} [n23] - 2-3 matrix element. * @param {number} [n31] - 3-1 matrix element. * @param {number} [n32] - 3-2 matrix element. * @param {number} [n33] - 3-3 matrix element. */ constructor(