diff --git a/src/Process/3dTilesProcessing.js b/src/Process/3dTilesProcessing.js index 771bc72c47..a8ca6f57f3 100644 --- a/src/Process/3dTilesProcessing.js +++ b/src/Process/3dTilesProcessing.js @@ -15,6 +15,11 @@ function requestNewTile(view, scheduler, geometryLayer, metadata, parent, redraw return scheduler.execute(command); } +function getChildTiles(tile) { + // only keep children that have the same layer and a valid tileId + return tile.children.filter(n => n.layer == tile.layer && n.tileId); +} + function subdivideNode(context, layer, node, cullingTest) { if (node.additiveRefinement) { // Additive refinement can only fetch visible children. @@ -58,7 +63,7 @@ function _subdivideNodeAdditive(context, layer, node, cullingTest) { } function _subdivideNodeSubstractive(context, layer, node) { - if (!node.pendingSubdivision && node.children.filter(n => n.layer == layer).length == 0) { + if (!node.pendingSubdivision && getChildTiles(node).length == 0) { const childrenTiles = layer.tileIndex.index[node.tileId].children; if (childrenTiles === undefined || childrenTiles.length === 0) { return; @@ -165,7 +170,7 @@ function cleanup3dTileset(layer, n, depth = 0) { n.parent.remove(n); } } else { - const tiles = n.children.filter(n => n.tileId != undefined); + const tiles = getChildTiles(n); n.remove(...tiles); } } @@ -294,11 +299,11 @@ export function process3dTilesNode(cullingTest, subdivisionTest) { subdivideNode(context, layer, node, cullingTest); // display iff children aren't ready setDisplayed(node, node.pendingSubdivision || node.additiveRefinement); - returnValue = node.children.filter(n => n.layer == layer); + returnValue = getChildTiles(node); } else { setDisplayed(node, true); - for (const n of node.children.filter(n => n.layer == layer)) { + for (const n of getChildTiles(node)) { n.visible = false; markForDeletion(layer, n); } @@ -306,7 +311,7 @@ export function process3dTilesNode(cullingTest, subdivisionTest) { // toggle wireframe if (node.content && node.content.visible) { node.content.traverse((o) => { - if (o.userData.layer == layer && o.material) { + if (o.layer == layer && o.material) { o.material.wireframe = layer.wireframe; } }); @@ -315,8 +320,6 @@ export function process3dTilesNode(cullingTest, subdivisionTest) { } markForDeletion(layer, node); - - return undefined; }; } diff --git a/src/Provider/3dTilesProvider.js b/src/Provider/3dTilesProvider.js index 841d6346f3..69818b88c2 100644 --- a/src/Provider/3dTilesProvider.js +++ b/src/Provider/3dTilesProvider.js @@ -8,7 +8,7 @@ import { init3dTilesLayer } from '../Process/3dTilesProcessing'; import utf8Decoder from '../utils/Utf8Decoder'; function $3dTilesIndex(tileset, baseURL) { - let counter = 0; + let counter = 1; this.index = {}; const inverseTileTransform = new THREE.Matrix4(); const recurse = function recurse_f(node, baseURL, parent) { @@ -59,31 +59,33 @@ function $3dTilesIndex(tileset, baseURL) { }; } +export function getObjectToUpdateForAttachedLayers(meta) { + if (meta.content) { + const result = []; + meta.content.traverse((obj) => { + if (obj.isObject3D && obj.material && obj.layer == meta.layer) { + result.push(obj); + } + }); + const p = meta.parent; + if (p && p.content) { + return { + elements: result, + parent: p.content, + }; + } else { + return { + elements: result, + }; + } + } +} + function preprocessDataLayer(layer, view, scheduler) { layer.sseThreshold = layer.sseThreshold || 16; layer.cleanupDelay = layer.cleanupDelay || 1000; // override the default method, since updated objects are metadata in this case - layer.getObjectToUpdateForAttachedLayers = (meta) => { - if (meta.content) { - const result = []; - meta.content.traverse((obj) => { - if (obj.isObject3D && obj.material && obj.userData.layer == layer) { - result.push(obj); - } - }); - const p = meta.parent; - if (p && p.content) { - return { - elements: result, - parent: p.content, - }; - } else { - return { - elements: result, - }; - } - } - }; + layer.getObjectToUpdateForAttachedLayers = getObjectToUpdateForAttachedLayers; layer._cleanableTiles = []; return Fetcher.json(layer.url, layer.networkOptions).then((tileset) => { @@ -189,7 +191,7 @@ function executeCommand(command) { const setLayer = (obj) => { obj.layers.set(layer.threejsLayer); obj.userData.metadata = metadata; - obj.userData.layer = layer; + obj.layer = layer; }; if (path) { // Check if we have relative or absolute url (with tileset's lopocs for example) diff --git a/src/Provider/PointCloudProvider.js b/src/Provider/PointCloudProvider.js index 0a3275bb3a..e7ceae0d21 100644 --- a/src/Provider/PointCloudProvider.js +++ b/src/Provider/PointCloudProvider.js @@ -142,6 +142,22 @@ function addPickingAttribute(points) { return points; } +export function getObjectToUpdateForAttachedLayers(meta) { + if (meta.obj) { + const p = meta.parent; + if (p && p.obj) { + return { + element: meta.obj, + parent: p.obj, + }; + } else { + return { + element: meta.obj, + }; + } + } +} + export default { preprocessDataLayer(layer) { if (!layer.file) { @@ -176,21 +192,7 @@ export default { layer.postUpdate = PointCloudProcessing.postUpdate; // override the default method, since updated objects are metadata in this case - layer.getObjectToUpdateForAttachedLayers = (meta) => { - if (meta.obj) { - const p = meta.parent; - if (p && p.obj) { - return { - element: meta.obj, - parent: p.obj, - }; - } else { - return { - element: meta.obj, - }; - } - } - }; + layer.getObjectToUpdateForAttachedLayers = getObjectToUpdateForAttachedLayers; // this probably needs to be moved to somewhere else layer.pickObjectsAt = (view, mouse, radius) => Picking.pickPointsAt(view, mouse, radius, layer); diff --git a/test/3dtilesprovider_unit_test.js b/test/3dtilesprovider_unit_test.js new file mode 100644 index 0000000000..24045a29e6 --- /dev/null +++ b/test/3dtilesprovider_unit_test.js @@ -0,0 +1,24 @@ +/* global describe, it */ +import assert from 'assert'; +import { Group, Mesh } from 'three'; +import { getObjectToUpdateForAttachedLayers } from '../src/Provider/3dTilesProvider'; + +describe('getObjectToUpdateForAttachedLayers', function () { + it('should correctly return all children', function () { + const layer = { }; + const tile = { + content: new Group(), + layer, + }; + + for (let i = 0; i < 3; i++) { + const mesh = new Mesh(); + mesh.layer = layer; + tile.content.add(mesh); + } + + const result = getObjectToUpdateForAttachedLayers(tile); + assert.ok(Array.isArray(result.elements)); + assert.ok(result.elements.length, 3); + }); +}); diff --git a/test/pointcloudprovider_unit_test.js b/test/pointcloudprovider_unit_test.js new file mode 100644 index 0000000000..2888e3fb9a --- /dev/null +++ b/test/pointcloudprovider_unit_test.js @@ -0,0 +1,23 @@ +/* global describe, it */ +import assert from 'assert'; +import { getObjectToUpdateForAttachedLayers } from '../src/Provider/PointCloudProvider'; + +describe('getObjectToUpdateForAttachedLayers', function () { + it('should correctly no-parent for the root', function () { + const meta = { + obj: 'a', + }; + assert.equal(getObjectToUpdateForAttachedLayers(meta).element, 'a'); + }); + it('should correctly return the element and its parent', function () { + const meta = { + obj: 'a', + parent: { + obj: 'b', + }, + }; + const result = getObjectToUpdateForAttachedLayers(meta); + assert.equal(result.element, 'a'); + assert.equal(result.parent, 'b'); + }); +}); diff --git a/utils/debug/3dTilesDebug.js b/utils/debug/3dTilesDebug.js index 7f4eefe8ce..b6999ecc00 100644 --- a/utils/debug/3dTilesDebug.js +++ b/utils/debug/3dTilesDebug.js @@ -54,7 +54,7 @@ export default function create3dTilesDebugUI(datDebugTool, view, _3dTileslayer) } if (helper) { - helper.userData.layer = layer; + helper.layer = layer; // add the ability to hide all the debug obj for one layer at once const l3js = layer.threejsLayer; helper.layers.set(l3js); diff --git a/utils/debug/PointCloudDebug.js b/utils/debug/PointCloudDebug.js index 5f48574830..ededca3378 100644 --- a/utils/debug/PointCloudDebug.js +++ b/utils/debug/PointCloudDebug.js @@ -51,11 +51,11 @@ export default { for (const pts of layer.group.children) { pts.material.visible = false; for (const name of stickies) { - if (pts.owner.name == name) { + if (pts.userData.metadata.name == name) { pts.material.visible = true; - } else if (!isInHierarchy(pts.owner, name)) { + } else if (!isInHierarchy(pts.userData.metadata, name)) { continue; - } else if (pts.owner.name.length < name.length) { + } else if (pts.userData.metadata.name.length < name.length) { pts.material.visible = layer.dbgDisplayParents; break; } else {