|
| 1 | +import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, input } from '@angular/core'; |
| 2 | +import { NgtEuler, NgtVector3 } from 'angular-three'; |
| 3 | +import { NgtsOrbitControls } from 'angular-three-soba/controls'; |
| 4 | +import { injectGLTF } from 'angular-three-soba/loaders'; |
| 5 | +import { NgtsBakeShadows } from 'angular-three-soba/misc'; |
| 6 | +import { NgtsDetailed } from 'angular-three-soba/performances'; |
| 7 | +import { NgtsEnvironment } from 'angular-three-soba/staging'; |
| 8 | +import { Mesh, MeshStandardMaterial } from 'three'; |
| 9 | +import { GLTF } from 'three-stdlib'; |
| 10 | + |
| 11 | +const positions = [...Array(800)].map(() => ({ |
| 12 | + position: [40 - Math.random() * 80, 40 - Math.random() * 80, 40 - Math.random() * 80], |
| 13 | + rotation: [Math.random() * Math.PI * 2, Math.random() * Math.PI * 2, Math.random() * Math.PI * 2], |
| 14 | +})) as Array<{ position: [number, number, number]; rotation: [number, number, number] }>; |
| 15 | + |
| 16 | +interface BustGLTF extends GLTF { |
| 17 | + nodes: { Mesh_0001: Mesh }; |
| 18 | + materials: { default: MeshStandardMaterial }; |
| 19 | +} |
| 20 | + |
| 21 | +@Component({ |
| 22 | + selector: 'app-bust', |
| 23 | + template: ` |
| 24 | + <ngts-detailed [distances]="[0, 15, 25, 35, 100]" [options]="{ position: position(), rotation: rotation() }"> |
| 25 | + @for (level of gltfs() || []; track $index) { |
| 26 | + <ngt-mesh |
| 27 | + [receiveShadow]="true" |
| 28 | + [castShadow]="true" |
| 29 | + [geometry]="level.nodes.Mesh_0001.geometry" |
| 30 | + [material]="level.materials.default" |
| 31 | + > |
| 32 | + <ngt-value [rawValue]="0.25" attach="material.envMapIntensity" /> |
| 33 | + </ngt-mesh> |
| 34 | + } |
| 35 | + </ngts-detailed> |
| 36 | + `, |
| 37 | + schemas: [CUSTOM_ELEMENTS_SCHEMA], |
| 38 | + changeDetection: ChangeDetectionStrategy.OnPush, |
| 39 | + imports: [NgtsDetailed], |
| 40 | +}) |
| 41 | +export class LODBust { |
| 42 | + position = input<NgtVector3>([0, 0, 0]); |
| 43 | + rotation = input<NgtEuler>([0, 0, 0]); |
| 44 | + |
| 45 | + protected gltfs = injectGLTF<BustGLTF[]>(() => [ |
| 46 | + './bust-1-d.glb', |
| 47 | + './bust-2-d.glb', |
| 48 | + './bust-3-d.glb', |
| 49 | + './bust-4-d.glb', |
| 50 | + './bust-5-d.glb', |
| 51 | + ]); |
| 52 | +} |
| 53 | + |
| 54 | +@Component({ |
| 55 | + selector: 'app-lod-scene-graph', |
| 56 | + template: ` |
| 57 | + @for (p of positions; track $index) { |
| 58 | + <app-bust [position]="p.position" [rotation]="p.rotation" /> |
| 59 | + } |
| 60 | +
|
| 61 | + @if (!asRenderTexture()) { |
| 62 | + <ngts-orbit-controls [options]="{ autoRotate: true, autoRotateSpeed: 0.5, zoomSpeed: 0.075 }" /> |
| 63 | + } |
| 64 | +
|
| 65 | + <ngt-point-light [intensity]="0.5 * Math.PI" [decay]="0" /> |
| 66 | + <ngt-spot-light [position]="50" [intensity]="1.5 * Math.PI" castShadow [decay]="0" /> |
| 67 | + <ngts-environment [options]="{ preset: 'city' }" /> |
| 68 | + <ngts-bake-shadows /> |
| 69 | + `, |
| 70 | + schemas: [CUSTOM_ELEMENTS_SCHEMA], |
| 71 | + changeDetection: ChangeDetectionStrategy.OnPush, |
| 72 | + imports: [NgtsBakeShadows, NgtsEnvironment, NgtsOrbitControls, LODBust], |
| 73 | + host: { class: 'lod-soba-experience' }, |
| 74 | +}) |
| 75 | +export class SceneGraph { |
| 76 | + protected Math = Math; |
| 77 | + protected positions = positions; |
| 78 | + |
| 79 | + asRenderTexture = input(false); |
| 80 | +} |
0 commit comments