Constraints

SwingTwist Constraint

Combines elliptical swing limits, a signed twist range, friction and independent native swing/twist motors.

jolt_swing_twist() exposes Jolt Physics 5.6 SwingTwistConstraint directly. It keeps two attachment points together while controlling the orientation between articulated links, limbs, rope-like chains and other joints that need more detail than Cone.

Syntax#

Syntax
jolt_swing_twist(body_a, body_b, anchor_x, anchor_y, anchor_z, options=undefined)

Options#

FieldDefaultDescription
twist_axis{x:0,y:0,z:1}World-space constraint X axis around which twist occurs.
plane_axis{x:1,y:0,z:0}World-space constraint Z axis defining the swing frame.
swing_angle45Degree alias used for both swing half-angles unless they are supplied separately.
normal_half_angleswing_angleSwing half-angle around constraint-space normal/Y, 0..180 degrees.
plane_half_angleswing_angleSwing half-angle around constraint-space plane/Z, 0..180 degrees.
twist_min-30Inclusive signed minimum twist in degrees, at least -180.
twist_max30Inclusive signed maximum twist in degrees, at most 180.
friction_torque0Non-negative maximum passive friction torque in N m.
collisionfalseWhether the connected bodies may collide.
enabledtrueInitial solver state.

Reference frame#

  • The anchor and both axes are world-space values at creation.
  • Twist Axis becomes constraint-space X. Plane Axis becomes constraint-space Z, and Jolt derives the normal/Y axis.
  • Axes are normalized and the plane axis is orthogonalized around the twist axis.
  • Zero-length or nearly parallel axes are rejected.
  • Different normal and plane half-angles create a real elliptical swing range rather than a visual approximation.

Limits and state#

MethodResult
set_limits(normal, plane, twist_min, twist_max)Updates all four degree limits.
set_swing_limits(normal, plane)Updates only the elliptical swing half-angles.
set_twist_limits(minimum, maximum)Updates only the signed twist range.
get_limits()Returns {normal_half_angle, plane_half_angle, twist_min, twist_max}.
set_friction_torque(value) / get_friction_torque()Changes or reads passive maximum friction torque.
get_twist_angle()Returns current signed twist in degrees.
get_orientation()Returns current constraint-space quaternion {x,y,z,w}.
get_swing_twist_impulses()Returns position, twist, swing and motor solver impulses.

Independent motors#

SwingTwist
set_swing_motor_velocity(y_deg_s, z_deg_s)set_twist_motor_velocity(deg_s)
set_swing_motor_position(angle_deg, axis_y=1, axis_z=0)set_twist_motor_position(angle_deg)
enable_swing_motor(enabled)enable_twist_motor(enabled)
set_swing_motor_max_torque(value)set_twist_motor_max_torque(value)
set_swing_motor_spring(frequency, damping)set_twist_motor_spring(frequency, damping)
get_swing_motor_state()get_twist_motor_state()

Swing velocity components use constraint-space Y/Z. A swing position is an angle around a normalized axis in that Y/Z plane. Twist uses constraint-space X. These high-level motor velocities are degrees per second.

GML
var upper = jolt_box_create_dynamic(0, 0, 5, 0.5, 0.5, 1, { mass: 2 });
var lower = jolt_box_create_dynamic(0, 0, 4, 0.5, 0.5, 1, { mass: 2 });

var joint = jolt_swing_twist(upper, lower, 0, 0, 4.5, {
    twist_axis: { x:0, y:0, z:1 },
    plane_axis: { x:1, y:0, z:0 },
    normal_half_angle: 20,
    plane_half_angle: 60,
    twist_min: -30,
    twist_max: 30,
    friction_torque: 0.5,
    collision: false
});

Example: twist motor#

GML
joint.set_twist_motor_max_torque(20);
joint.set_twist_motor_spring(3, 0.8);
joint.set_twist_motor_position(25);

var twist = joint.get_twist_angle();
var state = joint.get_twist_motor_state();

Lifecycle, debug and limitations#

  • is_valid() / get_native_handle(): Checks the wrapper or returns its opaque native handle.
  • destroy(): Idempotently releases the constraint without destroying either body.
  • set_enabled() / get_enabled(): Changes solver participation while preserving the resource.
  • set_collision_enabled() / get_collision_enabled(): Controls the connected-body pair filter.
  • Destroying either body invalidates the generational constraint handle; jolt_stop() cleans it before bodies and world.
  • JOLT_DEBUG_CONSTRAINTS draws the native frame, elliptical boundary, twist arc, current orientation and active motors.
  • This creator supports body-to-body Cone swing only. There is no world convenience variant and no public rope/chain helper.
  • Solver impulses are accumulated Lagrange multipliers from the latest step, not forces or torques per second.

Verified operation contracts#

These contracts distinguish units, return values, errors and lifetime according to the current implementation. Check results: false, 0 and undefined can mean different things for different methods.

Symbol / ownerSignatureOperation contract
jolt_swing_twistjolt_swing_twist(body_a, body_b, anchor_x, anchor_y, anchor_z, options = undefined)Returns JoltConstraint/undefined, does not own bodies. Two distinct live same-world bodies; _world variant one Dynamic body and fixed world. Enabled defaults true; ordinary two-body collision defaults true unless specified otherwise below. Also check jolt_has_error after creation: some subsequent options can fail while returning the created constraint. World anchor; twist_axis defaults+Z, plane_axis+X, nonzero nonparallel. Swing half angles0..180° default 45, twist-30..30° within±180, friction_torque>=0 default 0. Collision defaults false.
jolt_swing_twist_worldjolt_swing_twist_world(body,anchor_x,anchor_y,anchor_z,options=undefined)Returns JoltConstraint/undefined, does not own bodies. Two distinct live same-world bodies; _world variant one Dynamic body and fixed world. Enabled defaults true; ordinary two-body collision defaults true unless specified otherwise below. Also check jolt_has_error after creation: some subsequent options can fail while returning the created constraint. World anchor; twist_axis defaults+Z, plane_axis+X, nonzero nonparallel. Swing half angles0..180° default 45, twist-30..30° within±180, friction_torque>=0 default 0. Collision defaults false.
JoltConstraint.enable_swing_motorJoltConstraint.enable_swing_motor(enabled)SwingTwist only; Boolean success. False selects OFF, true restores the last selected mode (VELOCITY before the first setting).
JoltConstraint.enable_twist_motorJoltConstraint.enable_twist_motor(enabled)SwingTwist only; Boolean success. False selects OFF, true restores the last selected mode (VELOCITY before the first setting).
JoltConstraint.get_current_orientationJoltConstraint.get_current_orientation()SixDOF: target/current constraint-space quaternion {x, y, z, w}. Composes native reads without a reliable undefined sentinel; check type/liveness and errors first.
JoltConstraint.get_current_orientation_eulerJoltConstraint.get_current_orientation_euler()SixDOF: Euler {x, y, z} in degrees from the corresponding quaternion getter; check validity and errors first.
JoltConstraint.get_orientationJoltConstraint.get_orientation()SwingTwist only: current relative orientation in constraint space as {x, y, z, w}; undefined on error.
JoltConstraint.get_swing_motor_stateJoltConstraint.get_swing_motor_state()SwingTwist struct {mode, velocity_y, velocity_z, max_torque, spring_frequency, spring_damping}. Velocities °/s, torque N·m, frequency Hz. undefined for invalid type/wrapper; inspect individual native errors separately.
JoltConstraint.get_swing_twist_impulsesJoltConstraint.get_swing_twist_impulses()SwingTwist only, latest solver impulses: position {x, y, z} (N·s), twist/swing_y/swing_z and motor {x, y, z} (N·m·s). undefined for invalid type/wrapper; not forces per second.
JoltConstraint.get_target_orientationJoltConstraint.get_target_orientation()SixDOF: target/current constraint-space quaternion {x, y, z, w}. Composes native reads without a reliable undefined sentinel; check type/liveness and errors first.
JoltConstraint.get_target_orientation_eulerJoltConstraint.get_target_orientation_euler()SixDOF: Euler {x, y, z} in degrees from the corresponding quaternion getter; check validity and errors first.
JoltConstraint.get_twist_angleJoltConstraint.get_twist_angle()SwingTwist only: current twist around constraint X in degrees; 0 on error/invalid type.
JoltConstraint.get_twist_motor_stateJoltConstraint.get_twist_motor_state()SwingTwist struct {mode, velocity, max_torque, spring_frequency, spring_damping}; velocity °/s, N·m, Hz. undefined for invalid type/wrapper; inspect native errors separately.
JoltConstraint.set_swing_limitsJoltConstraint.set_swing_limits(normal, plane)SwingTwist only; Boolean. Swing half-angles 0..180°, twist min/max within -180..180° with min≤max. Preserves the other part of current limits.
JoltConstraint.set_swing_motor_max_torqueJoltConstraint.set_swing_motor_max_torque(torque)SwingTwist only; finite nonnegative limit in N·m; Boolean. Setting the limit alone does not enable the motor.
JoltConstraint.set_swing_motor_positionJoltConstraint.set_swing_motor_position(angle, constraint_axis_y=1, constraint_axis_z=0)SwingTwist only: finite angle in degrees and nonzero Y/Z-plane axis, default (1, 0), normalized natively. Boolean; enables position motor and preserves target twist.
JoltConstraint.set_swing_motor_springJoltConstraint.set_swing_motor_spring(frequency,damping)SwingTwist only; finite frequency ≥0 Hz, damping ≥0 as a damping ratio; Boolean.
JoltConstraint.set_swing_motor_velocityJoltConstraint.set_swing_motor_velocity(constraint_y, constraint_z)SwingTwist only: finite velocities around constraint Y/Z in degrees/s. Boolean; also enables the swing motor in velocity mode.
JoltConstraint.set_target_orientationJoltConstraint.set_target_orientation(x,y,z,w)SixDOF: constraint-space orientation; finite nonzero quaternion x/y/z/w normalized natively, or Euler XYZ in degrees. Boolean. Motors must be enabled separately.
JoltConstraint.set_target_orientation_eulerJoltConstraint.set_target_orientation_euler(x,y,z)SixDOF: constraint-space orientation; finite nonzero quaternion x/y/z/w normalized natively, or Euler XYZ in degrees. Boolean. Motors must be enabled separately.
JoltConstraint.set_twist_limitsJoltConstraint.set_twist_limits(minimum, maximum)SwingTwist only; Boolean. Swing half-angles 0..180°, twist min/max within -180..180° with min≤max. Preserves the other part of current limits.
JoltConstraint.set_twist_motor_max_torqueJoltConstraint.set_twist_motor_max_torque(torque)SwingTwist only; finite nonnegative limit in N·m; Boolean. Setting the limit alone does not enable the motor.
JoltConstraint.set_twist_motor_positionJoltConstraint.set_twist_motor_position(angle)SwingTwist only: finite twist angle in degrees. Boolean; enables position motor and preserves target swing.
JoltConstraint.set_twist_motor_springJoltConstraint.set_twist_motor_spring(frequency,damping)SwingTwist only; finite frequency ≥0 Hz, damping ≥0 as a damping ratio; Boolean.
JoltConstraint.set_twist_motor_velocityJoltConstraint.set_twist_motor_velocity(degrees_per_second)SwingTwist only: finite velocity around constraint X in degrees/s. Boolean; also enables the twist motor in velocity mode.