@jdultra/threedtiles 3.2.0 → 3.2.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 +10 -1
- package/package.json +1 -1
- package/src/index.js +16 -17
- package/src/tileset/OGC3DTile.js +5 -26
- package/src/tileset/TileLoader.js +23 -21
package/README.md
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
3DTiles viewer for three.js
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Photogrametry : https://ebeaufay.github.io/ThreedTilesViewer.github.io/
|
|
6
|
+
|
|
7
|
+
IFC : https://storage.googleapis.com/jdultra.com/ifc/index.html
|
|
8
|
+
|
|
9
|
+
Occlusion culling : https://storage.googleapis.com/jdultra.com/occlusionCulling/index.html
|
|
6
10
|
|
|
7
11
|
Adding a tileset to a scene is as easy as :
|
|
8
12
|
|
|
@@ -114,6 +118,11 @@ ogc3DTile.rotateOnAxis(new THREE.Vector3(1,0,0), -Math.PI*0.5);
|
|
|
114
118
|
...
|
|
115
119
|
```
|
|
116
120
|
|
|
121
|
+
### Occlusion culling
|
|
122
|
+
Occlusion culling is curently only available as a demo.
|
|
123
|
+
The reason is that it requires a specific render pass hence the setup is a little more complex.
|
|
124
|
+
I can expose this feature upon request.
|
|
125
|
+
|
|
117
126
|
# Displaying meshes on a globe
|
|
118
127
|
I'm working on this project in parallel https://github.com/ebeaufay/UltraGlobe which allows displaying a globe with multi resolution imagery, elevation and 3DTiles.
|
|
119
128
|
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -22,8 +22,10 @@ animate();
|
|
|
22
22
|
function initScene() {
|
|
23
23
|
const scene = new THREE.Scene();
|
|
24
24
|
scene.background = new THREE.Color(0xaaffcc);
|
|
25
|
-
scene.add(new THREE.AmbientLight(0xFFFFFF, 0.
|
|
26
|
-
const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.
|
|
25
|
+
scene.add(new THREE.AmbientLight(0xFFFFFF, 0.2));
|
|
26
|
+
const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.8 );
|
|
27
|
+
directionalLight.position.set(100,100,100)
|
|
28
|
+
directionalLight.lookAt(-1,-1,-1)
|
|
27
29
|
scene.add( directionalLight );
|
|
28
30
|
return scene;
|
|
29
31
|
}
|
|
@@ -71,8 +73,8 @@ function initStats(dom) {
|
|
|
71
73
|
|
|
72
74
|
|
|
73
75
|
function initCamera() {
|
|
74
|
-
const camera = new THREE.PerspectiveCamera(70, window.offsetWidth / window.offsetHeight, 1,
|
|
75
|
-
camera.position.set(
|
|
76
|
+
const camera = new THREE.PerspectiveCamera(70, window.offsetWidth / window.offsetHeight, 0.1, 1000);
|
|
77
|
+
camera.position.set(-10, 5, 20);
|
|
76
78
|
|
|
77
79
|
return camera;
|
|
78
80
|
}
|
|
@@ -80,29 +82,26 @@ function initCamera() {
|
|
|
80
82
|
function initTileset(scene) {
|
|
81
83
|
|
|
82
84
|
const ogc3DTile = new OGC3DTile({
|
|
83
|
-
url: "https://storage.googleapis.com/ogc-3d-tiles/
|
|
85
|
+
url: "https://storage.googleapis.com/ogc-3d-tiles/house3/tileset.json",
|
|
84
86
|
//url: "http://localhost:8080/tileset.json",
|
|
85
|
-
geometricErrorMultiplier: 1
|
|
86
|
-
loadOutsideView:
|
|
87
|
+
geometricErrorMultiplier: 1,
|
|
88
|
+
loadOutsideView: false,
|
|
87
89
|
tileLoader: new TileLoader(mesh => {
|
|
88
90
|
//// Insert code to be called on every newly decoded mesh e.g.:
|
|
89
|
-
|
|
91
|
+
mesh.material.wireframe = false;
|
|
90
92
|
//mesh.material = new THREE.MeshBasicMaterial({color:new THREE.Color("rgb("+Math.floor(Math.random()*256)+", "+Math.floor(Math.random()*256)+", "+Math.floor(Math.random()*256)+")")})
|
|
91
93
|
mesh.material.side = THREE.DoubleSide;
|
|
92
|
-
}, 1000)
|
|
93
|
-
onLoadCallback: tileset => {
|
|
94
|
-
console.log(tileset.json)
|
|
95
|
-
}
|
|
94
|
+
}, 1000)
|
|
96
95
|
});
|
|
97
96
|
|
|
98
97
|
|
|
99
98
|
|
|
100
99
|
//// The OGC3DTile object is a threejs Object3D so you may do all the usual opperations like transformations e.g.:
|
|
101
|
-
//ogc3DTile.translateOnAxis(new THREE.Vector3(
|
|
102
|
-
//ogc3DTile.translateOnAxis(new THREE.Vector3(1,0
|
|
103
|
-
//ogc3DTile.translateOnAxis(new THREE.Vector3(0,0,1),
|
|
104
|
-
ogc3DTile.scale.set(
|
|
105
|
-
|
|
100
|
+
// ogc3DTile.translateOnAxis(new THREE.Vector3(1,0,0), -2177749.59059337)
|
|
101
|
+
// ogc3DTile.translateOnAxis(new THREE.Vector3(0,1,0), 4388730.67973434)
|
|
102
|
+
// ogc3DTile.translateOnAxis(new THREE.Vector3(0,0,1), 4070064.60934734)
|
|
103
|
+
//ogc3DTile.scale.set(0.001,0.001,0.001);
|
|
104
|
+
ogc3DTile.rotateOnAxis(new THREE.Vector3(1, 0, 0), Math.PI * -0.5) // Z-UP to Y-UP
|
|
106
105
|
// ogc3DTile.translateOnAxis(new THREE.Vector3(1,0,0), -16.5)
|
|
107
106
|
// ogc3DTile.translateOnAxis(new THREE.Vector3(0,1,0), 0)
|
|
108
107
|
// ogc3DTile.translateOnAxis(new THREE.Vector3(0,0,1), -9.5)
|
package/src/tileset/OGC3DTile.js
CHANGED
|
@@ -2,9 +2,7 @@ import * as THREE from 'three';
|
|
|
2
2
|
import { OBB } from "../geometry/obb";
|
|
3
3
|
import { TileLoader } from "./TileLoader";
|
|
4
4
|
import { v4 as uuidv4 } from "uuid";
|
|
5
|
-
import
|
|
6
|
-
// import { clearIntervalAsync } from 'set-interval-async';
|
|
7
|
-
const path = require('path');
|
|
5
|
+
import * as path from "path-browserify"
|
|
8
6
|
|
|
9
7
|
const tempSphere = new THREE.Sphere(new THREE.Vector3(0, 0, 0, 1));
|
|
10
8
|
|
|
@@ -185,24 +183,6 @@ class OGC3DTile extends THREE.Object3D {
|
|
|
185
183
|
self.hasUnloadedJSONContent = false;
|
|
186
184
|
});
|
|
187
185
|
|
|
188
|
-
/* self.controller = new AbortController();
|
|
189
|
-
setTimeout(() => {
|
|
190
|
-
fetch(url, { signal: self.controller.signal }).then(result => {
|
|
191
|
-
if (!result.ok) {
|
|
192
|
-
throw new Error(`couldn't load "${properties.url}". Request failed with status ${result.status} : ${result.statusText}`);
|
|
193
|
-
}
|
|
194
|
-
result.json().then(json => {
|
|
195
|
-
// when json content is downloaded, it is inserted into this tile's original JSON as a child
|
|
196
|
-
// and the content object is deleted from the original JSON
|
|
197
|
-
if (!self.json.children) self.json.children = [];
|
|
198
|
-
json.rootPath = path.dirname(url);
|
|
199
|
-
self.json.children.push(json);
|
|
200
|
-
delete self.json.content;
|
|
201
|
-
self.hasUnloadedJSONContent = false;
|
|
202
|
-
}).catch(error => { });
|
|
203
|
-
}).catch(error => { });
|
|
204
|
-
}, 0); */
|
|
205
|
-
|
|
206
186
|
}
|
|
207
187
|
|
|
208
188
|
}
|
|
@@ -321,10 +301,9 @@ class OGC3DTile extends THREE.Object3D {
|
|
|
321
301
|
return;
|
|
322
302
|
}
|
|
323
303
|
if (metric >= self.geometricError) {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
}
|
|
304
|
+
self.disposeChildren();
|
|
305
|
+
updateNodeVisibility();
|
|
306
|
+
return;
|
|
328
307
|
}
|
|
329
308
|
|
|
330
309
|
}
|
|
@@ -458,7 +437,7 @@ class OGC3DTile extends THREE.Object3D {
|
|
|
458
437
|
return 0;
|
|
459
438
|
}
|
|
460
439
|
const scale = this.matrixWorld.getMaxScaleOnAxis();
|
|
461
|
-
return ((distance / 100) / this.geometricErrorMultiplier)
|
|
440
|
+
return ((distance / 100) / this.geometricErrorMultiplier) * scale;
|
|
462
441
|
} else if (this.boundingVolume instanceof THREE.Box3) {
|
|
463
442
|
// Region
|
|
464
443
|
// Region not supported
|
|
@@ -12,17 +12,19 @@ function scheduleDownload(f) {
|
|
|
12
12
|
downloads.unshift(f);
|
|
13
13
|
}
|
|
14
14
|
function download() {
|
|
15
|
-
if(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
if (nextDownloads.length == 0) {
|
|
16
|
+
getNextDownloads();
|
|
17
|
+
if (nextDownloads.length == 0) return;
|
|
18
|
+
}
|
|
19
|
+
while (nextDownloads.length > 0 && concurentDownloads < 500) {
|
|
20
20
|
const nextDownload = nextDownloads.shift();
|
|
21
21
|
if (!!nextDownload && nextDownload.shouldDoDownload()) {
|
|
22
22
|
nextDownload.doDownload();
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
26
28
|
return;
|
|
27
29
|
}
|
|
28
30
|
function meshReceived(cache, register, key, distanceFunction, getSiblings, level, uuid) {
|
|
@@ -60,11 +62,11 @@ function getNextDownloads() {
|
|
|
60
62
|
downloads.splice(i, 1);
|
|
61
63
|
continue;
|
|
62
64
|
}
|
|
63
|
-
if(!downloads[i].distanceFunction){ // if no distance function, must be a json, give absolute priority!
|
|
65
|
+
if (!downloads[i].distanceFunction) { // if no distance function, must be a json, give absolute priority!
|
|
64
66
|
nextDownloads.push(downloads.splice(i, 1)[0]);
|
|
65
67
|
}
|
|
66
68
|
}
|
|
67
|
-
if(nextDownloads.length>0) return;
|
|
69
|
+
if (nextDownloads.length > 0) return;
|
|
68
70
|
for (let i = downloads.length - 1; i >= 0; i--) {
|
|
69
71
|
const dist = downloads[i].distanceFunction();
|
|
70
72
|
if (dist < smallestDistance) {
|
|
@@ -92,12 +94,12 @@ function getNextReady() {
|
|
|
92
94
|
let smallestDistance = Number.MAX_VALUE;
|
|
93
95
|
let closest = -1;
|
|
94
96
|
for (let i = ready.length - 1; i >= 0; i--) {
|
|
95
|
-
|
|
96
|
-
if(!ready[i][3]){// if no distance function, must be a json, give absolute priority!
|
|
97
|
-
nextReady.push(ready.splice(i,1)[0]);
|
|
97
|
+
|
|
98
|
+
if (!ready[i][3]) {// if no distance function, must be a json, give absolute priority!
|
|
99
|
+
nextReady.push(ready.splice(i, 1)[0]);
|
|
98
100
|
}
|
|
99
101
|
}
|
|
100
|
-
if(nextReady.length>0) return;
|
|
102
|
+
if (nextReady.length > 0) return;
|
|
101
103
|
for (let i = ready.length - 1; i >= 0; i--) {
|
|
102
104
|
const dist = ready[i][3]();
|
|
103
105
|
if (dist < smallestDistance) {
|
|
@@ -120,23 +122,23 @@ function getNextReady() {
|
|
|
120
122
|
}
|
|
121
123
|
}
|
|
122
124
|
}
|
|
123
|
-
setIntervalAsync(()=>{
|
|
125
|
+
setIntervalAsync(() => {
|
|
124
126
|
download();
|
|
125
127
|
/* const start = Date.now();
|
|
126
128
|
let uploaded = 0;
|
|
127
129
|
do{
|
|
128
130
|
uploaded = download();
|
|
129
131
|
}while(uploaded > 0 && (Date.now() - start)<= 2 ) */
|
|
130
|
-
|
|
131
|
-
},10);
|
|
132
|
-
setIntervalAsync(()=>{
|
|
132
|
+
|
|
133
|
+
}, 10);
|
|
134
|
+
setIntervalAsync(() => {
|
|
133
135
|
const start = Date.now();
|
|
134
136
|
let loaded = 0;
|
|
135
|
-
do{
|
|
137
|
+
do {
|
|
136
138
|
loaded = loadBatch();
|
|
137
|
-
}while(loaded > 0 && (Date.now() - start)<=
|
|
138
|
-
|
|
139
|
-
},10);
|
|
139
|
+
} while (loaded > 0 && (Date.now() - start) <= 1)
|
|
140
|
+
|
|
141
|
+
}, 10);
|
|
140
142
|
|
|
141
143
|
class TileLoader {
|
|
142
144
|
constructor(meshCallback, maxCachedItems) {
|
|
@@ -185,7 +187,7 @@ class TileLoader {
|
|
|
185
187
|
|
|
186
188
|
});
|
|
187
189
|
}
|
|
188
|
-
}else if (path.includes(".json")) {
|
|
190
|
+
} else if (path.includes(".json")) {
|
|
189
191
|
downloadFunction = () => {
|
|
190
192
|
concurentDownloads++;
|
|
191
193
|
fetch(path).then(result => {
|