use std::ops::Mul;
use cgmath::{BaseFloat, EuclideanSpace, InnerSpace, Rotation, VectorSpace, Zero};
use super::{ApplyAngular, ForceAccumulator, Inertia, Mass, Velocity};
use {BodyPose, NextFrame};
pub fn next_frame_integration<'a, D, P, A, I, R>(data: D, dt: P::Scalar)
where
D: Iterator<
Item = (
&'a mut NextFrame<Velocity<P::Diff, A>>,
&'a NextFrame<BodyPose<P, R>>,
&'a mut ForceAccumulator<P::Diff, A>,
&'a Mass<P::Scalar, I>,
),
>,
P: EuclideanSpace + 'a,
P::Scalar: BaseFloat,
P::Diff: VectorSpace + InnerSpace + 'a,
I: Inertia<Orientation = R> + Mul<A, Output = A> + 'a,
A: Mul<P::Scalar, Output = A> + Clone + Copy + Zero + 'a,
R: Rotation<P> + ApplyAngular<P::Scalar, A> + 'a,
{
for (next_velocity, next_pose, force, mass) in data {
let a = force.consume_force() * mass.inverse_mass();
let new_velocity = *next_velocity.value.linear() + a * dt;
next_velocity.value.set_linear(new_velocity);
let a = mass.world_inverse_inertia(next_pose.value.rotation()) * force.consume_torque();
let new_velocity = *next_velocity.value.angular() + a * dt;
next_velocity.value.set_angular(new_velocity);
}
}
pub fn next_frame_pose<'a, D, P, A, R>(data: D, dt: P::Scalar)
where
D: Iterator<
Item = (
&'a NextFrame<Velocity<P::Diff, A>>,
&'a BodyPose<P, R>,
&'a mut NextFrame<BodyPose<P, R>>,
),
>,
P: EuclideanSpace + 'a,
P::Scalar: BaseFloat,
P::Diff: VectorSpace + InnerSpace + 'a,
A: Mul<P::Scalar, Output = A> + Clone + Copy + Zero + 'a,
R: Rotation<P> + ApplyAngular<P::Scalar, A> + 'a,
{
for (next_velocity, pose, next_pose) in data {
next_pose.value = next_velocity.value.apply(pose, dt)
}
}