@jdultra/threedtiles 6.0.4 → 7.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/README.md CHANGED
@@ -6,12 +6,16 @@ The fastest 3DTiles viewer for three.js
6
6
 
7
7
  [Photogrametry (OBJ conversion)](https://ebeaufay.github.io/ThreedTilesViewer.github.io/)
8
8
 
9
+ [Point cloud vs Mesh](https://www.jdultra.com/pointmeshing/index.html)
10
+
9
11
  [PBR material (GlTF conversion)](https://www.jdultra.com/pbr/)
10
12
 
11
13
  [Occlusion culling (IFC conversion)](https://www.jdultra.com/occlusion/index.html)
12
14
 
13
15
  [Instanced Tileset (pilot a swarm of highly detailed spaceships)](https://www.jdultra.com/instanced/index.html)
14
16
 
17
+ NPM dependency: "@jdultra/threedtiles": "^6.0.4"
18
+
15
19
  Adding a tileset to a scene is as easy as :
16
20
 
17
21
  ```
@@ -44,6 +48,13 @@ Unzip and run :
44
48
 
45
49
  > npm run dev
46
50
 
51
+ ## Mesh to 3DTiles Converter
52
+
53
+ If you need to convert meshes to 3DTiles, from small assets to gigabytes of data, contact me for a trial on UltraMesh tool.
54
+ It works for all types of meshes: photogrametry, BIM, colored or textured meshes with a single texture atlas or many individual textures.
55
+ There's support for OBJ, IFC and glTF meshes and las/laz point clouds.
56
+ I aim for optimal quality in terms of mesh, texture and tileset structure for optimal streaming.
57
+ Contact: emeric.beaufays@jdultra.com
47
58
 
48
59
  ## Features
49
60
 
@@ -339,17 +350,3 @@ setInterval(() => {
339
350
  ```
340
351
 
341
352
  window#requestIdleCallback is also a good option but the rate of updates becomes slightly unpredictable.
342
-
343
- # Projects that use this library
344
- https://github.com/ebeaufay/UltraGlobe allows displaying a globe with multi resolution imagery, elevation and 3DTiles.
345
-
346
- If you have a project that stems from this code. I'd love to link to it here and I'm always open to implementing extra features.
347
- Contact: emeric.beaufays@jdultra.com
348
-
349
-
350
- # Mesh to 3DTiles Converter
351
-
352
- I also have code to convert meshes to 3DTiles with no limit to the size of the dataset relative to faces or textures.
353
- It works for all types of meshes: photogrametry, BIM, colored or textured meshes with a single texture atlas or many individual textures.
354
- The code is not open source but feel free to contact me for a trial.
355
- Contact: emeric.beaufays@jdultra.com
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jdultra/threedtiles",
3
- "version": "6.0.4",
3
+ "version": "7.0.0",
4
4
  "description": "An OGC 3DTiles viewer for Three.js",
5
5
  "main": "tileset.js",
6
6
  "scripts": {
@@ -26,8 +26,8 @@ function parseB3DM(arrayBuffer, meshCallback, geometricError, zUpToYUp) {
26
26
  String.fromCharCode(dataView.getUint8(3));
27
27
  console.assert(magic === 'b3dm');
28
28
 
29
- const version = dataView.getUint32(4, true);
30
- console.assert(version === 1);
29
+ //const version = dataView.getUint32(4, true);
30
+ //console.assert(version === 1);
31
31
 
32
32
  const byteLength = dataView.getUint32(8, true);
33
33
  console.assert(byteLength === arrayBuffer.byteLength);
@@ -70,6 +70,13 @@ function parseB3DM(arrayBuffer, meshCallback, geometricError, zUpToYUp) {
70
70
  if (rtcCenter) {
71
71
  tempMatrix.makeTranslation(rtcCenter[0], rtcCenter[1], rtcCenter[2])
72
72
  model.scene.applyMatrix4(tempMatrix);
73
+ }else if(!!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);
73
80
  }
74
81
 
75
82
  model.scene.traverse((o) => {
@@ -2,10 +2,10 @@ import { Matrix3, Sphere, Vector3 } from "three";
2
2
 
3
3
  class OBB {
4
4
  constructor(values) {
5
- this.center = new Vector3(values[0], values[2], -values[1]);
6
- var e1 = new Vector3(values[3], values[5], values[4]);
7
- var e2 = new Vector3(values[6], values[8], values[7]);
8
- var e3 = new Vector3(values[9], values[11], values[10]);
5
+ this.center = new Vector3(values[0], values[1], values[2]);
6
+ var e1 = new Vector3(values[3], values[4], values[4]);
7
+ var e2 = new Vector3(values[6], values[7], values[8]);
8
+ var e3 = new Vector3(values[9], values[10], values[11]);
9
9
 
10
10
  this.halfWidth = e1.length();
11
11
  this.halfHeight = e2.length();
package/src/index.js CHANGED
@@ -8,11 +8,10 @@ import { setIntervalAsync } from 'set-interval-async/dynamic';
8
8
  import { OcclusionCullingService } from "./tileset/OcclusionCullingService";
9
9
  import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer';
10
10
  import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
11
- import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass.js';
12
- import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
13
11
 
14
12
  import { InstancedOGC3DTile } from "./tileset/instanced/InstancedOGC3DTile.js"
15
13
  import { InstancedTileLoader } from "./tileset/instanced/InstancedTileLoader.js"
14
+ import { Sky } from 'three/addons/objects/Sky.js';
16
15
 
17
16
 
18
17
  const occlusionCullingService = new OcclusionCullingService();
@@ -23,7 +22,8 @@ const domContainer = initDomContainer("screen");
23
22
  const camera = initCamera(domContainer.offsetWidth, domContainer.offsetHeight);
24
23
  const stats = initStats(domContainer);
25
24
  const renderer = initRenderer(camera, domContainer);
26
- const ogc3DTiles = initTileset(scene, 1.0);
25
+ const ogc3DTiles = initTileset(scene, 2.0);
26
+
27
27
 
28
28
  //const instancedTileLoader = createInstancedTileLoader(scene);
29
29
  //initInstancedTilesets(instancedTileLoader);
@@ -34,7 +34,41 @@ const composer = initComposer(scene, camera, renderer);
34
34
 
35
35
  animate();
36
36
 
37
+ let sky, sun;
38
+ initSky();
39
+ function initSky() {
40
+ sky = new Sky();
41
+ sky.scale.setScalar(450000);
42
+ scene.add(sky);
43
+
44
+ sun = new THREE.Vector3();
45
+
46
+ const effectController = {
47
+ turbidity: 10,
48
+ rayleigh: 1,
49
+ mieCoefficient: 0.005,
50
+ mieDirectionalG: 0.3,
51
+ elevation: 5,
52
+ azimuth: 40,
53
+ exposure: renderer.toneMappingExposure
54
+ };
55
+
56
+ const uniforms = sky.material.uniforms;
57
+ uniforms['turbidity'].value = effectController.turbidity;
58
+ uniforms['rayleigh'].value = effectController.rayleigh;
59
+ uniforms['mieCoefficient'].value = effectController.mieCoefficient;
60
+ uniforms['mieDirectionalG'].value = effectController.mieDirectionalG;
61
+
62
+ const phi = THREE.MathUtils.degToRad(90 - effectController.elevation);
63
+ const theta = THREE.MathUtils.degToRad(effectController.azimuth);
64
+
65
+ sun.setFromSphericalCoords(1, phi, theta);
37
66
 
67
+ uniforms['sunPosition'].value.copy(sun);
68
+
69
+ renderer.toneMappingExposure = effectController.exposure;
70
+ renderer.render(scene, camera);
71
+ }
38
72
  function initComposer(scene, camera, renderer) {
39
73
  const renderScene = new RenderPass(scene, camera);
40
74
  //const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 0.4, 0.5, 0);
@@ -49,9 +83,14 @@ function initScene() {
49
83
  const scene = new THREE.Scene();
50
84
  scene.matrixAutoUpdate = false;
51
85
  //scene.matrixWorldAutoUpdate = false;
52
- scene.background = new THREE.Color(0x888888);
53
- scene.add(new THREE.AmbientLight(0xFFFFFF, 1.0));
54
-
86
+ scene.background = new THREE.Color(0xE5E3E4);
87
+ const dirLight = new THREE.DirectionalLight(0xFFFFFF, 1.0);
88
+ dirLight.position.set(100,100,100);
89
+ dirLight.lookAt(new THREE.Vector3(0,0,0));
90
+ //scene.add(new THREE.AmbientLight(0xFFFFFF, 1.0));
91
+
92
+ scene.add(dirLight)
93
+
55
94
  /* const light = new THREE.PointLight(0xbbbbff, 2, 5000);
56
95
  const sphere = new THREE.SphereGeometry(2, 16, 8);
57
96
  light.add(new THREE.Mesh(sphere, new THREE.MeshBasicMaterial({ color: 0xbbbbff })));
@@ -111,14 +150,7 @@ function initStats(dom) {
111
150
  }
112
151
 
113
152
 
114
- function initCamera(width, height) {
115
- const camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 1000);
116
- camera.position.set(-0.5,-0.7,10);
117
- camera.lookAt(0,0,0);
118
153
 
119
- camera.matrixAutoUpdate = true;
120
- return camera;
121
- }
122
154
 
123
155
  function initTileset(scene, gem) {
124
156
 
@@ -126,32 +158,32 @@ function initTileset(scene, gem) {
126
158
  //// Insert code to be called on every newly decoded mesh e.g.:
127
159
  mesh.material.wireframe = false;
128
160
  mesh.material.side = THREE.DoubleSide;
129
- mesh.material.metalness = 0.0
130
- }, points=>{
131
- points.material.size = Math.min(1.0,0.5*Math.sqrt(points.geometricError));
161
+ //mesh.material.metalness = 0.0
162
+ }, points => {
163
+ points.material.size = Math.min(1.0, 0.5 * Math.sqrt(points.geometricError));
132
164
  points.material.sizeAttenuation = true;
133
165
  });
134
166
 
135
167
  const ogc3DTile = new OGC3DTile({
136
- url: "https://storage.googleapis.com/ogc-3d-tiles/baltimore/tileset.json",
137
- //url: "http://localhost:8080/tileset.json",
138
168
  //url: "https://storage.googleapis.com/ogc-3d-tiles/berlinTileset/tileset.json",
169
+ //url: "https://storage.googleapis.com/ogc-3d-tiles/ayutthaya/tiledWithSkirts/tileset.json",
170
+ url: "http://localhost:8080/tileset.json",
139
171
  geometricErrorMultiplier: 1,
140
- loadOutsideView: false,
172
+ loadOutsideView: true,
141
173
  tileLoader: tileLoader,
142
174
  //occlusionCullingService: occlusionCullingService,
143
175
  static: false,
144
- centerModel:true,
145
- renderer: renderer,
146
-
176
+ centerModel: true,
177
+ renderer: renderer
178
+
147
179
  });
148
180
  setIntervalAsync(function () {
149
181
  ogc3DTile.update(camera);
150
182
  }, 10);
151
183
 
152
-
184
+ //ogc3DTile.scale.set(0.1,0.1,0.1)
153
185
 
154
- //ogc3DTile.rotateOnAxis(new THREE.Vector3(1, 0, 0), Math.PI * -0.5) // Z-UP to Y-UP
186
+ //ogc3DTile.rotateOnAxis(new THREE.Vector3(1, 0, 0), -Math.PI * 0.5) // Z-UP to Y-UP
155
187
  //ogc3DTile.translateOnAxis(new THREE.Vector3(0, 0, 1), 1)
156
188
  /*
157
189
  ogc3DTile.translateOnAxis(new THREE.Vector3(0, 0, 1), 10) // Z-UP to Y-UP
@@ -181,13 +213,13 @@ function initInstancedTilesets(instancedTileLoader) {
181
213
 
182
214
 
183
215
  const tileset = new InstancedOGC3DTile({
184
- url: "https://storage.googleapis.com/ogc-3d-tiles/berlinTileset/tileset.json",
185
- //url: "http://localhost:8080/tileset.json",
216
+ //url: "https://storage.googleapis.com/ogc-3d-tiles/berlinTileset/tileset.json",
217
+ url: "http://localhost:8080/tileset.json",
186
218
  geometricErrorMultiplier: 0.1,
187
219
  loadOutsideView: true,
188
220
  tileLoader: instancedTileLoader,
189
221
  static: false,
190
- centerModel:true,
222
+ centerModel: true,
191
223
  renderer: renderer
192
224
  });
193
225
  //tileset.rotateOnAxis(new THREE.Vector3(1, 0, 0), Math.PI * -0.5) // Z-UP to Y-UP
@@ -227,15 +259,23 @@ function initLODMultiplierSlider(instancedTilesets) {
227
259
  }
228
260
  }
229
261
 
262
+ function initCamera(width, height) {
263
+ const camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 20000);
264
+ camera.position.set(50, 50, 50);
265
+ camera.lookAt(0, 0, 0);
266
+
267
+ camera.matrixAutoUpdate = true;
268
+ return camera;
269
+ }
230
270
  function initController(camera, dom) {
231
271
  const controller = new OrbitControls(camera, dom);
232
272
 
233
273
  //controller.target.set(4629210.73133627, 435359.7901640832, 4351492.357788198);
234
- controller.target.set(0,0,0);
274
+ controller.target.set(0, 0, 0);
235
275
 
236
276
 
237
277
  controller.minDistance = 0.1;
238
- controller.maxDistance = 1000;
278
+ controller.maxDistance = 10000;
239
279
  controller.update();
240
280
  return controller;
241
281
  }
@@ -90,7 +90,7 @@ class OGC3DTile extends THREE.Object3D {
90
90
  this.level = properties.level ? properties.level : 0;
91
91
  this.hasMeshContent = false; // true when the provided json has a content field pointing to a B3DM file
92
92
  this.hasUnloadedJSONContent = false; // true when the provided json has a content field pointing to a JSON file that is not yet loaded
93
-
93
+ this.centerModel = properties.centerModel;
94
94
  this.abortController = new AbortController();
95
95
  this.layers.disable(0);
96
96
 
@@ -106,7 +106,7 @@ class OGC3DTile extends THREE.Object3D {
106
106
  result.json().then(json => {
107
107
  self.setup({ rootPath: path.dirname(properties.url), json: json });
108
108
  if (properties.onLoadCallback) properties.onLoadCallback(self);
109
- if (!!properties.centerModel) {
109
+ if (!!self.centerModel) {
110
110
  const tempSphere = new THREE.Sphere();
111
111
  if (self.boundingVolume instanceof OBB) {
112
112
  // box
@@ -162,12 +162,14 @@ class OGC3DTile extends THREE.Object3D {
162
162
  } else {
163
163
  this.geometricError = properties.parentGeometricError;
164
164
  }
165
+
165
166
  // decode transform
166
- if (!!this.json.transform) {
167
+ if (!!this.json.transform && !this.centerModel) {
167
168
  let mat = new THREE.Matrix4();
168
169
  mat.elements = this.json.transform;
169
170
  this.applyMatrix4(mat);
170
171
  }
172
+
171
173
  // decode volume
172
174
  if (!!this.json.boundingVolume) {
173
175
  if (!!this.json.boundingVolume.box) {
@@ -180,7 +182,7 @@ class OGC3DTile extends THREE.Object3D {
180
182
  this.boundingVolume = new THREE.Sphere(new THREE.Vector3(tempVec1.x, tempVec1.y, tempVec1.z), tempVec1.distanceTo(tempVec2));
181
183
  } else if (!!this.json.boundingVolume.sphere) {
182
184
  const sphere = this.json.boundingVolume.sphere;
183
- this.boundingVolume = new THREE.Sphere(new THREE.Vector3(sphere[0], sphere[2], -sphere[1]), sphere[3]);
185
+ this.boundingVolume = new THREE.Sphere(new THREE.Vector3(sphere[0], sphere[1], sphere[2]), sphere[3]);
184
186
  } else {
185
187
  this.boundingVolume = properties.parentBoundingVolume;
186
188
  }
@@ -188,6 +190,8 @@ class OGC3DTile extends THREE.Object3D {
188
190
  this.boundingVolume = properties.parentBoundingVolume;
189
191
  }
190
192
 
193
+
194
+
191
195
  if (!!this.json.content) { //if there is a content, json or otherwise, schedule it to be loaded
192
196
  if (!!this.json.content.uri && this.json.content.uri.includes("json")) {
193
197
  this.hasUnloadedJSONContent = true;
@@ -222,9 +226,7 @@ class OGC3DTile extends THREE.Object3D {
222
226
  if (!!url) {
223
227
  if (url.includes(".b3dm") || url.includes(".glb") || url.includes(".gltf")) {
224
228
  self.contentURL = url;
225
- if(!!self.json.boundingVolume.region){
226
- //self.applyMatrix4(zUpToYUp);
227
- }
229
+
228
230
  self.tileLoader.get(self.abortController, this.uuid, url, mesh => {
229
231
  if (!!self.deleted) return;
230
232
  mesh.traverse((o) => {
@@ -423,7 +425,8 @@ class OGC3DTile extends THREE.Object3D {
423
425
  cameraOnLoad: camera,
424
426
  occlusionCullingService: self.occlusionCullingService,
425
427
  renderer: self.renderer,
426
- static: self.static
428
+ static: self.static,
429
+ centerModel: false
427
430
  });
428
431
  self.childrenTiles.push(childTile);
429
432
  self.add(childTile);
@@ -535,7 +538,7 @@ class OGC3DTile extends THREE.Object3D {
535
538
  }
536
539
  self.materialVisibility = visibility
537
540
 
538
- self.meshDisplayed = false;
541
+ self.meshDisplayed = true;
539
542
  if (!!self.meshContent.traverse) {
540
543
  self.meshContent.traverse(function (element) {
541
544
  if (element.material) setMeshVisibility(element, visibility);
@@ -65,6 +65,7 @@ class InstancedTile extends THREE.Object3D {
65
65
  this.level = properties.level ? properties.level : 0;
66
66
  this.hasMeshContent = false; // true when the provided json has a content field pointing to a B3DM file
67
67
  this.hasUnloadedJSONContent = false; // true when the provided json has a content field pointing to a JSON file that is not yet loaded
68
+ this.centerModel = properties.centerModel;
68
69
 
69
70
  this.deleted = false;
70
71
  this.abortController = new AbortController();
@@ -82,7 +83,7 @@ class InstancedTile extends THREE.Object3D {
82
83
  //json = JSON.parse(JSON.stringify(json))
83
84
  const p = path.dirname(url);
84
85
  self.setup({ rootPath: p, json: json });
85
- if (!!properties.centerModel) {
86
+ if (!!self.centerModel) {
86
87
  const tempSphere = new THREE.Sphere();
87
88
  if (self.boundingVolume instanceof OBB) {
88
89
  // box
@@ -155,7 +156,7 @@ class InstancedTile extends THREE.Object3D {
155
156
  this.geometricError = properties.parentGeometricError;
156
157
  }
157
158
  // decode transform
158
- if (!!this.json.transform) {
159
+ if (!!this.json.transform && !this.centerModel) {
159
160
  let mat = new THREE.Matrix4();
160
161
  mat.elements = this.json.transform;
161
162
  this.master.applyMatrix4(mat);
@@ -374,7 +375,8 @@ class InstancedTile extends THREE.Object3D {
374
375
  level: self.level + 1,
375
376
  tileLoader: self.tileLoader,
376
377
  cameraOnLoad: camera,
377
- master: self.master
378
+ master: self.master,
379
+ centerModel: false
378
380
  });
379
381
  self.childrenTiles.push(childTile);
380
382
  //self.add(childTile);