rhusics_ecs/physics/systems/
next_frame.rs

1use std::fmt::Debug;
2use std::marker;
3use std::ops::Mul;
4
5use cgmath::{BaseFloat, EuclideanSpace, InnerSpace, Rotation, VectorSpace, Zero};
6use core::{
7    next_frame_integration, next_frame_pose, ApplyAngular, ForceAccumulator, Inertia, Mass,
8    NextFrame, PhysicalEntity, PhysicsTime, Pose, Velocity, WorldParameters,
9};
10use specs::prelude::{Component, Join, Read, ReadStorage, System, WriteStorage};
11
12/// Setup the next frames positions and velocities.
13///
14/// ### Type parameters:
15///
16/// - `P`: Positional quantity, usually `Point2` or `Point3`
17/// - `R`: Rotational quantity, usually `Basis2` or `Quaternion`
18/// - `I`: Inertia, usually `Scalar` or `Matrix3`
19/// - `A`: Angular velocity, usually `Scalar` or `Vector3`
20/// - `T`: Transform type (`BodyPose2` or similar)
21///
22/// ### System function
23///
24/// `fn(DeltaTime, Mass, T, ForceAccumulator) -> (ForceAccumulator, NextFrame<Velocity>, NextFrame<T>)`
25pub struct NextFrameSetupSystem<P, R, I, A, T, D> {
26    m: marker::PhantomData<(P, R, I, A, T, D)>,
27}
28
29impl<P, R, I, A, T, D> NextFrameSetupSystem<P, R, I, A, T, D>
30where
31    T: Pose<P, R>,
32    P: EuclideanSpace,
33    P::Scalar: BaseFloat,
34    P::Diff: VectorSpace + InnerSpace + Debug,
35    R: Rotation<P> + ApplyAngular<P::Scalar, A>,
36    I: Inertia<Orientation = R> + Mul<A, Output = A>,
37    A: Mul<P::Scalar, Output = A> + Zero + Clone + Copy,
38    D: PhysicsTime<P::Scalar> + Default,
39{
40    /// Create system.
41    pub fn new() -> Self {
42        Self {
43            m: marker::PhantomData,
44        }
45    }
46}
47
48impl<'a, P, R, I, A, T, D> System<'a> for NextFrameSetupSystem<P, R, I, A, T, D>
49where
50    T: Pose<P, R> + Component + Send + Sync + 'static,
51    P: EuclideanSpace + Send + Sync + 'static,
52    P::Scalar: BaseFloat + Send + Sync + 'static,
53    P::Diff: VectorSpace + InnerSpace + Debug + Send + Sync + 'static,
54    R: Rotation<P> + ApplyAngular<P::Scalar, A> + Send + Sync + 'static,
55    I: Inertia<Orientation = R> + Mul<A, Output = A> + Send + Sync + 'static,
56    A: Mul<P::Scalar, Output = A> + Zero + Clone + Copy + Send + Sync + 'static,
57    D: PhysicsTime<P::Scalar> + Default + Send + Sync + 'static,
58{
59    type SystemData = (
60        Read<'a, D>,
61        Read<'a, WorldParameters<P::Diff, P::Scalar>>,
62        ReadStorage<'a, PhysicalEntity<P::Scalar>>,
63        ReadStorage<'a, Mass<P::Scalar, I>>,
64        WriteStorage<'a, NextFrame<Velocity<P::Diff, A>>>,
65        ReadStorage<'a, T>,
66        WriteStorage<'a, NextFrame<T>>,
67        WriteStorage<'a, ForceAccumulator<P::Diff, A>>,
68    );
69
70    fn run(&mut self, data: Self::SystemData) {
71        let (
72            time,
73            params,
74            entities,
75            masses,
76            mut next_velocities,
77            poses,
78            mut next_poses,
79            mut forces,
80        ) = data;
81
82        // Do force integration
83        next_frame_integration(
84            (
85                &mut next_velocities,
86                &next_poses,
87                &mut forces,
88                &masses,
89                &entities,
90            )
91                .join(),
92            &*params,
93            time.delta_seconds(),
94        );
95
96        // Compute next frames position
97        next_frame_pose(
98            (&next_velocities, &poses, &mut next_poses, &entities).join(),
99            time.delta_seconds(),
100        );
101    }
102}