physme 0.2.4

A simple 2d and 3d physics engine for bevy
Documentation
//! Commmon type definitions for 2d and 3d physics simulation.
use std::num::FpCategory;

use bevy::prelude::*;
use serde::{Deserialize, Serialize};

/// Extensions to the Bevy `Vec3` type
pub trait Vec3Ext {
    /// Returns the quaternion that describes the rotation from `self` to `other`.
    fn quat_between(&self, other: Vec3) -> Quat;
}

impl Vec3Ext for Vec3 {
    fn quat_between(&self, other: Vec3) -> Quat {
        let dot = self.dot(other);
        if dot > 0.995 || dot < -0.995 {
            return Quat::identity();
        }

        let axis = self.cross(other);
        let angle = (self.length_squared() * other.length_squared()).sqrt() + dot;
        Quat::from_axis_angle(axis, angle)
    }
}

/// The global friction that affects every `RigidBody`, both 2d and 3d.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct GlobalFriction(pub f32);

impl Default for GlobalFriction {
    fn default() -> Self {
        Self(0.95)
    }
}

/// The mass of the object or an infinite mass.
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Property)]
pub enum Mass {
    /// Infinite mass (useful for immobile static objects).
    Infinite,
    /// A real mass (useful for semikinematic and mobile static objects).
    Real(f32),
}

impl Mass {
    /// Get the inverse mass.
    pub fn inverse(self) -> f32 {
        match self {
            Self::Infinite => 0.0,
            Self::Real(mass) => mass.recip(),
        }
    }

    /// Get the scalar mass.
    pub fn scalar(self) -> f32 {
        match self {
            Self::Infinite => 0.0,
            Self::Real(mass) => mass,
        }
    }
}

impl From<f32> for Mass {
    fn from(mass: f32) -> Self {
        match mass.classify() {
            FpCategory::Normal | FpCategory::Subnormal => Mass::Real(mass),
            _ => Mass::Infinite,
        }
    }
}

/// The status of a `RigidBody`
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Property)]
pub enum Status {
    /// Static bodies do not check for collisions.
    ///
    /// They are normally unaffected by forces.
    /// They CAN be mobile, however only if the user sets its force/velocity manually.
    Static,
    /// Semikinematic bodies check for collisions.
    ///
    /// They are affected by forces, like gravity.
    /// Semikinematic bodies behave like kinematic bodies in some cases,
    /// and like dynamic bodies in others.  They have full collision detection with
    /// static bodies and with semikinematic bodies.  Two semikinematic bodies can
    /// push on each other based on their velocity and their mass.  A semikinematic
    /// body may stand on top of another.  Semikinematic bodies can step onto small
    /// static coliders (depending on the global step value).
    Semikinematic,
}

impl Default for Status {
    fn default() -> Self {
        Status::Semikinematic
    }
}