Skip to content

Commit 9a0ee1d

Browse files
committed
feat(core): expose meshes on loaded object graph
1 parent b22e0d7 commit 9a0ee1d

File tree

8 files changed

+58
-55
lines changed

8 files changed

+58
-55
lines changed

apps/examples/src/app/soba/decal/scene.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
ElementRef,
66
input,
77
signal,
8-
Signal,
98
viewChild,
109
} from '@angular/core';
1110
import { injectBeforeRender, NgtArgs } from 'angular-three';
@@ -71,7 +70,7 @@ export class Dodecahedron {
7170
selector: 'app-bunny',
7271
template: `
7372
@if (gltf(); as gltf) {
74-
<ngt-mesh castShadow receiveShadow [geometry]="gltf.nodes.bunny.geometry" [dispose]="null">
73+
<ngt-mesh castShadow receiveShadow [geometry]="gltf.meshes['bunny'].geometry" [dispose]="null">
7574
<ngt-mesh-standard-material color="black" />
7675
<ngts-decal
7776
[options]="{ position: [0, 0.9, 0.75], rotation: [-0.4, Math.PI, 0], scale: [0.9, 0.25, 1] }"
@@ -109,7 +108,7 @@ export class Dodecahedron {
109108
export class Bunny {
110109
protected readonly Math = Math;
111110

112-
protected gltf = injectGLTF(() => './bunny-transformed.glb') as Signal<any | null>;
111+
protected gltf = injectGLTF(() => './bunny-transformed.glb');
113112

114113
private textRef = viewChild(NgtsText);
115114

@@ -128,9 +127,9 @@ export class Bunny {
128127
template: `
129128
<ngt-color attach="background" *args="['#f0f0f0']" />
130129
<ngt-ambient-light [intensity]="0.25 * Math.PI" />
131-
<ngt-spot-light [decay]="0" [position]="[10, 10, 10]" [angle]="0.15" [penumbra]="1" />
130+
<ngt-spot-light [decay]="0" [position]="10" [angle]="0.15" [penumbra]="1" />
132131
<ngt-point-light [decay]="0" [position]="[-10, 0, -5]" [intensity]="6" />
133-
<ngt-group [position]="[0, -0.75, 0]">
132+
<ngt-group [position.y]="-0.75">
134133
<app-bunny />
135134
<app-dodecahedron [position]="[-0.9, 2, 0.4]" [scale]="0.1" />
136135
<ngts-accumulative-shadows

apps/examples/src/app/soba/lowpoly-earth/scene.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
ElementRef,
1010
input,
1111
signal,
12-
Signal,
1312
TemplateRef,
1413
viewChild,
1514
} from '@angular/core';
@@ -93,13 +92,13 @@ export class MarkerIcon extends NgtHTML {
9392
@if (gltf(); as gltf) {
9493
<ngt-group [rotation]="[-Math.PI / 2, 0, Math.PI]" [position]="position()" [dispose]="null">
9594
<ngt-mesh
96-
[geometry]="gltf.nodes['URF-Height_Lampd_Ice_0'].geometry"
97-
[material]="gltf.materials.Lampd_Ice"
95+
[geometry]="gltf.meshes['URF-Height_Lampd_Ice_0'].geometry"
96+
[material]="gltf.materials['Lampd_Ice']"
9897
/>
99-
<ngt-mesh [geometry]="gltf.nodes['URF-Height_watr_0'].geometry" [material]="gltf.materials.watr">
98+
<ngt-mesh [geometry]="gltf.meshes['URF-Height_watr_0'].geometry" [material]="gltf.materials['watr']">
10099
<ngt-value [rawValue]="0" attach="material.roughness" />
101100
</ngt-mesh>
102-
<ngt-mesh [geometry]="gltf.nodes['URF-Height_Lampd_0'].geometry" [material]="gltf.materials.Lampd">
101+
<ngt-mesh [geometry]="gltf.meshes['URF-Height_Lampd_0'].geometry" [material]="gltf.materials['Lampd']">
103102
<ngt-value [rawValue]="'lightgreen'" attach="material.color" />
104103
105104
<app-marker [position]="[0, 1.3, 0]" [rotation]="[0, Math.PI / 2, 0]">
@@ -128,7 +127,7 @@ export class Model {
128127

129128
protected content = contentChild.required(TemplateRef);
130129

131-
protected gltf = injectGLTF(() => './earth.gltf') as Signal<any>;
130+
protected gltf = injectGLTF(() => './earth.gltf');
132131
}
133132

134133
@Component({

apps/examples/src/app/soba/shaky/model.ts

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, input, Signal } from '@angular/core';
1+
import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, input } from '@angular/core';
22
import { NgtArgs, NgtVector3 } from 'angular-three';
33
import { injectGLTF } from 'angular-three-soba/loaders';
44
import { NgtsMeshReflectorMaterial } from 'angular-three-soba/materials';
@@ -32,23 +32,23 @@ injectGLTF.preload(() => './pink-d.glb');
3232
receiveShadow
3333
castShadow
3434
[material]="material"
35-
[geometry]="gltf.nodes.Sphere.geometry"
35+
[geometry]="gltf.meshes['Sphere'].geometry"
3636
[position]="[-1.93, 1, -0.94]"
3737
[rotation]="[-Math.PI, 0.73, -Math.PI]"
3838
/>
3939
<ngt-mesh
4040
receiveShadow
4141
castShadow
4242
[material]="material"
43-
[geometry]="gltf.nodes.Sphere001.geometry"
43+
[geometry]="gltf.meshes['Sphere001'].geometry"
4444
[position]="[4.49, 2.34, 3.58]"
4545
[scale]="[2.33, 2.33, 2.33]"
4646
/>
4747
<ngt-mesh
4848
receiveShadow
4949
castShadow
5050
[material]="material"
51-
[geometry]="gltf.nodes.Sphere001.geometry"
51+
[geometry]="gltf.meshes['Sphere001'].geometry"
5252
[position]="[-16, 5, 17]"
5353
[rotation]="[-0.26, 0.04, -0.16]"
5454
[scale]="[5, 5, 5]"
@@ -57,22 +57,22 @@ injectGLTF.preload(() => './pink-d.glb');
5757
receiveShadow
5858
castShadow
5959
[material]="material"
60-
[geometry]="gltf.nodes.Sphere002.geometry"
60+
[geometry]="gltf.meshes['Sphere002'].geometry"
6161
[position]="[-5.28, 4.8, 5.12]"
6262
/>
6363
<ngt-mesh
6464
receiveShadow
6565
castShadow
6666
[material]="material"
67-
[geometry]="gltf.nodes.Sphere003.geometry"
67+
[geometry]="gltf.meshes['Sphere003'].geometry"
6868
[position]="[-10.13, 1.3, -3.95]"
6969
[rotation]="[-0.15, 0.01, -0.02]"
7070
/>
7171
<ngt-mesh
7272
receiveShadow
7373
castShadow
7474
[material]="material"
75-
[geometry]="gltf.nodes.Sphere004.geometry"
75+
[geometry]="gltf.meshes['Sphere004'].geometry"
7676
[position]="[-19.36, 1.05, -2.05]"
7777
[rotation]="[0, 0, 0.64]"
7878
[scale]="[-1.33, -1.33, -1.33]"
@@ -81,15 +81,15 @@ injectGLTF.preload(() => './pink-d.glb');
8181
receiveShadow
8282
castShadow
8383
[material]="material"
84-
[geometry]="gltf.nodes.Sphere005.geometry"
84+
[geometry]="gltf.meshes['Sphere005'].geometry"
8585
[position]="[-18.17, 0.94, -2.35]"
8686
[scale]="[0.87, 0.87, 0.87]"
8787
/>
8888
<ngt-mesh
8989
receiveShadow
9090
castShadow
9191
[material]="material"
92-
[geometry]="gltf.nodes.Torus.geometry"
92+
[geometry]="gltf.meshes['Torus'].geometry"
9393
[position]="[-0.36, 1.46, 0.73]"
9494
[rotation]="[Math.PI, 0.73, -2.64]"
9595
[scale]="[2, 2, 2]"
@@ -98,23 +98,23 @@ injectGLTF.preload(() => './pink-d.glb');
9898
receiveShadow
9999
castShadow
100100
[material]="material"
101-
[geometry]="gltf.nodes.Cone.geometry"
101+
[geometry]="gltf.meshes['Cone'].geometry"
102102
[position]="[2.3, 1.91, -4.41]"
103103
[scale]="[1.86, 1.86, 1.86]"
104104
/>
105105
<ngt-mesh
106106
receiveShadow
107107
castShadow
108108
[material]="material"
109-
[geometry]="gltf.nodes.Cone001.geometry"
109+
[geometry]="gltf.meshes['Cone001'].geometry"
110110
[position]="[-4.82, 0.47, -5.51]"
111111
[rotation]="[2.14, 0, -0.58]"
112112
/>
113113
<ngt-mesh
114114
receiveShadow
115115
castShadow
116116
[material]="material"
117-
[geometry]="gltf.nodes.Cube.geometry"
117+
[geometry]="gltf.meshes['Cube'].geometry"
118118
[position]="[-5.36, 1.94, 5.46]"
119119
[rotation]="[0, 0.42, 0]"
120120
[scale]="[1.9, 1.9, 1.9]"
@@ -123,22 +123,22 @@ injectGLTF.preload(() => './pink-d.glb');
123123
receiveShadow
124124
castShadow
125125
[material]="material"
126-
[geometry]="gltf.nodes.Cube001.geometry"
126+
[geometry]="gltf.meshes['Cube001'].geometry"
127127
[position]="[-1.8, 1, -10.04]"
128128
[rotation]="[0, -0.23, 0]"
129129
/>
130130
<ngt-mesh
131131
receiveShadow
132132
castShadow
133133
[material]="material"
134-
[geometry]="gltf.nodes.Cylinder.geometry"
134+
[geometry]="gltf.meshes['Cylinder'].geometry"
135135
[position]="[-12.3, 2.41, 1.53]"
136136
/>
137137
<ngt-mesh
138138
receiveShadow
139139
castShadow
140140
[material]="material"
141-
[geometry]="gltf.nodes.Cylinder001.geometry"
141+
[geometry]="gltf.meshes['Cylinder001'].geometry"
142142
[position]="[-10.47, 1.57, -8.75]"
143143
[rotation]="[Math.PI / 2, 0, -1.87]"
144144
[scale]="[1.55, 1.55, 1.55]"
@@ -147,23 +147,23 @@ injectGLTF.preload(() => './pink-d.glb');
147147
receiveShadow
148148
castShadow
149149
[material]="material"
150-
[geometry]="gltf.nodes.Cylinder002.geometry"
150+
[geometry]="gltf.meshes['Cylinder002'].geometry"
151151
[position]="[-1.15, 3.38, 14.39]"
152152
[rotation]="[0, Math.PI, 0]"
153153
/>
154154
<ngt-mesh
155155
receiveShadow
156156
castShadow
157157
[material]="material"
158-
[geometry]="gltf.nodes.Icosphere.geometry"
158+
[geometry]="gltf.meshes['Icosphere'].geometry"
159159
[position]="[7.29, 0.6, -5.63]"
160160
[scale]="[0.64, 0.64, 0.64]"
161161
/>
162162
<ngt-mesh
163163
receiveShadow
164164
castShadow
165165
[material]="material"
166-
[geometry]="gltf.nodes.Icosphere001.geometry"
166+
[geometry]="gltf.meshes['Icosphere001'].geometry"
167167
[position]="[7.26, 0.98, 12.9]"
168168
[rotation]="[-0.26, 0.04, -0.16]"
169169
/>
@@ -180,7 +180,7 @@ export class Model {
180180
position = input<NgtVector3>([0, 0, 0]);
181181
rotation = input<NgtVector3>([0, 0, 0]);
182182

183-
protected gltf = injectGLTF(() => './pink-d.glb') as Signal<any | null>;
183+
protected gltf = injectGLTF(() => './pink-d.glb');
184184
protected material = new MeshPhysicalMaterial({
185185
color: new Color('#bb86a1').convertSRGBToLinear(),
186186
roughness: 0,

libs/core/src/lib/utils/make.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,12 @@ export function makeCameraInstance(isOrthographic: boolean, size: NgtSize) {
5050
export type NgtObjectMap = {
5151
nodes: Record<string, THREE.Object3D<any>>;
5252
materials: Record<string, THREE.Material>;
53+
meshes: Record<string, THREE.Mesh>;
5354
[key: string]: any;
5455
};
5556

5657
export function makeObjectGraph(object: THREE.Object3D): NgtObjectMap {
57-
const data: NgtObjectMap = { nodes: {}, materials: {} };
58+
const data: NgtObjectMap = { nodes: {}, materials: {}, meshes: {} };
5859

5960
if (object) {
6061
object.traverse((child) => {
@@ -63,6 +64,7 @@ export function makeObjectGraph(object: THREE.Object3D): NgtObjectMap {
6364
data.materials[((child as THREE.Mesh).material as THREE.Material).name] = (child as THREE.Mesh)
6465
.material as THREE.Material;
6566
}
67+
if (is.three<THREE.Mesh>(child, 'isMesh') && !data.meshes[child.name]) data.meshes[child.name] = child;
6668
});
6769
}
6870
return data;

libs/soba/src/controls/scroll-controls.stories.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
inject,
88
input,
99
signal,
10-
Signal,
1110
viewChild,
1211
} from '@angular/core';
1312
import { Meta } from '@storybook/angular';
@@ -113,7 +112,7 @@ class LittlestTokyoStory {
113112
<ngt-mesh
114113
#mesh
115114
[(intersect)]="isIntersect"
116-
[geometry]="gltf.nodes.Suzanne.geometry"
115+
[geometry]="gltf.meshes['Suzanne'].geometry"
117116
(pointerover)="hovered.set(true)"
118117
(pointerout)="hovered.set(false)"
119118
>
@@ -131,7 +130,7 @@ class Suzanne {
131130
position = input([0, 0, 0]);
132131
scale = input(1);
133132

134-
gltf = injectGLTF(() => './suzanne.glb') as Signal<any>;
133+
gltf = injectGLTF(() => './suzanne.glb');
135134

136135
hovered = signal(false);
137136
isIntersect = signal(false);

libs/soba/src/materials/mesh-refraction-materials.stories.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, input, Signal } from '@angular/core';
1+
import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, input } from '@angular/core';
22
import { Meta } from '@storybook/angular';
33
import { injectLoader, NgtArgs } from 'angular-three';
44
import { NgtsCameraContent, NgtsCubeCamera } from 'angular-three-soba/cameras';
@@ -28,7 +28,7 @@ injectLoader.preload(
2828
selector: 'diamond-flat',
2929
template: `
3030
@if (texture(); as envMap) {
31-
<ngts-cube-camera [options]="{ envMap, frames: 1, resolution: 256 }">
31+
<ngts-cube-camera [options]="{ envMap: envMap, frames: 1, resolution: 256 }">
3232
<ng-template cameraContent let-cameraTexture>
3333
@if (gltf(); as gltf) {
3434
<ngts-caustics
@@ -45,7 +45,7 @@ injectLoader.preload(
4545
>
4646
<ngt-mesh
4747
castShadow
48-
[geometry]="gltf.nodes.Diamond_1_0.geometry"
48+
[geometry]="gltf.meshes['Diamond_1_0'].geometry"
4949
[rotation]="rotation()"
5050
[position]="position()"
5151
>
@@ -67,7 +67,7 @@ class Diamond {
6767
lightSource = input<NgtsCausticsOptions['lightSource']>();
6868
options = input({} as NgtsMeshRefractionMaterialOptions);
6969

70-
gltf = injectGLTF(() => './dflat.glb') as Signal<any | null>;
70+
gltf = injectGLTF(() => './dflat.glb');
7171
texture = injectLoader(
7272
() => RGBELoader,
7373
() => 'https://dl.polyhaven.org/file/ph-assets/HDRIs/hdr/1k/aerodynamics_workshop_1k.hdr',

libs/soba/src/materials/mesh-transmission-material.stories.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, input, Signal } from '@angular/core';
1+
import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, input } from '@angular/core';
22
import { Meta } from '@storybook/angular';
33
import { NgtsOrbitControls } from 'angular-three-soba/controls';
44
import { injectGLTF } from 'angular-three-soba/loaders';
@@ -12,30 +12,36 @@ import { number, storyDecorators, storyObject } from '../setup-canvas';
1212
template: `
1313
<ngt-group [dispose]="null">
1414
@if (gltf(); as gltf) {
15-
<ngt-mesh [geometry]="gltf.nodes.cube1.geometry" [position]="[-0.56, 0.38, -0.11]">
15+
<ngt-mesh [geometry]="gltf.meshes['cube1'].geometry" [position]="[-0.56, 0.38, -0.11]">
1616
<ngts-mesh-transmission-material [options]="options()" />
1717
</ngt-mesh>
1818
1919
<ngt-mesh
2020
castShadow
2121
[renderOrder]="100"
22-
[geometry]="gltf.nodes.cube2.geometry"
23-
[material]="gltf.materials.cube_mat"
22+
[geometry]="gltf.meshes['cube2'].geometry"
23+
[material]="gltf.materials['cube_mat']"
2424
[position]="[-0.56, 0.38, -0.11]"
2525
>
2626
<ngt-value [rawValue]="FrontSide" attach="material.side" />
2727
</ngt-mesh>
2828
2929
<ngt-mesh
30-
[geometry]="gltf.nodes.bubbles.geometry"
31-
[material]="gltf.materials.cube_bubbles_mat"
30+
[geometry]="gltf.meshes['bubbles'].geometry"
31+
[material]="gltf.materials['cube_bubbles_mat']"
3232
[position]="[-0.56, 0.38, -0.11]"
3333
/>
3434
3535
<ngt-group [position]="[-0.56, 0.38, -0.41]">
36-
<ngt-mesh [geometry]="gltf.nodes.arrows.geometry" [material]="gltf.materials.weapons_mat" />
37-
<ngt-mesh [geometry]="gltf.nodes.skeleton_1.geometry" [material]="gltf.materials.skele_mat" />
38-
<ngt-mesh [geometry]="gltf.nodes.skeleton_2.geometry" [material]="gltf.materials.weapons_mat">
36+
<ngt-mesh [geometry]="gltf.meshes['arrows'].geometry" [material]="gltf.materials['weapons_mat']" />
37+
<ngt-mesh
38+
[geometry]="gltf.meshes['skeleton_1'].geometry"
39+
[material]="gltf.materials['skele_mat']"
40+
/>
41+
<ngt-mesh
42+
[geometry]="gltf.meshes['skeleton_2'].geometry"
43+
[material]="gltf.materials['weapons_mat']"
44+
>
3945
<ngt-value [rawValue]="FrontSide" attach="material.side" />
4046
</ngt-mesh>
4147
</ngt-group>
@@ -52,7 +58,7 @@ class GelatinousCube {
5258

5359
options = input({} as NgtsMeshTransmissionMaterialOptions);
5460

55-
gltf = injectGLTF(() => './gelatinous_cube.glb') as Signal<any>;
61+
gltf = injectGLTF(() => './gelatinous_cube.glb');
5662
}
5763

5864
@Component({

0 commit comments

Comments
 (0)