vue-three-glb-viewer 0.1.0

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.
package/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # Vue 3 + TypeScript + Three.js GLB 查看器(可复用组件)
2
+
3
+ 封装好的 GLB 交互组件,支持锚点绑定、图标+名称显示、右键菜单、拖拽换锚、连线、相机保存/恢复(含 2D/3D 视角),并暴露完整方法供业务方调用。
4
+
5
+ ## 快速上手(作为依赖使用)
6
+
7
+ ```bash
8
+ npm install vue-three-glb-viewer three vue
9
+ ```
10
+
11
+ 在组件中使用:
12
+
13
+ ```vue
14
+ <template>
15
+ <GLBViewer ref="viewerRef" />
16
+ </template>
17
+
18
+ <script setup lang="ts">
19
+ import { ref, onMounted } from 'vue'
20
+ import { GLBViewer } from 'vue-three-glb-viewer'
21
+ import type { GLBViewerPublicAPI, BoundComponentData } from 'vue-three-glb-viewer'
22
+
23
+ const viewerRef = ref<GLBViewerPublicAPI | null>(null)
24
+
25
+ onMounted(() => {
26
+ // 示例:加载已有锚点数据
27
+ const saved: BoundComponentData[] = []
28
+ viewerRef.value?.setBoundComponentsData?.(saved)
29
+ })
30
+
31
+ // 示例:保存/恢复相机
32
+ const save2D = () => viewerRef.value?.saveCamera2D()
33
+ const load2D = () => viewerRef.value?.loadCamera2D()
34
+ </script>
35
+ ```
36
+
37
+ > 模型加载可配置:
38
+ > - 默认使用静态地址 `modelUrl`(默认 `/models/model.glb`)。
39
+ > - 可传入 `fetchModel`,返回 url / Blob / ArrayBuffer(例如从 API 获取),组件会自动创建 object URL 后加载。
40
+ > - 若加载失败将回退到默认立方体。
41
+ > - 若不希望点击模型自动创建绑定,传入 `:enableBindOnClick="false"`。
42
+ > - 设计/运行模式:传入 `:isDesignMode="false"` 时仅查看,不可绑定/拖拽/右键取消绑定。
43
+
44
+ 示例:从接口拉取二进制再加载
45
+
46
+ ```ts
47
+ const fetchModel = async () => {
48
+ const res = await fetch('/api/model')
49
+ if (!res.ok) throw new Error('fetch model failed')
50
+ return await res.arrayBuffer()
51
+ }
52
+ ```
53
+
54
+ 示例:改用自定义静态地址
55
+
56
+ ```vue
57
+ <GLBViewer modelUrl="/assets/scene.glb" />
58
+ ```
59
+
60
+ ## 暴露的 API(通过模板 ref 调用)
61
+
62
+ - 相机:
63
+ - `getCameraState()` / `setCameraState(state)`
64
+ - `saveCameraToLocalStorage()` / `loadCameraFromLocalStorage()`
65
+ - `saveCamera2D()` / `loadCamera2D()`
66
+ - `saveCamera3D()` / `loadCamera3D()`
67
+ - 绑定数据:
68
+ - `getBoundComponentsData(): BoundComponentData[]`
69
+ - `setBoundComponentsData(data: BoundComponentInput[]): boolean`
70
+ - 图标与元数据:
71
+ - `setComponentIcon(id, iconSrc)`
72
+ - `setComponentsIcons(iconMap: Record<number, string>)`
73
+ - `setComponentsMeta([{ id, name?, iconSrc? }, ...])`
74
+ - 回调:
75
+ - `setOnBindCallback((component) => void)`(用户点击模型新建锚点时触发)
76
+ - `setOnBindEnd((component) => boolean | void)`(绑定结束回调,可用于业务自定义)
77
+ - `setOnUnbind((componentId) => boolean | void)`(取消绑定时触发)
78
+ - `setOnMarkerClick((component) => void)`(用户点击标记时触发)
79
+ - `setOnMarkerContextMenu((component, event) => boolean | void)`(标记右键时触发;返回 false 可阻止默认菜单)
80
+ - `setOnMarkerDragEnd((component) => boolean | void)`(标记拖拽结束时触发)
81
+ - `unbindComponent(id: number)`(直接取消绑定并触发回调)
82
+
83
+ 主要数据结构(从包内导出):
84
+
85
+ - `CameraState`:`{ position: {x,y,z}, target: {x,y,z} }`
86
+ - `AnchorData`:`{ objectUUID: string, local: { x, y, z } }`
87
+ - `BoundComponentData`:`{ id, name, meshName?, iconSrc, anchor: AnchorData }`
88
+ - `BoundComponentInput`:用于导入,`anchor` 必填,其余可选。
89
+
90
+ ## 运行与构建(本仓库)
91
+
92
+ - 开发:`npm run dev`
93
+ - 生产构建:`npm run build`
94
+ - 库构建:`npm run build:lib`
95
+
96
+ ## 发布到 npm(提示)
97
+
98
+ 1) 确保 Node ≥ 20.19。2) 更新 `package.json` 的 version。3) 登录 npm:`npm login`。4) 发布:`npm publish`(若包名带 scope 用 `npm publish --access public`)。
99
+
100
+ ## 许可证
101
+
102
+ MIT
@@ -0,0 +1,4 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const R=require("vue"),l=require("three");function je(h){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(h){for(const t in h)if(t!=="default"){const s=Object.getOwnPropertyDescriptor(h,t);Object.defineProperty(e,t,s.get?s:{enumerable:!0,get:()=>h[t]})}}return e.default=h,Object.freeze(e)}const I=je(l);function ye(h,e){if(e===l.TrianglesDrawMode)return console.warn("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles."),h;if(e===l.TriangleFanDrawMode||e===l.TriangleStripDrawMode){let t=h.getIndex();if(t===null){const o=[],a=h.getAttribute("position");if(a!==void 0){for(let r=0;r<a.count;r++)o.push(r);h.setIndex(o),t=h.getIndex()}else return console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Undefined position attribute. Processing not possible."),h}const s=t.count-2,n=[];if(e===l.TriangleFanDrawMode)for(let o=1;o<=s;o++)n.push(t.getX(0)),n.push(t.getX(o)),n.push(t.getX(o+1));else for(let o=0;o<s;o++)o%2===0?(n.push(t.getX(o)),n.push(t.getX(o+1)),n.push(t.getX(o+2))):(n.push(t.getX(o+2)),n.push(t.getX(o+1)),n.push(t.getX(o)));n.length/3!==s&&console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unable to generate correct amount of triangles.");const i=h.clone();return i.setIndex(n),i.clearGroups(),i}else return console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:",e),h}class Fe extends l.Loader{constructor(e){super(e),this.dracoLoader=null,this.ktx2Loader=null,this.meshoptDecoder=null,this.pluginCallbacks=[],this.register(function(t){return new Ve(t)}),this.register(function(t){return new ze(t)}),this.register(function(t){return new et(t)}),this.register(function(t){return new tt(t)}),this.register(function(t){return new nt(t)}),this.register(function(t){return new Ye(t)}),this.register(function(t){return new We(t)}),this.register(function(t){return new Ze(t)}),this.register(function(t){return new qe(t)}),this.register(function(t){return new Ke(t)}),this.register(function(t){return new Qe(t)}),this.register(function(t){return new Xe(t)}),this.register(function(t){return new $e(t)}),this.register(function(t){return new Je(t)}),this.register(function(t){return new Be(t)}),this.register(function(t){return new st(t)}),this.register(function(t){return new it(t)})}load(e,t,s,n){const i=this;let o;if(this.resourcePath!=="")o=this.resourcePath;else if(this.path!==""){const c=l.LoaderUtils.extractUrlBase(e);o=l.LoaderUtils.resolveURL(c,this.path)}else o=l.LoaderUtils.extractUrlBase(e);this.manager.itemStart(e);const a=function(c){n?n(c):console.error(c),i.manager.itemError(e),i.manager.itemEnd(e)},r=new l.FileLoader(this.manager);r.setPath(this.path),r.setResponseType("arraybuffer"),r.setRequestHeader(this.requestHeader),r.setWithCredentials(this.withCredentials),r.load(e,function(c){try{i.parse(c,o,function(u){t(u),i.manager.itemEnd(e)},a)}catch(u){a(u)}},s,a)}setDRACOLoader(e){return this.dracoLoader=e,this}setKTX2Loader(e){return this.ktx2Loader=e,this}setMeshoptDecoder(e){return this.meshoptDecoder=e,this}register(e){return this.pluginCallbacks.indexOf(e)===-1&&this.pluginCallbacks.push(e),this}unregister(e){return this.pluginCallbacks.indexOf(e)!==-1&&this.pluginCallbacks.splice(this.pluginCallbacks.indexOf(e),1),this}parse(e,t,s,n){let i;const o={},a={},r=new TextDecoder;if(typeof e=="string")i=JSON.parse(e);else if(e instanceof ArrayBuffer)if(r.decode(new Uint8Array(e,0,4))===we){try{o[x.KHR_BINARY_GLTF]=new ot(e)}catch(d){n&&n(d);return}i=JSON.parse(o[x.KHR_BINARY_GLTF].content)}else i=JSON.parse(r.decode(e));else i=e;if(i.asset===void 0||i.asset.version[0]<2){n&&n(new Error("THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported."));return}const c=new Tt(i,{path:t||this.resourcePath||"",crossOrigin:this.crossOrigin,requestHeader:this.requestHeader,manager:this.manager,ktx2Loader:this.ktx2Loader,meshoptDecoder:this.meshoptDecoder});c.fileLoader.setRequestHeader(this.requestHeader);for(let u=0;u<this.pluginCallbacks.length;u++){const d=this.pluginCallbacks[u](c);d.name||console.error("THREE.GLTFLoader: Invalid plugin found: missing name"),a[d.name]=d,o[d.name]=!0}if(i.extensionsUsed)for(let u=0;u<i.extensionsUsed.length;++u){const d=i.extensionsUsed[u],p=i.extensionsRequired||[];switch(d){case x.KHR_MATERIALS_UNLIT:o[d]=new Ge;break;case x.KHR_DRACO_MESH_COMPRESSION:o[d]=new rt(i,this.dracoLoader);break;case x.KHR_TEXTURE_TRANSFORM:o[d]=new at;break;case x.KHR_MESH_QUANTIZATION:o[d]=new ct;break;default:p.indexOf(d)>=0&&a[d]===void 0&&console.warn('THREE.GLTFLoader: Unknown extension "'+d+'".')}}c.setExtensions(o),c.setPlugins(a),c.parse(s,n)}parseAsync(e,t){const s=this;return new Promise(function(n,i){s.parse(e,t,n,i)})}}function He(){let h={};return{get:function(e){return h[e]},add:function(e,t){h[e]=t},remove:function(e){delete h[e]},removeAll:function(){h={}}}}const x={KHR_BINARY_GLTF:"KHR_binary_glTF",KHR_DRACO_MESH_COMPRESSION:"KHR_draco_mesh_compression",KHR_LIGHTS_PUNCTUAL:"KHR_lights_punctual",KHR_MATERIALS_CLEARCOAT:"KHR_materials_clearcoat",KHR_MATERIALS_DISPERSION:"KHR_materials_dispersion",KHR_MATERIALS_IOR:"KHR_materials_ior",KHR_MATERIALS_SHEEN:"KHR_materials_sheen",KHR_MATERIALS_SPECULAR:"KHR_materials_specular",KHR_MATERIALS_TRANSMISSION:"KHR_materials_transmission",KHR_MATERIALS_IRIDESCENCE:"KHR_materials_iridescence",KHR_MATERIALS_ANISOTROPY:"KHR_materials_anisotropy",KHR_MATERIALS_UNLIT:"KHR_materials_unlit",KHR_MATERIALS_VOLUME:"KHR_materials_volume",KHR_TEXTURE_BASISU:"KHR_texture_basisu",KHR_TEXTURE_TRANSFORM:"KHR_texture_transform",KHR_MESH_QUANTIZATION:"KHR_mesh_quantization",KHR_MATERIALS_EMISSIVE_STRENGTH:"KHR_materials_emissive_strength",EXT_MATERIALS_BUMP:"EXT_materials_bump",EXT_TEXTURE_WEBP:"EXT_texture_webp",EXT_TEXTURE_AVIF:"EXT_texture_avif",EXT_MESHOPT_COMPRESSION:"EXT_meshopt_compression",EXT_MESH_GPU_INSTANCING:"EXT_mesh_gpu_instancing"};class Be{constructor(e){this.parser=e,this.name=x.KHR_LIGHTS_PUNCTUAL,this.cache={refs:{},uses:{}}}_markDefs(){const e=this.parser,t=this.parser.json.nodes||[];for(let s=0,n=t.length;s<n;s++){const i=t[s];i.extensions&&i.extensions[this.name]&&i.extensions[this.name].light!==void 0&&e._addNodeRef(this.cache,i.extensions[this.name].light)}}_loadLight(e){const t=this.parser,s="light:"+e;let n=t.cache.get(s);if(n)return n;const i=t.json,r=((i.extensions&&i.extensions[this.name]||{}).lights||[])[e];let c;const u=new l.Color(16777215);r.color!==void 0&&u.setRGB(r.color[0],r.color[1],r.color[2],l.LinearSRGBColorSpace);const d=r.range!==void 0?r.range:0;switch(r.type){case"directional":c=new l.DirectionalLight(u),c.target.position.set(0,0,-1),c.add(c.target);break;case"point":c=new l.PointLight(u),c.distance=d;break;case"spot":c=new l.SpotLight(u),c.distance=d,r.spot=r.spot||{},r.spot.innerConeAngle=r.spot.innerConeAngle!==void 0?r.spot.innerConeAngle:0,r.spot.outerConeAngle=r.spot.outerConeAngle!==void 0?r.spot.outerConeAngle:Math.PI/4,c.angle=r.spot.outerConeAngle,c.penumbra=1-r.spot.innerConeAngle/r.spot.outerConeAngle,c.target.position.set(0,0,-1),c.add(c.target);break;default:throw new Error("THREE.GLTFLoader: Unexpected light type: "+r.type)}return c.position.set(0,0,0),j(c,r),r.intensity!==void 0&&(c.intensity=r.intensity),c.name=t.createUniqueName(r.name||"light_"+e),n=Promise.resolve(c),t.cache.add(s,n),n}getDependency(e,t){if(e==="light")return this._loadLight(t)}createNodeAttachment(e){const t=this,s=this.parser,i=s.json.nodes[e],a=(i.extensions&&i.extensions[this.name]||{}).light;return a===void 0?null:this._loadLight(a).then(function(r){return s._getNodeRef(t.cache,a,r)})}}class Ge{constructor(){this.name=x.KHR_MATERIALS_UNLIT}getMaterialType(){return l.MeshBasicMaterial}extendParams(e,t,s){const n=[];e.color=new l.Color(1,1,1),e.opacity=1;const i=t.pbrMetallicRoughness;if(i){if(Array.isArray(i.baseColorFactor)){const o=i.baseColorFactor;e.color.setRGB(o[0],o[1],o[2],l.LinearSRGBColorSpace),e.opacity=o[3]}i.baseColorTexture!==void 0&&n.push(s.assignTexture(e,"map",i.baseColorTexture,l.SRGBColorSpace))}return Promise.all(n)}}class Ke{constructor(e){this.parser=e,this.name=x.KHR_MATERIALS_EMISSIVE_STRENGTH}extendMaterialParams(e,t){const n=this.parser.json.materials[e];if(!n.extensions||!n.extensions[this.name])return Promise.resolve();const i=n.extensions[this.name].emissiveStrength;return i!==void 0&&(t.emissiveIntensity=i),Promise.resolve()}}class Ve{constructor(e){this.parser=e,this.name=x.KHR_MATERIALS_CLEARCOAT}getMaterialType(e){const s=this.parser.json.materials[e];return!s.extensions||!s.extensions[this.name]?null:l.MeshPhysicalMaterial}extendMaterialParams(e,t){const s=this.parser,n=s.json.materials[e];if(!n.extensions||!n.extensions[this.name])return Promise.resolve();const i=[],o=n.extensions[this.name];if(o.clearcoatFactor!==void 0&&(t.clearcoat=o.clearcoatFactor),o.clearcoatTexture!==void 0&&i.push(s.assignTexture(t,"clearcoatMap",o.clearcoatTexture)),o.clearcoatRoughnessFactor!==void 0&&(t.clearcoatRoughness=o.clearcoatRoughnessFactor),o.clearcoatRoughnessTexture!==void 0&&i.push(s.assignTexture(t,"clearcoatRoughnessMap",o.clearcoatRoughnessTexture)),o.clearcoatNormalTexture!==void 0&&(i.push(s.assignTexture(t,"clearcoatNormalMap",o.clearcoatNormalTexture)),o.clearcoatNormalTexture.scale!==void 0)){const a=o.clearcoatNormalTexture.scale;t.clearcoatNormalScale=new l.Vector2(a,a)}return Promise.all(i)}}class ze{constructor(e){this.parser=e,this.name=x.KHR_MATERIALS_DISPERSION}getMaterialType(e){const s=this.parser.json.materials[e];return!s.extensions||!s.extensions[this.name]?null:l.MeshPhysicalMaterial}extendMaterialParams(e,t){const n=this.parser.json.materials[e];if(!n.extensions||!n.extensions[this.name])return Promise.resolve();const i=n.extensions[this.name];return t.dispersion=i.dispersion!==void 0?i.dispersion:0,Promise.resolve()}}class Xe{constructor(e){this.parser=e,this.name=x.KHR_MATERIALS_IRIDESCENCE}getMaterialType(e){const s=this.parser.json.materials[e];return!s.extensions||!s.extensions[this.name]?null:l.MeshPhysicalMaterial}extendMaterialParams(e,t){const s=this.parser,n=s.json.materials[e];if(!n.extensions||!n.extensions[this.name])return Promise.resolve();const i=[],o=n.extensions[this.name];return o.iridescenceFactor!==void 0&&(t.iridescence=o.iridescenceFactor),o.iridescenceTexture!==void 0&&i.push(s.assignTexture(t,"iridescenceMap",o.iridescenceTexture)),o.iridescenceIor!==void 0&&(t.iridescenceIOR=o.iridescenceIor),t.iridescenceThicknessRange===void 0&&(t.iridescenceThicknessRange=[100,400]),o.iridescenceThicknessMinimum!==void 0&&(t.iridescenceThicknessRange[0]=o.iridescenceThicknessMinimum),o.iridescenceThicknessMaximum!==void 0&&(t.iridescenceThicknessRange[1]=o.iridescenceThicknessMaximum),o.iridescenceThicknessTexture!==void 0&&i.push(s.assignTexture(t,"iridescenceThicknessMap",o.iridescenceThicknessTexture)),Promise.all(i)}}class Ye{constructor(e){this.parser=e,this.name=x.KHR_MATERIALS_SHEEN}getMaterialType(e){const s=this.parser.json.materials[e];return!s.extensions||!s.extensions[this.name]?null:l.MeshPhysicalMaterial}extendMaterialParams(e,t){const s=this.parser,n=s.json.materials[e];if(!n.extensions||!n.extensions[this.name])return Promise.resolve();const i=[];t.sheenColor=new l.Color(0,0,0),t.sheenRoughness=0,t.sheen=1;const o=n.extensions[this.name];if(o.sheenColorFactor!==void 0){const a=o.sheenColorFactor;t.sheenColor.setRGB(a[0],a[1],a[2],l.LinearSRGBColorSpace)}return o.sheenRoughnessFactor!==void 0&&(t.sheenRoughness=o.sheenRoughnessFactor),o.sheenColorTexture!==void 0&&i.push(s.assignTexture(t,"sheenColorMap",o.sheenColorTexture,l.SRGBColorSpace)),o.sheenRoughnessTexture!==void 0&&i.push(s.assignTexture(t,"sheenRoughnessMap",o.sheenRoughnessTexture)),Promise.all(i)}}class We{constructor(e){this.parser=e,this.name=x.KHR_MATERIALS_TRANSMISSION}getMaterialType(e){const s=this.parser.json.materials[e];return!s.extensions||!s.extensions[this.name]?null:l.MeshPhysicalMaterial}extendMaterialParams(e,t){const s=this.parser,n=s.json.materials[e];if(!n.extensions||!n.extensions[this.name])return Promise.resolve();const i=[],o=n.extensions[this.name];return o.transmissionFactor!==void 0&&(t.transmission=o.transmissionFactor),o.transmissionTexture!==void 0&&i.push(s.assignTexture(t,"transmissionMap",o.transmissionTexture)),Promise.all(i)}}class Ze{constructor(e){this.parser=e,this.name=x.KHR_MATERIALS_VOLUME}getMaterialType(e){const s=this.parser.json.materials[e];return!s.extensions||!s.extensions[this.name]?null:l.MeshPhysicalMaterial}extendMaterialParams(e,t){const s=this.parser,n=s.json.materials[e];if(!n.extensions||!n.extensions[this.name])return Promise.resolve();const i=[],o=n.extensions[this.name];t.thickness=o.thicknessFactor!==void 0?o.thicknessFactor:0,o.thicknessTexture!==void 0&&i.push(s.assignTexture(t,"thicknessMap",o.thicknessTexture)),t.attenuationDistance=o.attenuationDistance||1/0;const a=o.attenuationColor||[1,1,1];return t.attenuationColor=new l.Color().setRGB(a[0],a[1],a[2],l.LinearSRGBColorSpace),Promise.all(i)}}class qe{constructor(e){this.parser=e,this.name=x.KHR_MATERIALS_IOR}getMaterialType(e){const s=this.parser.json.materials[e];return!s.extensions||!s.extensions[this.name]?null:l.MeshPhysicalMaterial}extendMaterialParams(e,t){const n=this.parser.json.materials[e];if(!n.extensions||!n.extensions[this.name])return Promise.resolve();const i=n.extensions[this.name];return t.ior=i.ior!==void 0?i.ior:1.5,Promise.resolve()}}class Qe{constructor(e){this.parser=e,this.name=x.KHR_MATERIALS_SPECULAR}getMaterialType(e){const s=this.parser.json.materials[e];return!s.extensions||!s.extensions[this.name]?null:l.MeshPhysicalMaterial}extendMaterialParams(e,t){const s=this.parser,n=s.json.materials[e];if(!n.extensions||!n.extensions[this.name])return Promise.resolve();const i=[],o=n.extensions[this.name];t.specularIntensity=o.specularFactor!==void 0?o.specularFactor:1,o.specularTexture!==void 0&&i.push(s.assignTexture(t,"specularIntensityMap",o.specularTexture));const a=o.specularColorFactor||[1,1,1];return t.specularColor=new l.Color().setRGB(a[0],a[1],a[2],l.LinearSRGBColorSpace),o.specularColorTexture!==void 0&&i.push(s.assignTexture(t,"specularColorMap",o.specularColorTexture,l.SRGBColorSpace)),Promise.all(i)}}class Je{constructor(e){this.parser=e,this.name=x.EXT_MATERIALS_BUMP}getMaterialType(e){const s=this.parser.json.materials[e];return!s.extensions||!s.extensions[this.name]?null:l.MeshPhysicalMaterial}extendMaterialParams(e,t){const s=this.parser,n=s.json.materials[e];if(!n.extensions||!n.extensions[this.name])return Promise.resolve();const i=[],o=n.extensions[this.name];return t.bumpScale=o.bumpFactor!==void 0?o.bumpFactor:1,o.bumpTexture!==void 0&&i.push(s.assignTexture(t,"bumpMap",o.bumpTexture)),Promise.all(i)}}class $e{constructor(e){this.parser=e,this.name=x.KHR_MATERIALS_ANISOTROPY}getMaterialType(e){const s=this.parser.json.materials[e];return!s.extensions||!s.extensions[this.name]?null:l.MeshPhysicalMaterial}extendMaterialParams(e,t){const s=this.parser,n=s.json.materials[e];if(!n.extensions||!n.extensions[this.name])return Promise.resolve();const i=[],o=n.extensions[this.name];return o.anisotropyStrength!==void 0&&(t.anisotropy=o.anisotropyStrength),o.anisotropyRotation!==void 0&&(t.anisotropyRotation=o.anisotropyRotation),o.anisotropyTexture!==void 0&&i.push(s.assignTexture(t,"anisotropyMap",o.anisotropyTexture)),Promise.all(i)}}class et{constructor(e){this.parser=e,this.name=x.KHR_TEXTURE_BASISU}loadTexture(e){const t=this.parser,s=t.json,n=s.textures[e];if(!n.extensions||!n.extensions[this.name])return null;const i=n.extensions[this.name],o=t.options.ktx2Loader;if(!o){if(s.extensionsRequired&&s.extensionsRequired.indexOf(this.name)>=0)throw new Error("THREE.GLTFLoader: setKTX2Loader must be called before loading KTX2 textures");return null}return t.loadTextureImage(e,i.source,o)}}class tt{constructor(e){this.parser=e,this.name=x.EXT_TEXTURE_WEBP}loadTexture(e){const t=this.name,s=this.parser,n=s.json,i=n.textures[e];if(!i.extensions||!i.extensions[t])return null;const o=i.extensions[t],a=n.images[o.source];let r=s.textureLoader;if(a.uri){const c=s.options.manager.getHandler(a.uri);c!==null&&(r=c)}return s.loadTextureImage(e,o.source,r)}}class nt{constructor(e){this.parser=e,this.name=x.EXT_TEXTURE_AVIF}loadTexture(e){const t=this.name,s=this.parser,n=s.json,i=n.textures[e];if(!i.extensions||!i.extensions[t])return null;const o=i.extensions[t],a=n.images[o.source];let r=s.textureLoader;if(a.uri){const c=s.options.manager.getHandler(a.uri);c!==null&&(r=c)}return s.loadTextureImage(e,o.source,r)}}class st{constructor(e){this.name=x.EXT_MESHOPT_COMPRESSION,this.parser=e}loadBufferView(e){const t=this.parser.json,s=t.bufferViews[e];if(s.extensions&&s.extensions[this.name]){const n=s.extensions[this.name],i=this.parser.getDependency("buffer",n.buffer),o=this.parser.options.meshoptDecoder;if(!o||!o.supported){if(t.extensionsRequired&&t.extensionsRequired.indexOf(this.name)>=0)throw new Error("THREE.GLTFLoader: setMeshoptDecoder must be called before loading compressed files");return null}return i.then(function(a){const r=n.byteOffset||0,c=n.byteLength||0,u=n.count,d=n.byteStride,p=new Uint8Array(a,r,c);return o.decodeGltfBufferAsync?o.decodeGltfBufferAsync(u,d,p,n.mode,n.filter).then(function(m){return m.buffer}):o.ready.then(function(){const m=new ArrayBuffer(u*d);return o.decodeGltfBuffer(new Uint8Array(m),u,d,p,n.mode,n.filter),m})})}else return null}}class it{constructor(e){this.name=x.EXT_MESH_GPU_INSTANCING,this.parser=e}createNodeMesh(e){const t=this.parser.json,s=t.nodes[e];if(!s.extensions||!s.extensions[this.name]||s.mesh===void 0)return null;const n=t.meshes[s.mesh];for(const c of n.primitives)if(c.mode!==U.TRIANGLES&&c.mode!==U.TRIANGLE_STRIP&&c.mode!==U.TRIANGLE_FAN&&c.mode!==void 0)return null;const o=s.extensions[this.name].attributes,a=[],r={};for(const c in o)a.push(this.parser.getDependency("accessor",o[c]).then(u=>(r[c]=u,r[c])));return a.length<1?null:(a.push(this.parser.createNodeMesh(e)),Promise.all(a).then(c=>{const u=c.pop(),d=u.isGroup?u.children:[u],p=c[0].count,m=[];for(const b of d){const M=new l.Matrix4,y=new l.Vector3,T=new l.Quaternion,L=new l.Vector3(1,1,1),A=new l.InstancedMesh(b.geometry,b.material,p);for(let S=0;S<p;S++)r.TRANSLATION&&y.fromBufferAttribute(r.TRANSLATION,S),r.ROTATION&&T.fromBufferAttribute(r.ROTATION,S),r.SCALE&&L.fromBufferAttribute(r.SCALE,S),A.setMatrixAt(S,M.compose(y,T,L));for(const S in r)if(S==="_COLOR_0"){const O=r[S];A.instanceColor=new l.InstancedBufferAttribute(O.array,O.itemSize,O.normalized)}else S!=="TRANSLATION"&&S!=="ROTATION"&&S!=="SCALE"&&b.geometry.setAttribute(S,r[S]);l.Object3D.prototype.copy.call(A,b),this.parser.assignFinalMaterial(A),m.push(A)}return u.isGroup?(u.clear(),u.add(...m),u):m[0]}))}}const we="glTF",W=12,be={JSON:1313821514,BIN:5130562};class ot{constructor(e){this.name=x.KHR_BINARY_GLTF,this.content=null,this.body=null;const t=new DataView(e,0,W),s=new TextDecoder;if(this.header={magic:s.decode(new Uint8Array(e.slice(0,4))),version:t.getUint32(4,!0),length:t.getUint32(8,!0)},this.header.magic!==we)throw new Error("THREE.GLTFLoader: Unsupported glTF-Binary header.");if(this.header.version<2)throw new Error("THREE.GLTFLoader: Legacy binary file detected.");const n=this.header.length-W,i=new DataView(e,W);let o=0;for(;o<n;){const a=i.getUint32(o,!0);o+=4;const r=i.getUint32(o,!0);if(o+=4,r===be.JSON){const c=new Uint8Array(e,W+o,a);this.content=s.decode(c)}else if(r===be.BIN){const c=W+o;this.body=e.slice(c,c+a)}o+=a}if(this.content===null)throw new Error("THREE.GLTFLoader: JSON content not found.")}}class rt{constructor(e,t){if(!t)throw new Error("THREE.GLTFLoader: No DRACOLoader instance provided.");this.name=x.KHR_DRACO_MESH_COMPRESSION,this.json=e,this.dracoLoader=t,this.dracoLoader.preload()}decodePrimitive(e,t){const s=this.json,n=this.dracoLoader,i=e.extensions[this.name].bufferView,o=e.extensions[this.name].attributes,a={},r={},c={};for(const u in o){const d=ne[u]||u.toLowerCase();a[d]=o[u]}for(const u in e.attributes){const d=ne[u]||u.toLowerCase();if(o[u]!==void 0){const p=s.accessors[e.attributes[u]],m=z[p.componentType];c[d]=m.name,r[d]=p.normalized===!0}}return t.getDependency("bufferView",i).then(function(u){return new Promise(function(d,p){n.decodeDracoFile(u,function(m){for(const b in m.attributes){const M=m.attributes[b],y=r[b];y!==void 0&&(M.normalized=y)}d(m)},a,c,l.LinearSRGBColorSpace,p)})})}}class at{constructor(){this.name=x.KHR_TEXTURE_TRANSFORM}extendTexture(e,t){return(t.texCoord===void 0||t.texCoord===e.channel)&&t.offset===void 0&&t.rotation===void 0&&t.scale===void 0||(e=e.clone(),t.texCoord!==void 0&&(e.channel=t.texCoord),t.offset!==void 0&&e.offset.fromArray(t.offset),t.rotation!==void 0&&(e.rotation=t.rotation),t.scale!==void 0&&e.repeat.fromArray(t.scale),e.needsUpdate=!0),e}}class ct{constructor(){this.name=x.KHR_MESH_QUANTIZATION}}class Le extends l.Interpolant{constructor(e,t,s,n){super(e,t,s,n)}copySampleValue_(e){const t=this.resultBuffer,s=this.sampleValues,n=this.valueSize,i=e*n*3+n;for(let o=0;o!==n;o++)t[o]=s[i+o];return t}interpolate_(e,t,s,n){const i=this.resultBuffer,o=this.sampleValues,a=this.valueSize,r=a*2,c=a*3,u=n-t,d=(s-t)/u,p=d*d,m=p*d,b=e*c,M=b-c,y=-2*m+3*p,T=m-p,L=1-y,A=T-p+d;for(let S=0;S!==a;S++){const O=o[M+S+a],v=o[M+S+r]*u,N=o[b+S+a],F=o[b+S]*u;i[S]=L*O+A*v+y*N+T*F}return i}}const lt=new l.Quaternion;class ht extends Le{interpolate_(e,t,s,n){const i=super.interpolate_(e,t,s,n);return lt.fromArray(i).normalize().toArray(i),i}}const U={POINTS:0,LINES:1,LINE_LOOP:2,LINE_STRIP:3,TRIANGLES:4,TRIANGLE_STRIP:5,TRIANGLE_FAN:6},z={5120:Int8Array,5121:Uint8Array,5122:Int16Array,5123:Uint16Array,5125:Uint32Array,5126:Float32Array},Ee={9728:l.NearestFilter,9729:l.LinearFilter,9984:l.NearestMipmapNearestFilter,9985:l.LinearMipmapNearestFilter,9986:l.NearestMipmapLinearFilter,9987:l.LinearMipmapLinearFilter},xe={33071:l.ClampToEdgeWrapping,33648:l.MirroredRepeatWrapping,10497:l.RepeatWrapping},J={SCALAR:1,VEC2:2,VEC3:3,VEC4:4,MAT2:4,MAT3:9,MAT4:16},ne={POSITION:"position",NORMAL:"normal",TANGENT:"tangent",TEXCOORD_0:"uv",TEXCOORD_1:"uv1",TEXCOORD_2:"uv2",TEXCOORD_3:"uv3",COLOR_0:"color",WEIGHTS_0:"skinWeight",JOINTS_0:"skinIndex"},G={scale:"scale",translation:"position",rotation:"quaternion",weights:"morphTargetInfluences"},ut={CUBICSPLINE:void 0,LINEAR:l.InterpolateLinear,STEP:l.InterpolateDiscrete},$={OPAQUE:"OPAQUE",MASK:"MASK",BLEND:"BLEND"};function dt(h){return h.DefaultMaterial===void 0&&(h.DefaultMaterial=new l.MeshStandardMaterial({color:16777215,emissive:0,metalness:1,roughness:1,transparent:!1,depthTest:!0,side:l.FrontSide})),h.DefaultMaterial}function V(h,e,t){for(const s in t.extensions)h[s]===void 0&&(e.userData.gltfExtensions=e.userData.gltfExtensions||{},e.userData.gltfExtensions[s]=t.extensions[s])}function j(h,e){e.extras!==void 0&&(typeof e.extras=="object"?Object.assign(h.userData,e.extras):console.warn("THREE.GLTFLoader: Ignoring primitive type .extras, "+e.extras))}function ft(h,e,t){let s=!1,n=!1,i=!1;for(let c=0,u=e.length;c<u;c++){const d=e[c];if(d.POSITION!==void 0&&(s=!0),d.NORMAL!==void 0&&(n=!0),d.COLOR_0!==void 0&&(i=!0),s&&n&&i)break}if(!s&&!n&&!i)return Promise.resolve(h);const o=[],a=[],r=[];for(let c=0,u=e.length;c<u;c++){const d=e[c];if(s){const p=d.POSITION!==void 0?t.getDependency("accessor",d.POSITION):h.attributes.position;o.push(p)}if(n){const p=d.NORMAL!==void 0?t.getDependency("accessor",d.NORMAL):h.attributes.normal;a.push(p)}if(i){const p=d.COLOR_0!==void 0?t.getDependency("accessor",d.COLOR_0):h.attributes.color;r.push(p)}}return Promise.all([Promise.all(o),Promise.all(a),Promise.all(r)]).then(function(c){const u=c[0],d=c[1],p=c[2];return s&&(h.morphAttributes.position=u),n&&(h.morphAttributes.normal=d),i&&(h.morphAttributes.color=p),h.morphTargetsRelative=!0,h})}function pt(h,e){if(h.updateMorphTargets(),e.weights!==void 0)for(let t=0,s=e.weights.length;t<s;t++)h.morphTargetInfluences[t]=e.weights[t];if(e.extras&&Array.isArray(e.extras.targetNames)){const t=e.extras.targetNames;if(h.morphTargetInfluences.length===t.length){h.morphTargetDictionary={};for(let s=0,n=t.length;s<n;s++)h.morphTargetDictionary[t[s]]=s}else console.warn("THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.")}}function mt(h){let e;const t=h.extensions&&h.extensions[x.KHR_DRACO_MESH_COMPRESSION];if(t?e="draco:"+t.bufferView+":"+t.indices+":"+ee(t.attributes):e=h.indices+":"+ee(h.attributes)+":"+h.mode,h.targets!==void 0)for(let s=0,n=h.targets.length;s<n;s++)e+=":"+ee(h.targets[s]);return e}function ee(h){let e="";const t=Object.keys(h).sort();for(let s=0,n=t.length;s<n;s++)e+=t[s]+":"+h[t[s]]+";";return e}function se(h){switch(h){case Int8Array:return 1/127;case Uint8Array:return 1/255;case Int16Array:return 1/32767;case Uint16Array:return 1/65535;default:throw new Error("THREE.GLTFLoader: Unsupported normalized accessor component type.")}}function gt(h){return h.search(/\.jpe?g($|\?)/i)>0||h.search(/^data\:image\/jpeg/)===0?"image/jpeg":h.search(/\.webp($|\?)/i)>0||h.search(/^data\:image\/webp/)===0?"image/webp":h.search(/\.ktx2($|\?)/i)>0||h.search(/^data\:image\/ktx2/)===0?"image/ktx2":"image/png"}const _t=new l.Matrix4;class Tt{constructor(e={},t={}){this.json=e,this.extensions={},this.plugins={},this.options=t,this.cache=new He,this.associations=new Map,this.primitiveCache={},this.nodeCache={},this.meshCache={refs:{},uses:{}},this.cameraCache={refs:{},uses:{}},this.lightCache={refs:{},uses:{}},this.sourceCache={},this.textureCache={},this.nodeNamesUsed={};let s=!1,n=-1,i=!1,o=-1;if(typeof navigator<"u"){const a=navigator.userAgent;s=/^((?!chrome|android).)*safari/i.test(a)===!0;const r=a.match(/Version\/(\d+)/);n=s&&r?parseInt(r[1],10):-1,i=a.indexOf("Firefox")>-1,o=i?a.match(/Firefox\/([0-9]+)\./)[1]:-1}typeof createImageBitmap>"u"||s&&n<17||i&&o<98?this.textureLoader=new l.TextureLoader(this.options.manager):this.textureLoader=new l.ImageBitmapLoader(this.options.manager),this.textureLoader.setCrossOrigin(this.options.crossOrigin),this.textureLoader.setRequestHeader(this.options.requestHeader),this.fileLoader=new l.FileLoader(this.options.manager),this.fileLoader.setResponseType("arraybuffer"),this.options.crossOrigin==="use-credentials"&&this.fileLoader.setWithCredentials(!0)}setExtensions(e){this.extensions=e}setPlugins(e){this.plugins=e}parse(e,t){const s=this,n=this.json,i=this.extensions;this.cache.removeAll(),this.nodeCache={},this._invokeAll(function(o){return o._markDefs&&o._markDefs()}),Promise.all(this._invokeAll(function(o){return o.beforeRoot&&o.beforeRoot()})).then(function(){return Promise.all([s.getDependencies("scene"),s.getDependencies("animation"),s.getDependencies("camera")])}).then(function(o){const a={scene:o[0][n.scene||0],scenes:o[0],animations:o[1],cameras:o[2],asset:n.asset,parser:s,userData:{}};return V(i,a,n),j(a,n),Promise.all(s._invokeAll(function(r){return r.afterRoot&&r.afterRoot(a)})).then(function(){for(const r of a.scenes)r.updateMatrixWorld();e(a)})}).catch(t)}_markDefs(){const e=this.json.nodes||[],t=this.json.skins||[],s=this.json.meshes||[];for(let n=0,i=t.length;n<i;n++){const o=t[n].joints;for(let a=0,r=o.length;a<r;a++)e[o[a]].isBone=!0}for(let n=0,i=e.length;n<i;n++){const o=e[n];o.mesh!==void 0&&(this._addNodeRef(this.meshCache,o.mesh),o.skin!==void 0&&(s[o.mesh].isSkinnedMesh=!0)),o.camera!==void 0&&this._addNodeRef(this.cameraCache,o.camera)}}_addNodeRef(e,t){t!==void 0&&(e.refs[t]===void 0&&(e.refs[t]=e.uses[t]=0),e.refs[t]++)}_getNodeRef(e,t,s){if(e.refs[t]<=1)return s;const n=s.clone(),i=(o,a)=>{const r=this.associations.get(o);r!=null&&this.associations.set(a,r);for(const[c,u]of o.children.entries())i(u,a.children[c])};return i(s,n),n.name+="_instance_"+e.uses[t]++,n}_invokeOne(e){const t=Object.values(this.plugins);t.push(this);for(let s=0;s<t.length;s++){const n=e(t[s]);if(n)return n}return null}_invokeAll(e){const t=Object.values(this.plugins);t.unshift(this);const s=[];for(let n=0;n<t.length;n++){const i=e(t[n]);i&&s.push(i)}return s}getDependency(e,t){const s=e+":"+t;let n=this.cache.get(s);if(!n){switch(e){case"scene":n=this.loadScene(t);break;case"node":n=this._invokeOne(function(i){return i.loadNode&&i.loadNode(t)});break;case"mesh":n=this._invokeOne(function(i){return i.loadMesh&&i.loadMesh(t)});break;case"accessor":n=this.loadAccessor(t);break;case"bufferView":n=this._invokeOne(function(i){return i.loadBufferView&&i.loadBufferView(t)});break;case"buffer":n=this.loadBuffer(t);break;case"material":n=this._invokeOne(function(i){return i.loadMaterial&&i.loadMaterial(t)});break;case"texture":n=this._invokeOne(function(i){return i.loadTexture&&i.loadTexture(t)});break;case"skin":n=this.loadSkin(t);break;case"animation":n=this._invokeOne(function(i){return i.loadAnimation&&i.loadAnimation(t)});break;case"camera":n=this.loadCamera(t);break;default:if(n=this._invokeOne(function(i){return i!=this&&i.getDependency&&i.getDependency(e,t)}),!n)throw new Error("Unknown type: "+e);break}this.cache.add(s,n)}return n}getDependencies(e){let t=this.cache.get(e);if(!t){const s=this,n=this.json[e+(e==="mesh"?"es":"s")]||[];t=Promise.all(n.map(function(i,o){return s.getDependency(e,o)})),this.cache.add(e,t)}return t}loadBuffer(e){const t=this.json.buffers[e],s=this.fileLoader;if(t.type&&t.type!=="arraybuffer")throw new Error("THREE.GLTFLoader: "+t.type+" buffer type is not supported.");if(t.uri===void 0&&e===0)return Promise.resolve(this.extensions[x.KHR_BINARY_GLTF].body);const n=this.options;return new Promise(function(i,o){s.load(l.LoaderUtils.resolveURL(t.uri,n.path),i,void 0,function(){o(new Error('THREE.GLTFLoader: Failed to load buffer "'+t.uri+'".'))})})}loadBufferView(e){const t=this.json.bufferViews[e];return this.getDependency("buffer",t.buffer).then(function(s){const n=t.byteLength||0,i=t.byteOffset||0;return s.slice(i,i+n)})}loadAccessor(e){const t=this,s=this.json,n=this.json.accessors[e];if(n.bufferView===void 0&&n.sparse===void 0){const o=J[n.type],a=z[n.componentType],r=n.normalized===!0,c=new a(n.count*o);return Promise.resolve(new l.BufferAttribute(c,o,r))}const i=[];return n.bufferView!==void 0?i.push(this.getDependency("bufferView",n.bufferView)):i.push(null),n.sparse!==void 0&&(i.push(this.getDependency("bufferView",n.sparse.indices.bufferView)),i.push(this.getDependency("bufferView",n.sparse.values.bufferView))),Promise.all(i).then(function(o){const a=o[0],r=J[n.type],c=z[n.componentType],u=c.BYTES_PER_ELEMENT,d=u*r,p=n.byteOffset||0,m=n.bufferView!==void 0?s.bufferViews[n.bufferView].byteStride:void 0,b=n.normalized===!0;let M,y;if(m&&m!==d){const T=Math.floor(p/m),L="InterleavedBuffer:"+n.bufferView+":"+n.componentType+":"+T+":"+n.count;let A=t.cache.get(L);A||(M=new c(a,T*m,n.count*m/u),A=new l.InterleavedBuffer(M,m/u),t.cache.add(L,A)),y=new l.InterleavedBufferAttribute(A,r,p%m/u,b)}else a===null?M=new c(n.count*r):M=new c(a,p,n.count*r),y=new l.BufferAttribute(M,r,b);if(n.sparse!==void 0){const T=J.SCALAR,L=z[n.sparse.indices.componentType],A=n.sparse.indices.byteOffset||0,S=n.sparse.values.byteOffset||0,O=new L(o[1],A,n.sparse.count*T),v=new c(o[2],S,n.sparse.count*r);a!==null&&(y=new l.BufferAttribute(y.array.slice(),y.itemSize,y.normalized)),y.normalized=!1;for(let N=0,F=O.length;N<F;N++){const H=O[N];if(y.setX(H,v[N*r]),r>=2&&y.setY(H,v[N*r+1]),r>=3&&y.setZ(H,v[N*r+2]),r>=4&&y.setW(H,v[N*r+3]),r>=5)throw new Error("THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.")}y.normalized=b}return y})}loadTexture(e){const t=this.json,s=this.options,i=t.textures[e].source,o=t.images[i];let a=this.textureLoader;if(o.uri){const r=s.manager.getHandler(o.uri);r!==null&&(a=r)}return this.loadTextureImage(e,i,a)}loadTextureImage(e,t,s){const n=this,i=this.json,o=i.textures[e],a=i.images[t],r=(a.uri||a.bufferView)+":"+o.sampler;if(this.textureCache[r])return this.textureCache[r];const c=this.loadImageSource(t,s).then(function(u){u.flipY=!1,u.name=o.name||a.name||"",u.name===""&&typeof a.uri=="string"&&a.uri.startsWith("data:image/")===!1&&(u.name=a.uri);const p=(i.samplers||{})[o.sampler]||{};return u.magFilter=Ee[p.magFilter]||l.LinearFilter,u.minFilter=Ee[p.minFilter]||l.LinearMipmapLinearFilter,u.wrapS=xe[p.wrapS]||l.RepeatWrapping,u.wrapT=xe[p.wrapT]||l.RepeatWrapping,u.generateMipmaps=!u.isCompressedTexture&&u.minFilter!==l.NearestFilter&&u.minFilter!==l.LinearFilter,n.associations.set(u,{textures:e}),u}).catch(function(){return null});return this.textureCache[r]=c,c}loadImageSource(e,t){const s=this,n=this.json,i=this.options;if(this.sourceCache[e]!==void 0)return this.sourceCache[e].then(d=>d.clone());const o=n.images[e],a=self.URL||self.webkitURL;let r=o.uri||"",c=!1;if(o.bufferView!==void 0)r=s.getDependency("bufferView",o.bufferView).then(function(d){c=!0;const p=new Blob([d],{type:o.mimeType});return r=a.createObjectURL(p),r});else if(o.uri===void 0)throw new Error("THREE.GLTFLoader: Image "+e+" is missing URI and bufferView");const u=Promise.resolve(r).then(function(d){return new Promise(function(p,m){let b=p;t.isImageBitmapLoader===!0&&(b=function(M){const y=new l.Texture(M);y.needsUpdate=!0,p(y)}),t.load(l.LoaderUtils.resolveURL(d,i.path),b,void 0,m)})}).then(function(d){return c===!0&&a.revokeObjectURL(r),j(d,o),d.userData.mimeType=o.mimeType||gt(o.uri),d}).catch(function(d){throw console.error("THREE.GLTFLoader: Couldn't load texture",r),d});return this.sourceCache[e]=u,u}assignTexture(e,t,s,n){const i=this;return this.getDependency("texture",s.index).then(function(o){if(!o)return null;if(s.texCoord!==void 0&&s.texCoord>0&&(o=o.clone(),o.channel=s.texCoord),i.extensions[x.KHR_TEXTURE_TRANSFORM]){const a=s.extensions!==void 0?s.extensions[x.KHR_TEXTURE_TRANSFORM]:void 0;if(a){const r=i.associations.get(o);o=i.extensions[x.KHR_TEXTURE_TRANSFORM].extendTexture(o,a),i.associations.set(o,r)}}return n!==void 0&&(o.colorSpace=n),e[t]=o,o})}assignFinalMaterial(e){const t=e.geometry;let s=e.material;const n=t.attributes.tangent===void 0,i=t.attributes.color!==void 0,o=t.attributes.normal===void 0;if(e.isPoints){const a="PointsMaterial:"+s.uuid;let r=this.cache.get(a);r||(r=new l.PointsMaterial,l.Material.prototype.copy.call(r,s),r.color.copy(s.color),r.map=s.map,r.sizeAttenuation=!1,this.cache.add(a,r)),s=r}else if(e.isLine){const a="LineBasicMaterial:"+s.uuid;let r=this.cache.get(a);r||(r=new l.LineBasicMaterial,l.Material.prototype.copy.call(r,s),r.color.copy(s.color),r.map=s.map,this.cache.add(a,r)),s=r}if(n||i||o){let a="ClonedMaterial:"+s.uuid+":";n&&(a+="derivative-tangents:"),i&&(a+="vertex-colors:"),o&&(a+="flat-shading:");let r=this.cache.get(a);r||(r=s.clone(),i&&(r.vertexColors=!0),o&&(r.flatShading=!0),n&&(r.normalScale&&(r.normalScale.y*=-1),r.clearcoatNormalScale&&(r.clearcoatNormalScale.y*=-1)),this.cache.add(a,r),this.associations.set(r,this.associations.get(s))),s=r}e.material=s}getMaterialType(){return l.MeshStandardMaterial}loadMaterial(e){const t=this,s=this.json,n=this.extensions,i=s.materials[e];let o;const a={},r=i.extensions||{},c=[];if(r[x.KHR_MATERIALS_UNLIT]){const d=n[x.KHR_MATERIALS_UNLIT];o=d.getMaterialType(),c.push(d.extendParams(a,i,t))}else{const d=i.pbrMetallicRoughness||{};if(a.color=new l.Color(1,1,1),a.opacity=1,Array.isArray(d.baseColorFactor)){const p=d.baseColorFactor;a.color.setRGB(p[0],p[1],p[2],l.LinearSRGBColorSpace),a.opacity=p[3]}d.baseColorTexture!==void 0&&c.push(t.assignTexture(a,"map",d.baseColorTexture,l.SRGBColorSpace)),a.metalness=d.metallicFactor!==void 0?d.metallicFactor:1,a.roughness=d.roughnessFactor!==void 0?d.roughnessFactor:1,d.metallicRoughnessTexture!==void 0&&(c.push(t.assignTexture(a,"metalnessMap",d.metallicRoughnessTexture)),c.push(t.assignTexture(a,"roughnessMap",d.metallicRoughnessTexture))),o=this._invokeOne(function(p){return p.getMaterialType&&p.getMaterialType(e)}),c.push(Promise.all(this._invokeAll(function(p){return p.extendMaterialParams&&p.extendMaterialParams(e,a)})))}i.doubleSided===!0&&(a.side=l.DoubleSide);const u=i.alphaMode||$.OPAQUE;if(u===$.BLEND?(a.transparent=!0,a.depthWrite=!1):(a.transparent=!1,u===$.MASK&&(a.alphaTest=i.alphaCutoff!==void 0?i.alphaCutoff:.5)),i.normalTexture!==void 0&&o!==l.MeshBasicMaterial&&(c.push(t.assignTexture(a,"normalMap",i.normalTexture)),a.normalScale=new l.Vector2(1,1),i.normalTexture.scale!==void 0)){const d=i.normalTexture.scale;a.normalScale.set(d,d)}if(i.occlusionTexture!==void 0&&o!==l.MeshBasicMaterial&&(c.push(t.assignTexture(a,"aoMap",i.occlusionTexture)),i.occlusionTexture.strength!==void 0&&(a.aoMapIntensity=i.occlusionTexture.strength)),i.emissiveFactor!==void 0&&o!==l.MeshBasicMaterial){const d=i.emissiveFactor;a.emissive=new l.Color().setRGB(d[0],d[1],d[2],l.LinearSRGBColorSpace)}return i.emissiveTexture!==void 0&&o!==l.MeshBasicMaterial&&c.push(t.assignTexture(a,"emissiveMap",i.emissiveTexture,l.SRGBColorSpace)),Promise.all(c).then(function(){const d=new o(a);return i.name&&(d.name=i.name),j(d,i),t.associations.set(d,{materials:e}),i.extensions&&V(n,d,i),d})}createUniqueName(e){const t=l.PropertyBinding.sanitizeNodeName(e||"");return t in this.nodeNamesUsed?t+"_"+ ++this.nodeNamesUsed[t]:(this.nodeNamesUsed[t]=0,t)}loadGeometries(e){const t=this,s=this.extensions,n=this.primitiveCache;function i(a){return s[x.KHR_DRACO_MESH_COMPRESSION].decodePrimitive(a,t).then(function(r){return Me(r,a,t)})}const o=[];for(let a=0,r=e.length;a<r;a++){const c=e[a],u=mt(c),d=n[u];if(d)o.push(d.promise);else{let p;c.extensions&&c.extensions[x.KHR_DRACO_MESH_COMPRESSION]?p=i(c):p=Me(new l.BufferGeometry,c,t),n[u]={primitive:c,promise:p},o.push(p)}}return Promise.all(o)}loadMesh(e){const t=this,s=this.json,n=this.extensions,i=s.meshes[e],o=i.primitives,a=[];for(let r=0,c=o.length;r<c;r++){const u=o[r].material===void 0?dt(this.cache):this.getDependency("material",o[r].material);a.push(u)}return a.push(t.loadGeometries(o)),Promise.all(a).then(function(r){const c=r.slice(0,r.length-1),u=r[r.length-1],d=[];for(let m=0,b=u.length;m<b;m++){const M=u[m],y=o[m];let T;const L=c[m];if(y.mode===U.TRIANGLES||y.mode===U.TRIANGLE_STRIP||y.mode===U.TRIANGLE_FAN||y.mode===void 0)T=i.isSkinnedMesh===!0?new l.SkinnedMesh(M,L):new l.Mesh(M,L),T.isSkinnedMesh===!0&&T.normalizeSkinWeights(),y.mode===U.TRIANGLE_STRIP?T.geometry=ye(T.geometry,l.TriangleStripDrawMode):y.mode===U.TRIANGLE_FAN&&(T.geometry=ye(T.geometry,l.TriangleFanDrawMode));else if(y.mode===U.LINES)T=new l.LineSegments(M,L);else if(y.mode===U.LINE_STRIP)T=new l.Line(M,L);else if(y.mode===U.LINE_LOOP)T=new l.LineLoop(M,L);else if(y.mode===U.POINTS)T=new l.Points(M,L);else throw new Error("THREE.GLTFLoader: Primitive mode unsupported: "+y.mode);Object.keys(T.geometry.morphAttributes).length>0&&pt(T,i),T.name=t.createUniqueName(i.name||"mesh_"+e),j(T,i),y.extensions&&V(n,T,y),t.assignFinalMaterial(T),d.push(T)}for(let m=0,b=d.length;m<b;m++)t.associations.set(d[m],{meshes:e,primitives:m});if(d.length===1)return i.extensions&&V(n,d[0],i),d[0];const p=new l.Group;i.extensions&&V(n,p,i),t.associations.set(p,{meshes:e});for(let m=0,b=d.length;m<b;m++)p.add(d[m]);return p})}loadCamera(e){let t;const s=this.json.cameras[e],n=s[s.type];if(!n){console.warn("THREE.GLTFLoader: Missing camera parameters.");return}return s.type==="perspective"?t=new l.PerspectiveCamera(l.MathUtils.radToDeg(n.yfov),n.aspectRatio||1,n.znear||1,n.zfar||2e6):s.type==="orthographic"&&(t=new l.OrthographicCamera(-n.xmag,n.xmag,n.ymag,-n.ymag,n.znear,n.zfar)),s.name&&(t.name=this.createUniqueName(s.name)),j(t,s),Promise.resolve(t)}loadSkin(e){const t=this.json.skins[e],s=[];for(let n=0,i=t.joints.length;n<i;n++)s.push(this._loadNodeShallow(t.joints[n]));return t.inverseBindMatrices!==void 0?s.push(this.getDependency("accessor",t.inverseBindMatrices)):s.push(null),Promise.all(s).then(function(n){const i=n.pop(),o=n,a=[],r=[];for(let c=0,u=o.length;c<u;c++){const d=o[c];if(d){a.push(d);const p=new l.Matrix4;i!==null&&p.fromArray(i.array,c*16),r.push(p)}else console.warn('THREE.GLTFLoader: Joint "%s" could not be found.',t.joints[c])}return new l.Skeleton(a,r)})}loadAnimation(e){const t=this.json,s=this,n=t.animations[e],i=n.name?n.name:"animation_"+e,o=[],a=[],r=[],c=[],u=[];for(let d=0,p=n.channels.length;d<p;d++){const m=n.channels[d],b=n.samplers[m.sampler],M=m.target,y=M.node,T=n.parameters!==void 0?n.parameters[b.input]:b.input,L=n.parameters!==void 0?n.parameters[b.output]:b.output;M.node!==void 0&&(o.push(this.getDependency("node",y)),a.push(this.getDependency("accessor",T)),r.push(this.getDependency("accessor",L)),c.push(b),u.push(M))}return Promise.all([Promise.all(o),Promise.all(a),Promise.all(r),Promise.all(c),Promise.all(u)]).then(function(d){const p=d[0],m=d[1],b=d[2],M=d[3],y=d[4],T=[];for(let A=0,S=p.length;A<S;A++){const O=p[A],v=m[A],N=b[A],F=M[A],H=y[A];if(O===void 0)continue;O.updateMatrix&&O.updateMatrix();const X=s._createAnimationTracks(O,v,N,F,H);if(X)for(let Y=0;Y<X.length;Y++)T.push(X[Y])}const L=new l.AnimationClip(i,void 0,T);return j(L,n),L})}createNodeMesh(e){const t=this.json,s=this,n=t.nodes[e];return n.mesh===void 0?null:s.getDependency("mesh",n.mesh).then(function(i){const o=s._getNodeRef(s.meshCache,n.mesh,i);return n.weights!==void 0&&o.traverse(function(a){if(a.isMesh)for(let r=0,c=n.weights.length;r<c;r++)a.morphTargetInfluences[r]=n.weights[r]}),o})}loadNode(e){const t=this.json,s=this,n=t.nodes[e],i=s._loadNodeShallow(e),o=[],a=n.children||[];for(let c=0,u=a.length;c<u;c++)o.push(s.getDependency("node",a[c]));const r=n.skin===void 0?Promise.resolve(null):s.getDependency("skin",n.skin);return Promise.all([i,Promise.all(o),r]).then(function(c){const u=c[0],d=c[1],p=c[2];p!==null&&u.traverse(function(m){m.isSkinnedMesh&&m.bind(p,_t)});for(let m=0,b=d.length;m<b;m++)u.add(d[m]);return u})}_loadNodeShallow(e){const t=this.json,s=this.extensions,n=this;if(this.nodeCache[e]!==void 0)return this.nodeCache[e];const i=t.nodes[e],o=i.name?n.createUniqueName(i.name):"",a=[],r=n._invokeOne(function(c){return c.createNodeMesh&&c.createNodeMesh(e)});return r&&a.push(r),i.camera!==void 0&&a.push(n.getDependency("camera",i.camera).then(function(c){return n._getNodeRef(n.cameraCache,i.camera,c)})),n._invokeAll(function(c){return c.createNodeAttachment&&c.createNodeAttachment(e)}).forEach(function(c){a.push(c)}),this.nodeCache[e]=Promise.all(a).then(function(c){let u;if(i.isBone===!0?u=new l.Bone:c.length>1?u=new l.Group:c.length===1?u=c[0]:u=new l.Object3D,u!==c[0])for(let d=0,p=c.length;d<p;d++)u.add(c[d]);if(i.name&&(u.userData.name=i.name,u.name=o),j(u,i),i.extensions&&V(s,u,i),i.matrix!==void 0){const d=new l.Matrix4;d.fromArray(i.matrix),u.applyMatrix4(d)}else i.translation!==void 0&&u.position.fromArray(i.translation),i.rotation!==void 0&&u.quaternion.fromArray(i.rotation),i.scale!==void 0&&u.scale.fromArray(i.scale);if(!n.associations.has(u))n.associations.set(u,{});else if(i.mesh!==void 0&&n.meshCache.refs[i.mesh]>1){const d=n.associations.get(u);n.associations.set(u,{...d})}return n.associations.get(u).nodes=e,u}),this.nodeCache[e]}loadScene(e){const t=this.extensions,s=this.json.scenes[e],n=this,i=new l.Group;s.name&&(i.name=n.createUniqueName(s.name)),j(i,s),s.extensions&&V(t,i,s);const o=s.nodes||[],a=[];for(let r=0,c=o.length;r<c;r++)a.push(n.getDependency("node",o[r]));return Promise.all(a).then(function(r){for(let u=0,d=r.length;u<d;u++)i.add(r[u]);const c=u=>{const d=new Map;for(const[p,m]of n.associations)(p instanceof l.Material||p instanceof l.Texture)&&d.set(p,m);return u.traverse(p=>{const m=n.associations.get(p);m!=null&&d.set(p,m)}),d};return n.associations=c(i),i})}_createAnimationTracks(e,t,s,n,i){const o=[],a=e.name?e.name:e.uuid,r=[];G[i.path]===G.weights?e.traverse(function(p){p.morphTargetInfluences&&r.push(p.name?p.name:p.uuid)}):r.push(a);let c;switch(G[i.path]){case G.weights:c=l.NumberKeyframeTrack;break;case G.rotation:c=l.QuaternionKeyframeTrack;break;case G.translation:case G.scale:c=l.VectorKeyframeTrack;break;default:s.itemSize===1?c=l.NumberKeyframeTrack:c=l.VectorKeyframeTrack;break}const u=n.interpolation!==void 0?ut[n.interpolation]:l.InterpolateLinear,d=this._getArrayFromAccessor(s);for(let p=0,m=r.length;p<m;p++){const b=new c(r[p]+"."+G[i.path],t.array,d,u);n.interpolation==="CUBICSPLINE"&&this._createCubicSplineTrackInterpolant(b),o.push(b)}return o}_getArrayFromAccessor(e){let t=e.array;if(e.normalized){const s=se(t.constructor),n=new Float32Array(t.length);for(let i=0,o=t.length;i<o;i++)n[i]=t[i]*s;t=n}return t}_createCubicSplineTrackInterpolant(e){e.createInterpolant=function(s){const n=this instanceof l.QuaternionKeyframeTrack?ht:Le;return new n(this.times,this.values,this.getValueSize()/3,s)},e.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline=!0}}function yt(h,e,t){const s=e.attributes,n=new l.Box3;if(s.POSITION!==void 0){const a=t.json.accessors[s.POSITION],r=a.min,c=a.max;if(r!==void 0&&c!==void 0){if(n.set(new l.Vector3(r[0],r[1],r[2]),new l.Vector3(c[0],c[1],c[2])),a.normalized){const u=se(z[a.componentType]);n.min.multiplyScalar(u),n.max.multiplyScalar(u)}}else{console.warn("THREE.GLTFLoader: Missing min/max properties for accessor POSITION.");return}}else return;const i=e.targets;if(i!==void 0){const a=new l.Vector3,r=new l.Vector3;for(let c=0,u=i.length;c<u;c++){const d=i[c];if(d.POSITION!==void 0){const p=t.json.accessors[d.POSITION],m=p.min,b=p.max;if(m!==void 0&&b!==void 0){if(r.setX(Math.max(Math.abs(m[0]),Math.abs(b[0]))),r.setY(Math.max(Math.abs(m[1]),Math.abs(b[1]))),r.setZ(Math.max(Math.abs(m[2]),Math.abs(b[2]))),p.normalized){const M=se(z[p.componentType]);r.multiplyScalar(M)}a.max(r)}else console.warn("THREE.GLTFLoader: Missing min/max properties for accessor POSITION.")}}n.expandByVector(a)}h.boundingBox=n;const o=new l.Sphere;n.getCenter(o.center),o.radius=n.min.distanceTo(n.max)/2,h.boundingSphere=o}function Me(h,e,t){const s=e.attributes,n=[];function i(o,a){return t.getDependency("accessor",o).then(function(r){h.setAttribute(a,r)})}for(const o in s){const a=ne[o]||o.toLowerCase();a in h.attributes||n.push(i(s[o],a))}if(e.indices!==void 0&&!h.index){const o=t.getDependency("accessor",e.indices).then(function(a){h.setIndex(a)});n.push(o)}return l.ColorManagement.workingColorSpace!==l.LinearSRGBColorSpace&&"COLOR_0"in s&&console.warn(`THREE.GLTFLoader: Converting vertex colors from "srgb-linear" to "${l.ColorManagement.workingColorSpace}" not supported.`),j(h,e),yt(h,e,t),Promise.all(n).then(function(){return e.targets!==void 0?ft(h,e.targets,t):h})}const Re={type:"change"},ie={type:"start"},Ae={type:"end"},Z=new l.Ray,Se=new l.Plane,bt=Math.cos(70*l.MathUtils.DEG2RAD),D=new l.Vector3,k=2*Math.PI,w={NONE:-1,ROTATE:0,DOLLY:1,PAN:2,TOUCH_ROTATE:3,TOUCH_PAN:4,TOUCH_DOLLY_PAN:5,TOUCH_DOLLY_ROTATE:6},te=1e-6;class Et extends l.Controls{constructor(e,t=null){super(e,t),this.state=w.NONE,this.target=new l.Vector3,this.cursor=new l.Vector3,this.minDistance=0,this.maxDistance=1/0,this.minZoom=0,this.maxZoom=1/0,this.minTargetRadius=0,this.maxTargetRadius=1/0,this.minPolarAngle=0,this.maxPolarAngle=Math.PI,this.minAzimuthAngle=-1/0,this.maxAzimuthAngle=1/0,this.enableDamping=!1,this.dampingFactor=.05,this.enableZoom=!0,this.zoomSpeed=1,this.enableRotate=!0,this.rotateSpeed=1,this.keyRotateSpeed=1,this.enablePan=!0,this.panSpeed=1,this.screenSpacePanning=!0,this.keyPanSpeed=7,this.zoomToCursor=!1,this.autoRotate=!1,this.autoRotateSpeed=2,this.keys={LEFT:"ArrowLeft",UP:"ArrowUp",RIGHT:"ArrowRight",BOTTOM:"ArrowDown"},this.mouseButtons={LEFT:l.MOUSE.ROTATE,MIDDLE:l.MOUSE.DOLLY,RIGHT:l.MOUSE.PAN},this.touches={ONE:l.TOUCH.ROTATE,TWO:l.TOUCH.DOLLY_PAN},this.target0=this.target.clone(),this.position0=this.object.position.clone(),this.zoom0=this.object.zoom,this._domElementKeyEvents=null,this._lastPosition=new l.Vector3,this._lastQuaternion=new l.Quaternion,this._lastTargetPosition=new l.Vector3,this._quat=new l.Quaternion().setFromUnitVectors(e.up,new l.Vector3(0,1,0)),this._quatInverse=this._quat.clone().invert(),this._spherical=new l.Spherical,this._sphericalDelta=new l.Spherical,this._scale=1,this._panOffset=new l.Vector3,this._rotateStart=new l.Vector2,this._rotateEnd=new l.Vector2,this._rotateDelta=new l.Vector2,this._panStart=new l.Vector2,this._panEnd=new l.Vector2,this._panDelta=new l.Vector2,this._dollyStart=new l.Vector2,this._dollyEnd=new l.Vector2,this._dollyDelta=new l.Vector2,this._dollyDirection=new l.Vector3,this._mouse=new l.Vector2,this._performCursorZoom=!1,this._pointers=[],this._pointerPositions={},this._controlActive=!1,this._onPointerMove=Mt.bind(this),this._onPointerDown=xt.bind(this),this._onPointerUp=Rt.bind(this),this._onContextMenu=Ot.bind(this),this._onMouseWheel=Lt.bind(this),this._onKeyDown=At.bind(this),this._onTouchStart=Ct.bind(this),this._onTouchMove=Dt.bind(this),this._onMouseDown=St.bind(this),this._onMouseMove=wt.bind(this),this._interceptControlDown=Pt.bind(this),this._interceptControlUp=Nt.bind(this),this.domElement!==null&&this.connect(this.domElement),this.update()}connect(e){super.connect(e),this.domElement.addEventListener("pointerdown",this._onPointerDown),this.domElement.addEventListener("pointercancel",this._onPointerUp),this.domElement.addEventListener("contextmenu",this._onContextMenu),this.domElement.addEventListener("wheel",this._onMouseWheel,{passive:!1}),this.domElement.getRootNode().addEventListener("keydown",this._interceptControlDown,{passive:!0,capture:!0}),this.domElement.style.touchAction="none"}disconnect(){this.domElement.removeEventListener("pointerdown",this._onPointerDown),this.domElement.ownerDocument.removeEventListener("pointermove",this._onPointerMove),this.domElement.ownerDocument.removeEventListener("pointerup",this._onPointerUp),this.domElement.removeEventListener("pointercancel",this._onPointerUp),this.domElement.removeEventListener("wheel",this._onMouseWheel),this.domElement.removeEventListener("contextmenu",this._onContextMenu),this.stopListenToKeyEvents(),this.domElement.getRootNode().removeEventListener("keydown",this._interceptControlDown,{capture:!0}),this.domElement.style.touchAction="auto"}dispose(){this.disconnect()}getPolarAngle(){return this._spherical.phi}getAzimuthalAngle(){return this._spherical.theta}getDistance(){return this.object.position.distanceTo(this.target)}listenToKeyEvents(e){e.addEventListener("keydown",this._onKeyDown),this._domElementKeyEvents=e}stopListenToKeyEvents(){this._domElementKeyEvents!==null&&(this._domElementKeyEvents.removeEventListener("keydown",this._onKeyDown),this._domElementKeyEvents=null)}saveState(){this.target0.copy(this.target),this.position0.copy(this.object.position),this.zoom0=this.object.zoom}reset(){this.target.copy(this.target0),this.object.position.copy(this.position0),this.object.zoom=this.zoom0,this.object.updateProjectionMatrix(),this.dispatchEvent(Re),this.update(),this.state=w.NONE}update(e=null){const t=this.object.position;D.copy(t).sub(this.target),D.applyQuaternion(this._quat),this._spherical.setFromVector3(D),this.autoRotate&&this.state===w.NONE&&this._rotateLeft(this._getAutoRotationAngle(e)),this.enableDamping?(this._spherical.theta+=this._sphericalDelta.theta*this.dampingFactor,this._spherical.phi+=this._sphericalDelta.phi*this.dampingFactor):(this._spherical.theta+=this._sphericalDelta.theta,this._spherical.phi+=this._sphericalDelta.phi);let s=this.minAzimuthAngle,n=this.maxAzimuthAngle;isFinite(s)&&isFinite(n)&&(s<-Math.PI?s+=k:s>Math.PI&&(s-=k),n<-Math.PI?n+=k:n>Math.PI&&(n-=k),s<=n?this._spherical.theta=Math.max(s,Math.min(n,this._spherical.theta)):this._spherical.theta=this._spherical.theta>(s+n)/2?Math.max(s,this._spherical.theta):Math.min(n,this._spherical.theta)),this._spherical.phi=Math.max(this.minPolarAngle,Math.min(this.maxPolarAngle,this._spherical.phi)),this._spherical.makeSafe(),this.enableDamping===!0?this.target.addScaledVector(this._panOffset,this.dampingFactor):this.target.add(this._panOffset),this.target.sub(this.cursor),this.target.clampLength(this.minTargetRadius,this.maxTargetRadius),this.target.add(this.cursor);let i=!1;if(this.zoomToCursor&&this._performCursorZoom||this.object.isOrthographicCamera)this._spherical.radius=this._clampDistance(this._spherical.radius);else{const o=this._spherical.radius;this._spherical.radius=this._clampDistance(this._spherical.radius*this._scale),i=o!=this._spherical.radius}if(D.setFromSpherical(this._spherical),D.applyQuaternion(this._quatInverse),t.copy(this.target).add(D),this.object.lookAt(this.target),this.enableDamping===!0?(this._sphericalDelta.theta*=1-this.dampingFactor,this._sphericalDelta.phi*=1-this.dampingFactor,this._panOffset.multiplyScalar(1-this.dampingFactor)):(this._sphericalDelta.set(0,0,0),this._panOffset.set(0,0,0)),this.zoomToCursor&&this._performCursorZoom){let o=null;if(this.object.isPerspectiveCamera){const a=D.length();o=this._clampDistance(a*this._scale);const r=a-o;this.object.position.addScaledVector(this._dollyDirection,r),this.object.updateMatrixWorld(),i=!!r}else if(this.object.isOrthographicCamera){const a=new l.Vector3(this._mouse.x,this._mouse.y,0);a.unproject(this.object);const r=this.object.zoom;this.object.zoom=Math.max(this.minZoom,Math.min(this.maxZoom,this.object.zoom/this._scale)),this.object.updateProjectionMatrix(),i=r!==this.object.zoom;const c=new l.Vector3(this._mouse.x,this._mouse.y,0);c.unproject(this.object),this.object.position.sub(c).add(a),this.object.updateMatrixWorld(),o=D.length()}else console.warn("WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled."),this.zoomToCursor=!1;o!==null&&(this.screenSpacePanning?this.target.set(0,0,-1).transformDirection(this.object.matrix).multiplyScalar(o).add(this.object.position):(Z.origin.copy(this.object.position),Z.direction.set(0,0,-1).transformDirection(this.object.matrix),Math.abs(this.object.up.dot(Z.direction))<bt?this.object.lookAt(this.target):(Se.setFromNormalAndCoplanarPoint(this.object.up,this.target),Z.intersectPlane(Se,this.target))))}else if(this.object.isOrthographicCamera){const o=this.object.zoom;this.object.zoom=Math.max(this.minZoom,Math.min(this.maxZoom,this.object.zoom/this._scale)),o!==this.object.zoom&&(this.object.updateProjectionMatrix(),i=!0)}return this._scale=1,this._performCursorZoom=!1,i||this._lastPosition.distanceToSquared(this.object.position)>te||8*(1-this._lastQuaternion.dot(this.object.quaternion))>te||this._lastTargetPosition.distanceToSquared(this.target)>te?(this.dispatchEvent(Re),this._lastPosition.copy(this.object.position),this._lastQuaternion.copy(this.object.quaternion),this._lastTargetPosition.copy(this.target),!0):!1}_getAutoRotationAngle(e){return e!==null?k/60*this.autoRotateSpeed*e:k/60/60*this.autoRotateSpeed}_getZoomScale(e){const t=Math.abs(e*.01);return Math.pow(.95,this.zoomSpeed*t)}_rotateLeft(e){this._sphericalDelta.theta-=e}_rotateUp(e){this._sphericalDelta.phi-=e}_panLeft(e,t){D.setFromMatrixColumn(t,0),D.multiplyScalar(-e),this._panOffset.add(D)}_panUp(e,t){this.screenSpacePanning===!0?D.setFromMatrixColumn(t,1):(D.setFromMatrixColumn(t,0),D.crossVectors(this.object.up,D)),D.multiplyScalar(e),this._panOffset.add(D)}_pan(e,t){const s=this.domElement;if(this.object.isPerspectiveCamera){const n=this.object.position;D.copy(n).sub(this.target);let i=D.length();i*=Math.tan(this.object.fov/2*Math.PI/180),this._panLeft(2*e*i/s.clientHeight,this.object.matrix),this._panUp(2*t*i/s.clientHeight,this.object.matrix)}else this.object.isOrthographicCamera?(this._panLeft(e*(this.object.right-this.object.left)/this.object.zoom/s.clientWidth,this.object.matrix),this._panUp(t*(this.object.top-this.object.bottom)/this.object.zoom/s.clientHeight,this.object.matrix)):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."),this.enablePan=!1)}_dollyOut(e){this.object.isPerspectiveCamera||this.object.isOrthographicCamera?this._scale/=e:(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),this.enableZoom=!1)}_dollyIn(e){this.object.isPerspectiveCamera||this.object.isOrthographicCamera?this._scale*=e:(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),this.enableZoom=!1)}_updateZoomParameters(e,t){if(!this.zoomToCursor)return;this._performCursorZoom=!0;const s=this.domElement.getBoundingClientRect(),n=e-s.left,i=t-s.top,o=s.width,a=s.height;this._mouse.x=n/o*2-1,this._mouse.y=-(i/a)*2+1,this._dollyDirection.set(this._mouse.x,this._mouse.y,1).unproject(this.object).sub(this.object.position).normalize()}_clampDistance(e){return Math.max(this.minDistance,Math.min(this.maxDistance,e))}_handleMouseDownRotate(e){this._rotateStart.set(e.clientX,e.clientY)}_handleMouseDownDolly(e){this._updateZoomParameters(e.clientX,e.clientX),this._dollyStart.set(e.clientX,e.clientY)}_handleMouseDownPan(e){this._panStart.set(e.clientX,e.clientY)}_handleMouseMoveRotate(e){this._rotateEnd.set(e.clientX,e.clientY),this._rotateDelta.subVectors(this._rotateEnd,this._rotateStart).multiplyScalar(this.rotateSpeed);const t=this.domElement;this._rotateLeft(k*this._rotateDelta.x/t.clientHeight),this._rotateUp(k*this._rotateDelta.y/t.clientHeight),this._rotateStart.copy(this._rotateEnd),this.update()}_handleMouseMoveDolly(e){this._dollyEnd.set(e.clientX,e.clientY),this._dollyDelta.subVectors(this._dollyEnd,this._dollyStart),this._dollyDelta.y>0?this._dollyOut(this._getZoomScale(this._dollyDelta.y)):this._dollyDelta.y<0&&this._dollyIn(this._getZoomScale(this._dollyDelta.y)),this._dollyStart.copy(this._dollyEnd),this.update()}_handleMouseMovePan(e){this._panEnd.set(e.clientX,e.clientY),this._panDelta.subVectors(this._panEnd,this._panStart).multiplyScalar(this.panSpeed),this._pan(this._panDelta.x,this._panDelta.y),this._panStart.copy(this._panEnd),this.update()}_handleMouseWheel(e){this._updateZoomParameters(e.clientX,e.clientY),e.deltaY<0?this._dollyIn(this._getZoomScale(e.deltaY)):e.deltaY>0&&this._dollyOut(this._getZoomScale(e.deltaY)),this.update()}_handleKeyDown(e){let t=!1;switch(e.code){case this.keys.UP:e.ctrlKey||e.metaKey||e.shiftKey?this.enableRotate&&this._rotateUp(k*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(0,this.keyPanSpeed),t=!0;break;case this.keys.BOTTOM:e.ctrlKey||e.metaKey||e.shiftKey?this.enableRotate&&this._rotateUp(-k*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(0,-this.keyPanSpeed),t=!0;break;case this.keys.LEFT:e.ctrlKey||e.metaKey||e.shiftKey?this.enableRotate&&this._rotateLeft(k*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(this.keyPanSpeed,0),t=!0;break;case this.keys.RIGHT:e.ctrlKey||e.metaKey||e.shiftKey?this.enableRotate&&this._rotateLeft(-k*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(-this.keyPanSpeed,0),t=!0;break}t&&(e.preventDefault(),this.update())}_handleTouchStartRotate(e){if(this._pointers.length===1)this._rotateStart.set(e.pageX,e.pageY);else{const t=this._getSecondPointerPosition(e),s=.5*(e.pageX+t.x),n=.5*(e.pageY+t.y);this._rotateStart.set(s,n)}}_handleTouchStartPan(e){if(this._pointers.length===1)this._panStart.set(e.pageX,e.pageY);else{const t=this._getSecondPointerPosition(e),s=.5*(e.pageX+t.x),n=.5*(e.pageY+t.y);this._panStart.set(s,n)}}_handleTouchStartDolly(e){const t=this._getSecondPointerPosition(e),s=e.pageX-t.x,n=e.pageY-t.y,i=Math.sqrt(s*s+n*n);this._dollyStart.set(0,i)}_handleTouchStartDollyPan(e){this.enableZoom&&this._handleTouchStartDolly(e),this.enablePan&&this._handleTouchStartPan(e)}_handleTouchStartDollyRotate(e){this.enableZoom&&this._handleTouchStartDolly(e),this.enableRotate&&this._handleTouchStartRotate(e)}_handleTouchMoveRotate(e){if(this._pointers.length==1)this._rotateEnd.set(e.pageX,e.pageY);else{const s=this._getSecondPointerPosition(e),n=.5*(e.pageX+s.x),i=.5*(e.pageY+s.y);this._rotateEnd.set(n,i)}this._rotateDelta.subVectors(this._rotateEnd,this._rotateStart).multiplyScalar(this.rotateSpeed);const t=this.domElement;this._rotateLeft(k*this._rotateDelta.x/t.clientHeight),this._rotateUp(k*this._rotateDelta.y/t.clientHeight),this._rotateStart.copy(this._rotateEnd)}_handleTouchMovePan(e){if(this._pointers.length===1)this._panEnd.set(e.pageX,e.pageY);else{const t=this._getSecondPointerPosition(e),s=.5*(e.pageX+t.x),n=.5*(e.pageY+t.y);this._panEnd.set(s,n)}this._panDelta.subVectors(this._panEnd,this._panStart).multiplyScalar(this.panSpeed),this._pan(this._panDelta.x,this._panDelta.y),this._panStart.copy(this._panEnd)}_handleTouchMoveDolly(e){const t=this._getSecondPointerPosition(e),s=e.pageX-t.x,n=e.pageY-t.y,i=Math.sqrt(s*s+n*n);this._dollyEnd.set(0,i),this._dollyDelta.set(0,Math.pow(this._dollyEnd.y/this._dollyStart.y,this.zoomSpeed)),this._dollyOut(this._dollyDelta.y),this._dollyStart.copy(this._dollyEnd);const o=(e.pageX+t.x)*.5,a=(e.pageY+t.y)*.5;this._updateZoomParameters(o,a)}_handleTouchMoveDollyPan(e){this.enableZoom&&this._handleTouchMoveDolly(e),this.enablePan&&this._handleTouchMovePan(e)}_handleTouchMoveDollyRotate(e){this.enableZoom&&this._handleTouchMoveDolly(e),this.enableRotate&&this._handleTouchMoveRotate(e)}_addPointer(e){this._pointers.push(e.pointerId)}_removePointer(e){delete this._pointerPositions[e.pointerId];for(let t=0;t<this._pointers.length;t++)if(this._pointers[t]==e.pointerId){this._pointers.splice(t,1);return}}_isTrackingPointer(e){for(let t=0;t<this._pointers.length;t++)if(this._pointers[t]==e.pointerId)return!0;return!1}_trackPointer(e){let t=this._pointerPositions[e.pointerId];t===void 0&&(t=new l.Vector2,this._pointerPositions[e.pointerId]=t),t.set(e.pageX,e.pageY)}_getSecondPointerPosition(e){const t=e.pointerId===this._pointers[0]?this._pointers[1]:this._pointers[0];return this._pointerPositions[t]}_customWheelEvent(e){const t=e.deltaMode,s={clientX:e.clientX,clientY:e.clientY,deltaY:e.deltaY};switch(t){case 1:s.deltaY*=16;break;case 2:s.deltaY*=100;break}return e.ctrlKey&&!this._controlActive&&(s.deltaY*=10),s}}function xt(h){this.enabled!==!1&&(this._pointers.length===0&&(this.domElement.setPointerCapture(h.pointerId),this.domElement.ownerDocument.addEventListener("pointermove",this._onPointerMove),this.domElement.ownerDocument.addEventListener("pointerup",this._onPointerUp)),!this._isTrackingPointer(h)&&(this._addPointer(h),h.pointerType==="touch"?this._onTouchStart(h):this._onMouseDown(h)))}function Mt(h){this.enabled!==!1&&(h.pointerType==="touch"?this._onTouchMove(h):this._onMouseMove(h))}function Rt(h){switch(this._removePointer(h),this._pointers.length){case 0:this.domElement.releasePointerCapture(h.pointerId),this.domElement.ownerDocument.removeEventListener("pointermove",this._onPointerMove),this.domElement.ownerDocument.removeEventListener("pointerup",this._onPointerUp),this.dispatchEvent(Ae),this.state=w.NONE;break;case 1:const e=this._pointers[0],t=this._pointerPositions[e];this._onTouchStart({pointerId:e,pageX:t.x,pageY:t.y});break}}function St(h){let e;switch(h.button){case 0:e=this.mouseButtons.LEFT;break;case 1:e=this.mouseButtons.MIDDLE;break;case 2:e=this.mouseButtons.RIGHT;break;default:e=-1}switch(e){case l.MOUSE.DOLLY:if(this.enableZoom===!1)return;this._handleMouseDownDolly(h),this.state=w.DOLLY;break;case l.MOUSE.ROTATE:if(h.ctrlKey||h.metaKey||h.shiftKey){if(this.enablePan===!1)return;this._handleMouseDownPan(h),this.state=w.PAN}else{if(this.enableRotate===!1)return;this._handleMouseDownRotate(h),this.state=w.ROTATE}break;case l.MOUSE.PAN:if(h.ctrlKey||h.metaKey||h.shiftKey){if(this.enableRotate===!1)return;this._handleMouseDownRotate(h),this.state=w.ROTATE}else{if(this.enablePan===!1)return;this._handleMouseDownPan(h),this.state=w.PAN}break;default:this.state=w.NONE}this.state!==w.NONE&&this.dispatchEvent(ie)}function wt(h){switch(this.state){case w.ROTATE:if(this.enableRotate===!1)return;this._handleMouseMoveRotate(h);break;case w.DOLLY:if(this.enableZoom===!1)return;this._handleMouseMoveDolly(h);break;case w.PAN:if(this.enablePan===!1)return;this._handleMouseMovePan(h);break}}function Lt(h){this.enabled===!1||this.enableZoom===!1||this.state!==w.NONE||(h.preventDefault(),this.dispatchEvent(ie),this._handleMouseWheel(this._customWheelEvent(h)),this.dispatchEvent(Ae))}function At(h){this.enabled!==!1&&this._handleKeyDown(h)}function Ct(h){switch(this._trackPointer(h),this._pointers.length){case 1:switch(this.touches.ONE){case l.TOUCH.ROTATE:if(this.enableRotate===!1)return;this._handleTouchStartRotate(h),this.state=w.TOUCH_ROTATE;break;case l.TOUCH.PAN:if(this.enablePan===!1)return;this._handleTouchStartPan(h),this.state=w.TOUCH_PAN;break;default:this.state=w.NONE}break;case 2:switch(this.touches.TWO){case l.TOUCH.DOLLY_PAN:if(this.enableZoom===!1&&this.enablePan===!1)return;this._handleTouchStartDollyPan(h),this.state=w.TOUCH_DOLLY_PAN;break;case l.TOUCH.DOLLY_ROTATE:if(this.enableZoom===!1&&this.enableRotate===!1)return;this._handleTouchStartDollyRotate(h),this.state=w.TOUCH_DOLLY_ROTATE;break;default:this.state=w.NONE}break;default:this.state=w.NONE}this.state!==w.NONE&&this.dispatchEvent(ie)}function Dt(h){switch(this._trackPointer(h),this.state){case w.TOUCH_ROTATE:if(this.enableRotate===!1)return;this._handleTouchMoveRotate(h),this.update();break;case w.TOUCH_PAN:if(this.enablePan===!1)return;this._handleTouchMovePan(h),this.update();break;case w.TOUCH_DOLLY_PAN:if(this.enableZoom===!1&&this.enablePan===!1)return;this._handleTouchMoveDollyPan(h),this.update();break;case w.TOUCH_DOLLY_ROTATE:if(this.enableZoom===!1&&this.enableRotate===!1)return;this._handleTouchMoveDollyRotate(h),this.update();break;default:this.state=w.NONE}}function Ot(h){this.enabled!==!1&&h.preventDefault()}function Pt(h){h.key==="Control"&&(this._controlActive=!0,this.domElement.getRootNode().addEventListener("keyup",this._interceptControlUp,{passive:!0,capture:!0}))}function Nt(h){h.key==="Control"&&(this._controlActive=!1,this.domElement.getRootNode().removeEventListener("keyup",this._interceptControlUp,{passive:!0,capture:!0}))}const It={class:"glb-viewer"},kt=["onClick","onMousedown","onContextmenu"],vt={class:"marker-label"},Ut=["src"],jt=R.defineComponent({__name:"GLBViewer",props:{modelUrl:{default:"/models/model.glb"},fetchModel:{type:Function,default:void 0},isDesignMode:{type:Boolean,default:!0},enableBindOnClick:{type:Boolean,default:!0}},setup(h,{expose:e}){const t=h,s=R.ref(null),n=R.ref(null),i=R.ref([]),o=R.ref({visible:!1,x:0,y:0,componentId:null});let a,r,c,u,d,p,m=null,b=0,M=!1,y=null,T=null;const L=new Map;let A=null,S=null,O=null,v=null,N=null,F=null;const H="data:image/svg+xml;utf8,"+encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
2
+ <circle cx="16" cy="16" r="14" fill="#42b883" stroke="#2c8c68" stroke-width="2" />
3
+ <path d="M16 7 L20.5 18 H11.5 Z" fill="#ffffff"/>
4
+ </svg>`),X=()=>{if(!s.value)return;a=new I.Scene,a.background=new I.Color(1710618),r=new I.PerspectiveCamera(75,s.value.clientWidth/s.value.clientHeight,.1,1e3),r.position.set(0,2,5),c=new I.WebGLRenderer({canvas:s.value,antialias:!0}),c.setSize(s.value.clientWidth,s.value.clientHeight),c.setPixelRatio(window.devicePixelRatio),n.value&&(n.value.width=s.value.clientWidth,n.value.height=s.value.clientHeight,T=n.value.getContext("2d")),u=new Et(r,c.domElement),u.enableDamping=!0,u.enableZoom=!0,u.zoomToCursor=!0,u.zoomSpeed=2,u.minDistance=.1,u.maxDistance=1/0;const f=new I.AmbientLight(16777215,.6);a.add(f);const g=new I.DirectionalLight(16777215,.8);g.position.set(5,10,5),a.add(g),d=new I.Raycaster,p=new I.Vector2,Ce(),ce(),window.addEventListener("resize",le),c.domElement.addEventListener("pointerdown",ue,{passive:!1})},Y=async()=>{if(t.fetchModel)try{const f=await t.fetchModel();if(typeof f=="string")return{url:f};if(f instanceof Blob){const g=URL.createObjectURL(f);return{url:g,revoke:()=>URL.revokeObjectURL(g)}}if(f instanceof ArrayBuffer){const g=new Blob([f],{type:"model/gltf-binary"}),_=URL.createObjectURL(g);return{url:_,revoke:()=>URL.revokeObjectURL(_)}}}catch(f){console.warn("fetchModel 获取模型失败,改用默认路径:",f)}return{url:t.modelUrl}},Ce=async()=>{const f=new Fe;try{const{url:g,revoke:_}=await Y();f.load(g,E=>{_&&_(),m=E.scene,a.add(m),console.log("GLB 模型加载成功")},E=>{E.total&&console.log("加载进度:",E.loaded/E.total*100+"%")},E=>{_&&_(),console.warn("GLB 模型加载失败,使用默认几何体",E),oe()})}catch(g){console.warn("加载模型异常,使用默认几何体",g),oe()}},oe=()=>{const f=new I.BoxGeometry(1,1,1),g=new I.MeshStandardMaterial({color:4372611}),_=new I.Mesh(f,g);_.name="DefaultCube",m=new I.Group,m.add(_),a.add(m)},De=f=>{if(!t.isDesignMode||!t.enableBindOnClick||!s.value||o.value.visible)return;const g=s.value.getBoundingClientRect();p.x=(f.clientX-g.left)/g.width*2-1,p.y=-((f.clientY-g.top)/g.height)*2+1,d.setFromCamera(p,r);const _=d.intersectObjects(a.children,!0);if(_.length>0){const E=_[0],C=E.object,P=E.point.clone(),K=C.worldToLocal(P.clone()),B={id:b++,name:`组件 ${b}`,screen:{x:0,y:0,visible:!0},anchor:{objectUUID:C.uuid,local:{x:K.x,y:K.y,z:K.z}},meshName:C.name||"未命名对象",iconSrc:H};i.value.push(B),console.log("绑定新组件:",B),A&&A(B),S&&S(B)}},Oe=f=>{f.preventDefault()},Pe=f=>{v&&v(f)},Ne=f=>{if(f.preventDefault(),!c)return;const g=new WheelEvent("wheel",{deltaY:f.deltaY,deltaX:f.deltaX,deltaZ:f.deltaZ,clientX:f.clientX,clientY:f.clientY,ctrlKey:f.ctrlKey,shiftKey:f.shiftKey,altKey:f.altKey,metaKey:f.metaKey,deltaMode:f.deltaMode,bubbles:!0,cancelable:!0});c.domElement.dispatchEvent(g)},Ie=(f,g)=>{if(f.preventDefault(),N&&N(g,f)===!1||!t.isDesignMode)return;const _=s.value?.getBoundingClientRect();_&&(o.value={visible:!0,x:f.clientX-_.left,y:f.clientY-_.top,componentId:g.id})},re=()=>{o.value.visible=!1,o.value.componentId=null},ae=f=>i.value.some(_=>_.id===f)?(i.value=i.value.filter(_=>_.id!==f),L.delete(f),O&&O(f),!0):!1,ke=()=>{if(o.value.componentId!==null){const f=o.value.componentId;ae(f)&&console.log("取消绑定组件:",f)}re()},ce=()=>{requestAnimationFrame(ce),u.update(),fe(),de(),c.render(a,r)},le=()=>{s.value&&(r.aspect=s.value.clientWidth/s.value.clientHeight,r.updateProjectionMatrix(),c.setSize(s.value.clientWidth,s.value.clientHeight),n.value&&(n.value.width=s.value.clientWidth,n.value.height=s.value.clientHeight))},he=()=>{o.value.visible&&re()};R.onMounted(()=>{X(),setTimeout(()=>{Te()},100),document.addEventListener("click",he),document.addEventListener("mousemove",pe),document.addEventListener("mouseup",me)}),R.onUnmounted(()=>{window.removeEventListener("resize",le),document.removeEventListener("click",he),document.removeEventListener("mousemove",pe),document.removeEventListener("mouseup",me),c?.domElement&&c.domElement.removeEventListener("pointerdown",ue),c?.dispose()});const ue=f=>{if(f.button!==0||!s.value)return;p.x=0,p.y=0,d.setFromCamera(p,r);const g=d.intersectObjects(a.children,!0);if(g.length>0){const _=g[0].point;u.target.copy(_)}else{const _=r.getWorldDirection(new I.Vector3),E=r.position.clone().add(_.multiplyScalar(10));u.target.copy(E)}},de=()=>{if(!(!T||!n.value)){T.clearRect(0,0,n.value.width,n.value.height);for(const f of i.value){const g=L.get(f.id);!g||!f.screen.visible||(T.strokeStyle="rgba(66, 184, 131, 0.6)",T.lineWidth=2,T.setLineDash([5,5]),T.beginPath(),T.moveTo(g.x,g.y),T.lineTo(f.screen.x,f.screen.y),T.stroke(),T.setLineDash([]),T.fillStyle="rgba(66, 184, 131, 0.8)",T.beginPath(),T.arc(g.x,g.y,3,0,Math.PI*2),T.fill())}}},fe=()=>{if(!s.value)return;const f=s.value.getBoundingClientRect();for(const g of i.value){const _=a.getObjectByProperty("uuid",g.anchor.objectUUID);if(!_){g.screen.visible=!1,L.delete(g.id);continue}const E=new I.Vector3(g.anchor.local.x,g.anchor.local.y,g.anchor.local.z),P=_.localToWorld(E.clone()).clone().project(r),K=P.z>=-1&&P.z<=1;g.screen.visible=K,g.screen.x=(P.x+1)/2*f.width,g.screen.y=(1-P.y)/2*f.height,L.set(g.id,{x:(P.x+1)/2*f.width,y:(1-P.y)/2*f.height})}},ve=(f,g)=>{t.isDesignMode&&(M=!0,y=f,u&&(u.enableRotate=!1,u.enablePan=!1))},pe=f=>{if(!M||y===null||!s.value)return;const g=i.value.find(C=>C.id===y);if(!g)return;const _=s.value.getBoundingClientRect();p.x=(f.clientX-_.left)/_.width*2-1,p.y=-((f.clientY-_.top)/_.height)*2+1,d.setFromCamera(p,r);const E=d.intersectObjects(a.children,!0);if(E.length>0){const C=E[0],P=C.object,K=C.point.clone(),B=P.worldToLocal(K.clone());g.anchor.objectUUID=P.uuid,g.anchor.local={x:B.x,y:B.y,z:B.z}}},me=()=>{if(!M)return;M=!1;const f=i.value.find(g=>g.id===y)||null;y=null,u&&(u.enableRotate=!0,u.enablePan=!0),f&&F&&F(f)},ge=()=>({position:{x:r.position.x,y:r.position.y,z:r.position.z},target:{x:u.target.x,y:u.target.y,z:u.target.z}}),_e=f=>{r.position.set(f.position.x,f.position.y,f.position.z),u.target.set(f.target.x,f.target.y,f.target.z),u.update()},q=f=>{const g=ge();return localStorage.setItem(f,JSON.stringify(g)),console.log(`已保存视角到 localStorage: ${f}`,g),g},Q=f=>{const g=localStorage.getItem(f);if(!g)return!1;const _=JSON.parse(g);return _e(_),console.log(`已从 localStorage 还原视角: ${f}`),!0},Ue=()=>{try{q("glbViewerCamera")}catch(f){console.warn("保存视角失败:",f)}},Te=()=>{try{return Q("glbViewerCamera")}catch(f){return console.warn("读取视角失败:",f),!1}};return e({getCameraState:ge,setCameraState:_e,saveCameraToLocalStorage:Ue,loadCameraFromLocalStorage:Te,saveCamera2D:()=>q("glbViewerCamera2D"),loadCamera2D:()=>Q("glbViewerCamera2D"),saveCamera3D:()=>q("glbViewerCamera3D"),loadCamera3D:()=>Q("glbViewerCamera3D"),getBoundComponentsData:()=>i.value.map(f=>({id:f.id,name:f.name,meshName:f.meshName,iconSrc:f.iconSrc,anchor:{objectUUID:f.anchor.objectUUID,local:{...f.anchor.local}}})),setBoundComponentsData:f=>{if(!Array.isArray(f))return!1;const g=f.map((E,C)=>({id:E.id??C,name:E.name??`组件 ${E.id??C}`,meshName:E.meshName??"未命名对象",iconSrc:E.iconSrc??H,screen:{x:0,y:0,visible:!0},anchor:{objectUUID:E.anchor.objectUUID,local:{...E.anchor.local}}}));return i.value=g,b=g.reduce((E,C)=>Math.max(E,C.id),0)+1,fe(),de(),!0},setComponentIcon:(f,g)=>{if(!g)return!1;const _=i.value.find(E=>E.id===f);return _?(_.iconSrc=g,!0):!1},setComponentsIcons:f=>{if(!f)return!1;let g=!1;for(const _ of i.value){const E=f[_.id];E&&(_.iconSrc=E,g=!0)}return g},setComponentsMeta:f=>{if(!Array.isArray(f))return{updated:0,skipped:0};let g=0,_=0;const E=new Map;for(const C of f)typeof C.id=="number"&&E.set(C.id,{name:C.name,iconSrc:C.iconSrc});for(const C of i.value){const P=E.get(C.id);if(!P){_++;continue}P.name!==void 0&&(C.name=P.name),P.iconSrc!==void 0&&(C.iconSrc=P.iconSrc),g++}return{updated:g,skipped:_}},setOnBindCallback:f=>(A=f,!0),setOnBindEnd:f=>(S=f,!0),setOnUnbind:f=>(O=f,!0),setOnMarkerClick:f=>(v=f,!0),setOnMarkerContextMenu:f=>(N=f,!0),setOnMarkerDragEnd:f=>(F=f,!0),unbindComponent:ae}),(f,g)=>(R.openBlock(),R.createElementBlock("div",It,[R.createElementVNode("canvas",{ref_key:"canvasRef",ref:s,onClick:De,onContextmenu:Oe},null,544),R.createElementVNode("canvas",{ref_key:"linesCanvasRef",ref:n,class:"lines-canvas"},null,512),(R.openBlock(!0),R.createElementBlock(R.Fragment,null,R.renderList(i.value,_=>R.withDirectives((R.openBlock(),R.createElementBlock("div",{key:_.id,class:"marker",style:R.normalizeStyle({left:_.screen.x+"px",top:_.screen.y+"px"}),onClick:E=>Pe(_),onWheel:R.withModifiers(Ne,["prevent","stop"]),onMousedown:R.withModifiers(E=>ve(_.id),["prevent"]),onContextmenu:R.withModifiers(E=>Ie(E,_),["prevent"])},[R.createElementVNode("div",vt,R.toDisplayString(_.name),1),R.createElementVNode("img",{class:"marker-icon",src:_.iconSrc,alt:"marker"},null,8,Ut)],44,kt)),[[R.vShow,_.screen.visible]])),128)),o.value.visible?(R.openBlock(),R.createElementBlock("div",{key:0,style:R.normalizeStyle({position:"absolute",left:o.value.x+"px",top:o.value.y+"px",backgroundColor:"rgba(32, 32, 32, 0.92)",border:"1px solid rgba(255,255,255,0.08)",borderRadius:"6px",boxShadow:"0 8px 24px rgba(0,0,0,0.35)",padding:"6px 0",minWidth:"140px",zIndex:1e3})},[R.createElementVNode("div",{class:"menu-item",onClick:ke},"取消绑定")],4)):R.createCommentVNode("",!0)]))}}),Ft=(h,e)=>{const t=h.__vccOpts||h;for(const[s,n]of e)t[s]=n;return t},Ht=Ft(jt,[["__scopeId","data-v-c440ea9c"]]);exports.GLBViewer=Ht;