Skip to content

Commit 83fa194

Browse files
committed
docs: port magic box demo
1 parent 064944c commit 83fa194

File tree

4 files changed

+158
-0
lines changed

4 files changed

+158
-0
lines changed
Binary file not shown.
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/dom';
3+
import { SceneGraph } from './scene';
4+
5+
@Component({
6+
template: `
7+
<ngt-canvas shadows [camera]="{ position: [-3, 0.5, 3] }">
8+
<app-scene-graph *canvasContent />
9+
</ngt-canvas>
10+
`,
11+
imports: [NgtCanvas, SceneGraph],
12+
changeDetection: ChangeDetectionStrategy.OnPush,
13+
host: { class: 'soba-magic-box' },
14+
})
15+
export default class MagicBox {}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import {
2+
ChangeDetectionStrategy,
3+
Component,
4+
computed,
5+
CUSTOM_ELEMENTS_SCHEMA,
6+
ElementRef,
7+
input,
8+
viewChild,
9+
} from '@angular/core';
10+
import { injectBeforeRender, NgtArgs } from 'angular-three';
11+
import { NgtsEdges } from 'angular-three-soba/abstractions';
12+
import { NgtsCameraControls } from 'angular-three-soba/controls';
13+
import { NgtsPivotControls } from 'angular-three-soba/gizmos';
14+
import { injectGLTF } from 'angular-three-soba/loaders';
15+
import { NgtsMeshPortalMaterial } from 'angular-three-soba/materials';
16+
import { NgtsEnvironment } from 'angular-three-soba/staging';
17+
import * as THREE from 'three';
18+
import { GLTF } from 'three-stdlib';
19+
20+
import aoboxGLB from './aobox-transformed.glb' with { loader: 'file' };
21+
22+
type AOBoxGLTF = GLTF & {
23+
nodes: { Cube: THREE.Mesh<THREE.BufferGeometry, THREE.MeshStandardMaterial> };
24+
};
25+
26+
@Component({
27+
selector: 'app-material-side',
28+
template: `
29+
<ngts-mesh-portal-material [attach]="attach()">
30+
<ng-template>
31+
<!-- Everything in here is inside the portal and isolated from the canvas -->
32+
<ngt-ambient-light [intensity]="0.5 * Math.PI" />
33+
<ngts-environment [options]="{ preset: 'city' }" />
34+
35+
<!-- A box with baked AO -->
36+
@if (gltf(); as gltf) {
37+
<ngt-mesh castShadow receiveShadow [rotation]="rotation()" [geometry]="gltf.nodes.Cube.geometry">
38+
<ngt-mesh-standard-material
39+
[aoMapIntensity]="1"
40+
[aoMap]="gltf.nodes.Cube.material.aoMap"
41+
[color]="bg()"
42+
/>
43+
<ngt-spot-light
44+
castShadow
45+
[color]="bg()"
46+
[intensity]="2 * Math.PI"
47+
[position]="10"
48+
[angle]="0.15"
49+
[penumbra]="1"
50+
[decay]="0"
51+
[shadow.normalBias]="0.05"
52+
[shadow.bias]="0.0001"
53+
/>
54+
</ngt-mesh>
55+
}
56+
57+
<!-- The shape -->
58+
<ngt-mesh #shape castShadow receiveShadow>
59+
<ng-content />
60+
<ngt-mesh-standard-material [color]="bg()" />
61+
</ngt-mesh>
62+
</ng-template>
63+
</ngts-mesh-portal-material>
64+
`,
65+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
66+
changeDetection: ChangeDetectionStrategy.OnPush,
67+
imports: [NgtsMeshPortalMaterial, NgtsEnvironment],
68+
})
69+
export class Side {
70+
protected readonly Math = Math;
71+
72+
rotation = input([0, 0, 0]);
73+
bg = input.required<THREE.ColorRepresentation>();
74+
index = input.required<number>();
75+
76+
protected attach = computed(() => ['material', this.index()]);
77+
78+
protected gltf = injectGLTF<AOBoxGLTF>(() => aoboxGLB);
79+
private shapeRef = viewChild<ElementRef<THREE.Mesh>>('shape');
80+
81+
constructor() {
82+
injectBeforeRender(({ delta }) => {
83+
const shape = this.shapeRef()?.nativeElement;
84+
if (!shape) return;
85+
shape.rotation.x = shape.rotation.y += delta;
86+
});
87+
}
88+
}
89+
90+
@Component({
91+
selector: 'app-scene-graph',
92+
template: `
93+
<ngt-color attach="background" *args="['#a0a0a0']" />
94+
<ngts-camera-controls [options]="{ makeDefault: true }" />
95+
96+
<ngts-pivot-controls [options]="{ anchor: [-1.1, -1.1, -1.1], scale: 0.75, lineWidth: 3.5 }">
97+
<ngt-mesh>
98+
<ngt-box-geometry *args="[2, 2, 2]" />
99+
<ngts-edges [options]="{ lineWidth: 2 }" />
100+
101+
<app-material-side [rotation]="[0, 0, 0]" bg="orange" [index]="0">
102+
<ngt-torus-geometry *args="[0.65, 0.3, 64]" />
103+
</app-material-side>
104+
105+
<app-material-side [rotation]="[0, Math.PI, 0]" bg="lightblue" [index]="1">
106+
<ngt-torus-knot-geometry *args="[0.55, 0.2, 128, 32]" />
107+
</app-material-side>
108+
109+
<app-material-side [rotation]="[0, Math.PI / 2, Math.PI / 2]" bg="lightgreen" [index]="2">
110+
<ngt-box-geometry *args="[1.15, 1.15, 1.15]" />
111+
</app-material-side>
112+
113+
<app-material-side [rotation]="[0, Math.PI / 2, -Math.PI / 2]" bg="aquamarine" [index]="3">
114+
<ngt-octahedron-geometry />
115+
</app-material-side>
116+
117+
<app-material-side [rotation]="[0, -Math.PI / 2, 0]" bg="indianred" [index]="4">
118+
<ngt-icosahedron-geometry />
119+
</app-material-side>
120+
121+
<app-material-side [rotation]="[0, Math.PI / 2, 0]" bg="hotpink" [index]="5">
122+
<ngt-dodecahedron-geometry />
123+
</app-material-side>
124+
</ngt-mesh>
125+
</ngts-pivot-controls>
126+
`,
127+
imports: [NgtsCameraControls, NgtArgs, Side, NgtsPivotControls, NgtsEdges],
128+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
129+
changeDetection: ChangeDetectionStrategy.OnPush,
130+
})
131+
export class SceneGraph {
132+
protected readonly Math = Math;
133+
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,16 @@ const routes: Routes = [
236236
},
237237
},
238238
},
239+
{
240+
path: 'magic-box',
241+
loadComponent: () => import('./magic-box/magic-box'),
242+
data: {
243+
credits: {
244+
title: 'Magic Box',
245+
link: 'https://pmndrs.github.io/examples/demos/magic-box',
246+
},
247+
},
248+
},
239249
{
240250
path: '',
241251
redirectTo: 'stars',

0 commit comments

Comments
 (0)