diff --git a/rapier3d/package.json b/rapier3d/package.json index 6a2e0b07..4791c575 100644 --- a/rapier3d/package.json +++ b/rapier3d/package.json @@ -17,5 +17,8 @@ }, "dependencies": { "wasm-pack": "^0.12.1" - } + }, + "sideEffects": [ + "./*.js" + ] } diff --git a/src.ts/geometry/collider.ts b/src.ts/geometry/collider.ts index edf72c9c..35647832 100644 --- a/src.ts/geometry/collider.ts +++ b/src.ts/geometry/collider.ts @@ -1,4 +1,4 @@ -import {RawColliderSet} from "../raw"; +import {RawColliderSet, RawCompoundShapePart} from "../raw"; import {Rotation, RotationOps, Vector, VectorOps} from "../math"; import { CoefficientCombineRule, @@ -36,6 +36,7 @@ import { RoundConvexPolyhedron, HeightFieldFlags, // #endif + Compound, } from "./shape"; import {Ray, RayIntersection} from "./ray"; import {PointProjection} from "./point"; @@ -1296,6 +1297,19 @@ export class ColliderDesc { return new ColliderDesc(shape); } + /** + * Creates a new collider descriptor with a heightfield shape. + * + * @param heights - The heights of the heightfield, along its local `y` axis. + * @param scale - The scale factor applied to the heightfield. + */ + public static compound( + shapes: RawCompoundShapePart[], + ): ColliderDesc { + const shape = new Compound(shapes); + return new ColliderDesc(shape); + } + /** * Computes the convex-hull of the given points and use the resulting * convex polygon as the shape for this new collider descriptor. @@ -1741,7 +1755,7 @@ export class ColliderDesc { * Sets the collision groups used by this collider. * * Two colliders will interact iff. their collision groups are compatible. - * See the documentation of `InteractionGroups` for details on teh used bit pattern. + * See the documentation of `InteractionGroups` for details on the used bit pattern. * * @param groups - The collision groups used for the collider being built. */ diff --git a/src.ts/geometry/shape.ts b/src.ts/geometry/shape.ts index 060eba94..66dc7022 100644 --- a/src.ts/geometry/shape.ts +++ b/src.ts/geometry/shape.ts @@ -1,5 +1,5 @@ import {Vector, VectorOps, Rotation, RotationOps} from "../math"; -import {RawColliderSet, RawShape, RawShapeType} from "../raw"; +import {RawColliderSet, RawCompoundShapePart, RawShape, RawShapeType} from "../raw"; import {ShapeContact} from "./contact"; import {PointProjection} from "./point"; import {Ray, RayIntersection} from "./ray"; @@ -510,7 +510,7 @@ export enum ShapeType { Triangle = 5, TriMesh = 6, HeightField = 7, - // Compound = 8, + Compound = 8, ConvexPolygon = 9, RoundCuboid = 10, RoundTriangle = 11, @@ -534,7 +534,7 @@ export enum ShapeType { Triangle = 5, TriMesh = 6, HeightField = 7, - // Compound = 8, + Compound = 8, ConvexPolyhedron = 9, Cylinder = 10, Cone = 11, @@ -1185,6 +1185,33 @@ export class Heightfield extends Shape { // #endif +/** + * A shape that is a compound. + */ +export class Compound extends Shape { + readonly type = ShapeType.Compound; + + /** + * The shapes constituting this compound shape. + */ + shapes: RawCompoundShapePart[]; + + /** + * Creates a new heightfield shape. + * + * @param shapes - The shapes constituting this compound shape. + */ + constructor(shapes: RawCompoundShapePart[]) { + super(); + this.shapes = shapes; + } + + public intoRaw(): RawShape { + let rawShape = RawShape.compound(this.shapes); + return rawShape; + } +} + // #if DIM3 /** * A shape that is a convex polygon. diff --git a/src.ts/math.ts b/src.ts/math.ts index ebca392b..2c2afea1 100644 --- a/src.ts/math.ts +++ b/src.ts/math.ts @@ -1,4 +1,4 @@ -import {RawVector, RawRotation} from "./raw"; +import {RawVector, RawRotation, RawIsometry} from "./raw"; // #if DIM3 import {RawSdpMatrix3} from "./raw"; // #endif @@ -73,8 +73,44 @@ export class RotationOps { } } +export interface Isometry { + rotation: Rotation; + position: Vector +} + // #endif +/** + * An Isometry: a rotation followed by a translation. + */ +export class Isometry implements Isometry { + rotation: Rotation; + position: Vector; + + public constructor(rotation: Rotation, position: Vector) { + this.rotation = rotation; + this.position = position; + } +} + +export class IsometryOps { + public static identity(): number { + return 0.0; + } + + public static fromRaw(raw: RawIsometry): Isometry { + if (!raw) return null; + + let res = new Isometry(RotationOps.fromRaw(raw.rotation()), VectorOps.fromRaw(raw.translation())); + raw.free(); + return res; + } + + public static intoRaw(isometry: Isometry): RawIsometry { + return new RawIsometry(RotationOps.intoRaw(isometry.rotation), VectorOps.intoRaw(isometry.position)); + } +} + // #if DIM3 export interface Vector { x: number; diff --git a/src/geometry/shape.rs b/src/geometry/shape.rs index cc2bacfa..14b190a3 100644 --- a/src/geometry/shape.rs +++ b/src/geometry/shape.rs @@ -322,6 +322,14 @@ impl RawShape { Self(SharedShape::heightfield_with_flags(heights, scale.0, flags)) } + pub fn compound(shapes: Vec) -> Self { + let shapes = shapes + .into_iter() + .map(|part| (part.pose, part.shape)) + .collect::>(); + Self(SharedShape::compound(shapes)) + } + pub fn segment(p1: &RawVector, p2: &RawVector) -> Self { Self(SharedShape::segment(p1.0.into(), p2.0.into())) } @@ -508,3 +516,10 @@ impl RawShape { .castRayAndGetNormal(&pos, rayOrig.0.into(), rayDir.0.into(), maxToi, solid) } } + +#[wasm_bindgen] +#[derive(Clone)] +pub struct RawCompoundShapePart { + pub(crate) pose: Isometry, + pub(crate) shape: SharedShape, +} diff --git a/src/math.rs b/src/math.rs index 5c50c142..b5ca996f 100644 --- a/src/math.rs +++ b/src/math.rs @@ -4,6 +4,7 @@ use js_sys::Float32Array; #[cfg(feature = "dim3")] use na::{Quaternion, Unit}; +use rapier::math::Isometry; #[cfg(feature = "dim3")] use rapier::math::Real; use rapier::math::{Point, Rotation, Vector}; @@ -264,3 +265,44 @@ impl RawSdpMatrix3 { output } } + +#[wasm_bindgen] +#[repr(transparent)] +#[cfg(feature = "dim3")] +#[derive(Copy, Clone)] +/// A rotation quaternion. +pub struct RawIsometry(pub(crate) Isometry); + +#[wasm_bindgen] +#[repr(transparent)] +#[cfg(feature = "dim2")] +#[derive(Copy, Clone)] +/// A rotation quaternion. +pub struct RawIsometry(pub(crate) Isometry); + +impl From> for RawIsometry { + fn from(v: Isometry) -> Self { + RawIsometry(v) + } +} + +#[wasm_bindgen] +/// A unit complex number describing the orientation of a Rapier entity. +impl RawIsometry { + #[wasm_bindgen(constructor)] + pub fn new(rotation: RawRotation, translation: RawVector) -> Self { + Self(Isometry::from_parts(translation.0.into(), rotation.0)) + } + /// The identity rotation. + pub fn translation(&self) -> RawVector { + RawVector(self.0.translation.vector) + } + + /// The rotation with the given angle. + pub fn rotation(&self) -> RawRotation { + #[cfg(feature = "dim2")] + return RawRotation(Rotation::new(self.0.rotation.angle())); + #[cfg(feature = "dim3")] + return RawRotation(Rotation::new(self.0.rotation.scaled_axis())); + } +}