Skip to content

Commit 6c7e720

Browse files
zdtangosebcrozet
andauthored
Expose revolute joints with separate local axes (#372)
* Expose revolute joints with separate local axes * Update src/dynamics/joint.rs Co-authored-by: Sébastien Crozet <sebastien@crozet.re> --------- Co-authored-by: Sébastien Crozet <sebastien@crozet.re>
1 parent 6b57282 commit 6c7e720

2 files changed

Lines changed: 74 additions & 3 deletions

File tree

src.ts/dynamics/impulse_joint.ts

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,10 @@ export class JointData {
369369
anchor1: Vector;
370370
anchor2: Vector;
371371
axis: Vector;
372+
// #if DIM3
373+
axis1: Vector;
374+
axis2: Vector;
375+
// #endif
372376
frame1: Rotation;
373377
frame2: Rotation;
374378
jointType: JointType;
@@ -588,6 +592,36 @@ export class JointData {
588592
res.jointType = JointType.Revolute;
589593
return res;
590594
}
595+
596+
/**
597+
* Create a new joint descriptor that builds Revolute joints with independent
598+
* local axes for each attached rigid-body.
599+
*
600+
* This is useful when the same world-space hinge axis is represented by
601+
* different local axes on the two bodies.
602+
*
603+
* @param anchor1 - Point where the joint is attached on the first rigid-body affected by this joint. Expressed in the
604+
* local-space of the rigid-body.
605+
* @param anchor2 - Point where the joint is attached on the second rigid-body affected by this joint. Expressed in the
606+
* local-space of the rigid-body.
607+
* @param axis1 - Axis of the joint, expressed in the local-space of the first rigid-body.
608+
* @param axis2 - Axis of the joint, expressed in the local-space of the second rigid-body.
609+
*/
610+
public static revoluteWithAxes(
611+
anchor1: Vector,
612+
anchor2: Vector,
613+
axis1: Vector,
614+
axis2: Vector,
615+
): JointData {
616+
let res = new JointData();
617+
res.anchor1 = anchor1;
618+
res.anchor2 = anchor2;
619+
res.axis = axis1;
620+
res.axis1 = axis1;
621+
res.axis2 = axis2;
622+
res.jointType = JointType.Revolute;
623+
return res;
624+
}
591625
// #endif
592626

593627
public intoRaw(): RawGenericJoint {
@@ -674,9 +708,22 @@ export class JointData {
674708
result = RawGenericJoint.spherical(rawA1, rawA2);
675709
break;
676710
case JointType.Revolute:
677-
rawAx = VectorOps.intoRaw(this.axis);
678-
result = RawGenericJoint.revolute(rawA1, rawA2, rawAx);
679-
rawAx.free();
711+
if (!!this.axis1 && !!this.axis2) {
712+
let rawAx1 = VectorOps.intoRaw(this.axis1);
713+
let rawAx2 = VectorOps.intoRaw(this.axis2);
714+
result = RawGenericJoint.revoluteWithAxes(
715+
rawA1,
716+
rawA2,
717+
rawAx1,
718+
rawAx2,
719+
);
720+
rawAx1.free();
721+
rawAx2.free();
722+
} else {
723+
rawAx = VectorOps.intoRaw(this.axis);
724+
result = RawGenericJoint.revolute(rawA1, rawA2, rawAx);
725+
rawAx.free();
726+
}
680727
break;
681728
// #endif
682729
}

src/dynamics/joint.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,4 +311,28 @@ impl RawGenericJoint {
311311
.into(),
312312
))
313313
}
314+
315+
/// Create a new joint descriptor that builds Revolute joints with
316+
/// independent local axes for each attached rigid-body.
317+
///
318+
/// This is equivalent to a revolute generic joint with all linear axes
319+
/// locked and only angular X free, but it preserves the local hinge axis
320+
/// on each body instead of assuming they are identical.
321+
#[cfg(feature = "dim3")]
322+
pub fn revoluteWithAxes(
323+
anchor1: &RawVector,
324+
anchor2: &RawVector,
325+
axis1: &RawVector,
326+
axis2: &RawVector,
327+
) -> Option<RawGenericJoint> {
328+
let axis1 = Unit::try_new(axis1.0, 0.0)?;
329+
let axis2 = Unit::try_new(axis2.0, 0.0)?;
330+
let joint: GenericJoint = GenericJointBuilder::new(JointAxesMask::LOCKED_REVOLUTE_AXES)
331+
.local_anchor1(anchor1.0.into())
332+
.local_anchor2(anchor2.0.into())
333+
.local_axis1(axis1)
334+
.local_axis2(axis2)
335+
.into();
336+
Some(Self(joint))
337+
}
314338
}

0 commit comments

Comments
 (0)