From 0b3b1074e09acbe49b0bd1e1b521e00d76cd58f3 Mon Sep 17 00:00:00 2001 From: Oscar Lorentzon Date: Tue, 19 Sep 2023 16:33:20 -0700 Subject: [PATCH] feat: handle unstable unprojection for fov --- src/geo/Geo.ts | 69 +++++++++++++++++++++++----- src/geometry/camera/FisheyeCamera.ts | 4 ++ src/render/RenderCamera.ts | 13 +++--- 3 files changed, 69 insertions(+), 17 deletions(-) diff --git a/src/geo/Geo.ts b/src/geo/Geo.ts index 0690f8b7..7be455f9 100644 --- a/src/geo/Geo.ts +++ b/src/geo/Geo.ts @@ -38,6 +38,15 @@ export function computeProjectedPoints( pointsPerLine: number, viewportCoords: ViewportCoords): number[][] { + // @ts-ignore + const camera: THREE.Camera = new THREE.Camera(); + camera.up.copy(transform.upVector()); + camera.position.copy(new THREE.Vector3().fromArray(transform.unprojectSfM([0, 0], 0))); + camera.lookAt(new THREE.Vector3().fromArray(transform.unprojectSfM([0, 0], 10))); + camera.updateMatrix(); + camera.updateMatrixWorld(true); + + const basicPoints: number[][] = []; for (let side: number = 0; side < basicVertices.length; ++side) { @@ -52,6 +61,33 @@ export function computeProjectedPoints( } } + + const projectedPoints: number[][] = []; + for (const [index, basicPoint] of basicPoints.entries()) { + const worldPoint = transform.unprojectBasic(basicPoint, 10000); + const cameraPoint = viewportCoords.worldToCamera(worldPoint, camera); + if (cameraPoint[2] > 0) { + continue; + } + + projectedPoints.push([ + cameraPoint[0] / cameraPoint[2], + cameraPoint[1] / cameraPoint[2], + index, + ]); + } + + + return projectedPoints; +} + +export function computeProjectedPointsSafe( + transform: Transform, + basicVertices: number[][], + basicDirections: number[][], + pointsPerLine: number, + viewportCoords: ViewportCoords): number[][] { + // @ts-ignore const camera: THREE.Camera = new THREE.Camera(); camera.up.copy(transform.upVector()); @@ -60,17 +96,28 @@ export function computeProjectedPoints( camera.updateMatrix(); camera.updateMatrixWorld(true); - const projectedPoints = basicPoints - .map( - (basicPoint: number[]): number[] => { - const worldPoint = transform.unprojectBasic(basicPoint, 10000); - const cameraPoint = viewportCoords.worldToCamera(worldPoint, camera); - - return [ - cameraPoint[0] / cameraPoint[2], - cameraPoint[1] / cameraPoint[2], - ]; - }); + const projectedPoints: number[][] = []; + for (let side: number = 0; side < basicVertices.length; ++side) { + const v: number[] = basicVertices[side]; + const d: number[] = basicDirections[side]; + + for (let i: number = 0; i <= pointsPerLine; ++i) { + const basicPoint = [ + v[0] + d[0] * i / pointsPerLine, + v[1] + d[1] * i / pointsPerLine, + ]; + const worldPoint = transform.unprojectBasic(basicPoint, 10000); + const cameraPoint = viewportCoords.worldToCamera(worldPoint, camera); + if (cameraPoint[2] > 0) { + break; + } + + projectedPoints.push([ + cameraPoint[0] / cameraPoint[2], + cameraPoint[1] / cameraPoint[2], + ]); + } + } return projectedPoints; } diff --git a/src/geometry/camera/FisheyeCamera.ts b/src/geometry/camera/FisheyeCamera.ts index 40d13d1f..20450063 100644 --- a/src/geometry/camera/FisheyeCamera.ts +++ b/src/geometry/camera/FisheyeCamera.ts @@ -90,6 +90,10 @@ vec2 projectToSfm(vec3 bearing, Parameters parameters, Uniforms uniforms) { float radialPeak = uniforms.radialPeak; // Projection + if (z < 0.) { + return vec2(POSITIVE_INFINITY, POSITIVE_INFINITY); + } + float r = sqrt(x * x + y * y); float theta = atan(r, z); diff --git a/src/render/RenderCamera.ts b/src/render/RenderCamera.ts index 4edced7b..5165f033 100644 --- a/src/render/RenderCamera.ts +++ b/src/render/RenderCamera.ts @@ -419,11 +419,11 @@ export class RenderCamera { } private _computeProjectedPoints(transform: Transform): number[][] { - const vertices = [[0, 0], [1, 0]]; - const directions = [[1, 0], [0, 1]]; - const pointsPerLine = 50; + const vertices = [[0.5, 0], [0.5, 0], [1, 0.5], [1, 0.5]]; + const directions = [[-0.5, 0], [0.5, 0], [0, -0.5], [0, 0.5]]; + const pointsPerLine = 25; - return Geo.computeProjectedPoints( + return Geo.computeProjectedPointsSafe( transform, vertices, directions, @@ -475,7 +475,9 @@ export class RenderCamera { aspect); }); - const vFovFill = Math.min(...fovs) * 0.995; + const fovMax = 125; + const minFov = Math.min(...fovs) * 0.995; + const vFovFill = Math.min(minFov, fovMax); if (renderMode === RenderMode.Fill) { return vFovFill; } @@ -492,7 +494,6 @@ export class RenderCamera { vFov *= hFovMax / hFovLetterbox; } - const fovMax = 135; const vFovMax = aspect > 2 ? vFovFill : fovCoeff * vFovFill; vFov = Math.min(vFov, vFovMax, fovMax); vFov = Math.max(vFov, vFovFill);