mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 02:14:01 +00:00
Merge branch 'main' into fix/geo-distance-dateline
This commit is contained in:
commit
1344b5d77e
4 files changed
+53
-4
No files matched your search
@@ -0,0 +1,3 @@
|
||||
- Director shot actions land on the requested shot. A seek to a shot's start
|
||||
could round a hair below it and select the end of the previous shot for some
|
||||
shot counts and durations (Aditya, @Rohilalala, #1171).
|
||||
@@ -430,6 +430,8 @@ reference. Legacy projects retain their ordinary flights, content and edits.
|
||||
Seeking between ordinary camera poses uses the shortest longitude arc across the
|
||||
dateline while preserving both authored endpoint longitudes, and turns heading
|
||||
and roll the short way for any authored angles.
|
||||
A seek to a shot's start, as a shot action makes, selects that shot rather than
|
||||
the end of the previous one.
|
||||
See [camera directions](DIRECTOR-CAMERA.md).
|
||||
|
||||
Realtime voice composes separate connection, response/tool, Radio handoff, input
|
||||
|
||||
@@ -72,19 +72,27 @@ export function sceneSeekState(scene, progress, durationForShot, holdForShot) {
|
||||
let shotIndex = scene.shots.length - 1;
|
||||
for (let index = 0; index < scene.shots.length; index += 1) {
|
||||
const endElapsedSec = startElapsedSec + durations[index];
|
||||
if (targetSec < endElapsedSec || index === scene.shots.length - 1) {
|
||||
// Compare in progress units: a shot's startProgress (start / total)
|
||||
// times total can round below its start and select the previous shot.
|
||||
if (
|
||||
normalized < endElapsedSec / totalSec ||
|
||||
index === scene.shots.length - 1
|
||||
) {
|
||||
shotIndex = index;
|
||||
break;
|
||||
}
|
||||
startElapsedSec = endElapsedSec;
|
||||
}
|
||||
// Keep the elapsed time inside the selected shot, so it agrees with
|
||||
// shotIndex when targetSec rounded below the shot's start.
|
||||
const elapsedSec = Math.max(targetSec, startElapsedSec);
|
||||
const shot = scene.shots[shotIndex];
|
||||
const flightDurationSec = shot.durationSec || DEFAULT_SHOT_DURATION_SEC;
|
||||
const holdDurationSec = holdForShot(scene, shot);
|
||||
const shotDurationSec = Math.max(0.001, flightDurationSec + holdDurationSec);
|
||||
const shotElapsedSec = Math.max(
|
||||
0,
|
||||
Math.min(shotDurationSec, targetSec - startElapsedSec),
|
||||
Math.min(shotDurationSec, elapsedSec - startElapsedSec),
|
||||
);
|
||||
const cameraProgress = clamp01(
|
||||
shotElapsedSec / Math.max(0.001, flightDurationSec),
|
||||
@@ -99,8 +107,8 @@ export function sceneSeekState(scene, progress, durationForShot, holdForShot) {
|
||||
);
|
||||
const move = resolveCameraMove(scene, shot);
|
||||
return {
|
||||
sceneProgress: totalSec > 0 ? targetSec / totalSec : 0,
|
||||
sceneElapsedSec: targetSec,
|
||||
sceneProgress: totalSec > 0 ? elapsedSec / totalSec : 0,
|
||||
sceneElapsedSec: elapsedSec,
|
||||
sceneDurationSec: totalSec,
|
||||
shotIndex,
|
||||
shot,
|
||||
|
||||
@@ -49,3 +49,39 @@ test('camera seeking preserves cubic easing and shortest-angle orientation', ()
|
||||
);
|
||||
assert.deepEqual(cameraAtProgress(null, camera(20, 350), 0), camera(20, 350));
|
||||
});
|
||||
|
||||
test('seeking to a shot start lands in that shot for every shot count and duration', () => {
|
||||
const misses = [];
|
||||
for (let count = 2; count <= 12; count += 1) {
|
||||
for (let flightTenths = 1; flightTenths <= 100; flightTenths += 1) {
|
||||
for (let holdTenths = 0; holdTenths <= 50; holdTenths += 1) {
|
||||
const shots = Array.from({ length: count }, (_, index) => ({
|
||||
id: `s${index}`,
|
||||
// Every third shot is longer, so boundaries are not all equal steps.
|
||||
durationSec: flightTenths / 10 + (index % 3 === 2 ? 1.7 : 0),
|
||||
holdSec: holdTenths / 10,
|
||||
camera: camera(20, 0),
|
||||
}));
|
||||
const mixed = { shots };
|
||||
for (const [index, shot] of shots.entries()) {
|
||||
const { startProgress, startElapsedSec } = sceneTimingForShot(
|
||||
mixed,
|
||||
shot,
|
||||
duration,
|
||||
);
|
||||
const seek = sceneSeekState(mixed, startProgress, duration, hold);
|
||||
// One or two ulps earlier still belongs to the previous shot.
|
||||
const before = startProgress * (1 - Number.EPSILON);
|
||||
const previous = sceneSeekState(mixed, before, duration, hold);
|
||||
if (
|
||||
seek.shotIndex !== index ||
|
||||
seek.sceneElapsedSec < startElapsedSec ||
|
||||
previous.shotIndex !== Math.max(0, index - 1)
|
||||
)
|
||||
misses.push(`${count}x${flightTenths}/${holdTenths}#${index}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert.deepEqual(misses.slice(0, 5), []);
|
||||
});
|
||||
Reference in new issue
Block a user