1010: preserve easing while baking parented Orientation

This commit is contained in:
Kristian Myram committed 2026-10-17 20:44:28 +00:00
1 parent 7e6d76406b
commit f64cd5ce38
2 files changed
+30 -1

No files matched your search

+9 -1
View File
@@ -818,7 +818,15 @@ fn bake_between(
let tm = Tick(ta.0 + (tb.0 - ta.0) / 2);
let blend = [(ea[0] + eb[0]) / 2.0, (ea[1] + eb[1]) / 2.0, (ea[2] + eb[2]) / 2.0];
let exact = correction * Mat4::orientation(Vec3::from(authored.value_at(tm).as_vec3()));
if rotation_angle(Mat4::orientation(Vec3::from(blend)), exact) <= BAKE_TOLERANCE_DEGREES {
// Symmetric easing crosses the straight blend at its midpoint. Check both sides too before
// accepting a segment whose original easing will be replaced with a linear blend.
let quarter = (tb.0 - ta.0) / 4;
if [Tick(ta.0 + quarter), tm, Tick(tb.0 - quarter)].into_iter().all(|t| {
let u = (t.0 - ta.0) as f64 / (tb.0 - ta.0) as f64;
let linear = std::array::from_fn(|i| ea[i] + (eb[i] - ea[i]) * u);
let target = correction * Mat4::orientation(Vec3::from(authored.value_at(t).as_vec3()));
rotation_angle(Mat4::orientation(Vec3::from(linear)), target) <= BAKE_TOLERANCE_DEGREES
}) {
return;
}
let em = nearest_euler(euler_zyx(exact.0), blend);
+21
View File
@@ -325,6 +325,27 @@ fn keyed_orientation_under_a_tilted_null_follows_between_the_keys() {
// ---------------------------------------------------------------- from 3D model
/// Easy Ease agrees with a straight blend at the midpoint, but not at the quarter points.
#[test]
fn eased_orientation_under_x_parent_keeps_motion_between_keys() {
let mut s = session();
let light = s.execute("layer.newLight", json!({"kind": "Point", "position": [320, 180, -500]})).unwrap()["layer"].as_u64().unwrap();
for (time, value) in [(0.0, json!([0.0, 0.0, 0.0])), (1.0, json!([90.0, 0.0, 0.0]))] {
s.execute("prop.addKey", json!({"layer": light, "path": "transform/orientation", "time": time, "value": value})).unwrap();
}
let uid = layer_in(&s, cid(&s), light).props.prop("transform/orientation").unwrap().uid;
s.execute("keys.select", json!({"keys": [{"layer": light, "prop": uid, "time": 0.0}, {"layer": light, "prop": uid, "time": 1.0}]})).unwrap();
s.execute("keys.easyEase", json!({})).unwrap();
let times: Vec<_> = (0..=100).map(|i| Tick::from_seconds_f64(i as f64 / 100.0)).collect();
let before: Vec<_> = times.iter().map(|t| frame_at(&s, light, *t)).collect();
let parent = rotated_null(&mut s, [30.0, 0.0, 0.0], 0.0);
s.execute("layer.setParent", json!({"layers": [light], "parent": parent})).unwrap();
for (t, b) in times.into_iter().zip(before) {
let a = frame_at(&s, light, t);
assert!((a.0 - b.0).length() < 1e-6 && (a.1 - b.1).length() < 1e-3, "at {t:?}: {:?} vs {:?}", a.1, b.1);
}
}
struct DiskModels;
impl FootageSource for DiskModels {