feat: improve camera motion and shot transitions
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f8bdd831f8794ea18ca288f3745462b1
|
||||
guid: 572fff6d310f4e669243b957117466c1
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ef4feff8a1c42a0be6affcf5d6429db
|
||||
guid: c0bd869f0b114cca884580f0d6229b19
|
||||
|
||||
@@ -41,6 +41,15 @@ namespace Streamingle.Editor
|
||||
private const string PreviewGenerationProvenanceName =
|
||||
"AI Camera Preview Generation Provenance";
|
||||
private const double CutBoundaryGuardSeconds = 0.000001;
|
||||
private const int DirectionChangeDetectionFlankFrames = 5;
|
||||
// Matches the worker's 0.35-second braking radius at 60 fps.
|
||||
private const int DirectionChangePreserveRadiusFrames = 21;
|
||||
private const float DirectionChangeMinimumSpeedMetersPerSecond = 0.04f;
|
||||
// Preserve the generated braking envelope for every concentrated turn
|
||||
// covered by the worker policy (40 degrees and above), not only an
|
||||
// almost complete reversal. Linear curve simplification may otherwise
|
||||
// collapse a mild 40--55 or clear 60/90-degree slowdown into a kink.
|
||||
private const float DirectionChangeMaximumCosine = 0.76604444f;
|
||||
public const CurveSimplificationPreset DefaultCurveSimplificationPreset =
|
||||
CurveSimplificationPreset.Balanced;
|
||||
|
||||
@@ -2451,6 +2460,7 @@ namespace Streamingle.Editor
|
||||
AddScalarExtrema(values.Count, index => values[index].x, required);
|
||||
AddScalarExtrema(values.Count, index => values[index].y, required);
|
||||
AddScalarExtrema(values.Count, index => values[index].z, required);
|
||||
AddDirectionChangeNeighborhoods(times, values, required);
|
||||
return SimplifyIndices(
|
||||
times,
|
||||
maximumError,
|
||||
@@ -2593,6 +2603,61 @@ namespace Streamingle.Editor
|
||||
indices.Add(maximumIndex);
|
||||
}
|
||||
|
||||
private static void AddDirectionChangeNeighborhoods(
|
||||
IReadOnlyList<double> times,
|
||||
IReadOnlyList<Vector3> values,
|
||||
ISet<int> indices)
|
||||
{
|
||||
var flank = DirectionChangeDetectionFlankFrames;
|
||||
if (values.Count < flank * 2 + 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (var center = flank; center + flank < values.Count; center++)
|
||||
{
|
||||
var beforeDuration = times[center] - times[center - flank];
|
||||
var afterDuration = times[center + flank] - times[center];
|
||||
if (beforeDuration <= double.Epsilon ||
|
||||
afterDuration <= double.Epsilon)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var beforeVelocity =
|
||||
(values[center] - values[center - flank]) /
|
||||
(float)beforeDuration;
|
||||
var afterVelocity =
|
||||
(values[center + flank] - values[center]) /
|
||||
(float)afterDuration;
|
||||
var beforeSpeed = beforeVelocity.magnitude;
|
||||
var afterSpeed = afterVelocity.magnitude;
|
||||
if (Mathf.Min(beforeSpeed, afterSpeed) <
|
||||
DirectionChangeMinimumSpeedMetersPerSecond)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var cosine = Vector3.Dot(beforeVelocity, afterVelocity) /
|
||||
(beforeSpeed * afterSpeed);
|
||||
if (cosine > DirectionChangeMaximumCosine)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var start = Mathf.Max(
|
||||
0,
|
||||
center - DirectionChangePreserveRadiusFrames);
|
||||
var end = Mathf.Min(
|
||||
values.Count - 1,
|
||||
center + DirectionChangePreserveRadiusFrames);
|
||||
for (var index = start; index <= end; index++)
|
||||
{
|
||||
indices.Add(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Quaternion[] MakeQuaternionSequenceContinuous(
|
||||
IReadOnlyList<Quaternion> rotations)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user