endset_three_editor 0.2.5 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"three-editor.cjs.js","sources":["../node_modules/three/examples/jsm/controls/OrbitControls.js","../node_modules/three/examples/jsm/controls/TransformControls.js","../src/three/index.ts","../node_modules/three/examples/jsm/loaders/OBJLoader.js","../node_modules/three/examples/jsm/utils/BufferGeometryUtils.js","../node_modules/three/examples/jsm/utils/SkeletonUtils.js","../node_modules/three/examples/jsm/loaders/GLTFLoader.js","../src/three/addHandle.ts","../src/components/TreeItem.vue","../src/composables/useTreeExpand.ts","../src/components/PropertyPanel.vue","../src/components/TopBar.vue","../src/components/BottomBar.vue","../src/components/DrawingBoard.vue"],"sourcesContent":["import {\n\tControls,\n\tMOUSE,\n\tQuaternion,\n\tSpherical,\n\tTOUCH,\n\tVector2,\n\tVector3,\n\tPlane,\n\tRay,\n\tMathUtils\n} from 'three';\n\n/**\n * Fires when the camera has been transformed by the controls.\n *\n * @event OrbitControls#change\n * @type {Object}\n */\nconst _changeEvent = { type: 'change' };\n\n/**\n * Fires when an interaction was initiated.\n *\n * @event OrbitControls#start\n * @type {Object}\n */\nconst _startEvent = { type: 'start' };\n\n/**\n * Fires when an interaction has finished.\n *\n * @event OrbitControls#end\n * @type {Object}\n */\nconst _endEvent = { type: 'end' };\n\nconst _ray = new Ray();\nconst _plane = new Plane();\nconst _TILT_LIMIT = Math.cos( 70 * MathUtils.DEG2RAD );\n\nconst _v = new Vector3();\nconst _twoPI = 2 * Math.PI;\n\nconst _STATE = {\n\tNONE: - 1,\n\tROTATE: 0,\n\tDOLLY: 1,\n\tPAN: 2,\n\tTOUCH_ROTATE: 3,\n\tTOUCH_PAN: 4,\n\tTOUCH_DOLLY_PAN: 5,\n\tTOUCH_DOLLY_ROTATE: 6\n};\nconst _EPS = 0.000001;\n\n\n/**\n * Orbit controls allow the camera to orbit around a target.\n *\n * OrbitControls performs orbiting, dollying (zooming), and panning. Unlike {@link TrackballControls},\n * it maintains the \"up\" direction `object.up` (+Y by default).\n *\n * - Orbit: Left mouse / touch: one-finger move.\n * - Zoom: Middle mouse, or mousewheel / touch: two-finger spread or squish.\n * - Pan: Right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move.\n *\n * ```js\n * const controls = new OrbitControls( camera, renderer.domElement );\n *\n * // controls.update() must be called after any manual changes to the camera's transform\n * camera.position.set( 0, 20, 100 );\n * controls.update();\n *\n * function animate() {\n *\n * \t// required if controls.enableDamping or controls.autoRotate are set to true\n * \tcontrols.update();\n *\n * \trenderer.render( scene, camera );\n *\n * }\n * ```\n *\n * @augments Controls\n * @three_import import { OrbitControls } from 'three/addons/controls/OrbitControls.js';\n */\nclass OrbitControls extends Controls {\n\n\t/**\n\t * Constructs a new controls instance.\n\t *\n\t * @param {Object3D} object - The object that is managed by the controls.\n\t * @param {?HTMLElement} domElement - The HTML element used for event listeners.\n\t */\n\tconstructor( object, domElement = null ) {\n\n\t\tsuper( object, domElement );\n\n\t\tthis.state = _STATE.NONE;\n\n\t\t/**\n\t\t * The focus point of the controls, the `object` orbits around this.\n\t\t * It can be updated manually at any point to change the focus of the controls.\n\t\t *\n\t\t * @type {Vector3}\n\t\t */\n\t\tthis.target = new Vector3();\n\n\t\t/**\n\t\t * The focus point of the `minTargetRadius` and `maxTargetRadius` limits.\n\t\t * It can be updated manually at any point to change the center of interest\n\t\t * for the `target`.\n\t\t *\n\t\t * @type {Vector3}\n\t\t */\n\t\tthis.cursor = new Vector3();\n\n\t\t/**\n\t\t * How far you can dolly in (perspective camera only).\n\t\t *\n\t\t * @type {number}\n\t\t * @default 0\n\t\t */\n\t\tthis.minDistance = 0;\n\n\t\t/**\n\t\t * How far you can dolly out (perspective camera only).\n\t\t *\n\t\t * @type {number}\n\t\t * @default Infinity\n\t\t */\n\t\tthis.maxDistance = Infinity;\n\n\t\t/**\n\t\t * How far you can zoom in (orthographic camera only).\n\t\t *\n\t\t * @type {number}\n\t\t * @default 0\n\t\t */\n\t\tthis.minZoom = 0;\n\n\t\t/**\n\t\t * How far you can zoom out (orthographic camera only).\n\t\t *\n\t\t * @type {number}\n\t\t * @default Infinity\n\t\t */\n\t\tthis.maxZoom = Infinity;\n\n\t\t/**\n\t\t * How close you can get the target to the 3D `cursor`.\n\t\t *\n\t\t * @type {number}\n\t\t * @default 0\n\t\t */\n\t\tthis.minTargetRadius = 0;\n\n\t\t/**\n\t\t * How far you can move the target from the 3D `cursor`.\n\t\t *\n\t\t * @type {number}\n\t\t * @default Infinity\n\t\t */\n\t\tthis.maxTargetRadius = Infinity;\n\n\t\t/**\n\t\t * How far you can orbit vertically, lower limit. Range is `[0, Math.PI]` radians.\n\t\t *\n\t\t * @type {number}\n\t\t * @default 0\n\t\t */\n\t\tthis.minPolarAngle = 0;\n\n\t\t/**\n\t\t * How far you can orbit vertically, upper limit. Range is `[0, Math.PI]` radians.\n\t\t *\n\t\t * @type {number}\n\t\t * @default Math.PI\n\t\t */\n\t\tthis.maxPolarAngle = Math.PI;\n\n\t\t/**\n\t\t * How far you can orbit horizontally, lower limit. If set, the interval `[ min, max ]`\n\t\t * must be a sub-interval of `[ - 2 PI, 2 PI ]`, with `( max - min < 2 PI )`.\n\t\t *\n\t\t * @type {number}\n\t\t * @default -Infinity\n\t\t */\n\t\tthis.minAzimuthAngle = - Infinity;\n\n\t\t/**\n\t\t * How far you can orbit horizontally, upper limit. If set, the interval `[ min, max ]`\n\t\t * must be a sub-interval of `[ - 2 PI, 2 PI ]`, with `( max - min < 2 PI )`.\n\t\t *\n\t\t * @type {number}\n\t\t * @default -Infinity\n\t\t */\n\t\tthis.maxAzimuthAngle = Infinity;\n\n\t\t/**\n\t\t * Set to `true` to enable damping (inertia), which can be used to give a sense of weight\n\t\t * to the controls. Note that if this is enabled, you must call `update()` in your animation\n\t\t * loop.\n\t\t *\n\t\t * @type {boolean}\n\t\t * @default false\n\t\t */\n\t\tthis.enableDamping = false;\n\n\t\t/**\n\t\t * The damping inertia used if `enableDamping` is set to `true`.\n\t\t *\n\t\t * Note that for this to work, you must call `update()` in your animation loop.\n\t\t *\n\t\t * @type {number}\n\t\t * @default 0.05\n\t\t */\n\t\tthis.dampingFactor = 0.05;\n\n\t\t/**\n\t\t * Enable or disable zooming (dollying) of the camera.\n\t\t *\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t */\n\t\tthis.enableZoom = true;\n\n\t\t/**\n\t\t * Speed of zooming / dollying.\n\t\t *\n\t\t * @type {number}\n\t\t * @default 1\n\t\t */\n\t\tthis.zoomSpeed = 1.0;\n\n\t\t/**\n\t\t * Enable or disable horizontal and vertical rotation of the camera.\n\t\t *\n\t\t * Note that it is possible to disable a single axis by setting the min and max of the\n\t\t * `minPolarAngle` or `minAzimuthAngle` to the same value, which will cause the vertical\n\t\t * or horizontal rotation to be fixed at that value.\n\t\t *\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t */\n\t\tthis.enableRotate = true;\n\n\t\t/**\n\t\t * Speed of rotation.\n\t\t *\n\t\t * @type {number}\n\t\t * @default 1\n\t\t */\n\t\tthis.rotateSpeed = 1.0;\n\n\t\t/**\n\t\t * How fast to rotate the camera when the keyboard is used.\n\t\t *\n\t\t * @type {number}\n\t\t * @default 1\n\t\t */\n\t\tthis.keyRotateSpeed = 1.0;\n\n\t\t/**\n\t\t * Enable or disable camera panning.\n\t\t *\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t */\n\t\tthis.enablePan = true;\n\n\t\t/**\n\t\t * Speed of panning.\n\t\t *\n\t\t * @type {number}\n\t\t * @default 1\n\t\t */\n\t\tthis.panSpeed = 1.0;\n\n\t\t/**\n\t\t * Defines how the camera's position is translated when panning. If `true`, the camera pans\n\t\t * in screen space. Otherwise, the camera pans in the plane orthogonal to the camera's up\n\t\t * direction.\n\t\t *\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t */\n\t\tthis.screenSpacePanning = true;\n\n\t\t/**\n\t\t * How fast to pan the camera when the keyboard is used in\n\t\t * pixels per keypress.\n\t\t *\n\t\t * @type {number}\n\t\t * @default 7\n\t\t */\n\t\tthis.keyPanSpeed = 7.0;\n\n\t\t/**\n\t\t * Setting this property to `true` allows to zoom to the cursor's position.\n\t\t *\n\t\t * @type {boolean}\n\t\t * @default false\n\t\t */\n\t\tthis.zoomToCursor = false;\n\n\t\t/**\n\t\t * Set to true to automatically rotate around the target\n\t\t *\n\t\t * Note that if this is enabled, you must call `update()` in your animation loop.\n\t\t * If you want the auto-rotate speed to be independent of the frame rate (the refresh\n\t\t * rate of the display), you must pass the time `deltaTime`, in seconds, to `update()`.\n\t\t *\n\t\t * @type {boolean}\n\t\t * @default false\n\t\t */\n\t\tthis.autoRotate = false;\n\n\t\t/**\n\t\t * How fast to rotate around the target if `autoRotate` is `true`. The default equates to 30 seconds\n\t\t * per orbit at 60fps.\n\t\t *\n\t\t * Note that if `autoRotate` is enabled, you must call `update()` in your animation loop.\n\t\t *\n\t\t * @type {number}\n\t\t * @default 2\n\t\t */\n\t\tthis.autoRotateSpeed = 2.0;\n\n\t\t/**\n\t\t * This object contains references to the keycodes for controlling camera panning.\n\t\t *\n\t\t * ```js\n\t\t * controls.keys = {\n\t\t * \tLEFT: 'ArrowLeft', //left arrow\n\t\t * \tUP: 'ArrowUp', // up arrow\n\t\t * \tRIGHT: 'ArrowRight', // right arrow\n\t\t * \tBOTTOM: 'ArrowDown' // down arrow\n\t\t * }\n\t\t * ```\n\t\t * @type {Object}\n\t\t */\n\t\tthis.keys = { LEFT: 'ArrowLeft', UP: 'ArrowUp', RIGHT: 'ArrowRight', BOTTOM: 'ArrowDown' };\n\n\t\t/**\n\t\t * This object contains references to the mouse actions used by the controls.\n\t\t *\n\t\t * ```js\n\t\t * controls.mouseButtons = {\n\t\t * \tLEFT: THREE.MOUSE.ROTATE,\n\t\t * \tMIDDLE: THREE.MOUSE.DOLLY,\n\t\t * \tRIGHT: THREE.MOUSE.PAN\n\t\t * }\n\t\t * ```\n\t\t * @type {Object}\n\t\t */\n\t\tthis.mouseButtons = { LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN };\n\n\t\t/**\n\t\t * This object contains references to the touch actions used by the controls.\n\t\t *\n\t\t * ```js\n\t\t * controls.mouseButtons = {\n\t\t * \tONE: THREE.TOUCH.ROTATE,\n\t\t * \tTWO: THREE.TOUCH.DOLLY_PAN\n\t\t * }\n\t\t * ```\n\t\t * @type {Object}\n\t\t */\n\t\tthis.touches = { ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN };\n\n\t\t/**\n\t\t * Used internally by `saveState()` and `reset()`.\n\t\t *\n\t\t * @type {Vector3}\n\t\t */\n\t\tthis.target0 = this.target.clone();\n\n\t\t/**\n\t\t * Used internally by `saveState()` and `reset()`.\n\t\t *\n\t\t * @type {Vector3}\n\t\t */\n\t\tthis.position0 = this.object.position.clone();\n\n\t\t/**\n\t\t * Used internally by `saveState()` and `reset()`.\n\t\t *\n\t\t * @type {number}\n\t\t */\n\t\tthis.zoom0 = this.object.zoom;\n\n\t\tthis._cursorStyle = 'auto';\n\n\t\t// the target DOM element for key events\n\t\tthis._domElementKeyEvents = null;\n\n\t\t// internals\n\n\t\tthis._lastPosition = new Vector3();\n\t\tthis._lastQuaternion = new Quaternion();\n\t\tthis._lastTargetPosition = new Vector3();\n\n\t\t// so camera.up is the orbit axis\n\t\tthis._quat = new Quaternion().setFromUnitVectors( object.up, new Vector3( 0, 1, 0 ) );\n\t\tthis._quatInverse = this._quat.clone().invert();\n\n\t\t// current position in spherical coordinates\n\t\tthis._spherical = new Spherical();\n\t\tthis._sphericalDelta = new Spherical();\n\n\t\tthis._scale = 1;\n\t\tthis._panOffset = new Vector3();\n\n\t\tthis._rotateStart = new Vector2();\n\t\tthis._rotateEnd = new Vector2();\n\t\tthis._rotateDelta = new Vector2();\n\n\t\tthis._panStart = new Vector2();\n\t\tthis._panEnd = new Vector2();\n\t\tthis._panDelta = new Vector2();\n\n\t\tthis._dollyStart = new Vector2();\n\t\tthis._dollyEnd = new Vector2();\n\t\tthis._dollyDelta = new Vector2();\n\n\t\tthis._dollyDirection = new Vector3();\n\t\tthis._mouse = new Vector2();\n\t\tthis._performCursorZoom = false;\n\n\t\tthis._pointers = [];\n\t\tthis._pointerPositions = {};\n\n\t\tthis._controlActive = false;\n\n\t\t// event listeners\n\n\t\tthis._onPointerMove = onPointerMove.bind( this );\n\t\tthis._onPointerDown = onPointerDown.bind( this );\n\t\tthis._onPointerUp = onPointerUp.bind( this );\n\t\tthis._onContextMenu = onContextMenu.bind( this );\n\t\tthis._onMouseWheel = onMouseWheel.bind( this );\n\t\tthis._onKeyDown = onKeyDown.bind( this );\n\n\t\tthis._onTouchStart = onTouchStart.bind( this );\n\t\tthis._onTouchMove = onTouchMove.bind( this );\n\n\t\tthis._onMouseDown = onMouseDown.bind( this );\n\t\tthis._onMouseMove = onMouseMove.bind( this );\n\n\t\tthis._interceptControlDown = interceptControlDown.bind( this );\n\t\tthis._interceptControlUp = interceptControlUp.bind( this );\n\n\t\t//\n\n\t\tif ( this.domElement !== null ) {\n\n\t\t\tthis.connect( this.domElement );\n\n\t\t}\n\n\t\tthis.update();\n\n\t}\n\n\t/**\n\t * Defines the visual representation of the cursor.\n\t *\n\t * @type {('auto'|'grab')}\n\t * @default 'auto'\n\t */\n\tset cursorStyle( type ) {\n\n\t\tthis._cursorStyle = type;\n\n\t\tif ( type === 'grab' ) {\n\n\t\t\tthis.domElement.style.cursor = 'grab';\n\n\t\t} else {\n\n\t\t\tthis.domElement.style.cursor = 'auto';\n\n\t\t}\n\n\t}\n\n\tget cursorStyle() {\n\n\t\treturn this._cursorStyle;\n\n\t}\n\n\tconnect( element ) {\n\n\t\tsuper.connect( element );\n\n\t\tthis.domElement.addEventListener( 'pointerdown', this._onPointerDown );\n\t\tthis.domElement.addEventListener( 'pointercancel', this._onPointerUp );\n\n\t\tthis.domElement.addEventListener( 'contextmenu', this._onContextMenu );\n\t\tthis.domElement.addEventListener( 'wheel', this._onMouseWheel, { passive: false } );\n\n\t\tconst document = this.domElement.getRootNode(); // offscreen canvas compatibility\n\t\tdocument.addEventListener( 'keydown', this._interceptControlDown, { passive: true, capture: true } );\n\n\t\tthis.domElement.style.touchAction = 'none'; // Disable touch scroll\n\n\t}\n\n\tdisconnect() {\n\n\t\tthis.domElement.removeEventListener( 'pointerdown', this._onPointerDown );\n\t\tthis.domElement.ownerDocument.removeEventListener( 'pointermove', this._onPointerMove );\n\t\tthis.domElement.ownerDocument.removeEventListener( 'pointerup', this._onPointerUp );\n\t\tthis.domElement.removeEventListener( 'pointercancel', this._onPointerUp );\n\n\t\tthis.domElement.removeEventListener( 'wheel', this._onMouseWheel );\n\t\tthis.domElement.removeEventListener( 'contextmenu', this._onContextMenu );\n\n\t\tthis.stopListenToKeyEvents();\n\n\t\tconst document = this.domElement.getRootNode(); // offscreen canvas compatibility\n\t\tdocument.removeEventListener( 'keydown', this._interceptControlDown, { capture: true } );\n\n\t\tthis.domElement.style.touchAction = ''; // Restore touch scroll\n\n\t}\n\n\tdispose() {\n\n\t\tthis.disconnect();\n\n\t}\n\n\t/**\n\t * Get the current vertical rotation, in radians.\n\t *\n\t * @return {number} The current vertical rotation, in radians.\n\t */\n\tgetPolarAngle() {\n\n\t\treturn this._spherical.phi;\n\n\t}\n\n\t/**\n\t * Get the current horizontal rotation, in radians.\n\t *\n\t * @return {number} The current horizontal rotation, in radians.\n\t */\n\tgetAzimuthalAngle() {\n\n\t\treturn this._spherical.theta;\n\n\t}\n\n\t/**\n\t * Returns the distance from the camera to the target.\n\t *\n\t * @return {number} The distance from the camera to the target.\n\t */\n\tgetDistance() {\n\n\t\treturn this.object.position.distanceTo( this.target );\n\n\t}\n\n\t/**\n\t * Adds key event listeners to the given DOM element.\n\t * `window` is a recommended argument for using this method.\n\t *\n\t * @param {HTMLElement} domElement - The DOM element\n\t */\n\tlistenToKeyEvents( domElement ) {\n\n\t\tdomElement.addEventListener( 'keydown', this._onKeyDown );\n\t\tthis._domElementKeyEvents = domElement;\n\n\t}\n\n\t/**\n\t * Removes the key event listener previously defined with `listenToKeyEvents()`.\n\t */\n\tstopListenToKeyEvents() {\n\n\t\tif ( this._domElementKeyEvents !== null ) {\n\n\t\t\tthis._domElementKeyEvents.removeEventListener( 'keydown', this._onKeyDown );\n\t\t\tthis._domElementKeyEvents = null;\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Save the current state of the controls. This can later be recovered with `reset()`.\n\t */\n\tsaveState() {\n\n\t\tthis.target0.copy( this.target );\n\t\tthis.position0.copy( this.object.position );\n\t\tthis.zoom0 = this.object.zoom;\n\n\t}\n\n\t/**\n\t * Reset the controls to their state from either the last time the `saveState()`\n\t * was called, or the initial state.\n\t */\n\treset() {\n\n\t\tthis.target.copy( this.target0 );\n\t\tthis.object.position.copy( this.position0 );\n\t\tthis.object.zoom = this.zoom0;\n\n\t\tthis.object.updateProjectionMatrix();\n\t\tthis.dispatchEvent( _changeEvent );\n\n\t\tthis.update();\n\n\t\tthis.state = _STATE.NONE;\n\n\t}\n\n\t/**\n\t * Programmatically pan the camera.\n\t *\n\t * @param {number} deltaX - The horizontal pan amount in pixels.\n\t * @param {number} deltaY - The vertical pan amount in pixels.\n\t */\n\tpan( deltaX, deltaY ) {\n\n\t\tthis._pan( deltaX, deltaY );\n\t\tthis.update();\n\n\t}\n\n\t/**\n\t * Programmatically dolly in (zoom in for perspective camera).\n\t *\n\t * @param {number} dollyScale - The dolly scale factor.\n\t */\n\tdollyIn( dollyScale ) {\n\n\t\tthis._dollyIn( dollyScale );\n\t\tthis.update();\n\n\t}\n\n\t/**\n\t * Programmatically dolly out (zoom out for perspective camera).\n\t *\n\t * @param {number} dollyScale - The dolly scale factor.\n\t */\n\tdollyOut( dollyScale ) {\n\n\t\tthis._dollyOut( dollyScale );\n\t\tthis.update();\n\n\t}\n\n\t/**\n\t * Programmatically rotate the camera left (around the vertical axis).\n\t *\n\t * @param {number} angle - The rotation angle in radians.\n\t */\n\trotateLeft( angle ) {\n\n\t\tthis._rotateLeft( angle );\n\t\tthis.update();\n\n\t}\n\n\t/**\n\t * Programmatically rotate the camera up (around the horizontal axis).\n\t *\n\t * @param {number} angle - The rotation angle in radians.\n\t */\n\trotateUp( angle ) {\n\n\t\tthis._rotateUp( angle );\n\t\tthis.update();\n\n\t}\n\n\tupdate( deltaTime = null ) {\n\n\t\tconst position = this.object.position;\n\n\t\t_v.copy( position ).sub( this.target );\n\n\t\t// rotate offset to \"y-axis-is-up\" space\n\t\t_v.applyQuaternion( this._quat );\n\n\t\t// angle from z-axis around y-axis\n\t\tthis._spherical.setFromVector3( _v );\n\n\t\tif ( this.autoRotate && this.state === _STATE.NONE ) {\n\n\t\t\tthis._rotateLeft( this._getAutoRotationAngle( deltaTime ) );\n\n\t\t}\n\n\t\tif ( this.enableDamping ) {\n\n\t\t\tthis._spherical.theta += this._sphericalDelta.theta * this.dampingFactor;\n\t\t\tthis._spherical.phi += this._sphericalDelta.phi * this.dampingFactor;\n\n\t\t} else {\n\n\t\t\tthis._spherical.theta += this._sphericalDelta.theta;\n\t\t\tthis._spherical.phi += this._sphericalDelta.phi;\n\n\t\t}\n\n\t\t// restrict theta to be between desired limits\n\n\t\tlet min = this.minAzimuthAngle;\n\t\tlet max = this.maxAzimuthAngle;\n\n\t\tif ( isFinite( min ) && isFinite( max ) ) {\n\n\t\t\tif ( min < - Math.PI ) min += _twoPI; else if ( min > Math.PI ) min -= _twoPI;\n\n\t\t\tif ( max < - Math.PI ) max += _twoPI; else if ( max > Math.PI ) max -= _twoPI;\n\n\t\t\tif ( min <= max ) {\n\n\t\t\t\tthis._spherical.theta = Math.max( min, Math.min( max, this._spherical.theta ) );\n\n\t\t\t} else {\n\n\t\t\t\tthis._spherical.theta = ( this._spherical.theta > ( min + max ) / 2 ) ?\n\t\t\t\t\tMath.max( min, this._spherical.theta ) :\n\t\t\t\t\tMath.min( max, this._spherical.theta );\n\n\t\t\t}\n\n\t\t}\n\n\t\t// restrict phi to be between desired limits\n\t\tthis._spherical.phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, this._spherical.phi ) );\n\n\t\tthis._spherical.makeSafe();\n\n\n\t\t// move target to panned location\n\n\t\tif ( this.enableDamping === true ) {\n\n\t\t\tthis.target.addScaledVector( this._panOffset, this.dampingFactor );\n\n\t\t} else {\n\n\t\t\tthis.target.add( this._panOffset );\n\n\t\t}\n\n\t\t// Limit the target distance from the cursor to create a sphere around the center of interest\n\t\tthis.target.sub( this.cursor );\n\t\tthis.target.clampLength( this.minTargetRadius, this.maxTargetRadius );\n\t\tthis.target.add( this.cursor );\n\n\t\tlet zoomChanged = false;\n\t\t// adjust the camera position based on zoom only if we're not zooming to the cursor or if it's an ortho camera\n\t\t// we adjust zoom later in these cases\n\t\tif ( this.zoomToCursor && this._performCursorZoom || this.object.isOrthographicCamera ) {\n\n\t\t\tthis._spherical.radius = this._clampDistance( this._spherical.radius );\n\n\t\t} else {\n\n\t\t\tconst prevRadius = this._spherical.radius;\n\t\t\tthis._spherical.radius = this._clampDistance( this._spherical.radius * this._scale );\n\t\t\tzoomChanged = prevRadius != this._spherical.radius;\n\n\t\t}\n\n\t\t_v.setFromSpherical( this._spherical );\n\n\t\t// rotate offset back to \"camera-up-vector-is-up\" space\n\t\t_v.applyQuaternion( this._quatInverse );\n\n\t\tposition.copy( this.target ).add( _v );\n\n\t\tthis.object.lookAt( this.target );\n\n\t\tif ( this.enableDamping === true ) {\n\n\t\t\tthis._sphericalDelta.theta *= ( 1 - this.dampingFactor );\n\t\t\tthis._sphericalDelta.phi *= ( 1 - this.dampingFactor );\n\n\t\t\tthis._panOffset.multiplyScalar( 1 - this.dampingFactor );\n\n\t\t} else {\n\n\t\t\tthis._sphericalDelta.set( 0, 0, 0 );\n\n\t\t\tthis._panOffset.set( 0, 0, 0 );\n\n\t\t}\n\n\t\t// adjust camera position\n\t\tif ( this.zoomToCursor && this._performCursorZoom ) {\n\n\t\t\tlet newRadius = null;\n\t\t\tif ( this.object.isPerspectiveCamera ) {\n\n\t\t\t\t// move the camera down the pointer ray\n\t\t\t\t// this method avoids floating point error\n\t\t\t\tconst prevRadius = _v.length();\n\t\t\t\tnewRadius = this._clampDistance( prevRadius * this._scale );\n\n\t\t\t\tconst radiusDelta = prevRadius - newRadius;\n\t\t\t\tthis.object.position.addScaledVector( this._dollyDirection, radiusDelta );\n\t\t\t\tthis.object.updateMatrixWorld();\n\n\t\t\t\tzoomChanged = !! radiusDelta;\n\n\t\t\t} else if ( this.object.isOrthographicCamera ) {\n\n\t\t\t\t// adjust the ortho camera position based on zoom changes\n\t\t\t\tconst mouseBefore = new Vector3( this._mouse.x, this._mouse.y, 0 );\n\t\t\t\tmouseBefore.unproject( this.object );\n\n\t\t\t\tconst prevZoom = this.object.zoom;\n\t\t\t\tthis.object.zoom = Math.max( this.minZoom, Math.min( this.maxZoom, this.object.zoom / this._scale ) );\n\t\t\t\tthis.object.updateProjectionMatrix();\n\n\t\t\t\tzoomChanged = prevZoom !== this.object.zoom;\n\n\t\t\t\tconst mouseAfter = new Vector3( this._mouse.x, this._mouse.y, 0 );\n\t\t\t\tmouseAfter.unproject( this.object );\n\n\t\t\t\tthis.object.position.sub( mouseAfter ).add( mouseBefore );\n\t\t\t\tthis.object.updateMatrixWorld();\n\n\t\t\t\tnewRadius = _v.length();\n\n\t\t\t} else {\n\n\t\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled.' );\n\t\t\t\tthis.zoomToCursor = false;\n\n\t\t\t}\n\n\t\t\t// handle the placement of the target\n\t\t\tif ( newRadius !== null ) {\n\n\t\t\t\tif ( this.screenSpacePanning ) {\n\n\t\t\t\t\t// position the orbit target in front of the new camera position\n\t\t\t\t\tthis.target.set( 0, 0, - 1 )\n\t\t\t\t\t\t.transformDirection( this.object.matrix )\n\t\t\t\t\t\t.multiplyScalar( newRadius )\n\t\t\t\t\t\t.add( this.object.position );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// get the ray and translation plane to compute target\n\t\t\t\t\t_ray.origin.copy( this.object.position );\n\t\t\t\t\t_ray.direction.set( 0, 0, - 1 ).transformDirection( this.object.matrix );\n\n\t\t\t\t\t// if the camera is 20 degrees above the horizon then don't adjust the focus target to avoid\n\t\t\t\t\t// extremely large values\n\t\t\t\t\tif ( Math.abs( this.object.up.dot( _ray.direction ) ) < _TILT_LIMIT ) {\n\n\t\t\t\t\t\tthis.object.lookAt( this.target );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t_plane.setFromNormalAndCoplanarPoint( this.object.up, this.target );\n\t\t\t\t\t\t_ray.intersectPlane( _plane, this.target );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else if ( this.object.isOrthographicCamera ) {\n\n\t\t\tconst prevZoom = this.object.zoom;\n\t\t\tthis.object.zoom = Math.max( this.minZoom, Math.min( this.maxZoom, this.object.zoom / this._scale ) );\n\n\t\t\tif ( prevZoom !== this.object.zoom ) {\n\n\t\t\t\tthis.object.updateProjectionMatrix();\n\t\t\t\tzoomChanged = true;\n\n\t\t\t}\n\n\t\t}\n\n\t\tthis._scale = 1;\n\t\tthis._performCursorZoom = false;\n\n\t\t// update condition is:\n\t\t// min(camera displacement, camera rotation in radians)^2 > EPS\n\t\t// using small-angle approximation cos(x/2) = 1 - x^2 / 8\n\n\t\tif ( zoomChanged ||\n\t\t\tthis._lastPosition.distanceToSquared( this.object.position ) > _EPS ||\n\t\t\t8 * ( 1 - this._lastQuaternion.dot( this.object.quaternion ) ) > _EPS ||\n\t\t\tthis._lastTargetPosition.distanceToSquared( this.target ) > _EPS ) {\n\n\t\t\tthis.dispatchEvent( _changeEvent );\n\n\t\t\tthis._lastPosition.copy( this.object.position );\n\t\t\tthis._lastQuaternion.copy( this.object.quaternion );\n\t\t\tthis._lastTargetPosition.copy( this.target );\n\n\t\t\treturn true;\n\n\t\t}\n\n\t\treturn false;\n\n\t}\n\n\t_getAutoRotationAngle( deltaTime ) {\n\n\t\tif ( deltaTime !== null ) {\n\n\t\t\treturn ( _twoPI / 60 * this.autoRotateSpeed ) * deltaTime;\n\n\t\t} else {\n\n\t\t\treturn _twoPI / 60 / 60 * this.autoRotateSpeed;\n\n\t\t}\n\n\t}\n\n\t_getZoomScale( delta ) {\n\n\t\tconst normalizedDelta = Math.abs( delta * 0.01 );\n\t\treturn Math.pow( 0.95, this.zoomSpeed * normalizedDelta );\n\n\t}\n\n\t_rotateLeft( angle ) {\n\n\t\tthis._sphericalDelta.theta -= angle;\n\n\t}\n\n\t_rotateUp( angle ) {\n\n\t\tthis._sphericalDelta.phi -= angle;\n\n\t}\n\n\t_panLeft( distance, objectMatrix ) {\n\n\t\t_v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix\n\t\t_v.multiplyScalar( - distance );\n\n\t\tthis._panOffset.add( _v );\n\n\t}\n\n\t_panUp( distance, objectMatrix ) {\n\n\t\tif ( this.screenSpacePanning === true ) {\n\n\t\t\t_v.setFromMatrixColumn( objectMatrix, 1 );\n\n\t\t} else {\n\n\t\t\t_v.setFromMatrixColumn( objectMatrix, 0 );\n\t\t\t_v.crossVectors( this.object.up, _v );\n\n\t\t}\n\n\t\t_v.multiplyScalar( distance );\n\n\t\tthis._panOffset.add( _v );\n\n\t}\n\n\t// deltaX and deltaY are in pixels; right and down are positive\n\t_pan( deltaX, deltaY ) {\n\n\t\tconst element = this.domElement;\n\n\t\tif ( this.object.isPerspectiveCamera ) {\n\n\t\t\t// perspective\n\t\t\tconst position = this.object.position;\n\t\t\t_v.copy( position ).sub( this.target );\n\t\t\tlet targetDistance = _v.length();\n\n\t\t\t// half of the fov is center to top of screen\n\t\t\ttargetDistance *= Math.tan( ( this.object.fov / 2 ) * Math.PI / 180.0 );\n\n\t\t\t// we use only clientHeight here so aspect ratio does not distort speed\n\t\t\tthis._panLeft( 2 * deltaX * targetDistance / element.clientHeight, this.object.matrix );\n\t\t\tthis._panUp( 2 * deltaY * targetDistance / element.clientHeight, this.object.matrix );\n\n\t\t} else if ( this.object.isOrthographicCamera ) {\n\n\t\t\t// orthographic\n\t\t\tthis._panLeft( deltaX * ( this.object.right - this.object.left ) / this.object.zoom / element.clientWidth, this.object.matrix );\n\t\t\tthis._panUp( deltaY * ( this.object.top - this.object.bottom ) / this.object.zoom / element.clientHeight, this.object.matrix );\n\n\t\t} else {\n\n\t\t\t// camera neither orthographic nor perspective\n\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );\n\t\t\tthis.enablePan = false;\n\n\t\t}\n\n\t}\n\n\t_dollyOut( dollyScale ) {\n\n\t\tif ( this.object.isPerspectiveCamera || this.object.isOrthographicCamera ) {\n\n\t\t\tthis._scale /= dollyScale;\n\n\t\t} else {\n\n\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );\n\t\t\tthis.enableZoom = false;\n\n\t\t}\n\n\t}\n\n\t_dollyIn( dollyScale ) {\n\n\t\tif ( this.object.isPerspectiveCamera || this.object.isOrthographicCamera ) {\n\n\t\t\tthis._scale *= dollyScale;\n\n\t\t} else {\n\n\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );\n\t\t\tthis.enableZoom = false;\n\n\t\t}\n\n\t}\n\n\t_updateZoomParameters( x, y ) {\n\n\t\tif ( ! this.zoomToCursor ) {\n\n\t\t\treturn;\n\n\t\t}\n\n\t\tthis._performCursorZoom = true;\n\n\t\tconst rect = this.domElement.getBoundingClientRect();\n\t\tconst dx = x - rect.left;\n\t\tconst dy = y - rect.top;\n\t\tconst w = rect.width;\n\t\tconst h = rect.height;\n\n\t\tthis._mouse.x = ( dx / w ) * 2 - 1;\n\t\tthis._mouse.y = - ( dy / h ) * 2 + 1;\n\n\t\tthis._dollyDirection.set( this._mouse.x, this._mouse.y, 1 ).unproject( this.object ).sub( this.object.position ).normalize();\n\n\t}\n\n\t_clampDistance( dist ) {\n\n\t\treturn Math.max( this.minDistance, Math.min( this.maxDistance, dist ) );\n\n\t}\n\n\t//\n\t// event callbacks - update the object state\n\t//\n\n\t_handleMouseDownRotate( event ) {\n\n\t\tthis._rotateStart.set( event.clientX, event.clientY );\n\n\t}\n\n\t_handleMouseDownDolly( event ) {\n\n\t\tthis._updateZoomParameters( event.clientX, event.clientX );\n\t\tthis._dollyStart.set( event.clientX, event.clientY );\n\n\t}\n\n\t_handleMouseDownPan( event ) {\n\n\t\tthis._panStart.set( event.clientX, event.clientY );\n\n\t}\n\n\t_handleMouseMoveRotate( event ) {\n\n\t\tthis._rotateEnd.set( event.clientX, event.clientY );\n\n\t\tthis._rotateDelta.subVectors( this._rotateEnd, this._rotateStart ).multiplyScalar( this.rotateSpeed );\n\n\t\tconst element = this.domElement;\n\n\t\tthis._rotateLeft( _twoPI * this._rotateDelta.x / element.clientHeight ); // yes, height\n\n\t\tthis._rotateUp( _twoPI * this._rotateDelta.y / element.clientHeight );\n\n\t\tthis._rotateStart.copy( this._rotateEnd );\n\n\t\tthis.update();\n\n\t}\n\n\t_handleMouseMoveDolly( event ) {\n\n\t\tthis._dollyEnd.set( event.clientX, event.clientY );\n\n\t\tthis._dollyDelta.subVectors( this._dollyEnd, this._dollyStart );\n\n\t\tif ( this._dollyDelta.y > 0 ) {\n\n\t\t\tthis._dollyOut( this._getZoomScale( this._dollyDelta.y ) );\n\n\t\t} else if ( this._dollyDelta.y < 0 ) {\n\n\t\t\tthis._dollyIn( this._getZoomScale( this._dollyDelta.y ) );\n\n\t\t}\n\n\t\tthis._dollyStart.copy( this._dollyEnd );\n\n\t\tthis.update();\n\n\t}\n\n\t_handleMouseMovePan( event ) {\n\n\t\tthis._panEnd.set( event.clientX, event.clientY );\n\n\t\tthis._panDelta.subVectors( this._panEnd, this._panStart ).multiplyScalar( this.panSpeed );\n\n\t\tthis._pan( this._panDelta.x, this._panDelta.y );\n\n\t\tthis._panStart.copy( this._panEnd );\n\n\t\tthis.update();\n\n\t}\n\n\t_handleMouseWheel( event ) {\n\n\t\tthis._updateZoomParameters( event.clientX, event.clientY );\n\n\t\tif ( event.deltaY < 0 ) {\n\n\t\t\tthis._dollyIn( this._getZoomScale( event.deltaY ) );\n\n\t\t} else if ( event.deltaY > 0 ) {\n\n\t\t\tthis._dollyOut( this._getZoomScale( event.deltaY ) );\n\n\t\t}\n\n\t\tthis.update();\n\n\t}\n\n\t_handleKeyDown( event ) {\n\n\t\tlet needsUpdate = false;\n\n\t\tswitch ( event.code ) {\n\n\t\t\tcase this.keys.UP:\n\n\t\t\t\tif ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n\t\t\t\t\tif ( this.enableRotate ) {\n\n\t\t\t\t\t\tthis._rotateUp( _twoPI * this.keyRotateSpeed / this.domElement.clientHeight );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( this.enablePan ) {\n\n\t\t\t\t\t\tthis._pan( 0, this.keyPanSpeed );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tneedsUpdate = true;\n\t\t\t\tbreak;\n\n\t\t\tcase this.keys.BOTTOM:\n\n\t\t\t\tif ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n\t\t\t\t\tif ( this.enableRotate ) {\n\n\t\t\t\t\t\tthis._rotateUp( - _twoPI * this.keyRotateSpeed / this.domElement.clientHeight );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( this.enablePan ) {\n\n\t\t\t\t\t\tthis._pan( 0, - this.keyPanSpeed );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tneedsUpdate = true;\n\t\t\t\tbreak;\n\n\t\t\tcase this.keys.LEFT:\n\n\t\t\t\tif ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n\t\t\t\t\tif ( this.enableRotate ) {\n\n\t\t\t\t\t\tthis._rotateLeft( _twoPI * this.keyRotateSpeed / this.domElement.clientHeight );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( this.enablePan ) {\n\n\t\t\t\t\t\tthis._pan( this.keyPanSpeed, 0 );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tneedsUpdate = true;\n\t\t\t\tbreak;\n\n\t\t\tcase this.keys.RIGHT:\n\n\t\t\t\tif ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n\t\t\t\t\tif ( this.enableRotate ) {\n\n\t\t\t\t\t\tthis._rotateLeft( - _twoPI * this.keyRotateSpeed / this.domElement.clientHeight );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( this.enablePan ) {\n\n\t\t\t\t\t\tthis._pan( - this.keyPanSpeed, 0 );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tneedsUpdate = true;\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\tif ( needsUpdate ) {\n\n\t\t\t// prevent the browser from scrolling on cursor keys\n\t\t\tevent.preventDefault();\n\n\t\t\tthis.update();\n\n\t\t}\n\n\n\t}\n\n\t_handleTouchStartRotate( event ) {\n\n\t\tif ( this._pointers.length === 1 ) {\n\n\t\t\tthis._rotateStart.set( event.pageX, event.pageY );\n\n\t\t} else {\n\n\t\t\tconst position = this._getSecondPointerPosition( event );\n\n\t\t\tconst x = 0.5 * ( event.pageX + position.x );\n\t\t\tconst y = 0.5 * ( event.pageY + position.y );\n\n\t\t\tthis._rotateStart.set( x, y );\n\n\t\t}\n\n\t}\n\n\t_handleTouchStartPan( event ) {\n\n\t\tif ( this._pointers.length === 1 ) {\n\n\t\t\tthis._panStart.set( event.pageX, event.pageY );\n\n\t\t} else {\n\n\t\t\tconst position = this._getSecondPointerPosition( event );\n\n\t\t\tconst x = 0.5 * ( event.pageX + position.x );\n\t\t\tconst y = 0.5 * ( event.pageY + position.y );\n\n\t\t\tthis._panStart.set( x, y );\n\n\t\t}\n\n\t}\n\n\t_handleTouchStartDolly( event ) {\n\n\t\tconst position = this._getSecondPointerPosition( event );\n\n\t\tconst dx = event.pageX - position.x;\n\t\tconst dy = event.pageY - position.y;\n\n\t\tconst distance = Math.sqrt( dx * dx + dy * dy );\n\n\t\tthis._dollyStart.set( 0, distance );\n\n\t}\n\n\t_handleTouchStartDollyPan( event ) {\n\n\t\tif ( this.enableZoom ) this._handleTouchStartDolly( event );\n\n\t\tif ( this.enablePan ) this._handleTouchStartPan( event );\n\n\t}\n\n\t_handleTouchStartDollyRotate( event ) {\n\n\t\tif ( this.enableZoom ) this._handleTouchStartDolly( event );\n\n\t\tif ( this.enableRotate ) this._handleTouchStartRotate( event );\n\n\t}\n\n\t_handleTouchMoveRotate( event ) {\n\n\t\tif ( this._pointers.length == 1 ) {\n\n\t\t\tthis._rotateEnd.set( event.pageX, event.pageY );\n\n\t\t} else {\n\n\t\t\tconst position = this._getSecondPointerPosition( event );\n\n\t\t\tconst x = 0.5 * ( event.pageX + position.x );\n\t\t\tconst y = 0.5 * ( event.pageY + position.y );\n\n\t\t\tthis._rotateEnd.set( x, y );\n\n\t\t}\n\n\t\tthis._rotateDelta.subVectors( this._rotateEnd, this._rotateStart ).multiplyScalar( this.rotateSpeed );\n\n\t\tconst element = this.domElement;\n\n\t\tthis._rotateLeft( _twoPI * this._rotateDelta.x / element.clientHeight ); // yes, height\n\n\t\tthis._rotateUp( _twoPI * this._rotateDelta.y / element.clientHeight );\n\n\t\tthis._rotateStart.copy( this._rotateEnd );\n\n\t}\n\n\t_handleTouchMovePan( event ) {\n\n\t\tif ( this._pointers.length === 1 ) {\n\n\t\t\tthis._panEnd.set( event.pageX, event.pageY );\n\n\t\t} else {\n\n\t\t\tconst position = this._getSecondPointerPosition( event );\n\n\t\t\tconst x = 0.5 * ( event.pageX + position.x );\n\t\t\tconst y = 0.5 * ( event.pageY + position.y );\n\n\t\t\tthis._panEnd.set( x, y );\n\n\t\t}\n\n\t\tthis._panDelta.subVectors( this._panEnd, this._panStart ).multiplyScalar( this.panSpeed );\n\n\t\tthis._pan( this._panDelta.x, this._panDelta.y );\n\n\t\tthis._panStart.copy( this._panEnd );\n\n\t}\n\n\t_handleTouchMoveDolly( event ) {\n\n\t\tconst position = this._getSecondPointerPosition( event );\n\n\t\tconst dx = event.pageX - position.x;\n\t\tconst dy = event.pageY - position.y;\n\n\t\tconst distance = Math.sqrt( dx * dx + dy * dy );\n\n\t\tthis._dollyEnd.set( 0, distance );\n\n\t\tthis._dollyDelta.set( 0, Math.pow( this._dollyEnd.y / this._dollyStart.y, this.zoomSpeed ) );\n\n\t\tthis._dollyOut( this._dollyDelta.y );\n\n\t\tthis._dollyStart.copy( this._dollyEnd );\n\n\t\tconst centerX = ( event.pageX + position.x ) * 0.5;\n\t\tconst centerY = ( event.pageY + position.y ) * 0.5;\n\n\t\tthis._updateZoomParameters( centerX, centerY );\n\n\t}\n\n\t_handleTouchMoveDollyPan( event ) {\n\n\t\tif ( this.enableZoom ) this._handleTouchMoveDolly( event );\n\n\t\tif ( this.enablePan ) this._handleTouchMovePan( event );\n\n\t}\n\n\t_handleTouchMoveDollyRotate( event ) {\n\n\t\tif ( this.enableZoom ) this._handleTouchMoveDolly( event );\n\n\t\tif ( this.enableRotate ) this._handleTouchMoveRotate( event );\n\n\t}\n\n\t// pointers\n\n\t_addPointer( event ) {\n\n\t\tthis._pointers.push( event.pointerId );\n\n\t}\n\n\t_removePointer( event ) {\n\n\t\tdelete this._pointerPositions[ event.pointerId ];\n\n\t\tfor ( let i = 0; i < this._pointers.length; i ++ ) {\n\n\t\t\tif ( this._pointers[ i ] == event.pointerId ) {\n\n\t\t\t\tthis._pointers.splice( i, 1 );\n\t\t\t\treturn;\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t_isTrackingPointer( event ) {\n\n\t\tfor ( let i = 0; i < this._pointers.length; i ++ ) {\n\n\t\t\tif ( this._pointers[ i ] == event.pointerId ) return true;\n\n\t\t}\n\n\t\treturn false;\n\n\t}\n\n\t_trackPointer( event ) {\n\n\t\tlet position = this._pointerPositions[ event.pointerId ];\n\n\t\tif ( position === undefined ) {\n\n\t\t\tposition = new Vector2();\n\t\t\tthis._pointerPositions[ event.pointerId ] = position;\n\n\t\t}\n\n\t\tposition.set( event.pageX, event.pageY );\n\n\t}\n\n\t_getSecondPointerPosition( event ) {\n\n\t\tconst pointerId = ( event.pointerId === this._pointers[ 0 ] ) ? this._pointers[ 1 ] : this._pointers[ 0 ];\n\n\t\treturn this._pointerPositions[ pointerId ];\n\n\t}\n\n\t//\n\n\t_customWheelEvent( event ) {\n\n\t\tconst mode = event.deltaMode;\n\n\t\t// minimal wheel event altered to meet delta-zoom demand\n\t\tconst newEvent = {\n\t\t\tclientX: event.clientX,\n\t\t\tclientY: event.clientY,\n\t\t\tdeltaY: event.deltaY,\n\t\t};\n\n\t\tswitch ( mode ) {\n\n\t\t\tcase 1: // LINE_MODE\n\t\t\t\tnewEvent.deltaY *= 16;\n\t\t\t\tbreak;\n\n\t\t\tcase 2: // PAGE_MODE\n\t\t\t\tnewEvent.deltaY *= 100;\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\t// detect if event was triggered by pinching\n\t\tif ( event.ctrlKey && ! this._controlActive ) {\n\n\t\t\tnewEvent.deltaY *= 10;\n\n\t\t}\n\n\t\treturn newEvent;\n\n\t}\n\n}\n\nfunction onPointerDown( event ) {\n\n\tif ( this.enabled === false ) return;\n\n\tif ( this._pointers.length === 0 ) {\n\n\t\tthis.domElement.setPointerCapture( event.pointerId );\n\n\t\tthis.domElement.ownerDocument.addEventListener( 'pointermove', this._onPointerMove );\n\t\tthis.domElement.ownerDocument.addEventListener( 'pointerup', this._onPointerUp );\n\n\t}\n\n\t//\n\n\tif ( this._isTrackingPointer( event ) ) return;\n\n\t//\n\n\tthis._addPointer( event );\n\n\tif ( event.pointerType === 'touch' ) {\n\n\t\tthis._onTouchStart( event );\n\n\t} else {\n\n\t\tthis._onMouseDown( event );\n\n\t}\n\n\tif ( this._cursorStyle === 'grab' ) {\n\n\t\tthis.domElement.style.cursor = 'grabbing';\n\n\t}\n\n}\n\nfunction onPointerMove( event ) {\n\n\tif ( this.enabled === false ) return;\n\n\tif ( event.pointerType === 'touch' ) {\n\n\t\tthis._onTouchMove( event );\n\n\t} else {\n\n\t\tthis._onMouseMove( event );\n\n\t}\n\n}\n\nfunction onPointerUp( event ) {\n\n\tthis._removePointer( event );\n\n\tswitch ( this._pointers.length ) {\n\n\t\tcase 0:\n\n\t\t\tthis.domElement.releasePointerCapture( event.pointerId );\n\n\t\t\tthis.domElement.ownerDocument.removeEventListener( 'pointermove', this._onPointerMove );\n\t\t\tthis.domElement.ownerDocument.removeEventListener( 'pointerup', this._onPointerUp );\n\n\t\t\tthis.dispatchEvent( _endEvent );\n\n\t\t\tthis.state = _STATE.NONE;\n\n\t\t\tif ( this._cursorStyle === 'grab' ) {\n\n\t\t\t\tthis.domElement.style.cursor = 'grab';\n\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tcase 1:\n\n\t\t\tconst pointerId = this._pointers[ 0 ];\n\t\t\tconst position = this._pointerPositions[ pointerId ];\n\n\t\t\t// minimal placeholder event - allows state correction on pointer-up\n\t\t\tthis._onTouchStart( { pointerId: pointerId, pageX: position.x, pageY: position.y } );\n\n\t\t\tbreak;\n\n\t}\n\n}\n\nfunction onMouseDown( event ) {\n\n\tlet mouseAction;\n\n\tswitch ( event.button ) {\n\n\t\tcase 0:\n\n\t\t\tmouseAction = this.mouseButtons.LEFT;\n\t\t\tbreak;\n\n\t\tcase 1:\n\n\t\t\tmouseAction = this.mouseButtons.MIDDLE;\n\t\t\tbreak;\n\n\t\tcase 2:\n\n\t\t\tmouseAction = this.mouseButtons.RIGHT;\n\t\t\tbreak;\n\n\t\tdefault:\n\n\t\t\tmouseAction = - 1;\n\n\t}\n\n\tswitch ( mouseAction ) {\n\n\t\tcase MOUSE.DOLLY:\n\n\t\t\tif ( this.enableZoom === false ) return;\n\n\t\t\tthis._handleMouseDownDolly( event );\n\n\t\t\tthis.state = _STATE.DOLLY;\n\n\t\t\tbreak;\n\n\t\tcase MOUSE.ROTATE:\n\n\t\t\tif ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n\t\t\t\tif ( this.enablePan === false ) return;\n\n\t\t\t\tthis._handleMouseDownPan( event );\n\n\t\t\t\tthis.state = _STATE.PAN;\n\n\t\t\t} else {\n\n\t\t\t\tif ( this.enableRotate === false ) return;\n\n\t\t\t\tthis._handleMouseDownRotate( event );\n\n\t\t\t\tthis.state = _STATE.ROTATE;\n\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tcase MOUSE.PAN:\n\n\t\t\tif ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n\t\t\t\tif ( this.enableRotate === false ) return;\n\n\t\t\t\tthis._handleMouseDownRotate( event );\n\n\t\t\t\tthis.state = _STATE.ROTATE;\n\n\t\t\t} else {\n\n\t\t\t\tif ( this.enablePan === false ) return;\n\n\t\t\t\tthis._handleMouseDownPan( event );\n\n\t\t\t\tthis.state = _STATE.PAN;\n\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tdefault:\n\n\t\t\tthis.state = _STATE.NONE;\n\n\t}\n\n\tif ( this.state !== _STATE.NONE ) {\n\n\t\tthis.dispatchEvent( _startEvent );\n\n\t}\n\n}\n\nfunction onMouseMove( event ) {\n\n\tswitch ( this.state ) {\n\n\t\tcase _STATE.ROTATE:\n\n\t\t\tif ( this.enableRotate === false ) return;\n\n\t\t\tthis._handleMouseMoveRotate( event );\n\n\t\t\tbreak;\n\n\t\tcase _STATE.DOLLY:\n\n\t\t\tif ( this.enableZoom === false ) return;\n\n\t\t\tthis._handleMouseMoveDolly( event );\n\n\t\t\tbreak;\n\n\t\tcase _STATE.PAN:\n\n\t\t\tif ( this.enablePan === false ) return;\n\n\t\t\tthis._handleMouseMovePan( event );\n\n\t\t\tbreak;\n\n\t}\n\n}\n\nfunction onMouseWheel( event ) {\n\n\tif ( this.enabled === false || this.enableZoom === false || this.state !== _STATE.NONE ) return;\n\n\tevent.preventDefault();\n\n\tthis.dispatchEvent( _startEvent );\n\n\tthis._handleMouseWheel( this._customWheelEvent( event ) );\n\n\tthis.dispatchEvent( _endEvent );\n\n}\n\nfunction onKeyDown( event ) {\n\n\tif ( this.enabled === false ) return;\n\n\tthis._handleKeyDown( event );\n\n}\n\nfunction onTouchStart( event ) {\n\n\tthis._trackPointer( event );\n\n\tswitch ( this._pointers.length ) {\n\n\t\tcase 1:\n\n\t\t\tswitch ( this.touches.ONE ) {\n\n\t\t\t\tcase TOUCH.ROTATE:\n\n\t\t\t\t\tif ( this.enableRotate === false ) return;\n\n\t\t\t\t\tthis._handleTouchStartRotate( event );\n\n\t\t\t\t\tthis.state = _STATE.TOUCH_ROTATE;\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TOUCH.PAN:\n\n\t\t\t\t\tif ( this.enablePan === false ) return;\n\n\t\t\t\t\tthis._handleTouchStartPan( event );\n\n\t\t\t\t\tthis.state = _STATE.TOUCH_PAN;\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\n\t\t\t\t\tthis.state = _STATE.NONE;\n\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tcase 2:\n\n\t\t\tswitch ( this.touches.TWO ) {\n\n\t\t\t\tcase TOUCH.DOLLY_PAN:\n\n\t\t\t\t\tif ( this.enableZoom === false && this.enablePan === false ) return;\n\n\t\t\t\t\tthis._handleTouchStartDollyPan( event );\n\n\t\t\t\t\tthis.state = _STATE.TOUCH_DOLLY_PAN;\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TOUCH.DOLLY_ROTATE:\n\n\t\t\t\t\tif ( this.enableZoom === false && this.enableRotate === false ) return;\n\n\t\t\t\t\tthis._handleTouchStartDollyRotate( event );\n\n\t\t\t\t\tthis.state = _STATE.TOUCH_DOLLY_ROTATE;\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\n\t\t\t\t\tthis.state = _STATE.NONE;\n\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tdefault:\n\n\t\t\tthis.state = _STATE.NONE;\n\n\t}\n\n\tif ( this.state !== _STATE.NONE ) {\n\n\t\tthis.dispatchEvent( _startEvent );\n\n\t}\n\n}\n\nfunction onTouchMove( event ) {\n\n\tthis._trackPointer( event );\n\n\tswitch ( this.state ) {\n\n\t\tcase _STATE.TOUCH_ROTATE:\n\n\t\t\tif ( this.enableRotate === false ) return;\n\n\t\t\tthis._handleTouchMoveRotate( event );\n\n\t\t\tthis.update();\n\n\t\t\tbreak;\n\n\t\tcase _STATE.TOUCH_PAN:\n\n\t\t\tif ( this.enablePan === false ) return;\n\n\t\t\tthis._handleTouchMovePan( event );\n\n\t\t\tthis.update();\n\n\t\t\tbreak;\n\n\t\tcase _STATE.TOUCH_DOLLY_PAN:\n\n\t\t\tif ( this.enableZoom === false && this.enablePan === false ) return;\n\n\t\t\tthis._handleTouchMoveDollyPan( event );\n\n\t\t\tthis.update();\n\n\t\t\tbreak;\n\n\t\tcase _STATE.TOUCH_DOLLY_ROTATE:\n\n\t\t\tif ( this.enableZoom === false && this.enableRotate === false ) return;\n\n\t\t\tthis._handleTouchMoveDollyRotate( event );\n\n\t\t\tthis.update();\n\n\t\t\tbreak;\n\n\t\tdefault:\n\n\t\t\tthis.state = _STATE.NONE;\n\n\t}\n\n}\n\nfunction onContextMenu( event ) {\n\n\tif ( this.enabled === false ) return;\n\n\tevent.preventDefault();\n\n}\n\nfunction interceptControlDown( event ) {\n\n\tif ( event.key === 'Control' ) {\n\n\t\tthis._controlActive = true;\n\n\t\tconst document = this.domElement.getRootNode(); // offscreen canvas compatibility\n\n\t\tdocument.addEventListener( 'keyup', this._interceptControlUp, { passive: true, capture: true } );\n\n\t}\n\n}\n\nfunction interceptControlUp( event ) {\n\n\tif ( event.key === 'Control' ) {\n\n\t\tthis._controlActive = false;\n\n\t\tconst document = this.domElement.getRootNode(); // offscreen canvas compatibility\n\n\t\tdocument.removeEventListener( 'keyup', this._interceptControlUp, { passive: true, capture: true } );\n\n\t}\n\n}\n\nexport { OrbitControls };\n","import {\n\tBoxGeometry,\n\tBufferGeometry,\n\tControls,\n\tCylinderGeometry,\n\tDoubleSide,\n\tEuler,\n\tFloat32BufferAttribute,\n\tLine,\n\tLineBasicMaterial,\n\tMatrix4,\n\tMesh,\n\tMeshBasicMaterial,\n\tObject3D,\n\tOctahedronGeometry,\n\tPlaneGeometry,\n\tQuaternion,\n\tRaycaster,\n\tSphereGeometry,\n\tTorusGeometry,\n\tVector3\n} from 'three';\n\nconst _raycaster = new Raycaster();\n\nconst _tempVector = new Vector3();\nconst _tempVector2 = new Vector3();\nconst _tempQuaternion = new Quaternion();\nconst _unit = {\n\tX: new Vector3( 1, 0, 0 ),\n\tY: new Vector3( 0, 1, 0 ),\n\tZ: new Vector3( 0, 0, 1 )\n};\n\n/**\n * Fires if any type of change (object or property change) is performed. Property changes\n * are separate events you can add event listeners to. The event type is \"propertyname-changed\".\n *\n * @event TransformControls#change\n * @type {Object}\n */\nconst _changeEvent = { type: 'change' };\n\n/**\n * Fires if a pointer (mouse/touch) becomes active.\n *\n * @event TransformControls#mouseDown\n * @type {Object}\n */\nconst _mouseDownEvent = { type: 'mouseDown', mode: null };\n\n/**\n * Fires if a pointer (mouse/touch) is no longer active.\n *\n * @event TransformControls#mouseUp\n * @type {Object}\n */\nconst _mouseUpEvent = { type: 'mouseUp', mode: null };\n\n/**\n * Fires if the controlled 3D object is changed.\n *\n * @event TransformControls#objectChange\n * @type {Object}\n */\nconst _objectChangeEvent = { type: 'objectChange' };\n\n/**\n * This class can be used to transform objects in 3D space by adapting a similar interaction model\n * of DCC tools like Blender. Unlike other controls, it is not intended to transform the scene's camera.\n *\n * `TransformControls` expects that its attached 3D object is part of the scene graph.\n *\n * @augments Controls\n * @three_import import { TransformControls } from 'three/addons/controls/TransformControls.js';\n */\nclass TransformControls extends Controls {\n\n\t/**\n\t * Constructs a new controls instance.\n\t *\n\t * @param {Camera} camera - The camera of the rendered scene.\n\t * @param {?HTMLElement} domElement - The HTML element used for event listeners.\n\t */\n\tconstructor( camera, domElement = null ) {\n\n\t\tsuper( undefined, domElement );\n\n\t\tconst root = new TransformControlsRoot( this );\n\t\tthis._root = root;\n\n\t\tconst gizmo = new TransformControlsGizmo();\n\t\tthis._gizmo = gizmo;\n\t\troot.add( gizmo );\n\n\t\tconst plane = new TransformControlsPlane();\n\t\tthis._plane = plane;\n\t\troot.add( plane );\n\n\t\tconst scope = this;\n\n\t\t// Defined getter, setter and store for a property\n\t\tfunction defineProperty( propName, defaultValue ) {\n\n\t\t\tlet propValue = defaultValue;\n\n\t\t\tObject.defineProperty( scope, propName, {\n\n\t\t\t\tget: function () {\n\n\t\t\t\t\treturn propValue !== undefined ? propValue : defaultValue;\n\n\t\t\t\t},\n\n\t\t\t\tset: function ( value ) {\n\n\t\t\t\t\tif ( propValue !== value ) {\n\n\t\t\t\t\t\tpropValue = value;\n\t\t\t\t\t\tplane[ propName ] = value;\n\t\t\t\t\t\tgizmo[ propName ] = value;\n\n\t\t\t\t\t\tscope.dispatchEvent( { type: propName + '-changed', value: value } );\n\t\t\t\t\t\tscope.dispatchEvent( _changeEvent );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} );\n\n\t\t\tscope[ propName ] = defaultValue;\n\t\t\tplane[ propName ] = defaultValue;\n\t\t\tgizmo[ propName ] = defaultValue;\n\n\t\t}\n\n\t\t// Define properties with getters/setter\n\t\t// Setting the defined property will automatically trigger change event\n\t\t// Defined properties are passed down to gizmo and plane\n\n\t\t/**\n\t\t * The camera of the rendered scene.\n\t\t *\n\t\t * @name TransformControls#camera\n\t\t * @type {Camera}\n\t\t */\n\t\tdefineProperty( 'camera', camera );\n\t\tdefineProperty( 'object', undefined );\n\t\tdefineProperty( 'enabled', true );\n\n\t\t/**\n\t\t * The current transformation axis.\n\t\t *\n\t\t * @name TransformControls#axis\n\t\t * @type {string}\n\t\t */\n\t\tdefineProperty( 'axis', null );\n\n\t\t/**\n\t\t * The current transformation axis.\n\t\t *\n\t\t * @name TransformControls#mode\n\t\t * @type {('translate'|'rotate'|'scale')}\n\t\t * @default 'translate'\n\t\t */\n\t\tdefineProperty( 'mode', 'translate' );\n\n\t\t/**\n\t\t * By default, 3D objects are continuously translated. If you set this property to a numeric\n\t\t * value (world units), you can define in which steps the 3D object should be translated.\n\t\t *\n\t\t * @name TransformControls#translationSnap\n\t\t * @type {?number}\n\t\t * @default null\n\t\t */\n\t\tdefineProperty( 'translationSnap', null );\n\n\t\t/**\n\t\t * By default, 3D objects are continuously rotated. If you set this property to a numeric\n\t\t * value (radians), you can define in which steps the 3D object should be rotated.\n\t\t *\n\t\t * @name TransformControls#rotationSnap\n\t\t * @type {?number}\n\t\t * @default null\n\t\t */\n\t\tdefineProperty( 'rotationSnap', null );\n\n\t\t/**\n\t\t * By default, 3D objects are continuously scaled. If you set this property to a numeric\n\t\t * value, you can define in which steps the 3D object should be scaled.\n\t\t *\n\t\t * @name TransformControls#scaleSnap\n\t\t * @type {?number}\n\t\t * @default null\n\t\t */\n\t\tdefineProperty( 'scaleSnap', null );\n\n\t\t/**\n\t\t * Defines in which coordinate space transformations should be performed.\n\t\t *\n\t\t * @name TransformControls#space\n\t\t * @type {('world'|'local')}\n\t\t * @default 'world'\n\t\t */\n\t\tdefineProperty( 'space', 'world' );\n\n\t\t/**\n\t\t * The size of the helper UI (axes/planes).\n\t\t *\n\t\t * @name TransformControls#size\n\t\t * @type {number}\n\t\t * @default 1\n\t\t */\n\t\tdefineProperty( 'size', 1 );\n\n\t\t/**\n\t\t * Whether dragging is currently performed or not.\n\t\t *\n\t\t * @name TransformControls#dragging\n\t\t * @type {boolean}\n\t\t * @readonly\n\t\t * @default false\n\t\t */\n\t\tdefineProperty( 'dragging', false );\n\n\t\t/**\n\t\t * Whether the x-axis helper should be visible or not.\n\t\t *\n\t\t * @name TransformControls#showX\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t */\n\t\tdefineProperty( 'showX', true );\n\n\t\t/**\n\t\t * Whether the y-axis helper should be visible or not.\n\t\t *\n\t\t * @name TransformControls#showY\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t */\n\t\tdefineProperty( 'showY', true );\n\n\t\t/**\n\t\t * Whether the z-axis helper should be visible or not.\n\t\t *\n\t\t * @name TransformControls#showZ\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t */\n\t\tdefineProperty( 'showZ', true );\n\n\t\t/**\n\t\t * Whether the xy-plane helper should be visible or not.\n\t\t *\n\t\t * @name TransformControls#showXY\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t */\n\t\tdefineProperty( 'showXY', true );\n\n\t\t/**\n\t\t * Whether the yz-plane helper should be visible or not.\n\t\t *\n\t\t * @name TransformControls#showYZ\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t */\n\t\tdefineProperty( 'showYZ', true );\n\n\t\t/**\n\t\t * Whether the xz-axis helper should be visible or not.\n\t\t *\n\t\t * @name TransformControls#showXZ\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t */\n\t\tdefineProperty( 'showXZ', true );\n\n\t\t/**\n\t\t * The minimum allowed X position during translation.\n\t\t *\n\t\t * @name TransformControls#minX\n\t\t * @type {number}\n\t\t * @default -Infinity\n\t\t */\n\t\tdefineProperty( 'minX', - Infinity );\n\n\t\t/**\n\t\t * The maximum allowed X position during translation.\n\t\t *\n\t\t * @name TransformControls#maxX\n\t\t * @type {number}\n\t\t * @default Infinity\n\t\t */\n\t\tdefineProperty( 'maxX', Infinity );\n\n\t\t/**\n\t\t * The minimum allowed y position during translation.\n\t\t *\n\t\t * @name TransformControls#minY\n\t\t * @type {number}\n\t\t * @default -Infinity\n\t\t */\n\t\tdefineProperty( 'minY', - Infinity );\n\n\t\t/**\n\t\t * The maximum allowed Y position during translation.\n\t\t *\n\t\t * @name TransformControls#maxY\n\t\t * @type {number}\n\t\t * @default Infinity\n\t\t */\n\t\tdefineProperty( 'maxY', Infinity );\n\n\t\t/**\n\t\t * The minimum allowed z position during translation.\n\t\t *\n\t\t * @name TransformControls#minZ\n\t\t * @type {number}\n\t\t * @default -Infinity\n\t\t */\n\t\tdefineProperty( 'minZ', - Infinity );\n\n\t\t/**\n\t\t * The maximum allowed Z position during translation.\n\t\t *\n\t\t * @name TransformControls#maxZ\n\t\t * @type {number}\n\t\t * @default Infinity\n\t\t */\n\t\tdefineProperty( 'maxZ', Infinity );\n\n\t\t// Reusable utility variables\n\n\t\tconst worldPosition = new Vector3();\n\t\tconst worldPositionStart = new Vector3();\n\t\tconst worldQuaternion = new Quaternion();\n\t\tconst worldQuaternionStart = new Quaternion();\n\t\tconst cameraPosition = new Vector3();\n\t\tconst cameraQuaternion = new Quaternion();\n\t\tconst pointStart = new Vector3();\n\t\tconst pointEnd = new Vector3();\n\t\tconst rotationAxis = new Vector3();\n\t\tconst rotationAngle = 0;\n\t\tconst eye = new Vector3();\n\n\t\t// TODO: remove properties unused in plane and gizmo\n\n\t\tdefineProperty( 'worldPosition', worldPosition );\n\t\tdefineProperty( 'worldPositionStart', worldPositionStart );\n\t\tdefineProperty( 'worldQuaternion', worldQuaternion );\n\t\tdefineProperty( 'worldQuaternionStart', worldQuaternionStart );\n\t\tdefineProperty( 'cameraPosition', cameraPosition );\n\t\tdefineProperty( 'cameraQuaternion', cameraQuaternion );\n\t\tdefineProperty( 'pointStart', pointStart );\n\t\tdefineProperty( 'pointEnd', pointEnd );\n\t\tdefineProperty( 'rotationAxis', rotationAxis );\n\t\tdefineProperty( 'rotationAngle', rotationAngle );\n\t\tdefineProperty( 'eye', eye );\n\n\t\tthis._offset = new Vector3();\n\t\tthis._startNorm = new Vector3();\n\t\tthis._endNorm = new Vector3();\n\t\tthis._cameraScale = new Vector3();\n\n\t\tthis._parentPosition = new Vector3();\n\t\tthis._parentQuaternion = new Quaternion();\n\t\tthis._parentQuaternionInv = new Quaternion();\n\t\tthis._parentScale = new Vector3();\n\n\t\tthis._worldScaleStart = new Vector3();\n\t\tthis._worldQuaternionInv = new Quaternion();\n\t\tthis._worldScale = new Vector3();\n\n\t\tthis._positionStart = new Vector3();\n\t\tthis._quaternionStart = new Quaternion();\n\t\tthis._scaleStart = new Vector3();\n\n\t\tthis._getPointer = getPointer.bind( this );\n\t\tthis._onPointerDown = onPointerDown.bind( this );\n\t\tthis._onPointerHover = onPointerHover.bind( this );\n\t\tthis._onPointerMove = onPointerMove.bind( this );\n\t\tthis._onPointerUp = onPointerUp.bind( this );\n\n\t\tif ( domElement !== null ) {\n\n\t\t\tthis.connect( domElement );\n\n\t\t}\n\n\t}\n\n\tconnect( element ) {\n\n\t\tsuper.connect( element );\n\n\t\tthis.domElement.addEventListener( 'pointerdown', this._onPointerDown );\n\t\tthis.domElement.addEventListener( 'pointermove', this._onPointerHover );\n\t\tthis.domElement.addEventListener( 'pointerup', this._onPointerUp );\n\n\t\tthis.domElement.style.touchAction = 'none'; // Disable touch scroll\n\n\t}\n\n\tdisconnect() {\n\n\t\tthis.domElement.removeEventListener( 'pointerdown', this._onPointerDown );\n\t\tthis.domElement.removeEventListener( 'pointermove', this._onPointerHover );\n\t\tthis.domElement.removeEventListener( 'pointermove', this._onPointerMove );\n\t\tthis.domElement.removeEventListener( 'pointerup', this._onPointerUp );\n\n\t\tthis.domElement.style.touchAction = ''; // Restore touch scroll\n\n\t}\n\n\t/**\n\t * Returns the visual representation of the controls. Add the helper to your scene to\n\t * visually transform the attached 3D object.\n\t *\n\t * @return {TransformControlsRoot} The helper.\n\t */\n\tgetHelper() {\n\n\t\treturn this._root;\n\n\t}\n\n\tpointerHover( pointer ) {\n\n\t\tif ( this.object === undefined || this.dragging === true ) return;\n\n\t\tif ( pointer !== null ) _raycaster.setFromCamera( pointer, this.camera );\n\n\t\tconst intersect = intersectObjectWithRay( this._gizmo.picker[ this.mode ], _raycaster );\n\n\t\tif ( intersect ) {\n\n\t\t\tthis.axis = intersect.object.name;\n\n\t\t} else {\n\n\t\t\tthis.axis = null;\n\n\t\t}\n\n\t}\n\n\tpointerDown( pointer ) {\n\n\t\tif ( this.object === undefined || this.dragging === true || ( pointer != null && pointer.button !== 0 ) ) return;\n\n\t\tif ( this.axis !== null ) {\n\n\t\t\tif ( pointer !== null ) _raycaster.setFromCamera( pointer, this.camera );\n\n\t\t\tconst planeIntersect = intersectObjectWithRay( this._plane, _raycaster, true );\n\n\t\t\tif ( planeIntersect ) {\n\n\t\t\t\tthis.object.updateMatrixWorld();\n\t\t\t\tthis.object.parent.updateMatrixWorld();\n\n\t\t\t\tthis._positionStart.copy( this.object.position );\n\t\t\t\tthis._quaternionStart.copy( this.object.quaternion );\n\t\t\t\tthis._scaleStart.copy( this.object.scale );\n\n\t\t\t\tthis.object.matrixWorld.decompose( this.worldPositionStart, this.worldQuaternionStart, this._worldScaleStart );\n\n\t\t\t\tthis.pointStart.copy( planeIntersect.point ).sub( this.worldPositionStart );\n\n\t\t\t}\n\n\t\t\tthis.dragging = true;\n\t\t\t_mouseDownEvent.mode = this.mode;\n\t\t\tthis.dispatchEvent( _mouseDownEvent );\n\n\t\t}\n\n\t}\n\n\tpointerMove( pointer ) {\n\n\t\tconst axis = this.axis;\n\t\tconst mode = this.mode;\n\t\tconst object = this.object;\n\t\tlet space = this.space;\n\n\t\tif ( mode === 'scale' ) {\n\n\t\t\tspace = 'local';\n\n\t\t} else if ( axis === 'E' || axis === 'XYZE' || axis === 'XYZ' ) {\n\n\t\t\tspace = 'world';\n\n\t\t}\n\n\t\tif ( object === undefined || axis === null || this.dragging === false || ( pointer !== null && pointer.button !== - 1 ) ) return;\n\n\t\tif ( pointer !== null ) _raycaster.setFromCamera( pointer, this.camera );\n\n\t\tconst planeIntersect = intersectObjectWithRay( this._plane, _raycaster, true );\n\n\t\tif ( ! planeIntersect ) return;\n\n\t\tthis.pointEnd.copy( planeIntersect.point ).sub( this.worldPositionStart );\n\n\t\tif ( mode === 'translate' ) {\n\n\t\t\t// Apply translate\n\n\t\t\tthis._offset.copy( this.pointEnd ).sub( this.pointStart );\n\n\t\t\tif ( space === 'local' && axis !== 'XYZ' ) {\n\n\t\t\t\tthis._offset.applyQuaternion( this._worldQuaternionInv );\n\n\t\t\t}\n\n\t\t\tif ( axis.indexOf( 'X' ) === - 1 ) this._offset.x = 0;\n\t\t\tif ( axis.indexOf( 'Y' ) === - 1 ) this._offset.y = 0;\n\t\t\tif ( axis.indexOf( 'Z' ) === - 1 ) this._offset.z = 0;\n\n\t\t\tif ( space === 'local' && axis !== 'XYZ' ) {\n\n\t\t\t\tthis._offset.applyQuaternion( this._quaternionStart ).divide( this._parentScale );\n\n\t\t\t} else {\n\n\t\t\t\tthis._offset.applyQuaternion( this._parentQuaternionInv ).divide( this._parentScale );\n\n\t\t\t}\n\n\t\t\tobject.position.copy( this._offset ).add( this._positionStart );\n\n\t\t\t// Apply translation snap\n\n\t\t\tif ( this.translationSnap ) {\n\n\t\t\t\tif ( space === 'local' ) {\n\n\t\t\t\t\tobject.position.applyQuaternion( _tempQuaternion.copy( this._quaternionStart ).invert() );\n\n\t\t\t\t\tif ( axis.search( 'X' ) !== - 1 ) {\n\n\t\t\t\t\t\tobject.position.x = Math.round( object.position.x / this.translationSnap ) * this.translationSnap;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( axis.search( 'Y' ) !== - 1 ) {\n\n\t\t\t\t\t\tobject.position.y = Math.round( object.position.y / this.translationSnap ) * this.translationSnap;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( axis.search( 'Z' ) !== - 1 ) {\n\n\t\t\t\t\t\tobject.position.z = Math.round( object.position.z / this.translationSnap ) * this.translationSnap;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tobject.position.applyQuaternion( this._quaternionStart );\n\n\t\t\t\t}\n\n\t\t\t\tif ( space === 'world' ) {\n\n\t\t\t\t\tif ( object.parent ) {\n\n\t\t\t\t\t\tobject.position.add( _tempVector.setFromMatrixPosition( object.parent.matrixWorld ) );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( axis.search( 'X' ) !== - 1 ) {\n\n\t\t\t\t\t\tobject.position.x = Math.round( object.position.x / this.translationSnap ) * this.translationSnap;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( axis.search( 'Y' ) !== - 1 ) {\n\n\t\t\t\t\t\tobject.position.y = Math.round( object.position.y / this.translationSnap ) * this.translationSnap;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( axis.search( 'Z' ) !== - 1 ) {\n\n\t\t\t\t\t\tobject.position.z = Math.round( object.position.z / this.translationSnap ) * this.translationSnap;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( object.parent ) {\n\n\t\t\t\t\t\tobject.position.sub( _tempVector.setFromMatrixPosition( object.parent.matrixWorld ) );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tobject.position.x = Math.max( this.minX, Math.min( this.maxX, object.position.x ) );\n\t\t\tobject.position.y = Math.max( this.minY, Math.min( this.maxY, object.position.y ) );\n\t\t\tobject.position.z = Math.max( this.minZ, Math.min( this.maxZ, object.position.z ) );\n\n\t\t} else if ( mode === 'scale' ) {\n\n\t\t\tif ( axis.search( 'XYZ' ) !== - 1 ) {\n\n\t\t\t\tlet d = this.pointEnd.length() / this.pointStart.length();\n\n\t\t\t\tif ( this.pointEnd.dot( this.pointStart ) < 0 ) d *= - 1;\n\n\t\t\t\t_tempVector2.set( d, d, d );\n\n\t\t\t} else {\n\n\t\t\t\t_tempVector.copy( this.pointStart );\n\t\t\t\t_tempVector2.copy( this.pointEnd );\n\n\t\t\t\t_tempVector.applyQuaternion( this._worldQuaternionInv );\n\t\t\t\t_tempVector2.applyQuaternion( this._worldQuaternionInv );\n\n\t\t\t\t_tempVector2.divide( _tempVector );\n\n\t\t\t\tif ( axis.search( 'X' ) === - 1 ) {\n\n\t\t\t\t\t_tempVector2.x = 1;\n\n\t\t\t\t}\n\n\t\t\t\tif ( axis.search( 'Y' ) === - 1 ) {\n\n\t\t\t\t\t_tempVector2.y = 1;\n\n\t\t\t\t}\n\n\t\t\t\tif ( axis.search( 'Z' ) === - 1 ) {\n\n\t\t\t\t\t_tempVector2.z = 1;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// Apply scale\n\n\t\t\tobject.scale.copy( this._scaleStart ).multiply( _tempVector2 );\n\n\t\t\tif ( this.scaleSnap ) {\n\n\t\t\t\tif ( axis.search( 'X' ) !== - 1 ) {\n\n\t\t\t\t\tobject.scale.x = Math.round( object.scale.x / this.scaleSnap ) * this.scaleSnap || this.scaleSnap;\n\n\t\t\t\t}\n\n\t\t\t\tif ( axis.search( 'Y' ) !== - 1 ) {\n\n\t\t\t\t\tobject.scale.y = Math.round( object.scale.y / this.scaleSnap ) * this.scaleSnap || this.scaleSnap;\n\n\t\t\t\t}\n\n\t\t\t\tif ( axis.search( 'Z' ) !== - 1 ) {\n\n\t\t\t\t\tobject.scale.z = Math.round( object.scale.z / this.scaleSnap ) * this.scaleSnap || this.scaleSnap;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else if ( mode === 'rotate' ) {\n\n\t\t\tthis._offset.copy( this.pointEnd ).sub( this.pointStart );\n\n\t\t\tconst ROTATION_SPEED = 20 / this.worldPosition.distanceTo( _tempVector.setFromMatrixPosition( this.camera.matrixWorld ) );\n\n\t\t\tlet _inPlaneRotation = false;\n\n\t\t\tif ( axis === 'XYZE' ) {\n\n\t\t\t\tthis.rotationAxis.copy( this._offset ).cross( this.eye ).normalize();\n\t\t\t\tthis.rotationAngle = this._offset.dot( _tempVector.copy( this.rotationAxis ).cross( this.eye ) ) * ROTATION_SPEED;\n\n\t\t\t} else if ( axis === 'X' || axis === 'Y' || axis === 'Z' ) {\n\n\t\t\t\tthis.rotationAxis.copy( _unit[ axis ] );\n\n\t\t\t\t_tempVector.copy( _unit[ axis ] );\n\n\t\t\t\tif ( space === 'local' ) {\n\n\t\t\t\t\t_tempVector.applyQuaternion( this.worldQuaternion );\n\n\t\t\t\t}\n\n\t\t\t\t_tempVector.cross( this.eye );\n\n\t\t\t\t// When _tempVector is 0 after cross with this.eye the vectors are parallel and should use in-plane rotation logic.\n\t\t\t\tif ( _tempVector.length() === 0 ) {\n\n\t\t\t\t\t_inPlaneRotation = true;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthis.rotationAngle = this._offset.dot( _tempVector.normalize() ) * ROTATION_SPEED;\n\n\t\t\t\t}\n\n\n\t\t\t}\n\n\t\t\tif ( axis === 'E' || _inPlaneRotation ) {\n\n\t\t\t\tthis.rotationAxis.copy( this.eye );\n\t\t\t\tthis.rotationAngle = this.pointEnd.angleTo( this.pointStart );\n\n\t\t\t\tthis._startNorm.copy( this.pointStart ).normalize();\n\t\t\t\tthis._endNorm.copy( this.pointEnd ).normalize();\n\n\t\t\t\tthis.rotationAngle *= ( this._endNorm.cross( this._startNorm ).dot( this.eye ) < 0 ? 1 : - 1 );\n\n\t\t\t}\n\n\t\t\t// Apply rotation snap\n\n\t\t\tif ( this.rotationSnap ) this.rotationAngle = Math.round( this.rotationAngle / this.rotationSnap ) * this.rotationSnap;\n\n\t\t\t// Apply rotate\n\t\t\tif ( space === 'local' && axis !== 'E' && axis !== 'XYZE' ) {\n\n\t\t\t\tobject.quaternion.copy( this._quaternionStart );\n\t\t\t\tobject.quaternion.multiply( _tempQuaternion.setFromAxisAngle( this.rotationAxis, this.rotationAngle ) ).normalize();\n\n\t\t\t} else {\n\n\t\t\t\tthis.rotationAxis.applyQuaternion( this._parentQuaternionInv );\n\t\t\t\tobject.quaternion.copy( _tempQuaternion.setFromAxisAngle( this.rotationAxis, this.rotationAngle ) );\n\t\t\t\tobject.quaternion.multiply( this._quaternionStart ).normalize();\n\n\t\t\t}\n\n\t\t}\n\n\t\tthis.dispatchEvent( _changeEvent );\n\t\tthis.dispatchEvent( _objectChangeEvent );\n\n\t}\n\n\tpointerUp( pointer ) {\n\n\t\tif ( pointer !== null && pointer.button !== 0 ) return;\n\n\t\tif ( this.dragging && ( this.axis !== null ) ) {\n\n\t\t\t_mouseUpEvent.mode = this.mode;\n\t\t\tthis.dispatchEvent( _mouseUpEvent );\n\n\t\t}\n\n\t\tthis.dragging = false;\n\t\tthis.axis = null;\n\n\t}\n\n\tdispose() {\n\n\t\tthis.disconnect();\n\n\t\tthis._root.dispose();\n\n\t}\n\n\t/**\n\t * Sets the 3D object that should be transformed and ensures the controls UI is visible.\n\t *\n\t * @param {Object3D} object - The 3D object that should be transformed.\n\t * @return {TransformControls} A reference to this controls.\n\t */\n\tattach( object ) {\n\n\t\tthis.object = object;\n\t\tthis._root.visible = true;\n\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Removes the current 3D object from the controls and makes the helper UI invisible.\n\t *\n\t * @return {TransformControls} A reference to this controls.\n\t */\n\tdetach() {\n\n\t\tthis.object = undefined;\n\t\tthis.axis = null;\n\n\t\tthis._root.visible = false;\n\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Resets the object's position, rotation and scale to when the current transform began.\n\t */\n\treset() {\n\n\t\tif ( ! this.enabled ) return;\n\n\t\tif ( this.dragging ) {\n\n\t\t\tthis.object.position.copy( this._positionStart );\n\t\t\tthis.object.quaternion.copy( this._quaternionStart );\n\t\t\tthis.object.scale.copy( this._scaleStart );\n\n\t\t\tthis.dispatchEvent( _changeEvent );\n\t\t\tthis.dispatchEvent( _objectChangeEvent );\n\n\t\t\tthis.pointStart.copy( this.pointEnd );\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Returns the raycaster that is used for user interaction. This object is shared between all\n\t * instances of `TransformControls`.\n\t *\n\t * @returns {Raycaster} The internal raycaster.\n\t */\n\tgetRaycaster() {\n\n\t\treturn _raycaster;\n\n\t}\n\n\t/**\n\t * Returns the transformation mode.\n\t *\n\t * @returns {'translate'|'rotate'|'scale'} The transformation mode.\n\t */\n\tgetMode() {\n\n\t\treturn this.mode;\n\n\t}\n\n\t/**\n\t * Sets the given transformation mode.\n\t *\n\t * @param {'translate'|'rotate'|'scale'} mode - The transformation mode to set.\n\t */\n\tsetMode( mode ) {\n\n\t\tthis.mode = mode;\n\n\t}\n\n\t/**\n\t * Sets the translation snap.\n\t *\n\t * @param {?number} translationSnap - The translation snap to set.\n\t */\n\tsetTranslationSnap( translationSnap ) {\n\n\t\tthis.translationSnap = translationSnap;\n\n\t}\n\n\t/**\n\t * Sets the rotation snap.\n\t *\n\t * @param {?number} rotationSnap - The rotation snap to set.\n\t */\n\tsetRotationSnap( rotationSnap ) {\n\n\t\tthis.rotationSnap = rotationSnap;\n\n\t}\n\n\t/**\n\t * Sets the scale snap.\n\t *\n\t * @param {?number} scaleSnap - The scale snap to set.\n\t */\n\tsetScaleSnap( scaleSnap ) {\n\n\t\tthis.scaleSnap = scaleSnap;\n\n\t}\n\n\t/**\n\t * Sets the size of the helper UI.\n\t *\n\t * @param {number} size - The size to set.\n\t */\n\tsetSize( size ) {\n\n\t\tthis.size = size;\n\n\t}\n\n\t/**\n\t * Sets the coordinate space in which transformations are applied.\n\t *\n\t * @param {'world'|'local'} space - The space to set.\n\t */\n\tsetSpace( space ) {\n\n\t\tthis.space = space;\n\n\t}\n\n\t/**\n\t * Sets the colors of the control's gizmo.\n\t *\n\t * @param {number|Color|string} xAxis - The x-axis color.\n\t * @param {number|Color|string} yAxis - The y-axis color.\n\t * @param {number|Color|string} zAxis - The z-axis color.\n\t * @param {number|Color|string} active - The color for active elements.\n\t */\n\tsetColors( xAxis, yAxis, zAxis, active ) {\n\n\t\tconst materialLib = this._gizmo.materialLib;\n\n\t\tmaterialLib.xAxis.color.set( xAxis );\n\t\tmaterialLib.yAxis.color.set( yAxis );\n\t\tmaterialLib.zAxis.color.set( zAxis );\n\t\tmaterialLib.active.color.set( active );\n\t\tmaterialLib.xAxisTransparent.color.set( xAxis );\n\t\tmaterialLib.yAxisTransparent.color.set( yAxis );\n\t\tmaterialLib.zAxisTransparent.color.set( zAxis );\n\t\tmaterialLib.activeTransparent.color.set( active );\n\n\t\t// update color caches\n\n\t\tif ( materialLib.xAxis._color ) materialLib.xAxis._color.set( xAxis );\n\t\tif ( materialLib.yAxis._color ) materialLib.yAxis._color.set( yAxis );\n\t\tif ( materialLib.zAxis._color ) materialLib.zAxis._color.set( zAxis );\n\t\tif ( materialLib.active._color ) materialLib.active._color.set( active );\n\t\tif ( materialLib.xAxisTransparent._color ) materialLib.xAxisTransparent._color.set( xAxis );\n\t\tif ( materialLib.yAxisTransparent._color ) materialLib.yAxisTransparent._color.set( yAxis );\n\t\tif ( materialLib.zAxisTransparent._color ) materialLib.zAxisTransparent._color.set( zAxis );\n\t\tif ( materialLib.activeTransparent._color ) materialLib.activeTransparent._color.set( active );\n\n\t}\n\n}\n\n// mouse / touch event handlers\n\nfunction getPointer( event ) {\n\n\tif ( this.domElement.ownerDocument.pointerLockElement ) {\n\n\t\treturn {\n\t\t\tx: 0,\n\t\t\ty: 0,\n\t\t\tbutton: event.button\n\t\t};\n\n\t} else {\n\n\t\tconst rect = this.domElement.getBoundingClientRect();\n\n\t\treturn {\n\t\t\tx: ( event.clientX - rect.left ) / rect.width * 2 - 1,\n\t\t\ty: - ( event.clientY - rect.top ) / rect.height * 2 + 1,\n\t\t\tbutton: event.button\n\t\t};\n\n\t}\n\n}\n\nfunction onPointerHover( event ) {\n\n\tif ( ! this.enabled ) return;\n\n\tswitch ( event.pointerType ) {\n\n\t\tcase 'mouse':\n\t\tcase 'pen':\n\t\t\tthis.pointerHover( this._getPointer( event ) );\n\t\t\tbreak;\n\n\t}\n\n}\n\nfunction onPointerDown( event ) {\n\n\tif ( ! this.enabled ) return;\n\n\tif ( ! document.pointerLockElement ) {\n\n\t\tthis.domElement.setPointerCapture( event.pointerId );\n\n\t}\n\n\tthis.domElement.addEventListener( 'pointermove', this._onPointerMove );\n\n\tthis.pointerHover( this._getPointer( event ) );\n\tthis.pointerDown( this._getPointer( event ) );\n\n}\n\nfunction onPointerMove( event ) {\n\n\tif ( ! this.enabled ) return;\n\n\tthis.pointerMove( this._getPointer( event ) );\n\n}\n\nfunction onPointerUp( event ) {\n\n\tif ( ! this.enabled ) return;\n\n\tthis.domElement.releasePointerCapture( event.pointerId );\n\n\tthis.domElement.removeEventListener( 'pointermove', this._onPointerMove );\n\n\tthis.pointerUp( this._getPointer( event ) );\n\n}\n\nfunction intersectObjectWithRay( object, raycaster, includeInvisible ) {\n\n\tconst allIntersections = raycaster.intersectObject( object, true );\n\n\tfor ( let i = 0; i < allIntersections.length; i ++ ) {\n\n\t\tif ( allIntersections[ i ].object.visible || includeInvisible ) {\n\n\t\t\treturn allIntersections[ i ];\n\n\t\t}\n\n\t}\n\n\treturn false;\n\n}\n\n//\n\n// Reusable utility variables\n\nconst _tempEuler = new Euler();\nconst _alignVector = new Vector3( 0, 1, 0 );\nconst _zeroVector = new Vector3( 0, 0, 0 );\nconst _lookAtMatrix = new Matrix4();\nconst _tempQuaternion2 = new Quaternion();\nconst _identityQuaternion = new Quaternion();\nconst _dirVector = new Vector3();\nconst _tempMatrix = new Matrix4();\n\nconst _unitX = new Vector3( 1, 0, 0 );\nconst _unitY = new Vector3( 0, 1, 0 );\nconst _unitZ = new Vector3( 0, 0, 1 );\n\nconst _v1 = new Vector3();\nconst _v2 = new Vector3();\nconst _v3 = new Vector3();\n\nclass TransformControlsRoot extends Object3D {\n\n\tconstructor( controls ) {\n\n\t\tsuper();\n\n\t\tthis.isTransformControlsRoot = true;\n\n\t\tthis.controls = controls;\n\t\tthis.visible = false;\n\n\t}\n\n\t// updateMatrixWorld updates key transformation variables\n\tupdateMatrixWorld( force ) {\n\n\t\tconst controls = this.controls;\n\n\t\tif ( controls.object !== undefined ) {\n\n\t\t\tcontrols.object.updateMatrixWorld();\n\n\t\t\tif ( controls.object.parent === null ) {\n\n\t\t\t\tconsole.error( 'TransformControls: The attached 3D object must be a part of the scene graph.' );\n\n\t\t\t} else {\n\n\t\t\t\tcontrols.object.parent.matrixWorld.decompose( controls._parentPosition, controls._parentQuaternion, controls._parentScale );\n\n\t\t\t}\n\n\t\t\tcontrols.object.matrixWorld.decompose( controls.worldPosition, controls.worldQuaternion, controls._worldScale );\n\n\t\t\tcontrols._parentQuaternionInv.copy( controls._parentQuaternion ).invert();\n\t\t\tcontrols._worldQuaternionInv.copy( controls.worldQuaternion ).invert();\n\n\t\t}\n\n\t\tcontrols.camera.updateMatrixWorld();\n\t\tcontrols.camera.matrixWorld.decompose( controls.cameraPosition, controls.cameraQuaternion, controls._cameraScale );\n\n\t\tif ( controls.camera.isOrthographicCamera ) {\n\n\t\t\tcontrols.camera.getWorldDirection( controls.eye ).negate();\n\n\t\t} else {\n\n\t\t\tcontrols.eye.copy( controls.cameraPosition ).sub( controls.worldPosition ).normalize();\n\n\t\t}\n\n\t\tsuper.updateMatrixWorld( force );\n\n\t}\n\n\tdispose() {\n\n\t\tthis.traverse( function ( child ) {\n\n\t\t\tif ( child.geometry ) child.geometry.dispose();\n\t\t\tif ( child.material ) child.material.dispose();\n\n\t\t} );\n\n\t}\n\n}\n\nclass TransformControlsGizmo extends Object3D {\n\n\tconstructor() {\n\n\t\tsuper();\n\n\t\tthis.isTransformControlsGizmo = true;\n\n\t\tthis.type = 'TransformControlsGizmo';\n\n\t\t// shared materials\n\n\t\tconst gizmoMaterial = new MeshBasicMaterial( {\n\t\t\tdepthTest: false,\n\t\t\tdepthWrite: false,\n\t\t\tfog: false,\n\t\t\ttoneMapped: false,\n\t\t\ttransparent: true\n\t\t} );\n\n\t\tconst gizmoLineMaterial = new LineBasicMaterial( {\n\t\t\tdepthTest: false,\n\t\t\tdepthWrite: false,\n\t\t\tfog: false,\n\t\t\ttoneMapped: false,\n\t\t\ttransparent: true\n\t\t} );\n\n\t\t// Make unique material for each axis/color\n\n\t\tconst matInvisible = gizmoMaterial.clone();\n\t\tmatInvisible.opacity = 0.15;\n\n\t\tconst matHelper = gizmoLineMaterial.clone();\n\t\tmatHelper.opacity = 0.5;\n\n\t\tconst matRed = gizmoMaterial.clone();\n\t\tmatRed.color.setHex( 0xff0000 );\n\n\t\tconst matGreen = gizmoMaterial.clone();\n\t\tmatGreen.color.setHex( 0x00ff00 );\n\n\t\tconst matBlue = gizmoMaterial.clone();\n\t\tmatBlue.color.setHex( 0x0000ff );\n\n\t\tconst matRedTransparent = gizmoMaterial.clone();\n\t\tmatRedTransparent.color.setHex( 0xff0000 );\n\t\tmatRedTransparent.opacity = 0.5;\n\n\t\tconst matGreenTransparent = gizmoMaterial.clone();\n\t\tmatGreenTransparent.color.setHex( 0x00ff00 );\n\t\tmatGreenTransparent.opacity = 0.5;\n\n\t\tconst matBlueTransparent = gizmoMaterial.clone();\n\t\tmatBlueTransparent.color.setHex( 0x0000ff );\n\t\tmatBlueTransparent.opacity = 0.5;\n\n\t\tconst matWhiteTransparent = gizmoMaterial.clone();\n\t\tmatWhiteTransparent.opacity = 0.25;\n\n\t\tconst matYellowTransparent = gizmoMaterial.clone();\n\t\tmatYellowTransparent.color.setHex( 0xffff00 );\n\t\tmatYellowTransparent.opacity = 0.25;\n\n\t\tconst matYellow = gizmoMaterial.clone();\n\t\tmatYellow.color.setHex( 0xffff00 );\n\n\t\tconst matGray = gizmoMaterial.clone();\n\t\tmatGray.color.setHex( 0x787878 );\n\n\t\t// materials in the below property are configurable via setColors()\n\n\t\tthis.materialLib = {\n\t\t\txAxis: matRed,\n\t\t\tyAxis: matGreen,\n\t\t\tzAxis: matBlue,\n\t\t\tactive: matYellow,\n\t\t\txAxisTransparent: matRedTransparent,\n\t\t\tyAxisTransparent: matGreenTransparent,\n\t\t\tzAxisTransparent: matBlueTransparent,\n\t\t\tactiveTransparent: matYellowTransparent\n\t\t};\n\n\t\t// reusable geometry\n\n\t\tconst arrowGeometry = new CylinderGeometry( 0, 0.04, 0.1, 12 );\n\t\tarrowGeometry.translate( 0, 0.05, 0 );\n\n\t\tconst scaleHandleGeometry = new BoxGeometry( 0.08, 0.08, 0.08 );\n\t\tscaleHandleGeometry.translate( 0, 0.04, 0 );\n\n\t\tconst lineGeometry = new BufferGeometry();\n\t\tlineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0,\t1, 0, 0 ], 3 ) );\n\n\t\tconst lineGeometry2 = new CylinderGeometry( 0.0075, 0.0075, 0.5, 3 );\n\t\tlineGeometry2.translate( 0, 0.25, 0 );\n\n\t\tfunction CircleGeometry( radius, arc ) {\n\n\t\t\tconst geometry = new TorusGeometry( radius, 0.0075, 3, 64, arc * Math.PI * 2 );\n\t\t\tgeometry.rotateY( Math.PI / 2 );\n\t\t\tgeometry.rotateX( Math.PI / 2 );\n\t\t\treturn geometry;\n\n\t\t}\n\n\t\t// Special geometry for transform helper. If scaled with position vector it spans from [0,0,0] to position\n\n\t\tfunction TranslateHelperGeometry() {\n\n\t\t\tconst geometry = new BufferGeometry();\n\n\t\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 1, 1, 1 ], 3 ) );\n\n\t\t\treturn geometry;\n\n\t\t}\n\n\t\t// Gizmo definitions - custom hierarchy definitions for setupGizmo() function\n\n\t\tconst gizmoTranslate = {\n\t\t\tX: [\n\t\t\t\t[ new Mesh( arrowGeometry, matRed ), [ 0.5, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],\n\t\t\t\t[ new Mesh( arrowGeometry, matRed ), [ - 0.5, 0, 0 ], [ 0, 0, Math.PI / 2 ]],\n\t\t\t\t[ new Mesh( lineGeometry2, matRed ), [ 0, 0, 0 ], [ 0, 0, - Math.PI / 2 ]]\n\t\t\t],\n\t\t\tY: [\n\t\t\t\t[ new Mesh( arrowGeometry, matGreen ), [ 0, 0.5, 0 ]],\n\t\t\t\t[ new Mesh( arrowGeometry, matGreen ), [ 0, - 0.5, 0 ], [ Math.PI, 0, 0 ]],\n\t\t\t\t[ new Mesh( lineGeometry2, matGreen ) ]\n\t\t\t],\n\t\t\tZ: [\n\t\t\t\t[ new Mesh( arrowGeometry, matBlue ), [ 0, 0, 0.5 ], [ Math.PI / 2, 0, 0 ]],\n\t\t\t\t[ new Mesh( arrowGeometry, matBlue ), [ 0, 0, - 0.5 ], [ - Math.PI / 2, 0, 0 ]],\n\t\t\t\t[ new Mesh( lineGeometry2, matBlue ), null, [ Math.PI / 2, 0, 0 ]]\n\t\t\t],\n\t\t\tXYZ: [\n\t\t\t\t[ new Mesh( new OctahedronGeometry( 0.1, 0 ), matWhiteTransparent ), [ 0, 0, 0 ]]\n\t\t\t],\n\t\t\tXY: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.15, 0.15, 0.01 ), matBlueTransparent ), [ 0.15, 0.15, 0 ]]\n\t\t\t],\n\t\t\tYZ: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.15, 0.15, 0.01 ), matRedTransparent ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ]]\n\t\t\t],\n\t\t\tXZ: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.15, 0.15, 0.01 ), matGreenTransparent ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ]]\n\t\t\t]\n\t\t};\n\n\t\tconst pickerTranslate = {\n\t\t\tX: [\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0.3, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ - 0.3, 0, 0 ], [ 0, 0, Math.PI / 2 ]]\n\t\t\t],\n\t\t\tY: [\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0.3, 0 ]],\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, - 0.3, 0 ], [ 0, 0, Math.PI ]]\n\t\t\t],\n\t\t\tZ: [\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0, 0.3 ], [ Math.PI / 2, 0, 0 ]],\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0, - 0.3 ], [ - Math.PI / 2, 0, 0 ]]\n\t\t\t],\n\t\t\tXYZ: [\n\t\t\t\t[ new Mesh( new OctahedronGeometry( 0.2, 0 ), matInvisible ) ]\n\t\t\t],\n\t\t\tXY: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0.15, 0.15, 0 ]]\n\t\t\t],\n\t\t\tYZ: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ]]\n\t\t\t],\n\t\t\tXZ: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ]]\n\t\t\t]\n\t\t};\n\n\t\tconst helperTranslate = {\n\t\t\tSTART: [\n\t\t\t\t[ new Mesh( new OctahedronGeometry( 0.01, 2 ), matHelper ), null, null, null, 'helper' ]\n\t\t\t],\n\t\t\tEND: [\n\t\t\t\t[ new Mesh( new OctahedronGeometry( 0.01, 2 ), matHelper ), null, null, null, 'helper' ]\n\t\t\t],\n\t\t\tDELTA: [\n\t\t\t\t[ new Line( TranslateHelperGeometry(), matHelper ), null, null, null, 'helper' ]\n\t\t\t],\n\t\t\tX: [\n\t\t\t\t[ new Line( lineGeometry, matHelper ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]\n\t\t\t],\n\t\t\tY: [\n\t\t\t\t[ new Line( lineGeometry, matHelper ), [ 0, - 1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], 'helper' ]\n\t\t\t],\n\t\t\tZ: [\n\t\t\t\t[ new Line( lineGeometry, matHelper ), [ 0, 0, - 1e3 ], [ 0, - Math.PI / 2, 0 ], [ 1e6, 1, 1 ], 'helper' ]\n\t\t\t]\n\t\t};\n\n\t\tconst gizmoRotate = {\n\t\t\tXYZE: [\n\t\t\t\t[ new Mesh( CircleGeometry( 0.5, 1 ), matGray ), null, [ 0, Math.PI / 2, 0 ]]\n\t\t\t],\n\t\t\tX: [\n\t\t\t\t[ new Mesh( CircleGeometry( 0.5, 0.5 ), matRed ) ]\n\t\t\t],\n\t\t\tY: [\n\t\t\t\t[ new Mesh( CircleGeometry( 0.5, 0.5 ), matGreen ), null, [ 0, 0, - Math.PI / 2 ]]\n\t\t\t],\n\t\t\tZ: [\n\t\t\t\t[ new Mesh( CircleGeometry( 0.5, 0.5 ), matBlue ), null, [ 0, Math.PI / 2, 0 ]]\n\t\t\t],\n\t\t\tE: [\n\t\t\t\t[ new Mesh( CircleGeometry( 0.75, 1 ), matYellowTransparent ), null, [ 0, Math.PI / 2, 0 ]]\n\t\t\t]\n\t\t};\n\n\t\tconst helperRotate = {\n\t\t\tAXIS: [\n\t\t\t\t[ new Line( lineGeometry, matHelper ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]\n\t\t\t]\n\t\t};\n\n\t\tconst pickerRotate = {\n\t\t\tXYZE: [\n\t\t\t\t[ new Mesh( new SphereGeometry( 0.25, 10, 8 ), matInvisible ) ]\n\t\t\t],\n\t\t\tX: [\n\t\t\t\t[ new Mesh( new TorusGeometry( 0.5, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ 0, - Math.PI / 2, - Math.PI / 2 ]],\n\t\t\t],\n\t\t\tY: [\n\t\t\t\t[ new Mesh( new TorusGeometry( 0.5, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ Math.PI / 2, 0, 0 ]],\n\t\t\t],\n\t\t\tZ: [\n\t\t\t\t[ new Mesh( new TorusGeometry( 0.5, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],\n\t\t\t],\n\t\t\tE: [\n\t\t\t\t[ new Mesh( new TorusGeometry( 0.75, 0.1, 2, 24 ), matInvisible ) ]\n\t\t\t]\n\t\t};\n\n\t\tconst gizmoScale = {\n\t\t\tX: [\n\t\t\t\t[ new Mesh( scaleHandleGeometry, matRed ), [ 0.5, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],\n\t\t\t\t[ new Mesh( lineGeometry2, matRed ), [ 0, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],\n\t\t\t\t[ new Mesh( scaleHandleGeometry, matRed ), [ - 0.5, 0, 0 ], [ 0, 0, Math.PI / 2 ]],\n\t\t\t],\n\t\t\tY: [\n\t\t\t\t[ new Mesh( scaleHandleGeometry, matGreen ), [ 0, 0.5, 0 ]],\n\t\t\t\t[ new Mesh( lineGeometry2, matGreen ) ],\n\t\t\t\t[ new Mesh( scaleHandleGeometry, matGreen ), [ 0, - 0.5, 0 ], [ 0, 0, Math.PI ]],\n\t\t\t],\n\t\t\tZ: [\n\t\t\t\t[ new Mesh( scaleHandleGeometry, matBlue ), [ 0, 0, 0.5 ], [ Math.PI / 2, 0, 0 ]],\n\t\t\t\t[ new Mesh( lineGeometry2, matBlue ), [ 0, 0, 0 ], [ Math.PI / 2, 0, 0 ]],\n\t\t\t\t[ new Mesh( scaleHandleGeometry, matBlue ), [ 0, 0, - 0.5 ], [ - Math.PI / 2, 0, 0 ]]\n\t\t\t],\n\t\t\tXY: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.15, 0.15, 0.01 ), matBlueTransparent ), [ 0.15, 0.15, 0 ]]\n\t\t\t],\n\t\t\tYZ: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.15, 0.15, 0.01 ), matRedTransparent ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ]]\n\t\t\t],\n\t\t\tXZ: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.15, 0.15, 0.01 ), matGreenTransparent ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ]]\n\t\t\t],\n\t\t\tXYZ: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.1, 0.1, 0.1 ), matWhiteTransparent ) ],\n\t\t\t]\n\t\t};\n\n\t\tconst pickerScale = {\n\t\t\tX: [\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0.3, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ - 0.3, 0, 0 ], [ 0, 0, Math.PI / 2 ]]\n\t\t\t],\n\t\t\tY: [\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0.3, 0 ]],\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, - 0.3, 0 ], [ 0, 0, Math.PI ]]\n\t\t\t],\n\t\t\tZ: [\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0, 0.3 ], [ Math.PI / 2, 0, 0 ]],\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0, - 0.3 ], [ - Math.PI / 2, 0, 0 ]]\n\t\t\t],\n\t\t\tXY: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0.15, 0.15, 0 ]],\n\t\t\t],\n\t\t\tYZ: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ]],\n\t\t\t],\n\t\t\tXZ: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ]],\n\t\t\t],\n\t\t\tXYZ: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 0, 0, 0 ]],\n\t\t\t]\n\t\t};\n\n\t\tconst helperScale = {\n\t\t\tX: [\n\t\t\t\t[ new Line( lineGeometry, matHelper ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]\n\t\t\t],\n\t\t\tY: [\n\t\t\t\t[ new Line( lineGeometry, matHelper ), [ 0, - 1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], 'helper' ]\n\t\t\t],\n\t\t\tZ: [\n\t\t\t\t[ new Line( lineGeometry, matHelper ), [ 0, 0, - 1e3 ], [ 0, - Math.PI / 2, 0 ], [ 1e6, 1, 1 ], 'helper' ]\n\t\t\t]\n\t\t};\n\n\t\t// Creates an Object3D with gizmos described in custom hierarchy definition.\n\n\t\tfunction setupGizmo( gizmoMap ) {\n\n\t\t\tconst gizmo = new Object3D();\n\n\t\t\tfor ( const name in gizmoMap ) {\n\n\t\t\t\tfor ( let i = gizmoMap[ name ].length; i --; ) {\n\n\t\t\t\t\tconst object = gizmoMap[ name ][ i ][ 0 ].clone();\n\t\t\t\t\tconst position = gizmoMap[ name ][ i ][ 1 ];\n\t\t\t\t\tconst rotation = gizmoMap[ name ][ i ][ 2 ];\n\t\t\t\t\tconst scale = gizmoMap[ name ][ i ][ 3 ];\n\t\t\t\t\tconst tag = gizmoMap[ name ][ i ][ 4 ];\n\n\t\t\t\t\t// name and tag properties are essential for picking and updating logic.\n\t\t\t\t\tobject.name = name;\n\t\t\t\t\tobject.tag = tag;\n\n\t\t\t\t\tif ( position ) {\n\n\t\t\t\t\t\tobject.position.set( position[ 0 ], position[ 1 ], position[ 2 ] );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( rotation ) {\n\n\t\t\t\t\t\tobject.rotation.set( rotation[ 0 ], rotation[ 1 ], rotation[ 2 ] );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( scale ) {\n\n\t\t\t\t\t\tobject.scale.set( scale[ 0 ], scale[ 1 ], scale[ 2 ] );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tobject.updateMatrix();\n\n\t\t\t\t\tconst tempGeometry = object.geometry.clone();\n\t\t\t\t\ttempGeometry.applyMatrix4( object.matrix );\n\t\t\t\t\tobject.geometry = tempGeometry;\n\t\t\t\t\tobject.renderOrder = Infinity;\n\n\t\t\t\t\tobject.position.set( 0, 0, 0 );\n\t\t\t\t\tobject.rotation.set( 0, 0, 0 );\n\t\t\t\t\tobject.scale.set( 1, 1, 1 );\n\n\t\t\t\t\tgizmo.add( object );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn gizmo;\n\n\t\t}\n\n\t\t// Gizmo creation\n\n\t\tthis.gizmo = {};\n\t\tthis.picker = {};\n\t\tthis.helper = {};\n\n\t\tthis.add( this.gizmo[ 'translate' ] = setupGizmo( gizmoTranslate ) );\n\t\tthis.add( this.gizmo[ 'rotate' ] = setupGizmo( gizmoRotate ) );\n\t\tthis.add( this.gizmo[ 'scale' ] = setupGizmo( gizmoScale ) );\n\t\tthis.add( this.picker[ 'translate' ] = setupGizmo( pickerTranslate ) );\n\t\tthis.add( this.picker[ 'rotate' ] = setupGizmo( pickerRotate ) );\n\t\tthis.add( this.picker[ 'scale' ] = setupGizmo( pickerScale ) );\n\t\tthis.add( this.helper[ 'translate' ] = setupGizmo( helperTranslate ) );\n\t\tthis.add( this.helper[ 'rotate' ] = setupGizmo( helperRotate ) );\n\t\tthis.add( this.helper[ 'scale' ] = setupGizmo( helperScale ) );\n\n\t\t// Pickers should be hidden always\n\n\t\tthis.picker[ 'translate' ].visible = false;\n\t\tthis.picker[ 'rotate' ].visible = false;\n\t\tthis.picker[ 'scale' ].visible = false;\n\n\t}\n\n\t// updateMatrixWorld will update transformations and appearance of individual handles\n\n\tupdateMatrixWorld( force ) {\n\n\t\tconst space = ( this.mode === 'scale' ) ? 'local' : this.space; // scale always oriented to local rotation\n\n\t\tconst quaternion = ( space === 'local' ) ? this.worldQuaternion : _identityQuaternion;\n\n\t\t// Show only gizmos for current transform mode\n\n\t\tthis.gizmo[ 'translate' ].visible = this.mode === 'translate';\n\t\tthis.gizmo[ 'rotate' ].visible = this.mode === 'rotate';\n\t\tthis.gizmo[ 'scale' ].visible = this.mode === 'scale';\n\n\t\tthis.helper[ 'translate' ].visible = this.mode === 'translate';\n\t\tthis.helper[ 'rotate' ].visible = this.mode === 'rotate';\n\t\tthis.helper[ 'scale' ].visible = this.mode === 'scale';\n\n\n\t\tlet handles = [];\n\t\thandles = handles.concat( this.picker[ this.mode ].children );\n\t\thandles = handles.concat( this.gizmo[ this.mode ].children );\n\t\thandles = handles.concat( this.helper[ this.mode ].children );\n\n\t\tfor ( let i = 0; i < handles.length; i ++ ) {\n\n\t\t\tconst handle = handles[ i ];\n\n\t\t\t// hide aligned to camera\n\n\t\t\thandle.visible = true;\n\t\t\thandle.rotation.set( 0, 0, 0 );\n\t\t\thandle.position.copy( this.worldPosition );\n\n\t\t\tlet factor;\n\n\t\t\tif ( this.camera.isOrthographicCamera ) {\n\n\t\t\t\tfactor = ( this.camera.top - this.camera.bottom ) / this.camera.zoom;\n\n\t\t\t} else {\n\n\t\t\t\tfactor = this.worldPosition.distanceTo( this.cameraPosition ) * Math.min( 1.9 * Math.tan( Math.PI * this.camera.fov / 360 ) / this.camera.zoom, 7 );\n\n\t\t\t}\n\n\t\t\thandle.scale.set( 1, 1, 1 ).multiplyScalar( factor * this.size / 4 );\n\n\t\t\t// TODO: simplify helpers and consider decoupling from gizmo\n\n\t\t\tif ( handle.tag === 'helper' ) {\n\n\t\t\t\thandle.visible = false;\n\n\t\t\t\tif ( handle.name === 'AXIS' ) {\n\n\t\t\t\t\thandle.visible = !! this.axis;\n\n\t\t\t\t\tif ( this.axis === 'X' ) {\n\n\t\t\t\t\t\t_tempQuaternion.setFromEuler( _tempEuler.set( 0, 0, 0 ) );\n\t\t\t\t\t\thandle.quaternion.copy( quaternion ).multiply( _tempQuaternion );\n\n\t\t\t\t\t\tif ( Math.abs( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) {\n\n\t\t\t\t\t\t\thandle.visible = false;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( this.axis === 'Y' ) {\n\n\t\t\t\t\t\t_tempQuaternion.setFromEuler( _tempEuler.set( 0, 0, Math.PI / 2 ) );\n\t\t\t\t\t\thandle.quaternion.copy( quaternion ).multiply( _tempQuaternion );\n\n\t\t\t\t\t\tif ( Math.abs( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) {\n\n\t\t\t\t\t\t\thandle.visible = false;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( this.axis === 'Z' ) {\n\n\t\t\t\t\t\t_tempQuaternion.setFromEuler( _tempEuler.set( 0, Math.PI / 2, 0 ) );\n\t\t\t\t\t\thandle.quaternion.copy( quaternion ).multiply( _tempQuaternion );\n\n\t\t\t\t\t\tif ( Math.abs( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) {\n\n\t\t\t\t\t\t\thandle.visible = false;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( this.axis === 'XYZE' ) {\n\n\t\t\t\t\t\t_tempQuaternion.setFromEuler( _tempEuler.set( 0, Math.PI / 2, 0 ) );\n\t\t\t\t\t\t_alignVector.copy( this.rotationAxis );\n\t\t\t\t\t\thandle.quaternion.setFromRotationMatrix( _lookAtMatrix.lookAt( _zeroVector, _alignVector, _unitY ) );\n\t\t\t\t\t\thandle.quaternion.multiply( _tempQuaternion );\n\t\t\t\t\t\thandle.visible = this.dragging;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( this.axis === 'E' ) {\n\n\t\t\t\t\t\thandle.visible = false;\n\n\t\t\t\t\t}\n\n\n\t\t\t\t} else if ( handle.name === 'START' ) {\n\n\t\t\t\t\thandle.position.copy( this.worldPositionStart );\n\t\t\t\t\thandle.visible = this.dragging;\n\n\t\t\t\t} else if ( handle.name === 'END' ) {\n\n\t\t\t\t\thandle.position.copy( this.worldPosition );\n\t\t\t\t\thandle.visible = this.dragging;\n\n\t\t\t\t} else if ( handle.name === 'DELTA' ) {\n\n\t\t\t\t\thandle.position.copy( this.worldPositionStart );\n\t\t\t\t\thandle.quaternion.copy( this.worldQuaternionStart );\n\t\t\t\t\t_tempVector.set( 1e-10, 1e-10, 1e-10 ).add( this.worldPositionStart ).sub( this.worldPosition ).multiplyScalar( - 1 );\n\t\t\t\t\t_tempVector.applyQuaternion( this.worldQuaternionStart.clone().invert() );\n\t\t\t\t\thandle.scale.copy( _tempVector );\n\t\t\t\t\thandle.visible = this.dragging;\n\n\t\t\t\t} else {\n\n\t\t\t\t\thandle.quaternion.copy( quaternion );\n\n\t\t\t\t\tif ( this.dragging ) {\n\n\t\t\t\t\t\thandle.position.copy( this.worldPositionStart );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\thandle.position.copy( this.worldPosition );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( this.axis ) {\n\n\t\t\t\t\t\thandle.visible = this.axis.search( handle.name ) !== - 1;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\t// If updating helper, skip rest of the loop\n\t\t\t\tcontinue;\n\n\t\t\t}\n\n\t\t\t// Align handles to current local or world rotation\n\n\t\t\thandle.quaternion.copy( quaternion );\n\n\t\t\tif ( this.mode === 'translate' || this.mode === 'scale' ) {\n\n\t\t\t\t// Hide translate and scale axis facing the camera\n\n\t\t\t\tconst AXIS_HIDE_THRESHOLD = 0.99;\n\t\t\t\tconst PLANE_HIDE_THRESHOLD = 0.2;\n\n\t\t\t\tif ( handle.name === 'X' ) {\n\n\t\t\t\t\tif ( Math.abs( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_THRESHOLD ) {\n\n\t\t\t\t\t\thandle.scale.set( 1e-10, 1e-10, 1e-10 );\n\t\t\t\t\t\thandle.visible = false;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( handle.name === 'Y' ) {\n\n\t\t\t\t\tif ( Math.abs( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_THRESHOLD ) {\n\n\t\t\t\t\t\thandle.scale.set( 1e-10, 1e-10, 1e-10 );\n\t\t\t\t\t\thandle.visible = false;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( handle.name === 'Z' ) {\n\n\t\t\t\t\tif ( Math.abs( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_THRESHOLD ) {\n\n\t\t\t\t\t\thandle.scale.set( 1e-10, 1e-10, 1e-10 );\n\t\t\t\t\t\thandle.visible = false;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( handle.name === 'XY' ) {\n\n\t\t\t\t\tif ( Math.abs( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_THRESHOLD ) {\n\n\t\t\t\t\t\thandle.scale.set( 1e-10, 1e-10, 1e-10 );\n\t\t\t\t\t\thandle.visible = false;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( handle.name === 'YZ' ) {\n\n\t\t\t\t\tif ( Math.abs( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_THRESHOLD ) {\n\n\t\t\t\t\t\thandle.scale.set( 1e-10, 1e-10, 1e-10 );\n\t\t\t\t\t\thandle.visible = false;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( handle.name === 'XZ' ) {\n\n\t\t\t\t\tif ( Math.abs( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_THRESHOLD ) {\n\n\t\t\t\t\t\thandle.scale.set( 1e-10, 1e-10, 1e-10 );\n\t\t\t\t\t\thandle.visible = false;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} else if ( this.mode === 'rotate' ) {\n\n\t\t\t\t// Align handles to current local or world rotation\n\n\t\t\t\t_tempQuaternion2.copy( quaternion );\n\t\t\t\t_alignVector.copy( this.eye ).applyQuaternion( _tempQuaternion.copy( quaternion ).invert() );\n\n\t\t\t\tif ( handle.name.search( 'E' ) !== - 1 ) {\n\n\t\t\t\t\thandle.quaternion.setFromRotationMatrix( _lookAtMatrix.lookAt( this.eye, _zeroVector, _unitY ) );\n\n\t\t\t\t}\n\n\t\t\t\tif ( handle.name === 'X' ) {\n\n\t\t\t\t\t_tempQuaternion.setFromAxisAngle( _unitX, Math.atan2( - _alignVector.y, _alignVector.z ) );\n\t\t\t\t\t_tempQuaternion.multiplyQuaternions( _tempQuaternion2, _tempQuaternion );\n\t\t\t\t\thandle.quaternion.copy( _tempQuaternion );\n\n\t\t\t\t}\n\n\t\t\t\tif ( handle.name === 'Y' ) {\n\n\t\t\t\t\t_tempQuaternion.setFromAxisAngle( _unitY, Math.atan2( _alignVector.x, _alignVector.z ) );\n\t\t\t\t\t_tempQuaternion.multiplyQuaternions( _tempQuaternion2, _tempQuaternion );\n\t\t\t\t\thandle.quaternion.copy( _tempQuaternion );\n\n\t\t\t\t}\n\n\t\t\t\tif ( handle.name === 'Z' ) {\n\n\t\t\t\t\t_tempQuaternion.setFromAxisAngle( _unitZ, Math.atan2( _alignVector.y, _alignVector.x ) );\n\t\t\t\t\t_tempQuaternion.multiplyQuaternions( _tempQuaternion2, _tempQuaternion );\n\t\t\t\t\thandle.quaternion.copy( _tempQuaternion );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// Hide disabled axes\n\t\t\thandle.visible = handle.visible && ( handle.name.indexOf( 'X' ) === - 1 || this.showX );\n\t\t\thandle.visible = handle.visible && ( handle.name.indexOf( 'Y' ) === - 1 || this.showY );\n\t\t\thandle.visible = handle.visible && ( handle.name.indexOf( 'Z' ) === - 1 || this.showZ );\n\t\t\thandle.visible = handle.visible && ( handle.name.indexOf( 'E' ) === - 1 || ( this.showX && this.showY && this.showZ ) );\n\n\t\t\t// Hide disabled plane helpers\n\t\t\thandle.visible = handle.visible && ( handle.name.indexOf( 'XY' ) === - 1 || this.showXY );\n\t\t\thandle.visible = handle.visible && ( handle.name.indexOf( 'YZ' ) === - 1 || this.showYZ );\n\t\t\thandle.visible = handle.visible && ( handle.name.indexOf( 'XZ' ) === - 1 || this.showXZ );\n\n\t\t\t// highlight selected axis\n\n\t\t\thandle.material._color = handle.material._color || handle.material.color.clone();\n\t\t\thandle.material._opacity = handle.material._opacity || handle.material.opacity;\n\n\t\t\thandle.material.color.copy( handle.material._color );\n\t\t\thandle.material.opacity = handle.material._opacity;\n\n\t\t\tif ( this.enabled && this.axis ) {\n\n\t\t\t\tif ( handle.name === this.axis ) {\n\n\t\t\t\t\thandle.material.color.copy( this.materialLib.active.color );\n\t\t\t\t\thandle.material.opacity = 1.0;\n\n\t\t\t\t} else if ( this.axis.split( '' ).some( function ( a ) {\n\n\t\t\t\t\treturn handle.name === a;\n\n\t\t\t\t} ) ) {\n\n\t\t\t\t\thandle.material.color.copy( this.materialLib.active.color );\n\t\t\t\t\thandle.material.opacity = 1.0;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tsuper.updateMatrixWorld( force );\n\n\t}\n\n}\n\n//\n\nclass TransformControlsPlane extends Mesh {\n\n\tconstructor() {\n\n\t\tsuper(\n\t\t\tnew PlaneGeometry( 100000, 100000, 2, 2 ),\n\t\t\tnew MeshBasicMaterial( { visible: false, wireframe: true, side: DoubleSide, transparent: true, opacity: 0.1, toneMapped: false } )\n\t\t);\n\n\t\tthis.isTransformControlsPlane = true;\n\n\t\tthis.type = 'TransformControlsPlane';\n\n\t}\n\n\tupdateMatrixWorld( force ) {\n\n\t\tlet space = this.space;\n\n\t\tthis.position.copy( this.worldPosition );\n\n\t\tif ( this.mode === 'scale' ) space = 'local'; // scale always oriented to local rotation\n\n\t\t_v1.copy( _unitX ).applyQuaternion( space === 'local' ? this.worldQuaternion : _identityQuaternion );\n\t\t_v2.copy( _unitY ).applyQuaternion( space === 'local' ? this.worldQuaternion : _identityQuaternion );\n\t\t_v3.copy( _unitZ ).applyQuaternion( space === 'local' ? this.worldQuaternion : _identityQuaternion );\n\n\t\t// Align the plane for current transform mode, axis and space.\n\n\t\t_alignVector.copy( _v2 );\n\n\t\tswitch ( this.mode ) {\n\n\t\t\tcase 'translate':\n\t\t\tcase 'scale':\n\t\t\t\tswitch ( this.axis ) {\n\n\t\t\t\t\tcase 'X':\n\t\t\t\t\t\t_alignVector.copy( this.eye ).cross( _v1 );\n\t\t\t\t\t\t_dirVector.copy( _v1 ).cross( _alignVector );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'Y':\n\t\t\t\t\t\t_alignVector.copy( this.eye ).cross( _v2 );\n\t\t\t\t\t\t_dirVector.copy( _v2 ).cross( _alignVector );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'Z':\n\t\t\t\t\t\t_alignVector.copy( this.eye ).cross( _v3 );\n\t\t\t\t\t\t_dirVector.copy( _v3 ).cross( _alignVector );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'XY':\n\t\t\t\t\t\t_dirVector.copy( _v3 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'YZ':\n\t\t\t\t\t\t_dirVector.copy( _v1 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'XZ':\n\t\t\t\t\t\t_alignVector.copy( _v3 );\n\t\t\t\t\t\t_dirVector.copy( _v2 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'XYZ':\n\t\t\t\t\tcase 'E':\n\t\t\t\t\t\t_dirVector.set( 0, 0, 0 );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\tcase 'rotate':\n\t\t\tdefault:\n\t\t\t\t// special case for rotate\n\t\t\t\t_dirVector.set( 0, 0, 0 );\n\n\t\t}\n\n\t\tif ( _dirVector.length() === 0 ) {\n\n\t\t\t// If in rotate mode, make the plane parallel to camera\n\t\t\tthis.quaternion.copy( this.cameraQuaternion );\n\n\t\t} else {\n\n\t\t\t_tempMatrix.lookAt( _tempVector.set( 0, 0, 0 ), _dirVector, _alignVector );\n\n\t\t\tthis.quaternion.setFromRotationMatrix( _tempMatrix );\n\n\t\t}\n\n\t\tsuper.updateMatrixWorld( force );\n\n\t}\n\n}\n\nexport { TransformControls, TransformControlsGizmo, TransformControlsPlane };\n","/**\r\n * 3D 模型编辑器核心模块\r\n * 提供场景管理、物体增删、选中/变换控制、树形数据同步等功能\r\n * 采用单例模式管理所有 Three.js 相关状态\r\n */\r\n\r\nimport * as THREE from \"three\";\r\nimport TWEEN from \"@tweenjs/tween.js\";\r\nimport { OrbitControls } from \"three/examples/jsm/controls/OrbitControls.js\";\r\nimport { TransformControls } from \"three/examples/jsm/controls/TransformControls.js\";\r\nimport type { Object3D } from \"three\";\r\nimport type {\r\n SelectedChangeCallback,\r\n TransformChangeCallback,\r\n SceneObjectsChangeCallback,\r\n} from \"./types\";\r\n\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n//#region 编辑器状态(单例)\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n\r\n/** 编辑器核心状态容器,所有 Three.js 核心对象均存放于此 */\r\nconst state = {\r\n mode: \"\",\r\n /** Three.js 场景 */\r\n scene: null as THREE.Scene | null,\r\n /** 透视相机 */\r\n camera: null as THREE.PerspectiveCamera | null,\r\n /** WebGL 渲染器 */\r\n renderer: null as THREE.WebGLRenderer | null,\r\n /** 轨道控制器(用于场景浏览) */\r\n orbitControls: null as OrbitControls | null,\r\n /** 变换控制器(用于平移/旋转/缩放物体) */\r\n transformControls: null as TransformControls | null,\r\n /** 编辑器挂载的 DOM 容器 */\r\n container: null as HTMLElement | null,\r\n /** 网格辅助对象(地板) */\r\n gridHelper: null as THREE.GridHelper | null,\r\n /** 当前选中的物体 */\r\n selectedObject: null as Object3D | null,\r\n};\r\n//#endregion\r\n\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n//#region 辅助标志\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n\r\n/** 轨道控制器是否发生了旋转/平移/缩放操作 */\r\nlet orbitChanged = false;\r\n/** 是否应该跳过下一次鼠标点击事件(用于防止拖拽后误触发选中) */\r\nlet skipNextClick = false;\r\n//#endregion\r\n\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n//#region 外部回调\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n\r\n/** 选中物体变化时的回调(由外部注册,用于同步 UI) */\r\nlet onSelectedChange: SelectedChangeCallback | null = null;\r\n/** 变换过程中(拖拽)的回调(由外部注册,用于实时更新属性面板) */\r\nlet onTransformChange: TransformChangeCallback | null = null;\r\n/** 场景物体列表变化时的回调(由外部注册,用于更新树形面板) */\r\nlet onSceneObjectsChange: SceneObjectsChangeCallback | null = null;\r\n//#endregion\r\n\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n//#region 树形数据(仅存储顶层可移动物体)\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n\r\n/** 场景中顶层可移动物体的列表(不包含子物体,子物体通过 parent 关系访问) */\r\nlet sceneObjects: Object3D[] = [];\r\n//#endregion\r\n\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n//#region 初始化场景数据\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n\r\n// 如果有场景数据,恢复相机参数并保存 target\r\nlet cameraTarget: number[] | undefined;\r\n//#endregion\r\n\r\n\r\n// ═══════════════════════════════════════════════════════════════════\r\n//#region 初始化\r\n// ═══════════════════════════════════════════════════════════════════\r\n\r\n/**\r\n * 初始化编辑器,挂载到指定 DOM 容器\r\n * @param container - 编辑器挂载的 DOM 元素\r\n */\r\nexport function initEditor(\r\n container: HTMLElement,\r\n mode = \"edit\",\r\n sceneData?: any,\r\n) {\r\n state.container = container;\r\n state.mode = mode;\r\n initRenderer(); // 创建渲染器\r\n initScene(); // 创建场景\r\n initCamera(); // 创建相机\r\n\r\n // 如果有传入场景数据\r\n if (sceneData) {\r\n // 设置场景数据\r\n loadSceneFromJSON(sceneData.scene, mode);\r\n\r\n if (sceneData?.camera) {\r\n const camData = sceneData.camera;\r\n state.camera!.position.set(\r\n camData.position[0],\r\n camData.position[1],\r\n camData.position[2],\r\n );\r\n state.camera!.rotation.set(\r\n camData.rotation[0],\r\n camData.rotation[1],\r\n camData.rotation[2],\r\n );\r\n state.camera!.updateProjectionMatrix();\r\n cameraTarget = camData.target;\r\n }\r\n }\r\n\r\n initTransformControls(); // 初始化变换控制器(需在 OrbitControls 前,因为辅助对象要加入场景)\r\n initOrbitControls(); // 初始化轨道控制器\r\n\r\n // 如果有 target,恢复 OrbitControls 的目标并更新\r\n if (cameraTarget && state.orbitControls) {\r\n state.orbitControls.target.fromArray(cameraTarget);\r\n state.orbitControls.update();\r\n }\r\n\r\n refreshSceneObjects(); // 刷新顶层物体列表\r\n animate(); // 启动动画循环\r\n // 绑定事件\r\n if (mode === \"edit\") container.addEventListener(\"click\", onMouseClick);\r\n window.addEventListener(\"resize\", onResize);\r\n\r\n // 如果没有传入场景数据\r\n if (!sceneData) {\r\n addDefaultLightAndCube(); // 添加默认灯光和立方体(演示用)\r\n }\r\n\r\n if (mode === \"edit\") initGrid(); // 添加网格地板\r\n}\r\n\r\n/** 创建 WebGL 渲染器,设置尺寸和像素比 */\r\nfunction initRenderer() {\r\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\r\n renderer.setSize(state.container!.clientWidth, state.container!.clientHeight);\r\n // 限制像素比不超过 2,以平衡性能和显示效果\r\n renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));\r\n state.container!.appendChild(renderer.domElement);\r\n state.renderer = renderer;\r\n}\r\n\r\n/** 创建场景并命名(便于调试) */\r\nfunction initScene() {\r\n state.scene = new THREE.Scene();\r\n state.scene.name = \"sl_scene\";\r\n}\r\n\r\n/** 创建网格辅助对象(地板),不加入树形列表 */\r\nfunction initGrid() {\r\n const grid = new THREE.GridHelper(30, 30, 0x88aaff, 0x335588);\r\n grid.name = \"地板\";\r\n grid.userData.type = \"initFloor\";\r\n // 地板不可移动,故不设置 isMovable\r\n state.scene!.add(grid);\r\n state.gridHelper = grid;\r\n}\r\n\r\n/** 创建透视相机,设置初始位置 */\r\nfunction initCamera() {\r\n const container = state.container!;\r\n const aspect = container.clientWidth / container.clientHeight;\r\n const camera = new THREE.PerspectiveCamera(45, aspect, 0.1, 1000);\r\n camera.position.set(0, 6, 15);\r\n camera.lookAt(0, 0, 0);\r\n state.camera = camera;\r\n}\r\n\r\n/** 创建轨道控制器,允许用户旋转/平移/缩放视图 */\r\nfunction initOrbitControls() {\r\n const controls = new OrbitControls(state.camera!, state.renderer!.domElement);\r\n\r\n controls.minDistance = 0;\r\n controls.maxDistance = Infinity;\r\n // 监测操作是否改变了相机状态\r\n controls.addEventListener(\"start\", () => {\r\n orbitChanged = false;\r\n });\r\n controls.addEventListener(\"change\", () => {\r\n orbitChanged = true;\r\n });\r\n controls.addEventListener(\"end\", () => {\r\n // 如果相机发生了改变,则标记跳过下一次点击(避免拖拽后选中物体)\r\n if (orbitChanged) {\r\n skipNextClick = true;\r\n setTimeout(() => {\r\n skipNextClick = false;\r\n }, 200);\r\n }\r\n });\r\n state.orbitControls = controls;\r\n}\r\n\r\n/** 创建变换控制器,用于拖拽移动物体(平移模式) */\r\nfunction initTransformControls() {\r\n const controls = new TransformControls(\r\n state.camera!,\r\n state.renderer!.domElement,\r\n );\r\n // 拖拽变换控制器时,暂时禁用轨道控制器\r\n controls.addEventListener(\"dragging-changed\", (event: any) => {\r\n state.orbitControls!.enabled = !event.value;\r\n if (!event.value) {\r\n // 拖拽结束后,跳过下一次点击\r\n skipNextClick = true;\r\n setTimeout(() => {\r\n skipNextClick = false;\r\n }, 200);\r\n }\r\n });\r\n // 物体变换过程中(位置/旋转/缩放变化),触发外部回调以更新 UI\r\n controls.addEventListener(\"objectChange\", () => {\r\n if (onTransformChange && state.selectedObject) {\r\n onTransformChange(state.selectedObject);\r\n }\r\n });\r\n // 将变换控制器的辅助轴添加到场景\r\n state.scene!.add(controls.getHelper());\r\n state.transformControls = controls;\r\n}\r\n\r\n/** 添加默认的环境光、平行光和一个示例立方体 */\r\nfunction addDefaultLightAndCube() {\r\n // 环境光\r\n const ambient = new THREE.AmbientLight(0xffffff, 2);\r\n state.scene!.add(ambient);\r\n // 平行光\r\n const dirLight = new THREE.DirectionalLight(0xffffff, 3);\r\n dirLight.position.set(48, 104, 138);\r\n state.scene!.add(dirLight);\r\n\r\n // 默认立方体(方便演示)\r\n // const geo = new THREE.BoxGeometry(1, 1, 1);\r\n // const mat = new THREE.MeshStandardMaterial({ color: 0xffffff });\r\n // const cube = new THREE.Mesh(geo, mat);\r\n // cube.position.y = 1;\r\n // cube.userData.isMovable = true;\r\n // cube.name = \"默认立方体\";\r\n // addModel(cube, true);\r\n}\r\n//#endregion\r\n\r\n// ═══════════════════════════════════════════════════════════════════\r\n//#region 动画循环 & 窗口自适应\r\n// ═══════════════════════════════════════════════════════════════════\r\n\r\n/** 动画循环:更新 Tween 动画、轨道控制器,并渲染场景 */\r\nfunction animate() {\r\n requestAnimationFrame(animate);\r\n TWEEN.update(); // 更新补间动画(当前未使用,保留扩展)\r\n state.orbitControls?.update();\r\n state.renderer?.render(state.scene!, state.camera!);\r\n}\r\n\r\n/** 窗口大小变化时,自适应渲染尺寸和相机比例 */\r\nfunction onResize() {\r\n if (!state.container || !state.camera || !state.renderer) return;\r\n const width = state.container.clientWidth;\r\n const height = state.container.clientHeight;\r\n if (width === 0 || height === 0) return;\r\n state.camera.aspect = width / height;\r\n state.camera.updateProjectionMatrix();\r\n state.renderer.setSize(width, height);\r\n}\r\n//#endregion\r\n\r\n// ═══════════════════════════════════════════════════════════════════\r\n//#region 选中 / 取消选中\r\n// ═══════════════════════════════════════════════════════════════════\r\n\r\n/**\r\n * 选中场景中的一个物体,将其附着到变换控制器并显示平移轴\r\n * @param obj - 要选中的物体\r\n */\r\nexport function selectObject(obj: Object3D) {\r\n if (state.selectedObject === obj) return; // 已选中则忽略\r\n // 取消之前的附着\r\n if (state.selectedObject) {\r\n state.transformControls!.detach();\r\n }\r\n state.selectedObject = obj;\r\n state.transformControls!.attach(obj);\r\n state.transformControls!.setMode(\"translate\"); // 默认平移模式\r\n state.transformControls!.showX = true;\r\n state.transformControls!.showY = true;\r\n state.transformControls!.showZ = true;\r\n // 通知外部选中变化\r\n onSelectedChange?.(obj);\r\n}\r\n\r\n/** 取消选中:隐藏变换控制器,并通知外部 */\r\nfunction deselectObject() {\r\n if (state.selectedObject) {\r\n state.transformControls!.detach();\r\n state.selectedObject = null;\r\n onSelectedChange?.(null);\r\n }\r\n}\r\n//#endregion\r\n\r\n// ═══════════════════════════════════════════════════════════════════\r\n//#region 鼠标点击(射线拾取)\r\n// ═══════════════════════════════════════════════════════════════════\r\n\r\n/**\r\n * 鼠标点击事件处理:使用射线检测拾取场景中的可移动 Mesh,\r\n * 若点击到物体则选中它,否则取消选中\r\n */\r\nfunction onMouseClick(event: MouseEvent) {\r\n // 如果标记跳过本次点击(如拖拽刚结束),则忽略并重置标记\r\n if (skipNextClick) {\r\n skipNextClick = false;\r\n return;\r\n }\r\n // 计算鼠标位置归一化坐标\r\n const rect = state.renderer!.domElement.getBoundingClientRect();\r\n const mouse = new THREE.Vector2(\r\n ((event.clientX - rect.left) / rect.width) * 2 - 1,\r\n -((event.clientY - rect.top) / rect.height) * 2 + 1,\r\n );\r\n const raycaster = new THREE.Raycaster();\r\n raycaster.setFromCamera(mouse, state.camera!);\r\n\r\n // 收集场景中所有可点击的物体(isMovable 且为 Mesh)\r\n const clickables: Object3D[] = [];\r\n state.scene!.traverse((obj) => {\r\n if (obj.type === \"Mesh\" && obj.userData.isMovable) {\r\n clickables.push(obj);\r\n }\r\n });\r\n const intersects = raycaster.intersectObjects(clickables);\r\n if (intersects.length > 0) {\r\n selectObject(intersects[0].object);\r\n } else {\r\n deselectObject();\r\n }\r\n}\r\n//#endregion\r\n\r\n// ═══════════════════════════════════════════════════════════════════\r\n//#region 模型管理(增删改查)\r\n// ═══════════════════════════════════════════════════════════════════\r\n\r\n/**\r\n * 向场景添加一个模型(Object3D 及其子节点)\r\n * @param model - 要添加的模型对象\r\n * @param selected - 是否添加后立即选中\r\n */\r\nexport function addModel(model: Object3D, selected = false) {\r\n state.scene!.add(model);\r\n // 如果模型本身是可移动的,则加入顶层列表(但只有顶层对象才加入)\r\n if (model.userData.isMovable) {\r\n addObjectToTree(model);\r\n notifyChange();\r\n }\r\n if (selected && state.mode === \"edit\") selectObject(model);\r\n}\r\n\r\n/**\r\n * 从场景中移除一个模型及其子节点\r\n * @param model - 要移除的模型对象\r\n */\r\nexport function removeModel(model: Object3D) {\r\n if (state.selectedObject === model) deselectObject();\r\n // 从父节点移除(更通用),若没有父节点则从场景移除\r\n if (model.parent) {\r\n model.parent.remove(model);\r\n } else {\r\n state.scene!.remove(model);\r\n }\r\n // 如果该对象在顶层列表中,则移除\r\n removeObjectFromTree(model);\r\n notifyChange();\r\n}\r\n\r\n/**\r\n * 根据 UUID 删除场景中的物体\r\n * @param uuid - 物体的唯一标识符\r\n */\r\nexport function removeModelById(uuid: string) {\r\n const obj = state.scene!.getObjectByProperty(\"uuid\", uuid);\r\n if (obj) removeModel(obj);\r\n}\r\n\r\n// ─── 树形数据管理(仅顶层对象) ───\r\n\r\n/**\r\n * 将一个可移动物体加入顶层列表(前提是它是场景的直接子级)\r\n */\r\nfunction addObjectToTree(obj: Object3D) {\r\n if (obj.userData.isMovable && obj.parent === state.scene) {\r\n if (!sceneObjects.includes(obj)) {\r\n sceneObjects.push(obj);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * 从顶层列表中移除物体(如果存在)\r\n */\r\nfunction removeObjectFromTree(obj: Object3D) {\r\n const idx = sceneObjects.indexOf(obj);\r\n if (idx !== -1) sceneObjects.splice(idx, 1);\r\n}\r\n\r\n/** 全量刷新顶层物体列表(初始化时调用) */\r\nfunction refreshSceneObjects() {\r\n const list: Object3D[] = [];\r\n state.scene!.children.forEach((child) => {\r\n if (child.userData.isMovable) list.push(child);\r\n });\r\n sceneObjects = list;\r\n notifyChange();\r\n}\r\n\r\n/** 通知外部树形数据变化,传递列表副本以触发 shallowRef 更新 */\r\nfunction notifyChange() {\r\n onSceneObjectsChange?.([...sceneObjects]);\r\n}\r\n//#endregion\r\n\r\n// ═══════════════════════════════════════════════════════════════════\r\n//#region 回调注册\r\n// ═══════════════════════════════════════════════════════════════════\r\n\r\n/**\r\n * 注册选中物体变化的回调\r\n * @param cb - 回调函数,参数为当前选中的物体或 null\r\n */\r\nexport function setSelectedObjectCallback(cb: SelectedChangeCallback) {\r\n onSelectedChange = cb;\r\n}\r\n\r\n/**\r\n * 注册变换过程中(拖拽)的回调\r\n * @param cb - 回调函数,参数为正在变换的物体\r\n */\r\nexport function setTransformChangeCallback(cb: TransformChangeCallback) {\r\n onTransformChange = cb;\r\n}\r\n\r\n/**\r\n * 注册场景物体列表变化的回调\r\n * @param cb - 回调函数,参数为当前顶层物体列表\r\n */\r\nexport function onSceneObjectsChangeCallback(cb: SceneObjectsChangeCallback) {\r\n onSceneObjectsChange = cb;\r\n}\r\n\r\n/**\r\n * 获取当前顶层物体列表\r\n * @returns 顶层物体数组\r\n */\r\nexport function getSceneObjects() {\r\n return sceneObjects;\r\n}\r\n//#endregion\r\n\r\n// ═══════════════════════════════════════════════════════════════════\r\n//#region 场景导出导入\r\n// ═══════════════════════════════════════════════════════════════════\r\n\r\nexport function getScene() {\r\n return state.scene;\r\n}\r\nexport function getCamera() {\r\n return state.camera;\r\n}\r\nexport function getRenderer() {\r\n return state.renderer;\r\n}\r\n\r\n/**\r\n * 将当前 Three.js 场景导出为 JSON 数据(使用 Three.js 内置 toJSON)\r\n * @returns JSON 字符串\r\n */\r\nexport function exportSceneToJSON(): string {\r\n // 首先取消选中模型\r\n deselectObject();\r\n\r\n const scene = state.scene;\r\n if (!scene) return \"{}\";\r\n\r\n // 不需要初始化地板对象,创建一个临时场景副本\r\n let exportScene = scene;\r\n\r\n exportScene = scene.clone();\r\n // 移除初始化地板的对象\r\n exportScene.children = exportScene.children.filter(\r\n (child) => child.userData.type !== \"initFloor\",\r\n );\r\n\r\n // 场景 json\r\n const sceneJson = exportScene.toJSON();\r\n // 摄像机 json\r\n const cameraJson = {\r\n position: state.camera?.position.toArray(),\r\n rotation: state.camera?.rotation.toArray(),\r\n target: state.orbitControls?.target.toArray() || [0, 0, 0],\r\n };\r\n\r\n return JSON.stringify({ scene: sceneJson, camera: cameraJson });\r\n}\r\n\r\n/**\r\n * 从 JSON 数据恢复场景(使用 Three.js 内置 ObjectLoader)\r\n * @param json - JSON 字符串或对象\r\n * @returns 解析后的 Object3D 或 Scene\r\n */\r\nexport function loadSceneFromJSON(\r\n json: string | object,\r\n mode: string = \"edit\",\r\n) {\r\n const data = typeof json === \"string\" ? JSON.parse(json) : json;\r\n const loader = new THREE.ObjectLoader();\r\n const loaded = loader.parse(data);\r\n\r\n if (loaded.type === \"Scene\") {\r\n if (mode === \"run\") {\r\n }\r\n state.scene = loaded as THREE.Scene;\r\n } else {\r\n state.scene?.add(loaded);\r\n }\r\n}\r\n//#endregion\r\n","import {\n\tBufferGeometry,\n\tFileLoader,\n\tFloat32BufferAttribute,\n\tGroup,\n\tLineBasicMaterial,\n\tLineSegments,\n\tLoader,\n\tMaterial,\n\tMesh,\n\tMeshPhongMaterial,\n\tPoints,\n\tPointsMaterial,\n\tVector3,\n\tColor,\n\tSRGBColorSpace\n} from 'three';\n\n// o object_name | g group_name\nconst _object_pattern = /^[og]\\s*(.+)?/;\n// mtllib file_reference\nconst _material_library_pattern = /^mtllib /;\n// usemtl material_name\nconst _material_use_pattern = /^usemtl /;\n// usemap map_name\nconst _map_use_pattern = /^usemap /;\nconst _face_vertex_data_separator_pattern = /\\s+/;\n\nconst _vA = new Vector3();\nconst _vB = new Vector3();\nconst _vC = new Vector3();\n\nconst _ab = new Vector3();\nconst _cb = new Vector3();\n\nconst _color = new Color();\n\nfunction ParserState() {\n\n\tconst state = {\n\t\tobjects: [],\n\t\tobject: {},\n\n\t\tvertices: [],\n\t\tnormals: [],\n\t\tcolors: [],\n\t\tuvs: [],\n\n\t\tmaterials: {},\n\t\tmaterialLibraries: [],\n\n\t\tstartObject: function ( name, fromDeclaration ) {\n\n\t\t\t// If the current object (initial from reset) is not from a g/o declaration in the parsed\n\t\t\t// file. We need to use it for the first parsed g/o to keep things in sync.\n\t\t\tif ( this.object && this.object.fromDeclaration === false ) {\n\n\t\t\t\tthis.object.name = name;\n\t\t\t\tthis.object.fromDeclaration = ( fromDeclaration !== false );\n\t\t\t\treturn;\n\n\t\t\t}\n\n\t\t\tconst previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined );\n\n\t\t\tif ( this.object && typeof this.object._finalize === 'function' ) {\n\n\t\t\t\tthis.object._finalize( true );\n\n\t\t\t}\n\n\t\t\tthis.object = {\n\t\t\t\tname: name || '',\n\t\t\t\tfromDeclaration: ( fromDeclaration !== false ),\n\n\t\t\t\tgeometry: {\n\t\t\t\t\tvertices: [],\n\t\t\t\t\tnormals: [],\n\t\t\t\t\tcolors: [],\n\t\t\t\t\tuvs: [],\n\t\t\t\t\thasUVIndices: false\n\t\t\t\t},\n\t\t\t\tmaterials: [],\n\t\t\t\tsmooth: true,\n\n\t\t\t\tstartMaterial: function ( name, libraries ) {\n\n\t\t\t\t\tconst previous = this._finalize( false );\n\n\t\t\t\t\t// New usemtl declaration overwrites an inherited material, except if faces were declared\n\t\t\t\t\t// after the material, then it must be preserved for proper MultiMaterial continuation.\n\t\t\t\t\tif ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) {\n\n\t\t\t\t\t\tthis.materials.splice( previous.index, 1 );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tconst material = {\n\t\t\t\t\t\tindex: this.materials.length,\n\t\t\t\t\t\tname: name || '',\n\t\t\t\t\t\tmtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ),\n\t\t\t\t\t\tsmooth: ( previous !== undefined ? previous.smooth : this.smooth ),\n\t\t\t\t\t\tgroupStart: ( previous !== undefined ? previous.groupEnd : 0 ),\n\t\t\t\t\t\tgroupEnd: - 1,\n\t\t\t\t\t\tgroupCount: - 1,\n\t\t\t\t\t\tinherited: false,\n\n\t\t\t\t\t\tclone: function ( index ) {\n\n\t\t\t\t\t\t\tconst cloned = {\n\t\t\t\t\t\t\t\tindex: ( typeof index === 'number' ? index : this.index ),\n\t\t\t\t\t\t\t\tname: this.name,\n\t\t\t\t\t\t\t\tmtllib: this.mtllib,\n\t\t\t\t\t\t\t\tsmooth: this.smooth,\n\t\t\t\t\t\t\t\tgroupStart: 0,\n\t\t\t\t\t\t\t\tgroupEnd: - 1,\n\t\t\t\t\t\t\t\tgroupCount: - 1,\n\t\t\t\t\t\t\t\tinherited: false\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tcloned.clone = this.clone.bind( cloned );\n\t\t\t\t\t\t\treturn cloned;\n\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tthis.materials.push( material );\n\n\t\t\t\t\treturn material;\n\n\t\t\t\t},\n\n\t\t\t\tcurrentMaterial: function () {\n\n\t\t\t\t\tif ( this.materials.length > 0 ) {\n\n\t\t\t\t\t\treturn this.materials[ this.materials.length - 1 ];\n\n\t\t\t\t\t}\n\n\t\t\t\t\treturn undefined;\n\n\t\t\t\t},\n\n\t\t\t\t_finalize: function ( end ) {\n\n\t\t\t\t\tconst lastMultiMaterial = this.currentMaterial();\n\t\t\t\t\tif ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) {\n\n\t\t\t\t\t\tlastMultiMaterial.groupEnd = this.geometry.vertices.length / 3;\n\t\t\t\t\t\tlastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart;\n\t\t\t\t\t\tlastMultiMaterial.inherited = false;\n\n\t\t\t\t\t}\n\n\t\t\t\t\t// Ignore objects tail materials if no face declarations followed them before a new o/g started.\n\t\t\t\t\tif ( end && this.materials.length > 1 ) {\n\n\t\t\t\t\t\tfor ( let mi = this.materials.length - 1; mi >= 0; mi -- ) {\n\n\t\t\t\t\t\t\tif ( this.materials[ mi ].groupCount <= 0 ) {\n\n\t\t\t\t\t\t\t\tthis.materials.splice( mi, 1 );\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\t// Guarantee at least one empty material, this makes the creation later more straight forward.\n\t\t\t\t\tif ( end && this.materials.length === 0 ) {\n\n\t\t\t\t\t\tthis.materials.push( {\n\t\t\t\t\t\t\tname: '',\n\t\t\t\t\t\t\tsmooth: this.smooth\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t}\n\n\t\t\t\t\treturn lastMultiMaterial;\n\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// Inherit previous objects material.\n\t\t\t// Spec tells us that a declared material must be set to all objects until a new material is declared.\n\t\t\t// If a usemtl declaration is encountered while this new object is being parsed, it will\n\t\t\t// overwrite the inherited material. Exception being that there was already face declarations\n\t\t\t// to the inherited material, then it will be preserved for proper MultiMaterial continuation.\n\n\t\t\tif ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) {\n\n\t\t\t\tconst declared = previousMaterial.clone( 0 );\n\t\t\t\tdeclared.inherited = true;\n\t\t\t\tthis.object.materials.push( declared );\n\n\t\t\t}\n\n\t\t\tthis.objects.push( this.object );\n\n\t\t},\n\n\t\tfinalize: function () {\n\n\t\t\tif ( this.object && typeof this.object._finalize === 'function' ) {\n\n\t\t\t\tthis.object._finalize( true );\n\n\t\t\t}\n\n\t\t},\n\n\t\tparseVertexIndex: function ( value, len ) {\n\n\t\t\tconst index = parseInt( value, 10 );\n\t\t\treturn ( index >= 0 ? index - 1 : index + len / 3 ) * 3;\n\n\t\t},\n\n\t\tparseNormalIndex: function ( value, len ) {\n\n\t\t\tconst index = parseInt( value, 10 );\n\t\t\treturn ( index >= 0 ? index - 1 : index + len / 3 ) * 3;\n\n\t\t},\n\n\t\tparseUVIndex: function ( value, len ) {\n\n\t\t\tconst index = parseInt( value, 10 );\n\t\t\treturn ( index >= 0 ? index - 1 : index + len / 2 ) * 2;\n\n\t\t},\n\n\t\taddVertex: function ( a, b, c ) {\n\n\t\t\tconst src = this.vertices;\n\t\t\tconst dst = this.object.geometry.vertices;\n\n\t\t\tdst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );\n\t\t\tdst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );\n\t\t\tdst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );\n\n\t\t},\n\n\t\taddVertexPoint: function ( a ) {\n\n\t\t\tconst src = this.vertices;\n\t\t\tconst dst = this.object.geometry.vertices;\n\n\t\t\tdst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );\n\n\t\t},\n\n\t\taddVertexLine: function ( a ) {\n\n\t\t\tconst src = this.vertices;\n\t\t\tconst dst = this.object.geometry.vertices;\n\n\t\t\tdst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );\n\n\t\t},\n\n\t\taddNormal: function ( a, b, c ) {\n\n\t\t\tconst src = this.normals;\n\t\t\tconst dst = this.object.geometry.normals;\n\n\t\t\tdst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );\n\t\t\tdst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );\n\t\t\tdst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );\n\n\t\t},\n\n\t\taddFaceNormal: function ( a, b, c ) {\n\n\t\t\tconst src = this.vertices;\n\t\t\tconst dst = this.object.geometry.normals;\n\n\t\t\t_vA.fromArray( src, a );\n\t\t\t_vB.fromArray( src, b );\n\t\t\t_vC.fromArray( src, c );\n\n\t\t\t_cb.subVectors( _vC, _vB );\n\t\t\t_ab.subVectors( _vA, _vB );\n\t\t\t_cb.cross( _ab );\n\n\t\t\t_cb.normalize();\n\n\t\t\tdst.push( _cb.x, _cb.y, _cb.z );\n\t\t\tdst.push( _cb.x, _cb.y, _cb.z );\n\t\t\tdst.push( _cb.x, _cb.y, _cb.z );\n\n\t\t},\n\n\t\taddColor: function ( a, b, c ) {\n\n\t\t\tconst src = this.colors;\n\t\t\tconst dst = this.object.geometry.colors;\n\n\t\t\tif ( src[ a ] !== undefined ) dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );\n\t\t\tif ( src[ b ] !== undefined ) dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );\n\t\t\tif ( src[ c ] !== undefined ) dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );\n\n\t\t},\n\n\t\taddUV: function ( a, b, c ) {\n\n\t\t\tconst src = this.uvs;\n\t\t\tconst dst = this.object.geometry.uvs;\n\n\t\t\tdst.push( src[ a + 0 ], src[ a + 1 ] );\n\t\t\tdst.push( src[ b + 0 ], src[ b + 1 ] );\n\t\t\tdst.push( src[ c + 0 ], src[ c + 1 ] );\n\n\t\t},\n\n\t\taddDefaultUV: function () {\n\n\t\t\tconst dst = this.object.geometry.uvs;\n\n\t\t\tdst.push( 0, 0 );\n\t\t\tdst.push( 0, 0 );\n\t\t\tdst.push( 0, 0 );\n\n\t\t},\n\n\t\taddUVLine: function ( a ) {\n\n\t\t\tconst src = this.uvs;\n\t\t\tconst dst = this.object.geometry.uvs;\n\n\t\t\tdst.push( src[ a + 0 ], src[ a + 1 ] );\n\n\t\t},\n\n\t\taddFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) {\n\n\t\t\tconst vLen = this.vertices.length;\n\n\t\t\tlet ia = this.parseVertexIndex( a, vLen );\n\t\t\tlet ib = this.parseVertexIndex( b, vLen );\n\t\t\tlet ic = this.parseVertexIndex( c, vLen );\n\n\t\t\tthis.addVertex( ia, ib, ic );\n\t\t\tthis.addColor( ia, ib, ic );\n\n\t\t\t// normals\n\n\t\t\tif ( na !== undefined && na !== '' ) {\n\n\t\t\t\tconst nLen = this.normals.length;\n\n\t\t\t\tia = this.parseNormalIndex( na, nLen );\n\t\t\t\tib = this.parseNormalIndex( nb, nLen );\n\t\t\t\tic = this.parseNormalIndex( nc, nLen );\n\n\t\t\t\tthis.addNormal( ia, ib, ic );\n\n\t\t\t} else {\n\n\t\t\t\tthis.addFaceNormal( ia, ib, ic );\n\n\t\t\t}\n\n\t\t\t// uvs\n\n\t\t\tif ( ua !== undefined && ua !== '' ) {\n\n\t\t\t\tconst uvLen = this.uvs.length;\n\n\t\t\t\tia = this.parseUVIndex( ua, uvLen );\n\t\t\t\tib = this.parseUVIndex( ub, uvLen );\n\t\t\t\tic = this.parseUVIndex( uc, uvLen );\n\n\t\t\t\tthis.addUV( ia, ib, ic );\n\n\t\t\t\tthis.object.geometry.hasUVIndices = true;\n\n\t\t\t} else {\n\n\t\t\t\t// add placeholder values (for inconsistent face definitions)\n\n\t\t\t\tthis.addDefaultUV();\n\n\t\t\t}\n\n\t\t},\n\n\t\taddPointGeometry: function ( vertices ) {\n\n\t\t\tthis.object.geometry.type = 'Points';\n\n\t\t\tconst vLen = this.vertices.length;\n\n\t\t\tfor ( let vi = 0, l = vertices.length; vi < l; vi ++ ) {\n\n\t\t\t\tconst index = this.parseVertexIndex( vertices[ vi ], vLen );\n\n\t\t\t\tthis.addVertexPoint( index );\n\t\t\t\tthis.addColor( index );\n\n\t\t\t}\n\n\t\t},\n\n\t\taddLineGeometry: function ( vertices, uvs ) {\n\n\t\t\tthis.object.geometry.type = 'Line';\n\n\t\t\tconst vLen = this.vertices.length;\n\t\t\tconst uvLen = this.uvs.length;\n\n\t\t\tfor ( let vi = 0, l = vertices.length; vi < l; vi ++ ) {\n\n\t\t\t\tthis.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) );\n\n\t\t\t}\n\n\t\t\tfor ( let uvi = 0, l = uvs.length; uvi < l; uvi ++ ) {\n\n\t\t\t\tthis.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) );\n\n\t\t\t}\n\n\t\t}\n\n\t};\n\n\tstate.startObject( '', false );\n\n\treturn state;\n\n}\n\n\n/**\n * A loader for the OBJ format.\n *\n * The [OBJ format](https://en.wikipedia.org/wiki/Wavefront_.obj_file) is a simple data-format that\n * represents 3D geometry in a human readable format as the position of each vertex, the UV position of\n * each texture coordinate vertex, vertex normals, and the faces that make each polygon defined as a list\n * of vertices, and texture vertices.\n *\n * ```js\n * const loader = new OBJLoader();\n * const object = await loader.loadAsync( 'models/monster.obj' );\n * scene.add( object );\n * ```\n *\n * @augments Loader\n * @three_import import { OBJLoader } from 'three/addons/loaders/OBJLoader.js';\n */\nclass OBJLoader extends Loader {\n\n\t/**\n\t * Constructs a new OBJ loader.\n\t *\n\t * @param {LoadingManager} [manager] - The loading manager.\n\t */\n\tconstructor( manager ) {\n\n\t\tsuper( manager );\n\n\t\t/**\n\t\t * A reference to a material creator.\n\t\t *\n\t\t * @type {?MaterialCreator}\n\t\t * @default null\n\t\t */\n\t\tthis.materials = null;\n\n\t}\n\n\t/**\n\t * Starts loading from the given URL and passes the loaded OBJ asset\n\t * to the `onLoad()` callback.\n\t *\n\t * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.\n\t * @param {function(Group)} onLoad - Executed when the loading process has been finished.\n\t * @param {onProgressCallback} onProgress - Executed while the loading is in progress.\n\t * @param {onErrorCallback} onError - Executed when errors occur.\n\t */\n\tload( url, onLoad, onProgress, onError ) {\n\n\t\tconst scope = this;\n\n\t\tconst loader = new FileLoader( this.manager );\n\t\tloader.setPath( this.path );\n\t\tloader.setRequestHeader( this.requestHeader );\n\t\tloader.setWithCredentials( this.withCredentials );\n\t\tloader.load( url, function ( text ) {\n\n\t\t\ttry {\n\n\t\t\t\tonLoad( scope.parse( text ) );\n\n\t\t\t} catch ( e ) {\n\n\t\t\t\tif ( onError ) {\n\n\t\t\t\t\tonError( e );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.error( e );\n\n\t\t\t\t}\n\n\t\t\t\tscope.manager.itemError( url );\n\n\t\t\t}\n\n\t\t}, onProgress, onError );\n\n\t}\n\n\t/**\n\t * Sets the material creator for this OBJ. This object is loaded via {@link MTLLoader}.\n\t *\n\t * @param {MaterialCreator} materials - An object that creates the materials for this OBJ.\n\t * @return {OBJLoader} A reference to this loader.\n\t */\n\tsetMaterials( materials ) {\n\n\t\tthis.materials = materials;\n\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Parses the given OBJ data and returns the resulting group.\n\t *\n\t * @param {string} text - The raw OBJ data as a string.\n\t * @return {Group} The parsed OBJ.\n\t */\n\tparse( text ) {\n\n\t\tconst state = new ParserState();\n\n\t\tif ( text.indexOf( '\\r\\n' ) !== - 1 ) {\n\n\t\t\t// This is faster than String.split with regex that splits on both\n\t\t\ttext = text.replace( /\\r\\n/g, '\\n' );\n\n\t\t}\n\n\t\tif ( text.indexOf( '\\\\\\n' ) !== - 1 ) {\n\n\t\t\t// join lines separated by a line continuation character (\\)\n\t\t\ttext = text.replace( /\\\\\\n/g, '' );\n\n\t\t}\n\n\t\tconst lines = text.split( '\\n' );\n\t\tlet result = [];\n\n\t\tfor ( let i = 0, l = lines.length; i < l; i ++ ) {\n\n\t\t\tconst line = lines[ i ].trimStart();\n\n\t\t\tif ( line.length === 0 ) continue;\n\n\t\t\tconst lineFirstChar = line.charAt( 0 );\n\n\t\t\t// @todo invoke passed in handler if any\n\t\t\tif ( lineFirstChar === '#' ) continue; // skip comments\n\n\t\t\tif ( lineFirstChar === 'v' ) {\n\n\t\t\t\tconst data = line.split( _face_vertex_data_separator_pattern );\n\n\t\t\t\tswitch ( data[ 0 ] ) {\n\n\t\t\t\t\tcase 'v':\n\t\t\t\t\t\tstate.vertices.push(\n\t\t\t\t\t\t\tparseFloat( data[ 1 ] ),\n\t\t\t\t\t\t\tparseFloat( data[ 2 ] ),\n\t\t\t\t\t\t\tparseFloat( data[ 3 ] )\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif ( data.length >= 7 ) {\n\n\t\t\t\t\t\t\t_color.setRGB(\n\t\t\t\t\t\t\t\tparseFloat( data[ 4 ] ),\n\t\t\t\t\t\t\t\tparseFloat( data[ 5 ] ),\n\t\t\t\t\t\t\t\tparseFloat( data[ 6 ] ),\n\t\t\t\t\t\t\t\tSRGBColorSpace\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tstate.colors.push( _color.r, _color.g, _color.b );\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t// if no colors are defined, add placeholders so color and vertex indices match\n\n\t\t\t\t\t\t\tstate.colors.push( undefined, undefined, undefined );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'vn':\n\t\t\t\t\t\tstate.normals.push(\n\t\t\t\t\t\t\tparseFloat( data[ 1 ] ),\n\t\t\t\t\t\t\tparseFloat( data[ 2 ] ),\n\t\t\t\t\t\t\tparseFloat( data[ 3 ] )\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'vt':\n\t\t\t\t\t\tstate.uvs.push(\n\t\t\t\t\t\t\tparseFloat( data[ 1 ] ),\n\t\t\t\t\t\t\tparseFloat( data[ 2 ] )\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t} else if ( lineFirstChar === 'f' ) {\n\n\t\t\t\tconst lineData = line.slice( 1 ).trim();\n\t\t\t\tconst vertexData = lineData.split( _face_vertex_data_separator_pattern );\n\t\t\t\tconst faceVertices = [];\n\n\t\t\t\t// Parse the face vertex data into an easy to work with format\n\n\t\t\t\tfor ( let j = 0, jl = vertexData.length; j < jl; j ++ ) {\n\n\t\t\t\t\tconst vertex = vertexData[ j ];\n\n\t\t\t\t\tif ( vertex.length > 0 ) {\n\n\t\t\t\t\t\tconst vertexParts = vertex.split( '/' );\n\t\t\t\t\t\tfaceVertices.push( vertexParts );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\t// Draw an edge between the first vertex and all subsequent vertices to form an n-gon\n\n\t\t\t\tconst v1 = faceVertices[ 0 ];\n\n\t\t\t\tfor ( let j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) {\n\n\t\t\t\t\tconst v2 = faceVertices[ j ];\n\t\t\t\t\tconst v3 = faceVertices[ j + 1 ];\n\n\t\t\t\t\tstate.addFace(\n\t\t\t\t\t\tv1[ 0 ], v2[ 0 ], v3[ 0 ],\n\t\t\t\t\t\tv1[ 1 ], v2[ 1 ], v3[ 1 ],\n\t\t\t\t\t\tv1[ 2 ], v2[ 2 ], v3[ 2 ]\n\t\t\t\t\t);\n\n\t\t\t\t}\n\n\t\t\t} else if ( lineFirstChar === 'l' ) {\n\n\t\t\t\tconst lineParts = line.substring( 1 ).trim().split( ' ' );\n\t\t\t\tlet lineVertices = [];\n\t\t\t\tconst lineUVs = [];\n\n\t\t\t\tif ( line.indexOf( '/' ) === - 1 ) {\n\n\t\t\t\t\tlineVertices = lineParts;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tfor ( let li = 0, llen = lineParts.length; li < llen; li ++ ) {\n\n\t\t\t\t\t\tconst parts = lineParts[ li ].split( '/' );\n\n\t\t\t\t\t\tif ( parts[ 0 ] !== '' ) lineVertices.push( parts[ 0 ] );\n\t\t\t\t\t\tif ( parts[ 1 ] !== '' ) lineUVs.push( parts[ 1 ] );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tstate.addLineGeometry( lineVertices, lineUVs );\n\n\t\t\t} else if ( lineFirstChar === 'p' ) {\n\n\t\t\t\tconst lineData = line.slice( 1 ).trim();\n\t\t\t\tconst pointData = lineData.split( ' ' );\n\n\t\t\t\tstate.addPointGeometry( pointData );\n\n\t\t\t} else if ( ( result = _object_pattern.exec( line ) ) !== null ) {\n\n\t\t\t\t// o object_name\n\t\t\t\t// or\n\t\t\t\t// g group_name\n\n\t\t\t\t// WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869\n\t\t\t\t// let name = result[ 0 ].slice( 1 ).trim();\n\t\t\t\tconst name = ( ' ' + result[ 0 ].slice( 1 ).trim() ).slice( 1 );\n\n\t\t\t\tstate.startObject( name );\n\n\t\t\t} else if ( _material_use_pattern.test( line ) ) {\n\n\t\t\t\t// material\n\n\t\t\t\tstate.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries );\n\n\t\t\t} else if ( _material_library_pattern.test( line ) ) {\n\n\t\t\t\t// mtl file\n\n\t\t\t\tstate.materialLibraries.push( line.substring( 7 ).trim() );\n\n\t\t\t} else if ( _map_use_pattern.test( line ) ) {\n\n\t\t\t\t// the line is parsed but ignored since the loader assumes textures are defined MTL files\n\t\t\t\t// (according to https://www.okino.com/conv/imp_wave.htm, 'usemap' is the old-style Wavefront texture reference method)\n\n\t\t\t\tconsole.warn( 'THREE.OBJLoader: Rendering identifier \"usemap\" not supported. Textures must be defined in MTL files.' );\n\n\t\t\t} else if ( lineFirstChar === 's' ) {\n\n\t\t\t\tresult = line.split( ' ' );\n\n\t\t\t\t// smooth shading\n\n\t\t\t\t// @todo Handle files that have varying smooth values for a set of faces inside one geometry,\n\t\t\t\t// but does not define a usemtl for each face set.\n\t\t\t\t// This should be detected and a dummy material created (later MultiMaterial and geometry groups).\n\t\t\t\t// This requires some care to not create extra material on each smooth value for \"normal\" obj files.\n\t\t\t\t// where explicit usemtl defines geometry groups.\n\t\t\t\t// Example asset: examples/models/obj/cerberus/Cerberus.obj\n\n\t\t\t\t/*\n\t\t\t\t\t * http://paulbourke.net/dataformats/obj/\n\t\t\t\t\t *\n\t\t\t\t\t * From chapter \"Grouping\" Syntax explanation \"s group_number\":\n\t\t\t\t\t * \"group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off.\n\t\t\t\t\t * Polygonal elements use group numbers to put elements in different smoothing groups. For free-form\n\t\t\t\t\t * surfaces, smoothing groups are either turned on or off; there is no difference between values greater\n\t\t\t\t\t * than 0.\"\n\t\t\t\t\t */\n\t\t\t\tif ( result.length > 1 ) {\n\n\t\t\t\t\tconst value = result[ 1 ].trim().toLowerCase();\n\t\t\t\t\tstate.object.smooth = ( value !== '0' && value !== 'off' );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// ZBrush can produce \"s\" lines #11707\n\t\t\t\t\tstate.object.smooth = true;\n\n\t\t\t\t}\n\n\t\t\t\tconst material = state.object.currentMaterial();\n\t\t\t\tif ( material ) material.smooth = state.object.smooth;\n\n\t\t\t} else {\n\n\t\t\t\t// Handle null terminated files without exception\n\t\t\t\tif ( line === '\\0' ) continue;\n\n\t\t\t\tconsole.warn( 'THREE.OBJLoader: Unexpected line: \"' + line + '\"' );\n\n\t\t\t}\n\n\t\t}\n\n\t\tstate.finalize();\n\n\t\tconst container = new Group();\n\t\tcontainer.materialLibraries = [].concat( state.materialLibraries );\n\n\t\tconst hasPrimitives = ! ( state.objects.length === 1 && state.objects[ 0 ].geometry.vertices.length === 0 );\n\n\t\tif ( hasPrimitives === true ) {\n\n\t\t\tfor ( let i = 0, l = state.objects.length; i < l; i ++ ) {\n\n\t\t\t\tconst object = state.objects[ i ];\n\t\t\t\tconst geometry = object.geometry;\n\t\t\t\tconst materials = object.materials;\n\t\t\t\tconst isLine = ( geometry.type === 'Line' );\n\t\t\t\tconst isPoints = ( geometry.type === 'Points' );\n\t\t\t\tlet hasVertexColors = false;\n\n\t\t\t\t// Skip o/g line declarations that did not follow with any faces\n\t\t\t\tif ( geometry.vertices.length === 0 ) continue;\n\n\t\t\t\tconst buffergeometry = new BufferGeometry();\n\n\t\t\t\tbuffergeometry.setAttribute( 'position', new Float32BufferAttribute( geometry.vertices, 3 ) );\n\n\t\t\t\tif ( geometry.normals.length > 0 ) {\n\n\t\t\t\t\tbuffergeometry.setAttribute( 'normal', new Float32BufferAttribute( geometry.normals, 3 ) );\n\n\t\t\t\t}\n\n\t\t\t\tif ( geometry.colors.length > 0 ) {\n\n\t\t\t\t\thasVertexColors = true;\n\t\t\t\t\tbuffergeometry.setAttribute( 'color', new Float32BufferAttribute( geometry.colors, 3 ) );\n\n\t\t\t\t}\n\n\t\t\t\tif ( geometry.hasUVIndices === true ) {\n\n\t\t\t\t\tbuffergeometry.setAttribute( 'uv', new Float32BufferAttribute( geometry.uvs, 2 ) );\n\n\t\t\t\t}\n\n\t\t\t\t// Create materials\n\n\t\t\t\tconst createdMaterials = [];\n\n\t\t\t\tfor ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {\n\n\t\t\t\t\tconst sourceMaterial = materials[ mi ];\n\t\t\t\t\tconst materialHash = sourceMaterial.name + '_' + sourceMaterial.smooth + '_' + hasVertexColors;\n\t\t\t\t\tlet material = state.materials[ materialHash ];\n\n\t\t\t\t\tif ( this.materials !== null ) {\n\n\t\t\t\t\t\tmaterial = this.materials.create( sourceMaterial.name );\n\n\t\t\t\t\t\t// mtl etc. loaders probably can't create line materials correctly, copy properties to a line material.\n\t\t\t\t\t\tif ( isLine && material && ! ( material instanceof LineBasicMaterial ) ) {\n\n\t\t\t\t\t\t\tconst materialLine = new LineBasicMaterial();\n\t\t\t\t\t\t\tMaterial.prototype.copy.call( materialLine, material );\n\t\t\t\t\t\t\tmaterialLine.color.copy( material.color );\n\t\t\t\t\t\t\tmaterial = materialLine;\n\n\t\t\t\t\t\t} else if ( isPoints && material && ! ( material instanceof PointsMaterial ) ) {\n\n\t\t\t\t\t\t\tconst materialPoints = new PointsMaterial( { size: 10, sizeAttenuation: false } );\n\t\t\t\t\t\t\tMaterial.prototype.copy.call( materialPoints, material );\n\t\t\t\t\t\t\tmaterialPoints.color.copy( material.color );\n\t\t\t\t\t\t\tmaterialPoints.map = material.map;\n\t\t\t\t\t\t\tmaterial = materialPoints;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( material === undefined ) {\n\n\t\t\t\t\t\tif ( isLine ) {\n\n\t\t\t\t\t\t\tmaterial = new LineBasicMaterial();\n\n\t\t\t\t\t\t} else if ( isPoints ) {\n\n\t\t\t\t\t\t\tmaterial = new PointsMaterial( { size: 1, sizeAttenuation: false } );\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tmaterial = new MeshPhongMaterial();\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmaterial.name = sourceMaterial.name;\n\t\t\t\t\t\tmaterial.flatShading = sourceMaterial.smooth ? false : true;\n\t\t\t\t\t\tmaterial.vertexColors = hasVertexColors;\n\n\t\t\t\t\t\tstate.materials[ materialHash ] = material;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tcreatedMaterials.push( material );\n\n\t\t\t\t}\n\n\t\t\t\t// Create mesh\n\n\t\t\t\tlet mesh;\n\n\t\t\t\tif ( createdMaterials.length > 1 ) {\n\n\t\t\t\t\tfor ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {\n\n\t\t\t\t\t\tconst sourceMaterial = materials[ mi ];\n\t\t\t\t\t\tbuffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( isLine ) {\n\n\t\t\t\t\t\tmesh = new LineSegments( buffergeometry, createdMaterials );\n\n\t\t\t\t\t} else if ( isPoints ) {\n\n\t\t\t\t\t\tmesh = new Points( buffergeometry, createdMaterials );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tmesh = new Mesh( buffergeometry, createdMaterials );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( isLine ) {\n\n\t\t\t\t\t\tmesh = new LineSegments( buffergeometry, createdMaterials[ 0 ] );\n\n\t\t\t\t\t} else if ( isPoints ) {\n\n\t\t\t\t\t\tmesh = new Points( buffergeometry, createdMaterials[ 0 ] );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tmesh = new Mesh( buffergeometry, createdMaterials[ 0 ] );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tmesh.name = object.name;\n\n\t\t\t\tcontainer.add( mesh );\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t// if there is only the default parser state object with no geometry data, interpret data as point cloud\n\n\t\t\tif ( state.vertices.length > 0 ) {\n\n\t\t\t\tconst material = new PointsMaterial( { size: 1, sizeAttenuation: false } );\n\n\t\t\t\tconst buffergeometry = new BufferGeometry();\n\n\t\t\t\tbuffergeometry.setAttribute( 'position', new Float32BufferAttribute( state.vertices, 3 ) );\n\n\t\t\t\tif ( state.colors.length > 0 && state.colors[ 0 ] !== undefined ) {\n\n\t\t\t\t\tbuffergeometry.setAttribute( 'color', new Float32BufferAttribute( state.colors, 3 ) );\n\t\t\t\t\tmaterial.vertexColors = true;\n\n\t\t\t\t}\n\n\t\t\t\tconst points = new Points( buffergeometry, material );\n\t\t\t\tcontainer.add( points );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn container;\n\n\t}\n\n}\n\nexport { OBJLoader };\n","import {\n\tBufferAttribute,\n\tBufferGeometry,\n\tFloat32BufferAttribute,\n\tInstancedBufferAttribute,\n\tInterleavedBuffer,\n\tInterleavedBufferAttribute,\n\tTriangleFanDrawMode,\n\tTriangleStripDrawMode,\n\tTrianglesDrawMode,\n\tVector3,\n} from 'three';\n\n/**\n * @module BufferGeometryUtils\n * @three_import import * as BufferGeometryUtils from 'three/addons/utils/BufferGeometryUtils.js';\n */\n\n/**\n * Computes vertex tangents using the MikkTSpace algorithm. MikkTSpace generates the same tangents consistently,\n * and is used in most modelling tools and normal map bakers. Use MikkTSpace for materials with normal maps,\n * because inconsistent tangents may lead to subtle visual issues in the normal map, particularly around mirrored\n * UV seams.\n *\n * In comparison to this method, {@link BufferGeometry#computeTangents} (a custom algorithm) generates tangents that\n * probably will not match the tangents in other software. The custom algorithm is sufficient for general use with a\n * custom material, and may be faster than MikkTSpace.\n *\n * Returns the original BufferGeometry. Indexed geometries will be de-indexed. Requires position, normal, and uv attributes.\n *\n * @param {BufferGeometry} geometry - The geometry to compute tangents for.\n * @param {Object} MikkTSpace - Instance of `examples/jsm/libs/mikktspace.module.js`, or `mikktspace` npm package.\n * Await `MikkTSpace.ready` before use.\n * @param {boolean} [negateSign=true] - Whether to negate the sign component (.w) of each tangent.\n * Required for normal map conventions in some formats, including glTF.\n * @return {BufferGeometry} The updated geometry.\n */\nfunction computeMikkTSpaceTangents( geometry, MikkTSpace, negateSign = true ) {\n\n\tif ( ! MikkTSpace || ! MikkTSpace.isReady ) {\n\n\t\tthrow new Error( 'BufferGeometryUtils: Initialized MikkTSpace library required.' );\n\n\t}\n\n\tif ( ! geometry.hasAttribute( 'position' ) || ! geometry.hasAttribute( 'normal' ) || ! geometry.hasAttribute( 'uv' ) ) {\n\n\t\tthrow new Error( 'BufferGeometryUtils: Tangents require \"position\", \"normal\", and \"uv\" attributes.' );\n\n\t}\n\n\tfunction getAttributeArray( attribute ) {\n\n\t\tif ( attribute.normalized || attribute.isInterleavedBufferAttribute ) {\n\n\t\t\tconst dstArray = new Float32Array( attribute.count * attribute.itemSize );\n\n\t\t\tfor ( let i = 0, j = 0; i < attribute.count; i ++ ) {\n\n\t\t\t\tdstArray[ j ++ ] = attribute.getX( i );\n\t\t\t\tdstArray[ j ++ ] = attribute.getY( i );\n\n\t\t\t\tif ( attribute.itemSize > 2 ) {\n\n\t\t\t\t\tdstArray[ j ++ ] = attribute.getZ( i );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn dstArray;\n\n\t\t}\n\n\t\tif ( attribute.array instanceof Float32Array ) {\n\n\t\t\treturn attribute.array;\n\n\t\t}\n\n\t\treturn new Float32Array( attribute.array );\n\n\t}\n\n\t// MikkTSpace algorithm requires non-indexed input.\n\n\tconst _geometry = geometry.index ? geometry.toNonIndexed() : geometry;\n\n\t// Compute vertex tangents.\n\n\tconst tangents = MikkTSpace.generateTangents(\n\n\t\tgetAttributeArray( _geometry.attributes.position ),\n\t\tgetAttributeArray( _geometry.attributes.normal ),\n\t\tgetAttributeArray( _geometry.attributes.uv )\n\n\t);\n\n\t// Texture coordinate convention of glTF differs from the apparent\n\t// default of the MikkTSpace library; .w component must be flipped.\n\n\tif ( negateSign ) {\n\n\t\tfor ( let i = 3; i < tangents.length; i += 4 ) {\n\n\t\t\ttangents[ i ] *= - 1;\n\n\t\t}\n\n\t}\n\n\t//\n\n\t_geometry.setAttribute( 'tangent', new BufferAttribute( tangents, 4 ) );\n\n\tif ( geometry !== _geometry ) {\n\n\t\tgeometry.copy( _geometry );\n\n\t}\n\n\treturn geometry;\n\n}\n\n/**\n * Merges a set of geometries into a single instance. All geometries must have compatible attributes.\n *\n * @param {Array<BufferGeometry>} geometries - The geometries to merge.\n * @param {boolean} [useGroups=false] - Whether to use groups or not.\n * @return {?BufferGeometry} The merged geometry. Returns `null` if the merge does not succeed.\n */\nfunction mergeGeometries( geometries, useGroups = false ) {\n\n\tconst isIndexed = geometries[ 0 ].index !== null;\n\n\tconst attributesUsed = new Set( Object.keys( geometries[ 0 ].attributes ) );\n\tconst morphAttributesUsed = new Set( Object.keys( geometries[ 0 ].morphAttributes ) );\n\n\tconst attributes = {};\n\tconst morphAttributes = {};\n\n\tconst morphTargetsRelative = geometries[ 0 ].morphTargetsRelative;\n\n\tconst mergedGeometry = new BufferGeometry();\n\n\tlet offset = 0;\n\n\tfor ( let i = 0; i < geometries.length; ++ i ) {\n\n\t\tconst geometry = geometries[ i ];\n\t\tlet attributesCount = 0;\n\n\t\t// ensure that all geometries are indexed, or none\n\n\t\tif ( isIndexed !== ( geometry.index !== null ) ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index ' + i + '. All geometries must have compatible attributes; make sure index attribute exists among all geometries, or in none of them.' );\n\t\t\treturn null;\n\n\t\t}\n\n\t\t// gather attributes, exit early if they're different\n\n\t\tfor ( const name in geometry.attributes ) {\n\n\t\t\tif ( ! attributesUsed.has( name ) ) {\n\n\t\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index ' + i + '. All geometries must have compatible attributes; make sure \"' + name + '\" attribute exists among all geometries, or in none of them.' );\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t\tif ( attributes[ name ] === undefined ) attributes[ name ] = [];\n\n\t\t\tattributes[ name ].push( geometry.attributes[ name ] );\n\n\t\t\tattributesCount ++;\n\n\t\t}\n\n\t\t// ensure geometries have the same number of attributes\n\n\t\tif ( attributesCount !== attributesUsed.size ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index ' + i + '. Make sure all geometries have the same number of attributes.' );\n\t\t\treturn null;\n\n\t\t}\n\n\t\t// gather morph attributes, exit early if they're different\n\n\t\tif ( morphTargetsRelative !== geometry.morphTargetsRelative ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index ' + i + '. .morphTargetsRelative must be consistent throughout all geometries.' );\n\t\t\treturn null;\n\n\t\t}\n\n\t\tfor ( const name in geometry.morphAttributes ) {\n\n\t\t\tif ( ! morphAttributesUsed.has( name ) ) {\n\n\t\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index ' + i + '. .morphAttributes must be consistent throughout all geometries.' );\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t\tif ( morphAttributes[ name ] === undefined ) morphAttributes[ name ] = [];\n\n\t\t\tmorphAttributes[ name ].push( geometry.morphAttributes[ name ] );\n\n\t\t}\n\n\t\tif ( useGroups ) {\n\n\t\t\tlet count;\n\n\t\t\tif ( isIndexed ) {\n\n\t\t\t\tcount = geometry.index.count;\n\n\t\t\t} else if ( geometry.attributes.position !== undefined ) {\n\n\t\t\t\tcount = geometry.attributes.position.count;\n\n\t\t\t} else {\n\n\t\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index ' + i + '. The geometry must have either an index or a position attribute' );\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t\tmergedGeometry.addGroup( offset, count, i );\n\n\t\t\toffset += count;\n\n\t\t}\n\n\t}\n\n\t// merge indices\n\n\tif ( isIndexed ) {\n\n\t\tlet indexOffset = 0;\n\t\tconst mergedIndex = [];\n\n\t\tfor ( let i = 0; i < geometries.length; ++ i ) {\n\n\t\t\tconst index = geometries[ i ].index;\n\n\t\t\tfor ( let j = 0; j < index.count; ++ j ) {\n\n\t\t\t\tmergedIndex.push( index.getX( j ) + indexOffset );\n\n\t\t\t}\n\n\t\t\tindexOffset += geometries[ i ].attributes.position.count;\n\n\t\t}\n\n\t\tmergedGeometry.setIndex( mergedIndex );\n\n\t}\n\n\t// merge attributes\n\n\tfor ( const name in attributes ) {\n\n\t\tconst mergedAttribute = mergeAttributes( attributes[ name ] );\n\n\t\tif ( ! mergedAttribute ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed while trying to merge the ' + name + ' attribute.' );\n\t\t\treturn null;\n\n\t\t}\n\n\t\tmergedGeometry.setAttribute( name, mergedAttribute );\n\n\t}\n\n\t// merge morph attributes\n\n\tfor ( const name in morphAttributes ) {\n\n\t\tconst numMorphTargets = morphAttributes[ name ][ 0 ].length;\n\t\tif ( numMorphTargets === 0 ) continue;\n\n\t\tmergedGeometry.morphAttributes = mergedGeometry.morphAttributes || {};\n\t\tmergedGeometry.morphAttributes[ name ] = [];\n\n\t\tfor ( let i = 0; i < numMorphTargets; ++ i ) {\n\n\t\t\tconst morphAttributesToMerge = [];\n\n\t\t\tfor ( let j = 0; j < morphAttributes[ name ].length; ++ j ) {\n\n\t\t\t\tmorphAttributesToMerge.push( morphAttributes[ name ][ j ][ i ] );\n\n\t\t\t}\n\n\t\t\tconst mergedMorphAttribute = mergeAttributes( morphAttributesToMerge );\n\n\t\t\tif ( ! mergedMorphAttribute ) {\n\n\t\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed while trying to merge the ' + name + ' morphAttribute.' );\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t\tmergedGeometry.morphAttributes[ name ].push( mergedMorphAttribute );\n\n\t\t}\n\n\t}\n\n\treturn mergedGeometry;\n\n}\n\n/**\n * Merges a set of attributes into a single instance. All attributes must have compatible properties and types.\n * Instances of {@link InterleavedBufferAttribute} are not supported.\n *\n * @param {Array<BufferAttribute>} attributes - The attributes to merge.\n * @return {?BufferAttribute} The merged attribute. Returns `null` if the merge does not succeed.\n */\nfunction mergeAttributes( attributes ) {\n\n\tlet TypedArray;\n\tlet itemSize;\n\tlet normalized;\n\tlet gpuType = - 1;\n\tlet arrayLength = 0;\n\n\tfor ( let i = 0; i < attributes.length; ++ i ) {\n\n\t\tconst attribute = attributes[ i ];\n\n\t\tif ( TypedArray === undefined ) TypedArray = attribute.array.constructor;\n\t\tif ( TypedArray !== attribute.array.constructor ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeAttributes() failed. BufferAttribute.array must be of consistent array types across matching attributes.' );\n\t\t\treturn null;\n\n\t\t}\n\n\t\tif ( itemSize === undefined ) itemSize = attribute.itemSize;\n\t\tif ( itemSize !== attribute.itemSize ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeAttributes() failed. BufferAttribute.itemSize must be consistent across matching attributes.' );\n\t\t\treturn null;\n\n\t\t}\n\n\t\tif ( normalized === undefined ) normalized = attribute.normalized;\n\t\tif ( normalized !== attribute.normalized ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeAttributes() failed. BufferAttribute.normalized must be consistent across matching attributes.' );\n\t\t\treturn null;\n\n\t\t}\n\n\t\tif ( gpuType === - 1 ) gpuType = attribute.gpuType;\n\t\tif ( gpuType !== attribute.gpuType ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeAttributes() failed. BufferAttribute.gpuType must be consistent across matching attributes.' );\n\t\t\treturn null;\n\n\t\t}\n\n\t\tarrayLength += attribute.count * itemSize;\n\n\t}\n\n\tconst array = new TypedArray( arrayLength );\n\tconst result = new BufferAttribute( array, itemSize, normalized );\n\tlet offset = 0;\n\n\tfor ( let i = 0; i < attributes.length; ++ i ) {\n\n\t\tconst attribute = attributes[ i ];\n\t\tif ( attribute.isInterleavedBufferAttribute ) {\n\n\t\t\tconst tupleOffset = offset / itemSize;\n\t\t\tfor ( let j = 0, l = attribute.count; j < l; j ++ ) {\n\n\t\t\t\tfor ( let c = 0; c < itemSize; c ++ ) {\n\n\t\t\t\t\tconst value = attribute.getComponent( j, c );\n\t\t\t\t\tresult.setComponent( j + tupleOffset, c, value );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tarray.set( attribute.array, offset );\n\n\t\t}\n\n\t\toffset += attribute.count * itemSize;\n\n\t}\n\n\tif ( gpuType !== undefined ) {\n\n\t\tresult.gpuType = gpuType;\n\n\t}\n\n\treturn result;\n\n}\n\n/**\n * Performs a deep clone of the given buffer attribute.\n *\n * @param {BufferAttribute} attribute - The attribute to clone.\n * @return {BufferAttribute} The cloned attribute.\n */\nfunction deepCloneAttribute( attribute ) {\n\n\tif ( attribute.isInstancedInterleavedBufferAttribute || attribute.isInterleavedBufferAttribute ) {\n\n\t\treturn deinterleaveAttribute( attribute );\n\n\t}\n\n\tif ( attribute.isInstancedBufferAttribute ) {\n\n\t\treturn new InstancedBufferAttribute().copy( attribute );\n\n\t}\n\n\treturn new BufferAttribute().copy( attribute );\n\n}\n\n/**\n * Interleaves a set of attributes and returns a new array of corresponding attributes that share a\n * single {@link InterleavedBuffer} instance. All attributes must have compatible types.\n *\n * @param {Array<BufferAttribute>} attributes - The attributes to interleave.\n * @return {?Array<InterleavedBufferAttribute>} An array of interleaved attributes. If interleave does not succeed, the method returns `null`.\n */\nfunction interleaveAttributes( attributes ) {\n\n\t// Interleaves the provided attributes into an InterleavedBuffer and returns\n\t// a set of InterleavedBufferAttributes for each attribute\n\tlet TypedArray;\n\tlet arrayLength = 0;\n\tlet stride = 0;\n\n\t// calculate the length and type of the interleavedBuffer\n\tfor ( let i = 0, l = attributes.length; i < l; ++ i ) {\n\n\t\tconst attribute = attributes[ i ];\n\n\t\tif ( TypedArray === undefined ) TypedArray = attribute.array.constructor;\n\t\tif ( TypedArray !== attribute.array.constructor ) {\n\n\t\t\tconsole.error( 'AttributeBuffers of different types cannot be interleaved' );\n\t\t\treturn null;\n\n\t\t}\n\n\t\tarrayLength += attribute.array.length;\n\t\tstride += attribute.itemSize;\n\n\t}\n\n\t// Create the set of buffer attributes\n\tconst interleavedBuffer = new InterleavedBuffer( new TypedArray( arrayLength ), stride );\n\tlet offset = 0;\n\tconst res = [];\n\tconst getters = [ 'getX', 'getY', 'getZ', 'getW' ];\n\tconst setters = [ 'setX', 'setY', 'setZ', 'setW' ];\n\n\tfor ( let j = 0, l = attributes.length; j < l; j ++ ) {\n\n\t\tconst attribute = attributes[ j ];\n\t\tconst itemSize = attribute.itemSize;\n\t\tconst count = attribute.count;\n\t\tconst iba = new InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, attribute.normalized );\n\t\tres.push( iba );\n\n\t\toffset += itemSize;\n\n\t\t// Move the data for each attribute into the new interleavedBuffer\n\t\t// at the appropriate offset\n\t\tfor ( let c = 0; c < count; c ++ ) {\n\n\t\t\tfor ( let k = 0; k < itemSize; k ++ ) {\n\n\t\t\t\tiba[ setters[ k ] ]( c, attribute[ getters[ k ] ]( c ) );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\treturn res;\n\n}\n\n/**\n * Returns a new, non-interleaved version of the given attribute.\n *\n * @param {InterleavedBufferAttribute} attribute - The interleaved attribute.\n * @return {BufferAttribute} The non-interleaved attribute.\n */\nfunction deinterleaveAttribute( attribute ) {\n\n\tconst cons = attribute.data.array.constructor;\n\tconst count = attribute.count;\n\tconst itemSize = attribute.itemSize;\n\tconst normalized = attribute.normalized;\n\n\tconst array = new cons( count * itemSize );\n\tlet newAttribute;\n\tif ( attribute.isInstancedInterleavedBufferAttribute ) {\n\n\t\tnewAttribute = new InstancedBufferAttribute( array, itemSize, normalized, attribute.meshPerAttribute );\n\n\t} else {\n\n\t\tnewAttribute = new BufferAttribute( array, itemSize, normalized );\n\n\t}\n\n\tfor ( let i = 0; i < count; i ++ ) {\n\n\t\tnewAttribute.setX( i, attribute.getX( i ) );\n\n\t\tif ( itemSize >= 2 ) {\n\n\t\t\tnewAttribute.setY( i, attribute.getY( i ) );\n\n\t\t}\n\n\t\tif ( itemSize >= 3 ) {\n\n\t\t\tnewAttribute.setZ( i, attribute.getZ( i ) );\n\n\t\t}\n\n\t\tif ( itemSize >= 4 ) {\n\n\t\t\tnewAttribute.setW( i, attribute.getW( i ) );\n\n\t\t}\n\n\t}\n\n\treturn newAttribute;\n\n}\n\n/**\n * Deinterleaves all attributes on the given geometry.\n *\n * @param {BufferGeometry} geometry - The geometry to deinterleave.\n */\nfunction deinterleaveGeometry( geometry ) {\n\n\tconst attributes = geometry.attributes;\n\tconst morphTargets = geometry.morphTargets;\n\tconst attrMap = new Map();\n\n\tfor ( const key in attributes ) {\n\n\t\tconst attr = attributes[ key ];\n\t\tif ( attr.isInterleavedBufferAttribute ) {\n\n\t\t\tif ( ! attrMap.has( attr ) ) {\n\n\t\t\t\tattrMap.set( attr, deinterleaveAttribute( attr ) );\n\n\t\t\t}\n\n\t\t\tattributes[ key ] = attrMap.get( attr );\n\n\t\t}\n\n\t}\n\n\tfor ( const key in morphTargets ) {\n\n\t\tconst attr = morphTargets[ key ];\n\t\tif ( attr.isInterleavedBufferAttribute ) {\n\n\t\t\tif ( ! attrMap.has( attr ) ) {\n\n\t\t\t\tattrMap.set( attr, deinterleaveAttribute( attr ) );\n\n\t\t\t}\n\n\t\t\tmorphTargets[ key ] = attrMap.get( attr );\n\n\t\t}\n\n\t}\n\n}\n\n/**\n * Returns the amount of bytes used by all attributes to represent the geometry.\n *\n * @param {BufferGeometry} geometry - The geometry.\n * @return {number} The estimate bytes used.\n */\nfunction estimateBytesUsed( geometry ) {\n\n\t// Return the estimated memory used by this geometry in bytes\n\t// Calculate using itemSize, count, and BYTES_PER_ELEMENT to account\n\t// for InterleavedBufferAttributes.\n\tlet mem = 0;\n\tfor ( const name in geometry.attributes ) {\n\n\t\tconst attr = geometry.getAttribute( name );\n\t\tmem += attr.count * attr.itemSize * attr.array.BYTES_PER_ELEMENT;\n\n\t}\n\n\tconst indices = geometry.getIndex();\n\tmem += indices ? indices.count * indices.itemSize * indices.array.BYTES_PER_ELEMENT : 0;\n\treturn mem;\n\n}\n\n/**\n * Returns a new geometry with vertices for which all similar vertex attributes (within tolerance) are merged.\n *\n * @param {BufferGeometry} geometry - The geometry to merge vertices for.\n * @param {number} [tolerance=1e-4] - The tolerance value.\n * @return {BufferGeometry} - The new geometry with merged vertices.\n */\nfunction mergeVertices( geometry, tolerance = 1e-4 ) {\n\n\ttolerance = Math.max( tolerance, Number.EPSILON );\n\n\t// Generate an index buffer if the geometry doesn't have one, or optimize it\n\t// if it's already available.\n\tconst hashToIndex = {};\n\tconst indices = geometry.getIndex();\n\tconst positions = geometry.getAttribute( 'position' );\n\tconst vertexCount = indices ? indices.count : positions.count;\n\n\t// next value for triangle indices\n\tlet nextIndex = 0;\n\n\t// attributes and new attribute arrays\n\tconst attributeNames = Object.keys( geometry.attributes );\n\tconst tmpAttributes = {};\n\tconst tmpMorphAttributes = {};\n\tconst newIndices = [];\n\tconst getters = [ 'getX', 'getY', 'getZ', 'getW' ];\n\tconst setters = [ 'setX', 'setY', 'setZ', 'setW' ];\n\n\t// Initialize the arrays, allocating space conservatively. Extra\n\t// space will be trimmed in the last step.\n\tfor ( let i = 0, l = attributeNames.length; i < l; i ++ ) {\n\n\t\tconst name = attributeNames[ i ];\n\t\tconst attr = geometry.attributes[ name ];\n\n\t\ttmpAttributes[ name ] = new attr.constructor(\n\t\t\tnew attr.array.constructor( attr.count * attr.itemSize ),\n\t\t\tattr.itemSize,\n\t\t\tattr.normalized\n\t\t);\n\n\t\tconst morphAttributes = geometry.morphAttributes[ name ];\n\t\tif ( morphAttributes ) {\n\n\t\t\tif ( ! tmpMorphAttributes[ name ] ) tmpMorphAttributes[ name ] = [];\n\t\t\tmorphAttributes.forEach( ( morphAttr, i ) => {\n\n\t\t\t\tconst array = new morphAttr.array.constructor( morphAttr.count * morphAttr.itemSize );\n\t\t\t\ttmpMorphAttributes[ name ][ i ] = new morphAttr.constructor( array, morphAttr.itemSize, morphAttr.normalized );\n\n\t\t\t} );\n\n\t\t}\n\n\t}\n\n\t// convert the error tolerance to an amount of decimal places to truncate to\n\tconst halfTolerance = tolerance * 0.5;\n\tconst exponent = Math.log10( 1 / tolerance );\n\tconst hashMultiplier = Math.pow( 10, exponent );\n\tconst hashAdditive = halfTolerance * hashMultiplier;\n\tfor ( let i = 0; i < vertexCount; i ++ ) {\n\n\t\tconst index = indices ? indices.getX( i ) : i;\n\n\t\t// Generate a hash for the vertex attributes at the current index 'i'\n\t\tlet hash = '';\n\t\tfor ( let j = 0, l = attributeNames.length; j < l; j ++ ) {\n\n\t\t\tconst name = attributeNames[ j ];\n\t\t\tconst attribute = geometry.getAttribute( name );\n\t\t\tconst itemSize = attribute.itemSize;\n\n\t\t\tfor ( let k = 0; k < itemSize; k ++ ) {\n\n\t\t\t\t// double tilde truncates the decimal value\n\t\t\t\thash += `${ ~ ~ ( attribute[ getters[ k ] ]( index ) * hashMultiplier + hashAdditive ) },`;\n\n\t\t\t}\n\n\t\t}\n\n\t\t// Add another reference to the vertex if it's already\n\t\t// used by another index\n\t\tif ( hash in hashToIndex ) {\n\n\t\t\tnewIndices.push( hashToIndex[ hash ] );\n\n\t\t} else {\n\n\t\t\t// copy data to the new index in the temporary attributes\n\t\t\tfor ( let j = 0, l = attributeNames.length; j < l; j ++ ) {\n\n\t\t\t\tconst name = attributeNames[ j ];\n\t\t\t\tconst attribute = geometry.getAttribute( name );\n\t\t\t\tconst morphAttributes = geometry.morphAttributes[ name ];\n\t\t\t\tconst itemSize = attribute.itemSize;\n\t\t\t\tconst newArray = tmpAttributes[ name ];\n\t\t\t\tconst newMorphArrays = tmpMorphAttributes[ name ];\n\n\t\t\t\tfor ( let k = 0; k < itemSize; k ++ ) {\n\n\t\t\t\t\tconst getterFunc = getters[ k ];\n\t\t\t\t\tconst setterFunc = setters[ k ];\n\t\t\t\t\tnewArray[ setterFunc ]( nextIndex, attribute[ getterFunc ]( index ) );\n\n\t\t\t\t\tif ( morphAttributes ) {\n\n\t\t\t\t\t\tfor ( let m = 0, ml = morphAttributes.length; m < ml; m ++ ) {\n\n\t\t\t\t\t\t\tnewMorphArrays[ m ][ setterFunc ]( nextIndex, morphAttributes[ m ][ getterFunc ]( index ) );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\thashToIndex[ hash ] = nextIndex;\n\t\t\tnewIndices.push( nextIndex );\n\t\t\tnextIndex ++;\n\n\t\t}\n\n\t}\n\n\t// generate result BufferGeometry\n\tconst result = geometry.clone();\n\tfor ( const name in geometry.attributes ) {\n\n\t\tconst tmpAttribute = tmpAttributes[ name ];\n\n\t\tresult.setAttribute( name, new tmpAttribute.constructor(\n\t\t\ttmpAttribute.array.slice( 0, nextIndex * tmpAttribute.itemSize ),\n\t\t\ttmpAttribute.itemSize,\n\t\t\ttmpAttribute.normalized,\n\t\t) );\n\n\t\tif ( ! ( name in tmpMorphAttributes ) ) continue;\n\n\t\tfor ( let j = 0; j < tmpMorphAttributes[ name ].length; j ++ ) {\n\n\t\t\tconst tmpMorphAttribute = tmpMorphAttributes[ name ][ j ];\n\n\t\t\tresult.morphAttributes[ name ][ j ] = new tmpMorphAttribute.constructor(\n\t\t\t\ttmpMorphAttribute.array.slice( 0, nextIndex * tmpMorphAttribute.itemSize ),\n\t\t\t\ttmpMorphAttribute.itemSize,\n\t\t\t\ttmpMorphAttribute.normalized,\n\t\t\t);\n\n\t\t}\n\n\t}\n\n\t// indices\n\n\tresult.setIndex( newIndices );\n\n\treturn result;\n\n}\n\n/**\n * Returns a new indexed geometry based on `TrianglesDrawMode` draw mode.\n * This mode corresponds to the `gl.TRIANGLES` primitive in WebGL.\n *\n * @param {BufferGeometry} geometry - The geometry to convert.\n * @param {number} drawMode - The current draw mode.\n * @return {BufferGeometry} The new geometry using `TrianglesDrawMode`.\n */\nfunction toTrianglesDrawMode( geometry, drawMode ) {\n\n\tif ( drawMode === TrianglesDrawMode ) {\n\n\t\tconsole.warn( 'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles.' );\n\t\treturn geometry;\n\n\t}\n\n\tif ( drawMode === TriangleFanDrawMode || drawMode === TriangleStripDrawMode ) {\n\n\t\tlet index = geometry.getIndex();\n\n\t\t// generate index if not present\n\n\t\tif ( index === null ) {\n\n\t\t\tconst indices = [];\n\n\t\t\tconst position = geometry.getAttribute( 'position' );\n\n\t\t\tif ( position !== undefined ) {\n\n\t\t\t\tfor ( let i = 0; i < position.count; i ++ ) {\n\n\t\t\t\t\tindices.push( i );\n\n\t\t\t\t}\n\n\t\t\t\tgeometry.setIndex( indices );\n\t\t\t\tindex = geometry.getIndex();\n\n\t\t\t} else {\n\n\t\t\t\tconsole.error( 'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Undefined position attribute. Processing not possible.' );\n\t\t\t\treturn geometry;\n\n\t\t\t}\n\n\t\t}\n\n\t\t//\n\n\t\tconst numberOfTriangles = index.count - 2;\n\t\tconst newIndices = [];\n\n\t\tif ( drawMode === TriangleFanDrawMode ) {\n\n\t\t\t// gl.TRIANGLE_FAN\n\n\t\t\tfor ( let i = 1; i <= numberOfTriangles; i ++ ) {\n\n\t\t\t\tnewIndices.push( index.getX( 0 ) );\n\t\t\t\tnewIndices.push( index.getX( i ) );\n\t\t\t\tnewIndices.push( index.getX( i + 1 ) );\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t// gl.TRIANGLE_STRIP\n\n\t\t\tfor ( let i = 0; i < numberOfTriangles; i ++ ) {\n\n\t\t\t\tif ( i % 2 === 0 ) {\n\n\t\t\t\t\tnewIndices.push( index.getX( i ) );\n\t\t\t\t\tnewIndices.push( index.getX( i + 1 ) );\n\t\t\t\t\tnewIndices.push( index.getX( i + 2 ) );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tnewIndices.push( index.getX( i + 2 ) );\n\t\t\t\t\tnewIndices.push( index.getX( i + 1 ) );\n\t\t\t\t\tnewIndices.push( index.getX( i ) );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( ( newIndices.length / 3 ) !== numberOfTriangles ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unable to generate correct amount of triangles.' );\n\n\t\t}\n\n\t\t// build final geometry\n\n\t\tconst newGeometry = geometry.clone();\n\t\tnewGeometry.setIndex( newIndices );\n\t\tnewGeometry.clearGroups();\n\n\t\treturn newGeometry;\n\n\t} else {\n\n\t\tconsole.error( 'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:', drawMode );\n\t\treturn geometry;\n\n\t}\n\n}\n\n/**\n * Calculates the morphed attributes of a morphed/skinned BufferGeometry.\n *\n * Helpful for Raytracing or Decals (i.e. a `DecalGeometry` applied to a morphed Object with a `BufferGeometry`\n * will use the original `BufferGeometry`, not the morphed/skinned one, generating an incorrect result.\n * Using this function to create a shadow `Object3`D the `DecalGeometry` can be correctly generated).\n *\n * @param {Mesh|Line|Points} object - The 3D object to compute morph attributes for.\n * @return {Object} An object with original position/normal attributes and morphed ones.\n */\nfunction computeMorphedAttributes( object ) {\n\n\tconst _vA = new Vector3();\n\tconst _vB = new Vector3();\n\tconst _vC = new Vector3();\n\n\tconst _tempA = new Vector3();\n\tconst _tempB = new Vector3();\n\tconst _tempC = new Vector3();\n\n\tconst _morphA = new Vector3();\n\tconst _morphB = new Vector3();\n\tconst _morphC = new Vector3();\n\n\tfunction _calculateMorphedAttributeData(\n\t\tobject,\n\t\tattribute,\n\t\tmorphAttribute,\n\t\tmorphTargetsRelative,\n\t\ta,\n\t\tb,\n\t\tc,\n\t\tmodifiedAttributeArray\n\t) {\n\n\t\t_vA.fromBufferAttribute( attribute, a );\n\t\t_vB.fromBufferAttribute( attribute, b );\n\t\t_vC.fromBufferAttribute( attribute, c );\n\n\t\tconst morphInfluences = object.morphTargetInfluences;\n\n\t\tif ( morphAttribute && morphInfluences ) {\n\n\t\t\t_morphA.set( 0, 0, 0 );\n\t\t\t_morphB.set( 0, 0, 0 );\n\t\t\t_morphC.set( 0, 0, 0 );\n\n\t\t\tfor ( let i = 0, il = morphAttribute.length; i < il; i ++ ) {\n\n\t\t\t\tconst influence = morphInfluences[ i ];\n\t\t\t\tconst morph = morphAttribute[ i ];\n\n\t\t\t\tif ( influence === 0 ) continue;\n\n\t\t\t\t_tempA.fromBufferAttribute( morph, a );\n\t\t\t\t_tempB.fromBufferAttribute( morph, b );\n\t\t\t\t_tempC.fromBufferAttribute( morph, c );\n\n\t\t\t\tif ( morphTargetsRelative ) {\n\n\t\t\t\t\t_morphA.addScaledVector( _tempA, influence );\n\t\t\t\t\t_morphB.addScaledVector( _tempB, influence );\n\t\t\t\t\t_morphC.addScaledVector( _tempC, influence );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t_morphA.addScaledVector( _tempA.sub( _vA ), influence );\n\t\t\t\t\t_morphB.addScaledVector( _tempB.sub( _vB ), influence );\n\t\t\t\t\t_morphC.addScaledVector( _tempC.sub( _vC ), influence );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t_vA.add( _morphA );\n\t\t\t_vB.add( _morphB );\n\t\t\t_vC.add( _morphC );\n\n\t\t}\n\n\t\tif ( object.isSkinnedMesh ) {\n\n\t\t\tobject.applyBoneTransform( a, _vA );\n\t\t\tobject.applyBoneTransform( b, _vB );\n\t\t\tobject.applyBoneTransform( c, _vC );\n\n\t\t}\n\n\t\tmodifiedAttributeArray[ a * 3 + 0 ] = _vA.x;\n\t\tmodifiedAttributeArray[ a * 3 + 1 ] = _vA.y;\n\t\tmodifiedAttributeArray[ a * 3 + 2 ] = _vA.z;\n\t\tmodifiedAttributeArray[ b * 3 + 0 ] = _vB.x;\n\t\tmodifiedAttributeArray[ b * 3 + 1 ] = _vB.y;\n\t\tmodifiedAttributeArray[ b * 3 + 2 ] = _vB.z;\n\t\tmodifiedAttributeArray[ c * 3 + 0 ] = _vC.x;\n\t\tmodifiedAttributeArray[ c * 3 + 1 ] = _vC.y;\n\t\tmodifiedAttributeArray[ c * 3 + 2 ] = _vC.z;\n\n\t}\n\n\tconst geometry = object.geometry;\n\tconst material = object.material;\n\n\tlet a, b, c;\n\tconst index = geometry.index;\n\tconst positionAttribute = geometry.attributes.position;\n\tconst morphPosition = geometry.morphAttributes.position;\n\tconst morphTargetsRelative = geometry.morphTargetsRelative;\n\tconst normalAttribute = geometry.attributes.normal;\n\tconst morphNormal = geometry.morphAttributes.normal;\n\n\tconst groups = geometry.groups;\n\tconst drawRange = geometry.drawRange;\n\tlet i, j, il, jl;\n\tlet group;\n\tlet start, end;\n\n\tconst modifiedPosition = new Float32Array( positionAttribute.count * positionAttribute.itemSize );\n\tconst modifiedNormal = new Float32Array( normalAttribute.count * normalAttribute.itemSize );\n\n\tif ( index !== null ) {\n\n\t\t// indexed buffer geometry\n\n\t\tif ( Array.isArray( material ) ) {\n\n\t\t\tfor ( i = 0, il = groups.length; i < il; i ++ ) {\n\n\t\t\t\tgroup = groups[ i ];\n\n\t\t\t\tstart = Math.max( group.start, drawRange.start );\n\t\t\t\tend = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );\n\n\t\t\t\tfor ( j = start, jl = end; j < jl; j += 3 ) {\n\n\t\t\t\t\ta = index.getX( j );\n\t\t\t\t\tb = index.getX( j + 1 );\n\t\t\t\t\tc = index.getX( j + 2 );\n\n\t\t\t\t\t_calculateMorphedAttributeData(\n\t\t\t\t\t\tobject,\n\t\t\t\t\t\tpositionAttribute,\n\t\t\t\t\t\tmorphPosition,\n\t\t\t\t\t\tmorphTargetsRelative,\n\t\t\t\t\t\ta, b, c,\n\t\t\t\t\t\tmodifiedPosition\n\t\t\t\t\t);\n\n\t\t\t\t\t_calculateMorphedAttributeData(\n\t\t\t\t\t\tobject,\n\t\t\t\t\t\tnormalAttribute,\n\t\t\t\t\t\tmorphNormal,\n\t\t\t\t\t\tmorphTargetsRelative,\n\t\t\t\t\t\ta, b, c,\n\t\t\t\t\t\tmodifiedNormal\n\t\t\t\t\t);\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tstart = Math.max( 0, drawRange.start );\n\t\t\tend = Math.min( index.count, ( drawRange.start + drawRange.count ) );\n\n\t\t\tfor ( i = start, il = end; i < il; i += 3 ) {\n\n\t\t\t\ta = index.getX( i );\n\t\t\t\tb = index.getX( i + 1 );\n\t\t\t\tc = index.getX( i + 2 );\n\n\t\t\t\t_calculateMorphedAttributeData(\n\t\t\t\t\tobject,\n\t\t\t\t\tpositionAttribute,\n\t\t\t\t\tmorphPosition,\n\t\t\t\t\tmorphTargetsRelative,\n\t\t\t\t\ta, b, c,\n\t\t\t\t\tmodifiedPosition\n\t\t\t\t);\n\n\t\t\t\t_calculateMorphedAttributeData(\n\t\t\t\t\tobject,\n\t\t\t\t\tnormalAttribute,\n\t\t\t\t\tmorphNormal,\n\t\t\t\t\tmorphTargetsRelative,\n\t\t\t\t\ta, b, c,\n\t\t\t\t\tmodifiedNormal\n\t\t\t\t);\n\n\t\t\t}\n\n\t\t}\n\n\t} else {\n\n\t\t// non-indexed buffer geometry\n\n\t\tif ( Array.isArray( material ) ) {\n\n\t\t\tfor ( i = 0, il = groups.length; i < il; i ++ ) {\n\n\t\t\t\tgroup = groups[ i ];\n\n\t\t\t\tstart = Math.max( group.start, drawRange.start );\n\t\t\t\tend = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );\n\n\t\t\t\tfor ( j = start, jl = end; j < jl; j += 3 ) {\n\n\t\t\t\t\ta = j;\n\t\t\t\t\tb = j + 1;\n\t\t\t\t\tc = j + 2;\n\n\t\t\t\t\t_calculateMorphedAttributeData(\n\t\t\t\t\t\tobject,\n\t\t\t\t\t\tpositionAttribute,\n\t\t\t\t\t\tmorphPosition,\n\t\t\t\t\t\tmorphTargetsRelative,\n\t\t\t\t\t\ta, b, c,\n\t\t\t\t\t\tmodifiedPosition\n\t\t\t\t\t);\n\n\t\t\t\t\t_calculateMorphedAttributeData(\n\t\t\t\t\t\tobject,\n\t\t\t\t\t\tnormalAttribute,\n\t\t\t\t\t\tmorphNormal,\n\t\t\t\t\t\tmorphTargetsRelative,\n\t\t\t\t\t\ta, b, c,\n\t\t\t\t\t\tmodifiedNormal\n\t\t\t\t\t);\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tstart = Math.max( 0, drawRange.start );\n\t\t\tend = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) );\n\n\t\t\tfor ( i = start, il = end; i < il; i += 3 ) {\n\n\t\t\t\ta = i;\n\t\t\t\tb = i + 1;\n\t\t\t\tc = i + 2;\n\n\t\t\t\t_calculateMorphedAttributeData(\n\t\t\t\t\tobject,\n\t\t\t\t\tpositionAttribute,\n\t\t\t\t\tmorphPosition,\n\t\t\t\t\tmorphTargetsRelative,\n\t\t\t\t\ta, b, c,\n\t\t\t\t\tmodifiedPosition\n\t\t\t\t);\n\n\t\t\t\t_calculateMorphedAttributeData(\n\t\t\t\t\tobject,\n\t\t\t\t\tnormalAttribute,\n\t\t\t\t\tmorphNormal,\n\t\t\t\t\tmorphTargetsRelative,\n\t\t\t\t\ta, b, c,\n\t\t\t\t\tmodifiedNormal\n\t\t\t\t);\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tconst morphedPositionAttribute = new Float32BufferAttribute( modifiedPosition, 3 );\n\tconst morphedNormalAttribute = new Float32BufferAttribute( modifiedNormal, 3 );\n\n\treturn {\n\n\t\tpositionAttribute: positionAttribute,\n\t\tnormalAttribute: normalAttribute,\n\t\tmorphedPositionAttribute: morphedPositionAttribute,\n\t\tmorphedNormalAttribute: morphedNormalAttribute\n\n\t};\n\n}\n\n/**\n * Merges the {@link BufferGeometry#groups} for the given geometry.\n *\n * @param {BufferGeometry} geometry - The geometry to modify.\n * @return {BufferGeometry} - The updated geometry\n */\nfunction mergeGroups( geometry ) {\n\n\tif ( geometry.groups.length === 0 ) {\n\n\t\tconsole.warn( 'THREE.BufferGeometryUtils.mergeGroups(): No groups are defined. Nothing to merge.' );\n\t\treturn geometry;\n\n\t}\n\n\tlet groups = geometry.groups;\n\n\t// sort groups by material index\n\n\tgroups = groups.sort( ( a, b ) => {\n\n\t\tif ( a.materialIndex !== b.materialIndex ) return a.materialIndex - b.materialIndex;\n\n\t\treturn a.start - b.start;\n\n\t} );\n\n\t// create index for non-indexed geometries\n\n\tif ( geometry.getIndex() === null ) {\n\n\t\tconst positionAttribute = geometry.getAttribute( 'position' );\n\t\tconst indices = [];\n\n\t\tfor ( let i = 0; i < positionAttribute.count; i += 3 ) {\n\n\t\t\tindices.push( i, i + 1, i + 2 );\n\n\t\t}\n\n\t\tgeometry.setIndex( indices );\n\n\t}\n\n\t// sort index\n\n\tconst index = geometry.getIndex();\n\n\tconst newIndices = [];\n\n\tfor ( let i = 0; i < groups.length; i ++ ) {\n\n\t\tconst group = groups[ i ];\n\n\t\tconst groupStart = group.start;\n\t\tconst groupLength = groupStart + group.count;\n\n\t\tfor ( let j = groupStart; j < groupLength; j ++ ) {\n\n\t\t\tnewIndices.push( index.getX( j ) );\n\n\t\t}\n\n\t}\n\n\tgeometry.dispose(); // Required to force buffer recreation\n\tgeometry.setIndex( newIndices );\n\n\t// update groups indices\n\n\tlet start = 0;\n\n\tfor ( let i = 0; i < groups.length; i ++ ) {\n\n\t\tconst group = groups[ i ];\n\n\t\tgroup.start = start;\n\t\tstart += group.count;\n\n\t}\n\n\t// merge groups\n\n\tlet currentGroup = groups[ 0 ];\n\n\tgeometry.groups = [ currentGroup ];\n\n\tfor ( let i = 1; i < groups.length; i ++ ) {\n\n\t\tconst group = groups[ i ];\n\n\t\tif ( currentGroup.materialIndex === group.materialIndex ) {\n\n\t\t\tcurrentGroup.count += group.count;\n\n\t\t} else {\n\n\t\t\tcurrentGroup = group;\n\t\t\tgeometry.groups.push( currentGroup );\n\n\t\t}\n\n\t}\n\n\treturn geometry;\n\n}\n\n/**\n * Modifies the supplied geometry if it is non-indexed, otherwise creates a new,\n * non-indexed geometry. Returns the geometry with smooth normals everywhere except\n * faces that meet at an angle greater than the crease angle.\n *\n * @param {BufferGeometry} geometry - The geometry to modify.\n * @param {number} [creaseAngle=Math.PI/3] - The crease angle in radians.\n * @return {BufferGeometry} - The updated geometry\n */\nfunction toCreasedNormals( geometry, creaseAngle = Math.PI / 3 /* 60 degrees */ ) {\n\n\tconst creaseDot = Math.cos( creaseAngle );\n\tconst hashMultiplier = ( 1 + 1e-10 ) * 1e2;\n\n\t// reusable vectors\n\tconst verts = [ new Vector3(), new Vector3(), new Vector3() ];\n\tconst tempVec1 = new Vector3();\n\tconst tempVec2 = new Vector3();\n\tconst tempNorm = new Vector3();\n\tconst tempNorm2 = new Vector3();\n\n\t// hashes a vector\n\tfunction hashVertex( v ) {\n\n\t\tconst x = ~ ~ ( v.x * hashMultiplier );\n\t\tconst y = ~ ~ ( v.y * hashMultiplier );\n\t\tconst z = ~ ~ ( v.z * hashMultiplier );\n\t\treturn `${x},${y},${z}`;\n\n\t}\n\n\t// BufferGeometry.toNonIndexed() warns if the geometry is non-indexed\n\t// and returns the original geometry\n\tconst resultGeometry = geometry.index ? geometry.toNonIndexed() : geometry;\n\tconst posAttr = resultGeometry.attributes.position;\n\tconst vertexMap = {};\n\n\t// find all the normals shared by commonly located vertices\n\tfor ( let i = 0, l = posAttr.count / 3; i < l; i ++ ) {\n\n\t\tconst i3 = 3 * i;\n\t\tconst a = verts[ 0 ].fromBufferAttribute( posAttr, i3 + 0 );\n\t\tconst b = verts[ 1 ].fromBufferAttribute( posAttr, i3 + 1 );\n\t\tconst c = verts[ 2 ].fromBufferAttribute( posAttr, i3 + 2 );\n\n\t\ttempVec1.subVectors( c, b );\n\t\ttempVec2.subVectors( a, b );\n\n\t\t// add the normal to the map for all vertices\n\t\tconst normal = new Vector3().crossVectors( tempVec1, tempVec2 ).normalize();\n\t\tfor ( let n = 0; n < 3; n ++ ) {\n\n\t\t\tconst vert = verts[ n ];\n\t\t\tconst hash = hashVertex( vert );\n\t\t\tif ( ! ( hash in vertexMap ) ) {\n\n\t\t\t\tvertexMap[ hash ] = [];\n\n\t\t\t}\n\n\t\t\tvertexMap[ hash ].push( normal );\n\n\t\t}\n\n\t}\n\n\t// average normals from all vertices that share a common location if they are within the\n\t// provided crease threshold\n\tconst normalArray = new Float32Array( posAttr.count * 3 );\n\tconst normAttr = new BufferAttribute( normalArray, 3, false );\n\tfor ( let i = 0, l = posAttr.count / 3; i < l; i ++ ) {\n\n\t\t// get the face normal for this vertex\n\t\tconst i3 = 3 * i;\n\t\tconst a = verts[ 0 ].fromBufferAttribute( posAttr, i3 + 0 );\n\t\tconst b = verts[ 1 ].fromBufferAttribute( posAttr, i3 + 1 );\n\t\tconst c = verts[ 2 ].fromBufferAttribute( posAttr, i3 + 2 );\n\n\t\ttempVec1.subVectors( c, b );\n\t\ttempVec2.subVectors( a, b );\n\n\t\ttempNorm.crossVectors( tempVec1, tempVec2 ).normalize();\n\n\t\t// average all normals that meet the threshold and set the normal value\n\t\tfor ( let n = 0; n < 3; n ++ ) {\n\n\t\t\tconst vert = verts[ n ];\n\t\t\tconst hash = hashVertex( vert );\n\t\t\tconst otherNormals = vertexMap[ hash ];\n\t\t\ttempNorm2.set( 0, 0, 0 );\n\n\t\t\tfor ( let k = 0, lk = otherNormals.length; k < lk; k ++ ) {\n\n\t\t\t\tconst otherNorm = otherNormals[ k ];\n\t\t\t\tif ( tempNorm.dot( otherNorm ) > creaseDot ) {\n\n\t\t\t\t\ttempNorm2.add( otherNorm );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\ttempNorm2.normalize();\n\t\t\tnormAttr.setXYZ( i3 + n, tempNorm2.x, tempNorm2.y, tempNorm2.z );\n\n\t\t}\n\n\t}\n\n\tresultGeometry.setAttribute( 'normal', normAttr );\n\treturn resultGeometry;\n\n}\n\nexport {\n\tcomputeMikkTSpaceTangents,\n\tmergeGeometries,\n\tmergeAttributes,\n\tdeepCloneAttribute,\n\tdeinterleaveAttribute,\n\tdeinterleaveGeometry,\n\tinterleaveAttributes,\n\testimateBytesUsed,\n\tmergeVertices,\n\ttoTrianglesDrawMode,\n\tcomputeMorphedAttributes,\n\tmergeGroups,\n\ttoCreasedNormals\n};\n","import {\n\tAnimationClip,\n\tAnimationMixer,\n\tMatrix4,\n\tQuaternion,\n\tQuaternionKeyframeTrack,\n\tSkeletonHelper,\n\tVector3,\n\tVectorKeyframeTrack\n} from 'three';\n\n/**\n * @module SkeletonUtils\n * @three_import import * as SkeletonUtils from 'three/addons/utils/SkeletonUtils.js';\n */\n\nfunction getBoneName( bone, options ) {\n\n\tif ( options.getBoneName !== undefined ) {\n\n\t\treturn options.getBoneName( bone );\n\n\t}\n\n\treturn options.names[ bone.name ];\n\n}\n\n/**\n * Retargets the skeleton from the given source to the target.\n *\n * Both `target` and `source` can be a 3D object with a skeleton property (e.g. a skinned mesh)\n * or a {@link Skeleton} directly.\n *\n * @param {Object3D|Skeleton} target - The target object.\n * @param {Object3D|Skeleton} source - The source object.\n * @param {module:SkeletonUtils~RetargetOptions} options - The options.\n */\nfunction retarget( target, source, options = {} ) {\n\n\tconst quat = new Quaternion(),\n\t\tscale = new Vector3(),\n\t\trelativeMatrix = new Matrix4(),\n\t\tglobalMatrix = new Matrix4();\n\n\toptions.preserveBoneMatrix = options.preserveBoneMatrix !== undefined ? options.preserveBoneMatrix : true;\n\toptions.preserveBonePositions = options.preserveBonePositions !== undefined ? options.preserveBonePositions : true;\n\toptions.useTargetMatrix = options.useTargetMatrix !== undefined ? options.useTargetMatrix : false;\n\toptions.hip = options.hip !== undefined ? options.hip : 'hip';\n\toptions.hipInfluence = options.hipInfluence !== undefined ? options.hipInfluence : new Vector3( 1, 1, 1 );\n\toptions.scale = options.scale !== undefined ? options.scale : 1;\n\toptions.names = options.names || {};\n\n\tconst sourceBones = source.isObject3D ? source.skeleton.bones : getBones( source ),\n\t\tbones = target.isObject3D ? target.skeleton.bones : getBones( target );\n\n\tlet bone, name, boneTo,\n\t\tbonesPosition;\n\n\t// reset bones\n\n\tif ( target.isObject3D ) {\n\n\t\ttarget.skeleton.pose();\n\n\t} else {\n\n\t\toptions.useTargetMatrix = true;\n\t\toptions.preserveBoneMatrix = false;\n\n\t}\n\n\tif ( options.preserveBonePositions ) {\n\n\t\tbonesPosition = [];\n\n\t\tfor ( let i = 0; i < bones.length; i ++ ) {\n\n\t\t\tbonesPosition.push( bones[ i ].position.clone() );\n\n\t\t}\n\n\t}\n\n\tif ( options.preserveBoneMatrix ) {\n\n\t\t// reset matrix\n\n\t\ttarget.updateMatrixWorld();\n\n\t\ttarget.matrixWorld.identity();\n\n\t\t// reset children matrix\n\n\t\tfor ( let i = 0; i < target.children.length; ++ i ) {\n\n\t\t\ttarget.children[ i ].updateMatrixWorld( true );\n\n\t\t}\n\n\t}\n\n\tfor ( let i = 0; i < bones.length; ++ i ) {\n\n\t\tbone = bones[ i ];\n\t\tname = getBoneName( bone, options );\n\n\t\tboneTo = getBoneByName( name, sourceBones );\n\n\t\tglobalMatrix.copy( bone.matrixWorld );\n\n\t\tif ( boneTo ) {\n\n\t\t\tboneTo.updateMatrixWorld();\n\n\t\t\tif ( options.useTargetMatrix ) {\n\n\t\t\t\trelativeMatrix.copy( boneTo.matrixWorld );\n\n\t\t\t} else {\n\n\t\t\t\trelativeMatrix.copy( target.matrixWorld ).invert();\n\t\t\t\trelativeMatrix.multiply( boneTo.matrixWorld );\n\n\t\t\t}\n\n\t\t\t// ignore scale to extract rotation\n\n\t\t\tscale.setFromMatrixScale( relativeMatrix );\n\t\t\trelativeMatrix.scale( scale.set( 1 / scale.x, 1 / scale.y, 1 / scale.z ) );\n\n\t\t\t// apply to global matrix\n\n\t\t\tglobalMatrix.makeRotationFromQuaternion( quat.setFromRotationMatrix( relativeMatrix ) );\n\n\t\t\tif ( target.isObject3D ) {\n\n\t\t\t\tif ( options.localOffsets ) {\n\n\t\t\t\t\tif ( options.localOffsets[ bone.name ] ) {\n\n\t\t\t\t\t\tglobalMatrix.multiply( options.localOffsets[ bone.name ] );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tglobalMatrix.copyPosition( relativeMatrix );\n\n\t\t}\n\n\t\tif ( name === options.hip ) {\n\n\t\t\tglobalMatrix.elements[ 12 ] *= options.scale * options.hipInfluence.x;\n\t\t\tglobalMatrix.elements[ 13 ] *= options.scale * options.hipInfluence.y;\n\t\t\tglobalMatrix.elements[ 14 ] *= options.scale * options.hipInfluence.z;\n\n\t\t\tif ( options.hipPosition !== undefined ) {\n\n\t\t\t\tglobalMatrix.elements[ 12 ] += options.hipPosition.x * options.scale;\n\t\t\t\tglobalMatrix.elements[ 13 ] += options.hipPosition.y * options.scale;\n\t\t\t\tglobalMatrix.elements[ 14 ] += options.hipPosition.z * options.scale;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( bone.parent ) {\n\n\t\t\tbone.matrix.copy( bone.parent.matrixWorld ).invert();\n\t\t\tbone.matrix.multiply( globalMatrix );\n\n\t\t} else {\n\n\t\t\tbone.matrix.copy( globalMatrix );\n\n\t\t}\n\n\t\tbone.matrix.decompose( bone.position, bone.quaternion, bone.scale );\n\n\t\tbone.updateMatrixWorld();\n\n\t}\n\n\tif ( options.preserveBonePositions ) {\n\n\t\tfor ( let i = 0; i < bones.length; ++ i ) {\n\n\t\t\tbone = bones[ i ];\n\t\t\tname = getBoneName( bone, options ) || bone.name;\n\n\t\t\tif ( name !== options.hip ) {\n\n\t\t\t\tbone.position.copy( bonesPosition[ i ] );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tif ( options.preserveBoneMatrix ) {\n\n\t\t// restore matrix\n\n\t\ttarget.updateMatrixWorld( true );\n\n\t}\n\n}\n\n/**\n * Retargets the animation clip of the source to the target 3D object.\n *\n * The `source` can be a 3D object with a skeleton property (e.g. a skinned mesh)\n * or a {@link Skeleton} directly.\n *\n * @param {Object3D} target - The target 3D object. Must have a `skeleton` property.\n * @param {Object3D|Skeleton} source - The source object.\n * @param {AnimationClip} clip - The animation clip.\n * @param {module:SkeletonUtils~RetargetOptions} options - The options.\n * @return {AnimationClip} The retargeted animation clip.\n */\nfunction retargetClip( target, source, clip, options = {} ) {\n\n\toptions.useFirstFramePosition = options.useFirstFramePosition !== undefined ? options.useFirstFramePosition : false;\n\n\t// Calculate the fps from the source clip based on the track with the most frames, unless fps is already provided.\n\toptions.fps = options.fps !== undefined ? options.fps : ( Math.max( ...clip.tracks.map( track => track.times.length ) ) / clip.duration );\n\toptions.names = options.names || [];\n\n\tif ( ! source.isObject3D ) {\n\n\t\tsource = getHelperFromSkeleton( source );\n\n\t}\n\n\tconst numFrames = Math.round( clip.duration * ( options.fps / 1000 ) * 1000 ),\n\t\tdelta = clip.duration / ( numFrames - 1 ),\n\t\tconvertedTracks = [],\n\t\tmixer = new AnimationMixer( source ),\n\t\tbones = getBones( target.skeleton ),\n\t\tboneDatas = [];\n\n\tlet positionOffset,\n\t\tbone, boneTo, boneData,\n\t\tname;\n\n\tmixer.clipAction( clip ).play();\n\n\t// trim\n\n\tlet start = 0, end = numFrames;\n\n\tif ( options.trim !== undefined ) {\n\n\t\tstart = Math.round( options.trim[ 0 ] * options.fps );\n\t\tend = Math.min( Math.round( options.trim[ 1 ] * options.fps ), numFrames ) - start;\n\n\t\tmixer.update( options.trim[ 0 ] );\n\n\t} else {\n\n\t\tmixer.update( 0 );\n\n\t}\n\n\tsource.updateMatrixWorld();\n\n\t//\n\n\tfor ( let frame = 0; frame < end; ++ frame ) {\n\n\t\tconst time = frame * delta;\n\n\t\tretarget( target, source, options );\n\n\t\tfor ( let j = 0; j < bones.length; ++ j ) {\n\n\t\t\tbone = bones[ j ];\n\t\t\tname = getBoneName( bone, options ) || bone.name;\n\t\t\tboneTo = getBoneByName( name, source.skeleton );\n\n\t\t\tif ( boneTo ) {\n\n\t\t\t\tboneData = boneDatas[ j ] = boneDatas[ j ] || { bone: bone };\n\n\t\t\t\tif ( options.hip === name ) {\n\n\t\t\t\t\tif ( ! boneData.pos ) {\n\n\t\t\t\t\t\tboneData.pos = {\n\t\t\t\t\t\t\ttimes: new Float32Array( end ),\n\t\t\t\t\t\t\tvalues: new Float32Array( end * 3 )\n\t\t\t\t\t\t};\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( options.useFirstFramePosition ) {\n\n\t\t\t\t\t\tif ( frame === 0 ) {\n\n\t\t\t\t\t\t\tpositionOffset = bone.position.clone();\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbone.position.sub( positionOffset );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tboneData.pos.times[ frame ] = time;\n\n\t\t\t\t\tbone.position.toArray( boneData.pos.values, frame * 3 );\n\n\t\t\t\t}\n\n\t\t\t\tif ( ! boneData.quat ) {\n\n\t\t\t\t\tboneData.quat = {\n\t\t\t\t\t\ttimes: new Float32Array( end ),\n\t\t\t\t\t\tvalues: new Float32Array( end * 4 )\n\t\t\t\t\t};\n\n\t\t\t\t}\n\n\t\t\t\tboneData.quat.times[ frame ] = time;\n\n\t\t\t\tbone.quaternion.toArray( boneData.quat.values, frame * 4 );\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( frame === end - 2 ) {\n\n\t\t\t// last mixer update before final loop iteration\n\t\t\t// make sure we do not go over or equal to clip duration\n\t\t\tmixer.update( delta - 0.0000001 );\n\n\t\t} else {\n\n\t\t\tmixer.update( delta );\n\n\t\t}\n\n\t\tsource.updateMatrixWorld();\n\n\t}\n\n\tfor ( let i = 0; i < boneDatas.length; ++ i ) {\n\n\t\tboneData = boneDatas[ i ];\n\n\t\tif ( boneData ) {\n\n\t\t\tif ( boneData.pos ) {\n\n\t\t\t\tconvertedTracks.push( new VectorKeyframeTrack(\n\t\t\t\t\t'.bones[' + boneData.bone.name + '].position',\n\t\t\t\t\tboneData.pos.times,\n\t\t\t\t\tboneData.pos.values\n\t\t\t\t) );\n\n\t\t\t}\n\n\t\t\tconvertedTracks.push( new QuaternionKeyframeTrack(\n\t\t\t\t'.bones[' + boneData.bone.name + '].quaternion',\n\t\t\t\tboneData.quat.times,\n\t\t\t\tboneData.quat.values\n\t\t\t) );\n\n\t\t}\n\n\t}\n\n\tmixer.uncacheAction( clip );\n\n\treturn new AnimationClip( clip.name, - 1, convertedTracks );\n\n}\n\n/**\n * Clones the given 3D object and its descendants, ensuring that any `SkinnedMesh` instances are\n * correctly associated with their bones. Bones are also cloned, and must be descendants of the\n * object passed to this method. Other data, like geometries and materials, are reused by reference.\n *\n * @param {Object3D} source - The 3D object to clone.\n * @return {Object3D} The cloned 3D object.\n */\nfunction clone( source ) {\n\n\tconst sourceLookup = new Map();\n\tconst cloneLookup = new Map();\n\n\tconst clone = source.clone();\n\n\tparallelTraverse( source, clone, function ( sourceNode, clonedNode ) {\n\n\t\tsourceLookup.set( clonedNode, sourceNode );\n\t\tcloneLookup.set( sourceNode, clonedNode );\n\n\t} );\n\n\tclone.traverse( function ( node ) {\n\n\t\tif ( ! node.isSkinnedMesh ) return;\n\n\t\tconst clonedMesh = node;\n\t\tconst sourceMesh = sourceLookup.get( node );\n\t\tconst sourceBones = sourceMesh.skeleton.bones;\n\n\t\tclonedMesh.skeleton = sourceMesh.skeleton.clone();\n\t\tclonedMesh.bindMatrix.copy( sourceMesh.bindMatrix );\n\n\t\tclonedMesh.skeleton.bones = sourceBones.map( function ( bone ) {\n\n\t\t\treturn cloneLookup.get( bone );\n\n\t\t} );\n\n\t\tclonedMesh.bind( clonedMesh.skeleton, clonedMesh.bindMatrix );\n\n\t} );\n\n\treturn clone;\n\n}\n\n// internal helper\n\nfunction getBoneByName( name, skeleton ) {\n\n\tfor ( let i = 0, bones = getBones( skeleton ); i < bones.length; i ++ ) {\n\n\t\tif ( name === bones[ i ].name )\n\n\t\t\treturn bones[ i ];\n\n\t}\n\n}\n\nfunction getBones( skeleton ) {\n\n\treturn Array.isArray( skeleton ) ? skeleton : skeleton.bones;\n\n}\n\n\nfunction getHelperFromSkeleton( skeleton ) {\n\n\tconst source = new SkeletonHelper( skeleton.bones[ 0 ] );\n\tsource.skeleton = skeleton;\n\n\treturn source;\n\n}\n\nfunction parallelTraverse( a, b, callback ) {\n\n\tcallback( a, b );\n\n\tfor ( let i = 0; i < a.children.length; i ++ ) {\n\n\t\tparallelTraverse( a.children[ i ], b.children[ i ], callback );\n\n\t}\n\n}\n\n/**\n * Retarget options of `SkeletonUtils`.\n *\n * @typedef {Object} module:SkeletonUtils~RetargetOptions\n * @property {boolean} [useFirstFramePosition=false] - Whether to use the position of the first frame or not.\n * @property {number} [fps] - The FPS of the clip.\n * @property {Object<string,string>} [names] - A dictionary for mapping target to source bone names.\n * @property {function(string):string} [getBoneName] - A function for mapping bone names. Alternative to `names`.\n * @property {Array<number>} [trim] - Whether to trim the clip or not. If set the array should hold two values for the start and end.\n * @property {boolean} [preserveBoneMatrix=true] - Whether to preserve bone matrices or not.\n * @property {boolean} [preserveBonePositions=true] - Whether to preserve bone positions or not.\n * @property {boolean} [useTargetMatrix=false] - Whether to use the target matrix or not.\n * @property {string} [hip='hip'] - The name of the source's hip bone.\n * @property {Vector3} [hipInfluence=(1,1,1)] - The hip influence.\n * @property {number} [scale=1] - The scale.\n * @property {Object<string,Matrix4>} [localOffsets] - Per-bone local offset matrices, keyed by bone name.\n * @property {Vector3} [hipPosition] - An additional position offset applied to the hip bone.\n **/\n\nexport {\n\tretarget,\n\tretargetClip,\n\tclone,\n};\n","import {\n\tAnimationClip,\n\tBone,\n\tBox3,\n\tBufferAttribute,\n\tBufferGeometry,\n\tClampToEdgeWrapping,\n\tColor,\n\tColorManagement,\n\tDirectionalLight,\n\tDoubleSide,\n\tFileLoader,\n\tFrontSide,\n\tGroup,\n\tImageBitmapLoader,\n\tInstancedMesh,\n\tInterleavedBuffer,\n\tInterleavedBufferAttribute,\n\tInterpolant,\n\tInterpolateDiscrete,\n\tInterpolateLinear,\n\tLine,\n\tLineBasicMaterial,\n\tLineLoop,\n\tLineSegments,\n\tLinearFilter,\n\tLinearMipmapLinearFilter,\n\tLinearMipmapNearestFilter,\n\tLinearSRGBColorSpace,\n\tLoader,\n\tLoaderUtils,\n\tMaterial,\n\tMathUtils,\n\tMatrix4,\n\tMesh,\n\tMeshBasicMaterial,\n\tMeshPhysicalMaterial,\n\tMeshStandardMaterial,\n\tMirroredRepeatWrapping,\n\tNearestFilter,\n\tNearestMipmapLinearFilter,\n\tNearestMipmapNearestFilter,\n\tNumberKeyframeTrack,\n\tObject3D,\n\tOrthographicCamera,\n\tPerspectiveCamera,\n\tPointLight,\n\tPoints,\n\tPointsMaterial,\n\tPropertyBinding,\n\tQuaternion,\n\tQuaternionKeyframeTrack,\n\tRepeatWrapping,\n\tSkeleton,\n\tSkinnedMesh,\n\tSphere,\n\tSpotLight,\n\tTexture,\n\tTextureLoader,\n\tTriangleFanDrawMode,\n\tTriangleStripDrawMode,\n\tVector2,\n\tVector3,\n\tVectorKeyframeTrack,\n\tSRGBColorSpace,\n\tInstancedBufferAttribute\n} from 'three';\nimport { toTrianglesDrawMode } from '../utils/BufferGeometryUtils.js';\nimport { clone } from '../utils/SkeletonUtils.js';\n\n/**\n * A loader for the glTF 2.0 format.\n *\n * [glTF](https://www.khronos.org/gltf/) (GL Transmission Format) is an [open format specification]{@link https://github.com/KhronosGroup/glTF/tree/main/specification/2.0)\n * for efficient delivery and loading of 3D content. Assets may be provided either in JSON (.gltf) or binary (.glb)\n * format. External files store textures (.jpg, .png) and additional binary data (.bin). A glTF asset may deliver\n * one or more scenes, including meshes, materials, textures, skins, skeletons, morph targets, animations, lights,\n * and/or cameras.\n *\n * `GLTFLoader` uses {@link ImageBitmapLoader} whenever possible. Be advised that image bitmaps are not\n * automatically GC-collected when they are no longer referenced, and they require special handling during\n * the disposal process.\n *\n * `GLTFLoader` supports the following glTF 2.0 extensions:\n * - KHR_draco_mesh_compression\n * - KHR_lights_punctual\n * - KHR_materials_anisotropy\n * - KHR_materials_clearcoat\n * - KHR_materials_dispersion\n * - KHR_materials_emissive_strength\n * - KHR_materials_ior\n * - KHR_materials_specular\n * - KHR_materials_transmission\n * - KHR_materials_iridescence\n * - KHR_materials_unlit\n * - KHR_materials_volume\n * - KHR_mesh_quantization\n * - KHR_meshopt_compression\n * - KHR_texture_basisu\n * - KHR_texture_transform\n * - EXT_materials_bump\n * - EXT_meshopt_compression\n * - EXT_mesh_gpu_instancing\n * - EXT_texture_avif\n * - EXT_texture_webp\n *\n * The following glTF 2.0 extension is supported by an external user plugin:\n * - [KHR_materials_variants](https://github.com/takahirox/three-gltf-extensions)\n * - [MSFT_texture_dds](https://github.com/takahirox/three-gltf-extensions)\n * - [KHR_animation_pointer](https://github.com/needle-tools/three-animation-pointer)\n * - [NEEDLE_progressive](https://github.com/needle-tools/gltf-progressive)\n *\n * ```js\n * const loader = new GLTFLoader();\n *\n * // Optional: Provide a DRACOLoader instance to decode compressed mesh data\n * const dracoLoader = new DRACOLoader();\n * dracoLoader.setDecoderPath( '/examples/jsm/libs/draco/' );\n * loader.setDRACOLoader( dracoLoader );\n *\n * const gltf = await loader.loadAsync( 'models/gltf/duck/duck.gltf' );\n * scene.add( gltf.scene );\n * ```\n *\n * @augments Loader\n * @three_import import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';\n */\nclass GLTFLoader extends Loader {\n\n\t/**\n\t * Constructs a new glTF loader.\n\t *\n\t * @param {LoadingManager} [manager] - The loading manager.\n\t */\n\tconstructor( manager ) {\n\n\t\tsuper( manager );\n\n\t\tthis.dracoLoader = null;\n\t\tthis.ktx2Loader = null;\n\t\tthis.meshoptDecoder = null;\n\n\t\tthis.pluginCallbacks = [];\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsClearcoatExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsDispersionExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFTextureBasisUExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFTextureWebPExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFTextureAVIFExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsSheenExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsTransmissionExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsVolumeExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsIorExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsEmissiveStrengthExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsSpecularExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsIridescenceExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsAnisotropyExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsBumpExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFLightsExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMeshoptCompression( parser, EXTENSIONS.EXT_MESHOPT_COMPRESSION );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMeshoptCompression( parser, EXTENSIONS.KHR_MESHOPT_COMPRESSION );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMeshGpuInstancing( parser );\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Starts loading from the given URL and passes the loaded glTF asset\n\t * to the `onLoad()` callback.\n\t *\n\t * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.\n\t * @param {function(GLTFLoader~LoadObject)} onLoad - Executed when the loading process has been finished.\n\t * @param {onProgressCallback} onProgress - Executed while the loading is in progress.\n\t * @param {onErrorCallback} onError - Executed when errors occur.\n\t */\n\tload( url, onLoad, onProgress, onError ) {\n\n\t\tconst scope = this;\n\n\t\tlet resourcePath;\n\n\t\tif ( this.resourcePath !== '' ) {\n\n\t\t\tresourcePath = this.resourcePath;\n\n\t\t} else if ( this.path !== '' ) {\n\n\t\t\t// If a base path is set, resources will be relative paths from that plus the relative path of the gltf file\n\t\t\t// Example path = 'https://my-cnd-server.com/', url = 'assets/models/model.gltf'\n\t\t\t// resourcePath = 'https://my-cnd-server.com/assets/models/'\n\t\t\t// referenced resource 'model.bin' will be loaded from 'https://my-cnd-server.com/assets/models/model.bin'\n\t\t\t// referenced resource '../textures/texture.png' will be loaded from 'https://my-cnd-server.com/assets/textures/texture.png'\n\t\t\tconst relativeUrl = LoaderUtils.extractUrlBase( url );\n\t\t\tresourcePath = LoaderUtils.resolveURL( relativeUrl, this.path );\n\n\t\t} else {\n\n\t\t\tresourcePath = LoaderUtils.extractUrlBase( url );\n\n\t\t}\n\n\t\t// Tells the LoadingManager to track an extra item, which resolves after\n\t\t// the model is fully loaded. This means the count of items loaded will\n\t\t// be incorrect, but ensures manager.onLoad() does not fire early.\n\t\tthis.manager.itemStart( url );\n\n\t\tconst _onError = function ( e ) {\n\n\t\t\tif ( onError ) {\n\n\t\t\t\tonError( e );\n\n\t\t\t} else {\n\n\t\t\t\tconsole.error( e );\n\n\t\t\t}\n\n\t\t\tscope.manager.itemError( url );\n\t\t\tscope.manager.itemEnd( url );\n\n\t\t};\n\n\t\tconst loader = new FileLoader( this.manager );\n\n\t\tloader.setPath( this.path );\n\t\tloader.setResponseType( 'arraybuffer' );\n\t\tloader.setRequestHeader( this.requestHeader );\n\t\tloader.setWithCredentials( this.withCredentials );\n\n\t\tloader.load( url, function ( data ) {\n\n\t\t\ttry {\n\n\t\t\t\tscope.parse( data, resourcePath, function ( gltf ) {\n\n\t\t\t\t\tonLoad( gltf );\n\n\t\t\t\t\tscope.manager.itemEnd( url );\n\n\t\t\t\t}, _onError );\n\n\t\t\t} catch ( e ) {\n\n\t\t\t\t_onError( e );\n\n\t\t\t}\n\n\t\t}, onProgress, _onError );\n\n\t}\n\n\t/**\n\t * Sets the given Draco loader to this loader. Required for decoding assets\n\t * compressed with the `KHR_draco_mesh_compression` extension.\n\t *\n\t * @param {DRACOLoader} dracoLoader - The Draco loader to set.\n\t * @return {GLTFLoader} A reference to this loader.\n\t */\n\tsetDRACOLoader( dracoLoader ) {\n\n\t\tthis.dracoLoader = dracoLoader;\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Sets the given KTX2 loader to this loader. Required for loading KTX2\n\t * compressed textures.\n\t *\n\t * @param {KTX2Loader} ktx2Loader - The KTX2 loader to set.\n\t * @return {GLTFLoader} A reference to this loader.\n\t */\n\tsetKTX2Loader( ktx2Loader ) {\n\n\t\tthis.ktx2Loader = ktx2Loader;\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Sets the given meshopt decoder. Required for decoding assets\n\t * compressed with the `EXT_meshopt_compression` extension.\n\t *\n\t * @param {Object} meshoptDecoder - The meshopt decoder to set.\n\t * @return {GLTFLoader} A reference to this loader.\n\t */\n\tsetMeshoptDecoder( meshoptDecoder ) {\n\n\t\tthis.meshoptDecoder = meshoptDecoder;\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Registers a plugin callback. This API is internally used to implement the various\n\t * glTF extensions but can also used by third-party code to add additional logic\n\t * to the loader.\n\t *\n\t * @param {function(parser:GLTFParser)} callback - The callback function to register.\n\t * @return {GLTFLoader} A reference to this loader.\n\t */\n\tregister( callback ) {\n\n\t\tif ( this.pluginCallbacks.indexOf( callback ) === - 1 ) {\n\n\t\t\tthis.pluginCallbacks.push( callback );\n\n\t\t}\n\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Unregisters a plugin callback.\n\t *\n\t * @param {Function} callback - The callback function to unregister.\n\t * @return {GLTFLoader} A reference to this loader.\n\t */\n\tunregister( callback ) {\n\n\t\tif ( this.pluginCallbacks.indexOf( callback ) !== - 1 ) {\n\n\t\t\tthis.pluginCallbacks.splice( this.pluginCallbacks.indexOf( callback ), 1 );\n\n\t\t}\n\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Parses the given glTF data and returns the resulting group.\n\t *\n\t * @param {string|ArrayBuffer} data - The raw glTF data.\n\t * @param {string} path - The URL base path.\n\t * @param {function(GLTFLoader~LoadObject)} onLoad - Executed when the loading process has been finished.\n\t * @param {onErrorCallback} onError - Executed when errors occur.\n\t */\n\tparse( data, path, onLoad, onError ) {\n\n\t\tlet json;\n\t\tconst extensions = {};\n\t\tconst plugins = {};\n\t\tconst textDecoder = new TextDecoder();\n\n\t\tif ( typeof data === 'string' ) {\n\n\t\t\tjson = JSON.parse( data );\n\n\t\t} else if ( data instanceof ArrayBuffer ) {\n\n\t\t\tconst magic = textDecoder.decode( new Uint8Array( data, 0, 4 ) );\n\n\t\t\tif ( magic === BINARY_EXTENSION_HEADER_MAGIC ) {\n\n\t\t\t\ttry {\n\n\t\t\t\t\textensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new GLTFBinaryExtension( data );\n\n\t\t\t\t} catch ( error ) {\n\n\t\t\t\t\tif ( onError ) onError( error );\n\t\t\t\t\treturn;\n\n\t\t\t\t}\n\n\t\t\t\tjson = JSON.parse( extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content );\n\n\t\t\t} else {\n\n\t\t\t\tjson = JSON.parse( textDecoder.decode( data ) );\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tjson = data;\n\n\t\t}\n\n\t\tif ( json.asset === undefined || json.asset.version[ 0 ] < 2 ) {\n\n\t\t\tif ( onError ) onError( new Error( 'THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported.' ) );\n\t\t\treturn;\n\n\t\t}\n\n\t\tconst parser = new GLTFParser( json, {\n\n\t\t\tpath: path || this.resourcePath || '',\n\t\t\tcrossOrigin: this.crossOrigin,\n\t\t\trequestHeader: this.requestHeader,\n\t\t\tmanager: this.manager,\n\t\t\tktx2Loader: this.ktx2Loader,\n\t\t\tmeshoptDecoder: this.meshoptDecoder\n\n\t\t} );\n\n\t\tparser.fileLoader.setRequestHeader( this.requestHeader );\n\n\t\tfor ( let i = 0; i < this.pluginCallbacks.length; i ++ ) {\n\n\t\t\tconst plugin = this.pluginCallbacks[ i ]( parser );\n\n\t\t\tif ( ! plugin.name ) console.error( 'THREE.GLTFLoader: Invalid plugin found: missing name' );\n\n\t\t\tplugins[ plugin.name ] = plugin;\n\n\t\t\t// Workaround to avoid determining as unknown extension\n\t\t\t// in addUnknownExtensionsToUserData().\n\t\t\t// Remove this workaround if we move all the existing\n\t\t\t// extension handlers to plugin system\n\t\t\textensions[ plugin.name ] = true;\n\n\t\t}\n\n\t\tif ( json.extensionsUsed ) {\n\n\t\t\tfor ( let i = 0; i < json.extensionsUsed.length; ++ i ) {\n\n\t\t\t\tconst extensionName = json.extensionsUsed[ i ];\n\t\t\t\tconst extensionsRequired = json.extensionsRequired || [];\n\n\t\t\t\tswitch ( extensionName ) {\n\n\t\t\t\t\tcase EXTENSIONS.KHR_MATERIALS_UNLIT:\n\t\t\t\t\t\textensions[ extensionName ] = new GLTFMaterialsUnlitExtension();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:\n\t\t\t\t\t\textensions[ extensionName ] = new GLTFDracoMeshCompressionExtension( json, this.dracoLoader );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase EXTENSIONS.KHR_TEXTURE_TRANSFORM:\n\t\t\t\t\t\textensions[ extensionName ] = new GLTFTextureTransformExtension();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase EXTENSIONS.KHR_MESH_QUANTIZATION:\n\t\t\t\t\t\textensions[ extensionName ] = new GLTFMeshQuantizationExtension();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\n\t\t\t\t\t\tif ( extensionsRequired.indexOf( extensionName ) >= 0 && plugins[ extensionName ] === undefined ) {\n\n\t\t\t\t\t\t\tconsole.warn( 'THREE.GLTFLoader: Unknown extension \"' + extensionName + '\".' );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tparser.setExtensions( extensions );\n\t\tparser.setPlugins( plugins );\n\t\tparser.parse( onLoad, onError );\n\n\t}\n\n\t/**\n\t * Async version of {@link GLTFLoader#parse}.\n\t *\n\t * @async\n\t * @param {string|ArrayBuffer} data - The raw glTF data.\n\t * @param {string} path - The URL base path.\n\t * @return {Promise<GLTFLoader~LoadObject>} A Promise that resolves with the loaded glTF when the parsing has been finished.\n\t */\n\tparseAsync( data, path ) {\n\n\t\tconst scope = this;\n\n\t\treturn new Promise( function ( resolve, reject ) {\n\n\t\t\tscope.parse( data, path, resolve, reject );\n\n\t\t} );\n\n\t}\n\n}\n\n/* GLTFREGISTRY */\n\nfunction GLTFRegistry() {\n\n\tlet objects = {};\n\n\treturn\t{\n\n\t\tget: function ( key ) {\n\n\t\t\treturn objects[ key ];\n\n\t\t},\n\n\t\tadd: function ( key, object ) {\n\n\t\t\tobjects[ key ] = object;\n\n\t\t},\n\n\t\tremove: function ( key ) {\n\n\t\t\tdelete objects[ key ];\n\n\t\t},\n\n\t\tremoveAll: function () {\n\n\t\t\tobjects = {};\n\n\t\t}\n\n\t};\n\n}\n\n/*********************************/\n/********** EXTENSIONS ***********/\n/*********************************/\n\nfunction getMaterialExtension( parser, materialIndex, extensionName ) {\n\n\tconst materialDef = parser.json.materials[ materialIndex ];\n\n\tif ( materialDef.extensions && materialDef.extensions[ extensionName ] ) {\n\n\t\treturn materialDef.extensions[ extensionName ];\n\n\t}\n\n\treturn null;\n\n}\n\nconst EXTENSIONS = {\n\tKHR_BINARY_GLTF: 'KHR_binary_glTF',\n\tKHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression',\n\tKHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',\n\tKHR_MATERIALS_CLEARCOAT: 'KHR_materials_clearcoat',\n\tKHR_MATERIALS_DISPERSION: 'KHR_materials_dispersion',\n\tKHR_MATERIALS_IOR: 'KHR_materials_ior',\n\tKHR_MATERIALS_SHEEN: 'KHR_materials_sheen',\n\tKHR_MATERIALS_SPECULAR: 'KHR_materials_specular',\n\tKHR_MATERIALS_TRANSMISSION: 'KHR_materials_transmission',\n\tKHR_MATERIALS_IRIDESCENCE: 'KHR_materials_iridescence',\n\tKHR_MATERIALS_ANISOTROPY: 'KHR_materials_anisotropy',\n\tKHR_MATERIALS_UNLIT: 'KHR_materials_unlit',\n\tKHR_MATERIALS_VOLUME: 'KHR_materials_volume',\n\tKHR_TEXTURE_BASISU: 'KHR_texture_basisu',\n\tKHR_TEXTURE_TRANSFORM: 'KHR_texture_transform',\n\tKHR_MESH_QUANTIZATION: 'KHR_mesh_quantization',\n\tKHR_MATERIALS_EMISSIVE_STRENGTH: 'KHR_materials_emissive_strength',\n\tEXT_MATERIALS_BUMP: 'EXT_materials_bump',\n\tEXT_TEXTURE_WEBP: 'EXT_texture_webp',\n\tEXT_TEXTURE_AVIF: 'EXT_texture_avif',\n\tEXT_MESHOPT_COMPRESSION: 'EXT_meshopt_compression',\n\tKHR_MESHOPT_COMPRESSION: 'KHR_meshopt_compression',\n\tEXT_MESH_GPU_INSTANCING: 'EXT_mesh_gpu_instancing'\n};\n\n/**\n * Punctual Lights Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual\n *\n * @private\n */\nclass GLTFLightsExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_LIGHTS_PUNCTUAL;\n\n\t\t// Object3D instance caches\n\t\tthis.cache = { refs: {}, uses: {} };\n\n\t}\n\n\t_markDefs() {\n\n\t\tconst parser = this.parser;\n\t\tconst nodeDefs = this.parser.json.nodes || [];\n\n\t\tfor ( let nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex ++ ) {\n\n\t\t\tconst nodeDef = nodeDefs[ nodeIndex ];\n\n\t\t\tif ( nodeDef.extensions\n\t\t\t\t\t&& nodeDef.extensions[ this.name ]\n\t\t\t\t\t&& nodeDef.extensions[ this.name ].light !== undefined ) {\n\n\t\t\t\tparser._addNodeRef( this.cache, nodeDef.extensions[ this.name ].light );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t_loadLight( lightIndex ) {\n\n\t\tconst parser = this.parser;\n\t\tconst cacheKey = 'light:' + lightIndex;\n\t\tlet dependency = parser.cache.get( cacheKey );\n\n\t\tif ( dependency ) return dependency;\n\n\t\tconst json = parser.json;\n\t\tconst extensions = ( json.extensions && json.extensions[ this.name ] ) || {};\n\t\tconst lightDefs = extensions.lights || [];\n\t\tconst lightDef = lightDefs[ lightIndex ];\n\t\tlet lightNode;\n\n\t\tconst color = new Color( 0xffffff );\n\n\t\tif ( lightDef.color !== undefined ) color.setRGB( lightDef.color[ 0 ], lightDef.color[ 1 ], lightDef.color[ 2 ], LinearSRGBColorSpace );\n\n\t\tconst range = lightDef.range !== undefined ? lightDef.range : 0;\n\n\t\tswitch ( lightDef.type ) {\n\n\t\t\tcase 'directional':\n\t\t\t\tlightNode = new DirectionalLight( color );\n\t\t\t\tlightNode.target.position.set( 0, 0, - 1 );\n\t\t\t\tlightNode.add( lightNode.target );\n\t\t\t\tbreak;\n\n\t\t\tcase 'point':\n\t\t\t\tlightNode = new PointLight( color );\n\t\t\t\tlightNode.distance = range;\n\t\t\t\tbreak;\n\n\t\t\tcase 'spot':\n\t\t\t\tlightNode = new SpotLight( color );\n\t\t\t\tlightNode.distance = range;\n\t\t\t\t// Handle spotlight properties.\n\t\t\t\tlightDef.spot = lightDef.spot || {};\n\t\t\t\tlightDef.spot.innerConeAngle = lightDef.spot.innerConeAngle !== undefined ? lightDef.spot.innerConeAngle : 0;\n\t\t\t\tlightDef.spot.outerConeAngle = lightDef.spot.outerConeAngle !== undefined ? lightDef.spot.outerConeAngle : Math.PI / 4.0;\n\t\t\t\tlightNode.angle = lightDef.spot.outerConeAngle;\n\t\t\t\tlightNode.penumbra = 1.0 - lightDef.spot.innerConeAngle / lightDef.spot.outerConeAngle;\n\t\t\t\tlightNode.target.position.set( 0, 0, - 1 );\n\t\t\t\tlightNode.add( lightNode.target );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tthrow new Error( 'THREE.GLTFLoader: Unexpected light type: ' + lightDef.type );\n\n\t\t}\n\n\t\t// Some lights (e.g. spot) default to a position other than the origin. Reset the position\n\t\t// here, because node-level parsing will only override position if explicitly specified.\n\t\tlightNode.position.set( 0, 0, 0 );\n\n\t\tassignExtrasToUserData( lightNode, lightDef );\n\n\t\tif ( lightDef.intensity !== undefined ) lightNode.intensity = lightDef.intensity;\n\n\t\tlightNode.name = parser.createUniqueName( lightDef.name || ( 'light_' + lightIndex ) );\n\n\t\tdependency = Promise.resolve( lightNode );\n\n\t\tparser.cache.add( cacheKey, dependency );\n\n\t\treturn dependency;\n\n\t}\n\n\tgetDependency( type, index ) {\n\n\t\tif ( type !== 'light' ) return;\n\n\t\treturn this._loadLight( index );\n\n\t}\n\n\tcreateNodeAttachment( nodeIndex ) {\n\n\t\tconst self = this;\n\t\tconst parser = this.parser;\n\t\tconst json = parser.json;\n\t\tconst nodeDef = json.nodes[ nodeIndex ];\n\t\tconst lightDef = ( nodeDef.extensions && nodeDef.extensions[ this.name ] ) || {};\n\t\tconst lightIndex = lightDef.light;\n\n\t\tif ( lightIndex === undefined ) return null;\n\n\t\treturn this._loadLight( lightIndex ).then( function ( light ) {\n\n\t\t\treturn parser._getNodeRef( self.cache, lightIndex, light );\n\n\t\t} );\n\n\t}\n\n}\n\n/**\n * Unlit Materials Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_unlit\n *\n * @private\n */\nclass GLTFMaterialsUnlitExtension {\n\n\tconstructor() {\n\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_UNLIT;\n\n\t}\n\n\tgetMaterialType() {\n\n\t\treturn MeshBasicMaterial;\n\n\t}\n\n\textendParams( materialParams, materialDef, parser ) {\n\n\t\tconst pending = [];\n\n\t\tmaterialParams.color = new Color( 1.0, 1.0, 1.0 );\n\t\tmaterialParams.opacity = 1.0;\n\n\t\tconst metallicRoughness = materialDef.pbrMetallicRoughness;\n\n\t\tif ( metallicRoughness ) {\n\n\t\t\tif ( Array.isArray( metallicRoughness.baseColorFactor ) ) {\n\n\t\t\t\tconst array = metallicRoughness.baseColorFactor;\n\n\t\t\t\tmaterialParams.color.setRGB( array[ 0 ], array[ 1 ], array[ 2 ], LinearSRGBColorSpace );\n\t\t\t\tmaterialParams.opacity = array[ 3 ];\n\n\t\t\t}\n\n\t\t\tif ( metallicRoughness.baseColorTexture !== undefined ) {\n\n\t\t\t\tpending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture, SRGBColorSpace ) );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * Materials Emissive Strength Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/blob/5768b3ce0ef32bc39cdf1bef10b948586635ead3/extensions/2.0/Khronos/KHR_materials_emissive_strength/README.md\n *\n * @private\n */\nclass GLTFMaterialsEmissiveStrengthExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_EMISSIVE_STRENGTH;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tif ( extension.emissiveStrength !== undefined ) {\n\n\t\t\tmaterialParams.emissiveIntensity = extension.emissiveStrength;\n\n\t\t}\n\n\t\treturn Promise.resolve();\n\n\t}\n\n}\n\n/**\n * Clearcoat Materials Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_clearcoat\n *\n * @private\n */\nclass GLTFMaterialsClearcoatExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_CLEARCOAT;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\treturn extension !== null ? MeshPhysicalMaterial : null;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tconst pending = [];\n\n\t\tif ( extension.clearcoatFactor !== undefined ) {\n\n\t\t\tmaterialParams.clearcoat = extension.clearcoatFactor;\n\n\t\t}\n\n\t\tif ( extension.clearcoatTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'clearcoatMap', extension.clearcoatTexture ) );\n\n\t\t}\n\n\t\tif ( extension.clearcoatRoughnessFactor !== undefined ) {\n\n\t\t\tmaterialParams.clearcoatRoughness = extension.clearcoatRoughnessFactor;\n\n\t\t}\n\n\t\tif ( extension.clearcoatRoughnessTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'clearcoatRoughnessMap', extension.clearcoatRoughnessTexture ) );\n\n\t\t}\n\n\t\tif ( extension.clearcoatNormalTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'clearcoatNormalMap', extension.clearcoatNormalTexture ) );\n\n\t\t\tif ( extension.clearcoatNormalTexture.scale !== undefined ) {\n\n\t\t\t\tconst scale = extension.clearcoatNormalTexture.scale;\n\n\t\t\t\tmaterialParams.clearcoatNormalScale = new Vector2( scale, scale );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * Materials dispersion Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_dispersion\n *\n * @private\n */\nclass GLTFMaterialsDispersionExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_DISPERSION;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\treturn extension !== null ? MeshPhysicalMaterial : null;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tmaterialParams.dispersion = extension.dispersion !== undefined ? extension.dispersion : 0;\n\n\t\treturn Promise.resolve();\n\n\t}\n\n}\n\n/**\n * Iridescence Materials Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_iridescence\n *\n * @private\n */\nclass GLTFMaterialsIridescenceExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_IRIDESCENCE;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\treturn extension !== null ? MeshPhysicalMaterial : null;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tconst pending = [];\n\n\t\tif ( extension.iridescenceFactor !== undefined ) {\n\n\t\t\tmaterialParams.iridescence = extension.iridescenceFactor;\n\n\t\t}\n\n\t\tif ( extension.iridescenceTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'iridescenceMap', extension.iridescenceTexture ) );\n\n\t\t}\n\n\t\tif ( extension.iridescenceIor !== undefined ) {\n\n\t\t\tmaterialParams.iridescenceIOR = extension.iridescenceIor;\n\n\t\t}\n\n\t\tif ( materialParams.iridescenceThicknessRange === undefined ) {\n\n\t\t\tmaterialParams.iridescenceThicknessRange = [ 100, 400 ];\n\n\t\t}\n\n\t\tif ( extension.iridescenceThicknessMinimum !== undefined ) {\n\n\t\t\tmaterialParams.iridescenceThicknessRange[ 0 ] = extension.iridescenceThicknessMinimum;\n\n\t\t}\n\n\t\tif ( extension.iridescenceThicknessMaximum !== undefined ) {\n\n\t\t\tmaterialParams.iridescenceThicknessRange[ 1 ] = extension.iridescenceThicknessMaximum;\n\n\t\t}\n\n\t\tif ( extension.iridescenceThicknessTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'iridescenceThicknessMap', extension.iridescenceThicknessTexture ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * Sheen Materials Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_sheen\n *\n * @private\n */\nclass GLTFMaterialsSheenExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_SHEEN;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\treturn extension !== null ? MeshPhysicalMaterial : null;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tconst pending = [];\n\n\t\tmaterialParams.sheenColor = new Color( 0, 0, 0 );\n\t\tmaterialParams.sheenRoughness = 0;\n\t\tmaterialParams.sheen = 1;\n\n\t\tif ( extension.sheenColorFactor !== undefined ) {\n\n\t\t\tconst colorFactor = extension.sheenColorFactor;\n\t\t\tmaterialParams.sheenColor.setRGB( colorFactor[ 0 ], colorFactor[ 1 ], colorFactor[ 2 ], LinearSRGBColorSpace );\n\n\t\t}\n\n\t\tif ( extension.sheenRoughnessFactor !== undefined ) {\n\n\t\t\tmaterialParams.sheenRoughness = extension.sheenRoughnessFactor;\n\n\t\t}\n\n\t\tif ( extension.sheenColorTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'sheenColorMap', extension.sheenColorTexture, SRGBColorSpace ) );\n\n\t\t}\n\n\t\tif ( extension.sheenRoughnessTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'sheenRoughnessMap', extension.sheenRoughnessTexture ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * Transmission Materials Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_transmission\n * Draft: https://github.com/KhronosGroup/glTF/pull/1698\n *\n * @private\n */\nclass GLTFMaterialsTransmissionExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_TRANSMISSION;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\treturn extension !== null ? MeshPhysicalMaterial : null;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tconst pending = [];\n\n\t\tif ( extension.transmissionFactor !== undefined ) {\n\n\t\t\tmaterialParams.transmission = extension.transmissionFactor;\n\n\t\t}\n\n\t\tif ( extension.transmissionTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'transmissionMap', extension.transmissionTexture ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * Materials Volume Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_volume\n *\n * @private\n */\nclass GLTFMaterialsVolumeExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_VOLUME;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\treturn extension !== null ? MeshPhysicalMaterial : null;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tconst pending = [];\n\n\t\tmaterialParams.thickness = extension.thicknessFactor !== undefined ? extension.thicknessFactor : 0;\n\n\t\tif ( extension.thicknessTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'thicknessMap', extension.thicknessTexture ) );\n\n\t\t}\n\n\t\tmaterialParams.attenuationDistance = extension.attenuationDistance || Infinity;\n\n\t\tconst colorArray = extension.attenuationColor || [ 1, 1, 1 ];\n\t\tmaterialParams.attenuationColor = new Color().setRGB( colorArray[ 0 ], colorArray[ 1 ], colorArray[ 2 ], LinearSRGBColorSpace );\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * Materials ior Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_ior\n *\n * @private\n */\nclass GLTFMaterialsIorExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_IOR;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\treturn extension !== null ? MeshPhysicalMaterial : null;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tmaterialParams.ior = extension.ior !== undefined ? extension.ior : 1.5;\n\n\t\tif ( materialParams.ior === 0 ) materialParams.ior = 1000; // see #26167\n\n\t\treturn Promise.resolve();\n\n\t}\n\n}\n\n/**\n * Materials specular Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_specular\n *\n * @private\n */\nclass GLTFMaterialsSpecularExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_SPECULAR;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\treturn extension !== null ? MeshPhysicalMaterial : null;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tconst pending = [];\n\n\t\tmaterialParams.specularIntensity = extension.specularFactor !== undefined ? extension.specularFactor : 1.0;\n\n\t\tif ( extension.specularTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'specularIntensityMap', extension.specularTexture ) );\n\n\t\t}\n\n\t\tconst colorArray = extension.specularColorFactor || [ 1, 1, 1 ];\n\t\tmaterialParams.specularColor = new Color().setRGB( colorArray[ 0 ], colorArray[ 1 ], colorArray[ 2 ], LinearSRGBColorSpace );\n\n\t\tif ( extension.specularColorTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'specularColorMap', extension.specularColorTexture, SRGBColorSpace ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n\n/**\n * Materials bump Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/EXT_materials_bump\n *\n * @private\n */\nclass GLTFMaterialsBumpExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.EXT_MATERIALS_BUMP;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\treturn extension !== null ? MeshPhysicalMaterial : null;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tconst pending = [];\n\n\t\tmaterialParams.bumpScale = extension.bumpFactor !== undefined ? extension.bumpFactor : 1.0;\n\n\t\tif ( extension.bumpTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'bumpMap', extension.bumpTexture ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * Materials anisotropy Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_anisotropy\n *\n * @private\n */\nclass GLTFMaterialsAnisotropyExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_ANISOTROPY;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\treturn extension !== null ? MeshPhysicalMaterial : null;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tconst pending = [];\n\n\t\tif ( extension.anisotropyStrength !== undefined ) {\n\n\t\t\tmaterialParams.anisotropy = extension.anisotropyStrength;\n\n\t\t}\n\n\t\tif ( extension.anisotropyRotation !== undefined ) {\n\n\t\t\tmaterialParams.anisotropyRotation = extension.anisotropyRotation;\n\n\t\t}\n\n\t\tif ( extension.anisotropyTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'anisotropyMap', extension.anisotropyTexture ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * BasisU Texture Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_texture_basisu\n *\n * @private\n */\nclass GLTFTextureBasisUExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_TEXTURE_BASISU;\n\n\t}\n\n\tloadTexture( textureIndex ) {\n\n\t\tconst parser = this.parser;\n\t\tconst json = parser.json;\n\n\t\tconst textureDef = json.textures[ textureIndex ];\n\n\t\tif ( ! textureDef.extensions || ! textureDef.extensions[ this.name ] ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\tconst extension = textureDef.extensions[ this.name ];\n\t\tconst loader = parser.options.ktx2Loader;\n\n\t\tif ( ! loader ) {\n\n\t\t\tif ( json.extensionsRequired && json.extensionsRequired.indexOf( this.name ) >= 0 ) {\n\n\t\t\t\tthrow new Error( 'THREE.GLTFLoader: setKTX2Loader must be called before loading KTX2 textures' );\n\n\t\t\t} else {\n\n\t\t\t\t// Assumes that the extension is optional and that a fallback texture is present\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn parser.loadTextureImage( textureIndex, extension.source, loader );\n\n\t}\n\n}\n\n/**\n * WebP Texture Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_texture_webp\n *\n * @private\n */\nclass GLTFTextureWebPExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.EXT_TEXTURE_WEBP;\n\n\t}\n\n\tloadTexture( textureIndex ) {\n\n\t\tconst name = this.name;\n\t\tconst parser = this.parser;\n\t\tconst json = parser.json;\n\n\t\tconst textureDef = json.textures[ textureIndex ];\n\n\t\tif ( ! textureDef.extensions || ! textureDef.extensions[ name ] ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\tconst extension = textureDef.extensions[ name ];\n\t\tconst source = json.images[ extension.source ];\n\n\t\tlet loader = parser.textureLoader;\n\t\tif ( source.uri ) {\n\n\t\t\tconst handler = parser.options.manager.getHandler( source.uri );\n\t\t\tif ( handler !== null ) loader = handler;\n\n\t\t}\n\n\t\treturn parser.loadTextureImage( textureIndex, extension.source, loader );\n\n\t}\n\n}\n\n/**\n * AVIF Texture Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_texture_avif\n *\n * @private\n */\nclass GLTFTextureAVIFExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.EXT_TEXTURE_AVIF;\n\n\t}\n\n\tloadTexture( textureIndex ) {\n\n\t\tconst name = this.name;\n\t\tconst parser = this.parser;\n\t\tconst json = parser.json;\n\n\t\tconst textureDef = json.textures[ textureIndex ];\n\n\t\tif ( ! textureDef.extensions || ! textureDef.extensions[ name ] ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\tconst extension = textureDef.extensions[ name ];\n\t\tconst source = json.images[ extension.source ];\n\n\t\tlet loader = parser.textureLoader;\n\t\tif ( source.uri ) {\n\n\t\t\tconst handler = parser.options.manager.getHandler( source.uri );\n\t\t\tif ( handler !== null ) loader = handler;\n\n\t\t}\n\n\t\treturn parser.loadTextureImage( textureIndex, extension.source, loader );\n\n\t}\n\n}\n\n/**\n * meshopt BufferView Compression Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_meshopt_compression\n *\n * @private\n */\nclass GLTFMeshoptCompression {\n\n\tconstructor( parser, name ) {\n\n\t\tthis.name = name;\n\t\tthis.parser = parser;\n\n\t}\n\n\tloadBufferView( index ) {\n\n\t\tconst json = this.parser.json;\n\t\tconst bufferView = json.bufferViews[ index ];\n\n\t\tif ( bufferView.extensions && bufferView.extensions[ this.name ] ) {\n\n\t\t\tconst extensionDef = bufferView.extensions[ this.name ];\n\n\t\t\tconst buffer = this.parser.getDependency( 'buffer', extensionDef.buffer );\n\t\t\tconst decoder = this.parser.options.meshoptDecoder;\n\n\t\t\tif ( ! decoder || ! decoder.supported ) {\n\n\t\t\t\tif ( json.extensionsRequired && json.extensionsRequired.indexOf( this.name ) >= 0 ) {\n\n\t\t\t\t\tthrow new Error( 'THREE.GLTFLoader: setMeshoptDecoder must be called before loading compressed files' );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// Assumes that the extension is optional and that fallback buffer data is present\n\t\t\t\t\treturn null;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn buffer.then( function ( res ) {\n\n\t\t\t\tconst byteOffset = extensionDef.byteOffset || 0;\n\t\t\t\tconst byteLength = extensionDef.byteLength || 0;\n\n\t\t\t\tconst count = extensionDef.count;\n\t\t\t\tconst stride = extensionDef.byteStride;\n\n\t\t\t\tconst source = new Uint8Array( res, byteOffset, byteLength );\n\n\t\t\t\tif ( decoder.decodeGltfBufferAsync ) {\n\n\t\t\t\t\treturn decoder.decodeGltfBufferAsync( count, stride, source, extensionDef.mode, extensionDef.filter ).then( function ( res ) {\n\n\t\t\t\t\t\treturn res.buffer;\n\n\t\t\t\t\t} );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// Support for MeshoptDecoder 0.18 or earlier, without decodeGltfBufferAsync\n\t\t\t\t\treturn decoder.ready.then( function () {\n\n\t\t\t\t\t\tconst result = new ArrayBuffer( count * stride );\n\t\t\t\t\t\tdecoder.decodeGltfBuffer( new Uint8Array( result ), count, stride, source, extensionDef.mode, extensionDef.filter );\n\t\t\t\t\t\treturn result;\n\n\t\t\t\t\t} );\n\n\t\t\t\t}\n\n\t\t\t} );\n\n\t\t} else {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t}\n\n}\n\n/**\n * GPU Instancing Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_mesh_gpu_instancing\n *\n * @private\n */\nclass GLTFMeshGpuInstancing {\n\n\tconstructor( parser ) {\n\n\t\tthis.name = EXTENSIONS.EXT_MESH_GPU_INSTANCING;\n\t\tthis.parser = parser;\n\n\t}\n\n\tcreateNodeMesh( nodeIndex ) {\n\n\t\tconst json = this.parser.json;\n\t\tconst nodeDef = json.nodes[ nodeIndex ];\n\n\t\tif ( ! nodeDef.extensions || ! nodeDef.extensions[ this.name ] ||\n\t\t\tnodeDef.mesh === undefined ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\tconst meshDef = json.meshes[ nodeDef.mesh ];\n\n\t\t// No Points or Lines + Instancing support yet\n\n\t\tfor ( const primitive of meshDef.primitives ) {\n\n\t\t\tif ( primitive.mode !== WEBGL_CONSTANTS.TRIANGLES &&\n\t\t\t\t primitive.mode !== WEBGL_CONSTANTS.TRIANGLE_STRIP &&\n\t\t\t\t primitive.mode !== WEBGL_CONSTANTS.TRIANGLE_FAN &&\n\t\t\t\t primitive.mode !== undefined ) {\n\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t}\n\n\t\tconst extensionDef = nodeDef.extensions[ this.name ];\n\t\tconst attributesDef = extensionDef.attributes;\n\n\t\t// @TODO: Can we support InstancedMesh + SkinnedMesh?\n\n\t\tconst pending = [];\n\t\tconst attributes = {};\n\n\t\tfor ( const key in attributesDef ) {\n\n\t\t\tpending.push( this.parser.getDependency( 'accessor', attributesDef[ key ] ).then( accessor => {\n\n\t\t\t\tattributes[ key ] = accessor;\n\t\t\t\treturn attributes[ key ];\n\n\t\t\t} ) );\n\n\t\t}\n\n\t\tif ( pending.length < 1 ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\tpending.push( this.parser.createNodeMesh( nodeIndex ) );\n\n\t\treturn Promise.all( pending ).then( results => {\n\n\t\t\tconst nodeObject = results.pop();\n\t\t\tconst meshes = nodeObject.isGroup ? nodeObject.children : [ nodeObject ];\n\t\t\tconst count = results[ 0 ].count; // All attribute counts should be same\n\t\t\tconst instancedMeshes = [];\n\n\t\t\tfor ( const mesh of meshes ) {\n\n\t\t\t\t// Temporal variables\n\t\t\t\tconst m = new Matrix4();\n\t\t\t\tconst p = new Vector3();\n\t\t\t\tconst q = new Quaternion();\n\t\t\t\tconst s = new Vector3( 1, 1, 1 );\n\n\t\t\t\tconst instancedMesh = new InstancedMesh( mesh.geometry, mesh.material, count );\n\n\t\t\t\tfor ( let i = 0; i < count; i ++ ) {\n\n\t\t\t\t\tif ( attributes.TRANSLATION ) {\n\n\t\t\t\t\t\tp.fromBufferAttribute( attributes.TRANSLATION, i );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( attributes.ROTATION ) {\n\n\t\t\t\t\t\tq.fromBufferAttribute( attributes.ROTATION, i );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( attributes.SCALE ) {\n\n\t\t\t\t\t\ts.fromBufferAttribute( attributes.SCALE, i );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tinstancedMesh.setMatrixAt( i, m.compose( p, q, s ) );\n\n\t\t\t\t}\n\n\t\t\t\t// Add instance attributes to the geometry, excluding TRS.\n\t\t\t\tfor ( const attributeName in attributes ) {\n\n\t\t\t\t\tif ( attributeName === '_COLOR_0' ) {\n\n\t\t\t\t\t\tconst attr = attributes[ attributeName ];\n\t\t\t\t\t\tinstancedMesh.instanceColor = new InstancedBufferAttribute( attr.array, attr.itemSize, attr.normalized );\n\n\t\t\t\t\t} else if ( attributeName !== 'TRANSLATION' &&\n\t\t\t\t\t\t attributeName !== 'ROTATION' &&\n\t\t\t\t\t\t attributeName !== 'SCALE' ) {\n\n\t\t\t\t\t\tmesh.geometry.setAttribute( attributeName, attributes[ attributeName ] );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\t// Just in case\n\t\t\t\tObject3D.prototype.copy.call( instancedMesh, mesh );\n\n\t\t\t\tthis.parser.assignFinalMaterial( instancedMesh );\n\n\t\t\t\tinstancedMeshes.push( instancedMesh );\n\n\t\t\t}\n\n\t\t\tif ( nodeObject.isGroup ) {\n\n\t\t\t\tnodeObject.clear();\n\n\t\t\t\tnodeObject.add( ... instancedMeshes );\n\n\t\t\t\treturn nodeObject;\n\n\t\t\t}\n\n\t\t\treturn instancedMeshes[ 0 ];\n\n\t\t} );\n\n\t}\n\n}\n\n/* BINARY EXTENSION */\nconst BINARY_EXTENSION_HEADER_MAGIC = 'glTF';\nconst BINARY_EXTENSION_HEADER_LENGTH = 12;\nconst BINARY_EXTENSION_CHUNK_TYPES = { JSON: 0x4E4F534A, BIN: 0x004E4942 };\n\nclass GLTFBinaryExtension {\n\n\tconstructor( data ) {\n\n\t\tthis.name = EXTENSIONS.KHR_BINARY_GLTF;\n\t\tthis.content = null;\n\t\tthis.body = null;\n\n\t\tconst headerView = new DataView( data, 0, BINARY_EXTENSION_HEADER_LENGTH );\n\t\tconst textDecoder = new TextDecoder();\n\n\t\tthis.header = {\n\t\t\tmagic: textDecoder.decode( new Uint8Array( data.slice( 0, 4 ) ) ),\n\t\t\tversion: headerView.getUint32( 4, true ),\n\t\t\tlength: headerView.getUint32( 8, true )\n\t\t};\n\n\t\tif ( this.header.magic !== BINARY_EXTENSION_HEADER_MAGIC ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: Unsupported glTF-Binary header.' );\n\n\t\t} else if ( this.header.version < 2.0 ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: Legacy binary file detected.' );\n\n\t\t}\n\n\t\tconst chunkContentsLength = this.header.length - BINARY_EXTENSION_HEADER_LENGTH;\n\t\tconst chunkView = new DataView( data, BINARY_EXTENSION_HEADER_LENGTH );\n\t\tlet chunkIndex = 0;\n\n\t\twhile ( chunkIndex < chunkContentsLength ) {\n\n\t\t\tconst chunkLength = chunkView.getUint32( chunkIndex, true );\n\t\t\tchunkIndex += 4;\n\n\t\t\tconst chunkType = chunkView.getUint32( chunkIndex, true );\n\t\t\tchunkIndex += 4;\n\n\t\t\tif ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.JSON ) {\n\n\t\t\t\tconst contentArray = new Uint8Array( data, BINARY_EXTENSION_HEADER_LENGTH + chunkIndex, chunkLength );\n\t\t\t\tthis.content = textDecoder.decode( contentArray );\n\n\t\t\t} else if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.BIN ) {\n\n\t\t\t\tconst byteOffset = BINARY_EXTENSION_HEADER_LENGTH + chunkIndex;\n\t\t\t\tthis.body = data.slice( byteOffset, byteOffset + chunkLength );\n\n\t\t\t}\n\n\t\t\t// Clients must ignore chunks with unknown types.\n\n\t\t\tchunkIndex += chunkLength;\n\n\t\t}\n\n\t\tif ( this.content === null ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: JSON content not found.' );\n\n\t\t}\n\n\t}\n\n}\n\n/**\n * DRACO Mesh Compression Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression\n *\n * @private\n */\nclass GLTFDracoMeshCompressionExtension {\n\n\tconstructor( json, dracoLoader ) {\n\n\t\tif ( ! dracoLoader ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: No DRACOLoader instance provided.' );\n\n\t\t}\n\n\t\tthis.name = EXTENSIONS.KHR_DRACO_MESH_COMPRESSION;\n\t\tthis.json = json;\n\t\tthis.dracoLoader = dracoLoader;\n\t\tthis.dracoLoader.preload();\n\n\t}\n\n\tdecodePrimitive( primitive, parser ) {\n\n\t\tconst json = this.json;\n\t\tconst dracoLoader = this.dracoLoader;\n\t\tconst bufferViewIndex = primitive.extensions[ this.name ].bufferView;\n\t\tconst gltfAttributeMap = primitive.extensions[ this.name ].attributes;\n\t\tconst threeAttributeMap = {};\n\t\tconst attributeNormalizedMap = {};\n\t\tconst attributeTypeMap = {};\n\n\t\tfor ( const attributeName in gltfAttributeMap ) {\n\n\t\t\tconst threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase();\n\n\t\t\tthreeAttributeMap[ threeAttributeName ] = gltfAttributeMap[ attributeName ];\n\n\t\t}\n\n\t\tfor ( const attributeName in primitive.attributes ) {\n\n\t\t\tconst threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase();\n\n\t\t\tif ( gltfAttributeMap[ attributeName ] !== undefined ) {\n\n\t\t\t\tconst accessorDef = json.accessors[ primitive.attributes[ attributeName ] ];\n\t\t\t\tconst componentType = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];\n\n\t\t\t\tattributeTypeMap[ threeAttributeName ] = componentType.name;\n\t\t\t\tattributeNormalizedMap[ threeAttributeName ] = accessorDef.normalized === true;\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn parser.getDependency( 'bufferView', bufferViewIndex ).then( function ( bufferView ) {\n\n\t\t\treturn new Promise( function ( resolve, reject ) {\n\n\t\t\t\tdracoLoader.decodeDracoFile( bufferView, function ( geometry ) {\n\n\t\t\t\t\tfor ( const attributeName in geometry.attributes ) {\n\n\t\t\t\t\t\tconst attribute = geometry.attributes[ attributeName ];\n\t\t\t\t\t\tconst normalized = attributeNormalizedMap[ attributeName ];\n\n\t\t\t\t\t\tif ( normalized !== undefined ) attribute.normalized = normalized;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve( geometry );\n\n\t\t\t\t}, threeAttributeMap, attributeTypeMap, LinearSRGBColorSpace, reject );\n\n\t\t\t} );\n\n\t\t} );\n\n\t}\n\n}\n\n/**\n * Texture Transform Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_texture_transform\n *\n * @private\n */\nclass GLTFTextureTransformExtension {\n\n\tconstructor() {\n\n\t\tthis.name = EXTENSIONS.KHR_TEXTURE_TRANSFORM;\n\n\t}\n\n\textendTexture( texture, transform ) {\n\n\t\tif ( ( transform.texCoord === undefined || transform.texCoord === texture.channel )\n\t\t\t&& transform.offset === undefined\n\t\t\t&& transform.rotation === undefined\n\t\t\t&& transform.scale === undefined ) {\n\n\t\t\t// See https://github.com/mrdoob/three.js/issues/21819.\n\t\t\treturn texture;\n\n\t\t}\n\n\t\ttexture = texture.clone();\n\n\t\tif ( transform.texCoord !== undefined ) {\n\n\t\t\ttexture.channel = transform.texCoord;\n\n\t\t}\n\n\t\tif ( transform.offset !== undefined ) {\n\n\t\t\ttexture.offset.fromArray( transform.offset );\n\n\t\t}\n\n\t\tif ( transform.rotation !== undefined ) {\n\n\t\t\ttexture.rotation = transform.rotation;\n\n\t\t}\n\n\t\tif ( transform.scale !== undefined ) {\n\n\t\t\ttexture.repeat.fromArray( transform.scale );\n\n\t\t}\n\n\t\ttexture.needsUpdate = true;\n\n\t\treturn texture;\n\n\t}\n\n}\n\n/**\n * Mesh Quantization Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization\n *\n * @private\n */\nclass GLTFMeshQuantizationExtension {\n\n\tconstructor() {\n\n\t\tthis.name = EXTENSIONS.KHR_MESH_QUANTIZATION;\n\n\t}\n\n}\n\n/*********************************/\n/********** INTERPOLATION ********/\n/*********************************/\n\n// Spline Interpolation\n// Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#appendix-c-spline-interpolation\nclass GLTFCubicSplineInterpolant extends Interpolant {\n\n\tconstructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {\n\n\t\tsuper( parameterPositions, sampleValues, sampleSize, resultBuffer );\n\n\t}\n\n\tcopySampleValue_( index ) {\n\n\t\t// Copies a sample value to the result buffer. See description of glTF\n\t\t// CUBICSPLINE values layout in interpolate_() function below.\n\n\t\tconst result = this.resultBuffer,\n\t\t\tvalues = this.sampleValues,\n\t\t\tvalueSize = this.valueSize,\n\t\t\toffset = index * valueSize * 3 + valueSize;\n\n\t\tfor ( let i = 0; i !== valueSize; i ++ ) {\n\n\t\t\tresult[ i ] = values[ offset + i ];\n\n\t\t}\n\n\t\treturn result;\n\n\t}\n\n\tinterpolate_( i1, t0, t, t1 ) {\n\n\t\tconst result = this.resultBuffer;\n\t\tconst values = this.sampleValues;\n\t\tconst stride = this.valueSize;\n\n\t\tconst stride2 = stride * 2;\n\t\tconst stride3 = stride * 3;\n\n\t\tconst td = t1 - t0;\n\n\t\tconst p = ( t - t0 ) / td;\n\t\tconst pp = p * p;\n\t\tconst ppp = pp * p;\n\n\t\tconst offset1 = i1 * stride3;\n\t\tconst offset0 = offset1 - stride3;\n\n\t\tconst s2 = - 2 * ppp + 3 * pp;\n\t\tconst s3 = ppp - pp;\n\t\tconst s0 = 1 - s2;\n\t\tconst s1 = s3 - pp + p;\n\n\t\t// Layout of keyframe output values for CUBICSPLINE animations:\n\t\t// [ inTangent_1, splineVertex_1, outTangent_1, inTangent_2, splineVertex_2, ... ]\n\t\tfor ( let i = 0; i !== stride; i ++ ) {\n\n\t\t\tconst p0 = values[ offset0 + i + stride ]; // splineVertex_k\n\t\t\tconst m0 = values[ offset0 + i + stride2 ] * td; // outTangent_k * (t_k+1 - t_k)\n\t\t\tconst p1 = values[ offset1 + i + stride ]; // splineVertex_k+1\n\t\t\tconst m1 = values[ offset1 + i ] * td; // inTangent_k+1 * (t_k+1 - t_k)\n\n\t\t\tresult[ i ] = s0 * p0 + s1 * m0 + s2 * p1 + s3 * m1;\n\n\t\t}\n\n\t\treturn result;\n\n\t}\n\n}\n\nconst _quaternion = new Quaternion();\n\nclass GLTFCubicSplineQuaternionInterpolant extends GLTFCubicSplineInterpolant {\n\n\tinterpolate_( i1, t0, t, t1 ) {\n\n\t\tconst result = super.interpolate_( i1, t0, t, t1 );\n\n\t\t_quaternion.fromArray( result ).normalize().toArray( result );\n\n\t\treturn result;\n\n\t}\n\n}\n\n\n/*********************************/\n/********** INTERNALS ************/\n/*********************************/\n\n/* CONSTANTS */\n\nconst WEBGL_CONSTANTS = {\n\tFLOAT: 5126,\n\t//FLOAT_MAT2: 35674,\n\tFLOAT_MAT3: 35675,\n\tFLOAT_MAT4: 35676,\n\tFLOAT_VEC2: 35664,\n\tFLOAT_VEC3: 35665,\n\tFLOAT_VEC4: 35666,\n\tLINEAR: 9729,\n\tREPEAT: 10497,\n\tSAMPLER_2D: 35678,\n\tPOINTS: 0,\n\tLINES: 1,\n\tLINE_LOOP: 2,\n\tLINE_STRIP: 3,\n\tTRIANGLES: 4,\n\tTRIANGLE_STRIP: 5,\n\tTRIANGLE_FAN: 6,\n\tUNSIGNED_BYTE: 5121,\n\tUNSIGNED_SHORT: 5123\n};\n\nconst WEBGL_COMPONENT_TYPES = {\n\t5120: Int8Array,\n\t5121: Uint8Array,\n\t5122: Int16Array,\n\t5123: Uint16Array,\n\t5125: Uint32Array,\n\t5126: Float32Array\n};\n\nconst WEBGL_FILTERS = {\n\t9728: NearestFilter,\n\t9729: LinearFilter,\n\t9984: NearestMipmapNearestFilter,\n\t9985: LinearMipmapNearestFilter,\n\t9986: NearestMipmapLinearFilter,\n\t9987: LinearMipmapLinearFilter\n};\n\nconst WEBGL_WRAPPINGS = {\n\t33071: ClampToEdgeWrapping,\n\t33648: MirroredRepeatWrapping,\n\t10497: RepeatWrapping\n};\n\nconst WEBGL_TYPE_SIZES = {\n\t'SCALAR': 1,\n\t'VEC2': 2,\n\t'VEC3': 3,\n\t'VEC4': 4,\n\t'MAT2': 4,\n\t'MAT3': 9,\n\t'MAT4': 16\n};\n\nconst ATTRIBUTES = {\n\tPOSITION: 'position',\n\tNORMAL: 'normal',\n\tTANGENT: 'tangent',\n\tTEXCOORD_0: 'uv',\n\tTEXCOORD_1: 'uv1',\n\tTEXCOORD_2: 'uv2',\n\tTEXCOORD_3: 'uv3',\n\tCOLOR_0: 'color',\n\tWEIGHTS_0: 'skinWeight',\n\tJOINTS_0: 'skinIndex',\n};\n\nconst PATH_PROPERTIES = {\n\tscale: 'scale',\n\ttranslation: 'position',\n\trotation: 'quaternion',\n\tweights: 'morphTargetInfluences'\n};\n\nconst INTERPOLATION = {\n\tCUBICSPLINE: undefined, // We use a custom interpolant (GLTFCubicSplineInterpolation) for CUBICSPLINE tracks. Each\n\t\t // keyframe track will be initialized with a default interpolation type, then modified.\n\tLINEAR: InterpolateLinear,\n\tSTEP: InterpolateDiscrete\n};\n\nconst ALPHA_MODES = {\n\tOPAQUE: 'OPAQUE',\n\tMASK: 'MASK',\n\tBLEND: 'BLEND'\n};\n\n/**\n * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#default-material\n *\n * @private\n * @param {Object<string, Material>} cache\n * @return {Material}\n */\nfunction createDefaultMaterial( cache ) {\n\n\tif ( cache[ 'DefaultMaterial' ] === undefined ) {\n\n\t\tcache[ 'DefaultMaterial' ] = new MeshStandardMaterial( {\n\t\t\tcolor: 0xFFFFFF,\n\t\t\temissive: 0x000000,\n\t\t\tmetalness: 1,\n\t\t\troughness: 1,\n\t\t\ttransparent: false,\n\t\t\tdepthTest: true,\n\t\t\tside: FrontSide\n\t\t} );\n\n\t}\n\n\treturn cache[ 'DefaultMaterial' ];\n\n}\n\nfunction addUnknownExtensionsToUserData( knownExtensions, object, objectDef ) {\n\n\t// Add unknown glTF extensions to an object's userData.\n\n\tfor ( const name in objectDef.extensions ) {\n\n\t\tif ( knownExtensions[ name ] === undefined ) {\n\n\t\t\tobject.userData.gltfExtensions = object.userData.gltfExtensions || {};\n\t\t\tobject.userData.gltfExtensions[ name ] = objectDef.extensions[ name ];\n\n\t\t}\n\n\t}\n\n}\n\n/**\n *\n * @private\n * @param {Object3D|Material|BufferGeometry|Object|AnimationClip} object\n * @param {GLTF.definition} gltfDef\n */\nfunction assignExtrasToUserData( object, gltfDef ) {\n\n\tif ( gltfDef.extras !== undefined ) {\n\n\t\tif ( typeof gltfDef.extras === 'object' ) {\n\n\t\t\tObject.assign( object.userData, gltfDef.extras );\n\n\t\t} else {\n\n\t\t\tconsole.warn( 'THREE.GLTFLoader: Ignoring primitive type .extras, ' + gltfDef.extras );\n\n\t\t}\n\n\t}\n\n}\n\n/**\n * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#morph-targets\n *\n * @private\n * @param {BufferGeometry} geometry\n * @param {Array<GLTF.Target>} targets\n * @param {GLTFParser} parser\n * @return {Promise<BufferGeometry>}\n */\nfunction addMorphTargets( geometry, targets, parser ) {\n\n\tlet hasMorphPosition = false;\n\tlet hasMorphNormal = false;\n\tlet hasMorphColor = false;\n\n\tfor ( let i = 0, il = targets.length; i < il; i ++ ) {\n\n\t\tconst target = targets[ i ];\n\n\t\tif ( target.POSITION !== undefined ) hasMorphPosition = true;\n\t\tif ( target.NORMAL !== undefined ) hasMorphNormal = true;\n\t\tif ( target.COLOR_0 !== undefined ) hasMorphColor = true;\n\n\t\tif ( hasMorphPosition && hasMorphNormal && hasMorphColor ) break;\n\n\t}\n\n\tif ( ! hasMorphPosition && ! hasMorphNormal && ! hasMorphColor ) return Promise.resolve( geometry );\n\n\tconst pendingPositionAccessors = [];\n\tconst pendingNormalAccessors = [];\n\tconst pendingColorAccessors = [];\n\n\tfor ( let i = 0, il = targets.length; i < il; i ++ ) {\n\n\t\tconst target = targets[ i ];\n\n\t\tif ( hasMorphPosition ) {\n\n\t\t\tconst pendingAccessor = target.POSITION !== undefined\n\t\t\t\t? parser.getDependency( 'accessor', target.POSITION )\n\t\t\t\t: geometry.attributes.position;\n\n\t\t\tpendingPositionAccessors.push( pendingAccessor );\n\n\t\t}\n\n\t\tif ( hasMorphNormal ) {\n\n\t\t\tconst pendingAccessor = target.NORMAL !== undefined\n\t\t\t\t? parser.getDependency( 'accessor', target.NORMAL )\n\t\t\t\t: geometry.attributes.normal;\n\n\t\t\tpendingNormalAccessors.push( pendingAccessor );\n\n\t\t}\n\n\t\tif ( hasMorphColor ) {\n\n\t\t\tconst pendingAccessor = target.COLOR_0 !== undefined\n\t\t\t\t? parser.getDependency( 'accessor', target.COLOR_0 )\n\t\t\t\t: geometry.attributes.color;\n\n\t\t\tpendingColorAccessors.push( pendingAccessor );\n\n\t\t}\n\n\t}\n\n\treturn Promise.all( [\n\t\tPromise.all( pendingPositionAccessors ),\n\t\tPromise.all( pendingNormalAccessors ),\n\t\tPromise.all( pendingColorAccessors )\n\t] ).then( function ( accessors ) {\n\n\t\tconst morphPositions = accessors[ 0 ];\n\t\tconst morphNormals = accessors[ 1 ];\n\t\tconst morphColors = accessors[ 2 ];\n\n\t\tif ( hasMorphPosition ) geometry.morphAttributes.position = morphPositions;\n\t\tif ( hasMorphNormal ) geometry.morphAttributes.normal = morphNormals;\n\t\tif ( hasMorphColor ) geometry.morphAttributes.color = morphColors;\n\t\tgeometry.morphTargetsRelative = true;\n\n\t\treturn geometry;\n\n\t} );\n\n}\n\n/**\n *\n * @private\n * @param {Mesh} mesh\n * @param {GLTF.Mesh} meshDef\n */\nfunction updateMorphTargets( mesh, meshDef ) {\n\n\tmesh.updateMorphTargets();\n\n\tif ( meshDef.weights !== undefined ) {\n\n\t\tfor ( let i = 0, il = meshDef.weights.length; i < il; i ++ ) {\n\n\t\t\tmesh.morphTargetInfluences[ i ] = meshDef.weights[ i ];\n\n\t\t}\n\n\t}\n\n\t// .extras has user-defined data, so check that .extras.targetNames is an array.\n\tif ( meshDef.extras && Array.isArray( meshDef.extras.targetNames ) ) {\n\n\t\tconst targetNames = meshDef.extras.targetNames;\n\n\t\tif ( mesh.morphTargetInfluences.length === targetNames.length ) {\n\n\t\t\tmesh.morphTargetDictionary = {};\n\n\t\t\tfor ( let i = 0, il = targetNames.length; i < il; i ++ ) {\n\n\t\t\t\tmesh.morphTargetDictionary[ targetNames[ i ] ] = i;\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tconsole.warn( 'THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.' );\n\n\t\t}\n\n\t}\n\n}\n\nfunction createPrimitiveKey( primitiveDef ) {\n\n\tlet geometryKey;\n\n\tconst dracoExtension = primitiveDef.extensions && primitiveDef.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ];\n\n\tif ( dracoExtension ) {\n\n\t\tgeometryKey = 'draco:' + dracoExtension.bufferView\n\t\t\t\t+ ':' + dracoExtension.indices\n\t\t\t\t+ ':' + createAttributesKey( dracoExtension.attributes );\n\n\t} else {\n\n\t\tgeometryKey = primitiveDef.indices + ':' + createAttributesKey( primitiveDef.attributes ) + ':' + primitiveDef.mode;\n\n\t}\n\n\tif ( primitiveDef.targets !== undefined ) {\n\n\t\tfor ( let i = 0, il = primitiveDef.targets.length; i < il; i ++ ) {\n\n\t\t\tgeometryKey += ':' + createAttributesKey( primitiveDef.targets[ i ] );\n\n\t\t}\n\n\t}\n\n\treturn geometryKey;\n\n}\n\nfunction createAttributesKey( attributes ) {\n\n\tlet attributesKey = '';\n\n\tconst keys = Object.keys( attributes ).sort();\n\n\tfor ( let i = 0, il = keys.length; i < il; i ++ ) {\n\n\t\tattributesKey += keys[ i ] + ':' + attributes[ keys[ i ] ] + ';';\n\n\t}\n\n\treturn attributesKey;\n\n}\n\nfunction getNormalizedComponentScale( constructor ) {\n\n\t// Reference:\n\t// https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization#encoding-quantized-data\n\n\tswitch ( constructor ) {\n\n\t\tcase Int8Array:\n\t\t\treturn 1 / 127;\n\n\t\tcase Uint8Array:\n\t\t\treturn 1 / 255;\n\n\t\tcase Int16Array:\n\t\t\treturn 1 / 32767;\n\n\t\tcase Uint16Array:\n\t\t\treturn 1 / 65535;\n\n\t\tdefault:\n\t\t\tthrow new Error( 'THREE.GLTFLoader: Unsupported normalized accessor component type.' );\n\n\t}\n\n}\n\nfunction getImageURIMimeType( uri ) {\n\n\tif ( uri.search( /\\.jpe?g($|\\?)/i ) > 0 || uri.search( /^data\\:image\\/jpeg/ ) === 0 ) return 'image/jpeg';\n\tif ( uri.search( /\\.webp($|\\?)/i ) > 0 || uri.search( /^data\\:image\\/webp/ ) === 0 ) return 'image/webp';\n\tif ( uri.search( /\\.ktx2($|\\?)/i ) > 0 || uri.search( /^data\\:image\\/ktx2/ ) === 0 ) return 'image/ktx2';\n\n\treturn 'image/png';\n\n}\n\nconst _identityMatrix = new Matrix4();\n\n/* GLTF PARSER */\n\nclass GLTFParser {\n\n\tconstructor( json = {}, options = {} ) {\n\n\t\tthis.json = json;\n\t\tthis.extensions = {};\n\t\tthis.plugins = {};\n\t\tthis.options = options;\n\n\t\t// loader object cache\n\t\tthis.cache = new GLTFRegistry();\n\n\t\t// associations between Three.js objects and glTF elements\n\t\tthis.associations = new Map();\n\n\t\t// BufferGeometry caching\n\t\tthis.primitiveCache = {};\n\n\t\t// Node cache\n\t\tthis.nodeCache = {};\n\n\t\t// Object3D instance caches\n\t\tthis.meshCache = { refs: {}, uses: {} };\n\t\tthis.cameraCache = { refs: {}, uses: {} };\n\t\tthis.lightCache = { refs: {}, uses: {} };\n\n\t\tthis.sourceCache = {};\n\t\tthis.textureCache = {};\n\n\t\t// Track node names, to ensure no duplicates\n\t\tthis.nodeNamesUsed = {};\n\n\t\t// Use an ImageBitmapLoader if imageBitmaps are supported. Moves much of the\n\t\t// expensive work of uploading a texture to the GPU off the main thread.\n\n\t\tlet isSafari = false;\n\t\tlet safariVersion = - 1;\n\t\tlet isFirefox = false;\n\t\tlet firefoxVersion = - 1;\n\n\t\tif ( typeof navigator !== 'undefined' && typeof navigator.userAgent !== 'undefined' ) {\n\n\t\t\tconst userAgent = navigator.userAgent;\n\n\t\t\tisSafari = /^((?!chrome|android).)*safari/i.test( userAgent ) === true;\n\t\t\tconst safariMatch = userAgent.match( /Version\\/(\\d+)/ );\n\t\t\tsafariVersion = isSafari && safariMatch ? parseInt( safariMatch[ 1 ], 10 ) : - 1;\n\n\t\t\tisFirefox = userAgent.indexOf( 'Firefox' ) > - 1;\n\t\t\tfirefoxVersion = isFirefox ? userAgent.match( /Firefox\\/([0-9]+)\\./ )[ 1 ] : - 1;\n\n\t\t}\n\n\t\tif ( typeof createImageBitmap === 'undefined' || ( isSafari && safariVersion < 17 ) || ( isFirefox && firefoxVersion < 98 ) ) {\n\n\t\t\tthis.textureLoader = new TextureLoader( this.options.manager );\n\n\t\t} else {\n\n\t\t\tthis.textureLoader = new ImageBitmapLoader( this.options.manager );\n\n\t\t}\n\n\t\tthis.textureLoader.setCrossOrigin( this.options.crossOrigin );\n\t\tthis.textureLoader.setRequestHeader( this.options.requestHeader );\n\n\t\tthis.fileLoader = new FileLoader( this.options.manager );\n\t\tthis.fileLoader.setResponseType( 'arraybuffer' );\n\n\t\tif ( this.options.crossOrigin === 'use-credentials' ) {\n\n\t\t\tthis.fileLoader.setWithCredentials( true );\n\n\t\t}\n\n\t}\n\n\tsetExtensions( extensions ) {\n\n\t\tthis.extensions = extensions;\n\n\t}\n\n\tsetPlugins( plugins ) {\n\n\t\tthis.plugins = plugins;\n\n\t}\n\n\tparse( onLoad, onError ) {\n\n\t\tconst parser = this;\n\t\tconst json = this.json;\n\t\tconst extensions = this.extensions;\n\n\t\t// Clear the loader cache\n\t\tthis.cache.removeAll();\n\t\tthis.nodeCache = {};\n\n\t\t// Mark the special nodes/meshes in json for efficient parse\n\t\tthis._invokeAll( function ( ext ) {\n\n\t\t\treturn ext._markDefs && ext._markDefs();\n\n\t\t} );\n\n\t\tPromise.all( this._invokeAll( function ( ext ) {\n\n\t\t\treturn ext.beforeRoot && ext.beforeRoot();\n\n\t\t} ) ).then( function () {\n\n\t\t\treturn Promise.all( [\n\n\t\t\t\tparser.getDependencies( 'scene' ),\n\t\t\t\tparser.getDependencies( 'animation' ),\n\t\t\t\tparser.getDependencies( 'camera' ),\n\n\t\t\t] );\n\n\t\t} ).then( function ( dependencies ) {\n\n\t\t\tconst result = {\n\t\t\t\tscene: dependencies[ 0 ][ json.scene || 0 ],\n\t\t\t\tscenes: dependencies[ 0 ],\n\t\t\t\tanimations: dependencies[ 1 ],\n\t\t\t\tcameras: dependencies[ 2 ],\n\t\t\t\tasset: json.asset,\n\t\t\t\tparser: parser,\n\t\t\t\tuserData: {}\n\t\t\t};\n\n\t\t\taddUnknownExtensionsToUserData( extensions, result, json );\n\n\t\t\tassignExtrasToUserData( result, json );\n\n\t\t\treturn Promise.all( parser._invokeAll( function ( ext ) {\n\n\t\t\t\treturn ext.afterRoot && ext.afterRoot( result );\n\n\t\t\t} ) ).then( function () {\n\n\t\t\t\tfor ( const scene of result.scenes ) {\n\n\t\t\t\t\tscene.updateMatrixWorld();\n\n\t\t\t\t}\n\n\t\t\t\tonLoad( result );\n\n\t\t\t} );\n\n\t\t} ).catch( onError );\n\n\t}\n\n\t/**\n\t * Marks the special nodes/meshes in json for efficient parse.\n\t *\n\t * @private\n\t */\n\t_markDefs() {\n\n\t\tconst nodeDefs = this.json.nodes || [];\n\t\tconst skinDefs = this.json.skins || [];\n\t\tconst meshDefs = this.json.meshes || [];\n\n\t\t// Nothing in the node definition indicates whether it is a Bone or an\n\t\t// Object3D. Use the skins' joint references to mark bones.\n\t\tfor ( let skinIndex = 0, skinLength = skinDefs.length; skinIndex < skinLength; skinIndex ++ ) {\n\n\t\t\tconst joints = skinDefs[ skinIndex ].joints;\n\n\t\t\tfor ( let i = 0, il = joints.length; i < il; i ++ ) {\n\n\t\t\t\tnodeDefs[ joints[ i ] ].isBone = true;\n\n\t\t\t}\n\n\t\t}\n\n\t\t// Iterate over all nodes, marking references to shared resources,\n\t\t// as well as skeleton joints.\n\t\tfor ( let nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex ++ ) {\n\n\t\t\tconst nodeDef = nodeDefs[ nodeIndex ];\n\n\t\t\tif ( nodeDef.mesh !== undefined ) {\n\n\t\t\t\tthis._addNodeRef( this.meshCache, nodeDef.mesh );\n\n\t\t\t\t// Nothing in the mesh definition indicates whether it is\n\t\t\t\t// a SkinnedMesh or Mesh. Use the node's mesh reference\n\t\t\t\t// to mark SkinnedMesh if node has skin.\n\t\t\t\tif ( nodeDef.skin !== undefined ) {\n\n\t\t\t\t\tmeshDefs[ nodeDef.mesh ].isSkinnedMesh = true;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( nodeDef.camera !== undefined ) {\n\n\t\t\t\tthis._addNodeRef( this.cameraCache, nodeDef.camera );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Counts references to shared node / Object3D resources. These resources\n\t * can be reused, or \"instantiated\", at multiple nodes in the scene\n\t * hierarchy. Mesh, Camera, and Light instances are instantiated and must\n\t * be marked. Non-scenegraph resources (like Materials, Geometries, and\n\t * Textures) can be reused directly and are not marked here.\n\t *\n\t * Example: CesiumMilkTruck sample model reuses \"Wheel\" meshes.\n\t *\n\t * @private\n\t * @param {Object} cache\n\t * @param {Object3D} index\n\t */\n\t_addNodeRef( cache, index ) {\n\n\t\tif ( index === undefined ) return;\n\n\t\tif ( cache.refs[ index ] === undefined ) {\n\n\t\t\tcache.refs[ index ] = cache.uses[ index ] = 0;\n\n\t\t}\n\n\t\tcache.refs[ index ] ++;\n\n\t}\n\n\t/**\n\t * Returns a reference to a shared resource, cloning it if necessary.\n\t *\n\t * @private\n\t * @param {Object} cache\n\t * @param {number} index\n\t * @param {Object} object\n\t * @return {Object}\n\t */\n\t_getNodeRef( cache, index, object ) {\n\n\t\tif ( cache.refs[ index ] <= 1 ) return object;\n\n\t\tconst ref = object.clone();\n\n\t\t// Propagates mappings to the cloned object, prevents mappings on the\n\t\t// original object from being lost.\n\t\tconst updateMappings = ( original, clone ) => {\n\n\t\t\tconst mappings = this.associations.get( original );\n\t\t\tif ( mappings != null ) {\n\n\t\t\t\tthis.associations.set( clone, mappings );\n\n\t\t\t}\n\n\t\t\tfor ( const [ i, child ] of original.children.entries() ) {\n\n\t\t\t\tupdateMappings( child, clone.children[ i ] );\n\n\t\t\t}\n\n\t\t};\n\n\t\tupdateMappings( object, ref );\n\n\t\tref.name += '_instance_' + ( cache.uses[ index ] ++ );\n\n\t\treturn ref;\n\n\t}\n\n\t_invokeOne( func ) {\n\n\t\tconst extensions = Object.values( this.plugins );\n\t\textensions.push( this );\n\n\t\tfor ( let i = 0; i < extensions.length; i ++ ) {\n\n\t\t\tconst result = func( extensions[ i ] );\n\n\t\t\tif ( result ) return result;\n\n\t\t}\n\n\t\treturn null;\n\n\t}\n\n\t_invokeAll( func ) {\n\n\t\tconst extensions = Object.values( this.plugins );\n\t\textensions.unshift( this );\n\n\t\tconst pending = [];\n\n\t\tfor ( let i = 0; i < extensions.length; i ++ ) {\n\n\t\t\tconst result = func( extensions[ i ] );\n\n\t\t\tif ( result ) pending.push( result );\n\n\t\t}\n\n\t\treturn pending;\n\n\t}\n\n\t/**\n\t * Requests the specified dependency asynchronously, with caching.\n\t *\n\t * @private\n\t * @param {string} type\n\t * @param {number} index\n\t * @return {Promise<Object3D|Material|Texture|AnimationClip|ArrayBuffer|Object>}\n\t */\n\tgetDependency( type, index ) {\n\n\t\tconst cacheKey = type + ':' + index;\n\t\tlet dependency = this.cache.get( cacheKey );\n\n\t\tif ( ! dependency ) {\n\n\t\t\tswitch ( type ) {\n\n\t\t\t\tcase 'scene':\n\t\t\t\t\tdependency = this.loadScene( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'node':\n\t\t\t\t\tdependency = this._invokeOne( function ( ext ) {\n\n\t\t\t\t\t\treturn ext.loadNode && ext.loadNode( index );\n\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'mesh':\n\t\t\t\t\tdependency = this._invokeOne( function ( ext ) {\n\n\t\t\t\t\t\treturn ext.loadMesh && ext.loadMesh( index );\n\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'accessor':\n\t\t\t\t\tdependency = this.loadAccessor( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'bufferView':\n\t\t\t\t\tdependency = this._invokeOne( function ( ext ) {\n\n\t\t\t\t\t\treturn ext.loadBufferView && ext.loadBufferView( index );\n\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'buffer':\n\t\t\t\t\tdependency = this.loadBuffer( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'material':\n\t\t\t\t\tdependency = this._invokeOne( function ( ext ) {\n\n\t\t\t\t\t\treturn ext.loadMaterial && ext.loadMaterial( index );\n\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'texture':\n\t\t\t\t\tdependency = this._invokeOne( function ( ext ) {\n\n\t\t\t\t\t\treturn ext.loadTexture && ext.loadTexture( index );\n\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'skin':\n\t\t\t\t\tdependency = this.loadSkin( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'animation':\n\t\t\t\t\tdependency = this._invokeOne( function ( ext ) {\n\n\t\t\t\t\t\treturn ext.loadAnimation && ext.loadAnimation( index );\n\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'camera':\n\t\t\t\t\tdependency = this.loadCamera( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tdependency = this._invokeOne( function ( ext ) {\n\n\t\t\t\t\t\treturn ext != this && ext.getDependency && ext.getDependency( type, index );\n\n\t\t\t\t\t} );\n\n\t\t\t\t\tif ( ! dependency ) {\n\n\t\t\t\t\t\tthrow new Error( 'Unknown type: ' + type );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t\tthis.cache.add( cacheKey, dependency );\n\n\t\t}\n\n\t\treturn dependency;\n\n\t}\n\n\t/**\n\t * Requests all dependencies of the specified type asynchronously, with caching.\n\t *\n\t * @private\n\t * @param {string} type\n\t * @return {Promise<Array<Object>>}\n\t */\n\tgetDependencies( type ) {\n\n\t\tlet dependencies = this.cache.get( type );\n\n\t\tif ( ! dependencies ) {\n\n\t\t\tconst parser = this;\n\t\t\tconst defs = this.json[ type + ( type === 'mesh' ? 'es' : 's' ) ] || [];\n\n\t\t\tdependencies = Promise.all( defs.map( function ( def, index ) {\n\n\t\t\t\treturn parser.getDependency( type, index );\n\n\t\t\t} ) );\n\n\t\t\tthis.cache.add( type, dependencies );\n\n\t\t}\n\n\t\treturn dependencies;\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views\n\t *\n\t * @private\n\t * @param {number} bufferIndex\n\t * @return {Promise<ArrayBuffer>}\n\t */\n\tloadBuffer( bufferIndex ) {\n\n\t\tconst bufferDef = this.json.buffers[ bufferIndex ];\n\t\tconst loader = this.fileLoader;\n\n\t\tif ( bufferDef.type && bufferDef.type !== 'arraybuffer' ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: ' + bufferDef.type + ' buffer type is not supported.' );\n\n\t\t}\n\n\t\t// If present, GLB container is required to be the first buffer.\n\t\tif ( bufferDef.uri === undefined && bufferIndex === 0 ) {\n\n\t\t\treturn Promise.resolve( this.extensions[ EXTENSIONS.KHR_BINARY_GLTF ].body );\n\n\t\t}\n\n\t\tconst options = this.options;\n\n\t\treturn new Promise( function ( resolve, reject ) {\n\n\t\t\tloader.load( LoaderUtils.resolveURL( bufferDef.uri, options.path ), resolve, undefined, function () {\n\n\t\t\t\treject( new Error( 'THREE.GLTFLoader: Failed to load buffer \"' + bufferDef.uri + '\".' ) );\n\n\t\t\t} );\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views\n\t *\n\t * @private\n\t * @param {number} bufferViewIndex\n\t * @return {Promise<ArrayBuffer>}\n\t */\n\tloadBufferView( bufferViewIndex ) {\n\n\t\tconst bufferViewDef = this.json.bufferViews[ bufferViewIndex ];\n\n\t\treturn this.getDependency( 'buffer', bufferViewDef.buffer ).then( function ( buffer ) {\n\n\t\t\tconst byteLength = bufferViewDef.byteLength || 0;\n\t\t\tconst byteOffset = bufferViewDef.byteOffset || 0;\n\t\t\treturn buffer.slice( byteOffset, byteOffset + byteLength );\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#accessors\n\t *\n\t * @private\n\t * @param {number} accessorIndex\n\t * @return {Promise<BufferAttribute|InterleavedBufferAttribute>}\n\t */\n\tloadAccessor( accessorIndex ) {\n\n\t\tconst parser = this;\n\t\tconst json = this.json;\n\n\t\tconst accessorDef = this.json.accessors[ accessorIndex ];\n\n\t\tif ( accessorDef.bufferView === undefined && accessorDef.sparse === undefined ) {\n\n\t\t\tconst itemSize = WEBGL_TYPE_SIZES[ accessorDef.type ];\n\t\t\tconst TypedArray = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];\n\t\t\tconst normalized = accessorDef.normalized === true;\n\n\t\t\tconst array = new TypedArray( accessorDef.count * itemSize );\n\t\t\treturn Promise.resolve( new BufferAttribute( array, itemSize, normalized ) );\n\n\t\t}\n\n\t\tconst pendingBufferViews = [];\n\n\t\tif ( accessorDef.bufferView !== undefined ) {\n\n\t\t\tpendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.bufferView ) );\n\n\t\t} else {\n\n\t\t\tpendingBufferViews.push( null );\n\n\t\t}\n\n\t\tif ( accessorDef.sparse !== undefined ) {\n\n\t\t\tpendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.sparse.indices.bufferView ) );\n\t\t\tpendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.sparse.values.bufferView ) );\n\n\t\t}\n\n\t\treturn Promise.all( pendingBufferViews ).then( function ( bufferViews ) {\n\n\t\t\tconst bufferView = bufferViews[ 0 ];\n\n\t\t\tconst itemSize = WEBGL_TYPE_SIZES[ accessorDef.type ];\n\t\t\tconst TypedArray = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];\n\n\t\t\t// For VEC3: itemSize is 3, elementBytes is 4, itemBytes is 12.\n\t\t\tconst elementBytes = TypedArray.BYTES_PER_ELEMENT;\n\t\t\tconst itemBytes = elementBytes * itemSize;\n\t\t\tconst byteOffset = accessorDef.byteOffset || 0;\n\t\t\tconst byteStride = accessorDef.bufferView !== undefined ? json.bufferViews[ accessorDef.bufferView ].byteStride : undefined;\n\t\t\tconst normalized = accessorDef.normalized === true;\n\t\t\tlet array, bufferAttribute;\n\n\t\t\t// The buffer is not interleaved if the stride is the item size in bytes.\n\t\t\tif ( byteStride && byteStride !== itemBytes ) {\n\n\t\t\t\t// Each \"slice\" of the buffer, as defined by 'count' elements of 'byteStride' bytes, gets its own InterleavedBuffer\n\t\t\t\t// This makes sure that IBA.count reflects accessor.count properly\n\t\t\t\tconst ibSlice = Math.floor( byteOffset / byteStride );\n\t\t\t\tconst ibCacheKey = 'InterleavedBuffer:' + accessorDef.bufferView + ':' + accessorDef.componentType + ':' + ibSlice + ':' + accessorDef.count;\n\t\t\t\tlet ib = parser.cache.get( ibCacheKey );\n\n\t\t\t\tif ( ! ib ) {\n\n\t\t\t\t\tarray = new TypedArray( bufferView, ibSlice * byteStride, accessorDef.count * byteStride / elementBytes );\n\n\t\t\t\t\t// Integer parameters to IB/IBA are in array elements, not bytes.\n\t\t\t\t\tib = new InterleavedBuffer( array, byteStride / elementBytes );\n\n\t\t\t\t\tparser.cache.add( ibCacheKey, ib );\n\n\t\t\t\t}\n\n\t\t\t\tbufferAttribute = new InterleavedBufferAttribute( ib, itemSize, ( byteOffset % byteStride ) / elementBytes, normalized );\n\n\t\t\t} else {\n\n\t\t\t\tif ( bufferView === null ) {\n\n\t\t\t\t\tarray = new TypedArray( accessorDef.count * itemSize );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tarray = new TypedArray( bufferView, byteOffset, accessorDef.count * itemSize );\n\n\t\t\t\t}\n\n\t\t\t\tbufferAttribute = new BufferAttribute( array, itemSize, normalized );\n\n\t\t\t}\n\n\t\t\t// https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#sparse-accessors\n\t\t\tif ( accessorDef.sparse !== undefined ) {\n\n\t\t\t\tconst itemSizeIndices = WEBGL_TYPE_SIZES.SCALAR;\n\t\t\t\tconst TypedArrayIndices = WEBGL_COMPONENT_TYPES[ accessorDef.sparse.indices.componentType ];\n\n\t\t\t\tconst byteOffsetIndices = accessorDef.sparse.indices.byteOffset || 0;\n\t\t\t\tconst byteOffsetValues = accessorDef.sparse.values.byteOffset || 0;\n\n\t\t\t\tconst sparseIndices = new TypedArrayIndices( bufferViews[ 1 ], byteOffsetIndices, accessorDef.sparse.count * itemSizeIndices );\n\t\t\t\tconst sparseValues = new TypedArray( bufferViews[ 2 ], byteOffsetValues, accessorDef.sparse.count * itemSize );\n\n\t\t\t\tif ( bufferView !== null ) {\n\n\t\t\t\t\t// Avoid modifying the original ArrayBuffer, if the bufferView wasn't initialized with zeroes.\n\t\t\t\t\tbufferAttribute = new BufferAttribute( bufferAttribute.array.slice(), bufferAttribute.itemSize, bufferAttribute.normalized );\n\n\t\t\t\t}\n\n\t\t\t\t// Ignore normalized since we copy from sparse\n\t\t\t\tbufferAttribute.normalized = false;\n\n\t\t\t\tfor ( let i = 0, il = sparseIndices.length; i < il; i ++ ) {\n\n\t\t\t\t\tconst index = sparseIndices[ i ];\n\n\t\t\t\t\tbufferAttribute.setX( index, sparseValues[ i * itemSize ] );\n\t\t\t\t\tif ( itemSize >= 2 ) bufferAttribute.setY( index, sparseValues[ i * itemSize + 1 ] );\n\t\t\t\t\tif ( itemSize >= 3 ) bufferAttribute.setZ( index, sparseValues[ i * itemSize + 2 ] );\n\t\t\t\t\tif ( itemSize >= 4 ) bufferAttribute.setW( index, sparseValues[ i * itemSize + 3 ] );\n\t\t\t\t\tif ( itemSize >= 5 ) throw new Error( 'THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.' );\n\n\t\t\t\t}\n\n\t\t\t\tbufferAttribute.normalized = normalized;\n\n\t\t\t}\n\n\t\t\treturn bufferAttribute;\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#textures\n\t *\n\t * @private\n\t * @param {number} textureIndex\n\t * @return {Promise<?Texture>}\n\t */\n\tloadTexture( textureIndex ) {\n\n\t\tconst json = this.json;\n\t\tconst options = this.options;\n\t\tconst textureDef = json.textures[ textureIndex ];\n\t\tconst sourceIndex = textureDef.source;\n\t\tconst sourceDef = json.images[ sourceIndex ];\n\n\t\tlet loader = this.textureLoader;\n\n\t\tif ( sourceDef.uri ) {\n\n\t\t\tconst handler = options.manager.getHandler( sourceDef.uri );\n\t\t\tif ( handler !== null ) loader = handler;\n\n\t\t}\n\n\t\treturn this.loadTextureImage( textureIndex, sourceIndex, loader );\n\n\t}\n\n\tloadTextureImage( textureIndex, sourceIndex, loader ) {\n\n\t\tconst parser = this;\n\t\tconst json = this.json;\n\n\t\tconst textureDef = json.textures[ textureIndex ];\n\t\tconst sourceDef = json.images[ sourceIndex ];\n\n\t\tconst cacheKey = ( sourceDef.uri || sourceDef.bufferView ) + ':' + textureDef.sampler;\n\n\t\tif ( this.textureCache[ cacheKey ] ) {\n\n\t\t\t// See https://github.com/mrdoob/three.js/issues/21559.\n\t\t\treturn this.textureCache[ cacheKey ];\n\n\t\t}\n\n\t\tconst promise = this.loadImageSource( sourceIndex, loader ).then( function ( texture ) {\n\n\t\t\ttexture.flipY = false;\n\n\t\t\ttexture.name = textureDef.name || sourceDef.name || '';\n\n\t\t\tif ( texture.name === '' && typeof sourceDef.uri === 'string' && sourceDef.uri.startsWith( 'data:image/' ) === false ) {\n\n\t\t\t\ttexture.name = sourceDef.uri;\n\n\t\t\t}\n\n\t\t\tconst samplers = json.samplers || {};\n\t\t\tconst sampler = samplers[ textureDef.sampler ] || {};\n\n\t\t\ttexture.magFilter = WEBGL_FILTERS[ sampler.magFilter ] || LinearFilter;\n\t\t\ttexture.minFilter = WEBGL_FILTERS[ sampler.minFilter ] || LinearMipmapLinearFilter;\n\t\t\ttexture.wrapS = WEBGL_WRAPPINGS[ sampler.wrapS ] || RepeatWrapping;\n\t\t\ttexture.wrapT = WEBGL_WRAPPINGS[ sampler.wrapT ] || RepeatWrapping;\n\t\t\ttexture.generateMipmaps = ! texture.isCompressedTexture && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;\n\n\t\t\tparser.associations.set( texture, { textures: textureIndex } );\n\n\t\t\treturn texture;\n\n\t\t} ).catch( function () {\n\n\t\t\treturn null;\n\n\t\t} );\n\n\t\tthis.textureCache[ cacheKey ] = promise;\n\n\t\treturn promise;\n\n\t}\n\n\tloadImageSource( sourceIndex, loader ) {\n\n\t\tconst parser = this;\n\t\tconst json = this.json;\n\t\tconst options = this.options;\n\n\t\tif ( this.sourceCache[ sourceIndex ] !== undefined ) {\n\n\t\t\treturn this.sourceCache[ sourceIndex ].then( ( texture ) => texture.clone() );\n\n\t\t}\n\n\t\tconst sourceDef = json.images[ sourceIndex ];\n\n\t\tconst URL = self.URL || self.webkitURL;\n\n\t\tlet sourceURI = sourceDef.uri || '';\n\t\tlet isObjectURL = false;\n\n\t\tif ( sourceDef.bufferView !== undefined ) {\n\n\t\t\t// Load binary image data from bufferView, if provided.\n\n\t\t\tsourceURI = parser.getDependency( 'bufferView', sourceDef.bufferView ).then( function ( bufferView ) {\n\n\t\t\t\tisObjectURL = true;\n\t\t\t\tconst blob = new Blob( [ bufferView ], { type: sourceDef.mimeType } );\n\t\t\t\tsourceURI = URL.createObjectURL( blob );\n\t\t\t\treturn sourceURI;\n\n\t\t\t} );\n\n\t\t} else if ( sourceDef.uri === undefined ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: Image ' + sourceIndex + ' is missing URI and bufferView' );\n\n\t\t}\n\n\t\tconst promise = Promise.resolve( sourceURI ).then( function ( sourceURI ) {\n\n\t\t\treturn new Promise( function ( resolve, reject ) {\n\n\t\t\t\tlet onLoad = resolve;\n\n\t\t\t\tif ( loader.isImageBitmapLoader === true ) {\n\n\t\t\t\t\tonLoad = function ( imageBitmap ) {\n\n\t\t\t\t\t\tconst texture = new Texture( imageBitmap );\n\t\t\t\t\t\ttexture.needsUpdate = true;\n\n\t\t\t\t\t\tresolve( texture );\n\n\t\t\t\t\t};\n\n\t\t\t\t}\n\n\t\t\t\tloader.load( LoaderUtils.resolveURL( sourceURI, options.path ), onLoad, undefined, reject );\n\n\t\t\t} );\n\n\t\t} ).then( function ( texture ) {\n\n\t\t\t// Clean up resources and configure Texture.\n\n\t\t\tif ( isObjectURL === true ) {\n\n\t\t\t\tURL.revokeObjectURL( sourceURI );\n\n\t\t\t}\n\n\t\t\tassignExtrasToUserData( texture, sourceDef );\n\n\t\t\ttexture.userData.mimeType = sourceDef.mimeType || getImageURIMimeType( sourceDef.uri );\n\n\t\t\treturn texture;\n\n\t\t} ).catch( function ( error ) {\n\n\t\t\tconsole.error( 'THREE.GLTFLoader: Couldn\\'t load texture', sourceURI );\n\t\t\tthrow error;\n\n\t\t} );\n\n\t\tthis.sourceCache[ sourceIndex ] = promise;\n\t\treturn promise;\n\n\t}\n\n\t/**\n\t * Asynchronously assigns a texture to the given material parameters.\n\t *\n\t * @private\n\t * @param {Object} materialParams\n\t * @param {string} mapName\n\t * @param {Object} mapDef\n\t * @param {string} [colorSpace]\n\t * @return {Promise<Texture>}\n\t */\n\tassignTexture( materialParams, mapName, mapDef, colorSpace ) {\n\n\t\tconst parser = this;\n\n\t\treturn this.getDependency( 'texture', mapDef.index ).then( function ( texture ) {\n\n\t\t\tif ( ! texture ) return null;\n\n\t\t\tif ( mapDef.texCoord !== undefined && mapDef.texCoord > 0 ) {\n\n\t\t\t\ttexture = texture.clone();\n\t\t\t\ttexture.channel = mapDef.texCoord;\n\n\t\t\t}\n\n\t\t\tif ( parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] ) {\n\n\t\t\t\tconst transform = mapDef.extensions !== undefined ? mapDef.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] : undefined;\n\n\t\t\t\tif ( transform ) {\n\n\t\t\t\t\tconst gltfReference = parser.associations.get( texture );\n\t\t\t\t\ttexture = parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ].extendTexture( texture, transform );\n\t\t\t\t\tparser.associations.set( texture, gltfReference );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( colorSpace !== undefined ) {\n\n\t\t\t\ttexture.colorSpace = colorSpace;\n\n\t\t\t}\n\n\t\t\tmaterialParams[ mapName ] = texture;\n\n\t\t\treturn texture;\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Assigns final material to a Mesh, Line, or Points instance. The instance\n\t * already has a material (generated from the glTF material options alone)\n\t * but reuse of the same glTF material may require multiple threejs materials\n\t * to accommodate different primitive types, defines, etc. New materials will\n\t * be created if necessary, and reused from a cache.\n\t *\n\t * @private\n\t * @param {Object3D} mesh Mesh, Line, or Points instance.\n\t */\n\tassignFinalMaterial( mesh ) {\n\n\t\tconst geometry = mesh.geometry;\n\t\tlet material = mesh.material;\n\n\t\tconst useDerivativeTangents = geometry.attributes.tangent === undefined;\n\t\tconst useVertexColors = geometry.attributes.color !== undefined;\n\t\tconst useFlatShading = geometry.attributes.normal === undefined;\n\n\t\tif ( mesh.isPoints ) {\n\n\t\t\tconst cacheKey = 'PointsMaterial:' + material.uuid;\n\n\t\t\tlet pointsMaterial = this.cache.get( cacheKey );\n\n\t\t\tif ( ! pointsMaterial ) {\n\n\t\t\t\tpointsMaterial = new PointsMaterial();\n\t\t\t\tMaterial.prototype.copy.call( pointsMaterial, material );\n\t\t\t\tpointsMaterial.color.copy( material.color );\n\t\t\t\tpointsMaterial.map = material.map;\n\t\t\t\tpointsMaterial.sizeAttenuation = false; // glTF spec says points should be 1px\n\n\t\t\t\tthis.cache.add( cacheKey, pointsMaterial );\n\n\t\t\t}\n\n\t\t\tmaterial = pointsMaterial;\n\n\t\t} else if ( mesh.isLine ) {\n\n\t\t\tconst cacheKey = 'LineBasicMaterial:' + material.uuid;\n\n\t\t\tlet lineMaterial = this.cache.get( cacheKey );\n\n\t\t\tif ( ! lineMaterial ) {\n\n\t\t\t\tlineMaterial = new LineBasicMaterial();\n\t\t\t\tMaterial.prototype.copy.call( lineMaterial, material );\n\t\t\t\tlineMaterial.color.copy( material.color );\n\t\t\t\tlineMaterial.map = material.map;\n\n\t\t\t\tthis.cache.add( cacheKey, lineMaterial );\n\n\t\t\t}\n\n\t\t\tmaterial = lineMaterial;\n\n\t\t}\n\n\t\t// Clone the material if it will be modified\n\t\tif ( useDerivativeTangents || useVertexColors || useFlatShading ) {\n\n\t\t\tlet cacheKey = 'ClonedMaterial:' + material.uuid + ':';\n\n\t\t\tif ( useDerivativeTangents ) cacheKey += 'derivative-tangents:';\n\t\t\tif ( useVertexColors ) cacheKey += 'vertex-colors:';\n\t\t\tif ( useFlatShading ) cacheKey += 'flat-shading:';\n\n\t\t\tlet cachedMaterial = this.cache.get( cacheKey );\n\n\t\t\tif ( ! cachedMaterial ) {\n\n\t\t\t\tcachedMaterial = material.clone();\n\n\t\t\t\tif ( useVertexColors ) cachedMaterial.vertexColors = true;\n\t\t\t\tif ( useFlatShading ) cachedMaterial.flatShading = true;\n\n\t\t\t\tif ( useDerivativeTangents ) {\n\n\t\t\t\t\t// https://github.com/mrdoob/three.js/issues/11438#issuecomment-507003995\n\t\t\t\t\tif ( cachedMaterial.normalScale ) cachedMaterial.normalScale.y *= - 1;\n\t\t\t\t\tif ( cachedMaterial.clearcoatNormalScale ) cachedMaterial.clearcoatNormalScale.y *= - 1;\n\n\t\t\t\t}\n\n\t\t\t\tthis.cache.add( cacheKey, cachedMaterial );\n\n\t\t\t\tthis.associations.set( cachedMaterial, this.associations.get( material ) );\n\n\t\t\t}\n\n\t\t\tmaterial = cachedMaterial;\n\n\t\t}\n\n\t\tmesh.material = material;\n\n\t}\n\n\tgetMaterialType( /* materialIndex */ ) {\n\n\t\treturn MeshStandardMaterial;\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#materials\n\t *\n\t * @private\n\t * @param {number} materialIndex\n\t * @return {Promise<Material>}\n\t */\n\tloadMaterial( materialIndex ) {\n\n\t\tconst parser = this;\n\t\tconst json = this.json;\n\t\tconst extensions = this.extensions;\n\t\tconst materialDef = json.materials[ materialIndex ];\n\n\t\tlet materialType;\n\t\tconst materialParams = {};\n\t\tconst materialExtensions = materialDef.extensions || {};\n\n\t\tconst pending = [];\n\n\t\tif ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ] ) {\n\n\t\t\tconst kmuExtension = extensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ];\n\t\t\tmaterialType = kmuExtension.getMaterialType();\n\t\t\tpending.push( kmuExtension.extendParams( materialParams, materialDef, parser ) );\n\n\t\t} else {\n\n\t\t\t// Specification:\n\t\t\t// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#metallic-roughness-material\n\n\t\t\tconst metallicRoughness = materialDef.pbrMetallicRoughness || {};\n\n\t\t\tmaterialParams.color = new Color( 1.0, 1.0, 1.0 );\n\t\t\tmaterialParams.opacity = 1.0;\n\n\t\t\tif ( Array.isArray( metallicRoughness.baseColorFactor ) ) {\n\n\t\t\t\tconst array = metallicRoughness.baseColorFactor;\n\n\t\t\t\tmaterialParams.color.setRGB( array[ 0 ], array[ 1 ], array[ 2 ], LinearSRGBColorSpace );\n\t\t\t\tmaterialParams.opacity = array[ 3 ];\n\n\t\t\t}\n\n\t\t\tif ( metallicRoughness.baseColorTexture !== undefined ) {\n\n\t\t\t\tpending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture, SRGBColorSpace ) );\n\n\t\t\t}\n\n\t\t\tmaterialParams.metalness = metallicRoughness.metallicFactor !== undefined ? metallicRoughness.metallicFactor : 1.0;\n\t\t\tmaterialParams.roughness = metallicRoughness.roughnessFactor !== undefined ? metallicRoughness.roughnessFactor : 1.0;\n\n\t\t\tif ( metallicRoughness.metallicRoughnessTexture !== undefined ) {\n\n\t\t\t\tpending.push( parser.assignTexture( materialParams, 'metalnessMap', metallicRoughness.metallicRoughnessTexture ) );\n\t\t\t\tpending.push( parser.assignTexture( materialParams, 'roughnessMap', metallicRoughness.metallicRoughnessTexture ) );\n\n\t\t\t}\n\n\t\t\tmaterialType = this._invokeOne( function ( ext ) {\n\n\t\t\t\treturn ext.getMaterialType && ext.getMaterialType( materialIndex );\n\n\t\t\t} );\n\n\t\t\tpending.push( Promise.all( this._invokeAll( function ( ext ) {\n\n\t\t\t\treturn ext.extendMaterialParams && ext.extendMaterialParams( materialIndex, materialParams );\n\n\t\t\t} ) ) );\n\n\t\t}\n\n\t\tif ( materialDef.doubleSided === true ) {\n\n\t\t\tmaterialParams.side = DoubleSide;\n\n\t\t}\n\n\t\tconst alphaMode = materialDef.alphaMode || ALPHA_MODES.OPAQUE;\n\n\t\tif ( alphaMode === ALPHA_MODES.BLEND ) {\n\n\t\t\tmaterialParams.transparent = true;\n\n\t\t\t// See: https://github.com/mrdoob/three.js/issues/17706\n\t\t\tmaterialParams.depthWrite = false;\n\n\t\t} else {\n\n\t\t\tmaterialParams.transparent = false;\n\n\t\t\tif ( alphaMode === ALPHA_MODES.MASK ) {\n\n\t\t\t\tmaterialParams.alphaTest = materialDef.alphaCutoff !== undefined ? materialDef.alphaCutoff : 0.5;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( materialDef.normalTexture !== undefined && materialType !== MeshBasicMaterial ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'normalMap', materialDef.normalTexture ) );\n\n\t\t\tmaterialParams.normalScale = new Vector2( 1, 1 );\n\n\t\t\tif ( materialDef.normalTexture.scale !== undefined ) {\n\n\t\t\t\tconst scale = materialDef.normalTexture.scale;\n\n\t\t\t\tmaterialParams.normalScale.set( scale, scale );\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( materialDef.occlusionTexture !== undefined && materialType !== MeshBasicMaterial ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'aoMap', materialDef.occlusionTexture ) );\n\n\t\t\tif ( materialDef.occlusionTexture.strength !== undefined ) {\n\n\t\t\t\tmaterialParams.aoMapIntensity = materialDef.occlusionTexture.strength;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( materialDef.emissiveFactor !== undefined && materialType !== MeshBasicMaterial ) {\n\n\t\t\tconst emissiveFactor = materialDef.emissiveFactor;\n\t\t\tmaterialParams.emissive = new Color().setRGB( emissiveFactor[ 0 ], emissiveFactor[ 1 ], emissiveFactor[ 2 ], LinearSRGBColorSpace );\n\n\t\t}\n\n\t\tif ( materialDef.emissiveTexture !== undefined && materialType !== MeshBasicMaterial ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'emissiveMap', materialDef.emissiveTexture, SRGBColorSpace ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending ).then( function () {\n\n\t\t\tconst material = new materialType( materialParams );\n\n\t\t\tif ( materialDef.name ) material.name = materialDef.name;\n\n\t\t\tassignExtrasToUserData( material, materialDef );\n\n\t\t\tparser.associations.set( material, { materials: materialIndex } );\n\n\t\t\tif ( materialDef.extensions ) addUnknownExtensionsToUserData( extensions, material, materialDef );\n\n\t\t\treturn material;\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * When Object3D instances are targeted by animation, they need unique names.\n\t *\n\t * @private\n\t * @param {string} originalName\n\t * @return {string}\n\t */\n\tcreateUniqueName( originalName ) {\n\n\t\tconst sanitizedName = PropertyBinding.sanitizeNodeName( originalName || '' );\n\n\t\tif ( sanitizedName in this.nodeNamesUsed ) {\n\n\t\t\treturn sanitizedName + '_' + ( ++ this.nodeNamesUsed[ sanitizedName ] );\n\n\t\t} else {\n\n\t\t\tthis.nodeNamesUsed[ sanitizedName ] = 0;\n\n\t\t\treturn sanitizedName;\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#geometry\n\t *\n\t * Creates BufferGeometries from primitives.\n\t *\n\t * @private\n\t * @param {Array<GLTF.Primitive>} primitives\n\t * @return {Promise<Array<BufferGeometry>>}\n\t */\n\tloadGeometries( primitives ) {\n\n\t\tconst parser = this;\n\t\tconst extensions = this.extensions;\n\t\tconst cache = this.primitiveCache;\n\n\t\tfunction createDracoPrimitive( primitive ) {\n\n\t\t\treturn extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ]\n\t\t\t\t.decodePrimitive( primitive, parser )\n\t\t\t\t.then( function ( geometry ) {\n\n\t\t\t\t\treturn addPrimitiveAttributes( geometry, primitive, parser );\n\n\t\t\t\t} );\n\n\t\t}\n\n\t\tconst pending = [];\n\n\t\tfor ( let i = 0, il = primitives.length; i < il; i ++ ) {\n\n\t\t\tconst primitive = primitives[ i ];\n\t\t\tconst cacheKey = createPrimitiveKey( primitive );\n\n\t\t\t// See if we've already created this geometry\n\t\t\tconst cached = cache[ cacheKey ];\n\n\t\t\tif ( cached ) {\n\n\t\t\t\t// Use the cached geometry if it exists\n\t\t\t\tpending.push( cached.promise );\n\n\t\t\t} else {\n\n\t\t\t\tlet geometryPromise;\n\n\t\t\t\tif ( primitive.extensions && primitive.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ] ) {\n\n\t\t\t\t\t// Use DRACO geometry if available\n\t\t\t\t\tgeometryPromise = createDracoPrimitive( primitive );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// Otherwise create a new geometry\n\t\t\t\t\tgeometryPromise = addPrimitiveAttributes( new BufferGeometry(), primitive, parser );\n\n\t\t\t\t}\n\n\t\t\t\t// Cache this geometry\n\t\t\t\tcache[ cacheKey ] = { primitive: primitive, promise: geometryPromise };\n\n\t\t\t\tpending.push( geometryPromise );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#meshes\n\t *\n\t * @private\n\t * @param {number} meshIndex\n\t * @return {Promise<Group|Mesh|SkinnedMesh|Line|Points>}\n\t */\n\tloadMesh( meshIndex ) {\n\n\t\tconst parser = this;\n\t\tconst json = this.json;\n\t\tconst extensions = this.extensions;\n\n\t\tconst meshDef = json.meshes[ meshIndex ];\n\t\tconst primitives = meshDef.primitives;\n\n\t\tconst pending = [];\n\n\t\tfor ( let i = 0, il = primitives.length; i < il; i ++ ) {\n\n\t\t\tconst material = primitives[ i ].material === undefined\n\t\t\t\t? createDefaultMaterial( this.cache )\n\t\t\t\t: this.getDependency( 'material', primitives[ i ].material );\n\n\t\t\tpending.push( material );\n\n\t\t}\n\n\t\tpending.push( parser.loadGeometries( primitives ) );\n\n\t\treturn Promise.all( pending ).then( function ( results ) {\n\n\t\t\tconst materials = results.slice( 0, results.length - 1 );\n\t\t\tconst geometries = results[ results.length - 1 ];\n\n\t\t\tconst meshes = [];\n\n\t\t\tfor ( let i = 0, il = geometries.length; i < il; i ++ ) {\n\n\t\t\t\tconst geometry = geometries[ i ];\n\t\t\t\tconst primitive = primitives[ i ];\n\n\t\t\t\t// 1. create Mesh\n\n\t\t\t\tlet mesh;\n\n\t\t\t\tconst material = materials[ i ];\n\n\t\t\t\tif ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES ||\n\t\t\t\t\t\tprimitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ||\n\t\t\t\t\t\tprimitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ||\n\t\t\t\t\t\tprimitive.mode === undefined ) {\n\n\t\t\t\t\t// .isSkinnedMesh isn't in glTF spec. See ._markDefs()\n\t\t\t\t\tmesh = meshDef.isSkinnedMesh === true\n\t\t\t\t\t\t? new SkinnedMesh( geometry, material )\n\t\t\t\t\t\t: new Mesh( geometry, material );\n\n\t\t\t\t\tif ( mesh.isSkinnedMesh === true ) {\n\n\t\t\t\t\t\t// normalize skin weights to fix malformed assets (see #15319)\n\t\t\t\t\t\tmesh.normalizeSkinWeights();\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ) {\n\n\t\t\t\t\t\tmesh.geometry = toTrianglesDrawMode( mesh.geometry, TriangleStripDrawMode );\n\n\t\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ) {\n\n\t\t\t\t\t\tmesh.geometry = toTrianglesDrawMode( mesh.geometry, TriangleFanDrawMode );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {\n\n\t\t\t\t\tmesh = new LineSegments( geometry, material );\n\n\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_STRIP ) {\n\n\t\t\t\t\tmesh = new Line( geometry, material );\n\n\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_LOOP ) {\n\n\t\t\t\t\tmesh = new LineLoop( geometry, material );\n\n\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.POINTS ) {\n\n\t\t\t\t\tmesh = new Points( geometry, material );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthrow new Error( 'THREE.GLTFLoader: Primitive mode unsupported: ' + primitive.mode );\n\n\t\t\t\t}\n\n\t\t\t\tif ( Object.keys( mesh.geometry.morphAttributes ).length > 0 ) {\n\n\t\t\t\t\tupdateMorphTargets( mesh, meshDef );\n\n\t\t\t\t}\n\n\t\t\t\tmesh.name = parser.createUniqueName( meshDef.name || ( 'mesh_' + meshIndex ) );\n\n\t\t\t\tassignExtrasToUserData( mesh, meshDef );\n\n\t\t\t\tif ( primitive.extensions ) addUnknownExtensionsToUserData( extensions, mesh, primitive );\n\n\t\t\t\tparser.assignFinalMaterial( mesh );\n\n\t\t\t\tmeshes.push( mesh );\n\n\t\t\t}\n\n\t\t\tfor ( let i = 0, il = meshes.length; i < il; i ++ ) {\n\n\t\t\t\tparser.associations.set( meshes[ i ], {\n\t\t\t\t\tmeshes: meshIndex,\n\t\t\t\t\tprimitives: i\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\tif ( meshes.length === 1 ) {\n\n\t\t\t\tif ( meshDef.extensions ) addUnknownExtensionsToUserData( extensions, meshes[ 0 ], meshDef );\n\n\t\t\t\treturn meshes[ 0 ];\n\n\t\t\t}\n\n\t\t\tconst group = new Group();\n\n\t\t\tif ( meshDef.extensions ) addUnknownExtensionsToUserData( extensions, group, meshDef );\n\n\t\t\tparser.associations.set( group, { meshes: meshIndex } );\n\n\t\t\tfor ( let i = 0, il = meshes.length; i < il; i ++ ) {\n\n\t\t\t\tgroup.add( meshes[ i ] );\n\n\t\t\t}\n\n\t\t\treturn group;\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#cameras\n\t *\n\t * @private\n\t * @param {number} cameraIndex\n\t * @return {Promise<Camera>|undefined}\n\t */\n\tloadCamera( cameraIndex ) {\n\n\t\tlet camera;\n\t\tconst cameraDef = this.json.cameras[ cameraIndex ];\n\t\tconst params = cameraDef[ cameraDef.type ];\n\n\t\tif ( ! params ) {\n\n\t\t\tconsole.warn( 'THREE.GLTFLoader: Missing camera parameters.' );\n\t\t\treturn;\n\n\t\t}\n\n\t\tif ( cameraDef.type === 'perspective' ) {\n\n\t\t\tcamera = new PerspectiveCamera( MathUtils.radToDeg( params.yfov ), params.aspectRatio || 1, params.znear || 1, params.zfar || 2e6 );\n\n\t\t} else if ( cameraDef.type === 'orthographic' ) {\n\n\t\t\tcamera = new OrthographicCamera( - params.xmag, params.xmag, params.ymag, - params.ymag, params.znear, params.zfar );\n\n\t\t}\n\n\t\tif ( cameraDef.name ) camera.name = this.createUniqueName( cameraDef.name );\n\n\t\tassignExtrasToUserData( camera, cameraDef );\n\n\t\treturn Promise.resolve( camera );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins\n\t *\n\t * @private\n\t * @param {number} skinIndex\n\t * @return {Promise<Skeleton>}\n\t */\n\tloadSkin( skinIndex ) {\n\n\t\tconst skinDef = this.json.skins[ skinIndex ];\n\n\t\tconst pending = [];\n\n\t\tfor ( let i = 0, il = skinDef.joints.length; i < il; i ++ ) {\n\n\t\t\tpending.push( this._loadNodeShallow( skinDef.joints[ i ] ) );\n\n\t\t}\n\n\t\tif ( skinDef.inverseBindMatrices !== undefined ) {\n\n\t\t\tpending.push( this.getDependency( 'accessor', skinDef.inverseBindMatrices ) );\n\n\t\t} else {\n\n\t\t\tpending.push( null );\n\n\t\t}\n\n\t\treturn Promise.all( pending ).then( function ( results ) {\n\n\t\t\tconst inverseBindMatrices = results.pop();\n\t\t\tconst jointNodes = results;\n\n\t\t\t// Note that bones (joint nodes) may or may not be in the\n\t\t\t// scene graph at this time.\n\n\t\t\tconst bones = [];\n\t\t\tconst boneInverses = [];\n\n\t\t\tfor ( let i = 0, il = jointNodes.length; i < il; i ++ ) {\n\n\t\t\t\tconst jointNode = jointNodes[ i ];\n\n\t\t\t\tif ( jointNode ) {\n\n\t\t\t\t\tbones.push( jointNode );\n\n\t\t\t\t\tconst mat = new Matrix4();\n\n\t\t\t\t\tif ( inverseBindMatrices !== null ) {\n\n\t\t\t\t\t\tmat.fromArray( inverseBindMatrices.array, i * 16 );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tboneInverses.push( mat );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.warn( 'THREE.GLTFLoader: Joint \"%s\" could not be found.', skinDef.joints[ i ] );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn new Skeleton( bones, boneInverses );\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#animations\n\t *\n\t * @private\n\t * @param {number} animationIndex\n\t * @return {Promise<AnimationClip>}\n\t */\n\tloadAnimation( animationIndex ) {\n\n\t\tconst json = this.json;\n\t\tconst parser = this;\n\n\t\tconst animationDef = json.animations[ animationIndex ];\n\t\tconst animationName = animationDef.name ? animationDef.name : 'animation_' + animationIndex;\n\n\t\tconst pendingNodes = [];\n\t\tconst pendingInputAccessors = [];\n\t\tconst pendingOutputAccessors = [];\n\t\tconst pendingSamplers = [];\n\t\tconst pendingTargets = [];\n\n\t\tfor ( let i = 0, il = animationDef.channels.length; i < il; i ++ ) {\n\n\t\t\tconst channel = animationDef.channels[ i ];\n\t\t\tconst sampler = animationDef.samplers[ channel.sampler ];\n\t\t\tconst target = channel.target;\n\t\t\tconst name = target.node;\n\t\t\tconst input = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.input ] : sampler.input;\n\t\t\tconst output = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.output ] : sampler.output;\n\n\t\t\tif ( target.node === undefined ) continue;\n\n\t\t\tpendingNodes.push( this.getDependency( 'node', name ) );\n\t\t\tpendingInputAccessors.push( this.getDependency( 'accessor', input ) );\n\t\t\tpendingOutputAccessors.push( this.getDependency( 'accessor', output ) );\n\t\t\tpendingSamplers.push( sampler );\n\t\t\tpendingTargets.push( target );\n\n\t\t}\n\n\t\treturn Promise.all( [\n\n\t\t\tPromise.all( pendingNodes ),\n\t\t\tPromise.all( pendingInputAccessors ),\n\t\t\tPromise.all( pendingOutputAccessors ),\n\t\t\tPromise.all( pendingSamplers ),\n\t\t\tPromise.all( pendingTargets )\n\n\t\t] ).then( function ( dependencies ) {\n\n\t\t\tconst nodes = dependencies[ 0 ];\n\t\t\tconst inputAccessors = dependencies[ 1 ];\n\t\t\tconst outputAccessors = dependencies[ 2 ];\n\t\t\tconst samplers = dependencies[ 3 ];\n\t\t\tconst targets = dependencies[ 4 ];\n\n\t\t\tconst tracks = [];\n\n\t\t\tfor ( let i = 0, il = nodes.length; i < il; i ++ ) {\n\n\t\t\t\tconst node = nodes[ i ];\n\t\t\t\tconst inputAccessor = inputAccessors[ i ];\n\t\t\t\tconst outputAccessor = outputAccessors[ i ];\n\t\t\t\tconst sampler = samplers[ i ];\n\t\t\t\tconst target = targets[ i ];\n\n\t\t\t\tif ( node === undefined ) continue;\n\n\t\t\t\tif ( node.updateMatrix ) {\n\n\t\t\t\t\tnode.updateMatrix();\n\n\t\t\t\t}\n\n\t\t\t\tconst createdTracks = parser._createAnimationTracks( node, inputAccessor, outputAccessor, sampler, target );\n\n\t\t\t\tif ( createdTracks ) {\n\n\t\t\t\t\tfor ( let k = 0; k < createdTracks.length; k ++ ) {\n\n\t\t\t\t\t\ttracks.push( createdTracks[ k ] );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tconst animation = new AnimationClip( animationName, undefined, tracks );\n\n\t\t\tassignExtrasToUserData( animation, animationDef );\n\n\t\t\treturn animation;\n\n\t\t} );\n\n\t}\n\n\tcreateNodeMesh( nodeIndex ) {\n\n\t\tconst json = this.json;\n\t\tconst parser = this;\n\t\tconst nodeDef = json.nodes[ nodeIndex ];\n\n\t\tif ( nodeDef.mesh === undefined ) return null;\n\n\t\treturn parser.getDependency( 'mesh', nodeDef.mesh ).then( function ( mesh ) {\n\n\t\t\tconst node = parser._getNodeRef( parser.meshCache, nodeDef.mesh, mesh );\n\n\t\t\t// if weights are provided on the node, override weights on the mesh.\n\t\t\tif ( nodeDef.weights !== undefined ) {\n\n\t\t\t\tnode.traverse( function ( o ) {\n\n\t\t\t\t\tif ( ! o.isMesh ) return;\n\n\t\t\t\t\tfor ( let i = 0, il = nodeDef.weights.length; i < il; i ++ ) {\n\n\t\t\t\t\t\to.morphTargetInfluences[ i ] = nodeDef.weights[ i ];\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\treturn node;\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodes-and-hierarchy\n\t *\n\t * @private\n\t * @param {number} nodeIndex\n\t * @return {Promise<Object3D>}\n\t */\n\tloadNode( nodeIndex ) {\n\n\t\tconst json = this.json;\n\t\tconst parser = this;\n\n\t\tconst nodeDef = json.nodes[ nodeIndex ];\n\n\t\tconst nodePending = parser._loadNodeShallow( nodeIndex );\n\n\t\tconst childPending = [];\n\t\tconst childrenDef = nodeDef.children || [];\n\n\t\tfor ( let i = 0, il = childrenDef.length; i < il; i ++ ) {\n\n\t\t\tchildPending.push( parser.getDependency( 'node', childrenDef[ i ] ) );\n\n\t\t}\n\n\t\tconst skeletonPending = nodeDef.skin === undefined\n\t\t\t? Promise.resolve( null )\n\t\t\t: parser.getDependency( 'skin', nodeDef.skin );\n\n\t\treturn Promise.all( [\n\t\t\tnodePending,\n\t\t\tPromise.all( childPending ),\n\t\t\tskeletonPending\n\t\t] ).then( function ( results ) {\n\n\t\t\tconst node = results[ 0 ];\n\t\t\tconst children = results[ 1 ];\n\t\t\tconst skeleton = results[ 2 ];\n\n\t\t\tif ( skeleton !== null ) {\n\n\t\t\t\t// This full traverse should be fine because\n\t\t\t\t// child glTF nodes have not been added to this node yet.\n\t\t\t\tnode.traverse( function ( mesh ) {\n\n\t\t\t\t\tif ( ! mesh.isSkinnedMesh ) return;\n\n\t\t\t\t\tmesh.bind( skeleton, _identityMatrix );\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\tfor ( let i = 0, il = children.length; i < il; i ++ ) {\n\n\t\t\t\tnode.add( children[ i ] );\n\n\t\t\t}\n\n\t\t\t// Reconstruct pivot from container pattern created by GLTFExporter\n\t\t\t// The container has position+pivot, rotation, scale; child has -pivot offset and mesh\n\t\t\tif ( node.userData.pivot !== undefined && children.length > 0 ) {\n\n\t\t\t\tconst pivot = node.userData.pivot;\n\t\t\t\tconst pivotChild = children[ 0 ];\n\n\t\t\t\t// Set pivot on container and adjust transforms\n\t\t\t\tnode.pivot = new Vector3().fromArray( pivot );\n\n\t\t\t\t// Adjust container position: stored as position + pivot, so subtract pivot\n\t\t\t\tnode.position.x -= pivot[ 0 ];\n\t\t\t\tnode.position.y -= pivot[ 1 ];\n\t\t\t\tnode.position.z -= pivot[ 2 ];\n\n\t\t\t\t// Remove the child's -pivot offset since pivot now handles it\n\t\t\t\tpivotChild.position.set( 0, 0, 0 );\n\n\t\t\t\tdelete node.userData.pivot;\n\n\t\t\t}\n\n\t\t\treturn node;\n\n\t\t} );\n\n\t}\n\n\t// ._loadNodeShallow() parses a single node.\n\t// skin and child nodes are created and added in .loadNode() (no '_' prefix).\n\t_loadNodeShallow( nodeIndex ) {\n\n\t\tconst json = this.json;\n\t\tconst extensions = this.extensions;\n\t\tconst parser = this;\n\n\t\t// This method is called from .loadNode() and .loadSkin().\n\t\t// Cache a node to avoid duplication.\n\n\t\tif ( this.nodeCache[ nodeIndex ] !== undefined ) {\n\n\t\t\treturn this.nodeCache[ nodeIndex ];\n\n\t\t}\n\n\t\tconst nodeDef = json.nodes[ nodeIndex ];\n\n\t\t// reserve node's name before its dependencies, so the root has the intended name.\n\t\tconst nodeName = nodeDef.name ? parser.createUniqueName( nodeDef.name ) : '';\n\n\t\tconst pending = [];\n\n\t\tconst meshPromise = parser._invokeOne( function ( ext ) {\n\n\t\t\treturn ext.createNodeMesh && ext.createNodeMesh( nodeIndex );\n\n\t\t} );\n\n\t\tif ( meshPromise ) {\n\n\t\t\tpending.push( meshPromise );\n\n\t\t}\n\n\t\tif ( nodeDef.camera !== undefined ) {\n\n\t\t\tpending.push( parser.getDependency( 'camera', nodeDef.camera ).then( function ( camera ) {\n\n\t\t\t\treturn parser._getNodeRef( parser.cameraCache, nodeDef.camera, camera );\n\n\t\t\t} ) );\n\n\t\t}\n\n\t\tparser._invokeAll( function ( ext ) {\n\n\t\t\treturn ext.createNodeAttachment && ext.createNodeAttachment( nodeIndex );\n\n\t\t} ).forEach( function ( promise ) {\n\n\t\t\tpending.push( promise );\n\n\t\t} );\n\n\t\tthis.nodeCache[ nodeIndex ] = Promise.all( pending ).then( function ( objects ) {\n\n\t\t\tlet node;\n\n\t\t\t// .isBone isn't in glTF spec. See ._markDefs\n\t\t\tif ( nodeDef.isBone === true ) {\n\n\t\t\t\tnode = new Bone();\n\n\t\t\t} else if ( objects.length > 1 ) {\n\n\t\t\t\tnode = new Group();\n\n\t\t\t} else if ( objects.length === 1 ) {\n\n\t\t\t\tnode = objects[ 0 ];\n\n\t\t\t} else {\n\n\t\t\t\tnode = new Object3D();\n\n\t\t\t}\n\n\t\t\tif ( node !== objects[ 0 ] ) {\n\n\t\t\t\tfor ( let i = 0, il = objects.length; i < il; i ++ ) {\n\n\t\t\t\t\tnode.add( objects[ i ] );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( nodeDef.name ) {\n\n\t\t\t\tnode.userData.name = nodeDef.name;\n\t\t\t\tnode.name = nodeName;\n\n\t\t\t}\n\n\t\t\tassignExtrasToUserData( node, nodeDef );\n\n\t\t\tif ( nodeDef.extensions ) addUnknownExtensionsToUserData( extensions, node, nodeDef );\n\n\t\t\tif ( nodeDef.matrix !== undefined ) {\n\n\t\t\t\tconst matrix = new Matrix4();\n\t\t\t\tmatrix.fromArray( nodeDef.matrix );\n\t\t\t\tnode.applyMatrix4( matrix );\n\n\t\t\t} else {\n\n\t\t\t\tif ( nodeDef.translation !== undefined ) {\n\n\t\t\t\t\tnode.position.fromArray( nodeDef.translation );\n\n\t\t\t\t}\n\n\t\t\t\tif ( nodeDef.rotation !== undefined ) {\n\n\t\t\t\t\tnode.quaternion.fromArray( nodeDef.rotation );\n\n\t\t\t\t}\n\n\t\t\t\tif ( nodeDef.scale !== undefined ) {\n\n\t\t\t\t\tnode.scale.fromArray( nodeDef.scale );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( ! parser.associations.has( node ) ) {\n\n\t\t\t\tparser.associations.set( node, {} );\n\n\t\t\t} else if ( nodeDef.mesh !== undefined && parser.meshCache.refs[ nodeDef.mesh ] > 1 ) {\n\n\t\t\t\tconst mapping = parser.associations.get( node );\n\t\t\t\tparser.associations.set( node, { ...mapping } );\n\n\t\t\t}\n\n\t\t\tparser.associations.get( node ).nodes = nodeIndex;\n\n\t\t\treturn node;\n\n\t\t} );\n\n\t\treturn this.nodeCache[ nodeIndex ];\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#scenes\n\t *\n\t * @private\n\t * @param {number} sceneIndex\n\t * @return {Promise<Group>}\n\t */\n\tloadScene( sceneIndex ) {\n\n\t\tconst extensions = this.extensions;\n\t\tconst sceneDef = this.json.scenes[ sceneIndex ];\n\t\tconst parser = this;\n\n\t\t// Loader returns Group, not Scene.\n\t\t// See: https://github.com/mrdoob/three.js/issues/18342#issuecomment-578981172\n\t\tconst scene = new Group();\n\t\tif ( sceneDef.name ) scene.name = parser.createUniqueName( sceneDef.name );\n\n\t\tassignExtrasToUserData( scene, sceneDef );\n\n\t\tif ( sceneDef.extensions ) addUnknownExtensionsToUserData( extensions, scene, sceneDef );\n\n\t\tconst nodeIds = sceneDef.nodes || [];\n\n\t\tconst pending = [];\n\n\t\tfor ( let i = 0, il = nodeIds.length; i < il; i ++ ) {\n\n\t\t\tpending.push( parser.getDependency( 'node', nodeIds[ i ] ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending ).then( function ( nodes ) {\n\n\t\t\tfor ( let i = 0, il = nodes.length; i < il; i ++ ) {\n\n\t\t\t\tconst node = nodes[ i ];\n\n\t\t\t\t// If the node already has a parent, it means it's being reused across multiple scenes.\n\t\t\t\t// Clone it to avoid the second scene's add() removing it from the first scene.\n\t\t\t\t// See: https://github.com/mrdoob/three.js/issues/27993\n\t\t\t\tif ( node.parent !== null ) {\n\n\t\t\t\t\tscene.add( clone( node ) );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tscene.add( node );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// Removes dangling associations, associations that reference a node that\n\t\t\t// didn't make it into the scene.\n\t\t\tconst reduceAssociations = ( node ) => {\n\n\t\t\t\tconst reducedAssociations = new Map();\n\n\t\t\t\tfor ( const [ key, value ] of parser.associations ) {\n\n\t\t\t\t\tif ( key instanceof Material || key instanceof Texture ) {\n\n\t\t\t\t\t\treducedAssociations.set( key, value );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tnode.traverse( ( node ) => {\n\n\t\t\t\t\tconst mappings = parser.associations.get( node );\n\n\t\t\t\t\tif ( mappings != null ) {\n\n\t\t\t\t\t\treducedAssociations.set( node, mappings );\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t\treturn reducedAssociations;\n\n\t\t\t};\n\n\t\t\tparser.associations = reduceAssociations( scene );\n\n\t\t\treturn scene;\n\n\t\t} );\n\n\t}\n\n\t_createAnimationTracks( node, inputAccessor, outputAccessor, sampler, target ) {\n\n\t\tconst tracks = [];\n\n\t\tconst targetName = node.name ? node.name : node.uuid;\n\t\tconst targetNames = [];\n\n\t\tfunction collectMorphTargets( object ) {\n\n\t\t\tif ( object.morphTargetInfluences ) {\n\n\t\t\t\ttargetNames.push( object.name ? object.name : object.uuid );\n\n\t\t\t}\n\n\t\t}\n\n\n\t\tif ( PATH_PROPERTIES[ target.path ] === PATH_PROPERTIES.weights ) {\n\n\t\t\tcollectMorphTargets( node );\n\n\t\t\t// for multi-primitive meshes, the node is a Group containing the sub-meshes\n\n\t\t\tif ( node.isGroup ) {\n\n\t\t\t\tnode.children.forEach( collectMorphTargets );\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\ttargetNames.push( targetName );\n\n\t\t}\n\n\t\tlet TypedKeyframeTrack;\n\n\t\tswitch ( PATH_PROPERTIES[ target.path ] ) {\n\n\t\t\tcase PATH_PROPERTIES.weights:\n\n\t\t\t\tTypedKeyframeTrack = NumberKeyframeTrack;\n\t\t\t\tbreak;\n\n\t\t\tcase PATH_PROPERTIES.rotation:\n\n\t\t\t\tTypedKeyframeTrack = QuaternionKeyframeTrack;\n\t\t\t\tbreak;\n\n\t\t\tcase PATH_PROPERTIES.translation:\n\t\t\tcase PATH_PROPERTIES.scale:\n\n\t\t\t\tTypedKeyframeTrack = VectorKeyframeTrack;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\n\t\t\t\tswitch ( outputAccessor.itemSize ) {\n\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\tTypedKeyframeTrack = NumberKeyframeTrack;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2:\n\t\t\t\t\tcase 3:\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tTypedKeyframeTrack = VectorKeyframeTrack;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\tconst interpolation = sampler.interpolation !== undefined ? INTERPOLATION[ sampler.interpolation ] : InterpolateLinear;\n\n\n\t\tconst outputArray = this._getArrayFromAccessor( outputAccessor );\n\n\t\tfor ( let j = 0, jl = targetNames.length; j < jl; j ++ ) {\n\n\t\t\tconst track = new TypedKeyframeTrack(\n\t\t\t\ttargetNames[ j ] + '.' + PATH_PROPERTIES[ target.path ],\n\t\t\t\tinputAccessor.array,\n\t\t\t\toutputArray,\n\t\t\t\tinterpolation\n\t\t\t);\n\n\t\t\t// Override interpolation with custom factory method.\n\t\t\tif ( sampler.interpolation === 'CUBICSPLINE' ) {\n\n\t\t\t\tthis._createCubicSplineTrackInterpolant( track );\n\n\t\t\t}\n\n\t\t\ttracks.push( track );\n\n\t\t}\n\n\t\treturn tracks;\n\n\t}\n\n\t_getArrayFromAccessor( accessor ) {\n\n\t\tlet outputArray = accessor.array;\n\n\t\tif ( accessor.normalized ) {\n\n\t\t\tconst scale = getNormalizedComponentScale( outputArray.constructor );\n\t\t\tconst scaled = new Float32Array( outputArray.length );\n\n\t\t\tfor ( let j = 0, jl = outputArray.length; j < jl; j ++ ) {\n\n\t\t\t\tscaled[ j ] = outputArray[ j ] * scale;\n\n\t\t\t}\n\n\t\t\toutputArray = scaled;\n\n\t\t}\n\n\t\treturn outputArray;\n\n\t}\n\n\t_createCubicSplineTrackInterpolant( track ) {\n\n\t\ttrack.createInterpolant = function InterpolantFactoryMethodGLTFCubicSpline( result ) {\n\n\t\t\t// A CUBICSPLINE keyframe in glTF has three output values for each input value,\n\t\t\t// representing inTangent, splineVertex, and outTangent. As a result, track.getValueSize()\n\t\t\t// must be divided by three to get the interpolant's sampleSize argument.\n\n\t\t\tconst interpolantType = ( this instanceof QuaternionKeyframeTrack ) ? GLTFCubicSplineQuaternionInterpolant : GLTFCubicSplineInterpolant;\n\n\t\t\treturn new interpolantType( this.times, this.values, this.getValueSize() / 3, result );\n\n\t\t};\n\n\t\t// Mark as CUBICSPLINE. `track.getInterpolation()` doesn't support custom interpolants.\n\t\ttrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline = true;\n\n\t}\n\n}\n\n/**\n *\n * @private\n * @param {BufferGeometry} geometry\n * @param {GLTF.Primitive} primitiveDef\n * @param {GLTFParser} parser\n */\nfunction computeBounds( geometry, primitiveDef, parser ) {\n\n\tconst attributes = primitiveDef.attributes;\n\n\tconst box = new Box3();\n\n\tif ( attributes.POSITION !== undefined ) {\n\n\t\tconst accessor = parser.json.accessors[ attributes.POSITION ];\n\n\t\tconst min = accessor.min;\n\t\tconst max = accessor.max;\n\n\t\t// glTF requires 'min' and 'max', but VRM (which extends glTF) currently ignores that requirement.\n\n\t\tif ( min !== undefined && max !== undefined ) {\n\n\t\t\tbox.set(\n\t\t\t\tnew Vector3( min[ 0 ], min[ 1 ], min[ 2 ] ),\n\t\t\t\tnew Vector3( max[ 0 ], max[ 1 ], max[ 2 ] )\n\t\t\t);\n\n\t\t\tif ( accessor.normalized ) {\n\n\t\t\t\tconst boxScale = getNormalizedComponentScale( WEBGL_COMPONENT_TYPES[ accessor.componentType ] );\n\t\t\t\tbox.min.multiplyScalar( boxScale );\n\t\t\t\tbox.max.multiplyScalar( boxScale );\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tconsole.warn( 'THREE.GLTFLoader: Missing min/max properties for accessor POSITION.' );\n\n\t\t\treturn;\n\n\t\t}\n\n\t} else {\n\n\t\treturn;\n\n\t}\n\n\tconst targets = primitiveDef.targets;\n\n\tif ( targets !== undefined ) {\n\n\t\tconst maxDisplacement = new Vector3();\n\t\tconst vector = new Vector3();\n\n\t\tfor ( let i = 0, il = targets.length; i < il; i ++ ) {\n\n\t\t\tconst target = targets[ i ];\n\n\t\t\tif ( target.POSITION !== undefined ) {\n\n\t\t\t\tconst accessor = parser.json.accessors[ target.POSITION ];\n\t\t\t\tconst min = accessor.min;\n\t\t\t\tconst max = accessor.max;\n\n\t\t\t\t// glTF requires 'min' and 'max', but VRM (which extends glTF) currently ignores that requirement.\n\n\t\t\t\tif ( min !== undefined && max !== undefined ) {\n\n\t\t\t\t\t// we need to get max of absolute components because target weight is [-1,1]\n\t\t\t\t\tvector.setX( Math.max( Math.abs( min[ 0 ] ), Math.abs( max[ 0 ] ) ) );\n\t\t\t\t\tvector.setY( Math.max( Math.abs( min[ 1 ] ), Math.abs( max[ 1 ] ) ) );\n\t\t\t\t\tvector.setZ( Math.max( Math.abs( min[ 2 ] ), Math.abs( max[ 2 ] ) ) );\n\n\n\t\t\t\t\tif ( accessor.normalized ) {\n\n\t\t\t\t\t\tconst boxScale = getNormalizedComponentScale( WEBGL_COMPONENT_TYPES[ accessor.componentType ] );\n\t\t\t\t\t\tvector.multiplyScalar( boxScale );\n\n\t\t\t\t\t}\n\n\t\t\t\t\t// Note: this assumes that the sum of all weights is at most 1. This isn't quite correct - it's more conservative\n\t\t\t\t\t// to assume that each target can have a max weight of 1. However, for some use cases - notably, when morph targets\n\t\t\t\t\t// are used to implement key-frame animations and as such only two are active at a time - this results in very large\n\t\t\t\t\t// boxes. So for now we make a box that's sometimes a touch too small but is hopefully mostly of reasonable size.\n\t\t\t\t\tmaxDisplacement.max( vector );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.warn( 'THREE.GLTFLoader: Missing min/max properties for accessor POSITION.' );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\t// As per comment above this box isn't conservative, but has a reasonable size for a very large number of morph targets.\n\t\tbox.expandByVector( maxDisplacement );\n\n\t}\n\n\tgeometry.boundingBox = box;\n\n\tconst sphere = new Sphere();\n\n\tbox.getCenter( sphere.center );\n\tsphere.radius = box.min.distanceTo( box.max ) / 2;\n\n\tgeometry.boundingSphere = sphere;\n\n}\n\n/**\n *\n * @private\n * @param {BufferGeometry} geometry\n * @param {GLTF.Primitive} primitiveDef\n * @param {GLTFParser} parser\n * @return {Promise<BufferGeometry>}\n */\nfunction addPrimitiveAttributes( geometry, primitiveDef, parser ) {\n\n\tconst attributes = primitiveDef.attributes;\n\n\tconst pending = [];\n\n\tfunction assignAttributeAccessor( accessorIndex, attributeName ) {\n\n\t\treturn parser.getDependency( 'accessor', accessorIndex )\n\t\t\t.then( function ( accessor ) {\n\n\t\t\t\tgeometry.setAttribute( attributeName, accessor );\n\n\t\t\t} );\n\n\t}\n\n\tfor ( const gltfAttributeName in attributes ) {\n\n\t\tconst threeAttributeName = ATTRIBUTES[ gltfAttributeName ] || gltfAttributeName.toLowerCase();\n\n\t\t// Skip attributes already provided by e.g. Draco extension.\n\t\tif ( threeAttributeName in geometry.attributes ) continue;\n\n\t\tpending.push( assignAttributeAccessor( attributes[ gltfAttributeName ], threeAttributeName ) );\n\n\t}\n\n\tif ( primitiveDef.indices !== undefined && ! geometry.index ) {\n\n\t\tconst accessor = parser.getDependency( 'accessor', primitiveDef.indices ).then( function ( accessor ) {\n\n\t\t\tgeometry.setIndex( accessor );\n\n\t\t} );\n\n\t\tpending.push( accessor );\n\n\t}\n\n\tif ( ColorManagement.workingColorSpace !== LinearSRGBColorSpace && 'COLOR_0' in attributes ) {\n\n\t\tconsole.warn( `THREE.GLTFLoader: Converting vertex colors from \"srgb-linear\" to \"${ColorManagement.workingColorSpace}\" not supported.` );\n\n\t}\n\n\tassignExtrasToUserData( geometry, primitiveDef );\n\n\tcomputeBounds( geometry, primitiveDef, parser );\n\n\treturn Promise.all( pending ).then( function () {\n\n\t\treturn primitiveDef.targets !== undefined\n\t\t\t? addMorphTargets( geometry, primitiveDef.targets, parser )\n\t\t\t: geometry;\n\n\t} );\n\n}\n\n/**\n * Loader result of `GLTFLoader`.\n *\n * @typedef {Object} GLTFLoader~LoadObject\n * @property {Array<AnimationClip>} animations - An array of animation clips.\n * @property {Object} asset - Meta data about the loaded asset.\n * @property {Array<Camera>} cameras - An array of cameras.\n * @property {GLTFParser} parser - A reference to the internal parser.\n * @property {Group} scene - The default scene.\n * @property {Array<Group>} scenes - glTF assets might define multiple scenes.\n * @property {Object} userData - Additional data.\n **/\n\nexport { GLTFLoader };\n","/**\r\n * 提供添加基础几何体(正方体、球体)以及导入外部模型文件的功能\r\n * 所有模型均自动标记为可移动(isMovable = true)\r\n */\r\n\r\nimport * as THREE from \"three\";\r\nimport { addModel } from \"./index\";\r\nimport { OBJLoader } from \"three/examples/jsm/loaders/OBJLoader.js\";\r\nimport { GLTFLoader } from \"three/examples/jsm/loaders/GLTFLoader.js\";\r\n\r\n//#region ─── 添加基础体 ───\r\n\r\n/** 添加一个蓝色的正方体,位置在地面上方 0.5 单位 */\r\nexport function addBox() {\r\n const geo = new THREE.BoxGeometry(1, 1, 1);\r\n const mat = new THREE.MeshStandardMaterial({ color: 0x00aaff });\r\n const mesh = new THREE.Mesh(geo, mat);\r\n mesh.position.y = 0.5;\r\n mesh.userData.isMovable = true;\r\n mesh.name = \"正方体\";\r\n addModel(mesh, true);\r\n return mesh;\r\n}\r\n\r\n/** 添加一个橙色的球体,位置在地面上方 0.6 单位 */\r\nexport function addSphere() {\r\n const geo = new THREE.SphereGeometry(0.6, 32, 32);\r\n const mat = new THREE.MeshStandardMaterial({ color: 0xff8800 });\r\n const mesh = new THREE.Mesh(geo, mat);\r\n mesh.position.y = 0.6;\r\n mesh.userData.isMovable = true;\r\n mesh.name = \"球体\";\r\n addModel(mesh, true);\r\n return mesh;\r\n}\r\n//#endregion\r\n\r\n//#region ─── 导入外部模型 ───\r\n\r\n/**\r\n * 从 File 对象导入 3D 模型(支持 .obj, .gltf, .glb)\r\n * 导入后自动标记所有节点为可移动,并居中放置\r\n * @param file - 模型文件\r\n * @returns Promise 解析为模型根对象\r\n */\r\nexport function importModelFromFile(file: File): Promise<THREE.Object3D> {\r\n return new Promise((resolve, reject) => {\r\n const ext = file.name.split(\".\").pop()?.toLowerCase();\r\n const url = URL.createObjectURL(file);\r\n\r\n let loader: any;\r\n if (ext === \"obj\") loader = new OBJLoader();\r\n else if (ext === \"gltf\" || ext === \"glb\") loader = new GLTFLoader();\r\n else {\r\n reject(new Error(\"不支持的文件格式,请使用 .obj, .gltf, .glb\"));\r\n return;\r\n }\r\n\r\n loader.load(\r\n url,\r\n (result: any) => {\r\n // 获取模型根对象\r\n const model = ext === \"gltf\" || ext === \"glb\" ? result.scene : result;\r\n // 遍历所有后代,标记为可移动,设置默认名称,优化 Mesh\r\n model.traverse((child: THREE.Object3D) => {\r\n child.userData.isMovable = true;\r\n if (!child.name) child.name = child.type;\r\n if (child.type === \"Mesh\") {\r\n child.frustumCulled = true; // 启用视锥体裁剪\r\n (child as THREE.Mesh).geometry?.computeVertexNormals(); // 重新计算法线\r\n }\r\n });\r\n // 将模型包围盒中心置于原点(居中)\r\n const box = new THREE.Box3().setFromObject(model);\r\n const center = box.getCenter(new THREE.Vector3());\r\n model.position.sub(center);\r\n // 添加到场景并自动选中\r\n addModel(model, true);\r\n resolve(model);\r\n },\r\n undefined,\r\n (err: any) => reject(err),\r\n );\r\n });\r\n}\r\n\r\n/**\r\n * 根据类型字符串添加对应的基础模型\r\n * @param type - 'box' 或 'sphere'\r\n */\r\nexport function addModelByType(type: string) {\r\n switch (type) {\r\n case \"box\":\r\n addBox();\r\n break;\r\n case \"sphere\":\r\n addSphere();\r\n break;\r\n }\r\n}\r\n//#endregion\r\n","<template>\r\n <div class=\"tree-node\" ref=\"nodeRef\">\r\n <!-- 节点行 -->\r\n <div\r\n class=\"tree-item\"\r\n :class=\"{ selected: isSelected }\"\r\n @click=\"handleSelect\"\r\n >\r\n <!-- 展开/收起箭头 -->\r\n <span\r\n v-if=\"hasChildren\"\r\n class=\"toggle-icon\"\r\n @click.stop=\"toggleExpand(node.uuid)\"\r\n >\r\n {{ isExpanded ? \"▼\" : \"▶\" }}\r\n </span>\r\n <span v-else class=\"toggle-placeholder\"></span>\r\n <!-- 图标 -->\r\n <span class=\"tree-icon\">{{ getIcon(node) }}</span>\r\n <!-- 名称 -->\r\n <span class=\"tree-name\">{{ getDisplayName(node) }}</span>\r\n <!-- 删除按钮 -->\r\n <button class=\"tree-delete\" @click.stop=\"handleDelete\">×</button>\r\n </div>\r\n <!-- 子节点列表(递归) -->\r\n <div v-if=\"isExpanded && hasChildren\" class=\"tree-children\">\r\n <TreeItem\r\n v-for=\"child in childNodes\"\r\n :key=\"child.uuid\"\r\n :node=\"child\"\r\n :selected-object=\"selectedObject\"\r\n :version=\"version\"\r\n @select=\"emit('select', $event)\"\r\n @delete=\"emit('delete', $event)\"\r\n />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\n/**\r\n * 递归树节点组件,用于展示场景物体的层级结构\r\n * 展开状态由父组件通过 provide/inject 共享\r\n * 当节点被选中时自动滚动到可视区域\r\n */\r\n\r\nimport { computed, inject, ref, watchEffect, type Ref } from \"vue\";\r\nimport type { Object3D } from \"three\";\r\n\r\nconst props = defineProps<{\r\n /** 当前节点对应的 Three.js 物体 */\r\n node: Object3D;\r\n /** 当前选中的物体(外部传入) */\r\n selectedObject: Object3D | null;\r\n /** 版本号,用于强制重新计算子节点列表 */\r\n version: number;\r\n}>();\r\n\r\nconst emit = defineEmits<{\r\n (e: \"select\", obj: Object3D): void;\r\n (e: \"delete\", obj: Object3D): void;\r\n}>();\r\n\r\n// ─── DOM 引用 ───\r\nconst nodeRef = ref<HTMLElement | null>(null);\r\n\r\n// ─── 注入展开状态管理 ───\r\nconst { expandedSet, toggleExpand } = inject<{\r\n expandedSet: Ref<Set<string>>;\r\n toggleExpand: (uuid: string) => void;\r\n}>(\"treeExpand\")!;\r\n\r\n// ─── 计算属性 ───\r\n\r\n/** 当前节点是否展开(基于展开集合) */\r\nconst isExpanded = computed(() => expandedSet.value.has(props.node.uuid));\r\n\r\n/** 是否有可移动的子节点(依赖 version) */\r\nconst hasChildren = computed(() => {\r\n const _ = props.version; // 建立依赖\r\n _\r\n return props.node.children.some((child) => child.userData.isMovable === true);\r\n});\r\n\r\n/** 可移动的子节点列表(依赖 version) */\r\nconst childNodes = computed(() => {\r\n const _ = props.version; // 建立依赖\r\n _\r\n return props.node.children.filter(\r\n (child) => child.userData.isMovable === true,\r\n );\r\n});\r\n\r\n/** 当前节点是否被选中 */\r\nconst isSelected = computed(\r\n () => props.selectedObject?.uuid === props.node.uuid,\r\n);\r\n\r\n/**\r\n * 自动滚动到选中节点(使用 watchEffect + flush: 'post' 确保 DOM 更新后执行)\r\n */\r\nwatchEffect(\r\n () => {\r\n if (isSelected.value && nodeRef.value) {\r\n nodeRef.value.scrollIntoView({\r\n block: \"nearest\", // 仅当元素不在可视区域时才滚动\r\n behavior: \"smooth\", // 平滑滚动\r\n });\r\n }\r\n },\r\n { flush: \"post\" },\r\n);\r\n\r\n// ─── 事件处理 ───\r\n\r\n/** 点击节点行:阻止冒泡并触发选中事件 */\r\nconst handleSelect = (event: MouseEvent) => {\r\n event.stopPropagation();\r\n emit(\"select\", props.node);\r\n};\r\n\r\n/** 点击删除按钮:阻止冒泡并触发删除事件 */\r\nconst handleDelete = (event: MouseEvent) => {\r\n event.stopPropagation();\r\n emit(\"delete\", props.node);\r\n};\r\n\r\n// ─── 辅助函数 ───\r\n\r\n/** 根据对象类型返回对应的图标字符 */\r\nconst getIcon = (obj: Object3D) => {\r\n if (obj.type === \"Mesh\" || obj.type === \"Sprite\") return \"🟦\";\r\n if (obj.type === \"Light\") return \"💡\";\r\n return \"📦\";\r\n};\r\n\r\n/** 获取对象的显示名称,若没有则自动生成 */\r\nconst getDisplayName = (obj: Object3D) => obj.name || `${obj.type} (${obj.id})`;\r\n</script>\r\n\r\n<style lang=\"less\" scoped>\r\n/* 节点样式 */\r\n.tree-node {\r\n .tree-item {\r\n display: flex;\r\n align-items: center;\r\n padding: 4px 10px;\r\n cursor: pointer;\r\n transition: background 0.15s;\r\n &:hover {\r\n background: #2a4050;\r\n }\r\n }\r\n .tree-item.selected {\r\n background: #3e5a6b;\r\n }\r\n\r\n .toggle-icon {\r\n cursor: pointer;\r\n width: 20px;\r\n text-align: center;\r\n font-size: 12px;\r\n user-select: none;\r\n }\r\n .toggle-placeholder {\r\n width: 20px;\r\n display: inline-block;\r\n }\r\n .tree-icon {\r\n margin-right: 6px;\r\n font-size: 14px;\r\n }\r\n .tree-name {\r\n flex: 1;\r\n font-size: 13px;\r\n user-select: none;\r\n }\r\n .tree-delete {\r\n background: transparent;\r\n border: none;\r\n color: #e74c3c;\r\n font-size: 16px;\r\n cursor: pointer;\r\n padding: 0 4px;\r\n line-height: 1;\r\n &:hover {\r\n color: #ff6b6b;\r\n }\r\n }\r\n}\r\n.tree-children {\r\n padding-left: 20px;\r\n} /* 缩进 */\r\n</style>\r\n","/**\r\n * 树形展开状态管理的组合式函数\r\n * 提供展开集合的响应式管理、切换展开、展开路径(自动展开父级)等功能\r\n * 用于 PropertyPanel 和 TreeItem 组件之间共享展开状态\r\n */\r\n\r\nimport { ref, watch, type Ref } from \"vue\";\r\nimport type { Object3D } from \"three\";\r\n\r\n/**\r\n * @param selectedObject - 响应式的当前选中物体(Ref)\r\n * @returns 包含展开集合和切换方法的对象\r\n */\r\nexport function useTreeExpand(selectedObject: Ref<Object3D | null>) {\r\n /** 存储所有展开节点的 uuid 的 Set(响应式) */\r\n const expandedSet = ref<Set<string>>(new Set());\r\n\r\n /**\r\n * 切换某个节点的展开/收起状态\r\n * @param uuid - 节点的唯一标识符\r\n */\r\n const toggleExpand = (uuid: string) => {\r\n const newSet = new Set(expandedSet.value);\r\n if (newSet.has(uuid)) newSet.delete(uuid);\r\n else newSet.add(uuid);\r\n expandedSet.value = newSet;\r\n };\r\n\r\n /**\r\n * 展开从目标节点到根节点的所有父级节点(不展开目标节点自身)\r\n * 用于点击场景物体后自动展开树形路径\r\n * @param target - 目标物体\r\n */\r\n const expandPath = (target: Object3D) => {\r\n if (!target) return;\r\n const newSet = new Set(expandedSet.value);\r\n let current = target.parent;\r\n // 逐级向上遍历,直到遇到场景根节点\r\n while (current && current.type !== \"Scene\") {\r\n newSet.add(current.uuid);\r\n current = current.parent;\r\n }\r\n expandedSet.value = newSet;\r\n };\r\n\r\n // 监听选中物体的变化,当选中新物体时自动展开其路径\r\n watch(\r\n selectedObject,\r\n (obj) => {\r\n if (obj) expandPath(obj);\r\n },\r\n { immediate: true },\r\n );\r\n\r\n return { expandedSet, toggleExpand };\r\n}\r\n","<template>\r\n <div class=\"property-panel\" v-if=\"transform\">\r\n <h3>属性面板</h3>\r\n\r\n <!-- 场景物体树 -->\r\n <div class=\"property-group tree-group\">\r\n <label>场景物体</label>\r\n <div class=\"tree-container\">\r\n <TreeItem\r\n v-for=\"obj in treeData\"\r\n :key=\"obj.uuid\"\r\n :node=\"obj\"\r\n :selected-object=\"selectedObject\"\r\n :version=\"treeVersion\"\r\n @select=\"emit('treeSelect', $event)\"\r\n @delete=\"handleTreeDelete\"\r\n />\r\n <div v-if=\"treeData.length === 0\" class=\"tree-empty\">暂无物体</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"property-group\">\r\n <label>全局属性</label>\r\n <div class=\"row\"></div>\r\n </div>\r\n\r\n <!-- Tab 切换(仅控制变换属性) -->\r\n <div class=\"tabs\" v-if=\"selectedObject\">\r\n <button\r\n class=\"tab-btn\"\r\n :class=\"{ active: activeTab === 'transform' }\"\r\n @click=\"activeTab = 'transform'\"\r\n >\r\n 🔄 变换\r\n </button>\r\n <button\r\n class=\"tab-btn\"\r\n :class=\"{ active: activeTab === 'info' }\"\r\n @click=\"activeTab = 'info'\"\r\n >\r\n ℹ️ 信息\r\n </button>\r\n </div>\r\n\r\n <!-- Tab 内容 -->\r\n <div class=\"tab-content\" v-if=\"selectedObject\">\r\n <!-- 变换 Tab -->\r\n <div v-show=\"activeTab === 'transform'\">\r\n <!-- 位置 -->\r\n <div class=\"property-group\">\r\n <label>位置</label>\r\n <div class=\"row\">\r\n <span>X:</span>\r\n <input\r\n type=\"number\"\r\n v-model.number=\"transform.position.x\"\r\n step=\"0.01\"\r\n @input=\"emitChange\"\r\n />\r\n <span>Y:</span>\r\n <input\r\n type=\"number\"\r\n v-model.number=\"transform.position.y\"\r\n step=\"0.01\"\r\n @input=\"emitChange\"\r\n />\r\n <span>Z:</span>\r\n <input\r\n type=\"number\"\r\n v-model.number=\"transform.position.z\"\r\n step=\"0.01\"\r\n @input=\"emitChange\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- 旋转 (弧度) -->\r\n <div class=\"property-group\">\r\n <label>旋转 (弧度)</label>\r\n <div class=\"row\">\r\n <span>X:</span>\r\n <input\r\n type=\"number\"\r\n v-model.number=\"transform.rotation.x\"\r\n step=\"0.01\"\r\n @input=\"emitChange\"\r\n />\r\n <span>Y:</span>\r\n <input\r\n type=\"number\"\r\n v-model.number=\"transform.rotation.y\"\r\n step=\"0.01\"\r\n @input=\"emitChange\"\r\n />\r\n <span>Z:</span>\r\n <input\r\n type=\"number\"\r\n v-model.number=\"transform.rotation.z\"\r\n step=\"0.01\"\r\n @input=\"emitChange\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- 缩放 -->\r\n <div class=\"property-group\">\r\n <label>缩放</label>\r\n <div class=\"row\">\r\n <span>X:</span>\r\n <input\r\n type=\"number\"\r\n v-model.number=\"transform.scale.x\"\r\n step=\"0.01\"\r\n @input=\"emitChange\"\r\n />\r\n <span>Y:</span>\r\n <input\r\n type=\"number\"\r\n v-model.number=\"transform.scale.y\"\r\n step=\"0.01\"\r\n @input=\"emitChange\"\r\n />\r\n <span>Z:</span>\r\n <input\r\n type=\"number\"\r\n v-model.number=\"transform.scale.z\"\r\n step=\"0.01\"\r\n @input=\"emitChange\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- ─── 材质属性 ─── -->\r\n <div class=\"property-group material-group\" v-if=\"selectedObject\">\r\n <label>材质</label>\r\n <div class=\"slider-row\">\r\n <span class=\"slider-label\">金属度</span>\r\n <input\r\n type=\"range\"\r\n min=\"0\"\r\n max=\"1\"\r\n step=\"0.01\"\r\n v-model.number=\"materialProps.metalness\"\r\n @input=\"onMaterialChange\"\r\n />\r\n <span class=\"slider-value\">{{\r\n materialProps.metalness.toFixed(2)\r\n }}</span>\r\n </div>\r\n <div class=\"slider-row\">\r\n <span class=\"slider-label\">粗糙度</span>\r\n <input\r\n type=\"range\"\r\n min=\"0\"\r\n max=\"1\"\r\n step=\"0.01\"\r\n v-model.number=\"materialProps.roughness\"\r\n @input=\"onMaterialChange\"\r\n />\r\n <span class=\"slider-value\">{{\r\n materialProps.roughness.toFixed(2)\r\n }}</span>\r\n </div>\r\n <div class=\"slider-row\">\r\n <span class=\"slider-label\">透明度</span>\r\n <input\r\n type=\"range\"\r\n min=\"0\"\r\n max=\"1\"\r\n step=\"0.01\"\r\n v-model.number=\"materialProps.opacity\"\r\n @input=\"onMaterialChange\"\r\n />\r\n <span class=\"slider-value\">{{\r\n materialProps.opacity.toFixed(2)\r\n }}</span>\r\n </div>\r\n <div class=\"material-hint\" v-if=\"!hasStandardMaterial\">\r\n ⚠️ 当前材质不支持金属度/粗糙度(仅支持 Standard/Phong)\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"property-panel empty\" v-else>\r\n <p>未选中任何模型</p>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\n/**\r\n * 属性面板组件\r\n * 显示当前选中物体的变换参数,并提供树形场景物体列表\r\n * 使用 provide 向子组件提供树形展开状态管理\r\n */\r\n\r\nimport type { Object3D, Mesh } from \"three\";\r\nimport TreeItem from \"./TreeItem.vue\";\r\nimport { ref, provide, toRef, watch, reactive } from \"vue\";\r\nimport { useTreeExpand } from \"../composables/useTreeExpand\";\r\n\r\nconst props = defineProps<{\r\n /** 变换数据对象,包含 position, rotation, scale */\r\n transform: {\r\n position: { x: number; y: number; z: number };\r\n rotation: { x: number; y: number; z: number };\r\n scale: { x: number; y: number; z: number };\r\n } | null;\r\n /** 顶层物体列表 */\r\n treeData: Object3D[];\r\n /** 当前选中的物体 */\r\n selectedObject: Object3D | null;\r\n}>();\r\n\r\nconst emit = defineEmits<{\r\n (e: \"propertyChange\"): void; // 变换数据变化\r\n (e: \"treeSelect\", obj: Object3D): void; // 树形选中节点\r\n (e: \"treeDelete\", obj: Object3D): void; // 树形删除节点\r\n}>();\r\n\r\n/** 触发变换变更事件(输入框 input 事件) */\r\nconst emitChange = () => emit(\"propertyChange\");\r\n\r\n// ─── Tab 状态 ───\r\nconst activeTab = ref<\"transform\" | \"info\">(\"transform\");\r\n\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n//#region 树形组件\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n\r\n// ─── 树形版本号 ───\r\n/**\r\n * 版本号用于强制刷新 TreeItem 的子节点列表(在删除节点后增加)\r\n * 因为子节点列表依赖 version 来重新计算\r\n */\r\nconst treeVersion = ref(0);\r\n\r\n// ─── 树形展开状态管理 ───\r\n/**\r\n * 使用组合式函数管理展开集合,并提供给子组件\r\n * 将 selectedObject prop 转换为 Ref,以便 useTreeExpand 监听变化\r\n */\r\nconst selectedObjectRef = toRef(props, \"selectedObject\");\r\nconst { expandedSet, toggleExpand } = useTreeExpand(selectedObjectRef);\r\n\r\n// 向子组件提供展开状态\r\nprovide(\"treeExpand\", { expandedSet, toggleExpand });\r\n\r\n// ─── 自定义删除处理 ───\r\n/**\r\n * 删除节点时递增版本号,使所有 TreeItem 重新计算 childNodes\r\n */\r\nconst handleTreeDelete = (obj: Object3D) => {\r\n treeVersion.value++;\r\n emit(\"treeDelete\", obj);\r\n};\r\n//#endregion\r\n\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n//#region 材质属性管理\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n/**\r\n * 材质属性数据(与滑块双向绑定)\r\n */\r\nconst materialProps = reactive({\r\n metalness: 0,\r\n roughness: 0.5,\r\n opacity: 1,\r\n});\r\n\r\n/** 是否包含支持 PBR 的材质 */\r\nconst hasStandardMaterial = ref(false);\r\n\r\n/**\r\n * 读取选中物体的材质属性(取第一个 Mesh 的材质作为代表)\r\n */\r\nfunction readMaterialFromObject(\r\n obj: Object3D,\r\n): { metalness: number; roughness: number; opacity: number } | null {\r\n let result: { metalness: number; roughness: number; opacity: number } | null =\r\n null;\r\n obj.traverse((child) => {\r\n if (child.type === \"Mesh\" && !result) {\r\n const mesh = child as Mesh;\r\n const materials = Array.isArray(mesh.material)\r\n ? mesh.material\r\n : [mesh.material];\r\n for (const mat of materials) {\r\n // 支持 MeshStandardMaterial 和 MeshPhongMaterial\r\n if (\r\n mat &&\r\n (mat.type === \"MeshStandardMaterial\" ||\r\n mat.type === \"MeshPhongMaterial\")\r\n ) {\r\n const stdMat = mat as any;\r\n result = {\r\n metalness: stdMat.metalness ?? 0,\r\n roughness: stdMat.roughness ?? 0.5,\r\n opacity: mat.opacity ?? 1,\r\n };\r\n break;\r\n }\r\n }\r\n }\r\n });\r\n return result;\r\n}\r\n\r\n/**\r\n * 应用材质属性到选中物体的所有 Mesh\r\n */\r\nfunction applyMaterialToObject(\r\n obj: Object3D,\r\n props: { metalness?: number; roughness?: number; opacity?: number },\r\n) {\r\n let applied = false;\r\n obj.traverse((child) => {\r\n if (child.type === \"Mesh\") {\r\n const mesh = child as Mesh;\r\n const materials = Array.isArray(mesh.material)\r\n ? mesh.material\r\n : [mesh.material];\r\n for (const mat of materials) {\r\n if (\r\n mat &&\r\n (mat.type === \"MeshStandardMaterial\" ||\r\n mat.type === \"MeshPhongMaterial\")\r\n ) {\r\n if (props.metalness !== undefined)\r\n (mat as any).metalness = props.metalness;\r\n if (props.roughness !== undefined)\r\n (mat as any).roughness = props.roughness;\r\n if (props.opacity !== undefined) {\r\n mat.opacity = props.opacity;\r\n mat.transparent = props.opacity < 1;\r\n }\r\n mat.needsUpdate = true;\r\n applied = true;\r\n }\r\n }\r\n }\r\n });\r\n return applied;\r\n}\r\n\r\n/**\r\n * 当滑块变化时应用到物体\r\n */\r\nfunction onMaterialChange() {\r\n if (props.selectedObject) {\r\n const applied = applyMaterialToObject(props.selectedObject, {\r\n metalness: materialProps.metalness,\r\n roughness: materialProps.roughness,\r\n opacity: materialProps.opacity,\r\n });\r\n hasStandardMaterial.value = applied;\r\n }\r\n}\r\n\r\n/**\r\n * 监听选中物体变化,更新滑块值和材质支持状态\r\n */\r\nwatch(\r\n () => props.selectedObject,\r\n (newObj) => {\r\n if (newObj) {\r\n const read = readMaterialFromObject(newObj);\r\n if (read) {\r\n materialProps.metalness = read.metalness;\r\n materialProps.roughness = read.roughness;\r\n materialProps.opacity = read.opacity;\r\n hasStandardMaterial.value = true;\r\n } else {\r\n // 没有材质或材质不支持,设为默认值并标记不支持\r\n materialProps.metalness = 0;\r\n materialProps.roughness = 0.5;\r\n materialProps.opacity = 1;\r\n hasStandardMaterial.value = false;\r\n }\r\n } else {\r\n // 取消选中时重置\r\n materialProps.metalness = 0;\r\n materialProps.roughness = 0.5;\r\n materialProps.opacity = 1;\r\n hasStandardMaterial.value = false;\r\n }\r\n },\r\n { immediate: true },\r\n);\r\n//#endregion\r\n</script>\r\n\r\n<style lang=\"less\" scoped>\r\n// ─── Tabs ───\r\n.tabs {\r\n display: flex;\r\n gap: 0;\r\n border-bottom: 2px solid #1a2a36;\r\n margin-bottom: 16px;\r\n\r\n .tab-btn {\r\n flex: 1;\r\n padding: 8px 12px;\r\n background: transparent;\r\n border: none;\r\n color: #95a5a6;\r\n font-size: 13px;\r\n cursor: pointer;\r\n transition:\r\n color 0.2s,\r\n border-bottom 0.2s;\r\n border-bottom: 2px solid transparent;\r\n margin-bottom: -2px;\r\n\r\n &:hover {\r\n color: #ecf0f1;\r\n }\r\n\r\n &.active {\r\n color: #f1c40f;\r\n border-bottom-color: #f1c40f;\r\n }\r\n }\r\n}\r\n\r\n.property-panel {\r\n width: 320px;\r\n height: 100%;\r\n background: #2c3e50;\r\n color: #ecf0f1;\r\n padding: 16px;\r\n box-sizing: border-box;\r\n border-left: 1px solid #1a2a36;\r\n overflow-y: auto;\r\n font-size: 14px;\r\n h3 {\r\n margin-top: 0;\r\n text-align: center;\r\n }\r\n\r\n .property-group {\r\n margin-bottom: 20px;\r\n border-bottom: 1px solid #1a2a36;\r\n padding-bottom: 12px;\r\n label {\r\n font-weight: bold;\r\n display: block;\r\n margin-bottom: 8px;\r\n color: #f1c40f;\r\n }\r\n .row {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n margin-bottom: 6px;\r\n span {\r\n width: 20px;\r\n text-align: right;\r\n }\r\n input {\r\n background: #1e2a36;\r\n border: 1px solid #3e5a6b;\r\n color: #ecf0f1;\r\n padding: 4px 8px;\r\n border-radius: 4px;\r\n width: 48px;\r\n }\r\n }\r\n }\r\n\r\n .tab-content {\r\n // ─── 材质滑块 ───\r\n .material-group {\r\n .slider-row {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n margin-bottom: 6px;\r\n\r\n .slider-label {\r\n width: 50px;\r\n font-size: 12px;\r\n color: #95a5a6;\r\n }\r\n\r\n input[type=\"range\"] {\r\n flex: 1;\r\n height: 4px;\r\n -webkit-appearance: none;\r\n background: #1e2a36;\r\n border-radius: 2px;\r\n outline: none;\r\n\r\n &::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n width: 12px;\r\n height: 12px;\r\n border-radius: 50%;\r\n background: #f1c40f;\r\n cursor: pointer;\r\n }\r\n }\r\n\r\n .slider-value {\r\n width: 36px;\r\n font-size: 12px;\r\n text-align: center;\r\n color: #ecf0f1;\r\n }\r\n }\r\n\r\n .material-hint {\r\n margin-top: 6px;\r\n font-size: 12px;\r\n color: #e67e22;\r\n }\r\n }\r\n }\r\n}\r\n.empty {\r\n text-align: center;\r\n color: #95a5a6;\r\n}\r\n.tree-group {\r\n margin-top: 10px;\r\n .tree-container {\r\n max-height: 200px;\r\n overflow-y: auto;\r\n background: #1a2a36;\r\n border-radius: 4px;\r\n padding: 4px 0;\r\n }\r\n}\r\n.tree-empty {\r\n padding: 8px 10px;\r\n color: #95a5a6;\r\n font-style: italic;\r\n}\r\n</style>\r\n","<template>\r\n <div class=\"top-bar\">\r\n <div class=\"left-section\">\r\n <!-- 文件菜单 -->\r\n <div\r\n class=\"dropdown-wrapper\"\r\n @mouseenter=\"showFileMenu = true\"\r\n @mouseleave=\"showFileMenu = false\"\r\n >\r\n <button class=\"menu-btn\">文件</button>\r\n <div class=\"dropdown-menu\" v-show=\"showFileMenu\">\r\n <div class=\"menu-item\" @click=\"handleNew\">新建</div>\r\n <div\r\n class=\"menu-item dropdown-wrapper sub-trigger\"\r\n @mouseenter=\"showOpenSub = true\"\r\n @mouseleave=\"showOpenSub = false\"\r\n >\r\n <span>打开</span>\r\n <div class=\"dropdown-menu sub-menu\" v-show=\"showOpenSub\">\r\n <div class=\"menu-item\" @click=\"handleOpenProject\">打开项目</div>\r\n <div class=\"menu-item\" @click=\"handleOpenModel\">打开模型</div>\r\n <div class=\"menu-item\" @click=\"handleOpenScene\">打开场景</div>\r\n </div>\r\n </div>\r\n <div class=\"menu-item\" @click=\"handleSave\">保存</div>\r\n <div class=\"menu-item\" @click=\"handleExport\">导出</div>\r\n </div>\r\n </div>\r\n\r\n <!-- 添加菜单 -->\r\n <div\r\n class=\"dropdown-wrapper\"\r\n @mouseenter=\"showAddMenu = true\"\r\n @mouseleave=\"showAddMenu = false\"\r\n >\r\n <button class=\"menu-btn\">添加</button>\r\n <div class=\"dropdown-menu\" v-show=\"showAddMenu\">\r\n <div class=\"menu-item\" @click=\"handleUndo\">组</div>\r\n <div\r\n class=\"menu-item dropdown-wrapper sub-trigger\"\r\n @mouseenter=\"showOpenGrid = true\"\r\n @mouseleave=\"showOpenGrid = false\"\r\n >\r\n <span>网格</span>\r\n <div class=\"dropdown-menu sub-menu\" v-show=\"showOpenGrid\">\r\n <div class=\"menu-item\" @click=\"emit('addModel', 'box')\">\r\n 正方体\r\n </div>\r\n <div class=\"menu-item\" @click=\"emit('addModel', 'sphere')\">\r\n 球体\r\n </div>\r\n <div class=\"menu-item\" @click=\"triggerImport\">导入</div>\r\n </div>\r\n </div>\r\n <div class=\"menu-item\" @click=\"handleDuplicate\">光源</div>\r\n <div class=\"menu-item\" @click=\"handleDelete\">摄像机</div>\r\n </div>\r\n </div>\r\n\r\n <!-- 编辑菜单 -->\r\n <div\r\n class=\"dropdown-wrapper\"\r\n @mouseenter=\"showEditMenu = true\"\r\n @mouseleave=\"showEditMenu = false\"\r\n >\r\n <button class=\"menu-btn\">编辑</button>\r\n <div class=\"dropdown-menu\" v-show=\"showEditMenu\">\r\n <div class=\"menu-item\" @click=\"handleUndo\">撤销</div>\r\n <div class=\"menu-item\" @click=\"handleRedo\">重做</div>\r\n <div class=\"menu-item\" @click=\"handleDuplicate\">复制</div>\r\n <div class=\"menu-item\" @click=\"handleDelete\">删除</div>\r\n </div>\r\n </div>\r\n\r\n <!-- 视图菜单 -->\r\n <div\r\n class=\"dropdown-wrapper\"\r\n @mouseenter=\"showViewMenu = true\"\r\n @mouseleave=\"showViewMenu = false\"\r\n >\r\n <button class=\"menu-btn\">视图</button>\r\n <div class=\"dropdown-menu\" v-show=\"showViewMenu\">\r\n <div class=\"menu-item\" @click=\"handleResetCamera\">重置相机</div>\r\n <div class=\"menu-item\" @click=\"handleToggleGrid\">显示网格</div>\r\n </div>\r\n </div>\r\n\r\n <!-- 帮助菜单 -->\r\n <div\r\n class=\"dropdown-wrapper\"\r\n @mouseenter=\"showHelpMenu = true\"\r\n @mouseleave=\"showHelpMenu = false\"\r\n >\r\n <button class=\"menu-btn\">帮助</button>\r\n <div class=\"dropdown-menu\" v-show=\"showHelpMenu\">\r\n <div class=\"menu-item\" @click=\"handleHelp\">使用帮助</div>\r\n <div class=\"menu-item\" @click=\"handleAbout\">关于</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"right-section\">\r\n <span class=\"app-title\">3D 模型编辑器</span>\r\n </div>\r\n\r\n <!-- 隐藏的文件输入框,用于导入模型 -->\r\n <input\r\n type=\"file\"\r\n ref=\"fileInput\"\r\n accept=\".obj,.gltf,.glb\"\r\n style=\"display: none\"\r\n @change=\"onFileSelected\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\n/**\r\n * 顶部菜单栏组件\r\n * 包含文件、添加、编辑、视图、帮助等下拉菜单\r\n * 通过 emit 向父组件传递添加模型和导入模型事件\r\n */\r\n\r\nimport { ref } from \"vue\";\r\n\r\n// 各菜单显示状态\r\nconst showFileMenu = ref(false);\r\nconst showEditMenu = ref(false);\r\nconst showViewMenu = ref(false);\r\nconst showHelpMenu = ref(false);\r\nconst showAddMenu = ref(false);\r\nconst showOpenSub = ref(false); // 文件→打开子菜单\r\nconst showOpenGrid = ref(false); // 添加→网格子菜单\r\n\r\nconst emit = defineEmits<{\r\n (e: \"addModel\", type: string): void;\r\n (e: \"importModel\", file: File): void;\r\n}>();\r\n\r\n// ─── 文件输入 ───\r\nconst fileInput = ref<HTMLInputElement | null>(null);\r\n\r\n/** 触发文件选择对话框 */\r\nconst triggerImport = () => fileInput.value?.click();\r\n\r\n/** 文件选择后,向上传递文件对象,并重置 input 以便重复选择同一文件 */\r\nconst onFileSelected = (event: Event) => {\r\n const input = event.target as HTMLInputElement;\r\n if (input.files && input.files.length > 0) {\r\n emit(\"importModel\", input.files[0]);\r\n input.value = \"\";\r\n }\r\n};\r\n\r\n// ─── 各菜单项的占位处理(后续可扩展功能) ───\r\nconst handleNew = () => console.log(\"新建项目\");\r\nconst handleSave = () => console.log(\"保存场景\");\r\nconst handleExport = () => console.log(\"导出模型\");\r\nconst handleUndo = () => console.log(\"撤销\");\r\nconst handleRedo = () => console.log(\"重做\");\r\nconst handleDuplicate = () => console.log(\"复制物体\");\r\nconst handleDelete = () => console.log(\"删除物体\");\r\nconst handleResetCamera = () => console.log(\"重置相机\");\r\nconst handleToggleGrid = () => console.log(\"切换网格\");\r\nconst handleHelp = () => console.log(\"打开帮助\");\r\nconst handleAbout = () => console.log(\"关于编辑器\");\r\nconst handleOpenProject = () => console.log(\"打开项目\");\r\nconst handleOpenModel = () => console.log(\"打开模型\");\r\nconst handleOpenScene = () => console.log(\"打开场景\");\r\n</script>\r\n\r\n<style lang=\"less\" scoped>\r\n.top-bar {\r\n height: 40px;\r\n background: #1a2a36;\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 0 16px;\r\n border-bottom: 1px solid #2a4050;\r\n flex-shrink: 0;\r\n user-select: none;\r\n\r\n .left-section {\r\n display: flex;\r\n gap: 12px;\r\n align-items: center;\r\n\r\n .dropdown-wrapper {\r\n position: relative;\r\n display: inline-block;\r\n\r\n .menu-btn {\r\n background: transparent;\r\n border: none;\r\n color: #ecf0f1;\r\n padding: 6px 12px;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font-size: 14px;\r\n transition: background 0.2s;\r\n &:hover {\r\n background: #2a4050;\r\n }\r\n }\r\n\r\n .dropdown-menu {\r\n position: absolute;\r\n top: 100%;\r\n left: 0;\r\n background: #2c3e50;\r\n border: 1px solid #3e5a6b;\r\n border-radius: 4px;\r\n min-width: 140px;\r\n padding: 4px 0;\r\n z-index: 100;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\r\n\r\n .menu-item {\r\n padding: 6px 16px;\r\n color: #ecf0f1;\r\n cursor: pointer;\r\n font-size: 13px;\r\n transition: background 0.15s;\r\n white-space: nowrap;\r\n &:hover {\r\n background: #3e5a6b;\r\n }\r\n }\r\n .menu-item.sub-trigger {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n position: relative;\r\n }\r\n }\r\n .sub-menu {\r\n position: absolute;\r\n left: 100%;\r\n top: 0;\r\n background: #2c3e50;\r\n border: 1px solid #3e5a6b;\r\n border-radius: 4px;\r\n min-width: 140px;\r\n padding: 4px 0;\r\n z-index: 101;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\r\n }\r\n }\r\n }\r\n\r\n .right-section {\r\n display: flex;\r\n align-items: center;\r\n }\r\n .app-title {\r\n color: #88aaff;\r\n font-size: 16px;\r\n font-weight: 500;\r\n letter-spacing: 0.5px;\r\n }\r\n}\r\n</style>\r\n","<template>\r\n <div class=\"bottom-bar\">\r\n <div class=\"status-left\">\r\n <span>就绪</span>\r\n </div>\r\n <div class=\"status-right\">\r\n <span>顶点: 0 | 面: 0</span>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\n/**\r\n * 底部状态栏\r\n * 目前仅显示“就绪”和占位统计信息\r\n * 未来可扩展显示顶点/面数、坐标等\r\n */\r\n</script>\r\n\r\n<style lang=\"less\" scoped>\r\n.bottom-bar {\r\n height: 40px;\r\n background: #1a2a36;\r\n border-top: 1px solid #2a4050;\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 0 16px;\r\n flex-shrink: 0;\r\n color: #95a5a6;\r\n font-size: 13px;\r\n user-select: none;\r\n .status-left,\r\n .status-right {\r\n display: flex;\r\n gap: 16px;\r\n }\r\n}\r\n</style>\r\n","<template>\r\n <div class=\"app-layout\">\r\n <!-- 顶部菜单栏 -->\r\n <TopBar\r\n @add-model=\"handleAddModel\"\r\n @import-model=\"handleImportModel\"\r\n v-if=\"mode === 'edit'\"\r\n />\r\n <div :class=\"`editor-container editor-container-mode-${mode}`\">\r\n <!-- Three.js 画布 -->\r\n <div :class=\"`canvas canvas-mode-${mode}`\" ref=\"containerRef\"></div>\r\n <!-- 属性面板 -->\r\n <PropertyPanel\r\n :transform=\"transform\"\r\n :tree-data=\"treeData\"\r\n :selected-object=\"selectedModel\"\r\n @property-change=\"handlePropertyChange\"\r\n @tree-select=\"handleTreeSelect\"\r\n @tree-delete=\"handleTreeDelete\"\r\n v-if=\"mode === 'edit'\"\r\n />\r\n </div>\r\n <!-- 底部状态栏 -->\r\n <BottomBar v-if=\"mode === 'edit'\" />\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\n/**\r\n * 编辑器主组件,负责:\r\n * - 挂载 Three.js 编辑器\r\n * - 管理选中物体的变换数据(位置/旋转/缩放)\r\n * - 同步场景物体树形数据\r\n * - 处理添加模型、导入模型、树形选中/删除等交互\r\n */\r\n\r\nimport { onMounted, reactive, ref, shallowRef } from \"vue\";\r\nimport {\r\n initEditor,\r\n setSelectedObjectCallback,\r\n setTransformChangeCallback,\r\n onSceneObjectsChangeCallback,\r\n getSceneObjects,\r\n removeModelById,\r\n selectObject,\r\n} from \"../three/index\";\r\nimport { addModelByType, importModelFromFile } from \"../three/addHandle\";\r\nimport PropertyPanel from \"./PropertyPanel.vue\";\r\nimport TopBar from \"./TopBar.vue\";\r\nimport BottomBar from \"./BottomBar.vue\";\r\nimport type { Object3D } from \"three\";\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n mode: string;\r\n sceneData: any;\r\n }>(),\r\n {\r\n mode: \"edit\",\r\n sceneData: null,\r\n },\r\n);\r\n\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n//#region 属性面板\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n\r\n/** 当前选中的模型对象 */\r\nconst selectedModel = ref<Object3D | null>(null);\r\n\r\n/**\r\n * 变换数据(位置/旋转/缩放),与属性面板双向绑定\r\n * 使用 reactive 使每个属性独立响应式\r\n */\r\nconst transform = reactive({\r\n position: { x: 0, y: 0, z: 0 },\r\n rotation: { x: 0, y: 0, z: 0 },\r\n scale: { x: 1, y: 1, z: 1 },\r\n});\r\n\r\n// ─── 同步函数 ───\r\n\r\n/**\r\n * 从 Three.js 物体同步变换数据到 transform 对象\r\n * 保留三位小数,避免浮点数误差\r\n */\r\nconst syncTransformFromObject = (obj: Object3D) => {\r\n transform.position.x = Number(obj.position.x.toFixed(3));\r\n transform.position.y = Number(obj.position.y.toFixed(3));\r\n transform.position.z = Number(obj.position.z.toFixed(3));\r\n transform.rotation.x = Number(obj.rotation.x.toFixed(3));\r\n transform.rotation.y = Number(obj.rotation.y.toFixed(3));\r\n transform.rotation.z = Number(obj.rotation.z.toFixed(3));\r\n transform.scale.x = Number(obj.scale.x.toFixed(3));\r\n transform.scale.y = Number(obj.scale.y.toFixed(3));\r\n transform.scale.z = Number(obj.scale.z.toFixed(3));\r\n};\r\n\r\n/**\r\n * 将 transform 数据应用到 Three.js 物体\r\n * 用于属性面板输入变化时更新物体\r\n */\r\nconst applyTransformToObject = (obj: Object3D) => {\r\n obj.position.set(\r\n transform.position.x,\r\n transform.position.y,\r\n transform.position.z,\r\n );\r\n obj.rotation.set(\r\n transform.rotation.x,\r\n transform.rotation.y,\r\n transform.rotation.z,\r\n );\r\n obj.scale.set(transform.scale.x, transform.scale.y, transform.scale.z);\r\n};\r\n\r\n// ─── 注册回调 ───\r\n\r\n// 选中物体变化时同步到本地状态\r\nsetSelectedObjectCallback((obj) => {\r\n selectedModel.value = obj;\r\n if (obj) syncTransformFromObject(obj);\r\n});\r\n\r\n// 变换过程中(拖拽)实时更新面板\r\nsetTransformChangeCallback((obj) => {\r\n syncTransformFromObject(obj);\r\n});\r\n\r\n// ─── 事件处理 ───\r\n\r\n/** 属性面板数值变化时,应用变换到物体 */\r\nconst handlePropertyChange = () => {\r\n if (selectedModel.value) applyTransformToObject(selectedModel.value);\r\n};\r\n\r\n/** 添加模型(来自顶部菜单) */\r\nconst handleAddModel = (type: string) => addModelByType(type);\r\n\r\n/** 导入模型(来自顶部菜单) */\r\nconst handleImportModel = async (file: File) => {\r\n try {\r\n await importModelFromFile(file);\r\n } catch (error) {\r\n console.error(\"导入失败:\", error);\r\n alert(\"导入失败:\" + (error as Error).message);\r\n }\r\n};\r\n//#endregion\r\n\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n//#region 树形面板\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n\r\n/** 树形数据使用 shallowRef 避免深度响应式,提高性能 */\r\nconst treeData = shallowRef<Object3D[]>([]);\r\n\r\n// 注册树形数据变化回调\r\nonSceneObjectsChangeCallback((objects) => {\r\n treeData.value = objects;\r\n});\r\n\r\n/** 初始化树形数据 */\r\nconst initTree = () => {\r\n const objects = getSceneObjects();\r\n if (objects) treeData.value = objects;\r\n};\r\n\r\n/** 树形选中节点 → 同步选中场景物体 */\r\nconst handleTreeSelect = (obj: Object3D) => selectObject(obj);\r\n\r\n/** 树形删除节点 → 删除场景物体 */\r\nconst handleTreeDelete = (obj: Object3D) => removeModelById(obj.uuid);\r\n//#endregion\r\n\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n//#region 初始化\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n\r\nconst containerRef = ref<HTMLElement | null>(null);\r\n/** 挂载 Three.js 编辑器并初始化树 */\r\nconst init = () => {\r\n if (containerRef.value)\r\n initEditor(containerRef.value, props.mode, props.sceneData);\r\n // const dom = document.getElementById(\"sl_canvas\");\r\n // if (dom) initEditor(dom);\r\n initTree();\r\n};\r\n\r\nonMounted(init);\r\n//#endregion\r\n</script>\r\n\r\n<style lang=\"less\" scoped>\r\n/* 整体布局:纵向排列,编辑器区域占剩余高度 */\r\n.app-layout {\r\n display: flex;\r\n flex-direction: column;\r\n height: 100%;\r\n width: 100%;\r\n}\r\n.editor-container {\r\n display: flex;\r\n width: 100%;\r\n}\r\n.editor-container-mode-edit {\r\n height: calc(100% - 80px); /* 顶部栏 40px + 底部栏 40px */\r\n}\r\n.editor-container-mode-run {\r\n height: 100%; /* 顶部栏 40px + 底部栏 40px */\r\n}\r\n.canvas {\r\n height: 100%;\r\n background-color: #333;\r\n position: relative;\r\n}\r\n.canvas-mode-edit {\r\n width: calc(100% - 320px); /* 属性面板宽 320px */\r\n}\r\n.canvas-mode-run {\r\n width: 100%; /* 属性面板宽 320px */\r\n}\r\n</style>\r\n"],"names":["_changeEvent","_startEvent","_endEvent","_ray","Ray","_plane","Plane","_TILT_LIMIT","MathUtils","_v","Vector3","_twoPI","_STATE","_EPS","OrbitControls","Controls","object","domElement","MOUSE","TOUCH","Quaternion","Spherical","Vector2","onPointerMove","onPointerDown","onPointerUp","onContextMenu","onMouseWheel","onKeyDown","onTouchStart","onTouchMove","onMouseDown","onMouseMove","interceptControlDown","interceptControlUp","type","element","deltaX","deltaY","dollyScale","angle","deltaTime","position","min","max","zoomChanged","prevRadius","newRadius","radiusDelta","mouseBefore","prevZoom","mouseAfter","delta","normalizedDelta","distance","objectMatrix","targetDistance","x","y","rect","dx","dy","w","h","dist","event","needsUpdate","centerX","centerY","i","pointerId","mode","newEvent","mouseAction","_raycaster","Raycaster","_tempVector","_tempVector2","_tempQuaternion","_unit","_mouseDownEvent","_mouseUpEvent","_objectChangeEvent","TransformControls","camera","root","TransformControlsRoot","gizmo","TransformControlsGizmo","plane","TransformControlsPlane","scope","defineProperty","propName","defaultValue","propValue","value","worldPosition","worldPositionStart","worldQuaternion","worldQuaternionStart","cameraPosition","cameraQuaternion","pointStart","pointEnd","rotationAxis","rotationAngle","eye","getPointer","onPointerHover","pointer","intersect","intersectObjectWithRay","planeIntersect","axis","space","d","ROTATION_SPEED","_inPlaneRotation","translationSnap","rotationSnap","scaleSnap","size","xAxis","yAxis","zAxis","active","materialLib","raycaster","includeInvisible","allIntersections","_tempEuler","Euler","_alignVector","_zeroVector","_lookAtMatrix","Matrix4","_tempQuaternion2","_identityQuaternion","_dirVector","_tempMatrix","_unitX","_unitY","_unitZ","_v1","_v2","_v3","Object3D","controls","force","child","gizmoMaterial","MeshBasicMaterial","gizmoLineMaterial","LineBasicMaterial","matInvisible","matHelper","matRed","matGreen","matBlue","matRedTransparent","matGreenTransparent","matBlueTransparent","matWhiteTransparent","matYellowTransparent","matYellow","matGray","arrowGeometry","CylinderGeometry","scaleHandleGeometry","BoxGeometry","lineGeometry","BufferGeometry","Float32BufferAttribute","lineGeometry2","CircleGeometry","radius","arc","geometry","TorusGeometry","TranslateHelperGeometry","gizmoTranslate","Mesh","OctahedronGeometry","pickerTranslate","helperTranslate","Line","gizmoRotate","helperRotate","pickerRotate","SphereGeometry","gizmoScale","pickerScale","helperScale","setupGizmo","gizmoMap","name","rotation","scale","tag","tempGeometry","quaternion","handles","handle","factor","a","PlaneGeometry","DoubleSide","state","orbitChanged","skipNextClick","onSelectedChange","onTransformChange","onSceneObjectsChange","sceneObjects","cameraTarget","initEditor","container","sceneData","initRenderer","initScene","initCamera","loadSceneFromJSON","camData","initTransformControls","initOrbitControls","refreshSceneObjects","animate","onMouseClick","onResize","addDefaultLightAndCube","initGrid","renderer","THREE","grid","aspect","ambient","dirLight","TWEEN","_a","_b","width","height","selectObject","obj","deselectObject","mouse","clickables","intersects","addModel","model","selected","addObjectToTree","notifyChange","removeModel","removeObjectFromTree","removeModelById","uuid","idx","list","setSelectedObjectCallback","cb","setTransformChangeCallback","onSceneObjectsChangeCallback","getSceneObjects","getScene","getCamera","getRenderer","exportSceneToJSON","scene","exportScene","sceneJson","cameraJson","_c","json","data","loaded","_object_pattern","_material_library_pattern","_material_use_pattern","_map_use_pattern","_face_vertex_data_separator_pattern","_vA","_vB","_vC","_ab","_cb","_color","Color","ParserState","fromDeclaration","previousMaterial","libraries","previous","material","index","cloned","end","lastMultiMaterial","mi","declared","len","b","c","src","dst","ua","ub","uc","na","nb","nc","vLen","ia","ib","ic","nLen","uvLen","vertices","vi","l","uvs","uvi","OBJLoader","Loader","manager","url","onLoad","onProgress","onError","loader","FileLoader","text","e","materials","lines","result","line","lineFirstChar","SRGBColorSpace","vertexData","faceVertices","j","jl","vertex","vertexParts","v1","v2","v3","lineParts","lineVertices","lineUVs","li","llen","parts","pointData","Group","isLine","isPoints","hasVertexColors","buffergeometry","createdMaterials","miLen","sourceMaterial","materialHash","materialLine","Material","PointsMaterial","materialPoints","MeshPhongMaterial","mesh","LineSegments","Points","points","toTrianglesDrawMode","drawMode","TrianglesDrawMode","TriangleFanDrawMode","TriangleStripDrawMode","indices","numberOfTriangles","newIndices","newGeometry","clone","source","sourceLookup","cloneLookup","parallelTraverse","sourceNode","clonedNode","node","clonedMesh","sourceMesh","sourceBones","bone","callback","GLTFLoader","parser","GLTFMaterialsClearcoatExtension","GLTFMaterialsDispersionExtension","GLTFTextureBasisUExtension","GLTFTextureWebPExtension","GLTFTextureAVIFExtension","GLTFMaterialsSheenExtension","GLTFMaterialsTransmissionExtension","GLTFMaterialsVolumeExtension","GLTFMaterialsIorExtension","GLTFMaterialsEmissiveStrengthExtension","GLTFMaterialsSpecularExtension","GLTFMaterialsIridescenceExtension","GLTFMaterialsAnisotropyExtension","GLTFMaterialsBumpExtension","GLTFLightsExtension","GLTFMeshoptCompression","EXTENSIONS","GLTFMeshGpuInstancing","resourcePath","relativeUrl","LoaderUtils","_onError","gltf","dracoLoader","ktx2Loader","meshoptDecoder","path","extensions","plugins","textDecoder","BINARY_EXTENSION_HEADER_MAGIC","GLTFBinaryExtension","error","GLTFParser","plugin","extensionName","extensionsRequired","GLTFMaterialsUnlitExtension","GLTFDracoMeshCompressionExtension","GLTFTextureTransformExtension","GLTFMeshQuantizationExtension","resolve","reject","GLTFRegistry","objects","key","getMaterialExtension","materialIndex","materialDef","nodeDefs","nodeIndex","nodeLength","nodeDef","lightIndex","cacheKey","dependency","lightDef","lightNode","color","LinearSRGBColorSpace","range","DirectionalLight","PointLight","SpotLight","assignExtrasToUserData","self","light","materialParams","pending","metallicRoughness","array","extension","MeshPhysicalMaterial","colorFactor","colorArray","textureIndex","textureDef","handler","bufferView","extensionDef","buffer","decoder","res","byteOffset","byteLength","count","stride","meshDef","primitive","WEBGL_CONSTANTS","attributesDef","attributes","accessor","results","nodeObject","meshes","instancedMeshes","m","p","q","s","instancedMesh","InstancedMesh","attributeName","attr","InstancedBufferAttribute","BINARY_EXTENSION_HEADER_LENGTH","BINARY_EXTENSION_CHUNK_TYPES","headerView","chunkContentsLength","chunkView","chunkIndex","chunkLength","chunkType","contentArray","bufferViewIndex","gltfAttributeMap","threeAttributeMap","attributeNormalizedMap","attributeTypeMap","threeAttributeName","ATTRIBUTES","accessorDef","componentType","WEBGL_COMPONENT_TYPES","attribute","normalized","texture","transform","GLTFCubicSplineInterpolant","Interpolant","parameterPositions","sampleValues","sampleSize","resultBuffer","values","valueSize","offset","i1","t0","t","t1","stride2","stride3","td","pp","ppp","offset1","offset0","s2","s3","s0","s1","p0","m0","p1","m1","_quaternion","GLTFCubicSplineQuaternionInterpolant","WEBGL_FILTERS","NearestFilter","LinearFilter","NearestMipmapNearestFilter","LinearMipmapNearestFilter","NearestMipmapLinearFilter","LinearMipmapLinearFilter","WEBGL_WRAPPINGS","ClampToEdgeWrapping","MirroredRepeatWrapping","RepeatWrapping","WEBGL_TYPE_SIZES","PATH_PROPERTIES","INTERPOLATION","InterpolateLinear","InterpolateDiscrete","ALPHA_MODES","createDefaultMaterial","cache","MeshStandardMaterial","FrontSide","addUnknownExtensionsToUserData","knownExtensions","objectDef","gltfDef","addMorphTargets","targets","hasMorphPosition","hasMorphNormal","hasMorphColor","il","target","pendingPositionAccessors","pendingNormalAccessors","pendingColorAccessors","pendingAccessor","accessors","morphPositions","morphNormals","morphColors","updateMorphTargets","targetNames","createPrimitiveKey","primitiveDef","geometryKey","dracoExtension","createAttributesKey","attributesKey","keys","getNormalizedComponentScale","constructor","getImageURIMimeType","uri","_identityMatrix","options","isSafari","safariVersion","isFirefox","firefoxVersion","userAgent","safariMatch","TextureLoader","ImageBitmapLoader","ext","dependencies","skinDefs","meshDefs","skinIndex","skinLength","joints","ref","updateMappings","original","mappings","func","defs","def","bufferIndex","bufferDef","bufferViewDef","accessorIndex","itemSize","TypedArray","BufferAttribute","pendingBufferViews","bufferViews","elementBytes","itemBytes","byteStride","bufferAttribute","ibSlice","ibCacheKey","InterleavedBuffer","InterleavedBufferAttribute","itemSizeIndices","TypedArrayIndices","byteOffsetIndices","byteOffsetValues","sparseIndices","sparseValues","sourceIndex","sourceDef","promise","sampler","URL","sourceURI","isObjectURL","blob","imageBitmap","Texture","mapName","mapDef","colorSpace","gltfReference","useDerivativeTangents","useVertexColors","useFlatShading","pointsMaterial","lineMaterial","cachedMaterial","materialType","materialExtensions","kmuExtension","alphaMode","emissiveFactor","originalName","sanitizedName","PropertyBinding","primitives","createDracoPrimitive","addPrimitiveAttributes","cached","geometryPromise","meshIndex","geometries","SkinnedMesh","LineLoop","group","cameraIndex","cameraDef","params","PerspectiveCamera","OrthographicCamera","skinDef","inverseBindMatrices","jointNodes","bones","boneInverses","jointNode","mat","Skeleton","animationIndex","animationDef","animationName","pendingNodes","pendingInputAccessors","pendingOutputAccessors","pendingSamplers","pendingTargets","channel","input","output","nodes","inputAccessors","outputAccessors","samplers","tracks","inputAccessor","outputAccessor","createdTracks","k","animation","AnimationClip","o","nodePending","childPending","childrenDef","skeletonPending","children","skeleton","pivot","pivotChild","nodeName","meshPromise","Bone","matrix","mapping","sceneIndex","sceneDef","nodeIds","reduceAssociations","reducedAssociations","targetName","collectMorphTargets","TypedKeyframeTrack","NumberKeyframeTrack","QuaternionKeyframeTrack","VectorKeyframeTrack","interpolation","outputArray","track","scaled","interpolantType","computeBounds","box","Box3","boxScale","maxDisplacement","vector","sphere","Sphere","assignAttributeAccessor","gltfAttributeName","ColorManagement","addBox","geo","addSphere","importModelFromFile","file","center","err","addModelByType","props","__props","emit","__emit","nodeRef","expandedSet","toggleExpand","inject","isExpanded","computed","hasChildren","childNodes","isSelected","watchEffect","handleSelect","handleDelete","getIcon","getDisplayName","_createElementBlock","_createElementVNode","_normalizeClass","_cache","_withModifiers","$event","_unref","_openBlock","_hoisted_1","_hoisted_2","_toDisplayString","_hoisted_3","_hoisted_4","_Fragment","_renderList","_createBlock","_component_TreeItem","useTreeExpand","selectedObject","newSet","expandPath","current","watch","emitChange","activeTab","treeVersion","selectedObjectRef","toRef","provide","handleTreeDelete","materialProps","reactive","hasStandardMaterial","readMaterialFromObject","stdMat","applyMaterialToObject","applied","onMaterialChange","newObj","read","TreeItem","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","_hoisted_14","_hoisted_15","_hoisted_16","_hoisted_17","_hoisted_18","_hoisted_19","_hoisted_20","_hoisted_21","showFileMenu","showEditMenu","showViewMenu","showHelpMenu","showAddMenu","showOpenSub","showOpenGrid","fileInput","triggerImport","onFileSelected","handleNew","handleSave","handleExport","handleUndo","handleRedo","handleDuplicate","handleResetCamera","handleToggleGrid","handleHelp","handleAbout","handleOpenProject","handleOpenModel","handleOpenScene","_withDirectives","selectedModel","syncTransformFromObject","applyTransformToObject","handlePropertyChange","handleAddModel","handleImportModel","treeData","shallowRef","initTree","handleTreeSelect","containerRef","init","onMounted","TopBar","PropertyPanel","BottomBar"],"mappings":"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","x_google_ignoreList":[0,1,3,4,5,6]}
1
+ {"version":3,"file":"three-editor.cjs.js","sources":["../node_modules/three/examples/jsm/controls/OrbitControls.js","../node_modules/three/examples/jsm/controls/TransformControls.js","../src/three/index.ts","../node_modules/three/examples/jsm/loaders/OBJLoader.js","../node_modules/three/examples/jsm/utils/BufferGeometryUtils.js","../node_modules/three/examples/jsm/utils/SkeletonUtils.js","../node_modules/three/examples/jsm/loaders/GLTFLoader.js","../src/three/addHandle.ts","../src/components/TreeItem.vue","../src/composables/useTreeExpand.ts","../src/components/PropertyPanel.vue","../src/components/TopBar.vue","../src/components/BottomBar.vue","../src/components/DrawingBoard.vue"],"sourcesContent":["import {\n\tControls,\n\tMOUSE,\n\tQuaternion,\n\tSpherical,\n\tTOUCH,\n\tVector2,\n\tVector3,\n\tPlane,\n\tRay,\n\tMathUtils\n} from 'three';\n\n/**\n * Fires when the camera has been transformed by the controls.\n *\n * @event OrbitControls#change\n * @type {Object}\n */\nconst _changeEvent = { type: 'change' };\n\n/**\n * Fires when an interaction was initiated.\n *\n * @event OrbitControls#start\n * @type {Object}\n */\nconst _startEvent = { type: 'start' };\n\n/**\n * Fires when an interaction has finished.\n *\n * @event OrbitControls#end\n * @type {Object}\n */\nconst _endEvent = { type: 'end' };\n\nconst _ray = new Ray();\nconst _plane = new Plane();\nconst _TILT_LIMIT = Math.cos( 70 * MathUtils.DEG2RAD );\n\nconst _v = new Vector3();\nconst _twoPI = 2 * Math.PI;\n\nconst _STATE = {\n\tNONE: - 1,\n\tROTATE: 0,\n\tDOLLY: 1,\n\tPAN: 2,\n\tTOUCH_ROTATE: 3,\n\tTOUCH_PAN: 4,\n\tTOUCH_DOLLY_PAN: 5,\n\tTOUCH_DOLLY_ROTATE: 6\n};\nconst _EPS = 0.000001;\n\n\n/**\n * Orbit controls allow the camera to orbit around a target.\n *\n * OrbitControls performs orbiting, dollying (zooming), and panning. Unlike {@link TrackballControls},\n * it maintains the \"up\" direction `object.up` (+Y by default).\n *\n * - Orbit: Left mouse / touch: one-finger move.\n * - Zoom: Middle mouse, or mousewheel / touch: two-finger spread or squish.\n * - Pan: Right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move.\n *\n * ```js\n * const controls = new OrbitControls( camera, renderer.domElement );\n *\n * // controls.update() must be called after any manual changes to the camera's transform\n * camera.position.set( 0, 20, 100 );\n * controls.update();\n *\n * function animate() {\n *\n * \t// required if controls.enableDamping or controls.autoRotate are set to true\n * \tcontrols.update();\n *\n * \trenderer.render( scene, camera );\n *\n * }\n * ```\n *\n * @augments Controls\n * @three_import import { OrbitControls } from 'three/addons/controls/OrbitControls.js';\n */\nclass OrbitControls extends Controls {\n\n\t/**\n\t * Constructs a new controls instance.\n\t *\n\t * @param {Object3D} object - The object that is managed by the controls.\n\t * @param {?HTMLElement} domElement - The HTML element used for event listeners.\n\t */\n\tconstructor( object, domElement = null ) {\n\n\t\tsuper( object, domElement );\n\n\t\tthis.state = _STATE.NONE;\n\n\t\t/**\n\t\t * The focus point of the controls, the `object` orbits around this.\n\t\t * It can be updated manually at any point to change the focus of the controls.\n\t\t *\n\t\t * @type {Vector3}\n\t\t */\n\t\tthis.target = new Vector3();\n\n\t\t/**\n\t\t * The focus point of the `minTargetRadius` and `maxTargetRadius` limits.\n\t\t * It can be updated manually at any point to change the center of interest\n\t\t * for the `target`.\n\t\t *\n\t\t * @type {Vector3}\n\t\t */\n\t\tthis.cursor = new Vector3();\n\n\t\t/**\n\t\t * How far you can dolly in (perspective camera only).\n\t\t *\n\t\t * @type {number}\n\t\t * @default 0\n\t\t */\n\t\tthis.minDistance = 0;\n\n\t\t/**\n\t\t * How far you can dolly out (perspective camera only).\n\t\t *\n\t\t * @type {number}\n\t\t * @default Infinity\n\t\t */\n\t\tthis.maxDistance = Infinity;\n\n\t\t/**\n\t\t * How far you can zoom in (orthographic camera only).\n\t\t *\n\t\t * @type {number}\n\t\t * @default 0\n\t\t */\n\t\tthis.minZoom = 0;\n\n\t\t/**\n\t\t * How far you can zoom out (orthographic camera only).\n\t\t *\n\t\t * @type {number}\n\t\t * @default Infinity\n\t\t */\n\t\tthis.maxZoom = Infinity;\n\n\t\t/**\n\t\t * How close you can get the target to the 3D `cursor`.\n\t\t *\n\t\t * @type {number}\n\t\t * @default 0\n\t\t */\n\t\tthis.minTargetRadius = 0;\n\n\t\t/**\n\t\t * How far you can move the target from the 3D `cursor`.\n\t\t *\n\t\t * @type {number}\n\t\t * @default Infinity\n\t\t */\n\t\tthis.maxTargetRadius = Infinity;\n\n\t\t/**\n\t\t * How far you can orbit vertically, lower limit. Range is `[0, Math.PI]` radians.\n\t\t *\n\t\t * @type {number}\n\t\t * @default 0\n\t\t */\n\t\tthis.minPolarAngle = 0;\n\n\t\t/**\n\t\t * How far you can orbit vertically, upper limit. Range is `[0, Math.PI]` radians.\n\t\t *\n\t\t * @type {number}\n\t\t * @default Math.PI\n\t\t */\n\t\tthis.maxPolarAngle = Math.PI;\n\n\t\t/**\n\t\t * How far you can orbit horizontally, lower limit. If set, the interval `[ min, max ]`\n\t\t * must be a sub-interval of `[ - 2 PI, 2 PI ]`, with `( max - min < 2 PI )`.\n\t\t *\n\t\t * @type {number}\n\t\t * @default -Infinity\n\t\t */\n\t\tthis.minAzimuthAngle = - Infinity;\n\n\t\t/**\n\t\t * How far you can orbit horizontally, upper limit. If set, the interval `[ min, max ]`\n\t\t * must be a sub-interval of `[ - 2 PI, 2 PI ]`, with `( max - min < 2 PI )`.\n\t\t *\n\t\t * @type {number}\n\t\t * @default -Infinity\n\t\t */\n\t\tthis.maxAzimuthAngle = Infinity;\n\n\t\t/**\n\t\t * Set to `true` to enable damping (inertia), which can be used to give a sense of weight\n\t\t * to the controls. Note that if this is enabled, you must call `update()` in your animation\n\t\t * loop.\n\t\t *\n\t\t * @type {boolean}\n\t\t * @default false\n\t\t */\n\t\tthis.enableDamping = false;\n\n\t\t/**\n\t\t * The damping inertia used if `enableDamping` is set to `true`.\n\t\t *\n\t\t * Note that for this to work, you must call `update()` in your animation loop.\n\t\t *\n\t\t * @type {number}\n\t\t * @default 0.05\n\t\t */\n\t\tthis.dampingFactor = 0.05;\n\n\t\t/**\n\t\t * Enable or disable zooming (dollying) of the camera.\n\t\t *\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t */\n\t\tthis.enableZoom = true;\n\n\t\t/**\n\t\t * Speed of zooming / dollying.\n\t\t *\n\t\t * @type {number}\n\t\t * @default 1\n\t\t */\n\t\tthis.zoomSpeed = 1.0;\n\n\t\t/**\n\t\t * Enable or disable horizontal and vertical rotation of the camera.\n\t\t *\n\t\t * Note that it is possible to disable a single axis by setting the min and max of the\n\t\t * `minPolarAngle` or `minAzimuthAngle` to the same value, which will cause the vertical\n\t\t * or horizontal rotation to be fixed at that value.\n\t\t *\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t */\n\t\tthis.enableRotate = true;\n\n\t\t/**\n\t\t * Speed of rotation.\n\t\t *\n\t\t * @type {number}\n\t\t * @default 1\n\t\t */\n\t\tthis.rotateSpeed = 1.0;\n\n\t\t/**\n\t\t * How fast to rotate the camera when the keyboard is used.\n\t\t *\n\t\t * @type {number}\n\t\t * @default 1\n\t\t */\n\t\tthis.keyRotateSpeed = 1.0;\n\n\t\t/**\n\t\t * Enable or disable camera panning.\n\t\t *\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t */\n\t\tthis.enablePan = true;\n\n\t\t/**\n\t\t * Speed of panning.\n\t\t *\n\t\t * @type {number}\n\t\t * @default 1\n\t\t */\n\t\tthis.panSpeed = 1.0;\n\n\t\t/**\n\t\t * Defines how the camera's position is translated when panning. If `true`, the camera pans\n\t\t * in screen space. Otherwise, the camera pans in the plane orthogonal to the camera's up\n\t\t * direction.\n\t\t *\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t */\n\t\tthis.screenSpacePanning = true;\n\n\t\t/**\n\t\t * How fast to pan the camera when the keyboard is used in\n\t\t * pixels per keypress.\n\t\t *\n\t\t * @type {number}\n\t\t * @default 7\n\t\t */\n\t\tthis.keyPanSpeed = 7.0;\n\n\t\t/**\n\t\t * Setting this property to `true` allows to zoom to the cursor's position.\n\t\t *\n\t\t * @type {boolean}\n\t\t * @default false\n\t\t */\n\t\tthis.zoomToCursor = false;\n\n\t\t/**\n\t\t * Set to true to automatically rotate around the target\n\t\t *\n\t\t * Note that if this is enabled, you must call `update()` in your animation loop.\n\t\t * If you want the auto-rotate speed to be independent of the frame rate (the refresh\n\t\t * rate of the display), you must pass the time `deltaTime`, in seconds, to `update()`.\n\t\t *\n\t\t * @type {boolean}\n\t\t * @default false\n\t\t */\n\t\tthis.autoRotate = false;\n\n\t\t/**\n\t\t * How fast to rotate around the target if `autoRotate` is `true`. The default equates to 30 seconds\n\t\t * per orbit at 60fps.\n\t\t *\n\t\t * Note that if `autoRotate` is enabled, you must call `update()` in your animation loop.\n\t\t *\n\t\t * @type {number}\n\t\t * @default 2\n\t\t */\n\t\tthis.autoRotateSpeed = 2.0;\n\n\t\t/**\n\t\t * This object contains references to the keycodes for controlling camera panning.\n\t\t *\n\t\t * ```js\n\t\t * controls.keys = {\n\t\t * \tLEFT: 'ArrowLeft', //left arrow\n\t\t * \tUP: 'ArrowUp', // up arrow\n\t\t * \tRIGHT: 'ArrowRight', // right arrow\n\t\t * \tBOTTOM: 'ArrowDown' // down arrow\n\t\t * }\n\t\t * ```\n\t\t * @type {Object}\n\t\t */\n\t\tthis.keys = { LEFT: 'ArrowLeft', UP: 'ArrowUp', RIGHT: 'ArrowRight', BOTTOM: 'ArrowDown' };\n\n\t\t/**\n\t\t * This object contains references to the mouse actions used by the controls.\n\t\t *\n\t\t * ```js\n\t\t * controls.mouseButtons = {\n\t\t * \tLEFT: THREE.MOUSE.ROTATE,\n\t\t * \tMIDDLE: THREE.MOUSE.DOLLY,\n\t\t * \tRIGHT: THREE.MOUSE.PAN\n\t\t * }\n\t\t * ```\n\t\t * @type {Object}\n\t\t */\n\t\tthis.mouseButtons = { LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN };\n\n\t\t/**\n\t\t * This object contains references to the touch actions used by the controls.\n\t\t *\n\t\t * ```js\n\t\t * controls.mouseButtons = {\n\t\t * \tONE: THREE.TOUCH.ROTATE,\n\t\t * \tTWO: THREE.TOUCH.DOLLY_PAN\n\t\t * }\n\t\t * ```\n\t\t * @type {Object}\n\t\t */\n\t\tthis.touches = { ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN };\n\n\t\t/**\n\t\t * Used internally by `saveState()` and `reset()`.\n\t\t *\n\t\t * @type {Vector3}\n\t\t */\n\t\tthis.target0 = this.target.clone();\n\n\t\t/**\n\t\t * Used internally by `saveState()` and `reset()`.\n\t\t *\n\t\t * @type {Vector3}\n\t\t */\n\t\tthis.position0 = this.object.position.clone();\n\n\t\t/**\n\t\t * Used internally by `saveState()` and `reset()`.\n\t\t *\n\t\t * @type {number}\n\t\t */\n\t\tthis.zoom0 = this.object.zoom;\n\n\t\tthis._cursorStyle = 'auto';\n\n\t\t// the target DOM element for key events\n\t\tthis._domElementKeyEvents = null;\n\n\t\t// internals\n\n\t\tthis._lastPosition = new Vector3();\n\t\tthis._lastQuaternion = new Quaternion();\n\t\tthis._lastTargetPosition = new Vector3();\n\n\t\t// so camera.up is the orbit axis\n\t\tthis._quat = new Quaternion().setFromUnitVectors( object.up, new Vector3( 0, 1, 0 ) );\n\t\tthis._quatInverse = this._quat.clone().invert();\n\n\t\t// current position in spherical coordinates\n\t\tthis._spherical = new Spherical();\n\t\tthis._sphericalDelta = new Spherical();\n\n\t\tthis._scale = 1;\n\t\tthis._panOffset = new Vector3();\n\n\t\tthis._rotateStart = new Vector2();\n\t\tthis._rotateEnd = new Vector2();\n\t\tthis._rotateDelta = new Vector2();\n\n\t\tthis._panStart = new Vector2();\n\t\tthis._panEnd = new Vector2();\n\t\tthis._panDelta = new Vector2();\n\n\t\tthis._dollyStart = new Vector2();\n\t\tthis._dollyEnd = new Vector2();\n\t\tthis._dollyDelta = new Vector2();\n\n\t\tthis._dollyDirection = new Vector3();\n\t\tthis._mouse = new Vector2();\n\t\tthis._performCursorZoom = false;\n\n\t\tthis._pointers = [];\n\t\tthis._pointerPositions = {};\n\n\t\tthis._controlActive = false;\n\n\t\t// event listeners\n\n\t\tthis._onPointerMove = onPointerMove.bind( this );\n\t\tthis._onPointerDown = onPointerDown.bind( this );\n\t\tthis._onPointerUp = onPointerUp.bind( this );\n\t\tthis._onContextMenu = onContextMenu.bind( this );\n\t\tthis._onMouseWheel = onMouseWheel.bind( this );\n\t\tthis._onKeyDown = onKeyDown.bind( this );\n\n\t\tthis._onTouchStart = onTouchStart.bind( this );\n\t\tthis._onTouchMove = onTouchMove.bind( this );\n\n\t\tthis._onMouseDown = onMouseDown.bind( this );\n\t\tthis._onMouseMove = onMouseMove.bind( this );\n\n\t\tthis._interceptControlDown = interceptControlDown.bind( this );\n\t\tthis._interceptControlUp = interceptControlUp.bind( this );\n\n\t\t//\n\n\t\tif ( this.domElement !== null ) {\n\n\t\t\tthis.connect( this.domElement );\n\n\t\t}\n\n\t\tthis.update();\n\n\t}\n\n\t/**\n\t * Defines the visual representation of the cursor.\n\t *\n\t * @type {('auto'|'grab')}\n\t * @default 'auto'\n\t */\n\tset cursorStyle( type ) {\n\n\t\tthis._cursorStyle = type;\n\n\t\tif ( type === 'grab' ) {\n\n\t\t\tthis.domElement.style.cursor = 'grab';\n\n\t\t} else {\n\n\t\t\tthis.domElement.style.cursor = 'auto';\n\n\t\t}\n\n\t}\n\n\tget cursorStyle() {\n\n\t\treturn this._cursorStyle;\n\n\t}\n\n\tconnect( element ) {\n\n\t\tsuper.connect( element );\n\n\t\tthis.domElement.addEventListener( 'pointerdown', this._onPointerDown );\n\t\tthis.domElement.addEventListener( 'pointercancel', this._onPointerUp );\n\n\t\tthis.domElement.addEventListener( 'contextmenu', this._onContextMenu );\n\t\tthis.domElement.addEventListener( 'wheel', this._onMouseWheel, { passive: false } );\n\n\t\tconst document = this.domElement.getRootNode(); // offscreen canvas compatibility\n\t\tdocument.addEventListener( 'keydown', this._interceptControlDown, { passive: true, capture: true } );\n\n\t\tthis.domElement.style.touchAction = 'none'; // Disable touch scroll\n\n\t}\n\n\tdisconnect() {\n\n\t\tthis.domElement.removeEventListener( 'pointerdown', this._onPointerDown );\n\t\tthis.domElement.ownerDocument.removeEventListener( 'pointermove', this._onPointerMove );\n\t\tthis.domElement.ownerDocument.removeEventListener( 'pointerup', this._onPointerUp );\n\t\tthis.domElement.removeEventListener( 'pointercancel', this._onPointerUp );\n\n\t\tthis.domElement.removeEventListener( 'wheel', this._onMouseWheel );\n\t\tthis.domElement.removeEventListener( 'contextmenu', this._onContextMenu );\n\n\t\tthis.stopListenToKeyEvents();\n\n\t\tconst document = this.domElement.getRootNode(); // offscreen canvas compatibility\n\t\tdocument.removeEventListener( 'keydown', this._interceptControlDown, { capture: true } );\n\n\t\tthis.domElement.style.touchAction = ''; // Restore touch scroll\n\n\t}\n\n\tdispose() {\n\n\t\tthis.disconnect();\n\n\t}\n\n\t/**\n\t * Get the current vertical rotation, in radians.\n\t *\n\t * @return {number} The current vertical rotation, in radians.\n\t */\n\tgetPolarAngle() {\n\n\t\treturn this._spherical.phi;\n\n\t}\n\n\t/**\n\t * Get the current horizontal rotation, in radians.\n\t *\n\t * @return {number} The current horizontal rotation, in radians.\n\t */\n\tgetAzimuthalAngle() {\n\n\t\treturn this._spherical.theta;\n\n\t}\n\n\t/**\n\t * Returns the distance from the camera to the target.\n\t *\n\t * @return {number} The distance from the camera to the target.\n\t */\n\tgetDistance() {\n\n\t\treturn this.object.position.distanceTo( this.target );\n\n\t}\n\n\t/**\n\t * Adds key event listeners to the given DOM element.\n\t * `window` is a recommended argument for using this method.\n\t *\n\t * @param {HTMLElement} domElement - The DOM element\n\t */\n\tlistenToKeyEvents( domElement ) {\n\n\t\tdomElement.addEventListener( 'keydown', this._onKeyDown );\n\t\tthis._domElementKeyEvents = domElement;\n\n\t}\n\n\t/**\n\t * Removes the key event listener previously defined with `listenToKeyEvents()`.\n\t */\n\tstopListenToKeyEvents() {\n\n\t\tif ( this._domElementKeyEvents !== null ) {\n\n\t\t\tthis._domElementKeyEvents.removeEventListener( 'keydown', this._onKeyDown );\n\t\t\tthis._domElementKeyEvents = null;\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Save the current state of the controls. This can later be recovered with `reset()`.\n\t */\n\tsaveState() {\n\n\t\tthis.target0.copy( this.target );\n\t\tthis.position0.copy( this.object.position );\n\t\tthis.zoom0 = this.object.zoom;\n\n\t}\n\n\t/**\n\t * Reset the controls to their state from either the last time the `saveState()`\n\t * was called, or the initial state.\n\t */\n\treset() {\n\n\t\tthis.target.copy( this.target0 );\n\t\tthis.object.position.copy( this.position0 );\n\t\tthis.object.zoom = this.zoom0;\n\n\t\tthis.object.updateProjectionMatrix();\n\t\tthis.dispatchEvent( _changeEvent );\n\n\t\tthis.update();\n\n\t\tthis.state = _STATE.NONE;\n\n\t}\n\n\t/**\n\t * Programmatically pan the camera.\n\t *\n\t * @param {number} deltaX - The horizontal pan amount in pixels.\n\t * @param {number} deltaY - The vertical pan amount in pixels.\n\t */\n\tpan( deltaX, deltaY ) {\n\n\t\tthis._pan( deltaX, deltaY );\n\t\tthis.update();\n\n\t}\n\n\t/**\n\t * Programmatically dolly in (zoom in for perspective camera).\n\t *\n\t * @param {number} dollyScale - The dolly scale factor.\n\t */\n\tdollyIn( dollyScale ) {\n\n\t\tthis._dollyIn( dollyScale );\n\t\tthis.update();\n\n\t}\n\n\t/**\n\t * Programmatically dolly out (zoom out for perspective camera).\n\t *\n\t * @param {number} dollyScale - The dolly scale factor.\n\t */\n\tdollyOut( dollyScale ) {\n\n\t\tthis._dollyOut( dollyScale );\n\t\tthis.update();\n\n\t}\n\n\t/**\n\t * Programmatically rotate the camera left (around the vertical axis).\n\t *\n\t * @param {number} angle - The rotation angle in radians.\n\t */\n\trotateLeft( angle ) {\n\n\t\tthis._rotateLeft( angle );\n\t\tthis.update();\n\n\t}\n\n\t/**\n\t * Programmatically rotate the camera up (around the horizontal axis).\n\t *\n\t * @param {number} angle - The rotation angle in radians.\n\t */\n\trotateUp( angle ) {\n\n\t\tthis._rotateUp( angle );\n\t\tthis.update();\n\n\t}\n\n\tupdate( deltaTime = null ) {\n\n\t\tconst position = this.object.position;\n\n\t\t_v.copy( position ).sub( this.target );\n\n\t\t// rotate offset to \"y-axis-is-up\" space\n\t\t_v.applyQuaternion( this._quat );\n\n\t\t// angle from z-axis around y-axis\n\t\tthis._spherical.setFromVector3( _v );\n\n\t\tif ( this.autoRotate && this.state === _STATE.NONE ) {\n\n\t\t\tthis._rotateLeft( this._getAutoRotationAngle( deltaTime ) );\n\n\t\t}\n\n\t\tif ( this.enableDamping ) {\n\n\t\t\tthis._spherical.theta += this._sphericalDelta.theta * this.dampingFactor;\n\t\t\tthis._spherical.phi += this._sphericalDelta.phi * this.dampingFactor;\n\n\t\t} else {\n\n\t\t\tthis._spherical.theta += this._sphericalDelta.theta;\n\t\t\tthis._spherical.phi += this._sphericalDelta.phi;\n\n\t\t}\n\n\t\t// restrict theta to be between desired limits\n\n\t\tlet min = this.minAzimuthAngle;\n\t\tlet max = this.maxAzimuthAngle;\n\n\t\tif ( isFinite( min ) && isFinite( max ) ) {\n\n\t\t\tif ( min < - Math.PI ) min += _twoPI; else if ( min > Math.PI ) min -= _twoPI;\n\n\t\t\tif ( max < - Math.PI ) max += _twoPI; else if ( max > Math.PI ) max -= _twoPI;\n\n\t\t\tif ( min <= max ) {\n\n\t\t\t\tthis._spherical.theta = Math.max( min, Math.min( max, this._spherical.theta ) );\n\n\t\t\t} else {\n\n\t\t\t\tthis._spherical.theta = ( this._spherical.theta > ( min + max ) / 2 ) ?\n\t\t\t\t\tMath.max( min, this._spherical.theta ) :\n\t\t\t\t\tMath.min( max, this._spherical.theta );\n\n\t\t\t}\n\n\t\t}\n\n\t\t// restrict phi to be between desired limits\n\t\tthis._spherical.phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, this._spherical.phi ) );\n\n\t\tthis._spherical.makeSafe();\n\n\n\t\t// move target to panned location\n\n\t\tif ( this.enableDamping === true ) {\n\n\t\t\tthis.target.addScaledVector( this._panOffset, this.dampingFactor );\n\n\t\t} else {\n\n\t\t\tthis.target.add( this._panOffset );\n\n\t\t}\n\n\t\t// Limit the target distance from the cursor to create a sphere around the center of interest\n\t\tthis.target.sub( this.cursor );\n\t\tthis.target.clampLength( this.minTargetRadius, this.maxTargetRadius );\n\t\tthis.target.add( this.cursor );\n\n\t\tlet zoomChanged = false;\n\t\t// adjust the camera position based on zoom only if we're not zooming to the cursor or if it's an ortho camera\n\t\t// we adjust zoom later in these cases\n\t\tif ( this.zoomToCursor && this._performCursorZoom || this.object.isOrthographicCamera ) {\n\n\t\t\tthis._spherical.radius = this._clampDistance( this._spherical.radius );\n\n\t\t} else {\n\n\t\t\tconst prevRadius = this._spherical.radius;\n\t\t\tthis._spherical.radius = this._clampDistance( this._spherical.radius * this._scale );\n\t\t\tzoomChanged = prevRadius != this._spherical.radius;\n\n\t\t}\n\n\t\t_v.setFromSpherical( this._spherical );\n\n\t\t// rotate offset back to \"camera-up-vector-is-up\" space\n\t\t_v.applyQuaternion( this._quatInverse );\n\n\t\tposition.copy( this.target ).add( _v );\n\n\t\tthis.object.lookAt( this.target );\n\n\t\tif ( this.enableDamping === true ) {\n\n\t\t\tthis._sphericalDelta.theta *= ( 1 - this.dampingFactor );\n\t\t\tthis._sphericalDelta.phi *= ( 1 - this.dampingFactor );\n\n\t\t\tthis._panOffset.multiplyScalar( 1 - this.dampingFactor );\n\n\t\t} else {\n\n\t\t\tthis._sphericalDelta.set( 0, 0, 0 );\n\n\t\t\tthis._panOffset.set( 0, 0, 0 );\n\n\t\t}\n\n\t\t// adjust camera position\n\t\tif ( this.zoomToCursor && this._performCursorZoom ) {\n\n\t\t\tlet newRadius = null;\n\t\t\tif ( this.object.isPerspectiveCamera ) {\n\n\t\t\t\t// move the camera down the pointer ray\n\t\t\t\t// this method avoids floating point error\n\t\t\t\tconst prevRadius = _v.length();\n\t\t\t\tnewRadius = this._clampDistance( prevRadius * this._scale );\n\n\t\t\t\tconst radiusDelta = prevRadius - newRadius;\n\t\t\t\tthis.object.position.addScaledVector( this._dollyDirection, radiusDelta );\n\t\t\t\tthis.object.updateMatrixWorld();\n\n\t\t\t\tzoomChanged = !! radiusDelta;\n\n\t\t\t} else if ( this.object.isOrthographicCamera ) {\n\n\t\t\t\t// adjust the ortho camera position based on zoom changes\n\t\t\t\tconst mouseBefore = new Vector3( this._mouse.x, this._mouse.y, 0 );\n\t\t\t\tmouseBefore.unproject( this.object );\n\n\t\t\t\tconst prevZoom = this.object.zoom;\n\t\t\t\tthis.object.zoom = Math.max( this.minZoom, Math.min( this.maxZoom, this.object.zoom / this._scale ) );\n\t\t\t\tthis.object.updateProjectionMatrix();\n\n\t\t\t\tzoomChanged = prevZoom !== this.object.zoom;\n\n\t\t\t\tconst mouseAfter = new Vector3( this._mouse.x, this._mouse.y, 0 );\n\t\t\t\tmouseAfter.unproject( this.object );\n\n\t\t\t\tthis.object.position.sub( mouseAfter ).add( mouseBefore );\n\t\t\t\tthis.object.updateMatrixWorld();\n\n\t\t\t\tnewRadius = _v.length();\n\n\t\t\t} else {\n\n\t\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled.' );\n\t\t\t\tthis.zoomToCursor = false;\n\n\t\t\t}\n\n\t\t\t// handle the placement of the target\n\t\t\tif ( newRadius !== null ) {\n\n\t\t\t\tif ( this.screenSpacePanning ) {\n\n\t\t\t\t\t// position the orbit target in front of the new camera position\n\t\t\t\t\tthis.target.set( 0, 0, - 1 )\n\t\t\t\t\t\t.transformDirection( this.object.matrix )\n\t\t\t\t\t\t.multiplyScalar( newRadius )\n\t\t\t\t\t\t.add( this.object.position );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// get the ray and translation plane to compute target\n\t\t\t\t\t_ray.origin.copy( this.object.position );\n\t\t\t\t\t_ray.direction.set( 0, 0, - 1 ).transformDirection( this.object.matrix );\n\n\t\t\t\t\t// if the camera is 20 degrees above the horizon then don't adjust the focus target to avoid\n\t\t\t\t\t// extremely large values\n\t\t\t\t\tif ( Math.abs( this.object.up.dot( _ray.direction ) ) < _TILT_LIMIT ) {\n\n\t\t\t\t\t\tthis.object.lookAt( this.target );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t_plane.setFromNormalAndCoplanarPoint( this.object.up, this.target );\n\t\t\t\t\t\t_ray.intersectPlane( _plane, this.target );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else if ( this.object.isOrthographicCamera ) {\n\n\t\t\tconst prevZoom = this.object.zoom;\n\t\t\tthis.object.zoom = Math.max( this.minZoom, Math.min( this.maxZoom, this.object.zoom / this._scale ) );\n\n\t\t\tif ( prevZoom !== this.object.zoom ) {\n\n\t\t\t\tthis.object.updateProjectionMatrix();\n\t\t\t\tzoomChanged = true;\n\n\t\t\t}\n\n\t\t}\n\n\t\tthis._scale = 1;\n\t\tthis._performCursorZoom = false;\n\n\t\t// update condition is:\n\t\t// min(camera displacement, camera rotation in radians)^2 > EPS\n\t\t// using small-angle approximation cos(x/2) = 1 - x^2 / 8\n\n\t\tif ( zoomChanged ||\n\t\t\tthis._lastPosition.distanceToSquared( this.object.position ) > _EPS ||\n\t\t\t8 * ( 1 - this._lastQuaternion.dot( this.object.quaternion ) ) > _EPS ||\n\t\t\tthis._lastTargetPosition.distanceToSquared( this.target ) > _EPS ) {\n\n\t\t\tthis.dispatchEvent( _changeEvent );\n\n\t\t\tthis._lastPosition.copy( this.object.position );\n\t\t\tthis._lastQuaternion.copy( this.object.quaternion );\n\t\t\tthis._lastTargetPosition.copy( this.target );\n\n\t\t\treturn true;\n\n\t\t}\n\n\t\treturn false;\n\n\t}\n\n\t_getAutoRotationAngle( deltaTime ) {\n\n\t\tif ( deltaTime !== null ) {\n\n\t\t\treturn ( _twoPI / 60 * this.autoRotateSpeed ) * deltaTime;\n\n\t\t} else {\n\n\t\t\treturn _twoPI / 60 / 60 * this.autoRotateSpeed;\n\n\t\t}\n\n\t}\n\n\t_getZoomScale( delta ) {\n\n\t\tconst normalizedDelta = Math.abs( delta * 0.01 );\n\t\treturn Math.pow( 0.95, this.zoomSpeed * normalizedDelta );\n\n\t}\n\n\t_rotateLeft( angle ) {\n\n\t\tthis._sphericalDelta.theta -= angle;\n\n\t}\n\n\t_rotateUp( angle ) {\n\n\t\tthis._sphericalDelta.phi -= angle;\n\n\t}\n\n\t_panLeft( distance, objectMatrix ) {\n\n\t\t_v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix\n\t\t_v.multiplyScalar( - distance );\n\n\t\tthis._panOffset.add( _v );\n\n\t}\n\n\t_panUp( distance, objectMatrix ) {\n\n\t\tif ( this.screenSpacePanning === true ) {\n\n\t\t\t_v.setFromMatrixColumn( objectMatrix, 1 );\n\n\t\t} else {\n\n\t\t\t_v.setFromMatrixColumn( objectMatrix, 0 );\n\t\t\t_v.crossVectors( this.object.up, _v );\n\n\t\t}\n\n\t\t_v.multiplyScalar( distance );\n\n\t\tthis._panOffset.add( _v );\n\n\t}\n\n\t// deltaX and deltaY are in pixels; right and down are positive\n\t_pan( deltaX, deltaY ) {\n\n\t\tconst element = this.domElement;\n\n\t\tif ( this.object.isPerspectiveCamera ) {\n\n\t\t\t// perspective\n\t\t\tconst position = this.object.position;\n\t\t\t_v.copy( position ).sub( this.target );\n\t\t\tlet targetDistance = _v.length();\n\n\t\t\t// half of the fov is center to top of screen\n\t\t\ttargetDistance *= Math.tan( ( this.object.fov / 2 ) * Math.PI / 180.0 );\n\n\t\t\t// we use only clientHeight here so aspect ratio does not distort speed\n\t\t\tthis._panLeft( 2 * deltaX * targetDistance / element.clientHeight, this.object.matrix );\n\t\t\tthis._panUp( 2 * deltaY * targetDistance / element.clientHeight, this.object.matrix );\n\n\t\t} else if ( this.object.isOrthographicCamera ) {\n\n\t\t\t// orthographic\n\t\t\tthis._panLeft( deltaX * ( this.object.right - this.object.left ) / this.object.zoom / element.clientWidth, this.object.matrix );\n\t\t\tthis._panUp( deltaY * ( this.object.top - this.object.bottom ) / this.object.zoom / element.clientHeight, this.object.matrix );\n\n\t\t} else {\n\n\t\t\t// camera neither orthographic nor perspective\n\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );\n\t\t\tthis.enablePan = false;\n\n\t\t}\n\n\t}\n\n\t_dollyOut( dollyScale ) {\n\n\t\tif ( this.object.isPerspectiveCamera || this.object.isOrthographicCamera ) {\n\n\t\t\tthis._scale /= dollyScale;\n\n\t\t} else {\n\n\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );\n\t\t\tthis.enableZoom = false;\n\n\t\t}\n\n\t}\n\n\t_dollyIn( dollyScale ) {\n\n\t\tif ( this.object.isPerspectiveCamera || this.object.isOrthographicCamera ) {\n\n\t\t\tthis._scale *= dollyScale;\n\n\t\t} else {\n\n\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );\n\t\t\tthis.enableZoom = false;\n\n\t\t}\n\n\t}\n\n\t_updateZoomParameters( x, y ) {\n\n\t\tif ( ! this.zoomToCursor ) {\n\n\t\t\treturn;\n\n\t\t}\n\n\t\tthis._performCursorZoom = true;\n\n\t\tconst rect = this.domElement.getBoundingClientRect();\n\t\tconst dx = x - rect.left;\n\t\tconst dy = y - rect.top;\n\t\tconst w = rect.width;\n\t\tconst h = rect.height;\n\n\t\tthis._mouse.x = ( dx / w ) * 2 - 1;\n\t\tthis._mouse.y = - ( dy / h ) * 2 + 1;\n\n\t\tthis._dollyDirection.set( this._mouse.x, this._mouse.y, 1 ).unproject( this.object ).sub( this.object.position ).normalize();\n\n\t}\n\n\t_clampDistance( dist ) {\n\n\t\treturn Math.max( this.minDistance, Math.min( this.maxDistance, dist ) );\n\n\t}\n\n\t//\n\t// event callbacks - update the object state\n\t//\n\n\t_handleMouseDownRotate( event ) {\n\n\t\tthis._rotateStart.set( event.clientX, event.clientY );\n\n\t}\n\n\t_handleMouseDownDolly( event ) {\n\n\t\tthis._updateZoomParameters( event.clientX, event.clientX );\n\t\tthis._dollyStart.set( event.clientX, event.clientY );\n\n\t}\n\n\t_handleMouseDownPan( event ) {\n\n\t\tthis._panStart.set( event.clientX, event.clientY );\n\n\t}\n\n\t_handleMouseMoveRotate( event ) {\n\n\t\tthis._rotateEnd.set( event.clientX, event.clientY );\n\n\t\tthis._rotateDelta.subVectors( this._rotateEnd, this._rotateStart ).multiplyScalar( this.rotateSpeed );\n\n\t\tconst element = this.domElement;\n\n\t\tthis._rotateLeft( _twoPI * this._rotateDelta.x / element.clientHeight ); // yes, height\n\n\t\tthis._rotateUp( _twoPI * this._rotateDelta.y / element.clientHeight );\n\n\t\tthis._rotateStart.copy( this._rotateEnd );\n\n\t\tthis.update();\n\n\t}\n\n\t_handleMouseMoveDolly( event ) {\n\n\t\tthis._dollyEnd.set( event.clientX, event.clientY );\n\n\t\tthis._dollyDelta.subVectors( this._dollyEnd, this._dollyStart );\n\n\t\tif ( this._dollyDelta.y > 0 ) {\n\n\t\t\tthis._dollyOut( this._getZoomScale( this._dollyDelta.y ) );\n\n\t\t} else if ( this._dollyDelta.y < 0 ) {\n\n\t\t\tthis._dollyIn( this._getZoomScale( this._dollyDelta.y ) );\n\n\t\t}\n\n\t\tthis._dollyStart.copy( this._dollyEnd );\n\n\t\tthis.update();\n\n\t}\n\n\t_handleMouseMovePan( event ) {\n\n\t\tthis._panEnd.set( event.clientX, event.clientY );\n\n\t\tthis._panDelta.subVectors( this._panEnd, this._panStart ).multiplyScalar( this.panSpeed );\n\n\t\tthis._pan( this._panDelta.x, this._panDelta.y );\n\n\t\tthis._panStart.copy( this._panEnd );\n\n\t\tthis.update();\n\n\t}\n\n\t_handleMouseWheel( event ) {\n\n\t\tthis._updateZoomParameters( event.clientX, event.clientY );\n\n\t\tif ( event.deltaY < 0 ) {\n\n\t\t\tthis._dollyIn( this._getZoomScale( event.deltaY ) );\n\n\t\t} else if ( event.deltaY > 0 ) {\n\n\t\t\tthis._dollyOut( this._getZoomScale( event.deltaY ) );\n\n\t\t}\n\n\t\tthis.update();\n\n\t}\n\n\t_handleKeyDown( event ) {\n\n\t\tlet needsUpdate = false;\n\n\t\tswitch ( event.code ) {\n\n\t\t\tcase this.keys.UP:\n\n\t\t\t\tif ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n\t\t\t\t\tif ( this.enableRotate ) {\n\n\t\t\t\t\t\tthis._rotateUp( _twoPI * this.keyRotateSpeed / this.domElement.clientHeight );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( this.enablePan ) {\n\n\t\t\t\t\t\tthis._pan( 0, this.keyPanSpeed );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tneedsUpdate = true;\n\t\t\t\tbreak;\n\n\t\t\tcase this.keys.BOTTOM:\n\n\t\t\t\tif ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n\t\t\t\t\tif ( this.enableRotate ) {\n\n\t\t\t\t\t\tthis._rotateUp( - _twoPI * this.keyRotateSpeed / this.domElement.clientHeight );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( this.enablePan ) {\n\n\t\t\t\t\t\tthis._pan( 0, - this.keyPanSpeed );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tneedsUpdate = true;\n\t\t\t\tbreak;\n\n\t\t\tcase this.keys.LEFT:\n\n\t\t\t\tif ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n\t\t\t\t\tif ( this.enableRotate ) {\n\n\t\t\t\t\t\tthis._rotateLeft( _twoPI * this.keyRotateSpeed / this.domElement.clientHeight );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( this.enablePan ) {\n\n\t\t\t\t\t\tthis._pan( this.keyPanSpeed, 0 );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tneedsUpdate = true;\n\t\t\t\tbreak;\n\n\t\t\tcase this.keys.RIGHT:\n\n\t\t\t\tif ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n\t\t\t\t\tif ( this.enableRotate ) {\n\n\t\t\t\t\t\tthis._rotateLeft( - _twoPI * this.keyRotateSpeed / this.domElement.clientHeight );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( this.enablePan ) {\n\n\t\t\t\t\t\tthis._pan( - this.keyPanSpeed, 0 );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tneedsUpdate = true;\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\tif ( needsUpdate ) {\n\n\t\t\t// prevent the browser from scrolling on cursor keys\n\t\t\tevent.preventDefault();\n\n\t\t\tthis.update();\n\n\t\t}\n\n\n\t}\n\n\t_handleTouchStartRotate( event ) {\n\n\t\tif ( this._pointers.length === 1 ) {\n\n\t\t\tthis._rotateStart.set( event.pageX, event.pageY );\n\n\t\t} else {\n\n\t\t\tconst position = this._getSecondPointerPosition( event );\n\n\t\t\tconst x = 0.5 * ( event.pageX + position.x );\n\t\t\tconst y = 0.5 * ( event.pageY + position.y );\n\n\t\t\tthis._rotateStart.set( x, y );\n\n\t\t}\n\n\t}\n\n\t_handleTouchStartPan( event ) {\n\n\t\tif ( this._pointers.length === 1 ) {\n\n\t\t\tthis._panStart.set( event.pageX, event.pageY );\n\n\t\t} else {\n\n\t\t\tconst position = this._getSecondPointerPosition( event );\n\n\t\t\tconst x = 0.5 * ( event.pageX + position.x );\n\t\t\tconst y = 0.5 * ( event.pageY + position.y );\n\n\t\t\tthis._panStart.set( x, y );\n\n\t\t}\n\n\t}\n\n\t_handleTouchStartDolly( event ) {\n\n\t\tconst position = this._getSecondPointerPosition( event );\n\n\t\tconst dx = event.pageX - position.x;\n\t\tconst dy = event.pageY - position.y;\n\n\t\tconst distance = Math.sqrt( dx * dx + dy * dy );\n\n\t\tthis._dollyStart.set( 0, distance );\n\n\t}\n\n\t_handleTouchStartDollyPan( event ) {\n\n\t\tif ( this.enableZoom ) this._handleTouchStartDolly( event );\n\n\t\tif ( this.enablePan ) this._handleTouchStartPan( event );\n\n\t}\n\n\t_handleTouchStartDollyRotate( event ) {\n\n\t\tif ( this.enableZoom ) this._handleTouchStartDolly( event );\n\n\t\tif ( this.enableRotate ) this._handleTouchStartRotate( event );\n\n\t}\n\n\t_handleTouchMoveRotate( event ) {\n\n\t\tif ( this._pointers.length == 1 ) {\n\n\t\t\tthis._rotateEnd.set( event.pageX, event.pageY );\n\n\t\t} else {\n\n\t\t\tconst position = this._getSecondPointerPosition( event );\n\n\t\t\tconst x = 0.5 * ( event.pageX + position.x );\n\t\t\tconst y = 0.5 * ( event.pageY + position.y );\n\n\t\t\tthis._rotateEnd.set( x, y );\n\n\t\t}\n\n\t\tthis._rotateDelta.subVectors( this._rotateEnd, this._rotateStart ).multiplyScalar( this.rotateSpeed );\n\n\t\tconst element = this.domElement;\n\n\t\tthis._rotateLeft( _twoPI * this._rotateDelta.x / element.clientHeight ); // yes, height\n\n\t\tthis._rotateUp( _twoPI * this._rotateDelta.y / element.clientHeight );\n\n\t\tthis._rotateStart.copy( this._rotateEnd );\n\n\t}\n\n\t_handleTouchMovePan( event ) {\n\n\t\tif ( this._pointers.length === 1 ) {\n\n\t\t\tthis._panEnd.set( event.pageX, event.pageY );\n\n\t\t} else {\n\n\t\t\tconst position = this._getSecondPointerPosition( event );\n\n\t\t\tconst x = 0.5 * ( event.pageX + position.x );\n\t\t\tconst y = 0.5 * ( event.pageY + position.y );\n\n\t\t\tthis._panEnd.set( x, y );\n\n\t\t}\n\n\t\tthis._panDelta.subVectors( this._panEnd, this._panStart ).multiplyScalar( this.panSpeed );\n\n\t\tthis._pan( this._panDelta.x, this._panDelta.y );\n\n\t\tthis._panStart.copy( this._panEnd );\n\n\t}\n\n\t_handleTouchMoveDolly( event ) {\n\n\t\tconst position = this._getSecondPointerPosition( event );\n\n\t\tconst dx = event.pageX - position.x;\n\t\tconst dy = event.pageY - position.y;\n\n\t\tconst distance = Math.sqrt( dx * dx + dy * dy );\n\n\t\tthis._dollyEnd.set( 0, distance );\n\n\t\tthis._dollyDelta.set( 0, Math.pow( this._dollyEnd.y / this._dollyStart.y, this.zoomSpeed ) );\n\n\t\tthis._dollyOut( this._dollyDelta.y );\n\n\t\tthis._dollyStart.copy( this._dollyEnd );\n\n\t\tconst centerX = ( event.pageX + position.x ) * 0.5;\n\t\tconst centerY = ( event.pageY + position.y ) * 0.5;\n\n\t\tthis._updateZoomParameters( centerX, centerY );\n\n\t}\n\n\t_handleTouchMoveDollyPan( event ) {\n\n\t\tif ( this.enableZoom ) this._handleTouchMoveDolly( event );\n\n\t\tif ( this.enablePan ) this._handleTouchMovePan( event );\n\n\t}\n\n\t_handleTouchMoveDollyRotate( event ) {\n\n\t\tif ( this.enableZoom ) this._handleTouchMoveDolly( event );\n\n\t\tif ( this.enableRotate ) this._handleTouchMoveRotate( event );\n\n\t}\n\n\t// pointers\n\n\t_addPointer( event ) {\n\n\t\tthis._pointers.push( event.pointerId );\n\n\t}\n\n\t_removePointer( event ) {\n\n\t\tdelete this._pointerPositions[ event.pointerId ];\n\n\t\tfor ( let i = 0; i < this._pointers.length; i ++ ) {\n\n\t\t\tif ( this._pointers[ i ] == event.pointerId ) {\n\n\t\t\t\tthis._pointers.splice( i, 1 );\n\t\t\t\treturn;\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t_isTrackingPointer( event ) {\n\n\t\tfor ( let i = 0; i < this._pointers.length; i ++ ) {\n\n\t\t\tif ( this._pointers[ i ] == event.pointerId ) return true;\n\n\t\t}\n\n\t\treturn false;\n\n\t}\n\n\t_trackPointer( event ) {\n\n\t\tlet position = this._pointerPositions[ event.pointerId ];\n\n\t\tif ( position === undefined ) {\n\n\t\t\tposition = new Vector2();\n\t\t\tthis._pointerPositions[ event.pointerId ] = position;\n\n\t\t}\n\n\t\tposition.set( event.pageX, event.pageY );\n\n\t}\n\n\t_getSecondPointerPosition( event ) {\n\n\t\tconst pointerId = ( event.pointerId === this._pointers[ 0 ] ) ? this._pointers[ 1 ] : this._pointers[ 0 ];\n\n\t\treturn this._pointerPositions[ pointerId ];\n\n\t}\n\n\t//\n\n\t_customWheelEvent( event ) {\n\n\t\tconst mode = event.deltaMode;\n\n\t\t// minimal wheel event altered to meet delta-zoom demand\n\t\tconst newEvent = {\n\t\t\tclientX: event.clientX,\n\t\t\tclientY: event.clientY,\n\t\t\tdeltaY: event.deltaY,\n\t\t};\n\n\t\tswitch ( mode ) {\n\n\t\t\tcase 1: // LINE_MODE\n\t\t\t\tnewEvent.deltaY *= 16;\n\t\t\t\tbreak;\n\n\t\t\tcase 2: // PAGE_MODE\n\t\t\t\tnewEvent.deltaY *= 100;\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\t// detect if event was triggered by pinching\n\t\tif ( event.ctrlKey && ! this._controlActive ) {\n\n\t\t\tnewEvent.deltaY *= 10;\n\n\t\t}\n\n\t\treturn newEvent;\n\n\t}\n\n}\n\nfunction onPointerDown( event ) {\n\n\tif ( this.enabled === false ) return;\n\n\tif ( this._pointers.length === 0 ) {\n\n\t\tthis.domElement.setPointerCapture( event.pointerId );\n\n\t\tthis.domElement.ownerDocument.addEventListener( 'pointermove', this._onPointerMove );\n\t\tthis.domElement.ownerDocument.addEventListener( 'pointerup', this._onPointerUp );\n\n\t}\n\n\t//\n\n\tif ( this._isTrackingPointer( event ) ) return;\n\n\t//\n\n\tthis._addPointer( event );\n\n\tif ( event.pointerType === 'touch' ) {\n\n\t\tthis._onTouchStart( event );\n\n\t} else {\n\n\t\tthis._onMouseDown( event );\n\n\t}\n\n\tif ( this._cursorStyle === 'grab' ) {\n\n\t\tthis.domElement.style.cursor = 'grabbing';\n\n\t}\n\n}\n\nfunction onPointerMove( event ) {\n\n\tif ( this.enabled === false ) return;\n\n\tif ( event.pointerType === 'touch' ) {\n\n\t\tthis._onTouchMove( event );\n\n\t} else {\n\n\t\tthis._onMouseMove( event );\n\n\t}\n\n}\n\nfunction onPointerUp( event ) {\n\n\tthis._removePointer( event );\n\n\tswitch ( this._pointers.length ) {\n\n\t\tcase 0:\n\n\t\t\tthis.domElement.releasePointerCapture( event.pointerId );\n\n\t\t\tthis.domElement.ownerDocument.removeEventListener( 'pointermove', this._onPointerMove );\n\t\t\tthis.domElement.ownerDocument.removeEventListener( 'pointerup', this._onPointerUp );\n\n\t\t\tthis.dispatchEvent( _endEvent );\n\n\t\t\tthis.state = _STATE.NONE;\n\n\t\t\tif ( this._cursorStyle === 'grab' ) {\n\n\t\t\t\tthis.domElement.style.cursor = 'grab';\n\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tcase 1:\n\n\t\t\tconst pointerId = this._pointers[ 0 ];\n\t\t\tconst position = this._pointerPositions[ pointerId ];\n\n\t\t\t// minimal placeholder event - allows state correction on pointer-up\n\t\t\tthis._onTouchStart( { pointerId: pointerId, pageX: position.x, pageY: position.y } );\n\n\t\t\tbreak;\n\n\t}\n\n}\n\nfunction onMouseDown( event ) {\n\n\tlet mouseAction;\n\n\tswitch ( event.button ) {\n\n\t\tcase 0:\n\n\t\t\tmouseAction = this.mouseButtons.LEFT;\n\t\t\tbreak;\n\n\t\tcase 1:\n\n\t\t\tmouseAction = this.mouseButtons.MIDDLE;\n\t\t\tbreak;\n\n\t\tcase 2:\n\n\t\t\tmouseAction = this.mouseButtons.RIGHT;\n\t\t\tbreak;\n\n\t\tdefault:\n\n\t\t\tmouseAction = - 1;\n\n\t}\n\n\tswitch ( mouseAction ) {\n\n\t\tcase MOUSE.DOLLY:\n\n\t\t\tif ( this.enableZoom === false ) return;\n\n\t\t\tthis._handleMouseDownDolly( event );\n\n\t\t\tthis.state = _STATE.DOLLY;\n\n\t\t\tbreak;\n\n\t\tcase MOUSE.ROTATE:\n\n\t\t\tif ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n\t\t\t\tif ( this.enablePan === false ) return;\n\n\t\t\t\tthis._handleMouseDownPan( event );\n\n\t\t\t\tthis.state = _STATE.PAN;\n\n\t\t\t} else {\n\n\t\t\t\tif ( this.enableRotate === false ) return;\n\n\t\t\t\tthis._handleMouseDownRotate( event );\n\n\t\t\t\tthis.state = _STATE.ROTATE;\n\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tcase MOUSE.PAN:\n\n\t\t\tif ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n\t\t\t\tif ( this.enableRotate === false ) return;\n\n\t\t\t\tthis._handleMouseDownRotate( event );\n\n\t\t\t\tthis.state = _STATE.ROTATE;\n\n\t\t\t} else {\n\n\t\t\t\tif ( this.enablePan === false ) return;\n\n\t\t\t\tthis._handleMouseDownPan( event );\n\n\t\t\t\tthis.state = _STATE.PAN;\n\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tdefault:\n\n\t\t\tthis.state = _STATE.NONE;\n\n\t}\n\n\tif ( this.state !== _STATE.NONE ) {\n\n\t\tthis.dispatchEvent( _startEvent );\n\n\t}\n\n}\n\nfunction onMouseMove( event ) {\n\n\tswitch ( this.state ) {\n\n\t\tcase _STATE.ROTATE:\n\n\t\t\tif ( this.enableRotate === false ) return;\n\n\t\t\tthis._handleMouseMoveRotate( event );\n\n\t\t\tbreak;\n\n\t\tcase _STATE.DOLLY:\n\n\t\t\tif ( this.enableZoom === false ) return;\n\n\t\t\tthis._handleMouseMoveDolly( event );\n\n\t\t\tbreak;\n\n\t\tcase _STATE.PAN:\n\n\t\t\tif ( this.enablePan === false ) return;\n\n\t\t\tthis._handleMouseMovePan( event );\n\n\t\t\tbreak;\n\n\t}\n\n}\n\nfunction onMouseWheel( event ) {\n\n\tif ( this.enabled === false || this.enableZoom === false || this.state !== _STATE.NONE ) return;\n\n\tevent.preventDefault();\n\n\tthis.dispatchEvent( _startEvent );\n\n\tthis._handleMouseWheel( this._customWheelEvent( event ) );\n\n\tthis.dispatchEvent( _endEvent );\n\n}\n\nfunction onKeyDown( event ) {\n\n\tif ( this.enabled === false ) return;\n\n\tthis._handleKeyDown( event );\n\n}\n\nfunction onTouchStart( event ) {\n\n\tthis._trackPointer( event );\n\n\tswitch ( this._pointers.length ) {\n\n\t\tcase 1:\n\n\t\t\tswitch ( this.touches.ONE ) {\n\n\t\t\t\tcase TOUCH.ROTATE:\n\n\t\t\t\t\tif ( this.enableRotate === false ) return;\n\n\t\t\t\t\tthis._handleTouchStartRotate( event );\n\n\t\t\t\t\tthis.state = _STATE.TOUCH_ROTATE;\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TOUCH.PAN:\n\n\t\t\t\t\tif ( this.enablePan === false ) return;\n\n\t\t\t\t\tthis._handleTouchStartPan( event );\n\n\t\t\t\t\tthis.state = _STATE.TOUCH_PAN;\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\n\t\t\t\t\tthis.state = _STATE.NONE;\n\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tcase 2:\n\n\t\t\tswitch ( this.touches.TWO ) {\n\n\t\t\t\tcase TOUCH.DOLLY_PAN:\n\n\t\t\t\t\tif ( this.enableZoom === false && this.enablePan === false ) return;\n\n\t\t\t\t\tthis._handleTouchStartDollyPan( event );\n\n\t\t\t\t\tthis.state = _STATE.TOUCH_DOLLY_PAN;\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TOUCH.DOLLY_ROTATE:\n\n\t\t\t\t\tif ( this.enableZoom === false && this.enableRotate === false ) return;\n\n\t\t\t\t\tthis._handleTouchStartDollyRotate( event );\n\n\t\t\t\t\tthis.state = _STATE.TOUCH_DOLLY_ROTATE;\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\n\t\t\t\t\tthis.state = _STATE.NONE;\n\n\t\t\t}\n\n\t\t\tbreak;\n\n\t\tdefault:\n\n\t\t\tthis.state = _STATE.NONE;\n\n\t}\n\n\tif ( this.state !== _STATE.NONE ) {\n\n\t\tthis.dispatchEvent( _startEvent );\n\n\t}\n\n}\n\nfunction onTouchMove( event ) {\n\n\tthis._trackPointer( event );\n\n\tswitch ( this.state ) {\n\n\t\tcase _STATE.TOUCH_ROTATE:\n\n\t\t\tif ( this.enableRotate === false ) return;\n\n\t\t\tthis._handleTouchMoveRotate( event );\n\n\t\t\tthis.update();\n\n\t\t\tbreak;\n\n\t\tcase _STATE.TOUCH_PAN:\n\n\t\t\tif ( this.enablePan === false ) return;\n\n\t\t\tthis._handleTouchMovePan( event );\n\n\t\t\tthis.update();\n\n\t\t\tbreak;\n\n\t\tcase _STATE.TOUCH_DOLLY_PAN:\n\n\t\t\tif ( this.enableZoom === false && this.enablePan === false ) return;\n\n\t\t\tthis._handleTouchMoveDollyPan( event );\n\n\t\t\tthis.update();\n\n\t\t\tbreak;\n\n\t\tcase _STATE.TOUCH_DOLLY_ROTATE:\n\n\t\t\tif ( this.enableZoom === false && this.enableRotate === false ) return;\n\n\t\t\tthis._handleTouchMoveDollyRotate( event );\n\n\t\t\tthis.update();\n\n\t\t\tbreak;\n\n\t\tdefault:\n\n\t\t\tthis.state = _STATE.NONE;\n\n\t}\n\n}\n\nfunction onContextMenu( event ) {\n\n\tif ( this.enabled === false ) return;\n\n\tevent.preventDefault();\n\n}\n\nfunction interceptControlDown( event ) {\n\n\tif ( event.key === 'Control' ) {\n\n\t\tthis._controlActive = true;\n\n\t\tconst document = this.domElement.getRootNode(); // offscreen canvas compatibility\n\n\t\tdocument.addEventListener( 'keyup', this._interceptControlUp, { passive: true, capture: true } );\n\n\t}\n\n}\n\nfunction interceptControlUp( event ) {\n\n\tif ( event.key === 'Control' ) {\n\n\t\tthis._controlActive = false;\n\n\t\tconst document = this.domElement.getRootNode(); // offscreen canvas compatibility\n\n\t\tdocument.removeEventListener( 'keyup', this._interceptControlUp, { passive: true, capture: true } );\n\n\t}\n\n}\n\nexport { OrbitControls };\n","import {\n\tBoxGeometry,\n\tBufferGeometry,\n\tControls,\n\tCylinderGeometry,\n\tDoubleSide,\n\tEuler,\n\tFloat32BufferAttribute,\n\tLine,\n\tLineBasicMaterial,\n\tMatrix4,\n\tMesh,\n\tMeshBasicMaterial,\n\tObject3D,\n\tOctahedronGeometry,\n\tPlaneGeometry,\n\tQuaternion,\n\tRaycaster,\n\tSphereGeometry,\n\tTorusGeometry,\n\tVector3\n} from 'three';\n\nconst _raycaster = new Raycaster();\n\nconst _tempVector = new Vector3();\nconst _tempVector2 = new Vector3();\nconst _tempQuaternion = new Quaternion();\nconst _unit = {\n\tX: new Vector3( 1, 0, 0 ),\n\tY: new Vector3( 0, 1, 0 ),\n\tZ: new Vector3( 0, 0, 1 )\n};\n\n/**\n * Fires if any type of change (object or property change) is performed. Property changes\n * are separate events you can add event listeners to. The event type is \"propertyname-changed\".\n *\n * @event TransformControls#change\n * @type {Object}\n */\nconst _changeEvent = { type: 'change' };\n\n/**\n * Fires if a pointer (mouse/touch) becomes active.\n *\n * @event TransformControls#mouseDown\n * @type {Object}\n */\nconst _mouseDownEvent = { type: 'mouseDown', mode: null };\n\n/**\n * Fires if a pointer (mouse/touch) is no longer active.\n *\n * @event TransformControls#mouseUp\n * @type {Object}\n */\nconst _mouseUpEvent = { type: 'mouseUp', mode: null };\n\n/**\n * Fires if the controlled 3D object is changed.\n *\n * @event TransformControls#objectChange\n * @type {Object}\n */\nconst _objectChangeEvent = { type: 'objectChange' };\n\n/**\n * This class can be used to transform objects in 3D space by adapting a similar interaction model\n * of DCC tools like Blender. Unlike other controls, it is not intended to transform the scene's camera.\n *\n * `TransformControls` expects that its attached 3D object is part of the scene graph.\n *\n * @augments Controls\n * @three_import import { TransformControls } from 'three/addons/controls/TransformControls.js';\n */\nclass TransformControls extends Controls {\n\n\t/**\n\t * Constructs a new controls instance.\n\t *\n\t * @param {Camera} camera - The camera of the rendered scene.\n\t * @param {?HTMLElement} domElement - The HTML element used for event listeners.\n\t */\n\tconstructor( camera, domElement = null ) {\n\n\t\tsuper( undefined, domElement );\n\n\t\tconst root = new TransformControlsRoot( this );\n\t\tthis._root = root;\n\n\t\tconst gizmo = new TransformControlsGizmo();\n\t\tthis._gizmo = gizmo;\n\t\troot.add( gizmo );\n\n\t\tconst plane = new TransformControlsPlane();\n\t\tthis._plane = plane;\n\t\troot.add( plane );\n\n\t\tconst scope = this;\n\n\t\t// Defined getter, setter and store for a property\n\t\tfunction defineProperty( propName, defaultValue ) {\n\n\t\t\tlet propValue = defaultValue;\n\n\t\t\tObject.defineProperty( scope, propName, {\n\n\t\t\t\tget: function () {\n\n\t\t\t\t\treturn propValue !== undefined ? propValue : defaultValue;\n\n\t\t\t\t},\n\n\t\t\t\tset: function ( value ) {\n\n\t\t\t\t\tif ( propValue !== value ) {\n\n\t\t\t\t\t\tpropValue = value;\n\t\t\t\t\t\tplane[ propName ] = value;\n\t\t\t\t\t\tgizmo[ propName ] = value;\n\n\t\t\t\t\t\tscope.dispatchEvent( { type: propName + '-changed', value: value } );\n\t\t\t\t\t\tscope.dispatchEvent( _changeEvent );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} );\n\n\t\t\tscope[ propName ] = defaultValue;\n\t\t\tplane[ propName ] = defaultValue;\n\t\t\tgizmo[ propName ] = defaultValue;\n\n\t\t}\n\n\t\t// Define properties with getters/setter\n\t\t// Setting the defined property will automatically trigger change event\n\t\t// Defined properties are passed down to gizmo and plane\n\n\t\t/**\n\t\t * The camera of the rendered scene.\n\t\t *\n\t\t * @name TransformControls#camera\n\t\t * @type {Camera}\n\t\t */\n\t\tdefineProperty( 'camera', camera );\n\t\tdefineProperty( 'object', undefined );\n\t\tdefineProperty( 'enabled', true );\n\n\t\t/**\n\t\t * The current transformation axis.\n\t\t *\n\t\t * @name TransformControls#axis\n\t\t * @type {string}\n\t\t */\n\t\tdefineProperty( 'axis', null );\n\n\t\t/**\n\t\t * The current transformation axis.\n\t\t *\n\t\t * @name TransformControls#mode\n\t\t * @type {('translate'|'rotate'|'scale')}\n\t\t * @default 'translate'\n\t\t */\n\t\tdefineProperty( 'mode', 'translate' );\n\n\t\t/**\n\t\t * By default, 3D objects are continuously translated. If you set this property to a numeric\n\t\t * value (world units), you can define in which steps the 3D object should be translated.\n\t\t *\n\t\t * @name TransformControls#translationSnap\n\t\t * @type {?number}\n\t\t * @default null\n\t\t */\n\t\tdefineProperty( 'translationSnap', null );\n\n\t\t/**\n\t\t * By default, 3D objects are continuously rotated. If you set this property to a numeric\n\t\t * value (radians), you can define in which steps the 3D object should be rotated.\n\t\t *\n\t\t * @name TransformControls#rotationSnap\n\t\t * @type {?number}\n\t\t * @default null\n\t\t */\n\t\tdefineProperty( 'rotationSnap', null );\n\n\t\t/**\n\t\t * By default, 3D objects are continuously scaled. If you set this property to a numeric\n\t\t * value, you can define in which steps the 3D object should be scaled.\n\t\t *\n\t\t * @name TransformControls#scaleSnap\n\t\t * @type {?number}\n\t\t * @default null\n\t\t */\n\t\tdefineProperty( 'scaleSnap', null );\n\n\t\t/**\n\t\t * Defines in which coordinate space transformations should be performed.\n\t\t *\n\t\t * @name TransformControls#space\n\t\t * @type {('world'|'local')}\n\t\t * @default 'world'\n\t\t */\n\t\tdefineProperty( 'space', 'world' );\n\n\t\t/**\n\t\t * The size of the helper UI (axes/planes).\n\t\t *\n\t\t * @name TransformControls#size\n\t\t * @type {number}\n\t\t * @default 1\n\t\t */\n\t\tdefineProperty( 'size', 1 );\n\n\t\t/**\n\t\t * Whether dragging is currently performed or not.\n\t\t *\n\t\t * @name TransformControls#dragging\n\t\t * @type {boolean}\n\t\t * @readonly\n\t\t * @default false\n\t\t */\n\t\tdefineProperty( 'dragging', false );\n\n\t\t/**\n\t\t * Whether the x-axis helper should be visible or not.\n\t\t *\n\t\t * @name TransformControls#showX\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t */\n\t\tdefineProperty( 'showX', true );\n\n\t\t/**\n\t\t * Whether the y-axis helper should be visible or not.\n\t\t *\n\t\t * @name TransformControls#showY\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t */\n\t\tdefineProperty( 'showY', true );\n\n\t\t/**\n\t\t * Whether the z-axis helper should be visible or not.\n\t\t *\n\t\t * @name TransformControls#showZ\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t */\n\t\tdefineProperty( 'showZ', true );\n\n\t\t/**\n\t\t * Whether the xy-plane helper should be visible or not.\n\t\t *\n\t\t * @name TransformControls#showXY\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t */\n\t\tdefineProperty( 'showXY', true );\n\n\t\t/**\n\t\t * Whether the yz-plane helper should be visible or not.\n\t\t *\n\t\t * @name TransformControls#showYZ\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t */\n\t\tdefineProperty( 'showYZ', true );\n\n\t\t/**\n\t\t * Whether the xz-axis helper should be visible or not.\n\t\t *\n\t\t * @name TransformControls#showXZ\n\t\t * @type {boolean}\n\t\t * @default true\n\t\t */\n\t\tdefineProperty( 'showXZ', true );\n\n\t\t/**\n\t\t * The minimum allowed X position during translation.\n\t\t *\n\t\t * @name TransformControls#minX\n\t\t * @type {number}\n\t\t * @default -Infinity\n\t\t */\n\t\tdefineProperty( 'minX', - Infinity );\n\n\t\t/**\n\t\t * The maximum allowed X position during translation.\n\t\t *\n\t\t * @name TransformControls#maxX\n\t\t * @type {number}\n\t\t * @default Infinity\n\t\t */\n\t\tdefineProperty( 'maxX', Infinity );\n\n\t\t/**\n\t\t * The minimum allowed y position during translation.\n\t\t *\n\t\t * @name TransformControls#minY\n\t\t * @type {number}\n\t\t * @default -Infinity\n\t\t */\n\t\tdefineProperty( 'minY', - Infinity );\n\n\t\t/**\n\t\t * The maximum allowed Y position during translation.\n\t\t *\n\t\t * @name TransformControls#maxY\n\t\t * @type {number}\n\t\t * @default Infinity\n\t\t */\n\t\tdefineProperty( 'maxY', Infinity );\n\n\t\t/**\n\t\t * The minimum allowed z position during translation.\n\t\t *\n\t\t * @name TransformControls#minZ\n\t\t * @type {number}\n\t\t * @default -Infinity\n\t\t */\n\t\tdefineProperty( 'minZ', - Infinity );\n\n\t\t/**\n\t\t * The maximum allowed Z position during translation.\n\t\t *\n\t\t * @name TransformControls#maxZ\n\t\t * @type {number}\n\t\t * @default Infinity\n\t\t */\n\t\tdefineProperty( 'maxZ', Infinity );\n\n\t\t// Reusable utility variables\n\n\t\tconst worldPosition = new Vector3();\n\t\tconst worldPositionStart = new Vector3();\n\t\tconst worldQuaternion = new Quaternion();\n\t\tconst worldQuaternionStart = new Quaternion();\n\t\tconst cameraPosition = new Vector3();\n\t\tconst cameraQuaternion = new Quaternion();\n\t\tconst pointStart = new Vector3();\n\t\tconst pointEnd = new Vector3();\n\t\tconst rotationAxis = new Vector3();\n\t\tconst rotationAngle = 0;\n\t\tconst eye = new Vector3();\n\n\t\t// TODO: remove properties unused in plane and gizmo\n\n\t\tdefineProperty( 'worldPosition', worldPosition );\n\t\tdefineProperty( 'worldPositionStart', worldPositionStart );\n\t\tdefineProperty( 'worldQuaternion', worldQuaternion );\n\t\tdefineProperty( 'worldQuaternionStart', worldQuaternionStart );\n\t\tdefineProperty( 'cameraPosition', cameraPosition );\n\t\tdefineProperty( 'cameraQuaternion', cameraQuaternion );\n\t\tdefineProperty( 'pointStart', pointStart );\n\t\tdefineProperty( 'pointEnd', pointEnd );\n\t\tdefineProperty( 'rotationAxis', rotationAxis );\n\t\tdefineProperty( 'rotationAngle', rotationAngle );\n\t\tdefineProperty( 'eye', eye );\n\n\t\tthis._offset = new Vector3();\n\t\tthis._startNorm = new Vector3();\n\t\tthis._endNorm = new Vector3();\n\t\tthis._cameraScale = new Vector3();\n\n\t\tthis._parentPosition = new Vector3();\n\t\tthis._parentQuaternion = new Quaternion();\n\t\tthis._parentQuaternionInv = new Quaternion();\n\t\tthis._parentScale = new Vector3();\n\n\t\tthis._worldScaleStart = new Vector3();\n\t\tthis._worldQuaternionInv = new Quaternion();\n\t\tthis._worldScale = new Vector3();\n\n\t\tthis._positionStart = new Vector3();\n\t\tthis._quaternionStart = new Quaternion();\n\t\tthis._scaleStart = new Vector3();\n\n\t\tthis._getPointer = getPointer.bind( this );\n\t\tthis._onPointerDown = onPointerDown.bind( this );\n\t\tthis._onPointerHover = onPointerHover.bind( this );\n\t\tthis._onPointerMove = onPointerMove.bind( this );\n\t\tthis._onPointerUp = onPointerUp.bind( this );\n\n\t\tif ( domElement !== null ) {\n\n\t\t\tthis.connect( domElement );\n\n\t\t}\n\n\t}\n\n\tconnect( element ) {\n\n\t\tsuper.connect( element );\n\n\t\tthis.domElement.addEventListener( 'pointerdown', this._onPointerDown );\n\t\tthis.domElement.addEventListener( 'pointermove', this._onPointerHover );\n\t\tthis.domElement.addEventListener( 'pointerup', this._onPointerUp );\n\n\t\tthis.domElement.style.touchAction = 'none'; // Disable touch scroll\n\n\t}\n\n\tdisconnect() {\n\n\t\tthis.domElement.removeEventListener( 'pointerdown', this._onPointerDown );\n\t\tthis.domElement.removeEventListener( 'pointermove', this._onPointerHover );\n\t\tthis.domElement.removeEventListener( 'pointermove', this._onPointerMove );\n\t\tthis.domElement.removeEventListener( 'pointerup', this._onPointerUp );\n\n\t\tthis.domElement.style.touchAction = ''; // Restore touch scroll\n\n\t}\n\n\t/**\n\t * Returns the visual representation of the controls. Add the helper to your scene to\n\t * visually transform the attached 3D object.\n\t *\n\t * @return {TransformControlsRoot} The helper.\n\t */\n\tgetHelper() {\n\n\t\treturn this._root;\n\n\t}\n\n\tpointerHover( pointer ) {\n\n\t\tif ( this.object === undefined || this.dragging === true ) return;\n\n\t\tif ( pointer !== null ) _raycaster.setFromCamera( pointer, this.camera );\n\n\t\tconst intersect = intersectObjectWithRay( this._gizmo.picker[ this.mode ], _raycaster );\n\n\t\tif ( intersect ) {\n\n\t\t\tthis.axis = intersect.object.name;\n\n\t\t} else {\n\n\t\t\tthis.axis = null;\n\n\t\t}\n\n\t}\n\n\tpointerDown( pointer ) {\n\n\t\tif ( this.object === undefined || this.dragging === true || ( pointer != null && pointer.button !== 0 ) ) return;\n\n\t\tif ( this.axis !== null ) {\n\n\t\t\tif ( pointer !== null ) _raycaster.setFromCamera( pointer, this.camera );\n\n\t\t\tconst planeIntersect = intersectObjectWithRay( this._plane, _raycaster, true );\n\n\t\t\tif ( planeIntersect ) {\n\n\t\t\t\tthis.object.updateMatrixWorld();\n\t\t\t\tthis.object.parent.updateMatrixWorld();\n\n\t\t\t\tthis._positionStart.copy( this.object.position );\n\t\t\t\tthis._quaternionStart.copy( this.object.quaternion );\n\t\t\t\tthis._scaleStart.copy( this.object.scale );\n\n\t\t\t\tthis.object.matrixWorld.decompose( this.worldPositionStart, this.worldQuaternionStart, this._worldScaleStart );\n\n\t\t\t\tthis.pointStart.copy( planeIntersect.point ).sub( this.worldPositionStart );\n\n\t\t\t}\n\n\t\t\tthis.dragging = true;\n\t\t\t_mouseDownEvent.mode = this.mode;\n\t\t\tthis.dispatchEvent( _mouseDownEvent );\n\n\t\t}\n\n\t}\n\n\tpointerMove( pointer ) {\n\n\t\tconst axis = this.axis;\n\t\tconst mode = this.mode;\n\t\tconst object = this.object;\n\t\tlet space = this.space;\n\n\t\tif ( mode === 'scale' ) {\n\n\t\t\tspace = 'local';\n\n\t\t} else if ( axis === 'E' || axis === 'XYZE' || axis === 'XYZ' ) {\n\n\t\t\tspace = 'world';\n\n\t\t}\n\n\t\tif ( object === undefined || axis === null || this.dragging === false || ( pointer !== null && pointer.button !== - 1 ) ) return;\n\n\t\tif ( pointer !== null ) _raycaster.setFromCamera( pointer, this.camera );\n\n\t\tconst planeIntersect = intersectObjectWithRay( this._plane, _raycaster, true );\n\n\t\tif ( ! planeIntersect ) return;\n\n\t\tthis.pointEnd.copy( planeIntersect.point ).sub( this.worldPositionStart );\n\n\t\tif ( mode === 'translate' ) {\n\n\t\t\t// Apply translate\n\n\t\t\tthis._offset.copy( this.pointEnd ).sub( this.pointStart );\n\n\t\t\tif ( space === 'local' && axis !== 'XYZ' ) {\n\n\t\t\t\tthis._offset.applyQuaternion( this._worldQuaternionInv );\n\n\t\t\t}\n\n\t\t\tif ( axis.indexOf( 'X' ) === - 1 ) this._offset.x = 0;\n\t\t\tif ( axis.indexOf( 'Y' ) === - 1 ) this._offset.y = 0;\n\t\t\tif ( axis.indexOf( 'Z' ) === - 1 ) this._offset.z = 0;\n\n\t\t\tif ( space === 'local' && axis !== 'XYZ' ) {\n\n\t\t\t\tthis._offset.applyQuaternion( this._quaternionStart ).divide( this._parentScale );\n\n\t\t\t} else {\n\n\t\t\t\tthis._offset.applyQuaternion( this._parentQuaternionInv ).divide( this._parentScale );\n\n\t\t\t}\n\n\t\t\tobject.position.copy( this._offset ).add( this._positionStart );\n\n\t\t\t// Apply translation snap\n\n\t\t\tif ( this.translationSnap ) {\n\n\t\t\t\tif ( space === 'local' ) {\n\n\t\t\t\t\tobject.position.applyQuaternion( _tempQuaternion.copy( this._quaternionStart ).invert() );\n\n\t\t\t\t\tif ( axis.search( 'X' ) !== - 1 ) {\n\n\t\t\t\t\t\tobject.position.x = Math.round( object.position.x / this.translationSnap ) * this.translationSnap;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( axis.search( 'Y' ) !== - 1 ) {\n\n\t\t\t\t\t\tobject.position.y = Math.round( object.position.y / this.translationSnap ) * this.translationSnap;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( axis.search( 'Z' ) !== - 1 ) {\n\n\t\t\t\t\t\tobject.position.z = Math.round( object.position.z / this.translationSnap ) * this.translationSnap;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tobject.position.applyQuaternion( this._quaternionStart );\n\n\t\t\t\t}\n\n\t\t\t\tif ( space === 'world' ) {\n\n\t\t\t\t\tif ( object.parent ) {\n\n\t\t\t\t\t\tobject.position.add( _tempVector.setFromMatrixPosition( object.parent.matrixWorld ) );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( axis.search( 'X' ) !== - 1 ) {\n\n\t\t\t\t\t\tobject.position.x = Math.round( object.position.x / this.translationSnap ) * this.translationSnap;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( axis.search( 'Y' ) !== - 1 ) {\n\n\t\t\t\t\t\tobject.position.y = Math.round( object.position.y / this.translationSnap ) * this.translationSnap;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( axis.search( 'Z' ) !== - 1 ) {\n\n\t\t\t\t\t\tobject.position.z = Math.round( object.position.z / this.translationSnap ) * this.translationSnap;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( object.parent ) {\n\n\t\t\t\t\t\tobject.position.sub( _tempVector.setFromMatrixPosition( object.parent.matrixWorld ) );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tobject.position.x = Math.max( this.minX, Math.min( this.maxX, object.position.x ) );\n\t\t\tobject.position.y = Math.max( this.minY, Math.min( this.maxY, object.position.y ) );\n\t\t\tobject.position.z = Math.max( this.minZ, Math.min( this.maxZ, object.position.z ) );\n\n\t\t} else if ( mode === 'scale' ) {\n\n\t\t\tif ( axis.search( 'XYZ' ) !== - 1 ) {\n\n\t\t\t\tlet d = this.pointEnd.length() / this.pointStart.length();\n\n\t\t\t\tif ( this.pointEnd.dot( this.pointStart ) < 0 ) d *= - 1;\n\n\t\t\t\t_tempVector2.set( d, d, d );\n\n\t\t\t} else {\n\n\t\t\t\t_tempVector.copy( this.pointStart );\n\t\t\t\t_tempVector2.copy( this.pointEnd );\n\n\t\t\t\t_tempVector.applyQuaternion( this._worldQuaternionInv );\n\t\t\t\t_tempVector2.applyQuaternion( this._worldQuaternionInv );\n\n\t\t\t\t_tempVector2.divide( _tempVector );\n\n\t\t\t\tif ( axis.search( 'X' ) === - 1 ) {\n\n\t\t\t\t\t_tempVector2.x = 1;\n\n\t\t\t\t}\n\n\t\t\t\tif ( axis.search( 'Y' ) === - 1 ) {\n\n\t\t\t\t\t_tempVector2.y = 1;\n\n\t\t\t\t}\n\n\t\t\t\tif ( axis.search( 'Z' ) === - 1 ) {\n\n\t\t\t\t\t_tempVector2.z = 1;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// Apply scale\n\n\t\t\tobject.scale.copy( this._scaleStart ).multiply( _tempVector2 );\n\n\t\t\tif ( this.scaleSnap ) {\n\n\t\t\t\tif ( axis.search( 'X' ) !== - 1 ) {\n\n\t\t\t\t\tobject.scale.x = Math.round( object.scale.x / this.scaleSnap ) * this.scaleSnap || this.scaleSnap;\n\n\t\t\t\t}\n\n\t\t\t\tif ( axis.search( 'Y' ) !== - 1 ) {\n\n\t\t\t\t\tobject.scale.y = Math.round( object.scale.y / this.scaleSnap ) * this.scaleSnap || this.scaleSnap;\n\n\t\t\t\t}\n\n\t\t\t\tif ( axis.search( 'Z' ) !== - 1 ) {\n\n\t\t\t\t\tobject.scale.z = Math.round( object.scale.z / this.scaleSnap ) * this.scaleSnap || this.scaleSnap;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else if ( mode === 'rotate' ) {\n\n\t\t\tthis._offset.copy( this.pointEnd ).sub( this.pointStart );\n\n\t\t\tconst ROTATION_SPEED = 20 / this.worldPosition.distanceTo( _tempVector.setFromMatrixPosition( this.camera.matrixWorld ) );\n\n\t\t\tlet _inPlaneRotation = false;\n\n\t\t\tif ( axis === 'XYZE' ) {\n\n\t\t\t\tthis.rotationAxis.copy( this._offset ).cross( this.eye ).normalize();\n\t\t\t\tthis.rotationAngle = this._offset.dot( _tempVector.copy( this.rotationAxis ).cross( this.eye ) ) * ROTATION_SPEED;\n\n\t\t\t} else if ( axis === 'X' || axis === 'Y' || axis === 'Z' ) {\n\n\t\t\t\tthis.rotationAxis.copy( _unit[ axis ] );\n\n\t\t\t\t_tempVector.copy( _unit[ axis ] );\n\n\t\t\t\tif ( space === 'local' ) {\n\n\t\t\t\t\t_tempVector.applyQuaternion( this.worldQuaternion );\n\n\t\t\t\t}\n\n\t\t\t\t_tempVector.cross( this.eye );\n\n\t\t\t\t// When _tempVector is 0 after cross with this.eye the vectors are parallel and should use in-plane rotation logic.\n\t\t\t\tif ( _tempVector.length() === 0 ) {\n\n\t\t\t\t\t_inPlaneRotation = true;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthis.rotationAngle = this._offset.dot( _tempVector.normalize() ) * ROTATION_SPEED;\n\n\t\t\t\t}\n\n\n\t\t\t}\n\n\t\t\tif ( axis === 'E' || _inPlaneRotation ) {\n\n\t\t\t\tthis.rotationAxis.copy( this.eye );\n\t\t\t\tthis.rotationAngle = this.pointEnd.angleTo( this.pointStart );\n\n\t\t\t\tthis._startNorm.copy( this.pointStart ).normalize();\n\t\t\t\tthis._endNorm.copy( this.pointEnd ).normalize();\n\n\t\t\t\tthis.rotationAngle *= ( this._endNorm.cross( this._startNorm ).dot( this.eye ) < 0 ? 1 : - 1 );\n\n\t\t\t}\n\n\t\t\t// Apply rotation snap\n\n\t\t\tif ( this.rotationSnap ) this.rotationAngle = Math.round( this.rotationAngle / this.rotationSnap ) * this.rotationSnap;\n\n\t\t\t// Apply rotate\n\t\t\tif ( space === 'local' && axis !== 'E' && axis !== 'XYZE' ) {\n\n\t\t\t\tobject.quaternion.copy( this._quaternionStart );\n\t\t\t\tobject.quaternion.multiply( _tempQuaternion.setFromAxisAngle( this.rotationAxis, this.rotationAngle ) ).normalize();\n\n\t\t\t} else {\n\n\t\t\t\tthis.rotationAxis.applyQuaternion( this._parentQuaternionInv );\n\t\t\t\tobject.quaternion.copy( _tempQuaternion.setFromAxisAngle( this.rotationAxis, this.rotationAngle ) );\n\t\t\t\tobject.quaternion.multiply( this._quaternionStart ).normalize();\n\n\t\t\t}\n\n\t\t}\n\n\t\tthis.dispatchEvent( _changeEvent );\n\t\tthis.dispatchEvent( _objectChangeEvent );\n\n\t}\n\n\tpointerUp( pointer ) {\n\n\t\tif ( pointer !== null && pointer.button !== 0 ) return;\n\n\t\tif ( this.dragging && ( this.axis !== null ) ) {\n\n\t\t\t_mouseUpEvent.mode = this.mode;\n\t\t\tthis.dispatchEvent( _mouseUpEvent );\n\n\t\t}\n\n\t\tthis.dragging = false;\n\t\tthis.axis = null;\n\n\t}\n\n\tdispose() {\n\n\t\tthis.disconnect();\n\n\t\tthis._root.dispose();\n\n\t}\n\n\t/**\n\t * Sets the 3D object that should be transformed and ensures the controls UI is visible.\n\t *\n\t * @param {Object3D} object - The 3D object that should be transformed.\n\t * @return {TransformControls} A reference to this controls.\n\t */\n\tattach( object ) {\n\n\t\tthis.object = object;\n\t\tthis._root.visible = true;\n\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Removes the current 3D object from the controls and makes the helper UI invisible.\n\t *\n\t * @return {TransformControls} A reference to this controls.\n\t */\n\tdetach() {\n\n\t\tthis.object = undefined;\n\t\tthis.axis = null;\n\n\t\tthis._root.visible = false;\n\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Resets the object's position, rotation and scale to when the current transform began.\n\t */\n\treset() {\n\n\t\tif ( ! this.enabled ) return;\n\n\t\tif ( this.dragging ) {\n\n\t\t\tthis.object.position.copy( this._positionStart );\n\t\t\tthis.object.quaternion.copy( this._quaternionStart );\n\t\t\tthis.object.scale.copy( this._scaleStart );\n\n\t\t\tthis.dispatchEvent( _changeEvent );\n\t\t\tthis.dispatchEvent( _objectChangeEvent );\n\n\t\t\tthis.pointStart.copy( this.pointEnd );\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Returns the raycaster that is used for user interaction. This object is shared between all\n\t * instances of `TransformControls`.\n\t *\n\t * @returns {Raycaster} The internal raycaster.\n\t */\n\tgetRaycaster() {\n\n\t\treturn _raycaster;\n\n\t}\n\n\t/**\n\t * Returns the transformation mode.\n\t *\n\t * @returns {'translate'|'rotate'|'scale'} The transformation mode.\n\t */\n\tgetMode() {\n\n\t\treturn this.mode;\n\n\t}\n\n\t/**\n\t * Sets the given transformation mode.\n\t *\n\t * @param {'translate'|'rotate'|'scale'} mode - The transformation mode to set.\n\t */\n\tsetMode( mode ) {\n\n\t\tthis.mode = mode;\n\n\t}\n\n\t/**\n\t * Sets the translation snap.\n\t *\n\t * @param {?number} translationSnap - The translation snap to set.\n\t */\n\tsetTranslationSnap( translationSnap ) {\n\n\t\tthis.translationSnap = translationSnap;\n\n\t}\n\n\t/**\n\t * Sets the rotation snap.\n\t *\n\t * @param {?number} rotationSnap - The rotation snap to set.\n\t */\n\tsetRotationSnap( rotationSnap ) {\n\n\t\tthis.rotationSnap = rotationSnap;\n\n\t}\n\n\t/**\n\t * Sets the scale snap.\n\t *\n\t * @param {?number} scaleSnap - The scale snap to set.\n\t */\n\tsetScaleSnap( scaleSnap ) {\n\n\t\tthis.scaleSnap = scaleSnap;\n\n\t}\n\n\t/**\n\t * Sets the size of the helper UI.\n\t *\n\t * @param {number} size - The size to set.\n\t */\n\tsetSize( size ) {\n\n\t\tthis.size = size;\n\n\t}\n\n\t/**\n\t * Sets the coordinate space in which transformations are applied.\n\t *\n\t * @param {'world'|'local'} space - The space to set.\n\t */\n\tsetSpace( space ) {\n\n\t\tthis.space = space;\n\n\t}\n\n\t/**\n\t * Sets the colors of the control's gizmo.\n\t *\n\t * @param {number|Color|string} xAxis - The x-axis color.\n\t * @param {number|Color|string} yAxis - The y-axis color.\n\t * @param {number|Color|string} zAxis - The z-axis color.\n\t * @param {number|Color|string} active - The color for active elements.\n\t */\n\tsetColors( xAxis, yAxis, zAxis, active ) {\n\n\t\tconst materialLib = this._gizmo.materialLib;\n\n\t\tmaterialLib.xAxis.color.set( xAxis );\n\t\tmaterialLib.yAxis.color.set( yAxis );\n\t\tmaterialLib.zAxis.color.set( zAxis );\n\t\tmaterialLib.active.color.set( active );\n\t\tmaterialLib.xAxisTransparent.color.set( xAxis );\n\t\tmaterialLib.yAxisTransparent.color.set( yAxis );\n\t\tmaterialLib.zAxisTransparent.color.set( zAxis );\n\t\tmaterialLib.activeTransparent.color.set( active );\n\n\t\t// update color caches\n\n\t\tif ( materialLib.xAxis._color ) materialLib.xAxis._color.set( xAxis );\n\t\tif ( materialLib.yAxis._color ) materialLib.yAxis._color.set( yAxis );\n\t\tif ( materialLib.zAxis._color ) materialLib.zAxis._color.set( zAxis );\n\t\tif ( materialLib.active._color ) materialLib.active._color.set( active );\n\t\tif ( materialLib.xAxisTransparent._color ) materialLib.xAxisTransparent._color.set( xAxis );\n\t\tif ( materialLib.yAxisTransparent._color ) materialLib.yAxisTransparent._color.set( yAxis );\n\t\tif ( materialLib.zAxisTransparent._color ) materialLib.zAxisTransparent._color.set( zAxis );\n\t\tif ( materialLib.activeTransparent._color ) materialLib.activeTransparent._color.set( active );\n\n\t}\n\n}\n\n// mouse / touch event handlers\n\nfunction getPointer( event ) {\n\n\tif ( this.domElement.ownerDocument.pointerLockElement ) {\n\n\t\treturn {\n\t\t\tx: 0,\n\t\t\ty: 0,\n\t\t\tbutton: event.button\n\t\t};\n\n\t} else {\n\n\t\tconst rect = this.domElement.getBoundingClientRect();\n\n\t\treturn {\n\t\t\tx: ( event.clientX - rect.left ) / rect.width * 2 - 1,\n\t\t\ty: - ( event.clientY - rect.top ) / rect.height * 2 + 1,\n\t\t\tbutton: event.button\n\t\t};\n\n\t}\n\n}\n\nfunction onPointerHover( event ) {\n\n\tif ( ! this.enabled ) return;\n\n\tswitch ( event.pointerType ) {\n\n\t\tcase 'mouse':\n\t\tcase 'pen':\n\t\t\tthis.pointerHover( this._getPointer( event ) );\n\t\t\tbreak;\n\n\t}\n\n}\n\nfunction onPointerDown( event ) {\n\n\tif ( ! this.enabled ) return;\n\n\tif ( ! document.pointerLockElement ) {\n\n\t\tthis.domElement.setPointerCapture( event.pointerId );\n\n\t}\n\n\tthis.domElement.addEventListener( 'pointermove', this._onPointerMove );\n\n\tthis.pointerHover( this._getPointer( event ) );\n\tthis.pointerDown( this._getPointer( event ) );\n\n}\n\nfunction onPointerMove( event ) {\n\n\tif ( ! this.enabled ) return;\n\n\tthis.pointerMove( this._getPointer( event ) );\n\n}\n\nfunction onPointerUp( event ) {\n\n\tif ( ! this.enabled ) return;\n\n\tthis.domElement.releasePointerCapture( event.pointerId );\n\n\tthis.domElement.removeEventListener( 'pointermove', this._onPointerMove );\n\n\tthis.pointerUp( this._getPointer( event ) );\n\n}\n\nfunction intersectObjectWithRay( object, raycaster, includeInvisible ) {\n\n\tconst allIntersections = raycaster.intersectObject( object, true );\n\n\tfor ( let i = 0; i < allIntersections.length; i ++ ) {\n\n\t\tif ( allIntersections[ i ].object.visible || includeInvisible ) {\n\n\t\t\treturn allIntersections[ i ];\n\n\t\t}\n\n\t}\n\n\treturn false;\n\n}\n\n//\n\n// Reusable utility variables\n\nconst _tempEuler = new Euler();\nconst _alignVector = new Vector3( 0, 1, 0 );\nconst _zeroVector = new Vector3( 0, 0, 0 );\nconst _lookAtMatrix = new Matrix4();\nconst _tempQuaternion2 = new Quaternion();\nconst _identityQuaternion = new Quaternion();\nconst _dirVector = new Vector3();\nconst _tempMatrix = new Matrix4();\n\nconst _unitX = new Vector3( 1, 0, 0 );\nconst _unitY = new Vector3( 0, 1, 0 );\nconst _unitZ = new Vector3( 0, 0, 1 );\n\nconst _v1 = new Vector3();\nconst _v2 = new Vector3();\nconst _v3 = new Vector3();\n\nclass TransformControlsRoot extends Object3D {\n\n\tconstructor( controls ) {\n\n\t\tsuper();\n\n\t\tthis.isTransformControlsRoot = true;\n\n\t\tthis.controls = controls;\n\t\tthis.visible = false;\n\n\t}\n\n\t// updateMatrixWorld updates key transformation variables\n\tupdateMatrixWorld( force ) {\n\n\t\tconst controls = this.controls;\n\n\t\tif ( controls.object !== undefined ) {\n\n\t\t\tcontrols.object.updateMatrixWorld();\n\n\t\t\tif ( controls.object.parent === null ) {\n\n\t\t\t\tconsole.error( 'TransformControls: The attached 3D object must be a part of the scene graph.' );\n\n\t\t\t} else {\n\n\t\t\t\tcontrols.object.parent.matrixWorld.decompose( controls._parentPosition, controls._parentQuaternion, controls._parentScale );\n\n\t\t\t}\n\n\t\t\tcontrols.object.matrixWorld.decompose( controls.worldPosition, controls.worldQuaternion, controls._worldScale );\n\n\t\t\tcontrols._parentQuaternionInv.copy( controls._parentQuaternion ).invert();\n\t\t\tcontrols._worldQuaternionInv.copy( controls.worldQuaternion ).invert();\n\n\t\t}\n\n\t\tcontrols.camera.updateMatrixWorld();\n\t\tcontrols.camera.matrixWorld.decompose( controls.cameraPosition, controls.cameraQuaternion, controls._cameraScale );\n\n\t\tif ( controls.camera.isOrthographicCamera ) {\n\n\t\t\tcontrols.camera.getWorldDirection( controls.eye ).negate();\n\n\t\t} else {\n\n\t\t\tcontrols.eye.copy( controls.cameraPosition ).sub( controls.worldPosition ).normalize();\n\n\t\t}\n\n\t\tsuper.updateMatrixWorld( force );\n\n\t}\n\n\tdispose() {\n\n\t\tthis.traverse( function ( child ) {\n\n\t\t\tif ( child.geometry ) child.geometry.dispose();\n\t\t\tif ( child.material ) child.material.dispose();\n\n\t\t} );\n\n\t}\n\n}\n\nclass TransformControlsGizmo extends Object3D {\n\n\tconstructor() {\n\n\t\tsuper();\n\n\t\tthis.isTransformControlsGizmo = true;\n\n\t\tthis.type = 'TransformControlsGizmo';\n\n\t\t// shared materials\n\n\t\tconst gizmoMaterial = new MeshBasicMaterial( {\n\t\t\tdepthTest: false,\n\t\t\tdepthWrite: false,\n\t\t\tfog: false,\n\t\t\ttoneMapped: false,\n\t\t\ttransparent: true\n\t\t} );\n\n\t\tconst gizmoLineMaterial = new LineBasicMaterial( {\n\t\t\tdepthTest: false,\n\t\t\tdepthWrite: false,\n\t\t\tfog: false,\n\t\t\ttoneMapped: false,\n\t\t\ttransparent: true\n\t\t} );\n\n\t\t// Make unique material for each axis/color\n\n\t\tconst matInvisible = gizmoMaterial.clone();\n\t\tmatInvisible.opacity = 0.15;\n\n\t\tconst matHelper = gizmoLineMaterial.clone();\n\t\tmatHelper.opacity = 0.5;\n\n\t\tconst matRed = gizmoMaterial.clone();\n\t\tmatRed.color.setHex( 0xff0000 );\n\n\t\tconst matGreen = gizmoMaterial.clone();\n\t\tmatGreen.color.setHex( 0x00ff00 );\n\n\t\tconst matBlue = gizmoMaterial.clone();\n\t\tmatBlue.color.setHex( 0x0000ff );\n\n\t\tconst matRedTransparent = gizmoMaterial.clone();\n\t\tmatRedTransparent.color.setHex( 0xff0000 );\n\t\tmatRedTransparent.opacity = 0.5;\n\n\t\tconst matGreenTransparent = gizmoMaterial.clone();\n\t\tmatGreenTransparent.color.setHex( 0x00ff00 );\n\t\tmatGreenTransparent.opacity = 0.5;\n\n\t\tconst matBlueTransparent = gizmoMaterial.clone();\n\t\tmatBlueTransparent.color.setHex( 0x0000ff );\n\t\tmatBlueTransparent.opacity = 0.5;\n\n\t\tconst matWhiteTransparent = gizmoMaterial.clone();\n\t\tmatWhiteTransparent.opacity = 0.25;\n\n\t\tconst matYellowTransparent = gizmoMaterial.clone();\n\t\tmatYellowTransparent.color.setHex( 0xffff00 );\n\t\tmatYellowTransparent.opacity = 0.25;\n\n\t\tconst matYellow = gizmoMaterial.clone();\n\t\tmatYellow.color.setHex( 0xffff00 );\n\n\t\tconst matGray = gizmoMaterial.clone();\n\t\tmatGray.color.setHex( 0x787878 );\n\n\t\t// materials in the below property are configurable via setColors()\n\n\t\tthis.materialLib = {\n\t\t\txAxis: matRed,\n\t\t\tyAxis: matGreen,\n\t\t\tzAxis: matBlue,\n\t\t\tactive: matYellow,\n\t\t\txAxisTransparent: matRedTransparent,\n\t\t\tyAxisTransparent: matGreenTransparent,\n\t\t\tzAxisTransparent: matBlueTransparent,\n\t\t\tactiveTransparent: matYellowTransparent\n\t\t};\n\n\t\t// reusable geometry\n\n\t\tconst arrowGeometry = new CylinderGeometry( 0, 0.04, 0.1, 12 );\n\t\tarrowGeometry.translate( 0, 0.05, 0 );\n\n\t\tconst scaleHandleGeometry = new BoxGeometry( 0.08, 0.08, 0.08 );\n\t\tscaleHandleGeometry.translate( 0, 0.04, 0 );\n\n\t\tconst lineGeometry = new BufferGeometry();\n\t\tlineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0,\t1, 0, 0 ], 3 ) );\n\n\t\tconst lineGeometry2 = new CylinderGeometry( 0.0075, 0.0075, 0.5, 3 );\n\t\tlineGeometry2.translate( 0, 0.25, 0 );\n\n\t\tfunction CircleGeometry( radius, arc ) {\n\n\t\t\tconst geometry = new TorusGeometry( radius, 0.0075, 3, 64, arc * Math.PI * 2 );\n\t\t\tgeometry.rotateY( Math.PI / 2 );\n\t\t\tgeometry.rotateX( Math.PI / 2 );\n\t\t\treturn geometry;\n\n\t\t}\n\n\t\t// Special geometry for transform helper. If scaled with position vector it spans from [0,0,0] to position\n\n\t\tfunction TranslateHelperGeometry() {\n\n\t\t\tconst geometry = new BufferGeometry();\n\n\t\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 1, 1, 1 ], 3 ) );\n\n\t\t\treturn geometry;\n\n\t\t}\n\n\t\t// Gizmo definitions - custom hierarchy definitions for setupGizmo() function\n\n\t\tconst gizmoTranslate = {\n\t\t\tX: [\n\t\t\t\t[ new Mesh( arrowGeometry, matRed ), [ 0.5, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],\n\t\t\t\t[ new Mesh( arrowGeometry, matRed ), [ - 0.5, 0, 0 ], [ 0, 0, Math.PI / 2 ]],\n\t\t\t\t[ new Mesh( lineGeometry2, matRed ), [ 0, 0, 0 ], [ 0, 0, - Math.PI / 2 ]]\n\t\t\t],\n\t\t\tY: [\n\t\t\t\t[ new Mesh( arrowGeometry, matGreen ), [ 0, 0.5, 0 ]],\n\t\t\t\t[ new Mesh( arrowGeometry, matGreen ), [ 0, - 0.5, 0 ], [ Math.PI, 0, 0 ]],\n\t\t\t\t[ new Mesh( lineGeometry2, matGreen ) ]\n\t\t\t],\n\t\t\tZ: [\n\t\t\t\t[ new Mesh( arrowGeometry, matBlue ), [ 0, 0, 0.5 ], [ Math.PI / 2, 0, 0 ]],\n\t\t\t\t[ new Mesh( arrowGeometry, matBlue ), [ 0, 0, - 0.5 ], [ - Math.PI / 2, 0, 0 ]],\n\t\t\t\t[ new Mesh( lineGeometry2, matBlue ), null, [ Math.PI / 2, 0, 0 ]]\n\t\t\t],\n\t\t\tXYZ: [\n\t\t\t\t[ new Mesh( new OctahedronGeometry( 0.1, 0 ), matWhiteTransparent ), [ 0, 0, 0 ]]\n\t\t\t],\n\t\t\tXY: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.15, 0.15, 0.01 ), matBlueTransparent ), [ 0.15, 0.15, 0 ]]\n\t\t\t],\n\t\t\tYZ: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.15, 0.15, 0.01 ), matRedTransparent ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ]]\n\t\t\t],\n\t\t\tXZ: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.15, 0.15, 0.01 ), matGreenTransparent ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ]]\n\t\t\t]\n\t\t};\n\n\t\tconst pickerTranslate = {\n\t\t\tX: [\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0.3, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ - 0.3, 0, 0 ], [ 0, 0, Math.PI / 2 ]]\n\t\t\t],\n\t\t\tY: [\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0.3, 0 ]],\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, - 0.3, 0 ], [ 0, 0, Math.PI ]]\n\t\t\t],\n\t\t\tZ: [\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0, 0.3 ], [ Math.PI / 2, 0, 0 ]],\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0, - 0.3 ], [ - Math.PI / 2, 0, 0 ]]\n\t\t\t],\n\t\t\tXYZ: [\n\t\t\t\t[ new Mesh( new OctahedronGeometry( 0.2, 0 ), matInvisible ) ]\n\t\t\t],\n\t\t\tXY: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0.15, 0.15, 0 ]]\n\t\t\t],\n\t\t\tYZ: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ]]\n\t\t\t],\n\t\t\tXZ: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ]]\n\t\t\t]\n\t\t};\n\n\t\tconst helperTranslate = {\n\t\t\tSTART: [\n\t\t\t\t[ new Mesh( new OctahedronGeometry( 0.01, 2 ), matHelper ), null, null, null, 'helper' ]\n\t\t\t],\n\t\t\tEND: [\n\t\t\t\t[ new Mesh( new OctahedronGeometry( 0.01, 2 ), matHelper ), null, null, null, 'helper' ]\n\t\t\t],\n\t\t\tDELTA: [\n\t\t\t\t[ new Line( TranslateHelperGeometry(), matHelper ), null, null, null, 'helper' ]\n\t\t\t],\n\t\t\tX: [\n\t\t\t\t[ new Line( lineGeometry, matHelper ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]\n\t\t\t],\n\t\t\tY: [\n\t\t\t\t[ new Line( lineGeometry, matHelper ), [ 0, - 1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], 'helper' ]\n\t\t\t],\n\t\t\tZ: [\n\t\t\t\t[ new Line( lineGeometry, matHelper ), [ 0, 0, - 1e3 ], [ 0, - Math.PI / 2, 0 ], [ 1e6, 1, 1 ], 'helper' ]\n\t\t\t]\n\t\t};\n\n\t\tconst gizmoRotate = {\n\t\t\tXYZE: [\n\t\t\t\t[ new Mesh( CircleGeometry( 0.5, 1 ), matGray ), null, [ 0, Math.PI / 2, 0 ]]\n\t\t\t],\n\t\t\tX: [\n\t\t\t\t[ new Mesh( CircleGeometry( 0.5, 0.5 ), matRed ) ]\n\t\t\t],\n\t\t\tY: [\n\t\t\t\t[ new Mesh( CircleGeometry( 0.5, 0.5 ), matGreen ), null, [ 0, 0, - Math.PI / 2 ]]\n\t\t\t],\n\t\t\tZ: [\n\t\t\t\t[ new Mesh( CircleGeometry( 0.5, 0.5 ), matBlue ), null, [ 0, Math.PI / 2, 0 ]]\n\t\t\t],\n\t\t\tE: [\n\t\t\t\t[ new Mesh( CircleGeometry( 0.75, 1 ), matYellowTransparent ), null, [ 0, Math.PI / 2, 0 ]]\n\t\t\t]\n\t\t};\n\n\t\tconst helperRotate = {\n\t\t\tAXIS: [\n\t\t\t\t[ new Line( lineGeometry, matHelper ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]\n\t\t\t]\n\t\t};\n\n\t\tconst pickerRotate = {\n\t\t\tXYZE: [\n\t\t\t\t[ new Mesh( new SphereGeometry( 0.25, 10, 8 ), matInvisible ) ]\n\t\t\t],\n\t\t\tX: [\n\t\t\t\t[ new Mesh( new TorusGeometry( 0.5, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ 0, - Math.PI / 2, - Math.PI / 2 ]],\n\t\t\t],\n\t\t\tY: [\n\t\t\t\t[ new Mesh( new TorusGeometry( 0.5, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ Math.PI / 2, 0, 0 ]],\n\t\t\t],\n\t\t\tZ: [\n\t\t\t\t[ new Mesh( new TorusGeometry( 0.5, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],\n\t\t\t],\n\t\t\tE: [\n\t\t\t\t[ new Mesh( new TorusGeometry( 0.75, 0.1, 2, 24 ), matInvisible ) ]\n\t\t\t]\n\t\t};\n\n\t\tconst gizmoScale = {\n\t\t\tX: [\n\t\t\t\t[ new Mesh( scaleHandleGeometry, matRed ), [ 0.5, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],\n\t\t\t\t[ new Mesh( lineGeometry2, matRed ), [ 0, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],\n\t\t\t\t[ new Mesh( scaleHandleGeometry, matRed ), [ - 0.5, 0, 0 ], [ 0, 0, Math.PI / 2 ]],\n\t\t\t],\n\t\t\tY: [\n\t\t\t\t[ new Mesh( scaleHandleGeometry, matGreen ), [ 0, 0.5, 0 ]],\n\t\t\t\t[ new Mesh( lineGeometry2, matGreen ) ],\n\t\t\t\t[ new Mesh( scaleHandleGeometry, matGreen ), [ 0, - 0.5, 0 ], [ 0, 0, Math.PI ]],\n\t\t\t],\n\t\t\tZ: [\n\t\t\t\t[ new Mesh( scaleHandleGeometry, matBlue ), [ 0, 0, 0.5 ], [ Math.PI / 2, 0, 0 ]],\n\t\t\t\t[ new Mesh( lineGeometry2, matBlue ), [ 0, 0, 0 ], [ Math.PI / 2, 0, 0 ]],\n\t\t\t\t[ new Mesh( scaleHandleGeometry, matBlue ), [ 0, 0, - 0.5 ], [ - Math.PI / 2, 0, 0 ]]\n\t\t\t],\n\t\t\tXY: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.15, 0.15, 0.01 ), matBlueTransparent ), [ 0.15, 0.15, 0 ]]\n\t\t\t],\n\t\t\tYZ: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.15, 0.15, 0.01 ), matRedTransparent ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ]]\n\t\t\t],\n\t\t\tXZ: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.15, 0.15, 0.01 ), matGreenTransparent ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ]]\n\t\t\t],\n\t\t\tXYZ: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.1, 0.1, 0.1 ), matWhiteTransparent ) ],\n\t\t\t]\n\t\t};\n\n\t\tconst pickerScale = {\n\t\t\tX: [\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0.3, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ - 0.3, 0, 0 ], [ 0, 0, Math.PI / 2 ]]\n\t\t\t],\n\t\t\tY: [\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0.3, 0 ]],\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, - 0.3, 0 ], [ 0, 0, Math.PI ]]\n\t\t\t],\n\t\t\tZ: [\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0, 0.3 ], [ Math.PI / 2, 0, 0 ]],\n\t\t\t\t[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0, - 0.3 ], [ - Math.PI / 2, 0, 0 ]]\n\t\t\t],\n\t\t\tXY: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0.15, 0.15, 0 ]],\n\t\t\t],\n\t\t\tYZ: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ]],\n\t\t\t],\n\t\t\tXZ: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ]],\n\t\t\t],\n\t\t\tXYZ: [\n\t\t\t\t[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 0, 0, 0 ]],\n\t\t\t]\n\t\t};\n\n\t\tconst helperScale = {\n\t\t\tX: [\n\t\t\t\t[ new Line( lineGeometry, matHelper ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]\n\t\t\t],\n\t\t\tY: [\n\t\t\t\t[ new Line( lineGeometry, matHelper ), [ 0, - 1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], 'helper' ]\n\t\t\t],\n\t\t\tZ: [\n\t\t\t\t[ new Line( lineGeometry, matHelper ), [ 0, 0, - 1e3 ], [ 0, - Math.PI / 2, 0 ], [ 1e6, 1, 1 ], 'helper' ]\n\t\t\t]\n\t\t};\n\n\t\t// Creates an Object3D with gizmos described in custom hierarchy definition.\n\n\t\tfunction setupGizmo( gizmoMap ) {\n\n\t\t\tconst gizmo = new Object3D();\n\n\t\t\tfor ( const name in gizmoMap ) {\n\n\t\t\t\tfor ( let i = gizmoMap[ name ].length; i --; ) {\n\n\t\t\t\t\tconst object = gizmoMap[ name ][ i ][ 0 ].clone();\n\t\t\t\t\tconst position = gizmoMap[ name ][ i ][ 1 ];\n\t\t\t\t\tconst rotation = gizmoMap[ name ][ i ][ 2 ];\n\t\t\t\t\tconst scale = gizmoMap[ name ][ i ][ 3 ];\n\t\t\t\t\tconst tag = gizmoMap[ name ][ i ][ 4 ];\n\n\t\t\t\t\t// name and tag properties are essential for picking and updating logic.\n\t\t\t\t\tobject.name = name;\n\t\t\t\t\tobject.tag = tag;\n\n\t\t\t\t\tif ( position ) {\n\n\t\t\t\t\t\tobject.position.set( position[ 0 ], position[ 1 ], position[ 2 ] );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( rotation ) {\n\n\t\t\t\t\t\tobject.rotation.set( rotation[ 0 ], rotation[ 1 ], rotation[ 2 ] );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( scale ) {\n\n\t\t\t\t\t\tobject.scale.set( scale[ 0 ], scale[ 1 ], scale[ 2 ] );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tobject.updateMatrix();\n\n\t\t\t\t\tconst tempGeometry = object.geometry.clone();\n\t\t\t\t\ttempGeometry.applyMatrix4( object.matrix );\n\t\t\t\t\tobject.geometry = tempGeometry;\n\t\t\t\t\tobject.renderOrder = Infinity;\n\n\t\t\t\t\tobject.position.set( 0, 0, 0 );\n\t\t\t\t\tobject.rotation.set( 0, 0, 0 );\n\t\t\t\t\tobject.scale.set( 1, 1, 1 );\n\n\t\t\t\t\tgizmo.add( object );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn gizmo;\n\n\t\t}\n\n\t\t// Gizmo creation\n\n\t\tthis.gizmo = {};\n\t\tthis.picker = {};\n\t\tthis.helper = {};\n\n\t\tthis.add( this.gizmo[ 'translate' ] = setupGizmo( gizmoTranslate ) );\n\t\tthis.add( this.gizmo[ 'rotate' ] = setupGizmo( gizmoRotate ) );\n\t\tthis.add( this.gizmo[ 'scale' ] = setupGizmo( gizmoScale ) );\n\t\tthis.add( this.picker[ 'translate' ] = setupGizmo( pickerTranslate ) );\n\t\tthis.add( this.picker[ 'rotate' ] = setupGizmo( pickerRotate ) );\n\t\tthis.add( this.picker[ 'scale' ] = setupGizmo( pickerScale ) );\n\t\tthis.add( this.helper[ 'translate' ] = setupGizmo( helperTranslate ) );\n\t\tthis.add( this.helper[ 'rotate' ] = setupGizmo( helperRotate ) );\n\t\tthis.add( this.helper[ 'scale' ] = setupGizmo( helperScale ) );\n\n\t\t// Pickers should be hidden always\n\n\t\tthis.picker[ 'translate' ].visible = false;\n\t\tthis.picker[ 'rotate' ].visible = false;\n\t\tthis.picker[ 'scale' ].visible = false;\n\n\t}\n\n\t// updateMatrixWorld will update transformations and appearance of individual handles\n\n\tupdateMatrixWorld( force ) {\n\n\t\tconst space = ( this.mode === 'scale' ) ? 'local' : this.space; // scale always oriented to local rotation\n\n\t\tconst quaternion = ( space === 'local' ) ? this.worldQuaternion : _identityQuaternion;\n\n\t\t// Show only gizmos for current transform mode\n\n\t\tthis.gizmo[ 'translate' ].visible = this.mode === 'translate';\n\t\tthis.gizmo[ 'rotate' ].visible = this.mode === 'rotate';\n\t\tthis.gizmo[ 'scale' ].visible = this.mode === 'scale';\n\n\t\tthis.helper[ 'translate' ].visible = this.mode === 'translate';\n\t\tthis.helper[ 'rotate' ].visible = this.mode === 'rotate';\n\t\tthis.helper[ 'scale' ].visible = this.mode === 'scale';\n\n\n\t\tlet handles = [];\n\t\thandles = handles.concat( this.picker[ this.mode ].children );\n\t\thandles = handles.concat( this.gizmo[ this.mode ].children );\n\t\thandles = handles.concat( this.helper[ this.mode ].children );\n\n\t\tfor ( let i = 0; i < handles.length; i ++ ) {\n\n\t\t\tconst handle = handles[ i ];\n\n\t\t\t// hide aligned to camera\n\n\t\t\thandle.visible = true;\n\t\t\thandle.rotation.set( 0, 0, 0 );\n\t\t\thandle.position.copy( this.worldPosition );\n\n\t\t\tlet factor;\n\n\t\t\tif ( this.camera.isOrthographicCamera ) {\n\n\t\t\t\tfactor = ( this.camera.top - this.camera.bottom ) / this.camera.zoom;\n\n\t\t\t} else {\n\n\t\t\t\tfactor = this.worldPosition.distanceTo( this.cameraPosition ) * Math.min( 1.9 * Math.tan( Math.PI * this.camera.fov / 360 ) / this.camera.zoom, 7 );\n\n\t\t\t}\n\n\t\t\thandle.scale.set( 1, 1, 1 ).multiplyScalar( factor * this.size / 4 );\n\n\t\t\t// TODO: simplify helpers and consider decoupling from gizmo\n\n\t\t\tif ( handle.tag === 'helper' ) {\n\n\t\t\t\thandle.visible = false;\n\n\t\t\t\tif ( handle.name === 'AXIS' ) {\n\n\t\t\t\t\thandle.visible = !! this.axis;\n\n\t\t\t\t\tif ( this.axis === 'X' ) {\n\n\t\t\t\t\t\t_tempQuaternion.setFromEuler( _tempEuler.set( 0, 0, 0 ) );\n\t\t\t\t\t\thandle.quaternion.copy( quaternion ).multiply( _tempQuaternion );\n\n\t\t\t\t\t\tif ( Math.abs( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) {\n\n\t\t\t\t\t\t\thandle.visible = false;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( this.axis === 'Y' ) {\n\n\t\t\t\t\t\t_tempQuaternion.setFromEuler( _tempEuler.set( 0, 0, Math.PI / 2 ) );\n\t\t\t\t\t\thandle.quaternion.copy( quaternion ).multiply( _tempQuaternion );\n\n\t\t\t\t\t\tif ( Math.abs( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) {\n\n\t\t\t\t\t\t\thandle.visible = false;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( this.axis === 'Z' ) {\n\n\t\t\t\t\t\t_tempQuaternion.setFromEuler( _tempEuler.set( 0, Math.PI / 2, 0 ) );\n\t\t\t\t\t\thandle.quaternion.copy( quaternion ).multiply( _tempQuaternion );\n\n\t\t\t\t\t\tif ( Math.abs( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) {\n\n\t\t\t\t\t\t\thandle.visible = false;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( this.axis === 'XYZE' ) {\n\n\t\t\t\t\t\t_tempQuaternion.setFromEuler( _tempEuler.set( 0, Math.PI / 2, 0 ) );\n\t\t\t\t\t\t_alignVector.copy( this.rotationAxis );\n\t\t\t\t\t\thandle.quaternion.setFromRotationMatrix( _lookAtMatrix.lookAt( _zeroVector, _alignVector, _unitY ) );\n\t\t\t\t\t\thandle.quaternion.multiply( _tempQuaternion );\n\t\t\t\t\t\thandle.visible = this.dragging;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( this.axis === 'E' ) {\n\n\t\t\t\t\t\thandle.visible = false;\n\n\t\t\t\t\t}\n\n\n\t\t\t\t} else if ( handle.name === 'START' ) {\n\n\t\t\t\t\thandle.position.copy( this.worldPositionStart );\n\t\t\t\t\thandle.visible = this.dragging;\n\n\t\t\t\t} else if ( handle.name === 'END' ) {\n\n\t\t\t\t\thandle.position.copy( this.worldPosition );\n\t\t\t\t\thandle.visible = this.dragging;\n\n\t\t\t\t} else if ( handle.name === 'DELTA' ) {\n\n\t\t\t\t\thandle.position.copy( this.worldPositionStart );\n\t\t\t\t\thandle.quaternion.copy( this.worldQuaternionStart );\n\t\t\t\t\t_tempVector.set( 1e-10, 1e-10, 1e-10 ).add( this.worldPositionStart ).sub( this.worldPosition ).multiplyScalar( - 1 );\n\t\t\t\t\t_tempVector.applyQuaternion( this.worldQuaternionStart.clone().invert() );\n\t\t\t\t\thandle.scale.copy( _tempVector );\n\t\t\t\t\thandle.visible = this.dragging;\n\n\t\t\t\t} else {\n\n\t\t\t\t\thandle.quaternion.copy( quaternion );\n\n\t\t\t\t\tif ( this.dragging ) {\n\n\t\t\t\t\t\thandle.position.copy( this.worldPositionStart );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\thandle.position.copy( this.worldPosition );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( this.axis ) {\n\n\t\t\t\t\t\thandle.visible = this.axis.search( handle.name ) !== - 1;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\t// If updating helper, skip rest of the loop\n\t\t\t\tcontinue;\n\n\t\t\t}\n\n\t\t\t// Align handles to current local or world rotation\n\n\t\t\thandle.quaternion.copy( quaternion );\n\n\t\t\tif ( this.mode === 'translate' || this.mode === 'scale' ) {\n\n\t\t\t\t// Hide translate and scale axis facing the camera\n\n\t\t\t\tconst AXIS_HIDE_THRESHOLD = 0.99;\n\t\t\t\tconst PLANE_HIDE_THRESHOLD = 0.2;\n\n\t\t\t\tif ( handle.name === 'X' ) {\n\n\t\t\t\t\tif ( Math.abs( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_THRESHOLD ) {\n\n\t\t\t\t\t\thandle.scale.set( 1e-10, 1e-10, 1e-10 );\n\t\t\t\t\t\thandle.visible = false;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( handle.name === 'Y' ) {\n\n\t\t\t\t\tif ( Math.abs( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_THRESHOLD ) {\n\n\t\t\t\t\t\thandle.scale.set( 1e-10, 1e-10, 1e-10 );\n\t\t\t\t\t\thandle.visible = false;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( handle.name === 'Z' ) {\n\n\t\t\t\t\tif ( Math.abs( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_THRESHOLD ) {\n\n\t\t\t\t\t\thandle.scale.set( 1e-10, 1e-10, 1e-10 );\n\t\t\t\t\t\thandle.visible = false;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( handle.name === 'XY' ) {\n\n\t\t\t\t\tif ( Math.abs( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_THRESHOLD ) {\n\n\t\t\t\t\t\thandle.scale.set( 1e-10, 1e-10, 1e-10 );\n\t\t\t\t\t\thandle.visible = false;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( handle.name === 'YZ' ) {\n\n\t\t\t\t\tif ( Math.abs( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_THRESHOLD ) {\n\n\t\t\t\t\t\thandle.scale.set( 1e-10, 1e-10, 1e-10 );\n\t\t\t\t\t\thandle.visible = false;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( handle.name === 'XZ' ) {\n\n\t\t\t\t\tif ( Math.abs( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_THRESHOLD ) {\n\n\t\t\t\t\t\thandle.scale.set( 1e-10, 1e-10, 1e-10 );\n\t\t\t\t\t\thandle.visible = false;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} else if ( this.mode === 'rotate' ) {\n\n\t\t\t\t// Align handles to current local or world rotation\n\n\t\t\t\t_tempQuaternion2.copy( quaternion );\n\t\t\t\t_alignVector.copy( this.eye ).applyQuaternion( _tempQuaternion.copy( quaternion ).invert() );\n\n\t\t\t\tif ( handle.name.search( 'E' ) !== - 1 ) {\n\n\t\t\t\t\thandle.quaternion.setFromRotationMatrix( _lookAtMatrix.lookAt( this.eye, _zeroVector, _unitY ) );\n\n\t\t\t\t}\n\n\t\t\t\tif ( handle.name === 'X' ) {\n\n\t\t\t\t\t_tempQuaternion.setFromAxisAngle( _unitX, Math.atan2( - _alignVector.y, _alignVector.z ) );\n\t\t\t\t\t_tempQuaternion.multiplyQuaternions( _tempQuaternion2, _tempQuaternion );\n\t\t\t\t\thandle.quaternion.copy( _tempQuaternion );\n\n\t\t\t\t}\n\n\t\t\t\tif ( handle.name === 'Y' ) {\n\n\t\t\t\t\t_tempQuaternion.setFromAxisAngle( _unitY, Math.atan2( _alignVector.x, _alignVector.z ) );\n\t\t\t\t\t_tempQuaternion.multiplyQuaternions( _tempQuaternion2, _tempQuaternion );\n\t\t\t\t\thandle.quaternion.copy( _tempQuaternion );\n\n\t\t\t\t}\n\n\t\t\t\tif ( handle.name === 'Z' ) {\n\n\t\t\t\t\t_tempQuaternion.setFromAxisAngle( _unitZ, Math.atan2( _alignVector.y, _alignVector.x ) );\n\t\t\t\t\t_tempQuaternion.multiplyQuaternions( _tempQuaternion2, _tempQuaternion );\n\t\t\t\t\thandle.quaternion.copy( _tempQuaternion );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// Hide disabled axes\n\t\t\thandle.visible = handle.visible && ( handle.name.indexOf( 'X' ) === - 1 || this.showX );\n\t\t\thandle.visible = handle.visible && ( handle.name.indexOf( 'Y' ) === - 1 || this.showY );\n\t\t\thandle.visible = handle.visible && ( handle.name.indexOf( 'Z' ) === - 1 || this.showZ );\n\t\t\thandle.visible = handle.visible && ( handle.name.indexOf( 'E' ) === - 1 || ( this.showX && this.showY && this.showZ ) );\n\n\t\t\t// Hide disabled plane helpers\n\t\t\thandle.visible = handle.visible && ( handle.name.indexOf( 'XY' ) === - 1 || this.showXY );\n\t\t\thandle.visible = handle.visible && ( handle.name.indexOf( 'YZ' ) === - 1 || this.showYZ );\n\t\t\thandle.visible = handle.visible && ( handle.name.indexOf( 'XZ' ) === - 1 || this.showXZ );\n\n\t\t\t// highlight selected axis\n\n\t\t\thandle.material._color = handle.material._color || handle.material.color.clone();\n\t\t\thandle.material._opacity = handle.material._opacity || handle.material.opacity;\n\n\t\t\thandle.material.color.copy( handle.material._color );\n\t\t\thandle.material.opacity = handle.material._opacity;\n\n\t\t\tif ( this.enabled && this.axis ) {\n\n\t\t\t\tif ( handle.name === this.axis ) {\n\n\t\t\t\t\thandle.material.color.copy( this.materialLib.active.color );\n\t\t\t\t\thandle.material.opacity = 1.0;\n\n\t\t\t\t} else if ( this.axis.split( '' ).some( function ( a ) {\n\n\t\t\t\t\treturn handle.name === a;\n\n\t\t\t\t} ) ) {\n\n\t\t\t\t\thandle.material.color.copy( this.materialLib.active.color );\n\t\t\t\t\thandle.material.opacity = 1.0;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tsuper.updateMatrixWorld( force );\n\n\t}\n\n}\n\n//\n\nclass TransformControlsPlane extends Mesh {\n\n\tconstructor() {\n\n\t\tsuper(\n\t\t\tnew PlaneGeometry( 100000, 100000, 2, 2 ),\n\t\t\tnew MeshBasicMaterial( { visible: false, wireframe: true, side: DoubleSide, transparent: true, opacity: 0.1, toneMapped: false } )\n\t\t);\n\n\t\tthis.isTransformControlsPlane = true;\n\n\t\tthis.type = 'TransformControlsPlane';\n\n\t}\n\n\tupdateMatrixWorld( force ) {\n\n\t\tlet space = this.space;\n\n\t\tthis.position.copy( this.worldPosition );\n\n\t\tif ( this.mode === 'scale' ) space = 'local'; // scale always oriented to local rotation\n\n\t\t_v1.copy( _unitX ).applyQuaternion( space === 'local' ? this.worldQuaternion : _identityQuaternion );\n\t\t_v2.copy( _unitY ).applyQuaternion( space === 'local' ? this.worldQuaternion : _identityQuaternion );\n\t\t_v3.copy( _unitZ ).applyQuaternion( space === 'local' ? this.worldQuaternion : _identityQuaternion );\n\n\t\t// Align the plane for current transform mode, axis and space.\n\n\t\t_alignVector.copy( _v2 );\n\n\t\tswitch ( this.mode ) {\n\n\t\t\tcase 'translate':\n\t\t\tcase 'scale':\n\t\t\t\tswitch ( this.axis ) {\n\n\t\t\t\t\tcase 'X':\n\t\t\t\t\t\t_alignVector.copy( this.eye ).cross( _v1 );\n\t\t\t\t\t\t_dirVector.copy( _v1 ).cross( _alignVector );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'Y':\n\t\t\t\t\t\t_alignVector.copy( this.eye ).cross( _v2 );\n\t\t\t\t\t\t_dirVector.copy( _v2 ).cross( _alignVector );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'Z':\n\t\t\t\t\t\t_alignVector.copy( this.eye ).cross( _v3 );\n\t\t\t\t\t\t_dirVector.copy( _v3 ).cross( _alignVector );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'XY':\n\t\t\t\t\t\t_dirVector.copy( _v3 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'YZ':\n\t\t\t\t\t\t_dirVector.copy( _v1 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'XZ':\n\t\t\t\t\t\t_alignVector.copy( _v3 );\n\t\t\t\t\t\t_dirVector.copy( _v2 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'XYZ':\n\t\t\t\t\tcase 'E':\n\t\t\t\t\t\t_dirVector.set( 0, 0, 0 );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\tcase 'rotate':\n\t\t\tdefault:\n\t\t\t\t// special case for rotate\n\t\t\t\t_dirVector.set( 0, 0, 0 );\n\n\t\t}\n\n\t\tif ( _dirVector.length() === 0 ) {\n\n\t\t\t// If in rotate mode, make the plane parallel to camera\n\t\t\tthis.quaternion.copy( this.cameraQuaternion );\n\n\t\t} else {\n\n\t\t\t_tempMatrix.lookAt( _tempVector.set( 0, 0, 0 ), _dirVector, _alignVector );\n\n\t\t\tthis.quaternion.setFromRotationMatrix( _tempMatrix );\n\n\t\t}\n\n\t\tsuper.updateMatrixWorld( force );\n\n\t}\n\n}\n\nexport { TransformControls, TransformControlsGizmo, TransformControlsPlane };\n","/**\r\n * 3D 模型编辑器核心模块\r\n * 提供场景管理、物体增删、选中/变换控制、树形数据同步等功能\r\n * 采用单例模式管理所有 Three.js 相关状态\r\n */\r\n\r\nimport * as THREE from \"three\";\r\nimport TWEEN from \"@tweenjs/tween.js\";\r\nimport { OrbitControls } from \"three/examples/jsm/controls/OrbitControls.js\";\r\nimport { TransformControls } from \"three/examples/jsm/controls/TransformControls.js\";\r\nimport type { Object3D } from \"three\";\r\nimport type {\r\n SelectedChangeCallback,\r\n TransformChangeCallback,\r\n SceneObjectsChangeCallback,\r\n} from \"./types\";\r\n\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n//#region 编辑器状态(单例)\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n\r\n/** 编辑器核心状态容器,所有 Three.js 核心对象均存放于此 */\r\nconst state = {\r\n mode: \"\",\r\n /** Three.js 场景 */\r\n scene: null as THREE.Scene | null,\r\n /** 透视相机 */\r\n camera: null as THREE.PerspectiveCamera | null,\r\n /** WebGL 渲染器 */\r\n renderer: null as THREE.WebGLRenderer | null,\r\n /** 轨道控制器(用于场景浏览) */\r\n orbitControls: null as OrbitControls | null,\r\n /** 变换控制器(用于平移/旋转/缩放物体) */\r\n transformControls: null as TransformControls | null,\r\n /** 编辑器挂载的 DOM 容器 */\r\n container: null as HTMLElement | null,\r\n /** 网格辅助对象(地板) */\r\n gridHelper: null as THREE.GridHelper | null,\r\n /** 当前选中的物体 */\r\n selectedObject: null as Object3D | null,\r\n};\r\n//#endregion\r\n\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n//#region 辅助标志\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n\r\n/** 轨道控制器是否发生了旋转/平移/缩放操作 */\r\nlet orbitChanged = false;\r\n/** 是否应该跳过下一次鼠标点击事件(用于防止拖拽后误触发选中) */\r\nlet skipNextClick = false;\r\n//#endregion\r\n\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n//#region 外部回调\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n\r\n/** 选中物体变化时的回调(由外部注册,用于同步 UI) */\r\nlet onSelectedChange: SelectedChangeCallback | null = null;\r\n/** 变换过程中(拖拽)的回调(由外部注册,用于实时更新属性面板) */\r\nlet onTransformChange: TransformChangeCallback | null = null;\r\n/** 场景物体列表变化时的回调(由外部注册,用于更新树形面板) */\r\nlet onSceneObjectsChange: SceneObjectsChangeCallback | null = null;\r\n//#endregion\r\n\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n//#region 树形数据(仅存储顶层可移动物体)\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n\r\n/** 场景中顶层可移动物体的列表(不包含子物体,子物体通过 parent 关系访问) */\r\nlet sceneObjects: Object3D[] = [];\r\n//#endregion\r\n\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n//#region 初始化场景数据\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n\r\n// 如果有场景数据,恢复相机参数并保存 target\r\nlet cameraTarget: number[] | undefined;\r\n//#endregion\r\n\r\n\r\n// ═══════════════════════════════════════════════════════════════════\r\n//#region 初始化\r\n// ═══════════════════════════════════════════════════════════════════\r\n\r\n/**\r\n * 初始化编辑器,挂载到指定 DOM 容器\r\n * @param container - 编辑器挂载的 DOM 元素\r\n */\r\nexport function initEditor(\r\n container: HTMLElement,\r\n mode = \"edit\",\r\n sceneData?: any,\r\n) {\r\n state.container = container;\r\n state.mode = mode;\r\n initRenderer(); // 创建渲染器\r\n initScene(); // 创建场景\r\n initCamera(); // 创建相机\r\n\r\n // 如果有传入场景数据\r\n if (sceneData) {\r\n // 设置场景数据\r\n loadSceneFromJSON(sceneData.scene, mode);\r\n\r\n if (sceneData?.camera) {\r\n const camData = sceneData.camera;\r\n state.camera!.position.set(\r\n camData.position[0],\r\n camData.position[1],\r\n camData.position[2],\r\n );\r\n state.camera!.rotation.set(\r\n camData.rotation[0],\r\n camData.rotation[1],\r\n camData.rotation[2],\r\n );\r\n state.camera!.updateProjectionMatrix();\r\n cameraTarget = camData.target;\r\n }\r\n }\r\n\r\n initTransformControls(); // 初始化变换控制器(需在 OrbitControls 前,因为辅助对象要加入场景)\r\n initOrbitControls(); // 初始化轨道控制器\r\n\r\n // 如果有 target,恢复 OrbitControls 的目标并更新\r\n if (cameraTarget && state.orbitControls) {\r\n state.orbitControls.target.fromArray(cameraTarget);\r\n state.orbitControls.update();\r\n }\r\n\r\n refreshSceneObjects(); // 刷新顶层物体列表\r\n animate(); // 启动动画循环\r\n // 绑定事件\r\n if (mode === \"edit\") container.addEventListener(\"click\", onMouseClick);\r\n window.addEventListener(\"resize\", onResize);\r\n\r\n // 如果没有传入场景数据\r\n if (!sceneData) {\r\n addDefaultLightAndCube(); // 添加默认灯光和立方体(演示用)\r\n }\r\n\r\n if (mode === \"edit\") initGrid(); // 添加网格地板\r\n}\r\n\r\n/** 创建 WebGL 渲染器,设置尺寸和像素比 */\r\nfunction initRenderer() {\r\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\r\n renderer.setSize(state.container!.clientWidth, state.container!.clientHeight);\r\n // 限制像素比不超过 2,以平衡性能和显示效果\r\n renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));\r\n state.container!.appendChild(renderer.domElement);\r\n state.renderer = renderer;\r\n}\r\n\r\n/** 创建场景并命名(便于调试) */\r\nfunction initScene() {\r\n state.scene = new THREE.Scene();\r\n state.scene.name = \"sl_scene\";\r\n}\r\n\r\n/** 创建网格辅助对象(地板),不加入树形列表 */\r\nfunction initGrid() {\r\n const grid = new THREE.GridHelper(30, 30, 0x88aaff, 0x335588);\r\n grid.name = \"地板\";\r\n grid.userData.type = \"initFloor\";\r\n // 地板不可移动,故不设置 isMovable\r\n state.scene!.add(grid);\r\n state.gridHelper = grid;\r\n}\r\n\r\n/** 创建透视相机,设置初始位置 */\r\nfunction initCamera() {\r\n const container = state.container!;\r\n const aspect = container.clientWidth / container.clientHeight;\r\n const camera = new THREE.PerspectiveCamera(45, aspect, 0.1, 1000);\r\n camera.position.set(0, 6, 15);\r\n camera.lookAt(0, 0, 0);\r\n state.camera = camera;\r\n}\r\n\r\n/** 创建轨道控制器,允许用户旋转/平移/缩放视图 */\r\nfunction initOrbitControls() {\r\n const controls = new OrbitControls(state.camera!, state.renderer!.domElement);\r\n\r\n controls.minDistance = 0;\r\n controls.maxDistance = Infinity;\r\n // 监测操作是否改变了相机状态\r\n controls.addEventListener(\"start\", () => {\r\n orbitChanged = false;\r\n });\r\n controls.addEventListener(\"change\", () => {\r\n orbitChanged = true;\r\n });\r\n controls.addEventListener(\"end\", () => {\r\n // 如果相机发生了改变,则标记跳过下一次点击(避免拖拽后选中物体)\r\n if (orbitChanged) {\r\n skipNextClick = true;\r\n setTimeout(() => {\r\n skipNextClick = false;\r\n }, 200);\r\n }\r\n });\r\n state.orbitControls = controls;\r\n}\r\n\r\n/** 创建变换控制器,用于拖拽移动物体(平移模式) */\r\nfunction initTransformControls() {\r\n const controls = new TransformControls(\r\n state.camera!,\r\n state.renderer!.domElement,\r\n );\r\n // 拖拽变换控制器时,暂时禁用轨道控制器\r\n controls.addEventListener(\"dragging-changed\", (event: any) => {\r\n state.orbitControls!.enabled = !event.value;\r\n if (!event.value) {\r\n // 拖拽结束后,跳过下一次点击\r\n skipNextClick = true;\r\n setTimeout(() => {\r\n skipNextClick = false;\r\n }, 200);\r\n }\r\n });\r\n // 物体变换过程中(位置/旋转/缩放变化),触发外部回调以更新 UI\r\n controls.addEventListener(\"objectChange\", () => {\r\n if (onTransformChange && state.selectedObject) {\r\n onTransformChange(state.selectedObject);\r\n }\r\n });\r\n // 将变换控制器的辅助轴添加到场景\r\n state.scene!.add(controls.getHelper());\r\n state.transformControls = controls;\r\n}\r\n\r\n/** 添加默认的环境光、平行光和一个示例立方体 */\r\nfunction addDefaultLightAndCube() {\r\n // 环境光\r\n const ambient = new THREE.AmbientLight(0xffffff, 2);\r\n state.scene!.add(ambient);\r\n // 平行光\r\n const dirLight = new THREE.DirectionalLight(0xffffff, 3);\r\n dirLight.position.set(48, 104, 138);\r\n state.scene!.add(dirLight);\r\n\r\n // 默认立方体(方便演示)\r\n // const geo = new THREE.BoxGeometry(1, 1, 1);\r\n // const mat = new THREE.MeshStandardMaterial({ color: 0xffffff });\r\n // const cube = new THREE.Mesh(geo, mat);\r\n // cube.position.y = 1;\r\n // cube.userData.isMovable = true;\r\n // cube.name = \"默认立方体\";\r\n // addModel(cube, true);\r\n}\r\n//#endregion\r\n\r\n// ═══════════════════════════════════════════════════════════════════\r\n//#region 动画循环 & 窗口自适应\r\n// ═══════════════════════════════════════════════════════════════════\r\n\r\n/** 动画循环:更新 Tween 动画、轨道控制器,并渲染场景 */\r\nfunction animate() {\r\n requestAnimationFrame(animate);\r\n TWEEN.update(); // 更新补间动画(当前未使用,保留扩展)\r\n state.orbitControls?.update();\r\n state.renderer?.render(state.scene!, state.camera!);\r\n}\r\n\r\n/** 窗口大小变化时,自适应渲染尺寸和相机比例 */\r\nfunction onResize() {\r\n if (!state.container || !state.camera || !state.renderer) return;\r\n const width = state.container.clientWidth;\r\n const height = state.container.clientHeight;\r\n if (width === 0 || height === 0) return;\r\n state.camera.aspect = width / height;\r\n state.camera.updateProjectionMatrix();\r\n state.renderer.setSize(width, height);\r\n}\r\n//#endregion\r\n\r\n// ═══════════════════════════════════════════════════════════════════\r\n//#region 选中 / 取消选中\r\n// ═══════════════════════════════════════════════════════════════════\r\n\r\n/**\r\n * 选中场景中的一个物体,将其附着到变换控制器并显示平移轴\r\n * @param obj - 要选中的物体\r\n */\r\nexport function selectObject(obj: Object3D) {\r\n if (state.selectedObject === obj) return; // 已选中则忽略\r\n // 取消之前的附着\r\n if (state.selectedObject) {\r\n state.transformControls!.detach();\r\n }\r\n state.selectedObject = obj;\r\n state.transformControls!.attach(obj);\r\n state.transformControls!.setMode(\"translate\"); // 默认平移模式\r\n state.transformControls!.showX = true;\r\n state.transformControls!.showY = true;\r\n state.transformControls!.showZ = true;\r\n // 通知外部选中变化\r\n onSelectedChange?.(obj);\r\n}\r\n\r\n/** 取消选中:隐藏变换控制器,并通知外部 */\r\nfunction deselectObject() {\r\n if (state.selectedObject) {\r\n state.transformControls!.detach();\r\n state.selectedObject = null;\r\n onSelectedChange?.(null);\r\n }\r\n}\r\n//#endregion\r\n\r\n// ═══════════════════════════════════════════════════════════════════\r\n//#region 鼠标点击(射线拾取)\r\n// ═══════════════════════════════════════════════════════════════════\r\n\r\n/**\r\n * 鼠标点击事件处理:使用射线检测拾取场景中的可移动 Mesh,\r\n * 若点击到物体则选中它,否则取消选中\r\n */\r\nfunction onMouseClick(event: MouseEvent) {\r\n // 如果标记跳过本次点击(如拖拽刚结束),则忽略并重置标记\r\n if (skipNextClick) {\r\n skipNextClick = false;\r\n return;\r\n }\r\n // 计算鼠标位置归一化坐标\r\n const rect = state.renderer!.domElement.getBoundingClientRect();\r\n const mouse = new THREE.Vector2(\r\n ((event.clientX - rect.left) / rect.width) * 2 - 1,\r\n -((event.clientY - rect.top) / rect.height) * 2 + 1,\r\n );\r\n const raycaster = new THREE.Raycaster();\r\n raycaster.setFromCamera(mouse, state.camera!);\r\n\r\n // 收集场景中所有可点击的物体(isMovable 且为 Mesh)\r\n const clickables: Object3D[] = [];\r\n state.scene!.traverse((obj) => {\r\n if (obj.type === \"Mesh\" && obj.userData.isMovable) {\r\n clickables.push(obj);\r\n }\r\n });\r\n const intersects = raycaster.intersectObjects(clickables);\r\n if (intersects.length > 0) {\r\n selectObject(intersects[0].object);\r\n } else {\r\n deselectObject();\r\n }\r\n}\r\n//#endregion\r\n\r\n// ═══════════════════════════════════════════════════════════════════\r\n//#region 模型管理(增删改查)\r\n// ═══════════════════════════════════════════════════════════════════\r\n\r\n/**\r\n * 向场景添加一个模型(Object3D 及其子节点)\r\n * @param model - 要添加的模型对象\r\n * @param selected - 是否添加后立即选中\r\n */\r\nexport function addModel(model: Object3D, selected = false) {\r\n state.scene!.add(model);\r\n // 如果模型本身是可移动的,则加入顶层列表(但只有顶层对象才加入)\r\n if (model.userData.isMovable) {\r\n addObjectToTree(model);\r\n notifyChange();\r\n }\r\n if (selected && state.mode === \"edit\") selectObject(model);\r\n}\r\n\r\n/**\r\n * 从场景中移除一个模型及其子节点\r\n * @param model - 要移除的模型对象\r\n */\r\nexport function removeModel(model: Object3D) {\r\n if (state.selectedObject === model) deselectObject();\r\n // 从父节点移除(更通用),若没有父节点则从场景移除\r\n if (model.parent) {\r\n model.parent.remove(model);\r\n } else {\r\n state.scene!.remove(model);\r\n }\r\n // 如果该对象在顶层列表中,则移除\r\n removeObjectFromTree(model);\r\n notifyChange();\r\n}\r\n\r\n/**\r\n * 根据 UUID 删除场景中的物体\r\n * @param uuid - 物体的唯一标识符\r\n */\r\nexport function removeModelById(uuid: string) {\r\n const obj = state.scene!.getObjectByProperty(\"uuid\", uuid);\r\n if (obj) removeModel(obj);\r\n}\r\n\r\n// ─── 树形数据管理(仅顶层对象) ───\r\n\r\n/**\r\n * 将一个可移动物体加入顶层列表(前提是它是场景的直接子级)\r\n */\r\nfunction addObjectToTree(obj: Object3D) {\r\n if (obj.userData.isMovable && obj.parent === state.scene) {\r\n if (!sceneObjects.includes(obj)) {\r\n sceneObjects.push(obj);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * 从顶层列表中移除物体(如果存在)\r\n */\r\nfunction removeObjectFromTree(obj: Object3D) {\r\n const idx = sceneObjects.indexOf(obj);\r\n if (idx !== -1) sceneObjects.splice(idx, 1);\r\n}\r\n\r\n/** 全量刷新顶层物体列表(初始化时调用) */\r\nfunction refreshSceneObjects() {\r\n const list: Object3D[] = [];\r\n state.scene!.children.forEach((child) => {\r\n if (child.userData.isMovable) list.push(child);\r\n });\r\n sceneObjects = list;\r\n notifyChange();\r\n}\r\n\r\n/** 通知外部树形数据变化,传递列表副本以触发 shallowRef 更新 */\r\nfunction notifyChange() {\r\n onSceneObjectsChange?.([...sceneObjects]);\r\n}\r\n//#endregion\r\n\r\n// ═══════════════════════════════════════════════════════════════════\r\n//#region 回调注册\r\n// ═══════════════════════════════════════════════════════════════════\r\n\r\n/**\r\n * 注册选中物体变化的回调\r\n * @param cb - 回调函数,参数为当前选中的物体或 null\r\n */\r\nexport function setSelectedObjectCallback(cb: SelectedChangeCallback) {\r\n onSelectedChange = cb;\r\n}\r\n\r\n/**\r\n * 注册变换过程中(拖拽)的回调\r\n * @param cb - 回调函数,参数为正在变换的物体\r\n */\r\nexport function setTransformChangeCallback(cb: TransformChangeCallback) {\r\n onTransformChange = cb;\r\n}\r\n\r\n/**\r\n * 注册场景物体列表变化的回调\r\n * @param cb - 回调函数,参数为当前顶层物体列表\r\n */\r\nexport function onSceneObjectsChangeCallback(cb: SceneObjectsChangeCallback) {\r\n onSceneObjectsChange = cb;\r\n}\r\n\r\n/**\r\n * 获取当前顶层物体列表\r\n * @returns 顶层物体数组\r\n */\r\nexport function getSceneObjects() {\r\n return sceneObjects;\r\n}\r\n//#endregion\r\n\r\n// ═══════════════════════════════════════════════════════════════════\r\n//#region 场景导出导入\r\n// ═══════════════════════════════════════════════════════════════════\r\n\r\nexport function getScene() {\r\n return state.scene;\r\n}\r\nexport function getCamera() {\r\n return state.camera;\r\n}\r\nexport function getRenderer() {\r\n return state.renderer;\r\n}\r\n\r\n/**\r\n * 将当前 Three.js 场景导出为 JSON 数据(使用 Three.js 内置 toJSON)\r\n * @returns JSON 字符串\r\n */\r\nexport function exportSceneToJSON(): string {\r\n // 首先取消选中模型\r\n deselectObject();\r\n\r\n const scene = state.scene;\r\n if (!scene) return \"{}\";\r\n\r\n // 不需要初始化地板对象,创建一个临时场景副本\r\n let exportScene = scene;\r\n\r\n exportScene = scene.clone();\r\n // 移除初始化地板的对象\r\n exportScene.children = exportScene.children.filter(\r\n (child) => child.userData.type !== \"initFloor\",\r\n );\r\n\r\n // 场景 json\r\n const sceneJson = exportScene.toJSON();\r\n // 摄像机 json\r\n const cameraJson = {\r\n position: state.camera?.position.toArray(),\r\n rotation: state.camera?.rotation.toArray(),\r\n target: state.orbitControls?.target.toArray() || [0, 0, 0],\r\n };\r\n\r\n return JSON.stringify({ scene: sceneJson, camera: cameraJson });\r\n}\r\n\r\n/**\r\n * 从 JSON 数据恢复场景(使用 Three.js 内置 ObjectLoader)\r\n * @param json - JSON 字符串或对象\r\n * @returns 解析后的 Object3D 或 Scene\r\n */\r\nexport function loadSceneFromJSON(\r\n json: string | object,\r\n mode: string = \"edit\",\r\n) {\r\n const data = typeof json === \"string\" ? JSON.parse(json) : json;\r\n const loader = new THREE.ObjectLoader();\r\n const loaded = loader.parse(data);\r\n\r\n if (loaded.type === \"Scene\") {\r\n if (mode === \"run\") {\r\n }\r\n state.scene = loaded as THREE.Scene;\r\n } else {\r\n state.scene?.add(loaded);\r\n }\r\n}\r\n//#endregion\r\n","import {\n\tBufferGeometry,\n\tFileLoader,\n\tFloat32BufferAttribute,\n\tGroup,\n\tLineBasicMaterial,\n\tLineSegments,\n\tLoader,\n\tMaterial,\n\tMesh,\n\tMeshPhongMaterial,\n\tPoints,\n\tPointsMaterial,\n\tVector3,\n\tColor,\n\tSRGBColorSpace\n} from 'three';\n\n// o object_name | g group_name\nconst _object_pattern = /^[og]\\s*(.+)?/;\n// mtllib file_reference\nconst _material_library_pattern = /^mtllib /;\n// usemtl material_name\nconst _material_use_pattern = /^usemtl /;\n// usemap map_name\nconst _map_use_pattern = /^usemap /;\nconst _face_vertex_data_separator_pattern = /\\s+/;\n\nconst _vA = new Vector3();\nconst _vB = new Vector3();\nconst _vC = new Vector3();\n\nconst _ab = new Vector3();\nconst _cb = new Vector3();\n\nconst _color = new Color();\n\nfunction ParserState() {\n\n\tconst state = {\n\t\tobjects: [],\n\t\tobject: {},\n\n\t\tvertices: [],\n\t\tnormals: [],\n\t\tcolors: [],\n\t\tuvs: [],\n\n\t\tmaterials: {},\n\t\tmaterialLibraries: [],\n\n\t\tstartObject: function ( name, fromDeclaration ) {\n\n\t\t\t// If the current object (initial from reset) is not from a g/o declaration in the parsed\n\t\t\t// file. We need to use it for the first parsed g/o to keep things in sync.\n\t\t\tif ( this.object && this.object.fromDeclaration === false ) {\n\n\t\t\t\tthis.object.name = name;\n\t\t\t\tthis.object.fromDeclaration = ( fromDeclaration !== false );\n\t\t\t\treturn;\n\n\t\t\t}\n\n\t\t\tconst previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined );\n\n\t\t\tif ( this.object && typeof this.object._finalize === 'function' ) {\n\n\t\t\t\tthis.object._finalize( true );\n\n\t\t\t}\n\n\t\t\tthis.object = {\n\t\t\t\tname: name || '',\n\t\t\t\tfromDeclaration: ( fromDeclaration !== false ),\n\n\t\t\t\tgeometry: {\n\t\t\t\t\tvertices: [],\n\t\t\t\t\tnormals: [],\n\t\t\t\t\tcolors: [],\n\t\t\t\t\tuvs: [],\n\t\t\t\t\thasUVIndices: false\n\t\t\t\t},\n\t\t\t\tmaterials: [],\n\t\t\t\tsmooth: true,\n\n\t\t\t\tstartMaterial: function ( name, libraries ) {\n\n\t\t\t\t\tconst previous = this._finalize( false );\n\n\t\t\t\t\t// New usemtl declaration overwrites an inherited material, except if faces were declared\n\t\t\t\t\t// after the material, then it must be preserved for proper MultiMaterial continuation.\n\t\t\t\t\tif ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) {\n\n\t\t\t\t\t\tthis.materials.splice( previous.index, 1 );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tconst material = {\n\t\t\t\t\t\tindex: this.materials.length,\n\t\t\t\t\t\tname: name || '',\n\t\t\t\t\t\tmtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ),\n\t\t\t\t\t\tsmooth: ( previous !== undefined ? previous.smooth : this.smooth ),\n\t\t\t\t\t\tgroupStart: ( previous !== undefined ? previous.groupEnd : 0 ),\n\t\t\t\t\t\tgroupEnd: - 1,\n\t\t\t\t\t\tgroupCount: - 1,\n\t\t\t\t\t\tinherited: false,\n\n\t\t\t\t\t\tclone: function ( index ) {\n\n\t\t\t\t\t\t\tconst cloned = {\n\t\t\t\t\t\t\t\tindex: ( typeof index === 'number' ? index : this.index ),\n\t\t\t\t\t\t\t\tname: this.name,\n\t\t\t\t\t\t\t\tmtllib: this.mtllib,\n\t\t\t\t\t\t\t\tsmooth: this.smooth,\n\t\t\t\t\t\t\t\tgroupStart: 0,\n\t\t\t\t\t\t\t\tgroupEnd: - 1,\n\t\t\t\t\t\t\t\tgroupCount: - 1,\n\t\t\t\t\t\t\t\tinherited: false\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tcloned.clone = this.clone.bind( cloned );\n\t\t\t\t\t\t\treturn cloned;\n\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tthis.materials.push( material );\n\n\t\t\t\t\treturn material;\n\n\t\t\t\t},\n\n\t\t\t\tcurrentMaterial: function () {\n\n\t\t\t\t\tif ( this.materials.length > 0 ) {\n\n\t\t\t\t\t\treturn this.materials[ this.materials.length - 1 ];\n\n\t\t\t\t\t}\n\n\t\t\t\t\treturn undefined;\n\n\t\t\t\t},\n\n\t\t\t\t_finalize: function ( end ) {\n\n\t\t\t\t\tconst lastMultiMaterial = this.currentMaterial();\n\t\t\t\t\tif ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) {\n\n\t\t\t\t\t\tlastMultiMaterial.groupEnd = this.geometry.vertices.length / 3;\n\t\t\t\t\t\tlastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart;\n\t\t\t\t\t\tlastMultiMaterial.inherited = false;\n\n\t\t\t\t\t}\n\n\t\t\t\t\t// Ignore objects tail materials if no face declarations followed them before a new o/g started.\n\t\t\t\t\tif ( end && this.materials.length > 1 ) {\n\n\t\t\t\t\t\tfor ( let mi = this.materials.length - 1; mi >= 0; mi -- ) {\n\n\t\t\t\t\t\t\tif ( this.materials[ mi ].groupCount <= 0 ) {\n\n\t\t\t\t\t\t\t\tthis.materials.splice( mi, 1 );\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\t// Guarantee at least one empty material, this makes the creation later more straight forward.\n\t\t\t\t\tif ( end && this.materials.length === 0 ) {\n\n\t\t\t\t\t\tthis.materials.push( {\n\t\t\t\t\t\t\tname: '',\n\t\t\t\t\t\t\tsmooth: this.smooth\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t}\n\n\t\t\t\t\treturn lastMultiMaterial;\n\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// Inherit previous objects material.\n\t\t\t// Spec tells us that a declared material must be set to all objects until a new material is declared.\n\t\t\t// If a usemtl declaration is encountered while this new object is being parsed, it will\n\t\t\t// overwrite the inherited material. Exception being that there was already face declarations\n\t\t\t// to the inherited material, then it will be preserved for proper MultiMaterial continuation.\n\n\t\t\tif ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) {\n\n\t\t\t\tconst declared = previousMaterial.clone( 0 );\n\t\t\t\tdeclared.inherited = true;\n\t\t\t\tthis.object.materials.push( declared );\n\n\t\t\t}\n\n\t\t\tthis.objects.push( this.object );\n\n\t\t},\n\n\t\tfinalize: function () {\n\n\t\t\tif ( this.object && typeof this.object._finalize === 'function' ) {\n\n\t\t\t\tthis.object._finalize( true );\n\n\t\t\t}\n\n\t\t},\n\n\t\tparseVertexIndex: function ( value, len ) {\n\n\t\t\tconst index = parseInt( value, 10 );\n\t\t\treturn ( index >= 0 ? index - 1 : index + len / 3 ) * 3;\n\n\t\t},\n\n\t\tparseNormalIndex: function ( value, len ) {\n\n\t\t\tconst index = parseInt( value, 10 );\n\t\t\treturn ( index >= 0 ? index - 1 : index + len / 3 ) * 3;\n\n\t\t},\n\n\t\tparseUVIndex: function ( value, len ) {\n\n\t\t\tconst index = parseInt( value, 10 );\n\t\t\treturn ( index >= 0 ? index - 1 : index + len / 2 ) * 2;\n\n\t\t},\n\n\t\taddVertex: function ( a, b, c ) {\n\n\t\t\tconst src = this.vertices;\n\t\t\tconst dst = this.object.geometry.vertices;\n\n\t\t\tdst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );\n\t\t\tdst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );\n\t\t\tdst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );\n\n\t\t},\n\n\t\taddVertexPoint: function ( a ) {\n\n\t\t\tconst src = this.vertices;\n\t\t\tconst dst = this.object.geometry.vertices;\n\n\t\t\tdst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );\n\n\t\t},\n\n\t\taddVertexLine: function ( a ) {\n\n\t\t\tconst src = this.vertices;\n\t\t\tconst dst = this.object.geometry.vertices;\n\n\t\t\tdst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );\n\n\t\t},\n\n\t\taddNormal: function ( a, b, c ) {\n\n\t\t\tconst src = this.normals;\n\t\t\tconst dst = this.object.geometry.normals;\n\n\t\t\tdst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );\n\t\t\tdst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );\n\t\t\tdst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );\n\n\t\t},\n\n\t\taddFaceNormal: function ( a, b, c ) {\n\n\t\t\tconst src = this.vertices;\n\t\t\tconst dst = this.object.geometry.normals;\n\n\t\t\t_vA.fromArray( src, a );\n\t\t\t_vB.fromArray( src, b );\n\t\t\t_vC.fromArray( src, c );\n\n\t\t\t_cb.subVectors( _vC, _vB );\n\t\t\t_ab.subVectors( _vA, _vB );\n\t\t\t_cb.cross( _ab );\n\n\t\t\t_cb.normalize();\n\n\t\t\tdst.push( _cb.x, _cb.y, _cb.z );\n\t\t\tdst.push( _cb.x, _cb.y, _cb.z );\n\t\t\tdst.push( _cb.x, _cb.y, _cb.z );\n\n\t\t},\n\n\t\taddColor: function ( a, b, c ) {\n\n\t\t\tconst src = this.colors;\n\t\t\tconst dst = this.object.geometry.colors;\n\n\t\t\tif ( src[ a ] !== undefined ) dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );\n\t\t\tif ( src[ b ] !== undefined ) dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );\n\t\t\tif ( src[ c ] !== undefined ) dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );\n\n\t\t},\n\n\t\taddUV: function ( a, b, c ) {\n\n\t\t\tconst src = this.uvs;\n\t\t\tconst dst = this.object.geometry.uvs;\n\n\t\t\tdst.push( src[ a + 0 ], src[ a + 1 ] );\n\t\t\tdst.push( src[ b + 0 ], src[ b + 1 ] );\n\t\t\tdst.push( src[ c + 0 ], src[ c + 1 ] );\n\n\t\t},\n\n\t\taddDefaultUV: function () {\n\n\t\t\tconst dst = this.object.geometry.uvs;\n\n\t\t\tdst.push( 0, 0 );\n\t\t\tdst.push( 0, 0 );\n\t\t\tdst.push( 0, 0 );\n\n\t\t},\n\n\t\taddUVLine: function ( a ) {\n\n\t\t\tconst src = this.uvs;\n\t\t\tconst dst = this.object.geometry.uvs;\n\n\t\t\tdst.push( src[ a + 0 ], src[ a + 1 ] );\n\n\t\t},\n\n\t\taddFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) {\n\n\t\t\tconst vLen = this.vertices.length;\n\n\t\t\tlet ia = this.parseVertexIndex( a, vLen );\n\t\t\tlet ib = this.parseVertexIndex( b, vLen );\n\t\t\tlet ic = this.parseVertexIndex( c, vLen );\n\n\t\t\tthis.addVertex( ia, ib, ic );\n\t\t\tthis.addColor( ia, ib, ic );\n\n\t\t\t// normals\n\n\t\t\tif ( na !== undefined && na !== '' ) {\n\n\t\t\t\tconst nLen = this.normals.length;\n\n\t\t\t\tia = this.parseNormalIndex( na, nLen );\n\t\t\t\tib = this.parseNormalIndex( nb, nLen );\n\t\t\t\tic = this.parseNormalIndex( nc, nLen );\n\n\t\t\t\tthis.addNormal( ia, ib, ic );\n\n\t\t\t} else {\n\n\t\t\t\tthis.addFaceNormal( ia, ib, ic );\n\n\t\t\t}\n\n\t\t\t// uvs\n\n\t\t\tif ( ua !== undefined && ua !== '' ) {\n\n\t\t\t\tconst uvLen = this.uvs.length;\n\n\t\t\t\tia = this.parseUVIndex( ua, uvLen );\n\t\t\t\tib = this.parseUVIndex( ub, uvLen );\n\t\t\t\tic = this.parseUVIndex( uc, uvLen );\n\n\t\t\t\tthis.addUV( ia, ib, ic );\n\n\t\t\t\tthis.object.geometry.hasUVIndices = true;\n\n\t\t\t} else {\n\n\t\t\t\t// add placeholder values (for inconsistent face definitions)\n\n\t\t\t\tthis.addDefaultUV();\n\n\t\t\t}\n\n\t\t},\n\n\t\taddPointGeometry: function ( vertices ) {\n\n\t\t\tthis.object.geometry.type = 'Points';\n\n\t\t\tconst vLen = this.vertices.length;\n\n\t\t\tfor ( let vi = 0, l = vertices.length; vi < l; vi ++ ) {\n\n\t\t\t\tconst index = this.parseVertexIndex( vertices[ vi ], vLen );\n\n\t\t\t\tthis.addVertexPoint( index );\n\t\t\t\tthis.addColor( index );\n\n\t\t\t}\n\n\t\t},\n\n\t\taddLineGeometry: function ( vertices, uvs ) {\n\n\t\t\tthis.object.geometry.type = 'Line';\n\n\t\t\tconst vLen = this.vertices.length;\n\t\t\tconst uvLen = this.uvs.length;\n\n\t\t\tfor ( let vi = 0, l = vertices.length; vi < l; vi ++ ) {\n\n\t\t\t\tthis.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) );\n\n\t\t\t}\n\n\t\t\tfor ( let uvi = 0, l = uvs.length; uvi < l; uvi ++ ) {\n\n\t\t\t\tthis.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) );\n\n\t\t\t}\n\n\t\t}\n\n\t};\n\n\tstate.startObject( '', false );\n\n\treturn state;\n\n}\n\n\n/**\n * A loader for the OBJ format.\n *\n * The [OBJ format](https://en.wikipedia.org/wiki/Wavefront_.obj_file) is a simple data-format that\n * represents 3D geometry in a human readable format as the position of each vertex, the UV position of\n * each texture coordinate vertex, vertex normals, and the faces that make each polygon defined as a list\n * of vertices, and texture vertices.\n *\n * ```js\n * const loader = new OBJLoader();\n * const object = await loader.loadAsync( 'models/monster.obj' );\n * scene.add( object );\n * ```\n *\n * @augments Loader\n * @three_import import { OBJLoader } from 'three/addons/loaders/OBJLoader.js';\n */\nclass OBJLoader extends Loader {\n\n\t/**\n\t * Constructs a new OBJ loader.\n\t *\n\t * @param {LoadingManager} [manager] - The loading manager.\n\t */\n\tconstructor( manager ) {\n\n\t\tsuper( manager );\n\n\t\t/**\n\t\t * A reference to a material creator.\n\t\t *\n\t\t * @type {?MaterialCreator}\n\t\t * @default null\n\t\t */\n\t\tthis.materials = null;\n\n\t}\n\n\t/**\n\t * Starts loading from the given URL and passes the loaded OBJ asset\n\t * to the `onLoad()` callback.\n\t *\n\t * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.\n\t * @param {function(Group)} onLoad - Executed when the loading process has been finished.\n\t * @param {onProgressCallback} onProgress - Executed while the loading is in progress.\n\t * @param {onErrorCallback} onError - Executed when errors occur.\n\t */\n\tload( url, onLoad, onProgress, onError ) {\n\n\t\tconst scope = this;\n\n\t\tconst loader = new FileLoader( this.manager );\n\t\tloader.setPath( this.path );\n\t\tloader.setRequestHeader( this.requestHeader );\n\t\tloader.setWithCredentials( this.withCredentials );\n\t\tloader.load( url, function ( text ) {\n\n\t\t\ttry {\n\n\t\t\t\tonLoad( scope.parse( text ) );\n\n\t\t\t} catch ( e ) {\n\n\t\t\t\tif ( onError ) {\n\n\t\t\t\t\tonError( e );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.error( e );\n\n\t\t\t\t}\n\n\t\t\t\tscope.manager.itemError( url );\n\n\t\t\t}\n\n\t\t}, onProgress, onError );\n\n\t}\n\n\t/**\n\t * Sets the material creator for this OBJ. This object is loaded via {@link MTLLoader}.\n\t *\n\t * @param {MaterialCreator} materials - An object that creates the materials for this OBJ.\n\t * @return {OBJLoader} A reference to this loader.\n\t */\n\tsetMaterials( materials ) {\n\n\t\tthis.materials = materials;\n\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Parses the given OBJ data and returns the resulting group.\n\t *\n\t * @param {string} text - The raw OBJ data as a string.\n\t * @return {Group} The parsed OBJ.\n\t */\n\tparse( text ) {\n\n\t\tconst state = new ParserState();\n\n\t\tif ( text.indexOf( '\\r\\n' ) !== - 1 ) {\n\n\t\t\t// This is faster than String.split with regex that splits on both\n\t\t\ttext = text.replace( /\\r\\n/g, '\\n' );\n\n\t\t}\n\n\t\tif ( text.indexOf( '\\\\\\n' ) !== - 1 ) {\n\n\t\t\t// join lines separated by a line continuation character (\\)\n\t\t\ttext = text.replace( /\\\\\\n/g, '' );\n\n\t\t}\n\n\t\tconst lines = text.split( '\\n' );\n\t\tlet result = [];\n\n\t\tfor ( let i = 0, l = lines.length; i < l; i ++ ) {\n\n\t\t\tconst line = lines[ i ].trimStart();\n\n\t\t\tif ( line.length === 0 ) continue;\n\n\t\t\tconst lineFirstChar = line.charAt( 0 );\n\n\t\t\t// @todo invoke passed in handler if any\n\t\t\tif ( lineFirstChar === '#' ) continue; // skip comments\n\n\t\t\tif ( lineFirstChar === 'v' ) {\n\n\t\t\t\tconst data = line.split( _face_vertex_data_separator_pattern );\n\n\t\t\t\tswitch ( data[ 0 ] ) {\n\n\t\t\t\t\tcase 'v':\n\t\t\t\t\t\tstate.vertices.push(\n\t\t\t\t\t\t\tparseFloat( data[ 1 ] ),\n\t\t\t\t\t\t\tparseFloat( data[ 2 ] ),\n\t\t\t\t\t\t\tparseFloat( data[ 3 ] )\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif ( data.length >= 7 ) {\n\n\t\t\t\t\t\t\t_color.setRGB(\n\t\t\t\t\t\t\t\tparseFloat( data[ 4 ] ),\n\t\t\t\t\t\t\t\tparseFloat( data[ 5 ] ),\n\t\t\t\t\t\t\t\tparseFloat( data[ 6 ] ),\n\t\t\t\t\t\t\t\tSRGBColorSpace\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tstate.colors.push( _color.r, _color.g, _color.b );\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t// if no colors are defined, add placeholders so color and vertex indices match\n\n\t\t\t\t\t\t\tstate.colors.push( undefined, undefined, undefined );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'vn':\n\t\t\t\t\t\tstate.normals.push(\n\t\t\t\t\t\t\tparseFloat( data[ 1 ] ),\n\t\t\t\t\t\t\tparseFloat( data[ 2 ] ),\n\t\t\t\t\t\t\tparseFloat( data[ 3 ] )\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'vt':\n\t\t\t\t\t\tstate.uvs.push(\n\t\t\t\t\t\t\tparseFloat( data[ 1 ] ),\n\t\t\t\t\t\t\tparseFloat( data[ 2 ] )\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t} else if ( lineFirstChar === 'f' ) {\n\n\t\t\t\tconst lineData = line.slice( 1 ).trim();\n\t\t\t\tconst vertexData = lineData.split( _face_vertex_data_separator_pattern );\n\t\t\t\tconst faceVertices = [];\n\n\t\t\t\t// Parse the face vertex data into an easy to work with format\n\n\t\t\t\tfor ( let j = 0, jl = vertexData.length; j < jl; j ++ ) {\n\n\t\t\t\t\tconst vertex = vertexData[ j ];\n\n\t\t\t\t\tif ( vertex.length > 0 ) {\n\n\t\t\t\t\t\tconst vertexParts = vertex.split( '/' );\n\t\t\t\t\t\tfaceVertices.push( vertexParts );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\t// Draw an edge between the first vertex and all subsequent vertices to form an n-gon\n\n\t\t\t\tconst v1 = faceVertices[ 0 ];\n\n\t\t\t\tfor ( let j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) {\n\n\t\t\t\t\tconst v2 = faceVertices[ j ];\n\t\t\t\t\tconst v3 = faceVertices[ j + 1 ];\n\n\t\t\t\t\tstate.addFace(\n\t\t\t\t\t\tv1[ 0 ], v2[ 0 ], v3[ 0 ],\n\t\t\t\t\t\tv1[ 1 ], v2[ 1 ], v3[ 1 ],\n\t\t\t\t\t\tv1[ 2 ], v2[ 2 ], v3[ 2 ]\n\t\t\t\t\t);\n\n\t\t\t\t}\n\n\t\t\t} else if ( lineFirstChar === 'l' ) {\n\n\t\t\t\tconst lineParts = line.substring( 1 ).trim().split( ' ' );\n\t\t\t\tlet lineVertices = [];\n\t\t\t\tconst lineUVs = [];\n\n\t\t\t\tif ( line.indexOf( '/' ) === - 1 ) {\n\n\t\t\t\t\tlineVertices = lineParts;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tfor ( let li = 0, llen = lineParts.length; li < llen; li ++ ) {\n\n\t\t\t\t\t\tconst parts = lineParts[ li ].split( '/' );\n\n\t\t\t\t\t\tif ( parts[ 0 ] !== '' ) lineVertices.push( parts[ 0 ] );\n\t\t\t\t\t\tif ( parts[ 1 ] !== '' ) lineUVs.push( parts[ 1 ] );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tstate.addLineGeometry( lineVertices, lineUVs );\n\n\t\t\t} else if ( lineFirstChar === 'p' ) {\n\n\t\t\t\tconst lineData = line.slice( 1 ).trim();\n\t\t\t\tconst pointData = lineData.split( ' ' );\n\n\t\t\t\tstate.addPointGeometry( pointData );\n\n\t\t\t} else if ( ( result = _object_pattern.exec( line ) ) !== null ) {\n\n\t\t\t\t// o object_name\n\t\t\t\t// or\n\t\t\t\t// g group_name\n\n\t\t\t\t// WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869\n\t\t\t\t// let name = result[ 0 ].slice( 1 ).trim();\n\t\t\t\tconst name = ( ' ' + result[ 0 ].slice( 1 ).trim() ).slice( 1 );\n\n\t\t\t\tstate.startObject( name );\n\n\t\t\t} else if ( _material_use_pattern.test( line ) ) {\n\n\t\t\t\t// material\n\n\t\t\t\tstate.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries );\n\n\t\t\t} else if ( _material_library_pattern.test( line ) ) {\n\n\t\t\t\t// mtl file\n\n\t\t\t\tstate.materialLibraries.push( line.substring( 7 ).trim() );\n\n\t\t\t} else if ( _map_use_pattern.test( line ) ) {\n\n\t\t\t\t// the line is parsed but ignored since the loader assumes textures are defined MTL files\n\t\t\t\t// (according to https://www.okino.com/conv/imp_wave.htm, 'usemap' is the old-style Wavefront texture reference method)\n\n\t\t\t\tconsole.warn( 'THREE.OBJLoader: Rendering identifier \"usemap\" not supported. Textures must be defined in MTL files.' );\n\n\t\t\t} else if ( lineFirstChar === 's' ) {\n\n\t\t\t\tresult = line.split( ' ' );\n\n\t\t\t\t// smooth shading\n\n\t\t\t\t// @todo Handle files that have varying smooth values for a set of faces inside one geometry,\n\t\t\t\t// but does not define a usemtl for each face set.\n\t\t\t\t// This should be detected and a dummy material created (later MultiMaterial and geometry groups).\n\t\t\t\t// This requires some care to not create extra material on each smooth value for \"normal\" obj files.\n\t\t\t\t// where explicit usemtl defines geometry groups.\n\t\t\t\t// Example asset: examples/models/obj/cerberus/Cerberus.obj\n\n\t\t\t\t/*\n\t\t\t\t\t * http://paulbourke.net/dataformats/obj/\n\t\t\t\t\t *\n\t\t\t\t\t * From chapter \"Grouping\" Syntax explanation \"s group_number\":\n\t\t\t\t\t * \"group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off.\n\t\t\t\t\t * Polygonal elements use group numbers to put elements in different smoothing groups. For free-form\n\t\t\t\t\t * surfaces, smoothing groups are either turned on or off; there is no difference between values greater\n\t\t\t\t\t * than 0.\"\n\t\t\t\t\t */\n\t\t\t\tif ( result.length > 1 ) {\n\n\t\t\t\t\tconst value = result[ 1 ].trim().toLowerCase();\n\t\t\t\t\tstate.object.smooth = ( value !== '0' && value !== 'off' );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// ZBrush can produce \"s\" lines #11707\n\t\t\t\t\tstate.object.smooth = true;\n\n\t\t\t\t}\n\n\t\t\t\tconst material = state.object.currentMaterial();\n\t\t\t\tif ( material ) material.smooth = state.object.smooth;\n\n\t\t\t} else {\n\n\t\t\t\t// Handle null terminated files without exception\n\t\t\t\tif ( line === '\\0' ) continue;\n\n\t\t\t\tconsole.warn( 'THREE.OBJLoader: Unexpected line: \"' + line + '\"' );\n\n\t\t\t}\n\n\t\t}\n\n\t\tstate.finalize();\n\n\t\tconst container = new Group();\n\t\tcontainer.materialLibraries = [].concat( state.materialLibraries );\n\n\t\tconst hasPrimitives = ! ( state.objects.length === 1 && state.objects[ 0 ].geometry.vertices.length === 0 );\n\n\t\tif ( hasPrimitives === true ) {\n\n\t\t\tfor ( let i = 0, l = state.objects.length; i < l; i ++ ) {\n\n\t\t\t\tconst object = state.objects[ i ];\n\t\t\t\tconst geometry = object.geometry;\n\t\t\t\tconst materials = object.materials;\n\t\t\t\tconst isLine = ( geometry.type === 'Line' );\n\t\t\t\tconst isPoints = ( geometry.type === 'Points' );\n\t\t\t\tlet hasVertexColors = false;\n\n\t\t\t\t// Skip o/g line declarations that did not follow with any faces\n\t\t\t\tif ( geometry.vertices.length === 0 ) continue;\n\n\t\t\t\tconst buffergeometry = new BufferGeometry();\n\n\t\t\t\tbuffergeometry.setAttribute( 'position', new Float32BufferAttribute( geometry.vertices, 3 ) );\n\n\t\t\t\tif ( geometry.normals.length > 0 ) {\n\n\t\t\t\t\tbuffergeometry.setAttribute( 'normal', new Float32BufferAttribute( geometry.normals, 3 ) );\n\n\t\t\t\t}\n\n\t\t\t\tif ( geometry.colors.length > 0 ) {\n\n\t\t\t\t\thasVertexColors = true;\n\t\t\t\t\tbuffergeometry.setAttribute( 'color', new Float32BufferAttribute( geometry.colors, 3 ) );\n\n\t\t\t\t}\n\n\t\t\t\tif ( geometry.hasUVIndices === true ) {\n\n\t\t\t\t\tbuffergeometry.setAttribute( 'uv', new Float32BufferAttribute( geometry.uvs, 2 ) );\n\n\t\t\t\t}\n\n\t\t\t\t// Create materials\n\n\t\t\t\tconst createdMaterials = [];\n\n\t\t\t\tfor ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {\n\n\t\t\t\t\tconst sourceMaterial = materials[ mi ];\n\t\t\t\t\tconst materialHash = sourceMaterial.name + '_' + sourceMaterial.smooth + '_' + hasVertexColors;\n\t\t\t\t\tlet material = state.materials[ materialHash ];\n\n\t\t\t\t\tif ( this.materials !== null ) {\n\n\t\t\t\t\t\tmaterial = this.materials.create( sourceMaterial.name );\n\n\t\t\t\t\t\t// mtl etc. loaders probably can't create line materials correctly, copy properties to a line material.\n\t\t\t\t\t\tif ( isLine && material && ! ( material instanceof LineBasicMaterial ) ) {\n\n\t\t\t\t\t\t\tconst materialLine = new LineBasicMaterial();\n\t\t\t\t\t\t\tMaterial.prototype.copy.call( materialLine, material );\n\t\t\t\t\t\t\tmaterialLine.color.copy( material.color );\n\t\t\t\t\t\t\tmaterial = materialLine;\n\n\t\t\t\t\t\t} else if ( isPoints && material && ! ( material instanceof PointsMaterial ) ) {\n\n\t\t\t\t\t\t\tconst materialPoints = new PointsMaterial( { size: 10, sizeAttenuation: false } );\n\t\t\t\t\t\t\tMaterial.prototype.copy.call( materialPoints, material );\n\t\t\t\t\t\t\tmaterialPoints.color.copy( material.color );\n\t\t\t\t\t\t\tmaterialPoints.map = material.map;\n\t\t\t\t\t\t\tmaterial = materialPoints;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( material === undefined ) {\n\n\t\t\t\t\t\tif ( isLine ) {\n\n\t\t\t\t\t\t\tmaterial = new LineBasicMaterial();\n\n\t\t\t\t\t\t} else if ( isPoints ) {\n\n\t\t\t\t\t\t\tmaterial = new PointsMaterial( { size: 1, sizeAttenuation: false } );\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tmaterial = new MeshPhongMaterial();\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmaterial.name = sourceMaterial.name;\n\t\t\t\t\t\tmaterial.flatShading = sourceMaterial.smooth ? false : true;\n\t\t\t\t\t\tmaterial.vertexColors = hasVertexColors;\n\n\t\t\t\t\t\tstate.materials[ materialHash ] = material;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tcreatedMaterials.push( material );\n\n\t\t\t\t}\n\n\t\t\t\t// Create mesh\n\n\t\t\t\tlet mesh;\n\n\t\t\t\tif ( createdMaterials.length > 1 ) {\n\n\t\t\t\t\tfor ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {\n\n\t\t\t\t\t\tconst sourceMaterial = materials[ mi ];\n\t\t\t\t\t\tbuffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( isLine ) {\n\n\t\t\t\t\t\tmesh = new LineSegments( buffergeometry, createdMaterials );\n\n\t\t\t\t\t} else if ( isPoints ) {\n\n\t\t\t\t\t\tmesh = new Points( buffergeometry, createdMaterials );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tmesh = new Mesh( buffergeometry, createdMaterials );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( isLine ) {\n\n\t\t\t\t\t\tmesh = new LineSegments( buffergeometry, createdMaterials[ 0 ] );\n\n\t\t\t\t\t} else if ( isPoints ) {\n\n\t\t\t\t\t\tmesh = new Points( buffergeometry, createdMaterials[ 0 ] );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tmesh = new Mesh( buffergeometry, createdMaterials[ 0 ] );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tmesh.name = object.name;\n\n\t\t\t\tcontainer.add( mesh );\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t// if there is only the default parser state object with no geometry data, interpret data as point cloud\n\n\t\t\tif ( state.vertices.length > 0 ) {\n\n\t\t\t\tconst material = new PointsMaterial( { size: 1, sizeAttenuation: false } );\n\n\t\t\t\tconst buffergeometry = new BufferGeometry();\n\n\t\t\t\tbuffergeometry.setAttribute( 'position', new Float32BufferAttribute( state.vertices, 3 ) );\n\n\t\t\t\tif ( state.colors.length > 0 && state.colors[ 0 ] !== undefined ) {\n\n\t\t\t\t\tbuffergeometry.setAttribute( 'color', new Float32BufferAttribute( state.colors, 3 ) );\n\t\t\t\t\tmaterial.vertexColors = true;\n\n\t\t\t\t}\n\n\t\t\t\tconst points = new Points( buffergeometry, material );\n\t\t\t\tcontainer.add( points );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn container;\n\n\t}\n\n}\n\nexport { OBJLoader };\n","import {\n\tBufferAttribute,\n\tBufferGeometry,\n\tFloat32BufferAttribute,\n\tInstancedBufferAttribute,\n\tInterleavedBuffer,\n\tInterleavedBufferAttribute,\n\tTriangleFanDrawMode,\n\tTriangleStripDrawMode,\n\tTrianglesDrawMode,\n\tVector3,\n} from 'three';\n\n/**\n * @module BufferGeometryUtils\n * @three_import import * as BufferGeometryUtils from 'three/addons/utils/BufferGeometryUtils.js';\n */\n\n/**\n * Computes vertex tangents using the MikkTSpace algorithm. MikkTSpace generates the same tangents consistently,\n * and is used in most modelling tools and normal map bakers. Use MikkTSpace for materials with normal maps,\n * because inconsistent tangents may lead to subtle visual issues in the normal map, particularly around mirrored\n * UV seams.\n *\n * In comparison to this method, {@link BufferGeometry#computeTangents} (a custom algorithm) generates tangents that\n * probably will not match the tangents in other software. The custom algorithm is sufficient for general use with a\n * custom material, and may be faster than MikkTSpace.\n *\n * Returns the original BufferGeometry. Indexed geometries will be de-indexed. Requires position, normal, and uv attributes.\n *\n * @param {BufferGeometry} geometry - The geometry to compute tangents for.\n * @param {Object} MikkTSpace - Instance of `examples/jsm/libs/mikktspace.module.js`, or `mikktspace` npm package.\n * Await `MikkTSpace.ready` before use.\n * @param {boolean} [negateSign=true] - Whether to negate the sign component (.w) of each tangent.\n * Required for normal map conventions in some formats, including glTF.\n * @return {BufferGeometry} The updated geometry.\n */\nfunction computeMikkTSpaceTangents( geometry, MikkTSpace, negateSign = true ) {\n\n\tif ( ! MikkTSpace || ! MikkTSpace.isReady ) {\n\n\t\tthrow new Error( 'BufferGeometryUtils: Initialized MikkTSpace library required.' );\n\n\t}\n\n\tif ( ! geometry.hasAttribute( 'position' ) || ! geometry.hasAttribute( 'normal' ) || ! geometry.hasAttribute( 'uv' ) ) {\n\n\t\tthrow new Error( 'BufferGeometryUtils: Tangents require \"position\", \"normal\", and \"uv\" attributes.' );\n\n\t}\n\n\tfunction getAttributeArray( attribute ) {\n\n\t\tif ( attribute.normalized || attribute.isInterleavedBufferAttribute ) {\n\n\t\t\tconst dstArray = new Float32Array( attribute.count * attribute.itemSize );\n\n\t\t\tfor ( let i = 0, j = 0; i < attribute.count; i ++ ) {\n\n\t\t\t\tdstArray[ j ++ ] = attribute.getX( i );\n\t\t\t\tdstArray[ j ++ ] = attribute.getY( i );\n\n\t\t\t\tif ( attribute.itemSize > 2 ) {\n\n\t\t\t\t\tdstArray[ j ++ ] = attribute.getZ( i );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn dstArray;\n\n\t\t}\n\n\t\tif ( attribute.array instanceof Float32Array ) {\n\n\t\t\treturn attribute.array;\n\n\t\t}\n\n\t\treturn new Float32Array( attribute.array );\n\n\t}\n\n\t// MikkTSpace algorithm requires non-indexed input.\n\n\tconst _geometry = geometry.index ? geometry.toNonIndexed() : geometry;\n\n\t// Compute vertex tangents.\n\n\tconst tangents = MikkTSpace.generateTangents(\n\n\t\tgetAttributeArray( _geometry.attributes.position ),\n\t\tgetAttributeArray( _geometry.attributes.normal ),\n\t\tgetAttributeArray( _geometry.attributes.uv )\n\n\t);\n\n\t// Texture coordinate convention of glTF differs from the apparent\n\t// default of the MikkTSpace library; .w component must be flipped.\n\n\tif ( negateSign ) {\n\n\t\tfor ( let i = 3; i < tangents.length; i += 4 ) {\n\n\t\t\ttangents[ i ] *= - 1;\n\n\t\t}\n\n\t}\n\n\t//\n\n\t_geometry.setAttribute( 'tangent', new BufferAttribute( tangents, 4 ) );\n\n\tif ( geometry !== _geometry ) {\n\n\t\tgeometry.copy( _geometry );\n\n\t}\n\n\treturn geometry;\n\n}\n\n/**\n * Merges a set of geometries into a single instance. All geometries must have compatible attributes.\n *\n * @param {Array<BufferGeometry>} geometries - The geometries to merge.\n * @param {boolean} [useGroups=false] - Whether to use groups or not.\n * @return {?BufferGeometry} The merged geometry. Returns `null` if the merge does not succeed.\n */\nfunction mergeGeometries( geometries, useGroups = false ) {\n\n\tconst isIndexed = geometries[ 0 ].index !== null;\n\n\tconst attributesUsed = new Set( Object.keys( geometries[ 0 ].attributes ) );\n\tconst morphAttributesUsed = new Set( Object.keys( geometries[ 0 ].morphAttributes ) );\n\n\tconst attributes = {};\n\tconst morphAttributes = {};\n\n\tconst morphTargetsRelative = geometries[ 0 ].morphTargetsRelative;\n\n\tconst mergedGeometry = new BufferGeometry();\n\n\tlet offset = 0;\n\n\tfor ( let i = 0; i < geometries.length; ++ i ) {\n\n\t\tconst geometry = geometries[ i ];\n\t\tlet attributesCount = 0;\n\n\t\t// ensure that all geometries are indexed, or none\n\n\t\tif ( isIndexed !== ( geometry.index !== null ) ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index ' + i + '. All geometries must have compatible attributes; make sure index attribute exists among all geometries, or in none of them.' );\n\t\t\treturn null;\n\n\t\t}\n\n\t\t// gather attributes, exit early if they're different\n\n\t\tfor ( const name in geometry.attributes ) {\n\n\t\t\tif ( ! attributesUsed.has( name ) ) {\n\n\t\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index ' + i + '. All geometries must have compatible attributes; make sure \"' + name + '\" attribute exists among all geometries, or in none of them.' );\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t\tif ( attributes[ name ] === undefined ) attributes[ name ] = [];\n\n\t\t\tattributes[ name ].push( geometry.attributes[ name ] );\n\n\t\t\tattributesCount ++;\n\n\t\t}\n\n\t\t// ensure geometries have the same number of attributes\n\n\t\tif ( attributesCount !== attributesUsed.size ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index ' + i + '. Make sure all geometries have the same number of attributes.' );\n\t\t\treturn null;\n\n\t\t}\n\n\t\t// gather morph attributes, exit early if they're different\n\n\t\tif ( morphTargetsRelative !== geometry.morphTargetsRelative ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index ' + i + '. .morphTargetsRelative must be consistent throughout all geometries.' );\n\t\t\treturn null;\n\n\t\t}\n\n\t\tfor ( const name in geometry.morphAttributes ) {\n\n\t\t\tif ( ! morphAttributesUsed.has( name ) ) {\n\n\t\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index ' + i + '. .morphAttributes must be consistent throughout all geometries.' );\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t\tif ( morphAttributes[ name ] === undefined ) morphAttributes[ name ] = [];\n\n\t\t\tmorphAttributes[ name ].push( geometry.morphAttributes[ name ] );\n\n\t\t}\n\n\t\tif ( useGroups ) {\n\n\t\t\tlet count;\n\n\t\t\tif ( isIndexed ) {\n\n\t\t\t\tcount = geometry.index.count;\n\n\t\t\t} else if ( geometry.attributes.position !== undefined ) {\n\n\t\t\t\tcount = geometry.attributes.position.count;\n\n\t\t\t} else {\n\n\t\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index ' + i + '. The geometry must have either an index or a position attribute' );\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t\tmergedGeometry.addGroup( offset, count, i );\n\n\t\t\toffset += count;\n\n\t\t}\n\n\t}\n\n\t// merge indices\n\n\tif ( isIndexed ) {\n\n\t\tlet indexOffset = 0;\n\t\tconst mergedIndex = [];\n\n\t\tfor ( let i = 0; i < geometries.length; ++ i ) {\n\n\t\t\tconst index = geometries[ i ].index;\n\n\t\t\tfor ( let j = 0; j < index.count; ++ j ) {\n\n\t\t\t\tmergedIndex.push( index.getX( j ) + indexOffset );\n\n\t\t\t}\n\n\t\t\tindexOffset += geometries[ i ].attributes.position.count;\n\n\t\t}\n\n\t\tmergedGeometry.setIndex( mergedIndex );\n\n\t}\n\n\t// merge attributes\n\n\tfor ( const name in attributes ) {\n\n\t\tconst mergedAttribute = mergeAttributes( attributes[ name ] );\n\n\t\tif ( ! mergedAttribute ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed while trying to merge the ' + name + ' attribute.' );\n\t\t\treturn null;\n\n\t\t}\n\n\t\tmergedGeometry.setAttribute( name, mergedAttribute );\n\n\t}\n\n\t// merge morph attributes\n\n\tfor ( const name in morphAttributes ) {\n\n\t\tconst numMorphTargets = morphAttributes[ name ][ 0 ].length;\n\t\tif ( numMorphTargets === 0 ) continue;\n\n\t\tmergedGeometry.morphAttributes = mergedGeometry.morphAttributes || {};\n\t\tmergedGeometry.morphAttributes[ name ] = [];\n\n\t\tfor ( let i = 0; i < numMorphTargets; ++ i ) {\n\n\t\t\tconst morphAttributesToMerge = [];\n\n\t\t\tfor ( let j = 0; j < morphAttributes[ name ].length; ++ j ) {\n\n\t\t\t\tmorphAttributesToMerge.push( morphAttributes[ name ][ j ][ i ] );\n\n\t\t\t}\n\n\t\t\tconst mergedMorphAttribute = mergeAttributes( morphAttributesToMerge );\n\n\t\t\tif ( ! mergedMorphAttribute ) {\n\n\t\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed while trying to merge the ' + name + ' morphAttribute.' );\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t\tmergedGeometry.morphAttributes[ name ].push( mergedMorphAttribute );\n\n\t\t}\n\n\t}\n\n\treturn mergedGeometry;\n\n}\n\n/**\n * Merges a set of attributes into a single instance. All attributes must have compatible properties and types.\n * Instances of {@link InterleavedBufferAttribute} are not supported.\n *\n * @param {Array<BufferAttribute>} attributes - The attributes to merge.\n * @return {?BufferAttribute} The merged attribute. Returns `null` if the merge does not succeed.\n */\nfunction mergeAttributes( attributes ) {\n\n\tlet TypedArray;\n\tlet itemSize;\n\tlet normalized;\n\tlet gpuType = - 1;\n\tlet arrayLength = 0;\n\n\tfor ( let i = 0; i < attributes.length; ++ i ) {\n\n\t\tconst attribute = attributes[ i ];\n\n\t\tif ( TypedArray === undefined ) TypedArray = attribute.array.constructor;\n\t\tif ( TypedArray !== attribute.array.constructor ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeAttributes() failed. BufferAttribute.array must be of consistent array types across matching attributes.' );\n\t\t\treturn null;\n\n\t\t}\n\n\t\tif ( itemSize === undefined ) itemSize = attribute.itemSize;\n\t\tif ( itemSize !== attribute.itemSize ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeAttributes() failed. BufferAttribute.itemSize must be consistent across matching attributes.' );\n\t\t\treturn null;\n\n\t\t}\n\n\t\tif ( normalized === undefined ) normalized = attribute.normalized;\n\t\tif ( normalized !== attribute.normalized ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeAttributes() failed. BufferAttribute.normalized must be consistent across matching attributes.' );\n\t\t\treturn null;\n\n\t\t}\n\n\t\tif ( gpuType === - 1 ) gpuType = attribute.gpuType;\n\t\tif ( gpuType !== attribute.gpuType ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometryUtils: .mergeAttributes() failed. BufferAttribute.gpuType must be consistent across matching attributes.' );\n\t\t\treturn null;\n\n\t\t}\n\n\t\tarrayLength += attribute.count * itemSize;\n\n\t}\n\n\tconst array = new TypedArray( arrayLength );\n\tconst result = new BufferAttribute( array, itemSize, normalized );\n\tlet offset = 0;\n\n\tfor ( let i = 0; i < attributes.length; ++ i ) {\n\n\t\tconst attribute = attributes[ i ];\n\t\tif ( attribute.isInterleavedBufferAttribute ) {\n\n\t\t\tconst tupleOffset = offset / itemSize;\n\t\t\tfor ( let j = 0, l = attribute.count; j < l; j ++ ) {\n\n\t\t\t\tfor ( let c = 0; c < itemSize; c ++ ) {\n\n\t\t\t\t\tconst value = attribute.getComponent( j, c );\n\t\t\t\t\tresult.setComponent( j + tupleOffset, c, value );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tarray.set( attribute.array, offset );\n\n\t\t}\n\n\t\toffset += attribute.count * itemSize;\n\n\t}\n\n\tif ( gpuType !== undefined ) {\n\n\t\tresult.gpuType = gpuType;\n\n\t}\n\n\treturn result;\n\n}\n\n/**\n * Performs a deep clone of the given buffer attribute.\n *\n * @param {BufferAttribute} attribute - The attribute to clone.\n * @return {BufferAttribute} The cloned attribute.\n */\nfunction deepCloneAttribute( attribute ) {\n\n\tif ( attribute.isInstancedInterleavedBufferAttribute || attribute.isInterleavedBufferAttribute ) {\n\n\t\treturn deinterleaveAttribute( attribute );\n\n\t}\n\n\tif ( attribute.isInstancedBufferAttribute ) {\n\n\t\treturn new InstancedBufferAttribute().copy( attribute );\n\n\t}\n\n\treturn new BufferAttribute().copy( attribute );\n\n}\n\n/**\n * Interleaves a set of attributes and returns a new array of corresponding attributes that share a\n * single {@link InterleavedBuffer} instance. All attributes must have compatible types.\n *\n * @param {Array<BufferAttribute>} attributes - The attributes to interleave.\n * @return {?Array<InterleavedBufferAttribute>} An array of interleaved attributes. If interleave does not succeed, the method returns `null`.\n */\nfunction interleaveAttributes( attributes ) {\n\n\t// Interleaves the provided attributes into an InterleavedBuffer and returns\n\t// a set of InterleavedBufferAttributes for each attribute\n\tlet TypedArray;\n\tlet arrayLength = 0;\n\tlet stride = 0;\n\n\t// calculate the length and type of the interleavedBuffer\n\tfor ( let i = 0, l = attributes.length; i < l; ++ i ) {\n\n\t\tconst attribute = attributes[ i ];\n\n\t\tif ( TypedArray === undefined ) TypedArray = attribute.array.constructor;\n\t\tif ( TypedArray !== attribute.array.constructor ) {\n\n\t\t\tconsole.error( 'AttributeBuffers of different types cannot be interleaved' );\n\t\t\treturn null;\n\n\t\t}\n\n\t\tarrayLength += attribute.array.length;\n\t\tstride += attribute.itemSize;\n\n\t}\n\n\t// Create the set of buffer attributes\n\tconst interleavedBuffer = new InterleavedBuffer( new TypedArray( arrayLength ), stride );\n\tlet offset = 0;\n\tconst res = [];\n\tconst getters = [ 'getX', 'getY', 'getZ', 'getW' ];\n\tconst setters = [ 'setX', 'setY', 'setZ', 'setW' ];\n\n\tfor ( let j = 0, l = attributes.length; j < l; j ++ ) {\n\n\t\tconst attribute = attributes[ j ];\n\t\tconst itemSize = attribute.itemSize;\n\t\tconst count = attribute.count;\n\t\tconst iba = new InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, attribute.normalized );\n\t\tres.push( iba );\n\n\t\toffset += itemSize;\n\n\t\t// Move the data for each attribute into the new interleavedBuffer\n\t\t// at the appropriate offset\n\t\tfor ( let c = 0; c < count; c ++ ) {\n\n\t\t\tfor ( let k = 0; k < itemSize; k ++ ) {\n\n\t\t\t\tiba[ setters[ k ] ]( c, attribute[ getters[ k ] ]( c ) );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\treturn res;\n\n}\n\n/**\n * Returns a new, non-interleaved version of the given attribute.\n *\n * @param {InterleavedBufferAttribute} attribute - The interleaved attribute.\n * @return {BufferAttribute} The non-interleaved attribute.\n */\nfunction deinterleaveAttribute( attribute ) {\n\n\tconst cons = attribute.data.array.constructor;\n\tconst count = attribute.count;\n\tconst itemSize = attribute.itemSize;\n\tconst normalized = attribute.normalized;\n\n\tconst array = new cons( count * itemSize );\n\tlet newAttribute;\n\tif ( attribute.isInstancedInterleavedBufferAttribute ) {\n\n\t\tnewAttribute = new InstancedBufferAttribute( array, itemSize, normalized, attribute.meshPerAttribute );\n\n\t} else {\n\n\t\tnewAttribute = new BufferAttribute( array, itemSize, normalized );\n\n\t}\n\n\tfor ( let i = 0; i < count; i ++ ) {\n\n\t\tnewAttribute.setX( i, attribute.getX( i ) );\n\n\t\tif ( itemSize >= 2 ) {\n\n\t\t\tnewAttribute.setY( i, attribute.getY( i ) );\n\n\t\t}\n\n\t\tif ( itemSize >= 3 ) {\n\n\t\t\tnewAttribute.setZ( i, attribute.getZ( i ) );\n\n\t\t}\n\n\t\tif ( itemSize >= 4 ) {\n\n\t\t\tnewAttribute.setW( i, attribute.getW( i ) );\n\n\t\t}\n\n\t}\n\n\treturn newAttribute;\n\n}\n\n/**\n * Deinterleaves all attributes on the given geometry.\n *\n * @param {BufferGeometry} geometry - The geometry to deinterleave.\n */\nfunction deinterleaveGeometry( geometry ) {\n\n\tconst attributes = geometry.attributes;\n\tconst morphTargets = geometry.morphTargets;\n\tconst attrMap = new Map();\n\n\tfor ( const key in attributes ) {\n\n\t\tconst attr = attributes[ key ];\n\t\tif ( attr.isInterleavedBufferAttribute ) {\n\n\t\t\tif ( ! attrMap.has( attr ) ) {\n\n\t\t\t\tattrMap.set( attr, deinterleaveAttribute( attr ) );\n\n\t\t\t}\n\n\t\t\tattributes[ key ] = attrMap.get( attr );\n\n\t\t}\n\n\t}\n\n\tfor ( const key in morphTargets ) {\n\n\t\tconst attr = morphTargets[ key ];\n\t\tif ( attr.isInterleavedBufferAttribute ) {\n\n\t\t\tif ( ! attrMap.has( attr ) ) {\n\n\t\t\t\tattrMap.set( attr, deinterleaveAttribute( attr ) );\n\n\t\t\t}\n\n\t\t\tmorphTargets[ key ] = attrMap.get( attr );\n\n\t\t}\n\n\t}\n\n}\n\n/**\n * Returns the amount of bytes used by all attributes to represent the geometry.\n *\n * @param {BufferGeometry} geometry - The geometry.\n * @return {number} The estimate bytes used.\n */\nfunction estimateBytesUsed( geometry ) {\n\n\t// Return the estimated memory used by this geometry in bytes\n\t// Calculate using itemSize, count, and BYTES_PER_ELEMENT to account\n\t// for InterleavedBufferAttributes.\n\tlet mem = 0;\n\tfor ( const name in geometry.attributes ) {\n\n\t\tconst attr = geometry.getAttribute( name );\n\t\tmem += attr.count * attr.itemSize * attr.array.BYTES_PER_ELEMENT;\n\n\t}\n\n\tconst indices = geometry.getIndex();\n\tmem += indices ? indices.count * indices.itemSize * indices.array.BYTES_PER_ELEMENT : 0;\n\treturn mem;\n\n}\n\n/**\n * Returns a new geometry with vertices for which all similar vertex attributes (within tolerance) are merged.\n *\n * @param {BufferGeometry} geometry - The geometry to merge vertices for.\n * @param {number} [tolerance=1e-4] - The tolerance value.\n * @return {BufferGeometry} - The new geometry with merged vertices.\n */\nfunction mergeVertices( geometry, tolerance = 1e-4 ) {\n\n\ttolerance = Math.max( tolerance, Number.EPSILON );\n\n\t// Generate an index buffer if the geometry doesn't have one, or optimize it\n\t// if it's already available.\n\tconst hashToIndex = {};\n\tconst indices = geometry.getIndex();\n\tconst positions = geometry.getAttribute( 'position' );\n\tconst vertexCount = indices ? indices.count : positions.count;\n\n\t// next value for triangle indices\n\tlet nextIndex = 0;\n\n\t// attributes and new attribute arrays\n\tconst attributeNames = Object.keys( geometry.attributes );\n\tconst tmpAttributes = {};\n\tconst tmpMorphAttributes = {};\n\tconst newIndices = [];\n\tconst getters = [ 'getX', 'getY', 'getZ', 'getW' ];\n\tconst setters = [ 'setX', 'setY', 'setZ', 'setW' ];\n\n\t// Initialize the arrays, allocating space conservatively. Extra\n\t// space will be trimmed in the last step.\n\tfor ( let i = 0, l = attributeNames.length; i < l; i ++ ) {\n\n\t\tconst name = attributeNames[ i ];\n\t\tconst attr = geometry.attributes[ name ];\n\n\t\ttmpAttributes[ name ] = new attr.constructor(\n\t\t\tnew attr.array.constructor( attr.count * attr.itemSize ),\n\t\t\tattr.itemSize,\n\t\t\tattr.normalized\n\t\t);\n\n\t\tconst morphAttributes = geometry.morphAttributes[ name ];\n\t\tif ( morphAttributes ) {\n\n\t\t\tif ( ! tmpMorphAttributes[ name ] ) tmpMorphAttributes[ name ] = [];\n\t\t\tmorphAttributes.forEach( ( morphAttr, i ) => {\n\n\t\t\t\tconst array = new morphAttr.array.constructor( morphAttr.count * morphAttr.itemSize );\n\t\t\t\ttmpMorphAttributes[ name ][ i ] = new morphAttr.constructor( array, morphAttr.itemSize, morphAttr.normalized );\n\n\t\t\t} );\n\n\t\t}\n\n\t}\n\n\t// convert the error tolerance to an amount of decimal places to truncate to\n\tconst halfTolerance = tolerance * 0.5;\n\tconst exponent = Math.log10( 1 / tolerance );\n\tconst hashMultiplier = Math.pow( 10, exponent );\n\tconst hashAdditive = halfTolerance * hashMultiplier;\n\tfor ( let i = 0; i < vertexCount; i ++ ) {\n\n\t\tconst index = indices ? indices.getX( i ) : i;\n\n\t\t// Generate a hash for the vertex attributes at the current index 'i'\n\t\tlet hash = '';\n\t\tfor ( let j = 0, l = attributeNames.length; j < l; j ++ ) {\n\n\t\t\tconst name = attributeNames[ j ];\n\t\t\tconst attribute = geometry.getAttribute( name );\n\t\t\tconst itemSize = attribute.itemSize;\n\n\t\t\tfor ( let k = 0; k < itemSize; k ++ ) {\n\n\t\t\t\t// double tilde truncates the decimal value\n\t\t\t\thash += `${ ~ ~ ( attribute[ getters[ k ] ]( index ) * hashMultiplier + hashAdditive ) },`;\n\n\t\t\t}\n\n\t\t}\n\n\t\t// Add another reference to the vertex if it's already\n\t\t// used by another index\n\t\tif ( hash in hashToIndex ) {\n\n\t\t\tnewIndices.push( hashToIndex[ hash ] );\n\n\t\t} else {\n\n\t\t\t// copy data to the new index in the temporary attributes\n\t\t\tfor ( let j = 0, l = attributeNames.length; j < l; j ++ ) {\n\n\t\t\t\tconst name = attributeNames[ j ];\n\t\t\t\tconst attribute = geometry.getAttribute( name );\n\t\t\t\tconst morphAttributes = geometry.morphAttributes[ name ];\n\t\t\t\tconst itemSize = attribute.itemSize;\n\t\t\t\tconst newArray = tmpAttributes[ name ];\n\t\t\t\tconst newMorphArrays = tmpMorphAttributes[ name ];\n\n\t\t\t\tfor ( let k = 0; k < itemSize; k ++ ) {\n\n\t\t\t\t\tconst getterFunc = getters[ k ];\n\t\t\t\t\tconst setterFunc = setters[ k ];\n\t\t\t\t\tnewArray[ setterFunc ]( nextIndex, attribute[ getterFunc ]( index ) );\n\n\t\t\t\t\tif ( morphAttributes ) {\n\n\t\t\t\t\t\tfor ( let m = 0, ml = morphAttributes.length; m < ml; m ++ ) {\n\n\t\t\t\t\t\t\tnewMorphArrays[ m ][ setterFunc ]( nextIndex, morphAttributes[ m ][ getterFunc ]( index ) );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\thashToIndex[ hash ] = nextIndex;\n\t\t\tnewIndices.push( nextIndex );\n\t\t\tnextIndex ++;\n\n\t\t}\n\n\t}\n\n\t// generate result BufferGeometry\n\tconst result = geometry.clone();\n\tfor ( const name in geometry.attributes ) {\n\n\t\tconst tmpAttribute = tmpAttributes[ name ];\n\n\t\tresult.setAttribute( name, new tmpAttribute.constructor(\n\t\t\ttmpAttribute.array.slice( 0, nextIndex * tmpAttribute.itemSize ),\n\t\t\ttmpAttribute.itemSize,\n\t\t\ttmpAttribute.normalized,\n\t\t) );\n\n\t\tif ( ! ( name in tmpMorphAttributes ) ) continue;\n\n\t\tfor ( let j = 0; j < tmpMorphAttributes[ name ].length; j ++ ) {\n\n\t\t\tconst tmpMorphAttribute = tmpMorphAttributes[ name ][ j ];\n\n\t\t\tresult.morphAttributes[ name ][ j ] = new tmpMorphAttribute.constructor(\n\t\t\t\ttmpMorphAttribute.array.slice( 0, nextIndex * tmpMorphAttribute.itemSize ),\n\t\t\t\ttmpMorphAttribute.itemSize,\n\t\t\t\ttmpMorphAttribute.normalized,\n\t\t\t);\n\n\t\t}\n\n\t}\n\n\t// indices\n\n\tresult.setIndex( newIndices );\n\n\treturn result;\n\n}\n\n/**\n * Returns a new indexed geometry based on `TrianglesDrawMode` draw mode.\n * This mode corresponds to the `gl.TRIANGLES` primitive in WebGL.\n *\n * @param {BufferGeometry} geometry - The geometry to convert.\n * @param {number} drawMode - The current draw mode.\n * @return {BufferGeometry} The new geometry using `TrianglesDrawMode`.\n */\nfunction toTrianglesDrawMode( geometry, drawMode ) {\n\n\tif ( drawMode === TrianglesDrawMode ) {\n\n\t\tconsole.warn( 'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles.' );\n\t\treturn geometry;\n\n\t}\n\n\tif ( drawMode === TriangleFanDrawMode || drawMode === TriangleStripDrawMode ) {\n\n\t\tlet index = geometry.getIndex();\n\n\t\t// generate index if not present\n\n\t\tif ( index === null ) {\n\n\t\t\tconst indices = [];\n\n\t\t\tconst position = geometry.getAttribute( 'position' );\n\n\t\t\tif ( position !== undefined ) {\n\n\t\t\t\tfor ( let i = 0; i < position.count; i ++ ) {\n\n\t\t\t\t\tindices.push( i );\n\n\t\t\t\t}\n\n\t\t\t\tgeometry.setIndex( indices );\n\t\t\t\tindex = geometry.getIndex();\n\n\t\t\t} else {\n\n\t\t\t\tconsole.error( 'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Undefined position attribute. Processing not possible.' );\n\t\t\t\treturn geometry;\n\n\t\t\t}\n\n\t\t}\n\n\t\t//\n\n\t\tconst numberOfTriangles = index.count - 2;\n\t\tconst newIndices = [];\n\n\t\tif ( drawMode === TriangleFanDrawMode ) {\n\n\t\t\t// gl.TRIANGLE_FAN\n\n\t\t\tfor ( let i = 1; i <= numberOfTriangles; i ++ ) {\n\n\t\t\t\tnewIndices.push( index.getX( 0 ) );\n\t\t\t\tnewIndices.push( index.getX( i ) );\n\t\t\t\tnewIndices.push( index.getX( i + 1 ) );\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t// gl.TRIANGLE_STRIP\n\n\t\t\tfor ( let i = 0; i < numberOfTriangles; i ++ ) {\n\n\t\t\t\tif ( i % 2 === 0 ) {\n\n\t\t\t\t\tnewIndices.push( index.getX( i ) );\n\t\t\t\t\tnewIndices.push( index.getX( i + 1 ) );\n\t\t\t\t\tnewIndices.push( index.getX( i + 2 ) );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tnewIndices.push( index.getX( i + 2 ) );\n\t\t\t\t\tnewIndices.push( index.getX( i + 1 ) );\n\t\t\t\t\tnewIndices.push( index.getX( i ) );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( ( newIndices.length / 3 ) !== numberOfTriangles ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unable to generate correct amount of triangles.' );\n\n\t\t}\n\n\t\t// build final geometry\n\n\t\tconst newGeometry = geometry.clone();\n\t\tnewGeometry.setIndex( newIndices );\n\t\tnewGeometry.clearGroups();\n\n\t\treturn newGeometry;\n\n\t} else {\n\n\t\tconsole.error( 'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:', drawMode );\n\t\treturn geometry;\n\n\t}\n\n}\n\n/**\n * Calculates the morphed attributes of a morphed/skinned BufferGeometry.\n *\n * Helpful for Raytracing or Decals (i.e. a `DecalGeometry` applied to a morphed Object with a `BufferGeometry`\n * will use the original `BufferGeometry`, not the morphed/skinned one, generating an incorrect result.\n * Using this function to create a shadow `Object3`D the `DecalGeometry` can be correctly generated).\n *\n * @param {Mesh|Line|Points} object - The 3D object to compute morph attributes for.\n * @return {Object} An object with original position/normal attributes and morphed ones.\n */\nfunction computeMorphedAttributes( object ) {\n\n\tconst _vA = new Vector3();\n\tconst _vB = new Vector3();\n\tconst _vC = new Vector3();\n\n\tconst _tempA = new Vector3();\n\tconst _tempB = new Vector3();\n\tconst _tempC = new Vector3();\n\n\tconst _morphA = new Vector3();\n\tconst _morphB = new Vector3();\n\tconst _morphC = new Vector3();\n\n\tfunction _calculateMorphedAttributeData(\n\t\tobject,\n\t\tattribute,\n\t\tmorphAttribute,\n\t\tmorphTargetsRelative,\n\t\ta,\n\t\tb,\n\t\tc,\n\t\tmodifiedAttributeArray\n\t) {\n\n\t\t_vA.fromBufferAttribute( attribute, a );\n\t\t_vB.fromBufferAttribute( attribute, b );\n\t\t_vC.fromBufferAttribute( attribute, c );\n\n\t\tconst morphInfluences = object.morphTargetInfluences;\n\n\t\tif ( morphAttribute && morphInfluences ) {\n\n\t\t\t_morphA.set( 0, 0, 0 );\n\t\t\t_morphB.set( 0, 0, 0 );\n\t\t\t_morphC.set( 0, 0, 0 );\n\n\t\t\tfor ( let i = 0, il = morphAttribute.length; i < il; i ++ ) {\n\n\t\t\t\tconst influence = morphInfluences[ i ];\n\t\t\t\tconst morph = morphAttribute[ i ];\n\n\t\t\t\tif ( influence === 0 ) continue;\n\n\t\t\t\t_tempA.fromBufferAttribute( morph, a );\n\t\t\t\t_tempB.fromBufferAttribute( morph, b );\n\t\t\t\t_tempC.fromBufferAttribute( morph, c );\n\n\t\t\t\tif ( morphTargetsRelative ) {\n\n\t\t\t\t\t_morphA.addScaledVector( _tempA, influence );\n\t\t\t\t\t_morphB.addScaledVector( _tempB, influence );\n\t\t\t\t\t_morphC.addScaledVector( _tempC, influence );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t_morphA.addScaledVector( _tempA.sub( _vA ), influence );\n\t\t\t\t\t_morphB.addScaledVector( _tempB.sub( _vB ), influence );\n\t\t\t\t\t_morphC.addScaledVector( _tempC.sub( _vC ), influence );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t_vA.add( _morphA );\n\t\t\t_vB.add( _morphB );\n\t\t\t_vC.add( _morphC );\n\n\t\t}\n\n\t\tif ( object.isSkinnedMesh ) {\n\n\t\t\tobject.applyBoneTransform( a, _vA );\n\t\t\tobject.applyBoneTransform( b, _vB );\n\t\t\tobject.applyBoneTransform( c, _vC );\n\n\t\t}\n\n\t\tmodifiedAttributeArray[ a * 3 + 0 ] = _vA.x;\n\t\tmodifiedAttributeArray[ a * 3 + 1 ] = _vA.y;\n\t\tmodifiedAttributeArray[ a * 3 + 2 ] = _vA.z;\n\t\tmodifiedAttributeArray[ b * 3 + 0 ] = _vB.x;\n\t\tmodifiedAttributeArray[ b * 3 + 1 ] = _vB.y;\n\t\tmodifiedAttributeArray[ b * 3 + 2 ] = _vB.z;\n\t\tmodifiedAttributeArray[ c * 3 + 0 ] = _vC.x;\n\t\tmodifiedAttributeArray[ c * 3 + 1 ] = _vC.y;\n\t\tmodifiedAttributeArray[ c * 3 + 2 ] = _vC.z;\n\n\t}\n\n\tconst geometry = object.geometry;\n\tconst material = object.material;\n\n\tlet a, b, c;\n\tconst index = geometry.index;\n\tconst positionAttribute = geometry.attributes.position;\n\tconst morphPosition = geometry.morphAttributes.position;\n\tconst morphTargetsRelative = geometry.morphTargetsRelative;\n\tconst normalAttribute = geometry.attributes.normal;\n\tconst morphNormal = geometry.morphAttributes.normal;\n\n\tconst groups = geometry.groups;\n\tconst drawRange = geometry.drawRange;\n\tlet i, j, il, jl;\n\tlet group;\n\tlet start, end;\n\n\tconst modifiedPosition = new Float32Array( positionAttribute.count * positionAttribute.itemSize );\n\tconst modifiedNormal = new Float32Array( normalAttribute.count * normalAttribute.itemSize );\n\n\tif ( index !== null ) {\n\n\t\t// indexed buffer geometry\n\n\t\tif ( Array.isArray( material ) ) {\n\n\t\t\tfor ( i = 0, il = groups.length; i < il; i ++ ) {\n\n\t\t\t\tgroup = groups[ i ];\n\n\t\t\t\tstart = Math.max( group.start, drawRange.start );\n\t\t\t\tend = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );\n\n\t\t\t\tfor ( j = start, jl = end; j < jl; j += 3 ) {\n\n\t\t\t\t\ta = index.getX( j );\n\t\t\t\t\tb = index.getX( j + 1 );\n\t\t\t\t\tc = index.getX( j + 2 );\n\n\t\t\t\t\t_calculateMorphedAttributeData(\n\t\t\t\t\t\tobject,\n\t\t\t\t\t\tpositionAttribute,\n\t\t\t\t\t\tmorphPosition,\n\t\t\t\t\t\tmorphTargetsRelative,\n\t\t\t\t\t\ta, b, c,\n\t\t\t\t\t\tmodifiedPosition\n\t\t\t\t\t);\n\n\t\t\t\t\t_calculateMorphedAttributeData(\n\t\t\t\t\t\tobject,\n\t\t\t\t\t\tnormalAttribute,\n\t\t\t\t\t\tmorphNormal,\n\t\t\t\t\t\tmorphTargetsRelative,\n\t\t\t\t\t\ta, b, c,\n\t\t\t\t\t\tmodifiedNormal\n\t\t\t\t\t);\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tstart = Math.max( 0, drawRange.start );\n\t\t\tend = Math.min( index.count, ( drawRange.start + drawRange.count ) );\n\n\t\t\tfor ( i = start, il = end; i < il; i += 3 ) {\n\n\t\t\t\ta = index.getX( i );\n\t\t\t\tb = index.getX( i + 1 );\n\t\t\t\tc = index.getX( i + 2 );\n\n\t\t\t\t_calculateMorphedAttributeData(\n\t\t\t\t\tobject,\n\t\t\t\t\tpositionAttribute,\n\t\t\t\t\tmorphPosition,\n\t\t\t\t\tmorphTargetsRelative,\n\t\t\t\t\ta, b, c,\n\t\t\t\t\tmodifiedPosition\n\t\t\t\t);\n\n\t\t\t\t_calculateMorphedAttributeData(\n\t\t\t\t\tobject,\n\t\t\t\t\tnormalAttribute,\n\t\t\t\t\tmorphNormal,\n\t\t\t\t\tmorphTargetsRelative,\n\t\t\t\t\ta, b, c,\n\t\t\t\t\tmodifiedNormal\n\t\t\t\t);\n\n\t\t\t}\n\n\t\t}\n\n\t} else {\n\n\t\t// non-indexed buffer geometry\n\n\t\tif ( Array.isArray( material ) ) {\n\n\t\t\tfor ( i = 0, il = groups.length; i < il; i ++ ) {\n\n\t\t\t\tgroup = groups[ i ];\n\n\t\t\t\tstart = Math.max( group.start, drawRange.start );\n\t\t\t\tend = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );\n\n\t\t\t\tfor ( j = start, jl = end; j < jl; j += 3 ) {\n\n\t\t\t\t\ta = j;\n\t\t\t\t\tb = j + 1;\n\t\t\t\t\tc = j + 2;\n\n\t\t\t\t\t_calculateMorphedAttributeData(\n\t\t\t\t\t\tobject,\n\t\t\t\t\t\tpositionAttribute,\n\t\t\t\t\t\tmorphPosition,\n\t\t\t\t\t\tmorphTargetsRelative,\n\t\t\t\t\t\ta, b, c,\n\t\t\t\t\t\tmodifiedPosition\n\t\t\t\t\t);\n\n\t\t\t\t\t_calculateMorphedAttributeData(\n\t\t\t\t\t\tobject,\n\t\t\t\t\t\tnormalAttribute,\n\t\t\t\t\t\tmorphNormal,\n\t\t\t\t\t\tmorphTargetsRelative,\n\t\t\t\t\t\ta, b, c,\n\t\t\t\t\t\tmodifiedNormal\n\t\t\t\t\t);\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tstart = Math.max( 0, drawRange.start );\n\t\t\tend = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) );\n\n\t\t\tfor ( i = start, il = end; i < il; i += 3 ) {\n\n\t\t\t\ta = i;\n\t\t\t\tb = i + 1;\n\t\t\t\tc = i + 2;\n\n\t\t\t\t_calculateMorphedAttributeData(\n\t\t\t\t\tobject,\n\t\t\t\t\tpositionAttribute,\n\t\t\t\t\tmorphPosition,\n\t\t\t\t\tmorphTargetsRelative,\n\t\t\t\t\ta, b, c,\n\t\t\t\t\tmodifiedPosition\n\t\t\t\t);\n\n\t\t\t\t_calculateMorphedAttributeData(\n\t\t\t\t\tobject,\n\t\t\t\t\tnormalAttribute,\n\t\t\t\t\tmorphNormal,\n\t\t\t\t\tmorphTargetsRelative,\n\t\t\t\t\ta, b, c,\n\t\t\t\t\tmodifiedNormal\n\t\t\t\t);\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tconst morphedPositionAttribute = new Float32BufferAttribute( modifiedPosition, 3 );\n\tconst morphedNormalAttribute = new Float32BufferAttribute( modifiedNormal, 3 );\n\n\treturn {\n\n\t\tpositionAttribute: positionAttribute,\n\t\tnormalAttribute: normalAttribute,\n\t\tmorphedPositionAttribute: morphedPositionAttribute,\n\t\tmorphedNormalAttribute: morphedNormalAttribute\n\n\t};\n\n}\n\n/**\n * Merges the {@link BufferGeometry#groups} for the given geometry.\n *\n * @param {BufferGeometry} geometry - The geometry to modify.\n * @return {BufferGeometry} - The updated geometry\n */\nfunction mergeGroups( geometry ) {\n\n\tif ( geometry.groups.length === 0 ) {\n\n\t\tconsole.warn( 'THREE.BufferGeometryUtils.mergeGroups(): No groups are defined. Nothing to merge.' );\n\t\treturn geometry;\n\n\t}\n\n\tlet groups = geometry.groups;\n\n\t// sort groups by material index\n\n\tgroups = groups.sort( ( a, b ) => {\n\n\t\tif ( a.materialIndex !== b.materialIndex ) return a.materialIndex - b.materialIndex;\n\n\t\treturn a.start - b.start;\n\n\t} );\n\n\t// create index for non-indexed geometries\n\n\tif ( geometry.getIndex() === null ) {\n\n\t\tconst positionAttribute = geometry.getAttribute( 'position' );\n\t\tconst indices = [];\n\n\t\tfor ( let i = 0; i < positionAttribute.count; i += 3 ) {\n\n\t\t\tindices.push( i, i + 1, i + 2 );\n\n\t\t}\n\n\t\tgeometry.setIndex( indices );\n\n\t}\n\n\t// sort index\n\n\tconst index = geometry.getIndex();\n\n\tconst newIndices = [];\n\n\tfor ( let i = 0; i < groups.length; i ++ ) {\n\n\t\tconst group = groups[ i ];\n\n\t\tconst groupStart = group.start;\n\t\tconst groupLength = groupStart + group.count;\n\n\t\tfor ( let j = groupStart; j < groupLength; j ++ ) {\n\n\t\t\tnewIndices.push( index.getX( j ) );\n\n\t\t}\n\n\t}\n\n\tgeometry.dispose(); // Required to force buffer recreation\n\tgeometry.setIndex( newIndices );\n\n\t// update groups indices\n\n\tlet start = 0;\n\n\tfor ( let i = 0; i < groups.length; i ++ ) {\n\n\t\tconst group = groups[ i ];\n\n\t\tgroup.start = start;\n\t\tstart += group.count;\n\n\t}\n\n\t// merge groups\n\n\tlet currentGroup = groups[ 0 ];\n\n\tgeometry.groups = [ currentGroup ];\n\n\tfor ( let i = 1; i < groups.length; i ++ ) {\n\n\t\tconst group = groups[ i ];\n\n\t\tif ( currentGroup.materialIndex === group.materialIndex ) {\n\n\t\t\tcurrentGroup.count += group.count;\n\n\t\t} else {\n\n\t\t\tcurrentGroup = group;\n\t\t\tgeometry.groups.push( currentGroup );\n\n\t\t}\n\n\t}\n\n\treturn geometry;\n\n}\n\n/**\n * Modifies the supplied geometry if it is non-indexed, otherwise creates a new,\n * non-indexed geometry. Returns the geometry with smooth normals everywhere except\n * faces that meet at an angle greater than the crease angle.\n *\n * @param {BufferGeometry} geometry - The geometry to modify.\n * @param {number} [creaseAngle=Math.PI/3] - The crease angle in radians.\n * @return {BufferGeometry} - The updated geometry\n */\nfunction toCreasedNormals( geometry, creaseAngle = Math.PI / 3 /* 60 degrees */ ) {\n\n\tconst creaseDot = Math.cos( creaseAngle );\n\tconst hashMultiplier = ( 1 + 1e-10 ) * 1e2;\n\n\t// reusable vectors\n\tconst verts = [ new Vector3(), new Vector3(), new Vector3() ];\n\tconst tempVec1 = new Vector3();\n\tconst tempVec2 = new Vector3();\n\tconst tempNorm = new Vector3();\n\tconst tempNorm2 = new Vector3();\n\n\t// hashes a vector\n\tfunction hashVertex( v ) {\n\n\t\tconst x = ~ ~ ( v.x * hashMultiplier );\n\t\tconst y = ~ ~ ( v.y * hashMultiplier );\n\t\tconst z = ~ ~ ( v.z * hashMultiplier );\n\t\treturn `${x},${y},${z}`;\n\n\t}\n\n\t// BufferGeometry.toNonIndexed() warns if the geometry is non-indexed\n\t// and returns the original geometry\n\tconst resultGeometry = geometry.index ? geometry.toNonIndexed() : geometry;\n\tconst posAttr = resultGeometry.attributes.position;\n\tconst vertexMap = {};\n\n\t// find all the normals shared by commonly located vertices\n\tfor ( let i = 0, l = posAttr.count / 3; i < l; i ++ ) {\n\n\t\tconst i3 = 3 * i;\n\t\tconst a = verts[ 0 ].fromBufferAttribute( posAttr, i3 + 0 );\n\t\tconst b = verts[ 1 ].fromBufferAttribute( posAttr, i3 + 1 );\n\t\tconst c = verts[ 2 ].fromBufferAttribute( posAttr, i3 + 2 );\n\n\t\ttempVec1.subVectors( c, b );\n\t\ttempVec2.subVectors( a, b );\n\n\t\t// add the normal to the map for all vertices\n\t\tconst normal = new Vector3().crossVectors( tempVec1, tempVec2 ).normalize();\n\t\tfor ( let n = 0; n < 3; n ++ ) {\n\n\t\t\tconst vert = verts[ n ];\n\t\t\tconst hash = hashVertex( vert );\n\t\t\tif ( ! ( hash in vertexMap ) ) {\n\n\t\t\t\tvertexMap[ hash ] = [];\n\n\t\t\t}\n\n\t\t\tvertexMap[ hash ].push( normal );\n\n\t\t}\n\n\t}\n\n\t// average normals from all vertices that share a common location if they are within the\n\t// provided crease threshold\n\tconst normalArray = new Float32Array( posAttr.count * 3 );\n\tconst normAttr = new BufferAttribute( normalArray, 3, false );\n\tfor ( let i = 0, l = posAttr.count / 3; i < l; i ++ ) {\n\n\t\t// get the face normal for this vertex\n\t\tconst i3 = 3 * i;\n\t\tconst a = verts[ 0 ].fromBufferAttribute( posAttr, i3 + 0 );\n\t\tconst b = verts[ 1 ].fromBufferAttribute( posAttr, i3 + 1 );\n\t\tconst c = verts[ 2 ].fromBufferAttribute( posAttr, i3 + 2 );\n\n\t\ttempVec1.subVectors( c, b );\n\t\ttempVec2.subVectors( a, b );\n\n\t\ttempNorm.crossVectors( tempVec1, tempVec2 ).normalize();\n\n\t\t// average all normals that meet the threshold and set the normal value\n\t\tfor ( let n = 0; n < 3; n ++ ) {\n\n\t\t\tconst vert = verts[ n ];\n\t\t\tconst hash = hashVertex( vert );\n\t\t\tconst otherNormals = vertexMap[ hash ];\n\t\t\ttempNorm2.set( 0, 0, 0 );\n\n\t\t\tfor ( let k = 0, lk = otherNormals.length; k < lk; k ++ ) {\n\n\t\t\t\tconst otherNorm = otherNormals[ k ];\n\t\t\t\tif ( tempNorm.dot( otherNorm ) > creaseDot ) {\n\n\t\t\t\t\ttempNorm2.add( otherNorm );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\ttempNorm2.normalize();\n\t\t\tnormAttr.setXYZ( i3 + n, tempNorm2.x, tempNorm2.y, tempNorm2.z );\n\n\t\t}\n\n\t}\n\n\tresultGeometry.setAttribute( 'normal', normAttr );\n\treturn resultGeometry;\n\n}\n\nexport {\n\tcomputeMikkTSpaceTangents,\n\tmergeGeometries,\n\tmergeAttributes,\n\tdeepCloneAttribute,\n\tdeinterleaveAttribute,\n\tdeinterleaveGeometry,\n\tinterleaveAttributes,\n\testimateBytesUsed,\n\tmergeVertices,\n\ttoTrianglesDrawMode,\n\tcomputeMorphedAttributes,\n\tmergeGroups,\n\ttoCreasedNormals\n};\n","import {\n\tAnimationClip,\n\tAnimationMixer,\n\tMatrix4,\n\tQuaternion,\n\tQuaternionKeyframeTrack,\n\tSkeletonHelper,\n\tVector3,\n\tVectorKeyframeTrack\n} from 'three';\n\n/**\n * @module SkeletonUtils\n * @three_import import * as SkeletonUtils from 'three/addons/utils/SkeletonUtils.js';\n */\n\nfunction getBoneName( bone, options ) {\n\n\tif ( options.getBoneName !== undefined ) {\n\n\t\treturn options.getBoneName( bone );\n\n\t}\n\n\treturn options.names[ bone.name ];\n\n}\n\n/**\n * Retargets the skeleton from the given source to the target.\n *\n * Both `target` and `source` can be a 3D object with a skeleton property (e.g. a skinned mesh)\n * or a {@link Skeleton} directly.\n *\n * @param {Object3D|Skeleton} target - The target object.\n * @param {Object3D|Skeleton} source - The source object.\n * @param {module:SkeletonUtils~RetargetOptions} options - The options.\n */\nfunction retarget( target, source, options = {} ) {\n\n\tconst quat = new Quaternion(),\n\t\tscale = new Vector3(),\n\t\trelativeMatrix = new Matrix4(),\n\t\tglobalMatrix = new Matrix4();\n\n\toptions.preserveBoneMatrix = options.preserveBoneMatrix !== undefined ? options.preserveBoneMatrix : true;\n\toptions.preserveBonePositions = options.preserveBonePositions !== undefined ? options.preserveBonePositions : true;\n\toptions.useTargetMatrix = options.useTargetMatrix !== undefined ? options.useTargetMatrix : false;\n\toptions.hip = options.hip !== undefined ? options.hip : 'hip';\n\toptions.hipInfluence = options.hipInfluence !== undefined ? options.hipInfluence : new Vector3( 1, 1, 1 );\n\toptions.scale = options.scale !== undefined ? options.scale : 1;\n\toptions.names = options.names || {};\n\n\tconst sourceBones = source.isObject3D ? source.skeleton.bones : getBones( source ),\n\t\tbones = target.isObject3D ? target.skeleton.bones : getBones( target );\n\n\tlet bone, name, boneTo,\n\t\tbonesPosition;\n\n\t// reset bones\n\n\tif ( target.isObject3D ) {\n\n\t\ttarget.skeleton.pose();\n\n\t} else {\n\n\t\toptions.useTargetMatrix = true;\n\t\toptions.preserveBoneMatrix = false;\n\n\t}\n\n\tif ( options.preserveBonePositions ) {\n\n\t\tbonesPosition = [];\n\n\t\tfor ( let i = 0; i < bones.length; i ++ ) {\n\n\t\t\tbonesPosition.push( bones[ i ].position.clone() );\n\n\t\t}\n\n\t}\n\n\tif ( options.preserveBoneMatrix ) {\n\n\t\t// reset matrix\n\n\t\ttarget.updateMatrixWorld();\n\n\t\ttarget.matrixWorld.identity();\n\n\t\t// reset children matrix\n\n\t\tfor ( let i = 0; i < target.children.length; ++ i ) {\n\n\t\t\ttarget.children[ i ].updateMatrixWorld( true );\n\n\t\t}\n\n\t}\n\n\tfor ( let i = 0; i < bones.length; ++ i ) {\n\n\t\tbone = bones[ i ];\n\t\tname = getBoneName( bone, options );\n\n\t\tboneTo = getBoneByName( name, sourceBones );\n\n\t\tglobalMatrix.copy( bone.matrixWorld );\n\n\t\tif ( boneTo ) {\n\n\t\t\tboneTo.updateMatrixWorld();\n\n\t\t\tif ( options.useTargetMatrix ) {\n\n\t\t\t\trelativeMatrix.copy( boneTo.matrixWorld );\n\n\t\t\t} else {\n\n\t\t\t\trelativeMatrix.copy( target.matrixWorld ).invert();\n\t\t\t\trelativeMatrix.multiply( boneTo.matrixWorld );\n\n\t\t\t}\n\n\t\t\t// ignore scale to extract rotation\n\n\t\t\tscale.setFromMatrixScale( relativeMatrix );\n\t\t\trelativeMatrix.scale( scale.set( 1 / scale.x, 1 / scale.y, 1 / scale.z ) );\n\n\t\t\t// apply to global matrix\n\n\t\t\tglobalMatrix.makeRotationFromQuaternion( quat.setFromRotationMatrix( relativeMatrix ) );\n\n\t\t\tif ( target.isObject3D ) {\n\n\t\t\t\tif ( options.localOffsets ) {\n\n\t\t\t\t\tif ( options.localOffsets[ bone.name ] ) {\n\n\t\t\t\t\t\tglobalMatrix.multiply( options.localOffsets[ bone.name ] );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tglobalMatrix.copyPosition( relativeMatrix );\n\n\t\t}\n\n\t\tif ( name === options.hip ) {\n\n\t\t\tglobalMatrix.elements[ 12 ] *= options.scale * options.hipInfluence.x;\n\t\t\tglobalMatrix.elements[ 13 ] *= options.scale * options.hipInfluence.y;\n\t\t\tglobalMatrix.elements[ 14 ] *= options.scale * options.hipInfluence.z;\n\n\t\t\tif ( options.hipPosition !== undefined ) {\n\n\t\t\t\tglobalMatrix.elements[ 12 ] += options.hipPosition.x * options.scale;\n\t\t\t\tglobalMatrix.elements[ 13 ] += options.hipPosition.y * options.scale;\n\t\t\t\tglobalMatrix.elements[ 14 ] += options.hipPosition.z * options.scale;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( bone.parent ) {\n\n\t\t\tbone.matrix.copy( bone.parent.matrixWorld ).invert();\n\t\t\tbone.matrix.multiply( globalMatrix );\n\n\t\t} else {\n\n\t\t\tbone.matrix.copy( globalMatrix );\n\n\t\t}\n\n\t\tbone.matrix.decompose( bone.position, bone.quaternion, bone.scale );\n\n\t\tbone.updateMatrixWorld();\n\n\t}\n\n\tif ( options.preserveBonePositions ) {\n\n\t\tfor ( let i = 0; i < bones.length; ++ i ) {\n\n\t\t\tbone = bones[ i ];\n\t\t\tname = getBoneName( bone, options ) || bone.name;\n\n\t\t\tif ( name !== options.hip ) {\n\n\t\t\t\tbone.position.copy( bonesPosition[ i ] );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tif ( options.preserveBoneMatrix ) {\n\n\t\t// restore matrix\n\n\t\ttarget.updateMatrixWorld( true );\n\n\t}\n\n}\n\n/**\n * Retargets the animation clip of the source to the target 3D object.\n *\n * The `source` can be a 3D object with a skeleton property (e.g. a skinned mesh)\n * or a {@link Skeleton} directly.\n *\n * @param {Object3D} target - The target 3D object. Must have a `skeleton` property.\n * @param {Object3D|Skeleton} source - The source object.\n * @param {AnimationClip} clip - The animation clip.\n * @param {module:SkeletonUtils~RetargetOptions} options - The options.\n * @return {AnimationClip} The retargeted animation clip.\n */\nfunction retargetClip( target, source, clip, options = {} ) {\n\n\toptions.useFirstFramePosition = options.useFirstFramePosition !== undefined ? options.useFirstFramePosition : false;\n\n\t// Calculate the fps from the source clip based on the track with the most frames, unless fps is already provided.\n\toptions.fps = options.fps !== undefined ? options.fps : ( Math.max( ...clip.tracks.map( track => track.times.length ) ) / clip.duration );\n\toptions.names = options.names || [];\n\n\tif ( ! source.isObject3D ) {\n\n\t\tsource = getHelperFromSkeleton( source );\n\n\t}\n\n\tconst numFrames = Math.round( clip.duration * ( options.fps / 1000 ) * 1000 ),\n\t\tdelta = clip.duration / ( numFrames - 1 ),\n\t\tconvertedTracks = [],\n\t\tmixer = new AnimationMixer( source ),\n\t\tbones = getBones( target.skeleton ),\n\t\tboneDatas = [];\n\n\tlet positionOffset,\n\t\tbone, boneTo, boneData,\n\t\tname;\n\n\tmixer.clipAction( clip ).play();\n\n\t// trim\n\n\tlet start = 0, end = numFrames;\n\n\tif ( options.trim !== undefined ) {\n\n\t\tstart = Math.round( options.trim[ 0 ] * options.fps );\n\t\tend = Math.min( Math.round( options.trim[ 1 ] * options.fps ), numFrames ) - start;\n\n\t\tmixer.update( options.trim[ 0 ] );\n\n\t} else {\n\n\t\tmixer.update( 0 );\n\n\t}\n\n\tsource.updateMatrixWorld();\n\n\t//\n\n\tfor ( let frame = 0; frame < end; ++ frame ) {\n\n\t\tconst time = frame * delta;\n\n\t\tretarget( target, source, options );\n\n\t\tfor ( let j = 0; j < bones.length; ++ j ) {\n\n\t\t\tbone = bones[ j ];\n\t\t\tname = getBoneName( bone, options ) || bone.name;\n\t\t\tboneTo = getBoneByName( name, source.skeleton );\n\n\t\t\tif ( boneTo ) {\n\n\t\t\t\tboneData = boneDatas[ j ] = boneDatas[ j ] || { bone: bone };\n\n\t\t\t\tif ( options.hip === name ) {\n\n\t\t\t\t\tif ( ! boneData.pos ) {\n\n\t\t\t\t\t\tboneData.pos = {\n\t\t\t\t\t\t\ttimes: new Float32Array( end ),\n\t\t\t\t\t\t\tvalues: new Float32Array( end * 3 )\n\t\t\t\t\t\t};\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( options.useFirstFramePosition ) {\n\n\t\t\t\t\t\tif ( frame === 0 ) {\n\n\t\t\t\t\t\t\tpositionOffset = bone.position.clone();\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbone.position.sub( positionOffset );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tboneData.pos.times[ frame ] = time;\n\n\t\t\t\t\tbone.position.toArray( boneData.pos.values, frame * 3 );\n\n\t\t\t\t}\n\n\t\t\t\tif ( ! boneData.quat ) {\n\n\t\t\t\t\tboneData.quat = {\n\t\t\t\t\t\ttimes: new Float32Array( end ),\n\t\t\t\t\t\tvalues: new Float32Array( end * 4 )\n\t\t\t\t\t};\n\n\t\t\t\t}\n\n\t\t\t\tboneData.quat.times[ frame ] = time;\n\n\t\t\t\tbone.quaternion.toArray( boneData.quat.values, frame * 4 );\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( frame === end - 2 ) {\n\n\t\t\t// last mixer update before final loop iteration\n\t\t\t// make sure we do not go over or equal to clip duration\n\t\t\tmixer.update( delta - 0.0000001 );\n\n\t\t} else {\n\n\t\t\tmixer.update( delta );\n\n\t\t}\n\n\t\tsource.updateMatrixWorld();\n\n\t}\n\n\tfor ( let i = 0; i < boneDatas.length; ++ i ) {\n\n\t\tboneData = boneDatas[ i ];\n\n\t\tif ( boneData ) {\n\n\t\t\tif ( boneData.pos ) {\n\n\t\t\t\tconvertedTracks.push( new VectorKeyframeTrack(\n\t\t\t\t\t'.bones[' + boneData.bone.name + '].position',\n\t\t\t\t\tboneData.pos.times,\n\t\t\t\t\tboneData.pos.values\n\t\t\t\t) );\n\n\t\t\t}\n\n\t\t\tconvertedTracks.push( new QuaternionKeyframeTrack(\n\t\t\t\t'.bones[' + boneData.bone.name + '].quaternion',\n\t\t\t\tboneData.quat.times,\n\t\t\t\tboneData.quat.values\n\t\t\t) );\n\n\t\t}\n\n\t}\n\n\tmixer.uncacheAction( clip );\n\n\treturn new AnimationClip( clip.name, - 1, convertedTracks );\n\n}\n\n/**\n * Clones the given 3D object and its descendants, ensuring that any `SkinnedMesh` instances are\n * correctly associated with their bones. Bones are also cloned, and must be descendants of the\n * object passed to this method. Other data, like geometries and materials, are reused by reference.\n *\n * @param {Object3D} source - The 3D object to clone.\n * @return {Object3D} The cloned 3D object.\n */\nfunction clone( source ) {\n\n\tconst sourceLookup = new Map();\n\tconst cloneLookup = new Map();\n\n\tconst clone = source.clone();\n\n\tparallelTraverse( source, clone, function ( sourceNode, clonedNode ) {\n\n\t\tsourceLookup.set( clonedNode, sourceNode );\n\t\tcloneLookup.set( sourceNode, clonedNode );\n\n\t} );\n\n\tclone.traverse( function ( node ) {\n\n\t\tif ( ! node.isSkinnedMesh ) return;\n\n\t\tconst clonedMesh = node;\n\t\tconst sourceMesh = sourceLookup.get( node );\n\t\tconst sourceBones = sourceMesh.skeleton.bones;\n\n\t\tclonedMesh.skeleton = sourceMesh.skeleton.clone();\n\t\tclonedMesh.bindMatrix.copy( sourceMesh.bindMatrix );\n\n\t\tclonedMesh.skeleton.bones = sourceBones.map( function ( bone ) {\n\n\t\t\treturn cloneLookup.get( bone );\n\n\t\t} );\n\n\t\tclonedMesh.bind( clonedMesh.skeleton, clonedMesh.bindMatrix );\n\n\t} );\n\n\treturn clone;\n\n}\n\n// internal helper\n\nfunction getBoneByName( name, skeleton ) {\n\n\tfor ( let i = 0, bones = getBones( skeleton ); i < bones.length; i ++ ) {\n\n\t\tif ( name === bones[ i ].name )\n\n\t\t\treturn bones[ i ];\n\n\t}\n\n}\n\nfunction getBones( skeleton ) {\n\n\treturn Array.isArray( skeleton ) ? skeleton : skeleton.bones;\n\n}\n\n\nfunction getHelperFromSkeleton( skeleton ) {\n\n\tconst source = new SkeletonHelper( skeleton.bones[ 0 ] );\n\tsource.skeleton = skeleton;\n\n\treturn source;\n\n}\n\nfunction parallelTraverse( a, b, callback ) {\n\n\tcallback( a, b );\n\n\tfor ( let i = 0; i < a.children.length; i ++ ) {\n\n\t\tparallelTraverse( a.children[ i ], b.children[ i ], callback );\n\n\t}\n\n}\n\n/**\n * Retarget options of `SkeletonUtils`.\n *\n * @typedef {Object} module:SkeletonUtils~RetargetOptions\n * @property {boolean} [useFirstFramePosition=false] - Whether to use the position of the first frame or not.\n * @property {number} [fps] - The FPS of the clip.\n * @property {Object<string,string>} [names] - A dictionary for mapping target to source bone names.\n * @property {function(string):string} [getBoneName] - A function for mapping bone names. Alternative to `names`.\n * @property {Array<number>} [trim] - Whether to trim the clip or not. If set the array should hold two values for the start and end.\n * @property {boolean} [preserveBoneMatrix=true] - Whether to preserve bone matrices or not.\n * @property {boolean} [preserveBonePositions=true] - Whether to preserve bone positions or not.\n * @property {boolean} [useTargetMatrix=false] - Whether to use the target matrix or not.\n * @property {string} [hip='hip'] - The name of the source's hip bone.\n * @property {Vector3} [hipInfluence=(1,1,1)] - The hip influence.\n * @property {number} [scale=1] - The scale.\n * @property {Object<string,Matrix4>} [localOffsets] - Per-bone local offset matrices, keyed by bone name.\n * @property {Vector3} [hipPosition] - An additional position offset applied to the hip bone.\n **/\n\nexport {\n\tretarget,\n\tretargetClip,\n\tclone,\n};\n","import {\n\tAnimationClip,\n\tBone,\n\tBox3,\n\tBufferAttribute,\n\tBufferGeometry,\n\tClampToEdgeWrapping,\n\tColor,\n\tColorManagement,\n\tDirectionalLight,\n\tDoubleSide,\n\tFileLoader,\n\tFrontSide,\n\tGroup,\n\tImageBitmapLoader,\n\tInstancedMesh,\n\tInterleavedBuffer,\n\tInterleavedBufferAttribute,\n\tInterpolant,\n\tInterpolateDiscrete,\n\tInterpolateLinear,\n\tLine,\n\tLineBasicMaterial,\n\tLineLoop,\n\tLineSegments,\n\tLinearFilter,\n\tLinearMipmapLinearFilter,\n\tLinearMipmapNearestFilter,\n\tLinearSRGBColorSpace,\n\tLoader,\n\tLoaderUtils,\n\tMaterial,\n\tMathUtils,\n\tMatrix4,\n\tMesh,\n\tMeshBasicMaterial,\n\tMeshPhysicalMaterial,\n\tMeshStandardMaterial,\n\tMirroredRepeatWrapping,\n\tNearestFilter,\n\tNearestMipmapLinearFilter,\n\tNearestMipmapNearestFilter,\n\tNumberKeyframeTrack,\n\tObject3D,\n\tOrthographicCamera,\n\tPerspectiveCamera,\n\tPointLight,\n\tPoints,\n\tPointsMaterial,\n\tPropertyBinding,\n\tQuaternion,\n\tQuaternionKeyframeTrack,\n\tRepeatWrapping,\n\tSkeleton,\n\tSkinnedMesh,\n\tSphere,\n\tSpotLight,\n\tTexture,\n\tTextureLoader,\n\tTriangleFanDrawMode,\n\tTriangleStripDrawMode,\n\tVector2,\n\tVector3,\n\tVectorKeyframeTrack,\n\tSRGBColorSpace,\n\tInstancedBufferAttribute\n} from 'three';\nimport { toTrianglesDrawMode } from '../utils/BufferGeometryUtils.js';\nimport { clone } from '../utils/SkeletonUtils.js';\n\n/**\n * A loader for the glTF 2.0 format.\n *\n * [glTF](https://www.khronos.org/gltf/) (GL Transmission Format) is an [open format specification]{@link https://github.com/KhronosGroup/glTF/tree/main/specification/2.0)\n * for efficient delivery and loading of 3D content. Assets may be provided either in JSON (.gltf) or binary (.glb)\n * format. External files store textures (.jpg, .png) and additional binary data (.bin). A glTF asset may deliver\n * one or more scenes, including meshes, materials, textures, skins, skeletons, morph targets, animations, lights,\n * and/or cameras.\n *\n * `GLTFLoader` uses {@link ImageBitmapLoader} whenever possible. Be advised that image bitmaps are not\n * automatically GC-collected when they are no longer referenced, and they require special handling during\n * the disposal process.\n *\n * `GLTFLoader` supports the following glTF 2.0 extensions:\n * - KHR_draco_mesh_compression\n * - KHR_lights_punctual\n * - KHR_materials_anisotropy\n * - KHR_materials_clearcoat\n * - KHR_materials_dispersion\n * - KHR_materials_emissive_strength\n * - KHR_materials_ior\n * - KHR_materials_specular\n * - KHR_materials_transmission\n * - KHR_materials_iridescence\n * - KHR_materials_unlit\n * - KHR_materials_volume\n * - KHR_mesh_quantization\n * - KHR_meshopt_compression\n * - KHR_texture_basisu\n * - KHR_texture_transform\n * - EXT_materials_bump\n * - EXT_meshopt_compression\n * - EXT_mesh_gpu_instancing\n * - EXT_texture_avif\n * - EXT_texture_webp\n *\n * The following glTF 2.0 extension is supported by an external user plugin:\n * - [KHR_materials_variants](https://github.com/takahirox/three-gltf-extensions)\n * - [MSFT_texture_dds](https://github.com/takahirox/three-gltf-extensions)\n * - [KHR_animation_pointer](https://github.com/needle-tools/three-animation-pointer)\n * - [NEEDLE_progressive](https://github.com/needle-tools/gltf-progressive)\n *\n * ```js\n * const loader = new GLTFLoader();\n *\n * // Optional: Provide a DRACOLoader instance to decode compressed mesh data\n * const dracoLoader = new DRACOLoader();\n * dracoLoader.setDecoderPath( '/examples/jsm/libs/draco/' );\n * loader.setDRACOLoader( dracoLoader );\n *\n * const gltf = await loader.loadAsync( 'models/gltf/duck/duck.gltf' );\n * scene.add( gltf.scene );\n * ```\n *\n * @augments Loader\n * @three_import import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';\n */\nclass GLTFLoader extends Loader {\n\n\t/**\n\t * Constructs a new glTF loader.\n\t *\n\t * @param {LoadingManager} [manager] - The loading manager.\n\t */\n\tconstructor( manager ) {\n\n\t\tsuper( manager );\n\n\t\tthis.dracoLoader = null;\n\t\tthis.ktx2Loader = null;\n\t\tthis.meshoptDecoder = null;\n\n\t\tthis.pluginCallbacks = [];\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsClearcoatExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsDispersionExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFTextureBasisUExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFTextureWebPExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFTextureAVIFExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsSheenExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsTransmissionExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsVolumeExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsIorExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsEmissiveStrengthExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsSpecularExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsIridescenceExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsAnisotropyExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsBumpExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFLightsExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMeshoptCompression( parser, EXTENSIONS.EXT_MESHOPT_COMPRESSION );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMeshoptCompression( parser, EXTENSIONS.KHR_MESHOPT_COMPRESSION );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMeshGpuInstancing( parser );\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Starts loading from the given URL and passes the loaded glTF asset\n\t * to the `onLoad()` callback.\n\t *\n\t * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.\n\t * @param {function(GLTFLoader~LoadObject)} onLoad - Executed when the loading process has been finished.\n\t * @param {onProgressCallback} onProgress - Executed while the loading is in progress.\n\t * @param {onErrorCallback} onError - Executed when errors occur.\n\t */\n\tload( url, onLoad, onProgress, onError ) {\n\n\t\tconst scope = this;\n\n\t\tlet resourcePath;\n\n\t\tif ( this.resourcePath !== '' ) {\n\n\t\t\tresourcePath = this.resourcePath;\n\n\t\t} else if ( this.path !== '' ) {\n\n\t\t\t// If a base path is set, resources will be relative paths from that plus the relative path of the gltf file\n\t\t\t// Example path = 'https://my-cnd-server.com/', url = 'assets/models/model.gltf'\n\t\t\t// resourcePath = 'https://my-cnd-server.com/assets/models/'\n\t\t\t// referenced resource 'model.bin' will be loaded from 'https://my-cnd-server.com/assets/models/model.bin'\n\t\t\t// referenced resource '../textures/texture.png' will be loaded from 'https://my-cnd-server.com/assets/textures/texture.png'\n\t\t\tconst relativeUrl = LoaderUtils.extractUrlBase( url );\n\t\t\tresourcePath = LoaderUtils.resolveURL( relativeUrl, this.path );\n\n\t\t} else {\n\n\t\t\tresourcePath = LoaderUtils.extractUrlBase( url );\n\n\t\t}\n\n\t\t// Tells the LoadingManager to track an extra item, which resolves after\n\t\t// the model is fully loaded. This means the count of items loaded will\n\t\t// be incorrect, but ensures manager.onLoad() does not fire early.\n\t\tthis.manager.itemStart( url );\n\n\t\tconst _onError = function ( e ) {\n\n\t\t\tif ( onError ) {\n\n\t\t\t\tonError( e );\n\n\t\t\t} else {\n\n\t\t\t\tconsole.error( e );\n\n\t\t\t}\n\n\t\t\tscope.manager.itemError( url );\n\t\t\tscope.manager.itemEnd( url );\n\n\t\t};\n\n\t\tconst loader = new FileLoader( this.manager );\n\n\t\tloader.setPath( this.path );\n\t\tloader.setResponseType( 'arraybuffer' );\n\t\tloader.setRequestHeader( this.requestHeader );\n\t\tloader.setWithCredentials( this.withCredentials );\n\n\t\tloader.load( url, function ( data ) {\n\n\t\t\ttry {\n\n\t\t\t\tscope.parse( data, resourcePath, function ( gltf ) {\n\n\t\t\t\t\tonLoad( gltf );\n\n\t\t\t\t\tscope.manager.itemEnd( url );\n\n\t\t\t\t}, _onError );\n\n\t\t\t} catch ( e ) {\n\n\t\t\t\t_onError( e );\n\n\t\t\t}\n\n\t\t}, onProgress, _onError );\n\n\t}\n\n\t/**\n\t * Sets the given Draco loader to this loader. Required for decoding assets\n\t * compressed with the `KHR_draco_mesh_compression` extension.\n\t *\n\t * @param {DRACOLoader} dracoLoader - The Draco loader to set.\n\t * @return {GLTFLoader} A reference to this loader.\n\t */\n\tsetDRACOLoader( dracoLoader ) {\n\n\t\tthis.dracoLoader = dracoLoader;\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Sets the given KTX2 loader to this loader. Required for loading KTX2\n\t * compressed textures.\n\t *\n\t * @param {KTX2Loader} ktx2Loader - The KTX2 loader to set.\n\t * @return {GLTFLoader} A reference to this loader.\n\t */\n\tsetKTX2Loader( ktx2Loader ) {\n\n\t\tthis.ktx2Loader = ktx2Loader;\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Sets the given meshopt decoder. Required for decoding assets\n\t * compressed with the `EXT_meshopt_compression` extension.\n\t *\n\t * @param {Object} meshoptDecoder - The meshopt decoder to set.\n\t * @return {GLTFLoader} A reference to this loader.\n\t */\n\tsetMeshoptDecoder( meshoptDecoder ) {\n\n\t\tthis.meshoptDecoder = meshoptDecoder;\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Registers a plugin callback. This API is internally used to implement the various\n\t * glTF extensions but can also used by third-party code to add additional logic\n\t * to the loader.\n\t *\n\t * @param {function(parser:GLTFParser)} callback - The callback function to register.\n\t * @return {GLTFLoader} A reference to this loader.\n\t */\n\tregister( callback ) {\n\n\t\tif ( this.pluginCallbacks.indexOf( callback ) === - 1 ) {\n\n\t\t\tthis.pluginCallbacks.push( callback );\n\n\t\t}\n\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Unregisters a plugin callback.\n\t *\n\t * @param {Function} callback - The callback function to unregister.\n\t * @return {GLTFLoader} A reference to this loader.\n\t */\n\tunregister( callback ) {\n\n\t\tif ( this.pluginCallbacks.indexOf( callback ) !== - 1 ) {\n\n\t\t\tthis.pluginCallbacks.splice( this.pluginCallbacks.indexOf( callback ), 1 );\n\n\t\t}\n\n\t\treturn this;\n\n\t}\n\n\t/**\n\t * Parses the given glTF data and returns the resulting group.\n\t *\n\t * @param {string|ArrayBuffer} data - The raw glTF data.\n\t * @param {string} path - The URL base path.\n\t * @param {function(GLTFLoader~LoadObject)} onLoad - Executed when the loading process has been finished.\n\t * @param {onErrorCallback} onError - Executed when errors occur.\n\t */\n\tparse( data, path, onLoad, onError ) {\n\n\t\tlet json;\n\t\tconst extensions = {};\n\t\tconst plugins = {};\n\t\tconst textDecoder = new TextDecoder();\n\n\t\tif ( typeof data === 'string' ) {\n\n\t\t\tjson = JSON.parse( data );\n\n\t\t} else if ( data instanceof ArrayBuffer ) {\n\n\t\t\tconst magic = textDecoder.decode( new Uint8Array( data, 0, 4 ) );\n\n\t\t\tif ( magic === BINARY_EXTENSION_HEADER_MAGIC ) {\n\n\t\t\t\ttry {\n\n\t\t\t\t\textensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new GLTFBinaryExtension( data );\n\n\t\t\t\t} catch ( error ) {\n\n\t\t\t\t\tif ( onError ) onError( error );\n\t\t\t\t\treturn;\n\n\t\t\t\t}\n\n\t\t\t\tjson = JSON.parse( extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content );\n\n\t\t\t} else {\n\n\t\t\t\tjson = JSON.parse( textDecoder.decode( data ) );\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tjson = data;\n\n\t\t}\n\n\t\tif ( json.asset === undefined || json.asset.version[ 0 ] < 2 ) {\n\n\t\t\tif ( onError ) onError( new Error( 'THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported.' ) );\n\t\t\treturn;\n\n\t\t}\n\n\t\tconst parser = new GLTFParser( json, {\n\n\t\t\tpath: path || this.resourcePath || '',\n\t\t\tcrossOrigin: this.crossOrigin,\n\t\t\trequestHeader: this.requestHeader,\n\t\t\tmanager: this.manager,\n\t\t\tktx2Loader: this.ktx2Loader,\n\t\t\tmeshoptDecoder: this.meshoptDecoder\n\n\t\t} );\n\n\t\tparser.fileLoader.setRequestHeader( this.requestHeader );\n\n\t\tfor ( let i = 0; i < this.pluginCallbacks.length; i ++ ) {\n\n\t\t\tconst plugin = this.pluginCallbacks[ i ]( parser );\n\n\t\t\tif ( ! plugin.name ) console.error( 'THREE.GLTFLoader: Invalid plugin found: missing name' );\n\n\t\t\tplugins[ plugin.name ] = plugin;\n\n\t\t\t// Workaround to avoid determining as unknown extension\n\t\t\t// in addUnknownExtensionsToUserData().\n\t\t\t// Remove this workaround if we move all the existing\n\t\t\t// extension handlers to plugin system\n\t\t\textensions[ plugin.name ] = true;\n\n\t\t}\n\n\t\tif ( json.extensionsUsed ) {\n\n\t\t\tfor ( let i = 0; i < json.extensionsUsed.length; ++ i ) {\n\n\t\t\t\tconst extensionName = json.extensionsUsed[ i ];\n\t\t\t\tconst extensionsRequired = json.extensionsRequired || [];\n\n\t\t\t\tswitch ( extensionName ) {\n\n\t\t\t\t\tcase EXTENSIONS.KHR_MATERIALS_UNLIT:\n\t\t\t\t\t\textensions[ extensionName ] = new GLTFMaterialsUnlitExtension();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:\n\t\t\t\t\t\textensions[ extensionName ] = new GLTFDracoMeshCompressionExtension( json, this.dracoLoader );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase EXTENSIONS.KHR_TEXTURE_TRANSFORM:\n\t\t\t\t\t\textensions[ extensionName ] = new GLTFTextureTransformExtension();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase EXTENSIONS.KHR_MESH_QUANTIZATION:\n\t\t\t\t\t\textensions[ extensionName ] = new GLTFMeshQuantizationExtension();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\n\t\t\t\t\t\tif ( extensionsRequired.indexOf( extensionName ) >= 0 && plugins[ extensionName ] === undefined ) {\n\n\t\t\t\t\t\t\tconsole.warn( 'THREE.GLTFLoader: Unknown extension \"' + extensionName + '\".' );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tparser.setExtensions( extensions );\n\t\tparser.setPlugins( plugins );\n\t\tparser.parse( onLoad, onError );\n\n\t}\n\n\t/**\n\t * Async version of {@link GLTFLoader#parse}.\n\t *\n\t * @async\n\t * @param {string|ArrayBuffer} data - The raw glTF data.\n\t * @param {string} path - The URL base path.\n\t * @return {Promise<GLTFLoader~LoadObject>} A Promise that resolves with the loaded glTF when the parsing has been finished.\n\t */\n\tparseAsync( data, path ) {\n\n\t\tconst scope = this;\n\n\t\treturn new Promise( function ( resolve, reject ) {\n\n\t\t\tscope.parse( data, path, resolve, reject );\n\n\t\t} );\n\n\t}\n\n}\n\n/* GLTFREGISTRY */\n\nfunction GLTFRegistry() {\n\n\tlet objects = {};\n\n\treturn\t{\n\n\t\tget: function ( key ) {\n\n\t\t\treturn objects[ key ];\n\n\t\t},\n\n\t\tadd: function ( key, object ) {\n\n\t\t\tobjects[ key ] = object;\n\n\t\t},\n\n\t\tremove: function ( key ) {\n\n\t\t\tdelete objects[ key ];\n\n\t\t},\n\n\t\tremoveAll: function () {\n\n\t\t\tobjects = {};\n\n\t\t}\n\n\t};\n\n}\n\n/*********************************/\n/********** EXTENSIONS ***********/\n/*********************************/\n\nfunction getMaterialExtension( parser, materialIndex, extensionName ) {\n\n\tconst materialDef = parser.json.materials[ materialIndex ];\n\n\tif ( materialDef.extensions && materialDef.extensions[ extensionName ] ) {\n\n\t\treturn materialDef.extensions[ extensionName ];\n\n\t}\n\n\treturn null;\n\n}\n\nconst EXTENSIONS = {\n\tKHR_BINARY_GLTF: 'KHR_binary_glTF',\n\tKHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression',\n\tKHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',\n\tKHR_MATERIALS_CLEARCOAT: 'KHR_materials_clearcoat',\n\tKHR_MATERIALS_DISPERSION: 'KHR_materials_dispersion',\n\tKHR_MATERIALS_IOR: 'KHR_materials_ior',\n\tKHR_MATERIALS_SHEEN: 'KHR_materials_sheen',\n\tKHR_MATERIALS_SPECULAR: 'KHR_materials_specular',\n\tKHR_MATERIALS_TRANSMISSION: 'KHR_materials_transmission',\n\tKHR_MATERIALS_IRIDESCENCE: 'KHR_materials_iridescence',\n\tKHR_MATERIALS_ANISOTROPY: 'KHR_materials_anisotropy',\n\tKHR_MATERIALS_UNLIT: 'KHR_materials_unlit',\n\tKHR_MATERIALS_VOLUME: 'KHR_materials_volume',\n\tKHR_TEXTURE_BASISU: 'KHR_texture_basisu',\n\tKHR_TEXTURE_TRANSFORM: 'KHR_texture_transform',\n\tKHR_MESH_QUANTIZATION: 'KHR_mesh_quantization',\n\tKHR_MATERIALS_EMISSIVE_STRENGTH: 'KHR_materials_emissive_strength',\n\tEXT_MATERIALS_BUMP: 'EXT_materials_bump',\n\tEXT_TEXTURE_WEBP: 'EXT_texture_webp',\n\tEXT_TEXTURE_AVIF: 'EXT_texture_avif',\n\tEXT_MESHOPT_COMPRESSION: 'EXT_meshopt_compression',\n\tKHR_MESHOPT_COMPRESSION: 'KHR_meshopt_compression',\n\tEXT_MESH_GPU_INSTANCING: 'EXT_mesh_gpu_instancing'\n};\n\n/**\n * Punctual Lights Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual\n *\n * @private\n */\nclass GLTFLightsExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_LIGHTS_PUNCTUAL;\n\n\t\t// Object3D instance caches\n\t\tthis.cache = { refs: {}, uses: {} };\n\n\t}\n\n\t_markDefs() {\n\n\t\tconst parser = this.parser;\n\t\tconst nodeDefs = this.parser.json.nodes || [];\n\n\t\tfor ( let nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex ++ ) {\n\n\t\t\tconst nodeDef = nodeDefs[ nodeIndex ];\n\n\t\t\tif ( nodeDef.extensions\n\t\t\t\t\t&& nodeDef.extensions[ this.name ]\n\t\t\t\t\t&& nodeDef.extensions[ this.name ].light !== undefined ) {\n\n\t\t\t\tparser._addNodeRef( this.cache, nodeDef.extensions[ this.name ].light );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t_loadLight( lightIndex ) {\n\n\t\tconst parser = this.parser;\n\t\tconst cacheKey = 'light:' + lightIndex;\n\t\tlet dependency = parser.cache.get( cacheKey );\n\n\t\tif ( dependency ) return dependency;\n\n\t\tconst json = parser.json;\n\t\tconst extensions = ( json.extensions && json.extensions[ this.name ] ) || {};\n\t\tconst lightDefs = extensions.lights || [];\n\t\tconst lightDef = lightDefs[ lightIndex ];\n\t\tlet lightNode;\n\n\t\tconst color = new Color( 0xffffff );\n\n\t\tif ( lightDef.color !== undefined ) color.setRGB( lightDef.color[ 0 ], lightDef.color[ 1 ], lightDef.color[ 2 ], LinearSRGBColorSpace );\n\n\t\tconst range = lightDef.range !== undefined ? lightDef.range : 0;\n\n\t\tswitch ( lightDef.type ) {\n\n\t\t\tcase 'directional':\n\t\t\t\tlightNode = new DirectionalLight( color );\n\t\t\t\tlightNode.target.position.set( 0, 0, - 1 );\n\t\t\t\tlightNode.add( lightNode.target );\n\t\t\t\tbreak;\n\n\t\t\tcase 'point':\n\t\t\t\tlightNode = new PointLight( color );\n\t\t\t\tlightNode.distance = range;\n\t\t\t\tbreak;\n\n\t\t\tcase 'spot':\n\t\t\t\tlightNode = new SpotLight( color );\n\t\t\t\tlightNode.distance = range;\n\t\t\t\t// Handle spotlight properties.\n\t\t\t\tlightDef.spot = lightDef.spot || {};\n\t\t\t\tlightDef.spot.innerConeAngle = lightDef.spot.innerConeAngle !== undefined ? lightDef.spot.innerConeAngle : 0;\n\t\t\t\tlightDef.spot.outerConeAngle = lightDef.spot.outerConeAngle !== undefined ? lightDef.spot.outerConeAngle : Math.PI / 4.0;\n\t\t\t\tlightNode.angle = lightDef.spot.outerConeAngle;\n\t\t\t\tlightNode.penumbra = 1.0 - lightDef.spot.innerConeAngle / lightDef.spot.outerConeAngle;\n\t\t\t\tlightNode.target.position.set( 0, 0, - 1 );\n\t\t\t\tlightNode.add( lightNode.target );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tthrow new Error( 'THREE.GLTFLoader: Unexpected light type: ' + lightDef.type );\n\n\t\t}\n\n\t\t// Some lights (e.g. spot) default to a position other than the origin. Reset the position\n\t\t// here, because node-level parsing will only override position if explicitly specified.\n\t\tlightNode.position.set( 0, 0, 0 );\n\n\t\tassignExtrasToUserData( lightNode, lightDef );\n\n\t\tif ( lightDef.intensity !== undefined ) lightNode.intensity = lightDef.intensity;\n\n\t\tlightNode.name = parser.createUniqueName( lightDef.name || ( 'light_' + lightIndex ) );\n\n\t\tdependency = Promise.resolve( lightNode );\n\n\t\tparser.cache.add( cacheKey, dependency );\n\n\t\treturn dependency;\n\n\t}\n\n\tgetDependency( type, index ) {\n\n\t\tif ( type !== 'light' ) return;\n\n\t\treturn this._loadLight( index );\n\n\t}\n\n\tcreateNodeAttachment( nodeIndex ) {\n\n\t\tconst self = this;\n\t\tconst parser = this.parser;\n\t\tconst json = parser.json;\n\t\tconst nodeDef = json.nodes[ nodeIndex ];\n\t\tconst lightDef = ( nodeDef.extensions && nodeDef.extensions[ this.name ] ) || {};\n\t\tconst lightIndex = lightDef.light;\n\n\t\tif ( lightIndex === undefined ) return null;\n\n\t\treturn this._loadLight( lightIndex ).then( function ( light ) {\n\n\t\t\treturn parser._getNodeRef( self.cache, lightIndex, light );\n\n\t\t} );\n\n\t}\n\n}\n\n/**\n * Unlit Materials Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_unlit\n *\n * @private\n */\nclass GLTFMaterialsUnlitExtension {\n\n\tconstructor() {\n\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_UNLIT;\n\n\t}\n\n\tgetMaterialType() {\n\n\t\treturn MeshBasicMaterial;\n\n\t}\n\n\textendParams( materialParams, materialDef, parser ) {\n\n\t\tconst pending = [];\n\n\t\tmaterialParams.color = new Color( 1.0, 1.0, 1.0 );\n\t\tmaterialParams.opacity = 1.0;\n\n\t\tconst metallicRoughness = materialDef.pbrMetallicRoughness;\n\n\t\tif ( metallicRoughness ) {\n\n\t\t\tif ( Array.isArray( metallicRoughness.baseColorFactor ) ) {\n\n\t\t\t\tconst array = metallicRoughness.baseColorFactor;\n\n\t\t\t\tmaterialParams.color.setRGB( array[ 0 ], array[ 1 ], array[ 2 ], LinearSRGBColorSpace );\n\t\t\t\tmaterialParams.opacity = array[ 3 ];\n\n\t\t\t}\n\n\t\t\tif ( metallicRoughness.baseColorTexture !== undefined ) {\n\n\t\t\t\tpending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture, SRGBColorSpace ) );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * Materials Emissive Strength Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/blob/5768b3ce0ef32bc39cdf1bef10b948586635ead3/extensions/2.0/Khronos/KHR_materials_emissive_strength/README.md\n *\n * @private\n */\nclass GLTFMaterialsEmissiveStrengthExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_EMISSIVE_STRENGTH;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tif ( extension.emissiveStrength !== undefined ) {\n\n\t\t\tmaterialParams.emissiveIntensity = extension.emissiveStrength;\n\n\t\t}\n\n\t\treturn Promise.resolve();\n\n\t}\n\n}\n\n/**\n * Clearcoat Materials Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_clearcoat\n *\n * @private\n */\nclass GLTFMaterialsClearcoatExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_CLEARCOAT;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\treturn extension !== null ? MeshPhysicalMaterial : null;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tconst pending = [];\n\n\t\tif ( extension.clearcoatFactor !== undefined ) {\n\n\t\t\tmaterialParams.clearcoat = extension.clearcoatFactor;\n\n\t\t}\n\n\t\tif ( extension.clearcoatTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'clearcoatMap', extension.clearcoatTexture ) );\n\n\t\t}\n\n\t\tif ( extension.clearcoatRoughnessFactor !== undefined ) {\n\n\t\t\tmaterialParams.clearcoatRoughness = extension.clearcoatRoughnessFactor;\n\n\t\t}\n\n\t\tif ( extension.clearcoatRoughnessTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'clearcoatRoughnessMap', extension.clearcoatRoughnessTexture ) );\n\n\t\t}\n\n\t\tif ( extension.clearcoatNormalTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'clearcoatNormalMap', extension.clearcoatNormalTexture ) );\n\n\t\t\tif ( extension.clearcoatNormalTexture.scale !== undefined ) {\n\n\t\t\t\tconst scale = extension.clearcoatNormalTexture.scale;\n\n\t\t\t\tmaterialParams.clearcoatNormalScale = new Vector2( scale, scale );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * Materials dispersion Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_dispersion\n *\n * @private\n */\nclass GLTFMaterialsDispersionExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_DISPERSION;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\treturn extension !== null ? MeshPhysicalMaterial : null;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tmaterialParams.dispersion = extension.dispersion !== undefined ? extension.dispersion : 0;\n\n\t\treturn Promise.resolve();\n\n\t}\n\n}\n\n/**\n * Iridescence Materials Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_iridescence\n *\n * @private\n */\nclass GLTFMaterialsIridescenceExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_IRIDESCENCE;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\treturn extension !== null ? MeshPhysicalMaterial : null;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tconst pending = [];\n\n\t\tif ( extension.iridescenceFactor !== undefined ) {\n\n\t\t\tmaterialParams.iridescence = extension.iridescenceFactor;\n\n\t\t}\n\n\t\tif ( extension.iridescenceTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'iridescenceMap', extension.iridescenceTexture ) );\n\n\t\t}\n\n\t\tif ( extension.iridescenceIor !== undefined ) {\n\n\t\t\tmaterialParams.iridescenceIOR = extension.iridescenceIor;\n\n\t\t}\n\n\t\tif ( materialParams.iridescenceThicknessRange === undefined ) {\n\n\t\t\tmaterialParams.iridescenceThicknessRange = [ 100, 400 ];\n\n\t\t}\n\n\t\tif ( extension.iridescenceThicknessMinimum !== undefined ) {\n\n\t\t\tmaterialParams.iridescenceThicknessRange[ 0 ] = extension.iridescenceThicknessMinimum;\n\n\t\t}\n\n\t\tif ( extension.iridescenceThicknessMaximum !== undefined ) {\n\n\t\t\tmaterialParams.iridescenceThicknessRange[ 1 ] = extension.iridescenceThicknessMaximum;\n\n\t\t}\n\n\t\tif ( extension.iridescenceThicknessTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'iridescenceThicknessMap', extension.iridescenceThicknessTexture ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * Sheen Materials Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_sheen\n *\n * @private\n */\nclass GLTFMaterialsSheenExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_SHEEN;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\treturn extension !== null ? MeshPhysicalMaterial : null;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tconst pending = [];\n\n\t\tmaterialParams.sheenColor = new Color( 0, 0, 0 );\n\t\tmaterialParams.sheenRoughness = 0;\n\t\tmaterialParams.sheen = 1;\n\n\t\tif ( extension.sheenColorFactor !== undefined ) {\n\n\t\t\tconst colorFactor = extension.sheenColorFactor;\n\t\t\tmaterialParams.sheenColor.setRGB( colorFactor[ 0 ], colorFactor[ 1 ], colorFactor[ 2 ], LinearSRGBColorSpace );\n\n\t\t}\n\n\t\tif ( extension.sheenRoughnessFactor !== undefined ) {\n\n\t\t\tmaterialParams.sheenRoughness = extension.sheenRoughnessFactor;\n\n\t\t}\n\n\t\tif ( extension.sheenColorTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'sheenColorMap', extension.sheenColorTexture, SRGBColorSpace ) );\n\n\t\t}\n\n\t\tif ( extension.sheenRoughnessTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'sheenRoughnessMap', extension.sheenRoughnessTexture ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * Transmission Materials Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_transmission\n * Draft: https://github.com/KhronosGroup/glTF/pull/1698\n *\n * @private\n */\nclass GLTFMaterialsTransmissionExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_TRANSMISSION;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\treturn extension !== null ? MeshPhysicalMaterial : null;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tconst pending = [];\n\n\t\tif ( extension.transmissionFactor !== undefined ) {\n\n\t\t\tmaterialParams.transmission = extension.transmissionFactor;\n\n\t\t}\n\n\t\tif ( extension.transmissionTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'transmissionMap', extension.transmissionTexture ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * Materials Volume Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_volume\n *\n * @private\n */\nclass GLTFMaterialsVolumeExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_VOLUME;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\treturn extension !== null ? MeshPhysicalMaterial : null;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tconst pending = [];\n\n\t\tmaterialParams.thickness = extension.thicknessFactor !== undefined ? extension.thicknessFactor : 0;\n\n\t\tif ( extension.thicknessTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'thicknessMap', extension.thicknessTexture ) );\n\n\t\t}\n\n\t\tmaterialParams.attenuationDistance = extension.attenuationDistance || Infinity;\n\n\t\tconst colorArray = extension.attenuationColor || [ 1, 1, 1 ];\n\t\tmaterialParams.attenuationColor = new Color().setRGB( colorArray[ 0 ], colorArray[ 1 ], colorArray[ 2 ], LinearSRGBColorSpace );\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * Materials ior Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_ior\n *\n * @private\n */\nclass GLTFMaterialsIorExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_IOR;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\treturn extension !== null ? MeshPhysicalMaterial : null;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tmaterialParams.ior = extension.ior !== undefined ? extension.ior : 1.5;\n\n\t\tif ( materialParams.ior === 0 ) materialParams.ior = 1000; // see #26167\n\n\t\treturn Promise.resolve();\n\n\t}\n\n}\n\n/**\n * Materials specular Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_specular\n *\n * @private\n */\nclass GLTFMaterialsSpecularExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_SPECULAR;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\treturn extension !== null ? MeshPhysicalMaterial : null;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tconst pending = [];\n\n\t\tmaterialParams.specularIntensity = extension.specularFactor !== undefined ? extension.specularFactor : 1.0;\n\n\t\tif ( extension.specularTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'specularIntensityMap', extension.specularTexture ) );\n\n\t\t}\n\n\t\tconst colorArray = extension.specularColorFactor || [ 1, 1, 1 ];\n\t\tmaterialParams.specularColor = new Color().setRGB( colorArray[ 0 ], colorArray[ 1 ], colorArray[ 2 ], LinearSRGBColorSpace );\n\n\t\tif ( extension.specularColorTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'specularColorMap', extension.specularColorTexture, SRGBColorSpace ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n\n/**\n * Materials bump Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/EXT_materials_bump\n *\n * @private\n */\nclass GLTFMaterialsBumpExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.EXT_MATERIALS_BUMP;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\treturn extension !== null ? MeshPhysicalMaterial : null;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tconst pending = [];\n\n\t\tmaterialParams.bumpScale = extension.bumpFactor !== undefined ? extension.bumpFactor : 1.0;\n\n\t\tif ( extension.bumpTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'bumpMap', extension.bumpTexture ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * Materials anisotropy Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_anisotropy\n *\n * @private\n */\nclass GLTFMaterialsAnisotropyExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_ANISOTROPY;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\treturn extension !== null ? MeshPhysicalMaterial : null;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst extension = getMaterialExtension( this.parser, materialIndex, this.name );\n\n\t\tif ( extension === null ) return Promise.resolve();\n\n\t\tconst pending = [];\n\n\t\tif ( extension.anisotropyStrength !== undefined ) {\n\n\t\t\tmaterialParams.anisotropy = extension.anisotropyStrength;\n\n\t\t}\n\n\t\tif ( extension.anisotropyRotation !== undefined ) {\n\n\t\t\tmaterialParams.anisotropyRotation = extension.anisotropyRotation;\n\n\t\t}\n\n\t\tif ( extension.anisotropyTexture !== undefined ) {\n\n\t\t\tpending.push( this.parser.assignTexture( materialParams, 'anisotropyMap', extension.anisotropyTexture ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * BasisU Texture Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_texture_basisu\n *\n * @private\n */\nclass GLTFTextureBasisUExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_TEXTURE_BASISU;\n\n\t}\n\n\tloadTexture( textureIndex ) {\n\n\t\tconst parser = this.parser;\n\t\tconst json = parser.json;\n\n\t\tconst textureDef = json.textures[ textureIndex ];\n\n\t\tif ( ! textureDef.extensions || ! textureDef.extensions[ this.name ] ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\tconst extension = textureDef.extensions[ this.name ];\n\t\tconst loader = parser.options.ktx2Loader;\n\n\t\tif ( ! loader ) {\n\n\t\t\tif ( json.extensionsRequired && json.extensionsRequired.indexOf( this.name ) >= 0 ) {\n\n\t\t\t\tthrow new Error( 'THREE.GLTFLoader: setKTX2Loader must be called before loading KTX2 textures' );\n\n\t\t\t} else {\n\n\t\t\t\t// Assumes that the extension is optional and that a fallback texture is present\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn parser.loadTextureImage( textureIndex, extension.source, loader );\n\n\t}\n\n}\n\n/**\n * WebP Texture Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_texture_webp\n *\n * @private\n */\nclass GLTFTextureWebPExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.EXT_TEXTURE_WEBP;\n\n\t}\n\n\tloadTexture( textureIndex ) {\n\n\t\tconst name = this.name;\n\t\tconst parser = this.parser;\n\t\tconst json = parser.json;\n\n\t\tconst textureDef = json.textures[ textureIndex ];\n\n\t\tif ( ! textureDef.extensions || ! textureDef.extensions[ name ] ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\tconst extension = textureDef.extensions[ name ];\n\t\tconst source = json.images[ extension.source ];\n\n\t\tlet loader = parser.textureLoader;\n\t\tif ( source.uri ) {\n\n\t\t\tconst handler = parser.options.manager.getHandler( source.uri );\n\t\t\tif ( handler !== null ) loader = handler;\n\n\t\t}\n\n\t\treturn parser.loadTextureImage( textureIndex, extension.source, loader );\n\n\t}\n\n}\n\n/**\n * AVIF Texture Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_texture_avif\n *\n * @private\n */\nclass GLTFTextureAVIFExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.EXT_TEXTURE_AVIF;\n\n\t}\n\n\tloadTexture( textureIndex ) {\n\n\t\tconst name = this.name;\n\t\tconst parser = this.parser;\n\t\tconst json = parser.json;\n\n\t\tconst textureDef = json.textures[ textureIndex ];\n\n\t\tif ( ! textureDef.extensions || ! textureDef.extensions[ name ] ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\tconst extension = textureDef.extensions[ name ];\n\t\tconst source = json.images[ extension.source ];\n\n\t\tlet loader = parser.textureLoader;\n\t\tif ( source.uri ) {\n\n\t\t\tconst handler = parser.options.manager.getHandler( source.uri );\n\t\t\tif ( handler !== null ) loader = handler;\n\n\t\t}\n\n\t\treturn parser.loadTextureImage( textureIndex, extension.source, loader );\n\n\t}\n\n}\n\n/**\n * meshopt BufferView Compression Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_meshopt_compression\n *\n * @private\n */\nclass GLTFMeshoptCompression {\n\n\tconstructor( parser, name ) {\n\n\t\tthis.name = name;\n\t\tthis.parser = parser;\n\n\t}\n\n\tloadBufferView( index ) {\n\n\t\tconst json = this.parser.json;\n\t\tconst bufferView = json.bufferViews[ index ];\n\n\t\tif ( bufferView.extensions && bufferView.extensions[ this.name ] ) {\n\n\t\t\tconst extensionDef = bufferView.extensions[ this.name ];\n\n\t\t\tconst buffer = this.parser.getDependency( 'buffer', extensionDef.buffer );\n\t\t\tconst decoder = this.parser.options.meshoptDecoder;\n\n\t\t\tif ( ! decoder || ! decoder.supported ) {\n\n\t\t\t\tif ( json.extensionsRequired && json.extensionsRequired.indexOf( this.name ) >= 0 ) {\n\n\t\t\t\t\tthrow new Error( 'THREE.GLTFLoader: setMeshoptDecoder must be called before loading compressed files' );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// Assumes that the extension is optional and that fallback buffer data is present\n\t\t\t\t\treturn null;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn buffer.then( function ( res ) {\n\n\t\t\t\tconst byteOffset = extensionDef.byteOffset || 0;\n\t\t\t\tconst byteLength = extensionDef.byteLength || 0;\n\n\t\t\t\tconst count = extensionDef.count;\n\t\t\t\tconst stride = extensionDef.byteStride;\n\n\t\t\t\tconst source = new Uint8Array( res, byteOffset, byteLength );\n\n\t\t\t\tif ( decoder.decodeGltfBufferAsync ) {\n\n\t\t\t\t\treturn decoder.decodeGltfBufferAsync( count, stride, source, extensionDef.mode, extensionDef.filter ).then( function ( res ) {\n\n\t\t\t\t\t\treturn res.buffer;\n\n\t\t\t\t\t} );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// Support for MeshoptDecoder 0.18 or earlier, without decodeGltfBufferAsync\n\t\t\t\t\treturn decoder.ready.then( function () {\n\n\t\t\t\t\t\tconst result = new ArrayBuffer( count * stride );\n\t\t\t\t\t\tdecoder.decodeGltfBuffer( new Uint8Array( result ), count, stride, source, extensionDef.mode, extensionDef.filter );\n\t\t\t\t\t\treturn result;\n\n\t\t\t\t\t} );\n\n\t\t\t\t}\n\n\t\t\t} );\n\n\t\t} else {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t}\n\n}\n\n/**\n * GPU Instancing Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_mesh_gpu_instancing\n *\n * @private\n */\nclass GLTFMeshGpuInstancing {\n\n\tconstructor( parser ) {\n\n\t\tthis.name = EXTENSIONS.EXT_MESH_GPU_INSTANCING;\n\t\tthis.parser = parser;\n\n\t}\n\n\tcreateNodeMesh( nodeIndex ) {\n\n\t\tconst json = this.parser.json;\n\t\tconst nodeDef = json.nodes[ nodeIndex ];\n\n\t\tif ( ! nodeDef.extensions || ! nodeDef.extensions[ this.name ] ||\n\t\t\tnodeDef.mesh === undefined ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\tconst meshDef = json.meshes[ nodeDef.mesh ];\n\n\t\t// No Points or Lines + Instancing support yet\n\n\t\tfor ( const primitive of meshDef.primitives ) {\n\n\t\t\tif ( primitive.mode !== WEBGL_CONSTANTS.TRIANGLES &&\n\t\t\t\t primitive.mode !== WEBGL_CONSTANTS.TRIANGLE_STRIP &&\n\t\t\t\t primitive.mode !== WEBGL_CONSTANTS.TRIANGLE_FAN &&\n\t\t\t\t primitive.mode !== undefined ) {\n\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t}\n\n\t\tconst extensionDef = nodeDef.extensions[ this.name ];\n\t\tconst attributesDef = extensionDef.attributes;\n\n\t\t// @TODO: Can we support InstancedMesh + SkinnedMesh?\n\n\t\tconst pending = [];\n\t\tconst attributes = {};\n\n\t\tfor ( const key in attributesDef ) {\n\n\t\t\tpending.push( this.parser.getDependency( 'accessor', attributesDef[ key ] ).then( accessor => {\n\n\t\t\t\tattributes[ key ] = accessor;\n\t\t\t\treturn attributes[ key ];\n\n\t\t\t} ) );\n\n\t\t}\n\n\t\tif ( pending.length < 1 ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\tpending.push( this.parser.createNodeMesh( nodeIndex ) );\n\n\t\treturn Promise.all( pending ).then( results => {\n\n\t\t\tconst nodeObject = results.pop();\n\t\t\tconst meshes = nodeObject.isGroup ? nodeObject.children : [ nodeObject ];\n\t\t\tconst count = results[ 0 ].count; // All attribute counts should be same\n\t\t\tconst instancedMeshes = [];\n\n\t\t\tfor ( const mesh of meshes ) {\n\n\t\t\t\t// Temporal variables\n\t\t\t\tconst m = new Matrix4();\n\t\t\t\tconst p = new Vector3();\n\t\t\t\tconst q = new Quaternion();\n\t\t\t\tconst s = new Vector3( 1, 1, 1 );\n\n\t\t\t\tconst instancedMesh = new InstancedMesh( mesh.geometry, mesh.material, count );\n\n\t\t\t\tfor ( let i = 0; i < count; i ++ ) {\n\n\t\t\t\t\tif ( attributes.TRANSLATION ) {\n\n\t\t\t\t\t\tp.fromBufferAttribute( attributes.TRANSLATION, i );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( attributes.ROTATION ) {\n\n\t\t\t\t\t\tq.fromBufferAttribute( attributes.ROTATION, i );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( attributes.SCALE ) {\n\n\t\t\t\t\t\ts.fromBufferAttribute( attributes.SCALE, i );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tinstancedMesh.setMatrixAt( i, m.compose( p, q, s ) );\n\n\t\t\t\t}\n\n\t\t\t\t// Add instance attributes to the geometry, excluding TRS.\n\t\t\t\tfor ( const attributeName in attributes ) {\n\n\t\t\t\t\tif ( attributeName === '_COLOR_0' ) {\n\n\t\t\t\t\t\tconst attr = attributes[ attributeName ];\n\t\t\t\t\t\tinstancedMesh.instanceColor = new InstancedBufferAttribute( attr.array, attr.itemSize, attr.normalized );\n\n\t\t\t\t\t} else if ( attributeName !== 'TRANSLATION' &&\n\t\t\t\t\t\t attributeName !== 'ROTATION' &&\n\t\t\t\t\t\t attributeName !== 'SCALE' ) {\n\n\t\t\t\t\t\tmesh.geometry.setAttribute( attributeName, attributes[ attributeName ] );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\t// Just in case\n\t\t\t\tObject3D.prototype.copy.call( instancedMesh, mesh );\n\n\t\t\t\tthis.parser.assignFinalMaterial( instancedMesh );\n\n\t\t\t\tinstancedMeshes.push( instancedMesh );\n\n\t\t\t}\n\n\t\t\tif ( nodeObject.isGroup ) {\n\n\t\t\t\tnodeObject.clear();\n\n\t\t\t\tnodeObject.add( ... instancedMeshes );\n\n\t\t\t\treturn nodeObject;\n\n\t\t\t}\n\n\t\t\treturn instancedMeshes[ 0 ];\n\n\t\t} );\n\n\t}\n\n}\n\n/* BINARY EXTENSION */\nconst BINARY_EXTENSION_HEADER_MAGIC = 'glTF';\nconst BINARY_EXTENSION_HEADER_LENGTH = 12;\nconst BINARY_EXTENSION_CHUNK_TYPES = { JSON: 0x4E4F534A, BIN: 0x004E4942 };\n\nclass GLTFBinaryExtension {\n\n\tconstructor( data ) {\n\n\t\tthis.name = EXTENSIONS.KHR_BINARY_GLTF;\n\t\tthis.content = null;\n\t\tthis.body = null;\n\n\t\tconst headerView = new DataView( data, 0, BINARY_EXTENSION_HEADER_LENGTH );\n\t\tconst textDecoder = new TextDecoder();\n\n\t\tthis.header = {\n\t\t\tmagic: textDecoder.decode( new Uint8Array( data.slice( 0, 4 ) ) ),\n\t\t\tversion: headerView.getUint32( 4, true ),\n\t\t\tlength: headerView.getUint32( 8, true )\n\t\t};\n\n\t\tif ( this.header.magic !== BINARY_EXTENSION_HEADER_MAGIC ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: Unsupported glTF-Binary header.' );\n\n\t\t} else if ( this.header.version < 2.0 ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: Legacy binary file detected.' );\n\n\t\t}\n\n\t\tconst chunkContentsLength = this.header.length - BINARY_EXTENSION_HEADER_LENGTH;\n\t\tconst chunkView = new DataView( data, BINARY_EXTENSION_HEADER_LENGTH );\n\t\tlet chunkIndex = 0;\n\n\t\twhile ( chunkIndex < chunkContentsLength ) {\n\n\t\t\tconst chunkLength = chunkView.getUint32( chunkIndex, true );\n\t\t\tchunkIndex += 4;\n\n\t\t\tconst chunkType = chunkView.getUint32( chunkIndex, true );\n\t\t\tchunkIndex += 4;\n\n\t\t\tif ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.JSON ) {\n\n\t\t\t\tconst contentArray = new Uint8Array( data, BINARY_EXTENSION_HEADER_LENGTH + chunkIndex, chunkLength );\n\t\t\t\tthis.content = textDecoder.decode( contentArray );\n\n\t\t\t} else if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.BIN ) {\n\n\t\t\t\tconst byteOffset = BINARY_EXTENSION_HEADER_LENGTH + chunkIndex;\n\t\t\t\tthis.body = data.slice( byteOffset, byteOffset + chunkLength );\n\n\t\t\t}\n\n\t\t\t// Clients must ignore chunks with unknown types.\n\n\t\t\tchunkIndex += chunkLength;\n\n\t\t}\n\n\t\tif ( this.content === null ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: JSON content not found.' );\n\n\t\t}\n\n\t}\n\n}\n\n/**\n * DRACO Mesh Compression Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression\n *\n * @private\n */\nclass GLTFDracoMeshCompressionExtension {\n\n\tconstructor( json, dracoLoader ) {\n\n\t\tif ( ! dracoLoader ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: No DRACOLoader instance provided.' );\n\n\t\t}\n\n\t\tthis.name = EXTENSIONS.KHR_DRACO_MESH_COMPRESSION;\n\t\tthis.json = json;\n\t\tthis.dracoLoader = dracoLoader;\n\t\tthis.dracoLoader.preload();\n\n\t}\n\n\tdecodePrimitive( primitive, parser ) {\n\n\t\tconst json = this.json;\n\t\tconst dracoLoader = this.dracoLoader;\n\t\tconst bufferViewIndex = primitive.extensions[ this.name ].bufferView;\n\t\tconst gltfAttributeMap = primitive.extensions[ this.name ].attributes;\n\t\tconst threeAttributeMap = {};\n\t\tconst attributeNormalizedMap = {};\n\t\tconst attributeTypeMap = {};\n\n\t\tfor ( const attributeName in gltfAttributeMap ) {\n\n\t\t\tconst threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase();\n\n\t\t\tthreeAttributeMap[ threeAttributeName ] = gltfAttributeMap[ attributeName ];\n\n\t\t}\n\n\t\tfor ( const attributeName in primitive.attributes ) {\n\n\t\t\tconst threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase();\n\n\t\t\tif ( gltfAttributeMap[ attributeName ] !== undefined ) {\n\n\t\t\t\tconst accessorDef = json.accessors[ primitive.attributes[ attributeName ] ];\n\t\t\t\tconst componentType = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];\n\n\t\t\t\tattributeTypeMap[ threeAttributeName ] = componentType.name;\n\t\t\t\tattributeNormalizedMap[ threeAttributeName ] = accessorDef.normalized === true;\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn parser.getDependency( 'bufferView', bufferViewIndex ).then( function ( bufferView ) {\n\n\t\t\treturn new Promise( function ( resolve, reject ) {\n\n\t\t\t\tdracoLoader.decodeDracoFile( bufferView, function ( geometry ) {\n\n\t\t\t\t\tfor ( const attributeName in geometry.attributes ) {\n\n\t\t\t\t\t\tconst attribute = geometry.attributes[ attributeName ];\n\t\t\t\t\t\tconst normalized = attributeNormalizedMap[ attributeName ];\n\n\t\t\t\t\t\tif ( normalized !== undefined ) attribute.normalized = normalized;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve( geometry );\n\n\t\t\t\t}, threeAttributeMap, attributeTypeMap, LinearSRGBColorSpace, reject );\n\n\t\t\t} );\n\n\t\t} );\n\n\t}\n\n}\n\n/**\n * Texture Transform Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_texture_transform\n *\n * @private\n */\nclass GLTFTextureTransformExtension {\n\n\tconstructor() {\n\n\t\tthis.name = EXTENSIONS.KHR_TEXTURE_TRANSFORM;\n\n\t}\n\n\textendTexture( texture, transform ) {\n\n\t\tif ( ( transform.texCoord === undefined || transform.texCoord === texture.channel )\n\t\t\t&& transform.offset === undefined\n\t\t\t&& transform.rotation === undefined\n\t\t\t&& transform.scale === undefined ) {\n\n\t\t\t// See https://github.com/mrdoob/three.js/issues/21819.\n\t\t\treturn texture;\n\n\t\t}\n\n\t\ttexture = texture.clone();\n\n\t\tif ( transform.texCoord !== undefined ) {\n\n\t\t\ttexture.channel = transform.texCoord;\n\n\t\t}\n\n\t\tif ( transform.offset !== undefined ) {\n\n\t\t\ttexture.offset.fromArray( transform.offset );\n\n\t\t}\n\n\t\tif ( transform.rotation !== undefined ) {\n\n\t\t\ttexture.rotation = transform.rotation;\n\n\t\t}\n\n\t\tif ( transform.scale !== undefined ) {\n\n\t\t\ttexture.repeat.fromArray( transform.scale );\n\n\t\t}\n\n\t\ttexture.needsUpdate = true;\n\n\t\treturn texture;\n\n\t}\n\n}\n\n/**\n * Mesh Quantization Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization\n *\n * @private\n */\nclass GLTFMeshQuantizationExtension {\n\n\tconstructor() {\n\n\t\tthis.name = EXTENSIONS.KHR_MESH_QUANTIZATION;\n\n\t}\n\n}\n\n/*********************************/\n/********** INTERPOLATION ********/\n/*********************************/\n\n// Spline Interpolation\n// Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#appendix-c-spline-interpolation\nclass GLTFCubicSplineInterpolant extends Interpolant {\n\n\tconstructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {\n\n\t\tsuper( parameterPositions, sampleValues, sampleSize, resultBuffer );\n\n\t}\n\n\tcopySampleValue_( index ) {\n\n\t\t// Copies a sample value to the result buffer. See description of glTF\n\t\t// CUBICSPLINE values layout in interpolate_() function below.\n\n\t\tconst result = this.resultBuffer,\n\t\t\tvalues = this.sampleValues,\n\t\t\tvalueSize = this.valueSize,\n\t\t\toffset = index * valueSize * 3 + valueSize;\n\n\t\tfor ( let i = 0; i !== valueSize; i ++ ) {\n\n\t\t\tresult[ i ] = values[ offset + i ];\n\n\t\t}\n\n\t\treturn result;\n\n\t}\n\n\tinterpolate_( i1, t0, t, t1 ) {\n\n\t\tconst result = this.resultBuffer;\n\t\tconst values = this.sampleValues;\n\t\tconst stride = this.valueSize;\n\n\t\tconst stride2 = stride * 2;\n\t\tconst stride3 = stride * 3;\n\n\t\tconst td = t1 - t0;\n\n\t\tconst p = ( t - t0 ) / td;\n\t\tconst pp = p * p;\n\t\tconst ppp = pp * p;\n\n\t\tconst offset1 = i1 * stride3;\n\t\tconst offset0 = offset1 - stride3;\n\n\t\tconst s2 = - 2 * ppp + 3 * pp;\n\t\tconst s3 = ppp - pp;\n\t\tconst s0 = 1 - s2;\n\t\tconst s1 = s3 - pp + p;\n\n\t\t// Layout of keyframe output values for CUBICSPLINE animations:\n\t\t// [ inTangent_1, splineVertex_1, outTangent_1, inTangent_2, splineVertex_2, ... ]\n\t\tfor ( let i = 0; i !== stride; i ++ ) {\n\n\t\t\tconst p0 = values[ offset0 + i + stride ]; // splineVertex_k\n\t\t\tconst m0 = values[ offset0 + i + stride2 ] * td; // outTangent_k * (t_k+1 - t_k)\n\t\t\tconst p1 = values[ offset1 + i + stride ]; // splineVertex_k+1\n\t\t\tconst m1 = values[ offset1 + i ] * td; // inTangent_k+1 * (t_k+1 - t_k)\n\n\t\t\tresult[ i ] = s0 * p0 + s1 * m0 + s2 * p1 + s3 * m1;\n\n\t\t}\n\n\t\treturn result;\n\n\t}\n\n}\n\nconst _quaternion = new Quaternion();\n\nclass GLTFCubicSplineQuaternionInterpolant extends GLTFCubicSplineInterpolant {\n\n\tinterpolate_( i1, t0, t, t1 ) {\n\n\t\tconst result = super.interpolate_( i1, t0, t, t1 );\n\n\t\t_quaternion.fromArray( result ).normalize().toArray( result );\n\n\t\treturn result;\n\n\t}\n\n}\n\n\n/*********************************/\n/********** INTERNALS ************/\n/*********************************/\n\n/* CONSTANTS */\n\nconst WEBGL_CONSTANTS = {\n\tFLOAT: 5126,\n\t//FLOAT_MAT2: 35674,\n\tFLOAT_MAT3: 35675,\n\tFLOAT_MAT4: 35676,\n\tFLOAT_VEC2: 35664,\n\tFLOAT_VEC3: 35665,\n\tFLOAT_VEC4: 35666,\n\tLINEAR: 9729,\n\tREPEAT: 10497,\n\tSAMPLER_2D: 35678,\n\tPOINTS: 0,\n\tLINES: 1,\n\tLINE_LOOP: 2,\n\tLINE_STRIP: 3,\n\tTRIANGLES: 4,\n\tTRIANGLE_STRIP: 5,\n\tTRIANGLE_FAN: 6,\n\tUNSIGNED_BYTE: 5121,\n\tUNSIGNED_SHORT: 5123\n};\n\nconst WEBGL_COMPONENT_TYPES = {\n\t5120: Int8Array,\n\t5121: Uint8Array,\n\t5122: Int16Array,\n\t5123: Uint16Array,\n\t5125: Uint32Array,\n\t5126: Float32Array\n};\n\nconst WEBGL_FILTERS = {\n\t9728: NearestFilter,\n\t9729: LinearFilter,\n\t9984: NearestMipmapNearestFilter,\n\t9985: LinearMipmapNearestFilter,\n\t9986: NearestMipmapLinearFilter,\n\t9987: LinearMipmapLinearFilter\n};\n\nconst WEBGL_WRAPPINGS = {\n\t33071: ClampToEdgeWrapping,\n\t33648: MirroredRepeatWrapping,\n\t10497: RepeatWrapping\n};\n\nconst WEBGL_TYPE_SIZES = {\n\t'SCALAR': 1,\n\t'VEC2': 2,\n\t'VEC3': 3,\n\t'VEC4': 4,\n\t'MAT2': 4,\n\t'MAT3': 9,\n\t'MAT4': 16\n};\n\nconst ATTRIBUTES = {\n\tPOSITION: 'position',\n\tNORMAL: 'normal',\n\tTANGENT: 'tangent',\n\tTEXCOORD_0: 'uv',\n\tTEXCOORD_1: 'uv1',\n\tTEXCOORD_2: 'uv2',\n\tTEXCOORD_3: 'uv3',\n\tCOLOR_0: 'color',\n\tWEIGHTS_0: 'skinWeight',\n\tJOINTS_0: 'skinIndex',\n};\n\nconst PATH_PROPERTIES = {\n\tscale: 'scale',\n\ttranslation: 'position',\n\trotation: 'quaternion',\n\tweights: 'morphTargetInfluences'\n};\n\nconst INTERPOLATION = {\n\tCUBICSPLINE: undefined, // We use a custom interpolant (GLTFCubicSplineInterpolation) for CUBICSPLINE tracks. Each\n\t\t // keyframe track will be initialized with a default interpolation type, then modified.\n\tLINEAR: InterpolateLinear,\n\tSTEP: InterpolateDiscrete\n};\n\nconst ALPHA_MODES = {\n\tOPAQUE: 'OPAQUE',\n\tMASK: 'MASK',\n\tBLEND: 'BLEND'\n};\n\n/**\n * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#default-material\n *\n * @private\n * @param {Object<string, Material>} cache\n * @return {Material}\n */\nfunction createDefaultMaterial( cache ) {\n\n\tif ( cache[ 'DefaultMaterial' ] === undefined ) {\n\n\t\tcache[ 'DefaultMaterial' ] = new MeshStandardMaterial( {\n\t\t\tcolor: 0xFFFFFF,\n\t\t\temissive: 0x000000,\n\t\t\tmetalness: 1,\n\t\t\troughness: 1,\n\t\t\ttransparent: false,\n\t\t\tdepthTest: true,\n\t\t\tside: FrontSide\n\t\t} );\n\n\t}\n\n\treturn cache[ 'DefaultMaterial' ];\n\n}\n\nfunction addUnknownExtensionsToUserData( knownExtensions, object, objectDef ) {\n\n\t// Add unknown glTF extensions to an object's userData.\n\n\tfor ( const name in objectDef.extensions ) {\n\n\t\tif ( knownExtensions[ name ] === undefined ) {\n\n\t\t\tobject.userData.gltfExtensions = object.userData.gltfExtensions || {};\n\t\t\tobject.userData.gltfExtensions[ name ] = objectDef.extensions[ name ];\n\n\t\t}\n\n\t}\n\n}\n\n/**\n *\n * @private\n * @param {Object3D|Material|BufferGeometry|Object|AnimationClip} object\n * @param {GLTF.definition} gltfDef\n */\nfunction assignExtrasToUserData( object, gltfDef ) {\n\n\tif ( gltfDef.extras !== undefined ) {\n\n\t\tif ( typeof gltfDef.extras === 'object' ) {\n\n\t\t\tObject.assign( object.userData, gltfDef.extras );\n\n\t\t} else {\n\n\t\t\tconsole.warn( 'THREE.GLTFLoader: Ignoring primitive type .extras, ' + gltfDef.extras );\n\n\t\t}\n\n\t}\n\n}\n\n/**\n * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#morph-targets\n *\n * @private\n * @param {BufferGeometry} geometry\n * @param {Array<GLTF.Target>} targets\n * @param {GLTFParser} parser\n * @return {Promise<BufferGeometry>}\n */\nfunction addMorphTargets( geometry, targets, parser ) {\n\n\tlet hasMorphPosition = false;\n\tlet hasMorphNormal = false;\n\tlet hasMorphColor = false;\n\n\tfor ( let i = 0, il = targets.length; i < il; i ++ ) {\n\n\t\tconst target = targets[ i ];\n\n\t\tif ( target.POSITION !== undefined ) hasMorphPosition = true;\n\t\tif ( target.NORMAL !== undefined ) hasMorphNormal = true;\n\t\tif ( target.COLOR_0 !== undefined ) hasMorphColor = true;\n\n\t\tif ( hasMorphPosition && hasMorphNormal && hasMorphColor ) break;\n\n\t}\n\n\tif ( ! hasMorphPosition && ! hasMorphNormal && ! hasMorphColor ) return Promise.resolve( geometry );\n\n\tconst pendingPositionAccessors = [];\n\tconst pendingNormalAccessors = [];\n\tconst pendingColorAccessors = [];\n\n\tfor ( let i = 0, il = targets.length; i < il; i ++ ) {\n\n\t\tconst target = targets[ i ];\n\n\t\tif ( hasMorphPosition ) {\n\n\t\t\tconst pendingAccessor = target.POSITION !== undefined\n\t\t\t\t? parser.getDependency( 'accessor', target.POSITION )\n\t\t\t\t: geometry.attributes.position;\n\n\t\t\tpendingPositionAccessors.push( pendingAccessor );\n\n\t\t}\n\n\t\tif ( hasMorphNormal ) {\n\n\t\t\tconst pendingAccessor = target.NORMAL !== undefined\n\t\t\t\t? parser.getDependency( 'accessor', target.NORMAL )\n\t\t\t\t: geometry.attributes.normal;\n\n\t\t\tpendingNormalAccessors.push( pendingAccessor );\n\n\t\t}\n\n\t\tif ( hasMorphColor ) {\n\n\t\t\tconst pendingAccessor = target.COLOR_0 !== undefined\n\t\t\t\t? parser.getDependency( 'accessor', target.COLOR_0 )\n\t\t\t\t: geometry.attributes.color;\n\n\t\t\tpendingColorAccessors.push( pendingAccessor );\n\n\t\t}\n\n\t}\n\n\treturn Promise.all( [\n\t\tPromise.all( pendingPositionAccessors ),\n\t\tPromise.all( pendingNormalAccessors ),\n\t\tPromise.all( pendingColorAccessors )\n\t] ).then( function ( accessors ) {\n\n\t\tconst morphPositions = accessors[ 0 ];\n\t\tconst morphNormals = accessors[ 1 ];\n\t\tconst morphColors = accessors[ 2 ];\n\n\t\tif ( hasMorphPosition ) geometry.morphAttributes.position = morphPositions;\n\t\tif ( hasMorphNormal ) geometry.morphAttributes.normal = morphNormals;\n\t\tif ( hasMorphColor ) geometry.morphAttributes.color = morphColors;\n\t\tgeometry.morphTargetsRelative = true;\n\n\t\treturn geometry;\n\n\t} );\n\n}\n\n/**\n *\n * @private\n * @param {Mesh} mesh\n * @param {GLTF.Mesh} meshDef\n */\nfunction updateMorphTargets( mesh, meshDef ) {\n\n\tmesh.updateMorphTargets();\n\n\tif ( meshDef.weights !== undefined ) {\n\n\t\tfor ( let i = 0, il = meshDef.weights.length; i < il; i ++ ) {\n\n\t\t\tmesh.morphTargetInfluences[ i ] = meshDef.weights[ i ];\n\n\t\t}\n\n\t}\n\n\t// .extras has user-defined data, so check that .extras.targetNames is an array.\n\tif ( meshDef.extras && Array.isArray( meshDef.extras.targetNames ) ) {\n\n\t\tconst targetNames = meshDef.extras.targetNames;\n\n\t\tif ( mesh.morphTargetInfluences.length === targetNames.length ) {\n\n\t\t\tmesh.morphTargetDictionary = {};\n\n\t\t\tfor ( let i = 0, il = targetNames.length; i < il; i ++ ) {\n\n\t\t\t\tmesh.morphTargetDictionary[ targetNames[ i ] ] = i;\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tconsole.warn( 'THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.' );\n\n\t\t}\n\n\t}\n\n}\n\nfunction createPrimitiveKey( primitiveDef ) {\n\n\tlet geometryKey;\n\n\tconst dracoExtension = primitiveDef.extensions && primitiveDef.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ];\n\n\tif ( dracoExtension ) {\n\n\t\tgeometryKey = 'draco:' + dracoExtension.bufferView\n\t\t\t\t+ ':' + dracoExtension.indices\n\t\t\t\t+ ':' + createAttributesKey( dracoExtension.attributes );\n\n\t} else {\n\n\t\tgeometryKey = primitiveDef.indices + ':' + createAttributesKey( primitiveDef.attributes ) + ':' + primitiveDef.mode;\n\n\t}\n\n\tif ( primitiveDef.targets !== undefined ) {\n\n\t\tfor ( let i = 0, il = primitiveDef.targets.length; i < il; i ++ ) {\n\n\t\t\tgeometryKey += ':' + createAttributesKey( primitiveDef.targets[ i ] );\n\n\t\t}\n\n\t}\n\n\treturn geometryKey;\n\n}\n\nfunction createAttributesKey( attributes ) {\n\n\tlet attributesKey = '';\n\n\tconst keys = Object.keys( attributes ).sort();\n\n\tfor ( let i = 0, il = keys.length; i < il; i ++ ) {\n\n\t\tattributesKey += keys[ i ] + ':' + attributes[ keys[ i ] ] + ';';\n\n\t}\n\n\treturn attributesKey;\n\n}\n\nfunction getNormalizedComponentScale( constructor ) {\n\n\t// Reference:\n\t// https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization#encoding-quantized-data\n\n\tswitch ( constructor ) {\n\n\t\tcase Int8Array:\n\t\t\treturn 1 / 127;\n\n\t\tcase Uint8Array:\n\t\t\treturn 1 / 255;\n\n\t\tcase Int16Array:\n\t\t\treturn 1 / 32767;\n\n\t\tcase Uint16Array:\n\t\t\treturn 1 / 65535;\n\n\t\tdefault:\n\t\t\tthrow new Error( 'THREE.GLTFLoader: Unsupported normalized accessor component type.' );\n\n\t}\n\n}\n\nfunction getImageURIMimeType( uri ) {\n\n\tif ( uri.search( /\\.jpe?g($|\\?)/i ) > 0 || uri.search( /^data\\:image\\/jpeg/ ) === 0 ) return 'image/jpeg';\n\tif ( uri.search( /\\.webp($|\\?)/i ) > 0 || uri.search( /^data\\:image\\/webp/ ) === 0 ) return 'image/webp';\n\tif ( uri.search( /\\.ktx2($|\\?)/i ) > 0 || uri.search( /^data\\:image\\/ktx2/ ) === 0 ) return 'image/ktx2';\n\n\treturn 'image/png';\n\n}\n\nconst _identityMatrix = new Matrix4();\n\n/* GLTF PARSER */\n\nclass GLTFParser {\n\n\tconstructor( json = {}, options = {} ) {\n\n\t\tthis.json = json;\n\t\tthis.extensions = {};\n\t\tthis.plugins = {};\n\t\tthis.options = options;\n\n\t\t// loader object cache\n\t\tthis.cache = new GLTFRegistry();\n\n\t\t// associations between Three.js objects and glTF elements\n\t\tthis.associations = new Map();\n\n\t\t// BufferGeometry caching\n\t\tthis.primitiveCache = {};\n\n\t\t// Node cache\n\t\tthis.nodeCache = {};\n\n\t\t// Object3D instance caches\n\t\tthis.meshCache = { refs: {}, uses: {} };\n\t\tthis.cameraCache = { refs: {}, uses: {} };\n\t\tthis.lightCache = { refs: {}, uses: {} };\n\n\t\tthis.sourceCache = {};\n\t\tthis.textureCache = {};\n\n\t\t// Track node names, to ensure no duplicates\n\t\tthis.nodeNamesUsed = {};\n\n\t\t// Use an ImageBitmapLoader if imageBitmaps are supported. Moves much of the\n\t\t// expensive work of uploading a texture to the GPU off the main thread.\n\n\t\tlet isSafari = false;\n\t\tlet safariVersion = - 1;\n\t\tlet isFirefox = false;\n\t\tlet firefoxVersion = - 1;\n\n\t\tif ( typeof navigator !== 'undefined' && typeof navigator.userAgent !== 'undefined' ) {\n\n\t\t\tconst userAgent = navigator.userAgent;\n\n\t\t\tisSafari = /^((?!chrome|android).)*safari/i.test( userAgent ) === true;\n\t\t\tconst safariMatch = userAgent.match( /Version\\/(\\d+)/ );\n\t\t\tsafariVersion = isSafari && safariMatch ? parseInt( safariMatch[ 1 ], 10 ) : - 1;\n\n\t\t\tisFirefox = userAgent.indexOf( 'Firefox' ) > - 1;\n\t\t\tfirefoxVersion = isFirefox ? userAgent.match( /Firefox\\/([0-9]+)\\./ )[ 1 ] : - 1;\n\n\t\t}\n\n\t\tif ( typeof createImageBitmap === 'undefined' || ( isSafari && safariVersion < 17 ) || ( isFirefox && firefoxVersion < 98 ) ) {\n\n\t\t\tthis.textureLoader = new TextureLoader( this.options.manager );\n\n\t\t} else {\n\n\t\t\tthis.textureLoader = new ImageBitmapLoader( this.options.manager );\n\n\t\t}\n\n\t\tthis.textureLoader.setCrossOrigin( this.options.crossOrigin );\n\t\tthis.textureLoader.setRequestHeader( this.options.requestHeader );\n\n\t\tthis.fileLoader = new FileLoader( this.options.manager );\n\t\tthis.fileLoader.setResponseType( 'arraybuffer' );\n\n\t\tif ( this.options.crossOrigin === 'use-credentials' ) {\n\n\t\t\tthis.fileLoader.setWithCredentials( true );\n\n\t\t}\n\n\t}\n\n\tsetExtensions( extensions ) {\n\n\t\tthis.extensions = extensions;\n\n\t}\n\n\tsetPlugins( plugins ) {\n\n\t\tthis.plugins = plugins;\n\n\t}\n\n\tparse( onLoad, onError ) {\n\n\t\tconst parser = this;\n\t\tconst json = this.json;\n\t\tconst extensions = this.extensions;\n\n\t\t// Clear the loader cache\n\t\tthis.cache.removeAll();\n\t\tthis.nodeCache = {};\n\n\t\t// Mark the special nodes/meshes in json for efficient parse\n\t\tthis._invokeAll( function ( ext ) {\n\n\t\t\treturn ext._markDefs && ext._markDefs();\n\n\t\t} );\n\n\t\tPromise.all( this._invokeAll( function ( ext ) {\n\n\t\t\treturn ext.beforeRoot && ext.beforeRoot();\n\n\t\t} ) ).then( function () {\n\n\t\t\treturn Promise.all( [\n\n\t\t\t\tparser.getDependencies( 'scene' ),\n\t\t\t\tparser.getDependencies( 'animation' ),\n\t\t\t\tparser.getDependencies( 'camera' ),\n\n\t\t\t] );\n\n\t\t} ).then( function ( dependencies ) {\n\n\t\t\tconst result = {\n\t\t\t\tscene: dependencies[ 0 ][ json.scene || 0 ],\n\t\t\t\tscenes: dependencies[ 0 ],\n\t\t\t\tanimations: dependencies[ 1 ],\n\t\t\t\tcameras: dependencies[ 2 ],\n\t\t\t\tasset: json.asset,\n\t\t\t\tparser: parser,\n\t\t\t\tuserData: {}\n\t\t\t};\n\n\t\t\taddUnknownExtensionsToUserData( extensions, result, json );\n\n\t\t\tassignExtrasToUserData( result, json );\n\n\t\t\treturn Promise.all( parser._invokeAll( function ( ext ) {\n\n\t\t\t\treturn ext.afterRoot && ext.afterRoot( result );\n\n\t\t\t} ) ).then( function () {\n\n\t\t\t\tfor ( const scene of result.scenes ) {\n\n\t\t\t\t\tscene.updateMatrixWorld();\n\n\t\t\t\t}\n\n\t\t\t\tonLoad( result );\n\n\t\t\t} );\n\n\t\t} ).catch( onError );\n\n\t}\n\n\t/**\n\t * Marks the special nodes/meshes in json for efficient parse.\n\t *\n\t * @private\n\t */\n\t_markDefs() {\n\n\t\tconst nodeDefs = this.json.nodes || [];\n\t\tconst skinDefs = this.json.skins || [];\n\t\tconst meshDefs = this.json.meshes || [];\n\n\t\t// Nothing in the node definition indicates whether it is a Bone or an\n\t\t// Object3D. Use the skins' joint references to mark bones.\n\t\tfor ( let skinIndex = 0, skinLength = skinDefs.length; skinIndex < skinLength; skinIndex ++ ) {\n\n\t\t\tconst joints = skinDefs[ skinIndex ].joints;\n\n\t\t\tfor ( let i = 0, il = joints.length; i < il; i ++ ) {\n\n\t\t\t\tnodeDefs[ joints[ i ] ].isBone = true;\n\n\t\t\t}\n\n\t\t}\n\n\t\t// Iterate over all nodes, marking references to shared resources,\n\t\t// as well as skeleton joints.\n\t\tfor ( let nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex ++ ) {\n\n\t\t\tconst nodeDef = nodeDefs[ nodeIndex ];\n\n\t\t\tif ( nodeDef.mesh !== undefined ) {\n\n\t\t\t\tthis._addNodeRef( this.meshCache, nodeDef.mesh );\n\n\t\t\t\t// Nothing in the mesh definition indicates whether it is\n\t\t\t\t// a SkinnedMesh or Mesh. Use the node's mesh reference\n\t\t\t\t// to mark SkinnedMesh if node has skin.\n\t\t\t\tif ( nodeDef.skin !== undefined ) {\n\n\t\t\t\t\tmeshDefs[ nodeDef.mesh ].isSkinnedMesh = true;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( nodeDef.camera !== undefined ) {\n\n\t\t\t\tthis._addNodeRef( this.cameraCache, nodeDef.camera );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Counts references to shared node / Object3D resources. These resources\n\t * can be reused, or \"instantiated\", at multiple nodes in the scene\n\t * hierarchy. Mesh, Camera, and Light instances are instantiated and must\n\t * be marked. Non-scenegraph resources (like Materials, Geometries, and\n\t * Textures) can be reused directly and are not marked here.\n\t *\n\t * Example: CesiumMilkTruck sample model reuses \"Wheel\" meshes.\n\t *\n\t * @private\n\t * @param {Object} cache\n\t * @param {Object3D} index\n\t */\n\t_addNodeRef( cache, index ) {\n\n\t\tif ( index === undefined ) return;\n\n\t\tif ( cache.refs[ index ] === undefined ) {\n\n\t\t\tcache.refs[ index ] = cache.uses[ index ] = 0;\n\n\t\t}\n\n\t\tcache.refs[ index ] ++;\n\n\t}\n\n\t/**\n\t * Returns a reference to a shared resource, cloning it if necessary.\n\t *\n\t * @private\n\t * @param {Object} cache\n\t * @param {number} index\n\t * @param {Object} object\n\t * @return {Object}\n\t */\n\t_getNodeRef( cache, index, object ) {\n\n\t\tif ( cache.refs[ index ] <= 1 ) return object;\n\n\t\tconst ref = object.clone();\n\n\t\t// Propagates mappings to the cloned object, prevents mappings on the\n\t\t// original object from being lost.\n\t\tconst updateMappings = ( original, clone ) => {\n\n\t\t\tconst mappings = this.associations.get( original );\n\t\t\tif ( mappings != null ) {\n\n\t\t\t\tthis.associations.set( clone, mappings );\n\n\t\t\t}\n\n\t\t\tfor ( const [ i, child ] of original.children.entries() ) {\n\n\t\t\t\tupdateMappings( child, clone.children[ i ] );\n\n\t\t\t}\n\n\t\t};\n\n\t\tupdateMappings( object, ref );\n\n\t\tref.name += '_instance_' + ( cache.uses[ index ] ++ );\n\n\t\treturn ref;\n\n\t}\n\n\t_invokeOne( func ) {\n\n\t\tconst extensions = Object.values( this.plugins );\n\t\textensions.push( this );\n\n\t\tfor ( let i = 0; i < extensions.length; i ++ ) {\n\n\t\t\tconst result = func( extensions[ i ] );\n\n\t\t\tif ( result ) return result;\n\n\t\t}\n\n\t\treturn null;\n\n\t}\n\n\t_invokeAll( func ) {\n\n\t\tconst extensions = Object.values( this.plugins );\n\t\textensions.unshift( this );\n\n\t\tconst pending = [];\n\n\t\tfor ( let i = 0; i < extensions.length; i ++ ) {\n\n\t\t\tconst result = func( extensions[ i ] );\n\n\t\t\tif ( result ) pending.push( result );\n\n\t\t}\n\n\t\treturn pending;\n\n\t}\n\n\t/**\n\t * Requests the specified dependency asynchronously, with caching.\n\t *\n\t * @private\n\t * @param {string} type\n\t * @param {number} index\n\t * @return {Promise<Object3D|Material|Texture|AnimationClip|ArrayBuffer|Object>}\n\t */\n\tgetDependency( type, index ) {\n\n\t\tconst cacheKey = type + ':' + index;\n\t\tlet dependency = this.cache.get( cacheKey );\n\n\t\tif ( ! dependency ) {\n\n\t\t\tswitch ( type ) {\n\n\t\t\t\tcase 'scene':\n\t\t\t\t\tdependency = this.loadScene( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'node':\n\t\t\t\t\tdependency = this._invokeOne( function ( ext ) {\n\n\t\t\t\t\t\treturn ext.loadNode && ext.loadNode( index );\n\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'mesh':\n\t\t\t\t\tdependency = this._invokeOne( function ( ext ) {\n\n\t\t\t\t\t\treturn ext.loadMesh && ext.loadMesh( index );\n\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'accessor':\n\t\t\t\t\tdependency = this.loadAccessor( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'bufferView':\n\t\t\t\t\tdependency = this._invokeOne( function ( ext ) {\n\n\t\t\t\t\t\treturn ext.loadBufferView && ext.loadBufferView( index );\n\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'buffer':\n\t\t\t\t\tdependency = this.loadBuffer( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'material':\n\t\t\t\t\tdependency = this._invokeOne( function ( ext ) {\n\n\t\t\t\t\t\treturn ext.loadMaterial && ext.loadMaterial( index );\n\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'texture':\n\t\t\t\t\tdependency = this._invokeOne( function ( ext ) {\n\n\t\t\t\t\t\treturn ext.loadTexture && ext.loadTexture( index );\n\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'skin':\n\t\t\t\t\tdependency = this.loadSkin( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'animation':\n\t\t\t\t\tdependency = this._invokeOne( function ( ext ) {\n\n\t\t\t\t\t\treturn ext.loadAnimation && ext.loadAnimation( index );\n\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'camera':\n\t\t\t\t\tdependency = this.loadCamera( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tdependency = this._invokeOne( function ( ext ) {\n\n\t\t\t\t\t\treturn ext != this && ext.getDependency && ext.getDependency( type, index );\n\n\t\t\t\t\t} );\n\n\t\t\t\t\tif ( ! dependency ) {\n\n\t\t\t\t\t\tthrow new Error( 'Unknown type: ' + type );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t\tthis.cache.add( cacheKey, dependency );\n\n\t\t}\n\n\t\treturn dependency;\n\n\t}\n\n\t/**\n\t * Requests all dependencies of the specified type asynchronously, with caching.\n\t *\n\t * @private\n\t * @param {string} type\n\t * @return {Promise<Array<Object>>}\n\t */\n\tgetDependencies( type ) {\n\n\t\tlet dependencies = this.cache.get( type );\n\n\t\tif ( ! dependencies ) {\n\n\t\t\tconst parser = this;\n\t\t\tconst defs = this.json[ type + ( type === 'mesh' ? 'es' : 's' ) ] || [];\n\n\t\t\tdependencies = Promise.all( defs.map( function ( def, index ) {\n\n\t\t\t\treturn parser.getDependency( type, index );\n\n\t\t\t} ) );\n\n\t\t\tthis.cache.add( type, dependencies );\n\n\t\t}\n\n\t\treturn dependencies;\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views\n\t *\n\t * @private\n\t * @param {number} bufferIndex\n\t * @return {Promise<ArrayBuffer>}\n\t */\n\tloadBuffer( bufferIndex ) {\n\n\t\tconst bufferDef = this.json.buffers[ bufferIndex ];\n\t\tconst loader = this.fileLoader;\n\n\t\tif ( bufferDef.type && bufferDef.type !== 'arraybuffer' ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: ' + bufferDef.type + ' buffer type is not supported.' );\n\n\t\t}\n\n\t\t// If present, GLB container is required to be the first buffer.\n\t\tif ( bufferDef.uri === undefined && bufferIndex === 0 ) {\n\n\t\t\treturn Promise.resolve( this.extensions[ EXTENSIONS.KHR_BINARY_GLTF ].body );\n\n\t\t}\n\n\t\tconst options = this.options;\n\n\t\treturn new Promise( function ( resolve, reject ) {\n\n\t\t\tloader.load( LoaderUtils.resolveURL( bufferDef.uri, options.path ), resolve, undefined, function () {\n\n\t\t\t\treject( new Error( 'THREE.GLTFLoader: Failed to load buffer \"' + bufferDef.uri + '\".' ) );\n\n\t\t\t} );\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views\n\t *\n\t * @private\n\t * @param {number} bufferViewIndex\n\t * @return {Promise<ArrayBuffer>}\n\t */\n\tloadBufferView( bufferViewIndex ) {\n\n\t\tconst bufferViewDef = this.json.bufferViews[ bufferViewIndex ];\n\n\t\treturn this.getDependency( 'buffer', bufferViewDef.buffer ).then( function ( buffer ) {\n\n\t\t\tconst byteLength = bufferViewDef.byteLength || 0;\n\t\t\tconst byteOffset = bufferViewDef.byteOffset || 0;\n\t\t\treturn buffer.slice( byteOffset, byteOffset + byteLength );\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#accessors\n\t *\n\t * @private\n\t * @param {number} accessorIndex\n\t * @return {Promise<BufferAttribute|InterleavedBufferAttribute>}\n\t */\n\tloadAccessor( accessorIndex ) {\n\n\t\tconst parser = this;\n\t\tconst json = this.json;\n\n\t\tconst accessorDef = this.json.accessors[ accessorIndex ];\n\n\t\tif ( accessorDef.bufferView === undefined && accessorDef.sparse === undefined ) {\n\n\t\t\tconst itemSize = WEBGL_TYPE_SIZES[ accessorDef.type ];\n\t\t\tconst TypedArray = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];\n\t\t\tconst normalized = accessorDef.normalized === true;\n\n\t\t\tconst array = new TypedArray( accessorDef.count * itemSize );\n\t\t\treturn Promise.resolve( new BufferAttribute( array, itemSize, normalized ) );\n\n\t\t}\n\n\t\tconst pendingBufferViews = [];\n\n\t\tif ( accessorDef.bufferView !== undefined ) {\n\n\t\t\tpendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.bufferView ) );\n\n\t\t} else {\n\n\t\t\tpendingBufferViews.push( null );\n\n\t\t}\n\n\t\tif ( accessorDef.sparse !== undefined ) {\n\n\t\t\tpendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.sparse.indices.bufferView ) );\n\t\t\tpendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.sparse.values.bufferView ) );\n\n\t\t}\n\n\t\treturn Promise.all( pendingBufferViews ).then( function ( bufferViews ) {\n\n\t\t\tconst bufferView = bufferViews[ 0 ];\n\n\t\t\tconst itemSize = WEBGL_TYPE_SIZES[ accessorDef.type ];\n\t\t\tconst TypedArray = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];\n\n\t\t\t// For VEC3: itemSize is 3, elementBytes is 4, itemBytes is 12.\n\t\t\tconst elementBytes = TypedArray.BYTES_PER_ELEMENT;\n\t\t\tconst itemBytes = elementBytes * itemSize;\n\t\t\tconst byteOffset = accessorDef.byteOffset || 0;\n\t\t\tconst byteStride = accessorDef.bufferView !== undefined ? json.bufferViews[ accessorDef.bufferView ].byteStride : undefined;\n\t\t\tconst normalized = accessorDef.normalized === true;\n\t\t\tlet array, bufferAttribute;\n\n\t\t\t// The buffer is not interleaved if the stride is the item size in bytes.\n\t\t\tif ( byteStride && byteStride !== itemBytes ) {\n\n\t\t\t\t// Each \"slice\" of the buffer, as defined by 'count' elements of 'byteStride' bytes, gets its own InterleavedBuffer\n\t\t\t\t// This makes sure that IBA.count reflects accessor.count properly\n\t\t\t\tconst ibSlice = Math.floor( byteOffset / byteStride );\n\t\t\t\tconst ibCacheKey = 'InterleavedBuffer:' + accessorDef.bufferView + ':' + accessorDef.componentType + ':' + ibSlice + ':' + accessorDef.count;\n\t\t\t\tlet ib = parser.cache.get( ibCacheKey );\n\n\t\t\t\tif ( ! ib ) {\n\n\t\t\t\t\tarray = new TypedArray( bufferView, ibSlice * byteStride, accessorDef.count * byteStride / elementBytes );\n\n\t\t\t\t\t// Integer parameters to IB/IBA are in array elements, not bytes.\n\t\t\t\t\tib = new InterleavedBuffer( array, byteStride / elementBytes );\n\n\t\t\t\t\tparser.cache.add( ibCacheKey, ib );\n\n\t\t\t\t}\n\n\t\t\t\tbufferAttribute = new InterleavedBufferAttribute( ib, itemSize, ( byteOffset % byteStride ) / elementBytes, normalized );\n\n\t\t\t} else {\n\n\t\t\t\tif ( bufferView === null ) {\n\n\t\t\t\t\tarray = new TypedArray( accessorDef.count * itemSize );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tarray = new TypedArray( bufferView, byteOffset, accessorDef.count * itemSize );\n\n\t\t\t\t}\n\n\t\t\t\tbufferAttribute = new BufferAttribute( array, itemSize, normalized );\n\n\t\t\t}\n\n\t\t\t// https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#sparse-accessors\n\t\t\tif ( accessorDef.sparse !== undefined ) {\n\n\t\t\t\tconst itemSizeIndices = WEBGL_TYPE_SIZES.SCALAR;\n\t\t\t\tconst TypedArrayIndices = WEBGL_COMPONENT_TYPES[ accessorDef.sparse.indices.componentType ];\n\n\t\t\t\tconst byteOffsetIndices = accessorDef.sparse.indices.byteOffset || 0;\n\t\t\t\tconst byteOffsetValues = accessorDef.sparse.values.byteOffset || 0;\n\n\t\t\t\tconst sparseIndices = new TypedArrayIndices( bufferViews[ 1 ], byteOffsetIndices, accessorDef.sparse.count * itemSizeIndices );\n\t\t\t\tconst sparseValues = new TypedArray( bufferViews[ 2 ], byteOffsetValues, accessorDef.sparse.count * itemSize );\n\n\t\t\t\tif ( bufferView !== null ) {\n\n\t\t\t\t\t// Avoid modifying the original ArrayBuffer, if the bufferView wasn't initialized with zeroes.\n\t\t\t\t\tbufferAttribute = new BufferAttribute( bufferAttribute.array.slice(), bufferAttribute.itemSize, bufferAttribute.normalized );\n\n\t\t\t\t}\n\n\t\t\t\t// Ignore normalized since we copy from sparse\n\t\t\t\tbufferAttribute.normalized = false;\n\n\t\t\t\tfor ( let i = 0, il = sparseIndices.length; i < il; i ++ ) {\n\n\t\t\t\t\tconst index = sparseIndices[ i ];\n\n\t\t\t\t\tbufferAttribute.setX( index, sparseValues[ i * itemSize ] );\n\t\t\t\t\tif ( itemSize >= 2 ) bufferAttribute.setY( index, sparseValues[ i * itemSize + 1 ] );\n\t\t\t\t\tif ( itemSize >= 3 ) bufferAttribute.setZ( index, sparseValues[ i * itemSize + 2 ] );\n\t\t\t\t\tif ( itemSize >= 4 ) bufferAttribute.setW( index, sparseValues[ i * itemSize + 3 ] );\n\t\t\t\t\tif ( itemSize >= 5 ) throw new Error( 'THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.' );\n\n\t\t\t\t}\n\n\t\t\t\tbufferAttribute.normalized = normalized;\n\n\t\t\t}\n\n\t\t\treturn bufferAttribute;\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#textures\n\t *\n\t * @private\n\t * @param {number} textureIndex\n\t * @return {Promise<?Texture>}\n\t */\n\tloadTexture( textureIndex ) {\n\n\t\tconst json = this.json;\n\t\tconst options = this.options;\n\t\tconst textureDef = json.textures[ textureIndex ];\n\t\tconst sourceIndex = textureDef.source;\n\t\tconst sourceDef = json.images[ sourceIndex ];\n\n\t\tlet loader = this.textureLoader;\n\n\t\tif ( sourceDef.uri ) {\n\n\t\t\tconst handler = options.manager.getHandler( sourceDef.uri );\n\t\t\tif ( handler !== null ) loader = handler;\n\n\t\t}\n\n\t\treturn this.loadTextureImage( textureIndex, sourceIndex, loader );\n\n\t}\n\n\tloadTextureImage( textureIndex, sourceIndex, loader ) {\n\n\t\tconst parser = this;\n\t\tconst json = this.json;\n\n\t\tconst textureDef = json.textures[ textureIndex ];\n\t\tconst sourceDef = json.images[ sourceIndex ];\n\n\t\tconst cacheKey = ( sourceDef.uri || sourceDef.bufferView ) + ':' + textureDef.sampler;\n\n\t\tif ( this.textureCache[ cacheKey ] ) {\n\n\t\t\t// See https://github.com/mrdoob/three.js/issues/21559.\n\t\t\treturn this.textureCache[ cacheKey ];\n\n\t\t}\n\n\t\tconst promise = this.loadImageSource( sourceIndex, loader ).then( function ( texture ) {\n\n\t\t\ttexture.flipY = false;\n\n\t\t\ttexture.name = textureDef.name || sourceDef.name || '';\n\n\t\t\tif ( texture.name === '' && typeof sourceDef.uri === 'string' && sourceDef.uri.startsWith( 'data:image/' ) === false ) {\n\n\t\t\t\ttexture.name = sourceDef.uri;\n\n\t\t\t}\n\n\t\t\tconst samplers = json.samplers || {};\n\t\t\tconst sampler = samplers[ textureDef.sampler ] || {};\n\n\t\t\ttexture.magFilter = WEBGL_FILTERS[ sampler.magFilter ] || LinearFilter;\n\t\t\ttexture.minFilter = WEBGL_FILTERS[ sampler.minFilter ] || LinearMipmapLinearFilter;\n\t\t\ttexture.wrapS = WEBGL_WRAPPINGS[ sampler.wrapS ] || RepeatWrapping;\n\t\t\ttexture.wrapT = WEBGL_WRAPPINGS[ sampler.wrapT ] || RepeatWrapping;\n\t\t\ttexture.generateMipmaps = ! texture.isCompressedTexture && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;\n\n\t\t\tparser.associations.set( texture, { textures: textureIndex } );\n\n\t\t\treturn texture;\n\n\t\t} ).catch( function () {\n\n\t\t\treturn null;\n\n\t\t} );\n\n\t\tthis.textureCache[ cacheKey ] = promise;\n\n\t\treturn promise;\n\n\t}\n\n\tloadImageSource( sourceIndex, loader ) {\n\n\t\tconst parser = this;\n\t\tconst json = this.json;\n\t\tconst options = this.options;\n\n\t\tif ( this.sourceCache[ sourceIndex ] !== undefined ) {\n\n\t\t\treturn this.sourceCache[ sourceIndex ].then( ( texture ) => texture.clone() );\n\n\t\t}\n\n\t\tconst sourceDef = json.images[ sourceIndex ];\n\n\t\tconst URL = self.URL || self.webkitURL;\n\n\t\tlet sourceURI = sourceDef.uri || '';\n\t\tlet isObjectURL = false;\n\n\t\tif ( sourceDef.bufferView !== undefined ) {\n\n\t\t\t// Load binary image data from bufferView, if provided.\n\n\t\t\tsourceURI = parser.getDependency( 'bufferView', sourceDef.bufferView ).then( function ( bufferView ) {\n\n\t\t\t\tisObjectURL = true;\n\t\t\t\tconst blob = new Blob( [ bufferView ], { type: sourceDef.mimeType } );\n\t\t\t\tsourceURI = URL.createObjectURL( blob );\n\t\t\t\treturn sourceURI;\n\n\t\t\t} );\n\n\t\t} else if ( sourceDef.uri === undefined ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: Image ' + sourceIndex + ' is missing URI and bufferView' );\n\n\t\t}\n\n\t\tconst promise = Promise.resolve( sourceURI ).then( function ( sourceURI ) {\n\n\t\t\treturn new Promise( function ( resolve, reject ) {\n\n\t\t\t\tlet onLoad = resolve;\n\n\t\t\t\tif ( loader.isImageBitmapLoader === true ) {\n\n\t\t\t\t\tonLoad = function ( imageBitmap ) {\n\n\t\t\t\t\t\tconst texture = new Texture( imageBitmap );\n\t\t\t\t\t\ttexture.needsUpdate = true;\n\n\t\t\t\t\t\tresolve( texture );\n\n\t\t\t\t\t};\n\n\t\t\t\t}\n\n\t\t\t\tloader.load( LoaderUtils.resolveURL( sourceURI, options.path ), onLoad, undefined, reject );\n\n\t\t\t} );\n\n\t\t} ).then( function ( texture ) {\n\n\t\t\t// Clean up resources and configure Texture.\n\n\t\t\tif ( isObjectURL === true ) {\n\n\t\t\t\tURL.revokeObjectURL( sourceURI );\n\n\t\t\t}\n\n\t\t\tassignExtrasToUserData( texture, sourceDef );\n\n\t\t\ttexture.userData.mimeType = sourceDef.mimeType || getImageURIMimeType( sourceDef.uri );\n\n\t\t\treturn texture;\n\n\t\t} ).catch( function ( error ) {\n\n\t\t\tconsole.error( 'THREE.GLTFLoader: Couldn\\'t load texture', sourceURI );\n\t\t\tthrow error;\n\n\t\t} );\n\n\t\tthis.sourceCache[ sourceIndex ] = promise;\n\t\treturn promise;\n\n\t}\n\n\t/**\n\t * Asynchronously assigns a texture to the given material parameters.\n\t *\n\t * @private\n\t * @param {Object} materialParams\n\t * @param {string} mapName\n\t * @param {Object} mapDef\n\t * @param {string} [colorSpace]\n\t * @return {Promise<Texture>}\n\t */\n\tassignTexture( materialParams, mapName, mapDef, colorSpace ) {\n\n\t\tconst parser = this;\n\n\t\treturn this.getDependency( 'texture', mapDef.index ).then( function ( texture ) {\n\n\t\t\tif ( ! texture ) return null;\n\n\t\t\tif ( mapDef.texCoord !== undefined && mapDef.texCoord > 0 ) {\n\n\t\t\t\ttexture = texture.clone();\n\t\t\t\ttexture.channel = mapDef.texCoord;\n\n\t\t\t}\n\n\t\t\tif ( parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] ) {\n\n\t\t\t\tconst transform = mapDef.extensions !== undefined ? mapDef.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] : undefined;\n\n\t\t\t\tif ( transform ) {\n\n\t\t\t\t\tconst gltfReference = parser.associations.get( texture );\n\t\t\t\t\ttexture = parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ].extendTexture( texture, transform );\n\t\t\t\t\tparser.associations.set( texture, gltfReference );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( colorSpace !== undefined ) {\n\n\t\t\t\ttexture.colorSpace = colorSpace;\n\n\t\t\t}\n\n\t\t\tmaterialParams[ mapName ] = texture;\n\n\t\t\treturn texture;\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Assigns final material to a Mesh, Line, or Points instance. The instance\n\t * already has a material (generated from the glTF material options alone)\n\t * but reuse of the same glTF material may require multiple threejs materials\n\t * to accommodate different primitive types, defines, etc. New materials will\n\t * be created if necessary, and reused from a cache.\n\t *\n\t * @private\n\t * @param {Object3D} mesh Mesh, Line, or Points instance.\n\t */\n\tassignFinalMaterial( mesh ) {\n\n\t\tconst geometry = mesh.geometry;\n\t\tlet material = mesh.material;\n\n\t\tconst useDerivativeTangents = geometry.attributes.tangent === undefined;\n\t\tconst useVertexColors = geometry.attributes.color !== undefined;\n\t\tconst useFlatShading = geometry.attributes.normal === undefined;\n\n\t\tif ( mesh.isPoints ) {\n\n\t\t\tconst cacheKey = 'PointsMaterial:' + material.uuid;\n\n\t\t\tlet pointsMaterial = this.cache.get( cacheKey );\n\n\t\t\tif ( ! pointsMaterial ) {\n\n\t\t\t\tpointsMaterial = new PointsMaterial();\n\t\t\t\tMaterial.prototype.copy.call( pointsMaterial, material );\n\t\t\t\tpointsMaterial.color.copy( material.color );\n\t\t\t\tpointsMaterial.map = material.map;\n\t\t\t\tpointsMaterial.sizeAttenuation = false; // glTF spec says points should be 1px\n\n\t\t\t\tthis.cache.add( cacheKey, pointsMaterial );\n\n\t\t\t}\n\n\t\t\tmaterial = pointsMaterial;\n\n\t\t} else if ( mesh.isLine ) {\n\n\t\t\tconst cacheKey = 'LineBasicMaterial:' + material.uuid;\n\n\t\t\tlet lineMaterial = this.cache.get( cacheKey );\n\n\t\t\tif ( ! lineMaterial ) {\n\n\t\t\t\tlineMaterial = new LineBasicMaterial();\n\t\t\t\tMaterial.prototype.copy.call( lineMaterial, material );\n\t\t\t\tlineMaterial.color.copy( material.color );\n\t\t\t\tlineMaterial.map = material.map;\n\n\t\t\t\tthis.cache.add( cacheKey, lineMaterial );\n\n\t\t\t}\n\n\t\t\tmaterial = lineMaterial;\n\n\t\t}\n\n\t\t// Clone the material if it will be modified\n\t\tif ( useDerivativeTangents || useVertexColors || useFlatShading ) {\n\n\t\t\tlet cacheKey = 'ClonedMaterial:' + material.uuid + ':';\n\n\t\t\tif ( useDerivativeTangents ) cacheKey += 'derivative-tangents:';\n\t\t\tif ( useVertexColors ) cacheKey += 'vertex-colors:';\n\t\t\tif ( useFlatShading ) cacheKey += 'flat-shading:';\n\n\t\t\tlet cachedMaterial = this.cache.get( cacheKey );\n\n\t\t\tif ( ! cachedMaterial ) {\n\n\t\t\t\tcachedMaterial = material.clone();\n\n\t\t\t\tif ( useVertexColors ) cachedMaterial.vertexColors = true;\n\t\t\t\tif ( useFlatShading ) cachedMaterial.flatShading = true;\n\n\t\t\t\tif ( useDerivativeTangents ) {\n\n\t\t\t\t\t// https://github.com/mrdoob/three.js/issues/11438#issuecomment-507003995\n\t\t\t\t\tif ( cachedMaterial.normalScale ) cachedMaterial.normalScale.y *= - 1;\n\t\t\t\t\tif ( cachedMaterial.clearcoatNormalScale ) cachedMaterial.clearcoatNormalScale.y *= - 1;\n\n\t\t\t\t}\n\n\t\t\t\tthis.cache.add( cacheKey, cachedMaterial );\n\n\t\t\t\tthis.associations.set( cachedMaterial, this.associations.get( material ) );\n\n\t\t\t}\n\n\t\t\tmaterial = cachedMaterial;\n\n\t\t}\n\n\t\tmesh.material = material;\n\n\t}\n\n\tgetMaterialType( /* materialIndex */ ) {\n\n\t\treturn MeshStandardMaterial;\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#materials\n\t *\n\t * @private\n\t * @param {number} materialIndex\n\t * @return {Promise<Material>}\n\t */\n\tloadMaterial( materialIndex ) {\n\n\t\tconst parser = this;\n\t\tconst json = this.json;\n\t\tconst extensions = this.extensions;\n\t\tconst materialDef = json.materials[ materialIndex ];\n\n\t\tlet materialType;\n\t\tconst materialParams = {};\n\t\tconst materialExtensions = materialDef.extensions || {};\n\n\t\tconst pending = [];\n\n\t\tif ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ] ) {\n\n\t\t\tconst kmuExtension = extensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ];\n\t\t\tmaterialType = kmuExtension.getMaterialType();\n\t\t\tpending.push( kmuExtension.extendParams( materialParams, materialDef, parser ) );\n\n\t\t} else {\n\n\t\t\t// Specification:\n\t\t\t// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#metallic-roughness-material\n\n\t\t\tconst metallicRoughness = materialDef.pbrMetallicRoughness || {};\n\n\t\t\tmaterialParams.color = new Color( 1.0, 1.0, 1.0 );\n\t\t\tmaterialParams.opacity = 1.0;\n\n\t\t\tif ( Array.isArray( metallicRoughness.baseColorFactor ) ) {\n\n\t\t\t\tconst array = metallicRoughness.baseColorFactor;\n\n\t\t\t\tmaterialParams.color.setRGB( array[ 0 ], array[ 1 ], array[ 2 ], LinearSRGBColorSpace );\n\t\t\t\tmaterialParams.opacity = array[ 3 ];\n\n\t\t\t}\n\n\t\t\tif ( metallicRoughness.baseColorTexture !== undefined ) {\n\n\t\t\t\tpending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture, SRGBColorSpace ) );\n\n\t\t\t}\n\n\t\t\tmaterialParams.metalness = metallicRoughness.metallicFactor !== undefined ? metallicRoughness.metallicFactor : 1.0;\n\t\t\tmaterialParams.roughness = metallicRoughness.roughnessFactor !== undefined ? metallicRoughness.roughnessFactor : 1.0;\n\n\t\t\tif ( metallicRoughness.metallicRoughnessTexture !== undefined ) {\n\n\t\t\t\tpending.push( parser.assignTexture( materialParams, 'metalnessMap', metallicRoughness.metallicRoughnessTexture ) );\n\t\t\t\tpending.push( parser.assignTexture( materialParams, 'roughnessMap', metallicRoughness.metallicRoughnessTexture ) );\n\n\t\t\t}\n\n\t\t\tmaterialType = this._invokeOne( function ( ext ) {\n\n\t\t\t\treturn ext.getMaterialType && ext.getMaterialType( materialIndex );\n\n\t\t\t} );\n\n\t\t\tpending.push( Promise.all( this._invokeAll( function ( ext ) {\n\n\t\t\t\treturn ext.extendMaterialParams && ext.extendMaterialParams( materialIndex, materialParams );\n\n\t\t\t} ) ) );\n\n\t\t}\n\n\t\tif ( materialDef.doubleSided === true ) {\n\n\t\t\tmaterialParams.side = DoubleSide;\n\n\t\t}\n\n\t\tconst alphaMode = materialDef.alphaMode || ALPHA_MODES.OPAQUE;\n\n\t\tif ( alphaMode === ALPHA_MODES.BLEND ) {\n\n\t\t\tmaterialParams.transparent = true;\n\n\t\t\t// See: https://github.com/mrdoob/three.js/issues/17706\n\t\t\tmaterialParams.depthWrite = false;\n\n\t\t} else {\n\n\t\t\tmaterialParams.transparent = false;\n\n\t\t\tif ( alphaMode === ALPHA_MODES.MASK ) {\n\n\t\t\t\tmaterialParams.alphaTest = materialDef.alphaCutoff !== undefined ? materialDef.alphaCutoff : 0.5;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( materialDef.normalTexture !== undefined && materialType !== MeshBasicMaterial ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'normalMap', materialDef.normalTexture ) );\n\n\t\t\tmaterialParams.normalScale = new Vector2( 1, 1 );\n\n\t\t\tif ( materialDef.normalTexture.scale !== undefined ) {\n\n\t\t\t\tconst scale = materialDef.normalTexture.scale;\n\n\t\t\t\tmaterialParams.normalScale.set( scale, scale );\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( materialDef.occlusionTexture !== undefined && materialType !== MeshBasicMaterial ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'aoMap', materialDef.occlusionTexture ) );\n\n\t\t\tif ( materialDef.occlusionTexture.strength !== undefined ) {\n\n\t\t\t\tmaterialParams.aoMapIntensity = materialDef.occlusionTexture.strength;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( materialDef.emissiveFactor !== undefined && materialType !== MeshBasicMaterial ) {\n\n\t\t\tconst emissiveFactor = materialDef.emissiveFactor;\n\t\t\tmaterialParams.emissive = new Color().setRGB( emissiveFactor[ 0 ], emissiveFactor[ 1 ], emissiveFactor[ 2 ], LinearSRGBColorSpace );\n\n\t\t}\n\n\t\tif ( materialDef.emissiveTexture !== undefined && materialType !== MeshBasicMaterial ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'emissiveMap', materialDef.emissiveTexture, SRGBColorSpace ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending ).then( function () {\n\n\t\t\tconst material = new materialType( materialParams );\n\n\t\t\tif ( materialDef.name ) material.name = materialDef.name;\n\n\t\t\tassignExtrasToUserData( material, materialDef );\n\n\t\t\tparser.associations.set( material, { materials: materialIndex } );\n\n\t\t\tif ( materialDef.extensions ) addUnknownExtensionsToUserData( extensions, material, materialDef );\n\n\t\t\treturn material;\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * When Object3D instances are targeted by animation, they need unique names.\n\t *\n\t * @private\n\t * @param {string} originalName\n\t * @return {string}\n\t */\n\tcreateUniqueName( originalName ) {\n\n\t\tconst sanitizedName = PropertyBinding.sanitizeNodeName( originalName || '' );\n\n\t\tif ( sanitizedName in this.nodeNamesUsed ) {\n\n\t\t\treturn sanitizedName + '_' + ( ++ this.nodeNamesUsed[ sanitizedName ] );\n\n\t\t} else {\n\n\t\t\tthis.nodeNamesUsed[ sanitizedName ] = 0;\n\n\t\t\treturn sanitizedName;\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#geometry\n\t *\n\t * Creates BufferGeometries from primitives.\n\t *\n\t * @private\n\t * @param {Array<GLTF.Primitive>} primitives\n\t * @return {Promise<Array<BufferGeometry>>}\n\t */\n\tloadGeometries( primitives ) {\n\n\t\tconst parser = this;\n\t\tconst extensions = this.extensions;\n\t\tconst cache = this.primitiveCache;\n\n\t\tfunction createDracoPrimitive( primitive ) {\n\n\t\t\treturn extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ]\n\t\t\t\t.decodePrimitive( primitive, parser )\n\t\t\t\t.then( function ( geometry ) {\n\n\t\t\t\t\treturn addPrimitiveAttributes( geometry, primitive, parser );\n\n\t\t\t\t} );\n\n\t\t}\n\n\t\tconst pending = [];\n\n\t\tfor ( let i = 0, il = primitives.length; i < il; i ++ ) {\n\n\t\t\tconst primitive = primitives[ i ];\n\t\t\tconst cacheKey = createPrimitiveKey( primitive );\n\n\t\t\t// See if we've already created this geometry\n\t\t\tconst cached = cache[ cacheKey ];\n\n\t\t\tif ( cached ) {\n\n\t\t\t\t// Use the cached geometry if it exists\n\t\t\t\tpending.push( cached.promise );\n\n\t\t\t} else {\n\n\t\t\t\tlet geometryPromise;\n\n\t\t\t\tif ( primitive.extensions && primitive.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ] ) {\n\n\t\t\t\t\t// Use DRACO geometry if available\n\t\t\t\t\tgeometryPromise = createDracoPrimitive( primitive );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// Otherwise create a new geometry\n\t\t\t\t\tgeometryPromise = addPrimitiveAttributes( new BufferGeometry(), primitive, parser );\n\n\t\t\t\t}\n\n\t\t\t\t// Cache this geometry\n\t\t\t\tcache[ cacheKey ] = { primitive: primitive, promise: geometryPromise };\n\n\t\t\t\tpending.push( geometryPromise );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#meshes\n\t *\n\t * @private\n\t * @param {number} meshIndex\n\t * @return {Promise<Group|Mesh|SkinnedMesh|Line|Points>}\n\t */\n\tloadMesh( meshIndex ) {\n\n\t\tconst parser = this;\n\t\tconst json = this.json;\n\t\tconst extensions = this.extensions;\n\n\t\tconst meshDef = json.meshes[ meshIndex ];\n\t\tconst primitives = meshDef.primitives;\n\n\t\tconst pending = [];\n\n\t\tfor ( let i = 0, il = primitives.length; i < il; i ++ ) {\n\n\t\t\tconst material = primitives[ i ].material === undefined\n\t\t\t\t? createDefaultMaterial( this.cache )\n\t\t\t\t: this.getDependency( 'material', primitives[ i ].material );\n\n\t\t\tpending.push( material );\n\n\t\t}\n\n\t\tpending.push( parser.loadGeometries( primitives ) );\n\n\t\treturn Promise.all( pending ).then( function ( results ) {\n\n\t\t\tconst materials = results.slice( 0, results.length - 1 );\n\t\t\tconst geometries = results[ results.length - 1 ];\n\n\t\t\tconst meshes = [];\n\n\t\t\tfor ( let i = 0, il = geometries.length; i < il; i ++ ) {\n\n\t\t\t\tconst geometry = geometries[ i ];\n\t\t\t\tconst primitive = primitives[ i ];\n\n\t\t\t\t// 1. create Mesh\n\n\t\t\t\tlet mesh;\n\n\t\t\t\tconst material = materials[ i ];\n\n\t\t\t\tif ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES ||\n\t\t\t\t\t\tprimitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ||\n\t\t\t\t\t\tprimitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ||\n\t\t\t\t\t\tprimitive.mode === undefined ) {\n\n\t\t\t\t\t// .isSkinnedMesh isn't in glTF spec. See ._markDefs()\n\t\t\t\t\tmesh = meshDef.isSkinnedMesh === true\n\t\t\t\t\t\t? new SkinnedMesh( geometry, material )\n\t\t\t\t\t\t: new Mesh( geometry, material );\n\n\t\t\t\t\tif ( mesh.isSkinnedMesh === true ) {\n\n\t\t\t\t\t\t// normalize skin weights to fix malformed assets (see #15319)\n\t\t\t\t\t\tmesh.normalizeSkinWeights();\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ) {\n\n\t\t\t\t\t\tmesh.geometry = toTrianglesDrawMode( mesh.geometry, TriangleStripDrawMode );\n\n\t\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ) {\n\n\t\t\t\t\t\tmesh.geometry = toTrianglesDrawMode( mesh.geometry, TriangleFanDrawMode );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {\n\n\t\t\t\t\tmesh = new LineSegments( geometry, material );\n\n\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_STRIP ) {\n\n\t\t\t\t\tmesh = new Line( geometry, material );\n\n\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_LOOP ) {\n\n\t\t\t\t\tmesh = new LineLoop( geometry, material );\n\n\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.POINTS ) {\n\n\t\t\t\t\tmesh = new Points( geometry, material );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthrow new Error( 'THREE.GLTFLoader: Primitive mode unsupported: ' + primitive.mode );\n\n\t\t\t\t}\n\n\t\t\t\tif ( Object.keys( mesh.geometry.morphAttributes ).length > 0 ) {\n\n\t\t\t\t\tupdateMorphTargets( mesh, meshDef );\n\n\t\t\t\t}\n\n\t\t\t\tmesh.name = parser.createUniqueName( meshDef.name || ( 'mesh_' + meshIndex ) );\n\n\t\t\t\tassignExtrasToUserData( mesh, meshDef );\n\n\t\t\t\tif ( primitive.extensions ) addUnknownExtensionsToUserData( extensions, mesh, primitive );\n\n\t\t\t\tparser.assignFinalMaterial( mesh );\n\n\t\t\t\tmeshes.push( mesh );\n\n\t\t\t}\n\n\t\t\tfor ( let i = 0, il = meshes.length; i < il; i ++ ) {\n\n\t\t\t\tparser.associations.set( meshes[ i ], {\n\t\t\t\t\tmeshes: meshIndex,\n\t\t\t\t\tprimitives: i\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\tif ( meshes.length === 1 ) {\n\n\t\t\t\tif ( meshDef.extensions ) addUnknownExtensionsToUserData( extensions, meshes[ 0 ], meshDef );\n\n\t\t\t\treturn meshes[ 0 ];\n\n\t\t\t}\n\n\t\t\tconst group = new Group();\n\n\t\t\tif ( meshDef.extensions ) addUnknownExtensionsToUserData( extensions, group, meshDef );\n\n\t\t\tparser.associations.set( group, { meshes: meshIndex } );\n\n\t\t\tfor ( let i = 0, il = meshes.length; i < il; i ++ ) {\n\n\t\t\t\tgroup.add( meshes[ i ] );\n\n\t\t\t}\n\n\t\t\treturn group;\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#cameras\n\t *\n\t * @private\n\t * @param {number} cameraIndex\n\t * @return {Promise<Camera>|undefined}\n\t */\n\tloadCamera( cameraIndex ) {\n\n\t\tlet camera;\n\t\tconst cameraDef = this.json.cameras[ cameraIndex ];\n\t\tconst params = cameraDef[ cameraDef.type ];\n\n\t\tif ( ! params ) {\n\n\t\t\tconsole.warn( 'THREE.GLTFLoader: Missing camera parameters.' );\n\t\t\treturn;\n\n\t\t}\n\n\t\tif ( cameraDef.type === 'perspective' ) {\n\n\t\t\tcamera = new PerspectiveCamera( MathUtils.radToDeg( params.yfov ), params.aspectRatio || 1, params.znear || 1, params.zfar || 2e6 );\n\n\t\t} else if ( cameraDef.type === 'orthographic' ) {\n\n\t\t\tcamera = new OrthographicCamera( - params.xmag, params.xmag, params.ymag, - params.ymag, params.znear, params.zfar );\n\n\t\t}\n\n\t\tif ( cameraDef.name ) camera.name = this.createUniqueName( cameraDef.name );\n\n\t\tassignExtrasToUserData( camera, cameraDef );\n\n\t\treturn Promise.resolve( camera );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins\n\t *\n\t * @private\n\t * @param {number} skinIndex\n\t * @return {Promise<Skeleton>}\n\t */\n\tloadSkin( skinIndex ) {\n\n\t\tconst skinDef = this.json.skins[ skinIndex ];\n\n\t\tconst pending = [];\n\n\t\tfor ( let i = 0, il = skinDef.joints.length; i < il; i ++ ) {\n\n\t\t\tpending.push( this._loadNodeShallow( skinDef.joints[ i ] ) );\n\n\t\t}\n\n\t\tif ( skinDef.inverseBindMatrices !== undefined ) {\n\n\t\t\tpending.push( this.getDependency( 'accessor', skinDef.inverseBindMatrices ) );\n\n\t\t} else {\n\n\t\t\tpending.push( null );\n\n\t\t}\n\n\t\treturn Promise.all( pending ).then( function ( results ) {\n\n\t\t\tconst inverseBindMatrices = results.pop();\n\t\t\tconst jointNodes = results;\n\n\t\t\t// Note that bones (joint nodes) may or may not be in the\n\t\t\t// scene graph at this time.\n\n\t\t\tconst bones = [];\n\t\t\tconst boneInverses = [];\n\n\t\t\tfor ( let i = 0, il = jointNodes.length; i < il; i ++ ) {\n\n\t\t\t\tconst jointNode = jointNodes[ i ];\n\n\t\t\t\tif ( jointNode ) {\n\n\t\t\t\t\tbones.push( jointNode );\n\n\t\t\t\t\tconst mat = new Matrix4();\n\n\t\t\t\t\tif ( inverseBindMatrices !== null ) {\n\n\t\t\t\t\t\tmat.fromArray( inverseBindMatrices.array, i * 16 );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tboneInverses.push( mat );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.warn( 'THREE.GLTFLoader: Joint \"%s\" could not be found.', skinDef.joints[ i ] );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn new Skeleton( bones, boneInverses );\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#animations\n\t *\n\t * @private\n\t * @param {number} animationIndex\n\t * @return {Promise<AnimationClip>}\n\t */\n\tloadAnimation( animationIndex ) {\n\n\t\tconst json = this.json;\n\t\tconst parser = this;\n\n\t\tconst animationDef = json.animations[ animationIndex ];\n\t\tconst animationName = animationDef.name ? animationDef.name : 'animation_' + animationIndex;\n\n\t\tconst pendingNodes = [];\n\t\tconst pendingInputAccessors = [];\n\t\tconst pendingOutputAccessors = [];\n\t\tconst pendingSamplers = [];\n\t\tconst pendingTargets = [];\n\n\t\tfor ( let i = 0, il = animationDef.channels.length; i < il; i ++ ) {\n\n\t\t\tconst channel = animationDef.channels[ i ];\n\t\t\tconst sampler = animationDef.samplers[ channel.sampler ];\n\t\t\tconst target = channel.target;\n\t\t\tconst name = target.node;\n\t\t\tconst input = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.input ] : sampler.input;\n\t\t\tconst output = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.output ] : sampler.output;\n\n\t\t\tif ( target.node === undefined ) continue;\n\n\t\t\tpendingNodes.push( this.getDependency( 'node', name ) );\n\t\t\tpendingInputAccessors.push( this.getDependency( 'accessor', input ) );\n\t\t\tpendingOutputAccessors.push( this.getDependency( 'accessor', output ) );\n\t\t\tpendingSamplers.push( sampler );\n\t\t\tpendingTargets.push( target );\n\n\t\t}\n\n\t\treturn Promise.all( [\n\n\t\t\tPromise.all( pendingNodes ),\n\t\t\tPromise.all( pendingInputAccessors ),\n\t\t\tPromise.all( pendingOutputAccessors ),\n\t\t\tPromise.all( pendingSamplers ),\n\t\t\tPromise.all( pendingTargets )\n\n\t\t] ).then( function ( dependencies ) {\n\n\t\t\tconst nodes = dependencies[ 0 ];\n\t\t\tconst inputAccessors = dependencies[ 1 ];\n\t\t\tconst outputAccessors = dependencies[ 2 ];\n\t\t\tconst samplers = dependencies[ 3 ];\n\t\t\tconst targets = dependencies[ 4 ];\n\n\t\t\tconst tracks = [];\n\n\t\t\tfor ( let i = 0, il = nodes.length; i < il; i ++ ) {\n\n\t\t\t\tconst node = nodes[ i ];\n\t\t\t\tconst inputAccessor = inputAccessors[ i ];\n\t\t\t\tconst outputAccessor = outputAccessors[ i ];\n\t\t\t\tconst sampler = samplers[ i ];\n\t\t\t\tconst target = targets[ i ];\n\n\t\t\t\tif ( node === undefined ) continue;\n\n\t\t\t\tif ( node.updateMatrix ) {\n\n\t\t\t\t\tnode.updateMatrix();\n\n\t\t\t\t}\n\n\t\t\t\tconst createdTracks = parser._createAnimationTracks( node, inputAccessor, outputAccessor, sampler, target );\n\n\t\t\t\tif ( createdTracks ) {\n\n\t\t\t\t\tfor ( let k = 0; k < createdTracks.length; k ++ ) {\n\n\t\t\t\t\t\ttracks.push( createdTracks[ k ] );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tconst animation = new AnimationClip( animationName, undefined, tracks );\n\n\t\t\tassignExtrasToUserData( animation, animationDef );\n\n\t\t\treturn animation;\n\n\t\t} );\n\n\t}\n\n\tcreateNodeMesh( nodeIndex ) {\n\n\t\tconst json = this.json;\n\t\tconst parser = this;\n\t\tconst nodeDef = json.nodes[ nodeIndex ];\n\n\t\tif ( nodeDef.mesh === undefined ) return null;\n\n\t\treturn parser.getDependency( 'mesh', nodeDef.mesh ).then( function ( mesh ) {\n\n\t\t\tconst node = parser._getNodeRef( parser.meshCache, nodeDef.mesh, mesh );\n\n\t\t\t// if weights are provided on the node, override weights on the mesh.\n\t\t\tif ( nodeDef.weights !== undefined ) {\n\n\t\t\t\tnode.traverse( function ( o ) {\n\n\t\t\t\t\tif ( ! o.isMesh ) return;\n\n\t\t\t\t\tfor ( let i = 0, il = nodeDef.weights.length; i < il; i ++ ) {\n\n\t\t\t\t\t\to.morphTargetInfluences[ i ] = nodeDef.weights[ i ];\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\treturn node;\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodes-and-hierarchy\n\t *\n\t * @private\n\t * @param {number} nodeIndex\n\t * @return {Promise<Object3D>}\n\t */\n\tloadNode( nodeIndex ) {\n\n\t\tconst json = this.json;\n\t\tconst parser = this;\n\n\t\tconst nodeDef = json.nodes[ nodeIndex ];\n\n\t\tconst nodePending = parser._loadNodeShallow( nodeIndex );\n\n\t\tconst childPending = [];\n\t\tconst childrenDef = nodeDef.children || [];\n\n\t\tfor ( let i = 0, il = childrenDef.length; i < il; i ++ ) {\n\n\t\t\tchildPending.push( parser.getDependency( 'node', childrenDef[ i ] ) );\n\n\t\t}\n\n\t\tconst skeletonPending = nodeDef.skin === undefined\n\t\t\t? Promise.resolve( null )\n\t\t\t: parser.getDependency( 'skin', nodeDef.skin );\n\n\t\treturn Promise.all( [\n\t\t\tnodePending,\n\t\t\tPromise.all( childPending ),\n\t\t\tskeletonPending\n\t\t] ).then( function ( results ) {\n\n\t\t\tconst node = results[ 0 ];\n\t\t\tconst children = results[ 1 ];\n\t\t\tconst skeleton = results[ 2 ];\n\n\t\t\tif ( skeleton !== null ) {\n\n\t\t\t\t// This full traverse should be fine because\n\t\t\t\t// child glTF nodes have not been added to this node yet.\n\t\t\t\tnode.traverse( function ( mesh ) {\n\n\t\t\t\t\tif ( ! mesh.isSkinnedMesh ) return;\n\n\t\t\t\t\tmesh.bind( skeleton, _identityMatrix );\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\tfor ( let i = 0, il = children.length; i < il; i ++ ) {\n\n\t\t\t\tnode.add( children[ i ] );\n\n\t\t\t}\n\n\t\t\t// Reconstruct pivot from container pattern created by GLTFExporter\n\t\t\t// The container has position+pivot, rotation, scale; child has -pivot offset and mesh\n\t\t\tif ( node.userData.pivot !== undefined && children.length > 0 ) {\n\n\t\t\t\tconst pivot = node.userData.pivot;\n\t\t\t\tconst pivotChild = children[ 0 ];\n\n\t\t\t\t// Set pivot on container and adjust transforms\n\t\t\t\tnode.pivot = new Vector3().fromArray( pivot );\n\n\t\t\t\t// Adjust container position: stored as position + pivot, so subtract pivot\n\t\t\t\tnode.position.x -= pivot[ 0 ];\n\t\t\t\tnode.position.y -= pivot[ 1 ];\n\t\t\t\tnode.position.z -= pivot[ 2 ];\n\n\t\t\t\t// Remove the child's -pivot offset since pivot now handles it\n\t\t\t\tpivotChild.position.set( 0, 0, 0 );\n\n\t\t\t\tdelete node.userData.pivot;\n\n\t\t\t}\n\n\t\t\treturn node;\n\n\t\t} );\n\n\t}\n\n\t// ._loadNodeShallow() parses a single node.\n\t// skin and child nodes are created and added in .loadNode() (no '_' prefix).\n\t_loadNodeShallow( nodeIndex ) {\n\n\t\tconst json = this.json;\n\t\tconst extensions = this.extensions;\n\t\tconst parser = this;\n\n\t\t// This method is called from .loadNode() and .loadSkin().\n\t\t// Cache a node to avoid duplication.\n\n\t\tif ( this.nodeCache[ nodeIndex ] !== undefined ) {\n\n\t\t\treturn this.nodeCache[ nodeIndex ];\n\n\t\t}\n\n\t\tconst nodeDef = json.nodes[ nodeIndex ];\n\n\t\t// reserve node's name before its dependencies, so the root has the intended name.\n\t\tconst nodeName = nodeDef.name ? parser.createUniqueName( nodeDef.name ) : '';\n\n\t\tconst pending = [];\n\n\t\tconst meshPromise = parser._invokeOne( function ( ext ) {\n\n\t\t\treturn ext.createNodeMesh && ext.createNodeMesh( nodeIndex );\n\n\t\t} );\n\n\t\tif ( meshPromise ) {\n\n\t\t\tpending.push( meshPromise );\n\n\t\t}\n\n\t\tif ( nodeDef.camera !== undefined ) {\n\n\t\t\tpending.push( parser.getDependency( 'camera', nodeDef.camera ).then( function ( camera ) {\n\n\t\t\t\treturn parser._getNodeRef( parser.cameraCache, nodeDef.camera, camera );\n\n\t\t\t} ) );\n\n\t\t}\n\n\t\tparser._invokeAll( function ( ext ) {\n\n\t\t\treturn ext.createNodeAttachment && ext.createNodeAttachment( nodeIndex );\n\n\t\t} ).forEach( function ( promise ) {\n\n\t\t\tpending.push( promise );\n\n\t\t} );\n\n\t\tthis.nodeCache[ nodeIndex ] = Promise.all( pending ).then( function ( objects ) {\n\n\t\t\tlet node;\n\n\t\t\t// .isBone isn't in glTF spec. See ._markDefs\n\t\t\tif ( nodeDef.isBone === true ) {\n\n\t\t\t\tnode = new Bone();\n\n\t\t\t} else if ( objects.length > 1 ) {\n\n\t\t\t\tnode = new Group();\n\n\t\t\t} else if ( objects.length === 1 ) {\n\n\t\t\t\tnode = objects[ 0 ];\n\n\t\t\t} else {\n\n\t\t\t\tnode = new Object3D();\n\n\t\t\t}\n\n\t\t\tif ( node !== objects[ 0 ] ) {\n\n\t\t\t\tfor ( let i = 0, il = objects.length; i < il; i ++ ) {\n\n\t\t\t\t\tnode.add( objects[ i ] );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( nodeDef.name ) {\n\n\t\t\t\tnode.userData.name = nodeDef.name;\n\t\t\t\tnode.name = nodeName;\n\n\t\t\t}\n\n\t\t\tassignExtrasToUserData( node, nodeDef );\n\n\t\t\tif ( nodeDef.extensions ) addUnknownExtensionsToUserData( extensions, node, nodeDef );\n\n\t\t\tif ( nodeDef.matrix !== undefined ) {\n\n\t\t\t\tconst matrix = new Matrix4();\n\t\t\t\tmatrix.fromArray( nodeDef.matrix );\n\t\t\t\tnode.applyMatrix4( matrix );\n\n\t\t\t} else {\n\n\t\t\t\tif ( nodeDef.translation !== undefined ) {\n\n\t\t\t\t\tnode.position.fromArray( nodeDef.translation );\n\n\t\t\t\t}\n\n\t\t\t\tif ( nodeDef.rotation !== undefined ) {\n\n\t\t\t\t\tnode.quaternion.fromArray( nodeDef.rotation );\n\n\t\t\t\t}\n\n\t\t\t\tif ( nodeDef.scale !== undefined ) {\n\n\t\t\t\t\tnode.scale.fromArray( nodeDef.scale );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( ! parser.associations.has( node ) ) {\n\n\t\t\t\tparser.associations.set( node, {} );\n\n\t\t\t} else if ( nodeDef.mesh !== undefined && parser.meshCache.refs[ nodeDef.mesh ] > 1 ) {\n\n\t\t\t\tconst mapping = parser.associations.get( node );\n\t\t\t\tparser.associations.set( node, { ...mapping } );\n\n\t\t\t}\n\n\t\t\tparser.associations.get( node ).nodes = nodeIndex;\n\n\t\t\treturn node;\n\n\t\t} );\n\n\t\treturn this.nodeCache[ nodeIndex ];\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#scenes\n\t *\n\t * @private\n\t * @param {number} sceneIndex\n\t * @return {Promise<Group>}\n\t */\n\tloadScene( sceneIndex ) {\n\n\t\tconst extensions = this.extensions;\n\t\tconst sceneDef = this.json.scenes[ sceneIndex ];\n\t\tconst parser = this;\n\n\t\t// Loader returns Group, not Scene.\n\t\t// See: https://github.com/mrdoob/three.js/issues/18342#issuecomment-578981172\n\t\tconst scene = new Group();\n\t\tif ( sceneDef.name ) scene.name = parser.createUniqueName( sceneDef.name );\n\n\t\tassignExtrasToUserData( scene, sceneDef );\n\n\t\tif ( sceneDef.extensions ) addUnknownExtensionsToUserData( extensions, scene, sceneDef );\n\n\t\tconst nodeIds = sceneDef.nodes || [];\n\n\t\tconst pending = [];\n\n\t\tfor ( let i = 0, il = nodeIds.length; i < il; i ++ ) {\n\n\t\t\tpending.push( parser.getDependency( 'node', nodeIds[ i ] ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending ).then( function ( nodes ) {\n\n\t\t\tfor ( let i = 0, il = nodes.length; i < il; i ++ ) {\n\n\t\t\t\tconst node = nodes[ i ];\n\n\t\t\t\t// If the node already has a parent, it means it's being reused across multiple scenes.\n\t\t\t\t// Clone it to avoid the second scene's add() removing it from the first scene.\n\t\t\t\t// See: https://github.com/mrdoob/three.js/issues/27993\n\t\t\t\tif ( node.parent !== null ) {\n\n\t\t\t\t\tscene.add( clone( node ) );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tscene.add( node );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// Removes dangling associations, associations that reference a node that\n\t\t\t// didn't make it into the scene.\n\t\t\tconst reduceAssociations = ( node ) => {\n\n\t\t\t\tconst reducedAssociations = new Map();\n\n\t\t\t\tfor ( const [ key, value ] of parser.associations ) {\n\n\t\t\t\t\tif ( key instanceof Material || key instanceof Texture ) {\n\n\t\t\t\t\t\treducedAssociations.set( key, value );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tnode.traverse( ( node ) => {\n\n\t\t\t\t\tconst mappings = parser.associations.get( node );\n\n\t\t\t\t\tif ( mappings != null ) {\n\n\t\t\t\t\t\treducedAssociations.set( node, mappings );\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t\treturn reducedAssociations;\n\n\t\t\t};\n\n\t\t\tparser.associations = reduceAssociations( scene );\n\n\t\t\treturn scene;\n\n\t\t} );\n\n\t}\n\n\t_createAnimationTracks( node, inputAccessor, outputAccessor, sampler, target ) {\n\n\t\tconst tracks = [];\n\n\t\tconst targetName = node.name ? node.name : node.uuid;\n\t\tconst targetNames = [];\n\n\t\tfunction collectMorphTargets( object ) {\n\n\t\t\tif ( object.morphTargetInfluences ) {\n\n\t\t\t\ttargetNames.push( object.name ? object.name : object.uuid );\n\n\t\t\t}\n\n\t\t}\n\n\n\t\tif ( PATH_PROPERTIES[ target.path ] === PATH_PROPERTIES.weights ) {\n\n\t\t\tcollectMorphTargets( node );\n\n\t\t\t// for multi-primitive meshes, the node is a Group containing the sub-meshes\n\n\t\t\tif ( node.isGroup ) {\n\n\t\t\t\tnode.children.forEach( collectMorphTargets );\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\ttargetNames.push( targetName );\n\n\t\t}\n\n\t\tlet TypedKeyframeTrack;\n\n\t\tswitch ( PATH_PROPERTIES[ target.path ] ) {\n\n\t\t\tcase PATH_PROPERTIES.weights:\n\n\t\t\t\tTypedKeyframeTrack = NumberKeyframeTrack;\n\t\t\t\tbreak;\n\n\t\t\tcase PATH_PROPERTIES.rotation:\n\n\t\t\t\tTypedKeyframeTrack = QuaternionKeyframeTrack;\n\t\t\t\tbreak;\n\n\t\t\tcase PATH_PROPERTIES.translation:\n\t\t\tcase PATH_PROPERTIES.scale:\n\n\t\t\t\tTypedKeyframeTrack = VectorKeyframeTrack;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\n\t\t\t\tswitch ( outputAccessor.itemSize ) {\n\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\tTypedKeyframeTrack = NumberKeyframeTrack;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2:\n\t\t\t\t\tcase 3:\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tTypedKeyframeTrack = VectorKeyframeTrack;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\tconst interpolation = sampler.interpolation !== undefined ? INTERPOLATION[ sampler.interpolation ] : InterpolateLinear;\n\n\n\t\tconst outputArray = this._getArrayFromAccessor( outputAccessor );\n\n\t\tfor ( let j = 0, jl = targetNames.length; j < jl; j ++ ) {\n\n\t\t\tconst track = new TypedKeyframeTrack(\n\t\t\t\ttargetNames[ j ] + '.' + PATH_PROPERTIES[ target.path ],\n\t\t\t\tinputAccessor.array,\n\t\t\t\toutputArray,\n\t\t\t\tinterpolation\n\t\t\t);\n\n\t\t\t// Override interpolation with custom factory method.\n\t\t\tif ( sampler.interpolation === 'CUBICSPLINE' ) {\n\n\t\t\t\tthis._createCubicSplineTrackInterpolant( track );\n\n\t\t\t}\n\n\t\t\ttracks.push( track );\n\n\t\t}\n\n\t\treturn tracks;\n\n\t}\n\n\t_getArrayFromAccessor( accessor ) {\n\n\t\tlet outputArray = accessor.array;\n\n\t\tif ( accessor.normalized ) {\n\n\t\t\tconst scale = getNormalizedComponentScale( outputArray.constructor );\n\t\t\tconst scaled = new Float32Array( outputArray.length );\n\n\t\t\tfor ( let j = 0, jl = outputArray.length; j < jl; j ++ ) {\n\n\t\t\t\tscaled[ j ] = outputArray[ j ] * scale;\n\n\t\t\t}\n\n\t\t\toutputArray = scaled;\n\n\t\t}\n\n\t\treturn outputArray;\n\n\t}\n\n\t_createCubicSplineTrackInterpolant( track ) {\n\n\t\ttrack.createInterpolant = function InterpolantFactoryMethodGLTFCubicSpline( result ) {\n\n\t\t\t// A CUBICSPLINE keyframe in glTF has three output values for each input value,\n\t\t\t// representing inTangent, splineVertex, and outTangent. As a result, track.getValueSize()\n\t\t\t// must be divided by three to get the interpolant's sampleSize argument.\n\n\t\t\tconst interpolantType = ( this instanceof QuaternionKeyframeTrack ) ? GLTFCubicSplineQuaternionInterpolant : GLTFCubicSplineInterpolant;\n\n\t\t\treturn new interpolantType( this.times, this.values, this.getValueSize() / 3, result );\n\n\t\t};\n\n\t\t// Mark as CUBICSPLINE. `track.getInterpolation()` doesn't support custom interpolants.\n\t\ttrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline = true;\n\n\t}\n\n}\n\n/**\n *\n * @private\n * @param {BufferGeometry} geometry\n * @param {GLTF.Primitive} primitiveDef\n * @param {GLTFParser} parser\n */\nfunction computeBounds( geometry, primitiveDef, parser ) {\n\n\tconst attributes = primitiveDef.attributes;\n\n\tconst box = new Box3();\n\n\tif ( attributes.POSITION !== undefined ) {\n\n\t\tconst accessor = parser.json.accessors[ attributes.POSITION ];\n\n\t\tconst min = accessor.min;\n\t\tconst max = accessor.max;\n\n\t\t// glTF requires 'min' and 'max', but VRM (which extends glTF) currently ignores that requirement.\n\n\t\tif ( min !== undefined && max !== undefined ) {\n\n\t\t\tbox.set(\n\t\t\t\tnew Vector3( min[ 0 ], min[ 1 ], min[ 2 ] ),\n\t\t\t\tnew Vector3( max[ 0 ], max[ 1 ], max[ 2 ] )\n\t\t\t);\n\n\t\t\tif ( accessor.normalized ) {\n\n\t\t\t\tconst boxScale = getNormalizedComponentScale( WEBGL_COMPONENT_TYPES[ accessor.componentType ] );\n\t\t\t\tbox.min.multiplyScalar( boxScale );\n\t\t\t\tbox.max.multiplyScalar( boxScale );\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tconsole.warn( 'THREE.GLTFLoader: Missing min/max properties for accessor POSITION.' );\n\n\t\t\treturn;\n\n\t\t}\n\n\t} else {\n\n\t\treturn;\n\n\t}\n\n\tconst targets = primitiveDef.targets;\n\n\tif ( targets !== undefined ) {\n\n\t\tconst maxDisplacement = new Vector3();\n\t\tconst vector = new Vector3();\n\n\t\tfor ( let i = 0, il = targets.length; i < il; i ++ ) {\n\n\t\t\tconst target = targets[ i ];\n\n\t\t\tif ( target.POSITION !== undefined ) {\n\n\t\t\t\tconst accessor = parser.json.accessors[ target.POSITION ];\n\t\t\t\tconst min = accessor.min;\n\t\t\t\tconst max = accessor.max;\n\n\t\t\t\t// glTF requires 'min' and 'max', but VRM (which extends glTF) currently ignores that requirement.\n\n\t\t\t\tif ( min !== undefined && max !== undefined ) {\n\n\t\t\t\t\t// we need to get max of absolute components because target weight is [-1,1]\n\t\t\t\t\tvector.setX( Math.max( Math.abs( min[ 0 ] ), Math.abs( max[ 0 ] ) ) );\n\t\t\t\t\tvector.setY( Math.max( Math.abs( min[ 1 ] ), Math.abs( max[ 1 ] ) ) );\n\t\t\t\t\tvector.setZ( Math.max( Math.abs( min[ 2 ] ), Math.abs( max[ 2 ] ) ) );\n\n\n\t\t\t\t\tif ( accessor.normalized ) {\n\n\t\t\t\t\t\tconst boxScale = getNormalizedComponentScale( WEBGL_COMPONENT_TYPES[ accessor.componentType ] );\n\t\t\t\t\t\tvector.multiplyScalar( boxScale );\n\n\t\t\t\t\t}\n\n\t\t\t\t\t// Note: this assumes that the sum of all weights is at most 1. This isn't quite correct - it's more conservative\n\t\t\t\t\t// to assume that each target can have a max weight of 1. However, for some use cases - notably, when morph targets\n\t\t\t\t\t// are used to implement key-frame animations and as such only two are active at a time - this results in very large\n\t\t\t\t\t// boxes. So for now we make a box that's sometimes a touch too small but is hopefully mostly of reasonable size.\n\t\t\t\t\tmaxDisplacement.max( vector );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.warn( 'THREE.GLTFLoader: Missing min/max properties for accessor POSITION.' );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\t// As per comment above this box isn't conservative, but has a reasonable size for a very large number of morph targets.\n\t\tbox.expandByVector( maxDisplacement );\n\n\t}\n\n\tgeometry.boundingBox = box;\n\n\tconst sphere = new Sphere();\n\n\tbox.getCenter( sphere.center );\n\tsphere.radius = box.min.distanceTo( box.max ) / 2;\n\n\tgeometry.boundingSphere = sphere;\n\n}\n\n/**\n *\n * @private\n * @param {BufferGeometry} geometry\n * @param {GLTF.Primitive} primitiveDef\n * @param {GLTFParser} parser\n * @return {Promise<BufferGeometry>}\n */\nfunction addPrimitiveAttributes( geometry, primitiveDef, parser ) {\n\n\tconst attributes = primitiveDef.attributes;\n\n\tconst pending = [];\n\n\tfunction assignAttributeAccessor( accessorIndex, attributeName ) {\n\n\t\treturn parser.getDependency( 'accessor', accessorIndex )\n\t\t\t.then( function ( accessor ) {\n\n\t\t\t\tgeometry.setAttribute( attributeName, accessor );\n\n\t\t\t} );\n\n\t}\n\n\tfor ( const gltfAttributeName in attributes ) {\n\n\t\tconst threeAttributeName = ATTRIBUTES[ gltfAttributeName ] || gltfAttributeName.toLowerCase();\n\n\t\t// Skip attributes already provided by e.g. Draco extension.\n\t\tif ( threeAttributeName in geometry.attributes ) continue;\n\n\t\tpending.push( assignAttributeAccessor( attributes[ gltfAttributeName ], threeAttributeName ) );\n\n\t}\n\n\tif ( primitiveDef.indices !== undefined && ! geometry.index ) {\n\n\t\tconst accessor = parser.getDependency( 'accessor', primitiveDef.indices ).then( function ( accessor ) {\n\n\t\t\tgeometry.setIndex( accessor );\n\n\t\t} );\n\n\t\tpending.push( accessor );\n\n\t}\n\n\tif ( ColorManagement.workingColorSpace !== LinearSRGBColorSpace && 'COLOR_0' in attributes ) {\n\n\t\tconsole.warn( `THREE.GLTFLoader: Converting vertex colors from \"srgb-linear\" to \"${ColorManagement.workingColorSpace}\" not supported.` );\n\n\t}\n\n\tassignExtrasToUserData( geometry, primitiveDef );\n\n\tcomputeBounds( geometry, primitiveDef, parser );\n\n\treturn Promise.all( pending ).then( function () {\n\n\t\treturn primitiveDef.targets !== undefined\n\t\t\t? addMorphTargets( geometry, primitiveDef.targets, parser )\n\t\t\t: geometry;\n\n\t} );\n\n}\n\n/**\n * Loader result of `GLTFLoader`.\n *\n * @typedef {Object} GLTFLoader~LoadObject\n * @property {Array<AnimationClip>} animations - An array of animation clips.\n * @property {Object} asset - Meta data about the loaded asset.\n * @property {Array<Camera>} cameras - An array of cameras.\n * @property {GLTFParser} parser - A reference to the internal parser.\n * @property {Group} scene - The default scene.\n * @property {Array<Group>} scenes - glTF assets might define multiple scenes.\n * @property {Object} userData - Additional data.\n **/\n\nexport { GLTFLoader };\n","/**\r\n * 提供添加基础几何体(正方体、球体)以及导入外部模型文件的功能\r\n * 所有模型均自动标记为可移动(isMovable = true)\r\n */\r\n\r\nimport * as THREE from \"three\";\r\nimport { addModel } from \"./index\";\r\nimport { OBJLoader } from \"three/examples/jsm/loaders/OBJLoader.js\";\r\nimport { GLTFLoader } from \"three/examples/jsm/loaders/GLTFLoader.js\";\r\n\r\n//#region ─── 添加基础体 ───\r\n\r\n/** 添加一个蓝色的正方体,位置在地面上方 0.5 单位 */\r\nexport function addBox() {\r\n const geo = new THREE.BoxGeometry(1, 1, 1);\r\n const mat = new THREE.MeshStandardMaterial({ color: 0x00aaff });\r\n const mesh = new THREE.Mesh(geo, mat);\r\n mesh.position.y = 0.5;\r\n mesh.userData.isMovable = true;\r\n mesh.name = \"正方体\";\r\n addModel(mesh, true);\r\n return mesh;\r\n}\r\n\r\n/** 添加一个橙色的球体,位置在地面上方 0.6 单位 */\r\nexport function addSphere() {\r\n const geo = new THREE.SphereGeometry(0.6, 32, 32);\r\n const mat = new THREE.MeshStandardMaterial({ color: 0xff8800 });\r\n const mesh = new THREE.Mesh(geo, mat);\r\n mesh.position.y = 0.6;\r\n mesh.userData.isMovable = true;\r\n mesh.name = \"球体\";\r\n addModel(mesh, true);\r\n return mesh;\r\n}\r\n//#endregion\r\n\r\n//#region ─── 导入外部模型 ───\r\n\r\n/**\r\n * 从 File 对象导入 3D 模型(支持 .obj, .gltf, .glb)\r\n * 导入后自动标记所有节点为可移动,并居中放置\r\n * @param file - 模型文件\r\n * @returns Promise 解析为模型根对象\r\n */\r\nexport function importModelFromFile(file: File): Promise<THREE.Object3D> {\r\n return new Promise((resolve, reject) => {\r\n const ext = file.name.split(\".\").pop()?.toLowerCase();\r\n const url = URL.createObjectURL(file);\r\n\r\n let loader: any;\r\n if (ext === \"obj\") loader = new OBJLoader();\r\n else if (ext === \"gltf\" || ext === \"glb\") loader = new GLTFLoader();\r\n else {\r\n reject(new Error(\"不支持的文件格式,请使用 .obj, .gltf, .glb\"));\r\n return;\r\n }\r\n\r\n loader.load(\r\n url,\r\n (result: any) => {\r\n // 获取模型根对象\r\n const model = ext === \"gltf\" || ext === \"glb\" ? result.scene : result;\r\n // 遍历所有后代,标记为可移动,设置默认名称,优化 Mesh\r\n model.traverse((child: THREE.Object3D) => {\r\n child.userData.isMovable = true;\r\n if (!child.name) child.name = child.type;\r\n if (child.type === \"Mesh\") {\r\n child.frustumCulled = true; // 启用视锥体裁剪\r\n (child as THREE.Mesh).geometry?.computeVertexNormals(); // 重新计算法线\r\n }\r\n });\r\n // 将模型包围盒中心置于原点(居中)\r\n const box = new THREE.Box3().setFromObject(model);\r\n const center = box.getCenter(new THREE.Vector3());\r\n model.position.sub(center);\r\n // 添加到场景并自动选中\r\n addModel(model, true);\r\n resolve(model);\r\n },\r\n undefined,\r\n (err: any) => reject(err),\r\n );\r\n });\r\n}\r\n\r\n/**\r\n * 根据类型字符串添加对应的基础模型\r\n * @param type - 'box' 或 'sphere'\r\n */\r\nexport function addModelByType(type: string) {\r\n switch (type) {\r\n case \"box\":\r\n addBox();\r\n break;\r\n case \"sphere\":\r\n addSphere();\r\n break;\r\n }\r\n}\r\n//#endregion\r\n","<template>\r\n <div class=\"tree-node\" ref=\"nodeRef\">\r\n <!-- 节点行 -->\r\n <div\r\n class=\"tree-item\"\r\n :class=\"{ selected: isSelected }\"\r\n @click=\"handleSelect\"\r\n >\r\n <!-- 展开/收起箭头 -->\r\n <span\r\n v-if=\"hasChildren\"\r\n class=\"toggle-icon\"\r\n @click.stop=\"toggleExpand(node.uuid)\"\r\n >\r\n {{ isExpanded ? \"▼\" : \"▶\" }}\r\n </span>\r\n <span v-else class=\"toggle-placeholder\"></span>\r\n <!-- 图标 -->\r\n <span class=\"tree-icon\">{{ getIcon(node) }}</span>\r\n <!-- 名称 -->\r\n <span class=\"tree-name\">{{ getDisplayName(node) }}</span>\r\n <!-- 删除按钮 -->\r\n <button class=\"tree-delete\" @click.stop=\"handleDelete\">×</button>\r\n </div>\r\n <!-- 子节点列表(递归) -->\r\n <div v-if=\"isExpanded && hasChildren\" class=\"tree-children\">\r\n <TreeItem\r\n v-for=\"child in childNodes\"\r\n :key=\"child.uuid\"\r\n :node=\"child\"\r\n :selected-object=\"selectedObject\"\r\n :version=\"version\"\r\n @select=\"emit('select', $event)\"\r\n @delete=\"emit('delete', $event)\"\r\n />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\n/**\r\n * 递归树节点组件,用于展示场景物体的层级结构\r\n * 展开状态由父组件通过 provide/inject 共享\r\n * 当节点被选中时自动滚动到可视区域\r\n */\r\n\r\nimport { computed, inject, ref, watchEffect, type Ref } from \"vue\";\r\nimport type { Object3D } from \"three\";\r\n\r\nconst props = defineProps<{\r\n /** 当前节点对应的 Three.js 物体 */\r\n node: Object3D;\r\n /** 当前选中的物体(外部传入) */\r\n selectedObject: Object3D | null;\r\n /** 版本号,用于强制重新计算子节点列表 */\r\n version: number;\r\n}>();\r\n\r\nconst emit = defineEmits<{\r\n (e: \"select\", obj: Object3D): void;\r\n (e: \"delete\", obj: Object3D): void;\r\n}>();\r\n\r\n// ─── DOM 引用 ───\r\nconst nodeRef = ref<HTMLElement | null>(null);\r\n\r\n// ─── 注入展开状态管理 ───\r\nconst { expandedSet, toggleExpand } = inject<{\r\n expandedSet: Ref<Set<string>>;\r\n toggleExpand: (uuid: string) => void;\r\n}>(\"treeExpand\")!;\r\n\r\n// ─── 计算属性 ───\r\n\r\n/** 当前节点是否展开(基于展开集合) */\r\nconst isExpanded = computed(() => expandedSet.value.has(props.node.uuid));\r\n\r\n/** 是否有可移动的子节点(依赖 version) */\r\nconst hasChildren = computed(() => {\r\n const _ = props.version; // 建立依赖\r\n _\r\n return props.node.children.some((child) => child.userData.isMovable === true);\r\n});\r\n\r\n/** 可移动的子节点列表(依赖 version) */\r\nconst childNodes = computed(() => {\r\n const _ = props.version; // 建立依赖\r\n _\r\n return props.node.children.filter(\r\n (child) => child.userData.isMovable === true,\r\n );\r\n});\r\n\r\n/** 当前节点是否被选中 */\r\nconst isSelected = computed(\r\n () => props.selectedObject?.uuid === props.node.uuid,\r\n);\r\n\r\n/**\r\n * 自动滚动到选中节点(使用 watchEffect + flush: 'post' 确保 DOM 更新后执行)\r\n */\r\nwatchEffect(\r\n () => {\r\n if (isSelected.value && nodeRef.value) {\r\n nodeRef.value.scrollIntoView({\r\n block: \"nearest\", // 仅当元素不在可视区域时才滚动\r\n behavior: \"smooth\", // 平滑滚动\r\n });\r\n }\r\n },\r\n { flush: \"post\" },\r\n);\r\n\r\n// ─── 事件处理 ───\r\n\r\n/** 点击节点行:阻止冒泡并触发选中事件 */\r\nconst handleSelect = (event: MouseEvent) => {\r\n event.stopPropagation();\r\n emit(\"select\", props.node);\r\n};\r\n\r\n/** 点击删除按钮:阻止冒泡并触发删除事件 */\r\nconst handleDelete = (event: MouseEvent) => {\r\n event.stopPropagation();\r\n emit(\"delete\", props.node);\r\n};\r\n\r\n// ─── 辅助函数 ───\r\n\r\n/** 根据对象类型返回对应的图标字符 */\r\nconst getIcon = (obj: Object3D) => {\r\n if (obj.type === \"Mesh\" || obj.type === \"Sprite\") return \"🟦\";\r\n if (obj.type === \"Light\") return \"💡\";\r\n return \"📦\";\r\n};\r\n\r\n/** 获取对象的显示名称,若没有则自动生成 */\r\nconst getDisplayName = (obj: Object3D) => obj.name || `${obj.type} (${obj.id})`;\r\n</script>\r\n\r\n<style lang=\"less\" scoped>\r\n/* 节点样式 */\r\n.tree-node {\r\n .tree-item {\r\n display: flex;\r\n align-items: center;\r\n padding: 4px 10px;\r\n cursor: pointer;\r\n transition: background 0.15s;\r\n &:hover {\r\n background: #2a4050;\r\n }\r\n }\r\n .tree-item.selected {\r\n background: #3e5a6b;\r\n }\r\n\r\n .toggle-icon {\r\n cursor: pointer;\r\n width: 20px;\r\n text-align: center;\r\n font-size: 12px;\r\n user-select: none;\r\n }\r\n .toggle-placeholder {\r\n width: 20px;\r\n display: inline-block;\r\n }\r\n .tree-icon {\r\n margin-right: 6px;\r\n font-size: 14px;\r\n }\r\n .tree-name {\r\n flex: 1;\r\n font-size: 13px;\r\n user-select: none;\r\n }\r\n .tree-delete {\r\n background: transparent;\r\n border: none;\r\n color: #e74c3c;\r\n font-size: 16px;\r\n cursor: pointer;\r\n padding: 0 4px;\r\n line-height: 1;\r\n &:hover {\r\n color: #ff6b6b;\r\n }\r\n }\r\n}\r\n.tree-children {\r\n padding-left: 20px;\r\n} /* 缩进 */\r\n</style>\r\n","/**\r\n * 树形展开状态管理的组合式函数\r\n * 提供展开集合的响应式管理、切换展开、展开路径(自动展开父级)等功能\r\n * 用于 PropertyPanel 和 TreeItem 组件之间共享展开状态\r\n */\r\n\r\nimport { ref, watch, type Ref } from \"vue\";\r\nimport type { Object3D } from \"three\";\r\n\r\n/**\r\n * @param selectedObject - 响应式的当前选中物体(Ref)\r\n * @returns 包含展开集合和切换方法的对象\r\n */\r\nexport function useTreeExpand(selectedObject: Ref<Object3D | null>) {\r\n /** 存储所有展开节点的 uuid 的 Set(响应式) */\r\n const expandedSet = ref<Set<string>>(new Set());\r\n\r\n /**\r\n * 切换某个节点的展开/收起状态\r\n * @param uuid - 节点的唯一标识符\r\n */\r\n const toggleExpand = (uuid: string) => {\r\n const newSet = new Set(expandedSet.value);\r\n if (newSet.has(uuid)) newSet.delete(uuid);\r\n else newSet.add(uuid);\r\n expandedSet.value = newSet;\r\n };\r\n\r\n /**\r\n * 展开从目标节点到根节点的所有父级节点(不展开目标节点自身)\r\n * 用于点击场景物体后自动展开树形路径\r\n * @param target - 目标物体\r\n */\r\n const expandPath = (target: Object3D) => {\r\n if (!target) return;\r\n const newSet = new Set(expandedSet.value);\r\n let current = target.parent;\r\n // 逐级向上遍历,直到遇到场景根节点\r\n while (current && current.type !== \"Scene\") {\r\n newSet.add(current.uuid);\r\n current = current.parent;\r\n }\r\n expandedSet.value = newSet;\r\n };\r\n\r\n // 监听选中物体的变化,当选中新物体时自动展开其路径\r\n watch(\r\n selectedObject,\r\n (obj) => {\r\n if (obj) expandPath(obj);\r\n },\r\n { immediate: true },\r\n );\r\n\r\n return { expandedSet, toggleExpand };\r\n}\r\n","<template>\r\n <div class=\"property-panel\" v-if=\"transform\">\r\n <h3>属性面板</h3>\r\n\r\n <!-- 场景物体树 -->\r\n <div class=\"property-group tree-group\">\r\n <label>场景物体</label>\r\n <div class=\"tree-container\">\r\n <TreeItem\r\n v-for=\"obj in treeData\"\r\n :key=\"obj.uuid\"\r\n :node=\"obj\"\r\n :selected-object=\"selectedObject\"\r\n :version=\"treeVersion\"\r\n @select=\"emit('treeSelect', $event)\"\r\n @delete=\"handleTreeDelete\"\r\n />\r\n <div v-if=\"treeData.length === 0\" class=\"tree-empty\">暂无物体</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"property-group\">\r\n <label>全局属性</label>\r\n <div class=\"row\"></div>\r\n </div>\r\n\r\n <!-- Tab 切换(仅控制变换属性) -->\r\n <div class=\"tabs\" v-if=\"selectedObject\">\r\n <button\r\n class=\"tab-btn\"\r\n :class=\"{ active: activeTab === 'transform' }\"\r\n @click=\"activeTab = 'transform'\"\r\n >\r\n 🔄 变换\r\n </button>\r\n <button\r\n class=\"tab-btn\"\r\n :class=\"{ active: activeTab === 'info' }\"\r\n @click=\"activeTab = 'info'\"\r\n >\r\n ℹ️ 信息\r\n </button>\r\n </div>\r\n\r\n <!-- Tab 内容 -->\r\n <div class=\"tab-content\" v-if=\"selectedObject\">\r\n <!-- 变换 Tab -->\r\n <div v-show=\"activeTab === 'transform'\">\r\n <!-- 位置 -->\r\n <div class=\"property-group\">\r\n <label>位置</label>\r\n <div class=\"row\">\r\n <span>X:</span>\r\n <input\r\n type=\"number\"\r\n v-model.number=\"transform.position.x\"\r\n step=\"0.01\"\r\n @input=\"emitChange\"\r\n />\r\n <span>Y:</span>\r\n <input\r\n type=\"number\"\r\n v-model.number=\"transform.position.y\"\r\n step=\"0.01\"\r\n @input=\"emitChange\"\r\n />\r\n <span>Z:</span>\r\n <input\r\n type=\"number\"\r\n v-model.number=\"transform.position.z\"\r\n step=\"0.01\"\r\n @input=\"emitChange\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- 旋转 (弧度) -->\r\n <div class=\"property-group\">\r\n <label>旋转 (弧度)</label>\r\n <div class=\"row\">\r\n <span>X:</span>\r\n <input\r\n type=\"number\"\r\n v-model.number=\"transform.rotation.x\"\r\n step=\"0.01\"\r\n @input=\"emitChange\"\r\n />\r\n <span>Y:</span>\r\n <input\r\n type=\"number\"\r\n v-model.number=\"transform.rotation.y\"\r\n step=\"0.01\"\r\n @input=\"emitChange\"\r\n />\r\n <span>Z:</span>\r\n <input\r\n type=\"number\"\r\n v-model.number=\"transform.rotation.z\"\r\n step=\"0.01\"\r\n @input=\"emitChange\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- 缩放 -->\r\n <div class=\"property-group\">\r\n <label>缩放</label>\r\n <div class=\"row\">\r\n <span>X:</span>\r\n <input\r\n type=\"number\"\r\n v-model.number=\"transform.scale.x\"\r\n step=\"0.01\"\r\n @input=\"emitChange\"\r\n />\r\n <span>Y:</span>\r\n <input\r\n type=\"number\"\r\n v-model.number=\"transform.scale.y\"\r\n step=\"0.01\"\r\n @input=\"emitChange\"\r\n />\r\n <span>Z:</span>\r\n <input\r\n type=\"number\"\r\n v-model.number=\"transform.scale.z\"\r\n step=\"0.01\"\r\n @input=\"emitChange\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- ─── 材质属性 ─── -->\r\n <div class=\"property-group material-group\" v-if=\"selectedObject\">\r\n <label>材质</label>\r\n <div class=\"slider-row\">\r\n <span class=\"slider-label\">金属度</span>\r\n <input\r\n type=\"range\"\r\n min=\"0\"\r\n max=\"1\"\r\n step=\"0.01\"\r\n v-model.number=\"materialProps.metalness\"\r\n @input=\"onMaterialChange\"\r\n />\r\n <span class=\"slider-value\">{{\r\n materialProps.metalness.toFixed(2)\r\n }}</span>\r\n </div>\r\n <div class=\"slider-row\">\r\n <span class=\"slider-label\">粗糙度</span>\r\n <input\r\n type=\"range\"\r\n min=\"0\"\r\n max=\"1\"\r\n step=\"0.01\"\r\n v-model.number=\"materialProps.roughness\"\r\n @input=\"onMaterialChange\"\r\n />\r\n <span class=\"slider-value\">{{\r\n materialProps.roughness.toFixed(2)\r\n }}</span>\r\n </div>\r\n <div class=\"slider-row\">\r\n <span class=\"slider-label\">透明度</span>\r\n <input\r\n type=\"range\"\r\n min=\"0\"\r\n max=\"1\"\r\n step=\"0.01\"\r\n v-model.number=\"materialProps.opacity\"\r\n @input=\"onMaterialChange\"\r\n />\r\n <span class=\"slider-value\">{{\r\n materialProps.opacity.toFixed(2)\r\n }}</span>\r\n </div>\r\n <div class=\"material-hint\" v-if=\"!hasStandardMaterial\">\r\n ⚠️ 当前材质不支持金属度/粗糙度(仅支持 Standard/Phong)\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"property-panel empty\" v-else>\r\n <p>未选中任何模型</p>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\n/**\r\n * 属性面板组件\r\n * 显示当前选中物体的变换参数,并提供树形场景物体列表\r\n * 使用 provide 向子组件提供树形展开状态管理\r\n */\r\n\r\nimport type { Object3D, Mesh } from \"three\";\r\nimport TreeItem from \"./TreeItem.vue\";\r\nimport { ref, provide, toRef, watch, reactive } from \"vue\";\r\nimport { useTreeExpand } from \"../composables/useTreeExpand\";\r\n\r\nconst props = defineProps<{\r\n /** 变换数据对象,包含 position, rotation, scale */\r\n transform: {\r\n position: { x: number; y: number; z: number };\r\n rotation: { x: number; y: number; z: number };\r\n scale: { x: number; y: number; z: number };\r\n } | null;\r\n /** 顶层物体列表 */\r\n treeData: Object3D[];\r\n /** 当前选中的物体 */\r\n selectedObject: Object3D | null;\r\n}>();\r\n\r\nconst emit = defineEmits<{\r\n (e: \"propertyChange\"): void; // 变换数据变化\r\n (e: \"treeSelect\", obj: Object3D): void; // 树形选中节点\r\n (e: \"treeDelete\", obj: Object3D): void; // 树形删除节点\r\n}>();\r\n\r\n/** 触发变换变更事件(输入框 input 事件) */\r\nconst emitChange = () => emit(\"propertyChange\");\r\n\r\n// ─── Tab 状态 ───\r\nconst activeTab = ref<\"transform\" | \"info\">(\"transform\");\r\n\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n//#region 树形组件\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n\r\n// ─── 树形版本号 ───\r\n/**\r\n * 版本号用于强制刷新 TreeItem 的子节点列表(在删除节点后增加)\r\n * 因为子节点列表依赖 version 来重新计算\r\n */\r\nconst treeVersion = ref(0);\r\n\r\n// ─── 树形展开状态管理 ───\r\n/**\r\n * 使用组合式函数管理展开集合,并提供给子组件\r\n * 将 selectedObject prop 转换为 Ref,以便 useTreeExpand 监听变化\r\n */\r\nconst selectedObjectRef = toRef(props, \"selectedObject\");\r\nconst { expandedSet, toggleExpand } = useTreeExpand(selectedObjectRef);\r\n\r\n// 向子组件提供展开状态\r\nprovide(\"treeExpand\", { expandedSet, toggleExpand });\r\n\r\n// ─── 自定义删除处理 ───\r\n/**\r\n * 删除节点时递增版本号,使所有 TreeItem 重新计算 childNodes\r\n */\r\nconst handleTreeDelete = (obj: Object3D) => {\r\n treeVersion.value++;\r\n emit(\"treeDelete\", obj);\r\n};\r\n//#endregion\r\n\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n//#region 材质属性管理\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n/**\r\n * 材质属性数据(与滑块双向绑定)\r\n */\r\nconst materialProps = reactive({\r\n metalness: 0,\r\n roughness: 0.5,\r\n opacity: 1,\r\n});\r\n\r\n/** 是否包含支持 PBR 的材质 */\r\nconst hasStandardMaterial = ref(false);\r\n\r\n/**\r\n * 读取选中物体的材质属性(取第一个 Mesh 的材质作为代表)\r\n */\r\nfunction readMaterialFromObject(\r\n obj: Object3D,\r\n): { metalness: number; roughness: number; opacity: number } | null {\r\n let result: { metalness: number; roughness: number; opacity: number } | null =\r\n null;\r\n obj.traverse((child) => {\r\n if (child.type === \"Mesh\" && !result) {\r\n const mesh = child as Mesh;\r\n const materials = Array.isArray(mesh.material)\r\n ? mesh.material\r\n : [mesh.material];\r\n for (const mat of materials) {\r\n // 支持 MeshStandardMaterial 和 MeshPhongMaterial\r\n if (\r\n mat &&\r\n (mat.type === \"MeshStandardMaterial\" ||\r\n mat.type === \"MeshPhongMaterial\")\r\n ) {\r\n const stdMat = mat as any;\r\n result = {\r\n metalness: stdMat.metalness ?? 0,\r\n roughness: stdMat.roughness ?? 0.5,\r\n opacity: mat.opacity ?? 1,\r\n };\r\n break;\r\n }\r\n }\r\n }\r\n });\r\n return result;\r\n}\r\n\r\n/**\r\n * 应用材质属性到选中物体的所有 Mesh\r\n */\r\nfunction applyMaterialToObject(\r\n obj: Object3D,\r\n props: { metalness?: number; roughness?: number; opacity?: number },\r\n) {\r\n let applied = false;\r\n obj.traverse((child) => {\r\n if (child.type === \"Mesh\") {\r\n const mesh = child as Mesh;\r\n const materials = Array.isArray(mesh.material)\r\n ? mesh.material\r\n : [mesh.material];\r\n for (const mat of materials) {\r\n if (\r\n mat &&\r\n (mat.type === \"MeshStandardMaterial\" ||\r\n mat.type === \"MeshPhongMaterial\")\r\n ) {\r\n if (props.metalness !== undefined)\r\n (mat as any).metalness = props.metalness;\r\n if (props.roughness !== undefined)\r\n (mat as any).roughness = props.roughness;\r\n if (props.opacity !== undefined) {\r\n mat.opacity = props.opacity;\r\n mat.transparent = props.opacity < 1;\r\n }\r\n mat.needsUpdate = true;\r\n applied = true;\r\n }\r\n }\r\n }\r\n });\r\n return applied;\r\n}\r\n\r\n/**\r\n * 当滑块变化时应用到物体\r\n */\r\nfunction onMaterialChange() {\r\n if (props.selectedObject) {\r\n const applied = applyMaterialToObject(props.selectedObject, {\r\n metalness: materialProps.metalness,\r\n roughness: materialProps.roughness,\r\n opacity: materialProps.opacity,\r\n });\r\n hasStandardMaterial.value = applied;\r\n }\r\n}\r\n\r\n/**\r\n * 监听选中物体变化,更新滑块值和材质支持状态\r\n */\r\nwatch(\r\n () => props.selectedObject,\r\n (newObj) => {\r\n if (newObj) {\r\n const read = readMaterialFromObject(newObj);\r\n if (read) {\r\n materialProps.metalness = read.metalness;\r\n materialProps.roughness = read.roughness;\r\n materialProps.opacity = read.opacity;\r\n hasStandardMaterial.value = true;\r\n } else {\r\n // 没有材质或材质不支持,设为默认值并标记不支持\r\n materialProps.metalness = 0;\r\n materialProps.roughness = 0.5;\r\n materialProps.opacity = 1;\r\n hasStandardMaterial.value = false;\r\n }\r\n } else {\r\n // 取消选中时重置\r\n materialProps.metalness = 0;\r\n materialProps.roughness = 0.5;\r\n materialProps.opacity = 1;\r\n hasStandardMaterial.value = false;\r\n }\r\n },\r\n { immediate: true },\r\n);\r\n//#endregion\r\n</script>\r\n\r\n<style lang=\"less\" scoped>\r\n// ─── Tabs ───\r\n.tabs {\r\n display: flex;\r\n gap: 0;\r\n border-bottom: 2px solid #1a2a36;\r\n margin-bottom: 16px;\r\n\r\n .tab-btn {\r\n flex: 1;\r\n padding: 8px 12px;\r\n background: transparent;\r\n border: none;\r\n color: #95a5a6;\r\n font-size: 13px;\r\n cursor: pointer;\r\n transition:\r\n color 0.2s,\r\n border-bottom 0.2s;\r\n border-bottom: 2px solid transparent;\r\n margin-bottom: -2px;\r\n\r\n &:hover {\r\n color: #ecf0f1;\r\n }\r\n\r\n &.active {\r\n color: #f1c40f;\r\n border-bottom-color: #f1c40f;\r\n }\r\n }\r\n}\r\n\r\n.property-panel {\r\n width: 320px;\r\n height: 100%;\r\n background: #2c3e50;\r\n color: #ecf0f1;\r\n padding: 16px;\r\n box-sizing: border-box;\r\n border-left: 1px solid #1a2a36;\r\n overflow-y: auto;\r\n font-size: 14px;\r\n h3 {\r\n margin-top: 0;\r\n text-align: center;\r\n }\r\n\r\n .property-group {\r\n margin-bottom: 20px;\r\n border-bottom: 1px solid #1a2a36;\r\n padding-bottom: 12px;\r\n label {\r\n font-weight: bold;\r\n display: block;\r\n margin-bottom: 8px;\r\n color: #f1c40f;\r\n }\r\n .row {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n margin-bottom: 6px;\r\n span {\r\n width: 20px;\r\n text-align: right;\r\n }\r\n input {\r\n background: #1e2a36;\r\n border: 1px solid #3e5a6b;\r\n color: #ecf0f1;\r\n padding: 4px 8px;\r\n border-radius: 4px;\r\n width: 48px;\r\n }\r\n }\r\n }\r\n\r\n .tab-content {\r\n // ─── 材质滑块 ───\r\n .material-group {\r\n .slider-row {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n margin-bottom: 6px;\r\n\r\n .slider-label {\r\n width: 50px;\r\n font-size: 12px;\r\n color: #95a5a6;\r\n }\r\n\r\n input[type=\"range\"] {\r\n flex: 1;\r\n height: 4px;\r\n -webkit-appearance: none;\r\n background: #1e2a36;\r\n border-radius: 2px;\r\n outline: none;\r\n\r\n &::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n width: 12px;\r\n height: 12px;\r\n border-radius: 50%;\r\n background: #f1c40f;\r\n cursor: pointer;\r\n }\r\n }\r\n\r\n .slider-value {\r\n width: 36px;\r\n font-size: 12px;\r\n text-align: center;\r\n color: #ecf0f1;\r\n }\r\n }\r\n\r\n .material-hint {\r\n margin-top: 6px;\r\n font-size: 12px;\r\n color: #e67e22;\r\n }\r\n }\r\n }\r\n}\r\n.empty {\r\n text-align: center;\r\n color: #95a5a6;\r\n}\r\n.tree-group {\r\n margin-top: 10px;\r\n .tree-container {\r\n max-height: 200px;\r\n overflow-y: auto;\r\n background: #1a2a36;\r\n border-radius: 4px;\r\n padding: 4px 0;\r\n }\r\n}\r\n.tree-empty {\r\n padding: 8px 10px;\r\n color: #95a5a6;\r\n font-style: italic;\r\n}\r\n</style>\r\n","<template>\r\n <div class=\"top-bar\">\r\n <div class=\"left-section\">\r\n <!-- 文件菜单 -->\r\n <div\r\n class=\"dropdown-wrapper\"\r\n @mouseenter=\"showFileMenu = true\"\r\n @mouseleave=\"showFileMenu = false\"\r\n >\r\n <button class=\"menu-btn\">文件</button>\r\n <div class=\"dropdown-menu\" v-show=\"showFileMenu\">\r\n <div class=\"menu-item\" @click=\"handleNew\">新建</div>\r\n <div\r\n class=\"menu-item dropdown-wrapper sub-trigger\"\r\n @mouseenter=\"showOpenSub = true\"\r\n @mouseleave=\"showOpenSub = false\"\r\n >\r\n <span>打开</span>\r\n <div class=\"dropdown-menu sub-menu\" v-show=\"showOpenSub\">\r\n <div class=\"menu-item\" @click=\"handleOpenProject\">打开项目</div>\r\n <div class=\"menu-item\" @click=\"handleOpenModel\">打开模型</div>\r\n <div class=\"menu-item\" @click=\"handleOpenScene\">打开场景</div>\r\n </div>\r\n </div>\r\n <div class=\"menu-item\" @click=\"handleSave\">保存</div>\r\n <div class=\"menu-item\" @click=\"handleExport\">导出</div>\r\n </div>\r\n </div>\r\n\r\n <!-- 添加菜单 -->\r\n <div\r\n class=\"dropdown-wrapper\"\r\n @mouseenter=\"showAddMenu = true\"\r\n @mouseleave=\"showAddMenu = false\"\r\n >\r\n <button class=\"menu-btn\">添加</button>\r\n <div class=\"dropdown-menu\" v-show=\"showAddMenu\">\r\n <div class=\"menu-item\" @click=\"handleUndo\">组</div>\r\n <div\r\n class=\"menu-item dropdown-wrapper sub-trigger\"\r\n @mouseenter=\"showOpenGrid = true\"\r\n @mouseleave=\"showOpenGrid = false\"\r\n >\r\n <span>网格</span>\r\n <div class=\"dropdown-menu sub-menu\" v-show=\"showOpenGrid\">\r\n <div class=\"menu-item\" @click=\"emit('addModel', 'box')\">\r\n 正方体\r\n </div>\r\n <div class=\"menu-item\" @click=\"emit('addModel', 'sphere')\">\r\n 球体\r\n </div>\r\n <div class=\"menu-item\" @click=\"triggerImport\">导入</div>\r\n </div>\r\n </div>\r\n <div class=\"menu-item\" @click=\"handleDuplicate\">光源</div>\r\n <div class=\"menu-item\" @click=\"handleDelete\">摄像机</div>\r\n </div>\r\n </div>\r\n\r\n <!-- 编辑菜单 -->\r\n <div\r\n class=\"dropdown-wrapper\"\r\n @mouseenter=\"showEditMenu = true\"\r\n @mouseleave=\"showEditMenu = false\"\r\n >\r\n <button class=\"menu-btn\">编辑</button>\r\n <div class=\"dropdown-menu\" v-show=\"showEditMenu\">\r\n <div class=\"menu-item\" @click=\"handleUndo\">撤销</div>\r\n <div class=\"menu-item\" @click=\"handleRedo\">重做</div>\r\n <div class=\"menu-item\" @click=\"handleDuplicate\">复制</div>\r\n <div class=\"menu-item\" @click=\"handleDelete\">删除</div>\r\n </div>\r\n </div>\r\n\r\n <!-- 视图菜单 -->\r\n <div\r\n class=\"dropdown-wrapper\"\r\n @mouseenter=\"showViewMenu = true\"\r\n @mouseleave=\"showViewMenu = false\"\r\n >\r\n <button class=\"menu-btn\">视图</button>\r\n <div class=\"dropdown-menu\" v-show=\"showViewMenu\">\r\n <div class=\"menu-item\" @click=\"handleResetCamera\">重置相机</div>\r\n <div class=\"menu-item\" @click=\"handleToggleGrid\">显示网格</div>\r\n </div>\r\n </div>\r\n\r\n <!-- 帮助菜单 -->\r\n <div\r\n class=\"dropdown-wrapper\"\r\n @mouseenter=\"showHelpMenu = true\"\r\n @mouseleave=\"showHelpMenu = false\"\r\n >\r\n <button class=\"menu-btn\">帮助</button>\r\n <div class=\"dropdown-menu\" v-show=\"showHelpMenu\">\r\n <div class=\"menu-item\" @click=\"handleHelp\">使用帮助</div>\r\n <div class=\"menu-item\" @click=\"handleAbout\">关于</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"right-section\">\r\n <span class=\"app-title\">3D 模型编辑器</span>\r\n </div>\r\n\r\n <!-- 隐藏的文件输入框,用于导入模型 -->\r\n <input\r\n type=\"file\"\r\n ref=\"fileInput\"\r\n accept=\".obj,.gltf,.glb\"\r\n style=\"display: none\"\r\n @change=\"onFileSelected\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\n/**\r\n * 顶部菜单栏组件\r\n * 包含文件、添加、编辑、视图、帮助等下拉菜单\r\n * 通过 emit 向父组件传递添加模型和导入模型事件\r\n */\r\n\r\nimport { ref } from \"vue\";\r\n\r\n// 各菜单显示状态\r\nconst showFileMenu = ref(false);\r\nconst showEditMenu = ref(false);\r\nconst showViewMenu = ref(false);\r\nconst showHelpMenu = ref(false);\r\nconst showAddMenu = ref(false);\r\nconst showOpenSub = ref(false); // 文件→打开子菜单\r\nconst showOpenGrid = ref(false); // 添加→网格子菜单\r\n\r\nconst emit = defineEmits<{\r\n (e: \"addModel\", type: string): void;\r\n (e: \"importModel\", file: File): void;\r\n}>();\r\n\r\n// ─── 文件输入 ───\r\nconst fileInput = ref<HTMLInputElement | null>(null);\r\n\r\n/** 触发文件选择对话框 */\r\nconst triggerImport = () => fileInput.value?.click();\r\n\r\n/** 文件选择后,向上传递文件对象,并重置 input 以便重复选择同一文件 */\r\nconst onFileSelected = (event: Event) => {\r\n const input = event.target as HTMLInputElement;\r\n if (input.files && input.files.length > 0) {\r\n emit(\"importModel\", input.files[0]);\r\n input.value = \"\";\r\n }\r\n};\r\n\r\n// ─── 各菜单项的占位处理(后续可扩展功能) ───\r\nconst handleNew = () => console.log(\"新建项目\");\r\nconst handleSave = () => console.log(\"保存场景\");\r\nconst handleExport = () => console.log(\"导出模型\");\r\nconst handleUndo = () => console.log(\"撤销\");\r\nconst handleRedo = () => console.log(\"重做\");\r\nconst handleDuplicate = () => console.log(\"复制物体\");\r\nconst handleDelete = () => console.log(\"删除物体\");\r\nconst handleResetCamera = () => console.log(\"重置相机\");\r\nconst handleToggleGrid = () => console.log(\"切换网格\");\r\nconst handleHelp = () => console.log(\"打开帮助\");\r\nconst handleAbout = () => console.log(\"关于编辑器\");\r\nconst handleOpenProject = () => console.log(\"打开项目\");\r\nconst handleOpenModel = () => console.log(\"打开模型\");\r\nconst handleOpenScene = () => console.log(\"打开场景\");\r\n</script>\r\n\r\n<style lang=\"less\" scoped>\r\n.top-bar {\r\n height: 40px;\r\n background: #1a2a36;\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 0 16px;\r\n border-bottom: 1px solid #2a4050;\r\n flex-shrink: 0;\r\n user-select: none;\r\n\r\n .left-section {\r\n display: flex;\r\n gap: 12px;\r\n align-items: center;\r\n\r\n .dropdown-wrapper {\r\n position: relative;\r\n display: inline-block;\r\n\r\n .menu-btn {\r\n background: transparent;\r\n border: none;\r\n color: #ecf0f1;\r\n padding: 6px 12px;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font-size: 14px;\r\n transition: background 0.2s;\r\n &:hover {\r\n background: #2a4050;\r\n }\r\n }\r\n\r\n .dropdown-menu {\r\n position: absolute;\r\n top: 100%;\r\n left: 0;\r\n background: #2c3e50;\r\n border: 1px solid #3e5a6b;\r\n border-radius: 4px;\r\n min-width: 140px;\r\n padding: 4px 0;\r\n z-index: 100;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\r\n\r\n .menu-item {\r\n padding: 6px 16px;\r\n color: #ecf0f1;\r\n cursor: pointer;\r\n font-size: 13px;\r\n transition: background 0.15s;\r\n white-space: nowrap;\r\n &:hover {\r\n background: #3e5a6b;\r\n }\r\n }\r\n .menu-item.sub-trigger {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n position: relative;\r\n }\r\n }\r\n .sub-menu {\r\n position: absolute;\r\n left: 100%;\r\n top: 0;\r\n background: #2c3e50;\r\n border: 1px solid #3e5a6b;\r\n border-radius: 4px;\r\n min-width: 140px;\r\n padding: 4px 0;\r\n z-index: 101;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\r\n }\r\n }\r\n }\r\n\r\n .right-section {\r\n display: flex;\r\n align-items: center;\r\n }\r\n .app-title {\r\n color: #88aaff;\r\n font-size: 16px;\r\n font-weight: 500;\r\n letter-spacing: 0.5px;\r\n }\r\n}\r\n</style>\r\n","<template>\r\n <div class=\"bottom-bar\">\r\n <div class=\"status-left\">\r\n <span>就绪</span>\r\n </div>\r\n <div class=\"status-right\">\r\n <span>顶点: 0 | 面: 0</span>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\n/**\r\n * 底部状态栏\r\n * 目前仅显示“就绪”和占位统计信息\r\n * 未来可扩展显示顶点/面数、坐标等\r\n */\r\n</script>\r\n\r\n<style lang=\"less\" scoped>\r\n.bottom-bar {\r\n height: 40px;\r\n background: #1a2a36;\r\n border-top: 1px solid #2a4050;\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 0 16px;\r\n flex-shrink: 0;\r\n color: #95a5a6;\r\n font-size: 13px;\r\n user-select: none;\r\n .status-left,\r\n .status-right {\r\n display: flex;\r\n gap: 16px;\r\n }\r\n}\r\n</style>\r\n","<template>\r\n <div class=\"app-layout\">\r\n <!-- 顶部菜单栏 -->\r\n <TopBar\r\n @add-model=\"handleAddModel\"\r\n @import-model=\"handleImportModel\"\r\n v-if=\"mode === 'edit'\"\r\n />\r\n <div :class=\"`editor-container editor-container-mode-${mode}`\">\r\n <!-- Three.js 画布 -->\r\n <div :class=\"`canvas canvas-mode-${mode}`\" ref=\"containerRef\"></div>\r\n <!-- 属性面板 -->\r\n <PropertyPanel\r\n :transform=\"transform\"\r\n :tree-data=\"treeData\"\r\n :selected-object=\"selectedModel\"\r\n @property-change=\"handlePropertyChange\"\r\n @tree-select=\"handleTreeSelect\"\r\n @tree-delete=\"handleTreeDelete\"\r\n v-if=\"mode === 'edit'\"\r\n />\r\n </div>\r\n <!-- 底部状态栏 -->\r\n <BottomBar v-if=\"mode === 'edit'\" />\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\n/**\r\n * 编辑器主组件,负责:\r\n * - 挂载 Three.js 编辑器\r\n * - 管理选中物体的变换数据(位置/旋转/缩放)\r\n * - 同步场景物体树形数据\r\n * - 处理添加模型、导入模型、树形选中/删除等交互\r\n */\r\n\r\nimport { onMounted, reactive, ref, shallowRef } from \"vue\";\r\nimport {\r\n initEditor,\r\n setSelectedObjectCallback,\r\n setTransformChangeCallback,\r\n onSceneObjectsChangeCallback,\r\n getSceneObjects,\r\n removeModelById,\r\n selectObject,\r\n} from \"../three/index\";\r\nimport { addModelByType, importModelFromFile } from \"../three/addHandle\";\r\nimport PropertyPanel from \"./PropertyPanel.vue\";\r\nimport TopBar from \"./TopBar.vue\";\r\nimport BottomBar from \"./BottomBar.vue\";\r\nimport type { Object3D } from \"three\";\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n mode: string;\r\n sceneData: any;\r\n }>(),\r\n {\r\n mode: \"edit\",\r\n sceneData: null,\r\n },\r\n);\r\n\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n//#region 属性面板\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n\r\n/** 当前选中的模型对象 */\r\nconst selectedModel = ref<Object3D | null>(null);\r\n\r\n/**\r\n * 变换数据(位置/旋转/缩放),与属性面板双向绑定\r\n * 使用 reactive 使每个属性独立响应式\r\n */\r\nconst transform = reactive({\r\n position: { x: 0, y: 0, z: 0 },\r\n rotation: { x: 0, y: 0, z: 0 },\r\n scale: { x: 1, y: 1, z: 1 },\r\n});\r\n\r\n// ─── 同步函数 ───\r\n\r\n/**\r\n * 从 Three.js 物体同步变换数据到 transform 对象\r\n * 保留三位小数,避免浮点数误差\r\n */\r\nconst syncTransformFromObject = (obj: Object3D) => {\r\n transform.position.x = Number(obj.position.x.toFixed(3));\r\n transform.position.y = Number(obj.position.y.toFixed(3));\r\n transform.position.z = Number(obj.position.z.toFixed(3));\r\n transform.rotation.x = Number(obj.rotation.x.toFixed(3));\r\n transform.rotation.y = Number(obj.rotation.y.toFixed(3));\r\n transform.rotation.z = Number(obj.rotation.z.toFixed(3));\r\n transform.scale.x = Number(obj.scale.x.toFixed(3));\r\n transform.scale.y = Number(obj.scale.y.toFixed(3));\r\n transform.scale.z = Number(obj.scale.z.toFixed(3));\r\n};\r\n\r\n/**\r\n * 将 transform 数据应用到 Three.js 物体\r\n * 用于属性面板输入变化时更新物体\r\n */\r\nconst applyTransformToObject = (obj: Object3D) => {\r\n obj.position.set(\r\n transform.position.x,\r\n transform.position.y,\r\n transform.position.z,\r\n );\r\n obj.rotation.set(\r\n transform.rotation.x,\r\n transform.rotation.y,\r\n transform.rotation.z,\r\n );\r\n obj.scale.set(transform.scale.x, transform.scale.y, transform.scale.z);\r\n};\r\n\r\n// ─── 注册回调 ───\r\n\r\n// 选中物体变化时同步到本地状态\r\nsetSelectedObjectCallback((obj) => {\r\n selectedModel.value = obj;\r\n if (obj) syncTransformFromObject(obj);\r\n});\r\n\r\n// 变换过程中(拖拽)实时更新面板\r\nsetTransformChangeCallback((obj) => {\r\n syncTransformFromObject(obj);\r\n});\r\n\r\n// ─── 事件处理 ───\r\n\r\n/** 属性面板数值变化时,应用变换到物体 */\r\nconst handlePropertyChange = () => {\r\n if (selectedModel.value) applyTransformToObject(selectedModel.value);\r\n};\r\n\r\n/** 添加模型(来自顶部菜单) */\r\nconst handleAddModel = (type: string) => addModelByType(type);\r\n\r\n/** 导入模型(来自顶部菜单) */\r\nconst handleImportModel = async (file: File) => {\r\n try {\r\n await importModelFromFile(file);\r\n } catch (error) {\r\n console.error(\"导入失败:\", error);\r\n alert(\"导入失败:\" + (error as Error).message);\r\n }\r\n};\r\n//#endregion\r\n\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n//#region 树形面板\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n\r\n/** 树形数据使用 shallowRef 避免深度响应式,提高性能 */\r\nconst treeData = shallowRef<Object3D[]>([]);\r\n\r\n// 注册树形数据变化回调\r\nonSceneObjectsChangeCallback((objects) => {\r\n treeData.value = objects;\r\n});\r\n\r\n/** 初始化树形数据 */\r\nconst initTree = () => {\r\n const objects = getSceneObjects();\r\n if (objects) treeData.value = objects;\r\n};\r\n\r\n/** 树形选中节点 → 同步选中场景物体 */\r\nconst handleTreeSelect = (obj: Object3D) => selectObject(obj);\r\n\r\n/** 树形删除节点 → 删除场景物体 */\r\nconst handleTreeDelete = (obj: Object3D) => removeModelById(obj.uuid);\r\n//#endregion\r\n\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n//#region 初始化\r\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n\r\nconst containerRef = ref<HTMLElement | null>(null);\r\n/** 挂载 Three.js 编辑器并初始化树 */\r\nconst init = () => {\r\n if (containerRef.value)\r\n initEditor(containerRef.value, props.mode, props.sceneData);\r\n // const dom = document.getElementById(\"sl_canvas\");\r\n // if (dom) initEditor(dom);\r\n initTree();\r\n};\r\n\r\nonMounted(init);\r\n//#endregion\r\n</script>\r\n\r\n<style lang=\"less\" scoped>\r\n/* 整体布局:纵向排列,编辑器区域占剩余高度 */\r\n.app-layout {\r\n display: flex;\r\n flex-direction: column;\r\n height: 100%;\r\n width: 100%;\r\n}\r\n.editor-container {\r\n display: flex;\r\n width: 100%;\r\n}\r\n.editor-container-mode-edit {\r\n height: calc(100% - 80px); /* 顶部栏 40px + 底部栏 40px */\r\n}\r\n.editor-container-mode-run {\r\n height: 100%; /* 顶部栏 40px + 底部栏 40px */\r\n}\r\n.canvas {\r\n height: 100%;\r\n background-color: transparent;\r\n position: relative;\r\n}\r\n.canvas-mode-edit {\r\n width: calc(100% - 320px); /* 属性面板宽 320px */\r\n}\r\n.canvas-mode-run {\r\n width: 100%; /* 属性面板宽 320px */\r\n}\r\n</style>\r\n"],"names":["_changeEvent","_startEvent","_endEvent","_ray","Ray","_plane","Plane","_TILT_LIMIT","MathUtils","_v","Vector3","_twoPI","_STATE","_EPS","OrbitControls","Controls","object","domElement","MOUSE","TOUCH","Quaternion","Spherical","Vector2","onPointerMove","onPointerDown","onPointerUp","onContextMenu","onMouseWheel","onKeyDown","onTouchStart","onTouchMove","onMouseDown","onMouseMove","interceptControlDown","interceptControlUp","type","element","deltaX","deltaY","dollyScale","angle","deltaTime","position","min","max","zoomChanged","prevRadius","newRadius","radiusDelta","mouseBefore","prevZoom","mouseAfter","delta","normalizedDelta","distance","objectMatrix","targetDistance","x","y","rect","dx","dy","w","h","dist","event","needsUpdate","centerX","centerY","i","pointerId","mode","newEvent","mouseAction","_raycaster","Raycaster","_tempVector","_tempVector2","_tempQuaternion","_unit","_mouseDownEvent","_mouseUpEvent","_objectChangeEvent","TransformControls","camera","root","TransformControlsRoot","gizmo","TransformControlsGizmo","plane","TransformControlsPlane","scope","defineProperty","propName","defaultValue","propValue","value","worldPosition","worldPositionStart","worldQuaternion","worldQuaternionStart","cameraPosition","cameraQuaternion","pointStart","pointEnd","rotationAxis","rotationAngle","eye","getPointer","onPointerHover","pointer","intersect","intersectObjectWithRay","planeIntersect","axis","space","d","ROTATION_SPEED","_inPlaneRotation","translationSnap","rotationSnap","scaleSnap","size","xAxis","yAxis","zAxis","active","materialLib","raycaster","includeInvisible","allIntersections","_tempEuler","Euler","_alignVector","_zeroVector","_lookAtMatrix","Matrix4","_tempQuaternion2","_identityQuaternion","_dirVector","_tempMatrix","_unitX","_unitY","_unitZ","_v1","_v2","_v3","Object3D","controls","force","child","gizmoMaterial","MeshBasicMaterial","gizmoLineMaterial","LineBasicMaterial","matInvisible","matHelper","matRed","matGreen","matBlue","matRedTransparent","matGreenTransparent","matBlueTransparent","matWhiteTransparent","matYellowTransparent","matYellow","matGray","arrowGeometry","CylinderGeometry","scaleHandleGeometry","BoxGeometry","lineGeometry","BufferGeometry","Float32BufferAttribute","lineGeometry2","CircleGeometry","radius","arc","geometry","TorusGeometry","TranslateHelperGeometry","gizmoTranslate","Mesh","OctahedronGeometry","pickerTranslate","helperTranslate","Line","gizmoRotate","helperRotate","pickerRotate","SphereGeometry","gizmoScale","pickerScale","helperScale","setupGizmo","gizmoMap","name","rotation","scale","tag","tempGeometry","quaternion","handles","handle","factor","a","PlaneGeometry","DoubleSide","state","orbitChanged","skipNextClick","onSelectedChange","onTransformChange","onSceneObjectsChange","sceneObjects","cameraTarget","initEditor","container","sceneData","initRenderer","initScene","initCamera","loadSceneFromJSON","camData","initTransformControls","initOrbitControls","refreshSceneObjects","animate","onMouseClick","onResize","addDefaultLightAndCube","initGrid","renderer","THREE","grid","aspect","ambient","dirLight","TWEEN","_a","_b","width","height","selectObject","obj","deselectObject","mouse","clickables","intersects","addModel","model","selected","addObjectToTree","notifyChange","removeModel","removeObjectFromTree","removeModelById","uuid","idx","list","setSelectedObjectCallback","cb","setTransformChangeCallback","onSceneObjectsChangeCallback","getSceneObjects","getScene","getCamera","getRenderer","exportSceneToJSON","scene","exportScene","sceneJson","cameraJson","_c","json","data","loaded","_object_pattern","_material_library_pattern","_material_use_pattern","_map_use_pattern","_face_vertex_data_separator_pattern","_vA","_vB","_vC","_ab","_cb","_color","Color","ParserState","fromDeclaration","previousMaterial","libraries","previous","material","index","cloned","end","lastMultiMaterial","mi","declared","len","b","c","src","dst","ua","ub","uc","na","nb","nc","vLen","ia","ib","ic","nLen","uvLen","vertices","vi","l","uvs","uvi","OBJLoader","Loader","manager","url","onLoad","onProgress","onError","loader","FileLoader","text","e","materials","lines","result","line","lineFirstChar","SRGBColorSpace","vertexData","faceVertices","j","jl","vertex","vertexParts","v1","v2","v3","lineParts","lineVertices","lineUVs","li","llen","parts","pointData","Group","isLine","isPoints","hasVertexColors","buffergeometry","createdMaterials","miLen","sourceMaterial","materialHash","materialLine","Material","PointsMaterial","materialPoints","MeshPhongMaterial","mesh","LineSegments","Points","points","toTrianglesDrawMode","drawMode","TrianglesDrawMode","TriangleFanDrawMode","TriangleStripDrawMode","indices","numberOfTriangles","newIndices","newGeometry","clone","source","sourceLookup","cloneLookup","parallelTraverse","sourceNode","clonedNode","node","clonedMesh","sourceMesh","sourceBones","bone","callback","GLTFLoader","parser","GLTFMaterialsClearcoatExtension","GLTFMaterialsDispersionExtension","GLTFTextureBasisUExtension","GLTFTextureWebPExtension","GLTFTextureAVIFExtension","GLTFMaterialsSheenExtension","GLTFMaterialsTransmissionExtension","GLTFMaterialsVolumeExtension","GLTFMaterialsIorExtension","GLTFMaterialsEmissiveStrengthExtension","GLTFMaterialsSpecularExtension","GLTFMaterialsIridescenceExtension","GLTFMaterialsAnisotropyExtension","GLTFMaterialsBumpExtension","GLTFLightsExtension","GLTFMeshoptCompression","EXTENSIONS","GLTFMeshGpuInstancing","resourcePath","relativeUrl","LoaderUtils","_onError","gltf","dracoLoader","ktx2Loader","meshoptDecoder","path","extensions","plugins","textDecoder","BINARY_EXTENSION_HEADER_MAGIC","GLTFBinaryExtension","error","GLTFParser","plugin","extensionName","extensionsRequired","GLTFMaterialsUnlitExtension","GLTFDracoMeshCompressionExtension","GLTFTextureTransformExtension","GLTFMeshQuantizationExtension","resolve","reject","GLTFRegistry","objects","key","getMaterialExtension","materialIndex","materialDef","nodeDefs","nodeIndex","nodeLength","nodeDef","lightIndex","cacheKey","dependency","lightDef","lightNode","color","LinearSRGBColorSpace","range","DirectionalLight","PointLight","SpotLight","assignExtrasToUserData","self","light","materialParams","pending","metallicRoughness","array","extension","MeshPhysicalMaterial","colorFactor","colorArray","textureIndex","textureDef","handler","bufferView","extensionDef","buffer","decoder","res","byteOffset","byteLength","count","stride","meshDef","primitive","WEBGL_CONSTANTS","attributesDef","attributes","accessor","results","nodeObject","meshes","instancedMeshes","m","p","q","s","instancedMesh","InstancedMesh","attributeName","attr","InstancedBufferAttribute","BINARY_EXTENSION_HEADER_LENGTH","BINARY_EXTENSION_CHUNK_TYPES","headerView","chunkContentsLength","chunkView","chunkIndex","chunkLength","chunkType","contentArray","bufferViewIndex","gltfAttributeMap","threeAttributeMap","attributeNormalizedMap","attributeTypeMap","threeAttributeName","ATTRIBUTES","accessorDef","componentType","WEBGL_COMPONENT_TYPES","attribute","normalized","texture","transform","GLTFCubicSplineInterpolant","Interpolant","parameterPositions","sampleValues","sampleSize","resultBuffer","values","valueSize","offset","i1","t0","t","t1","stride2","stride3","td","pp","ppp","offset1","offset0","s2","s3","s0","s1","p0","m0","p1","m1","_quaternion","GLTFCubicSplineQuaternionInterpolant","WEBGL_FILTERS","NearestFilter","LinearFilter","NearestMipmapNearestFilter","LinearMipmapNearestFilter","NearestMipmapLinearFilter","LinearMipmapLinearFilter","WEBGL_WRAPPINGS","ClampToEdgeWrapping","MirroredRepeatWrapping","RepeatWrapping","WEBGL_TYPE_SIZES","PATH_PROPERTIES","INTERPOLATION","InterpolateLinear","InterpolateDiscrete","ALPHA_MODES","createDefaultMaterial","cache","MeshStandardMaterial","FrontSide","addUnknownExtensionsToUserData","knownExtensions","objectDef","gltfDef","addMorphTargets","targets","hasMorphPosition","hasMorphNormal","hasMorphColor","il","target","pendingPositionAccessors","pendingNormalAccessors","pendingColorAccessors","pendingAccessor","accessors","morphPositions","morphNormals","morphColors","updateMorphTargets","targetNames","createPrimitiveKey","primitiveDef","geometryKey","dracoExtension","createAttributesKey","attributesKey","keys","getNormalizedComponentScale","constructor","getImageURIMimeType","uri","_identityMatrix","options","isSafari","safariVersion","isFirefox","firefoxVersion","userAgent","safariMatch","TextureLoader","ImageBitmapLoader","ext","dependencies","skinDefs","meshDefs","skinIndex","skinLength","joints","ref","updateMappings","original","mappings","func","defs","def","bufferIndex","bufferDef","bufferViewDef","accessorIndex","itemSize","TypedArray","BufferAttribute","pendingBufferViews","bufferViews","elementBytes","itemBytes","byteStride","bufferAttribute","ibSlice","ibCacheKey","InterleavedBuffer","InterleavedBufferAttribute","itemSizeIndices","TypedArrayIndices","byteOffsetIndices","byteOffsetValues","sparseIndices","sparseValues","sourceIndex","sourceDef","promise","sampler","URL","sourceURI","isObjectURL","blob","imageBitmap","Texture","mapName","mapDef","colorSpace","gltfReference","useDerivativeTangents","useVertexColors","useFlatShading","pointsMaterial","lineMaterial","cachedMaterial","materialType","materialExtensions","kmuExtension","alphaMode","emissiveFactor","originalName","sanitizedName","PropertyBinding","primitives","createDracoPrimitive","addPrimitiveAttributes","cached","geometryPromise","meshIndex","geometries","SkinnedMesh","LineLoop","group","cameraIndex","cameraDef","params","PerspectiveCamera","OrthographicCamera","skinDef","inverseBindMatrices","jointNodes","bones","boneInverses","jointNode","mat","Skeleton","animationIndex","animationDef","animationName","pendingNodes","pendingInputAccessors","pendingOutputAccessors","pendingSamplers","pendingTargets","channel","input","output","nodes","inputAccessors","outputAccessors","samplers","tracks","inputAccessor","outputAccessor","createdTracks","k","animation","AnimationClip","o","nodePending","childPending","childrenDef","skeletonPending","children","skeleton","pivot","pivotChild","nodeName","meshPromise","Bone","matrix","mapping","sceneIndex","sceneDef","nodeIds","reduceAssociations","reducedAssociations","targetName","collectMorphTargets","TypedKeyframeTrack","NumberKeyframeTrack","QuaternionKeyframeTrack","VectorKeyframeTrack","interpolation","outputArray","track","scaled","interpolantType","computeBounds","box","Box3","boxScale","maxDisplacement","vector","sphere","Sphere","assignAttributeAccessor","gltfAttributeName","ColorManagement","addBox","geo","addSphere","importModelFromFile","file","center","err","addModelByType","props","__props","emit","__emit","nodeRef","expandedSet","toggleExpand","inject","isExpanded","computed","hasChildren","childNodes","isSelected","watchEffect","handleSelect","handleDelete","getIcon","getDisplayName","_createElementBlock","_createElementVNode","_normalizeClass","_cache","_withModifiers","$event","_unref","_openBlock","_hoisted_1","_hoisted_2","_toDisplayString","_hoisted_3","_hoisted_4","_Fragment","_renderList","_createBlock","_component_TreeItem","useTreeExpand","selectedObject","newSet","expandPath","current","watch","emitChange","activeTab","treeVersion","selectedObjectRef","toRef","provide","handleTreeDelete","materialProps","reactive","hasStandardMaterial","readMaterialFromObject","stdMat","applyMaterialToObject","applied","onMaterialChange","newObj","read","TreeItem","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","_hoisted_14","_hoisted_15","_hoisted_16","_hoisted_17","_hoisted_18","_hoisted_19","_hoisted_20","_hoisted_21","showFileMenu","showEditMenu","showViewMenu","showHelpMenu","showAddMenu","showOpenSub","showOpenGrid","fileInput","triggerImport","onFileSelected","handleNew","handleSave","handleExport","handleUndo","handleRedo","handleDuplicate","handleResetCamera","handleToggleGrid","handleHelp","handleAbout","handleOpenProject","handleOpenModel","handleOpenScene","_withDirectives","selectedModel","syncTransformFromObject","applyTransformToObject","handlePropertyChange","handleAddModel","handleImportModel","treeData","shallowRef","initTree","handleTreeSelect","containerRef","init","onMounted","TopBar","PropertyPanel","BottomBar"],"mappings":"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","x_google_ignoreList":[0,1,3,4,5,6]}