t3d-3dtiles 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +28 -0
- package/README.md +41 -0
- package/build/t3d.3dtiles.js +5418 -0
- package/build/t3d.3dtiles.min.js +2 -0
- package/build/t3d.3dtiles.module.js +6183 -0
- package/examples/jsm/CesiumIon.js +30 -0
- package/examples/jsm/Tiles3DDebugger.js +219 -0
- package/examples/jsm/Tiles3DUtils.js +32 -0
- package/examples/jsm/helpers/LineSegmentHelper.js +74 -0
- package/examples/jsm/helpers/OBBHelper.js +48 -0
- package/examples/jsm/helpers/Tiles3DHelper.js +135 -0
- package/examples/jsm/math/Intersects.js +100 -0
- package/examples/jsm/math/LineSegment.js +234 -0
- package/package.json +57 -0
- package/src/Tiles3D.js +402 -0
- package/src/libs/ImageBitmapLoader.js +56 -0
- package/src/libs/glTF/Constants.js +85 -0
- package/src/libs/glTF/GLTFLoader.js +169 -0
- package/src/libs/glTF/GLTFResource.js +28 -0
- package/src/libs/glTF/GLTFUtils.js +131 -0
- package/src/libs/glTF/extensions/EXT_meshopt_compression.js +35 -0
- package/src/libs/glTF/extensions/KHR_draco_mesh_compression.js +54 -0
- package/src/libs/glTF/extensions/KHR_lights_punctual.js +53 -0
- package/src/libs/glTF/extensions/KHR_materials_clearcoat.js +42 -0
- package/src/libs/glTF/extensions/KHR_materials_pbrSpecularGlossiness.js +53 -0
- package/src/libs/glTF/extensions/KHR_materials_unlit.js +13 -0
- package/src/libs/glTF/extensions/KHR_texture_basisu.js +14 -0
- package/src/libs/glTF/extensions/KHR_texture_transform.js +31 -0
- package/src/libs/glTF/parsers/AccessorParser.js +99 -0
- package/src/libs/glTF/parsers/AnimationParser.js +118 -0
- package/src/libs/glTF/parsers/BufferParser.js +35 -0
- package/src/libs/glTF/parsers/BufferViewParser.js +27 -0
- package/src/libs/glTF/parsers/ImageParser.js +97 -0
- package/src/libs/glTF/parsers/IndexParser.js +22 -0
- package/src/libs/glTF/parsers/MaterialParser.js +146 -0
- package/src/libs/glTF/parsers/NodeParser.js +145 -0
- package/src/libs/glTF/parsers/PrimitiveParser.js +289 -0
- package/src/libs/glTF/parsers/ReferenceParser.js +67 -0
- package/src/libs/glTF/parsers/SceneParser.js +41 -0
- package/src/libs/glTF/parsers/SkinParser.js +53 -0
- package/src/libs/glTF/parsers/TextureParser.js +71 -0
- package/src/libs/glTF/parsers/Validator.js +16 -0
- package/src/loaders/B3DMLoader.js +49 -0
- package/src/loaders/CMPTLoader.js +48 -0
- package/src/loaders/I3DMLoader.js +49 -0
- package/src/loaders/PNTSLoader.js +20 -0
- package/src/loaders/TileGLTFLoader.js +17 -0
- package/src/loaders/parsers/HeaderParser.js +104 -0
- package/src/loaders/parsers/LoadParser.js +22 -0
- package/src/loaders/parsers/TableParser.js +66 -0
- package/src/loaders/parsers/b3dm/B3DMParser.js +18 -0
- package/src/loaders/parsers/b3dm/B3DMRootParser.js +22 -0
- package/src/loaders/parsers/b3dm/MaterialParser.js +156 -0
- package/src/loaders/parsers/cmpt/CMPTParser.js +37 -0
- package/src/loaders/parsers/cmpt/CMPTRootParser.js +44 -0
- package/src/loaders/parsers/gltf/IndexParser.js +24 -0
- package/src/loaders/parsers/i3dm/I3DMParser.js +28 -0
- package/src/loaders/parsers/i3dm/I3DMRootParser.js +123 -0
- package/src/loaders/parsers/i3dm/MaterialParser.js +152 -0
- package/src/loaders/parsers/i3dm/PrimitiveParser.js +291 -0
- package/src/loaders/parsers/pnts/PNTSRootParser.js +69 -0
- package/src/main.js +14 -0
- package/src/materials/InstancedBasicMaterial.js +32 -0
- package/src/materials/InstancedPBRMaterial.js +32 -0
- package/src/materials/InstancedShaderChunks.js +23 -0
- package/src/math/Ellipsoid.js +41 -0
- package/src/math/EllipsoidRegion.js +160 -0
- package/src/math/FastFrustum.js +49 -0
- package/src/math/GeoUtils.js +31 -0
- package/src/math/OBB.js +395 -0
- package/src/math/TileBoundingVolume.js +172 -0
- package/src/math/TileOBB.js +103 -0
- package/src/utils/BatchTable.js +14 -0
- package/src/utils/CameraList.js +131 -0
- package/src/utils/FeatureTable.js +107 -0
- package/src/utils/IntersectionUtils.js +136 -0
- package/src/utils/LRUCache.js +159 -0
- package/src/utils/ModelLoader.js +150 -0
- package/src/utils/PriorityQueue.js +102 -0
- package/src/utils/RequestState.js +17 -0
- package/src/utils/TilesLoader.js +386 -0
- package/src/utils/TilesScheduler.js +375 -0
- package/src/utils/Utils.js +43 -0
package/src/math/OBB.js
ADDED
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
import { Box3, Matrix3, Vector3 } from 't3d';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* An oriented bounding box.
|
|
5
|
+
*/
|
|
6
|
+
export class OBB {
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Create a new OBB.
|
|
10
|
+
* @param {Box3} [box] - The axis-aligned bounding box.
|
|
11
|
+
* @param {Matrix3} [rotation] - The rotation matrix.
|
|
12
|
+
*/
|
|
13
|
+
constructor(box = new Box3(), rotation = new Matrix3()) {
|
|
14
|
+
this.box = box;
|
|
15
|
+
this.rotation = rotation;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Set the OBB from a center point and axes with half sizes.
|
|
20
|
+
* @param {Vector3} center - The center of the OBB.
|
|
21
|
+
* @param {Vector3} axisX - The X axis with half size.
|
|
22
|
+
* @param {Vector3} axisY - The Y axis with half size.
|
|
23
|
+
* @param {Vector3} axisZ - The Z axis with half size.
|
|
24
|
+
* @return {OBB} A reference to this OBB.
|
|
25
|
+
*/
|
|
26
|
+
setFromCenterAndAxes(center, axisX, axisY, axisZ) {
|
|
27
|
+
_vec3_1.copy(axisX);
|
|
28
|
+
_vec3_2.copy(axisY);
|
|
29
|
+
_vec3_3.copy(axisZ);
|
|
30
|
+
|
|
31
|
+
const scaleX = _vec3_1.getLength();
|
|
32
|
+
const scaleY = _vec3_2.getLength();
|
|
33
|
+
const scaleZ = _vec3_3.getLength();
|
|
34
|
+
|
|
35
|
+
_vec3_1.normalize();
|
|
36
|
+
_vec3_2.normalize();
|
|
37
|
+
_vec3_3.normalize();
|
|
38
|
+
|
|
39
|
+
// handle the case where the box has a dimension of 0 in one axis
|
|
40
|
+
if (scaleX === 0) {
|
|
41
|
+
_vec3_1.crossVectors(_vec3_2, _vec3_3);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (scaleY === 0) {
|
|
45
|
+
_vec3_2.crossVectors(_vec3_1, _vec3_3);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (scaleZ === 0) {
|
|
49
|
+
_vec3_3.crossVectors(_vec3_1, _vec3_2);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
this.rotation.set(
|
|
53
|
+
_vec3_1.x, _vec3_2.x, _vec3_3.x,
|
|
54
|
+
_vec3_1.y, _vec3_2.y, _vec3_3.y,
|
|
55
|
+
_vec3_1.z, _vec3_2.z, _vec3_3.z
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const halfSize = _vec3_1.set(scaleX, scaleY, scaleZ);
|
|
59
|
+
this.box.min.copy(center).sub(halfSize);
|
|
60
|
+
this.box.max.copy(center).add(halfSize);
|
|
61
|
+
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Transforms this OBB with the supplied matrix.
|
|
67
|
+
* @param {Matrix4} matrix - The transformation matrix.
|
|
68
|
+
* @return {OBB} A reference to this OBB.
|
|
69
|
+
*/
|
|
70
|
+
applyMatrix4(matrix) {
|
|
71
|
+
const e = matrix.elements;
|
|
72
|
+
|
|
73
|
+
let sx = _vec3_1.set(e[0], e[1], e[2]).getLength();
|
|
74
|
+
const sy = _vec3_1.set(e[4], e[5], e[6]).getLength();
|
|
75
|
+
const sz = _vec3_1.set(e[8], e[9], e[10]).getLength();
|
|
76
|
+
|
|
77
|
+
const det = matrix.determinant();
|
|
78
|
+
if (det < 0) sx = -sx;
|
|
79
|
+
|
|
80
|
+
_mat3_1.setFromMatrix4(matrix);
|
|
81
|
+
|
|
82
|
+
const invSX = 1 / sx;
|
|
83
|
+
const invSY = 1 / sy;
|
|
84
|
+
const invSZ = 1 / sz;
|
|
85
|
+
|
|
86
|
+
_mat3_1.elements[0] *= invSX;
|
|
87
|
+
_mat3_1.elements[1] *= invSX;
|
|
88
|
+
_mat3_1.elements[2] *= invSX;
|
|
89
|
+
|
|
90
|
+
_mat3_1.elements[3] *= invSY;
|
|
91
|
+
_mat3_1.elements[4] *= invSY;
|
|
92
|
+
_mat3_1.elements[5] *= invSY;
|
|
93
|
+
|
|
94
|
+
_mat3_1.elements[6] *= invSZ;
|
|
95
|
+
_mat3_1.elements[7] *= invSZ;
|
|
96
|
+
_mat3_1.elements[8] *= invSZ;
|
|
97
|
+
|
|
98
|
+
this.rotation.multiply(_mat3_1);
|
|
99
|
+
|
|
100
|
+
const center = this.box.getCenter(_vec3_1);
|
|
101
|
+
const halfSize = this.box.getSize(_vec3_2).multiplyScalar(0.5);
|
|
102
|
+
|
|
103
|
+
halfSize.x *= sx;
|
|
104
|
+
halfSize.y *= sy;
|
|
105
|
+
halfSize.z *= sz;
|
|
106
|
+
|
|
107
|
+
// https://github.com/mrdoob/three.js/issues/21753
|
|
108
|
+
center.applyMatrix4(matrix);
|
|
109
|
+
|
|
110
|
+
this.box.min.copy(center).sub(halfSize);
|
|
111
|
+
this.box.max.copy(center).add(halfSize);
|
|
112
|
+
|
|
113
|
+
return this;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Get the 8 corner points of the OBB.
|
|
118
|
+
* @param {Vector3[]} points - The array to store the points.
|
|
119
|
+
* @return {Vector3[]} The array of points.
|
|
120
|
+
*/
|
|
121
|
+
getPoints(points) {
|
|
122
|
+
const center = this.box.getCenter(_vec3_1);
|
|
123
|
+
const min = _vec3_2.subVectors(this.box.min, center);
|
|
124
|
+
const max = _vec3_3.subVectors(this.box.max, center);
|
|
125
|
+
|
|
126
|
+
let index = 0;
|
|
127
|
+
for (let x = -1; x <= 1; x += 2) {
|
|
128
|
+
for (let y = -1; y <= 1; y += 2) {
|
|
129
|
+
for (let z = -1; z <= 1; z += 2) {
|
|
130
|
+
points[index]
|
|
131
|
+
.set(
|
|
132
|
+
x < 0 ? min.x : max.x,
|
|
133
|
+
y < 0 ? min.y : max.y,
|
|
134
|
+
z < 0 ? min.z : max.z
|
|
135
|
+
)
|
|
136
|
+
.applyMatrix3(this.rotation)
|
|
137
|
+
.add(center);
|
|
138
|
+
index++;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return points;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Get the 6 planes of the OBB.
|
|
148
|
+
* @param {Plane[]} planes - The array to store the planes.
|
|
149
|
+
* @return {Plane[]} The array of planes.
|
|
150
|
+
*/
|
|
151
|
+
getPlanes(planes) {
|
|
152
|
+
const center = this.box.getCenter(_vec3_1);
|
|
153
|
+
const worldMin = _vec3_2.subVectors(this.box.min, center).applyMatrix3(this.rotation).add(center);
|
|
154
|
+
const worldMax = _vec3_3.subVectors(this.box.max, center).applyMatrix3(this.rotation).add(center);
|
|
155
|
+
|
|
156
|
+
_vec3_1.set(0, 0, 1).applyMatrix3(this.rotation).normalize();
|
|
157
|
+
planes[0].setFromNormalAndCoplanarPoint(_vec3_1, worldMin);
|
|
158
|
+
planes[1].setFromNormalAndCoplanarPoint(_vec3_1, worldMax);
|
|
159
|
+
planes[1].normal.negate();
|
|
160
|
+
planes[1].constant *= -1;
|
|
161
|
+
|
|
162
|
+
_vec3_1.set(0, 1, 0).applyMatrix3(this.rotation).normalize();
|
|
163
|
+
planes[2].setFromNormalAndCoplanarPoint(_vec3_1, worldMin);
|
|
164
|
+
planes[3].setFromNormalAndCoplanarPoint(_vec3_1, worldMax);
|
|
165
|
+
planes[3].normal.negate();
|
|
166
|
+
planes[3].constant *= -1;
|
|
167
|
+
|
|
168
|
+
_vec3_1.set(1, 0, 0).applyMatrix3(this.rotation).normalize();
|
|
169
|
+
planes[4].setFromNormalAndCoplanarPoint(_vec3_1, worldMin);
|
|
170
|
+
planes[5].setFromNormalAndCoplanarPoint(_vec3_1, worldMax);
|
|
171
|
+
planes[5].normal.negate();
|
|
172
|
+
planes[5].constant *= -1;
|
|
173
|
+
|
|
174
|
+
return planes;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
containsPoint(point) {
|
|
178
|
+
const obbStruct = getOBBStruct(this, a);
|
|
179
|
+
|
|
180
|
+
const v = _vec3_1.subVectors(point, obbStruct.c);
|
|
181
|
+
|
|
182
|
+
// project _vec3_4 onto each axis and check if these points lie inside the OBB
|
|
183
|
+
|
|
184
|
+
return Math.abs(v.dot(obbStruct.u[0])) <= obbStruct.e[0] &&
|
|
185
|
+
Math.abs(v.dot(obbStruct.u[1])) <= obbStruct.e[1] &&
|
|
186
|
+
Math.abs(v.dot(obbStruct.u[2])) <= obbStruct.e[2];
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Reference: Closest Point on OBB to Point in Real-Time Collision Detection
|
|
191
|
+
* by Christer Ericson (chapter 5.1.4)
|
|
192
|
+
*/
|
|
193
|
+
clampPoint(point, result) {
|
|
194
|
+
const obbStruct = getOBBStruct(this, a);
|
|
195
|
+
|
|
196
|
+
const v = _vec3_1.subVectors(point, obbStruct.c);
|
|
197
|
+
|
|
198
|
+
// start at the center position of the OBB
|
|
199
|
+
|
|
200
|
+
result.copy(obbStruct.c);
|
|
201
|
+
|
|
202
|
+
// project the target onto the OBB axes and walk towards that point
|
|
203
|
+
|
|
204
|
+
const x = Math.max(Math.min(v.dot(obbStruct.u[0]), obbStruct.e[0]), -obbStruct.e[0]);
|
|
205
|
+
result.add(obbStruct.u[0].multiplyScalar(x));
|
|
206
|
+
|
|
207
|
+
const y = Math.max(Math.min(v.dot(obbStruct.u[1]), obbStruct.e[1]), -obbStruct.e[1]);
|
|
208
|
+
result.add(obbStruct.u[1].multiplyScalar(y));
|
|
209
|
+
|
|
210
|
+
const z = Math.max(Math.min(v.dot(obbStruct.u[2]), obbStruct.e[2]), -obbStruct.e[2]);
|
|
211
|
+
result.add(obbStruct.u[2].multiplyScalar(z));
|
|
212
|
+
|
|
213
|
+
return result;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
intersectsSphere(sphere) {
|
|
217
|
+
// find the point on the OBB closest to the sphere center
|
|
218
|
+
this.clampPoint(sphere.center, closestPoint);
|
|
219
|
+
// if that point is inside the sphere, the OBB and sphere intersect
|
|
220
|
+
return closestPoint.distanceToSquared(sphere.center) <= (sphere.radius * sphere.radius);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
intersectsOBB(obb, epsilon = Number.EPSILON) {
|
|
224
|
+
// prepare data structures (the code uses the same nomenclature like the reference)
|
|
225
|
+
|
|
226
|
+
getOBBStruct(this, a);
|
|
227
|
+
getOBBStruct(obb, b);
|
|
228
|
+
|
|
229
|
+
// compute rotation matrix expressing b in a's coordinate frame
|
|
230
|
+
|
|
231
|
+
for (let i = 0; i < 3; i++) {
|
|
232
|
+
for (let j = 0; j < 3; j++) {
|
|
233
|
+
R[i][j] = a.u[i].dot(b.u[j]);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// compute translation vector
|
|
238
|
+
|
|
239
|
+
const v1 = _vec3_1.subVectors(b.c, a.c);
|
|
240
|
+
|
|
241
|
+
// bring translation into a's coordinate frame
|
|
242
|
+
|
|
243
|
+
t[0] = v1.dot(a.u[0]);
|
|
244
|
+
t[1] = v1.dot(a.u[1]);
|
|
245
|
+
t[2] = v1.dot(a.u[2]);
|
|
246
|
+
|
|
247
|
+
// compute common subexpressions. Add in an epsilon term to
|
|
248
|
+
// counteract arithmetic errors when two edges are parallel and
|
|
249
|
+
// their cross product is (near) null
|
|
250
|
+
|
|
251
|
+
for (let i = 0; i < 3; i++) {
|
|
252
|
+
for (let j = 0; j < 3; j++) {
|
|
253
|
+
AbsR[i][j] = Math.abs(R[i][j]) + epsilon;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
let ra, rb;
|
|
258
|
+
|
|
259
|
+
// test axes L = A0, L = A1, L = A2
|
|
260
|
+
|
|
261
|
+
for (let i = 0; i < 3; i++) {
|
|
262
|
+
ra = a.e[i];
|
|
263
|
+
rb = b.e[0] * AbsR[i][0] + b.e[1] * AbsR[i][1] + b.e[2] * AbsR[i][2];
|
|
264
|
+
if (Math.abs(t[i]) > ra + rb) return false;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// test axes L = B0, L = B1, L = B2
|
|
268
|
+
|
|
269
|
+
for (let i = 0; i < 3; i++) {
|
|
270
|
+
ra = a.e[0] * AbsR[0][i] + a.e[1] * AbsR[1][i] + a.e[2] * AbsR[2][i];
|
|
271
|
+
rb = b.e[i];
|
|
272
|
+
if (Math.abs(t[0] * R[0][i] + t[1] * R[1][i] + t[2] * R[2][i]) > ra + rb) return false;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// test axis L = A0 x B0
|
|
276
|
+
|
|
277
|
+
ra = a.e[1] * AbsR[2][0] + a.e[2] * AbsR[1][0];
|
|
278
|
+
rb = b.e[1] * AbsR[0][2] + b.e[2] * AbsR[0][1];
|
|
279
|
+
if (Math.abs(t[2] * R[1][0] - t[1] * R[2][0]) > ra + rb) return false;
|
|
280
|
+
|
|
281
|
+
// test axis L = A0 x B1
|
|
282
|
+
|
|
283
|
+
ra = a.e[1] * AbsR[2][1] + a.e[2] * AbsR[1][1];
|
|
284
|
+
rb = b.e[0] * AbsR[0][2] + b.e[2] * AbsR[0][0];
|
|
285
|
+
if (Math.abs(t[2] * R[1][1] - t[1] * R[2][1]) > ra + rb) return false;
|
|
286
|
+
|
|
287
|
+
// test axis L = A0 x B2
|
|
288
|
+
|
|
289
|
+
ra = a.e[1] * AbsR[2][2] + a.e[2] * AbsR[1][2];
|
|
290
|
+
rb = b.e[0] * AbsR[0][1] + b.e[1] * AbsR[0][0];
|
|
291
|
+
if (Math.abs(t[2] * R[1][2] - t[1] * R[2][2]) > ra + rb) return false;
|
|
292
|
+
|
|
293
|
+
// test axis L = A1 x B0
|
|
294
|
+
|
|
295
|
+
ra = a.e[0] * AbsR[2][0] + a.e[2] * AbsR[0][0];
|
|
296
|
+
rb = b.e[1] * AbsR[1][2] + b.e[2] * AbsR[1][1];
|
|
297
|
+
if (Math.abs(t[0] * R[2][0] - t[2] * R[0][0]) > ra + rb) return false;
|
|
298
|
+
|
|
299
|
+
// test axis L = A1 x B1
|
|
300
|
+
|
|
301
|
+
ra = a.e[0] * AbsR[2][1] + a.e[2] * AbsR[0][1];
|
|
302
|
+
rb = b.e[0] * AbsR[1][2] + b.e[2] * AbsR[1][0];
|
|
303
|
+
if (Math.abs(t[0] * R[2][1] - t[2] * R[0][1]) > ra + rb) return false;
|
|
304
|
+
|
|
305
|
+
// test axis L = A1 x B2
|
|
306
|
+
|
|
307
|
+
ra = a.e[0] * AbsR[2][2] + a.e[2] * AbsR[0][2];
|
|
308
|
+
rb = b.e[0] * AbsR[1][1] + b.e[1] * AbsR[1][0];
|
|
309
|
+
if (Math.abs(t[0] * R[2][2] - t[2] * R[0][2]) > ra + rb) return false;
|
|
310
|
+
|
|
311
|
+
// test axis L = A2 x B0
|
|
312
|
+
|
|
313
|
+
ra = a.e[0] * AbsR[1][0] + a.e[1] * AbsR[0][0];
|
|
314
|
+
rb = b.e[1] * AbsR[2][2] + b.e[2] * AbsR[2][1];
|
|
315
|
+
if (Math.abs(t[1] * R[0][0] - t[0] * R[1][0]) > ra + rb) return false;
|
|
316
|
+
|
|
317
|
+
// test axis L = A2 x B1
|
|
318
|
+
|
|
319
|
+
ra = a.e[0] * AbsR[1][1] + a.e[1] * AbsR[0][1];
|
|
320
|
+
rb = b.e[0] * AbsR[2][2] + b.e[2] * AbsR[2][0];
|
|
321
|
+
if (Math.abs(t[1] * R[0][1] - t[0] * R[1][1]) > ra + rb) return false;
|
|
322
|
+
|
|
323
|
+
// test axis L = A2 x B2
|
|
324
|
+
|
|
325
|
+
ra = a.e[0] * AbsR[1][2] + a.e[1] * AbsR[0][2];
|
|
326
|
+
rb = b.e[0] * AbsR[2][1] + b.e[1] * AbsR[2][0];
|
|
327
|
+
if (Math.abs(t[1] * R[0][2] - t[0] * R[1][2]) > ra + rb) return false;
|
|
328
|
+
|
|
329
|
+
// since no separating axis is found, the OBBs must be intersecting
|
|
330
|
+
|
|
331
|
+
return true;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* To AABB with matrix4 transform.
|
|
336
|
+
* This method can ensure the AABB center is origin,
|
|
337
|
+
* and transform only contains rotation and offset.
|
|
338
|
+
* @param {Box3} box3 - The target box.
|
|
339
|
+
* @param {Matrix4} transform - The transformation matrix.
|
|
340
|
+
*/
|
|
341
|
+
toBoundingBoxWithTransform(box3, transform) {
|
|
342
|
+
const center = this.box.getCenter(_vec3_1);
|
|
343
|
+
|
|
344
|
+
box3.min.copy(this.box.min).sub(center);
|
|
345
|
+
box3.max.copy(this.box.max).sub(center);
|
|
346
|
+
|
|
347
|
+
const e = this.rotation.elements;
|
|
348
|
+
|
|
349
|
+
transform.set(
|
|
350
|
+
e[0], e[3], e[6], center.x,
|
|
351
|
+
e[1], e[4], e[7], center.y,
|
|
352
|
+
e[2], e[5], e[8], center.z,
|
|
353
|
+
0, 0, 0, 1
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
const closestPoint = new Vector3();
|
|
360
|
+
|
|
361
|
+
const _vec3_1 = new Vector3();
|
|
362
|
+
const _vec3_2 = new Vector3();
|
|
363
|
+
const _vec3_3 = new Vector3();
|
|
364
|
+
const _mat3_1 = new Matrix3();
|
|
365
|
+
|
|
366
|
+
const R = [[], [], []];
|
|
367
|
+
const AbsR = [[], [], []];
|
|
368
|
+
const t = [];
|
|
369
|
+
|
|
370
|
+
const _halfSize = new Vector3();
|
|
371
|
+
|
|
372
|
+
const a = {
|
|
373
|
+
c: new Vector3(), // center
|
|
374
|
+
u: [new Vector3(), new Vector3(), new Vector3()], // basis vectors
|
|
375
|
+
e: [] // half width
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
const b = {
|
|
379
|
+
c: new Vector3(), // center
|
|
380
|
+
u: [new Vector3(), new Vector3(), new Vector3()], // basis vectors
|
|
381
|
+
e: [] // half width
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
function getOBBStruct(obb, target) {
|
|
385
|
+
obb.box.getCenter(target.c);
|
|
386
|
+
|
|
387
|
+
const rotationElements = obb.rotation.elements;
|
|
388
|
+
target.u[0].fromArray(rotationElements, 0);
|
|
389
|
+
target.u[1].fromArray(rotationElements, 3);
|
|
390
|
+
target.u[2].fromArray(rotationElements, 6);
|
|
391
|
+
|
|
392
|
+
obb.box.getSize(_halfSize).multiplyScalar(0.5).toArray(target.e);
|
|
393
|
+
|
|
394
|
+
return target;
|
|
395
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { Sphere, Vector2, Vector3 } from 't3d';
|
|
2
|
+
import { TileOBB } from './TileOBB.js';
|
|
3
|
+
import { EllipsoidRegion } from './EllipsoidRegion.js';
|
|
4
|
+
|
|
5
|
+
export class TileBoundingVolume {
|
|
6
|
+
|
|
7
|
+
constructor() {
|
|
8
|
+
this.sphere = null;
|
|
9
|
+
this.obb = null;
|
|
10
|
+
this.region = null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
setOBBData(data, transform) {
|
|
14
|
+
const obb = new TileOBB();
|
|
15
|
+
|
|
16
|
+
obb.setFromCenterAndAxes(
|
|
17
|
+
_vec3_4.set(data[0], data[1], data[2]),
|
|
18
|
+
_vec3_1.set(data[3], data[4], data[5]),
|
|
19
|
+
_vec3_2.set(data[6], data[7], data[8]),
|
|
20
|
+
_vec3_3.set(data[9], data[10], data[11])
|
|
21
|
+
).applyMatrix4(transform);
|
|
22
|
+
obb.updateCache();
|
|
23
|
+
|
|
24
|
+
this.obb = obb;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
setSphereData(data, transform) {
|
|
28
|
+
const sphere = new Sphere();
|
|
29
|
+
|
|
30
|
+
sphere.center.set(data[0], data[1], data[2]);
|
|
31
|
+
sphere.radius = data[3];
|
|
32
|
+
sphere.applyMatrix4(transform);
|
|
33
|
+
|
|
34
|
+
this.sphere = sphere;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
setRegionData(west, south, east, north, minHeight, maxHeight) {
|
|
38
|
+
const region = new EllipsoidRegion(
|
|
39
|
+
WGS84_RADIUS.clone(),
|
|
40
|
+
new Vector2(south, north),
|
|
41
|
+
new Vector2(west, east),
|
|
42
|
+
new Vector2(minHeight, maxHeight)
|
|
43
|
+
);
|
|
44
|
+
this.region = region;
|
|
45
|
+
|
|
46
|
+
const obb = new TileOBB();
|
|
47
|
+
region.getOrientedBoundingBox(obb);
|
|
48
|
+
obb.updateCache();
|
|
49
|
+
this.obb = obb;
|
|
50
|
+
|
|
51
|
+
// const sphere = new Sphere();
|
|
52
|
+
// obb.getBoundingSphere(sphere);
|
|
53
|
+
// this.sphere = sphere;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
intersectsRay(ray) {
|
|
57
|
+
const sphere = this.sphere;
|
|
58
|
+
const obb = this.obb;
|
|
59
|
+
|
|
60
|
+
// Early out if we don't hit this tile sphere
|
|
61
|
+
if (sphere && !ray.intersectsSphere(sphere)) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Early out if we don't this this tile box
|
|
66
|
+
if (obb && !obb.intersectsRay(ray)) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
intersectRay(ray, target) {
|
|
74
|
+
const sphere = this.sphere;
|
|
75
|
+
const obb = this.obb;
|
|
76
|
+
|
|
77
|
+
let sphereDistSq = -Infinity;
|
|
78
|
+
let obbDistSq = -Infinity;
|
|
79
|
+
|
|
80
|
+
if (sphere) {
|
|
81
|
+
if (ray.intersectSphere(sphere, _vec3_1)) {
|
|
82
|
+
sphereDistSq = sphere.containsPoint(ray.origin) ? 0 : ray.origin.distanceToSquared(_vec3_1);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (obb) {
|
|
87
|
+
if (obb.intersectRay(ray, _vec3_1)) {
|
|
88
|
+
obbDistSq = obb.containsPoint(ray.origin) ? 0 : ray.origin.distanceToSquared(_vec3_1);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// if we didn't hit anything then exit
|
|
93
|
+
const furthestDist = Math.max(sphereDistSq, obbDistSq);
|
|
94
|
+
if (furthestDist === -Infinity) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// get the furthest hit point if needed
|
|
99
|
+
return ray.at(Math.sqrt(furthestDist), target);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
distanceToPoint(point) {
|
|
103
|
+
const sphere = this.sphere;
|
|
104
|
+
const obb = this.obb;
|
|
105
|
+
|
|
106
|
+
let sphereDistance = -Infinity;
|
|
107
|
+
let obbDistance = -Infinity;
|
|
108
|
+
|
|
109
|
+
if (sphere) {
|
|
110
|
+
// Sphere#distanceToPoint is negative inside the sphere, whereas Box3#distanceToPoint is
|
|
111
|
+
// zero inside the box. Clipping the distance to a minimum of zero ensures that both
|
|
112
|
+
// types of bounding volume behave the same way.
|
|
113
|
+
sphereDistance = Math.max(sphere.distanceToPoint(point), 0);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (obb) {
|
|
117
|
+
obbDistance = obb.distanceToPoint(point);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// return the further distance of the two volumes
|
|
121
|
+
return sphereDistance > obbDistance ? sphereDistance : obbDistance;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
intersectsFrustum(frustum) {
|
|
125
|
+
const sphere = this.sphere;
|
|
126
|
+
if (sphere && !frustum.intersectsSphere(sphere)) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const obb = this.obb;
|
|
131
|
+
if (obb && !obb.intersectsFrustum(frustum)) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// if we don't have a sphere or obb then just say we did intersect
|
|
136
|
+
return Boolean(sphere || obb);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
getOrientedBoundingBox(targetBox, targetMatrix) {
|
|
140
|
+
if (this.obb) {
|
|
141
|
+
targetBox.copy(this.obb._originBox);
|
|
142
|
+
targetMatrix.copy(this.obb._originBoxTransform);
|
|
143
|
+
} else {
|
|
144
|
+
this.getBoundingBox(targetBox);
|
|
145
|
+
targetMatrix.identity();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
getBoundingBox(target) {
|
|
150
|
+
if (this.sphere) {
|
|
151
|
+
return this.sphere.getBoundingBox(target);
|
|
152
|
+
} else {
|
|
153
|
+
return this.obb.getBoundingBox(target);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
getBoundingSphere(target) {
|
|
158
|
+
if (this.sphere) {
|
|
159
|
+
return target.copy(this.sphere);
|
|
160
|
+
} else {
|
|
161
|
+
return this.obb.getBoundingSphere(target);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const WGS84_RADIUS = new Vector3(6378137, 6378137, 6356752.3142451793);
|
|
168
|
+
|
|
169
|
+
const _vec3_1 = new Vector3();
|
|
170
|
+
const _vec3_2 = new Vector3();
|
|
171
|
+
const _vec3_3 = new Vector3();
|
|
172
|
+
const _vec3_4 = new Vector3();
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { Box3, Matrix4, Plane, Ray, Vector3 } from 't3d';
|
|
2
|
+
import { OBB } from './OBB.js';
|
|
3
|
+
|
|
4
|
+
export class TileOBB extends OBB {
|
|
5
|
+
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
|
|
9
|
+
// cache obb points and planes
|
|
10
|
+
// to speed up intersection test with frustum
|
|
11
|
+
this._points = new Array(8).fill().map(() => new Vector3());
|
|
12
|
+
this._planes = new Array(6).fill().map(() => new Plane());
|
|
13
|
+
|
|
14
|
+
// cache obb origin box and transform matrix4x4
|
|
15
|
+
// to speed up intersection test with ray and error calculation
|
|
16
|
+
this._originBox = new Box3();
|
|
17
|
+
this._originBoxTransform = new Matrix4();
|
|
18
|
+
this._originBoxTransformInverse = new Matrix4();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
updateCache() {
|
|
22
|
+
this.getPoints(this._points);
|
|
23
|
+
this.getPlanes(this._planes);
|
|
24
|
+
|
|
25
|
+
this.toBoundingBoxWithTransform(
|
|
26
|
+
this._originBox, this._originBoxTransform
|
|
27
|
+
);
|
|
28
|
+
this._originBoxTransformInverse.copy(this._originBoxTransform).inverse();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
containsPoint(point) {
|
|
32
|
+
_vec3_1.copy(point).applyMatrix4(this._originBoxTransformInverse);
|
|
33
|
+
return this.box.containsPoint(_vec3_1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
intersectsRay(ray) {
|
|
37
|
+
_ray_1.copy(ray).applyMatrix4(this._originBoxTransformInverse);
|
|
38
|
+
return _ray_1.intersectsBox(this._originBox);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
intersectRay(ray, target) {
|
|
42
|
+
_ray_1.copy(ray).applyMatrix4(this._originBoxTransformInverse);
|
|
43
|
+
|
|
44
|
+
if (_ray_1.intersectBox(this._originBox, target)) {
|
|
45
|
+
return target.applyMatrix4(this._originBoxTransform);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// optimized intersection test with frustum
|
|
52
|
+
intersectsFrustum(frustum) {
|
|
53
|
+
for (let i = 0; i < 6; i++) {
|
|
54
|
+
const plane = frustum.planes[i];
|
|
55
|
+
let maxDistance = -Infinity;
|
|
56
|
+
for (let j = 0; j < 8; j++) {
|
|
57
|
+
const v = this._points[j];
|
|
58
|
+
const dist = plane.distanceToPoint(v);
|
|
59
|
+
maxDistance = maxDistance < dist ? dist : maxDistance;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (maxDistance < 0) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// do the opposite check using the obb planes to avoid false positives
|
|
68
|
+
for (let i = 0; i < 6; i++) {
|
|
69
|
+
const plane = this._planes[i];
|
|
70
|
+
let maxDistance = -Infinity;
|
|
71
|
+
for (let j = 0; j < 8; j++) {
|
|
72
|
+
const v = frustum.points[j];
|
|
73
|
+
const dist = plane.distanceToPoint(v);
|
|
74
|
+
maxDistance = maxDistance < dist ? dist : maxDistance;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (maxDistance < 0) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
distanceToPoint(point) {
|
|
86
|
+
// originBoxTransformInverse has no scale,
|
|
87
|
+
// so we don't need to scale the distance
|
|
88
|
+
_vec3_1.copy(point).applyMatrix4(this._originBoxTransformInverse);
|
|
89
|
+
return this._originBox.distanceToPoint(_vec3_1);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
getBoundingSphere(target) {
|
|
93
|
+
return this.box.getBoundingSphere(target);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
getBoundingBox(target) {
|
|
97
|
+
return target.setFromPoints(this._points);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const _ray_1 = new Ray();
|
|
103
|
+
const _vec3_1 = new Vector3();
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { FeatureTable } from './FeatureTable.js';
|
|
2
|
+
|
|
3
|
+
export class BatchTable extends FeatureTable {
|
|
4
|
+
|
|
5
|
+
constructor(buffer, batchSize, start, headerLength, binLength) {
|
|
6
|
+
super(buffer, start, headerLength, binLength);
|
|
7
|
+
this.batchSize = batchSize;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
getData(key, componentType = null, type = null) {
|
|
11
|
+
return super.getData(key, this.batchSize, componentType, type);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
}
|