use crate::models::{DruckerPrager, DruckerPragerPlasticState, ElasticCoefficients};
use bytemuck::{NoUninit, Pod, Zeroable};
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ParticleModel {
ElasticLinear(ElasticCoefficients),
ElasticNeoHookean(ElasticCoefficients),
SandLinear(SandModel),
SandNeoHookean(SandModel),
}
impl Default for ParticleModel {
fn default() -> Self {
Self::elastic(Self::DEFAULT_YOUNG_MODULUS, Self::DEFAULT_POISSON_RATIO)
}
}
impl ParticleModel {
pub const DEFAULT_YOUNG_MODULUS: f32 = 1_000.0;
pub const DEFAULT_POISSON_RATIO: f32 = 0.2;
pub fn elastic(young_modulus: f32, poisson_ratio: f32) -> Self {
Self::ElasticLinear(ElasticCoefficients::from_young_modulus(
young_modulus,
poisson_ratio,
))
}
pub fn elastic_neo_hookean(young_modulus: f32, poisson_ratio: f32) -> Self {
Self::ElasticNeoHookean(ElasticCoefficients::from_young_modulus(
young_modulus,
poisson_ratio,
))
}
pub fn sand(young_modulus: f32, poisson_ratio: f32) -> Self {
ParticleModel::SandLinear(SandModel {
plastic_state: DruckerPragerPlasticState::default(),
plastic: DruckerPrager::new(young_modulus, poisson_ratio),
elastic: ElasticCoefficients::from_young_modulus(young_modulus, poisson_ratio),
})
}
pub fn sand_neo_hookean(young_modulus: f32, poisson_ratio: f32) -> Self {
ParticleModel::SandNeoHookean(SandModel {
plastic_state: DruckerPragerPlasticState::default(),
plastic: DruckerPrager::new(young_modulus, poisson_ratio),
elastic: ElasticCoefficients::from_young_modulus(young_modulus, poisson_ratio),
})
}
}
#[derive(Copy, Clone, Debug, PartialEq, NoUninit)]
#[repr(u32)]
pub enum GpuParticleModel {
ElasticLinear(ElasticCoefficients, [u32; 9]) = 0,
ElasticNeoHookean(ElasticCoefficients, [u32; 9]) = 1,
SandLinear(SandModel) = 2,
SandNeoHookean(SandModel) = 3,
}
static_assertions::assert_eq_size!(GpuParticleModel, [u8; 52]);
impl From<ParticleModel> for GpuParticleModel {
fn from(val: ParticleModel) -> Self {
match val {
ParticleModel::ElasticLinear(elastic_linear) => {
GpuParticleModel::ElasticLinear(elastic_linear, [0; _])
}
ParticleModel::ElasticNeoHookean(elastic_neo_hookean) => {
GpuParticleModel::ElasticNeoHookean(elastic_neo_hookean, [0; _])
}
ParticleModel::SandLinear(sand_linear) => GpuParticleModel::SandLinear(sand_linear),
ParticleModel::SandNeoHookean(sand_neo_hookean) => {
GpuParticleModel::SandNeoHookean(sand_neo_hookean)
}
}
}
}
impl From<GpuParticleModel> for ParticleModel {
fn from(val: GpuParticleModel) -> Self {
match val {
GpuParticleModel::ElasticLinear(elastic_linear, _) => {
ParticleModel::ElasticLinear(elastic_linear)
}
GpuParticleModel::ElasticNeoHookean(elastic_neo_hookean, _) => {
ParticleModel::ElasticNeoHookean(elastic_neo_hookean)
}
GpuParticleModel::SandLinear(sand_linear) => ParticleModel::SandLinear(sand_linear),
GpuParticleModel::SandNeoHookean(sand_neo_hookean) => {
ParticleModel::SandNeoHookean(sand_neo_hookean)
}
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Pod, Zeroable)]
#[repr(C)]
pub struct SandModel {
pub plastic_state: DruckerPragerPlasticState,
pub plastic: DruckerPrager,
pub elastic: ElasticCoefficients,
}
pub trait GpuParticleModelData: NoUninit + Send + Sync {
type Model: Copy;
fn from_model(model: Self::Model) -> Self;
fn specialization_modules() -> Vec<String>;
}
impl GpuParticleModelData for GpuParticleModel {
type Model = ParticleModel;
fn specialization_modules() -> Vec<String> {
vec!["slosh::models::specializations".to_string()]
}
fn from_model(model: Self::Model) -> Self {
model.into()
}
}