Skip to content

Commit 4b7dd01

Browse files
committed
Improves performance of quadtree customdata
1 parent a158b2f commit 4b7dd01

File tree

2 files changed

+62
-44
lines changed

2 files changed

+62
-44
lines changed

packages/engine/Source/Scene/QuadtreePrimitive.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -550,13 +550,14 @@ function selectTilesForRendering(primitive, frameState) {
550550

551551
const customDataAdded = primitive._addHeightCallbacks;
552552
const customDataRemoved = primitive._removeHeightCallbacks;
553-
const frameNumber = frameState.frameNumber;
554553

555554
let len;
556555
if (customDataAdded.length > 0 || customDataRemoved.length > 0) {
557556
for (i = 0, len = levelZeroTiles.length; i < len; ++i) {
558557
tile = levelZeroTiles[i];
559-
tile._updateCustomData(frameNumber, customDataAdded, customDataRemoved);
558+
tile._addedCustomData = customDataAdded;
559+
tile._removedCustomData = customDataRemoved;
560+
tile._updateCustomData();
560561
}
561562

562563
customDataAdded.length = 0;
@@ -596,7 +597,7 @@ function selectTilesForRendering(primitive, frameState) {
596597
}
597598
}
598599

599-
primitive._lastSelectionFrameNumber = frameNumber;
600+
primitive._lastSelectionFrameNumber = frameState.frameNumber;
600601
}
601602

602603
function queueTileLoad(primitive, queue, tile, frameState) {
@@ -716,7 +717,7 @@ function visitTile(
716717
++debug.tilesVisited;
717718

718719
primitive._tileReplacementQueue.markTileRendered(tile);
719-
tile._updateCustomData(frameState.frameNumber);
720+
tile._updateCustomData();
720721

721722
if (tile.level > debug.maxDepthVisited) {
722723
debug.maxDepthVisited = tile.level;

packages/engine/Source/Scene/QuadtreeTile.js

Lines changed: 57 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import defined from "../Core/defined.js";
22
import DeveloperError from "../Core/DeveloperError.js";
33
import Rectangle from "../Core/Rectangle.js";
4+
import Cartographic from "../Core/Cartographic.js";
45
import QuadtreeTileLoadState from "./QuadtreeTileLoadState.js";
56
import TileSelectionResult from "./TileSelectionResult.js";
67

@@ -108,7 +109,8 @@ function QuadtreeTile(options) {
108109
this._loadPriority = 0.0;
109110

110111
this._customData = [];
111-
this._frameUpdated = undefined;
112+
this._addedCustomData = [];
113+
this._removedCustomData = [];
112114
this._lastSelectionResult = TileSelectionResult.NONE;
113115
this._lastSelectionResultFrame = undefined;
114116
this._loadedCallbacks = {};
@@ -311,52 +313,67 @@ QuadtreeTile.prototype.clearPositionCache = function () {
311313
}
312314
};
313315

314-
QuadtreeTile.prototype._updateCustomData = function (
315-
frameNumber,
316-
added,
317-
removed,
318-
) {
319-
let customData = this.customData;
320-
321-
let i;
322-
let data;
323-
let rectangle;
324-
325-
if (defined(added) && defined(removed)) {
326-
customData = customData.filter(function (value) {
327-
return removed.indexOf(value) === -1;
328-
});
329-
this._customData = customData;
330-
331-
rectangle = this._rectangle;
332-
for (i = 0; i < added.length; ++i) {
333-
data = added[i];
334-
if (Rectangle.contains(rectangle, data.positionCartographic)) {
335-
customData.push(data);
336-
}
316+
QuadtreeTile.prototype._updateCustomData = function () {
317+
const added = this._addedCustomData;
318+
const removed = this._removedCustomData;
319+
if (added.length === 0 && removed.length === 0) {
320+
return;
321+
}
322+
323+
const customData = this.customData;
324+
for (let i = 0; i < added.length; ++i) {
325+
const data = added[i];
326+
if (!Rectangle.contains(this._rectangle, data.positionCartographic)) {
327+
continue;
337328
}
338329

339-
this._frameUpdated = frameNumber;
340-
} else {
341-
// interior or leaf tile, update from parent
342-
const parent = this._parent;
343-
if (defined(parent) && this._frameUpdated !== parent._frameUpdated) {
344-
customData.length = 0;
345-
346-
rectangle = this._rectangle;
347-
const parentCustomData = parent.customData;
348-
for (i = 0; i < parentCustomData.length; ++i) {
349-
data = parentCustomData[i];
350-
if (Rectangle.contains(rectangle, data.positionCartographic)) {
351-
customData.push(data);
352-
}
353-
}
330+
customData.push(data);
331+
332+
const child = childTileAtPosition(this, data.positionCartographic);
333+
child._addedCustomData.push(data);
334+
}
335+
this._addedCustomData.length = 0;
354336

355-
this._frameUpdated = parent._frameUpdated;
337+
for (let i = 0; i < removed.length; ++i) {
338+
const data = removed[i];
339+
const index = customData.indexOf(data);
340+
if (index !== -1) {
341+
customData.splice(index, 1);
356342
}
343+
344+
const child = childTileAtPosition(this, data.positionCartographic);
345+
child._removedCustomData.push(data);
357346
}
347+
this._removedCustomData.length = 0;
358348
};
359349

350+
const centerScratch = new Cartographic();
351+
352+
/**
353+
* Determines which child tile that contains the specified position. Assumes the position is within
354+
* the bounds of the parent tile.
355+
* @private
356+
* @param {QuadtreeTile} tile - The parent tile.
357+
* @param {Cartographic} positionCartographic - The cartographic position.
358+
* @returns {QuadtreeTile} The child tile that contains the position.
359+
*/
360+
function childTileAtPosition(tile, positionCartographic) {
361+
const center = Rectangle.center(tile.rectangle, centerScratch);
362+
const x = positionCartographic.longitude >= center.longitude ? 1 : 0;
363+
const y = positionCartographic.latitude < center.latitude ? 1 : 0;
364+
365+
switch (y * 2 + x) {
366+
case 0:
367+
return tile.northwestChild;
368+
case 1:
369+
return tile.northeastChild;
370+
case 2:
371+
return tile.southwestChild;
372+
default:
373+
return tile.southeastChild;
374+
}
375+
}
376+
360377
Object.defineProperties(QuadtreeTile.prototype, {
361378
/**
362379
* Gets the tiling scheme used to tile the surface.

0 commit comments

Comments
 (0)