@ridp/threejs 1.3.3 → 1.4.1

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/dist/hooks.js CHANGED
@@ -1,9 +1,11 @@
1
- import { i as a, o, c as r, b, a as t, u } from "./useGLTFLoader-MhUFIZp1.js";
1
+ import { i as a, o, c as r, b as t, a as u, u as b } from "./useBatchGLTFLoader-B5EUagWI.js";
2
+ import { u as L } from "./PredictiveLoader-CZfMSjv-.js";
2
3
  export {
3
4
  a as intersectColor,
4
5
  o as obbObjects,
5
- r as useGLTFLoader,
6
- b as useObb,
7
- t as useRaycaster,
8
- u as useThreeJs
6
+ r as useBatchGLTFLoader,
7
+ L as useGLTFLoader,
8
+ t as useObb,
9
+ u as useRaycaster,
10
+ b as useThreeJs
9
11
  };
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("three");function g(u){const o=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(u){for(const r in u)if(r!=="default"){const e=Object.getOwnPropertyDescriptor(u,r);Object.defineProperty(o,r,e.get?e:{enumerable:!0,get:()=>u[r]})}}return o.default=u,Object.freeze(o)}const a=g(p);class c{constructor(){this.simplifyRatio=.5}simplifyGeometry(o,r=this.simplifyRatio){const e=o.geometry;if(!e.isBufferGeometry)return console.warn("[ ModelOptimizer ] 非BufferGeometry,跳过简化"),e;const t=e.index?e.index.count/3:e.attributes.position.count/3,i=Math.floor(t*r);if(i<4)return console.warn("[ ModelOptimizer ] 简化后面数太少,跳过"),e;try{const n=this.modifierModify(e,i);return console.log(`[ ModelOptimizer ] 简化完成: ${t} -> ${i} 面`),n}catch(n){return console.warn("[ ModelOptimizer ] 简化失败,使用原几何体",n),e}}modifierModify(o,r){if(typeof a.SimplifyModifier<"u")return new a.SimplifyModifier().modify(o,r);const e=o.clone();return e.attributes.normal&&e.deleteAttribute("normal"),e.attributes.uv&&this.simplifyRatio<.3&&e.deleteAttribute("uv"),e}optimizeMaterials(o){const r=new Map;let e=0;return o.traverse(t=>{if(t.isMesh&&t.material){const i=this.getMaterialKey(t.material);if(r.has(i)){const n=t.material;t.material=r.get(i),e++,n.dispose&&n.dispose()}else r.set(i,t.material)}}),console.log(`[ ModelOptimizer ] 材质合并: 合并了 ${e} 个重复材质`),o}getMaterialKey(o){var e;return[o.type,(e=o.color)==null?void 0:e.getHex(),o.roughness,o.metalness,o.opacity,o.transparent].join("|")}mergeMeshes(o){if(o.length===0)return null;const r=[],e=[];if(o.forEach(t=>{t.geometry&&r.push(t.geometry),t.material&&e.push(t.material)}),r.length===0)return null;try{if(typeof a.BufferGeometryUtils<"u"&&a.BufferGeometryUtils.mergeGeometries){const t=a.BufferGeometryUtils.mergeGeometries(r),i=new a.Mesh(t,e[0]);return console.log(`[ ModelOptimizer ] 合并了 ${o.length} 个网格`),i}}catch(t){console.warn("[ ModelOptimizer ] 合并网格失败",t)}return null}createLOD(o,r=[0,50,100],e=[1,.5,.25]){const t=new a.LOD;t.addLevel(o,r[0]);for(let i=1;i<r.length;i++){const n=o.clone();n.geometry=this.simplifyGeometry(o,e[i]),t.addLevel(n,r[i])}return console.log(`[ ModelOptimizer ] 创建 LOD: ${r.length} 个细节级别`),t}getModelStats(o){let r=0,e=0,t=0,i=new Set;return o.traverse(n=>{if(n.isMesh){r++;const s=n.geometry;s.index?e+=s.index.count/3:s.attributes.position&&(e+=s.attributes.position.count/3),s.attributes.position&&(t+=s.attributes.position.count),n.material&&(Array.isArray(n.material)?n.material.forEach(l=>i.add(l.uuid)):i.add(n.material.uuid))}}),{meshCount:r,triangleCount:e,vertexCount:t,materialCount:i.size}}generateReport(o,r){const e=this.getModelStats(o),t=this.getModelStats(r);return console.group("📊 模型优化报告"),console.log("网格数量:",`${e.meshCount} -> ${t.meshCount}`),console.log("三角形数量:",`${e.triangleCount} -> ${t.triangleCount} (${((1-t.triangleCount/e.triangleCount)*100).toFixed(1)}% 减少)`),console.log("顶点数量:",`${e.vertexCount} -> ${t.vertexCount} (${((1-t.vertexCount/e.vertexCount)*100).toFixed(1)}% 减少)`),console.log("材质数量:",`${e.materialCount} -> ${t.materialCount}`),console.groupEnd(),{original:e,optimized:t,reduction:{triangles:1-t.triangleCount/e.triangleCount,vertices:1-t.vertexCount/e.vertexCount}}}simplifyModel(o,r=.5,e={}){const{minFaceCount:t=100,preserveUVs:i=!0}=e;let n=0,s=0;return o.traverse(l=>{if(l.isMesh){const f=l.geometry;if(!f.isBufferGeometry){s++;return}if((f.index?f.index.count/3:f.attributes.position.count/3)<t){s++;return}try{const m=this.simplifyGeometry(l,r);l.geometry=m,n++,!i&&m.attributes.uv&&m.deleteAttribute("uv")}catch(m){console.warn("[ ModelOptimizer ] 简化网格失败:",l.name||l.uuid,m),s++}}}),console.log(`[ ModelOptimizer ] 模型简化完成: 成功 ${n} 个, 跳过 ${s} 个`),o}}const d=new c;exports.ModelOptimizer=c;exports.modelOptimizer=d;
@@ -0,0 +1,179 @@
1
+ import * as a from "three";
2
+ class f {
3
+ constructor() {
4
+ this.simplifyRatio = 0.5;
5
+ }
6
+ /**
7
+ * 简化模型几何体
8
+ * @param {THREE.Mesh} mesh - 要简化的网格
9
+ * @param {number} ratio - 简化比例 (0-1), 0.5 表示保留 50% 的面
10
+ * @returns {THREE.BufferGeometry} 简化后的几何体
11
+ */
12
+ simplifyGeometry(o, r = this.simplifyRatio) {
13
+ const e = o.geometry;
14
+ if (!e.isBufferGeometry)
15
+ return console.warn("[ ModelOptimizer ] 非BufferGeometry,跳过简化"), e;
16
+ const t = e.index ? e.index.count / 3 : e.attributes.position.count / 3, i = Math.floor(t * r);
17
+ if (i < 4)
18
+ return console.warn("[ ModelOptimizer ] 简化后面数太少,跳过"), e;
19
+ try {
20
+ const n = this.modifierModify(e, i);
21
+ return console.log(`[ ModelOptimizer ] 简化完成: ${t} -> ${i} 面`), n;
22
+ } catch (n) {
23
+ return console.warn("[ ModelOptimizer ] 简化失败,使用原几何体", n), e;
24
+ }
25
+ }
26
+ /**
27
+ * 使用修饰器修改几何体(简化实现)
28
+ * 注意: 完整实现需要 three/examples/jsm/modifiers/SimplifyModifier.js
29
+ * 这里提供一个基础实现
30
+ */
31
+ modifierModify(o, r) {
32
+ if (typeof a.SimplifyModifier < "u")
33
+ return new a.SimplifyModifier().modify(o, r);
34
+ const e = o.clone();
35
+ return e.attributes.normal && e.deleteAttribute("normal"), e.attributes.uv && this.simplifyRatio < 0.3 && e.deleteAttribute("uv"), e;
36
+ }
37
+ /**
38
+ * 优化材质 - 合并相同材质
39
+ * @param {THREE.Object3D} object - 要优化的对象
40
+ */
41
+ optimizeMaterials(o) {
42
+ const r = /* @__PURE__ */ new Map();
43
+ let e = 0;
44
+ return o.traverse((t) => {
45
+ if (t.isMesh && t.material) {
46
+ const i = this.getMaterialKey(t.material);
47
+ if (r.has(i)) {
48
+ const n = t.material;
49
+ t.material = r.get(i), e++, n.dispose && n.dispose();
50
+ } else
51
+ r.set(i, t.material);
52
+ }
53
+ }), console.log(`[ ModelOptimizer ] 材质合并: 合并了 ${e} 个重复材质`), o;
54
+ }
55
+ /**
56
+ * 获取材质的唯一标识
57
+ */
58
+ getMaterialKey(o) {
59
+ var e;
60
+ return [
61
+ o.type,
62
+ (e = o.color) == null ? void 0 : e.getHex(),
63
+ o.roughness,
64
+ o.metalness,
65
+ o.opacity,
66
+ o.transparent
67
+ ].join("|");
68
+ }
69
+ /**
70
+ * 合并网格 - 将多个网格合并为一个
71
+ * @param {Array<THREE.Mesh>} meshes - 要合并的网格数组
72
+ * @returns {THREE.Mesh} 合并后的网格
73
+ */
74
+ mergeMeshes(o) {
75
+ if (o.length === 0) return null;
76
+ const r = [], e = [];
77
+ if (o.forEach((t) => {
78
+ t.geometry && r.push(t.geometry), t.material && e.push(t.material);
79
+ }), r.length === 0) return null;
80
+ try {
81
+ if (typeof a.BufferGeometryUtils < "u" && a.BufferGeometryUtils.mergeGeometries) {
82
+ const t = a.BufferGeometryUtils.mergeGeometries(r), i = new a.Mesh(t, e[0]);
83
+ return console.log(`[ ModelOptimizer ] 合并了 ${o.length} 个网格`), i;
84
+ }
85
+ } catch (t) {
86
+ console.warn("[ ModelOptimizer ] 合并网格失败", t);
87
+ }
88
+ return null;
89
+ }
90
+ /**
91
+ * 生成 LOD (Level of Detail) 对象
92
+ * @param {THREE.Mesh} mesh - 原始网格
93
+ * @param {Array<number>} distances - LOD 距离数组
94
+ * @param {Array<number>} ratios - 简化比例数组
95
+ * @returns {THREE.LOD} LOD 对象
96
+ */
97
+ createLOD(o, r = [0, 50, 100], e = [1, 0.5, 0.25]) {
98
+ const t = new a.LOD();
99
+ t.addLevel(o, r[0]);
100
+ for (let i = 1; i < r.length; i++) {
101
+ const n = o.clone();
102
+ n.geometry = this.simplifyGeometry(o, e[i]), t.addLevel(n, r[i]);
103
+ }
104
+ return console.log(`[ ModelOptimizer ] 创建 LOD: ${r.length} 个细节级别`), t;
105
+ }
106
+ /**
107
+ * 计算模型统计信息
108
+ * @param {THREE.Object3D} object - 要分析的对象
109
+ * @returns {Object} 统计信息
110
+ */
111
+ getModelStats(o) {
112
+ let r = 0, e = 0, t = 0, i = /* @__PURE__ */ new Set();
113
+ return o.traverse((n) => {
114
+ if (n.isMesh) {
115
+ r++;
116
+ const s = n.geometry;
117
+ s.index ? e += s.index.count / 3 : s.attributes.position && (e += s.attributes.position.count / 3), s.attributes.position && (t += s.attributes.position.count), n.material && (Array.isArray(n.material) ? n.material.forEach((l) => i.add(l.uuid)) : i.add(n.material.uuid));
118
+ }
119
+ }), {
120
+ meshCount: r,
121
+ triangleCount: e,
122
+ vertexCount: t,
123
+ materialCount: i.size
124
+ };
125
+ }
126
+ /**
127
+ * 生成优化报告
128
+ * @param {THREE.Object3D} original - 原始对象
129
+ * @param {THREE.Object3D} optimized - 优化后对象
130
+ */
131
+ generateReport(o, r) {
132
+ const e = this.getModelStats(o), t = this.getModelStats(r);
133
+ return console.group("📊 模型优化报告"), console.log("网格数量:", `${e.meshCount} -> ${t.meshCount}`), console.log("三角形数量:", `${e.triangleCount} -> ${t.triangleCount} (${((1 - t.triangleCount / e.triangleCount) * 100).toFixed(1)}% 减少)`), console.log("顶点数量:", `${e.vertexCount} -> ${t.vertexCount} (${((1 - t.vertexCount / e.vertexCount) * 100).toFixed(1)}% 减少)`), console.log("材质数量:", `${e.materialCount} -> ${t.materialCount}`), console.groupEnd(), {
134
+ original: e,
135
+ optimized: t,
136
+ reduction: {
137
+ triangles: 1 - t.triangleCount / e.triangleCount,
138
+ vertices: 1 - t.vertexCount / e.vertexCount
139
+ }
140
+ };
141
+ }
142
+ /**
143
+ * 简化模型 - 对整个模型进行几何体简化
144
+ * @param {THREE.Object3D} object - 要简化的 3D 对象
145
+ * @param {number} ratio - 简化比例 (0-1), 0.5 表示保留 50% 的面
146
+ * @param {Object} options - 简化选项
147
+ * @param {number} options.minFaceCount - 最小面数阈值,低于此值不简化(默认 100)
148
+ * @param {boolean} options.preserveUVs - 是否保留 UV 坐标(默认 true)
149
+ * @returns {THREE.Object3D} 简化后的对象
150
+ */
151
+ simplifyModel(o, r = 0.5, e = {}) {
152
+ const { minFaceCount: t = 100, preserveUVs: i = !0 } = e;
153
+ let n = 0, s = 0;
154
+ return o.traverse((l) => {
155
+ if (l.isMesh) {
156
+ const m = l.geometry;
157
+ if (!m.isBufferGeometry) {
158
+ s++;
159
+ return;
160
+ }
161
+ if ((m.index ? m.index.count / 3 : m.attributes.position.count / 3) < t) {
162
+ s++;
163
+ return;
164
+ }
165
+ try {
166
+ const u = this.simplifyGeometry(l, r);
167
+ l.geometry = u, n++, !i && u.attributes.uv && u.deleteAttribute("uv");
168
+ } catch (u) {
169
+ console.warn("[ ModelOptimizer ] 简化网格失败:", l.name || l.uuid, u), s++;
170
+ }
171
+ }
172
+ }), console.log(`[ ModelOptimizer ] 模型简化完成: 成功 ${n} 个, 跳过 ${s} 个`), o;
173
+ }
174
+ }
175
+ const c = new f();
176
+ export {
177
+ f as ModelOptimizer,
178
+ c as modelOptimizer
179
+ };
package/dist/threejs.cjs CHANGED
@@ -1 +1,3 @@
1
- "use strict";var g=Object.defineProperty;var O=(h,e,s)=>e in h?g(h,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):h[e]=s;var t=(h,e,s)=>O(h,typeof e!="symbol"?e+"":e,s);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("./useGLTFLoader-D01iU8lB.cjs"),r=require("./ImageLoader-DwvBWW6h.cjs"),c=require("./modelSerialize-B8gu_KnK.cjs"),o=require("three"),T="1.3.2",L={enableDamping:!0,dampingFactor:.25,screenSpacePanning:!1,minDistance:.1,maxDistance:1e3,maxPolarAngle:o.MathUtils.degToRad(60)};class p{constructor(e,s){t(this,"isReady",!1);t(this,"scene",null);t(this,"camera",null);t(this,"renderer",null);t(this,"control",null);t(this,"css3dRenderer",null);t(this,"el",null);t(this,"renderRequested",!1);t(this,"selector",null);t(this,"eventsListener",{});t(this,"stats",null);t(this,"isDispose",!1);t(this,"version","0.0.0");t(this,"initOpt",{css3d:!1,stats:!1,renderType:"change",initListener:"True",control:{init:!0,options:{}}});t(this,"setup",e=>{this.isDispose=!1,this.selector=e,this.el=document.querySelector(e);const s=Math.tan(Math.PI/180*this.camera.fov/2),[i,d]=this.getTargetSize();if(this.camera.aspect=i/d,this.camera.position.set(47,39,100),this.camera.fov=360/Math.PI*Math.atan(s*(d/i)),this.camera.lookAt(0,0,0),this.camera.updateProjectionMatrix(),this.renderer.setPixelRatio(window.devicePixelRatio),this.renderer.setSize(i,d),this.el.appendChild(this.renderer.domElement),this.initOpt.control&&this.initOpt.control.init){this.control=r.createOrbitControl(this.camera,this.renderer.domElement);const m=Object.assign(L,this.initOpt.control.options||{});Object.keys(m).forEach(n=>{this.control[n]=m[n]})}setTimeout(()=>{this.isReady=!0},20),this.initOpt.stats&&this.initStats(),this.initOpt.css3d&&this.initCss3dRenderer(),this.initOpt.renderType==="loop"?requestAnimationFrame(this.animate):this.initOpt.renderType==="change"&&this.control&&this.control.addEventListener("change",this.requestRenderIfNotRequested),this.initListener()});t(this,"onContextLost",e=>{e.preventDefault(),cancelAnimationFrame(this.animate)});t(this,"onContextRestored",e=>{e.preventDefault(),this.dispose(),setTimeout(()=>{this.setup(this.selector)},20)});t(this,"initListener",()=>{this.initOpt.initListener=="True"&&window&&window.addEventListener("resize",()=>this.onResize(),!1),this.renderer.domElement.addEventListener("webglcontextlost",this.onContextLost,!1),this.renderer.domElement.addEventListener("webglcontextrestored",this.onContextRestored,!1)});t(this,"removeListener",()=>{window&&window.removeEventListener("resize",this.onResize,!1),this.renderer.domElement.removeEventListener("webglcontextlost",this.onContextLost.bind(p),!1),this.renderer.domElement.removeEventListener("webglcontextrestored",this.onContextRestored.bind(p),!1)});t(this,"animate",()=>{this.initOpt.renderType==="loop"&&this.onRender(),requestAnimationFrame(this.animate)});t(this,"onRender",()=>{this.isDispose||(this.renderRequested=!1,this.stats&&this.stats.update(),this.control&&this.control.update(),this.renderer.render(this.scene,this.camera),this.css3dRenderer&&this.css3dRenderer.render(this.scene,this.camera),this.eventsListener.onRender&&this.eventsListener.onRender.length&&this.eventsListener.onRender.forEach(e=>e()))});t(this,"requestRenderIfNotRequested",()=>{this.renderRequested||(this.renderRequested=!0,requestAnimationFrame(()=>{this.onRender()}))});t(this,"onResize",()=>{setTimeout(()=>{const e=Math.tan(Math.PI/180*this.camera.fov/2),[s,i]=this.getTargetSize();this.camera.aspect=s/i,this.camera.fov=360/Math.PI*Math.atan(e*(i/s)),this.camera.updateProjectionMatrix(),this.camera.lookAt(this.scene.position),this.renderer.setSize(s,i),this.css3dRenderer&&this.css3dRenderer.setSize(s,i),this.onRender()},0)});t(this,"frameArea",(e,s,i)=>{const d=new o.Box3().setFromObject(e),m=d.getSize(new o.Vector3).length(),n=d.getCenter(new o.Vector3);i&&n.add(i);const f=m*s*.5,R=o.MathUtils.degToRad(this.camera.fov*.5),b=f/Math.tan(R),u=new o.Vector3().subVectors(this.camera.position,n).multiply(new o.Vector3(1,1,1)).normalize().multiplyScalar(b).add(n),l={x:u.x,y:u.y,z:u.z,lookAt_x:n.x,lookAt_y:n.y,lookAt_z:n.z};return this.camera.position.set(l.x,l.y,l.z),this.camera.lookAt(l.lookAt_x,l.lookAt_y,l.lookAt_z),this.camera.updateProjectionMatrix(),this.control.target.copy(n),this.control.update(),m});t(this,"on",(e,s)=>{!e||!s||(this.eventsListener[e]||(this.eventsListener[e]=[]),this.eventsListener[e].push(s))});this.isReady=!1,this.scene=new o.Scene({}),this.camera=new o.PerspectiveCamera(50,1,.1,2e3),this.renderer=new o.WebGLRenderer({antialias:!0,alpha:!0,precision:"mediump",logarithmicDepthBuffer:!0}),this.version=T,s&&(this.initOpt=Object.assign(this.initOpt,s)),e&&this.setup(e)}initStats(){const e=new Stats;e.dom.style.cssText="position:absolute;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000",this.el.appendChild(e.dom)}initCss3dRenderer(){this.css3dRenderer=new r.CSS3DRenderer;const[e,s]=this.getTargetSize();this.css3dRenderer.setSize(e,s),this.css3dRenderer.domElement.style.position="absolute",this.css3dRenderer.domElement.style.pointerEvents="none",this.css3dRenderer.domElement.style.top=0,this.css3dRenderer.domElement.style.left=0,this.el.appendChild(this.css3dRenderer.domElement)}getTargetSize(){const e=document.querySelector(this.selector);return e?[e.clientWidth,e.clientHeight]:[0,0]}off(e){e||(this.eventsListener={}),this.eventsListener[e]&&(this.eventsListener[e]=[])}dispose(){this.isDispose=!0,this.removeListener(),r.disposeThreeObject(this.scene),this.renderer.dispose(),this.renderer.domElement.remove(),this.el=null,this.renderer=null,this.camera=null,this.scene=null,this.control=null,this.css3dRenderer=null}}exports.IDBCache=a.IDBCache;exports.intersectColor=a.intersectColor;exports.obbObjects=a.obbObjects;exports.useGLTFLoader=a.useGLTFLoader;exports.useObb=a.useObb;exports.useRaycaster=a.useRaycaster;exports.useThreeJs=a.useThreeJs;exports.ImageLoader=r.ImageLoader;exports.createArrowHelper=r.createArrowHelper;exports.createAxesHelper=r.createAxesHelper;exports.createBox3Helper=r.createBox3Helper;exports.createCameraHelper=r.createCameraHelper;exports.createGridHelper=r.createGridHelper;exports.createMapControls=r.createMapControls;exports.createOrbitControl=r.createOrbitControl;exports.createRaycaster=r.createRaycaster;exports.createStats=r.createStats;exports.disposeThreeObject=r.disposeThreeObject;exports.initEnvImage=r.initEnvImage;exports.createInfoPlane=c.createInfoPlane;exports.createTagPlane=c.createTagPlane;exports.dataToObject3D=c.dataToObject3D;exports.dataToObject3DSync=c.dataToObject3DSync;exports.getCommonParent=c.getCommonParent;exports.object3DToData=c.object3DToData;exports.object3DToDataSync=c.object3DToDataSync;exports.ThreeIns=p;
1
+ "use strict";var j=Object.defineProperty;var q=(x,e,t)=>e in x?j(x,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):x[e]=t;var o=(x,e,t)=>q(x,typeof e!="symbol"?e+"":e,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g=require("./useBatchGLTFLoader-BjAvIpyB.cjs"),i=require("./PredictiveLoader-DDxh7dDg.cjs"),R=require("./ImageLoader-DL32KyTh.cjs"),S=require("./modelOptimizer-A0Cs6f9e.cjs"),r=require("three"),B="1.4.1",X=50,Y=20,Z=20,E={TOP:"top",RIGHT:"right",LEFT:"left",ISO:"iso"},G={enableDamping:!0,dampingFactor:.25,screenSpacePanning:!1,minDistance:.1,maxDistance:1e3,maxPolarAngle:r.MathUtils.degToRad(60)};class I{constructor(e,t){o(this,"isReady",!1);o(this,"scene",null);o(this,"camera",null);o(this,"renderer",null);o(this,"control",null);o(this,"css3dRenderer",null);o(this,"el",null);o(this,"renderRequested",!1);o(this,"selector",null);o(this,"eventsListener",{});o(this,"stats",null);o(this,"isDispose",!1);o(this,"version","0.0.0");o(this,"boxHelper",null);o(this,"initOpt",{css3d:!1,stats:!1,renderType:"change",initListener:!0,initialFov:50,control:{init:!0,options:{}}});o(this,"setup",e=>{if(this.isDispose=!1,this.selector=e,this.el=document.querySelector(e),!this.el){console.error(`ThreeIns: 找不到元素 ${e}`);return}const[t,h]=this.getTargetSize();if(this.updateCameraFOV(t,h),this.camera.position.set(0,0,0),this.camera.lookAt(0,0,0),this.camera.updateProjectionMatrix(),this.renderer.setPixelRatio(window.devicePixelRatio),this.renderer.setSize(t,h),this.el.appendChild(this.renderer.domElement),this.initOpt.control&&this.initOpt.control.init){this.control=i.createOrbitControl(this.camera,this.renderer.domElement);const s=Object.assign(G,this.initOpt.control.options||{});Object.keys(s).forEach(F=>{this.control[F]=s[F]})}setTimeout(()=>{this.isReady=!0},Y),this.initOpt.stats&&this.initStats(),this.initOpt.css3d&&this.initCss3dRenderer(),this.initOpt.renderType==="loop"?this.animate():this.initOpt.renderType==="change"&&this.control&&this.control.addEventListener("change",this.requestRenderIfNotRequested),this.initListener()});o(this,"onContextLost",e=>{e.preventDefault(),this.animationFrameId&&cancelAnimationFrame(this.animationFrameId)});o(this,"onContextRestored",e=>{e.preventDefault(),this.dispose(),setTimeout(()=>{this.setup(this.selector)},Z)});o(this,"initListener",()=>{this.initOpt.initListener&&window&&window.addEventListener("resize",this.onResize,!1),this.renderer.domElement.addEventListener("webglcontextlost",this.onContextLost,!1),this.renderer.domElement.addEventListener("webglcontextrestored",this.onContextRestored,!1)});o(this,"removeListener",()=>{window&&window.removeEventListener("resize",this.onResize,!1),this.renderer&&this.renderer.domElement&&(this.renderer.domElement.removeEventListener("webglcontextlost",this.onContextLost,!1),this.renderer.domElement.removeEventListener("webglcontextrestored",this.onContextRestored,!1))});o(this,"animate",()=>{this.isDispose||(this.initOpt.renderType==="loop"&&this.onRender(),this.animationFrameId=requestAnimationFrame(this.animate))});o(this,"onRender",()=>{this.isDispose||(this.renderRequested=!1,this.stats&&this.stats.update(),this.control&&this.control.update(),this.renderer.render(this.scene,this.camera),this.css3dRenderer&&this.css3dRenderer.render(this.scene,this.camera),this.eventsListener.onRender&&this.eventsListener.onRender.length&&this.eventsListener.onRender.forEach(e=>e()))});o(this,"requestRenderIfNotRequested",()=>{this.renderRequested||(this.renderRequested=!0,requestAnimationFrame(()=>{this.onRender()}))});o(this,"onResize",()=>{this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=setTimeout(()=>{const[e,t]=this.getTargetSize();this.updateCameraFOV(e,t),this.camera.lookAt(this.scene.position),this.renderer.setSize(e,t),this.css3dRenderer&&this.css3dRenderer.setSize(e,t),this.onRender()},X)});o(this,"frameArea",(e,t)=>(console.warn(`[ThreeIns] frameArea() 已弃用,建议使用 setView() 方法。
2
+ 旧用法: threeIns.frameArea(model, scale)
3
+ 新用法: threeIns.setView(model, ViewType.ISO, { scale })`),this.setView(e,E.ISO,{scale:t,animate:!1,showBox:!1})));o(this,"setView",(e,t,h={})=>{let s=h.scale||.8,F=h.offset||null,b=h.showBox||!1,H=h.boxColor||16776960,O=h.animate!==void 0?h.animate:!0,z=h.duration||1e3;const T=new r.Box3().setFromObject(e);let d=T.getCenter(new r.Vector3);F&&d.add(F);const w={top:new r.Vector3(0,1,0),right:new r.Vector3(2,1,1).normalize(),left:new r.Vector3(-2,1,1).normalize(),iso:new r.Vector3(0,1,1).normalize()},M=w[t]||w.iso,n=T.getSize(new r.Vector3),v=this.camera.aspect,a=r.MathUtils.degToRad(this.camera.fov*.5),P=r.MathUtils.degToRad(80),m=Math.min(Math.atan(Math.tan(a)*v),P);let u;if(t==="top"){const l=n.x*.5/(Math.tan(m)*s),c=n.z*.5/(Math.tan(a)*s);u=Math.max(l,c)}else if(t==="right"||t==="left"){const l=n.y*.5/(Math.tan(a)*s),c=n.z*.5/(Math.tan(a)*s);u=Math.max(l,c)}else{const l=n.x*.5/(Math.tan(m)*s),c=n.y*.5/(Math.tan(a)*s),f=n.z*.5/(Math.tan(a)*s);u=Math.max(l,c,f)}const p=M.clone().multiplyScalar(u).add(d);if(b&&(console.log("📍 相机位置验证:"),console.log(" - 方向向量:",M),console.log(" - 距离:",u.toFixed(2)),console.log(" - 包围盒中心:",d),console.log(" - 计算公式: direction * distance + boxCenter"),console.log(" - 目标位置:",p),console.log(" - 实际相机与中心的距离:",p.clone().sub(d).length().toFixed(2))),b?(this.boxHelper&&(this.scene.remove(this.boxHelper),this.boxHelper=null),this.boxHelper=new r.Box3Helper(T,H),this.scene.add(this.boxHelper)):this.boxHelper&&(this.scene.remove(this.boxHelper),this.boxHelper=null),O){const l=this.camera.position.clone(),c=this.control?this.control.target.clone():new r.Vector3(0,0,0),f=d,V=Date.now(),C=()=>{const A=Date.now()-V,y=Math.min(A/z,1),D=1-Math.pow(1-y,3);if(this.camera.position.lerpVectors(l,p,D),this.control){const L=new r.Vector3;L.lerpVectors(c,f,D),this.control.target.copy(L),this.camera.lookAt(L)}else this.camera.lookAt(d);this.camera.updateProjectionMatrix(),y<1?requestAnimationFrame(C):(this.camera.position.copy(p),this.camera.lookAt(d),this.camera.updateProjectionMatrix(),this.control&&(this.control.target.copy(d),this.control.update()),this.onRender())};C()}else this.camera.position.copy(p),this.camera.lookAt(d),this.camera.updateProjectionMatrix(),this.control&&(this.control.target.copy(d),this.control.update()),this.onRender();if(b){if(console.log("🎥 视角切换信息:"),console.log(" - 视角类型:",t),console.log(" - 相机位置:",p),console.log(" - 观察目标:",d),console.log(" - 方向向量:",M),console.log(" - 包围盒尺寸:",n),console.log(" - 包围盒中心:",T.getCenter(new r.Vector3)),console.log(" - 水平 FOV:",r.MathUtils.radToDeg(m*2).toFixed(2)+"°"),console.log(" - 垂直 FOV:",r.MathUtils.radToDeg(a*2).toFixed(2)+"°"),console.log(" - 宽高比:",v.toFixed(4)),console.log(" - 模型宽度:",n.x.toFixed(2)),console.log(" - 模型高度:",n.y.toFixed(2)),console.log(" - 模型深度:",n.z.toFixed(2)),console.log(" - 传入的 scale 参数:",s),t==="top"){const l=n.x*.5/(Math.tan(m)*s),c=n.z*.5/(Math.tan(a)*s);console.log(" - 模型 X 尺寸 (宽度):",n.x.toFixed(2)),console.log(" - 模型 Z 尺寸 (深度):",n.z.toFixed(2)),console.log(" - tan(halfFovX):",Math.tan(m).toFixed(4)),console.log(" - tan(halfFovY):",Math.tan(a).toFixed(4)),console.log(" - X方向距离计算: (",(n.x*.5).toFixed(2),") / (",Math.tan(m).toFixed(4)," *",s,") =",l.toFixed(2)),console.log(" - Z方向距离计算: (",(n.z*.5).toFixed(2),") / (",Math.tan(a).toFixed(4)," *",s,") =",c.toFixed(2)),console.log(" - X方向距离 (scale="+s+"):",l.toFixed(2)),console.log(" - Z方向距离 (scale="+s+"):",c.toFixed(2))}else if(t==="right"||t==="left"){const l=n.y*.5/(Math.tan(a)*s),c=n.z*.5/(Math.tan(a)*s);console.log(" - Y方向距离 (scale="+s+"):",l.toFixed(2)),console.log(" - Z方向距离 (scale="+s+"):",c.toFixed(2))}else{const l=n.x*.5/(Math.tan(m)*s),c=n.y*.5/(Math.tan(a)*s),f=n.z*.5/(Math.tan(a)*s);console.log(" - 模型 X 尺寸 (宽度):",n.x.toFixed(2)),console.log(" - 模型 Y 尺寸 (高度):",n.y.toFixed(2)),console.log(" - 模型 Z 尺寸 (深度):",n.z.toFixed(2)),console.log(" - tan(halfFovX):",Math.tan(m).toFixed(4)),console.log(" - tan(halfFovY):",Math.tan(a).toFixed(4)),console.log(" - X方向距离计算: (",(n.x*.5).toFixed(2),") / (",Math.tan(m).toFixed(4)," *",s,") =",l.toFixed(2)),console.log(" - Y方向距离计算: (",(n.y*.5).toFixed(2),") / (",Math.tan(a).toFixed(4)," *",s,") =",c.toFixed(2)),console.log(" - Z方向距离计算: (",(n.z*.5).toFixed(2),") / (",Math.tan(a).toFixed(4)," *",s,") =",f.toFixed(2)),console.log(" - X方向距离 (scale="+s+"):",l.toFixed(2)),console.log(" - Y方向距离 (scale="+s+"):",c.toFixed(2)),console.log(" - Z方向距离 (scale="+s+"):",f.toFixed(2)),console.log(" - 最大距离 (Max):",Math.max(l,c,f).toFixed(2))}console.log(" - 最终距离:",u.toFixed(2)),console.log(" - 缩放比例:",s),console.log(" - 动画:",O?"是 ("+z+"ms)":"否")}return{position:p,target:d,distance:u,viewType:t}});o(this,"on",(e,t)=>!e||!t||typeof t!="function"?(console.warn("ThreeIns.on: 无效的参数"),()=>{}):(this.eventsListener[e]||(this.eventsListener[e]=[]),this.eventsListener[e].push(t),()=>this.off(e,t)));this.isReady=!1,this.scene=new r.Scene({}),this.camera=new r.PerspectiveCamera(50,1,.1,2e3),this.renderer=new r.WebGLRenderer({antialias:!0,alpha:!0,precision:"mediump",logarithmicDepthBuffer:!0}),this.version=B,this.onContextLost=this.onContextLost.bind(this),this.onContextRestored=this.onContextRestored.bind(this),this.onResize=this.onResize.bind(this),this.animate=this.animate.bind(this),this.resizeTimer=null,this.animationFrameId=null,t&&(this.initOpt=Object.assign(this.initOpt,t)),e&&this.setup(e)}updateCameraFOV(e,t){const h=this.initOpt.initialFov||50,s=Math.tan(Math.PI/180*h/2);this.camera.aspect=e/t,this.camera.fov=360/Math.PI*Math.atan(s*(t/e)),this.camera.updateProjectionMatrix()}initStats(){this.stats=new i.Stats,this.stats.dom.style.cssText="position:absolute;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000",this.el.appendChild(this.stats.dom)}initCss3dRenderer(){this.css3dRenderer=new i.CSS3DRenderer;const[e,t]=this.getTargetSize();this.css3dRenderer.setSize(e,t),this.css3dRenderer.domElement.style.position="absolute",this.css3dRenderer.domElement.style.pointerEvents="none",this.css3dRenderer.domElement.style.top=0,this.css3dRenderer.domElement.style.left=0,this.el.appendChild(this.css3dRenderer.domElement)}getTargetSize(){return document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement?[window.innerWidth,window.innerHeight]:this.el?!document.body.contains(this.el)&&(console.warn(`ThreeIns: 缓存的元素已失效,重新查询 ${this.selector}`),this.el=document.querySelector(this.selector),!this.el)?[0,0]:[this.el.clientWidth,this.el.clientHeight]:[0,0]}off(e,t){if(!e){this.eventsListener={};return}this.eventsListener[e]&&(t?this.eventsListener[e]=this.eventsListener[e].filter(h=>h!==t):this.eventsListener[e]=[])}dispose(){this.isDispose||(this.isDispose=!0,this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.resizeTimer&&(clearTimeout(this.resizeTimer),this.resizeTimer=null),this.removeListener(),this.eventsListener={},this.stats&&this.stats.dom&&(this.stats.dom.remove(),this.stats=null),this.css3dRenderer&&(this.css3dRenderer.domElement.remove(),this.css3dRenderer=null),this.boxHelper&&(this.scene.remove(this.boxHelper),this.boxHelper=null),this.scene&&(i.disposeThreeObject(this.scene),this.scene=null),this.renderer&&(this.renderer.dispose(),this.renderer.domElement&&this.renderer.domElement.remove(),this.renderer=null),this.control&&(this.control.dispose(),this.control=null),this.camera=null,this.el=null,this.selector=null,console.log("ThreeIns: 资源已清理完成"))}}o(I,"ViewType",E);exports.intersectColor=g.intersectColor;exports.obbObjects=g.obbObjects;exports.useBatchGLTFLoader=g.useBatchGLTFLoader;exports.useObb=g.useObb;exports.useRaycaster=g.useRaycaster;exports.useThreeJs=g.useThreeJs;exports.CacheMonitor=i.CacheMonitor;exports.ErrorType=i.ErrorType;exports.IDBCache=i.IDBCache;exports.ModelLoadError=i.ModelLoadError;exports.PredictiveLoader=i.PredictiveLoader;exports.ProgressiveSceneBuilder=i.ProgressiveSceneBuilder;exports.RetryHelper=i.RetryHelper;exports.cacheMonitor=i.cacheMonitor;exports.createArrowHelper=i.createArrowHelper;exports.createAxesHelper=i.createAxesHelper;exports.createBox3Helper=i.createBox3Helper;exports.createCameraHelper=i.createCameraHelper;exports.createGridHelper=i.createGridHelper;exports.createMapControls=i.createMapControls;exports.createOrbitControl=i.createOrbitControl;exports.createRaycaster=i.createRaycaster;exports.createStats=i.createStats;exports.dataToObject3D=i.dataToObject3D;exports.dataToObject3DSync=i.dataToObject3DSync;exports.disposeThreeObject=i.disposeThreeObject;exports.object3DToData=i.object3DToData;exports.object3DToDataSync=i.object3DToDataSync;exports.predictiveLoader=i.predictiveLoader;exports.rebuildScene=i.rebuildScene;exports.useGLTFLoader=i.useGLTFLoader;exports.ImageLoader=R.ImageLoader;exports.createInfoPlane=R.createInfoPlane;exports.createTagPlane=R.createTagPlane;exports.getCommonParent=R.getCommonParent;exports.initEnvImage=R.initEnvImage;exports.ModelOptimizer=S.ModelOptimizer;exports.modelOptimizer=S.modelOptimizer;exports.ThreeIns=I;exports.ViewType=E;