Skip to content

Commit 52cf031

Browse files
committed
backdrop
1 parent 3efbeba commit 52cf031

File tree

25 files changed

+210
-34
lines changed

25 files changed

+210
-34
lines changed

libs/soba/abstractions/src/edges/edges.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { NgIf, NgTemplateOutlet } from '@angular/common';
22
import { CUSTOM_ELEMENTS_SCHEMA, Component, ContentChild, Input, TemplateRef, effect } from '@angular/core';
33
import { extend, injectNgtRef, signalStore, type NgtAnyRecord, type NgtLineSegments } from 'angular-three';
4-
import { NgtsSobaContent } from 'angular-three-soba/misc';
4+
import { NgtsSobaContent } from 'angular-three-soba/utils';
55
import * as THREE from 'three';
66
import { LineBasicMaterial, LineSegments } from 'three';
77

libs/soba/cameras/src/orthographic-camera/orthographic-camera.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ declare global {
4141
/>
4242
</ngt-orthographic-camera>
4343
<ngt-group #group *ngIf="cameraContent && cameraContent.ngtsCameraContent">
44-
<ng-container *ngTemplateOutlet="cameraContent.template; context: { fbo: fboRef(), group }" />
44+
<ng-container *ngTemplateOutlet="cameraContent.template; context: { fbo: fboRef.nativeElement, group }" />
4545
</ngt-group>
4646
`,
4747
imports: [NgIf, NgTemplateOutlet],

libs/soba/misc/src/animations/animations.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export function injectNgtsAnimations(
2525
const mixer = new THREE.AnimationMixer(null!);
2626
const actions = {} as Record<string, THREE.AnimationAction>;
2727
let cached = {} as Record<string, THREE.AnimationAction>;
28+
let object: THREE.Object3D | null = null;
2829

2930
const clips = [] as THREE.AnimationClip[];
3031
const names = [] as string[];
@@ -34,10 +35,12 @@ export function injectNgtsAnimations(
3435
cached = {};
3536
// uncache actions
3637
Object.values(actions).forEach((action) => {
37-
mixer.uncacheAction(action as unknown as THREE.AnimationClip, actualRef.untracked);
38+
mixer.uncacheAction(action as unknown as THREE.AnimationClip, object!);
3839
});
3940
// stop all actions
4041
mixer.stopAllAction();
42+
43+
object = null;
4144
});
4245

4346
injectBeforeRender(({ delta }) => mixer.update(delta));
@@ -47,6 +50,7 @@ export function injectNgtsAnimations(
4750
effect(() => {
4851
const actual = actualRef.nativeElement;
4952
if (!actual) return;
53+
object = actual;
5054
const animations = animationsFactory();
5155

5256
for (let i = 0; i < animations.length; i++) {

libs/soba/misc/src/caustics/caustics.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ import { NgIf } from '@angular/common';
22
import { Component, computed, CUSTOM_ELEMENTS_SCHEMA, effect, ElementRef, Input } from '@angular/core';
33
import { extend, injectNgtRef, injectNgtStore, NgtGroup, signalStore } from 'angular-three';
44
import { NgtsEdges } from 'angular-three-soba/abstractions';
5-
import { injectNgtsFBO, NgtsSobaContent } from 'angular-three-soba/misc';
65
import { CausticsMaterial, CausticsProjectionMaterial } from 'angular-three-soba/shaders';
6+
import { NgtsSobaContent } from 'angular-three-soba/utils';
77
import * as THREE from 'three';
88
import { Group, LineBasicMaterial, Mesh, OrthographicCamera, PlaneGeometry, Scene } from 'three';
99
import { FullScreenQuad } from 'three-stdlib';
10+
import { injectNgtsFBO } from '../fbo/fbo';
1011

1112
extend({ Group, Scene, Mesh, PlaneGeometry, OrthographicCamera, CausticsProjectionMaterial, LineBasicMaterial });
1213

libs/soba/misc/src/html/html.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ import {
2020
type NgtRef,
2121
type NgtVector3,
2222
} from 'angular-three';
23+
import { NgtsSobaContent } from 'angular-three-soba/utils';
2324
import * as THREE from 'three';
2425
import { Group, Mesh, PlaneGeometry, ShaderMaterial } from 'three';
25-
import { NgtsSobaContent } from '../content/content';
2626
import { NgtsHtmlWrapper, defaultCalculatePosition } from './html-wrapper';
2727

2828
extend({ Group, PlaneGeometry, Mesh, ShaderMaterial });

libs/soba/misc/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
export * from './animations/animations';
22
export * from './bake-shadows/bake-shadows';
33
export * from './caustics/caustics';
4-
export * from './content/content';
54
export * from './decal/decal';
65
export * from './depth-buffer/depth-buffer';
76
export * from './example/example';

libs/soba/performances/src/points/points-input.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Directive, Input } from '@angular/core';
1+
import { Directive, Input, computed } from '@angular/core';
22
import { injectNgtRef, signalStore } from 'angular-three';
33
import type { Points } from 'three';
44

@@ -53,6 +53,8 @@ export abstract class NgtsPointsInput {
5353
range = this.inputs.select('range');
5454
positions = this.inputs.select('positions');
5555
colors = this.inputs.select('colors');
56+
colorsLength = computed(() => this.colors()?.length || 0);
5657
sizes = this.inputs.select('sizes');
58+
sizesLength = computed(() => this.sizes()?.length || 0);
5759
stride = this.inputs.select('stride');
5860
}

libs/soba/performances/src/points/points.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import {
2727
type NgtPoints,
2828
type NgtRef,
2929
} from 'angular-three';
30-
import { NgtsSobaContent } from 'angular-three-soba/misc';
30+
import { NgtsSobaContent } from 'angular-three-soba/utils';
3131
import * as THREE from 'three';
3232
import { BufferAttribute, BufferGeometry, Points } from 'three';
3333
import { NgtsPointsInput, type NgtsPointsBuffersState, type NgtsPointsInstancesState } from './points-input';
@@ -240,14 +240,14 @@ export class NgtsPoint implements OnInit {
240240
/>
241241
<ngt-buffer-attribute
242242
attach="attributes.color"
243-
[count]="pointsInput.colors().length / pointsInput.stride()"
243+
[count]="pointsInput.colorsLength() / pointsInput.stride()"
244244
[array]="pointsInput.colors()"
245245
[itemSize]="pointsInput.stride()"
246246
[usage]="DynamicDrawUsage"
247247
/>
248248
<ngt-buffer-attribute
249249
attach="attributes.size"
250-
[count]="pointsInput.sizes().length / pointsInput.stride()"
250+
[count]="pointsInput.sizesLength() / pointsInput.stride()"
251251
[array]="pointsInput.sizes()"
252252
[itemSize]="1"
253253
[usage]="DynamicDrawUsage"

libs/soba/project.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@
7070
"libs/soba/materials/**/*.ts",
7171
"libs/soba/materials/**/*.html",
7272
"libs/soba/modifiers/**/*.ts",
73-
"libs/soba/modifiers/**/*.html"
73+
"libs/soba/modifiers/**/*.html",
74+
"libs/soba/utils/**/*.ts",
75+
"libs/soba/utils/**/*.html"
7476
]
7577
}
7678
},

libs/soba/src/misc/html.stories.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { CUSTOM_ELEMENTS_SCHEMA, Component, Input } from '@angular/core';
22
import { NgtArgs, injectNgtRef } from 'angular-three';
3-
import { NgtsHtml, NgtsSobaContent } from 'angular-three-soba/misc';
3+
import { NgtsHtml } from 'angular-three-soba/misc';
4+
import { NgtsSobaContent } from 'angular-three-soba/utils';
45
import { Mesh } from 'three';
56
import { makeDecorators, makeStoryFunction, makeStoryObject, turn } from '../setup-canvas';
67

libs/soba/src/performances/points.stories.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import * as THREE from 'three';
77
import { makeCanvasOptions, makeDecorators, makeStoryFunction } from '../setup-canvas';
88

99
import { NgFor } from '@angular/common';
10-
import { NgtsSobaContent } from 'angular-three-soba/misc';
10+
import { NgtsSobaContent } from 'angular-three-soba/utils';
1111
import * as buffer from 'maath/buffer';
1212
import * as misc from 'maath/misc';
1313

libs/soba/src/setup-canvas.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,11 @@ const STORY_INPUTS = new InjectionToken<Signal<Record<string, unknown>>>('story
8080
8181
<ng-container *ngIf="canvasOptions.lights">
8282
<ngt-ambient-light [intensity]="canvasOptions.useLegacyLights ? 0.8 : 0.8 * Math.PI" />
83-
<ngt-point-light [intensity]="canvasOptions.useLegacyLights ? 1 : Math.PI" [position]="[0, 6, 0]" />
83+
<ngt-point-light
84+
[intensity]="canvasOptions.useLegacyLights ? 1 : Math.PI"
85+
[position]="[0, 6, 0]"
86+
[castShadow]="true"
87+
/>
8488
</ng-container>
8589
8690
<ng-container *ngIf="canvasOptions.controls">
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { CUSTOM_ELEMENTS_SCHEMA, Component, computed } from '@angular/core';
2+
import { NgtArgs } from 'angular-three';
3+
import { NgtsOrbitControls } from 'angular-three-soba/controls';
4+
import { injectNgtsGLTFLoader } from 'angular-three-soba/loaders';
5+
import { injectNgtsAnimations } from 'angular-three-soba/misc';
6+
import { NgtsBackdrop, NgtsEnvironment } from 'angular-three-soba/staging';
7+
import { makeCanvasOptions, makeDecorators, makeStoryFunction } from '../setup-canvas';
8+
9+
@Component({
10+
selector: 'backdrop-robot',
11+
standalone: true,
12+
template: `<ngt-primitive ngtCompound *args="[robot()]" [ref]="animations.ref" />`,
13+
imports: [NgtArgs],
14+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
15+
})
16+
class Robot {
17+
private robotGltf = injectNgtsGLTFLoader(() => 'soba/assets/RobotExpressive.glb');
18+
robot = computed(() => {
19+
const robotGltf = this.robotGltf();
20+
if (!robotGltf) return null;
21+
22+
robotGltf.scene.traverse((child) => {
23+
if (child.type === 'Mesh') {
24+
child.receiveShadow = child.castShadow = true;
25+
}
26+
});
27+
28+
return robotGltf.scene;
29+
});
30+
31+
animations = injectNgtsAnimations(() => this.robotGltf()?.animations || []);
32+
}
33+
34+
@Component({
35+
standalone: true,
36+
template: `
37+
<ngt-group [position]="[0, -0.25, 0]">
38+
<backdrop-robot [scale]="0.2" [position]="[0, -0.5, 0]" />
39+
<ngts-backdrop [receiveShadow]="true" [scale]="[20, 5, 5]" [floor]="1.5" [position]="[0, -0.5, -2]">
40+
<ngt-mesh-physical-material [roughness]="1" color="#efefef" />
41+
</ngts-backdrop>
42+
</ngt-group>
43+
<ngts-orbit-controls [makeDefault]="true" [dampingFactor]="0.2" />
44+
<ngts-environment preset="warehouse" [background]="true" />
45+
`,
46+
imports: [NgtsBackdrop, Robot, NgtsOrbitControls, NgtsEnvironment, NgtArgs],
47+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
48+
})
49+
class DefaultBackdropStory {}
50+
51+
export default {
52+
title: 'Staging/Backdrop',
53+
decorators: makeDecorators(),
54+
};
55+
56+
const canvasOptions = makeCanvasOptions({
57+
camera: { position: [-1, 2, 4], fov: 35 },
58+
controls: false,
59+
compoundPrefixes: ['backdrop-robot'],
60+
useLegacyLights: true,
61+
});
62+
63+
export const Default = makeStoryFunction(DefaultBackdropStory, canvasOptions);
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { CUSTOM_ELEMENTS_SCHEMA, Component, Input, effect } from '@angular/core';
2+
import { NgtArgs, checkUpdate, extend, injectNgtRef, signalStore, type NgtGroup } from 'angular-three';
3+
import { Group, Mesh, PlaneGeometry, type BufferAttribute } from 'three';
4+
5+
const easeInExpo = (x: number) => (x === 0 ? 0 : Math.pow(2, 10 * x - 10));
6+
7+
export type NgtsBackdropState = {
8+
floor: number;
9+
segments: number;
10+
receiveShadow: boolean;
11+
};
12+
13+
declare global {
14+
interface HTMLElementTagNameMap {
15+
/**
16+
* @extends ngt-group
17+
*/
18+
'ngts-backdrop': NgtsBackdropState & NgtGroup;
19+
}
20+
}
21+
22+
extend({ Group, Mesh, PlaneGeometry });
23+
24+
@Component({
25+
selector: 'ngts-backdrop',
26+
standalone: true,
27+
template: `
28+
<ngt-group ngtCompound>
29+
<ngt-mesh [receiveShadow]="receiveShadow()" [rotation]="[-Math.PI / 2, 0, Math.PI / 2]">
30+
<ngt-plane-geometry [ref]="planeRef" *args="[1, 1, segments(), segments()]" />
31+
<ng-content />
32+
</ngt-mesh>
33+
</ngt-group>
34+
`,
35+
imports: [NgtArgs],
36+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
37+
})
38+
export class NgtsBackdrop {
39+
Math = Math;
40+
41+
private inputs = signalStore<NgtsBackdropState>({ floor: 0.25, segments: 20, receiveShadow: false });
42+
43+
@Input({ alias: 'floor' }) set _floor(floor: number) {
44+
this.inputs.set({ floor });
45+
}
46+
47+
@Input({ alias: 'segments' }) set _segments(segments: number) {
48+
this.inputs.set({ segments });
49+
}
50+
51+
@Input({ alias: 'receiveShadow' }) set _receiveShadow(receiveShadow: boolean) {
52+
this.inputs.set({ receiveShadow });
53+
}
54+
55+
private floor = this.inputs.select('floor');
56+
57+
planeRef = injectNgtRef<PlaneGeometry>();
58+
segments = this.inputs.select('segments');
59+
receiveShadow = this.inputs.select('receiveShadow');
60+
61+
constructor() {
62+
effect(() => {
63+
const plane = this.planeRef.nativeElement;
64+
if (!plane) return;
65+
const [segments, floor] = [this.segments(), this.floor()];
66+
const offset = segments / segments / 2;
67+
const position = plane.attributes['position'] as BufferAttribute;
68+
let i = 0;
69+
for (let x = 0; x < segments + 1; x++) {
70+
for (let y = 0; y < segments + 1; y++) {
71+
position.setXYZ(
72+
i++,
73+
x / segments - offset + (x === 0 ? -floor : 0),
74+
y / segments - offset,
75+
easeInExpo(x / segments),
76+
);
77+
}
78+
}
79+
80+
checkUpdate(position);
81+
plane.computeVertexNormals();
82+
});
83+
}
84+
}

libs/soba/staging/src/environment/environment.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { NgIf, NgTemplateOutlet } from '@angular/common';
22
import { CUSTOM_ELEMENTS_SCHEMA, Component, ContentChild, TemplateRef } from '@angular/core';
3-
import { NgtsSobaContent } from 'angular-three-soba/misc';
3+
import { NgtsSobaContent } from 'angular-three-soba/utils';
44
import { NgtsEnvironmentCube } from './environment-cube';
55
import { NgtsEnvironmentGround } from './environment-ground';
66
import { NgtsEnvironmentInput } from './environment-input';

libs/soba/staging/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export * from './accumulative-shadows/accumulative-shadows';
22
export * from './accumulative-shadows/randomized-lights';
3+
export * from './backdrop/backdrop';
34
export * from './bounds/bounds';
45
export * from './camera-shake/camera-shake';
56
export * from './center/center';

libs/soba/staging/src/stage/stage.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export class NgtsStageRefit implements OnChanges {
8989
boundsApi = injectNgtsBoundsApi();
9090

9191
@Input() radius = 0;
92-
@Input() adjustCamera = true;
92+
@Input() adjustCamera: boolean | number = true;
9393

9494
ngOnChanges() {
9595
if (this.adjustCamera) {
@@ -157,16 +157,16 @@ export class NgtsStageRefit implements OnChanges {
157157
[scale]="boundingState.get('radius') * 4"
158158
[far]="boundingState.get('radius')"
159159
[blur]="2"
160-
[opacity]="shadowsState().opacity"
161-
[width]="shadowsState().width"
162-
[height]="shadowsState().height"
163-
[smooth]="shadowsState().smooth"
164-
[resolution]="shadowsState().resolution"
165-
[frames]="shadowsState().frames"
166-
[scale]="shadowsState().scale"
167-
[color]="shadowsState().color"
168-
[depthWrite]="shadowsState().depthWrite"
169-
[renderOrder]="shadowsState().renderOrder"
160+
[opacity]="shadowsState().opacity!"
161+
[width]="shadowsState().width!"
162+
[height]="shadowsState().height!"
163+
[smooth]="shadowsState().smooth!"
164+
[resolution]="shadowsState().resolution!"
165+
[frames]="shadowsState().frames!"
166+
[scale]="shadowsState().scale!"
167+
[color]="shadowsState().color!"
168+
[depthWrite]="shadowsState().depthWrite!"
169+
[renderOrder]="shadowsState().renderOrder!"
170170
/>
171171
<ngts-accumulative-shadows
172172
*ngIf="shadowsState().accumulativeShadow"
@@ -175,11 +175,11 @@ export class NgtsStageRefit implements OnChanges {
175175
[alphaTest]="0.9"
176176
[toneMapped]="true"
177177
[scale]="boundingState.get('radius') * 4"
178-
[opacity]="shadowsState().opacity"
179-
[alphaTest]="shadowsState().alphaTest"
180-
[color]="shadowsState().color"
181-
[colorBlend]="shadowsState().colorBlend"
182-
[resolution]="shadowsState().resolution"
178+
[opacity]="shadowsState().opacity!"
179+
[alphaTest]="shadowsState().alphaTest!"
180+
[color]="shadowsState().color!"
181+
[colorBlend]="shadowsState().colorBlend!"
182+
[resolution]="shadowsState().resolution!"
183183
>
184184
<ngts-randomized-lights
185185
[amount]="shadowsState().amount ?? 8"

libs/soba/staging/src/stars/stars.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const genStar = (r: number) =>
3131
selector: 'ngts-stars',
3232
standalone: true,
3333
template: `
34-
<ngt-points [ref]="pointsRef">
34+
<ngt-points [ref]="starsRef">
3535
<ngt-buffer-geometry>
3636
<ngt-buffer-attribute attach="attributes.position" *args="[attributes().positions, 3]" />
3737
<ngt-buffer-attribute attach="attributes.color" *args="[attributes().colors, 3]" />

libs/soba/utils/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# angular-three-soba/utils
2+
3+
Secondary entry point of `angular-three-soba`. It can be used by importing from `angular-three-soba/utils`.

libs/soba/utils/ng-package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"lib": {
3+
"entryFile": "src/index.ts"
4+
}
5+
}

0 commit comments

Comments
 (0)