From 459afae532956bb9847815a8b9d743a1471cfe67 Mon Sep 17 00:00:00 2001 From: TheLMiffy1111 <6522061+TheLMiffy1111@users.noreply.github.com> Date: Fri, 22 May 2026 11:03:13 +0800 Subject: [PATCH] Add ability to set coupled_axes in GenericConstraint --- .../generic/GenericConstraintConfiguration.java | 7 ++++++- .../sable/physics/impl/rapier/Rapier3D.java | 4 +++- .../generic/RapierGenericConstraintHandle.java | 8 +++++++- common/src/main/rust/rapier/src/joints.rs | 12 ++++++++---- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/common/src/main/java/dev/ryanhcode/sable/api/physics/constraint/generic/GenericConstraintConfiguration.java b/common/src/main/java/dev/ryanhcode/sable/api/physics/constraint/generic/GenericConstraintConfiguration.java index 56150402..120f8b39 100644 --- a/common/src/main/java/dev/ryanhcode/sable/api/physics/constraint/generic/GenericConstraintConfiguration.java +++ b/common/src/main/java/dev/ryanhcode/sable/api/physics/constraint/generic/GenericConstraintConfiguration.java @@ -23,9 +23,14 @@ public record GenericConstraintConfiguration( Vector3dc pos2, Quaterniondc orientation1, Quaterniondc orientation2, - Set lockedAxes + Set lockedAxes, + Set coupledAxes ) implements PhysicsConstraintConfiguration { + public GenericConstraintConfiguration(final Vector3dc pos1, final Vector3dc pos2, final Quaterniondc orientation1, final Quaterniondc orientation2, final Set lockedAxes) { + this(pos1, pos2, orientation1, orientation2, lockedAxes, EnumSet.noneOf(ConstraintJointAxis.class)); + } + public GenericConstraintConfiguration(final Vector3dc pos1, final Vector3dc pos2, final Quaterniondc orientation1, final Quaterniondc orientation2) { this(pos1, pos2, orientation1, orientation2, EnumSet.noneOf(ConstraintJointAxis.class)); } diff --git a/common/src/main/java/dev/ryanhcode/sable/physics/impl/rapier/Rapier3D.java b/common/src/main/java/dev/ryanhcode/sable/physics/impl/rapier/Rapier3D.java index de0bf136..43809e52 100644 --- a/common/src/main/java/dev/ryanhcode/sable/physics/impl/rapier/Rapier3D.java +++ b/common/src/main/java/dev/ryanhcode/sable/physics/impl/rapier/Rapier3D.java @@ -422,6 +422,7 @@ public static native long addFreeConstraint(final int dimensionID, * @param localOrientationZB the local orientation Z of the second object * @param localOrientationWB the local orientation W of the second object * @param lockedAxesMask bit mask of locked axes; bit {@code n} corresponds to {@link dev.ryanhcode.sable.api.physics.constraint.ConstraintJointAxis#ordinal()} + * @param coupledAxesMask bit mask of coupled axes; bit {@code n} corresponds to {@link dev.ryanhcode.sable.api.physics.constraint.ConstraintJointAxis#ordinal()} */ @ApiStatus.Internal public static native long addGenericConstraint(final int dimensionID, @@ -441,7 +442,8 @@ public static native long addGenericConstraint(final int dimensionID, double localOrientationYB, double localOrientationZB, double localOrientationWB, - int lockedAxesMask); + int lockedAxesMask, + int coupledAxesMask); /** * Sets the local frame on one side of a constraint. diff --git a/common/src/main/java/dev/ryanhcode/sable/physics/impl/rapier/constraint/generic/RapierGenericConstraintHandle.java b/common/src/main/java/dev/ryanhcode/sable/physics/impl/rapier/constraint/generic/RapierGenericConstraintHandle.java index 24160741..bc7f3199 100644 --- a/common/src/main/java/dev/ryanhcode/sable/physics/impl/rapier/constraint/generic/RapierGenericConstraintHandle.java +++ b/common/src/main/java/dev/ryanhcode/sable/physics/impl/rapier/constraint/generic/RapierGenericConstraintHandle.java @@ -29,6 +29,11 @@ public static RapierGenericConstraintHandle create(final ServerLevel serverLevel lockedAxesMask |= 1 << axis.ordinal(); } + int coupledAxesMask = 0; + for (final ConstraintJointAxis axis : config.coupledAxes()) { + coupledAxesMask |= 1 << axis.ordinal(); + } + final long handle = Rapier3D.addGenericConstraint( sceneID, sublevelA == null ? -1 : Rapier3D.getID(sublevelA), @@ -47,7 +52,8 @@ public static RapierGenericConstraintHandle create(final ServerLevel serverLevel config.orientation2().y(), config.orientation2().z(), config.orientation2().w(), - lockedAxesMask + lockedAxesMask, + coupledAxesMask ); return new RapierGenericConstraintHandle(sceneID, handle); diff --git a/common/src/main/rust/rapier/src/joints.rs b/common/src/main/rust/rapier/src/joints.rs index 71f6a7d5..f9687821 100644 --- a/common/src/main/rust/rapier/src/joints.rs +++ b/common/src/main/rust/rapier/src/joints.rs @@ -518,6 +518,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_add local_q_z_b: jdouble, local_q_w_b: jdouble, locked_axes_mask: jint, + coupled_axes_mask: jint, ) -> SableJointHandle { let scene = get_scene_mut_ref(scene_id); @@ -534,6 +535,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_add }; let locked_axes = JointAxesMask::from_bits_truncate(locked_axes_mask as u8); + let coupled_axes = JointAxesMask::from_bits_truncate(coupled_axes_mask as u8); let rotation_a = Quat::from_xyzw( local_q_x_a as Real, @@ -548,10 +550,12 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_add local_q_w_b as Real, ); - let mut joint = GenericJointBuilder::new(locked_axes).softness(SpringCoefficients::new( - JOINT_SPRING_FREQUENCY, - JOINT_SPRING_DAMPING_RATIO, - )); + let mut joint = GenericJointBuilder::new(locked_axes) + .coupled_axes(coupled_axes) + .softness(SpringCoefficients::new( + JOINT_SPRING_FREQUENCY, + JOINT_SPRING_DAMPING_RATIO, + )); joint.0.local_frame1.rotation = rotation_a; joint.0.local_frame2.rotation = rotation_b;