#![allow(dead_code)]
use super::*;
use crate::body::BodyState;
use crate::distance_joint::{
get_distance_joint_force, prepare_distance_joint, solve_distance_joint,
warm_start_distance_joint,
};
use crate::math_functions::{abs_float, add, length, min_float, Vec2, VEC2_ZERO};
use crate::motor_joint::{
get_motor_joint_force, get_motor_joint_torque, prepare_motor_joint, solve_motor_joint,
warm_start_motor_joint,
};
use crate::prismatic_joint::{
get_prismatic_joint_force, get_prismatic_joint_torque, prepare_prismatic_joint,
solve_prismatic_joint, warm_start_prismatic_joint,
};
use crate::revolute_joint::{
get_revolute_joint_force, get_revolute_joint_torque, prepare_revolute_joint,
solve_revolute_joint, warm_start_revolute_joint,
};
use crate::solver::{make_soft, StepContext};
use crate::weld_joint::{
get_weld_joint_force, get_weld_joint_torque, prepare_weld_joint, solve_weld_joint,
warm_start_weld_joint,
};
use crate::wheel_joint::{
get_wheel_joint_force, get_wheel_joint_torque, prepare_wheel_joint, solve_wheel_joint,
warm_start_wheel_joint,
};
use crate::world::World;
pub fn prepare_joint(world: &World, joint: &mut JointSim, context: &StepContext) {
let hertz = min_float(joint.constraint_hertz, 0.25 * context.inv_h);
joint.constraint_softness = make_soft(hertz, joint.constraint_damping_ratio, context.h);
match joint.joint_type() {
JointType::Distance => prepare_distance_joint(world, joint, context),
JointType::Motor => prepare_motor_joint(world, joint, context),
JointType::Filter => {}
JointType::Prismatic => prepare_prismatic_joint(world, joint, context),
JointType::Revolute => prepare_revolute_joint(world, joint, context),
JointType::Weld => prepare_weld_joint(world, joint, context),
JointType::Wheel => prepare_wheel_joint(world, joint, context),
}
}
pub fn warm_start_joint(joint: &mut JointSim, states: &mut [BodyState]) {
match joint.joint_type() {
JointType::Distance => warm_start_distance_joint(joint, states),
JointType::Motor => warm_start_motor_joint(joint, states),
JointType::Filter => {}
JointType::Prismatic => warm_start_prismatic_joint(joint, states),
JointType::Revolute => warm_start_revolute_joint(joint, states),
JointType::Weld => warm_start_weld_joint(joint, states),
JointType::Wheel => warm_start_wheel_joint(joint, states),
}
}
pub fn solve_joint(
joint: &mut JointSim,
context: &StepContext,
states: &mut [BodyState],
use_bias: bool,
) {
match joint.joint_type() {
JointType::Distance => solve_distance_joint(joint, context, states, use_bias),
JointType::Motor => solve_motor_joint(joint, context, states),
JointType::Filter => {}
JointType::Prismatic => solve_prismatic_joint(joint, context, states, use_bias),
JointType::Revolute => solve_revolute_joint(joint, context, states, use_bias),
JointType::Weld => solve_weld_joint(joint, context, states, use_bias),
JointType::Wheel => solve_wheel_joint(joint, context, states, use_bias),
}
}
pub fn get_joint_reaction(sim: &JointSim, inv_time_step: f32) -> (f32, f32) {
let mut linear_impulse = 0.0;
let mut angular_impulse = 0.0;
match &sim.payload {
JointPayload::Distance(joint) => {
linear_impulse = abs_float(
joint.impulse + joint.lower_impulse - joint.upper_impulse + joint.motor_impulse,
);
}
JointPayload::Motor(joint) => {
linear_impulse = length(add(
joint.linear_velocity_impulse,
joint.linear_spring_impulse,
));
angular_impulse =
abs_float(joint.angular_velocity_impulse + joint.angular_spring_impulse);
}
JointPayload::Prismatic(joint) => {
let perp_impulse = joint.impulse.x;
let axial_impulse = joint.motor_impulse + joint.lower_impulse - joint.upper_impulse;
linear_impulse = (perp_impulse * perp_impulse + axial_impulse * axial_impulse).sqrt();
angular_impulse = abs_float(joint.impulse.y);
}
JointPayload::Revolute(joint) => {
linear_impulse = length(joint.linear_impulse);
angular_impulse =
abs_float(joint.motor_impulse + joint.lower_impulse - joint.upper_impulse);
}
JointPayload::Weld(joint) => {
linear_impulse = length(joint.linear_impulse);
angular_impulse = abs_float(joint.angular_impulse);
}
JointPayload::Wheel(joint) => {
let perp_impulse = joint.perp_impulse;
let axial_impulse = joint.spring_impulse + joint.lower_impulse - joint.upper_impulse;
linear_impulse = (perp_impulse * perp_impulse + axial_impulse * axial_impulse).sqrt();
angular_impulse = abs_float(joint.motor_impulse);
}
JointPayload::Filter => {}
}
(
linear_impulse * inv_time_step,
angular_impulse * inv_time_step,
)
}
pub(crate) fn get_joint_constraint_force(world: &World, joint_index: i32) -> Vec2 {
let base = get_joint_sim_ref(world, joint_index);
match world.joints[joint_index as usize].type_ {
JointType::Distance => get_distance_joint_force(world, base),
JointType::Motor => get_motor_joint_force(world, base),
JointType::Filter => VEC2_ZERO,
JointType::Prismatic => get_prismatic_joint_force(world, base),
JointType::Revolute => get_revolute_joint_force(world, base),
JointType::Weld => get_weld_joint_force(world, base),
JointType::Wheel => get_wheel_joint_force(world, base),
}
}
pub(crate) fn get_joint_constraint_torque(world: &World, joint_index: i32) -> f32 {
let base = get_joint_sim_ref(world, joint_index);
match world.joints[joint_index as usize].type_ {
JointType::Distance => 0.0,
JointType::Motor => get_motor_joint_torque(world, base),
JointType::Filter => 0.0,
JointType::Prismatic => get_prismatic_joint_torque(world, base),
JointType::Revolute => get_revolute_joint_torque(world, base),
JointType::Weld => get_weld_joint_torque(world, base),
JointType::Wheel => get_wheel_joint_torque(world, base),
}
}