Skip to content

Commit 7ef054e

Browse files
committed
feat(pointcloud): use 'changeSource' mechanism to avoid useless work
Implements a simple logic to avoid updating the full layer if we already know that the result won't change. This feature is already implemented for tile based layers (see 3f340b9).
1 parent d6a74ed commit 7ef054e

3 files changed

Lines changed: 98 additions & 9 deletions

File tree

src/Process/PointCloudProcessing.js

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -163,18 +163,46 @@ function markForDeletion(elt) {
163163
}
164164

165165
export default {
166-
preUpdate(context, layer) {
167-
// TODO: use changeSource
168-
layer.counters = {
169-
pointCount: 0,
170-
displayedCount: 0,
171-
};
172-
166+
preUpdate(context, layer, changeSources) {
173167
// Bail-out if not ready
174168
if (!layer.root) {
175169
return [];
176170
}
177171

172+
if (changeSources.has(undefined) || changeSources.size == 0) {
173+
return [layer.root];
174+
}
175+
176+
// lookup lowest common ancestor of changeSources
177+
let commonAncestorName;
178+
for (const source of changeSources.values()) {
179+
if (source.isCamera) {
180+
// if the change is caused by a camera move, no need to bother
181+
// to find common ancestor: we need to update the whole tree:
182+
// some invisible tiles may now be visible
183+
return [layer.root];
184+
}
185+
if (source.obj != undefined && source.obj.isPoints) {
186+
if (!commonAncestorName) {
187+
commonAncestorName = source.name;
188+
} else {
189+
let i;
190+
for (i = 0; i < Math.min(source.name.length, commonAncestorName.length); i++) {
191+
if (source.name[i] != commonAncestorName[i]) {
192+
break;
193+
}
194+
}
195+
commonAncestorName = commonAncestorName.substr(0, i);
196+
if (commonAncestorName.length == 0) {
197+
break;
198+
}
199+
}
200+
}
201+
}
202+
if (commonAncestorName && commonAncestorName.length > 0) {
203+
return [layer.root.findChildrenByName(commonAncestorName)];
204+
}
205+
178206
// Start updating from hierarchy root
179207
return [layer.root];
180208
},
@@ -205,8 +233,6 @@ export default {
205233
}
206234
const count = Math.max(1.0, Math.floor(shouldBeLoaded * elt.obj.geometry.attributes.position.count));
207235
elt.obj.geometry.setDrawRange(0, count);
208-
layer.counters.pointCount += elt.obj.realPointCount;
209-
layer.counters.displayedCount += Math.floor(shouldBeLoaded * elt.obj.geometry.attributes.position.count);
210236
elt.obj.material.uniforms.size.value = layer.pointSize;
211237
} else if (!elt.promise) {
212238
// TODO:
@@ -261,6 +287,13 @@ export default {
261287
return;
262288
}
263289

290+
layer.counters = {
291+
displayedCount: 0,
292+
};
293+
for (const pts of layer.group.children) {
294+
layer.counters.displayedCount += pts.geometry.drawRange.count;
295+
}
296+
264297
if (layer.counters.displayedCount > layer.pointBudget) {
265298
const reduction = layer.pointBudget / layer.counters.displayedCount;
266299
for (const pts of layer.group.children) {

src/Provider/PointCloudProvider.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,19 @@ function parseOctree(layer, hierarchyStepSize, root) {
9494
});
9595
}
9696

97+
function findChildrenByName(node, name) {
98+
if (node.name === name) {
99+
return node;
100+
}
101+
const charIndex = node.name.length;
102+
for (let i = 0; i < node.children.length; i++) {
103+
if (node.children[i].name[charIndex] == name[charIndex]) {
104+
return findChildrenByName(node.children[i], name);
105+
}
106+
}
107+
throw new Error(`Cannot find node with name '${name}'`);
108+
}
109+
97110
let nextuuid = 1;
98111
function addPickingAttribute(points) {
99112
// generate unique id for picking
@@ -206,6 +219,8 @@ export default {
206219
// eslint-disable-next-line no-console
207220
console.log('LAYER metadata:', root);
208221
layer.root = root;
222+
root.findChildrenByName = findChildrenByName.bind(root, root);
223+
209224
return layer;
210225
});
211226
},
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import PointCloudProcessing from '../src/Process/PointCloudProcessing';
2+
/* global describe, it */
3+
4+
const assert = require('assert');
5+
6+
describe('preUpdate', function () {
7+
it('should return root if no change source', () => {
8+
const layer = { root: {} };
9+
const sources = new Set();
10+
assert.equal(
11+
layer.root,
12+
PointCloudProcessing.preUpdate(null, layer, sources)[0]);
13+
});
14+
15+
it('should return root if no common ancestors', () => {
16+
const layer = { root: {} };
17+
const elt1 = { name: '12' };
18+
const elt2 = { name: '345' };
19+
const sources = new Set();
20+
sources.add(elt1);
21+
sources.add(elt2);
22+
assert.equal(
23+
layer.root,
24+
PointCloudProcessing.preUpdate(null, layer, sources)[0]);
25+
});
26+
27+
it('should return common ancestor', () => {
28+
const layer = { root: {} };
29+
const elt1 = { name: '123', obj: { isPoints: true } };
30+
const elt2 = { name: '12567', obj: { isPoints: true } };
31+
const elt3 = { name: '122', obj: { isPoints: true } };
32+
const sources = new Set();
33+
sources.add(elt1);
34+
sources.add(elt2);
35+
sources.add(elt3);
36+
layer.root.findChildrenByName = (name) => {
37+
assert.equal('12', name);
38+
};
39+
PointCloudProcessing.preUpdate(null, layer, sources);
40+
});
41+
});

0 commit comments

Comments
 (0)