npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

angular-three-rapier

v4.0.9

Published

Physics Rapier for Angular Three

Readme

angular-three-rapier

This library provides Rapier physics integration for Angular Three. Rapier is a fast, cross-platform physics engine written in Rust with JavaScript bindings.

Documentation

All public APIs are documented with JSDoc comments. Your IDE will provide inline documentation, parameter hints, and examples as you code.

Installation

npm install angular-three-rapier @dimforge/rapier3d-compat
# yarn add angular-three-rapier @dimforge/rapier3d-compat
# pnpm add angular-three-rapier @dimforge/rapier3d-compat

Make sure to already have angular-three installed

Usage

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: `
		<ngt-object3D rigidBody [position]="[0, 5, 0]">
			<ngt-mesh>
				<ngt-box-geometry />
				<ngt-mesh-standard-material color="hotpink" />
			</ngt-mesh>
		</ngt-object3D>
	`,
	imports: [NgtrRigidBody],
	schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class Box {}

@Component({
	selector: 'app-ground',
	template: `
		<ngt-object3D rigidBody="fixed" [position]="[0, -1, 0]">
			<ngt-mesh>
				<ngt-box-geometry *args="[20, 1, 20]" />
				<ngt-mesh-standard-material color="gray" />
			</ngt-mesh>
		</ngt-object3D>
	`,
	imports: [NgtrRigidBody, NgtArgs],
	schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class Ground {}

@Component({
	template: `
		<ngtr-physics [options]="{ gravity: [0, -9.81, 0] }">
			<ng-template>
				<app-box />
				<app-ground />
			</ng-template>
		</ngtr-physics>
	`,
	imports: [NgtrPhysics, Box, Ground],
})
export class SceneGraph {}

Physics Options

| 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' |

Rigid Body

Use ngt-object3D with the rigidBody attribute. The rigid body type is specified as the attribute value:

<!-- Dynamic (default when empty) -->
<ngt-object3D rigidBody [position]="[0, 5, 0]">
	<ngt-mesh>...</ngt-mesh>
</ngt-object3D>

<!-- Fixed (static) -->
<ngt-object3D rigidBody="fixed" [position]="[0, -1, 0]">
	<ngt-mesh>...</ngt-mesh>
</ngt-object3D>

<!-- Kinematic -->
<ngt-object3D rigidBody="kinematicPosition">
	<ngt-mesh>...</ngt-mesh>
</ngt-object3D>

Rigid Body Types

  • '' 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

Rigid Body Options

<ngt-object3D
	rigidBody
	[options]="{
		colliders: 'ball',
		ccd: true,
		gravityScale: 0.5,
		linearVelocity: [0, 10, 0],
		angularVelocity: [0, 1, 0]
	}"
>
	...
</ngt-object3D>

Rigid Body Events

<ngt-object3D
	rigidBody
	(collisionEnter)="onCollisionEnter($event)"
	(collisionExit)="onCollisionExit($event)"
	(intersectionEnter)="onIntersectionEnter($event)"
	(intersectionExit)="onIntersectionExit($event)"
	(contactForce)="onContactForce($event)"
	(sleep)="onSleep()"
	(wake)="onWake()"
>
	...
</ngt-object3D>

Colliders

Colliders use ngt-object3D with specific collider attributes. By default, rigid bodies auto-generate colliders from child meshes.

Explicit Colliders

<!-- Ball collider -->
<ngt-object3D [ballCollider]="[0.5]" [position]="[0, 2, 0]" />

<!-- Cuboid collider (half-extents) -->
<ngt-object3D [cuboidCollider]="[1, 0.5, 2]" [position]="[0, 0, 0]" />

<!-- Capsule collider (half-height, radius) -->
<ngt-object3D [capsuleCollider]="[0.5, 0.25]" [position]="[0, 1, 0]" />

<!-- Cylinder collider (half-height, radius) -->
<ngt-object3D [cylinderCollider]="[1, 0.5]" />

<!-- Cone collider (half-height, radius) -->
<ngt-object3D [coneCollider]="[1, 0.5]" />

Available Collider Directives

| 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 |

Disabling Auto-Colliders

<ngt-object3D rigidBody [options]="{ colliders: false }">
	<!-- Manual colliders only -->
	<ngt-object3D [ballCollider]="[0.5]" />
</ngt-object3D>

Mesh Collider

Generate colliders from mesh geometry:

<ngt-object3D rigidBody [options]="{ colliders: false }">
	<ngt-object3D [meshCollider]="'trimesh'">
		<ngt-mesh>
			<ngt-torus-geometry />
			<ngt-mesh-standard-material />
		</ngt-mesh>
	</ngt-object3D>
</ngt-object3D>

Joints

Create joints between rigid bodies using injectable functions:

import { Component, viewChild } from '@angular/core';
import {
	NgtrRigidBody,
	sphericalJoint,
	revoluteJoint,
	prismaticJoint,
	fixedJoint,
	ropeJoint,
	springJoint,
} from 'angular-three-rapier';

@Component({
	template: `
		<ngt-object3D rigidBody="fixed" #bodyA="rigidBody">...</ngt-object3D>
		<ngt-object3D rigidBody #bodyB="rigidBody">...</ngt-object3D>
	`,
})
export class JointExample {
	bodyA = viewChild.required<NgtrRigidBody>('bodyA');
	bodyB = viewChild.required<NgtrRigidBody>('bodyB');

	// 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,
			},
		},
	);
}

Instanced Rigid Bodies

For efficient physics with many identical objects:

import { NgtArgs } from 'angular-three';
import { NgtrInstancedRigidBodies } from 'angular-three-rapier';

@Component({
	template: `
		<ngt-object3D [instancedRigidBodies]="instances">
			<ngt-instanced-mesh [count]="instances.length" castShadow>
				<ngt-sphere-geometry *args="[0.5]" />
				<ngt-mesh-standard-material color="orange" />
			</ngt-instanced-mesh>
		</ngt-object3D>
	`,
	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],
	}));
}

Interaction Groups

Filter collisions between objects:

import { interactionGroups } from 'angular-three-rapier';

// Member of group 0, collides with groups 0 and 1
const groups = interactionGroups([0], [0, 1]);
<!-- Using directive -->
<ngt-object3D rigidBody [interactionGroups]="[[0], [0, 1]]">...</ngt-object3D>

Physics Hooks

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
		});
	}
}

Debug Visualization

Enable debug rendering via physics options:

<ngtr-physics [options]="{ debug: true }">
	<ng-template>
		<!-- your physics objects -->
	</ng-template>
</ngtr-physics>

Addons

Attractor

Apply gravitational or magnetic forces:

import { NgtrAttractor } from 'angular-three-rapier/addons';
<!-- Attractor with default options -->
<ngt-object3D attractor />

<!-- Attractor with custom options -->
<ngt-object3D [attractor]="{ strength: 10, range: 20, type: 'linear' }" />

<!-- Repeller (negative strength) -->
<ngt-object3D [attractor]="{ strength: -10, range: 15 }" [position]="[5, 0, 0]" />

<!-- Newtonian gravity -->
<ngt-object3D
	[attractor]="{
		strength: 1000,
		range: 50,
		type: 'newtonian',
		gravitationalConstant: 0.01
	}"
/>