@google/model-viewer
Version:
Easily display interactive 3D models on the web and in AR!
2,115 lines (1,730 loc) • 2.57 MB
JavaScript
/**
* @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$2=Symbol(),o$4=new WeakMap;let n$4 = class n{constructor(t,e,o){if(this._$cssResult$=true,o!==s$2)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$4.get(s)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&o$4.set(s,t));}return t}toString(){return this.cssText}};const r$3=t=>new n$4("string"==typeof t?t:t+"",void 0,s$2),S$2=(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$3(e)})(t):t;
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/const{is:i$3,defineProperty:e$1,getOwnPropertyDescriptor:h$1,getOwnPropertyNames:r$2,getOwnPropertySymbols:o$3,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),b$2={attribute:true,type:String,converter:u$2,reflect:false,useDefault:false,hasChanged:f$1};Symbol.metadata??=Symbol("metadata"),a$2.litPropertyMetadata??=new WeakMap;let y$2 = class y 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=b$2){if(s.state&&(s.attribute=false),this._$Ei(),this.prototype.hasOwnProperty(t)&&((s=Object.create(s)).wrapped=true),this.elementProperties.set(t,s),!s.noAccessor){const i=Symbol(),h=this.getPropertyDescriptor(t,i,s);void 0!==h&&e$1(this.prototype,t,h);}}static getPropertyDescriptor(t,s,i){const{get:e,set:r}=h$1(this.prototype,t)??{get(){return this[s]},set(t){this[s]=t;}};return {get:e,set(s){const h=e?.call(this);r?.call(this,s),this.requestUpdate(t,h,i);},configurable:true,enumerable:true}}static getPropertyOptions(t){return this.elementProperties.get(t)??b$2}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=[...r$2(t),...o$3(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$2(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);}_$ET(t,s){const i=this.constructor.elementProperties.get(t),e=this.constructor._$Eu(t,i);if(void 0!==e&&true===i.reflect){const h=(void 0!==i.converter?.toAttribute?i.converter:u$2).toAttribute(s,i.type);this._$Em=t,null==h?this.removeAttribute(e):this.setAttribute(e,h),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),h="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:u$2;this._$Em=e;const r=h.fromAttribute(s,t.type);this[e]=r??this._$Ej?.get(e)??r,this._$Em=null;}}requestUpdate(t,s,i,e=false,h){if(void 0!==t){const r=this.constructor;if(false===e&&(h=this[t]),i??=r.getPropertyOptions(t),!((i.hasChanged??f$1)(h,s)||i.useDefault&&i.reflect&&h===this._$Ej?.get(t)&&!this.hasAttribute(r._$Eu(t,i))))return;this.C(t,s,i);} false===this.isUpdatePending&&(this._$ES=this._$EP());}C(t,s,{useDefault:i,reflect:e,wrapped:h},r){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,r??s??this[t]),true!==h||void 0!==r)||(this._$AL.has(t)||(this.hasUpdated||i||(s=void 0),this._$AL.set(t,s)),true===e&&this._$Em!==t&&(this._$Eq??=new Set).add(t));}async _$EP(){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){const{wrapped:t}=i,e=this[s];true!==t||this._$AL.has(s)||void 0===e||this.C(s,void 0,i,e);}}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._$EM();}catch(s){throw t=false,this._$EM(),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);}_$EM(){this._$AL=new Map,this.isUpdatePending=false;}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return true}update(t){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM();}updated(t){}firstUpdated(t){}};y$2.elementStyles=[],y$2.shadowRootOptions={mode:"open"},y$2[d$1("elementProperties")]=new Map,y$2[d$1("finalized")]=new Map,p$1?.({ReactiveElement:y$2}),(a$2.reactiveElementVersions??=[]).push("2.1.2");
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/const o$2={attribute:true,type:String,converter:u$2,reflect:false,hasChanged:f$1},r$1=(t=o$2,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),"setter"===n&&((t=Object.create(t)).wrapped=true),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,true,r);},init(e){return void 0!==e&&this.C(o,void 0,t,e),e}}}if("setter"===n){const{name:o}=r;return function(r){const n=this[o];e.call(this,r),this.requestUpdate(o,n,t,true,r);}}throw Error("Unsupported decorator location: "+n)};function n$2(t){return (e,o)=>"object"==typeof o?r$1(t,e,o):((t,e,o)=>{const r=e.hasOwnProperty(o);return e.constructor.createProperty(o,t),r?Object.getOwnPropertyDescriptor(e,o):void 0})(t,e,o)}
/**
* @license
* Copyright 2010-2025 Three.js Authors
* SPDX-License-Identifier: MIT
*/
const REVISION = '182';
/**
* Disables face culling.
*
* @type {number}
* @constant
*/
const CullFaceNone = 0;
/**
* Culls back faces.
*
* @type {number}
* @constant
*/
const CullFaceBack = 1;
/**
* Culls front faces.
*
* @type {number}
* @constant
*/
const CullFaceFront = 2;
/**
* Filters shadow maps using the Percentage-Closer Filtering (PCF) algorithm.
*
* @type {number}
* @constant
*/
const PCFShadowMap = 1;
/**
* Filters shadow maps using the Percentage-Closer Filtering (PCF) algorithm with
* better soft shadows especially when using low-resolution shadow maps.
*
* @type {number}
* @constant
*/
const PCFSoftShadowMap = 2;
/**
* Filters shadow maps using the Variance Shadow Map (VSM) algorithm.
* When using VSMShadowMap all shadow receivers will also cast shadows.
*
* @type {number}
* @constant
*/
const VSMShadowMap = 3;
/**
* Only front faces are rendered.
*
* @type {number}
* @constant
*/
const FrontSide = 0;
/**
* Only back faces are rendered.
*
* @type {number}
* @constant
*/
const BackSide = 1;
/**
* Both front and back faces are rendered.
*
* @type {number}
* @constant
*/
const DoubleSide = 2;
/**
* No blending is performed which effectively disables
* alpha transparency.
*
* @type {number}
* @constant
*/
const NoBlending = 0;
/**
* The default blending.
*
* @type {number}
* @constant
*/
const NormalBlending = 1;
/**
* Represents additive blending.
*
* @type {number}
* @constant
*/
const AdditiveBlending = 2;
/**
* Represents subtractive blending.
*
* @type {number}
* @constant
*/
const SubtractiveBlending = 3;
/**
* Represents multiply blending.
*
* @type {number}
* @constant
*/
const MultiplyBlending = 4;
/**
* Represents custom blending.
*
* @type {number}
* @constant
*/
const CustomBlending = 5;
/**
* A `source + destination` blending equation.
*
* @type {number}
* @constant
*/
const AddEquation = 100;
/**
* A `source - destination` blending equation.
*
* @type {number}
* @constant
*/
const SubtractEquation = 101;
/**
* A `destination - source` blending equation.
*
* @type {number}
* @constant
*/
const ReverseSubtractEquation = 102;
/**
* A blend equation that uses the minimum of source and destination.
*
* @type {number}
* @constant
*/
const MinEquation = 103;
/**
* A blend equation that uses the maximum of source and destination.
*
* @type {number}
* @constant
*/
const MaxEquation = 104;
/**
* Multiplies all colors by `0`.
*
* @type {number}
* @constant
*/
const ZeroFactor = 200;
/**
* Multiplies all colors by `1`.
*
* @type {number}
* @constant
*/
const OneFactor = 201;
/**
* Multiplies all colors by the source colors.
*
* @type {number}
* @constant
*/
const SrcColorFactor = 202;
/**
* Multiplies all colors by `1` minus each source color.
*
* @type {number}
* @constant
*/
const OneMinusSrcColorFactor = 203;
/**
* Multiplies all colors by the source alpha value.
*
* @type {number}
* @constant
*/
const SrcAlphaFactor = 204;
/**
* Multiplies all colors by 1 minus the source alpha value.
*
* @type {number}
* @constant
*/
const OneMinusSrcAlphaFactor = 205;
/**
* Multiplies all colors by the destination alpha value.
*
* @type {number}
* @constant
*/
const DstAlphaFactor = 206;
/**
* Multiplies all colors by `1` minus the destination alpha value.
*
* @type {number}
* @constant
*/
const OneMinusDstAlphaFactor = 207;
/**
* Multiplies all colors by the destination color.
*
* @type {number}
* @constant
*/
const DstColorFactor = 208;
/**
* Multiplies all colors by `1` minus each destination color.
*
* @type {number}
* @constant
*/
const OneMinusDstColorFactor = 209;
/**
* Multiplies the RGB colors by the smaller of either the source alpha
* value or the value of `1` minus the destination alpha value. The alpha
* value is multiplied by `1`.
*
* @type {number}
* @constant
*/
const SrcAlphaSaturateFactor = 210;
/**
* Multiplies all colors by a constant color.
*
* @type {number}
* @constant
*/
const ConstantColorFactor = 211;
/**
* Multiplies all colors by `1` minus a constant color.
*
* @type {number}
* @constant
*/
const OneMinusConstantColorFactor = 212;
/**
* Multiplies all colors by a constant alpha value.
*
* @type {number}
* @constant
*/
const ConstantAlphaFactor = 213;
/**
* Multiplies all colors by 1 minus a constant alpha value.
*
* @type {number}
* @constant
*/
const OneMinusConstantAlphaFactor = 214;
/**
* Never pass.
*
* @type {number}
* @constant
*/
const NeverDepth = 0;
/**
* Always pass.
*
* @type {number}
* @constant
*/
const AlwaysDepth = 1;
/**
* Pass if the incoming value is less than the depth buffer value.
*
* @type {number}
* @constant
*/
const LessDepth = 2;
/**
* Pass if the incoming value is less than or equal to the depth buffer value.
*
* @type {number}
* @constant
*/
const LessEqualDepth = 3;
/**
* Pass if the incoming value equals the depth buffer value.
*
* @type {number}
* @constant
*/
const EqualDepth = 4;
/**
* Pass if the incoming value is greater than or equal to the depth buffer value.
*
* @type {number}
* @constant
*/
const GreaterEqualDepth = 5;
/**
* Pass if the incoming value is greater than the depth buffer value.
*
* @type {number}
* @constant
*/
const GreaterDepth = 6;
/**
* Pass if the incoming value is not equal to the depth buffer value.
*
* @type {number}
* @constant
*/
const NotEqualDepth = 7;
/**
* Multiplies the environment map color with the surface color.
*
* @type {number}
* @constant
*/
const MultiplyOperation = 0;
/**
* Uses reflectivity to blend between the two colors.
*
* @type {number}
* @constant
*/
const MixOperation = 1;
/**
* Adds the two colors.
*
* @type {number}
* @constant
*/
const AddOperation = 2;
/**
* No tone mapping is applied.
*
* @type {number}
* @constant
*/
const NoToneMapping = 0;
/**
* Linear tone mapping.
*
* @type {number}
* @constant
*/
const LinearToneMapping = 1;
/**
* Reinhard tone mapping.
*
* @type {number}
* @constant
*/
const ReinhardToneMapping = 2;
/**
* Cineon tone mapping.
*
* @type {number}
* @constant
*/
const CineonToneMapping = 3;
/**
* ACES Filmic tone mapping.
*
* @type {number}
* @constant
*/
const ACESFilmicToneMapping = 4;
/**
* Custom tone mapping.
*
* Expects a custom implementation by modifying shader code of the material's fragment shader.
*
* @type {number}
* @constant
*/
const CustomToneMapping = 5;
/**
* AgX tone mapping.
*
* @type {number}
* @constant
*/
const AgXToneMapping = 6;
/**
* Neutral tone mapping.
*
* Implementation based on the Khronos 3D Commerce Group standard tone mapping.
*
* @type {number}
* @constant
*/
const NeutralToneMapping = 7;
/**
* The skinned mesh shares the same world space as the skeleton.
*
* @type {string}
* @constant
*/
const AttachedBindMode = 'attached';
/**
* The skinned mesh does not share the same world space as the skeleton.
* This is useful when a skeleton is shared across multiple skinned meshes.
*
* @type {string}
* @constant
*/
const DetachedBindMode = 'detached';
/**
* Maps textures using the geometry's UV coordinates.
*
* @type {number}
* @constant
*/
const UVMapping = 300;
/**
* Reflection mapping for cube textures.
*
* @type {number}
* @constant
*/
const CubeReflectionMapping = 301;
/**
* Refraction mapping for cube textures.
*
* @type {number}
* @constant
*/
const CubeRefractionMapping = 302;
/**
* Reflection mapping for equirectangular textures.
*
* @type {number}
* @constant
*/
const EquirectangularReflectionMapping = 303;
/**
* Refraction mapping for equirectangular textures.
*
* @type {number}
* @constant
*/
const EquirectangularRefractionMapping = 304;
/**
* Reflection mapping for PMREM textures.
*
* @type {number}
* @constant
*/
const CubeUVReflectionMapping = 306;
/**
* The texture will simply repeat to infinity.
*
* @type {number}
* @constant
*/
const RepeatWrapping = 1000;
/**
* The last pixel of the texture stretches to the edge of the mesh.
*
* @type {number}
* @constant
*/
const ClampToEdgeWrapping = 1001;
/**
* The texture will repeats to infinity, mirroring on each repeat.
*
* @type {number}
* @constant
*/
const MirroredRepeatWrapping = 1002;
/**
* Returns the value of the texture element that is nearest (in Manhattan distance)
* to the specified texture coordinates.
*
* @type {number}
* @constant
*/
const NearestFilter = 1003;
/**
* Chooses the mipmap that most closely matches the size of the pixel being textured
* and uses the `NearestFilter` criterion (the texel nearest to the center of the pixel)
* to produce a texture value.
*
* @type {number}
* @constant
*/
const NearestMipmapNearestFilter = 1004;
/**
* Chooses the two mipmaps that most closely match the size of the pixel being textured and
* uses the `NearestFilter` criterion to produce a texture value from each mipmap.
* The final texture value is a weighted average of those two values.
*
* @type {number}
* @constant
*/
const NearestMipmapLinearFilter = 1005;
/**
* Returns the weighted average of the four texture elements that are closest to the specified
* texture coordinates, and can include items wrapped or repeated from other parts of a texture,
* depending on the values of `wrapS` and `wrapT`, and on the exact mapping.
*
* @type {number}
* @constant
*/
const LinearFilter = 1006;
/**
* Chooses the mipmap that most closely matches the size of the pixel being textured and uses
* the `LinearFilter` criterion (a weighted average of the four texels that are closest to the
* center of the pixel) to produce a texture value.
*
* @type {number}
* @constant
*/
const LinearMipmapNearestFilter = 1007;
/**
* Chooses the two mipmaps that most closely match the size of the pixel being textured and uses
* the `LinearFilter` criterion to produce a texture value from each mipmap. The final texture value
* is a weighted average of those two values.
*
* @type {number}
* @constant
*/
const LinearMipmapLinearFilter = 1008;
const LinearMipMapLinearFilter = 1008; // legacy
/**
* An unsigned byte data type for textures.
*
* @type {number}
* @constant
*/
const UnsignedByteType = 1009;
/**
* A byte data type for textures.
*
* @type {number}
* @constant
*/
const ByteType = 1010;
/**
* A short data type for textures.
*
* @type {number}
* @constant
*/
const ShortType = 1011;
/**
* An unsigned short data type for textures.
*
* @type {number}
* @constant
*/
const UnsignedShortType = 1012;
/**
* An int data type for textures.
*
* @type {number}
* @constant
*/
const IntType = 1013;
/**
* An unsigned int data type for textures.
*
* @type {number}
* @constant
*/
const UnsignedIntType = 1014;
/**
* A float data type for textures.
*
* @type {number}
* @constant
*/
const FloatType = 1015;
/**
* A half float data type for textures.
*
* @type {number}
* @constant
*/
const HalfFloatType = 1016;
/**
* An unsigned short 4_4_4_4 (packed) data type for textures.
*
* @type {number}
* @constant
*/
const UnsignedShort4444Type = 1017;
/**
* An unsigned short 5_5_5_1 (packed) data type for textures.
*
* @type {number}
* @constant
*/
const UnsignedShort5551Type = 1018;
/**
* An unsigned int 24_8 data type for textures.
*
* @type {number}
* @constant
*/
const UnsignedInt248Type = 1020;
/**
* An unsigned int 5_9_9_9 (packed) data type for textures.
*
* @type {number}
* @constant
*/
const UnsignedInt5999Type = 35902;
/**
* An unsigned int 10_11_11 (packed) data type for textures.
*
* @type {number}
* @constant
*/
const UnsignedInt101111Type = 35899;
/**
* Discards the red, green and blue components and reads just the alpha component.
*
* @type {number}
* @constant
*/
const AlphaFormat = 1021;
/**
* Discards the alpha component and reads the red, green and blue component.
*
* @type {number}
* @constant
*/
const RGBFormat = 1022;
/**
* Reads the red, green, blue and alpha components.
*
* @type {number}
* @constant
*/
const RGBAFormat = 1023;
/**
* Reads each element as a single depth value, converts it to floating point, and clamps to the range `[0,1]`.
*
* @type {number}
* @constant
*/
const DepthFormat = 1026;
/**
* Reads each element is a pair of depth and stencil values. The depth component of the pair is interpreted as
* in `DepthFormat`. The stencil component is interpreted based on the depth + stencil internal format.
*
* @type {number}
* @constant
*/
const DepthStencilFormat = 1027;
/**
* Discards the green, blue and alpha components and reads just the red component.
*
* @type {number}
* @constant
*/
const RedFormat = 1028;
/**
* Discards the green, blue and alpha components and reads just the red component. The texels are read as integers instead of floating point.
*
* @type {number}
* @constant
*/
const RedIntegerFormat = 1029;
/**
* Discards the alpha, and blue components and reads the red, and green components.
*
* @type {number}
* @constant
*/
const RGFormat = 1030;
/**
* Discards the alpha, and blue components and reads the red, and green components. The texels are read as integers instead of floating point.
*
* @type {number}
* @constant
*/
const RGIntegerFormat = 1031;
/**
* Reads the red, green, blue and alpha components. The texels are read as integers instead of floating point.
*
* @type {number}
* @constant
*/
const RGBAIntegerFormat = 1033;
/**
* A DXT1-compressed image in an RGB image format.
*
* @type {number}
* @constant
*/
const RGB_S3TC_DXT1_Format = 33776;
/**
* A DXT1-compressed image in an RGB image format with a simple on/off alpha value.
*
* @type {number}
* @constant
*/
const RGBA_S3TC_DXT1_Format = 33777;
/**
* A DXT3-compressed image in an RGBA image format. Compared to a 32-bit RGBA texture, it offers 4:1 compression.
*
* @type {number}
* @constant
*/
const RGBA_S3TC_DXT3_Format = 33778;
/**
* A DXT5-compressed image in an RGBA image format. It also provides a 4:1 compression, but differs to the DXT3
* compression in how the alpha compression is done.
*
* @type {number}
* @constant
*/
const RGBA_S3TC_DXT5_Format = 33779;
/**
* PVRTC RGB compression in 4-bit mode. One block for each 4×4 pixels.
*
* @type {number}
* @constant
*/
const RGB_PVRTC_4BPPV1_Format = 35840;
/**
* PVRTC RGB compression in 2-bit mode. One block for each 8×4 pixels.
*
* @type {number}
* @constant
*/
const RGB_PVRTC_2BPPV1_Format = 35841;
/**
* PVRTC RGBA compression in 4-bit mode. One block for each 4×4 pixels.
*
* @type {number}
* @constant
*/
const RGBA_PVRTC_4BPPV1_Format = 35842;
/**
* PVRTC RGBA compression in 2-bit mode. One block for each 8×4 pixels.
*
* @type {number}
* @constant
*/
const RGBA_PVRTC_2BPPV1_Format = 35843;
/**
* ETC1 RGB format.
*
* @type {number}
* @constant
*/
const RGB_ETC1_Format = 36196;
/**
* ETC2 RGB format.
*
* @type {number}
* @constant
*/
const RGB_ETC2_Format = 37492;
/**
* ETC2 RGBA format.
*
* @type {number}
* @constant
*/
const RGBA_ETC2_EAC_Format = 37496;
/**
* EAC R11 UNORM format.
*
* @type {number}
* @constant
*/
const R11_EAC_Format = 37488; // 0x9270
/**
* EAC R11 SNORM format.
*
* @type {number}
* @constant
*/
const SIGNED_R11_EAC_Format = 37489; // 0x9271
/**
* EAC RG11 UNORM format.
*
* @type {number}
* @constant
*/
const RG11_EAC_Format = 37490; // 0x9272
/**
* EAC RG11 SNORM format.
*
* @type {number}
* @constant
*/
const SIGNED_RG11_EAC_Format = 37491; // 0x9273
/**
* ASTC RGBA 4x4 format.
*
* @type {number}
* @constant
*/
const RGBA_ASTC_4x4_Format = 37808;
/**
* ASTC RGBA 5x4 format.
*
* @type {number}
* @constant
*/
const RGBA_ASTC_5x4_Format = 37809;
/**
* ASTC RGBA 5x5 format.
*
* @type {number}
* @constant
*/
const RGBA_ASTC_5x5_Format = 37810;
/**
* ASTC RGBA 6x5 format.
*
* @type {number}
* @constant
*/
const RGBA_ASTC_6x5_Format = 37811;
/**
* ASTC RGBA 6x6 format.
*
* @type {number}
* @constant
*/
const RGBA_ASTC_6x6_Format = 37812;
/**
* ASTC RGBA 8x5 format.
*
* @type {number}
* @constant
*/
const RGBA_ASTC_8x5_Format = 37813;
/**
* ASTC RGBA 8x6 format.
*
* @type {number}
* @constant
*/
const RGBA_ASTC_8x6_Format = 37814;
/**
* ASTC RGBA 8x8 format.
*
* @type {number}
* @constant
*/
const RGBA_ASTC_8x8_Format = 37815;
/**
* ASTC RGBA 10x5 format.
*
* @type {number}
* @constant
*/
const RGBA_ASTC_10x5_Format = 37816;
/**
* ASTC RGBA 10x6 format.
*
* @type {number}
* @constant
*/
const RGBA_ASTC_10x6_Format = 37817;
/**
* ASTC RGBA 10x8 format.
*
* @type {number}
* @constant
*/
const RGBA_ASTC_10x8_Format = 37818;
/**
* ASTC RGBA 10x10 format.
*
* @type {number}
* @constant
*/
const RGBA_ASTC_10x10_Format = 37819;
/**
* ASTC RGBA 12x10 format.
*
* @type {number}
* @constant
*/
const RGBA_ASTC_12x10_Format = 37820;
/**
* ASTC RGBA 12x12 format.
*
* @type {number}
* @constant
*/
const RGBA_ASTC_12x12_Format = 37821;
/**
* BPTC RGBA format.
*
* @type {number}
* @constant
*/
const RGBA_BPTC_Format = 36492;
/**
* BPTC Signed RGB format.
*
* @type {number}
* @constant
*/
const RGB_BPTC_SIGNED_Format = 36494;
/**
* BPTC Unsigned RGB format.
*
* @type {number}
* @constant
*/
const RGB_BPTC_UNSIGNED_Format = 36495;
/**
* RGTC1 Red format.
*
* @type {number}
* @constant
*/
const RED_RGTC1_Format = 36283;
/**
* RGTC1 Signed Red format.
*
* @type {number}
* @constant
*/
const SIGNED_RED_RGTC1_Format = 36284;
/**
* RGTC2 Red Green format.
*
* @type {number}
* @constant
*/
const RED_GREEN_RGTC2_Format = 36285;
/**
* RGTC2 Signed Red Green format.
*
* @type {number}
* @constant
*/
const SIGNED_RED_GREEN_RGTC2_Format = 36286;
/**
* Animations are played once.
*
* @type {number}
* @constant
*/
const LoopOnce = 2200;
/**
* Animations are played with a chosen number of repetitions, each time jumping from
* the end of the clip directly to its beginning.
*
* @type {number}
* @constant
*/
const LoopRepeat = 2201;
/**
* Animations are played with a chosen number of repetitions, alternately playing forward
* and backward.
*
* @type {number}
* @constant
*/
const LoopPingPong = 2202;
/**
* Discrete interpolation mode for keyframe tracks.
*
* @type {number}
* @constant
*/
const InterpolateDiscrete = 2300;
/**
* Linear interpolation mode for keyframe tracks.
*
* @type {number}
* @constant
*/
const InterpolateLinear = 2301;
/**
* Smooth interpolation mode for keyframe tracks.
*
* @type {number}
* @constant
*/
const InterpolateSmooth = 2302;
/**
* Zero curvature ending for animations.
*
* @type {number}
* @constant
*/
const ZeroCurvatureEnding = 2400;
/**
* Zero slope ending for animations.
*
* @type {number}
* @constant
*/
const ZeroSlopeEnding = 2401;
/**
* Wrap around ending for animations.
*
* @type {number}
* @constant
*/
const WrapAroundEnding = 2402;
/**
* Default animation blend mode.
*
* @type {number}
* @constant
*/
const NormalAnimationBlendMode = 2500;
/**
* Additive animation blend mode. Can be used to layer motions on top of
* each other to build complex performances from smaller re-usable assets.
*
* @type {number}
* @constant
*/
const AdditiveAnimationBlendMode = 2501;
/**
* For every three vertices draw a single triangle.
*
* @type {number}
* @constant
*/
const TrianglesDrawMode = 0;
/**
* For each vertex draw a triangle from the last three vertices.
*
* @type {number}
* @constant
*/
const TriangleStripDrawMode = 1;
/**
* For each vertex draw a triangle from the first vertex and the last two vertices.
*
* @type {number}
* @constant
*/
const TriangleFanDrawMode = 2;
/**
* The depth value is inverted (1.0 - z) for visualization purposes.
*
* @type {number}
* @constant
*/
const BasicDepthPacking = 3200;
/**
* Normal information is relative to the underlying surface.
*
* @type {number}
* @constant
*/
const TangentSpaceNormalMap = 0;
/**
* Normal information is relative to the object orientation.
*
* @type {number}
* @constant
*/
const ObjectSpaceNormalMap = 1;
// Color space string identifiers, matching CSS Color Module Level 4 and WebGPU names where available.
/**
* No color space.
*
* @type {string}
* @constant
*/
const NoColorSpace = '';
/**
* sRGB color space.
*
* @type {string}
* @constant
*/
const SRGBColorSpace = 'srgb';
/**
* sRGB-linear color space.
*
* @type {string}
* @constant
*/
const LinearSRGBColorSpace = 'srgb-linear';
/**
* Linear transfer function.
*
* @type {string}
* @constant
*/
const LinearTransfer = 'linear';
/**
* sRGB transfer function.
*
* @type {string}
* @constant
*/
const SRGBTransfer = 'srgb';
/**
* Keeps the current value.
*
* @type {number}
* @constant
*/
const KeepStencilOp = 7680;
/**
* Will always return true.
*
* @type {number}
* @constant
*/
const AlwaysStencilFunc = 519;
/**
* Never pass.
*
* @type {number}
* @constant
*/
const NeverCompare = 512;
/**
* Pass if the incoming value is less than the texture value.
*
* @type {number}
* @constant
*/
const LessCompare = 513;
/**
* Pass if the incoming value equals the texture value.
*
* @type {number}
* @constant
*/
const EqualCompare = 514;
/**
* Pass if the incoming value is less than or equal to the texture value.
*
* @type {number}
* @constant
*/
const LessEqualCompare = 515;
/**
* Pass if the incoming value is greater than the texture value.
*
* @type {number}
* @constant
*/
const GreaterCompare = 516;
/**
* Pass if the incoming value is not equal to the texture value.
*
* @type {number}
* @constant
*/
const NotEqualCompare = 517;
/**
* Pass if the incoming value is greater than or equal to the texture value.
*
* @type {number}
* @constant
*/
const GreaterEqualCompare = 518;
/**
* Always pass.
*
* @type {number}
* @constant
*/
const AlwaysCompare = 519;
/**
* The contents are intended to be specified once by the application, and used many
* times as the source for drawing and image specification commands.
*
* @type {number}
* @constant
*/
const StaticDrawUsage = 35044;
/**
* GLSL 3 shader code.
*
* @type {string}
* @constant
*/
const GLSL3 = '300 es';
/**
* WebGL coordinate system.
*
* @type {number}
* @constant
*/
const WebGLCoordinateSystem = 2000;
/**
* WebGPU coordinate system.
*
* @type {number}
* @constant
*/
const WebGPUCoordinateSystem = 2001;
/**
* This type represents mouse buttons and interaction types in context of controls.
*
* @typedef {Object} ConstantsMouse
* @property {number} MIDDLE - The left mouse button.
* @property {number} LEFT - The middle mouse button.
* @property {number} RIGHT - The right mouse button.
* @property {number} ROTATE - A rotate interaction.
* @property {number} DOLLY - A dolly interaction.
* @property {number} PAN - A pan interaction.
**/
/**
* This type represents touch interaction types in context of controls.
*
* @typedef {Object} ConstantsTouch
* @property {number} ROTATE - A rotate interaction.
* @property {number} PAN - A pan interaction.
* @property {number} DOLLY_PAN - The dolly-pan interaction.
* @property {number} DOLLY_ROTATE - A dolly-rotate interaction.
**/
/**
* This type represents the different timestamp query types.
*
* @typedef {Object} ConstantsTimestampQuery
* @property {string} COMPUTE - A `compute` timestamp query.
* @property {string} RENDER - A `render` timestamp query.
**/
/**
* Represents the different interpolation sampling types.
*
* @typedef {Object} ConstantsInterpolationSamplingType
* @property {string} PERSPECTIVE - Perspective-correct interpolation.
* @property {string} LINEAR - Linear interpolation.
* @property {string} FLAT - Flat interpolation.
*/
/**
* Represents the different interpolation sampling modes.
*
* @typedef {Object} ConstantsInterpolationSamplingMode
* @property {string} NORMAL - Normal sampling mode.
* @property {string} CENTROID - Centroid sampling mode.
* @property {string} SAMPLE - Sample-specific sampling mode.
* @property {string} FIRST - Flat interpolation using the first vertex.
* @property {string} EITHER - Flat interpolation using either vertex.
*/
function arrayNeedsUint32( array ) {
// assumes larger values usually on last
for ( let i = array.length - 1; i >= 0; -- i ) {
if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565
}
return false;
}
/**
* Returns `true` if the given object is a typed array.
*
* @param {any} array - The object to check.
* @return {boolean} Whether the given object is a typed array.
*/
function isTypedArray( array ) {
return ArrayBuffer.isView( array ) && ! ( array instanceof DataView );
}
function createElementNS( name ) {
return document.createElementNS( 'http://www.w3.org/1999/xhtml', name );
}
function createCanvasElement() {
const canvas = createElementNS( 'canvas' );
canvas.style.display = 'block';
return canvas;
}
const _cache = {};
function log( ...params ) {
const message = 'THREE.' + params.shift();
{
console.log( message, ...params );
}
}
function warn( ...params ) {
const message = 'THREE.' + params.shift();
{
console.warn( message, ...params );
}
}
function error( ...params ) {
const message = 'THREE.' + params.shift();
{
console.error( message, ...params );
}
}
function warnOnce( ...params ) {
const message = params.join( ' ' );
if ( message in _cache ) return;
_cache[ message ] = true;
warn( ...params );
}
function probeAsync( gl, sync, interval ) {
return new Promise( function ( resolve, reject ) {
function probe() {
switch ( gl.clientWaitSync( sync, gl.SYNC_FLUSH_COMMANDS_BIT, 0 ) ) {
case gl.WAIT_FAILED:
reject();
break;
case gl.TIMEOUT_EXPIRED:
setTimeout( probe, interval );
break;
default:
resolve();
}
}
setTimeout( probe, interval );
} );
}
/**
* This modules allows to dispatch event objects on custom JavaScript objects.
*
* Main repository: [eventdispatcher.js](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](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](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](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](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](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:
warn( '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.
*/
f