fl-web-component 2.0.17 → 2.0.19-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/fl-web-component.common.1.js.map +1 -1
- package/dist/fl-web-component.common.2.js.map +1 -1
- package/dist/fl-web-component.common.js +1439 -872
- package/dist/fl-web-component.common.js.map +1 -1
- package/dist/fl-web-component.css +1 -1
- package/package.json +4 -3
- package/packages/components/com-graphics/index.vue +87 -7
- package/packages/components/com-graphics/mock.json +115 -0
- package/packages/utils/StreamLoader.js +250 -107
- package/packages/utils/StreamLoaderParser.worker.js +184 -76
- package/src/utils/flgltf-parser.js +21 -9
- package/src/utils/instance-parser.js +75 -75
- package/src/utils/threejs/measure-clear-distance.js +346 -0
- package/packages/components/com-graphics/box.json +0 -77
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer';
|
|
3
|
+
import { Message } from 'element-ui';
|
|
4
|
+
|
|
5
|
+
var _this = null;
|
|
6
|
+
var MeasureClearDistance = function (renderer, scene, camera, width, height) {
|
|
7
|
+
this.renderer = renderer;
|
|
8
|
+
this.scene = scene;
|
|
9
|
+
this.camera = camera;
|
|
10
|
+
this.pointArray = []; // 保存当前操作所添加的点
|
|
11
|
+
this.raycaster = new THREE.Raycaster();
|
|
12
|
+
this.points = []; // 保存页面中所添加的点
|
|
13
|
+
this.polyline = []; //保存页面中所添加的直线
|
|
14
|
+
this.labels = []; // 保存页面中所添加的文本
|
|
15
|
+
this.timer = null;
|
|
16
|
+
this.width = width;
|
|
17
|
+
this.height = height;
|
|
18
|
+
this.firstTime = 0;
|
|
19
|
+
this.measureName = 'measureObj'
|
|
20
|
+
this.selectedObjects = []
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
MeasureClearDistance.prototype = {
|
|
24
|
+
start() {
|
|
25
|
+
_this = this;
|
|
26
|
+
this.renderer.domElement.style.cursor = 'crosshair';
|
|
27
|
+
this.renderer.domElement.addEventListener('mouseup', this.click, false);
|
|
28
|
+
this.renderer.domElement.addEventListener('mousedown', this.mousedown, false);
|
|
29
|
+
},
|
|
30
|
+
updateParams(width, height) {
|
|
31
|
+
this.camera.aspect = width / height;
|
|
32
|
+
this.camera.updateProjectionMatrix();
|
|
33
|
+
this.renderer.setSize(width, height, true);
|
|
34
|
+
this.width = width;
|
|
35
|
+
this.height = height;
|
|
36
|
+
},
|
|
37
|
+
getPosition(e) {
|
|
38
|
+
const mouse = new THREE.Vector2();
|
|
39
|
+
const elRect = this.renderer.domElement.getBoundingClientRect();
|
|
40
|
+
const canvasX = e.clientX - elRect.left;
|
|
41
|
+
const canvasY = e.clientY - elRect.top;
|
|
42
|
+
|
|
43
|
+
mouse.x = (canvasX / elRect.width) * 2.0 - 1.0;
|
|
44
|
+
mouse.y = -(canvasY / elRect.height) * 2.0 + 1.0;
|
|
45
|
+
|
|
46
|
+
_this.raycaster.setFromCamera(mouse, this.camera);
|
|
47
|
+
let intersects = _this.raycaster.intersectObjects(_this.scene.children, true);
|
|
48
|
+
if (intersects.length > 0) {
|
|
49
|
+
return intersects[0]
|
|
50
|
+
}
|
|
51
|
+
return null
|
|
52
|
+
},
|
|
53
|
+
createLine(p1, p2, config = { color: 0xff0000 }) {
|
|
54
|
+
const lineMaterial = new THREE.LineBasicMaterial({
|
|
55
|
+
color: config.color,
|
|
56
|
+
linewidth: 15,
|
|
57
|
+
depthTest: false,
|
|
58
|
+
depthWrite: false,
|
|
59
|
+
transparent: true,
|
|
60
|
+
});
|
|
61
|
+
const lineGeometry = new THREE.BufferGeometry().setFromPoints([p1, p2]);
|
|
62
|
+
const line = new THREE.Line(lineGeometry, lineMaterial);
|
|
63
|
+
line.name = this.measureName;
|
|
64
|
+
line.renderOrder = 999;
|
|
65
|
+
line.frustumCulled = false;
|
|
66
|
+
return line;
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
createLabel(name, text, position) {
|
|
70
|
+
const div = document.createElement('div');
|
|
71
|
+
div.className = name;
|
|
72
|
+
div.textContent = text;
|
|
73
|
+
const divLabel = new CSS2DObject(div);
|
|
74
|
+
divLabel.name = this.measureName
|
|
75
|
+
divLabel.position.set(position.x, position.y, position.z);
|
|
76
|
+
return divLabel;
|
|
77
|
+
},
|
|
78
|
+
createTipsLabel(label, position) {
|
|
79
|
+
const div = document.createElement('div');
|
|
80
|
+
div.className = 'tips-label';
|
|
81
|
+
div.textContent = label;
|
|
82
|
+
const tipsLabel = new CSS2DObject(div);
|
|
83
|
+
tipsLabel.name = this.measureName
|
|
84
|
+
tipsLabel.position.set(position.x + 0.1, position.y, position.z + 0.05);
|
|
85
|
+
return tipsLabel;
|
|
86
|
+
},
|
|
87
|
+
mousedown() {
|
|
88
|
+
this.firstTime = new Date().getTime();
|
|
89
|
+
},
|
|
90
|
+
click(e) {
|
|
91
|
+
let lastTime = new Date().getTime();
|
|
92
|
+
if (lastTime - this.firstTime < 300) {
|
|
93
|
+
const measureObj = _this.getPosition(e);
|
|
94
|
+
|
|
95
|
+
if (measureObj) {
|
|
96
|
+
_this.selectedObjects.push(measureObj)
|
|
97
|
+
|
|
98
|
+
if (_this.selectedObjects.length % 2 === 0) {
|
|
99
|
+
_this.calculateClearDistance()
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
Message.warning('请点击模型进行测量');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
calculateClearDistance() {
|
|
107
|
+
const l = this.selectedObjects.length;
|
|
108
|
+
// 每次都取最后两个
|
|
109
|
+
const obj1 = this.selectedObjects[l - 2];
|
|
110
|
+
const obj2 = this.selectedObjects[l - 1];
|
|
111
|
+
const isParallel = this.checkParallelism(obj1.object, obj1.instanceId, obj2.object, obj2.instanceId);
|
|
112
|
+
console.log(isParallel)
|
|
113
|
+
const pts1 = this.getInstanceSurfacePoints(obj1.object, obj1.instanceId, 600);
|
|
114
|
+
const pts2 = this.getInstanceSurfacePoints(obj2.object, obj2.instanceId, 600);
|
|
115
|
+
if (pts1.length === 0 || pts2.length === 0) {
|
|
116
|
+
return
|
|
117
|
+
}
|
|
118
|
+
const closestPair = this.findClosestPair(pts1, pts2);
|
|
119
|
+
const position = new THREE.Vector3((closestPair.point1.x + closestPair.point2.x) / 2, (closestPair.point1.y + closestPair.point2.y) / 2, (closestPair.point1.z + closestPair.point2.z) / 2);
|
|
120
|
+
// 将测量结果显示在页面中
|
|
121
|
+
const circleTag1 = this.createLabel('circle-tag', '', closestPair.point1);
|
|
122
|
+
const circleTag2 = this.createLabel('circle-tag', '', closestPair.point2);
|
|
123
|
+
const line = this.createLine(closestPair.point1, closestPair.point2)
|
|
124
|
+
const label = this.createLabel('measure-label', `${this.numberToString(closestPair.distance)}`, position)
|
|
125
|
+
this.points.push(circleTag1);
|
|
126
|
+
this.points.push(circleTag1);
|
|
127
|
+
this.polyline.push(line);
|
|
128
|
+
this.labels.push(label);
|
|
129
|
+
this.scene.add(circleTag1);
|
|
130
|
+
this.scene.add(circleTag2);
|
|
131
|
+
this.scene.add(line);
|
|
132
|
+
this.scene.add(label);
|
|
133
|
+
},
|
|
134
|
+
getInstanceSurfacePoints(instancedMesh, instanceId, maxPoints = 1000) {
|
|
135
|
+
const geometry = instancedMesh.geometry;
|
|
136
|
+
// let localPoints = this.generateGenericLocalPoints(geometry, maxPoints);
|
|
137
|
+
let localPoints = this.sampleGeometrySurface(geometry, maxPoints);
|
|
138
|
+
const worldMatrix = this.getInstanceWorldMatrix(instancedMesh, instanceId);
|
|
139
|
+
const worldPoints = localPoints.map(p => p.clone().applyMatrix4(worldMatrix));
|
|
140
|
+
return worldPoints.slice(0, maxPoints);
|
|
141
|
+
},
|
|
142
|
+
sampleGeometrySurface(geometry, maxPoints = 600) {
|
|
143
|
+
const positions = geometry.getAttribute('position');
|
|
144
|
+
if (!positions) return [];
|
|
145
|
+
|
|
146
|
+
// 获取三角形(优先使用索引)
|
|
147
|
+
let triangles = [];
|
|
148
|
+
if (geometry.index) {
|
|
149
|
+
const index = geometry.index.array;
|
|
150
|
+
for (let i = 0; i < index.length; i += 3) {
|
|
151
|
+
const a = new THREE.Vector3(positions.getX(index[i]), positions.getY(index[i]), positions.getZ(index[i]));
|
|
152
|
+
const b = new THREE.Vector3(positions.getX(index[i + 1]), positions.getY(index[i + 1]), positions.getZ(index[i + 1]));
|
|
153
|
+
const c = new THREE.Vector3(positions.getX(index[i + 2]), positions.getY(index[i + 2]), positions.getZ(index[i + 2]));
|
|
154
|
+
triangles.push([a, b, c]);
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
// 无索引时,每三个顶点组成一个三角形
|
|
158
|
+
for (let i = 0; i < positions.count; i += 3) {
|
|
159
|
+
const a = new THREE.Vector3(positions.getX(i), positions.getY(i), positions.getZ(i));
|
|
160
|
+
const b = new THREE.Vector3(positions.getX(i + 1), positions.getY(i + 1), positions.getZ(i + 1));
|
|
161
|
+
const c = new THREE.Vector3(positions.getX(i + 2), positions.getY(i + 2), positions.getZ(i + 2));
|
|
162
|
+
triangles.push([a, b, c]);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (triangles.length === 0) return [];
|
|
167
|
+
|
|
168
|
+
// 计算每个三角形的面积
|
|
169
|
+
const areas = triangles.map(([a, b, c]) => {
|
|
170
|
+
const ab = new THREE.Vector3().subVectors(b, a);
|
|
171
|
+
const ac = new THREE.Vector3().subVectors(c, a);
|
|
172
|
+
return new THREE.Vector3().crossVectors(ab, ac).length() * 0.5;
|
|
173
|
+
});
|
|
174
|
+
const totalArea = areas.reduce((sum, a) => sum + a, 0);
|
|
175
|
+
|
|
176
|
+
// 按面积比例分配采样点数
|
|
177
|
+
const points = [];
|
|
178
|
+
for (let i = 0; i < triangles.length; i++) {
|
|
179
|
+
const [a, b, c] = triangles[i];
|
|
180
|
+
const area = areas[i];
|
|
181
|
+
let samplesForFace = Math.round((area / totalArea) * maxPoints);
|
|
182
|
+
if (samplesForFace < 1 && points.length < maxPoints) samplesForFace = 1; // 确保每个面至少一个点
|
|
183
|
+
|
|
184
|
+
for (let j = 0; j < samplesForFace; j++) {
|
|
185
|
+
// 重心坐标随机采样
|
|
186
|
+
const u = Math.random();
|
|
187
|
+
const v = Math.random() * (1 - u);
|
|
188
|
+
const w = 1 - u - v;
|
|
189
|
+
const point = new THREE.Vector3()
|
|
190
|
+
.addScaledVector(a, u)
|
|
191
|
+
.addScaledVector(b, v)
|
|
192
|
+
.addScaledVector(c, w);
|
|
193
|
+
points.push(point);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// 如果点数不够,随机补充
|
|
198
|
+
while (points.length < maxPoints) {
|
|
199
|
+
const triIdx = Math.floor(Math.random() * triangles.length);
|
|
200
|
+
const [a, b, c] = triangles[triIdx];
|
|
201
|
+
const u = Math.random();
|
|
202
|
+
const v = Math.random() * (1 - u);
|
|
203
|
+
const w = 1 - u - v;
|
|
204
|
+
points.push(new THREE.Vector3().addScaledVector(a, u).addScaledVector(b, v).addScaledVector(c, w));
|
|
205
|
+
}
|
|
206
|
+
return points.slice(0, maxPoints);
|
|
207
|
+
},
|
|
208
|
+
generateGenericLocalPoints(geometry, maxPoints = 1000) {
|
|
209
|
+
const pos = geometry.getAttribute('position');
|
|
210
|
+
if (!pos) return [];
|
|
211
|
+
const allVerts = [];
|
|
212
|
+
for (let i = 0; i < pos.count; i++) {
|
|
213
|
+
allVerts.push(new THREE.Vector3(pos.getX(i), pos.getY(i), pos.getZ(i)));
|
|
214
|
+
}
|
|
215
|
+
let sourceVerts = allVerts;
|
|
216
|
+
if (geometry.index) {
|
|
217
|
+
const indexArr = geometry.index.array;
|
|
218
|
+
const seen = new Set();
|
|
219
|
+
sourceVerts = [];
|
|
220
|
+
for (let i = 0; i < indexArr.length; i++) {
|
|
221
|
+
const v = allVerts[indexArr[i]];
|
|
222
|
+
const key = `${v.x.toFixed(4)},${v.y.toFixed(4)},${v.z.toFixed(4)}`;
|
|
223
|
+
if (!seen.has(key)) {
|
|
224
|
+
seen.add(key);
|
|
225
|
+
sourceVerts.push(v.clone());
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
if (sourceVerts.length > maxPoints) {
|
|
230
|
+
const step = Math.ceil(sourceVerts.length / maxPoints);
|
|
231
|
+
const sampled = [];
|
|
232
|
+
for (let i = 0; i < sourceVerts.length; i += step) sampled.push(sourceVerts[i]);
|
|
233
|
+
sourceVerts = sampled;
|
|
234
|
+
}
|
|
235
|
+
return sourceVerts;
|
|
236
|
+
|
|
237
|
+
},
|
|
238
|
+
findClosestPair(points1, points2) {
|
|
239
|
+
let minDist = Infinity;
|
|
240
|
+
const c1 = new THREE.Vector3();
|
|
241
|
+
const c2 = new THREE.Vector3();
|
|
242
|
+
for (const p1 of points1) {
|
|
243
|
+
for (const p2 of points2) {
|
|
244
|
+
const d = p1.distanceTo(p2);
|
|
245
|
+
if (d < minDist) {
|
|
246
|
+
minDist = d;
|
|
247
|
+
c1.copy(p1);
|
|
248
|
+
c2.copy(p2);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return { point1: c1, point2: c2, distance: minDist };
|
|
253
|
+
},
|
|
254
|
+
|
|
255
|
+
// 平行判断 (基于包围盒主轴方向)
|
|
256
|
+
checkParallelism(inst1, id1, inst2, id2) {
|
|
257
|
+
const mat1 = this.getInstanceWorldMatrix(inst1, id1);
|
|
258
|
+
const mat2 = this.getInstanceWorldMatrix(inst2, id2);
|
|
259
|
+
const box1 = new THREE.Box3();
|
|
260
|
+
const box2 = new THREE.Box3();
|
|
261
|
+
|
|
262
|
+
// 确保包围盒存在
|
|
263
|
+
if (!inst1.geometry.boundingBox) inst1.geometry.computeBoundingBox();
|
|
264
|
+
if (!inst2.geometry.boundingBox) inst2.geometry.computeBoundingBox();
|
|
265
|
+
|
|
266
|
+
box1.copy(inst1.geometry.boundingBox).applyMatrix4(mat1);
|
|
267
|
+
box2.copy(inst2.geometry.boundingBox).applyMatrix4(mat2);
|
|
268
|
+
|
|
269
|
+
const size1 = new THREE.Vector3(); box1.getSize(size1);
|
|
270
|
+
const size2 = new THREE.Vector3(); box2.getSize(size2);
|
|
271
|
+
|
|
272
|
+
const getMainDir = (s) => {
|
|
273
|
+
if (s.x >= s.y && s.x >= s.z) return new THREE.Vector3(1, 0, 0);
|
|
274
|
+
if (s.y >= s.x && s.y >= s.z) return new THREE.Vector3(0, 1, 0);
|
|
275
|
+
return new THREE.Vector3(0, 0, 1);
|
|
276
|
+
};
|
|
277
|
+
const d1 = getMainDir(size1);
|
|
278
|
+
const d2 = getMainDir(size2);
|
|
279
|
+
|
|
280
|
+
const rot1 = new THREE.Quaternion().setFromRotationMatrix(new THREE.Matrix4().extractRotation(mat1));
|
|
281
|
+
const rot2 = new THREE.Quaternion().setFromRotationMatrix(new THREE.Matrix4().extractRotation(mat2));
|
|
282
|
+
d1.applyQuaternion(rot1);
|
|
283
|
+
d2.applyQuaternion(rot2);
|
|
284
|
+
|
|
285
|
+
return Math.abs(d1.dot(d2)) > 0.95;
|
|
286
|
+
},
|
|
287
|
+
getInstanceWorldMatrix(instancedMesh, instanceId) {
|
|
288
|
+
const matrix = new THREE.Matrix4();
|
|
289
|
+
const instanceMatrix = new THREE.Matrix4();
|
|
290
|
+
instancedMesh.getMatrixAt(instanceId, instanceMatrix);
|
|
291
|
+
matrix.multiplyMatrices(instancedMesh.matrixWorld, instanceMatrix);
|
|
292
|
+
return matrix;
|
|
293
|
+
},
|
|
294
|
+
close(isClear) {
|
|
295
|
+
this.renderer.domElement.removeEventListener('mousedown', this.mousedown);
|
|
296
|
+
this.renderer.domElement.removeEventListener('mouseup', this.click)
|
|
297
|
+
if (!isClear) {
|
|
298
|
+
this.remove(this.points);
|
|
299
|
+
this.remove(this.polyline);
|
|
300
|
+
this.remove(this.labels);
|
|
301
|
+
this.pointArray.splice(0);
|
|
302
|
+
this.points.splice(0);
|
|
303
|
+
this.polyline.splice(0);
|
|
304
|
+
this.labels.splice(0);
|
|
305
|
+
this.firstTime = 0;
|
|
306
|
+
}
|
|
307
|
+
this.renderer.domElement.style.cursor = 'pointer';
|
|
308
|
+
},
|
|
309
|
+
clear() {
|
|
310
|
+
this.remove(this.points);
|
|
311
|
+
this.remove(this.polyline);
|
|
312
|
+
this.remove(this.labels);
|
|
313
|
+
this.pointArray.splice(0);
|
|
314
|
+
this.points.splice(0);
|
|
315
|
+
this.polyline.splice(0);
|
|
316
|
+
this.labels.splice(0);
|
|
317
|
+
this.firstTime = 0;
|
|
318
|
+
},
|
|
319
|
+
remove(array) {
|
|
320
|
+
for (let index = 0; index < array.length; index++) {
|
|
321
|
+
const element = array[index];
|
|
322
|
+
if (element.geometry) {
|
|
323
|
+
element.geometry.dispose();
|
|
324
|
+
}
|
|
325
|
+
this.scene.remove(element);
|
|
326
|
+
}
|
|
327
|
+
},
|
|
328
|
+
numberToString(num) {
|
|
329
|
+
if (num < 0.0001) {
|
|
330
|
+
return num.toString();
|
|
331
|
+
}
|
|
332
|
+
let fractionDigits = 2;
|
|
333
|
+
if (num < 0.01) {
|
|
334
|
+
fractionDigits = 4;
|
|
335
|
+
} else if (num < 0.1) {
|
|
336
|
+
fractionDigits = 3;
|
|
337
|
+
}
|
|
338
|
+
return num.toFixed(fractionDigits);
|
|
339
|
+
},
|
|
340
|
+
preventContextMenu(event) {
|
|
341
|
+
event.preventDefault();
|
|
342
|
+
},
|
|
343
|
+
};
|
|
344
|
+
export default {
|
|
345
|
+
MeasureClearDistance
|
|
346
|
+
};
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"code": 200,
|
|
3
|
-
"msg": "操作成功",
|
|
4
|
-
"data": [
|
|
5
|
-
{
|
|
6
|
-
"id": 5,
|
|
7
|
-
"min": [268.0, 578.0, 5.0],
|
|
8
|
-
"max": [280.0, 588.0, 5.02],
|
|
9
|
-
"flag": 1,
|
|
10
|
-
"obb": [
|
|
11
|
-
268.0, 588.0, 5.0, 268.0, 578.0, 5.0, 268.0, 588.0, 5.02, 268.0, 588.0, 5.02, 268.0, 578.0,
|
|
12
|
-
5.0, 268.0, 578.0, 5.02, 268.0, 578.0, 5.0, 271.0, 578.0, 5.0, 268.0, 578.0, 5.02, 268.0,
|
|
13
|
-
578.0, 5.02, 271.0, 578.0, 5.0, 271.0, 578.0, 5.02, 271.0, 578.0, 5.0, 271.0, 585.0, 5.0,
|
|
14
|
-
271.0, 578.0, 5.02, 271.0, 578.0, 5.02, 271.0, 585.0, 5.0, 271.0, 585.0, 5.02, 271.0, 585.0,
|
|
15
|
-
5.0, 280.0, 585.0, 5.0, 271.0, 585.0, 5.02, 271.0, 585.0, 5.02, 280.0, 585.0, 5.0, 280.0,
|
|
16
|
-
585.0, 5.02, 271.0, 578.0, 5.0, 268.0, 578.0, 5.0, 271.0, 585.0, 5.0, 271.0, 585.0, 5.0,
|
|
17
|
-
268.0, 578.0, 5.0, 268.0, 588.0, 5.0, 271.0, 585.0, 5.0, 268.0, 588.0, 5.0, 280.0, 588.0,
|
|
18
|
-
5.0, 280.0, 588.0, 5.0, 280.0, 585.0, 5.0, 271.0, 585.0, 5.0, 268.0, 578.0, 5.02, 271.0,
|
|
19
|
-
578.0, 5.02, 268.0, 588.0, 5.02, 268.0, 588.0, 5.02, 271.0, 578.0, 5.02, 271.0, 585.0, 5.02,
|
|
20
|
-
268.0, 588.0, 5.02, 271.0, 585.0, 5.02, 280.0, 585.0, 5.02, 280.0, 585.0, 5.02, 280.0,
|
|
21
|
-
588.0, 5.02, 268.0, 588.0, 5.02, 280.0, 585.0, 5.0, 280.0, 588.0, 5.0, 280.0, 585.0, 5.02,
|
|
22
|
-
280.0, 585.0, 5.02, 280.0, 588.0, 5.0, 280.0, 588.0, 5.02, 280.0, 588.0, 5.0, 268.0, 588.0,
|
|
23
|
-
5.0, 280.0, 588.0, 5.02, 280.0, 588.0, 5.02, 268.0, 588.0, 5.0, 268.0, 588.0, 5.02
|
|
24
|
-
],
|
|
25
|
-
"transp": 1.0
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
"id": 288,
|
|
29
|
-
"min": [2881.839, 3967.814, -0.01065],
|
|
30
|
-
"max": [2882.217, 3967.836, 0.01065],
|
|
31
|
-
"flag": 2,
|
|
32
|
-
"obb": [
|
|
33
|
-
2882.02807617188, 3967.82495117188, -2.55106394476346e-20, 0.188999995589256,
|
|
34
|
-
0.0109999999403954, 0.0106499996036291, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0
|
|
35
|
-
],
|
|
36
|
-
"transp": 1.0
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
"id": 291,
|
|
40
|
-
"min": [2882.104, 3967.956, -0.01065],
|
|
41
|
-
"max": [2882.374, 3968.124, 0.01065],
|
|
42
|
-
"flag": 2,
|
|
43
|
-
"obb": [
|
|
44
|
-
2882.23901367188, 3968.0400390625, -2.55106394476346e-20, 0.188999995589256,
|
|
45
|
-
0.0109999999403954, 0.0106499996036291, 0.500014126300812, 0.86601722240448, 0.0,
|
|
46
|
-
-0.86601722240448, 0.500014126300812, 0.0, 0.0, 0.0, 1.0
|
|
47
|
-
],
|
|
48
|
-
"transp": 1.0
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
"id": 292,
|
|
52
|
-
"min": [2882.217, 3968.04, -0.01065],
|
|
53
|
-
"max": [2882.374, 3968.124, 0.01065],
|
|
54
|
-
"flag": 3,
|
|
55
|
-
"obb": [
|
|
56
|
-
276.758514404297, 586.730529785156, 5.27499485015869,
|
|
57
|
-
276.844261169434, 586.816268920898, 5.47500514984131,
|
|
58
|
-
276.758514404297, 586.816268920898, 5.27499485015869,
|
|
59
|
-
276.844261169434, 586.902008056641, 5.47500514984131,
|
|
60
|
-
276.758514404297, 586.987747192383, 5.27499485015869,
|
|
61
|
-
276.844261169434, 587.073486328125, 5.47500514984131
|
|
62
|
-
]
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
"id": 293,
|
|
66
|
-
"min": [2882.217, 3968.04, -0.01065],
|
|
67
|
-
"max": [2882.374, 3968.124, 0.01065],
|
|
68
|
-
"flag": 3,
|
|
69
|
-
"obb": [
|
|
70
|
-
276.758514404297, 586.730529785156, 5.27499485015869,
|
|
71
|
-
276.844261169434, 586.816268920898, 5.47500514984131,
|
|
72
|
-
276.758514404297, 586.816268920898, 5.27499485015869,
|
|
73
|
-
276.844261169434, 586.902008056641, 5.47500514984131
|
|
74
|
-
]
|
|
75
|
-
}
|
|
76
|
-
]
|
|
77
|
-
}
|