angular-three-rapier
Version:
Physics Rapier for Angular Three
1,165 lines (1,162 loc) • 86.1 kB
TypeScript
import * as _dimforge_rapier3d_compat from '@dimforge/rapier3d-compat';
import _dimforge_rapier3d_compat__default, { CoefficientCombineRule, InteractionGroups, ActiveCollisionTypes, Vector, Rotation, RigidBody, Collider, TempContactManifold, ColliderHandle, RigidBodyHandle, World, SolverFlags, FixedImpulseJoint, SphericalImpulseJoint, RevoluteImpulseJoint, PrismaticImpulseJoint, RopeImpulseJoint, SpringImpulseJoint } from '@dimforge/rapier3d-compat';
import * as _angular_core from '@angular/core';
import { ElementRef, InjectionToken, Injector, TemplateRef } from '@angular/core';
import * as angular_three from 'angular-three';
import { NgtThreeElements, NgtVector3, NgtQuaternion, NgtEuler } from 'angular-three';
import * as THREE from 'three';
import * as angular_three_rapier from 'angular-three-rapier';
/**
* Type of automatic collider generation for rigid bodies.
*
* - `'ball'` - Generates a spherical collider based on the bounding sphere
* - `'cuboid'` - Generates a box collider based on the bounding box
* - `'hull'` - Generates a convex hull collider from the mesh vertices
* - `'trimesh'` - Generates a triangle mesh collider (exact shape, most expensive)
* - `false` - Disables automatic collider generation
*/
type NgtrRigidBodyAutoCollider = 'ball' | 'cuboid' | 'hull' | 'trimesh' | false;
interface NgtrPhysicsOptions {
/**
* Set the gravity of the physics world
* @defaultValue [0, -9.81, 0]
*/
gravity: THREE.Vector3Tuple;
/**
* Amount of penetration the engine wont attempt to correct
* @defaultValue 0.001
*/
allowedLinearError: number;
/**
* The number of solver iterations run by the constraints solver for calculating forces.
* The greater this value is, the most rigid and realistic the physics simulation will be.
* However a greater number of iterations is more computationally intensive.
*
* @defaultValue 4
*/
numSolverIterations: number;
/**
* Number of internal Project Gauss Seidel (PGS) iterations run at each solver iteration.
* Increasing this parameter will improve stability of the simulation. It will have a lesser effect than
* increasing `numSolverIterations` but is also less computationally expensive.
*
* @defaultValue 1
*/
numInternalPgsIterations: number;
/**
* The maximal distance separating two objects that will generate predictive contacts
*
* @defaultValue 0.002
*
*/
predictionDistance: number;
/**
* Minimum number of dynamic bodies in each active island
*
* @defaultValue 128
*/
minIslandSize: number;
/**
* Maximum number of substeps performed by the solver
*
* @defaultValue 1
*/
maxCcdSubsteps: number;
/**
* Directly affects the erp (Error Reduction Parameter) which is the proportion (between 0 and 1) of the positional error to be corrected at each time step.
*
* The higher the value, the more the physics engine will try to correct the positional error.
*
* This property is currently undocumented in rapier docs.
*
* @defaultValue 30
*/
contactNaturalFrequency: number;
/**
* The approximate size of most dynamic objects in the scene.
*
* This value is used internally to estimate some length-based tolerance.
* This value can be understood as the number of units-per-meter in your physical world compared to a human-sized world in meter.
*
* @defaultValue 1
*/
lengthUnit: number;
/**
* Set the base automatic colliders for this physics world
* All Meshes inside RigidBodies will generate a collider
* based on this value, if not overridden.
*/
colliders?: NgtrRigidBodyAutoCollider;
/**
* Set the timestep for the simulation.
* Setting this to a number (eg. 1/60) will run the
* simulation at that framerate. Alternatively, you can set this to
* "vary", which will cause the simulation to always synchronize with
* the current frame delta times.
*
* @defaultValue 1/60
*/
timeStep: number | 'vary';
/**
* Pause the physics simulation
*
* @defaultValue false
*/
paused: boolean;
/**
* Interpolate the world transform using the frame delta times.
* Has no effect if timeStep is set to "vary".
*
* @defaultValue true
**/
interpolate: boolean;
/**
* The update priority at which the physics simulation should run.
* Only used when `updateLoop` is set to "follow".
*
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#taking-over-the-render-loop
* @defaultValue undefined
*/
updatePriority?: number;
/**
* Set the update loop strategy for the physics world.
*
* If set to "follow", the physics world will be stepped
* in a `useFrame` callback, managed by @react-three/fiber.
* You can use `updatePriority` prop to manage the scheduling.
*
* If set to "independent", the physics world will be stepped
* in a separate loop, not tied to the render loop.
* This is useful when using the "demand" `frameloop` strategy for the
* @react-three/fiber `<Canvas />`.
*
* @see https://docs.pmnd.rs/react-three-fiber/advanced/scaling-performance#on-demand-rendering
* @defaultValue "follow"
*/
updateLoop: 'follow' | 'independent';
/**
* Enable debug rendering of the physics world.
* @defaultValue false
*/
debug: boolean;
}
/**
* Internal state tracking for a rigid body in the physics simulation.
* Used by the physics system to synchronize Three.js objects with Rapier physics bodies.
*/
interface NgtrRigidBodyState {
/** The type of mesh associated with this rigid body */
meshType: 'instancedMesh' | 'mesh';
/** The underlying Rapier rigid body instance */
rigidBody: RigidBody;
/** The Three.js Object3D representing this rigid body */
object: THREE.Object3D;
/** Inverted world matrix for coordinate transformations */
invertedWorldMatrix: THREE.Matrix4;
/** Function to set the object's transformation matrix */
setMatrix: (matrix: THREE.Matrix4) => void;
/** Function to get the object's transformation matrix */
getMatrix: (matrix: THREE.Matrix4) => THREE.Matrix4;
/**
* The world scale of the object.
* Required for instanced rigid bodies.
*/
scale: THREE.Vector3;
/** Whether the rigid body is currently sleeping (inactive) */
isSleeping: boolean;
}
/**
* Map storing rigid body states indexed by their handle.
*/
type NgtrRigidBodyStateMap = Map<RigidBody['handle'], NgtrRigidBodyState>;
/**
* Internal state tracking for a collider in the physics simulation.
* Used by the physics system to synchronize Three.js objects with Rapier colliders.
*/
interface NgtrColliderState {
/** The underlying Rapier collider instance */
collider: Collider;
/** The Three.js Object3D representing this collider */
object: THREE.Object3D;
/**
* The parent of which this collider needs to base its
* world position on, can be empty
*/
worldParent?: THREE.Object3D;
}
/**
* Map storing collider states indexed by their handle.
*/
type NgtrColliderStateMap = Map<Collider['handle'], NgtrColliderState>;
/**
* Represents a collision target with references to both the physics objects
* and their corresponding Three.js representations.
*/
interface NgtrCollisionTarget {
/** The Rapier rigid body involved in the collision (if any) */
rigidBody?: RigidBody;
/** The Rapier collider involved in the collision */
collider: Collider;
/** The Three.js Object3D representing the rigid body */
rigidBodyObject?: THREE.Object3D;
/** The Three.js Object3D representing the collider */
colliderObject?: THREE.Object3D;
}
/**
* Base payload for collision events containing references to both objects involved.
*/
interface NgtrCollisionPayload {
/** The object firing the event */
target: NgtrCollisionTarget;
/** The other object involved in the event */
other: NgtrCollisionTarget;
}
/**
* Payload for collision enter events, includes contact manifold information.
*/
interface NgtrCollisionEnterPayload extends NgtrCollisionPayload {
/** The contact manifold containing contact point information */
manifold: TempContactManifold;
/** Whether the collision pair order was flipped */
flipped: boolean;
}
/**
* Payload for collision exit events.
*/
interface NgtrCollisionExitPayload extends NgtrCollisionPayload {
}
/**
* Payload for sensor intersection enter events.
*/
interface NgtrIntersectionEnterPayload extends NgtrCollisionPayload {
}
/**
* Payload for sensor intersection exit events.
*/
interface NgtrIntersectionExitPayload extends NgtrCollisionPayload {
}
/**
* Payload for contact force events, includes force magnitude and direction information.
*/
interface NgtrContactForcePayload extends NgtrCollisionPayload {
/** The total force vector applied during contact */
totalForce: Vector;
/** The magnitude of the total force */
totalForceMagnitude: number;
/** The direction of the maximum force component */
maxForceDirection: Vector;
/** The magnitude of the maximum force component */
maxForceMagnitude: number;
}
/**
* Handler function for collision enter events.
* @param payload - The collision enter event payload
*/
type NgtrCollisionEnterHandler = (payload: NgtrCollisionEnterPayload) => void;
/**
* Handler function for collision exit events.
* @param payload - The collision exit event payload
*/
type NgtrCollisionExitHandler = (payload: NgtrCollisionExitPayload) => void;
/**
* Handler function for intersection enter events (sensors).
* @param payload - The intersection enter event payload
*/
type NgtrIntersectionEnterHandler = (payload: NgtrIntersectionEnterPayload) => void;
/**
* Handler function for intersection exit events (sensors).
* @param payload - The intersection exit event payload
*/
type NgtrIntersectionExitHandler = (payload: NgtrIntersectionExitPayload) => void;
/**
* Handler function for contact force events.
* @param payload - The contact force event payload
*/
type NgtrContactForceHandler = (payload: NgtrContactForcePayload) => void;
/**
* Collection of event handlers for physics events on rigid bodies and colliders.
*/
interface NgtrEventMapValue {
/** Called when the rigid body enters sleep state */
onSleep?(): void;
/** Called when the rigid body wakes from sleep state */
onWake?(): void;
/** Called when a collision starts */
onCollisionEnter?: NgtrCollisionEnterHandler;
/** Called when a collision ends */
onCollisionExit?: NgtrCollisionExitHandler;
/** Called when a sensor intersection starts */
onIntersectionEnter?: NgtrIntersectionEnterHandler;
/** Called when a sensor intersection ends */
onIntersectionExit?: NgtrIntersectionExitHandler;
/** Called when contact forces are applied */
onContactForce?: NgtrContactForceHandler;
}
/**
* Map storing event handlers indexed by collider or rigid body handle.
*/
type NgtrEventMap = Map<ColliderHandle | RigidBodyHandle, NgtrEventMapValue>;
/**
* Callback function invoked during physics world step.
* @param world - The Rapier physics world instance
*/
type NgtrWorldStepCallback = (world: World) => void;
/**
* Callback to filter contact pairs and determine solver behavior.
*
* @param collider1 - Handle of the first collider
* @param collider2 - Handle of the second collider
* @param body1 - Handle of the first rigid body
* @param body2 - Handle of the second rigid body
* @returns SolverFlags to control collision response, or null to skip this hook
*
* @see https://rapier.rs/docs/user_guides/javascript/advanced_collision_detection#contact-and-intersection-filtering
*/
type NgtrFilterContactPairCallback = (collider1: ColliderHandle, collider2: ColliderHandle, body1: RigidBodyHandle, body2: RigidBodyHandle) => SolverFlags | null;
/**
* Callback to filter intersection pairs for sensors.
*
* @param collider1 - Handle of the first collider
* @param collider2 - Handle of the second collider
* @param body1 - Handle of the first rigid body
* @param body2 - Handle of the second rigid body
* @returns true to allow intersection detection, false to block it
*
* @see https://rapier.rs/docs/user_guides/javascript/advanced_collision_detection#contact-and-intersection-filtering
*/
type NgtrFilterIntersectionPairCallback = (collider1: ColliderHandle, collider2: ColliderHandle, body1: RigidBodyHandle, body2: RigidBodyHandle) => boolean;
/**
* Internal structure representing a collision source with its associated
* physics objects, events, and states.
*/
interface NgtrCollisionSource {
/** The collider information */
collider: {
/** The Rapier collider object */
object: Collider;
/** Event handlers for this collider */
events?: NgtrEventMapValue;
/** State tracking for this collider */
state?: NgtrColliderState;
};
/** The rigid body information (if any) */
rigidBody: {
/** The Rapier rigid body object */
object?: RigidBody;
/** Event handlers for this rigid body */
events?: NgtrEventMapValue;
/** State tracking for this rigid body */
state?: NgtrRigidBodyState;
};
}
/**
* Available collider shape types in Rapier.
*
* - `'cuboid'` - Box shape with half-extents
* - `'ball'` - Sphere shape with radius
* - `'capsule'` - Capsule shape with half-height and radius
* - `'cylinder'` - Cylinder shape with half-height and radius
* - `'cone'` - Cone shape with half-height and radius
* - `'convexHull'` - Convex hull computed from vertices
* - `'convexMesh'` - Convex mesh from vertices and indices
* - `'trimesh'` - Triangle mesh (exact collision shape)
* - `'heightfield'` - Height field terrain
* - `'polyline'` - Polyline shape
* - `'roundCuboid'` - Cuboid with rounded corners
* - `'roundCylinder'` - Cylinder with rounded edges
* - `'roundCone'` - Cone with rounded edges
* - `'roundConvexHull'` - Convex hull with rounded edges
* - `'roundConvexMesh'` - Convex mesh with rounded edges
*/
type NgtrColliderShape = 'cuboid' | 'trimesh' | 'ball' | 'capsule' | 'convexHull' | 'heightfield' | 'polyline' | 'roundCuboid' | 'cylinder' | 'roundCylinder' | 'cone' | 'roundCone' | 'convexMesh' | 'roundConvexHull' | 'roundConvexMesh';
/**
* Configuration options for colliders.
* These options control the physical properties of colliders.
*/
interface NgtrColliderOptions {
/**
* The optional name passed to THREE's Object3D
*/
name?: string;
/**
* Principal angular inertia of this rigid body
*/
principalAngularInertia?: THREE.Vector3Tuple;
/**
* Restitution controls how elastic (aka. bouncy) a contact is. Le elasticity of a contact is controlled by the restitution coefficient
*/
restitution?: number;
/**
* What happens when two bodies meet. See https://rapier.rs/docs/user_guides/javascript/colliders#friction.
*/
restitutionCombineRule?: CoefficientCombineRule;
/**
* Friction is a force that opposes the relative tangential motion between two rigid-bodies with colliders in contact.
* A friction coefficient of 0 implies no friction at all (completely sliding contact) and a coefficient
* greater or equal to 1 implies a very strong friction. Values greater than 1 are allowed.
*/
friction?: number;
/**
* What happens when two bodies meet. See https://rapier.rs/docs/user_guides/javascript/colliders#friction.
*/
frictionCombineRule?: CoefficientCombineRule;
/**
* The bit mask configuring the groups and mask for collision handling.
*/
collisionGroups?: InteractionGroups;
/**
* The bit mask configuring the groups and mask for solver handling.
*/
solverGroups?: InteractionGroups;
/**
* The collision types active for this collider.
*
* Use `ActiveCollisionTypes` to specify which collision types should be active for this collider.
*
* @see https://rapier.rs/javascript3d/classes/Collider.html#setActiveCollisionTypes
* @see https://rapier.rs/javascript3d/enums/ActiveCollisionTypes.html
*/
activeCollisionTypes?: ActiveCollisionTypes;
/**
* Sets the uniform density of this collider.
* If this is set, other mass-properties like the angular inertia tensor are computed
* automatically from the collider's shape.
* Cannot be used at the same time as the mass or massProperties values.
* More info https://rapier.rs/docs/user_guides/javascript/colliders#mass-properties
*/
density?: number;
/**
* The mass of this collider.
* Generally, it's not recommended to adjust the mass properties as it could lead to
* unexpected behaviors.
* Cannot be used at the same time as the density or massProperties values.
* More info https://rapier.rs/docs/user_guides/javascript/colliders#mass-properties
*/
mass?: number;
/**
* The mass properties of this rigid body.
* Cannot be used at the same time as the density or mass values.
*/
massProperties?: {
mass: number;
centerOfMass: Vector;
principalAngularInertia: Vector;
angularInertiaLocalFrame: Rotation;
};
/**
* The contact skin of the collider.
*
* The contact skin acts as if the collider was enlarged with a skin of width contactSkin around it, keeping objects further apart when colliding.
*
* A non-zero contact skin can increase performance, and in some cases, stability.
* However it creates a small gap between colliding object (equal to the sum of their skin).
* If the skin is sufficiently small, this might not be visually significant or can be hidden by the rendering assets.
*
* @defaultValue 0
*/
contactSkin: number;
/**
* Sets whether or not this collider is a sensor.
*/
sensor?: boolean;
}
/**
* Type of rigid body determining its behavior in the physics simulation.
*
* - `'dynamic'` - Fully simulated body affected by forces and collisions
* - `'fixed'` - Static body that doesn't move but can be collided with
* - `'kinematicPosition'` - User-controlled body moved by setting position
* - `'kinematicVelocity'` - User-controlled body moved by setting velocity
*/
type NgtrRigidBodyType = 'fixed' | 'dynamic' | 'kinematicPosition' | 'kinematicVelocity';
/**
* Configuration options for rigid bodies.
* Extends collider options with additional physics simulation properties.
*/
interface NgtrRigidBodyOptions extends NgtrColliderOptions {
/**
* Whether or not this body can sleep.
* @defaultValue true
*/
canSleep: boolean;
/** The linear damping coefficient of this rigid-body.*/
linearDamping?: number;
/** The angular damping coefficient of this rigid-body.*/
angularDamping?: number;
/**
* The initial linear velocity of this body.
* @defaultValue [0,0,0]
*/
linearVelocity: THREE.Vector3Tuple;
/**
* The initial angular velocity of this body.
* @defaultValue [0,0,0]
*/
angularVelocity: THREE.Vector3Tuple;
/**
* The scaling factor applied to the gravity affecting the rigid-body.
* @defaultValue 1.0
*/
gravityScale: number;
/**
* The dominance group of this RigidBody. If a rigid body has a higher domiance group,
* on collision it will be immune to forces originating from the other bodies.
* https://rapier.rs/docs/user_guides/javascript/rigid_bodies#dominance
* Default: 0
*/
dominanceGroup: number;
/**
* Whether or not Continous Collision Detection is enabled for this rigid-body.
* https://rapier.rs/docs/user_guides/javascript/rigid_bodies#continuous-collision-detection
* @defaultValue false
*/
ccd: boolean;
/**
* The maximum prediction distance Soft Continuous Collision-Detection.
*
* When set to 0, soft-CCD is disabled.
*
* Soft-CCD helps prevent tunneling especially of slow-but-thin to moderately fast objects.
* The soft CCD prediction distance indicates how far in the object’s path the CCD algorithm is allowed to inspect.
* Large values can impact performance badly by increasing the work needed from the broad-phase.
*
* It is a generally cheaper variant of regular CCD since it relies on predictive constraints instead of shape-cast and substeps.
*
* @defaultValue 0
*/
softCcdPrediction: number;
/**
* Initial position of the RigidBody
*/
position?: NgtThreeElements['ngt-object3D']['position'];
/**
* Initial rotation of the RigidBody
*/
rotation?: NgtThreeElements['ngt-object3D']['rotation'];
/**
* Automatically generate colliders based on meshes inside this
* rigid body.
*
* You can change the default setting globally by setting the colliders
* prop on the <Physics /> component.
*
* Setting this to false will disable automatic colliders.
*/
colliders?: NgtrRigidBodyAutoCollider | false;
/**
* Set the friction of auto-generated colliders.
* This does not affect any non-automatic child collider-components.
*/
friction?: number;
/**
* Set the restitution (bounciness) of auto-generated colliders.
* This does not affect any non-automatic child collider-components.
*/
restitution?: number;
/**
* Sets the number of additional solver iterations that will be run for this
* rigid-body and everything that interacts with it directly or indirectly
* through contacts or joints.
*
* Compared to increasing the global `World.numSolverIteration`, setting this
* value lets you increase accuracy on only a subset of the scene, resulting in reduced
* performance loss.
*/
additionalSolverIterations?: number;
/**
* The default collision groups bitmask for all colliders in this rigid body.
* Can be customized per-collider.
*/
collisionGroups?: InteractionGroups;
/**
* The default solver groups bitmask for all colliders in this rigid body.
* Can be customized per-collider.
*/
solverGroups?: InteractionGroups;
/**
* The default active collision types for all colliders in this rigid body.
* Can be customized per-collider.
*
* Use `ActiveCollisionTypes` to specify which collision types should be active for this collider.
*
* @see https://rapier.rs/javascript3d/classes/Collider.html#setActiveCollisionTypes
* @see https://rapier.rs/javascript3d/enums/ActiveCollisionTypes.html
*/
activeCollisionTypes?: ActiveCollisionTypes;
/**
* Locks all rotations that would have resulted from forces on the created rigid-body.
*/
lockRotations?: boolean;
/**
* Locks all translations that would have resulted from forces on the created rigid-body.
*/
lockTranslations?: boolean;
/**
* Allow rotation of this rigid-body only along specific axes.
*/
enabledRotations?: [x: boolean, y: boolean, z: boolean];
/**
* Allow translation of this rigid-body only along specific axes.
*/
enabledTranslations?: [x: boolean, y: boolean, z: boolean];
/**
* Passed down to the object3d representing this collider.
*/
userData?: NgtThreeElements['ngt-object3D']['userData'];
/**
* Include invisible objects on the collider creation estimation.
*/
includeInvisible?: boolean;
/**
* Transform the RigidBodyState
* @internal Do not use. Used internally by the InstancedRigidBodies to alter the RigidBody State
*/
transformState?: (state: NgtrRigidBodyState) => NgtrRigidBodyState;
}
/**
* Arguments for creating a cuboid (box) collider.
* @param halfWidth - Half-extent along the X axis
* @param halfHeight - Half-extent along the Y axis
* @param halfDepth - Half-extent along the Z axis
*/
type NgtrCuboidArgs = [halfWidth: number, halfHeight: number, halfDepth: number];
/**
* Arguments for creating a ball (sphere) collider.
* @param radius - The radius of the sphere
*/
type NgtrBallArgs = [radius: number];
/**
* Arguments for creating a capsule collider.
* @param halfHeight - Half the height of the cylindrical part
* @param radius - The radius of the capsule
*/
type NgtrCapsuleArgs = [halfHeight: number, radius: number];
/**
* Arguments for creating a convex hull collider.
* @param vertices - Array of vertex positions (x, y, z, x, y, z, ...)
*/
type NgtrConvexHullArgs = [vertices: ArrayLike<number>];
/**
* Arguments for creating a heightfield collider.
* @param width - Number of rows in the height grid
* @param height - Number of columns in the height grid
* @param heights - Array of height values
* @param scale - Scale factor for the heightfield dimensions
*/
type NgtrHeightfieldArgs = [
width: number,
height: number,
heights: number[],
scale: {
x: number;
y: number;
z: number;
}
];
/**
* Arguments for creating a triangle mesh collider.
* @param vertices - Array of vertex positions
* @param indices - Array of triangle indices
*/
type NgtrTrimeshArgs = [vertices: ArrayLike<number>, indices: ArrayLike<number>];
/**
* Arguments for creating a polyline collider.
* @param vertices - Array of vertex positions
* @param indices - Array of segment indices
*/
type NgtrPolylineArgs = [vertices: Float32Array, indices: Uint32Array];
/**
* Arguments for creating a round cuboid collider (cuboid with rounded corners).
* @param halfWidth - Half-extent along the X axis
* @param halfHeight - Half-extent along the Y axis
* @param halfDepth - Half-extent along the Z axis
* @param borderRadius - Radius of the rounded corners
*/
type NgtrRoundCuboidArgs = [halfWidth: number, halfHeight: number, halfDepth: number, borderRadius: number];
/**
* Arguments for creating a cylinder collider.
* @param halfHeight - Half the height of the cylinder
* @param radius - The radius of the cylinder
*/
type NgtrCylinderArgs = [halfHeight: number, radius: number];
/**
* Arguments for creating a round cylinder collider (cylinder with rounded edges).
* @param halfHeight - Half the height of the cylinder
* @param radius - The radius of the cylinder
* @param borderRadius - Radius of the rounded edges
*/
type NgtrRoundCylinderArgs = [halfHeight: number, radius: number, borderRadius: number];
/**
* Arguments for creating a cone collider.
* @param halfHeight - Half the height of the cone
* @param radius - The base radius of the cone
*/
type NgtrConeArgs = [halfHeight: number, radius: number];
/**
* Arguments for creating a round cone collider (cone with rounded edges).
* @param halfHeight - Half the height of the cone
* @param radius - The base radius of the cone
* @param borderRadius - Radius of the rounded edges
*/
type NgtrRoundConeArgs = [halfHeight: number, radius: number, borderRadius: number];
/**
* Arguments for creating a convex mesh collider.
* @param vertices - Array of vertex positions
* @param indices - Array of face indices
*/
type NgtrConvexMeshArgs = [vertices: ArrayLike<number>, indices: ArrayLike<number>];
/**
* Arguments for creating a round convex hull collider.
* @param vertices - Array of vertex positions
* @param indices - Array of face indices
* @param borderRadius - Radius of the rounded edges
*/
type NgtrRoundConvexHullArgs = [vertices: ArrayLike<number>, indices: ArrayLike<number>, borderRadius: number];
/**
* Arguments for creating a round convex mesh collider.
* @param vertices - Array of vertex positions
* @param indices - Array of face indices
* @param borderRadius - Radius of the rounded edges
*/
type NgtrRoundConvexMeshArgs = [vertices: ArrayLike<number>, indices: ArrayLike<number>, borderRadius: number];
/**
* Parameters for creating a spherical (ball-and-socket) joint.
* Allows rotation around all axes but prevents relative translation.
*
* @example
* ```typescript
* sphericalJoint(bodyA, bodyB, {
* data: { body1Anchor: [0, 1, 0], body2Anchor: [0, -1, 0] }
* });
* ```
*/
interface NgtrSphericalJointParams {
/** Anchor point on the first body in local coordinates */
body1Anchor: NgtVector3;
/** Anchor point on the second body in local coordinates */
body2Anchor: NgtVector3;
}
/**
* Parameters for creating a fixed joint.
* Prevents all relative movement between two bodies.
*
* @example
* ```typescript
* fixedJoint(bodyA, bodyB, {
* data: {
* body1Anchor: [0, 0, 0],
* body1LocalFrame: [0, 0, 0, 1],
* body2Anchor: [0, 0, 0],
* body2LocalFrame: [0, 0, 0, 1]
* }
* });
* ```
*/
interface NgtrFixedJointParams {
/** Anchor point on the first body in local coordinates */
body1Anchor: NgtVector3;
/** Local frame orientation of the first body (quaternion) */
body1LocalFrame: NgtQuaternion;
/** Anchor point on the second body in local coordinates */
body2Anchor: NgtVector3;
/** Local frame orientation of the second body (quaternion) */
body2LocalFrame: NgtQuaternion;
}
/**
* Parameters for creating a prismatic (slider) joint.
* Allows translation along one axis only.
*
* @example
* ```typescript
* prismaticJoint(bodyA, bodyB, {
* data: {
* body1Anchor: [0, 0, 0],
* body2Anchor: [2, 0, 0],
* axis: [1, 0, 0],
* limits: [-1, 1]
* }
* });
* ```
*/
interface NgtrPrismaticJointParams {
/** Anchor point on the first body in local coordinates */
body1Anchor: NgtVector3;
/** Anchor point on the second body in local coordinates */
body2Anchor: NgtVector3;
/** The axis along which translation is allowed */
axis: NgtVector3;
/** Optional translation limits [min, max] */
limits?: [min: number, max: number];
}
/**
* Parameters for creating a revolute (hinge) joint.
* Allows rotation around one axis only.
*
* @example
* ```typescript
* revoluteJoint(bodyA, bodyB, {
* data: {
* body1Anchor: [0, 0, 0],
* body2Anchor: [0, 1, 0],
* axis: [0, 1, 0],
* limits: [-Math.PI / 2, Math.PI / 2]
* }
* });
* ```
*/
interface NgtrRevoluteJointParams {
/** Anchor point on the first body in local coordinates */
body1Anchor: NgtVector3;
/** Anchor point on the second body in local coordinates */
body2Anchor: NgtVector3;
/** The axis of rotation */
axis: NgtVector3;
/** Optional rotation limits in radians [min, max] */
limits?: [min: number, max: number];
}
/**
* Parameters for creating a rope joint.
* Limits the maximum distance between two anchor points.
*
* @example
* ```typescript
* ropeJoint(bodyA, bodyB, {
* data: {
* body1Anchor: [0, 0, 0],
* body2Anchor: [0, 0, 0],
* length: 5
* }
* });
* ```
*/
interface NgtrRopeJointParams {
/** Anchor point on the first body in local coordinates */
body1Anchor: NgtVector3;
/** Anchor point on the second body in local coordinates */
body2Anchor: NgtVector3;
/** Maximum distance between the anchor points */
length: number;
}
/**
* Parameters for creating a spring joint.
* Applies a force proportional to the distance between two anchor points.
*
* @example
* ```typescript
* springJoint(bodyA, bodyB, {
* data: {
* body1Anchor: [0, 0, 0],
* body2Anchor: [0, 0, 0],
* restLength: 2,
* stiffness: 100,
* damping: 10
* }
* });
* ```
*/
interface NgtrSpringJointParams {
/** Anchor point on the first body in local coordinates */
body1Anchor: NgtVector3;
/** Anchor point on the second body in local coordinates */
body2Anchor: NgtVector3;
/** The rest length of the spring */
restLength: number;
/** The spring stiffness coefficient */
stiffness: number;
/** The damping coefficient */
damping: number;
}
/**
* Base directive for creating colliders in the physics simulation.
* This directive can be used to create any type of collider by specifying the shape.
*
* For convenience, use the specific collider directives like `NgtrCuboidCollider`,
* `NgtrBallCollider`, etc., which provide type-safe arguments.
*
* @example
* ```html
* <ngt-object3D [collider]="'cuboid'" [args]="[1, 1, 1]" [position]="[0, 5, 0]" />
* ```
*/
declare class NgtrAnyCollider {
position: _angular_core.InputSignal<number | THREE.Vector3 | [x: number, y: number, z: number]>;
rotation: _angular_core.InputSignal<number | THREE.Euler | [x: number, y: number, z: number, order?: THREE.EulerOrder | undefined] | undefined>;
scale: _angular_core.InputSignal<number | THREE.Vector3 | [x: number, y: number, z: number]>;
quaternion: _angular_core.InputSignal<THREE.Quaternion | [x: number, y: number, z: number, w: number] | undefined>;
userData: _angular_core.InputSignal<Record<string, any> | Readonly<Record<string, any> | undefined>>;
name: _angular_core.InputSignal<string | undefined>;
options: _angular_core.InputSignalWithTransform<NgtrColliderOptions, "" | Partial<NgtrRigidBodyOptions>>;
private object3DParameters;
shape: _angular_core.ModelSignal<NgtrColliderShape | undefined>;
args: _angular_core.ModelSignal<unknown[]>;
collisionEnter: _angular_core.OutputEmitterRef<NgtrCollisionEnterPayload>;
collisionExit: _angular_core.OutputEmitterRef<NgtrCollisionExitPayload>;
intersectionEnter: _angular_core.OutputEmitterRef<NgtrIntersectionEnterPayload>;
intersectionExit: _angular_core.OutputEmitterRef<NgtrIntersectionExitPayload>;
contactForce: _angular_core.OutputEmitterRef<NgtrContactForcePayload>;
private sensor;
private collisionGroups;
private solverGroups;
private friction;
private frictionCombineRule;
private restitution;
private restitutionCombineRule;
private activeCollisionTypes;
private contactSkin;
private mass;
private massProperties;
private density;
private rigidBody;
private physics;
private objectRef;
private scaledArgs;
collider: _angular_core.Signal<Collider | null>;
constructor();
get worldScale(): THREE.Vector3;
setShape(shape: NgtrColliderShape): void;
setArgs(args: unknown[]): void;
private createColliderStateEffect;
private createColliderEventsEffect;
private updateColliderEffect;
private updateMassPropertiesEffect;
private createColliderState;
private scaleVertices;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgtrAnyCollider, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NgtrAnyCollider, "ngt-object3D[collider]", never, { "position": { "alias": "position"; "required": false; "isSignal": true; }; "rotation": { "alias": "rotation"; "required": false; "isSignal": true; }; "scale": { "alias": "scale"; "required": false; "isSignal": true; }; "quaternion": { "alias": "quaternion"; "required": false; "isSignal": true; }; "userData": { "alias": "userData"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "shape": { "alias": "collider"; "required": false; "isSignal": true; }; "args": { "alias": "args"; "required": false; "isSignal": true; }; }, { "shape": "colliderChange"; "args": "argsChange"; "collisionEnter": "collisionEnter"; "collisionExit": "collisionExit"; "intersectionEnter": "intersectionEnter"; "intersectionExit": "intersectionExit"; "contactForce": "contactForce"; }, never, never, true, never>;
}
/**
* Default options for rigid bodies.
* These values are used when specific options are not provided.
*/
declare const rigidBodyDefaultOptions: NgtrRigidBodyOptions;
/**
* Component that creates a rigid body in the physics simulation.
* Rigid bodies can be dynamic (simulated), fixed (static), or kinematic (user-controlled).
*
* Child meshes automatically generate colliders based on their geometry.
* The collider type can be controlled via the `colliders` option.
*
* @example
* ```html
* <!-- Dynamic rigid body with automatic colliders -->
* <ngt-object3D rigidBody [position]="[0, 5, 0]">
* <ngt-mesh>
* <ngt-box-geometry />
* <ngt-mesh-standard-material />
* </ngt-mesh>
* </ngt-object3D>
*
* <!-- Fixed (static) rigid body -->
* <ngt-object3D rigidBody="fixed" [position]="[0, -1, 0]">
* <ngt-mesh>
* <ngt-plane-geometry [args]="[100, 100]" />
* </ngt-mesh>
* </ngt-object3D>
*
* <!-- Kinematic rigid body -->
* <ngt-object3D rigidBody="kinematicPosition" #kinematicBody="rigidBody">
* <ngt-mesh>
* <ngt-sphere-geometry />
* </ngt-mesh>
* </ngt-object3D>
* ```
*/
declare class NgtrRigidBody {
type: _angular_core.InputSignalWithTransform<NgtrRigidBodyType, "" | NgtrRigidBodyType | undefined>;
position: _angular_core.InputSignal<number | THREE.Vector3 | [x: number, y: number, z: number]>;
rotation: _angular_core.InputSignal<number | THREE.Euler | [x: number, y: number, z: number, order?: THREE.EulerOrder | undefined] | undefined>;
scale: _angular_core.InputSignal<number | THREE.Vector3 | [x: number, y: number, z: number]>;
quaternion: _angular_core.InputSignal<THREE.Quaternion | [x: number, y: number, z: number, w: number] | undefined>;
userData: _angular_core.InputSignal<Record<string, any> | Readonly<Record<string, any> | undefined>>;
options: _angular_core.InputSignalWithTransform<NgtrRigidBodyOptions, "" | Partial<NgtrRigidBodyOptions>>;
anyColliders: _angular_core.Signal<readonly NgtrAnyCollider[]>;
private object3DParameters;
wake: _angular_core.OutputEmitterRef<void>;
sleep: _angular_core.OutputEmitterRef<void>;
collisionEnter: _angular_core.OutputEmitterRef<NgtrCollisionEnterPayload>;
collisionExit: _angular_core.OutputEmitterRef<NgtrCollisionExitPayload>;
intersectionEnter: _angular_core.OutputEmitterRef<NgtrIntersectionEnterPayload>;
intersectionExit: _angular_core.OutputEmitterRef<NgtrIntersectionExitPayload>;
contactForce: _angular_core.OutputEmitterRef<NgtrContactForcePayload>;
private canSleep;
private colliders;
private transformState;
private gravityScale;
private dominanceGroup;
private ccd;
private softCcdPrediction;
private additionalSolverIterations;
private linearDamping;
private angularDamping;
private lockRotations;
private lockTranslations;
private enabledRotations;
private enabledTranslations;
private angularVelocity;
private linearVelocity;
objectRef: ElementRef<THREE.Object3D<THREE.Object3DEventMap>>;
private physics;
private bodyType;
private bodyDesc;
rigidBody: _angular_core.Signal<RigidBody | null>;
protected childColliderOptions: _angular_core.Signal<{
colliderOptions: NgtrColliderOptions;
args: unknown[];
shape: NgtrColliderShape;
rotation: NgtEuler;
position: NgtVector3;
scale: NgtVector3;
}[]>;
constructor();
private createRigidBodyStateEffect;
private createRigidBodyEventsEffect;
private updateRigidBodyEffect;
private createRigidBodyState;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgtrRigidBody, never>;
static ɵcmp: _angular_core.ɵɵComponentDeclaration<NgtrRigidBody, "ngt-object3D[rigidBody]", ["rigidBody"], { "type": { "alias": "rigidBody"; "required": true; "isSignal": true; }; "position": { "alias": "position"; "required": false; "isSignal": true; }; "rotation": { "alias": "rotation"; "required": false; "isSignal": true; }; "scale": { "alias": "scale"; "required": false; "isSignal": true; }; "quaternion": { "alias": "quaternion"; "required": false; "isSignal": true; }; "userData": { "alias": "userData"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; }, { "wake": "wake"; "sleep": "sleep"; "collisionEnter": "collisionEnter"; "collisionExit": "collisionExit"; "intersectionEnter": "intersectionEnter"; "intersectionExit": "intersectionExit"; "contactForce": "contactForce"; }, never, ["*"], true, never>;
}
/**
* Creates a cuboid (box) collider with specified half-extents.
*
* @example
* ```html
* <ngt-object3D [cuboidCollider]="[1, 0.5, 2]" [position]="[0, 0, 0]" />
* ```
*/
declare class NgtrCuboidCollider {
args: _angular_core.InputSignal<NgtrCuboidArgs>;
private anyCollider;
collider: _angular_core.Signal<_dimforge_rapier3d_compat.Collider | null>;
constructor();
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgtrCuboidCollider, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NgtrCuboidCollider, "ngt-object3D[cuboidCollider]", ["cuboidCollider"], { "args": { "alias": "cuboidCollider"; "required": true; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof NgtrAnyCollider; inputs: { "options": "options"; "name": "name"; "scale": "scale"; "position": "position"; "quaternion": "quaternion"; "rotation": "rotation"; "userData": "userData"; }; outputs: { "collisionEnter": "collisionEnter"; "collisionExit": "collisionExit"; "intersectionEnter": "intersectionEnter"; "intersectionExit": "intersectionExit"; "contactForce": "contactForce"; }; }]>;
}
/**
* Creates a capsule collider with specified half-height and radius.
*
* @example
* ```html
* <ngt-object3D [capsuleCollider]="[0.5, 0.25]" [position]="[0, 1, 0]" />
* ```
*/
declare class NgtrCapsuleCollider {
args: _angular_core.InputSignal<NgtrCapsuleArgs>;
private anyCollider;
collider: _angular_core.Signal<_dimforge_rapier3d_compat.Collider | null>;
constructor();
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgtrCapsuleCollider, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NgtrCapsuleCollider, "ngt-object3D[capsuleCollider]", ["capsuleCollider"], { "args": { "alias": "capsuleCollider"; "required": true; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof NgtrAnyCollider; inputs: { "options": "options"; "name": "name"; "scale": "scale"; "position": "position"; "quaternion": "quaternion"; "rotation": "rotation"; "userData": "userData"; }; outputs: { "collisionEnter": "collisionEnter"; "collisionExit": "collisionExit"; "intersectionEnter": "intersectionEnter"; "intersectionExit": "intersectionExit"; "contactForce": "contactForce"; }; }]>;
}
/**
* Creates a spherical (ball) collider with specified radius.
*
* @example
* ```html
* <ngt-object3D [ballCollider]="[0.5]" [position]="[0, 2, 0]" />
* ```
*/
declare class NgtrBallCollider {
args: _angular_core.InputSignal<NgtrBallArgs>;
private anyCollider;
collider: _angular_core.Signal<_dimforge_rapier3d_compat.Collider | null>;
constructor();
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgtrBallCollider, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NgtrBallCollider, "ngt-object3D[ballCollider]", ["ballCollider"], { "args": { "alias": "ballCollider"; "required": true; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof NgtrAnyCollider; inputs: { "options": "options"; "name": "name"; "scale": "scale"; "position": "position"; "quaternion": "quaternion"; "rotation": "rotation"; "userData": "userData"; }; outputs: { "collisionEnter": "collisionEnter"; "collisionExit": "collisionExit"; "intersectionEnter": "intersectionEnter"; "intersectionExit": "intersectionExit"; "contactForce": "contactForce"; }; }]>;
}
/**
* Creates a convex hull collider from an array of vertices.
* The convex hull is computed from the provided points.
*
* @example
* ```html
* <ngt-object3D [convexHullCollider]="[vertices]" />
* ```
*/
declare class NgtrConvexHullCollider {
args: _angular_core.InputSignal<NgtrConvexHullArgs>;
private anyCollider;
collider: _angular_core.Signal<_dimforge_rapier3d_compat.Collider | null>;
constructor();
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgtrConvexHullCollider, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NgtrConvexHullCollider, "ngt-object3D[convexHullCollider]", ["convexHullCollider"], { "args": { "alias": "convexHullCollider"; "required": true; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof NgtrAnyCollider; inputs: { "options": "options"; "name": "name"; "scale": "scale"; "position": "position"; "quaternion": "quaternion"; "rotation": "rotation"; "userData": "userData"; }; outputs: { "collisionEnter": "collisionEnter"; "collisionExit": "collisionExit"; "intersectionEnter": "intersectionEnter"; "intersectionExit": "intersectionExit"; "contactForce": "contactForce"; }; }]>;
}
/**
* Creates a heightfield collider for terrain-like surfaces.
* The heightfield is defined by a grid of height values.
*
* @example
* ```html
* <ngt-object3D [heightfieldCollider]="[width, height, heights, scale]" />
* ```
*/
declare class NgtrHeightfieldCollider {
args: _angular_core.InputSignal<NgtrHeightfieldArgs>;
private anyCollider;
collider: _angular_core.Signal<_dimforge_rapier3d_compat.Collider | null>;
constructor();
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgtrHeightfieldCollider, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NgtrHeightfieldCollider, "ngt-object3D[heightfieldCollider]", ["heightfieldCollider"], { "args": { "alias": "heightfieldCollider"; "required": true; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof NgtrAnyCollider; inputs: { "options": "options"; "name": "name"; "scale": "scale"; "position": "position"; "quaternion": "quaternion"; "rotation": "rotation"; "userData": "userData"; }; outputs: { "collisionEnter": "collisionEnter"; "collisionExit": "collisionExit"; "intersectionEnter": "intersectionEnter"; "intersectionExit": "intersectionExit"; "contactForce": "contactForce"; }; }]>;
}
/**
* Creates a triangle mesh collider for exact collision shapes.
* Note: Trimesh colliders are computationally expensive and should be used sparingly.
*
* @example
* ```html
* <ngt-object3D [trimeshCollider]="[vertices, indices]" />
* ```
*/
declare class NgtrTrimeshCollider {
args: _angular_core.InputSignal<NgtrTrimeshArgs>;
private anyCollider;
collider: _angular_core.Signal<_dimforge_rapier3d_compat.Collider | null>;
constructor();
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgtrTrimeshCollider, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NgtrTrimeshCollider, "ngt-object3D[trimeshCollider]", ["trimeshCollider"], { "args": { "alias": "trimeshCollider"; "required": true; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof NgtrAnyCollider; inputs: { "options": "options"; "name": "name"; "scale": "scale"; "position": "position"; "quaternion": "quaternion"; "rotation": "rotation"; "userData": "userData"; }; outputs: { "collisionEnter": "collisionEnter"; "collisionExit": "collisionExit"; "intersectionEnter": "intersectionEnter"; "intersectionExit": "intersectionExit"; "contactForce": "contactForce"; }; }]>;
}
/**
* Creates a polyline collider from connected line segments.
*
* @example
* ```html
* <ngt-object3D [polylineCollider]="[vertices, indices]" />
* ```
*/
declare class NgtrPolylineCollider {
args: _angular_core.InputSignal<NgtrPolylineArgs>;
private anyCollider;
collider: _angular_core.Signal<_dimforge_rapier3d_compat.Collider | null>;
constructor();
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgtrPolylineCollider, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NgtrPolylineCollider, "ngt-object3D[polylineCollider]", ["polylineCollider"], { "args": { "alias": "polylineCollider"; "required": true; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof NgtrAnyCollider; inputs: { "options": "options"; "name": "name"; "scale": "scale"; "position": "position"; "quaternion": "quaternion"; "rotation": "rotation"; "userData": "userData"; }; outputs: { "collisionEnter": "collisionEnter"; "collisionExit": "collisionExit"; "intersectionEnter": "intersectionEnter"; "intersectionExit": "intersectionExit"; "contactForce": "contactForce"; }; }]>;
}
/**
* Creates a cuboid collider with rounded corners.
*
* @example
* ```html
* <ngt-object3D [roundCuboidCollider]="[1, 0.5, 2, 0.1]" />
* ```
*/
declare class NgtrRoundCuboidCollider {
args: _angular_core.InputSignal<NgtrRoundCuboidArgs>;
private anyCollider;
collider: _angular_core.Signal<_dimforge_rapier3d_compat.Collider | null>;
constructor();
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgtrRoundCuboidCollider, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NgtrRoundCuboidCollider, "ngt-object3D[roundCuboidCollider]", ["roundCuboidCollider"], { "args": { "alias": "roundCuboidCollider"; "required": true; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof NgtrAnyCollider; inputs: { "options": "options"; "name": "name"; "scale": "scale"; "position": "position"; "quaternion": "quaternion"; "rotation": "rotation"; "userData": "userData"; }; outputs: { "collisionEnter": "collisionEnter"; "collisionExit": "collisionExit"; "intersectionEnter": "intersectionEnter"; "intersectionExit": "intersectionExit"; "contactForce": "contactForce"; }; }]>;
}
/**
* Creates a cylinder collider with specified half-height and radius.
*
* @example
* ```html
* <ngt-object3D [cylinderCollider]="[1, 0.5]" />
* ```
*/
declare class NgtrCylinderCollider {
args: _angular_core.InputSignal<NgtrCylinderArgs>;
private anyCollider;
collider: _angular_core.Signal<_dimforge_rapier3d_compat.Collider | null>;
constructor();
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgtrCylinderCollider