• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# SceneNode
2<!--Kit: ArkGraphics 3D-->
3<!--Subsystem: Graphics-->
4<!--Owner: @zzhao0-->
5<!--Designer: @zdustc-->
6<!--Tester: @zhangyue283-->
7<!--Adviser: @ge-yafang-->
8
9本模块提供3D图形中场景资源结点的类型及操作方法。
10
11> **说明:**
12>
13> 本模块首批接口从API version 12开始支持,后续版本的新增接口,采用上角标标记接口的起始版本。
14
15## 导入模块
16
17```ts
18import { LayerMask, NodeType, Container, Node, Geometry, LightType, Light, SpotLight, DirectionalLight,
19  Camera } from '@kit.ArkGraphics3D';
20```
21
22## LayerMask
23用于定义结点的图层掩码。
24
25### getEnabled
26getEnabled(index: number): boolean
27
28获取指定图层下标图层掩码的使能状态。
29
30**系统能力:** SystemCapability.ArkUi.Graphics3D
31
32**参数:**
33| 参数名 | 类型 | 必填 | 说明 |
34| ---- | ---- | ---- | ---- |
35| index | number | 是 | 要使能图层的下标,值域为大于等于0的整数。 |
36
37**返回值:**
38| 类型 | 说明 |
39| ---- | ---- |
40| boolean | 返回特定下标的图层是否使能。true表示使用图层掩码,false表示不使用。 |
41
42**示例:**
43```ts
44import { Image, Shader, MaterialType, Material, ShaderMaterial, Animation, Environment, Container, SceneNodeParameters,
45  LightType, Light, Camera, SceneResourceParameters, SceneResourceFactory, Scene, Node } from '@kit.ArkGraphics3D';
46
47function layerMask(): void {
48  // 加载场景资源,支持.gltf和.glb格式,路径和文件名可根据项目实际资源自定义
49  let scene: Promise<Scene> = Scene.load($rawfile("gltf/CubeWithFloor/glTF/AnimatedCube.gltf"));
50  scene.then(async (result: Scene) => {
51    if (result) {
52      let node : Node | null = result.getNodeByPath("rootNode_");
53      if (node) {
54          // 获取掩码的使能状态
55          let enabled: boolean = node.layerMask.getEnabled(1);
56      }
57    }
58  }).catch((error: Error) => {
59    console.error('Scene load failed:', error);
60  });
61}
62```
63
64### setEnabled
65
66setEnabled(index: number, enabled: boolean): void
67
68将特定下标的图层掩码使能。
69
70**系统能力:** SystemCapability.ArkUi.Graphics3D
71
72**参数:**
73| 参数名 | 类型 | 必填 | 说明 |
74| ---- | ---- | ---- | ---- |
75| index | number | 是 | 要使能图层的下标,值域为大于等于0的整数。 |
76| enabled | boolean | 是 | 要设置的使能状态。true表示使用图层掩码,false表示不使用。 |
77
78**示例:**
79```ts
80import { Image, Shader, MaterialType, Material, ShaderMaterial, Animation, Environment, Container, SceneNodeParameters,
81  LightType, Light, Camera, SceneResourceParameters, SceneResourceFactory, Scene, Node } from '@kit.ArkGraphics3D';
82
83function layerMask(): void {
84  // 加载场景资源,支持.gltf和.glb格式,路径和文件名可根据项目实际资源自定义
85  let scene: Promise<Scene> = Scene.load($rawfile("gltf/CubeWithFloor/glTF/AnimatedCube.gltf"));
86  scene.then(async (result: Scene) => {
87    if (result) {
88      let node : Node | null = result.getNodeByPath("rootNode/Scene/");
89      if (node) {
90          // 设置掩码状态
91          node.layerMask.setEnabled(1, true);
92      }
93    }
94  }).catch((error: Error) => {
95    console.error('Scene load failed:', error);
96  });
97}
98```
99
100## NodeType
101结点类型枚举。
102
103**系统能力:** SystemCapability.ArkUi.Graphics3D
104| 名称 | 值 | 说明 |
105| ---- | ---- | ---- |
106| NODE | 1 | 结点是空结点。 |
107| GEOMETRY | 2 | 几何类型结点。 |
108| CAMERA | 3 | 相机类型结点。 |
109| LIGHT | 4 | 灯光类型结点。 |
110
111## Container\<T>
112定义场景对象的容器。容器提供了一种将场景对象分组到层次结构中的方法。
113
114### append
115append(item: T): void
116
117追加一个对象到容器。
118
119**系统能力:** SystemCapability.ArkUi.Graphics3D
120
121**参数:**
122| 参数名 | 类型 | 必填 | 说明 |
123| ---- | ---- | ---- | ---- |
124| item | T | 是 | T类型对象。 |
125
126**示例:**
127```ts
128import { Image, Shader, MaterialType, Material, ShaderMaterial, Animation, Environment, Container, SceneNodeParameters,
129  LightType, Light, Camera, SceneResourceParameters, SceneResourceFactory, Scene, Node } from '@kit.ArkGraphics3D';
130
131function append(): void {
132  // 加载场景资源,支持.gltf和.glb格式,路径和文件名可根据项目实际资源自定义
133  let scene: Promise<Scene> = Scene.load($rawfile("gltf/CubeWithFloor/glTF/AnimatedCube.gltf"));
134  scene.then(async (result: Scene) => {
135    if (result) {
136      let node : Node | null = result.getNodeByPath("rootNode/Scene/");
137      // append 节点
138      result.root?.children.get(0)?.children.append(node);
139    }
140  }).catch((error: Error) => {
141    console.error('Scene load failed:', error);
142  });
143}
144```
145
146### insertAfter
147insertAfter(item: T, sibling: T | null): void
148
149在兄弟结点后面插入对象。
150
151**系统能力:** SystemCapability.ArkUi.Graphics3D
152
153**参数:**
154| 参数名 | 类型 | 必填 | 说明 |
155| ---- | ---- | ---- | ---- |
156| item | T | 是 | 要插入结点。 |
157| sibling | T \| null | 是 | 兄弟结点。 |
158
159**示例:**
160```ts
161import { Image, Shader, MaterialType, Material, ShaderMaterial, Animation, Environment, Container, SceneNodeParameters,
162  LightType, Light, Camera, SceneResourceParameters, SceneResourceFactory, Scene, Node } from '@kit.ArkGraphics3D';
163
164function insertAfter(): void {
165  // 加载场景资源,支持.gltf和.glb格式,路径和文件名可根据项目实际资源自定义
166  let scene: Promise<Scene> = Scene.load($rawfile("gltf/CubeWithFloor/glTF/AnimatedCube.gltf"));
167  scene.then(async (result: Scene) => {
168    if (result) {
169      let node : Node | null = result.getNodeByPath("rootNode/Scene/");
170      if (node) {
171        // insertAfter 节点
172        result.root?.children.get(0)?.children.insertAfter(node, null);
173      }
174    }
175  }).catch((error: Error) => {
176    console.error('Scene load failed:', error);
177  });
178}
179```
180
181### remove
182remove(item: T): void
183
184移除指定对象。
185
186**系统能力:** SystemCapability.ArkUi.Graphics3D
187
188**参数:**
189| 参数名 | 类型 | 必填 | 说明 |
190| ---- | ---- | ---- | ---- |
191| item | T | 是 | 要移除的对象。 |
192
193**示例:**
194```ts
195import { Image, Shader, MaterialType, Material, ShaderMaterial, Animation, Environment, Container, SceneNodeParameters,
196  LightType, Light, Camera, SceneResourceParameters, SceneResourceFactory, Scene, Node } from '@kit.ArkGraphics3D';
197
198function remove(): void {
199  // 加载场景资源,支持.gltf和.glb格式,路径和文件名可根据项目实际资源自定义
200  let scene: Promise<Scene> = Scene.load($rawfile("gltf/CubeWithFloor/glTF/AnimatedCube.gltf"));
201  scene.then(async (result: Scene) => {
202    if (result) {
203      let node : Node | null = result.getNodeByPath("rootNode/Scene/");
204      if (node) {
205        // remove 节点
206        result.root?.children.remove(node);
207      }
208    }
209  }).catch((error: Error) => {
210    console.error('Scene load failed:', error);
211  });
212}
213```
214
215### get
216get(index: number): T | null
217
218获取特定下标对象,获取不到则返回空。
219
220**系统能力:** SystemCapability.ArkUi.Graphics3D
221
222**参数:**
223| 参数名 | 类型 | 必填 | 说明 |
224| ---- | ---- | ---- | ---- |
225| index | number | 是 | 要获取对象的下标,取值范围是大于等于0的整数。 |
226
227**返回值:**
228| 类型 | 说明 |
229| ---- | ---- |
230| T \| null | 返回获取到的对象,获取不到则返回空值。 |
231
232**示例:**
233```ts
234import { Image, Shader, MaterialType, Material, ShaderMaterial, Animation, Environment, Container, SceneNodeParameters,
235  LightType, Light, Camera, SceneResourceParameters, SceneResourceFactory, Scene, Node } from '@kit.ArkGraphics3D';
236
237function get(): void {
238  // 加载场景资源,支持.gltf和.glb格式,路径和文件名可根据项目实际资源自定义
239  let scene: Promise<Scene> = Scene.load($rawfile("gltf/CubeWithFloor/glTF/AnimatedCube.gltf"));
240  scene.then(async (result: Scene) => {
241    if (result) {
242      let node : Node | null = result.getNodeByPath("rootNode/Scene/");
243      // 从children中get 0号节点
244      result.root?.children.get(0)?.children.insertAfter(node, null);
245    }
246  }).catch((error: Error) => {
247    console.error('Scene load failed:', error);
248  });
249}
250```
251
252### clear
253clear(): void
254
255清空容器内的所有对象。
256
257**系统能力:** SystemCapability.ArkUi.Graphics3D
258
259**示例:**
260```ts
261import { Image, Shader, MaterialType, Material, ShaderMaterial, Animation, Environment, Container, SceneNodeParameters,
262  LightType, Light, Camera, SceneResourceParameters, SceneResourceFactory, Scene, Node } from '@kit.ArkGraphics3D';
263
264function clear(): void {
265  // 加载场景资源,支持.gltf和.glb格式,路径和文件名可根据项目实际资源自定义
266  let scene: Promise<Scene> = Scene.load($rawfile("gltf/CubeWithFloor/glTF/AnimatedCube.gltf"));
267  scene.then(async (result: Scene) => {
268    if (result) {
269      let node : Node | null = result.getNodeByPath("rootNode/Scene/");
270      if (node) {
271        // 清空 node 节点下的所有子节点
272        node.children.clear();
273      }
274    }
275  }).catch((error: Error) => {
276    console.error('Scene load failed:', error);
277  });
278}
279```
280
281### count
282count(): number
283
284获取容器中对象的数量。
285
286**系统能力:** SystemCapability.ArkUi.Graphics3D
287
288**返回值:**
289| 类型 | 说明 |
290| ---- | ---- |
291| number | 返回容器中对象个数,取值范围是非负整数。 |
292
293**示例:**
294```ts
295import { Image, Shader, MaterialType, Material, ShaderMaterial, Animation, Environment, Container, SceneNodeParameters,
296  LightType, Light, Camera, SceneResourceParameters, SceneResourceFactory, Scene, Node } from '@kit.ArkGraphics3D';
297
298function count(): void {
299  // 加载场景资源,支持.gltf和.glb格式,路径和文件名可根据项目实际资源自定义
300  let scene: Promise<Scene> = Scene.load($rawfile("gltf/CubeWithFloor/glTF/AnimatedCube.gltf"));
301  scene.then(async (result: Scene) => {
302    if (result) {
303      let node : Node | null = result.getNodeByPath("rootNode_");
304      if (node) {
305        let container: Container<Node> = node.children;
306        // 获取children中的节点数
307        let count: number = container.count();
308      }
309    }
310  });
311}
312```
313
314## Node
3153D场景由树状层次结构的结点组成,其中每个结点都实现了Node接口。继承自[SceneResource](js-apis-inner-scene-resources.md#sceneresource-1)。
316
317### 属性
318
319**系统能力:** SystemCapability.ArkUi.Graphics3D
320
321| 名称 | 类型 | 只读 | 可选 | 说明 |
322| ---- | ---- | ---- | ---- | ---- |
323| position | [Position3](js-apis-inner-scene-types.md#position3) | 否 | 否 | 结点位置。 |
324| rotation | [Quaternion](js-apis-inner-scene-types.md#quaternion) | 否 | 否 | 结点旋转角度。 |
325| scale | [Scale3](js-apis-inner-scene-types.md#scale3) | 否 | 否 | 结点缩放。 |
326| visible | boolean | 否 | 否 | 结点是否可见。true表示该节点可见,false表示不可见。 |
327| nodeType | [NodeType](#nodetype) | 是 | 否 | 结点类型。 |
328| layerMask | [LayerMask](#layermask) | 是 | 否 | 结点的图层掩码。 |
329| path | string | 是 | 否 | 结点路径。 |
330| parent | [Node](#node) \| null | 是 | 否 | 结点的父结点,不存在则为空值。 |
331| children | [Container](js-apis-inner-scene-nodes.md#containert)\<[Node](#node)> | 是 | 否 | 结点的结点,不存在则为空值。 |
332
333### getNodeByPath
334getNodeByPath(path: string): Node | null
335
336根据路径获取结点,如果获取不到则返回空。
337
338**系统能力:** SystemCapability.ArkUi.Graphics3D
339
340**参数:**
341| 参数名 | 类型 | 必填 | 说明 |
342| ---- | ---- | ---- | ---- |
343| path | string | 是 | 场景结点层次中的路径。每层之间使用'/'符号进行分割。|
344
345**返回值:**
346| 类型 | 说明 |
347| ---- | ---- |
348| [Node](#node) \| null | 返回结点对象。 |
349
350**示例:**
351```ts
352import { Image, Shader, MaterialType, Material, ShaderMaterial, Animation, Environment, Container, SceneNodeParameters,
353  LightType, Light, Camera, SceneResourceParameters, SceneResourceFactory, Scene, Node } from '@kit.ArkGraphics3D';
354
355function getNode(): void {
356  // 加载场景资源,支持.gltf和.glb格式,路径和文件名可根据项目实际资源自定义
357  let scene: Promise<Scene> = Scene.load($rawfile("gltf/CubeWithFloor/glTF/AnimatedCube.gltf"));
358  scene.then(async (result: Scene) => {
359    if (result && result.root) {
360      // 查找节点
361      let geo : Node | null = result.root.getNodeByPath("scene/node");
362    }
363  });
364}
365```
366
367## Geometry
368几何节点类型,用于承载可渲染的网格数据,并支持可选的形变功能,继承自[Node](#node)。
369
370### 属性
371
372**系统能力:** SystemCapability.ArkUi.Graphics3D
373
374| 名称 | 类型 | 只读 | 可选 | 说明 |
375| ---- | ---- | ---- | ---- | ---- |
376| mesh | [Mesh](js-apis-inner-scene-resources.md#mesh) | 是 | 否 | 网格属性。 |
377| morpher<sup>20+</sup> | [Morpher](js-apis-inner-scene-resources.md#morpher20) | 是 | 是 | 可选的形变器,用于为几何体添加基于顶点的形变或动画效果。若未设置,则该几何体不支持形变功能。 |
378
379## LightType
380光源类型枚举。
381
382**系统能力:** SystemCapability.ArkUi.Graphics3D
383
384| 名称 | 值 | 说明 |
385| ---- | ---- | ---- |
386| DIRECTIONAL | 1 | 平行光类型。 |
387| SPOT | 2 | 点光源类型。 |
388
389## Light
390光源,继承自[Node](#node)。
391
392### 属性
393
394**系统能力:** SystemCapability.ArkUi.Graphics3D
395
396| 名称 | 类型 | 只读 | 可选 | 说明 |
397| ---- | ---- | ---- | ---- | ---- |
398| lightType | [LightType](#lighttype) | 是 | 否 | 光源类型。 |
399| color | [Color](js-apis-inner-scene-types.md#color) | 否 | 否 | 颜色。 |
400| intensity | number | 否 | 否 | 光照密度,取值范围是大于0的实数。 |
401| shadowEnabled | boolean | 否 | 否 | 是否使能阴影。true表示添加阴影,false表示没有阴影效果。 |
402| enabled | boolean | 否 | 否 | 是否使能光源。true表示使用光源,false表示不使用。 |
403
404## SpotLight
405点光源类型,继承自[Light](#light)。
406
407**系统能力:** SystemCapability.ArkUi.Graphics3D
408
409## DirectionalLight
410平行光类型,继承自[Light](#light)。
411
412**系统能力:** SystemCapability.ArkUi.Graphics3D
413
414
415## Camera
416相机类型,Camera继承自[Node](#node)。
417
418### 属性
419
420**系统能力:** SystemCapability.ArkUi.Graphics3D
421
422| 名称 | 类型 | 只读 | 可选 | 说明 |
423| ---- | ---- | ---- | ---- | ---- |
424| fov | number | 否 | 否 | 视场,取值在0到π弧度之间。 |
425| nearPlane | number | 否 | 否 | 近平面,取值大于0。 |
426| farPlane | number | 否 | 否 | 远平面,取值大于nearPlane。 |
427| enabled | boolean | 否 | 否 | 是否使能相机。true表示使用相机,false表示不使用相机。 |
428| postProcess | [PostProcessSettings](js-apis-inner-scene-post-process-settings.md#postprocesssettings) \| null | 否 | 否 | 后处理设置。 |
429| clearColor | [Color](js-apis-inner-scene-types.md#color) \| null | 否 | 否 | 将渲染目标(render target)清空后的特定颜色。 |
430
431### raycast<sup>20+</sup>
432raycast(viewPosition: Vec2, params: RaycastParameters): Promise<RaycastResult[]>
433
434从屏幕指定位置发射射线,检测并返回所有命中的3D物体信息。使用Promise异步回调。
435
436**系统能力:** SystemCapability.ArkUi.Graphics3D
437
438**参数:**
439| 参数名 | 类型 | 必填 | 说明 |
440| ---- | ---- | ---- | ---- |
441| viewPosition | [Vec2](js-apis-inner-scene-types.md#vec2) | 是 | 标准化设备坐标(NDC),范围[-1, 1]。(-1, -1)为屏幕左下角,(1, 1)为屏幕右上角。|
442| params | [RaycastParameters](js-apis-inner-scene.md#raycastparameters20) | 是 | 射线检测的配置参数(如检测范围、过滤节点等)。|
443
444**返回值:**
445| 类型 | 说明 |
446| ---- | ---- |
447| Promise<[RaycastResult](js-apis-inner-scene.md#raycastresult20)[]> | 返回命中的结果数组(按距离从近到远排序),若无命中则返回空数组。 |
448
449**示例:**
450```ts
451import { Image, Shader, MaterialType, Material, ShaderMaterial, Animation, Environment, Container, SceneNodeParameters,
452  LightType, Light, Camera, SceneResourceParameters, SceneResourceFactory, Scene, Node, Vec2, Vec3,
453  Quaternion } from '@kit.ArkGraphics3D';
454import { RaycastParameters } from '@ohos.graphics.scene';
455
456function Raycast(): void {
457  // 加载场景资源,支持.gltf和.glb格式,路径和文件名可根据项目实际资源自定义
458  Scene.load($rawfile("gltf/CubeWithFloor/glTF/AnimatedCube.glb"))
459    .then(async (result: Scene) => {
460      if (!result.root) {
461        return;
462      }
463      let node: Node | null | undefined = result.root.getNodeByPath("rootNode_/Unnamed Node 1/AnimatedCube");
464      let sceneFactory: SceneResourceFactory = result.getResourceFactory();
465      let sceneCameraParameter: SceneNodeParameters = { name: "camera1" };
466      // 创建相机
467      let camera: Camera = await sceneFactory.createCamera(sceneCameraParameter);
468      camera.enabled = true;
469      // 设置相机视角
470      lookAt(camera, { x: 0, y: 0, z: -3 }, { x: 0, y: 0, z: 0 }, { x: 0, y: 1, z: 0 });
471
472      let viewPos: Vec2 = { x: 0.5, y: 0.5 };
473      let raycastParams: RaycastParameters = {};
474      if (node) {
475        raycastParams.rootNode = node;
476      }
477      return camera.raycast(viewPos, raycastParams);
478    });
479}
480
481function Sub(l: Vec3, r: Vec3): Vec3 {
482  return { x: l.x - r.x, y: l.y - r.y, z: l.z - r.z };
483}
484function Dot(l: Vec3, r: Vec3): number {
485  return l.x * r.x + l.y * r.y + r.z * l.z;
486}
487function Normalize(l: Vec3): Vec3 {
488  let d = Math.sqrt(Dot(l, l));
489  return { x: l.x / d, y: l.y / d, z: l.z / d };
490}
491function Cross(l: Vec3, r: Vec3): Vec3 {
492  return { x: (l.y * r.z - l.z * r.y), y: (l.z * r.x - l.x * r.z), z: (l.x * r.y - l.y * r.x) };
493}
494function Mul(l: Quaternion, d: number): Quaternion {
495  return {
496    x: l.x * d,
497    y: l.y * d,
498    z: l.z * d,
499    w: l.w * d
500  };
501}
502function lookAt(node: Node, eye: Vec3, center: Vec3, up: Vec3) {
503
504  let t: number;
505
506  let q: Quaternion = {
507    x: 0.0,
508    y: 0.0,
509    z: 0.0,
510    w: 0.0
511  };
512  let f = Normalize(Sub(center, eye));
513  let m0 = Normalize(Cross(f, up));
514  let m1 = Cross(m0, f);
515  let m2: Vec3 = { x: -f.x, y: -f.y, z: -f.z };
516  if (m2.z < 0) {
517    if (m0.x > m1.y) {
518      t = 1.0 + m0.x - m1.y - m2.z;
519      q = {
520        x: t,
521        y: m0.y + m1.x,
522        z: m2.x + m0.z,
523        w: m1.z - m2.y
524      };
525    } else {
526      t = 1.0 - m0.x + m1.y - m2.z;
527      q = {
528        x: m0.y + m1.x,
529        y: t,
530        z: m1.z + m2.y,
531        w: m2.x - m0.z
532      };
533    }
534  } else {
535    if (m0.x < -m1.y) {
536      t = 1.0 - m0.x - m1.y + m2.z;
537      q = {
538        x: m2.x + m0.z,
539        y: m1.z + m2.y,
540        z: t,
541        w: m0.y - m1.x
542      };
543    } else {
544      t = 1.0 + m0.x + m1.y + m2.z;
545      q = {
546        x: m1.z - m2.y,
547        y: m2.x - m0.z,
548        z: m0.y - m1.x,
549        w: t
550      }
551    }
552  }
553  node.position = eye;
554  node.rotation = Mul(q, 0.5 / Math.sqrt(t));
555}
556```