Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 346523a

Browse files
ctranctran
ctran
authored and
ctran
committed
feels so good
1 parent 6d2e6fd commit 346523a

File tree

24 files changed

+934
-258
lines changed

24 files changed

+934
-258
lines changed

apps/kitchen-sink-new/src/app/app.routes.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,17 @@ export const appRoutes: Route[] = [
55
path: 'core-new-sink',
66
loadComponent: () => import('./core-new-sink/core-new-sink'),
77
},
8+
{
9+
path: 'cannon',
10+
loadComponent: () => import('./cannon/cannon'),
11+
loadChildren: () => import('./cannon/cannon.routes'),
12+
},
813
{
914
path: '',
1015
// redirectTo: 'cannon',
1116
// redirectTo: 'postprocessing',
1217
// redirectTo: 'soba',
13-
redirectTo: 'core-new-sink',
18+
redirectTo: 'cannon',
1419
pathMatch: 'full',
1520
},
1621
];
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
2+
import { NgtCanvas } from 'angular-three-core-new';
3+
import { Experience } from './experience';
4+
import { State } from './state';
5+
6+
@Component({
7+
standalone: true,
8+
template: `
9+
<ngt-canvas [sceneGraph]="scene" [options]="{ shadows: true, camera: { position: [0, 0, 15] } }" />
10+
<div class="font-mono absolute top-0 right-0 flex gap-4 text-white">
11+
<button (click)="state.toggleDebugging()">Toggle debugging: {{ state.isDebugging() }}</button>
12+
<span>|</span>
13+
<button (click)="state.changeGravity()">Change gravity: {{ state.gravity() }}</button>
14+
</div>
15+
`,
16+
imports: [NgtCanvas],
17+
changeDetection: ChangeDetectionStrategy.OnPush,
18+
host: { class: 'cannon-basic' },
19+
providers: [State],
20+
})
21+
export default class Basic {
22+
scene = Experience;
23+
24+
state = inject(State);
25+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import {
2+
CUSTOM_ELEMENTS_SCHEMA,
3+
ChangeDetectionStrategy,
4+
Component,
5+
ElementRef,
6+
afterNextRender,
7+
inject,
8+
input,
9+
signal,
10+
viewChild,
11+
} from '@angular/core';
12+
import { Triplet } from '@pmndrs/cannon-worker-api';
13+
import { NgtcPhysics } from 'angular-three-cannon';
14+
import { injectBox, injectPlane } from 'angular-three-cannon/body';
15+
import { NgtcDebug } from 'angular-three-cannon/debug';
16+
import { NgtArgs, extend } from 'angular-three-core-new';
17+
import * as THREE from 'three';
18+
import { Mesh } from 'three';
19+
import { State } from './state';
20+
21+
extend(THREE);
22+
23+
@Component({
24+
selector: 'app-plane',
25+
standalone: true,
26+
template: `
27+
<ngt-mesh #mesh [receiveShadow]="true">
28+
<ngt-plane-geometry *args="args" />
29+
<ngt-mesh-standard-material color="#171717" />
30+
</ngt-mesh>
31+
`,
32+
imports: [NgtArgs],
33+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
34+
changeDetection: ChangeDetectionStrategy.OnPush,
35+
})
36+
export class Plane {
37+
position = input<Triplet>([0, 0, 0]);
38+
args = [1000, 1000];
39+
mesh = viewChild.required<ElementRef<Mesh>>('mesh');
40+
plane = injectPlane(() => ({ mass: 0, position: this.position(), args: this.args }), this.mesh);
41+
}
42+
43+
@Component({
44+
selector: 'app-box',
45+
standalone: true,
46+
template: `
47+
<ngt-mesh #mesh [receiveShadow]="true" [castShadow]="true">
48+
<ngt-box-geometry *args="args" />
49+
<ngt-mesh-standard-material [roughness]="0.5" color="#575757" />
50+
</ngt-mesh>
51+
`,
52+
imports: [NgtArgs],
53+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
54+
changeDetection: ChangeDetectionStrategy.OnPush,
55+
})
56+
export class Box {
57+
position = input<Triplet>([0, 0, 0]);
58+
args: Triplet = [2, 2, 2];
59+
mesh = viewChild.required<ElementRef<Mesh>>('mesh');
60+
box = injectBox(() => ({ mass: 10000, position: this.position(), args: this.args }), this.mesh);
61+
}
62+
63+
@Component({
64+
standalone: true,
65+
template: `
66+
<ngt-point-light [position]="[-10, -10, 30]" [intensity]="0.25 * Math.PI" [decay]="0" />
67+
<ngt-spot-light
68+
[intensity]="0.3 * Math.PI"
69+
[position]="[30, 30, 50]"
70+
[angle]="0.2"
71+
[penumbra]="1"
72+
[decay]="0"
73+
[castShadow]="true"
74+
/>
75+
76+
<ngtc-physics
77+
[options]="{ gravity: [0, 0, state.gravity()], iterations: 10 }"
78+
[debug]="{ enabled: state.isDebugging(), color: 'white' }"
79+
>
80+
<app-plane [position]="[0, 0, -10]" />
81+
@if (showPlane()) {
82+
<app-plane />
83+
}
84+
85+
<app-box [position]="[1, 0, 1]" />
86+
<app-box [position]="[2, 1, 5]" />
87+
<app-box [position]="[0, 0, 6]" />
88+
<app-box [position]="[-1, 1, 8]" />
89+
<app-box [position]="[-2, 2, 13]" />
90+
<app-box [position]="[2, -1, 13]" />
91+
92+
@if (!showPlane()) {
93+
<app-box [position]="[0.5, 1.0, 20]" />
94+
}
95+
</ngtc-physics>
96+
`,
97+
imports: [Box, Plane, NgtcPhysics, NgtcDebug],
98+
changeDetection: ChangeDetectionStrategy.OnPush,
99+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
100+
host: { class: 'basic-experience' },
101+
})
102+
export class Experience {
103+
Math = Math;
104+
state = inject(State);
105+
showPlane = signal(true);
106+
107+
constructor() {
108+
afterNextRender(() => {
109+
setTimeout(() => {
110+
this.showPlane.set(false);
111+
}, 5000);
112+
});
113+
}
114+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { signal } from '@angular/core';
2+
import { createInjectable } from 'ngxtension/create-injectable';
3+
4+
export const State = createInjectable(
5+
() => {
6+
const isDebugging = signal(false);
7+
const gravity = signal(-20);
8+
9+
return {
10+
gravity: gravity.asReadonly(),
11+
isDebugging: isDebugging.asReadonly(),
12+
changeGravity: () => gravity.update((prev) => (prev === -20 ? -10 : -20)),
13+
toggleDebugging: () => isDebugging.update((prev) => !prev),
14+
};
15+
},
16+
{ providedIn: 'scoped' },
17+
);
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { Routes } from '@angular/router';
2+
3+
const routes: Routes = [
4+
{
5+
path: 'basic',
6+
loadComponent: () => import('./basic/basic'),
7+
},
8+
{
9+
path: 'kinematic-cube',
10+
loadComponent: () => import('./kinematic-cube/kinematic-cube'),
11+
},
12+
// {
13+
// path: 'compound',
14+
// loadComponent: () => import('./compound/compound'),
15+
// },
16+
// {
17+
// path: 'chain',
18+
// loadComponent: () => import('./chain/chain'),
19+
// },
20+
// {
21+
// path: 'cube-heap',
22+
// loadComponent: () => import('./cube-heap/cube-heap'),
23+
// },
24+
// {
25+
// path: 'convexpolyhedron',
26+
// loadComponent: () => import('./convexpolyhedron/convexpolyhedron'),
27+
// },
28+
// {
29+
// path: 'monday-morning',
30+
// loadComponent: () => import('./monday-morning/monday-morning'),
31+
// },
32+
{
33+
path: '',
34+
redirectTo: 'basic',
35+
pathMatch: 'full',
36+
},
37+
];
38+
39+
export default routes;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { ChangeDetectionStrategy, Component } from '@angular/core';
2+
import { RouterOutlet } from '@angular/router';
3+
import { UiNavigations } from '../shared/ui-navigations';
4+
5+
@Component({
6+
standalone: true,
7+
template: `
8+
<app-ui-navigations [examples]="examples" root="cannon">
9+
<router-outlet />
10+
</app-ui-navigations>
11+
`,
12+
imports: [RouterOutlet, UiNavigations],
13+
changeDetection: ChangeDetectionStrategy.OnPush,
14+
host: { class: 'cannon' },
15+
})
16+
export default class Cannon {
17+
examples = ['basic', 'kinematic-cube', 'compound', 'chain', 'cube-heap', 'convexpolyhedron', 'monday-morning'];
18+
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import {
2+
CUSTOM_ELEMENTS_SCHEMA,
3+
ChangeDetectionStrategy,
4+
Component,
5+
ElementRef,
6+
computed,
7+
input,
8+
viewChild,
9+
} from '@angular/core';
10+
import { Triplet } from '@pmndrs/cannon-worker-api';
11+
import { NgtcPhysics } from 'angular-three-cannon';
12+
import { injectBox, injectPlane, injectSphere } from 'angular-three-cannon/body';
13+
import { NgtcDebug } from 'angular-three-cannon/debug';
14+
import { NgtArgs, extend, injectBeforeRender } from 'angular-three-core-new';
15+
import * as THREE from 'three';
16+
import { Color, InstancedMesh, Mesh } from 'three';
17+
import { niceColors } from '../../shared/colors';
18+
19+
extend(THREE);
20+
21+
@Component({
22+
selector: 'app-plane',
23+
standalone: true,
24+
template: `
25+
<ngt-mesh #mesh [receiveShadow]="true">
26+
<ngt-plane-geometry *args="[1000, 1000]" />
27+
<ngt-mesh-phong-material [color]="color()" />
28+
</ngt-mesh>
29+
`,
30+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
31+
changeDetection: ChangeDetectionStrategy.OnPush,
32+
imports: [NgtArgs],
33+
})
34+
export class Plane {
35+
color = input.required<string>();
36+
position = input<Triplet>([0, 0, 0]);
37+
rotation = input<Triplet>([0, 0, 0]);
38+
39+
mesh = viewChild.required<ElementRef<Mesh>>('mesh');
40+
plane = injectPlane(() => ({ position: this.position(), rotation: this.rotation() }), this.mesh);
41+
}
42+
43+
@Component({
44+
selector: 'app-box',
45+
standalone: true,
46+
template: `
47+
<ngt-mesh #mesh [castShadow]="true" [receiveShadow]="true">
48+
<ngt-box-geometry *args="args" />
49+
<ngt-mesh-lambert-material color="white" />
50+
</ngt-mesh>
51+
`,
52+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
53+
changeDetection: ChangeDetectionStrategy.OnPush,
54+
imports: [NgtArgs],
55+
})
56+
export class Box {
57+
args: Triplet = [4, 4, 4];
58+
59+
mesh = viewChild.required<ElementRef<Mesh>>('mesh');
60+
boxApi = injectBox(() => ({ args: this.args, mass: 1, type: 'Kinematic' }), this.mesh);
61+
62+
constructor() {
63+
injectBeforeRender(({ clock }) => {
64+
const boxApi = this.boxApi();
65+
const t = clock.getElapsedTime();
66+
boxApi?.position.set(Math.sin(t * 2) * 5, Math.cos(t * 2) * 5, 3);
67+
boxApi?.rotation.set(Math.sin(t * 6), Math.cos(t * 6), 0);
68+
});
69+
}
70+
}
71+
72+
@Component({
73+
selector: 'app-instanced-spheres',
74+
standalone: true,
75+
template: `
76+
<ngt-instanced-mesh #mesh [castShadow]="true" [receiveShadow]="true" *args="[undefined, undefined, count()]">
77+
<ngt-sphere-geometry *args="[1, 16, 16]">
78+
<ngt-instanced-buffer-attribute attach="attributes.color" *args="[colors(), 3]" />
79+
</ngt-sphere-geometry>
80+
<ngt-mesh-phong-material [vertexColors]="true" />
81+
</ngt-instanced-mesh>
82+
`,
83+
imports: [NgtArgs],
84+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
85+
changeDetection: ChangeDetectionStrategy.OnPush,
86+
})
87+
export class InstancedSpheres {
88+
count = input(100);
89+
90+
mesh = viewChild<ElementRef<InstancedMesh>>('mesh');
91+
sphere = injectSphere(
92+
(index) => ({ args: [1], mass: 1, position: [Math.random() - 0.5, Math.random() - 0.5, index * 2] }),
93+
this.mesh,
94+
);
95+
96+
colors = computed(() => {
97+
const array = new Float32Array(this.count() * 3);
98+
const color = new Color();
99+
for (let i = 0; i < this.count(); i++) {
100+
color
101+
.convertSRGBToLinear()
102+
.set(niceColors[Math.floor(Math.random() * 5)])
103+
.toArray(array, i * 3);
104+
}
105+
return array;
106+
});
107+
}
108+
109+
@Component({
110+
standalone: true,
111+
template: `
112+
<ngt-hemisphere-light [intensity]="0.35 * Math.PI" />
113+
<ngt-spot-light
114+
[angle]="0.3"
115+
[castShadow]="true"
116+
[decay]="0"
117+
[intensity]="2 * Math.PI"
118+
[penumbra]="1"
119+
[position]="[30, 0, 30]"
120+
>
121+
<ngt-vector2 *args="[256, 256]" attach="shadow.mapSize" />
122+
</ngt-spot-light>
123+
<ngt-point-light [decay]="0" [intensity]="0.5 * Math.PI" [position]="[-30, 0, -30]" />
124+
<ngtc-physics [options]="{ gravity: [0, 0, -30] }">
125+
<app-plane [color]="niceColors[4]" />
126+
<app-plane [color]="niceColors[1]" [position]="[-6, 0, 0]" [rotation]="[0, 0.9, 0]" />
127+
<app-plane [color]="niceColors[2]" [position]="[6, 0, 0]" [rotation]="[0, -0.9, 0]" />
128+
<app-plane [color]="niceColors[3]" [position]="[0, 6, 0]" [rotation]="[0.9, 0, 0]" />
129+
<app-plane [color]="niceColors[0]" [position]="[0, -6, 0]" [rotation]="[-0.9, 0, 0]" />
130+
<app-box />
131+
<app-instanced-spheres />
132+
</ngtc-physics>
133+
`,
134+
imports: [InstancedSpheres, Box, Plane, NgtcPhysics, NgtArgs, NgtcDebug],
135+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
136+
changeDetection: ChangeDetectionStrategy.OnPush,
137+
host: { class: 'kimenatic-experience' },
138+
})
139+
export class Experience {
140+
Math = Math;
141+
niceColors = niceColors;
142+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { ChangeDetectionStrategy, Component } from '@angular/core';
2+
import { NgtCanvas } from 'angular-three-core-new';
3+
import { Experience } from './experience';
4+
5+
@Component({
6+
standalone: true,
7+
template: `
8+
<ngt-canvas [sceneGraph]="scene" [options]="{ shadows: true, camera: { position: [0, -12, 16] } }" />
9+
`,
10+
changeDetection: ChangeDetectionStrategy.OnPush,
11+
imports: [NgtCanvas],
12+
host: { class: 'kinematic-cannon' },
13+
})
14+
export default class KinematicCube {
15+
scene = Experience;
16+
}

0 commit comments

Comments
 (0)