Skip to content

Commit c387ee0

Browse files
committed
docs(examples): update porsche routes
1 parent becb622 commit c387ee0

File tree

5 files changed

+218
-11
lines changed

5 files changed

+218
-11
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { computed, signal } from '@angular/core';
2+
3+
export const color = signal('maroon');
4+
export const colorAsHex = computed(() => toHex(color()));
5+
6+
// convert various colors values to hex
7+
function toHex(value: string) {
8+
const ctx = document.createElement('canvas').getContext('2d')!;
9+
ctx.fillStyle = value;
10+
return ctx.fillStyle;
11+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, viewChild } from '@angular/core';
2+
import { injectBeforeRender, NgtArgs } from 'angular-three';
3+
import { NgtsFloat, NgtsLightformer } from 'angular-three-soba/staging';
4+
import { BackSide, Group } from 'three';
5+
6+
@Component({
7+
selector: 'app-lightformers',
8+
template: `
9+
<!-- ceiling-->
10+
<ngts-lightformer
11+
[options]="{ intensity: 0.75, rotation: [Math.PI / 2, 0, 0], position: [0, 5, -9], scale: [10, 10, 1] }"
12+
/>
13+
<ngt-group [rotation]="[0, 0.5, 0]">
14+
<ngt-group #group>
15+
@for (position of positions; track $index) {
16+
<ngts-lightformer
17+
[options]="{
18+
form: 'circle',
19+
intensity: 2,
20+
rotation: [Math.PI / 2, 0, 0],
21+
position: [position, 4, $index * 4],
22+
scale: [3, 1, 1],
23+
}"
24+
/>
25+
}
26+
</ngt-group>
27+
</ngt-group>
28+
29+
<!-- sides-->
30+
<ngts-lightformer
31+
[options]="{ intensity: 4, rotation: [0, Math.PI / 2, 0], position: [-5, 1, -1], scale: [20, 0.1, 1] }"
32+
/>
33+
<ngts-lightformer [options]="{ rotation: [0, Math.PI / 2, 0], position: [-5, -1, -1], scale: [20, 0.5, 1] }" />
34+
<ngts-lightformer [options]="{ rotation: [0, -Math.PI / 2, 0], position: [10, 1, 0], scale: [20, 1, 1] }" />
35+
36+
<!-- accent red-->
37+
<ngts-float [options]="{ speed: 5, floatIntensity: 2, rotationIntensity: 2 }">
38+
<ngts-lightformer
39+
[options]="{ form: 'ring', color: 'red', intensity: 1, scale: 10, position: [-15, 4, -18], target: [0, 0, 0] }"
40+
/>
41+
</ngts-float>
42+
43+
<!-- background-->
44+
<ngt-mesh [scale]="100">
45+
<ngt-sphere-geometry *args="[1, 64, 64]" />
46+
<!-- we don't have LayerMaterial in angular-three yet -->
47+
<ngt-mesh-standard-material color="#444" [side]="BackSide" />
48+
</ngt-mesh>
49+
`,
50+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
51+
changeDetection: ChangeDetectionStrategy.OnPush,
52+
imports: [NgtsLightformer, NgtsFloat, NgtArgs],
53+
})
54+
export class Lightformers {
55+
protected Math = Math;
56+
protected BackSide = BackSide;
57+
protected positions = [2, 0, 2, 0, 2, 0, 2, 0];
58+
59+
private group = viewChild.required<ElementRef<Group>>('group');
60+
61+
constructor() {
62+
injectBeforeRender(({ delta }) => {
63+
const group = this.group().nativeElement;
64+
(group.position.z += delta * 10) > 20 && (group.position.z = -60);
65+
});
66+
}
67+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { ChangeDetectionStrategy, Component, computed, CUSTOM_ELEMENTS_SCHEMA, effect, input } from '@angular/core';
2+
import { applyProps, NgtArgs } from 'angular-three';
3+
import { injectGLTF } from 'angular-three-soba/loaders';
4+
import { Mesh } from 'three';
5+
import { color } from './color';
6+
7+
@Component({
8+
selector: 'app-porsche-model',
9+
template: `
10+
<ngt-primitive *args="[model()]" [parameters]="{ position: position(), rotation: rotation(), scale: scale() }" />
11+
`,
12+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
13+
changeDetection: ChangeDetectionStrategy.OnPush,
14+
imports: [NgtArgs],
15+
})
16+
export class Model {
17+
position = input([0, 0, 0]);
18+
rotation = input([0, 0, 0]);
19+
scale = input(1);
20+
21+
gltf = injectGLTF(() => './911-transformed.glb');
22+
protected model = computed(() => {
23+
const gltf = this.gltf();
24+
if (!gltf) return null;
25+
26+
const { scene, nodes, materials } = gltf;
27+
28+
Object.values(nodes).forEach((node) => {
29+
if ((node as Mesh).isMesh) {
30+
node.receiveShadow = node.castShadow = true;
31+
}
32+
});
33+
34+
applyProps(materials['rubber'], { color: '#222', roughness: 0.6, roughnessMap: null, normalScale: [4, 4] });
35+
applyProps(materials['window'], { color: 'black', roughness: 0, clearcoat: 0.1 });
36+
applyProps(materials['coat'], { envMapIntensity: 4, roughness: 0.5, metalness: 1 });
37+
applyProps(materials['paint'], { envMapIntensity: 2, roughness: 0.45, metalness: 0.8, color: color() });
38+
39+
return scene;
40+
});
41+
42+
constructor() {
43+
effect(() => {
44+
const gltf = this.gltf();
45+
if (!gltf) return;
46+
const { materials } = gltf;
47+
applyProps(materials['paint'], { color: color() });
48+
});
49+
}
50+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
2+
import { injectBeforeRender } from 'angular-three';
3+
import { injectGLTF } from 'angular-three-soba/loaders';
4+
import { NgtsAccumulativeShadows, NgtsEnvironment, NgtsRandomizedLights } from 'angular-three-soba/staging';
5+
import { NgtCanvas, NgtCanvasContent } from 'angular-three/dom';
6+
import { Vector3 } from 'three';
7+
import { color, colorAsHex } from './color';
8+
import { Lightformers } from './lightformers';
9+
import { Model } from './model';
10+
11+
injectGLTF.preload(() => './911-transformed.glb');
12+
13+
@Component({
14+
selector: 'app-scene-graph',
15+
template: `
16+
<ngt-spot-light
17+
[position]="[0, 15, 0]"
18+
[angle]="0.3"
19+
[penumbra]="1"
20+
castShadow
21+
[intensity]="2 * Math.PI"
22+
[decay]="0"
23+
>
24+
<ngt-value [rawValue]="-0.0001" attach="shadow.bias" />
25+
</ngt-spot-light>
26+
<ngt-ambient-light [intensity]="0.5 * Math.PI" />
27+
28+
<app-porsche-model #model [position]="[-0.5, -0.18, 0]" [rotation]="[0, Math.PI / 5, 0]" [scale]="1.6" />
29+
30+
<ngts-accumulative-shadows
31+
[options]="{ position: [0, -1.16, 0], frames: 100, alphaTest: 0.9, scale: 10, visible: !!model.gltf() }"
32+
>
33+
<ngts-randomized-lights
34+
[options]="{ amount: 8, radius: 10, ambient: 0.5, position: [1, 5, -1], intensity: 1.5 * Math.PI }"
35+
/>
36+
</ngts-accumulative-shadows>
37+
38+
<ngts-environment [options]="{ background: true, blur: 1, resolution: 256, frames: Infinity }">
39+
<app-lightformers * />
40+
</ngts-environment>
41+
`,
42+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
43+
changeDetection: ChangeDetectionStrategy.OnPush,
44+
imports: [NgtsAccumulativeShadows, NgtsRandomizedLights, Model, NgtsEnvironment, Lightformers],
45+
})
46+
export class SceneGraph {
47+
protected Math = Math;
48+
protected Infinity = Infinity;
49+
50+
constructor() {
51+
const v = new Vector3();
52+
53+
injectBeforeRender(({ clock, camera }) => {
54+
const t = clock.elapsedTime;
55+
camera.position.lerp(v.set(Math.sin(t / 5), 0, 12 + Math.cos(t / 5) / 2), 0.05);
56+
camera.lookAt(0, 0, 0);
57+
});
58+
}
59+
}
60+
61+
@Component({
62+
template: `
63+
<ngt-canvas [camera]="{ position: [5, 0, 15], fov: 30 }" shadows>
64+
<app-scene-graph *canvasContent />
65+
</ngt-canvas>
66+
<input class="absolute top-0 right-0" type="color" [value]="colorAsHex()" (change)="onChange($event)" />
67+
`,
68+
changeDetection: ChangeDetectionStrategy.OnPush,
69+
imports: [NgtCanvas, NgtCanvasContent, SceneGraph],
70+
host: { class: 'porsche-soba' },
71+
})
72+
export default class Porsche {
73+
protected colorAsHex = colorAsHex;
74+
75+
onChange(event: Event): void {
76+
const input = event.target as HTMLInputElement;
77+
color.set(input.value);
78+
}
79+
}

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -90,17 +90,17 @@ const routes: Routes = [
9090
// },
9191
// },
9292
// },
93-
// {
94-
// path: 'porsche',
95-
// loadComponent: () => import('./porsche/porsche'),
96-
// data: {
97-
// credits: {
98-
// title: 'Porsche Lighting',
99-
// link: 'https://pmndrs.github.io/examples/demos/building-live-envmaps',
100-
// class: 'left-2 text-white',
101-
// },
102-
// },
103-
// },
93+
{
94+
path: 'porsche',
95+
loadComponent: () => import('./porsche/porsche'),
96+
data: {
97+
credits: {
98+
title: 'Porsche Lighting',
99+
link: 'https://pmndrs.github.io/examples/demos/building-live-envmaps',
100+
class: 'left-2 text-white',
101+
},
102+
},
103+
},
104104
{
105105
path: 'instances',
106106
loadComponent: () => import('./instances/instances'),

0 commit comments

Comments
 (0)