Skip to content

Commit 22c7e87

Browse files
committed
docs: add aquarium example
1 parent 41b95c4 commit 22c7e87

File tree

23 files changed

+340
-68
lines changed

23 files changed

+340
-68
lines changed

apps/kitchen-sink/src/app/cannon/convexpolyhedron/experience.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {
33
ChangeDetectionStrategy,
44
Component,
55
ElementRef,
6-
Signal,
76
computed,
87
inject,
98
input,
@@ -138,7 +137,7 @@ type DiamondGLTF = GLTF & {
138137
export class Diamond {
139138
protected positionRotationInputs = inject(PositionRotationInput, { host: true });
140139

141-
private gltf = injectGLTF(() => './diamond.glb') as Signal<DiamondGLTF | null>;
140+
private gltf = injectGLTF<DiamondGLTF>(() => './diamond.glb');
142141
protected geometry = computed(() => {
143142
const gltf = this.gltf();
144143
if (!gltf) return null;

apps/kitchen-sink/src/app/cannon/monday-morning/experience.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ interface CupGLTF extends GLTF {
327327
changeDetection: ChangeDetectionStrategy.OnPush,
328328
})
329329
export class Mug {
330-
protected gltf = injectGLTF(() => './cup.glb') as Signal<CupGLTF | null>;
330+
protected gltf = injectGLTF<CupGLTF>(() => './cup.glb');
331331
private group = viewChild.required<ElementRef<Group>>('group');
332332

333333
protected dragConstraint = injectDragConstraint(this.group);

apps/kitchen-sink/src/app/rapier/performance/performance.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
input,
77
output,
88
signal,
9-
Signal,
109
viewChild,
1110
} from '@angular/core';
1211
import { injectBeforeRender, NgtVector3, NON_ROOT } from 'angular-three';
@@ -113,7 +112,7 @@ export class Bendy {
113112
position = input<NgtVector3>([0, 0, 0]);
114113
scale = input<NgtVector3>([1, 1, 1]);
115114

116-
protected gltf = injectGLTF(() => './bendy.glb') as Signal<BendyGLTF | null>;
115+
protected gltf = injectGLTF<BendyGLTF>(() => './bendy.glb');
117116
}
118117

119118
@Component({
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { Signal } from '@angular/core';
21
import { injectGLTF } from 'angular-three-soba/loaders';
32
import { Mesh } from 'three';
43
import { GLTF } from 'three-stdlib';
@@ -8,5 +7,5 @@ type SuzanneGLTF = GLTF & {
87
};
98

109
export function injectSuzanne() {
11-
return injectGLTF(() => './suzanne.glb') as Signal<SuzanneGLTF | null>;
10+
return injectGLTF<SuzanneGLTF>(() => './suzanne.glb');
1211
}

apps/kitchen-sink/src/app/routed/bomb.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, Signal } from '@angular/core';
1+
import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
22
import { injectGLTF } from 'angular-three-soba/loaders';
33
import { NgtsMeshTransmissionMaterial } from 'angular-three-soba/materials';
44
import { Mesh } from 'three';
@@ -31,5 +31,5 @@ interface BombGLTF extends GLTF {
3131
imports: [NgtsMeshTransmissionMaterial],
3232
})
3333
export default class Bomb {
34-
protected gltf = injectGLTF(() => bombUrl) as Signal<BombGLTF | null>;
34+
protected gltf = injectGLTF<BombGLTF>(() => bombUrl);
3535
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { ChangeDetectionStrategy, Component } from '@angular/core';
2+
import { NgtCanvas } from 'angular-three';
3+
import { Experience } from './experience';
4+
5+
// <Canvas shadows camera={{ position: [30, 0, -3], fov: 35, near: 1, far: 50 }} gl={{ stencil: true }}>
6+
7+
@Component({
8+
template: `
9+
<ngt-canvas
10+
[sceneGraph]="sceneGraph"
11+
shadows
12+
[camera]="{ position: [30, 0, -3], fov: 35, near: 1, far: 50 }"
13+
[gl]="{ stencil: true }"
14+
/>
15+
`,
16+
changeDetection: ChangeDetectionStrategy.OnPush,
17+
host: { class: 'aquarium' },
18+
imports: [NgtCanvas],
19+
})
20+
export default class Aquarium {
21+
protected sceneGraph = Experience;
22+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
2+
import { NgtArgs } from 'angular-three';
3+
import { NgtsCameraControls } from 'angular-three-soba/controls';
4+
import {
5+
NgtsAccumulativeShadows,
6+
NgtsEnvironment,
7+
NgtsFloat,
8+
NgtsLightformer,
9+
NgtsRandomizedLights,
10+
} from 'angular-three-soba/staging';
11+
import { Spheres } from './spheres';
12+
import { Tank } from './tank';
13+
import { Turtle } from './turtle';
14+
15+
@Component({
16+
template: `
17+
<ngt-color *args="['#c6e5db']" attach="background" />
18+
19+
<!-- fish tank -->
20+
<app-tank [position]="[0, 0.25, 0]">
21+
<ngts-float [options]="{ rotationIntensity: 2, floatIntensity: 10, speed: 2 }">
22+
<app-turtle [position]="[0, -0.5, -1]" [rotation]="[0, Math.PI, 0]" [scale]="23" />
23+
</ngts-float>
24+
25+
<app-spheres />
26+
</app-tank>
27+
28+
<!-- soft shadows -->
29+
<ngts-accumulative-shadows
30+
[options]="{
31+
temporal: true,
32+
frames: 100,
33+
color: 'lightblue',
34+
colorBlend: 2,
35+
opacity: 0.7,
36+
alphaTest: 0.65,
37+
scale: 60,
38+
position: [0, -5, 0],
39+
}"
40+
>
41+
<ngts-randomized-lights
42+
[options]="{ amount: 8, radius: 15, ambient: 0.5, intensity: Math.PI, position: [-5, 10, -5], size: 20 }"
43+
/>
44+
</ngts-accumulative-shadows>
45+
46+
<!-- custom env map -->
47+
<ngts-environment [options]="{ resolution: 1024 }">
48+
<ngt-group * [rotation]="[-Math.PI / 3, 0, 0]">
49+
<ngts-lightformer
50+
[options]="{ intensity: 4, rotation: [Math.PI / 2, 0, 0], position: [0, 5, -9], scale: [10, 10, 1] }"
51+
/>
52+
53+
@for (x of lightPositions; track $index) {
54+
<ngts-lightformer
55+
[options]="{
56+
form: 'circle',
57+
intensity: 4,
58+
rotation: [Math.PI / 2, 0, 0],
59+
position: [x, 4, $index * 4],
60+
scale: [4, 1, 1],
61+
}"
62+
/>
63+
}
64+
65+
<ngts-lightformer
66+
[options]="{ intensity: 2, rotation: [Math.PI / 2, 0, 0], position: [-5, 1, -1], scale: [50, 2, 1] }"
67+
/>
68+
<ngts-lightformer
69+
[options]="{ intensity: 2, rotation: [-Math.PI / 2, 0, 0], position: [10, 1, 0], scale: [50, 2, 1] }"
70+
/>
71+
</ngt-group>
72+
</ngts-environment>
73+
74+
<ngts-camera-controls
75+
[options]="{
76+
minPolarAngle: 0,
77+
maxPolarAngle: Math.PI / 2,
78+
truckSpeed: 0,
79+
dollySpeed: 0,
80+
}"
81+
/>
82+
`,
83+
imports: [
84+
NgtArgs,
85+
Tank,
86+
NgtsFloat,
87+
Turtle,
88+
Spheres,
89+
NgtsAccumulativeShadows,
90+
NgtsRandomizedLights,
91+
NgtsEnvironment,
92+
NgtsLightformer,
93+
NgtsCameraControls,
94+
],
95+
changeDetection: ChangeDetectionStrategy.OnPush,
96+
host: { class: 'aquarium-soba-experience' },
97+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
98+
})
99+
export class Experience {
100+
protected readonly Math = Math;
101+
protected lightPositions = [2, 0, 2, 0, 2, 0, 2, 0];
102+
}
Binary file not shown.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
2+
import { NgtArgs } from 'angular-three';
3+
import { NgtsInstance, NgtsInstances } from 'angular-three-soba/performances';
4+
import { NgtsFloat } from 'angular-three-soba/staging';
5+
6+
@Component({
7+
selector: 'app-spheres',
8+
template: `
9+
<ngts-instances [options]="{ renderOrder: -1000 }">
10+
<ngt-sphere-geometry *args="[1, 64, 64]" />
11+
<ngt-mesh-basic-material [depthTest]="false" />
12+
13+
@for (sphere of spheres; track $index) {
14+
@let scale = sphere[0];
15+
@let color = sphere[1];
16+
@let speed = sphere[2];
17+
@let position = sphere[3];
18+
19+
<ngts-float [options]="{ rotationIntensity: 40, floatIntensity: 20, speed: speed / 2 }">
20+
<ngts-instance [options]="{ position, color, scale }" />
21+
</ngts-float>
22+
}
23+
</ngts-instances>
24+
`,
25+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
26+
changeDetection: ChangeDetectionStrategy.OnPush,
27+
imports: [NgtsInstances, NgtArgs, NgtsFloat, NgtsInstance],
28+
})
29+
export class Spheres {
30+
protected spheres = [
31+
[1, 'orange', 0.05, [-4, -1, -1]],
32+
[0.75, 'hotpink', 0.1, [-4, 2, -2]],
33+
[1.25, 'aquamarine', 0.2, [4, -3, 2]],
34+
[1.5, 'lightblue', 0.3, [-4, -2, -3]],
35+
[2, 'pink', 0.3, [-4, 2, -4]],
36+
[2, 'skyblue', 0.3, [-4, 2, -4]],
37+
[1.5, 'orange', 0.05, [-4, -1, -1]],
38+
[2, 'hotpink', 0.1, [-4, 2, -2]],
39+
[1.5, 'aquamarine', 0.2, [4, -3, 2]],
40+
[1.25, 'lightblue', 0.3, [-4, -2, -3]],
41+
[1, 'pink', 0.3, [-4, 2, -4]],
42+
[1, 'skyblue', 0.3, [-4, 2, -4]],
43+
] as const;
44+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import {
2+
ChangeDetectionStrategy,
3+
Component,
4+
CUSTOM_ELEMENTS_SCHEMA,
5+
effect,
6+
ElementRef,
7+
input,
8+
viewChild,
9+
} from '@angular/core';
10+
import { NgtVector3 } from 'angular-three';
11+
import { injectGLTF } from 'angular-three-soba/loaders';
12+
import { NgtsMeshTransmissionMaterial } from 'angular-three-soba/materials';
13+
import { injectMask } from 'angular-three-soba/staging';
14+
import { Group, Mesh } from 'three';
15+
import { GLTF } from 'three-stdlib';
16+
17+
import shapesGLB from './shapes-transformed.glb';
18+
19+
interface ShapesGLTF extends GLTF {
20+
nodes: { Cube: Mesh };
21+
}
22+
23+
@Component({
24+
selector: 'app-tank',
25+
template: `
26+
@if (gltf(); as gltf) {
27+
@let nodes = gltf.nodes;
28+
29+
<ngt-group [position]="position()" [dispose]="null">
30+
<ngt-mesh [castShadow]="true" [scale]="[0.61 * 6, 0.8 * 6, 6]" [geometry]="nodes.Cube.geometry">
31+
<ngts-mesh-transmission-material
32+
[options]="{
33+
backside: true,
34+
samples: 4,
35+
thickness: 3,
36+
anisotropy: 0.1,
37+
iridescence: 1,
38+
iridescenceIOR: 1,
39+
iridescenceThicknessRange: [0, 1400],
40+
}"
41+
/>
42+
</ngt-mesh>
43+
<ngt-group #group>
44+
<ng-content />
45+
</ngt-group>
46+
</ngt-group>
47+
}
48+
`,
49+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
50+
changeDetection: ChangeDetectionStrategy.OnPush,
51+
imports: [NgtsMeshTransmissionMaterial],
52+
})
53+
export class Tank {
54+
position = input<NgtVector3>([0, 0, 0]);
55+
56+
private groupRef = viewChild<ElementRef<Group>>('group');
57+
58+
protected gltf = injectGLTF<ShapesGLTF>(() => shapesGLB);
59+
60+
private stencilParameters = injectMask(() => 1);
61+
62+
constructor() {
63+
effect(() => {
64+
const gltf = this.gltf();
65+
if (!gltf) return;
66+
67+
const group = this.groupRef()?.nativeElement;
68+
if (!group) return;
69+
70+
// Apply stencil to all contents
71+
group.traverse((child) => {
72+
if (child instanceof Mesh && child.material) {
73+
Object.assign(child.material, { ...this.stencilParameters() });
74+
}
75+
});
76+
});
77+
}
78+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, effect, input } from '@angular/core';
2+
import { injectBeforeRender, NgtArgs, NgtEuler, NgtVector3 } from 'angular-three';
3+
import { injectGLTF } from 'angular-three-soba/loaders';
4+
import { injectAnimations, NgtsAnimationClips } from 'angular-three-soba/misc';
5+
import { GLTF } from 'three-stdlib';
6+
7+
import turtleGLB from './model_52a_-_kemps_ridley_sea_turtle_no_id-transformed.glb';
8+
9+
/*
10+
Author: DigitalLife3D (https://sketchfab.com/DigitalLife3D)
11+
License: CC-BY-NC-4.0 (http://creativecommons.org/licenses/by-nc/4.0/)
12+
Source: https://sketchfab.com/3d-models/model-52a-kemps-ridley-sea-turtle-no-id-7aba937dfbce480fb3aca47be3a9740b
13+
Title: Model 52A - Kemps Ridley Sea Turtle (no ID)
14+
*/
15+
@Component({
16+
selector: 'app-turtle',
17+
template: `
18+
@let parameters = { position: position(), rotation: rotation(), scale: scale() };
19+
<ngt-primitive *args="[gltf.scene()]" [parameters]="parameters" />
20+
`,
21+
imports: [NgtArgs],
22+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
23+
changeDetection: ChangeDetectionStrategy.OnPush,
24+
})
25+
export class Turtle {
26+
position = input<NgtVector3>([0, 0, 0]);
27+
rotation = input<NgtEuler>([0, 0, 0]);
28+
scale = input(1);
29+
30+
protected gltf = injectGLTF<GLTF & { animations: NgtsAnimationClips<'Swim Cycle'>[] }>(() => turtleGLB);
31+
32+
private animations = injectAnimations(this.gltf, this.gltf.scene);
33+
34+
constructor() {
35+
effect(() => {
36+
if (!this.animations.ready()) return;
37+
38+
this.animations.mixer.timeScale = 0.5;
39+
this.animations.actions['Swim Cycle']?.play();
40+
});
41+
42+
injectBeforeRender(({ clock }) => {
43+
const scene = this.gltf.scene();
44+
if (!scene) return;
45+
46+
scene.rotation.z = Math.sin(clock.elapsedTime / 4) / 2;
47+
});
48+
}
49+
}

apps/kitchen-sink/src/app/soba/backdrop-cable/astronaut.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
ElementRef,
1111
inject,
1212
input,
13-
Signal,
1413
viewChild,
1514
} from '@angular/core';
1615
import { extend, NgtGroup, NgtObjectEvents } from 'angular-three';
@@ -74,7 +73,7 @@ export class Astronaut {
7473

7574
modelRef = viewChild<ElementRef<Group>>('model');
7675

77-
protected gltf = injectGLTF(() => '/Astronaut-transformed.glb') as unknown as Signal<AstronautGLTFResult | null>;
76+
protected gltf = injectGLTF<AstronautGLTFResult>(() => '/Astronaut-transformed.glb');
7877

7978
constructor() {
8079
extend({ Group, Mesh });

0 commit comments

Comments
 (0)