Skip to content

Commit 0215709

Browse files
committed
docs: more rapier examples
1 parent 9a82fcc commit 0215709

File tree

11 files changed

+334
-16
lines changed

11 files changed

+334
-16
lines changed
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
2+
import { injectGLTF } from 'angular-three-soba/loaders';
3+
import { injectSuzanne } from '../suzanne';
4+
5+
import {
6+
NgtrBallCollider,
7+
NgtrConeCollider,
8+
NgtrConvexHullCollider,
9+
NgtrCuboidCollider,
10+
NgtrRigidBody,
11+
NgtrTrimeshCollider,
12+
} from 'angular-three-rapier';
13+
import { NgtsHTML } from 'angular-three-soba/misc';
14+
import { ResetOrbitControls } from '../reset-orbit-controls';
15+
import offsetTorusGLB from './offset-torus.glb' with { loader: 'file' };
16+
17+
injectGLTF.preload(() => offsetTorusGLB);
18+
19+
@Component({
20+
selector: 'app-offset-torus',
21+
template: `
22+
@if (gltf(); as gltf) {
23+
<ngt-mesh
24+
castShadow
25+
[geometry]="gltf.meshes['Torus'].geometry"
26+
[material]="gltf.meshes['Torus'].material"
27+
/>
28+
}
29+
`,
30+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
31+
changeDetection: ChangeDetectionStrategy.OnPush,
32+
})
33+
export class OffsetTorus {
34+
protected gltf = injectGLTF(() => offsetTorusGLB);
35+
}
36+
37+
@Component({
38+
selector: 'app-suzanne',
39+
template: `
40+
@if (gltf(); as gltf) {
41+
<ngt-mesh castShadow [geometry]="gltf.nodes.Suzanne.geometry" [material]="gltf.nodes.Suzanne.material" />
42+
}
43+
`,
44+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
45+
changeDetection: ChangeDetectionStrategy.OnPush,
46+
})
47+
export class Suzanne {
48+
protected gltf = injectSuzanne();
49+
}
50+
51+
@Component({
52+
selector: 'app-all-shapes-rapier-example',
53+
template: `
54+
<ngt-group>
55+
<ngt-object3D rigidBody [options]="{ colliders: 'cuboid' }">
56+
<app-suzanne />
57+
<ngts-html>
58+
<div htmlContent>Auto Cuboid</div>
59+
</ngts-html>
60+
</ngt-object3D>
61+
62+
<ngt-object3D rigidBody [position]="[4, 0, 0]" [options]="{ colliders: 'ball' }">
63+
<app-suzanne />
64+
<ngts-html>
65+
<div htmlContent>Auto Ball</div>
66+
</ngts-html>
67+
</ngt-object3D>
68+
69+
<ngt-object3D rigidBody [position]="[8, 0, 0]" [options]="{ colliders: 'hull' }">
70+
<app-suzanne />
71+
<ngts-html>
72+
<div htmlContent>Auto Hull</div>
73+
</ngts-html>
74+
</ngt-object3D>
75+
76+
<ngt-object3D rigidBody [position]="[12, 0, 0]" [options]="{ colliders: 'trimesh' }">
77+
<app-suzanne />
78+
<ngts-html>
79+
<div htmlContent>Auto Trimesh</div>
80+
</ngts-html>
81+
</ngt-object3D>
82+
83+
<ngt-object3D rigidBody [position]="[0, 4, 0]" [options]="{ colliders: false }">
84+
<app-suzanne />
85+
<ngt-object3D [cuboidCollider]="[1, 1, 1]" />
86+
<ngts-html>
87+
<div htmlContent>Custom Cuboid</div>
88+
</ngts-html>
89+
</ngt-object3D>
90+
91+
<ngt-object3D rigidBody [position]="[4.1, 4, 0]" [options]="{ colliders: false }">
92+
<app-suzanne />
93+
<ngt-object3D [ballCollider]="[1]" />
94+
<ngts-html>
95+
<div htmlContent>Custom Ball</div>
96+
</ngts-html>
97+
</ngt-object3D>
98+
99+
<ngt-object3D rigidBody [position]="[8, 4, 0]" [options]="{ colliders: false }">
100+
<app-suzanne />
101+
<ngt-object3D [coneCollider]="[1, 1]" />
102+
<ngts-html>
103+
<div htmlContent>Custom Cone</div>
104+
</ngts-html>
105+
</ngt-object3D>
106+
107+
@if (gltf(); as gltf) {
108+
@let geometry = gltf.nodes.Suzanne.geometry;
109+
110+
<ngt-object3D rigidBody [position]="[5, 8, 0]" [options]="{ colliders: false }">
111+
<app-suzanne />
112+
<ngt-object3D
113+
[trimeshCollider]="[geometry.attributes['position'].array, geometry.index?.array || []]"
114+
[options]="{ mass: 1 }"
115+
/>
116+
<ngts-html>
117+
<div htmlContent>Custom Trimesh</div>
118+
</ngts-html>
119+
</ngt-object3D>
120+
121+
<ngt-object3D rigidBody [position]="[0, 8, 0]" [options]="{ colliders: false }">
122+
<app-suzanne />
123+
<ngt-object3D [convexHullCollider]="[geometry.attributes['position'].array]" />
124+
<ngts-html>
125+
<div htmlContent>Custom Convex Hull</div>
126+
</ngts-html>
127+
</ngt-object3D>
128+
}
129+
130+
<ngt-object3D rigidBody [position]="[8, 8, 0]" [options]="{ colliders: false }">
131+
<app-suzanne />
132+
<ngt-object3D [cuboidCollider]="[0.5, 0.5, 0.5]" [position]="[1, 1, 1]" />
133+
<ngt-object3D [ballCollider]="[0.5]" [position]="[-1, -1, 1]" />
134+
<ngts-html>
135+
<div htmlContent>Custom Combound shape</div>
136+
</ngts-html>
137+
</ngt-object3D>
138+
139+
<ngt-object3D rigidBody [position]="[4, 10, 0]" [options]="{ colliders: 'ball' }">
140+
<app-suzanne />
141+
<ngt-object3D [cuboidCollider]="[0.5, 0.5, 0.5]" [position]="[1, 1, 1]" />
142+
<ngt-object3D [ballCollider]="[0.5]" [position]="[-1, -1, 1]" />
143+
<ngts-html>
144+
<div htmlContent>Auto and Custom Combound shape</div>
145+
</ngts-html>
146+
</ngt-object3D>
147+
148+
<ngt-group [scale]="1.5" [position]="[5, 10, 0]">
149+
<ngt-object3D rigidBody [options]="{ colliders: 'ball' }">
150+
<ngt-group [position]="-2" [scale]="1.2">
151+
<app-offset-torus />
152+
</ngt-group>
153+
<ngts-html>
154+
<div htmlContent>Mesh with offset geometry</div>
155+
</ngts-html>
156+
</ngt-object3D>
157+
</ngt-group>
158+
</ngt-group>
159+
`,
160+
hostDirectives: [ResetOrbitControls],
161+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
162+
changeDetection: ChangeDetectionStrategy.OnPush,
163+
imports: [
164+
NgtrRigidBody,
165+
Suzanne,
166+
NgtsHTML,
167+
NgtrCuboidCollider,
168+
NgtrBallCollider,
169+
NgtrConeCollider,
170+
NgtrTrimeshCollider,
171+
NgtrConvexHullCollider,
172+
OffsetTorus,
173+
],
174+
})
175+
export default class AllShapesExample {
176+
protected gltf = injectSuzanne();
177+
}
Binary file not shown.
20.2 KB
Binary file not shown.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { ChangeDetectionStrategy, Component, computed, CUSTOM_ELEMENTS_SCHEMA, input, viewChild } from '@angular/core';
2+
import { NgtEuler, NgtVector3 } from 'angular-three';
3+
import { injectSphericalJoint, NgtrBallCollider, NgtrCylinderCollider, NgtrRigidBody } from 'angular-three-rapier';
4+
import { ResetOrbitControls } from '../reset-orbit-controls';
5+
6+
@Component({
7+
selector: 'app-rod',
8+
template: `
9+
<ngt-group>
10+
<ngt-object3D #anchor="rigidBody" rigidBody [position]="position()" [rotation]="rotation()" />
11+
<ngt-object3D
12+
#rod="rigidBody"
13+
rigidBody
14+
[position]="position()"
15+
[rotation]="rotation()"
16+
[options]="{ colliders: false }"
17+
>
18+
<ngt-mesh castShadow receiveShadow [position.y]="-1" [scale]="[0.05, 2, 0.05]">
19+
<ngt-cylinder-geometry />
20+
<ngt-mesh-standard-material color="black" />
21+
</ngt-mesh>
22+
23+
<ngt-mesh castShadow receiveShadow [position.y]="-2" [scale]="0.2">
24+
<ngt-sphere-geometry />
25+
<ngt-mesh-standard-material [metalness]="1" [roughness]="0.3" />
26+
</ngt-mesh>
27+
28+
<ngt-object3D [cylinderCollider]="[1, 0.05]" [position]="[0, -1, 0]" />
29+
<ngt-object3D [ballCollider]="[0.2]" [position]="[0, -2, 0]" [options]="{ restitution: 1.2 }" />
30+
</ngt-object3D>
31+
</ngt-group>
32+
`,
33+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
34+
changeDetection: ChangeDetectionStrategy.OnPush,
35+
imports: [NgtrRigidBody, NgtrCylinderCollider, NgtrBallCollider],
36+
})
37+
export class Rod {
38+
position = input<NgtVector3>([0, 0, 0]);
39+
rotation = input<NgtEuler>([0, 0, 0]);
40+
41+
private anchorRef = viewChild.required('anchor', { read: NgtrRigidBody });
42+
private rodRef = viewChild.required('rod', { read: NgtrRigidBody });
43+
44+
constructor() {
45+
const anchor = computed(() => this.anchorRef().rigidBody());
46+
const rod = computed(() => this.rodRef().rigidBody());
47+
48+
injectSphericalJoint(anchor, rod, {
49+
data: { body1Anchor: [0, 0, 0], body2Anchor: [0, 0, 0] },
50+
});
51+
}
52+
}
53+
54+
@Component({
55+
selector: 'app-cradle-rapier',
56+
template: `
57+
<ngt-group [rotation.x]="1" [scale]="3">
58+
<app-rod [position]="[0, 0, 0]" />
59+
<app-rod [position]="[0.5, 0, 0]" />
60+
<app-rod [position]="[1, 0, 0]" />
61+
<app-rod [position]="[1.5, 0, 0]" />
62+
<app-rod [position]="[2, 0, 0]" [rotation]="[0, 0, 2]" />
63+
</ngt-group>
64+
`,
65+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
66+
hostDirectives: [ResetOrbitControls],
67+
changeDetection: ChangeDetectionStrategy.OnPush,
68+
imports: [Rod],
69+
})
70+
export default class CradleExample {}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
2+
import { NgtrRigidBody } from 'angular-three-rapier';
3+
import { NgtsHTML } from 'angular-three-soba/misc';
4+
import { ResetOrbitControls } from '../reset-orbit-controls';
5+
6+
@Component({
7+
selector: 'app-rapier-locked-transforms',
8+
template: `
9+
<ngt-group>
10+
<ngt-object3D
11+
rigidBody
12+
[position]="[0, 10, 0]"
13+
[options]="{ colliders: 'hull', lockRotations: true, restitution: 1 }"
14+
>
15+
<ngt-mesh castShadow receiveShadow [scale]="3">
16+
<ngt-torus-geometry />
17+
<ngt-mesh-physical-material />
18+
<ngts-html>
19+
<div htmlContent>Locked Rotations</div>
20+
</ngts-html>
21+
</ngt-mesh>
22+
</ngt-object3D>
23+
24+
<ngt-object3D
25+
rigidBody
26+
[position]="[0, 5, 0]"
27+
[options]="{ colliders: 'hull', lockTranslations: true, restitution: 1 }"
28+
>
29+
<ngt-mesh castShadow receiveShadow [scale]="3">
30+
<ngt-torus-geometry />
31+
<ngt-mesh-physical-material />
32+
<ngts-html>
33+
<div htmlContent>Locked Translations</div>
34+
</ngts-html>
35+
</ngt-mesh>
36+
</ngt-object3D>
37+
38+
<ngt-object3D
39+
rigidBody
40+
[position]="[0, 0, 0]"
41+
[options]="{ colliders: 'hull', enabledRotations: [true, false, false], restitution: 1 }"
42+
>
43+
<ngt-mesh castShadow receiveShadow [scale]="3">
44+
<ngt-torus-geometry />
45+
<ngt-mesh-physical-material />
46+
<ngts-html>
47+
<div htmlContent>Enabled Rotations [true, false, false]</div>
48+
</ngts-html>
49+
</ngt-mesh>
50+
</ngt-object3D>
51+
52+
<ngt-object3D
53+
rigidBody
54+
[position]="[0, 15, 0]"
55+
[options]="{ colliders: 'hull', enabledTranslations: [true, false, false], restitution: 1 }"
56+
>
57+
<ngt-mesh castShadow receiveShadow [scale]="3">
58+
<ngt-torus-geometry />
59+
<ngt-mesh-physical-material />
60+
<ngts-html>
61+
<div htmlContent>Enabled Translations [true, false, false]</div>
62+
</ngts-html>
63+
</ngt-mesh>
64+
</ngt-object3D>
65+
</ngt-group>
66+
`,
67+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
68+
hostDirectives: [ResetOrbitControls],
69+
changeDetection: ChangeDetectionStrategy.OnPush,
70+
imports: [NgtrRigidBody, NgtsHTML],
71+
})
72+
export default class LockedTransformsExample {}

apps/examples/src/app/rapier/map.glb

22.1 KB
Binary file not shown.
8.72 KB
Binary file not shown.
6.57 KB
Binary file not shown.

apps/examples/src/app/rapier/rapier.routes.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,19 @@ const routes: Routes = [
7373
providers: [provideResetOrbitControls(30)],
7474
loadComponent: () => import('./car/car'),
7575
},
76+
{
77+
path: 'locked-transforms',
78+
providers: [provideResetOrbitControls(30)],
79+
loadComponent: () => import('./locked-transforms/locked-transforms'),
80+
},
81+
{
82+
path: 'cradle',
83+
loadComponent: () => import('./cradle/cradle'),
84+
},
85+
{
86+
path: 'all-shapes',
87+
loadComponent: () => import('./all-shapes/all-shapes'),
88+
},
7689
{
7790
path: '',
7891
redirectTo: 'basic',

apps/examples/src/app/rapier/rapier.ts

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { ChangeDetectionStrategy, Component } from '@angular/core';
22
import { RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router';
33
import { extend } from 'angular-three';
44
import * as THREE from 'three';
5+
import routes from './rapier.routes';
56

67
extend(THREE);
78

@@ -32,20 +33,5 @@ extend(THREE);
3233
host: { class: 'rapier' },
3334
})
3435
export default class Rapier {
35-
protected examples = [
36-
'basic',
37-
'rope-joint',
38-
'spring',
39-
'cluster',
40-
'instanced-mesh',
41-
'joints',
42-
'performance',
43-
'all-colliders',
44-
'sensors',
45-
'contact-force-events',
46-
'active-collision-types',
47-
'attractors',
48-
'kinematics',
49-
'car',
50-
];
36+
protected examples = routes[0].children?.filter((route) => !!route.path).map((route) => route.path) || [];
5137
}

0 commit comments

Comments
 (0)