Multi Morph WIP

This commit is contained in:
Keavon Chambers 2024-12-20 00:14:55 -08:00
parent feba87449b
commit 12dd5007c1

View file

@ -951,31 +951,7 @@ async fn jitter_points<F: 'n + Send>(
vector_data vector_data
} }
#[node_macro::node(category("Vector"), path(graphene_core::vector))] fn morph_vector_data(source: VectorData, target: VectorData, time: Fraction, start_index: IntegerCount) -> VectorData {
async fn morph<F: 'n + Send + Copy>(
#[implementations(
(),
Footprint,
)]
footprint: F,
#[implementations(
() -> VectorData,
Footprint -> VectorData,
)]
source: impl Node<F, Output = VectorData>,
#[expose]
#[implementations(
() -> VectorData,
Footprint -> VectorData,
)]
target: impl Node<F, Output = VectorData>,
#[range((0., 1.))]
#[default(0.5)]
time: Fraction,
#[min(0.)] start_index: IntegerCount,
) -> VectorData {
let source = source.eval(footprint).await;
let target = target.eval(footprint).await;
let mut result = VectorData::empty(); let mut result = VectorData::empty();
// Lerp styles // Lerp styles
@ -984,6 +960,7 @@ async fn morph<F: 'n + Send + Copy>(
let mut source_paths = source.stroke_bezier_paths(); let mut source_paths = source.stroke_bezier_paths();
let mut target_paths = target.stroke_bezier_paths(); let mut target_paths = target.stroke_bezier_paths();
for (mut source_path, mut target_path) in (&mut source_paths).zip(&mut target_paths) { for (mut source_path, mut target_path) in (&mut source_paths).zip(&mut target_paths) {
// Deal with mismatched transforms // Deal with mismatched transforms
source_path.apply_transform(source.transform); source_path.apply_transform(source.transform);
@ -1005,22 +982,14 @@ async fn morph<F: 'n + Send + Copy>(
target_path.push_manipulator_group(target_path.manipulator_groups()[0].flip()); target_path.push_manipulator_group(target_path.manipulator_groups()[0].flip());
} }
// Mismatched subpath items // Equalize number of manipulator groups
'outer: loop { while source_path.len() < target_path.len() {
for segment_index in (0..(source_path.len() - 1)).rev() { let segment_index = (0..(source_path.len() - 1)).rev().next().unwrap_or(0);
if target_path.len() <= source_path.len() { source_path.insert(SubpathTValue::Parametric { segment_index, t: 0.5 });
break 'outer;
}
source_path.insert(SubpathTValue::Parametric { segment_index, t: 0.5 })
}
} }
'outer: loop { while target_path.len() < source_path.len() {
for segment_index in (0..(target_path.len() - 1)).rev() { let segment_index = (0..(target_path.len() - 1)).rev().next().unwrap_or(0);
if source_path.len() <= target_path.len() { target_path.insert(SubpathTValue::Parametric { segment_index, t: 0.5 });
break 'outer;
}
target_path.insert(SubpathTValue::Parametric { segment_index, t: 0.5 })
}
} }
// Lerp points // Lerp points
@ -1032,15 +1001,17 @@ async fn morph<F: 'n + Send + Copy>(
result.append_subpath(source_path, true); result.append_subpath(source_path, true);
} }
// Mismatched subpath count
// Handle mismatched subpath counts
for mut source_path in source_paths { for mut source_path in source_paths {
source_path.apply_transform(source.transform); source_path.apply_transform(source.transform);
let end = source_path.manipulator_groups().first().map(|group| group.anchor).unwrap_or_default(); let end = source_path.manipulator_groups().first().map(|group| group.anchor).unwrap_or_default();
for group in source_path.manipulator_groups_mut() { for group in source_path.manipulator_groups_mut() {
group.anchor = group.anchor.lerp(end, time); group.anchor = group.anchor.lerp(end, time);
group.in_handle = group.in_handle.map(|handle| handle.lerp(end, time)); group.in_handle = group.in_handle.map(|handle| handle.lerp(end, time));
group.out_handle = group.in_handle.map(|handle| handle.lerp(end, time)); group.out_handle = group.out_handle.map(|handle| handle.lerp(end, time));
} }
result.append_subpath(source_path, true);
} }
for mut target_path in target_paths { for mut target_path in target_paths {
target_path.apply_transform(target.transform); target_path.apply_transform(target.transform);
@ -1048,13 +1019,97 @@ async fn morph<F: 'n + Send + Copy>(
for group in target_path.manipulator_groups_mut() { for group in target_path.manipulator_groups_mut() {
group.anchor = start.lerp(group.anchor, time); group.anchor = start.lerp(group.anchor, time);
group.in_handle = group.in_handle.map(|handle| start.lerp(handle, time)); group.in_handle = group.in_handle.map(|handle| start.lerp(handle, time));
group.out_handle = group.in_handle.map(|handle| start.lerp(handle, time)); group.out_handle = group.out_handle.map(|handle| start.lerp(handle, time));
} }
result.append_subpath(target_path, true);
} }
result result
} }
#[node_macro::node(category("Vector"), path(graphene_core::vector))]
async fn morph<F: 'n + Send + Copy>(
#[implementations(
(),
Footprint,
)]
footprint: F,
#[implementations(
() -> VectorData,
Footprint -> VectorData,
)]
source: impl Node<F, Output = VectorData>,
#[expose]
#[implementations(
() -> VectorData,
Footprint -> VectorData,
)]
target: impl Node<F, Output = VectorData>,
// TODO: Rename to "progress"
#[range((0., 1.))]
#[default(0.5)]
time: Fraction,
#[min(0.)] start_index: IntegerCount,
) -> VectorData {
let source = source.eval(footprint).await;
let target = target.eval(footprint).await;
morph_vector_data(source, target, time, start_index)
}
#[node_macro::node(category("Vector"), path(graphene_core::vector))]
async fn multi_morph<F: 'n + Send + Copy>(
#[implementations(
(),
Footprint,
)]
footprint: F,
#[implementations(
() -> VectorData,
Footprint -> VectorData,
)]
source0: impl Node<F, Output = VectorData>,
#[implementations(
() -> VectorData,
Footprint -> VectorData,
)]
source1: impl Node<F, Output = VectorData>,
#[implementations(
() -> VectorData,
Footprint -> VectorData,
)]
source2: impl Node<F, Output = VectorData>,
#[implementations(
() -> VectorData,
Footprint -> VectorData,
)]
source3: impl Node<F, Output = VectorData>,
#[implementations(
() -> VectorData,
Footprint -> VectorData,
)]
source4: impl Node<F, Output = VectorData>,
// TODO: Rename to "progress"
#[range((0., 1.))]
#[default(0.5)]
time: Fraction,
#[min(0.)] start_index: IntegerCount,
) -> VectorData {
let sources = [
source0.eval(footprint).await,
source1.eval(footprint).await,
source2.eval(footprint).await,
source3.eval(footprint).await,
source4.eval(footprint).await,
];
let num_segments = sources.len() - 1;
let segment_time = time * num_segments as f64;
let index = segment_time.floor() as usize;
let local_time = segment_time - index as f64;
let source = sources[index].clone();
let target = sources[(index + 1).min(num_segments)].clone();
morph_vector_data(source, target, local_time, start_index)
}
fn bevel_algorithm(mut vector_data: VectorData, distance: f64) -> VectorData { fn bevel_algorithm(mut vector_data: VectorData, distance: f64) -> VectorData {
// Splits a bézier curve based on a distance measurement // Splits a bézier curve based on a distance measurement
fn split_distance(bezier: bezier_rs::Bezier, distance: f64, length: f64) -> bezier_rs::Bezier { fn split_distance(bezier: bezier_rs::Bezier, distance: f64, length: f64) -> bezier_rs::Bezier {