diff --git a/crates/effects/src/time_fx.rs b/crates/effects/src/time_fx.rs index cf7624d92..7fadc4f37 100644 --- a/crates/effects/src/time_fx.rs +++ b/crates/effects/src/time_fx.rs @@ -552,7 +552,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 feb033d65..85aada082 100644 --- a/crates/raster/src/flow.rs +++ b/crates/raster/src/flow.rs @@ -103,7 +103,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); @@ -280,6 +281,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);