Skip to content

Commit 4553199

Browse files
committed
docs: clean up camera demo
1 parent 781dc2e commit 4553199

File tree

1 file changed

+93
-91
lines changed

1 file changed

+93
-91
lines changed

apps/demo/src/app/camera/camera.component.ts

Lines changed: 93 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,27 @@ import {
55
ElementRef,
66
HostListener,
77
inject,
8+
OnInit,
89
ViewChild,
910
} from '@angular/core';
10-
import { injectBeforeRender, injectNgtRef, NgtArgs, NgtCanvas, NgtState, NgtStore } from 'angular-three';
11+
import { injectBeforeRender, NgtArgs, NgtCanvas, NgtRenderState, NgtState, NgtStore } from 'angular-three';
1112
import * as THREE from 'three';
1213

1314
@Component({
1415
standalone: true,
1516
template: `
1617
<ngt-group #cameras>
1718
<ngt-perspective-camera
18-
[ref]="cameraPerspectiveRef"
19+
#perspectiveCamera
1920
[aspect]="store.get('viewport', 'aspect') * 0.5"
2021
[near]="150"
2122
[far]="1000"
2223
[rotation]="[0, Math.PI, 0]"
2324
/>
2425
<ngt-orthographic-camera
25-
[ref]="cameraOrthographicRef"
26-
[left]="(0.5 * 600 * store.get('viewport', 'aspect')) / -2"
27-
[right]="(0.5 * 600 * store.get('viewport', 'aspect')) / 2"
26+
#orthographicCamera
27+
[left]="(300 * store.get('viewport', 'aspect')) / -2"
28+
[right]="(300 * store.get('viewport', 'aspect')) / 2"
2829
[top]="300"
2930
[bottom]="-300"
3031
[near]="150"
@@ -38,10 +39,10 @@ import * as THREE from 'three';
3839
</ngt-mesh>
3940
</ngt-group>
4041
41-
<ngt-camera-helper #perspective *args="[cameraPerspectiveRef.nativeElement]" />
42-
<ngt-camera-helper #orthographic *args="[cameraOrthographicRef.nativeElement]" />
42+
<ngt-camera-helper #perspectiveHelper *args="[perspectiveCamera]" />
43+
<ngt-camera-helper #orthographicHelper *args="[orthographicCamera]" />
4344
44-
<ngt-mesh #whiteMesh>
45+
<ngt-mesh #mesh>
4546
<ngt-sphere-geometry *args="[100, 16, 8]" />
4647
<ngt-mesh-basic-material [wireframe]="true" />
4748
@@ -59,128 +60,129 @@ import * as THREE from 'three';
5960
imports: [NgtArgs],
6061
schemas: [CUSTOM_ELEMENTS_SCHEMA],
6162
})
62-
export class Scene implements AfterViewInit {
63+
export class Scene implements AfterViewInit, OnInit {
6364
readonly Math = Math;
6465

65-
readonly cameraPerspectiveRef = injectNgtRef<THREE.PerspectiveCamera>();
66-
readonly cameraOrthographicRef = injectNgtRef<THREE.OrthographicCamera>();
67-
6866
readonly store = inject(NgtStore);
6967

68+
@ViewChild('perspectiveCamera', { static: true }) perspectiveCamera!: ElementRef<THREE.PerspectiveCamera>;
69+
@ViewChild('orthographicCamera', { static: true }) orthographicCamera!: ElementRef<THREE.OrthographicCamera>;
7070
@ViewChild('cameras', { static: true }) cameraGroup!: ElementRef<THREE.Group>;
71-
@ViewChild('perspective') cameraPerspectiveHelper?: ElementRef<THREE.CameraHelper>;
72-
@ViewChild('orthographic') cameraOrthographicHelper?: ElementRef<THREE.CameraHelper>;
71+
@ViewChild('mesh', { static: true }) mesh!: ElementRef<THREE.Mesh>;
7372

74-
@ViewChild('whiteMesh', { static: true }) whiteMesh!: ElementRef<THREE.Mesh>;
73+
@ViewChild('perspectiveHelper') perspectiveHelper?: ElementRef<THREE.CameraHelper>;
74+
@ViewChild('orthographicHelper') orthographicHelper?: ElementRef<THREE.CameraHelper>;
7575

7676
readonly vertices: number[] = [];
7777

7878
private activeCamera?: THREE.Camera;
7979
private activeCameraHelper?: THREE.CameraHelper;
8080

8181
constructor() {
82+
injectBeforeRender(this.onBeforeRender.bind(this), 1);
83+
}
84+
85+
ngOnInit() {
8286
for (let i = 0; i < 10000; i++) {
8387
this.vertices.push(THREE.MathUtils.randFloatSpread(2000)); // x
8488
this.vertices.push(THREE.MathUtils.randFloatSpread(2000)); // y
8589
this.vertices.push(THREE.MathUtils.randFloatSpread(2000)); // z
8690
}
87-
injectBeforeRender(({ gl, size, scene, camera }) => {
88-
const r = Date.now() * 0.0005;
89-
const mesh = this.whiteMesh.nativeElement;
90-
const cameraGroup = this.cameraGroup.nativeElement;
91-
const cameraPerspective = this.cameraPerspectiveRef.nativeElement;
92-
const cameraPerspectiveHelper = this.cameraPerspectiveHelper?.nativeElement;
93-
const cameraOrthographic = this.cameraOrthographicRef.nativeElement;
94-
const cameraOrthographicHelper = this.cameraOrthographicHelper?.nativeElement;
95-
96-
mesh.position.x = 700 * Math.cos(r);
97-
mesh.position.z = 700 * Math.sin(r);
98-
mesh.position.y = 700 * Math.sin(r);
99-
100-
mesh.children[0].position.x = 70 * Math.cos(2 * r);
101-
mesh.children[0].position.z = 70 * Math.sin(r);
102-
103-
if (cameraPerspective && cameraOrthographic && cameraPerspectiveHelper && cameraOrthographicHelper) {
104-
if (this.activeCamera === cameraPerspective) {
105-
cameraPerspective.fov = 35 + 30 * Math.sin(0.5 * r);
106-
cameraPerspective.far = mesh.position.length();
107-
cameraPerspective.updateProjectionMatrix();
108-
109-
cameraPerspectiveHelper.update();
110-
cameraPerspectiveHelper.visible = true;
111-
112-
cameraOrthographicHelper.visible = false;
113-
} else {
114-
cameraOrthographic.far = mesh.position.length();
115-
cameraOrthographic.updateProjectionMatrix();
116-
117-
cameraOrthographicHelper.update();
118-
cameraOrthographicHelper.visible = true;
119-
120-
cameraPerspectiveHelper.visible = false;
121-
}
122-
}
91+
}
12392

124-
cameraGroup.lookAt(mesh.position);
93+
ngAfterViewInit() {
94+
this.activeCamera = this.perspectiveCamera.nativeElement;
95+
this.activeCameraHelper = this.perspectiveHelper?.nativeElement;
96+
}
12597

126-
gl.clear();
98+
@HostListener('document:keydown', ['$event'])
99+
onKeyDown({ key }: KeyboardEvent) {
100+
switch (key.toLowerCase()) {
101+
case 'o':
102+
this.activeCamera = this.orthographicCamera.nativeElement;
103+
this.activeCameraHelper = this.orthographicHelper?.nativeElement;
104+
break;
105+
case 'p':
106+
this.activeCamera = this.perspectiveCamera.nativeElement;
107+
this.activeCameraHelper = this.perspectiveHelper?.nativeElement;
108+
}
109+
}
127110

128-
this.activeCameraHelper!.visible = false;
129-
gl.setViewport(0, 0, size.width / 2, size.height);
130-
gl.render(scene, this.activeCamera!);
111+
private onBeforeRender({ gl, size, camera, scene }: NgtRenderState) {
112+
if (!this.activeCamera || !this.activeCameraHelper) return;
131113

132-
this.activeCameraHelper!.visible = true;
114+
const r = Date.now() * 0.0005;
115+
// reassign shorthands
116+
const mesh = this.mesh.nativeElement;
117+
const camGroup = this.cameraGroup.nativeElement;
118+
const perspective = this.perspectiveCamera.nativeElement;
119+
const perspectiveHelper = this.perspectiveHelper?.nativeElement;
120+
const orthographic = this.orthographicCamera.nativeElement;
121+
const orthographicHelper = this.orthographicHelper?.nativeElement;
133122

134-
gl.setViewport(size.width / 2, 0, size.width / 2, size.height);
135-
gl.render(scene, camera);
136-
}, 1);
137-
}
123+
mesh.position.x = 700 * Math.cos(r);
124+
mesh.position.z = 700 * Math.sin(r);
125+
mesh.position.y = 700 * Math.sin(r);
138126

139-
ngAfterViewInit() {
140-
this.activeCamera = this.cameraPerspectiveRef.nativeElement;
141-
this.activeCameraHelper = this.cameraPerspectiveHelper?.nativeElement;
142-
}
127+
mesh.children[0].position.x = 70 * Math.cos(2 * r);
128+
mesh.children[0].position.z = 70 * Math.sin(r);
143129

144-
@HostListener('document:keydown', ['$event'])
145-
onKeyDown(event: KeyboardEvent) {
146-
if (event.key.toLowerCase() === 'o') {
147-
this.activeCamera = this.cameraOrthographicRef.nativeElement;
148-
this.activeCameraHelper = this.cameraOrthographicHelper?.nativeElement;
149-
} else if (event.key.toLowerCase() === 'p') {
150-
this.activeCamera = this.cameraPerspectiveRef.nativeElement;
151-
this.activeCameraHelper = this.cameraPerspectiveHelper?.nativeElement;
130+
if (perspective && orthographic && perspectiveHelper && orthographicHelper) {
131+
if (this.activeCamera === perspective) {
132+
perspective.fov = 35 + 30 * Math.sin(0.5 * r);
133+
perspective.far = mesh.position.length();
134+
perspective.updateProjectionMatrix();
135+
136+
perspectiveHelper.update();
137+
perspectiveHelper.visible = true;
138+
139+
orthographicHelper.visible = false;
140+
} else {
141+
orthographic.far = mesh.position.length();
142+
orthographic.updateProjectionMatrix();
143+
144+
orthographicHelper.update();
145+
orthographicHelper.visible = true;
146+
147+
perspectiveHelper.visible = false;
148+
}
152149
}
150+
151+
camGroup.lookAt(mesh.position);
152+
153+
gl.clear();
154+
155+
this.activeCameraHelper.visible = false;
156+
gl.setViewport(0, 0, size.width / 2, size.height);
157+
gl.render(scene, this.activeCamera);
158+
159+
this.activeCameraHelper.visible = true;
160+
161+
gl.setViewport(size.width / 2, 0, size.width / 2, size.height);
162+
gl.render(scene, camera);
153163
}
154164
}
155165

156166
@Component({
157167
standalone: true,
158168
template: `
169+
<div class="absolute text-center text-white w-full top-0 left-0 text-xl">
170+
<a href="https://threejs.org" target="_blank" rel="noopener" class="underline"> three.js </a> -
171+
<a href="https://angular-threejs.netlify.app" target="_blank" rel="noopener" class="underline">
172+
Angular Three
173+
</a>
174+
- cameras
175+
<br />
176+
<b class="text-green-300">O</b> orthographic <b class="text-green-300">P</b> perspective
177+
</div>
159178
<div class="block h-full w-full bg-black">
160179
<ngt-canvas
161180
[sceneGraph]="SceneGraph"
162181
[gl]="{ alpha: false }"
163-
[camera]="{
164-
fov: 50,
165-
near: 1,
166-
far: 10000,
167-
position: [0, 0, 2500]
168-
}"
182+
[camera]="{ fov: 50, near: 1, far: 10000, position: [0, 0, 2500] }"
169183
(created)="onCreated($event)"
170184
/>
171185
</div>
172-
<div class="absolute text-center text-white w-full top-0 left-0 text-xl">
173-
<a href="https://threejs.org" target="_blank" rel="noopener" class="underline">three.js</a> -<a
174-
href="https://angular-threejs.netlify.app"
175-
target="_blank"
176-
rel="noopener"
177-
class="underline"
178-
>Angular Three</a
179-
>
180-
- cameras
181-
<br />
182-
<b class="text-green-300">O</b> orthographic <b class="text-green-300">P</b> perspective
183-
</div>
184186
`,
185187
imports: [NgtCanvas],
186188
})

0 commit comments

Comments
 (0)