Skip to content

Commit 6762c5b

Browse files
committed
adjust app component in sandbox
1 parent 8203bbb commit 6762c5b

File tree

10 files changed

+167
-44
lines changed

10 files changed

+167
-44
lines changed

apps/sandbox/src/app/app.component.ts

Lines changed: 11 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { NgIf } from '@angular/common';
22
import { CUSTOM_ELEMENTS_SCHEMA, Component, computed, signal } from '@angular/core';
33
import { NgtArgs, NgtCanvas, extend } from 'angular-three';
4+
import { NgtsGrid } from 'angular-three-soba/abstractions';
45
import { NgtsOrbitControls } from 'angular-three-soba/controls';
56
import { injectNgtsGLTFLoader } from 'angular-three-soba/loaders';
67
import { injectNgtsAnimations } from 'angular-three-soba/misc';
@@ -11,27 +12,13 @@ extend(THREE);
1112
@Component({
1213
standalone: true,
1314
template: `
14-
<ngt-spot-light [position]="3" [castShadow]="true">
15-
<ngt-vector2 *args="[512, 512]" attach="shadow.mapSize" />
16-
</ngt-spot-light>
17-
18-
<ngt-mesh [rotation]="[-Math.PI / 2, 0, 0]" [receiveShadow]="true" [position]="[0, -1, 0]">
19-
<ngt-plane-geometry *args="[100, 100]" />
20-
<ngt-shadow-material />
21-
</ngt-mesh>
22-
23-
<ngt-primitive
24-
*args="[cloud()]"
25-
[ref]="animations.ref"
26-
[scale]="0.01"
27-
[rotation]="[0, -Math.PI / 2, 0]"
28-
[position]="[0, -1, 0]"
29-
(beforeRender)="onBeforeRender($event.object)"
30-
/>
31-
15+
<ngt-ambient-light [intensity]="Math.PI" />
16+
<ngt-point-light [intensity]="Math.PI" />
17+
<ngt-primitive *args="[bot()]" [ref]="animations.ref" [position]="[0, -1, 0]" />
3218
<ngts-orbit-controls />
19+
<ngts-grid [position]="[0, -1, 0]" [args]="[10, 10]" />
3320
`,
34-
imports: [NgtArgs, NgtsOrbitControls],
21+
imports: [NgtArgs, NgtsOrbitControls, NgtsGrid],
3522
schemas: [CUSTOM_ELEMENTS_SCHEMA],
3623
})
3724
export class Scene {
@@ -40,33 +27,23 @@ export class Scene {
4027
active = signal(false);
4128
hover = signal(false);
4229

43-
private cloudGltf = injectNgtsGLTFLoader(() => 'assets/cloud_from_world_of_final_fantasy/scene.gltf');
30+
private yBotGltf = injectNgtsGLTFLoader(() => 'assets/ybot.glb');
4431

45-
animations = injectNgtsAnimations(() => this.cloudGltf()?.animations || []);
46-
cloud = computed(() => {
47-
const gltf = this.cloudGltf();
32+
animations = injectNgtsAnimations(() => this.yBotGltf()?.animations || []);
33+
bot = computed(() => {
34+
const gltf = this.yBotGltf();
4835
if (gltf) {
49-
gltf.scene.traverse((child) => {
50-
if (child instanceof THREE.Mesh) child.castShadow = true;
51-
});
52-
5336
return gltf.scene;
5437
}
55-
5638
return null;
5739
});
58-
59-
onBeforeRender(cloud: THREE.Group) {
60-
cloud.rotation.y += 0.005;
61-
}
6240
}
6341

6442
@Component({
6543
standalone: true,
6644
imports: [NgtCanvas, NgIf],
6745
selector: 'sandbox-root',
68-
template: ` <ngt-canvas [sceneGraph]="Scene" [camera]="{ position: [2, 1, 3] }" [shadows]="true" /> `,
69-
styles: [''],
46+
template: ` <ngt-canvas [sceneGraph]="Scene" [camera]="{ position: [0, 1, 3] }" /> `,
7047
})
7148
export class AppComponent {
7249
readonly Scene = Scene;

apps/sandbox/src/assets/ybot.glb

2.35 MB
Binary file not shown.

libs/soba/abstractions/src/grid/grid.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ extend({ GridMaterial, Mesh, PlaneGeometry });
88

99
export type NgtsGridState = {
1010
/** Default plane-geometry arguments */
11-
args?: ConstructorParameters<typeof THREE.PlaneGeometry>;
11+
args: ConstructorParameters<typeof THREE.PlaneGeometry>;
1212
} & NgtGridMaterialState;
1313

1414
declare global {

libs/soba/loaders/src/gltf-loader/gltf-loader.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function _extensions(useDraco: boolean | string, useMeshOpt: boolean, extensions
1616
}
1717

1818
dracoLoader.setDecoderPath(
19-
typeof useDraco === 'string' ? useDraco : 'https://www.gstatic.com/draco/versioned/decoders/1.4.3/',
19+
typeof useDraco === 'string' ? useDraco : 'https://www.gstatic.com/draco/versioned/decoders/1.5.5/',
2020
);
2121
(loader as GLTFLoader).setDRACOLoader(dracoLoader);
2222
}

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,13 @@ class DefaultAnimationsStory {
4040
Math = Math;
4141

4242
yBotGltf = injectNgtsGLTFLoader(() => 'soba/ybot.glb') as Signal<YBotGLTF>;
43-
matcapBody = injectNgtsMatcapTexture(() => ({ id: '293534_B2BFC5_738289_8A9AA7', format: 1024 }));
43+
44+
private _bodyIndex = signal('293534_B2BFC5_738289_8A9AA7');
45+
@Input() set bodyIndex(index: string) {
46+
this._bodyIndex.set(index);
47+
}
48+
49+
matcapBody = injectNgtsMatcapTexture(() => ({ id: this._bodyIndex(), format: 1024 }));
4450
matcapJoints = injectNgtsMatcapTexture(() => ({ id: '3A2412_A78B5F_705434_836C47', format: 1024 }));
4551

4652
animations = injectNgtsAnimations(() => this.yBotGltf()?.animations || [], { playFirstClip: false });
@@ -75,5 +81,8 @@ export const Default = makeStoryObject(DefaultAnimationsStory, {
7581
canvasOptions: { camera: { position: [0, 0, 3] } },
7682
argsOptions: {
7783
animation: select('Strut', { options: ['Strut', 'Dance', 'Idle'] }),
84+
bodyIndex: select('293534_B2BFC5_738289_8A9AA7', {
85+
options: ['293534_B2BFC5_738289_8A9AA7', '3A2412_A78B5F_705434_836C47'],
86+
}),
7887
},
7988
});

libs/soba/src/setup-canvas.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ const STORY_INPUTS = new InjectionToken<Signal<Record<string, unknown>>>('story
7878
</ng-container>
7979
8080
<ng-container *ngIf="canvasOptions.lights">
81-
<ngt-ambient-light [intensity]="0.8 * Math.PI" />
81+
<ngt-ambient-light [intensity]="canvasOptions.useLegacyLights ? 0.8 : 0.8 * Math.PI" />
8282
<ngt-point-light [intensity]="1" [position]="[0, 6, 0]" />
8383
</ng-container>
8484
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { NgIf } from '@angular/common';
2+
import { CUSTOM_ELEMENTS_SCHEMA, Component, Input, signal, type Signal } from '@angular/core';
3+
import { injectNgtsGLTFLoader, type NgtsGLTF } from 'angular-three-soba/loaders';
4+
import { injectNgtsNormalTexture } from 'angular-three-soba/staging';
5+
import * as THREE from 'three';
6+
import { makeDecorators, makeStoryObject, number } from '../setup-canvas';
7+
8+
const textureIndex = signal(3);
9+
10+
type SuzanneGLTF = NgtsGLTF<{ nodes: { Suzanne: THREE.Mesh } }>;
11+
12+
@Component({
13+
standalone: true,
14+
template: `
15+
<ngt-mesh *ngIf="suzanneGltf() as suzanneGltf" [geometry]="suzanneGltf.nodes.Suzanne.geometry">
16+
<ngt-mesh-standard-material
17+
color="darkmagenta"
18+
[roughness]="0.9"
19+
[metalness]="0.1"
20+
[normalScale]="normalScale()"
21+
[normalMap]="normal.texture()"
22+
/>
23+
</ngt-mesh>
24+
`,
25+
imports: [NgIf],
26+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
27+
})
28+
class DefaultNormalTextureStory {
29+
suzanneGltf = injectNgtsGLTFLoader(() => 'soba/suzanne.glb', { useDraco: true }) as Signal<SuzanneGLTF>;
30+
31+
private _repeat = signal(8);
32+
@Input() set repeat(repeat: number) {
33+
this._repeat.set(repeat);
34+
}
35+
36+
private _scale = signal(4);
37+
@Input() set scale(scale: number) {
38+
this._scale.set(scale);
39+
}
40+
41+
@Input() set textureIndex(index: number) {
42+
textureIndex.set(index);
43+
}
44+
45+
normal = injectNgtsNormalTexture(() => ({
46+
id: textureIndex(),
47+
repeat: [this._repeat(), this._repeat()],
48+
anisotropy: 8,
49+
}));
50+
normalScale = () => new THREE.Vector2(this._scale(), this._scale());
51+
}
52+
53+
export default {
54+
title: 'Staging/injectNgtsNormalTexture',
55+
decorators: makeDecorators(),
56+
};
57+
58+
export const Default = makeStoryObject(DefaultNormalTextureStory, {
59+
canvasOptions: { camera: { position: [0, 0, 3] }, useLegacyLights: true },
60+
argsOptions: {
61+
textureIndex: number(textureIndex()),
62+
repeat: number(8),
63+
scale: number(4),
64+
},
65+
});

libs/soba/staging/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export * from './environment/assets';
66
export * from './environment/environment';
77
export * from './float/float';
88
export * from './matcap-texture/matcap-texture';
9+
export * from './normal-texture/normal-texture';
910
export * from './sky/sky';
1011
export * from './sparkles/sparkles';
1112
export { NgtsSpotLightShadow } from './spot-light/shadow-mesh';

libs/soba/staging/src/matcap-texture/matcap-texture.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ export function injectNgtsMatcapTexture(
4141

4242
const matcapList = signal<Record<string, string>>({});
4343

44-
const DEFAULT_MATCAP = computed(() => matcapList()[0]);
45-
const numTot = computed(() => Object.keys(matcapList()).length);
44+
const DEFAULT_MATCAP = () => matcapList()[0];
45+
const numTot = () => Object.keys(matcapList()).length;
4646

4747
effect(() => {
4848
if (!untracked(numTot)) {
@@ -54,7 +54,7 @@ export function injectNgtsMatcapTexture(
5454
}
5555
});
5656

57-
const fileHash = computed(() => {
57+
const fileHash = () => {
5858
const id = state().id;
5959
if (typeof id === 'string') {
6060
return id;
@@ -65,10 +65,10 @@ export function injectNgtsMatcapTexture(
6565
}
6666

6767
return null;
68-
});
68+
};
6969

70-
const fileName = computed(() => `${fileHash() || DEFAULT_MATCAP()}${getFormatString(state().format)}.png`);
71-
const url = computed(() => `${MATCAP_ROOT}/${state().format}/${fileName()}`);
70+
const fileName = () => `${fileHash() || DEFAULT_MATCAP()}${getFormatString(state().format)}.png`;
71+
const url = () => `${MATCAP_ROOT}/${state().format}/${fileName()}`;
7272

7373
let texture: Signal<THREE.Texture | null>;
7474
const matcapTexture = computed(() => {
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { computed, effect, runInInjectionContext, signal, untracked, type Injector, type Signal } from '@angular/core';
2+
import { assertInjectionContext } from 'angular-three';
3+
import { injectNgtsTextureLoader } from 'angular-three-soba/loaders';
4+
import * as THREE from 'three';
5+
6+
const NORMAL_ROOT = 'https://rawcdn.githack.com/pmndrs/drei-assets/7a3104997e1576f83472829815b00880d88b32fb';
7+
const LIST_URL = 'https://cdn.jsdelivr.net/gh/pmndrs/drei-assets@master/normals/normals.json';
8+
9+
export type NgtsNormalTextureState = {
10+
id: string | number;
11+
repeat: number[];
12+
anisotropy: number;
13+
offset: number[];
14+
onLoad?: (texture: THREE.Texture | THREE.Texture[]) => void;
15+
};
16+
17+
const defaultState: NgtsNormalTextureState = {
18+
id: 0,
19+
repeat: [1, 1],
20+
anisotropy: 1,
21+
offset: [0, 0],
22+
};
23+
24+
export function injectNgtsNormalTexture(
25+
normalTextureState: () => Partial<NgtsNormalTextureState>,
26+
{ injector }: { injector?: Injector } = {},
27+
) {
28+
injector = assertInjectionContext(injectNgtsNormalTexture, injector);
29+
return runInInjectionContext(injector, () => {
30+
const state = computed(() => ({ ...defaultState, ...normalTextureState() }));
31+
const normalsList = signal<Record<string, string>>({});
32+
33+
const DEFAULT_NORMAL = () => normalsList()[0];
34+
const numTot = () => Object.keys(normalsList()).length;
35+
36+
effect(() => {
37+
if (!untracked(numTot)) {
38+
fetch(LIST_URL)
39+
.then((res) => res.json())
40+
.then((data) => {
41+
normalsList.set(data);
42+
});
43+
}
44+
});
45+
46+
const imageName = () => normalsList()[state().id] || DEFAULT_NORMAL();
47+
const url = () => `${NORMAL_ROOT}/normals/${imageName()}`;
48+
49+
let texture: Signal<THREE.Texture | null>;
50+
const normalTexture = computed(() => {
51+
if (url().includes('undefined')) return null;
52+
if (!texture) {
53+
texture = injectNgtsTextureLoader(url, { onLoad: state().onLoad, injector });
54+
}
55+
return texture();
56+
});
57+
58+
effect(() => {
59+
const _texture = normalTexture();
60+
if (!_texture) return;
61+
62+
const { repeat, offset, anisotropy } = state();
63+
_texture.wrapS = _texture.wrapT = THREE.RepeatWrapping;
64+
_texture.repeat = new THREE.Vector2(repeat[0], repeat[1]);
65+
_texture.offset = new THREE.Vector2(offset[0], offset[1]);
66+
_texture.anisotropy = anisotropy;
67+
});
68+
69+
return { texture: normalTexture, numTot, url };
70+
});
71+
}

0 commit comments

Comments
 (0)