From 3bdf5982cbc869399a9d2dfabf7a7409755029df Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Sat, 25 Apr 2026 03:34:30 +0200 Subject: [PATCH] auto-git: [change] tests/unit/dialogue-attention-camera.test.ts --- tests/unit/dialogue-attention-camera.test.ts | 61 +++++++++++++++----- 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/tests/unit/dialogue-attention-camera.test.ts b/tests/unit/dialogue-attention-camera.test.ts index 89f4fc55..319996da 100644 --- a/tests/unit/dialogue-attention-camera.test.ts +++ b/tests/unit/dialogue-attention-camera.test.ts @@ -1,20 +1,23 @@ import { describe, expect, it } from "vitest"; +import { Vector3 } from "three"; import { resolveDialogueAttentionCameraSolution } from "../../src/runtime-three/dialogue-attention-camera"; describe("resolveDialogueAttentionCameraSolution", () => { - it("chooses a stable shoulder side from the reference camera and biases framing toward the NPC", () => { + it("orbits around the conversation midpoint and frames the player and npc on opposite sides", () => { + const playerFocusPoint = { + x: 0, + y: 1.6, + z: 0 + }; + const npcFocusPoint = { + x: 2, + y: 1.7, + z: 2 + }; const solution = resolveDialogueAttentionCameraSolution({ - playerFocusPoint: { - x: 0, - y: 1.6, - z: 0 - }, - npcFocusPoint: { - x: 2, - y: 1.7, - z: 2 - }, + playerFocusPoint, + npcFocusPoint, referenceCameraPosition: { x: 4, y: 2.2, @@ -26,11 +29,43 @@ describe("resolveDialogueAttentionCameraSolution", () => { z: 1 } }); + const forward = new Vector3( + solution.lookTarget.x - solution.position.x, + solution.lookTarget.y - solution.position.y, + solution.lookTarget.z - solution.position.z + ).normalize(); + const right = new Vector3().crossVectors(forward, new Vector3(0, 1, 0)).normalize(); + const playerViewOffset = right.dot( + new Vector3( + playerFocusPoint.x - solution.position.x, + playerFocusPoint.y - solution.position.y, + playerFocusPoint.z - solution.position.z + ) + ); + const npcViewOffset = right.dot( + new Vector3( + npcFocusPoint.x - solution.position.x, + npcFocusPoint.y - solution.position.y, + npcFocusPoint.z - solution.position.z + ) + ); + const pairDirection = new Vector3( + npcFocusPoint.x - playerFocusPoint.x, + 0, + npcFocusPoint.z - playerFocusPoint.z + ).normalize(); + const horizontalForward = new Vector3(forward.x, 0, forward.z).normalize(); expect(solution.sideSign).toBe(1); + expect(solution.pivot).toEqual({ + x: 1, + y: 1.65, + z: 1 + }); expect(solution.position.y).toBeGreaterThan(2); - expect(solution.lookTarget.x).toBeGreaterThan(1); - expect(solution.lookTarget.z).toBeGreaterThan(1); + expect(playerViewOffset * npcViewOffset).toBeLessThan(0); + expect(Math.abs(horizontalForward.dot(pairDirection))).toBeGreaterThan(0.2); + expect(Math.abs(horizontalForward.dot(pairDirection))).toBeLessThan(0.9); }); it("preserves the authored dialogue side sign across solver updates", () => {