From ce2636cac7587cacc68a601033cf34f0c78bcce2 Mon Sep 17 00:00:00 2001 From: Andres Mandado Date: Fri, 29 Jan 2021 13:17:31 +0100 Subject: [PATCH] HARP-13901: Keep canvas size in PickingRaycaster updated. Also, some cleaning in MapViewPoints. --- @here/harp-mapview/lib/MapViewPoints.ts | 84 ++++++++-------------- @here/harp-mapview/lib/PickHandler.ts | 11 +-- @here/harp-mapview/lib/PickingRaycaster.ts | 5 +- 3 files changed, 39 insertions(+), 61 deletions(-) diff --git a/@here/harp-mapview/lib/MapViewPoints.ts b/@here/harp-mapview/lib/MapViewPoints.ts index 011f7fd2a9..eead49d435 100644 --- a/@here/harp-mapview/lib/MapViewPoints.ts +++ b/@here/harp-mapview/lib/MapViewPoints.ts @@ -68,14 +68,25 @@ export abstract class MapViewPoints extends THREE.Points { const geometry = this.geometry; const matrixWorld = this.matrixWorld; - const screenCoords = raycaster.ray.origin + const ndc = raycaster.ray.origin .clone() .add(raycaster.ray.direction) .project(raycaster.camera); - const mouseCoords = new THREE.Vector2( - Math.ceil(((screenCoords.x + 1) / 2) * raycaster.width), - Math.ceil(((1 - screenCoords.y) / 2) * raycaster.height) - ); + const mouseCoords = ndcToScreen(ndc, raycaster); + + const testPoint = (point: THREE.Vector3, index: number) => { + const pointInfo = getPointInfo(point, matrixWorld, raycaster); + if (pointInfo.pointIsOnScreen) { + this.testPoint( + point, + pointInfo.absoluteScreenPosition!, + mouseCoords, + index, + pointInfo.distance!, + intersects + ); + } + }; if (geometry instanceof THREE.BufferGeometry) { const point = new THREE.Vector3(); @@ -85,56 +96,29 @@ export abstract class MapViewPoints extends THREE.Points { if (index !== null) { const indices = index.array; for (let i = 0, il = indices.length; i < il; i++) { - const a = indices[i]; - point.fromArray(positions as number[], a * 3); - const pointInfo = getPointInfo(point, matrixWorld, raycaster); - if (pointInfo.pointIsOnScreen) { - this.testPoint( - point, - pointInfo.absoluteScreenPosition!, - mouseCoords, - i, - pointInfo.distance!, - intersects - ); - } + testPoint(point.fromArray(positions as number[], indices[i] * 3), i); } } else { for (let i = 0, l = positions.length / 3; i < l; i++) { - point.fromArray(positions as number[], i * 3); - const pointInfo = getPointInfo(point, matrixWorld, raycaster); - if (pointInfo.pointIsOnScreen) { - this.testPoint( - point, - pointInfo.absoluteScreenPosition!, - mouseCoords, - i, - pointInfo.distance!, - intersects - ); - } + testPoint(point.fromArray(positions as number[], i * 3), i); } } } else { const vertices = geometry.vertices; for (let index = 0; index < vertices.length; index++) { - const point = vertices[index]; - const pointInfo = getPointInfo(point, matrixWorld, raycaster); - if (pointInfo.pointIsOnScreen) { - this.testPoint( - point, - pointInfo.absoluteScreenPosition!, - mouseCoords, - index, - pointInfo.distance!, - intersects - ); - } + testPoint(vertices[index], index); } } } } +function ndcToScreen(ndc: THREE.Vector3, raycaster: PickingRaycaster): THREE.Vector2 { + return new THREE.Vector2(ndc.x + 1, 1 - ndc.y) + .divideScalar(2) + .multiply(raycaster.canvasSize) + .ceil(); +} + function getPointInfo( point: THREE.Vector3, matrixWorld: THREE.Matrix4, @@ -144,20 +128,12 @@ function getPointInfo( absoluteScreenPosition?: THREE.Vector2; distance?: number; } { - const worldPosition = point.clone(); - worldPosition.applyMatrix4(matrixWorld); + const worldPosition = point.clone().applyMatrix4(matrixWorld); const distance = worldPosition.distanceTo(raycaster.ray.origin); - worldPosition.project(raycaster.camera); - const relativeScreenPosition = new THREE.Vector2(worldPosition.x, worldPosition.y); - const pointIsOnScreen = - relativeScreenPosition.x < 1 && - relativeScreenPosition.x > -1 && - relativeScreenPosition.y < 1 && - relativeScreenPosition.y > -1; + const ndc = worldPosition.project(raycaster.camera); + const pointIsOnScreen = ndc.x < 1 && ndc.x > -1 && ndc.y < 1 && ndc.y > -1; if (pointIsOnScreen) { - worldPosition.x = ((worldPosition.x + 1) / 2) * raycaster.width; - worldPosition.y = ((1 - worldPosition.y) / 2) * raycaster.height; - const absoluteScreenPosition = new THREE.Vector2(worldPosition.x, worldPosition.y); + const absoluteScreenPosition = ndcToScreen(ndc, raycaster); return { absoluteScreenPosition, pointIsOnScreen, diff --git a/@here/harp-mapview/lib/PickHandler.ts b/@here/harp-mapview/lib/PickHandler.ts index 974f0cd4c5..82cef09575 100644 --- a/@here/harp-mapview/lib/PickHandler.ts +++ b/@here/harp-mapview/lib/PickHandler.ts @@ -153,8 +153,9 @@ export class PickHandler { readonly camera: THREE.Camera, public enablePickTechnique = false ) { - const { width, height } = mapView.renderer.getSize(new THREE.Vector2()); - this.m_pickingRaycaster = new PickingRaycaster(width, height); + this.m_pickingRaycaster = new PickingRaycaster( + mapView.renderer.getSize(new THREE.Vector2()) + ); } /** @@ -168,7 +169,7 @@ export class PickHandler { */ intersectMapObjects(x: number, y: number, parameters?: IntersectParams): PickResult[] { const ndc = this.mapView.getNormalizedScreenCoordinates(x, y); - const rayCaster = this.createRaycaster(x, y); + const rayCaster = this.setupRaycaster(x, y); const pickListener = new PickListener(parameters); if (this.mapView.textElementsRenderer !== undefined) { @@ -238,6 +239,8 @@ export class PickHandler { this.mapView.getNormalizedScreenCoordinates(x, y), this.camera ); + + this.mapView.renderer.getSize(this.m_pickingRaycaster.canvasSize); return this.m_pickingRaycaster; } @@ -375,7 +378,7 @@ export class PickHandler { pickResult.userData = featureData.objInfos[objInfosIndex - 1]; } - private createRaycaster(x: number, y: number): THREE.Raycaster { + private setupRaycaster(x: number, y: number): THREE.Raycaster { const camera = this.mapView.camera; const rayCaster = this.raycasterFromScreenPoint(x, y); diff --git a/@here/harp-mapview/lib/PickingRaycaster.ts b/@here/harp-mapview/lib/PickingRaycaster.ts index c9c7223aae..16d2abd162 100644 --- a/@here/harp-mapview/lib/PickingRaycaster.ts +++ b/@here/harp-mapview/lib/PickingRaycaster.ts @@ -39,10 +39,9 @@ export class PickingRaycaster extends THREE.Raycaster { /** * Constructor. * - * @param width - the canvas width. - * @param height - the canvas height. + * @param canvasSize - the canvas width and height. */ - constructor(public width: number, public height: number) { + constructor(readonly canvasSize: THREE.Vector2) { super(); }