bevy_silk 0.10.0

Cloth physics implementation in bevy
Documentation
use bevy::{math::Vec3, reflect::Reflect};

/// Defines how the cloth will compute sticks from mesh indices.
#[derive(Debug, Copy, Clone, Default, Reflect, PartialEq, Eq)]
pub enum StickGeneration {
    #[default]
    /// 2 sticks will be generated by triangle, following the actual quad edges
    Quads,
    /// 3 sticks will be generated by triangle
    Triangles,
}

/// Defines the target length of cloth sticks
#[derive(Debug, Copy, Clone, Default, Reflect)]
pub enum StickLen {
    #[default]
    /// The target length will be the actual distance between the vertices
    Auto,
    /// Custom target length
    Fixed(f32),
    /// Same as [`StickLen::Auto`] with a custom additional offset
    Offset(f32),
    /// Same as [`StickLen::Auto`] with a custom coefficient
    Coefficient(f32),
}

/// Defines cloth stick behaviour
#[derive(Debug, Copy, Clone, Default, Reflect)]
pub enum StickMode {
    /// The stick will attempt to always remain at the same length (See
    /// [`StickLen`]). This is the default behaviour and the fastest to
    /// compute.
    #[default]
    Fixed,
    /// The stick will clamp its length between a `min_percent` and
    /// `max_percent` of its expected length (See [`StickLen`]).
    ///
    /// For example, the following mode:
    /// ```rust
    /// # use bevy_silk::prelude::*;
    /// let mode = StickMode::Spring {
    ///     min_percent: 0.0,
    ///     max_percent: 1.0,
    /// };
    /// ```
    /// will behave like a [`StickMode::Fixed`].
    ///
    /// # Notes
    ///
    /// * Please note that this mode is slower, as some distance computing
    ///   involving square roots, will happen every frame. If you just want to
    ///   have smaller or larger sticks, prefer setting a different [`StickLen`]
    ///   instead
    /// * Setting invalid `min_percent` and `max_percent` will result in
    ///   unexpected behaviour:
    ///   - max value being lower than the min value
    ///   - use of negative values
    /// * Setting both values to `None` will result in no constraint
    /// * The values are percentages expressed between 0 and 1:
    ///   - `0.0` means 0%
    ///   - `0.5` means 50%
    ///   - `1.0` means 100%
    ///   - `2.0` means 200%
    Spring {
        /// The stick will attempt to be at least this percent of its expected
        /// length.
        min_percent: f32,
        /// The stick will attempt to be at most this percent of its expected
        /// length.
        max_percent: f32,
    },
}

impl StickLen {
    /// Retrieves the stick length from the two points it connects
    #[must_use]
    pub fn get_len(&self, point_a: Vec3, point_b: Vec3) -> f32 {
        match self {
            Self::Auto => point_a.distance(point_b),
            Self::Fixed(v) => *v,
            Self::Offset(offset) => point_a.distance(point_b) + offset,
            Self::Coefficient(coeff) => point_a.distance(point_b) * coeff,
        }
    }
}

impl From<[f32; 2]> for StickMode {
    fn from([min, max]: [f32; 2]) -> Self {
        Self::Spring {
            min_percent: min,
            max_percent: max,
        }
    }
}

impl From<(f32, f32)> for StickMode {
    fn from((min, max): (f32, f32)) -> Self {
        Self::Spring {
            min_percent: min,
            max_percent: max,
        }
    }
}