Skip to content

Commit 048ca1a

Browse files
committed
docs: add backdrop and cable example from pmnrs
1 parent c4128ed commit 048ca1a

File tree

10 files changed

+370
-11
lines changed

10 files changed

+370
-11
lines changed
Binary file not shown.
Binary file not shown.

apps/kitchen-sink/public/spaceship.gltf

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/**Auto-generated by: https://github.com/angular-threejs/gltf
2+
Command: npx angular-three-gltf@1.1.11 apps/kitchen-sink/public/Astronaut-transformed.glb -o apps/kitchen-sink/src/app/soba/backdrop-cable/astronaut.ts --selector app-astronaut --name Astronaut
3+
**/
4+
5+
import {
6+
ChangeDetectionStrategy,
7+
Component,
8+
CUSTOM_ELEMENTS_SCHEMA,
9+
effect,
10+
ElementRef,
11+
inject,
12+
input,
13+
Signal,
14+
viewChild,
15+
} from '@angular/core';
16+
import { extend, NgtGroup, NgtObjectEvents } from 'angular-three';
17+
import { injectGLTF } from 'angular-three-soba/loaders';
18+
import type * as THREE from 'three';
19+
import { Group, Mesh } from 'three';
20+
import { GLTF } from 'three-stdlib';
21+
22+
export type AstronautGLTFResult = GLTF & {
23+
nodes: {
24+
Astronaut_mesh: THREE.Mesh;
25+
};
26+
materials: {
27+
Astronaut_mat: THREE.MeshStandardMaterial;
28+
};
29+
};
30+
31+
@Component({
32+
selector: 'app-astronaut',
33+
template: `
34+
@if (gltf(); as gltf) {
35+
<ngt-group #model [parameters]="options()">
36+
<ngt-mesh
37+
[receiveShadow]="true"
38+
[castShadow]="true"
39+
[geometry]="gltf.nodes.Astronaut_mesh.geometry"
40+
[material]="gltf.materials.Astronaut_mat"
41+
/>
42+
43+
<ng-content />
44+
</ngt-group>
45+
}
46+
`,
47+
hostDirectives: [
48+
{
49+
directive: NgtObjectEvents,
50+
outputs: [
51+
'click',
52+
'dblclick',
53+
'contextmenu',
54+
'pointerup',
55+
'pointerdown',
56+
'pointerover',
57+
'pointerout',
58+
'pointerenter',
59+
'pointerleave',
60+
'pointermove',
61+
'pointermissed',
62+
'pointercancel',
63+
'wheel',
64+
],
65+
},
66+
],
67+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
68+
changeDetection: ChangeDetectionStrategy.OnPush,
69+
})
70+
export class Astronaut {
71+
protected readonly Math = Math;
72+
73+
options = input({} as Partial<NgtGroup>);
74+
75+
modelRef = viewChild<ElementRef<Group>>('model');
76+
77+
protected gltf = injectGLTF(() => '/Astronaut-transformed.glb') as unknown as Signal<AstronautGLTFResult | null>;
78+
79+
constructor() {
80+
extend({ Group, Mesh });
81+
82+
effect(() => {
83+
const gltf = this.gltf();
84+
if (!gltf) return;
85+
86+
for (const materialKey in gltf.materials) {
87+
gltf.materials[materialKey as keyof AstronautGLTFResult['materials']].roughness = 0;
88+
}
89+
});
90+
91+
const objectEvents = inject(NgtObjectEvents, { host: true });
92+
effect(() => {
93+
const model = this.modelRef()?.nativeElement;
94+
if (!model) return;
95+
96+
objectEvents.ngtObjectEvents.set(model);
97+
});
98+
}
99+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { ChangeDetectionStrategy, Component } from '@angular/core';
2+
import { NgtCanvas } from 'angular-three';
3+
import { Experience } from './experience';
4+
5+
@Component({
6+
template: `
7+
<ngt-canvas [sceneGraph]="sceneGraph" shadows [camera]="{ position: [0, 1.5, 3] }" />
8+
`,
9+
changeDetection: ChangeDetectionStrategy.OnPush,
10+
imports: [NgtCanvas],
11+
host: { class: 'Backdrop-cable' },
12+
})
13+
export default class BackdropCable {
14+
protected sceneGraph = Experience;
15+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import {
2+
ChangeDetectionStrategy,
3+
Component,
4+
CUSTOM_ELEMENTS_SCHEMA,
5+
ElementRef,
6+
input,
7+
viewChild,
8+
} from '@angular/core';
9+
import { injectBeforeRender } from 'angular-three';
10+
import { NgtsQuadraticBezierLine } from 'angular-three-soba/abstractions';
11+
import { Group, Vector3 } from 'three';
12+
13+
@Component({
14+
selector: 'app-cable',
15+
template: `
16+
<ngts-quadratic-bezier-line [options]="{ lineWidth: 3, color: '#ff2060' }" />
17+
`,
18+
changeDetection: ChangeDetectionStrategy.OnPush,
19+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
20+
imports: [NgtsQuadraticBezierLine],
21+
})
22+
export class Cable {
23+
startRef = input.required<ElementRef<Group> | undefined>();
24+
endRef = input.required<ElementRef<Group>>();
25+
26+
bezierLine = viewChild.required(NgtsQuadraticBezierLine);
27+
28+
constructor() {
29+
const [v1, v2] = [new Vector3(), new Vector3()];
30+
31+
injectBeforeRender(() => {
32+
const [bezierLine, start, end] = [this.bezierLine(), this.startRef()?.nativeElement, this.endRef().nativeElement];
33+
if (!start || !end) return;
34+
bezierLine.setPoints(start.getWorldPosition(v1), end.getWorldPosition(v2));
35+
});
36+
}
37+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import {
2+
ChangeDetectionStrategy,
3+
Component,
4+
computed,
5+
CUSTOM_ELEMENTS_SCHEMA,
6+
ElementRef,
7+
viewChild,
8+
} from '@angular/core';
9+
import { NgtsOrbitControls } from 'angular-three-soba/controls';
10+
import { NgtsPivotControls } from 'angular-three-soba/gizmos';
11+
import { NgtsBackdrop, NgtsContactShadows, NgtsEnvironment, NgtsFloat } from 'angular-three-soba/staging';
12+
import { Group } from 'three';
13+
import { Astronaut } from './astronaut';
14+
import { Cable } from './cable';
15+
import { Spaceship } from './spaceship';
16+
17+
@Component({
18+
template: `
19+
<ngt-ambient-light [intensity]="Math.PI * 0.2" />
20+
<ngt-directional-light [position]="[-10, 0, -5]" [intensity]="Math.PI" color="red" />
21+
<ngt-directional-light [position]="[-1, -2, -5]" [intensity]="Math.PI * 0.2" color="#0c8cbf" />
22+
<ngt-spot-light
23+
[position]="[5, 0, 5]"
24+
[intensity]="Math.PI * 2.5"
25+
[penumbra]="1"
26+
[angle]="0.35"
27+
[decay]="0"
28+
[castShadow]="true"
29+
color="#0c8cbf"
30+
/>
31+
32+
<ngts-float [options]="{ scale: 0.75, position: [0, 0.65, 0], rotation: [0, 0.6, 0] }">
33+
<ngts-pivot-controls [options]="{ anchor: [0, 0.7, 0], depthTest: true, scale: 0.5, lineWidth: 2 }">
34+
<app-spaceship />
35+
</ngts-pivot-controls>
36+
</ngts-float>
37+
38+
<ngts-float
39+
[options]="{
40+
position: [1, 1.1, -0.5],
41+
rotation: [Math.PI / 3.5, 0, 0],
42+
rotationIntensity: 4,
43+
floatIntensity: 6,
44+
speed: 1.5,
45+
}"
46+
>
47+
<app-astronaut [options]="{ scale: 0.2 }">
48+
<ngt-group #astronaut [position]="[-0.6, 2, 0]" />
49+
</app-astronaut>
50+
</ngts-float>
51+
52+
<app-cable [startRef]="spaceshipModelRef()" [endRef]="astronautRef()" />
53+
54+
<ngts-backdrop [options]="{ castShadow: true, floor: 2, position: [0, -0.5, -3], scale: [50, 10, 4] }">
55+
<ngt-mesh-standard-material color="#353540" [envMapIntensity]="0.1" />
56+
</ngts-backdrop>
57+
58+
<ngts-contact-shadows [options]="{ position: [0, -0.485, 0], scale: 5, blur: 1.5, far: 1 }" />
59+
<ngts-environment [options]="{ preset: 'city' }" />
60+
<ngts-orbit-controls [options]="{ makeDefault: true }" />
61+
`,
62+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
63+
changeDetection: ChangeDetectionStrategy.OnPush,
64+
host: { class: 'backdrop-cable-soba-experience' },
65+
imports: [
66+
NgtsFloat,
67+
Spaceship,
68+
Astronaut,
69+
Cable,
70+
NgtsBackdrop,
71+
NgtsContactShadows,
72+
NgtsEnvironment,
73+
NgtsOrbitControls,
74+
NgtsPivotControls,
75+
],
76+
})
77+
export class Experience {
78+
protected readonly Math = Math;
79+
80+
protected astronautRef = viewChild.required<ElementRef<Group>>('astronaut');
81+
82+
private spaceship = viewChild.required(Spaceship);
83+
protected spaceshipModelRef = computed(() => this.spaceship().modelRef());
84+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/**Auto-generated by: https://github.com/angular-threejs/gltf
2+
Command: npx angular-three-gltf&#64;1.1.11 apps/kitchen-sink/public/spaceship.gltf -o apps/kitchen-sink/src/app/soba/backdrop-cable/spaceship.ts --selector app-spaceship --name Spaceship --transform Size: apps/kitchen-sink/public/spaceship.gltf [69.57KB] > /Users/nartc/code/github/angular-threejs/angular-three/apps/kitchen-sink/public/spaceship-transformed.glb [59.12KB] (15%)
3+
**/
4+
5+
import {
6+
ChangeDetectionStrategy,
7+
Component,
8+
CUSTOM_ELEMENTS_SCHEMA,
9+
effect,
10+
ElementRef,
11+
inject,
12+
input,
13+
Signal,
14+
viewChild,
15+
} from '@angular/core';
16+
import { extend, NgtGroup, NgtObjectEvents } from 'angular-three';
17+
import { injectGLTF } from 'angular-three-soba/loaders';
18+
import type * as THREE from 'three';
19+
import { Group, Mesh } from 'three';
20+
import { GLTF } from 'three-stdlib';
21+
22+
export type SpaceshipGLTFResult = GLTF & {
23+
nodes: {
24+
Cube005: THREE.Mesh;
25+
Cube005_1: THREE.Mesh;
26+
Cube005_2: THREE.Mesh;
27+
};
28+
materials: {
29+
PaletteMaterial001: THREE.MeshStandardMaterial;
30+
PaletteMaterial003: THREE.MeshStandardMaterial;
31+
PaletteMaterial002: THREE.MeshStandardMaterial;
32+
};
33+
};
34+
35+
@Component({
36+
selector: 'app-spaceship',
37+
template: `
38+
@if (gltf(); as gltf) {
39+
<ngt-group #model [parameters]="options()">
40+
<ngt-mesh
41+
[castShadow]="true"
42+
[receiveShadow]="true"
43+
[geometry]="gltf.nodes.Cube005.geometry"
44+
[material]="gltf.materials.PaletteMaterial001"
45+
/>
46+
<ngt-mesh
47+
[castShadow]="true"
48+
[receiveShadow]="true"
49+
[geometry]="gltf.nodes.Cube005_1.geometry"
50+
[material]="gltf.materials.PaletteMaterial003"
51+
/>
52+
<ngt-mesh
53+
[castShadow]="true"
54+
[receiveShadow]="true"
55+
[geometry]="gltf.nodes.Cube005_2.geometry"
56+
[material]="gltf.materials.PaletteMaterial002"
57+
/>
58+
59+
<ng-content />
60+
</ngt-group>
61+
}
62+
`,
63+
hostDirectives: [
64+
{
65+
directive: NgtObjectEvents,
66+
outputs: [
67+
'click',
68+
'dblclick',
69+
'contextmenu',
70+
'pointerup',
71+
'pointerdown',
72+
'pointerover',
73+
'pointerout',
74+
'pointerenter',
75+
'pointerleave',
76+
'pointermove',
77+
'pointermissed',
78+
'pointercancel',
79+
'wheel',
80+
],
81+
},
82+
],
83+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
84+
changeDetection: ChangeDetectionStrategy.OnPush,
85+
})
86+
export class Spaceship {
87+
protected readonly Math = Math;
88+
89+
options = input({} as Partial<NgtGroup>);
90+
91+
modelRef = viewChild<ElementRef<Group>>('model');
92+
93+
protected gltf = injectGLTF(() => '/spaceship-transformed.glb', {
94+
useDraco: true,
95+
}) as unknown as Signal<SpaceshipGLTFResult | null>;
96+
97+
constructor() {
98+
extend({ Group, Mesh });
99+
100+
effect(() => {
101+
const gltf = this.gltf();
102+
if (!gltf) return;
103+
104+
for (const materialKey in gltf.materials) {
105+
gltf.materials[materialKey as keyof SpaceshipGLTFResult['materials']].roughness = 0;
106+
}
107+
});
108+
109+
const objectEvents = inject(NgtObjectEvents, { host: true });
110+
effect(() => {
111+
const model = this.modelRef()?.nativeElement;
112+
if (!model) return;
113+
114+
objectEvents.ngtObjectEvents.set(model);
115+
});
116+
}
117+
}

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,17 @@ const routes: Routes = [
174174
},
175175
},
176176
},
177+
{
178+
path: 'backdrop-cable',
179+
loadComponent: () => import('./backdrop-cable/backdrop-cable'),
180+
data: {
181+
credits: {
182+
title: 'Backdrop Cable',
183+
link: 'https://pmndrs.github.io/examples/demos/backdrop-and-cables',
184+
class: 'text-white',
185+
},
186+
},
187+
},
177188
{
178189
path: '',
179190
redirectTo: 'stars',

0 commit comments

Comments
 (0)