@jdultra/threedtiles 7.0.2 → 8.0.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/.babelrc +8 -0
- package/package.json +8 -7
- package/src/decoder/B3DMDecoder.js +82 -203
- package/src/index.js +70 -30
- package/src/tileset/OGC3DTile.js +30 -25
- package/src/tileset/TileLoader.js +44 -10
- package/src/tileset/instanced/InstancedTile.js +1 -1
- package/src/tileset/instanced/InstancedTileLoader.js +85 -51
- package/threedtiles.js +80023 -20211
- package/threedtiles.js.map +1 -1
- package/webpack.config.js +17 -16
package/.babelrc
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jdultra/threedtiles",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"description": "An OGC 3DTiles viewer for Three.js",
|
|
5
5
|
"main": "tileset.js",
|
|
6
6
|
"scripts": {
|
|
@@ -35,17 +35,18 @@
|
|
|
35
35
|
"uuid": "^8.3.2"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@babel/core": "^7.
|
|
39
|
-
"@babel/
|
|
40
|
-
"babel-
|
|
38
|
+
"@babel/core": "^7.21.4",
|
|
39
|
+
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
|
40
|
+
"@babel/preset-env": "^7.21.4",
|
|
41
|
+
"babel-loader": "^9.1.2",
|
|
41
42
|
"copy-webpack-plugin": "^6.3.2",
|
|
42
43
|
"core-js": "^3.27.1",
|
|
43
44
|
"html-loader": "^1.3.2",
|
|
44
45
|
"html-webpack-plugin": "^4.5.0",
|
|
45
46
|
"mini-css-extract-plugin": "^1.6.2",
|
|
46
|
-
"webpack": "^5.
|
|
47
|
-
"webpack-cli": "
|
|
48
|
-
"webpack-dev-server": "^4.
|
|
47
|
+
"webpack": "^5.79.0",
|
|
48
|
+
"webpack-cli": "^5.0.1",
|
|
49
|
+
"webpack-dev-server": "^4.13.2",
|
|
49
50
|
"webpack-glsl-loader": "^1.0.1",
|
|
50
51
|
"whatwg-fetch": "^3.5.0"
|
|
51
52
|
}
|
|
@@ -1,109 +1,114 @@
|
|
|
1
1
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
2
2
|
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
|
|
3
|
+
import { KTX2Loader } from "three/examples/jsm/loaders/KTX2Loader";
|
|
3
4
|
import * as THREE from 'three';
|
|
4
|
-
import {FeatureTable, BatchTable} from './FeatureTable';
|
|
5
|
+
import { FeatureTable, BatchTable } from './FeatureTable';
|
|
5
6
|
|
|
6
|
-
const gltfLoader = new GLTFLoader();
|
|
7
|
-
const dracoLoader = new DRACOLoader();
|
|
8
|
-
dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.4.3/');
|
|
9
|
-
gltfLoader.setDRACOLoader(dracoLoader);
|
|
10
|
-
const tempMatrix = new THREE.Matrix4();
|
|
11
7
|
const zUpToYUpMatrix = new THREE.Matrix4();
|
|
12
|
-
zUpToYUpMatrix.set(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
8
|
+
zUpToYUpMatrix.set(
|
|
9
|
+
1, 0, 0, 0,
|
|
10
|
+
0, 0, -1, 0,
|
|
11
|
+
0, 1, 0, 0,
|
|
12
|
+
0, 0, 0, 1);
|
|
13
|
+
|
|
14
|
+
export class B3DMDecoder {
|
|
15
|
+
constructor(renderer) {
|
|
16
|
+
this.gltfLoader = new GLTFLoader();
|
|
17
|
+
const dracoLoader = new DRACOLoader();
|
|
18
|
+
dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.4.3/');
|
|
19
|
+
this.gltfLoader.setDRACOLoader(dracoLoader);
|
|
20
|
+
if (renderer) {
|
|
21
|
+
const ktx2Loader = new KTX2Loader();
|
|
22
|
+
ktx2Loader.setTranscoderPath('https://storage.googleapis.com/ogc-3d-tiles/basis/').detectSupport(renderer);
|
|
23
|
+
this.gltfLoader.setKTX2Loader(ktx2Loader)
|
|
24
|
+
}
|
|
18
25
|
|
|
19
|
-
|
|
20
|
-
|
|
26
|
+
this.tempMatrix = new THREE.Matrix4();
|
|
27
|
+
}
|
|
21
28
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
String.fromCharCode(dataView.getUint8(1)) +
|
|
25
|
-
String.fromCharCode(dataView.getUint8(2)) +
|
|
26
|
-
String.fromCharCode(dataView.getUint8(3));
|
|
27
|
-
console.assert(magic === 'b3dm');
|
|
29
|
+
parseB3DM(arrayBuffer, meshCallback, geometricError, zUpToYUp) {
|
|
30
|
+
const dataView = new DataView(arrayBuffer);
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
const magic =
|
|
33
|
+
String.fromCharCode(dataView.getUint8(0)) +
|
|
34
|
+
String.fromCharCode(dataView.getUint8(1)) +
|
|
35
|
+
String.fromCharCode(dataView.getUint8(2)) +
|
|
36
|
+
String.fromCharCode(dataView.getUint8(3));
|
|
37
|
+
console.assert(magic === 'b3dm');
|
|
31
38
|
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
const byteLength = dataView.getUint32(8, true);
|
|
40
|
+
console.assert(byteLength === arrayBuffer.byteLength);
|
|
34
41
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
42
|
+
const featureTableJSONByteLength = dataView.getUint32(12, true);
|
|
43
|
+
const featureTableBinaryByteLength = dataView.getUint32(16, true);
|
|
44
|
+
const batchTableJSONByteLength = dataView.getUint32(20, true);
|
|
45
|
+
const batchTableBinaryByteLength = dataView.getUint32(24, true);
|
|
39
46
|
|
|
40
|
-
|
|
41
|
-
|
|
47
|
+
const featureTableStart = 28;
|
|
48
|
+
const featureTable = new FeatureTable(arrayBuffer, featureTableStart, featureTableJSONByteLength, featureTableBinaryByteLength);
|
|
42
49
|
|
|
43
|
-
|
|
44
|
-
|
|
50
|
+
const batchTableStart = featureTableStart + featureTableJSONByteLength + featureTableBinaryByteLength;
|
|
51
|
+
const batchTable = new BatchTable(arrayBuffer, featureTable.getData('BATCH_LENGTH'), batchTableStart, batchTableJSONByteLength, batchTableBinaryByteLength);
|
|
45
52
|
|
|
46
|
-
|
|
47
|
-
|
|
53
|
+
const glbStart = batchTableStart + batchTableJSONByteLength + batchTableBinaryByteLength;
|
|
54
|
+
const glbBytes = new Uint8Array(arrayBuffer, glbStart, byteLength - glbStart);
|
|
48
55
|
|
|
49
56
|
|
|
50
|
-
|
|
57
|
+
const gltfBuffer = glbBytes.slice().buffer;
|
|
51
58
|
|
|
52
59
|
|
|
53
|
-
|
|
60
|
+
return new Promise((resolve, reject) => {
|
|
54
61
|
|
|
55
|
-
|
|
62
|
+
this.gltfLoader.parse(gltfBuffer, null, model => {
|
|
56
63
|
|
|
57
|
-
|
|
64
|
+
////TODO
|
|
58
65
|
|
|
59
|
-
|
|
60
|
-
|
|
66
|
+
//model.batchTable = b3dm.batchTable;
|
|
67
|
+
//model.featureTable = b3dm.featureTable;
|
|
61
68
|
|
|
62
|
-
|
|
63
|
-
|
|
69
|
+
//model.scene.batchTable = b3dm.batchTable;
|
|
70
|
+
//model.scene.featureTable = b3dm.featureTable;
|
|
64
71
|
|
|
65
|
-
|
|
72
|
+
//const scene = mergeColoredObject(model.scene);
|
|
66
73
|
|
|
67
|
-
|
|
74
|
+
//model.scene.applyMatrix4(ytozUpMatrix);
|
|
68
75
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if(!zUpToYUp){
|
|
79
|
-
model.scene.applyMatrix4(zUpToYUpMatrix);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
model.scene.traverse((o) => {
|
|
83
|
-
|
|
84
|
-
if (o.isMesh) {
|
|
85
|
-
o.geometricError = geometricError
|
|
86
|
-
if(zUpToYUp){
|
|
87
|
-
o.applyMatrix4(zUpToYUpMatrix);
|
|
88
|
-
}
|
|
89
|
-
if (!!meshCallback) {
|
|
90
|
-
meshCallback(o);
|
|
91
|
-
}
|
|
76
|
+
const rtcCenter = featureTable.getData('RTC_CENTER');
|
|
77
|
+
if (rtcCenter) {
|
|
78
|
+
this.tempMatrix.makeTranslation(rtcCenter[0], rtcCenter[1], rtcCenter[2])
|
|
79
|
+
model.scene.applyMatrix4(this.tempMatrix);
|
|
80
|
+
} else if (!!model.userData.gltfExtensions && !!model.userData.gltfExtensions.CESIUM_RTC) {
|
|
81
|
+
this.tempMatrix.makeTranslation(model.userData.gltfExtensions.CESIUM_RTC.center[0], model.userData.gltfExtensions.CESIUM_RTC.center[1], model.userData.gltfExtensions.CESIUM_RTC.center[2])
|
|
82
|
+
model.scene.applyMatrix4(this.tempMatrix);
|
|
83
|
+
}
|
|
92
84
|
|
|
85
|
+
if (!zUpToYUp) {
|
|
86
|
+
model.scene.applyMatrix4(zUpToYUpMatrix);
|
|
93
87
|
}
|
|
88
|
+
|
|
89
|
+
model.scene.traverse((o) => {
|
|
90
|
+
|
|
91
|
+
if (o.isMesh) {
|
|
92
|
+
o.geometricError = geometricError
|
|
93
|
+
if (zUpToYUp) {
|
|
94
|
+
o.applyMatrix4(zUpToYUpMatrix);
|
|
95
|
+
}
|
|
96
|
+
if (!!meshCallback) {
|
|
97
|
+
meshCallback(o);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
resolve(model.scene);
|
|
103
|
+
}, error => {
|
|
104
|
+
console.error(error);
|
|
94
105
|
});
|
|
95
|
-
resolve(model.scene);
|
|
96
|
-
}, error => {
|
|
97
|
-
console.error(error);
|
|
98
106
|
});
|
|
99
|
-
}
|
|
100
|
-
}
|
|
107
|
+
}
|
|
101
108
|
|
|
102
|
-
|
|
103
|
-
parseB3DM: parseB3DM,
|
|
104
|
-
parseB3DMInstanced: (arrayBuffer, meshCallback, maxCount, zUpToYUp) => { // expects GLTF with one node level
|
|
109
|
+
parseB3DMInstanced(arrayBuffer, meshCallback, maxCount, zUpToYUp) { // expects GLTF with one node level
|
|
105
110
|
|
|
106
|
-
return parseB3DM(arrayBuffer, meshCallback, zUpToYUp).then(mesh => {
|
|
111
|
+
return this.parseB3DM(arrayBuffer, meshCallback, zUpToYUp).then(mesh => {
|
|
107
112
|
// todo several meshes in a single gltf
|
|
108
113
|
let instancedMesh;
|
|
109
114
|
mesh.updateWorldMatrix(false, true)
|
|
@@ -117,130 +122,4 @@ const B3DMDecoder = {
|
|
|
117
122
|
});
|
|
118
123
|
|
|
119
124
|
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* //TODO find something else than this workaround
|
|
124
|
-
*
|
|
125
|
-
* Because B3DM doesn't support colored faces, they are usually encoded as separate meshes each one with a global color.
|
|
126
|
-
* However, when a mesh has many different face colors, this becomes very inneficient.
|
|
127
|
-
* This method doesn't fix the slow decoding of the GLTFLoader but at least merges meshes together and transfers the face color to vertex color
|
|
128
|
-
* which is much more efficient at render time.
|
|
129
|
-
* Textured meshes with the same texture are also merged and color is discarded
|
|
130
|
-
*
|
|
131
|
-
* Big assumption! all the meshes are assumed to have the same transformation matrix
|
|
132
|
-
*
|
|
133
|
-
* @param {*} scene
|
|
134
|
-
* @returns
|
|
135
|
-
*/
|
|
136
|
-
/*function mergeColoredObject(scene) {
|
|
137
|
-
|
|
138
|
-
const coloredMeshes = {};
|
|
139
|
-
const texturedMeshes = {};
|
|
140
|
-
scene.traverse((element) => {
|
|
141
|
-
if (element.isMesh) {
|
|
142
|
-
if (element.material) {
|
|
143
|
-
// dispose materials
|
|
144
|
-
if (element.material.length) {
|
|
145
|
-
// not supported
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
if (!element.material.map) {
|
|
149
|
-
let color = element.material.color;
|
|
150
|
-
color = "rgb("+Math.floor(color.r*255)+","+Math.floor(color.g*255)+","+Math.floor(color.b*255)+")";
|
|
151
|
-
if (!coloredMeshes[color]) {
|
|
152
|
-
coloredMeshes[color] = [];
|
|
153
|
-
}
|
|
154
|
-
coloredMeshes[color].push(element);
|
|
155
|
-
} else {
|
|
156
|
-
if (!texturedMeshes[element.material.map]) {
|
|
157
|
-
texturedMeshes[element.material.map] = [];
|
|
158
|
-
}
|
|
159
|
-
texturedMeshes[element.material.map].push(element);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
let coloredMeshMaterial;
|
|
167
|
-
const fullColoredGeometriesToMerge = [];
|
|
168
|
-
for (const color in coloredMeshes) {
|
|
169
|
-
if (coloredMeshes.hasOwnProperty(color)) {
|
|
170
|
-
const threeColor = new Color(color);
|
|
171
|
-
//const geometriesToMerge = [];
|
|
172
|
-
coloredMeshes[color].forEach(mesh => {
|
|
173
|
-
if(!coloredMeshMaterial){
|
|
174
|
-
coloredMeshMaterial = mesh.material.clone();
|
|
175
|
-
delete coloredMeshMaterial.color;
|
|
176
|
-
coloredMeshMaterial.vertexColors = true;
|
|
177
|
-
}
|
|
178
|
-
const colors = [];
|
|
179
|
-
for (let i = 0; i < mesh.geometry.attributes.position.count; i++) {
|
|
180
|
-
colors.push(threeColor.r);
|
|
181
|
-
colors.push(threeColor.g);
|
|
182
|
-
colors.push(threeColor.b);
|
|
183
|
-
}
|
|
184
|
-
mesh.geometry.setAttribute('color', new BufferAttribute(new Float32Array(colors), 3));
|
|
185
|
-
|
|
186
|
-
fullColoredGeometriesToMerge.push(mesh.geometry);
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
let mergedColoredMesh;
|
|
193
|
-
if(fullColoredGeometriesToMerge.length>0){
|
|
194
|
-
let mergedColoredGeometry = BufferGeometryUtils.mergeBufferGeometries(fullColoredGeometriesToMerge, false);
|
|
195
|
-
mergedColoredMesh = new Mesh(mergedColoredGeometry, coloredMeshMaterial);
|
|
196
|
-
//mergedColoredMesh.matrix = matrix;
|
|
197
|
-
for (const color in coloredMeshes) {
|
|
198
|
-
if (coloredMeshes.hasOwnProperty(color)) {
|
|
199
|
-
coloredMeshes[color].forEach(mesh => {
|
|
200
|
-
mesh.material.dispose();
|
|
201
|
-
mesh.geometry.dispose();
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const mergedTexturedMeshes = [];
|
|
209
|
-
for(const map in texturedMeshes){
|
|
210
|
-
if (texturedMeshes.hasOwnProperty(map)) {
|
|
211
|
-
if(texturedMeshes[map].length==1){
|
|
212
|
-
mergedTexturedMeshes.push(texturedMeshes[map][0]);
|
|
213
|
-
continue;
|
|
214
|
-
}
|
|
215
|
-
const geometries = [];
|
|
216
|
-
let material;
|
|
217
|
-
texturedMeshes[map].forEach(mesh => {
|
|
218
|
-
if(!material){
|
|
219
|
-
material = mesh.material.clone();
|
|
220
|
-
delete material.color;
|
|
221
|
-
material.vertexColors = false;
|
|
222
|
-
}
|
|
223
|
-
geometries.push(mesh.geometry);
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
const mergedGeometry = BufferGeometryUtils.mergeBufferGeometries(geometries, false);
|
|
227
|
-
const mesh = new Mesh(mergedGeometry, material);
|
|
228
|
-
//mesh.matrix = matrix;
|
|
229
|
-
mergedTexturedMeshes.push(mesh);
|
|
230
|
-
texturedMeshes[map].forEach(mesh => {
|
|
231
|
-
mesh.material.dispose();
|
|
232
|
-
mesh.geometry.dispose();
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
scene.clear();
|
|
238
|
-
if(!!mergedColoredMesh) scene.add(mergedColoredMesh);
|
|
239
|
-
mergedTexturedMeshes.forEach(mesh=>scene.add(mesh));
|
|
240
|
-
console.log();
|
|
241
|
-
scene.matrix = new THREE.Matrix4();
|
|
242
|
-
return scene;
|
|
243
|
-
}*/
|
|
244
|
-
|
|
245
|
-
export { B3DMDecoder }
|
|
246
|
-
|
|
125
|
+
}
|
package/src/index.js
CHANGED
|
@@ -13,6 +13,9 @@ import { InstancedOGC3DTile } from "./tileset/instanced/InstancedOGC3DTile.js"
|
|
|
13
13
|
import { InstancedTileLoader } from "./tileset/instanced/InstancedTileLoader.js"
|
|
14
14
|
import { Sky } from 'three/addons/objects/Sky.js';
|
|
15
15
|
|
|
16
|
+
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
|
17
|
+
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
|
|
18
|
+
import { KTX2Loader } from "three/examples/jsm/loaders/KTX2Loader";
|
|
16
19
|
|
|
17
20
|
const occlusionCullingService = new OcclusionCullingService();
|
|
18
21
|
occlusionCullingService.setSide(THREE.DoubleSide);
|
|
@@ -23,6 +26,43 @@ const camera = initCamera(domContainer.offsetWidth, domContainer.offsetHeight);
|
|
|
23
26
|
const stats = initStats(domContainer);
|
|
24
27
|
const renderer = initRenderer(camera, domContainer);
|
|
25
28
|
const ogc3DTiles = initTileset(scene, 2.0);
|
|
29
|
+
//const instancedTileLoader = createInstancedTileLoader(scene);
|
|
30
|
+
//const ogc3DTiles = initInstancedTilesets(instancedTileLoader);
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
/*const gltfLoader = new GLTFLoader();
|
|
34
|
+
const dracoLoader = new DRACOLoader();
|
|
35
|
+
dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.4.3/');
|
|
36
|
+
gltfLoader.setDRACOLoader(dracoLoader);
|
|
37
|
+
|
|
38
|
+
const ktx2Loader = new KTX2Loader();
|
|
39
|
+
ktx2Loader.setTranscoderPath('jsm/libs/basis/');
|
|
40
|
+
//gltfLoader.setKTX2Loader(ktx2Loader)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
gltfLoader.load(
|
|
44
|
+
// resource URL
|
|
45
|
+
'http://localhost:8080/3/15.glb',
|
|
46
|
+
// called when the resource is loaded
|
|
47
|
+
function (gltf) {
|
|
48
|
+
|
|
49
|
+
scene.add(gltf.scene);
|
|
50
|
+
|
|
51
|
+
},
|
|
52
|
+
// called while loading is progressing
|
|
53
|
+
function (xhr) {
|
|
54
|
+
|
|
55
|
+
console.log((xhr.loaded / xhr.total * 100) + '% loaded');
|
|
56
|
+
|
|
57
|
+
},
|
|
58
|
+
// called when loading has errors
|
|
59
|
+
function (error) {
|
|
60
|
+
|
|
61
|
+
console.log('An error happened : ' + error);
|
|
62
|
+
|
|
63
|
+
}
|
|
64
|
+
);*/
|
|
65
|
+
// Optional: Provide a DRACOLoader instance to decode compressed mesh data
|
|
26
66
|
|
|
27
67
|
const controller = initController(camera, domContainer);
|
|
28
68
|
|
|
@@ -150,21 +190,26 @@ function initStats(dom) {
|
|
|
150
190
|
|
|
151
191
|
function initTileset(scene, gem) {
|
|
152
192
|
|
|
153
|
-
const tileLoader = new TileLoader(
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
mesh
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
193
|
+
const tileLoader = new TileLoader({
|
|
194
|
+
renderer: renderer,
|
|
195
|
+
maxCachedItems: 100,
|
|
196
|
+
meshCallback: mesh => {
|
|
197
|
+
//// Insert code to be called on every newly decoded mesh e.g.:
|
|
198
|
+
mesh.material.wireframe = false;
|
|
199
|
+
mesh.material.side = THREE.DoubleSide;
|
|
200
|
+
//mesh.material.metalness = 0.0
|
|
201
|
+
},
|
|
202
|
+
pointsCallback: points => {
|
|
203
|
+
points.material.size = Math.min(1.0, 0.5 * Math.sqrt(points.geometricError));
|
|
204
|
+
points.material.sizeAttenuation = true;
|
|
205
|
+
}
|
|
161
206
|
});
|
|
162
207
|
|
|
163
208
|
const ogc3DTile = new OGC3DTile({
|
|
164
209
|
//url: "https://storage.googleapis.com/ogc-3d-tiles/berlinTileset/tileset.json",
|
|
165
|
-
url: "https://storage.googleapis.com/ogc-3d-tiles/ayutthaya/tiledWithSkirts/tileset.json",
|
|
166
|
-
|
|
167
|
-
geometricErrorMultiplier:
|
|
210
|
+
//url: "https://storage.googleapis.com/ogc-3d-tiles/ayutthaya/tiledWithSkirts/tileset.json",
|
|
211
|
+
url: "http://localhost:8080/tileset.json",
|
|
212
|
+
geometricErrorMultiplier: gem,
|
|
168
213
|
loadOutsideView: true,
|
|
169
214
|
tileLoader: tileLoader,
|
|
170
215
|
//occlusionCullingService: occlusionCullingService,
|
|
@@ -179,7 +224,7 @@ function initTileset(scene, gem) {
|
|
|
179
224
|
|
|
180
225
|
//ogc3DTile.scale.set(0.1,0.1,0.1)
|
|
181
226
|
|
|
182
|
-
|
|
227
|
+
ogc3DTile.rotateOnAxis(new THREE.Vector3(1, 0, 0), -Math.PI * 0.5) // Z-UP to Y-UP
|
|
183
228
|
//ogc3DTile.translateOnAxis(new THREE.Vector3(0, 0, 1), 1)
|
|
184
229
|
/*
|
|
185
230
|
ogc3DTile.translateOnAxis(new THREE.Vector3(0, 0, 1), 10) // Z-UP to Y-UP
|
|
@@ -191,13 +236,20 @@ function initTileset(scene, gem) {
|
|
|
191
236
|
|
|
192
237
|
|
|
193
238
|
function createInstancedTileLoader(scene) {
|
|
194
|
-
return new InstancedTileLoader(scene,
|
|
195
|
-
|
|
239
|
+
return new InstancedTileLoader(scene, {
|
|
240
|
+
renderer: renderer,
|
|
241
|
+
maxCachedItems : 100,
|
|
242
|
+
maxInstances : 1,
|
|
243
|
+
meshCallback: mesh => {
|
|
196
244
|
//// Insert code to be called on every newly decoded mesh e.g.:
|
|
197
245
|
mesh.material.wireframe = false;
|
|
198
246
|
mesh.material.side = THREE.DoubleSide;
|
|
199
|
-
|
|
200
|
-
|
|
247
|
+
},
|
|
248
|
+
pointsCallback: points => {
|
|
249
|
+
points.material.size = Math.min(1.0, 0.5 * Math.sqrt(points.geometricError));
|
|
250
|
+
points.material.sizeAttenuation = true;
|
|
251
|
+
}
|
|
252
|
+
});
|
|
201
253
|
}
|
|
202
254
|
function initInstancedTilesets(instancedTileLoader) {
|
|
203
255
|
|
|
@@ -211,14 +263,14 @@ function initInstancedTilesets(instancedTileLoader) {
|
|
|
211
263
|
const tileset = new InstancedOGC3DTile({
|
|
212
264
|
//url: "https://storage.googleapis.com/ogc-3d-tiles/berlinTileset/tileset.json",
|
|
213
265
|
url: "http://localhost:8080/tileset.json",
|
|
214
|
-
geometricErrorMultiplier:
|
|
266
|
+
geometricErrorMultiplier: 1,
|
|
215
267
|
loadOutsideView: true,
|
|
216
268
|
tileLoader: instancedTileLoader,
|
|
217
269
|
static: false,
|
|
218
270
|
centerModel: true,
|
|
219
271
|
renderer: renderer
|
|
220
272
|
});
|
|
221
|
-
|
|
273
|
+
tileset.rotateOnAxis(new THREE.Vector3(1, 0, 0), Math.PI * -1) // Z-UP to Y-UP
|
|
222
274
|
|
|
223
275
|
tileset.updateMatrix()
|
|
224
276
|
scene.add(tileset);
|
|
@@ -242,18 +294,6 @@ function initInstancedTilesets(instancedTileLoader) {
|
|
|
242
294
|
//initLODMultiplierSlider(instancedTilesets);
|
|
243
295
|
}
|
|
244
296
|
|
|
245
|
-
function initLODMultiplierSlider(instancedTilesets) {
|
|
246
|
-
var slider = document.getElementById("lodMultiplier");
|
|
247
|
-
var output = document.getElementById("multiplierValue");
|
|
248
|
-
output.innerHTML = slider.value;
|
|
249
|
-
|
|
250
|
-
slider.oninput = () => {
|
|
251
|
-
instancedTilesets.forEach(tileset => {
|
|
252
|
-
tileset.setGeometricErrorMultiplier(slider.value * 0.1)
|
|
253
|
-
})
|
|
254
|
-
output.innerHTML = slider.value;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
297
|
|
|
258
298
|
function initCamera(width, height) {
|
|
259
299
|
const camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 20000);
|
package/src/tileset/OGC3DTile.js
CHANGED
|
@@ -4,12 +4,14 @@ import { TileLoader } from "./TileLoader";
|
|
|
4
4
|
import { v4 as uuidv4 } from "uuid";
|
|
5
5
|
import * as path from "path-browserify"
|
|
6
6
|
import { clamp } from "three/src/math/MathUtils";
|
|
7
|
+
import { Octree } from 'three/addons/math/Octree.js';
|
|
8
|
+
import { OctreeHelper } from 'three/addons/helpers/OctreeHelper.js';
|
|
7
9
|
|
|
8
10
|
const tempSphere = new THREE.Sphere(new THREE.Vector3(0, 0, 0), 1);
|
|
9
11
|
const tempVec1 = new THREE.Vector3(0, 0, 0);
|
|
10
12
|
const tempVec2 = new THREE.Vector3(0, 0, 0);
|
|
11
13
|
const upVector = new THREE.Vector3(0, 1, 0);
|
|
12
|
-
const rendererSize = new THREE.Vector2(1000,1000);
|
|
14
|
+
const rendererSize = new THREE.Vector2(1000, 1000);
|
|
13
15
|
const tempQuaternion = new THREE.Quaternion();
|
|
14
16
|
|
|
15
17
|
|
|
@@ -46,16 +48,16 @@ class OGC3DTile extends THREE.Object3D {
|
|
|
46
48
|
if (!!properties.tileLoader) {
|
|
47
49
|
this.tileLoader = properties.tileLoader;
|
|
48
50
|
} else {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
51
|
+
const tileLoaderOptions = {};
|
|
52
|
+
tileLoaderOptions.meshCallback = !properties.meshCallback ? mesh => {
|
|
53
|
+
mesh.material.wireframe = false;
|
|
54
|
+
mesh.material.side = THREE.DoubleSide;
|
|
55
|
+
} : properties.meshCallback;
|
|
56
|
+
tileLoaderOptions.pointsCallback = !properties.pointsCallback ? points => {
|
|
57
|
+
points.material.size = 0.1;
|
|
58
|
+
points.material.sizeAttenuation = true;
|
|
59
|
+
} : properties.pointsCallback;
|
|
60
|
+
this.tileLoader = new TileLoader(tileLoaderOptions);
|
|
59
61
|
}
|
|
60
62
|
// set properties general to the entire tileset
|
|
61
63
|
this.geometricErrorMultiplier = !!properties.geometricErrorMultiplier ? properties.geometricErrorMultiplier : 1.0;
|
|
@@ -93,6 +95,7 @@ class OGC3DTile extends THREE.Object3D {
|
|
|
93
95
|
this.centerModel = properties.centerModel;
|
|
94
96
|
this.abortController = new AbortController();
|
|
95
97
|
this.layers.disable(0);
|
|
98
|
+
this.octree = new Octree();
|
|
96
99
|
|
|
97
100
|
if (!!properties.json) { // If this tile is created as a child of another tile, properties.json is not null
|
|
98
101
|
self.setup(properties);
|
|
@@ -123,11 +126,11 @@ class OGC3DTile extends THREE.Object3D {
|
|
|
123
126
|
(this.json.boundingVolume.region[1] + this.json.boundingVolume.region[3]) * 0.5,
|
|
124
127
|
(this.json.boundingVolume.region[4] + this.json.boundingVolume.region[5]) * 0.5,
|
|
125
128
|
tempVec1);
|
|
126
|
-
|
|
129
|
+
|
|
127
130
|
tempQuaternion.setFromUnitVectors(tempVec1.normalize(), upVector.normalize());
|
|
128
131
|
self.applyQuaternion(tempQuaternion);
|
|
129
132
|
}
|
|
130
|
-
|
|
133
|
+
|
|
131
134
|
self.translateX(-tempSphere.center.x * self.scale.x);
|
|
132
135
|
self.translateY(-tempSphere.center.y * self.scale.y);
|
|
133
136
|
self.translateZ(-tempSphere.center.z * self.scale.z);
|
|
@@ -169,7 +172,7 @@ class OGC3DTile extends THREE.Object3D {
|
|
|
169
172
|
mat.elements = this.json.transform;
|
|
170
173
|
this.applyMatrix4(mat);
|
|
171
174
|
}
|
|
172
|
-
|
|
175
|
+
|
|
173
176
|
// decode volume
|
|
174
177
|
if (!!this.json.boundingVolume) {
|
|
175
178
|
if (!!this.json.boundingVolume.box) {
|
|
@@ -190,7 +193,7 @@ class OGC3DTile extends THREE.Object3D {
|
|
|
190
193
|
this.boundingVolume = properties.parentBoundingVolume;
|
|
191
194
|
}
|
|
192
195
|
|
|
193
|
-
|
|
196
|
+
|
|
194
197
|
|
|
195
198
|
if (!!this.json.content) { //if there is a content, json or otherwise, schedule it to be loaded
|
|
196
199
|
if (!!this.json.content.uri && this.json.content.uri.includes("json")) {
|
|
@@ -215,7 +218,7 @@ class OGC3DTile extends THREE.Object3D {
|
|
|
215
218
|
|
|
216
219
|
return absoluteURL || absolutePath;
|
|
217
220
|
}
|
|
218
|
-
|
|
221
|
+
|
|
219
222
|
load() {
|
|
220
223
|
var self = this;
|
|
221
224
|
if (self.deleted) return;
|
|
@@ -238,12 +241,12 @@ class OGC3DTile extends THREE.Object3D {
|
|
|
238
241
|
if (!!url) {
|
|
239
242
|
if (url.includes(".b3dm") || url.includes(".glb") || url.includes(".gltf")) {
|
|
240
243
|
self.contentURL = url;
|
|
241
|
-
|
|
244
|
+
|
|
242
245
|
self.tileLoader.get(self.abortController, this.uuid, url, mesh => {
|
|
243
246
|
if (!!self.deleted) return;
|
|
244
247
|
mesh.traverse((o) => {
|
|
245
248
|
if (o.isMesh) {
|
|
246
|
-
|
|
249
|
+
|
|
247
250
|
o.layers.disable(0);
|
|
248
251
|
if (self.occlusionCullingService) {
|
|
249
252
|
const position = o.geometry.attributes.position;
|
|
@@ -259,17 +262,19 @@ class OGC3DTile extends THREE.Object3D {
|
|
|
259
262
|
//o.material.visible = false;
|
|
260
263
|
}
|
|
261
264
|
});
|
|
262
|
-
|
|
265
|
+
//let s = Date.now();
|
|
266
|
+
//self.octree.fromGraphNode( mesh );
|
|
267
|
+
//console.log(Date.now()-s);
|
|
263
268
|
self.add(mesh);
|
|
264
269
|
self.updateWorldMatrix(false, true);
|
|
265
270
|
// mesh.layers.disable(0);
|
|
266
271
|
self.meshContent = mesh;
|
|
267
272
|
}, !self.cameraOnLoad ? () => 0 : () => {
|
|
268
273
|
return self.calculateDistanceToCamera(self.cameraOnLoad);
|
|
269
|
-
}, () => self.getSiblings(),
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
274
|
+
}, () => self.getSiblings(),
|
|
275
|
+
self.level,
|
|
276
|
+
!!self.json.boundingVolume.region,
|
|
277
|
+
self.geometricError
|
|
273
278
|
);
|
|
274
279
|
} else if (url.includes(".json")) {
|
|
275
280
|
self.tileLoader.get(self.abortController, this.uuid, url, json => {
|
|
@@ -549,7 +554,7 @@ class OGC3DTile extends THREE.Object3D {
|
|
|
549
554
|
return;
|
|
550
555
|
}
|
|
551
556
|
self.materialVisibility = visibility
|
|
552
|
-
|
|
557
|
+
|
|
553
558
|
self.meshDisplayed = true;
|
|
554
559
|
if (!!self.meshContent.traverse) {
|
|
555
560
|
self.meshContent.traverse(function (element) {
|
|
@@ -597,7 +602,7 @@ class OGC3DTile extends THREE.Object3D {
|
|
|
597
602
|
return 0;
|
|
598
603
|
}
|
|
599
604
|
const scale = this.matrixWorld.getMaxScaleOnAxis();
|
|
600
|
-
if(!!this.renderer){
|
|
605
|
+
if (!!this.renderer) {
|
|
601
606
|
this.renderer.getDrawingBufferSize(rendererSize);
|
|
602
607
|
}
|
|
603
608
|
let s = rendererSize.y;
|