Physics Rapier for Angular Three
npm install angular-three-rapierangular-three-rapierThis library provides Rapier physics integration for Angular Three. Rapier is a fast, cross-platform physics engine written in Rust with JavaScript bindings.
All public APIs are documented with JSDoc comments. Your IDE will provide inline documentation, parameter hints, and examples as you code.
``bash`
npm install angular-three-rapier @dimforge/rapier3d-compatyarn add angular-three-rapier @dimforge/rapier3d-compat
pnpm add angular-three-rapier @dimforge/rapier3d-compat
> Make sure to already have angular-three installed
`typescript
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { extend, NgtArgs } from 'angular-three';
import { NgtrPhysics, NgtrRigidBody } from 'angular-three-rapier';
import * as THREE from 'three';
extend(THREE);
@Component({
selector: 'app-box',
template:
,
imports: [NgtrRigidBody],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class Box {}
@Component({
selector: 'app-ground',
template:
,
imports: [NgtrRigidBody, NgtArgs],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class Ground {}
@Component({
template:
,`
imports: [NgtrPhysics, Box, Ground],
})
export class SceneGraph {}
| Property | Description | Default |
| ------------- | ----------------------------------------------- | --------------- |
| gravity | Gravity vector [x, y, z] | [0, -9.81, 0] |colliders
| | Default collider type for rigid bodies | 'cuboid' |paused
| | Whether physics simulation is paused | false |timeStep
| | Fixed timestep for physics simulation | 1/60 |debug
| | Enable debug visualization | false |interpolate
| | Enable transform interpolation | true |updateLoop
| | Update loop type: 'follow' or 'independent' | 'follow' |
Use ngt-object3D with the rigidBody attribute. The rigid body type is specified as the attribute value:
`html
`
- '' or 'dynamic' - Affected by forces and collisions'fixed'
- - Static, immovable body'kinematicPosition'
- - Controlled by position, affects dynamic bodies'kinematicVelocity'
- - Controlled by velocity, affects dynamic bodies
`html`
[options]="{
colliders: 'ball',
ccd: true,
gravityScale: 0.5,
linearVelocity: [0, 10, 0],
angularVelocity: [0, 1, 0]
}"
>
...
`html`
(collisionEnter)="onCollisionEnter($event)"
(collisionExit)="onCollisionExit($event)"
(intersectionEnter)="onIntersectionEnter($event)"
(intersectionExit)="onIntersectionExit($event)"
(contactForce)="onContactForce($event)"
(sleep)="onSleep()"
(wake)="onWake()"
>
...
Colliders use ngt-object3D with specific collider attributes. By default, rigid bodies auto-generate colliders from child meshes.
`html
`
| Directive | Args | Description |
| --------------------------- | --------------------------------- | ------------------- |
| NgtrBallCollider | [radius] | Sphere shape |NgtrCuboidCollider
| | [halfW, halfH, halfD] | Box shape |NgtrCapsuleCollider
| | [halfHeight, radius] | Capsule shape |NgtrCylinderCollider
| | [halfHeight, radius] | Cylinder shape |NgtrConeCollider
| | [halfHeight, radius] | Cone shape |NgtrConvexHullCollider
| | [vertices] | Convex hull |NgtrTrimeshCollider
| | [vertices, indices] | Triangle mesh |NgtrHeightfieldCollider
| | [width, height, heights, scale] | Terrain heightfield |NgtrRoundCuboidCollider
| | [halfW, halfH, halfD, radius] | Rounded box |NgtrRoundCylinderCollider
| | [halfH, radius, borderRadius] | Rounded cylinder |NgtrRoundConeCollider
| | [halfH, radius, borderRadius] | Rounded cone |
`html`
Generate colliders from mesh geometry:
`html`
Create joints between rigid bodies using injectable functions:
`typescript
import { Component, viewChild } from '@angular/core';
import {
NgtrRigidBody,
sphericalJoint,
revoluteJoint,
prismaticJoint,
fixedJoint,
ropeJoint,
springJoint,
} from 'angular-three-rapier';
@Component({
template:
,
})
export class JointExample {
bodyA = viewChild.required
bodyB = viewChild.required
// Spherical joint (ball-and-socket)
joint = sphericalJoint(
() => this.bodyA().rigidBody(),
() => this.bodyB().rigidBody(),
{
data: {
body1Anchor: [0, -0.5, 0],
body2Anchor: [0, 0.5, 0],
},
},
);
// Revolute joint (hinge) with limits
hingeJoint = revoluteJoint(
() => this.bodyA().rigidBody(),
() => this.bodyB().rigidBody(),
{
data: {
body1Anchor: [0, 0, 0],
body2Anchor: [0, 1, 0],
axis: [0, 1, 0],
limits: [-Math.PI / 2, Math.PI / 2],
},
},
);
// Prismatic joint (slider)
sliderJoint = prismaticJoint(
() => this.bodyA().rigidBody(),
() => this.bodyB().rigidBody(),
{
data: {
body1Anchor: [0, 0, 0],
body2Anchor: [2, 0, 0],
axis: [1, 0, 0],
limits: [-1, 1],
},
},
);
// Rope joint (max distance constraint)
rope = ropeJoint(
() => this.bodyA().rigidBody(),
() => this.bodyB().rigidBody(),
{
data: {
body1Anchor: [0, 0, 0],
body2Anchor: [0, 0, 0],
length: 5,
},
},
);
// Spring joint
spring = springJoint(
() => this.bodyA().rigidBody(),
() => this.bodyB().rigidBody(),
{
data: {
body1Anchor: [0, 0, 0],
body2Anchor: [0, 0, 0],
restLength: 2,
stiffness: 100,
damping: 10,
},
},
);
}
`
For efficient physics with many identical objects:
`typescript
import { NgtArgs } from 'angular-three';
import { NgtrInstancedRigidBodies } from 'angular-three-rapier';
@Component({
template:
,`
imports: [NgtrInstancedRigidBodies, NgtArgs],
})
export class Spheres {
instances = Array.from({ length: 100 }, (_, i) => ({
key: i,
position: [Math.random() 10, Math.random() 10, 0] as [number, number, number],
}));
}
Filter collisions between objects:
`typescript
import { interactionGroups } from 'angular-three-rapier';
// Member of group 0, collides with groups 0 and 1
const groups = interactionGroups([0], [0, 1]);
`
`html`
`typescript
import { beforePhysicsStep, afterPhysicsStep } from 'angular-three-rapier';
@Component({...})
export class MyComponent {
constructor() {
beforePhysicsStep((world) => {
// Run before each physics step
});
afterPhysicsStep((world) => {
// Run after each physics step
});
}
}
`
Enable debug rendering via physics options:
`html`
Apply gravitational or magnetic forces:
`typescript`
import { NgtrAttractor } from 'angular-three-rapier/addons';
`html
strength: 1000,
range: 50,
type: 'newtonian',
gravitationalConstant: 0.01
}"
/>
``