spacetime_physics 0.1.1

Physics engine for SpacetimeDB
Documentation
use std::fmt::Display;

use bon::{builder, Builder};
use parry3d::na::Isometry3;
use spacetimedb::{table, ReducerContext, SpacetimeType, Table};

use crate::math::{Quat, Vec3};

pub type RigidBodyId = u64;

#[derive(SpacetimeType, Debug, Clone, Copy, PartialEq, Default)]
pub enum RigidBodyType {
    Static,
    #[default]
    Dynamic,
    Kinematic,
}

#[table(name = physics_rigid_bodies, public)]
#[derive(Builder, Clone, Copy, Debug, Default, PartialEq)]
#[builder(derive(Debug, Clone))]
pub struct RigidBody {
    #[primary_key]
    #[auto_inc]
    #[builder(default = 0)]
    pub id: u64,
    #[index(btree)]
    #[builder(default = 1)]
    pub world_id: u64,
    #[builder(default = Vec3::ZERO)]
    pub position: Vec3,
    #[builder(default = Quat::IDENTITY)]
    pub rotation: Quat,
    #[builder(default = Vec3::ZERO)]
    pub linear_velocity: Vec3,
    #[builder(default = Vec3::ZERO)]
    pub angular_velocity: Vec3,

    #[builder(default = Vec3::ZERO)]
    pub force: Vec3,

    #[builder(default = Vec3::ZERO)]
    pub torque: Vec3,

    #[builder(default = RigidBodyType::default())]
    pub body_type: RigidBodyType,

    pub collider_id: u64,
    pub properties_id: u64,
}

impl RigidBody {
    pub fn insert(self, ctx: &ReducerContext) -> Self {
        ctx.db.physics_rigid_bodies().insert(self)
    }

    pub fn find(ctx: &ReducerContext, id: u64) -> Option<Self> {
        ctx.db.physics_rigid_bodies().id().find(id)
    }

    pub fn all(ctx: &ReducerContext, world_id: u64) -> impl Iterator<Item = RigidBody> {
        ctx.db.physics_rigid_bodies().world_id().filter(world_id)
    }

    pub fn update(self, ctx: &ReducerContext) -> Self {
        ctx.db.physics_rigid_bodies().id().update(self)
    }

    pub fn delete(&self, ctx: &ReducerContext) {
        ctx.db.physics_rigid_bodies().id().delete(self.id);
    }

    pub fn delte_by_id(ctx: &ReducerContext, id: u64) {
        ctx.db.physics_rigid_bodies().id().delete(id);
    }

    pub fn is_dynamic(&self) -> bool {
        self.body_type == RigidBodyType::Dynamic
    }

    pub fn is_kinematic(&self) -> bool {
        self.body_type == RigidBodyType::Kinematic
    }
}

impl Display for RigidBody {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "RigidBody(id={}, world_id={}, position={}, orientation={}, velocity={}, force={})",
            self.id, self.world_id, self.position, self.rotation, self.linear_velocity, self.force
        )
    }
}

impl From<RigidBody> for Isometry3<f32> {
    fn from(value: RigidBody) -> Self {
        Isometry3::from_parts(value.position.into(), value.rotation.into())
    }
}

impl From<&RigidBody> for Isometry3<f32> {
    fn from(value: &RigidBody) -> Self {
        Isometry3::from_parts(value.position.into(), value.rotation.into())
    }
}