use crate::vrma::animation::bone_rotation::Transformation as RotationTransformation;
use crate::vrma::animation::bone_translation::Transformation as TranslationTransformation;
use bevy::animation::{AnimationEntityMut, animated_field};
use bevy::prelude::*;
const SAMPLE_RATE: f32 = 120.0;
pub(crate) fn bake_rotation_curve(
curve: &VariableCurve,
transformation: &RotationTransformation,
world: &mut World,
) -> Option<VariableCurve> {
let domain = curve.0.domain();
let start = domain.start();
let end = domain.end();
let duration = end - start;
if duration <= 0.0 || !duration.is_finite() {
return None;
}
let sample_count = ((duration * SAMPLE_RATE).ceil() as usize).max(2);
let dt = duration / (sample_count - 1) as f32;
let dummy = world.spawn(Transform::default()).id();
let mut evaluator = curve.0.create_evaluator();
let graph_node = AnimationNodeIndex::new(0);
let mut keyframes: Vec<(f32, Quat)> = Vec::with_capacity(sample_count);
let mut query = world.query::<AnimationEntityMut>();
for i in 0..sample_count {
let t = (start + dt * i as f32).min(end);
if let Some(mut tf) = world.get_mut::<Transform>(dummy) {
tf.rotation = Quat::IDENTITY;
}
if curve.0.apply(&mut *evaluator, t, 1.0, graph_node).is_err() {
world.despawn(dummy);
return None;
}
{
let Ok(entity_mut) = query.get_mut(world, dummy) else {
world.despawn(dummy);
return None;
};
if evaluator.commit(entity_mut).is_err() {
world.despawn(dummy);
return None;
}
}
let sampled_rotation = world
.get::<Transform>(dummy)
.map(|tf| tf.rotation)
.unwrap_or(Quat::IDENTITY);
let retargeted = transformation.transform(sampled_rotation);
keyframes.push((t, retargeted));
}
world.despawn(dummy);
let baked_curve = AnimatableKeyframeCurve::new(keyframes).ok()?;
Some(VariableCurve::new(AnimatableCurve::new(
animated_field!(Transform::rotation),
baked_curve,
)))
}
pub(crate) fn bake_translation_curve(
curve: &VariableCurve,
transformation: &TranslationTransformation,
world: &mut World,
) -> Option<VariableCurve> {
let domain = curve.0.domain();
let start = domain.start();
let end = domain.end();
let duration = end - start;
if duration <= 0.0 || !duration.is_finite() {
return None;
}
let sample_count = ((duration * SAMPLE_RATE).ceil() as usize).max(2);
let dt = duration / (sample_count - 1) as f32;
let dummy = world.spawn(Transform::default()).id();
let mut evaluator = curve.0.create_evaluator();
let graph_node = AnimationNodeIndex::new(0);
let mut keyframes: Vec<(f32, Vec3)> = Vec::with_capacity(sample_count);
let mut query = world.query::<AnimationEntityMut>();
for i in 0..sample_count {
let t = (start + dt * i as f32).min(end);
if let Some(mut tf) = world.get_mut::<Transform>(dummy) {
tf.translation = Vec3::ZERO;
}
if curve.0.apply(&mut *evaluator, t, 1.0, graph_node).is_err() {
world.despawn(dummy);
return None;
}
{
let Ok(entity_mut) = query.get_mut(world, dummy) else {
world.despawn(dummy);
return None;
};
if evaluator.commit(entity_mut).is_err() {
world.despawn(dummy);
return None;
}
}
let sampled_translation = world
.get::<Transform>(dummy)
.map(|tf| tf.translation)
.unwrap_or(Vec3::ZERO);
let retargeted = transformation.transform(sampled_translation);
keyframes.push((t, retargeted));
}
world.despawn(dummy);
let baked_curve = AnimatableKeyframeCurve::new(keyframes).ok()?;
Some(VariableCurve::new(AnimatableCurve::new(
animated_field!(Transform::translation),
baked_curve,
)))
}