added ball joint motor for 3d

This commit is contained in:
Zheng Luo
2025-09-09 14:20:40 -07:00
parent 3feaf705eb
commit c79fca4b75
2 changed files with 67 additions and 23 deletions
+18 -15
View File
@@ -1806,27 +1806,30 @@ impl PhysicsWorld {
convert_joint_params(v, native.data.local_frame1, native.data.local_frame2)
});
joint.motor_params.try_sync_model(|v|{
// The free axis is defined to be the x axis for both prismatic and revolute joints in fyrox.
// For prismatic and revolute joints, the free axis is defined to be the x axis.
// If you want the joint to translate / rotate along a different axis, you can rotate the joint itself.
let joint_axis = match joint.params.get_value_ref(){
JointParams::PrismaticJoint(_) => JointAxis::LinX,
JointParams::RevoluteJoint(_) => JointAxis::AngX,
let joint_axes: &[JointAxis] = match joint.params.get_value_ref(){
JointParams::PrismaticJoint(_) => &[JointAxis::LinX][..], // slice the array to unify arrays of different lengths.
JointParams::RevoluteJoint(_) => &[JointAxis::AngX][..],
JointParams::BallJoint(_) => &[JointAxis::AngX, JointAxis::AngY, JointAxis::AngZ][..],
_ => {
Log::warn("Try to modify motor parameters for unsupported joint type, this operation will be ignored.");
return;
}
};
// Force based motor model is better in the Fyrox's context
native.data.set_motor_model(joint_axis, rapier3d::prelude::MotorModel::ForceBased);
let JointMotorParams {
target_vel,
target_pos,
stiffness,
damping,
max_force
} = v;
native.data.set_motor(joint_axis, target_pos, target_vel, stiffness, damping);
native.data.set_motor_max_force(joint_axis, max_force);
for joint_axis in joint_axes {
// Force based motor model is better in the Fyrox's context
native.data.set_motor_model(*joint_axis, rapier3d::prelude::MotorModel::ForceBased);
let JointMotorParams {
target_vel,
target_pos,
stiffness,
damping,
max_force
} = v;
native.data.set_motor(*joint_axis, target_pos, target_vel, stiffness, damping);
native.data.set_motor_max_force(*joint_axis, max_force);
}
// wake up the bodies connected to the joint to ensure they respond to the motor changes immediately
// however, the rigid bodies may fall asleep any time later unless Joint::set_motor_* functions are called periodically,
// or the rigid bodies are set to cannot sleep
+49 -8
View File
@@ -402,7 +402,7 @@ impl Joint {
/// # Arguments
/// * `force` - The maximum force this motor can deliver.
/// * `max_vel` - The target velocity of the motor.
/// * `damping` - Controls how smoothly the motor will reach the target velocity. A higher damping value will result in a smoother transition to the target velocity.
/// * `damping` - Penalizes high velocities to avoid overshooting the target velocity. A higher damping value will result in a smoother transition to the target velocity.
/// # Errors
/// If the joint is not a [`PrismaticJoint`], this function will do nothing and return an Err.
/// # Notice
@@ -436,7 +436,7 @@ impl Joint {
/// # Arguments
/// * `torque` - The maximum torque this motor can deliver.
/// * `max_angular_vel` - The target angular velocity of the motor.
/// * `damping` - Controls how smoothly the motor will reach the target angular velocity. A higher damping value will result in a smoother transition to the target angular velocity.
/// * `damping` - Penalizes high angular velocities to avoid overshooting the target angular velocity. A higher damping value will result in a smoother transition to the target angular velocity.
/// # Errors
/// If the joint is not a [`RevoluteJoint`], this function will do nothing and return an Err.
/// # Notice
@@ -473,7 +473,7 @@ impl Joint {
/// * `target_position` - The target position that the joint will try to reach, can be negative.
/// * `stiffness` - Controls how fast the joint will try to reach the target position.
/// * `max_force` - The maximum force this motor can deliver.
/// * `damping` - Controls how much the joint will resist motion when it is moving towards the target position.
/// * `damping` - Penalizes high velocities to avoid overshooting the target position. A higher damping value will result in a smoother transition to the target position.
/// # Errors
/// If the joint is not a [`PrismaticJoint`], the function will do nothing and return an Err.
/// # Notice
@@ -511,7 +511,7 @@ impl Joint {
/// * `target_angle` - The target angle **in radians** that the joint will try to reach, can be negative. If the value is greater than 2π or less than -2π, the joint will turn multiple times to reach the target angle.
/// * `stiffness` - Controls how fast the joint will try to reach the target angle.
/// * `max_torque` - The maximum torque this motor can deliver.
/// * `damping` - Controls how much the joint will resist motion when it is moving towards the target angle.
/// * `damping` - Penalizes high angular velocities to avoid overshooting the target angle. A higher damping value will result in a smoother transition to the target angle.
/// # Errors
/// If the joint is not a [`RevoluteJoint`], the function will do nothing and return an Err.
/// # Notice
@@ -540,17 +540,58 @@ impl Joint {
Ok(())
}
/// Disables the motor of the joint assuming it is a [`RevoluteJoint`] or [`PrismaticJoint`].
/// Makes the [`BallJoint`] to restore its original orientation with motor torque.
///
/// Acts as a flexible fixed joint that tolerates some angular movement and tries to restore the original orientation.
///
/// For flexible fixed joints that tolerate some translational movement, consider using a [`PrismaticJoint`] and call [`Self::set_motor_target_position_as_prismatic`].
///
/// The motor torque is uniform across all three axes of the joint.
///
/// /// Call [`Self::disable_motor`] to stop the motor and remove the spring effect.
///
/// # Arguments
/// * `stiffness` - Controls how fast the joint will try to restore its original orientation.
/// * `max_torque` - The maximum torque this motor can deliver.
/// * `damping` - Penalizes high angular velocities to avoid overshooting the original orientation. A higher damping value will result in a smoother transition to the original orientation.
/// # Errors
/// If the joint is not a [`BallJoint`], the function will do nothing and return an Err.
/// # Notice
/// The rigid bodies attached to the joint may fall asleep anytime regardless whether the motor is enabled or not.
///
/// To avoid this behavior, call this function periodically or call [`RigidBody::set_can_sleep`] on the rigid bodies with "false".
pub fn set_motor_resistive_torque_as_ball(
&mut self,
stiffness: f32,
max_torque: f32,
damping: f32,
) -> Result<(), String> {
let JointParams::BallJoint(_) = self.params() else {
return Err("Joint is not a BallJoint".to_string());
};
let motor_params = JointMotorParams {
target_vel: 0.0,
target_pos: 0.0,
stiffness,
damping,
max_force: max_torque,
};
// retrieving the mutable reference to the joint params will cause the engine to do additional calculations to reflect changes to the physics engine.
self.set_motor_params(motor_params);
Ok(())
}
/// Disables the motor of the joint assuming it is a [`RevoluteJoint`], [`PrismaticJoint`] or [`BallJoint`].
///
/// After this call, the joint will no longer apply any motor force or torque to the connected bodies.
/// # Errors
/// If the joint is not a [`RevoluteJoint`] or [`PrismaticJoint`], the function will do nothing and return an Err.
/// If the joint is not a [`RevoluteJoint`], [`PrismaticJoint`] or [`BallJoint`], the function will do nothing and return an Err.
pub fn disable_motor(&mut self) -> Result<(), String> {
if !matches!(
self.params(),
JointParams::RevoluteJoint(_) | JointParams::PrismaticJoint(_)
JointParams::RevoluteJoint(_) | JointParams::PrismaticJoint(_) | JointParams::BallJoint(_)
) {
return Err("Joint is not a RevoluteJoint or PrismaticJoint".to_string());
return Err("Joint is not a RevoluteJoint, PrismaticJoint or BallJoint".to_string());
}
let motor_params = JointMotorParams {
target_vel: 0.0,