@jdultra/threedtiles 7.0.2 → 8.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.babelrc ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "presets": [
3
+ "@babel/preset-env"
4
+ ],
5
+ "plugins": [
6
+ "@babel/plugin-syntax-dynamic-import"
7
+ ]
8
+ }
package/README.md CHANGED
@@ -14,7 +14,7 @@ The fastest 3DTiles viewer for three.js
14
14
 
15
15
  [Instanced Tileset (pilot a swarm of highly detailed spaceships)](https://www.jdultra.com/instanced/index.html)
16
16
 
17
- NPM dependency: "@jdultra/threedtiles": "^6.0.4"
17
+ NPM dependency: "@jdultra/threedtiles": "^8.0.0"
18
18
 
19
19
  Adding a tileset to a scene is as easy as :
20
20
 
@@ -68,6 +68,7 @@ Contact: emeric.beaufays@jdultra.com
68
68
  - Instanced tilesets
69
69
  - Center tileset and re-orient geolocated data
70
70
  - gltf/glb tiles (OGC3DTiles 1.1)
71
+ - draco and ktx2 compression support
71
72
  - point clouds (only through gltf/glb tiles)
72
73
 
73
74
  Support for OGC3DTiles 1.1 is underway. gltf/glb tiles are already supported but not yet implicit tiling.
@@ -90,7 +91,10 @@ const ogc3DTile = new OGC3DTile({
90
91
  A lower value will result in lower detail tiles being loaded and a higher value results in higher detail tiles being loaded.
91
92
  A value of 1.0 is the default.
92
93
 
93
-
94
+ #### geometricErrorMultiplier vs maxScreenSpaceError
95
+ Many viewers use the maxScreenSpaceError instead of a geometric error multiplier and there is a direct correspondance.
96
+ A geometricErrorMultiplier of 1 corresponds to a maxScreenSpaceError of 16.
97
+ A geometricErrorMultiplier of 0.5 corresponds to a maxScreenSpaceError of 32.
94
98
 
95
99
  ### load tiles outside of view
96
100
  By default, only the tiles that intersect the view frustum are loaded. When the camera moves, the scene will have to load the missing tiles and the user might see some holes in the model.
@@ -154,25 +158,34 @@ If using a shared cache between tilesets, check out the next section.
154
158
  You may instanciate a cache through the TileLoader class and re-use it for several or all your tilesets.
155
159
  The limitation is that all the tilesets using the same cache will have the same callback.
156
160
 
157
- The TileLoader constructor takes 2 arguments. The first is a callback for meshes (see above section) and the second is
158
- the maximum number of items in the cache (default is 1000).
161
+ The TileLoader takes an optional object as argument:
162
+ @param {Object} [options] - Optional configuration object.
163
+ @param {number} [options.maxCachedItems=100] - the cache size.
164
+ @param {function} [options.meshCallback] - A callback to call on newly decoded meshes.
165
+ @param {function} [options.pointsCallback] - A callback to call on newly decoded points.
166
+ @param {renderer} [options.renderer] - The renderer, this is required for KTX2 support.
159
167
 
160
168
  ```
161
169
  import { TileLoader } from "@jdultra/threedtiles/src/tileset/TileLoader";
162
170
 
163
- const ogc3DTile = new OGC3DTile({
164
- url: "https://storage.googleapis.com/ogc-3d-tiles/ayutthaya/tileset.json",
171
+ const tileLoader = new TileLoader({
165
172
  renderer: renderer,
166
- tileLoader: new TileLoader(2000, mesh => {
173
+ maxCachedItems: 100,
174
+ meshCallback: mesh => {
167
175
  //// Insert code to be called on every newly decoded mesh e.g.:
168
176
  mesh.material.wireframe = false;
169
177
  mesh.material.side = THREE.DoubleSide;
170
- },
171
- points=>{
172
- points.material.size = 0.1;
173
- points.material.sizeAttenuation = true;
174
- }
175
- ),
178
+ //mesh.material.metalness = 0.0
179
+ },
180
+ pointsCallback: points => {
181
+ points.material.size = Math.min(1.0, 0.5 * Math.sqrt(points.geometricError));
182
+ points.material.sizeAttenuation = true;
183
+ }
184
+ });
185
+ const ogc3DTile = new OGC3DTile({
186
+ url: "https://storage.googleapis.com/ogc-3d-tiles/ayutthaya/tileset.json",
187
+ renderer: renderer,
188
+ tileLoader: tileLoader,
176
189
  meshCallback: mesh => { mesh.material.wireframe = true;} // This callback will not be used as the callback provided to the TileLoader takes priority
177
190
  });
178
191
  ```
@@ -242,12 +255,19 @@ higher performance when displaying the same Tileset many times.
242
255
  // First create the InstancedTileLoader that will manage caching
243
256
  const instancedTileLoader = new InstancedTileLoader(
244
257
  scene,
245
- 100, // cache size as in the number of tiles cached in memory
246
- 1, // max number of tilesets from the same source
247
- mesh => {
248
- //// Insert code to be called on every newly decoded mesh e.g.:
249
- mesh.material.wireframe = false;
250
- mesh.material.side = THREE.DoubleSide;
258
+ {
259
+ renderer: renderer,
260
+ maxCachedItems : 100,
261
+ maxInstances : 1,
262
+ meshCallback: mesh => {
263
+ //// Insert code to be called on every newly decoded mesh e.g.:
264
+ mesh.material.wireframe = false;
265
+ mesh.material.side = THREE.DoubleSide;
266
+ },
267
+ pointsCallback: points => {
268
+ points.material.size = Math.min(1.0, 0.5 * Math.sqrt(points.geometricError));
269
+ points.material.sizeAttenuation = true;
270
+ }
251
271
  }
252
272
  );
253
273
 
@@ -321,7 +341,12 @@ scene.matrixWorldAutoUpdate = false;
321
341
  scene.updateMatrixWorld(true);
322
342
 
323
343
  ```
324
- #### tileset update loop
344
+ ### Draco and Ktx2
345
+ Compressed meshes via Draco and compressed textures in Ktx2 format are supported automatically using the threejs plugins.
346
+ KTX uses an external wasm loaded at runtime so if you have trouble packaging your app correctly, check out the
347
+ [Getting started](https://drive.google.com/file/d/1kJ-yfYmy8ShOMMPPXgqW2gMgGkLOIidf/view?usp=share_link) project for a sample webpack configuration.
348
+
349
+ ### tileset update loop
325
350
  Updating a single tileset via OGC3DTile#update or InstancedOGC3DTile#update is quite fast, even when the tree is deep.
326
351
  For a single tileset, it's safe to call it regularly with a setInterval:
327
352
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jdultra/threedtiles",
3
- "version": "7.0.2",
3
+ "version": "8.0.1",
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.20.12",
39
- "@babel/preset-env": "^7.20.2",
40
- "babel-loader": "^8.3.0",
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.76.2",
47
- "webpack-cli": "4.9.1",
48
- "webpack-dev-server": "^4.11.1",
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(1,0,0,0,
13
- 0,0,-1,0,
14
- 0,1,0,0,
15
- 0,0,0,1);
16
-
17
- //const legacyGLTFLoader = new LegacyGLTFLoader();
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
- function parseB3DM(arrayBuffer, meshCallback, geometricError, zUpToYUp) {
20
- const dataView = new DataView(arrayBuffer);
26
+ this.tempMatrix = new THREE.Matrix4();
27
+ }
21
28
 
22
- const magic =
23
- String.fromCharCode(dataView.getUint8(0)) +
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
- //const version = dataView.getUint32(4, true);
30
- //console.assert(version === 1);
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
- const byteLength = dataView.getUint32(8, true);
33
- console.assert(byteLength === arrayBuffer.byteLength);
39
+ const byteLength = dataView.getUint32(8, true);
40
+ console.assert(byteLength === arrayBuffer.byteLength);
34
41
 
35
- const featureTableJSONByteLength = dataView.getUint32(12, true);
36
- const featureTableBinaryByteLength = dataView.getUint32(16, true);
37
- const batchTableJSONByteLength = dataView.getUint32(20, true);
38
- const batchTableBinaryByteLength = dataView.getUint32(24, true);
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
- const featureTableStart = 28;
41
- const featureTable = new FeatureTable(arrayBuffer, featureTableStart, featureTableJSONByteLength, featureTableBinaryByteLength);
47
+ const featureTableStart = 28;
48
+ const featureTable = new FeatureTable(arrayBuffer, featureTableStart, featureTableJSONByteLength, featureTableBinaryByteLength);
42
49
 
43
- const batchTableStart = featureTableStart + featureTableJSONByteLength + featureTableBinaryByteLength;
44
- const batchTable = new BatchTable(arrayBuffer, featureTable.getData('BATCH_LENGTH'), batchTableStart, batchTableJSONByteLength, batchTableBinaryByteLength);
50
+ const batchTableStart = featureTableStart + featureTableJSONByteLength + featureTableBinaryByteLength;
51
+ const batchTable = new BatchTable(arrayBuffer, featureTable.getData('BATCH_LENGTH'), batchTableStart, batchTableJSONByteLength, batchTableBinaryByteLength);
45
52
 
46
- const glbStart = batchTableStart + batchTableJSONByteLength + batchTableBinaryByteLength;
47
- const glbBytes = new Uint8Array(arrayBuffer, glbStart, byteLength - glbStart);
53
+ const glbStart = batchTableStart + batchTableJSONByteLength + batchTableBinaryByteLength;
54
+ const glbBytes = new Uint8Array(arrayBuffer, glbStart, byteLength - glbStart);
48
55
 
49
56
 
50
- const gltfBuffer = glbBytes.slice().buffer;
57
+ const gltfBuffer = glbBytes.slice().buffer;
51
58
 
52
59
 
53
- return new Promise((resolve, reject) => {
60
+ return new Promise((resolve, reject) => {
54
61
 
55
- gltfLoader.parse(gltfBuffer, null, model => {
62
+ this.gltfLoader.parse(gltfBuffer, null, model => {
56
63
 
57
- ////TODO
64
+ ////TODO
58
65
 
59
- //model.batchTable = b3dm.batchTable;
60
- //model.featureTable = b3dm.featureTable;
66
+ //model.batchTable = b3dm.batchTable;
67
+ //model.featureTable = b3dm.featureTable;
61
68
 
62
- //model.scene.batchTable = b3dm.batchTable;
63
- //model.scene.featureTable = b3dm.featureTable;
69
+ //model.scene.batchTable = b3dm.batchTable;
70
+ //model.scene.featureTable = b3dm.featureTable;
64
71
 
65
- //const scene = mergeColoredObject(model.scene);
72
+ //const scene = mergeColoredObject(model.scene);
66
73
 
67
- //model.scene.applyMatrix4(ytozUpMatrix);
74
+ //model.scene.applyMatrix4(ytozUpMatrix);
68
75
 
69
- const rtcCenter = featureTable.getData('RTC_CENTER');
70
- if (rtcCenter) {
71
- tempMatrix.makeTranslation(rtcCenter[0], rtcCenter[1], rtcCenter[2])
72
- model.scene.applyMatrix4(tempMatrix);
73
- }else if(!!model.userData.gltfExtensions && !!model.userData.gltfExtensions.CESIUM_RTC){
74
- tempMatrix.makeTranslation(model.userData.gltfExtensions.CESIUM_RTC.center[0], model.userData.gltfExtensions.CESIUM_RTC.center[1], model.userData.gltfExtensions.CESIUM_RTC.center[2])
75
- model.scene.applyMatrix4(tempMatrix);
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
- const B3DMDecoder = {
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);
@@ -22,7 +25,44 @@ const domContainer = initDomContainer("screen");
22
25
  const camera = initCamera(domContainer.offsetWidth, domContainer.offsetHeight);
23
26
  const stats = initStats(domContainer);
24
27
  const renderer = initRenderer(camera, domContainer);
25
- const ogc3DTiles = initTileset(scene, 2.0);
28
+ const ogc3DTiles = initTileset(scene, 1.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(100, mesh => {
154
- //// Insert code to be called on every newly decoded mesh e.g.:
155
- mesh.material.wireframe = false;
156
- mesh.material.side = THREE.DoubleSide;
157
- //mesh.material.metalness = 0.0
158
- }, points => {
159
- points.material.size = Math.min(1.0, 0.5 * Math.sqrt(points.geometricError));
160
- points.material.sizeAttenuation = true;
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
- //url: "http://localhost:8080/tileset.json",
167
- geometricErrorMultiplier: 1,
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
- //ogc3DTile.rotateOnAxis(new THREE.Vector3(1, 0, 0), -Math.PI * 0.5) // Z-UP to Y-UP
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, 100, 1,
195
- mesh => {
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
- mesh.material.metalness = 0.0;
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: 0.1,
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
- //tileset.rotateOnAxis(new THREE.Vector3(1, 0, 0), Math.PI * -0.5) // Z-UP to Y-UP
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);