@jdultra/threedtiles 6.0.4 → 7.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/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.1",
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 && !!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,10 +22,7 @@ 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);
27
-
28
- //const instancedTileLoader = createInstancedTileLoader(scene);
29
- //initInstancedTilesets(instancedTileLoader);
25
+ const ogc3DTiles = initTileset(scene, 2.0);
30
26
 
31
27
  const controller = initController(camera, domContainer);
32
28
 
@@ -34,7 +30,41 @@ const composer = initComposer(scene, camera, renderer);
34
30
 
35
31
  animate();
36
32
 
33
+ let sky, sun;
34
+ initSky();
35
+ function initSky() {
36
+ sky = new Sky();
37
+ sky.scale.setScalar(450000);
38
+ scene.add(sky);
39
+
40
+ sun = new THREE.Vector3();
41
+
42
+ const effectController = {
43
+ turbidity: 10,
44
+ rayleigh: 1,
45
+ mieCoefficient: 0.005,
46
+ mieDirectionalG: 0.3,
47
+ elevation: 5,
48
+ azimuth: 40,
49
+ exposure: renderer.toneMappingExposure
50
+ };
51
+
52
+ const uniforms = sky.material.uniforms;
53
+ uniforms['turbidity'].value = effectController.turbidity;
54
+ uniforms['rayleigh'].value = effectController.rayleigh;
55
+ uniforms['mieCoefficient'].value = effectController.mieCoefficient;
56
+ uniforms['mieDirectionalG'].value = effectController.mieDirectionalG;
57
+
58
+ const phi = THREE.MathUtils.degToRad(90 - effectController.elevation);
59
+ const theta = THREE.MathUtils.degToRad(effectController.azimuth);
60
+
61
+ sun.setFromSphericalCoords(1, phi, theta);
37
62
 
63
+ uniforms['sunPosition'].value.copy(sun);
64
+
65
+ renderer.toneMappingExposure = effectController.exposure;
66
+ renderer.render(scene, camera);
67
+ }
38
68
  function initComposer(scene, camera, renderer) {
39
69
  const renderScene = new RenderPass(scene, camera);
40
70
  //const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 0.4, 0.5, 0);
@@ -49,9 +79,14 @@ function initScene() {
49
79
  const scene = new THREE.Scene();
50
80
  scene.matrixAutoUpdate = false;
51
81
  //scene.matrixWorldAutoUpdate = false;
52
- scene.background = new THREE.Color(0x888888);
53
- scene.add(new THREE.AmbientLight(0xFFFFFF, 1.0));
54
-
82
+ scene.background = new THREE.Color(0xE5E3E4);
83
+ const dirLight = new THREE.DirectionalLight(0xFFFFFF, 1.0);
84
+ dirLight.position.set(100,100,100);
85
+ dirLight.lookAt(new THREE.Vector3(0,0,0));
86
+ //scene.add(new THREE.AmbientLight(0xFFFFFF, 1.0));
87
+
88
+ scene.add(dirLight)
89
+
55
90
  /* const light = new THREE.PointLight(0xbbbbff, 2, 5000);
56
91
  const sphere = new THREE.SphereGeometry(2, 16, 8);
57
92
  light.add(new THREE.Mesh(sphere, new THREE.MeshBasicMaterial({ color: 0xbbbbff })));
@@ -111,14 +146,7 @@ function initStats(dom) {
111
146
  }
112
147
 
113
148
 
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
149
 
119
- camera.matrixAutoUpdate = true;
120
- return camera;
121
- }
122
150
 
123
151
  function initTileset(scene, gem) {
124
152
 
@@ -126,32 +154,32 @@ function initTileset(scene, gem) {
126
154
  //// Insert code to be called on every newly decoded mesh e.g.:
127
155
  mesh.material.wireframe = false;
128
156
  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));
157
+ //mesh.material.metalness = 0.0
158
+ }, points => {
159
+ points.material.size = Math.min(1.0, 0.5 * Math.sqrt(points.geometricError));
132
160
  points.material.sizeAttenuation = true;
133
161
  });
134
162
 
135
163
  const ogc3DTile = new OGC3DTile({
136
- url: "https://storage.googleapis.com/ogc-3d-tiles/baltimore/tileset.json",
137
- //url: "http://localhost:8080/tileset.json",
138
164
  //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",
139
167
  geometricErrorMultiplier: 1,
140
- loadOutsideView: false,
168
+ loadOutsideView: true,
141
169
  tileLoader: tileLoader,
142
170
  //occlusionCullingService: occlusionCullingService,
143
171
  static: false,
144
- centerModel:true,
145
- renderer: renderer,
146
-
172
+ centerModel: true,
173
+ renderer: renderer
174
+
147
175
  });
148
176
  setIntervalAsync(function () {
149
177
  ogc3DTile.update(camera);
150
178
  }, 10);
151
179
 
152
-
180
+ //ogc3DTile.scale.set(0.1,0.1,0.1)
153
181
 
154
- //ogc3DTile.rotateOnAxis(new THREE.Vector3(1, 0, 0), Math.PI * -0.5) // Z-UP to Y-UP
182
+ //ogc3DTile.rotateOnAxis(new THREE.Vector3(1, 0, 0), -Math.PI * 0.5) // Z-UP to Y-UP
155
183
  //ogc3DTile.translateOnAxis(new THREE.Vector3(0, 0, 1), 1)
156
184
  /*
157
185
  ogc3DTile.translateOnAxis(new THREE.Vector3(0, 0, 1), 10) // Z-UP to Y-UP
@@ -181,13 +209,13 @@ function initInstancedTilesets(instancedTileLoader) {
181
209
 
182
210
 
183
211
  const tileset = new InstancedOGC3DTile({
184
- url: "https://storage.googleapis.com/ogc-3d-tiles/berlinTileset/tileset.json",
185
- //url: "http://localhost:8080/tileset.json",
212
+ //url: "https://storage.googleapis.com/ogc-3d-tiles/berlinTileset/tileset.json",
213
+ url: "http://localhost:8080/tileset.json",
186
214
  geometricErrorMultiplier: 0.1,
187
215
  loadOutsideView: true,
188
216
  tileLoader: instancedTileLoader,
189
217
  static: false,
190
- centerModel:true,
218
+ centerModel: true,
191
219
  renderer: renderer
192
220
  });
193
221
  //tileset.rotateOnAxis(new THREE.Vector3(1, 0, 0), Math.PI * -0.5) // Z-UP to Y-UP
@@ -227,15 +255,23 @@ function initLODMultiplierSlider(instancedTilesets) {
227
255
  }
228
256
  }
229
257
 
258
+ function initCamera(width, height) {
259
+ const camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 20000);
260
+ camera.position.set(50, 50, 50);
261
+ camera.lookAt(0, 0, 0);
262
+
263
+ camera.matrixAutoUpdate = true;
264
+ return camera;
265
+ }
230
266
  function initController(camera, dom) {
231
267
  const controller = new OrbitControls(camera, dom);
232
268
 
233
269
  //controller.target.set(4629210.73133627, 435359.7901640832, 4351492.357788198);
234
- controller.target.set(0,0,0);
270
+ controller.target.set(0, 0, 0);
235
271
 
236
272
 
237
273
  controller.minDistance = 0.1;
238
- controller.maxDistance = 1000;
274
+ controller.maxDistance = 10000;
239
275
  controller.update();
240
276
  return controller;
241
277
  }
@@ -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);