angular-three-rapier 4.0.0-next.12 → 4.0.0-next.121
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +406 -4
- package/addons/README.md +112 -0
- package/fesm2022/angular-three-rapier-addons.mjs +224 -0
- package/fesm2022/angular-three-rapier-addons.mjs.map +1 -0
- package/fesm2022/angular-three-rapier.mjs +1153 -283
- package/fesm2022/angular-three-rapier.mjs.map +1 -1
- package/package.json +11 -7
- package/types/angular-three-rapier-addons.d.ts +117 -0
- package/types/angular-three-rapier.d.ts +1846 -0
- package/index.d.ts +0 -7
- package/lib/colliders.d.ts +0 -93
- package/lib/debug.d.ts +0 -9
- package/lib/frame-stepper.d.ts +0 -10
- package/lib/instanced-rigid-bodies.d.ts +0 -46
- package/lib/joints.d.ts +0 -64
- package/lib/mesh-collider.d.ts +0 -20
- package/lib/physics.d.ts +0 -59
- package/lib/rigid-body.d.ts +0 -106
- package/lib/shared.d.ts +0 -9
- package/lib/types.d.ts +0 -504
- package/lib/utils.d.ts +0 -26
package/README.md
CHANGED
|
@@ -1,7 +1,409 @@
|
|
|
1
|
-
# rapier
|
|
1
|
+
# `angular-three-rapier`
|
|
2
2
|
|
|
3
|
-
This library
|
|
3
|
+
This library provides Rapier physics integration for Angular Three. [Rapier](https://rapier.rs/) is a fast, cross-platform physics engine written in Rust with JavaScript bindings.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Documentation
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
All public APIs are documented with JSDoc comments. Your IDE will provide inline documentation, parameter hints, and examples as you code.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install angular-three-rapier @dimforge/rapier3d-compat
|
|
13
|
+
# yarn add angular-three-rapier @dimforge/rapier3d-compat
|
|
14
|
+
# pnpm add angular-three-rapier @dimforge/rapier3d-compat
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
> Make sure to already have `angular-three` installed
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
23
|
+
import { extend, NgtArgs } from 'angular-three';
|
|
24
|
+
import { NgtrPhysics, NgtrRigidBody } from 'angular-three-rapier';
|
|
25
|
+
import * as THREE from 'three';
|
|
26
|
+
|
|
27
|
+
extend(THREE);
|
|
28
|
+
|
|
29
|
+
@Component({
|
|
30
|
+
selector: 'app-box',
|
|
31
|
+
template: `
|
|
32
|
+
<ngt-object3D rigidBody [position]="[0, 5, 0]">
|
|
33
|
+
<ngt-mesh>
|
|
34
|
+
<ngt-box-geometry />
|
|
35
|
+
<ngt-mesh-standard-material color="hotpink" />
|
|
36
|
+
</ngt-mesh>
|
|
37
|
+
</ngt-object3D>
|
|
38
|
+
`,
|
|
39
|
+
imports: [NgtrRigidBody],
|
|
40
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
41
|
+
})
|
|
42
|
+
export class Box {}
|
|
43
|
+
|
|
44
|
+
@Component({
|
|
45
|
+
selector: 'app-ground',
|
|
46
|
+
template: `
|
|
47
|
+
<ngt-object3D rigidBody="fixed" [position]="[0, -1, 0]">
|
|
48
|
+
<ngt-mesh>
|
|
49
|
+
<ngt-box-geometry *args="[20, 1, 20]" />
|
|
50
|
+
<ngt-mesh-standard-material color="gray" />
|
|
51
|
+
</ngt-mesh>
|
|
52
|
+
</ngt-object3D>
|
|
53
|
+
`,
|
|
54
|
+
imports: [NgtrRigidBody, NgtArgs],
|
|
55
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
56
|
+
})
|
|
57
|
+
export class Ground {}
|
|
58
|
+
|
|
59
|
+
@Component({
|
|
60
|
+
template: `
|
|
61
|
+
<ngtr-physics [options]="{ gravity: [0, -9.81, 0] }">
|
|
62
|
+
<ng-template>
|
|
63
|
+
<app-box />
|
|
64
|
+
<app-ground />
|
|
65
|
+
</ng-template>
|
|
66
|
+
</ngtr-physics>
|
|
67
|
+
`,
|
|
68
|
+
imports: [NgtrPhysics, Box, Ground],
|
|
69
|
+
})
|
|
70
|
+
export class SceneGraph {}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Physics Options
|
|
74
|
+
|
|
75
|
+
| Property | Description | Default |
|
|
76
|
+
| ------------- | ----------------------------------------------- | --------------- |
|
|
77
|
+
| `gravity` | Gravity vector `[x, y, z]` | `[0, -9.81, 0]` |
|
|
78
|
+
| `colliders` | Default collider type for rigid bodies | `'cuboid'` |
|
|
79
|
+
| `paused` | Whether physics simulation is paused | `false` |
|
|
80
|
+
| `timeStep` | Fixed timestep for physics simulation | `1/60` |
|
|
81
|
+
| `debug` | Enable debug visualization | `false` |
|
|
82
|
+
| `interpolate` | Enable transform interpolation | `true` |
|
|
83
|
+
| `updateLoop` | Update loop type: `'follow'` or `'independent'` | `'follow'` |
|
|
84
|
+
|
|
85
|
+
## Rigid Body
|
|
86
|
+
|
|
87
|
+
Use `ngt-object3D` with the `rigidBody` attribute. The rigid body type is specified as the attribute value:
|
|
88
|
+
|
|
89
|
+
```html
|
|
90
|
+
<!-- Dynamic (default when empty) -->
|
|
91
|
+
<ngt-object3D rigidBody [position]="[0, 5, 0]">
|
|
92
|
+
<ngt-mesh>...</ngt-mesh>
|
|
93
|
+
</ngt-object3D>
|
|
94
|
+
|
|
95
|
+
<!-- Fixed (static) -->
|
|
96
|
+
<ngt-object3D rigidBody="fixed" [position]="[0, -1, 0]">
|
|
97
|
+
<ngt-mesh>...</ngt-mesh>
|
|
98
|
+
</ngt-object3D>
|
|
99
|
+
|
|
100
|
+
<!-- Kinematic -->
|
|
101
|
+
<ngt-object3D rigidBody="kinematicPosition">
|
|
102
|
+
<ngt-mesh>...</ngt-mesh>
|
|
103
|
+
</ngt-object3D>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Rigid Body Types
|
|
107
|
+
|
|
108
|
+
- `''` or `'dynamic'` - Affected by forces and collisions
|
|
109
|
+
- `'fixed'` - Static, immovable body
|
|
110
|
+
- `'kinematicPosition'` - Controlled by position, affects dynamic bodies
|
|
111
|
+
- `'kinematicVelocity'` - Controlled by velocity, affects dynamic bodies
|
|
112
|
+
|
|
113
|
+
### Rigid Body Options
|
|
114
|
+
|
|
115
|
+
```html
|
|
116
|
+
<ngt-object3D
|
|
117
|
+
rigidBody
|
|
118
|
+
[options]="{
|
|
119
|
+
colliders: 'ball',
|
|
120
|
+
ccd: true,
|
|
121
|
+
gravityScale: 0.5,
|
|
122
|
+
linearVelocity: [0, 10, 0],
|
|
123
|
+
angularVelocity: [0, 1, 0]
|
|
124
|
+
}"
|
|
125
|
+
>
|
|
126
|
+
...
|
|
127
|
+
</ngt-object3D>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Rigid Body Events
|
|
131
|
+
|
|
132
|
+
```html
|
|
133
|
+
<ngt-object3D
|
|
134
|
+
rigidBody
|
|
135
|
+
(collisionEnter)="onCollisionEnter($event)"
|
|
136
|
+
(collisionExit)="onCollisionExit($event)"
|
|
137
|
+
(intersectionEnter)="onIntersectionEnter($event)"
|
|
138
|
+
(intersectionExit)="onIntersectionExit($event)"
|
|
139
|
+
(contactForce)="onContactForce($event)"
|
|
140
|
+
(sleep)="onSleep()"
|
|
141
|
+
(wake)="onWake()"
|
|
142
|
+
>
|
|
143
|
+
...
|
|
144
|
+
</ngt-object3D>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Colliders
|
|
148
|
+
|
|
149
|
+
Colliders use `ngt-object3D` with specific collider attributes. By default, rigid bodies auto-generate colliders from child meshes.
|
|
150
|
+
|
|
151
|
+
### Explicit Colliders
|
|
152
|
+
|
|
153
|
+
```html
|
|
154
|
+
<!-- Ball collider -->
|
|
155
|
+
<ngt-object3D [ballCollider]="[0.5]" [position]="[0, 2, 0]" />
|
|
156
|
+
|
|
157
|
+
<!-- Cuboid collider (half-extents) -->
|
|
158
|
+
<ngt-object3D [cuboidCollider]="[1, 0.5, 2]" [position]="[0, 0, 0]" />
|
|
159
|
+
|
|
160
|
+
<!-- Capsule collider (half-height, radius) -->
|
|
161
|
+
<ngt-object3D [capsuleCollider]="[0.5, 0.25]" [position]="[0, 1, 0]" />
|
|
162
|
+
|
|
163
|
+
<!-- Cylinder collider (half-height, radius) -->
|
|
164
|
+
<ngt-object3D [cylinderCollider]="[1, 0.5]" />
|
|
165
|
+
|
|
166
|
+
<!-- Cone collider (half-height, radius) -->
|
|
167
|
+
<ngt-object3D [coneCollider]="[1, 0.5]" />
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Available Collider Directives
|
|
171
|
+
|
|
172
|
+
| Directive | Args | Description |
|
|
173
|
+
| --------------------------- | --------------------------------- | ------------------- |
|
|
174
|
+
| `NgtrBallCollider` | `[radius]` | Sphere shape |
|
|
175
|
+
| `NgtrCuboidCollider` | `[halfW, halfH, halfD]` | Box shape |
|
|
176
|
+
| `NgtrCapsuleCollider` | `[halfHeight, radius]` | Capsule shape |
|
|
177
|
+
| `NgtrCylinderCollider` | `[halfHeight, radius]` | Cylinder shape |
|
|
178
|
+
| `NgtrConeCollider` | `[halfHeight, radius]` | Cone shape |
|
|
179
|
+
| `NgtrConvexHullCollider` | `[vertices]` | Convex hull |
|
|
180
|
+
| `NgtrTrimeshCollider` | `[vertices, indices]` | Triangle mesh |
|
|
181
|
+
| `NgtrHeightfieldCollider` | `[width, height, heights, scale]` | Terrain heightfield |
|
|
182
|
+
| `NgtrRoundCuboidCollider` | `[halfW, halfH, halfD, radius]` | Rounded box |
|
|
183
|
+
| `NgtrRoundCylinderCollider` | `[halfH, radius, borderRadius]` | Rounded cylinder |
|
|
184
|
+
| `NgtrRoundConeCollider` | `[halfH, radius, borderRadius]` | Rounded cone |
|
|
185
|
+
|
|
186
|
+
### Disabling Auto-Colliders
|
|
187
|
+
|
|
188
|
+
```html
|
|
189
|
+
<ngt-object3D rigidBody [options]="{ colliders: false }">
|
|
190
|
+
<!-- Manual colliders only -->
|
|
191
|
+
<ngt-object3D [ballCollider]="[0.5]" />
|
|
192
|
+
</ngt-object3D>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Mesh Collider
|
|
196
|
+
|
|
197
|
+
Generate colliders from mesh geometry:
|
|
198
|
+
|
|
199
|
+
```html
|
|
200
|
+
<ngt-object3D rigidBody [options]="{ colliders: false }">
|
|
201
|
+
<ngt-object3D [meshCollider]="'trimesh'">
|
|
202
|
+
<ngt-mesh>
|
|
203
|
+
<ngt-torus-geometry />
|
|
204
|
+
<ngt-mesh-standard-material />
|
|
205
|
+
</ngt-mesh>
|
|
206
|
+
</ngt-object3D>
|
|
207
|
+
</ngt-object3D>
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Joints
|
|
211
|
+
|
|
212
|
+
Create joints between rigid bodies using injectable functions:
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
import { Component, viewChild } from '@angular/core';
|
|
216
|
+
import {
|
|
217
|
+
NgtrRigidBody,
|
|
218
|
+
sphericalJoint,
|
|
219
|
+
revoluteJoint,
|
|
220
|
+
prismaticJoint,
|
|
221
|
+
fixedJoint,
|
|
222
|
+
ropeJoint,
|
|
223
|
+
springJoint,
|
|
224
|
+
} from 'angular-three-rapier';
|
|
225
|
+
|
|
226
|
+
@Component({
|
|
227
|
+
template: `
|
|
228
|
+
<ngt-object3D rigidBody="fixed" #bodyA="rigidBody">...</ngt-object3D>
|
|
229
|
+
<ngt-object3D rigidBody #bodyB="rigidBody">...</ngt-object3D>
|
|
230
|
+
`,
|
|
231
|
+
})
|
|
232
|
+
export class JointExample {
|
|
233
|
+
bodyA = viewChild.required<NgtrRigidBody>('bodyA');
|
|
234
|
+
bodyB = viewChild.required<NgtrRigidBody>('bodyB');
|
|
235
|
+
|
|
236
|
+
// Spherical joint (ball-and-socket)
|
|
237
|
+
joint = sphericalJoint(
|
|
238
|
+
() => this.bodyA().rigidBody(),
|
|
239
|
+
() => this.bodyB().rigidBody(),
|
|
240
|
+
{
|
|
241
|
+
data: {
|
|
242
|
+
body1Anchor: [0, -0.5, 0],
|
|
243
|
+
body2Anchor: [0, 0.5, 0],
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
// Revolute joint (hinge) with limits
|
|
249
|
+
hingeJoint = revoluteJoint(
|
|
250
|
+
() => this.bodyA().rigidBody(),
|
|
251
|
+
() => this.bodyB().rigidBody(),
|
|
252
|
+
{
|
|
253
|
+
data: {
|
|
254
|
+
body1Anchor: [0, 0, 0],
|
|
255
|
+
body2Anchor: [0, 1, 0],
|
|
256
|
+
axis: [0, 1, 0],
|
|
257
|
+
limits: [-Math.PI / 2, Math.PI / 2],
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
// Prismatic joint (slider)
|
|
263
|
+
sliderJoint = prismaticJoint(
|
|
264
|
+
() => this.bodyA().rigidBody(),
|
|
265
|
+
() => this.bodyB().rigidBody(),
|
|
266
|
+
{
|
|
267
|
+
data: {
|
|
268
|
+
body1Anchor: [0, 0, 0],
|
|
269
|
+
body2Anchor: [2, 0, 0],
|
|
270
|
+
axis: [1, 0, 0],
|
|
271
|
+
limits: [-1, 1],
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
// Rope joint (max distance constraint)
|
|
277
|
+
rope = ropeJoint(
|
|
278
|
+
() => this.bodyA().rigidBody(),
|
|
279
|
+
() => this.bodyB().rigidBody(),
|
|
280
|
+
{
|
|
281
|
+
data: {
|
|
282
|
+
body1Anchor: [0, 0, 0],
|
|
283
|
+
body2Anchor: [0, 0, 0],
|
|
284
|
+
length: 5,
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
// Spring joint
|
|
290
|
+
spring = springJoint(
|
|
291
|
+
() => this.bodyA().rigidBody(),
|
|
292
|
+
() => this.bodyB().rigidBody(),
|
|
293
|
+
{
|
|
294
|
+
data: {
|
|
295
|
+
body1Anchor: [0, 0, 0],
|
|
296
|
+
body2Anchor: [0, 0, 0],
|
|
297
|
+
restLength: 2,
|
|
298
|
+
stiffness: 100,
|
|
299
|
+
damping: 10,
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Instanced Rigid Bodies
|
|
307
|
+
|
|
308
|
+
For efficient physics with many identical objects:
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
import { NgtArgs } from 'angular-three';
|
|
312
|
+
import { NgtrInstancedRigidBodies } from 'angular-three-rapier';
|
|
313
|
+
|
|
314
|
+
@Component({
|
|
315
|
+
template: `
|
|
316
|
+
<ngt-object3D [instancedRigidBodies]="instances">
|
|
317
|
+
<ngt-instanced-mesh [count]="instances.length" castShadow>
|
|
318
|
+
<ngt-sphere-geometry *args="[0.5]" />
|
|
319
|
+
<ngt-mesh-standard-material color="orange" />
|
|
320
|
+
</ngt-instanced-mesh>
|
|
321
|
+
</ngt-object3D>
|
|
322
|
+
`,
|
|
323
|
+
imports: [NgtrInstancedRigidBodies, NgtArgs],
|
|
324
|
+
})
|
|
325
|
+
export class Spheres {
|
|
326
|
+
instances = Array.from({ length: 100 }, (_, i) => ({
|
|
327
|
+
key: i,
|
|
328
|
+
position: [Math.random() * 10, Math.random() * 10, 0] as [number, number, number],
|
|
329
|
+
}));
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## Interaction Groups
|
|
334
|
+
|
|
335
|
+
Filter collisions between objects:
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
import { interactionGroups } from 'angular-three-rapier';
|
|
339
|
+
|
|
340
|
+
// Member of group 0, collides with groups 0 and 1
|
|
341
|
+
const groups = interactionGroups([0], [0, 1]);
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
```html
|
|
345
|
+
<!-- Using directive -->
|
|
346
|
+
<ngt-object3D rigidBody [interactionGroups]="[[0], [0, 1]]">...</ngt-object3D>
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## Physics Hooks
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
import { beforePhysicsStep, afterPhysicsStep } from 'angular-three-rapier';
|
|
353
|
+
|
|
354
|
+
@Component({...})
|
|
355
|
+
export class MyComponent {
|
|
356
|
+
constructor() {
|
|
357
|
+
beforePhysicsStep((world) => {
|
|
358
|
+
// Run before each physics step
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
afterPhysicsStep((world) => {
|
|
362
|
+
// Run after each physics step
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
## Debug Visualization
|
|
369
|
+
|
|
370
|
+
Enable debug rendering via physics options:
|
|
371
|
+
|
|
372
|
+
```html
|
|
373
|
+
<ngtr-physics [options]="{ debug: true }">
|
|
374
|
+
<ng-template>
|
|
375
|
+
<!-- your physics objects -->
|
|
376
|
+
</ng-template>
|
|
377
|
+
</ngtr-physics>
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## Addons
|
|
381
|
+
|
|
382
|
+
### Attractor
|
|
383
|
+
|
|
384
|
+
Apply gravitational or magnetic forces:
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
import { NgtrAttractor } from 'angular-three-rapier/addons';
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
```html
|
|
391
|
+
<!-- Attractor with default options -->
|
|
392
|
+
<ngt-object3D attractor />
|
|
393
|
+
|
|
394
|
+
<!-- Attractor with custom options -->
|
|
395
|
+
<ngt-object3D [attractor]="{ strength: 10, range: 20, type: 'linear' }" />
|
|
396
|
+
|
|
397
|
+
<!-- Repeller (negative strength) -->
|
|
398
|
+
<ngt-object3D [attractor]="{ strength: -10, range: 15 }" [position]="[5, 0, 0]" />
|
|
399
|
+
|
|
400
|
+
<!-- Newtonian gravity -->
|
|
401
|
+
<ngt-object3D
|
|
402
|
+
[attractor]="{
|
|
403
|
+
strength: 1000,
|
|
404
|
+
range: 50,
|
|
405
|
+
type: 'newtonian',
|
|
406
|
+
gravitationalConstant: 0.01
|
|
407
|
+
}"
|
|
408
|
+
/>
|
|
409
|
+
```
|
package/addons/README.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# angular-three-rapier/addons
|
|
2
|
+
|
|
3
|
+
Secondary entry point of `angular-three-rapier`. It can be used by importing from `angular-three-rapier/addons`.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
This package requires `angular-three-rapier` as a peer dependency.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install angular-three-rapier @dimforge/rapier3d-compat
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## NgtrAttractor
|
|
14
|
+
|
|
15
|
+
A directive that creates a gravitational attractor point in the physics world. All dynamic rigid bodies within range will be attracted (or repelled) towards this point.
|
|
16
|
+
|
|
17
|
+
### Basic Usage
|
|
18
|
+
|
|
19
|
+
```html
|
|
20
|
+
<!-- Simple attractor at origin with default options -->
|
|
21
|
+
<ngt-object3D attractor />
|
|
22
|
+
|
|
23
|
+
<!-- Attractor with custom options -->
|
|
24
|
+
<ngt-object3D [attractor]="{ strength: 5, range: 20 }" />
|
|
25
|
+
|
|
26
|
+
<!-- Repeller (negative strength) -->
|
|
27
|
+
<ngt-object3D [attractor]="{ strength: -10, range: 15 }" [position]="[5, 0, 0]" />
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Gravity Types
|
|
31
|
+
|
|
32
|
+
The attractor supports three different gravity calculation models:
|
|
33
|
+
|
|
34
|
+
```html
|
|
35
|
+
<!-- Static: Constant force regardless of distance -->
|
|
36
|
+
<ngt-object3D [attractor]="{ type: 'static', strength: 5, range: 20 }" />
|
|
37
|
+
|
|
38
|
+
<!-- Linear: Force increases as objects get closer -->
|
|
39
|
+
<ngt-object3D [attractor]="{ type: 'linear', strength: 5, range: 20 }" />
|
|
40
|
+
|
|
41
|
+
<!-- Newtonian: Realistic inverse-square law (like real gravity) -->
|
|
42
|
+
<ngt-object3D
|
|
43
|
+
[attractor]="{
|
|
44
|
+
type: 'newtonian',
|
|
45
|
+
strength: 1000,
|
|
46
|
+
range: 50,
|
|
47
|
+
gravitationalConstant: 0.01
|
|
48
|
+
}"
|
|
49
|
+
/>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Options
|
|
53
|
+
|
|
54
|
+
| Option | Type | Default | Description |
|
|
55
|
+
| ----------------------- | ------------------------------------- | ----------- | ----------------------------------------------------------------------------- |
|
|
56
|
+
| `strength` | `number` | `1` | Force strength. Positive attracts, negative repels. |
|
|
57
|
+
| `range` | `number` | `10` | Effective range in world units. Objects outside this range are unaffected. |
|
|
58
|
+
| `type` | `'static' \| 'linear' \| 'newtonian'` | `'static'` | Gravity calculation model. |
|
|
59
|
+
| `gravitationalConstant` | `number` | `6.673e-11` | Gravitational constant for newtonian type. |
|
|
60
|
+
| `collisionGroups` | `InteractionGroups` | `undefined` | Limits which rigid bodies are affected. If unset, affects all dynamic bodies. |
|
|
61
|
+
|
|
62
|
+
### Gravity Type Details
|
|
63
|
+
|
|
64
|
+
- **static**: Constant force regardless of distance. Good for simple push/pull effects.
|
|
65
|
+
- **linear**: Force scales linearly with distance (closer = stronger). Provides smooth attraction.
|
|
66
|
+
- **newtonian**: Force follows Newton's law of universal gravitation (`F = G * m1 * m2 / r²`). Most realistic but can cause extreme forces at close range.
|
|
67
|
+
|
|
68
|
+
## applyAttractorForceOnRigidBody
|
|
69
|
+
|
|
70
|
+
A utility function for manually applying attractor forces to rigid bodies. Useful for custom physics behavior.
|
|
71
|
+
|
|
72
|
+
### Usage
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import { applyAttractorForceOnRigidBody } from 'angular-three-rapier/addons';
|
|
76
|
+
import { beforePhysicsStep } from 'angular-three-rapier';
|
|
77
|
+
|
|
78
|
+
// In your component
|
|
79
|
+
beforePhysicsStep((world) => {
|
|
80
|
+
world.bodies.forEach((body) => {
|
|
81
|
+
if (body.isDynamic()) {
|
|
82
|
+
applyAttractorForceOnRigidBody(body, {
|
|
83
|
+
object: attractorMesh, // THREE.Object3D position reference
|
|
84
|
+
strength: 10,
|
|
85
|
+
range: 20,
|
|
86
|
+
type: 'newtonian',
|
|
87
|
+
gravitationalConstant: 0.01,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Parameters
|
|
95
|
+
|
|
96
|
+
| Parameter | Type | Description |
|
|
97
|
+
| ------------------------------- | -------------------------- | ------------------------------------------------------ |
|
|
98
|
+
| `rigidBody` | `RigidBody` | The Rapier rigid body to apply force to. |
|
|
99
|
+
| `options.object` | `THREE.Object3D` | Object3D whose world position is the attractor center. |
|
|
100
|
+
| `options.strength` | `number` | Force strength (positive attracts, negative repels). |
|
|
101
|
+
| `options.range` | `number` | Maximum distance for the force to apply. |
|
|
102
|
+
| `options.type` | `NgtrAttractorGravityType` | Gravity calculation type. |
|
|
103
|
+
| `options.gravitationalConstant` | `number` | Gravitational constant for newtonian calculations. |
|
|
104
|
+
| `options.collisionGroups` | `InteractionGroups` | Optional collision group filter. |
|
|
105
|
+
|
|
106
|
+
## Debug Visualization
|
|
107
|
+
|
|
108
|
+
When physics debug mode is enabled on `NgtrPhysics`, attractors automatically display debug visualization:
|
|
109
|
+
|
|
110
|
+
- Blue sphere with normals for attractors (positive strength)
|
|
111
|
+
- Red sphere with normals for repellers (negative strength)
|
|
112
|
+
- Normal length indicates the range
|