fix: kak tmpfiles
This commit is contained in:
@@ -1,298 +0,0 @@
|
|||||||
use nalgebra::Vector3;
|
|
||||||
use rapier3d::prelude::*;
|
|
||||||
use std::collections::VecDeque;
|
|
||||||
use std::f32;
|
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, Copy)]
|
|
||||||
pub struct ConfigBuilder {
|
|
||||||
pub young: f32,
|
|
||||||
pub poisson: f32,
|
|
||||||
pub density: Option<f32>,
|
|
||||||
pub mass: Option<f32>,
|
|
||||||
|
|
||||||
pub h: Option<f32>,
|
|
||||||
pub r: Option<f32>,
|
|
||||||
|
|
||||||
pub pos: Option<Vector3<f32>>,
|
|
||||||
pub segments: Option<u64>,
|
|
||||||
pub up: Option<bool>,
|
|
||||||
|
|
||||||
pub damping: Option<f32>,
|
|
||||||
pub collision_group: Option<InteractionGroups>,
|
|
||||||
pub top_joint: Option<(RigidBodyHandle, Vector3<f32>)>,
|
|
||||||
pub bot_joint: Option<(RigidBodyHandle, Vector3<f32>)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ConfigBuilder> for Config {
|
|
||||||
fn from(b: ConfigBuilder) -> Config {
|
|
||||||
let (
|
|
||||||
damping,
|
|
||||||
density,
|
|
||||||
mass,
|
|
||||||
h,
|
|
||||||
segments,
|
|
||||||
pos,
|
|
||||||
r,
|
|
||||||
up,
|
|
||||||
top_joint,
|
|
||||||
bot_joint,
|
|
||||||
collision_group,
|
|
||||||
) = (
|
|
||||||
b.damping.unwrap_or(0.0),
|
|
||||||
b.density,
|
|
||||||
b.mass,
|
|
||||||
b.h.unwrap_or(1.0),
|
|
||||||
b.segments.unwrap_or(10),
|
|
||||||
b.pos.unwrap_or(Vector::zeros()),
|
|
||||||
b.r.unwrap_or(0.5),
|
|
||||||
b.up.unwrap_or(true),
|
|
||||||
b.top_joint,
|
|
||||||
b.bot_joint,
|
|
||||||
b.collision_group,
|
|
||||||
);
|
|
||||||
|
|
||||||
let seg_h = h / (segments as f32);
|
|
||||||
let k_rot = cyl_beam_spring_rot(r, seg_h, b.young);
|
|
||||||
|
|
||||||
Config {
|
|
||||||
up,
|
|
||||||
k_rot,
|
|
||||||
damping,
|
|
||||||
density,
|
|
||||||
mass,
|
|
||||||
h,
|
|
||||||
seg_h,
|
|
||||||
segments,
|
|
||||||
pos,
|
|
||||||
r,
|
|
||||||
top_joint,
|
|
||||||
bot_joint,
|
|
||||||
collision_group,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, Copy)]
|
|
||||||
pub struct Config {
|
|
||||||
pub k_rot: f32,
|
|
||||||
pub damping: f32,
|
|
||||||
pub density: Option<f32>,
|
|
||||||
pub mass: Option<f32>,
|
|
||||||
pub pos: Vector3<f32>,
|
|
||||||
pub h: f32,
|
|
||||||
pub up: bool,
|
|
||||||
pub seg_h: f32,
|
|
||||||
pub segments: u64,
|
|
||||||
pub r: f32,
|
|
||||||
pub collision_group: Option<InteractionGroups>,
|
|
||||||
pub top_joint: Option<(RigidBodyHandle, Vector3<f32>)>,
|
|
||||||
pub bot_joint: Option<(RigidBodyHandle, Vector3<f32>)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Handle(pub Config, VecDeque<RigidBodyHandle>);
|
|
||||||
|
|
||||||
impl Handle {
|
|
||||||
pub fn segs(&self) -> impl Iterator<Item = &RigidBodyHandle> {
|
|
||||||
self.1.iter()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn top(&self) -> RigidBodyHandle {
|
|
||||||
*self.1.back().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn bot(&self) -> RigidBodyHandle {
|
|
||||||
*self.1.front().unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spawn(
|
|
||||||
bodies: &mut RigidBodySet,
|
|
||||||
colliders: &mut ColliderSet,
|
|
||||||
impulse_joints: &mut ImpulseJointSet,
|
|
||||||
multibodies: &mut MultibodyJointSet,
|
|
||||||
cfg: impl Into<Config>,
|
|
||||||
) -> Handle {
|
|
||||||
let cfg = cfg.into();
|
|
||||||
|
|
||||||
let start = cfg.pos;
|
|
||||||
let end = cfg.pos - vector![0.0, cfg.h, 0.0];
|
|
||||||
let y = vector![0.0, cfg.seg_h, 0.0];
|
|
||||||
let y_half = y / 2.0;
|
|
||||||
|
|
||||||
let mut coll = ColliderBuilder::cylinder(cfg.seg_h / 2.0, cfg.r);
|
|
||||||
if let Some(coll_group) = cfg.collision_group {
|
|
||||||
coll = coll.collision_groups(coll_group);
|
|
||||||
};
|
|
||||||
|
|
||||||
match (cfg.density, cfg.mass) {
|
|
||||||
(Some(density), _) => coll = coll.density(density),
|
|
||||||
(_, Some(mass)) => coll = coll.mass(mass / cfg.segments as f32),
|
|
||||||
_ => (),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut pos = if cfg.up { end + y_half } else { start - y_half };
|
|
||||||
let pos_delta = if cfg.up { y } else { -y };
|
|
||||||
|
|
||||||
let jnts: Vec<GenericJoint> = {
|
|
||||||
let b = Spheri_rot_rot_rot_rotointBuilder::new()
|
|
||||||
.contacts_enabled(false)
|
|
||||||
.motor_position(JointAxis::AngZ, 0.0, cfg.k_rot, cfg.damping)
|
|
||||||
.motor_position(JointAxis::AngX, 0.0, cfg.k_rot, cfg.damping);
|
|
||||||
|
|
||||||
/*
|
|
||||||
[
|
|
||||||
0.0,
|
|
||||||
1.0 / 2.0 * f32::consts::PI,
|
|
||||||
f32::consts::PI,
|
|
||||||
3.0 / 2.0 * f32::consts::PI,
|
|
||||||
]
|
|
||||||
.into_iter()
|
|
||||||
.map(|t| (t.cos() * cfg.r, t.sin() * cfg.r))
|
|
||||||
*/
|
|
||||||
core::iter::once((0.0, 0.0))
|
|
||||||
.map(|(x, z)| {
|
|
||||||
if cfg.up {
|
|
||||||
((x, y_half.y, z), (x, -y_half.y, z))
|
|
||||||
} else {
|
|
||||||
((x, -y_half.y, z), (x, y_half.y, z))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map(|((ax, ay, az), (bx, by, bz))| {
|
|
||||||
b.clone()
|
|
||||||
.local_anchor1(Point::from(vector![ax, ay, az]))
|
|
||||||
.local_anchor2(Point::from(vector![bx, by, bz]))
|
|
||||||
.build()
|
|
||||||
.into()
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut ents = VecDeque::new();
|
|
||||||
let mut prev = None;
|
|
||||||
for n in 0..cfg.segments {
|
|
||||||
let rb = bodies.insert(RigidBodyBuilder::dynamic().translation(pos).angular_damping(cfg.damping).linear_damping(cfg.damping) );
|
|
||||||
colliders.insert_with_parent(coll.clone(), rb, bodies);
|
|
||||||
if cfg.up {
|
|
||||||
ents.push_back(rb)
|
|
||||||
} else {
|
|
||||||
ents.push_front(rb)
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(prev) = prev {
|
|
||||||
jnts.iter().cloned().for_each(|jnt| {
|
|
||||||
multibodies.insert(prev, rb, jnt.clone(), true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
struct _A {
|
|
||||||
first: bool,
|
|
||||||
last: bool,
|
|
||||||
up: bool,
|
|
||||||
bot_joint: Option<(RigidBodyHandle, Vector3<Real>)>,
|
|
||||||
top_joint: Option<(RigidBodyHandle, Vector3<Real>)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
let _a = _A {
|
|
||||||
first: n == 0,
|
|
||||||
last: n == cfg.segments - 1,
|
|
||||||
up: cfg.up,
|
|
||||||
bot_joint: cfg.bot_joint,
|
|
||||||
top_joint: cfg.top_joint,
|
|
||||||
};
|
|
||||||
|
|
||||||
let jnt = |a, b| {
|
|
||||||
GenericJoint::from(
|
|
||||||
FixedJointBuilder::new()
|
|
||||||
.local_anchor1(Point::from(a))
|
|
||||||
.local_anchor2(Point::from(b))
|
|
||||||
.contacts_enabled(false)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
match _a {
|
|
||||||
_A {
|
|
||||||
first: true,
|
|
||||||
up: true,
|
|
||||||
bot_joint: Some((b, pos)),
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
multibodies.insert(b, rb, jnt(pos, -y_half), true);
|
|
||||||
}
|
|
||||||
_A {
|
|
||||||
first: true,
|
|
||||||
up: false,
|
|
||||||
top_joint: Some((b, pos)),
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
multibodies.insert(b, rb, jnt(pos, y_half), true);
|
|
||||||
}
|
|
||||||
_A {
|
|
||||||
last: true,
|
|
||||||
up: true,
|
|
||||||
top_joint: Some((b, pos)),
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
multibodies.insert(rb, b, jnt(y_half, pos), true);
|
|
||||||
}
|
|
||||||
_A {
|
|
||||||
last: true,
|
|
||||||
up: false,
|
|
||||||
bot_joint: Some((b, pos)),
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
multibodies.insert(rb, b, jnt(-y_half, pos), true);
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
prev = Some(rb);
|
|
||||||
pos += pos_delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
Handle(cfg, ents)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// linear stiffness
|
|
||||||
fn cyl_beam_spring_rot(r: f32, length: f32, young: f32) -> f32 {
|
|
||||||
// Bending Stiffness
|
|
||||||
// The bending stiffness (EI) of a beam (slice) is given by:
|
|
||||||
// EI = E * (π * r^4) / 4
|
|
||||||
// Rotational Spring Constant
|
|
||||||
// Using the bending stiffness, the rotational spring constant (k_rot) about the axes perpendicular to the long axis can be approximated as:
|
|
||||||
// k_rot ≈ EI / L
|
|
||||||
// Substituting EI:
|
|
||||||
// k_rot ≈ (E * (π * r^4) / 4) / L
|
|
||||||
// k_rot ≈ (E * π * r^4) / (4 * L)
|
|
||||||
let i: f32 = f32::consts::PI * r.powi(4);
|
|
||||||
(young * i) / (4.0 * length)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// shear stiffness
|
|
||||||
fn cyl_beam_spring_xz(r: f32, length: f32, young: f32, poisson: f32) -> f32 {
|
|
||||||
// Given:
|
|
||||||
// poisson ratio, v
|
|
||||||
// young's modulus, E
|
|
||||||
// shear modulus, G
|
|
||||||
//
|
|
||||||
// G = E / (2 * (1 + v))
|
|
||||||
//
|
|
||||||
// Given material of length L,
|
|
||||||
// cross-sectional area A,
|
|
||||||
// force F required to deform material
|
|
||||||
// by dL orthogonal to L axis is:
|
|
||||||
//
|
|
||||||
// G = (F / A) / (dL / L)
|
|
||||||
// G = (F * L) / (A * dL)
|
|
||||||
// G = (F * L) / (A * dL)
|
|
||||||
// F = (GA / L) * dL
|
|
||||||
//
|
|
||||||
// Given Hooke's Law of form F = kx, let x = dL
|
|
||||||
// k = GA / L
|
|
||||||
|
|
||||||
// shear modulus
|
|
||||||
let g: f32 = young / (2.0 * (1.0 + poisson));
|
|
||||||
let a: f32 = f32::consts::PI * r.powi(2);
|
|
||||||
(g * a) / length
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user