Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 50 additions & 3 deletions src.ts/dynamics/impulse_joint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,10 @@ export class JointData {
anchor1: Vector;
anchor2: Vector;
axis: Vector;
// #if DIM3
axis1: Vector;
axis2: Vector;
// #endif
frame1: Rotation;
frame2: Rotation;
jointType: JointType;
Expand Down Expand Up @@ -588,6 +592,36 @@ export class JointData {
res.jointType = JointType.Revolute;
return res;
}

/**
* Create a new joint descriptor that builds Revolute joints with independent
* local axes for each attached rigid-body.
*
* This is useful when the same world-space hinge axis is represented by
* different local axes on the two bodies.
*
* @param anchor1 - Point where the joint is attached on the first rigid-body affected by this joint. Expressed in the
* local-space of the rigid-body.
* @param anchor2 - Point where the joint is attached on the second rigid-body affected by this joint. Expressed in the
* local-space of the rigid-body.
* @param axis1 - Axis of the joint, expressed in the local-space of the first rigid-body.
* @param axis2 - Axis of the joint, expressed in the local-space of the second rigid-body.
*/
public static revoluteWithAxes(
anchor1: Vector,
anchor2: Vector,
axis1: Vector,
axis2: Vector,
): JointData {
let res = new JointData();
res.anchor1 = anchor1;
res.anchor2 = anchor2;
res.axis = axis1;
res.axis1 = axis1;
res.axis2 = axis2;
res.jointType = JointType.Revolute;
return res;
}
// #endif

public intoRaw(): RawGenericJoint {
Expand Down Expand Up @@ -674,9 +708,22 @@ export class JointData {
result = RawGenericJoint.spherical(rawA1, rawA2);
break;
case JointType.Revolute:
rawAx = VectorOps.intoRaw(this.axis);
result = RawGenericJoint.revolute(rawA1, rawA2, rawAx);
rawAx.free();
if (!!this.axis1 && !!this.axis2) {
let rawAx1 = VectorOps.intoRaw(this.axis1);
let rawAx2 = VectorOps.intoRaw(this.axis2);
result = RawGenericJoint.revoluteWithAxes(
rawA1,
rawA2,
rawAx1,
rawAx2,
);
rawAx1.free();
rawAx2.free();
} else {
rawAx = VectorOps.intoRaw(this.axis);
result = RawGenericJoint.revolute(rawA1, rawA2, rawAx);
rawAx.free();
}
break;
// #endif
}
Expand Down
24 changes: 24 additions & 0 deletions src/dynamics/joint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,4 +311,28 @@ impl RawGenericJoint {
.into(),
))
}

/// Create a new joint descriptor that builds Revolute joints with
/// independent local axes for each attached rigid-body.
///
/// This is equivalent to a revolute generic joint with all linear axes
/// locked and only angular X free, but it preserves the local hinge axis
/// on each body instead of assuming they are identical.
#[cfg(feature = "dim3")]
pub fn revoluteWithAxes(
anchor1: &RawVector,
anchor2: &RawVector,
axis1: &RawVector,
axis2: &RawVector,
) -> Option<RawGenericJoint> {
let axis1 = Unit::try_new(axis1.0, 0.0)?;
let axis2 = Unit::try_new(axis2.0, 0.0)?;
let joint: GenericJoint = GenericJointBuilder::new(JointAxesMask::LOCKED_REVOLUTE_AXES)
.local_anchor1(anchor1.0.into())
.local_anchor2(anchor2.0.into())
.local_axis1(axis1)
.local_axis2(axis2)
.into();
Some(Self(joint))
}
}
Loading