1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
use super::*;
/// Joint component. A joint connects two dynamic, or one static and one dynamic, entity physically.
/// It doesn't have to be a component of one of the entities it connects, but that can be convenient at times.
///
/// There are many different kinds of joints. A `Joint` can represent all standard joint types except D6,
/// which we have `D6Joint` for.
///
/// If you don't set a `second_entity`, the joint will be to kind of a static invisible global frame - not super
/// realistic, but often useful.
///
/// Usually accessed through `entity.joint`().
///
/// Most of the time, you'll be better served by a `D6Joint`. `Joint` represent `PhysX`'s legacy joint types. They
/// can be easier to use for simpler applications but `D6Joint` has all the capabilities and are more flexible.
pub struct Joint {
id: Entity,
}
impl std::fmt::Debug for Joint {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Joint")
.field("entity", &self.id.name())
.finish_non_exhaustive()
}
}
impl Joint {
impl_world_accessor!(
/// Returns a `ValueAccessor` for the joint type of the entity.
///
/// Used to set/get the mesh style.
Joint,
Type,
JointType,
joint_type,
ValueAccessorReadWrite
);
impl_world_accessor!(
/// The first entity of the joint.
Joint,
FirstEntity,
Entity,
first_entity,
ValueAccessorReadWrite
);
impl_world_accessor!(
/// The second entity of the joint.
Joint,
SecondEntity,
Entity,
second_entity,
ValueAccessorReadWrite
);
impl_world_accessor!(
/// The location on the first entity that the joint is attached to.
Joint,
FirstOffset,
Vec3,
first_offset,
ValueAccessorReadWrite
);
impl_world_accessor!(
/// The location on the second entity that the joint is attached to.
Joint,
SecondOffset,
Vec3,
second_offset,
ValueAccessorReadWrite
);
impl_world_accessor!(
/// The orientation of the joint on the second entity that the joint is attached to.
/// For hinge joints, the default is the exact X axis, rotated by this orientation.
Joint,
FirstOrientation,
Quat,
first_orientation,
ValueAccessorReadWrite
);
impl_world_accessor!(
/// The orientation of the joint on the second entity that the joint is attached to.
/// For hinge joints, the default is the exact X axis, rotated by this orientation.
Joint,
SecondOrientation,
Quat,
second_orientation,
ValueAccessorReadWrite
);
impl_world_accessor!(
/// The limit bounds of a joint. x is min, y is max, what exactly it limits depends on the joint type:
/// * Ball joint: x is the y angle limit of the cone (around the x axis), while y sets the z angle limit.
/// * Hinge: x is the lower angle limit, y is the upper angle limit.
/// * Slider: x is the lower position limit, y is the upper position limit.
/// * Distance: x is the minimum distance, y is the maximum distance.
Joint,
Limits,
Vec2,
limits,
ValueAccessorReadWrite
);
impl_world_accessor!(
/// The limit type of a joint.
Joint,
LimitType,
JointLimitType,
limit_type,
ValueAccessorReadWrite
);
impl_world_accessor!(
/// The joint velocity (angular for hinge joints, linear for linear joints).
/// Can only be retrieved for now, need to use forces to change it.
Joint,
Velocity,
f32,
velocity,
ValueAccessorRead
);
impl_world_accessor!(
/// Turns on joint drive. Currently only works with Hinge joints. `D6Joint` has more flexible drive capabilities, though.
Joint,
DriveEnabled,
bool,
drive_enable,
ValueAccessorReadWriteAnimate
);
impl_world_accessor!(
/// The drive velocity. Does nothing unless `drive_enable` is set to true.
Joint,
DriveVelocity,
f32,
drive_velocity,
ValueAccessorReadWriteAnimate
);
impl_world_accessor!(
/// Sets the maximum force the joint drive can exercise.
Joint,
DriveForceLimit,
f32,
drive_force_limit,
ValueAccessorReadWriteAnimate
);
impl_world_accessor!(
/// Sets the gear ratio of the joint drive.
Joint,
DriveGearRatio,
f32,
drive_gear_ratio,
ValueAccessorReadWriteAnimate
);
impl_world_accessor!(
/// Enables freespin on the joint drive (it'll continue to spin by inertia if you
/// turn off the drive).
Joint,
DriveFreespin,
bool,
drive_freespin,
ValueAccessorReadWriteAnimate
);
impl_world_accessor!(
/// Sets the force threshold for breaking the joint. Default is std::f32::MAX (effectively unbreakable).
Joint,
BreakForce,
f32,
break_force,
ValueAccessorReadWrite
);
impl_world_accessor!(
/// Sets the torque threshold for breaking the joint. Default is std::f32::MAX (effectively unbreakable).
Joint,
BreakTorque,
f32,
break_torque,
ValueAccessorReadWrite
);
impl_world_accessor!(
/// Lets you check whether the joint is broken. Cannot be modified.
Joint,
IsBroken,
bool,
is_broken,
ValueAccessorRead
);
impl_world_accessor!(
/// Lets you check the angles or position of the joint. Interpreted differently depending on the joint type:
/// - Hinge: x means the angle. You can use `hinge_angle` instead.
/// - Ball: y means the y-angle, z means the z-angle. You can use `ball_swing_angles` instead.
/// - Linear: x means the position along the joint. You can use `linear_position` instead.
Joint,
AngleOrPosition,
Vec3,
angle_or_position,
ValueAccessorRead
);
/// Utility function for `angle_or_position`: If the joint is a hinge, returns the angle directly.
pub fn hinge_angle(&self) -> f32 {
self.angle_or_position().get().x
}
/// Utility function: If the joint is linear, returns the position along the line directly.
pub fn linear_position(&self) -> f32 {
self.angle_or_position().get().x
}
/// Utility function: If the joint is a ball joint, return the swing angles.
pub fn ball_swing_angles(&self) -> Vec2 {
Vec2::new(
self.angle_or_position().get().y,
self.angle_or_position().get().z,
)
}
}
impl_world_component!(Joint);