@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/ImageLoader-Br_nvMOg.js +1444 -0
- package/dist/ImageLoader-DL32KyTh.cjs +24 -0
- package/dist/PredictiveLoader-CZfMSjv-.js +3731 -0
- package/dist/PredictiveLoader-DDxh7dDg.cjs +2 -0
- package/dist/assets/gltfParser.worker-Bqz8BBJx.js +6 -0
- package/dist/assets/gltfParserOptimized.worker-DfipxPjm.js +6 -0
- package/dist/hooks.cjs +1 -1
- package/dist/hooks.js +7 -5
- package/dist/modelOptimizer-A0Cs6f9e.cjs +1 -0
- package/dist/modelOptimizer-BRPnM2RH.js +179 -0
- package/dist/threejs.cjs +3 -1
- package/dist/threejs.js +334 -118
- package/dist/useBatchGLTFLoader-B5EUagWI.js +493 -0
- package/dist/useBatchGLTFLoader-BjAvIpyB.cjs +5 -0
- package/dist/utils.cjs +1 -1
- package/dist/utils.js +32 -20
- package/package.json +1 -1
- package/readme.md +1186 -94
- package/dist/ImageLoader-DwvBWW6h.cjs +0 -5
- package/dist/ImageLoader-xzOH4Owt.js +0 -860
- package/dist/modelSerialize-B8gu_KnK.cjs +0 -15
- package/dist/modelSerialize-DWUt6OcZ.js +0 -276
- package/dist/useGLTFLoader-D01iU8lB.cjs +0 -2
- package/dist/useGLTFLoader-MhUFIZp1.js +0 -2510
package/dist/hooks.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { i as a, o, c as r, b, a as
|
|
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
|
|
6
|
-
|
|
7
|
-
t as
|
|
8
|
-
u as
|
|
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
|
|
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;
|