From ec578bfe68a02b7ce7d59d020fba9e8cf29e595f Mon Sep 17 00:00:00 2001 From: alan-wu Date: Fri, 21 Jun 2024 11:03:01 +1200 Subject: [PATCH] Fix points picking. --- src/controls.js | 23 ++++++++++++++++++++++- src/primitives/pointset.js | 13 +++++++++++++ src/scene.js | 11 ++++++++++- src/sceneLoader.js | 1 + src/three/Points.js | 3 ++- 5 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/controls.js b/src/controls.js index bc7d23f..4dd30bc 100644 --- a/src/controls.js +++ b/src/controls.js @@ -70,6 +70,7 @@ const CameraControls = function ( object, domElement, renderer, scene ) { this.touchZoomDistanceEnd = 0; this.directionalLight = 0; this.scrollRate = 50; + this.pixelHeight = 1; let duration = 6000; let enabled = true; let inbuildTime = 0; @@ -224,6 +225,25 @@ const CameraControls = function ( object, domElement, renderer, scene ) { viewports[defaultViewport]); } + this.getVisibleHeightAtZDepth = ( depth ) => { + // compensate for cameras not positioned at z=0 + const cameraOffset = this.cameraObject.position.z; + if ( depth < cameraOffset ) depth -= cameraOffset; + else depth += cameraOffset; + + // vertical fov in radians + const vFOV = this.cameraObject.fov * Math.PI / 180; + + // Math.abs to ensure the result is always positive + return 2 * Math.tan( vFOV / 2 ) * Math.abs( depth ); + }; + + this.calculateHeightPerPixelAtZeroDepth = ( wHeight ) => { + const height = this.getVisibleHeightAtZDepth(0); + this.pixelHeight = height / wHeight; + return this.pixelHeight; + } + /** * Get normalised coordinates from windows coordinates. * @@ -987,6 +1007,7 @@ const CameraControls = function ( object, domElement, renderer, scene ) { } else { this.cameraObject.lookAt( this.cameraObject.target ); } + return updated; }; @@ -1476,7 +1497,7 @@ const RayCaster = function (sceneIn, hostSceneIn, callbackFunctionIn, hoverCallb const enabled = true; const raycaster = new THREE.Raycaster(); raycaster.params.Line.threshold = 0.1; - raycaster.params.Points.threshold = 0.1; + raycaster.params.Points.threshold = 1; const mouse = new THREE.Vector2(); let awaiting = false; let lastHoveredDate = new Date(); diff --git a/src/primitives/pointset.js b/src/primitives/pointset.js index 08ab66c..5f8d533 100644 --- a/src/primitives/pointset.js +++ b/src/primitives/pointset.js @@ -85,6 +85,19 @@ const Pointset = function () { this.morph.material.needsUpdate = true; } } + + /** + * Turn size attenuation on/off based on the flag. + * + * @param {Boolean} flag - Determin either size attenuation + * should be on or off. + */ + this.render = (delta, playAnimation, cameraControls, options) => { + if (this.morph) { + this.morph.sizePerPixel = cameraControls.pixelHeight; + } + Pointset.prototype.render.call(this, delta, playAnimation, cameraControls, options); + } } Pointset.prototype = Object.create((require('./zincObject').ZincObject).prototype); diff --git a/src/scene.js b/src/scene.js index 13d9be6..43508df 100644 --- a/src/scene.js +++ b/src/scene.js @@ -111,10 +111,12 @@ exports.Scene = function (containerIn, rendererIn) { //called from Renderer when panel has been resized this.onWindowResize = () => { - this.camera.aspect = getDrawingWidth() / getDrawingHeight(); + const wHeight = getDrawingHeight(); + this.camera.aspect = getDrawingWidth() / wHeight; this.camera.updateProjectionMatrix(); this.minimapScissor.updateRequired = true; zincCameraControls.onResize(); + zincCameraControls.calculateHeightPerPixelAtZeroDepth(wHeight); } /** @@ -196,6 +198,7 @@ exports.Scene = function (containerIn, rendererIn) { if (boundingBox) { const viewport = zincCameraControls.getViewportFromBoundingBox(boundingBox, 1.0); zincCameraControls.setCurrentCameraSettings(viewport); + zincCameraControls.calculateHeightPerPixelAtZeroDepth(getDrawingHeight()); markerCluster.markerUpdateRequired = true; } } @@ -594,6 +597,9 @@ exports.Scene = function (containerIn, rendererIn) { if (0 == sceneLoader.toBeDownloaded) { zincCameraControls.setTime(currentTime); options.ndcToBeUpdated = zincCameraControls.update(0); + if (options.ndcToBeUpdated) { + zincCameraControls.calculateHeightPerPixelAtZeroDepth(getDrawingHeight()); + } rootRegion.setMorphTime(currentTime, true); rootRegion.renderGeometries(0, 0, playAnimation, zincCameraControls, options, true); } else { @@ -606,6 +612,9 @@ exports.Scene = function (containerIn, rendererIn) { } else { if (0 == sceneLoader.toBeDownloaded) { options.ndcToBeUpdated = zincCameraControls.update(delta); + if (options.ndcToBeUpdated) { + zincCameraControls.calculateHeightPerPixelAtZeroDepth(getDrawingHeight()); + } rootRegion.renderGeometries(playRate, delta, playAnimation, zincCameraControls, options, true); } else { zincCameraControls.update(0); diff --git a/src/sceneLoader.js b/src/sceneLoader.js index 5d520a9..1861a18 100644 --- a/src/sceneLoader.js +++ b/src/sceneLoader.js @@ -422,6 +422,7 @@ exports.SceneLoader = function (sceneIn) { scene.viewAll(); if (allCompletedCallback != undefined && (typeof allCompletedCallback == 'function')) allCompletedCallback(); + } }; }; diff --git a/src/three/Points.js b/src/three/Points.js index 00502d8..2879d7c 100644 --- a/src/three/Points.js +++ b/src/three/Points.js @@ -26,6 +26,7 @@ class Points extends Object3D { this.geometry = geometry; this.material = material; + this.sizePerPixel = 1; this.updateMorphTargets(); @@ -64,7 +65,7 @@ class Points extends Object3D { _inverseMatrix.copy( matrixWorld ).invert(); _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix ); - const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); + const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ) * this.material.size * this.sizePerPixel; const localThresholdSq = localThreshold * localThreshold; if ( geometry.isBufferGeometry ) {