@jdultra/threedtiles 3.2.0 → 3.3.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 +59 -5
- package/index.html +1 -1
- package/package.json +1 -1
- package/src/index.js +42 -29
- package/src/tileset/OGC3DTile.js +113 -41
- package/src/tileset/OcclusionCullingService.js +79 -0
- package/src/tileset/TileLoader.js +146 -128
- package/src/draco/draco_decoder.js +0 -48
- package/src/draco/draco_decoder.wasm +0 -0
- package/src/draco/draco_encoder.js +0 -33
- package/src/draco/draco_wasm_wrapper.js +0 -104
|
@@ -1,151 +1,169 @@
|
|
|
1
1
|
import { LinkedHashMap } from 'js-utils-z';
|
|
2
2
|
import { B3DMDecoder } from "../decoder/B3DMDecoder";
|
|
3
3
|
import { setIntervalAsync } from 'set-interval-async/dynamic';
|
|
4
|
+
import { initial } from 'lodash';
|
|
5
|
+
import * as THREE from 'three';
|
|
4
6
|
|
|
5
|
-
const ready = [];
|
|
6
|
-
const downloads = [];
|
|
7
|
-
const nextReady = [];
|
|
8
|
-
const nextDownloads = [];
|
|
9
7
|
let concurentDownloads = 0;
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
class TileLoader {
|
|
10
|
+
constructor(meshCallback, maxCachedItems) {
|
|
11
|
+
this.meshCallback = meshCallback;
|
|
12
|
+
this.cache = new LinkedHashMap();
|
|
13
|
+
this.maxCachedItems = !!maxCachedItems ? maxCachedItems : 100;
|
|
14
|
+
this.register = {};
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
this.ready = [];
|
|
18
|
+
this.downloads = [];
|
|
19
|
+
this.nextReady = [];
|
|
20
|
+
this.nextDownloads = [];
|
|
21
|
+
this.init();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
init(){
|
|
25
|
+
|
|
26
|
+
const self = this;
|
|
27
|
+
setIntervalAsync(() => {
|
|
28
|
+
self.download();
|
|
29
|
+
/* const start = Date.now();
|
|
30
|
+
let uploaded = 0;
|
|
31
|
+
do{
|
|
32
|
+
uploaded = download();
|
|
33
|
+
}while(uploaded > 0 && (Date.now() - start)<= 2 ) */
|
|
34
|
+
|
|
35
|
+
}, 10);
|
|
36
|
+
setIntervalAsync(() => {
|
|
37
|
+
const start = Date.now();
|
|
38
|
+
let loaded = 0;
|
|
39
|
+
do {
|
|
40
|
+
loaded = self.loadBatch();
|
|
41
|
+
} while (loaded > 0 && (Date.now() - start) <= 0)
|
|
42
|
+
|
|
43
|
+
}, 10);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
scheduleDownload(f) {
|
|
47
|
+
this.downloads.unshift(f);
|
|
48
|
+
}
|
|
49
|
+
download() {
|
|
50
|
+
if (this.nextDownloads.length == 0) {
|
|
51
|
+
this.getNextDownloads();
|
|
52
|
+
if (this.nextDownloads.length == 0) return;
|
|
19
53
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
nextDownload.
|
|
54
|
+
while (this.nextDownloads.length > 0 && concurentDownloads < 500) {
|
|
55
|
+
const nextDownload = this.nextDownloads.shift();
|
|
56
|
+
if (!!nextDownload && nextDownload.shouldDoDownload()) {
|
|
57
|
+
nextDownload.doDownload();
|
|
58
|
+
}
|
|
23
59
|
}
|
|
24
|
-
}
|
|
25
60
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
ready.unshift([cache, register, key, distanceFunction, getSiblings, level, uuid]);
|
|
30
|
-
}
|
|
31
|
-
function loadBatch() {
|
|
32
|
-
if (nextReady.length == 0) {
|
|
33
|
-
getNextReady();
|
|
34
|
-
if (nextReady.length == 0) return 0;
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
return;
|
|
35
64
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const cache = data[0];
|
|
39
|
-
const register = data[1];
|
|
40
|
-
const key = data[2];
|
|
41
|
-
const mesh = cache.get(key);
|
|
42
|
-
if (!!mesh && !!register[key]) {
|
|
43
|
-
Object.keys(register[key]).forEach(tile => {
|
|
44
|
-
const callback = register[key][tile];
|
|
45
|
-
if (!!callback) {
|
|
46
|
-
callback(mesh);
|
|
47
|
-
register[key][tile] = null;
|
|
48
|
-
}
|
|
49
|
-
});
|
|
65
|
+
meshReceived(cache, register, key, distanceFunction, getSiblings, level, uuid) {
|
|
66
|
+
this.ready.unshift([cache, register, key, distanceFunction, getSiblings, level, uuid]);
|
|
50
67
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
let smallestLevel = Number.MAX_VALUE;
|
|
56
|
-
let smallestDistance = Number.MAX_VALUE;
|
|
57
|
-
let closest = -1;
|
|
58
|
-
for (let i = downloads.length - 1; i >= 0; i--) {
|
|
59
|
-
if (!downloads[i].shouldDoDownload()) {
|
|
60
|
-
downloads.splice(i, 1);
|
|
61
|
-
continue;
|
|
68
|
+
loadBatch() {
|
|
69
|
+
if (this.nextReady.length == 0) {
|
|
70
|
+
this.getNextReady();
|
|
71
|
+
if (this.nextReady.length == 0) return 0;
|
|
62
72
|
}
|
|
63
|
-
|
|
64
|
-
|
|
73
|
+
const data = this.nextReady.shift();
|
|
74
|
+
if (!data) return 0;
|
|
75
|
+
const cache = data[0];
|
|
76
|
+
const register = data[1];
|
|
77
|
+
const key = data[2];
|
|
78
|
+
const mesh = cache.get(key);
|
|
79
|
+
if(mesh instanceof THREE.InstancedMesh){
|
|
80
|
+
console.log("instanced");
|
|
81
|
+
}else{
|
|
82
|
+
console.log(" not instanced");
|
|
65
83
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
smallestLevel = downloads[i].level;
|
|
75
|
-
closest = i
|
|
84
|
+
if (!!mesh && !!register[key]) {
|
|
85
|
+
Object.keys(register[key]).forEach(tile => {
|
|
86
|
+
const callback = register[key][tile];
|
|
87
|
+
if (!!callback) {
|
|
88
|
+
callback(mesh);
|
|
89
|
+
register[key][tile] = null;
|
|
90
|
+
}
|
|
91
|
+
});
|
|
76
92
|
}
|
|
93
|
+
return 1;
|
|
77
94
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
95
|
+
|
|
96
|
+
getNextDownloads() {
|
|
97
|
+
let smallestLevel = Number.MAX_VALUE;
|
|
98
|
+
let smallestDistance = Number.MAX_VALUE;
|
|
99
|
+
let closest = -1;
|
|
100
|
+
for (let i = this.downloads.length - 1; i >= 0; i--) {
|
|
101
|
+
if (!this.downloads[i].shouldDoDownload()) {
|
|
102
|
+
this.downloads.splice(i, 1);
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (!this.downloads[i].distanceFunction) { // if no distance function, must be a json, give absolute priority!
|
|
106
|
+
this.nextDownloads.push(this.downloads.splice(i, 1)[0]);
|
|
85
107
|
}
|
|
86
108
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
nextReady.push(ready.splice(i,1)[0]);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
if(nextReady.length>0) return;
|
|
101
|
-
for (let i = ready.length - 1; i >= 0; i--) {
|
|
102
|
-
const dist = ready[i][3]();
|
|
103
|
-
if (dist < smallestDistance) {
|
|
104
|
-
smallestDistance = dist;
|
|
105
|
-
smallestLevel = ready[i][5]
|
|
106
|
-
closest = i
|
|
107
|
-
} else if (dist == smallestDistance && ready[i][5] < smallestLevel) {
|
|
108
|
-
smallestLevel = ready[i][5]
|
|
109
|
-
closest = i
|
|
109
|
+
if (this.nextDownloads.length > 0) return;
|
|
110
|
+
for (let i = this.downloads.length - 1; i >= 0; i--) {
|
|
111
|
+
const dist = this.downloads[i].distanceFunction();
|
|
112
|
+
if (dist < smallestDistance) {
|
|
113
|
+
smallestDistance = dist;
|
|
114
|
+
closest = i;
|
|
115
|
+
} else if (dist == smallestDistance && this.downloads[i].level < smallestLevel) {
|
|
116
|
+
smallestLevel = this.downloads[i].level;
|
|
117
|
+
closest = i
|
|
118
|
+
}
|
|
110
119
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
120
|
+
if (closest >= 0) {
|
|
121
|
+
const closestItem = this.downloads.splice(closest, 1).pop();
|
|
122
|
+
this.nextDownloads.push(closestItem);
|
|
123
|
+
const siblings = closestItem.getSiblings();
|
|
124
|
+
for (let i = this.downloads.length - 1; i >= 0; i--) {
|
|
125
|
+
if (siblings.includes(this.downloads[i].uuid)) {
|
|
126
|
+
this.nextDownloads.push(this.downloads.splice(i, 1).pop());
|
|
127
|
+
}
|
|
119
128
|
}
|
|
120
129
|
}
|
|
121
130
|
}
|
|
122
|
-
}
|
|
123
|
-
setIntervalAsync(()=>{
|
|
124
|
-
download();
|
|
125
|
-
/* const start = Date.now();
|
|
126
|
-
let uploaded = 0;
|
|
127
|
-
do{
|
|
128
|
-
uploaded = download();
|
|
129
|
-
}while(uploaded > 0 && (Date.now() - start)<= 2 ) */
|
|
130
131
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
loaded = loadBatch();
|
|
137
|
-
}while(loaded > 0 && (Date.now() - start)<= 0 )
|
|
132
|
+
getNextReady() {
|
|
133
|
+
let smallestLevel = Number.MAX_VALUE;
|
|
134
|
+
let smallestDistance = Number.MAX_VALUE;
|
|
135
|
+
let closest = -1;
|
|
136
|
+
for (let i = this.ready.length - 1; i >= 0; i--) {
|
|
138
137
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
this.
|
|
144
|
-
this.
|
|
145
|
-
|
|
146
|
-
|
|
138
|
+
if (!this.ready[i][3]) {// if no distance function, must be a json, give absolute priority!
|
|
139
|
+
this.nextReady.push(this.ready.splice(i, 1)[0]);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (this.nextReady.length > 0) return;
|
|
143
|
+
for (let i = this.ready.length - 1; i >= 0; i--) {
|
|
144
|
+
const dist = this.ready[i][3]();
|
|
145
|
+
if (dist < smallestDistance) {
|
|
146
|
+
smallestDistance = dist;
|
|
147
|
+
smallestLevel = this.ready[i][5]
|
|
148
|
+
closest = i
|
|
149
|
+
} else if (dist == smallestDistance && this.ready[i][5] < smallestLevel) {
|
|
150
|
+
smallestLevel = this.ready[i][5]
|
|
151
|
+
closest = i
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (closest >= 0) {
|
|
155
|
+
const closestItem = this.ready.splice(closest, 1).pop();
|
|
156
|
+
this.nextReady.push(closestItem);
|
|
157
|
+
const siblings = closestItem[4]();
|
|
158
|
+
for (let i = this.ready.length - 1; i >= 0; i--) {
|
|
159
|
+
if (siblings.includes(this.ready[i][6])) {
|
|
160
|
+
this.nextready.push(this.ready.splice(i, 1).pop());
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
147
164
|
}
|
|
148
165
|
|
|
166
|
+
|
|
149
167
|
get(tileIdentifier, path, callback, distanceFunction, getSiblings, level) {
|
|
150
168
|
const self = this;
|
|
151
169
|
const key = simplifyPath(path);
|
|
@@ -165,7 +183,7 @@ class TileLoader {
|
|
|
165
183
|
|
|
166
184
|
const cachedObject = self.cache.get(key);
|
|
167
185
|
if (!!cachedObject) {
|
|
168
|
-
meshReceived(self.cache, self.register, key, distanceFunction, getSiblings, level, tileIdentifier);
|
|
186
|
+
this.meshReceived(self.cache, self.register, key, distanceFunction, getSiblings, level, tileIdentifier);
|
|
169
187
|
} else if (Object.keys(self.register[key]).length == 1) {
|
|
170
188
|
let downloadFunction;
|
|
171
189
|
if (path.includes(".b3dm")) {
|
|
@@ -180,12 +198,12 @@ class TileLoader {
|
|
|
180
198
|
result.arrayBuffer().then(buffer => B3DMDecoder.parseB3DM(buffer, self.meshCallback)).then(mesh => {
|
|
181
199
|
self.cache.put(key, mesh);
|
|
182
200
|
self.checkSize();
|
|
183
|
-
meshReceived(self.cache, self.register, key, distanceFunction, getSiblings, level, tileIdentifier);
|
|
201
|
+
this.meshReceived(self.cache, self.register, key, distanceFunction, getSiblings, level, tileIdentifier);
|
|
184
202
|
});
|
|
185
203
|
|
|
186
204
|
});
|
|
187
205
|
}
|
|
188
|
-
}else if (path.includes(".json")) {
|
|
206
|
+
} else if (path.includes(".json")) {
|
|
189
207
|
downloadFunction = () => {
|
|
190
208
|
concurentDownloads++;
|
|
191
209
|
fetch(path).then(result => {
|
|
@@ -197,12 +215,12 @@ class TileLoader {
|
|
|
197
215
|
result.json().then(json => {
|
|
198
216
|
self.cache.put(key, json);
|
|
199
217
|
self.checkSize();
|
|
200
|
-
meshReceived(self.cache, self.register, key);
|
|
218
|
+
this.meshReceived(self.cache, self.register, key);
|
|
201
219
|
});
|
|
202
220
|
});
|
|
203
221
|
}
|
|
204
222
|
}
|
|
205
|
-
scheduleDownload({
|
|
223
|
+
this.scheduleDownload({
|
|
206
224
|
"shouldDoDownload": () => {
|
|
207
225
|
return !!self.register[key] && Object.keys(self.register[key]).length > 0;
|
|
208
226
|
},
|