获取网格扫描信息（C/C++）
===============

本章节给出了关键开发步骤，完整代码可以参考[示例代码](https://gitcode.com/harmonyos_samples/arengine_-sample-code_-clientdemo_cpp)。

#### 约束与限制

从5.1.0(18)开始，获取网格扫描信息能力支持部分Phone、部分Tablet设备。请参考[硬件要求](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arengine-preparations#硬件要求)判断设备是否支持环境Mesh识别特性（[ARENGINE\_FEATURE\_TYPE\_MESH](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#arengine_featuretype)）。

#### 接口说明

以下接口为AR网格扫描相关接口。详细接口和说明，请参考[AR Engine API参考](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine)。

| 接口名 | 描述 |
| :-- | :-- |
| [HMS\_AREngine\_ARSession\_Create](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arsession_create) | 创建一个新的[AREngine\_ARSession](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#arengine_arsession)会话。 |
| [HMS\_AREngine\_ARSession\_Update](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arsession_update) | 更新AR Engine的计算结果。 |
| [HMS\_AREngine\_ARSession\_Configure](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arsession_configure) | 配置[AREngine\_ARSession](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#arengine_arsession)会话。 |
| [HMS\_AREngine\_ARFrame\_Create](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arframe_create) | 创建一个新的[AREngine\_ARFrame](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#arengine_arframe)对象，将指针存储到\*outFrame中。 |
| [HMS\_AREngine\_ARSession\_SetDisplayGeometry](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arsession_setdisplaygeometry) | 设置显示的高和宽（以Pixel为单位）。该高度和宽度是显示视图的高度和宽度，如果不一致，会导致显示相机预览出错。 |
| [HMS\_AREngine\_ARSession\_SetCameraGLTexture](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arsession_setcameragltexture) | 设置可用于存储相机预览流数据的openGL纹理。 |
| [HMS\_AREngine\_ARSession\_GetAllTrackables](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arsession_getalltrackables) | 获取所有指定类型的可跟踪对象集合。 |
| [HMS\_AREngine\_ARTrackableList\_AcquireItem](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_artrackablelist_acquireitem) | 从可跟踪列表中获取指定index的对象。 |
| [HMS\_AREngine\_ARPlane\_GetCenterPose](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arplane_getcenterpose) | 获取从平面的局部坐标系到世界坐标系转换的位姿信息。 |
| [HMS\_AREngine\_ARFrame\_AcquireCamera](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arframe_acquirecamera) | 获取当前帧的相机参数对象。 |
| [HMS\_AREngine\_ARPose\_Create](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arpose_create) | 分配并初始化一个新的位姿对象。 |
| [HMS\_AREngine\_ARCamera\_GetPose](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arcamera_getpose) | 获取当前相机对象在AR世界空间中的位姿。 |
| [HMS\_AREngine\_ARFrame\_AcquireSceneMesh](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arframe_acquirescenemesh) | 获取当前帧的mesh信息。 |
| [HMS\_AREngine\_ARSceneMesh\_AcquireVerticesSize](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arscenemesh_acquireverticessize) | 获取mesh的顶点个数。 |
| [HMS\_AREngine\_ARSceneMesh\_AcquireVertexList](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arscenemesh_acquirevertexlist) | 获取mesh顶点集合。 |
| [HMS\_AREngine\_ARSceneMesh\_AcquireIndexListSize](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arscenemesh_acquireindexlistsize) | 获取mesh面片的索引个数。 |
| [HMS\_AREngine\_ARSceneMesh\_AcquireIndexList](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arscenemesh_acquireindexlist) | 获取mesh面片的索引集合。 |
| [HMS\_AREngine\_ARSceneMesh\_Release](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arscenemesh_release) | 释放当前帧的mesh信息。 |

#### 开发步骤

#### \[h2\]声明Native接口

开发者可参考AR物体摆放章节的[声明Native接口](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arengine-c-arworld#声明native接口)。

#### \[h2\]创建UI界面

创建一个UI界面，使用[XComponent](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-xcomponent)组件用于显示相机预览画面，并定时触发每一帧绘制。

// 此代码可参考示例代码：ARSample/entry/src/main/ets/pages/ARMesh.ets。
import { deviceInfo } from '@kit.BasicServicesKit';
import { resourceManager } from '@kit.LocalizationKit';
import arEngineDemo from 'libentry.so';

@Builder
export function ARMeshBuilder() {
  ARMesh();
}

@Component
struct ARMesh {
  pageInfo: NavPathStack = new NavPathStack();
  private interval: number = -1;
  private xComponentId: string = 'ARMesh';
  @State context: Context = this.getUIContext().getHostContext() as Context;
  private resMgr: resourceManager.ResourceManager = this.context.resourceManager;
  @State rotation: number = deviceInfo.deviceType === 'tablet' ? 3 : 0;

  build(): void {
    NavDestination() {
      RelativeContainer() {
        XComponent({ id: this.xComponentId, type: XComponentType.SURFACE, libraryname: 'entry' })
          .width('100%')
          .height('100%')
          .alignRules({
            center: { anchor: '\_\_container\_\_', align: VerticalAlign.Center },
            middle: { anchor: '\_\_container\_\_', align: HorizontalAlign.Center }
          })
          .onLoad(() => {
            console.info(\`XComponent onLoad ${this.xComponentId}.\`);
            this.interval = setInterval(() => {
              // 调用更新Native API来更新AR Engine每帧的计算结果
              arEngineDemo.update(this.xComponentId);
            }, 33) // 将帧速率设置为30fps（每33ms刷新一次帧）
          })
          .onDestroy(() => {
            console.info(\`XComponent onDestroy ${this.xComponentId}.\`);
            clearInterval(this.interval);
          })
      }
    }
    .onAppear(() => {
      arEngineDemo.init(this.resMgr);
      let config: Int32Array = new Int32Array(\[1, this.rotation\]);
      arEngineDemo.start(this.xComponentId, config);
    })
    .onWillDisappear(() => {
      arEngineDemo.stop(this.xComponentId);
    })
    .onShown(() => {
      arEngineDemo.show(this.xComponentId);
    })
    .onHidden(() => {
      arEngineDemo.hide(this.xComponentId);
    })
    .onReady((context: NavDestinationContext) => {
      this.pageInfo = context.pathStack;
    })
    .hideTitleBar(true)
    .hideBackButton(true)
    .hideToolBar(true)
  }
}

#### \[h2\]引入AR Engine

开发者可参考AR物体摆放章节的[引入AR Engine](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arengine-c-arworld#引入ar-engine)。

#### \[h2\]创建AR会话

创建AR会话并配置为开启mesh模式。

AREngine\_ARSession \*arSession = nullptr;
// 创建AR会话。
HMS\_AREngine\_ARSession\_Create(nullptr, nullptr, &arSession);
AREngine\_ARConfig \*arConfig = nullptr;
// 创建AR会话配置器。
HMS\_AREngine\_ARConfig\_Create(arSession, &arConfig);
// 设置mesh模式为开启状态。
HMS\_AREngine\_ARConfig\_SetMeshMode(arSession, arConfig, ARENGINE\_MESH\_MODE\_ENABLED);
// 配置器设置给AR会话。
HMS\_AREngine\_ARSession\_Configure(arSession, arConfig);

#### \[h2\]获取当前环境中的mesh信息

调用[HMS\_AREngine\_ARFrame\_AcquireSceneMesh](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arframe_acquirescenemesh)函数，获取当前环境中的mesh信息，并将结果存放在sceneMesh中。

AREngine\_ARFrame \*arFrame = nullptr;
// 创建AR单帧对象
HMS\_AREngine\_ARFrame\_Create(arSession, &arFrame);
AREngine\_ARSceneMesh \*sceneMesh = nullptr;
// 获取当前帧的mesh信息
HMS\_AREngine\_ARFrame\_AcquireSceneMesh(arSession, arFrame, &sceneMesh);

#### \[h2\]获取当前mesh信息对应的mesh顶点信息

1.  调用[HMS\_AREngine\_ARSceneMesh\_AcquireVerticesSize](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arscenemesh_acquireverticessize)函数，获取mesh顶点信息包含的浮点数数量，每三个浮点数组成一个mesh顶点，将结果存放在meshVerticesSize 中。
    
    int32\_t meshVerticesSize = 0;
    // 获取mesh顶点信息包含的浮点数数量
    HMS\_AREngine\_ARSceneMesh\_AcquireVerticesSize(arSession, sceneMesh, &meshVerticesSize);
    
2.  调用[HMS\_AREngine\_ARSceneMesh\_AcquireVertexList](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arscenemesh_acquirevertexlist)函数，获取mesh顶点信息，并将结果保存在meshVertices中。
    
    float \*meshVertices = new float\[meshVerticesSize\];
    // 获取mesh顶点信息
    HMS\_AREngine\_ARSceneMesh\_AcquireVertexList(arSession, sceneMesh, meshVertices, meshVerticesSize);
    // 获取mesh顶点个数
    int32\_t mPointsNum = meshVerticesSize / 3;
    

#### \[h2\]获取当前mesh信息对应的mesh面片信息

1.  调用[HMS\_AREngine\_ARSceneMesh\_AcquireIndexListSize](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arscenemesh_acquireindexlistsize)函数，获取mesh面片信息对应顶点的索引个数，每三个顶点索引表示一个mesh面片，将结果存放在triangleIndicesSize 中。
    
    int32\_t triangleIndicesSize = 0;
    // 获取mesh面片信息对应顶点的索引个数
    HMS\_AREngine\_ARSceneMesh\_AcquireIndexListSize(arSession, sceneMesh, &triangleIndicesSize);
    
2.  调用[HMS\_AREngine\_ARSceneMesh\_AcquireIndexList](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_arscenemesh_acquireindexlist)函数，获取mesh面片信息对应顶点的索引列表，并将结果保存在meshTriangleIndices中。
    
    int32\_t \*meshTriangleIndices = new int32\_t\[triangleIndicesSize\];
    // 获取mesh面片信息对应顶点的索引列表
    HMS\_AREngine\_ARSceneMesh\_AcquireIndexList(arSession, sceneMesh, meshTriangleIndices, triangleIndicesSize);
    // 获取mesh面片个数
    int32\_t mTrianglesNum = triangleIndicesSize / 3;
    

#### \[h2\]使用完毕后，销毁mesh信息

void HMS\_AREngine\_ARSceneMesh\_Release(AREngine\_ARSceneMesh \*sceneMesh);