From 3624f454e2916b26bba5ecd52db787c373b9ec0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Thu, 24 Sep 2026 17:23:19 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=96=E6=99=AF=E8=A7=86=E8=A7=92=E9=99=90?= =?UTF-8?q?=E5=AE=9A=E5=9C=A8=20(0,=20180)=EF=BC=8C=E9=9D=9E=E6=B3=95?= =?UTF-8?q?=E5=80=BC=E5=9B=9E=E8=90=BD=E5=88=B0=E9=BB=98=E8=AE=A4=E8=A7=86?= =?UTF-8?q?=E8=A7=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - packages/model3d-viewer/src/framing.ts:新增 normalizeFovDegrees,fovDegrees 只在 (0, 180) 内采用,>=180 时 tan(halfFovY) 非正会把 limitY/limitX 与 fallbackDistance 算成 0 或负数,污染取景距离与 near/far - packages/model3d-viewer/src/framing.test.ts:补 180 / 360 / 0 / 负数 / NaN 回落到默认视角的用例 --- packages/model3d-viewer/src/framing.test.ts | 19 +++++++++++++++++++ packages/model3d-viewer/src/framing.ts | 18 ++++++++++++++---- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/packages/model3d-viewer/src/framing.test.ts b/packages/model3d-viewer/src/framing.test.ts index 9ef05ad96..e92af8579 100644 --- a/packages/model3d-viewer/src/framing.test.ts +++ b/packages/model3d-viewer/src/framing.test.ts @@ -146,6 +146,25 @@ describe('computeModel3dViewerFitDistance', () => { }); describe('createModel3dViewerFitSolver', () => { + it('视角超出 (0, 180) 时回落到默认视角,不把取景距离算成非正数', () => { + for (const fovDegrees of [180, 360, 0, -45, Number.NaN]) { + const solver = createModel3dViewerFitSolver({ + center: { x: 0, y: 0, z: 0 }, + aspect: 1, + fovDegrees, + }); + + expect(solver.resolve(), String(fovDegrees)).toBeCloseTo( + createModel3dViewerFitSolver({ + center: { x: 0, y: 0, z: 0 }, + aspect: 1, + fovDegrees: MODEL3D_VIEWER_CAMERA_FOV_DEGREES, + }).resolve(), + 6, + ); + } + }); + it('喂包围盒角点时与包围盒口径一致', () => { const expected = computeModel3dViewerFitDistance({ box: CUBE, aspect: 2 }); diff --git a/packages/model3d-viewer/src/framing.ts b/packages/model3d-viewer/src/framing.ts index 13fdf3455..f1ecaad0e 100644 --- a/packages/model3d-viewer/src/framing.ts +++ b/packages/model3d-viewer/src/framing.ts @@ -71,6 +71,19 @@ function normalizePositive(value: number, fallback: number): number { return Number.isFinite(value) && value > 0 ? value : fallback; } +/** + * 取景视角必须落在 (0, 180):>=180 时 `tan(halfFovY)` 非正,`limitY/limitX` 与 + * `fallbackDistance` 会算出 0 或负数,取景距离跟着变成负数并污染 near/far 与轨道范围。 + */ +function normalizeFovDegrees(value: number | null | undefined): number { + return typeof value === 'number' && + Number.isFinite(value) && + value > 0 && + value < 180 + ? value + : MODEL3D_VIEWER_CAMERA_FOV_DEGREES; +} + function subtract( left: Model3dViewerVector3, right: Model3dViewerVector3, @@ -152,10 +165,7 @@ export function createModel3dViewerFitSolver( input: Model3dViewerFitSolverInput, ): Model3dViewerFitSolver { const aspect = normalizePositive(input.aspect, FALLBACK_ASPECT); - const fovDegrees = normalizePositive( - input.fovDegrees ?? MODEL3D_VIEWER_CAMERA_FOV_DEGREES, - MODEL3D_VIEWER_CAMERA_FOV_DEGREES, - ); + const fovDegrees = normalizeFovDegrees(input.fovDegrees); const fitFraction = normalizePositive( input.fitFraction ?? MODEL3D_VIEWER_FIT_FRACTION, MODEL3D_VIEWER_FIT_FRACTION,