From e2afb4b17c2577f2fecc74de82488030c90203c5 Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Tue, 10 Nov 2026 18:00:27 -0500 Subject: [PATCH] Timewarp: hold Block Size to its declared range and the matching window to a cap (#3024) --- crates/effects/src/time_fx.rs | 3 ++- crates/raster/src/flow.rs | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/crates/effects/src/time_fx.rs b/crates/effects/src/time_fx.rs index b9d20e2a7..74b392db6 100644 --- a/crates/effects/src/time_fx.rs +++ b/crates/effects/src/time_fx.rs @@ -565,7 +565,8 @@ impl PixelMotion { let px = |id: &str| (g(id, 0.0).max(0.0) * scale).round() as u32; PixelMotion { tile, - window: ((g("tuning/blockSize", 8.0).max(4.0)) * scale).round().max(4.0) as u32, + // Block Size is declared 4..64; a project can store any number. + window: ((g("tuning/blockSize", 8.0).clamp(4.0, 64.0)) * scale).round().max(4.0) as u32, global_smoothness: g("tuning/smoothing/globalSmoothness", 0.5).clamp(0.0, 1.0) as f32, local_smoothness: g("tuning/smoothing/localSmoothness", 0.5).clamp(0.0, 1.0) as f32, iterations: g("tuning/smoothing/smoothingIterations", 20.0).clamp(0.0, 200.0) as u32, diff --git a/crates/raster/src/flow.rs b/crates/raster/src/flow.rs index 180b235bf..4fdf0e060 100644 --- a/crates/raster/src/flow.rs +++ b/crates/raster/src/flow.rs @@ -118,7 +118,8 @@ pub fn block_flow(a: &Image, b: &Image, block: u32, radius: i32) -> Flow { /// (Timewarp's Vector Detail and Block Size). pub fn block_flow_window(a: &Image, b: &Image, tile: u32, window: u32, radius: i32) -> Flow { let bs = tile.max(2) as usize; - let win = window.max(4) as i64; + // The matching cost per vector grows with the window's area; 512 is far above any block size the effects offer. + let win = i64::from(window.clamp(4, 512)); // Window origin relative to the tile origin. let wo = bs as i64 / 2 - win / 2; let (w, h) = (a.width as usize, a.height as usize); @@ -295,6 +296,13 @@ mod tests { s / n as f32 } + #[test] + fn a_huge_matching_window_is_held_to_the_cap() { + let (a, b) = (texture(520, 520, 0.0), texture(520, 520, 2.0)); + let capped = block_flow_window(&a, &b, 260, 512, 2); + assert_eq!(block_flow_window(&a, &b, 260, u32::MAX, 2).v, capped.v); + } + #[test] fn flow_finds_translation() { let a = texture(128, 96, 0.0);