UNPKG

@inweb/viewer-three

Version:

JavaScript library for rendering CAD and BIM files in a browser using Three.js

1,548 lines (1,545 loc) 2.39 MB
/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a // license agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.ODA = global.ODA || {}, global.ODA.Three = global.ODA.Three || {}))); })(this, (function (exports) { 'use strict'; class CommandsRegistry { constructor() { this._commands = new Map(); } registerCommand(id, handler, description, thisArg) { this._commands.set(id, { id, handler, thisArg, description }); } registerCommandAlias(id, alias) { this.registerCommand(alias, (viewer, ...args) => this.executeCommand(id, viewer, ...args)); } getCommand(id) { return this._commands.get(id); } getCommands() { const map = new Map(); this._commands.forEach((value, key) => map.set(key, value)); return map; } executeCommand(id, viewer, ...args) { const command = this._commands.get(id); if (!command) { if (viewer) { const isDraggerCommand = viewer.draggers.includes(id); if (isDraggerCommand) return viewer.setActiveDragger(id); } console.warn(`Command '${id}' not found`); return undefined; } const { handler, thisArg } = command; const result = handler.apply(thisArg, [viewer, ...args]); viewer === null || viewer === void 0 ? void 0 : viewer.emit({ type: "command", data: id, args }); return result; } } const _commandsRegistry = new Map(); function commandsRegistry(viewerType = "") { let result = _commandsRegistry.get(viewerType); if (!result) { result = new CommandsRegistry(); _commandsRegistry.set(viewerType, result); } return result; } class Dragger { constructor(viewer) { this.name = ""; } dispose() { } } class DraggersRegistry { constructor() { this._providers = new Map(); } registerDragger(name, provider) { this._providers.set(name, provider); } registerDraggerAlias(name, alias) { const provider = this._providers.get(name); if (provider) this.registerDragger(alias, (viewer) => provider(viewer)); } getDraggers() { const map = new Map(); this._providers.forEach((value, key) => map.set(key, value)); return map; } createDragger(name, viewer) { const provider = this._providers.get(name); if (!provider) return null; const dragger = provider(viewer); dragger.name = name; return dragger; } } const _draggersRegistry = new Map(); function draggersRegistry(viewerType = "") { let result = _draggersRegistry.get(viewerType); if (!result) { result = new DraggersRegistry(); _draggersRegistry.set(viewerType, result); } return result; } class Component { constructor(viewer) { this.name = ""; } dispose() { } } class Components { constructor() { this._providers = new Map(); } registerComponent(name, provider) { this._providers.set(name, provider); } registerComponentAlias(name, alias) { const provider = this._providers.get(name); if (provider) this.registerComponent(alias, (viewer) => provider(viewer)); } getComponents() { const map = new Map(); this._providers.forEach((value, key) => map.set(key, value)); return map; } createComponent(name, viewer) { const provider = this._providers.get(name); if (!provider) return null; const component = provider(viewer); component.name = name; return component; } } const _components = new Map(); function componentsRegistry(viewerType = "") { let result = _components.get(viewerType); if (!result) { result = new Components(); _components.set(viewerType, result); } return result; } let Loader$1 = class Loader { constructor() { this.name = ""; this.abortController = new AbortController(); } dispose() { this.abortController.abort(); this.abortController = undefined; } isSupport(file, format) { return false; } load(file, format, params) { return Promise.resolve(this); } cancel() { this.abortController.abort(); } extractFileName(file) { const regex = /[^/\\?#:]+(?=\?|#|$)/; if (typeof file === "string") return (file.match(regex) || [])[0]; else if (file instanceof globalThis.File) return (file.name.match(regex) || [])[0]; return undefined; } }; class Loaders { constructor() { this._providers = new Map(); } registerLoader(name, provider) { this._providers.set(name, provider); } getLoader(name) { return this._providers.get(name); } getLoaders() { const map = new Map(); this._providers.forEach((value, key) => map.set(key, value)); return map; } createLoader(viewer, file, format) { let result = null; this._providers.forEach((provider, key) => { const loader = provider(viewer); if (loader.isSupport(file, format)) { result = loader; result.name = key; } }); return result; } } const _loaders = new Map(); function loadersRegistry(viewerType = "") { let result = _loaders.get(viewerType); if (!result) { result = new Loaders(); _loaders.set(viewerType, result); } return result; } function defaultOptions() { return { showWCS: true, cameraAnimation: true, antialiasing: true, groundShadow: false, shadows: false, cameraAxisXSpeed: 4, cameraAxisYSpeed: 1, ambientOcclusion: false, enableStreamingMode: true, enablePartialMode: false, memoryLimit: 3294967296, cuttingPlaneFillColor: { red: 0xff, green: 0x98, blue: 0x00 }, edgesColor: { r: 0xff, g: 0x98, b: 0x00 }, facesColor: { r: 0xff, g: 0x98, b: 0x00 }, edgesVisibility: true, edgesOverlap: true, facesOverlap: false, facesTransparancy: 200, enableCustomHighlight: true, sceneGraph: false, edgeModel: true, reverseZoomWheel: false, enableZoomWheel: true, enableGestures: true, geometryType: "vsfx", rulerUnit: "Default", rulerPrecision: 2, cameraMode: "perspective", }; } class Options { constructor(emitter) { this._emitter = emitter; this._data = defaultOptions(); this.loadFromStorage(); } static defaults() { return defaultOptions(); } notifierChangeEvent() { console.warn("Options.notifierChangeEvent() has been deprecated since 25.3 and will be removed in a future release, use Options.change() instead."); this.change(); } change() { if (this._emitter !== undefined) { this.saveToStorage(); this._emitter.emit({ type: "optionschange", data: this }); } } saveToStorage() { if (typeof window !== "undefined") try { localStorage.setItem("od-client-settings", JSON.stringify(this.data)); } catch (error) { console.error("Cannot save client settings.", error); } } loadFromStorage() { if (typeof window !== "undefined") try { const item = localStorage.getItem("od-client-settings"); if (item) { const data = JSON.parse(item); this.data = { ...data }; } } catch (error) { console.error("Cannot load client settings.", error); } } resetToDefaults(fields) { if (fields !== undefined) { const defaults = Options.defaults(); const resetData = fields.reduce((acc, field) => { acc[field] = defaults[field]; return acc; }, {}); this.data = { ...this.data, ...resetData }; } else { this.data = { ...this.data, ...Options.defaults() }; } } get data() { return this._data; } set data(value) { const enablePartialMode = value.enableStreamingMode ? value.enablePartialMode : false; const sceneGraph = enablePartialMode ? false : value.sceneGraph; this._data = { ...Options.defaults(), ...this._data, ...value, enablePartialMode, sceneGraph }; this.change(); } get showWCS() { return this._data.showWCS; } set showWCS(value) { this._data.showWCS = value; this.change(); } get cameraAnimation() { return this._data.cameraAnimation; } set cameraAnimation(value) { this._data.cameraAnimation = value; this.change(); } get antialiasing() { return this._data.antialiasing; } set antialiasing(value) { this._data.antialiasing = value; this.change(); } get groundShadow() { return this._data.groundShadow; } set groundShadow(value) { this._data.groundShadow = value; this.change(); } get shadows() { return this._data.shadows; } set shadows(value) { this._data.shadows = value; this.change(); } get cameraAxisXSpeed() { return this._data.cameraAxisXSpeed; } set cameraAxisXSpeed(value) { this._data.cameraAxisXSpeed = value; this.change(); } get cameraAxisYSpeed() { return this._data.cameraAxisYSpeed; } set cameraAxisYSpeed(value) { this.cameraAxisYSpeed = value; this.change(); } get ambientOcclusion() { return this._data.ambientOcclusion; } set ambientOcclusion(value) { this._data.ambientOcclusion = value; this.change(); } get enableStreamingMode() { return this._data.enableStreamingMode; } set enableStreamingMode(value) { this._data.enableStreamingMode = value; if (!value) this._data.enablePartialMode = false; this.change(); } get enablePartialMode() { return this._data.enablePartialMode; } set enablePartialMode(value) { this._data.enablePartialMode = value; if (value) { this._data.enableStreamingMode = true; this._data.sceneGraph = false; } this.change(); } get memoryLimit() { return this._data.memoryLimit; } set memoryLimit(value) { this._data.memoryLimit = value; this.change(); } get cuttingPlaneFillColor() { return this._data.cuttingPlaneFillColor; } set cuttingPlaneFillColor(value) { this._data.cuttingPlaneFillColor = value; this.change(); } get edgesColor() { return this._data.edgesColor; } set edgesColor(value) { this._data.edgesColor = value; this.change(); } get facesColor() { return this._data.facesColor; } set facesColor(value) { this._data.facesColor = value; this.change(); } get edgesVisibility() { return this._data.edgesVisibility; } set edgesVisibility(value) { this._data.edgesVisibility = value; this.change(); } get edgesOverlap() { return this._data.edgesOverlap; } set edgesOverlap(value) { this._data.edgesOverlap = value; this.change(); } get facesOverlap() { return this._data.facesOverlap; } set facesOverlap(value) { this._data.facesOverlap = value; this.change(); } get facesTransparancy() { return this._data.facesTransparancy; } set facesTransparancy(value) { this._data.facesTransparancy = value; this.change(); } get enableCustomHighlight() { return this._data.enableCustomHighlight; } set enableCustomHighlight(value) { this._data.enableCustomHighlight = value; this.change(); } get sceneGraph() { return this._data.sceneGraph; } set sceneGraph(value) { this._data.sceneGraph = value; if (value) this._data.enablePartialMode = false; this.change(); } get edgeModel() { return Boolean(this._data.edgeModel); } set edgeModel(value) { this._data.edgeModel = Boolean(value); this.change(); } get reverseZoomWheel() { return this._data.reverseZoomWheel; } set reverseZoomWheel(value) { this._data.reverseZoomWheel = !!value; this.change(); } get enableZoomWheel() { return this._data.enableZoomWheel; } set enableZoomWheel(value) { this._data.enableZoomWheel = !!value; this.change(); } get enableGestures() { return this._data.enableGestures; } set enableGestures(value) { this._data.enableGestures = !!value; this.change(); } get geometryType() { return this._data.geometryType; } set geometryType(value) { this._data.geometryType = value; this.change(); } get rulerUnit() { return this._data.rulerUnit; } set rulerUnit(value) { this._data.rulerUnit = value; this.change(); } get rulerPrecision() { return this._data.rulerPrecision; } set rulerPrecision(value) { this._data.rulerPrecision = value; this.change(); } get cameraMode() { return this._data.cameraMode || "perspective"; } set cameraMode(value) { this._data.cameraMode = value; this.change(); } } const CanvasEvents = [ "click", "contextmenu", "dblclick", "mousedown", "mouseleave", "mousemove", "mouseup", "pointercancel", "pointerdown", "pointerleave", "pointermove", "pointerup", "touchcancel", "touchend", "touchmove", "touchstart", "wheel", ]; const CANVAS_EVENTS = CanvasEvents; class Info { constructor() { this.performance = { fps: 0, frameTime: 0, timeToFirstRender: 0, loadTime: 0, }; this.render = { viewport: { width: 0, height: 0 }, antialiasing: "", drawCalls: 0, triangles: 0, points: 0, lines: 0, }; this.scene = { objects: 0, triangles: 0, points: 0, lines: 0, edges: 0, }; this.optimizedScene = { objects: 0, triangles: 0, points: 0, lines: 0, edges: 0, }; this.memory = { geometries: 0, geometryBytes: 0, textures: 0, textureBytes: 0, materials: 0, totalEstimatedGpuBytes: 0, usedJSHeapSize: 0, }; this.system = { webglRenderer: "", webglVendor: "", }; } } /** * @license * Copyright 2010-2025 Three.js Authors * SPDX-License-Identifier: MIT */ const REVISION = '180'; const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }; const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; const CullFaceNone = 0; const CullFaceBack = 1; const CullFaceFront = 2; const CullFaceFrontBack = 3; const BasicShadowMap = 0; 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 NearestMipMapNearestFilter = 1004; const NearestMipmapLinearFilter = 1005; const NearestMipMapLinearFilter = 1005; const LinearFilter = 1006; const LinearMipmapNearestFilter = 1007; 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 UnsignedInt101111Type = 35899; const AlphaFormat = 1021; const RGBFormat = 1022; const RGBAFormat = 1023; const DepthFormat = 1026; const DepthStencilFormat = 1027; const RedFormat = 1028; const RedIntegerFormat = 1029; const RGFormat = 1030; const RGIntegerFormat = 1031; const RGBIntegerFormat = 1032; 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 RGBDepthPacking = 3202; const RGDepthPacking = 3203; const TangentSpaceNormalMap = 0; const ObjectSpaceNormalMap = 1; const NoColorSpace = ''; const SRGBColorSpace = 'srgb'; const LinearSRGBColorSpace = 'srgb-linear'; const LinearTransfer = 'linear'; const SRGBTransfer = 'srgb'; const ZeroStencilOp = 0; const KeepStencilOp = 7680; const ReplaceStencilOp = 7681; const IncrementStencilOp = 7682; const DecrementStencilOp = 7683; const IncrementWrapStencilOp = 34055; const DecrementWrapStencilOp = 34056; const InvertStencilOp = 5386; const NeverStencilFunc = 512; const LessStencilFunc = 513; const EqualStencilFunc = 514; const LessEqualStencilFunc = 515; const GreaterStencilFunc = 516; const NotEqualStencilFunc = 517; const GreaterEqualStencilFunc = 518; 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 DynamicDrawUsage = 35048; const StreamDrawUsage = 35040; const StaticReadUsage = 35045; const DynamicReadUsage = 35049; const StreamReadUsage = 35041; const StaticCopyUsage = 35046; const DynamicCopyUsage = 35050; const StreamCopyUsage = 35042; const GLSL1 = '100'; const GLSL3 = '300 es'; const WebGLCoordinateSystem = 2000; const WebGPUCoordinateSystem = 2001; const TimestampQuery = { COMPUTE: 'compute', RENDER: 'render' }; const InterpolationSamplingType = { PERSPECTIVE: 'perspective', LINEAR: 'linear', FLAT: 'flat' }; const InterpolationSamplingMode = { NORMAL: 'normal', CENTROID: 'centroid', SAMPLE: 'sample', FIRST: 'first', EITHER: 'either' }; class EventDispatcher { 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 ); } } hasEventListener( type, listener ) { const listeners = this._listeners; if ( listeners === undefined ) return false; return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== -1; } 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 ); } } } dispatchEvent( event ) { const listeners = this._listeners; if ( listeners === undefined ) return; const listenerArray = listeners[ event.type ]; if ( listenerArray !== undefined ) { event.target = this; 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; function generateUUID() { 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 ]; return uuid.toLowerCase(); } function clamp( value, min, max ) { return Math.max( min, Math.min( max, value ) ); } function euclideanModulo( n, m ) { return ( ( n % m ) + m ) % m; } function mapLinear( x, a1, a2, b1, b2 ) { return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); } function inverseLerp( x, y, value ) { if ( x !== y ) { return ( value - x ) / ( y - x ); } else { return 0; } } function lerp( x, y, t ) { return ( 1 - t ) * x + t * y; } function damp( x, y, lambda, dt ) { return lerp( x, y, 1 - Math.exp( - lambda * dt ) ); } function pingpong( x, length = 1 ) { return length - Math.abs( euclideanModulo( x, length * 2 ) - length ); } 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 ); } 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 ); } function randInt( low, high ) { return low + Math.floor( Math.random() * ( high - low + 1 ) ); } function randFloat( low, high ) { return low + Math.random() * ( high - low ); } function randFloatSpread( range ) { return range * ( 0.5 - Math.random() ); } function seededRandom( s ) { if ( s !== undefined ) _seed = s; 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; } function degToRad( degrees ) { return degrees * DEG2RAD; } function radToDeg( radians ) { return radians * RAD2DEG; } function isPowerOfTwo( value ) { return ( value & ( value - 1 ) ) === 0 && value !== 0; } function ceilPowerOfTwo( value ) { return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) ); } function floorPowerOfTwo( value ) { return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) ); } 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 ); } } 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.' ); } } 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, euclideanModulo: euclideanModulo, mapLinear: mapLinear, inverseLerp: inverseLerp, lerp: lerp, 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 Vector2 { constructor( x = 0, y = 0 ) { Vector2.prototype.isVector2 = true; this.x = x; this.y = y; } get width() { return this.x; } set width( value ) { this.x = value; } get height() { return this.y; } set height( value ) { this.y = value; } set( x, y ) { this.x = x; this.y = y; return this; } setScalar( scalar ) { this.x = scalar; this.y = scalar; return this; } setX( x ) { this.x = x; return this; } setY( y ) { this.y = y; return this; } 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; } getComponent( index ) { switch ( index ) { case 0: return this.x; case 1: return this.y; default: throw new Error( 'index is out of range: ' + index ); } } clone() { return new this.constructor( this.x, this.y ); } copy( v ) { this.x = v.x; this.y = v.y; return this; } add( v ) { this.x += v.x; this.y += v.y; return this; } addScalar( s ) { this.x += s; this.y += s; return this; } addVectors( a, b ) { this.x = a.x + b.x; this.y = a.y + b.y; return this; } addScaledVector( v, s ) { this.x += v.x * s; this.y += v.y * s; return this; } sub( v ) { this.x -= v.x; this.y -= v.y; return this; } subScalar( s ) { this.x -= s; this.y -= s; return this; } subVectors( a, b ) { this.x = a.x - b.x; this.y = a.y - b.y; return this; } multiply( v ) { this.x *= v.x; this.y *= v.y; return this; } multiplyScalar( scalar ) { this.x *= scalar; this.y *= scalar; return this; } divide( v ) { this.x /= v.x; this.y /= v.y; return this; } divideScalar( scalar ) { return this.multiplyScalar( 1 / scalar ); } 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; } min( v ) { this.x = Math.min( this.x, v.x ); this.y = Math.min( this.y, v.y ); return this; } max( v ) { this.x = Math.max( this.x, v.x ); this.y = Math.max( this.y, v.y ); return this; } clamp( min, max ) { this.x = clamp( this.x, min.x, max.x ); this.y = clamp( this.y, min.y, max.y ); return this; } clampScalar( minVal, maxVal ) { this.x = clamp( this.x, minVal, maxVal ); this.y = clamp( this.y, minVal, maxVal ); return this; } clampLength( min, max ) { const length = this.length(); return this.divideScalar( length || 1 ).multiplyScalar( clamp( length, min, max ) ); } floor() { this.x = Math.floor( this.x ); this.y = Math.floor( this.y ); return this; } ceil() { this.x = Math.ceil( this.x ); this.y = Math.ceil( this.y ); return this; } round() { this.x = Math.round( this.x ); this.y = Math.round( this.y ); return this; } roundToZero() { this.x = Math.trunc( this.x ); this.y = Math.trunc( this.y ); return this; } negate() { this.x = - this.x; this.y = - this.y; return this; } dot( v ) { return this.x * v.x + this.y * v.y; } cross( v ) { return this.x * v.y - this.y * v.x; } lengthSq() { return this.x * this.x + this.y * this.y; } length() { return Math.sqrt( this.x * this.x + this.y * this.y ); } manhattanLength() { return Math.abs( this.x ) + Math.abs( this.y ); } normalize() { return this.divideScalar( this.length() || 1 ); } angle() { const angle = Math.atan2( - this.y, - this.x ) + Math.PI; return angle; } angleTo( v ) { const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); if ( denominator === 0 ) return Math.PI / 2; const theta = this.dot( v ) / denominator; return Math.acos( clamp( theta, -1, 1 ) ); } distanceTo( v ) { return Math.sqrt( this.distanceToSquared( v ) ); } distanceToSquared( v ) { const dx = this.x - v.x, dy = this.y - v.y; return dx * dx + dy * dy; } manhattanDistanceTo( v ) { return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ); } setLength( length ) { return this.normalize().multiplyScalar( length ); } lerp( v, alpha ) { this.x += ( v.x - this.x ) * alpha; this.y += ( v.y - this.y ) * alpha; return this; } lerpVectors( v1, v2, alpha ) { this.x = v1.x + ( v2.x - v1.x ) * alpha; this.y = v1.y + ( v2.y - v1.y ) * alpha; return this; } equals( v ) { return ( ( v.x === this.x ) && ( v.y === this.y ) ); } fromArray( array, offset = 0 ) { this.x = array[ offset ]; this.y = array[ offset + 1 ]; return this; } toArray( array = [], offset = 0 ) { array[ offset ] = this.x; array[ offset + 1 ] = this.y; return array; } fromBufferAttribute( attribute, index ) { this.x = attribute.getX( index ); this.y = attribute.getY( index ); return this; } 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; } random() { this.x = Math.random(); this.y = Math.random(); return this; } *[ Symbol.iterator ]() { yield this.x; yield this.y; } } class Quaternion { constructor( x = 0, y = 0, z = 0, w = 1 ) { this.isQuaternion = true; this._x = x; this._y = y; this._z = z; this._w = w; } static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { let x0 = src0[ srcOffset0 + 0 ], y0 = src0[ srcOffset0 + 1 ], z0 = src0[ srcOffset0 + 2 ], w0 = src0[ srcOffset0 + 3 ]; const x1 = src1[ srcOffset1 + 0 ], y1 = src1[ srcOffset1 + 1 ], z1 = src1[ srcOffset1 + 2 ], w1 = src1[ srcOffset1 + 3 ]; if ( t === 0 ) { dst[ dstOffset + 0 ] = x0; dst[ dstOffset + 1 ] = y0; dst[ dstOffset + 2 ] = z0; dst[ dstOffset + 3 ] = w0; return; } if ( t === 1 ) { dst[ dstOffset + 0 ] = x1; dst[ dstOffset + 1 ] = y1; dst[ dstOffset + 2 ] = z1; dst[ dstOffset + 3 ] = w1; return; } if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { let s = 1 - t; const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, dir = ( cos >= 0 ? 1 : -1 ), sqrSin = 1 - cos * cos; if ( sqrSin > Number.EPSILON ) { const sin = Math.sqrt( sqrSin ), len = Math.atan2( sin, cos * dir ); s = Math.sin( s * len ) / sin; t = Math.sin( t * len ) / sin; } const tDir = t * dir; x0 = x0 * s + x1 * tDir; y0 = y0 * s + y1 * tDir; z0 = z0 * s + z1 * tDir; w0 = w0 * s + w1 * tDir; if ( s === 1 - t ) { const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); x0 *= f; y0 *= f; z0 *= f; w0 *= f; } } dst[ dstOffset ] = x0; dst[ dstOffset + 1 ] = y0; dst[ dstOffset + 2 ] = z0; dst[ dstOffset + 3 ] = w0; } static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) { const x0 = src0[ srcOffset0 ]; const y0 = src0[ srcOffset0 + 1 ]; const z0 = src0[ srcOffset0 + 2 ]; const w0 = src0[ srcOffset0 + 3 ]; const x1 = src1[ srcOffset1 ]; const y1 = src1[ srcOffset1 + 1 ]; const z1 = src1[ srcOffset1 + 2 ]; const w1 = src1[ srcOffset1 + 3 ]; dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1; dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1; dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1; dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1; return dst; } get x() { return this._x; } set x( value ) { this._x = value; this._onChangeCallback(); } get y() { return this._y; } set y( value ) { this._y = value; this._onChangeCallback(); } get z() { return this._z; } set z( value ) { this._z = value; this._onChangeCallback(); } get w() { return this._w; } set w( value ) { this._w = value; this._onChangeCallback(); } set( x, y, z, w ) { this._x = x; this._y = y; this._z = z; this._w = w; this._onChangeCallback(); return this; } clone() { return new this.constructor( this._x, this._y, this._z, this._w ); } copy( quaternion ) { this._x = quaternion.x; this._y = quaternion.y; this._z = quaternion.z; this._w = quaternion.w; this._onChangeCallback(); return this; } setFromEuler( euler, update = true ) { const x = euler._x, y = euler._y, z = euler._z, order = euler._order; const cos = Math.cos; const sin = Math.sin; const c1 = cos( x / 2 ); const c2 = cos( y / 2 ); const c3 = cos( z / 2 ); const s1 = sin( x / 2 ); const s2 = sin( y / 2 ); const s3 = sin( z / 2 ); switch ( order ) { case 'XYZ': this._x = s1 * c2 * c3 + c1 * s2 * s3; this._y = c1 * s2 * c3 - s1 * c2 * s3; this._z = c1 * c2 * s3 + s1 * s2 * c3; this._w = c1 * c2 * c3 - s1 * s2 * s3; break; case 'YXZ': this._x = s1 * c2 * c3 + c1 * s2 * s3; this._y = c1 * s2 * c3 - s1 * c2 * s3; this._z = c1 * c2 * s3 - s1 * s2 * c3; this._w = c1 * c2 * c3 + s1 * s2 * s3; break; case 'ZXY': this._x = s1 * c2 * c3 - c1 * s2 * s3; this._y = c1 * s2 * c3 + s1 * c2 * s3; this._z = c1 * c2 * s3 + s1 * s2 * c3; this._w = c1 * c2 * c3 - s1 * s2 * s3; break; case 'ZYX': this._x = s1 * c2 * c3 - c1 * s2 * s3; this._y = c1 * s2 * c3 + s1 * c2 * s3; this._z = c1 * c2 * s3 - s1 * s2 * c3; this._w = c1 * c2 * c3 + s1 * s2 * s3; break; case 'YZX': this._x = s1 * c2 * c3 + c1 * s2 * s3; this._y = c1 * s2 * c3 + s1 * c2 * s3; this._z = c1 * c2 * s3 - s1 * s2 * c3; this._w = c1 * c2 * c3 - s1 * s2 * s3; break; case 'XZY': this._x = s1 * c2 * c3 - c1 * s2 * s3; this._y = c1 * s2 * c3 - s1 * c2 * s3; this._z = c1 * c2 * s3 + s1 * s2 * c3; this._w = c1 * c2 * c3 + s1 * s2 * s3; break; default: console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order ); } if ( update === true ) this._onChangeCallback(); return this; } setFromAxisAngle( axis, angle ) { const halfAngle = angle / 2, s = Math.sin( halfAngle ); this._x = axis.x * s; this._y = axis.y * s; this._z = axis.z * s; this._w = Math.cos( halfAngle ); this._onChangeCallback(); return this; } setFromRotationMatrix( m ) { const te = m.elements, m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ], trace = m11 + m22 + m33; if ( trace > 0 ) { const s = 0.5 / Math.sqrt( trace + 1.0 ); this._w = 0.25 / s; this._x = ( m32 - m23 ) * s; this._y = ( m13 - m31 ) * s; this._z = ( m21 - m12 ) * s; } else if ( m11 > m22 && m11 > m33 ) { const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 ); this._w = ( m32 - m23 ) / s; this._x = 0.25 * s; this._y = ( m12 + m21 ) / s; this._z = ( m13 + m31 ) / s; } else if ( m22 > m33 ) { const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); this._w = ( m13 - m31 ) / s; this._x = ( m12 + m21 ) / s; this._y = 0.25 * s; this._z = ( m23 + m32 ) / s; } else { const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); this._w = ( m21 - m12 ) / s; this._x = ( m13 + m31 ) / s; this._y = ( m23 + m32 ) / s; this._z = 0.25 * s; } this._onChangeCallback(); return this; } setFromUnitVectors( vFrom, vTo ) { let r = vFrom.dot( vTo ) + 1; if ( r < 1e-8 ) { r = 0; if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { this._x = - vFrom.y; this._y = vFrom.x; this._z = 0; this._w = r; } else { this._x = 0; this._y = - vFrom.z; this._z = vFrom.y; this._w = r; } } else { this._x = vFrom.y * vTo.z - vFrom.z * vTo.y; this._y = vFrom.z * vTo.x - vFrom.x * vTo.z; this._z = vFrom.x * vTo.y - vFrom.y * vTo.x; this._w = r; } return this.normalize(); } angleTo( q ) { return 2 * Math.acos( Math.abs( clamp( this.dot( q ), -1, 1 ) ) ); } rotateTowards( q, step ) { const angle = this.angleTo( q ); if ( angle === 0 ) return this; const t = Math.min( 1, step / angle ); this.slerp( q, t ); return this; } identity() { return this.set( 0, 0, 0, 1 ); } invert() { return this.conjugate(); } conjugate() { this._x *= -1; this._y *= -1; this._z *= -1; this._onChangeCallback(); return this; } dot( v ) { return t