Skip to content

Commit

Permalink
Merge pull request #249 from pvdosev/generic-joints
Browse files Browse the repository at this point in the history
Expose 3D generic impulse joints
  • Loading branch information
sebcrozet authored Jan 28, 2024
2 parents c23a138 + e7af55f commit 802915c
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 3 deletions.
74 changes: 73 additions & 1 deletion src.ts/dynamics/impulse_joint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ export type ImpulseJointHandle = number;
* - `Prismatic`: A prismatic joint that removes all degrees of freedom between the affected
* bodies except for the translation along one axis.
* - `Spherical`: (3D only) A spherical joint that removes all relative linear degrees of freedom between the affected bodies.
* - `Generic`: (3D only) A joint with customizable degrees of freedom, allowing any of the 6 axes to be locked.
*/
export enum JointType {
Revolute,
Fixed,
Prismatic,
// #if DIM3
Spherical,
Generic,
// #endif
}

Expand All @@ -40,6 +42,30 @@ export enum MotorModel {
ForceBased,
}

/**
* An enum representing the possible joint axes of a generic joint.
* They can be ORed together, like:
* JointAxesMask.X || JointAxesMask.Y
* to get a joint that is only free in the X and Y translational (positional) axes.
*
* Possible free axes are:
*
* - `X`: X translation axis
* - `Y`: Y translation axis
* - `Z`: Z translation axis
* - `AngX`: X angular rotation axis
* - `AngY`: Y angular rotations axis
* - `AngZ`: Z angular rotation axis
*/
export enum JointAxesMask {
X = 1 << 0,
Y = 1 << 1,
Z = 1 << 2,
AngX = 1 << 3,
AngY = 1 << 4,
AngZ = 1 << 5,
}

export class ImpulseJoint {
protected rawSet: RawImpulseJointSet; // The ImpulseJoint won't need to free this.
protected bodySet: RigidBodySet; // The ImpulseJoint won’t need to free this.
Expand Down Expand Up @@ -70,6 +96,8 @@ export class ImpulseJoint {
// #if DIM3
case JointType.Spherical:
return new SphericalImpulseJoint(rawSet, bodySet, handle);
case JointType.Generic:
return new GenericImpulseJoint(rawSet, bodySet, handle);
// #endif
default:
return new ImpulseJoint(rawSet, bodySet, handle);
Expand Down Expand Up @@ -291,6 +319,8 @@ export class RevoluteImpulseJoint extends UnitImpulseJoint {
}

// #if DIM3
export class GenericImpulseJoint extends ImpulseJoint {}

export class SphericalImpulseJoint extends ImpulseJoint {
/* Unsupported by this alpha release.
public configureMotorModel(model: MotorModel) {
Expand Down Expand Up @@ -324,6 +354,7 @@ export class JointData {
jointType: JointType;
limitsEnabled: boolean;
limits: Array<number>;
axesMask: JointAxesMask;

private constructor() {}

Expand Down Expand Up @@ -405,6 +436,36 @@ export class JointData {
// #endif

// #if DIM3
/**
* Create a new joint descriptor that builds generic joints.
*
* A generic joint allows customizing its degrees of freedom
* by supplying a mask of the joint axes that should remain locked.
*
* @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 axis - The X axis of the joint, expressed in the local-space of the rigid-bodies it is attached to.
* @param axesMask - Mask representing the locked axes of the joint. You can use logical OR to select these from
* the JointAxesMask enum. For example, passing (JointAxesMask.AngX || JointAxesMask.AngY) will
* create a joint locked in the X and Y rotational axes.
*/
public static generic(
anchor1: Vector,
anchor2: Vector,
axis: Vector,
axesMask: JointAxesMask,
): JointData {
let res = new JointData();
res.anchor1 = anchor1;
res.anchor2 = anchor2;
res.axis = axis;
res.axesMask = axesMask;
res.jointType = JointType.Generic;
return res;
}

/**
* Create a new joint descriptor that builds spherical joints.
*
Expand Down Expand Up @@ -474,7 +535,6 @@ export class JointData {
res.jointType = JointType.Revolute;
return res;
}

// #endif

public intoRaw(): RawGenericJoint {
Expand Down Expand Up @@ -533,6 +593,18 @@ export class JointData {
break;
// #endif
// #if DIM3
case JointType.Generic:
rawAx = VectorOps.intoRaw(this.axis);
// implicit type cast: axesMask is a JointAxesMask bitflag enum,
// we're treating it as a u8 on the Rust side
let rawAxesMask = this.axesMask;
result = RawGenericJoint.generic(
rawA1,
rawA2,
rawAx,
rawAxesMask,
);
break;
case JointType.Spherical:
result = RawGenericJoint.spherical(rawA1, rawA2);
break;
Expand Down
26 changes: 24 additions & 2 deletions src/dynamics/joint.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::math::{RawRotation, RawVector};
use na::Unit;
#[cfg(feature = "dim3")]
use rapier::dynamics::SphericalJointBuilder;
use rapier::dynamics::{
FixedJointBuilder, GenericJoint, JointAxesMask, JointAxis, MotorModel, PrismaticJointBuilder,
RevoluteJointBuilder,
};
#[cfg(feature = "dim3")]
use rapier::dynamics::{GenericJointBuilder, SphericalJointBuilder};
use rapier::math::Isometry;
use wasm_bindgen::prelude::*;

Expand Down Expand Up @@ -141,6 +141,28 @@ pub struct RawGenericJoint(pub(crate) GenericJoint);

#[wasm_bindgen]
impl RawGenericJoint {
/// Creates a new joint descriptor that builds generic joints.
///
/// Generic joints allow arbitrary axes of freedom to be selected
/// for the joint from the available 6 degrees of freedom.
#[cfg(feature = "dim3")]
pub fn generic(
anchor1: &RawVector,
anchor2: &RawVector,
axis: &RawVector,
lockedAxes: u8,
) -> Option<RawGenericJoint> {
let axesMask: JointAxesMask = JointAxesMask::from_bits(lockedAxes)?;
let axis = Unit::try_new(axis.0, 0.0)?;
let joint: GenericJoint = GenericJointBuilder::new(axesMask)
.local_anchor1(anchor1.0.into())
.local_anchor2(anchor2.0.into())
.local_axis1(axis)
.local_axis2(axis)
.into();
Some(Self(joint))
}

/// Create a new joint descriptor that builds spehrical joints.
///
/// A spherical joints allows three relative rotational degrees of freedom
Expand Down

0 comments on commit 802915c

Please sign in to comment.