bevy_transform_interpolation::hermite

Struct TransformHermiteEasingPlugin

source
pub struct TransformHermiteEasingPlugin<LinVel: VelocitySource, AngVel: VelocitySource>(/* private fields */);
Expand description

A Hermite interpolation plugin for Transform easing.

By default, TransformInterpolationPlugin and TransformExtrapolationPlugin use linear interpolation (lerp) for easing translation and scale, and spherical linear interpolation (slerp) for easing rotation. This is computationally efficient and works well for most cases.

However, for more accurate and reliable easing that works at arbitrary velocities, it may be preferable to use Hermite interpolation. It uses both position and velocity information to estimate the trajectories of entities, producing smoother results.

This plugin should be used alongside the TransformInterpolationPlugin and/or TransformExtrapolationPlugin. The TransformEasingPlugin is also required, and it is automatically added if not already present in the app.

§Usage

Hermite interpolation requires velocity to produce accurate curves. Instead of providing its own velocity components, the TransformHermiteEasingPlugin lets you specify your own velocity components that you manage yourself.

First, make sure you have components for the previous and current velocity, and implement the VelocitySource trait on a QueryData type:

use bevy::{ecs::query::QueryData, prelude::*};
use bevy_transform_interpolation::VelocitySource;

#[derive(Component, Default)]
struct PreviousLinearVelocity(Vec3);

#[derive(Component, Default)]
struct PreviousAngularVelocity(Vec3);

#[derive(Component, Default)]
struct LinearVelocity(Vec3);

#[derive(Component, Default)]
struct AngularVelocity(Vec3);

#[derive(QueryData)]
struct LinVelSource;

impl VelocitySource for LinVelSource {
    // Components storing the previous and current velocities.
    type Previous = PreviousLinearVelocity;
    type Current = LinearVelocity;

    fn previous(start: &Self::Previous) -> Vec3 {
        start.0
    }

    fn current(end: &Self::Current) -> Vec3 {
        end.0
    }
}

#[derive(QueryData)]
struct AngVelSource;

impl VelocitySource for AngVelSource {
    type Previous = PreviousAngularVelocity;
    type Current = AngularVelocity;

    fn previous(start: &Self::Previous) -> Vec3 {
        start.0
    }

    fn current(end: &Self::Current) -> Vec3 {
        end.0
    }
}

Then, add the TransformHermiteEasingPlugin to the app with the velocity sources, along with the TransformInterpolationPlugin and/or TransformExtrapolationPlugin:

use bevy::{ecs::query::QueryData, prelude::*};
use bevy_transform_interpolation::{prelude::*, VelocitySource};

fn main() {
   let mut app = App::new();

    app.add_plugins((
       TransformInterpolationPlugin::default(),
       TransformHermiteEasingPlugin::<LinVelSource, AngVelSource>::default(),
   ));

   // Optional: Insert velocity components automatically for entities with Hermite interpolation.
   app.register_required_components::<TranslationHermiteEasing, LinearVelocity>();
   app.register_required_components::<TranslationHermiteEasing, PreviousLinearVelocity>();
   app.register_required_components::<RotationHermiteEasing, AngularVelocity>();
   app.register_required_components::<RotationHermiteEasing, PreviousAngularVelocity>();

   // ...

   app.run();
}

Hermite interpolation can now be used for any interpolated or extrapolated entity that has the velocity components by adding the TransformHermiteEasing component:

fn setup(mut commands: Commands) {
    // Use Hermite interpolation for interpolating translation and rotation.
    commands.spawn((
        Transform::default(),
        TransformInterpolation,
        TransformHermiteEasing,
    ));
}

Hermite interpolation can also be used for translation and rotation separately:

fn setup(mut commands: Commands) {
    // Use Hermite interpolation for interpolating translation.
    commands.spawn((
        Transform::default(),
        TranslationInterpolation,
        TranslationHermiteEasing,
    ));

    // Use Hermite interpolation for interpolating rotation.
    commands.spawn((
        Transform::default(),
        RotationInterpolation,
        RotationHermiteEasing,
    ));
}

Trait Implementations§

source§

impl<LinVel: Debug + VelocitySource, AngVel: Debug + VelocitySource> Debug for TransformHermiteEasingPlugin<LinVel, AngVel>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<LinVel: VelocitySource, AngVel: VelocitySource> Default for TransformHermiteEasingPlugin<LinVel, AngVel>

source§

fn default() -> Self

Returns the “default value” for a type. Read more
source§

impl<LinVel: VelocitySource, AngVel: VelocitySource> Plugin for TransformHermiteEasingPlugin<LinVel, AngVel>

source§

fn build(&self, app: &mut App)

Configures the App to which this plugin is added.
source§

fn ready(&self, _app: &App) -> bool

Has the plugin finished its setup? This can be useful for plugins that need something asynchronous to happen before they can finish their setup, like the initialization of a renderer. Once the plugin is ready, finish should be called.
source§

fn finish(&self, _app: &mut App)

Finish adding this plugin to the App, once all plugins registered are ready. This can be useful for plugins that depends on another plugin asynchronous setup, like the renderer.
source§

fn cleanup(&self, _app: &mut App)

Runs after all plugins are built and finished, but before the app schedule is executed. This can be useful if you have some resource that other plugins need during their build step, but after build you want to remove it and send it to another thread.
source§

fn name(&self) -> &str

Configures a name for the Plugin which is primarily used for checking plugin uniqueness and debugging.
source§

fn is_unique(&self) -> bool

If the plugin can be meaningfully instantiated several times in an App, override this method to return false.

Auto Trait Implementations§

§

impl<LinVel, AngVel> Freeze for TransformHermiteEasingPlugin<LinVel, AngVel>

§

impl<LinVel, AngVel> RefUnwindSafe for TransformHermiteEasingPlugin<LinVel, AngVel>
where LinVel: RefUnwindSafe, AngVel: RefUnwindSafe,

§

impl<LinVel, AngVel> Send for TransformHermiteEasingPlugin<LinVel, AngVel>

§

impl<LinVel, AngVel> Sync for TransformHermiteEasingPlugin<LinVel, AngVel>

§

impl<LinVel, AngVel> Unpin for TransformHermiteEasingPlugin<LinVel, AngVel>
where LinVel: Unpin, AngVel: Unpin,

§

impl<LinVel, AngVel> UnwindSafe for TransformHermiteEasingPlugin<LinVel, AngVel>
where LinVel: UnwindSafe, AngVel: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T, U> AsBindGroupShaderType<U> for T
where U: ShaderType, &'a T: for<'a> Into<U>,

source§

fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U

Return the T ShaderType for self. When used in AsBindGroup derives, it is safe to assume that all images in self exist.
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> Downcast<T> for T

source§

fn downcast(&self) -> &T

source§

impl<T> Downcast for T
where T: Any,

source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> FromWorld for T
where T: Default,

source§

fn from_world(_world: &mut World) -> T

Creates Self using default().

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> Upcast<T> for T

source§

fn upcast(&self) -> Option<&T>

source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

source§

fn vzip(self) -> V

source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

impl<T> ConditionalSend for T
where T: Send,

source§

impl<Marker, T> Plugins<Marker> for T
where T: Plugins<Marker>,

source§

impl<T> Settings for T
where T: 'static + Send + Sync,

source§

impl<T> WasmNotSend for T
where T: Send,

source§

impl<T> WasmNotSendSync for T

source§

impl<T> WasmNotSync for T
where T: Sync,