Skip to content

Commit

Permalink
refactor(THREE): Remove Three.js layers using.
Browse files Browse the repository at this point in the history
Replace the control GeometryLayer visibility, handled by Three.js layers, to GeometryLayer.object3D visibility.
  • Loading branch information
gchoqueux committed Jan 30, 2023
1 parent 05a0768 commit 971f175
Show file tree
Hide file tree
Showing 13 changed files with 59 additions and 128 deletions.
1 change: 0 additions & 1 deletion src/Converter/Feature2Mesh.js
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,6 @@ function featureToMesh(feature, options) {

if (options.layer) {
mesh.layer = options.layer;
mesh.layers.set(options.layer.threejsLayer);
}

return mesh;
Expand Down
4 changes: 0 additions & 4 deletions src/Converter/convertToTile.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,6 @@ export default {

const tile = new TileMesh(result.geometry, material, layer, extent, level);

// Commented because layer.threejsLayer is undefined;
// Fix me: conflict with object3d added in view.scene;
// tile.layers.set(layer.threejsLayer);

if (parent && parent.isTileMesh) {
// get parent extent transformation
const pTrans = builder.computeSharableExtent(parent.extent);
Expand Down
28 changes: 1 addition & 27 deletions src/Core/Picking.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,6 @@ import * as THREE from 'three';
import RenderMode from 'Renderer/RenderMode';
import { unpack1K } from 'Renderer/LayeredMaterial';

function hideEverythingElse(view, object, threejsLayer = 0) {
// We want to render only 'object' and its hierarchy.
// So if it uses threejsLayer defined -> force it on the camera
// (or use the default one: 0)
const prev = view.camera.camera3D.layers.mask;

view.camera.camera3D.layers.mask = 1 << threejsLayer;

return () => {
view.camera.camera3D.layers.mask = prev;
};
}

const depthRGBA = new THREE.Vector4();
// TileMesh picking support function
function screenCoordsToNodeId(view, tileLayer, viewCoords, radius = 0) {
Expand All @@ -24,8 +11,6 @@ function screenCoordsToNodeId(view, tileLayer, viewCoords, radius = 0) {

const restore = tileLayer.level0Nodes.map(n => RenderMode.push(n, RenderMode.MODES.ID));

const undoHide = hideEverythingElse(view, tileLayer.object3d, tileLayer.threejsLayer);

const buffer = view.mainLoop.gfxEngine.renderViewToBuffer(
{ camera: view.camera, scene: tileLayer.object3d },
{
Expand All @@ -35,8 +20,6 @@ function screenCoordsToNodeId(view, tileLayer, viewCoords, radius = 0) {
height: 1 + radius * 2,
});

undoHide();

restore.forEach(r => r());

const ids = [];
Expand Down Expand Up @@ -144,8 +127,6 @@ export default {
}
});

const undoHide = hideEverythingElse(view, layer.object3d, layer.threejsLayer);

// render 1 pixel
// TODO: support more than 1 pixel selection
const buffer = view.mainLoop.gfxEngine.renderViewToBuffer(
Expand All @@ -157,8 +138,6 @@ export default {
height: 1 + radius * 2,
});

undoHide();

const candidates = [];

traversePickingCircle(radius, (x, y) => {
Expand Down Expand Up @@ -203,12 +182,7 @@ export default {
/*
* Default picking method. Uses THREE.Raycaster
*/
pickObjectsAt(view, viewCoords, radius, object, target = [], threejsLayer) {
if (threejsLayer !== undefined) {
raycaster.layers.set(threejsLayer);
} else {
raycaster.layers.enableAll();
}
pickObjectsAt(view, viewCoords, radius, object, target = []) {
// Raycaster use NDC coordinate
view.viewToNormalizedCoords(viewCoords, normalized);
if (radius < 0) {
Expand Down
3 changes: 0 additions & 3 deletions src/Core/Prefab/Globe/Atmosphere.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,6 @@ class Atmosphere extends GeometryLayer {
const skyDome = new Sky();
skyDome.frustumCulled = false;

ground.layers.mask = this.object3d.layers.mask;
sky.layers.mask = this.object3d.layers.mask;
skyDome.layers.mask = this.object3d.layers.mask;
this.realisticAtmosphere.add(ground);
this.realisticAtmosphere.add(sky);
this.realisticAtmosphere.add(skyDome);
Expand Down
28 changes: 0 additions & 28 deletions src/Core/View.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,6 @@ export const VIEW_EVENTS = {
* @property {string} type dblclick-right
*/


const _syncGeometryLayerVisibility = function _syncGeometryLayerVisibility(layer, view) {
if (layer.object3d) {
layer.object3d.visible = layer.visible;
}

if (layer.threejsLayer) {
if (layer.visible) {
view.camera.camera3D.layers.enable(layer.threejsLayer);
} else {
view.camera.camera3D.layers.disable(layer.threejsLayer);
}
}
};

function _preprocessLayer(view, layer, parentLayer) {
const source = layer.source;
if (parentLayer && !layer.extent) {
Expand All @@ -65,13 +50,6 @@ function _preprocessLayer(view, layer, parentLayer) {
}

if (layer.isGeometryLayer) {
if (parentLayer) {
// layer.threejsLayer *must* be assigned before preprocessing,
// because TileProvider.preprocessDataLayer function uses it.
layer.threejsLayer = view.mainLoop.gfxEngine.getUniqueThreejsLayer();
}
layer.defineLayerProperty('visible', true, () => _syncGeometryLayerVisibility(layer, view));
_syncGeometryLayerVisibility(layer, view);
// Find crs projection layer, this is projection destination
layer.crs = view.referenceCrs;
} else if (!layer.crs) {
Expand Down Expand Up @@ -1001,10 +979,6 @@ class View extends THREE.EventDispatcher {
mouse.x = Math.floor(mouse.x);
mouse.y = Math.floor(mouse.y);

// Prepare state
const prev = camera.layers.mask;
camera.layers.mask = 1 << this.tileLayer.threejsLayer;

// Render/Read to buffer
let buffer;
if (viewPaused) {
Expand Down Expand Up @@ -1048,8 +1022,6 @@ class View extends THREE.EventDispatcher {
target.unproject(camera);
}

camera.layers.mask = prev;

if (target.length() > 10000000) { return undefined; }

return target;
Expand Down
23 changes: 21 additions & 2 deletions src/Layer/GeometryLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ class GeometryLayer extends Layer {
*/
constructor(id, object3d, config = {}) {
config.cacheLifeTime = config.cacheLifeTime ?? CACHE_POLICIES.GEOMETRY;

// Remove this part when Object.assign(this, config) will be removed from Layer Constructor
const visible = config.visible;
delete config.visible;

super(id, config);

this.isGeometryLayer = true;
Expand All @@ -79,7 +84,7 @@ class GeometryLayer extends Layer {
this.wireframe = false;

this.attachedLayers = [];
this.visible = config.visible == undefined ? true : config.visible;
this.visible = visible ?? true;
Object.defineProperty(this.zoom, 'max', {
value: Infinity,
writable: false,
Expand All @@ -90,6 +95,20 @@ class GeometryLayer extends Layer {
this.structure = '3d';
}

get visible() {
return this.object3d.visible;
}

set visible(value) {
if (this.object3d.visible !== value) {
const event = { type: 'visible-property-changed', previous: {}, new: {} };
event.previous.visible = this.object3d.visible;
event.new.visible = value;
this.dispatchEvent(event);
this.object3d.visible = value;
}
}

// Attached layers expect to receive the visual representation of a
// layer (= THREE object with a material). So if a layer's update
// function don't process this kind of object, the layer must provide a
Expand Down Expand Up @@ -182,7 +201,7 @@ class GeometryLayer extends Layer {
* specified coordinates.
*/
pickObjectsAt(view, coordinates, radius = this.options.defaultPickingRadius, target = []) {
return Picking.pickObjectsAt(view, coordinates, radius, this.object3d, target, this.threejsLayer);
return Picking.pickObjectsAt(view, coordinates, radius, this.object3d, target);
}
}

Expand Down
1 change: 0 additions & 1 deletion src/Layer/LabelLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,6 @@ class LabelLayer extends Layer {
layer: this,
extentsSource: extentsDestination,
view: context.view,
threejsLayer: this.threejsLayer,
requester: node,
};

Expand Down
1 change: 0 additions & 1 deletion src/Layer/OrientedImageLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ function updatePano(context, camera, layer) {
// put informations about image URL as extent to be used by generic DataSourceProvider, OrientedImageSource will use that.
extentsSource: imagesInfo,
view: context.view,
threejsLayer: layer.threejsLayer,
requester: newPano,
earlyDropFunction: commandCancellation,
};
Expand Down
1 change: 0 additions & 1 deletion src/Layer/PointCloudLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ function initBoundingBox(elt, layer) {
elt.obj.boxHelper.frustumCulled = false;
elt.obj.boxHelper.position.copy(elt.tightbbox.min).add(box3.max);
elt.obj.boxHelper.autoUpdateMatrix = false;
elt.obj.boxHelper.layers.mask = layer.bboxes.layers.mask;
layer.bboxes.add(elt.obj.boxHelper);
elt.obj.boxHelper.updateMatrix();
elt.obj.boxHelper.updateMatrixWorld();
Expand Down
1 change: 0 additions & 1 deletion src/Process/FeatureProcessing.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ export default {
layer,
extentsSource: extentsDestination,
view: context.view,
threejsLayer: layer.threejsLayer,
requester: node,
};

Expand Down
1 change: 0 additions & 1 deletion src/Provider/3dTilesProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ function executeCommand(command) {
const path = metadata.content && (metadata.content.url || metadata.content.uri);

const setLayer = (obj) => {
obj.layers.set(layer.threejsLayer);
obj.userData.metadata = metadata;
obj.layer = layer;
};
Expand Down
1 change: 0 additions & 1 deletion src/Provider/PointCloudProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ export default {
}
points.updateMatrix();
points.tightbbox = geometry.boundingBox.applyMatrix4(points.matrix);
points.layers.set(layer.threejsLayer);
points.layer = layer;
points.extent = Extent.fromBox3(command.view.referenceCrs, node.bbox);
points.userData.node = node;
Expand Down
94 changes: 37 additions & 57 deletions utils/debug/TileDebug.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as THREE from 'three';
import TWEEN from '@tweenjs/tween.js';
import View from 'Core/View';
import GeometryLayer from 'Layer/GeometryLayer';
import { MAIN_LOOP_EVENTS } from 'Core/MainLoop';
import ObjectRemovalHelper from 'Process/ObjectRemovalHelper';
Expand Down Expand Up @@ -117,101 +116,82 @@ export default function createTileDebugUI(datDebugTool, view, layer, debugInstan
const geometrySphere = new THREE.SphereGeometry(1, 16, 16);

function debugIdUpdate(context, layer, node) {
const enabled = context.camera.camera3D.layers.test({ mask: 1 << layer.threejsLayer });

if (!node.parent || !enabled) {
if (!node.parent || !layer.visible) {
ObjectRemovalHelper.removeChildrenAndCleanupRecursively(layer, node);
return;
}

let helper = node.children.filter(n => n.layer && (n.layer.id == layer.id))[0];

if (node.material && node.material.visible) {
// filtering helper attached to node with the current debug layer
let helper = node.link.filter(n => n.layer && (n.layer.id == layer.id))[0];
if (node.visible && node.material && node.material.visible) {
if (!helper) {
// add the ability to hide all the debug obj for one layer at once
const l = context.view.getLayerById(layer.id);
const l3js = l.threejsLayer;
helper = new THREE.Group();
helper.layer = layer;
node.matrixWorld.decompose(helper.position, helper.quaternion, helper.scale);

if (layer.id == obb_layer_id) {
helper = new OBBHelper(node.obb);
if (helper.children[0]) {
helper.children[0].layers.set(l3js);
}
const obbHelper = new OBBHelper(node.obb);
obbHelper.layer = layer;
helper.add(obbHelper);
} else if (layer.id == sb_layer_id) {
const color = new THREE.Color(Math.random(), Math.random(), Math.random());
const material = new THREE.MeshBasicMaterial({ color: color.getHex(), wireframe: true });
helper = new THREE.Mesh(geometrySphere, material);
helper.position.copy(node.boundingSphere.center);
helper.scale.multiplyScalar(node.boundingSphere.radius);
const sphereHelper = new THREE.Mesh(geometrySphere, material);
sphereHelper.position.copy(node.boundingSphere.center);
sphereHelper.scale.multiplyScalar(node.boundingSphere.radius);
sphereHelper.scale.set(1, 1, 1).multiplyScalar(node.boundingSphere.radius);
sphereHelper.layer = layer;
helper.add(sphereHelper);
}

helper.layers.set(l3js);
helper.layer = layer;
node.add(helper);
helper.updateMatrixWorld(true);

// if we don't do that, our OBBHelper will never get removed,
// because once a node is invisible, children are not removed
// any more
const hiddenHandler = node.material.addEventListener('hidden', () => {
node.material.removeEventListener(hiddenHandler);
let i = node.children.length;
while (i--) {
const c = node.children[i];
if (c.layer === sb_layer_id) {
if (c.dispose) {
c.dispose();
} else if (Array.isArray(c.material)) {
for (const material of c.material) {
material.dispose();
}
} else {
c.material.dispose();
}
node.children.splice(i, 1);
}
}
});
node.link.push(helper);
}

if (layer.id == sb_layer_id) {
helper.position.copy(node.boundingSphere.center);
helper.scale.set(1, 1, 1).multiplyScalar(node.boundingSphere.radius);
}
layer.object3d.add(helper);
helper.updateMatrixWorld(true);
helper.visible = true;
} else if (helper) {
helper.visible = false;
layer.object3d.remove(helper);
}
}

class DebugLayer extends GeometryLayer {
constructor(id, options = {}) {
options.update = debugIdUpdate;
super(id, options.object3d || new THREE.Group(), options);
this.isDebugLayer = true;
}

preUpdate(context, sources) {
if (sources.has(this.parent)) {
this.object3d.clear();
}
}
}

const obbLayer = new GeometryLayer(obb_layer_id, new THREE.Object3D(), {
update: debugIdUpdate,
const obbLayer = new DebugLayer(obb_layer_id, {
visible: false,
cacheLifeTime: Infinity,
source: false,
});

View.prototype.addLayer.call(view, obbLayer, layer).then((l) => {
view.addLayer(obbLayer).then((l) => {
gui.add(l, 'visible').name('Bounding boxes').onChange(() => {
view.notifyChange(l);
});
});

const sbLayer = new GeometryLayer(sb_layer_id, new THREE.Object3D(), {
update: debugIdUpdate,
const sbLayer = new DebugLayer(sb_layer_id, {
visible: false,
cacheLifeTime: Infinity,
source: false,
});

View.prototype.addLayer.call(view, sbLayer, layer).then((l) => {
view.addLayer(sbLayer).then((l) => {
gui.add(l, 'visible').name('Bounding Spheres').onChange(() => {
view.notifyChange(l);
});
});


const viewerDiv = document.getElementById('viewerDiv');
const circle = document.createElement('span');
circle.className = 'circleBase';
Expand Down

0 comments on commit 971f175

Please sign in to comment.