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```