fl-web-component 1.4.8 → 2.0.0-beta.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.
Files changed (37) hide show
  1. package/README.md +1 -30
  2. package/dist/fl-web-component.common.1.js +2 -2
  3. package/dist/fl-web-component.common.1.js.map +1 -1
  4. package/dist/fl-web-component.common.2.js.map +1 -1
  5. package/dist/fl-web-component.common.js +77408 -47295
  6. package/dist/fl-web-component.common.js.map +1 -1
  7. package/dist/fl-web-component.css +1 -1
  8. package/package.json +12 -4
  9. package/packages/components/com-graphics/box.json +77 -0
  10. package/packages/components/com-graphics/component/ann-tool.vue +465 -0
  11. package/packages/components/com-graphics/index copy.vue +1679 -0
  12. package/packages/components/com-graphics/index.vue +3890 -301
  13. package/packages/components/com-graphics/pid.vue +210 -44
  14. package/packages/components/com-graphics/test.html +127 -0
  15. package/packages/components/com-tiles/index.vue +187 -0
  16. package/packages/utils/StreamLoader.js +1498 -0
  17. package/packages/utils/StreamLoaderParser.worker.js +595 -0
  18. package/patches/camera-controls+2.9.0.patch +63 -63
  19. package/src/main.js +9 -1
  20. package/src/static/ann-img/mark_circle@2x.png +0 -0
  21. package/src/static/ann-img/mark_clear@2x.png +0 -0
  22. package/src/static/ann-img/mark_cloud@2x.png +0 -0
  23. package/src/static/ann-img/mark_color@2x.png +0 -0
  24. package/src/static/ann-img/mark_eraser@2x.png +0 -0
  25. package/src/static/ann-img/mark_exit@2x.png +0 -0
  26. package/src/static/ann-img/mark_finish@2x.png +0 -0
  27. package/src/static/ann-img/mark_font@2x.png +0 -0
  28. package/src/static/ann-img/mark_polyline@2x.png +0 -0
  29. package/src/static/ann-img/mark_rectangle@2x.png +0 -0
  30. package/src/static/ann-img/mark_zoomin@2x.png +0 -0
  31. package/src/static/ann-img/mark_zoomout@2x.png +0 -0
  32. package/src/utils/cloud.js +110 -0
  33. package/src/utils/cursor.js +10 -0
  34. package/src/utils/flgltf-parser.js +245 -193
  35. package/src/utils/instance-parser.js +718 -170
  36. package/dist/fl-web-component.common.3.js +0 -7740
  37. package/dist/fl-web-component.common.3.js.map +0 -1
@@ -3,6 +3,7 @@ import { FontLoader } from 'three/examples/jsm/loaders/FontLoader';
3
3
  import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry.js';
4
4
  import helvetikerFont from 'three/examples/fonts/helvetiker_regular.typeface.json';
5
5
  import { MeshLineGeometry, MeshLineMaterial } from 'meshline';
6
+ import StreamLoaderParserWorker from '../../packages/utils/StreamLoaderParser.worker.js';
6
7
 
7
8
  const GEOM_TYPES = {
8
9
  geom_3d: 53248,
@@ -38,13 +39,142 @@ const TextAlign = {
38
39
  TextFit: 14,
39
40
  };
40
41
 
42
+ // 图元加载模式
43
+ const PRIMITIVE_TYPE = {
44
+ full: 2, // 全量加载
45
+ onlyBounding: 1, // 仅加载边界框
46
+ };
47
+
41
48
  let drawObjMapInstance = {};
49
+ // 使用Set来跟踪已处理的drawObject,避免重复创建group
50
+ // let processedDrawObjects = new Set();
51
+ let instanceToInstancedMeshMap = new Map();
52
+ let instancedMappingWorker = null;
53
+ let instancedMappingWorkerRequestId = 0;
54
+ const instancedMappingWorkerRequests = new Map();
55
+
56
+ function ensureInstancedMappingWorker() {
57
+ if (instancedMappingWorker) return instancedMappingWorker;
58
+ try {
59
+ instancedMappingWorker = new StreamLoaderParserWorker();
60
+ } catch (e) {
61
+ instancedMappingWorker = null;
62
+ return null;
63
+ }
64
+ instancedMappingWorker.addEventListener('message', e => {
65
+ const payload = e.data || {};
66
+ const pending = instancedMappingWorkerRequests.get(payload.id);
67
+ if (!pending) return;
68
+ instancedMappingWorkerRequests.delete(payload.id);
69
+ if (payload.type === 'success') {
70
+ pending.resolve(payload.result);
71
+ } else {
72
+ pending.reject(new Error(payload.error));
73
+ }
74
+ });
75
+ return instancedMappingWorker;
76
+ }
77
+
78
+ function requestInstancedMapping(instances, drawObjs) {
79
+ const worker = ensureInstancedMappingWorker();
80
+ if (!worker) {
81
+ return Promise.reject(new Error('Worker is not initialized'));
82
+ }
83
+ return new Promise((resolve, reject) => {
84
+ const id = instancedMappingWorkerRequestId++;
85
+ instancedMappingWorkerRequests.set(id, { resolve, reject });
86
+ worker.postMessage({
87
+ id,
88
+ type: 'buildInstancedMapping',
89
+ data: { instances, drawObjs },
90
+ });
91
+ });
92
+ }
93
+
42
94
  /**
43
- * 处理 InstancedMesh 类型模型的核心方法
44
- * @param {Object} instance - 实例对象,包含绘制对象ID和实例ID等数据
95
+ * 重置处理状态,用于新的批量加载会话
96
+ */
97
+ function resetProcessingState() {
98
+ drawObjMapInstance = {};
99
+ // instanceToInstancedMeshMap.clear();
100
+ // processedDrawObjects.clear();
101
+ }
102
+
103
+ /**
104
+ * 获取已构建的绘制对象实例映射(用于根据 instanceId 查找其几何数据)
105
+ * @param {string} drawObjectId
106
+ * @returns {Object|undefined} 返回包含 MapMesh/MapInstance/lodLevel 的对象
107
+ */
108
+ function getDrawObjectInstance(drawObjectId) {
109
+ return drawObjMapInstance[drawObjectId];
110
+ }
111
+
112
+ function mergeInstancedMappingResult(result) {
113
+ if (!result) return;
114
+ const { drawObjMapInstance: incomingMap, instanceToDrawObject } = result;
115
+
116
+ if (incomingMap) {
117
+ const keys = Object.keys(incomingMap);
118
+ for (let i = 0; i < keys.length; i++) {
119
+ const drawObjectId = keys[i];
120
+ const incoming = incomingMap[drawObjectId];
121
+ if (!incoming) continue;
122
+ const existing = drawObjMapInstance[drawObjectId];
123
+ if (!existing) {
124
+ drawObjMapInstance[drawObjectId] = {
125
+ MapInstance: Array.isArray(incoming.MapInstance) ? [...incoming.MapInstance] : [],
126
+ MapMesh: incoming.MapMesh,
127
+ };
128
+ } else {
129
+ if (!Array.isArray(existing.MapInstance)) existing.MapInstance = [];
130
+ const existingIds = new Set();
131
+ for (let j = 0; j < existing.MapInstance.length; j++) {
132
+ const item = existing.MapInstance[j];
133
+ if (item && item.instanceId != null) existingIds.add(item.instanceId);
134
+ }
135
+ const incomingInstances = Array.isArray(incoming.MapInstance) ? incoming.MapInstance : [];
136
+ for (let j = 0; j < incomingInstances.length; j++) {
137
+ const item = incomingInstances[j];
138
+ if (item && !existingIds.has(item.instanceId)) {
139
+ existing.MapInstance.push(item);
140
+ existingIds.add(item.instanceId);
141
+ }
142
+ }
143
+ if (!existing.MapMesh && incoming.MapMesh) {
144
+ existing.MapMesh = incoming.MapMesh;
145
+ }
146
+ }
147
+ }
148
+ }
149
+
150
+ if (Array.isArray(instanceToDrawObject)) {
151
+ for (let i = 0; i < instanceToDrawObject.length; i++) {
152
+ const item = instanceToDrawObject[i];
153
+ if (!item || item.instanceId == null) continue;
154
+ if (!instanceToInstancedMeshMap.get(item.instanceId)) {
155
+ instanceToInstancedMeshMap.set(item.instanceId, {
156
+ instanceId: item.instanceId,
157
+ drawObjectId: item.drawObjectId,
158
+ });
159
+ }
160
+ }
161
+ }
162
+ }
163
+
164
+ /**
165
+ * 处理 InstancedMesh 类型模型的核心方法(优化版本,支持批量处理)
166
+ * @param {Object} modelGroup - 模型组对象
167
+ * @param {Array} instances - 实例数组
45
168
  * @param {Array} drawObjs - 绘制对象数组,包含几何数据
169
+ * @param {string} type - 类型
170
+ * @param {Object} scene - 场景对象
171
+ * @param {string} customColor - 自定义颜色
172
+ * @param {Object} meshNameConfig - 网格名称配置
173
+ * @param {string} customOpacity - 自定义透明度
174
+ * @param {Object} options - 选项配置
175
+ * @returns {Object} 模型组对象
46
176
  */
47
- function handleInstancedMeshModel(
177
+ async function handleInstancedMeshModel(
48
178
  modelGroup,
49
179
  instances,
50
180
  drawObjs,
@@ -52,125 +182,398 @@ function handleInstancedMeshModel(
52
182
  scene,
53
183
  customColor,
54
184
  meshNameConfig,
55
- customOpacity
56
- ) {
57
- drawObjMapInstance = {};
58
- // 第一阶段:构建实例映射表
59
- // let modelGroup = new THREE.Group();
60
- for (let i = 0; i < instances.length; i++) {
61
- formatInstancedMap(instances[i], drawObjs);
185
+ customOpacity,
186
+ options = {}
187
+ )
188
+ {
189
+ // const getObjectByName = (name, passType = 'group') => {
190
+ // if (!scene) return [];
191
+ // const object = [];
192
+ // const instancedMeshProps = instanceToInstancedMeshMap.get(name);
193
+ // scene.traverse(item => {
194
+ // const tempName = instancedMeshProps ? instancedMeshProps.drawObjectId : name;
195
+ // if (item.name == tempName && item.type.toLowerCase() != passType.toLowerCase()) {
196
+ // object.push(item);
197
+ // }
198
+ // });
199
+ // return object;
200
+ // };
201
+
202
+ // 如果是新的加载会话,重置状态
203
+ if (options.resetState) {
204
+ resetProcessingState();
62
205
  }
63
- // 第二阶段:遍历所有实例进行处理
64
- for (let i = 0; i < instances.length; i++) {
65
- let targetGroup, instancedMeshIndex, drawObjectName;
66
- const drawObjInstance = drawObjMapInstance[instances[i].drawObject];
67
- if (drawObjInstance.MapMesh?.length > 0) {
68
- // 确保始终使用当前实例的 drawObject 设置分组名
69
- drawObjectName = instances[i].drawObject;
70
- drawObjInstance.MapInstance.forEach((instance, index) => {
71
- if (instance.instanceId == instances[i].instanceId) {
72
- instancedMeshIndex = index;
73
- }
206
+
207
+ let mappingResult = null;
208
+ if (Array.isArray(instances) && instances.length) {
209
+ try {
210
+ mappingResult = await requestInstancedMapping(instances, drawObjs || []);
211
+ } catch (e) {
212
+ mappingResult = null;
213
+ }
214
+ }
215
+
216
+ if (mappingResult) {
217
+ mergeInstancedMappingResult(mappingResult);
218
+ } else {
219
+ const batchSize = options.batchSize || 50;
220
+ for (let i = 0; i < instances.length; i += batchSize) {
221
+ const batch = instances.slice(i, i + batchSize);
222
+ batch.forEach(instance => {
223
+ formatInstancedMap(instance, drawObjs);
74
224
  });
75
- // 在 modelGroup 中查找,避免因尚未加入 scene 而重复创建
76
- if (drawObjectName) {
77
- targetGroup = modelGroup.getObjectByName(drawObjectName);
225
+ }
226
+
227
+ for (let i = 0; i < instances.length; i++) {
228
+ const instance = instances[i];
229
+ const drawObjectId = instance.drawObject;
230
+
231
+ if (!instanceToInstancedMeshMap.get(instance.instanceId)) {
232
+ instanceToInstancedMeshMap.set(instance.instanceId, {
233
+ instanceId: instance.instanceId,
234
+ drawObjectId,
235
+ });
78
236
  }
79
- if (!targetGroup) {
80
- const drawObj = drawObjMapInstance[instances[i].drawObject];
81
- const group = new THREE.Group();
82
- // let grouphName = ''
83
- for (const key in meshNameConfig) {
84
- group.userData[key] = meshNameConfig[key];
85
- // grouphName += ':' + meshNameConfig[key]
86
- }
87
- // grouphName !== '' ? instances[i].drawObject + grouphName: instances[i].drawObject;
88
- group.name = instances[i].drawObject;
89
- group.userData.isInstancedMeshGroup = true;
90
- group.userData.category = instances[i].category;
91
- group.userData.instanceId = instances[i].drawObject;
92
- const instanceCount = drawObj.MapInstance.length;
93
- drawObj.MapMesh?.forEach(mesh => {
94
- const model = drawModel(
95
- mesh,
96
- instances[i].drawObject,
97
- instanceCount,
98
- customColor,
99
- customOpacity
100
- );
101
- if (!model) {
102
- return;
237
+ }
238
+ }
239
+
240
+ // 第二阶段:遍历所有实例进行处理(增量渲染优化)
241
+ // const processedInThisBatch = new Set();
242
+
243
+ // 预先建立映射表,避免在循环中频繁调用 getObjectByName
244
+ const existingGroupsMap = new Map();
245
+ if (modelGroup && modelGroup.children) {
246
+ modelGroup.children.forEach(child => {
247
+ if (child.name) {
248
+ existingGroupsMap.set(child.name, child);
249
+ }
250
+ });
251
+ }
252
+
253
+ const immediateUpdate = options.immediateUpdate || false;
254
+
255
+ for (let i = 0; i < instances.length; i++) {
256
+ const instance = instances[i];
257
+ const drawObjectId = instance.drawObject;
258
+ const instanceId = instance.instanceId;
259
+
260
+ // 检查该drawObject是否已经在本批次或之前处理过
261
+ // if (processedDrawObjects.has(drawObjectId) || processedInThisBatch.has(drawObjectId)) {
262
+ // continue; // 跳过已处理的drawObject
263
+ // }
264
+
265
+ const drawObjInstance = drawObjMapInstance[drawObjectId];
266
+
267
+ if (drawObjInstance?.MapMesh?.length > 0) {
268
+ // 检查modelGroup中是否已存在同名的group
269
+ // const existingGroup = getObjectByName(drawObjectId)[0];
270
+ const existingGroup = existingGroupsMap.get(drawObjectId);
271
+
272
+ if (!existingGroup) {
273
+ const group = createInstancedGroup(
274
+ drawObjInstance,
275
+ instance,
276
+ meshNameConfig,
277
+ customColor,
278
+ customOpacity,
279
+ options
280
+ );
281
+
282
+ if (group) {
283
+ // console.log('add(group)')
284
+ modelGroup.add(group);
285
+ if(immediateUpdate){
286
+ // 立即更新矩阵世界,确保位置正确
287
+ group.updateMatrixWorld(true);
103
288
  }
104
- let meshName = '';
105
- for (const key in meshNameConfig) {
106
- model.userData[key] = meshNameConfig[key];
107
- meshName += ':' + meshNameConfig[key];
289
+
290
+ // 更新映射表,以便后续循环能找到新添加的组
291
+ if (group.name) {
292
+ existingGroupsMap.set(group.name, group);
108
293
  }
109
294
 
110
- // 初始化实例映射表
111
- model.userData.instanceMaps = {}
112
- // 一次性为该 drawObject 的所有实例设置矩阵与颜色
113
- drawObj.MapInstance.forEach((item, index) => {
114
- model.userData.instanceIndex = index;
115
- model.userData.instanceId = item.instanceId;
116
- model.userData.primId = mesh.prmid;
117
- model.name = meshName !== '' ? item.instanceId + meshName : item.instanceId;
118
-
119
- model.userData.instanceMaps[item.instanceId] = {};
120
- model.userData.instanceMaps[item.instanceId]['instanceIndex'] = index;
121
- model.userData.instanceMaps[item.instanceId]['primId'] = mesh.prmid;
122
- model.userData.instanceMaps[item.instanceId]['name'] = model.name;
123
-
124
- const matrixVal = item.matrix?.val;
125
- if (matrixVal) {
126
- const m4 = new THREE.Matrix4();
127
- const meshMatrix = new THREE.Matrix4();
128
- const geomMatrix = new THREE.Matrix4();
129
- // m4.setPosition(new THREE.Vector3(9999999, 9999999, 9999999)); // TODO 临时隐藏方案
130
- meshMatrix.elements = item.matrix.val;
131
- geomMatrix.elements = mesh.matrix.val;
132
-
133
- // 处理文本居中对齐
134
- if (isTextType(mesh.type)) {
135
- const { points, alignType } = mesh;
136
- const positionMatrix = new THREE.Matrix4();
137
-
138
- const alignMatrix = createAlignedText(alignType, model.geometry);
139
-
140
- positionMatrix.identity().makeTranslation(points[0], points[1], points[2]);
141
- geomMatrix.multiply(alignMatrix).multiply(positionMatrix);
142
- }
143
-
144
- m4.multiplyMatrices(meshMatrix, geomMatrix);
145
-
146
- model.setMatrixAt(index, m4);
147
- const copyMatrix = new THREE.Matrix4().copy(m4);
148
- model.userData.copyMatrix = copyMatrix;
149
-
150
- model.userData.instanceMaps[item.instanceId]['copyMatrix'] = copyMatrix;
151
- }
152
- // 需要先设置全部实例颜色,否则后续设置颜色无效
153
- const { color } = mesh.prop;
154
- const meshColor = customColor
155
- ? new THREE.Color(customColor)
156
- : new THREE.Color(`rgb(${color[0]}, ${color[1]}, ${color[2]})`);
157
- model.setColorAt(index, meshColor);
158
- });
159
- // 标记实例属性更新
160
- if (model.instanceMatrix) model.instanceMatrix.needsUpdate = true;
161
- if (model.instanceColor) model.instanceColor.needsUpdate = true;
162
- // model.instanceColor.needsUpdate = true;
163
- group.add(model);
164
- });
165
- modelGroup.add(group);
295
+ // 标记该drawObject已处理
296
+ // processedDrawObjects.add(drawObjectId);
297
+ // processedInThisBatch.add(drawObjectId);
298
+ }
299
+ } else {
300
+ appendInstanceToInstancedGroup(existingGroup, drawObjInstance, instance, customColor);
166
301
  }
167
302
  }
168
303
  }
169
- console.log('modelGroup', modelGroup);
170
- console.log('drawObjMapInstance', drawObjMapInstance);
171
- return modelGroup;
172
- // timeRender();
173
- // console.log('scene', scene)
304
+
305
+ // console.log(instanceToInstancedMeshMap)
306
+ // return modelGroup;
307
+ }
308
+
309
+ /**
310
+ * 创建实例化组(从handleInstancedMeshModel中提取的逻辑)
311
+ * @param {Object} drawObj - 绘制对象数据
312
+ * @param {Object} instance - 实例数据
313
+ * @param {Object} meshNameConfig - 网格名称配置
314
+ * @param {string} customColor - 自定义颜色
315
+ * @param {string} customOpacity - 自定义透明度
316
+ * @param {Object} options - 选项配置
317
+ * @returns {THREE.Group} 创建的组对象
318
+ */
319
+ function createInstancedGroup(
320
+ drawObj,
321
+ instance,
322
+ meshNameConfig,
323
+ customColor,
324
+ customOpacity,
325
+ options
326
+ ) {
327
+ const group = new THREE.Group();
328
+
329
+ // 设置组的基本属性
330
+ for (const key in meshNameConfig) {
331
+ group.userData[key] = meshNameConfig[key];
332
+ }
333
+
334
+ // 可配置的用户数据
335
+ for (const key in options.userData) {
336
+ group.userData[key] = options.userData[key];
337
+ }
338
+
339
+ // group.name = options.defineGroupPreName ? `${options.defineGroupPreName}:${instance.drawObject}` : instance.drawObject;
340
+ group.name = instance.drawObject;
341
+ group.userData.isInstancedMeshGroup = true;
342
+ group.userData.category = instance.category;
343
+ group.userData.instanceId = instance.drawObject;
344
+
345
+ // const instanceCount = drawObj.MapInstance.length;
346
+ const instanceCount = 100; // 预分配容量,动态增加实例
347
+ const activeInstanceCount = Array.isArray(drawObj.MapInstance) ? drawObj.MapInstance.length : 0;
348
+
349
+ // 处理每个网格
350
+ drawObj.MapMesh?.forEach(mesh => {
351
+ // console.log(mesh)
352
+ // console.log(instance)
353
+ // if(mesh.prop.color[0] == 0 && mesh.prop.color[1] == 142 && mesh.prop.color[2] == 142){
354
+ // return
355
+ // }
356
+ // customColor 是原本初始化整个模型颜色的 这里暂时放弃
357
+ // (mesh, instance.drawObject, instanceCount, customColor, customOpacity
358
+ let color = options.colorConfig.get(instance.instanceId)
359
+
360
+ const model = drawModel(mesh, instance.drawObject, instanceCount, color, customOpacity, {
361
+ // lodLevel: drawObj.lodLevel || 2,
362
+ activeInstanceCount,
363
+ ...options
364
+ });
365
+
366
+ if (!model) {
367
+ return;
368
+ }
369
+
370
+ // 设置网格名称
371
+ let meshName = '';
372
+ for (const key in meshNameConfig) {
373
+ model.userData[key] = meshNameConfig[key];
374
+ // meshName += ':' + meshNameConfig[key];
375
+ }
376
+
377
+ // 批量设置实例矩阵和颜色(性能优化)
378
+ // setInstanceMatricesAndColors(model, drawObj, mesh, meshName, customColor, options);
379
+ setInstanceMatricesAndColors(model, drawObj, mesh, meshName, color, options);
380
+
381
+ group.add(model);
382
+ });
383
+
384
+ return group;
385
+ }
386
+
387
+ /**
388
+ * 批量设置实例矩阵和颜色(性能优化版本)
389
+ * @param {THREE.InstancedMesh} model - 实例化网格模型
390
+ * @param {Object} drawObj - 绘制对象数据
391
+ * @param {Object} mesh - 网格数据
392
+ * @param {string} meshName - 网格名称
393
+ * @param {string} customColor - 自定义颜色
394
+ */
395
+ function setInstanceMatricesAndColors(model, drawObj, mesh, meshName, customColor, options) {
396
+ const instances = drawObj.MapInstance;
397
+ const { color } = mesh.prop;
398
+
399
+ // 预计算颜色
400
+ const meshColor = customColor
401
+ ? new THREE.Color(customColor)
402
+ : new THREE.Color(`rgb(${color[0]}, ${color[1]}, ${color[2]})`);
403
+
404
+ // 批量处理实例
405
+ instances.forEach((item, index) => {
406
+ // 设置用户数据
407
+ model.userData.instanceIndex = index;
408
+ model.userData.instanceId = item.instanceId;
409
+ model.userData.primId = mesh.prmid;
410
+ // model.userData.lodLevel = drawObj.lodLevel || 2;
411
+ if (index == 0) {
412
+ model.name = meshName !== '' ? item.instanceId + meshName : item.instanceId;
413
+ }
414
+
415
+ let instanceProps = {
416
+ instanceIndex: index, // 序号来定位到底是哪个instancedMesh
417
+ instancedMeshId: model.name, // 多个instancedMesh共用一个name,用于查找模型
418
+ instanceId: item.instanceId, // instancedMesh实际的modelId
419
+ primId: mesh.prmid,
420
+ // lodLevel: drawObj.lodLevel || 2,
421
+ };
422
+ if (!model.userData.instancesMap) {
423
+ model.userData.instancesMap = new Map([[item.instanceId, instanceProps]]);
424
+ } else {
425
+ model.userData.instancesMap.set(item.instanceId, instanceProps);
426
+ }
427
+
428
+ // const instancedMesh = instanceToInstancedMeshMap.get(item.instanceId);
429
+
430
+ // 处理矩阵变换
431
+ const matrixVal = item.matrix?.val;
432
+ if (matrixVal) {
433
+ const m4 = new THREE.Matrix4();
434
+ const meshMatrix = new THREE.Matrix4();
435
+ const geomMatrix = new THREE.Matrix4();
436
+
437
+ meshMatrix.fromArray(matrixVal);
438
+ geomMatrix.fromArray(new THREE.Matrix4().identity().elements);
439
+
440
+ // 处理文本居中对齐
441
+ const { points, alignType } = mesh;
442
+ if (isTextType(mesh.type)) {
443
+ const positionMatrix = new THREE.Matrix4();
444
+ const alignMatrix = createAlignedText(alignType, model.geometry);
445
+ positionMatrix.identity().makeTranslation(points[0], points[1], points[2]);
446
+ geomMatrix.multiply(alignMatrix).multiply(positionMatrix);
447
+ }
448
+
449
+ m4.multiplyMatrices(meshMatrix, geomMatrix);
450
+ model.setMatrixAt(index, m4);
451
+
452
+ const copyMatrix = new THREE.Matrix4().copy(m4);
453
+ model.userData.copyMatrix = copyMatrix;
454
+
455
+ const temp = model.userData.instancesMap.get(item.instanceId);
456
+ temp.copyMatrix = copyMatrix;
457
+ }
458
+
459
+ // 设置颜色
460
+ model.setColorAt(index, meshColor);
461
+ });
462
+
463
+ // 标记需要更新
464
+ if (model.instanceMatrix) {
465
+ model.instanceMatrix.needsUpdate = true;
466
+ }
467
+ if (model.instanceColor) {
468
+ model.instanceColor.needsUpdate = true;
469
+ }
470
+
471
+ if (Array.isArray(instances)) {
472
+ const capacity =
473
+ model.instanceMatrix && typeof model.instanceMatrix.count === 'number'
474
+ ? model.instanceMatrix.count
475
+ : model.count;
476
+ model.count = Math.min(instances.length, capacity);
477
+ model.userData.instanceCapacity = capacity;
478
+ model.userData.instanceCount = model.count;
479
+ }
480
+ }
481
+
482
+ function appendInstanceToInstancedGroup(group, drawObj, instance, customColor) {
483
+ if (!group || !drawObj || !instance) return;
484
+ const meshes = Array.isArray(drawObj.MapMesh) ? drawObj.MapMesh : [];
485
+ if (meshes.length === 0) return;
486
+ const meshByPrimId = new Map();
487
+ for (let i = 0; i < meshes.length; i++) {
488
+ const m = meshes[i];
489
+ if (m && m.prmid !== undefined) meshByPrimId.set(m.prmid, m);
490
+ }
491
+
492
+ const children = Array.isArray(group.children) ? group.children : [];
493
+ for (let i = 0; i < children.length; i++) {
494
+ const obj = children[i];
495
+ if (!obj || !obj.isInstancedMesh) continue;
496
+ const primId = obj.userData ? obj.userData.primId : undefined;
497
+ const mesh = meshByPrimId.get(primId);
498
+ if (!mesh) continue;
499
+ appendInstanceToInstancedMesh(obj, drawObj, mesh, instance, customColor);
500
+ }
501
+ }
502
+
503
+ function appendInstanceToInstancedMesh(model, drawObj, mesh, instance, customColor) {
504
+ if (!model || !model.isInstancedMesh) return;
505
+ if (!instance || !instance.instanceId) return;
506
+
507
+ const capacity =
508
+ model.instanceMatrix && typeof model.instanceMatrix.count === 'number'
509
+ ? model.instanceMatrix.count
510
+ : model.count;
511
+ const currentCount = typeof model.count === 'number' ? model.count : 0;
512
+ if (currentCount >= capacity) return;
513
+
514
+ if (!model.userData) model.userData = {};
515
+ if (!model.userData.instancesMap) model.userData.instancesMap = new Map();
516
+ if (model.userData.instancesMap.has(instance.instanceId)) return;
517
+
518
+ const rawColor = mesh && mesh.prop ? mesh.prop.color : undefined;
519
+ const colorArr = Array.isArray(rawColor)
520
+ ? rawColor
521
+ : typeof rawColor === 'string'
522
+ ? rawColor.split(',')
523
+ : [255, 255, 255];
524
+ const meshColor = customColor
525
+ ? new THREE.Color(customColor)
526
+ : new THREE.Color(`rgb(${colorArr[0]}, ${colorArr[1]}, ${colorArr[2]})`);
527
+
528
+ const matrixVal = instance.matrix?.val;
529
+ if (!matrixVal || !mesh || !mesh.matrix || !mesh.matrix.val) return;
530
+
531
+ const m4 = new THREE.Matrix4();
532
+ const meshMatrix = new THREE.Matrix4();
533
+ const geomMatrix = new THREE.Matrix4();
534
+
535
+ meshMatrix.fromArray(instance.matrix.val);
536
+ geomMatrix.fromArray(new THREE.Matrix4().identity().elements);
537
+
538
+ const { points, alignType } = mesh;
539
+ if (isTextType(mesh.type)) {
540
+ const positionMatrix = new THREE.Matrix4();
541
+ const alignMatrix = createAlignedText(alignType, model.geometry);
542
+ positionMatrix.identity().makeTranslation(points[0], points[1], points[2]);
543
+ geomMatrix.multiply(alignMatrix).multiply(positionMatrix);
544
+ }
545
+
546
+ m4.multiplyMatrices(meshMatrix, geomMatrix);
547
+ model.setMatrixAt(currentCount, m4);
548
+ if (model.instanceMatrix) model.instanceMatrix.needsUpdate = true;
549
+
550
+ const copyMatrix = new THREE.Matrix4().copy(m4);
551
+ model.userData.copyMatrix = copyMatrix;
552
+ const instanceProps = {
553
+ instanceIndex: currentCount,
554
+ instancedMeshId: model.name,
555
+ instanceId: instance.instanceId,
556
+ primId: mesh.prmid,
557
+ // lodLevel: drawObj.lodLevel || 2,
558
+ copyMatrix,
559
+ };
560
+ model.userData.instancesMap.set(instance.instanceId, instanceProps);
561
+
562
+ model.setColorAt(currentCount, meshColor);
563
+ if (model.instanceColor) model.instanceColor.needsUpdate = true;
564
+
565
+ const opacityAttr =
566
+ model.geometry && model.geometry.getAttribute
567
+ ? model.geometry.getAttribute('opacity')
568
+ : undefined;
569
+ if (opacityAttr && opacityAttr.array && currentCount < opacityAttr.array.length) {
570
+ opacityAttr.array[currentCount] = opacityAttr.array[0] !== undefined ? opacityAttr.array[0] : 1;
571
+ opacityAttr.needsUpdate = true;
572
+ }
573
+
574
+ model.count = currentCount + 1;
575
+ model.userData.instanceCapacity = capacity;
576
+ model.userData.instanceCount = model.count;
174
577
  }
175
578
 
176
579
  /**
@@ -200,9 +603,17 @@ function formatInstancedMap(instance, drawObjs) {
200
603
 
201
604
  // 关联绘制对象的几何数据
202
605
  drawObjs.forEach(item => {
203
- if (item.drawObjId == drawObject) {
606
+ let hasMesh = false;
607
+ if (item && Array.isArray(item.geoms)) {
608
+ const found = item.geoms.some(g => g.prmid === drawObject);
609
+ if (found) {
610
+ hasMesh = true;
611
+ }
612
+ }
613
+ if (hasMesh) {
204
614
  // 将几何数据映射到对应的绘制对象
205
615
  drawObjMapInstance[drawObject].MapMesh = item.geoms;
616
+ // drawObjMapInstance[drawObject].lodLevel = item.lodLevel || 2;
206
617
  }
207
618
  });
208
619
  }
@@ -227,14 +638,14 @@ function formatDrawObjs(data) {
227
638
  * @param {Number} instanceCount - 实例化渲染的数量(用于InstancedMesh)
228
639
  * @returns {THREE.Object3D} 返回创建的3D模型对象
229
640
  */
230
- function drawModel(geom, instanceName, instanceCount, nColor, nOpacity) {
641
+ function drawModel(geom, instanceName, instanceCount, nColor, nOpacity, options = {}) {
231
642
  let model;
232
643
  // 处理二维几何体(普通2D图形和特殊2D图形)
233
644
  if (geom.type == GEOM_TYPES.geom_2d || geom.type == GEOM_TYPES.geom_2d_others) {
234
- model = draw2Dmodel(geom, instanceName, instanceCount); // TODO 该类型调试中
645
+ model = draw2Dmodel(geom, instanceName, instanceCount, options); // TODO 该类型调试中
235
646
  // 处理二维文本类型
236
647
  } else if (isTextType(geom.type)) {
237
- model = drawText(geom, instanceName, instanceCount);
648
+ model = drawText(geom, instanceName, instanceCount, options);
238
649
  // 处理各种曲线类型(圆形、圆弧、椭圆、椭圆弧)
239
650
  } else if (
240
651
  geom.type == GEOM_TYPES.geom_2d_circle ||
@@ -242,10 +653,10 @@ function drawModel(geom, instanceName, instanceCount, nColor, nOpacity) {
242
653
  geom.type == GEOM_TYPES.geom_2d_ellipse ||
243
654
  geom.type == GEOM_TYPES.geom_2d_ellipseArc
244
655
  ) {
245
- model = drawCurves(geom, instanceName, instanceCount); // TODO 该类型调试中
656
+ model = drawCurves(geom, instanceName, instanceCount, options); // TODO 该类型调试中
246
657
  // 处理三维几何体(普通3D模型和OBJ模型)
247
658
  } else if (geom.type == GEOM_TYPES.geom_3d || geom.type == GEOM_TYPES.geom_3d_obj) {
248
- model = draw3Dmodel(geom, instanceName, instanceCount, nColor, nOpacity);
659
+ model = draw3Dmodel(geom, instanceName, instanceCount, nColor, nOpacity, options);
249
660
  }
250
661
  return model;
251
662
  }
@@ -271,7 +682,7 @@ function isTextType(type) {
271
682
  * @param {String} instanceName- 曲线实例的名称
272
683
  * @return {Object}- 包含曲线模型和曲线信息的对象
273
684
  */
274
- function drawCurves(geom, instanceName, instanceCount) {
685
+ function drawCurves(geom, instanceName, instanceCount, options = {}) {
275
686
  let { points, normals } = geom;
276
687
  let aX = points[0];
277
688
  let aY = points[1];
@@ -311,7 +722,8 @@ function drawCurves(geom, instanceName, instanceCount) {
311
722
  normals,
312
723
  },
313
724
  instanceName,
314
- instanceCount
725
+ instanceCount,
726
+ options
315
727
  );
316
728
  // model.rotation.x = -Math.PI / 2;
317
729
  // model.position.set(aX, aY, aZ);
@@ -329,7 +741,18 @@ function drawCurves(geom, instanceName, instanceCount) {
329
741
  * @param {Number} instanceCount - 需要创建的实例数量
330
742
  * @returns {THREE.InstancedMesh} - 返回创建的三维实例化网格对象
331
743
  */
332
- function draw3Dmodel(geom, instanceName, instanceCount, nColor, nOpacity) {
744
+ function draw3Dmodel(
745
+ geom,
746
+ instanceName,
747
+ instanceCount,
748
+ nColor,
749
+ nOpacity,
750
+ options = {},
751
+ targetMesh = undefined
752
+ ) {
753
+ // const { lodLevel } = options;
754
+
755
+
333
756
  // 解构几何数据中的自定义几何体和材质
334
757
  const {
335
758
  geometry: customGeometry,
@@ -337,87 +760,203 @@ function draw3Dmodel(geom, instanceName, instanceCount, nColor, nOpacity) {
337
760
  triangles,
338
761
  points,
339
762
  normals,
340
- prop,
763
+ prop = {},
764
+ max,
765
+ min,
766
+ type,
341
767
  } = geom;
342
- // 使用自定义几何体或创建新的缓冲几何体
343
- const geometry = customGeometry || new THREE.BufferGeometry();
344
768
 
769
+ // 如果传入了现有 mesh,则进行几何体切换(不重新创建 Mesh)
770
+ // if (targetMesh && targetMesh.isInstancedMesh) {
771
+ // // 计算透明度,若现有材质已设置则沿用
772
+ // let opacityFromMat = (targetMesh.material && targetMesh.material.userData && targetMesh.material.userData.nOpacity) ? targetMesh.material.userData.nOpacity : undefined;
773
+ // let colors = Array.isArray(prop.color) ? prop.color : (typeof prop.color === 'string' ? prop.color.split(',') : [255, 255, 255, 1]);
774
+ // let fallbackOpacity = colors[3] !== undefined ? colors[3] : 1;
775
+ // const opacity = opacityFromMat !== undefined ? opacityFromMat : (nOpacity !== undefined ? nOpacity : fallbackOpacity);
776
+
777
+ // // 根据目标 lodLevel 切换几何体
778
+ // if (lodLevel === PRIMITIVE_TYPE.full) {
779
+ // const bufGeo = new THREE.BufferGeometry();
780
+ // // 设置索引
781
+ // if (triangles && triangles.length) {
782
+ // bufGeo.setIndex(triangles);
783
+ // } else {
784
+ // bufGeo.setIndex(null);
785
+ // }
786
+ // // 设置位置
787
+ // if (points && points.length) {
788
+ // const position = new Float32Array(points);
789
+ // bufGeo.setAttribute('position', new THREE.BufferAttribute(position, 3));
790
+ // }
791
+ // // 设置法线或计算
792
+ // if (normals && normals.length) {
793
+ // const normal = new Float32Array(normals);
794
+ // bufGeo.setAttribute('normal', new THREE.BufferAttribute(normal, 3));
795
+ // } else {
796
+ // bufGeo.computeVertexNormals();
797
+ // }
798
+
799
+ // // 绑定实例透明度属性
800
+ // const opacities = new Float32Array(instanceCount);
801
+ // for (let i = 0; i < instanceCount; i++) opacities[i] = opacity;
802
+ // bufGeo.setAttribute('opacity', new THREE.InstancedBufferAttribute(opacities, 1));
803
+
804
+ // // 包围体
805
+ // bufGeo.computeBoundingBox();
806
+ // bufGeo.computeBoundingSphere();
807
+
808
+ // // 替换旧几何体
809
+ // if (targetMesh.geometry) targetMesh.geometry.dispose();
810
+ // targetMesh.geometry = bufGeo;
811
+ // targetMesh.userData.lodLevel = PRIMITIVE_TYPE.full;
812
+ // return; // 更新完成,无需返回新mesh
813
+ // }
814
+
815
+ // if (lodLevel === PRIMITIVE_TYPE.onlyBounding) {
816
+ // // 使用 min/max 或从现有几何体计算包围盒
817
+ // let bbox;
818
+ // if (Array.isArray(min) && Array.isArray(max) && min.length === 3 && max.length === 3) {
819
+ // bbox = { min: { x: min[0], y: min[1], z: min[2] }, max: { x: max[0], y: max[1], z: max[2] } };
820
+ // } else {
821
+ // // 从现有几何体计算
822
+ // const geo = targetMesh.geometry;
823
+ // geo.computeBoundingBox();
824
+ // const bb = geo.boundingBox;
825
+ // bbox = { min: bb.min, max: bb.max };
826
+ // }
827
+ // const width = Math.max(0.0001, bbox.max.x - bbox.min.x);
828
+ // const height = Math.max(0.0001, bbox.max.y - bbox.min.y);
829
+ // const depth = Math.max(0.0001, bbox.max.z - bbox.min.z);
830
+ // const cx = (bbox.min.x + bbox.max.x) / 2;
831
+ // const cy = (bbox.min.y + bbox.max.y) / 2;
832
+ // const cz = (bbox.min.z + bbox.max.z) / 2;
833
+ // const bboxGeometry = new THREE.BoxGeometry(width, height, depth);
834
+ // bboxGeometry.translate(cx, cy, cz);
835
+
836
+ // // 绑定实例透明度属性(保持现有透明度)
837
+ // const opacities = new Float32Array(instanceCount);
838
+ // for (let i = 0; i < instanceCount; i++) opacities[i] = opacity;
839
+ // bboxGeometry.setAttribute('opacity', new THREE.InstancedBufferAttribute(opacities, 1));
840
+
841
+ // if (targetMesh.geometry) targetMesh.geometry.dispose();
842
+ // targetMesh.geometry = bboxGeometry;
843
+ // targetMesh.userData.lodLevel = PRIMITIVE_TYPE.onlyBounding;
844
+ // return; // 更新完成,无需返回新mesh
845
+ // }
846
+
847
+ // // 其它模式不处理
848
+ // return;
849
+ // }
850
+
851
+ // 未传入现有 mesh:按原逻辑创建新 InstancedMesh
852
+ let geometry = customGeometry || new THREE.BufferGeometry();
853
+ // if (lodLevel == PRIMITIVE_TYPE.onlyBounding) {
854
+ // if (Array.isArray(min) && Array.isArray(max) && min.length === 3 && max.length === 3) {
855
+ // const width = Math.max(0.0001, max[0] - min[0]);
856
+ // const height = Math.max(0.0001, max[1] - min[1]);
857
+ // const depth = Math.max(0.0001, max[2] - min[2]);
858
+ // const cx = (min[0] + max[0]) / 2;
859
+ // const cy = (min[1] + max[1]) / 2;
860
+ // const cz = (min[2] + max[2]) / 2;
861
+ // const bboxGeometry = new THREE.BoxGeometry(width, height, depth);
862
+ // bboxGeometry.translate(cx, cy, cz);
863
+ // geometry = bboxGeometry;
864
+ // }
865
+ // } else {
866
+ // if (triangles && triangles.length) {
867
+ // geometry.setIndex(triangles);
868
+ // }
869
+ // if (points && points.length) {
870
+ // const position = new Float32Array(points);
871
+ // geometry.setAttribute('position', new THREE.BufferAttribute(position, 3));
872
+ // }
873
+ // if (normals && normals.length) {
874
+ // const normal = new Float32Array(normals);
875
+ // geometry.setAttribute('normal', new THREE.BufferAttribute(normal, 3));
876
+ // }
877
+ // }
878
+
879
+ // triangle int16Array 索引时,需要转换为 uint16Array
345
880
  if(!customGeometry){
346
- // 设置三角形索引数据
347
881
  if (triangles && triangles.length) {
348
- geometry.setIndex(triangles);
882
+ geometry.setIndex(triangles instanceof Int16Array ? Array.from(triangles.buffer) : triangles);
349
883
  }
350
-
351
- // 设置顶点位置数据
352
884
  if (points && points.length) {
353
885
  const position = new Float32Array(points);
354
886
  geometry.setAttribute('position', new THREE.BufferAttribute(position, 3));
355
887
  }
356
-
357
- // 设置顶点法线数据
358
888
  if (normals && normals.length) {
359
889
  const normal = new Float32Array(normals);
360
890
  geometry.setAttribute('normal', new THREE.BufferAttribute(normal, 3));
361
891
  }
362
892
  }
363
-
893
+
364
894
  const { color, transparent } = prop;
365
895
  let material, mesh, colors, opacity;
366
- if (Array.isArray(color) && color.length) {
367
- colors = color;
368
- opacity = colors[3] || 1;
369
- } else if (typeof color === 'string') {
370
- colors = color.split(',');
371
- opacity = colors[3] || 1;
372
- } else {
373
- colors = [255, 255, 255];
374
- opacity = 1;
375
- }
896
+ if (Array.isArray(color) && color.length) {
897
+ colors = color;
898
+ opacity = colors[3] || 1;
899
+ } else if (typeof color === 'string') {
900
+ colors = color.split(',');
901
+ opacity = colors[3] || 1;
902
+ } else {
903
+ colors = [255, 255, 255];
904
+ opacity = 1;
905
+ }
376
906
 
377
907
  // 处理transparent透明度
378
- if (transparent) {
379
- opacity = 1 - transparent;
380
- }
908
+ opacity = 1 - transparent;
909
+
910
+ const finalOpacity = nOpacity !== '' ? nOpacity : opacity;
911
+
912
+ // 判断是否全透明
913
+ const isTransparent = finalOpacity < 1.0;
381
914
 
382
- // 使用自定义材质或创建标准材质(默认参数配置)
383
915
  let materialOptions = {
384
916
  userData: {
385
917
  nColor: nColor
386
918
  ? new THREE.Color(nColor)
387
919
  : new THREE.Color(`rgb(${colors[0]}, ${colors[1]}, ${colors[2]})`),
388
- nOpacity: nOpacity ? nOpacity : opacity,
920
+ nOpacity: finalOpacity,
921
+ // 这里记录模型原本的颜色 做颜色配置时 恢复原本的颜色用的
922
+ oColor: new THREE.Color(`rgb(${colors[0]}, ${colors[1]}, ${colors[2]})`)
389
923
  },
924
+ // side: THREE.DoubleSide,
925
+ // transparent: true,
926
+ // forceSinglePass: true,
390
927
  side: THREE.DoubleSide,
391
- transparent: true, // 着色器中需要设置透明度
928
+ transparent: true,
929
+ opacity: finalOpacity,
930
+ depthWrite: true,
931
+ forceSinglePass: true,
392
932
  };
393
933
 
394
934
  customMaterial && Object.assign(customMaterial, materialOptions);
395
-
396
935
  material =
397
936
  customMaterial ||
398
937
  new THREE.MeshStandardMaterial({
399
938
  ...materialOptions,
400
939
  roughness: 0.6,
401
940
  metalness: 0.5,
402
- envMapIntensity: 1, // 调低环境贴图的强度
403
- // wireframe: true
941
+ envMapIntensity: 1,
404
942
  });
405
943
 
406
- // 为每个实例存储透明度(opacity)
407
- const opacities = new Float32Array(instanceCount);
944
+ const activeInstanceCount = Math.max(
945
+ 0,
946
+ Math.min(
947
+ instanceCount,
948
+ typeof options.activeInstanceCount === 'number' ? options.activeInstanceCount : instanceCount
949
+ )
950
+ );
408
951
 
409
- // 填充透明度数据
952
+ const opacities = new Float32Array(instanceCount);
410
953
  for (let i = 0; i < instanceCount; i++) {
411
954
  opacities[i] = opacity;
412
955
  }
413
-
414
- // 创建实例属性并绑定到 InstancedMesh
415
956
  geometry.setAttribute('opacity', new THREE.InstancedBufferAttribute(opacities, 1));
416
957
 
417
- // 自定义着色器逻辑
418
958
  if (!customMaterial) {
419
959
  material.onBeforeCompile = shader => {
420
- // 添加顶点着色器输入
421
960
  shader.vertexShader = `
422
961
  in float opacity; // 实例透明度属性
423
962
  out float vAlpha;
@@ -429,8 +968,6 @@ function draw3Dmodel(geom, instanceName, instanceCount, nColor, nOpacity) {
429
968
  vAlpha = opacity; // 传递透明度到片段着色器
430
969
  `
431
970
  );
432
-
433
- // 修改片段着色器
434
971
  shader.fragmentShader = `
435
972
  in float vAlpha;
436
973
  ${shader.fragmentShader}
@@ -443,6 +980,7 @@ function draw3Dmodel(geom, instanceName, instanceCount, nColor, nOpacity) {
443
980
  );
444
981
  };
445
982
  }
983
+
446
984
  // 针对 MeshLineMaterial 开启实例化支持
447
985
  if (material.type === 'MeshLineMaterial') {
448
986
  material.defines = material.defines || {};
@@ -459,13 +997,14 @@ function draw3Dmodel(geom, instanceName, instanceCount, nColor, nOpacity) {
459
997
  }
460
998
 
461
999
  mesh = new THREE.InstancedMesh(geometry, material, instanceCount);
462
-
1000
+ mesh.count = activeInstanceCount;
463
1001
  const { visible } = prop;
464
- mesh.visible = visible;
1002
+ mesh.visible = visible !== undefined ? visible : true;
465
1003
  mesh.userData.drawObjectId = instanceName;
466
- mesh.userData.is3D = geom.type == GEOM_TYPES.geom_3d || geom.type == GEOM_TYPES.geom_3d_obj;
467
-
468
- // mesh.material = material;
1004
+ mesh.userData.is3D = type == GEOM_TYPES.geom_3d || type == GEOM_TYPES.geom_3d_obj;
1005
+ mesh.userData.transparent = isTransparent;
1006
+ mesh.userData.instanceCapacity = instanceCount;
1007
+ mesh.userData.instanceCount = activeInstanceCount;
469
1008
  return mesh;
470
1009
  }
471
1010
 
@@ -476,7 +1015,7 @@ function draw3Dmodel(geom, instanceName, instanceCount, nColor, nOpacity) {
476
1015
  * @param {String} instanceName - 模型实例的名称
477
1016
  * @returns {Object} - 包含所有 2D 模型的组对象
478
1017
  */
479
- function draw2Dmodel(geom, instanceName, instanceCount) {
1018
+ function draw2Dmodel(geom, instanceName, instanceCount, options = {}) {
480
1019
  const points = geom.points;
481
1020
  const normals = geom.normals;
482
1021
  const geometry = new THREE.BufferGeometry();
@@ -508,7 +1047,8 @@ function draw2Dmodel(geom, instanceName, instanceCount) {
508
1047
  material,
509
1048
  },
510
1049
  instanceName,
511
- instanceCount
1050
+ instanceCount,
1051
+ options
512
1052
  );
513
1053
  // mesh.raycast = raycast;
514
1054
 
@@ -519,7 +1059,7 @@ function draw2Dmodel(geom, instanceName, instanceCount) {
519
1059
  }
520
1060
 
521
1061
  // drawText 方法,用于渲染 2D 或 3D 文字
522
- function drawText(geom, instanceName, instanceCount) {
1062
+ function drawText(geom, instanceName, instanceCount, options = {}) {
523
1063
  const { prop, text, points, normals } = geom;
524
1064
  const { color, linewidth, fontsize, fontname, rotate, italic, widthscale } = prop;
525
1065
 
@@ -546,7 +1086,8 @@ function drawText(geom, instanceName, instanceCount) {
546
1086
  normals,
547
1087
  },
548
1088
  instanceName,
549
- instanceCount
1089
+ instanceCount,
1090
+ options
550
1091
  );
551
1092
 
552
1093
  // 创建平移矩阵并应用
@@ -648,4 +1189,11 @@ function createAlignedText(align = TextAlign.TextLeftBottom, geometry) {
648
1189
  return alignMatrix;
649
1190
  }
650
1191
 
651
- export { handleInstancedMeshModel };
1192
+ export {
1193
+ handleInstancedMeshModel,
1194
+ resetProcessingState,
1195
+ PRIMITIVE_TYPE,
1196
+ draw3Dmodel,
1197
+ getDrawObjectInstance,
1198
+ instanceToInstancedMeshMap,
1199
+ };