use serde::{Deserialize, Serialize};
use crate::assets::asset::AssetUuid;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
pub enum SceneBodyType {
#[default]
Static,
Dynamic,
KinematicPositionBased,
KinematicVelocityBased,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ScenePhysics {
pub body_type: SceneBodyType,
pub collider: SceneCollider,
#[serde(default = "default_friction")]
pub friction: f32,
#[serde(default = "default_restitution")]
pub restitution: f32,
#[serde(default)]
pub mass: Option<f32>,
#[serde(default)]
pub is_sensor: bool,
#[serde(default = "default_collision_membership")]
pub collision_membership: u32,
#[serde(default = "default_collision_filter")]
pub collision_filter: u32,
#[serde(default = "default_solver_membership")]
pub solver_membership: u32,
#[serde(default = "default_solver_filter")]
pub solver_filter: u32,
#[serde(default)]
pub locked_axes: u8,
#[serde(default)]
pub linvel: [f32; 3],
#[serde(default)]
pub angvel: [f32; 3],
}
fn default_collision_membership() -> u32 {
0xFFFFFFFF
}
fn default_collision_filter() -> u32 {
0xFFFFFFFF
}
fn default_solver_membership() -> u32 {
0xFFFFFFFF
}
fn default_solver_filter() -> u32 {
0xFFFFFFFF
}
fn default_friction() -> f32 {
0.8
}
fn default_restitution() -> f32 {
0.1
}
impl Default for ScenePhysics {
fn default() -> Self {
Self {
body_type: SceneBodyType::Static,
collider: SceneCollider::Cuboid {
half_extents: [0.5, 0.5, 0.5],
},
friction: default_friction(),
restitution: default_restitution(),
mass: None,
is_sensor: false,
collision_membership: default_collision_membership(),
collision_filter: default_collision_filter(),
solver_membership: default_solver_membership(),
solver_filter: default_solver_filter(),
locked_axes: 0,
linvel: [0.0, 0.0, 0.0],
angvel: [0.0, 0.0, 0.0],
}
}
}
impl ScenePhysics {
pub fn static_cuboid(half_extents: [f32; 3]) -> Self {
Self {
collider: SceneCollider::Cuboid { half_extents },
..Default::default()
}
}
pub fn dynamic_ball(radius: f32, mass: f32) -> Self {
Self {
body_type: SceneBodyType::Dynamic,
collider: SceneCollider::Ball { radius },
friction: 0.7,
restitution: 0.3,
mass: Some(mass),
..Default::default()
}
}
pub fn dynamic_cuboid(half_extents: [f32; 3], mass: f32) -> Self {
Self {
body_type: SceneBodyType::Dynamic,
collider: SceneCollider::Cuboid { half_extents },
friction: 0.7,
restitution: 0.2,
mass: Some(mass),
..Default::default()
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SceneJoint {
Fixed {
parent_anchor: [f32; 3],
child_anchor: [f32; 3],
},
Revolute {
parent_anchor: [f32; 3],
child_anchor: [f32; 3],
axis: [f32; 3],
#[serde(default)]
limits: Option<[f32; 2]>,
},
Prismatic {
parent_anchor: [f32; 3],
child_anchor: [f32; 3],
axis: [f32; 3],
#[serde(default)]
limits: Option<[f32; 2]>,
},
Spherical {
parent_anchor: [f32; 3],
child_anchor: [f32; 3],
},
Rope {
parent_anchor: [f32; 3],
child_anchor: [f32; 3],
max_distance: f32,
},
Spring {
parent_anchor: [f32; 3],
child_anchor: [f32; 3],
rest_length: f32,
stiffness: f32,
damping: f32,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SceneJointConnection {
pub parent_entity: AssetUuid,
pub child_entity: AssetUuid,
pub joint: SceneJoint,
#[serde(default)]
pub collisions_enabled: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SceneCollider {
Cuboid {
half_extents: [f32; 3],
},
Ball {
radius: f32,
},
Cylinder {
half_height: f32,
radius: f32,
},
Capsule {
half_height: f32,
radius: f32,
},
TriMesh {
vertices: Vec<[f32; 3]>,
indices: Vec<[u32; 3]>,
},
ConvexHull {
points: Vec<[f32; 3]>,
},
Cone {
half_height: f32,
radius: f32,
},
HeightField {
nrows: usize,
ncols: usize,
heights: Vec<f32>,
scale: [f32; 3],
},
}