alandtse / alandtse/devbench

Exact camera-rotation replay: capture forward vector instead of Euler

Abierto
#2 0 comentarios 0 reacciones 0 asignados Ver en GitHub
Lenguaje dominante
C++
Estrellas
10
Forks
4
Merge medio
1 d 10 h
PR fusionados (30 d)
17

Descripción

Follow-up to the camera free-cam replay work (commits bee4716, 89b0800). **Position** driving is exact; **rotation** capture via Euler is not reliable.

## What works now
- `camera freecam {on}` + `camera drive {x,y,z,pitch,yaw}` set the FreeCameraState transform.
- `camera get` reports `camX/Y/Z`, `camPitch/camYaw`, `freeCam`.
- **Position drive is exact at any distance** (verified: drove `(28022,-585,-932)` → read back delta `(0,0,0)`).
- For **A/B benchmarking** the drive is already useful: it's deterministic, so both A and B runs render the identical viewpoint even before absolute rotation is perfect.

## The rotation problem
Driving a pitch/yaw and reading back the camera's world Euler (via `NiMatrix3::ToEulerAnglesXYZ`):

| drove pitch | read | drove yaw | read |
|---|---|---|---|
| -0.4 | +0.400 | -1.0 | -1.000 |
| -0.2 | +0.200 | -0.5 | **+0.500** |
| 0.0 | -0.000 | 0.0 | -0.000 |
| +0.2 | -0.200 | +0.5 | **-0.500** |
| +0.4 | -0.400 | +1.0 | +1.000 |
| +0.6 | -0.600 | +2.0 | +2.000 |

- **Pitch**: exact magnitude, **sign-flipped** — `freecam pitch = -worldEuler.x`. Easy.
- **Yaw**: flips sign at ±0.5 but not ±1/±2 — `ToEulerAnglesXYZ` is **multivalued** (a rotation matrix has several XYZ decompositions; the extractor jumps branches). Capturing yaw this way is unstable and would make the replayed camera **jitter** between samples.

## Plan
1. **Capture the camera forward vector** (unambiguous) from `cameraRoot->world.rotate` instead of Euler angles, per sample.
2. At replay, convert forward → free-cam pitch/yaw: `yaw = atan2(fwd.x, fwd.y)` (confirm Skyrim convention), `pitch = -asin(fwd.z)` (sign per the table above). Nail the convention with a drive→read sweep.
3. Then wire per-sample `camera drive` into BuildScenario/BuildReplaySteps under a `driveCamera` replay flag (the `drive` tool already no-ops when not in free cam, so steps are inert on a normal replay; `driveCamera` prepends `freecam on`, skips `setPov`, appends `freecam off`).
4. Optional: RE `FreeCameraState::GetRotation` (Ghidra) to confirm the exact rotation/`zUpDown` convention rather than fitting empirically.

Until then: position-exact drive is landed; replay does not auto-drive the camera (POV mode + body pose remain the replay path; first-person is exact).

Guía de contribución

No hay ninguna guía de contribución indexada para este repositorio

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.