Big News: Socket Selected for OpenAI's Cybersecurity Grant Program.Details
Socket
Book a DemoSign in
Socket

@react-three/rapier

Package Overview
Dependencies
Maintainers
23
Versions
75
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@react-three/rapier - npm Package Compare versions

Comparing version
2.1.0
to
2.2.0
+19
-9
dist/declarations/src/components/Physics.d.ts
import type Rapier from "@dimforge/rapier3d-compat";
import { Collider, ColliderHandle, RigidBody, RigidBodyHandle, World } from "@dimforge/rapier3d-compat";
import { Collider, ColliderHandle, RigidBody, RigidBodyHandle, SolverFlags, World } from "@dimforge/rapier3d-compat";
import React, { FC, ReactNode } from "react";

@@ -24,2 +24,10 @@ import { Matrix4, Object3D, Vector3 } from "three";

}>;
export type FilterContactPairCallback = (collider1: ColliderHandle, collider2: ColliderHandle, body1: RigidBodyHandle, body2: RigidBodyHandle) => SolverFlags | null;
export type FilterIntersectionPairCallback = (collider1: ColliderHandle, collider2: ColliderHandle, body1: RigidBodyHandle, body2: RigidBodyHandle) => boolean;
export type FilterContactPairCallbackSet = Set<{
current: FilterContactPairCallback;
}>;
export type FilterIntersectionPairCallbackSet = Set<{
current: FilterIntersectionPairCallback;
}>;
export interface ColliderState {

@@ -74,2 +82,12 @@ collider: Collider;

/**
* Hooks to filter contact pairs
* @internal
*/
filterContactPairHooks: FilterContactPairCallbackSet;
/**
* Hooks to filter intersection pairs
* @internal
*/
filterIntersectionPairHooks: FilterIntersectionPairCallbackSet;
/**
* Direct access to the Rapier instance

@@ -167,10 +185,2 @@ */

/**
* Number of addition friction resolution iteration run during the last solver sub-step.
* The greater this value is, the most realistic friction will be.
* However a greater number of iterations is more computationally intensive.
*
* @defaultValue 4
*/
numAdditionalFrictionIterations?: number;
/**
* Number of internal Project Gauss Seidel (PGS) iterations run at each solver iteration.

@@ -177,0 +187,0 @@ * Increasing this parameter will improve stability of the simulation. It will have a lesser effect than

@@ -21,4 +21,72 @@ import { RefObject } from "react";

/**
* Registers a callback to filter contact pairs.
*
* The callback determines if contact computation should happen between two colliders,
* and how the constraints solver should behave for these contacts.
*
* This will only be executed if at least one of the involved colliders contains the
* `ActiveHooks.FILTER_CONTACT_PAIR` flag in its active hooks.
*
* @param callback - Function that returns:
* - `SolverFlags.COMPUTE_IMPULSE` (1) - Process the collision normally (compute impulses and resolve penetration)
* - `SolverFlags.EMPTY` (0) - Skip computing impulses for this collision pair (colliders pass through each other)
* - `null` - Skip this hook; let the next registered hook decide, or use Rapier's default behavior if no hook handles it
*
* When multiple hooks are registered, they are called in order until one returns a non-null value.
* That value is then passed to Rapier's physics engine.
*
* @category Hooks
*
* @example
* ```tsx
* import { useFilterContactPair } from '@react-three/rapier';
* import { SolverFlags } from '@dimforge/rapier3d-compat';
*
* useFilterContactPair((collider1, collider2, body1, body2) => {
* // Only process collisions for specific bodies
* if (body1 === myBodyHandle) {
* return SolverFlags.COMPUTE_IMPULSE;
* }
* // Let other hooks or default behavior handle it
* return null;
* });
* ```
*/
export declare const useFilterContactPair: (callback: (collider1: number, collider2: number, body1: number, body2: number) => number | null) => void;
/**
* Registers a callback to filter intersection pairs.
*
* The callback determines if intersection computation should happen between two colliders
* (where at least one is a sensor).
*
* This will only be executed if at least one of the involved colliders contains the
* `ActiveHooks.FILTER_INTERSECTION_PAIR` flag in its active hooks.
*
* @param callback - Function that returns:
* - `true` - Allow the intersection to be detected (trigger intersection events)
* - `false` - Block the intersection (no intersection events will fire)
*
* When multiple hooks are registered, the **first hook that returns `false` blocks** the intersection.
* If all hooks return `true`, the intersection is allowed.
*
* @category Hooks
*
* @example
* ```tsx
* import { useFilterIntersectionPair } from '@react-three/rapier';
*
* useFilterIntersectionPair((collider1, collider2, body1, body2) => {
* // Block intersections for specific body pairs
* if (body1 === myBodyHandle && body2 === otherBodyHandle) {
* return false;
* }
* // Allow all other intersections
* return true;
* });
* ```
*/
export declare const useFilterIntersectionPair: (callback: (collider1: number, collider2: number, body1: number, body2: number) => boolean) => void;
/**
* @internal
*/
export declare const useChildColliderProps: <O extends Object3D>(ref: RefObject<O | undefined | null>, options: RigidBodyProps, ignoreMeshColliders?: boolean) => ColliderProps[];

@@ -5,3 +5,3 @@ export * from "./types.js";

export type { CylinderColliderProps, BallColliderProps, CapsuleColliderProps, ConeColliderProps, ConvexHullColliderProps, CuboidColliderProps, HeightfieldColliderProps, RoundCuboidColliderProps, TrimeshColliderProps, ColliderOptionsRequiredArgs } from "./components/AnyCollider.js";
export type { PhysicsProps, RapierContext, WorldStepCallback } from "./components/Physics.js";
export type { PhysicsProps, RapierContext, WorldStepCallback, FilterContactPairCallback, FilterIntersectionPairCallback } from "./components/Physics.js";
export type { MeshColliderProps } from "./components/MeshCollider.js";

@@ -14,4 +14,4 @@ export { Physics } from "./components/Physics.js";

export * from "./hooks/joints.js";
export { useRapier, useBeforePhysicsStep, useAfterPhysicsStep } from "./hooks/hooks.js";
export { useRapier, useBeforePhysicsStep, useAfterPhysicsStep, useFilterContactPair, useFilterIntersectionPair } from "./hooks/hooks.js";
export * from "./utils/interaction-groups.js";
export * from "./utils/three-object-helpers.js";
{
"name": "@react-three/rapier",
"version": "2.1.0",
"version": "2.2.0",
"source": "src/index.ts",

@@ -28,3 +28,3 @@ "main": "dist/react-three-rapier.cjs.js",

"dependencies": {
"@dimforge/rapier3d-compat": "0.15.0",
"@dimforge/rapier3d-compat": "0.19.2",
"suspend-react": "^0.1.3",

@@ -31,0 +31,0 @@ "three-stdlib": "^2.35.12"

@@ -6,2 +6,7 @@ <p align="center">

<p align="center">
📣 @react-three/rapier v2 has been released, which adds support for @react-three/fiber v9 and react v19. If you are using react v18, you will need to use @react-three/rapier v1 and @react-three/fiber v8.
</p>
<p align="center">
<a href="https://www.npmjs.com/package/@react-three/rapier"><img src="https://img.shields.io/npm/v/@react-three/rapier?style=for-the-badge&colorA=0099DA&colorB=ffffff" /></a>

@@ -84,2 +89,3 @@ <a href="https://discord.gg/ZZjjNvJ"><img src="https://img.shields.io/discord/740090768164651008?style=for-the-badge&colorA=0099DA&colorB=ffffff&label=discord&logo=discord&logoColor=ffffff" /></a>

- [Advanced hooks usage](#advanced-hooks-usage)
- [Physics Hooks (Collision Filtering)](#physics-hooks-collision-filtering)
- [Manual stepping](#manual-stepping)

@@ -886,2 +892,91 @@ - [On-demand rendering](#on-demand-rendering)

### Physics Hooks (Collision Filtering)
You can implement advanced collision behaviors like one-way platforms by using physics hooks. These hooks allow you to filter collision and intersection pairs during the physics step.
`r3/rapier` provides two hooks for collision filtering:
- `useFilterContactPair` - Filter collision pairs and control solver behavior
- `useFilterIntersectionPair` - Filter intersection pairs for sensors
#### Filter Contact Pairs
`useFilterContactPair` allows you to control how collisions are processed. The callback should return:
- `SolverFlags.COMPUTE_IMPULSE` (1) - Process the collision normally
- `SolverFlags.EMPTY` (0) - Ignore the collision
- `null` - Let other hooks decide, or use default behavior
#### Filter Intersection Pairs
`useFilterIntersectionPair` controls which sensor intersections are detected. The callback should return:
- `true` - Allow the intersection to be detected
- `false` - Block the intersection
If multiple hooks are registered:
- For contact pairs, the **first hook that returns non-null wins**
- For intersection pairs, the **first hook that returns false blocks** the intersection
**Important:** To avoid Rust aliasing errors, you **cannot** access rigid body properties (like `translation()` or `linvel()`) directly during the physics step. Instead, cache the needed state before the step using `useBeforePhysicsStep`.
🧩 See [useFilterContactPair docs](https://pmndrs.github.io/react-three-rapier/functions/useFilterContactPair.html) and [useFilterIntersectionPair docs](https://pmndrs.github.io/react-three-rapier/functions/useFilterIntersectionPair.html) for more information.
```tsx
import {
useRapier,
useBeforePhysicsStep,
useFilterContactPair
} from "@react-three/rapier";
const OneWayPlatform = () => {
const platformRef = useRef<RapierRigidBody>(null);
const ballRef = useRef<RapierRigidBody>(null);
const colliderRef = useRef<RapierCollider>(null);
// Cache for storing body states before physics step
const bodyStateCache = useRef(new Map());
const { rapier } = useRapier();
// Cache body states BEFORE the physics step
useBeforePhysicsStep(() => {
if (platformRef.current && ballRef.current) {
const ballPos = ballRef.current.translation();
const ballVel = ballRef.current.linvel();
bodyStateCache.current.set(ballRef.current.handle, {
position: ballPos,
velocity: ballVel
});
}
});
// Filter collisions using cached data
useFilterContactPair((collider1, collider2, body1, body2) => {
const ballState = bodyStateCache.current.get(body1);
if (!ballState) return null; // Let other hooks or default behavior handle it
// Allow collision only if ball is moving down and above platform
if (ballState.velocity.y < 0 && ballState.position.y > 0) {
return rapier.SolverFlags.COMPUTE_IMPULSE; // Process collision
}
return rapier.SolverFlags.EMPTY; // Ignore collision
});
useEffect(() => {
// Enable active hooks on the collider (required for filtering)
colliderRef.current?.setActiveHooks(rapier.ActiveHooks.FILTER_CONTACT_PAIRS);
}, []);
return (
<>
<RigidBody ref={platformRef} type="fixed">
<CuboidCollider ref={colliderRef} args={[5, 0.1, 5]} />
</RigidBody>
<RigidBody ref={ballRef} position={[0, 3, 0]}>
<CuboidCollider args={[1, 1, 1]} />
</RigidBody>
</>
);
};
```
### Manual stepping

@@ -945,2 +1040,2 @@

}
```
```

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display