更新时间:2023-04-26 GMT+08:00
分享

开发指导

开发流程

图1 AR导航启动流程

开发过程

  1. 开启AR会话
  2. 选定终点位置。

    通过POI智能搜索(hwar.searchPoi)选定终点坐标。
    // POI智能搜索
    hwar.searchPoi({
        "floor": "1F",
        "address": "xxx",
        "title": "xxx",
        "pageNum": 0,
        "pageSize": 50
    }).then((res) => {
        // POI信息列表,包含POI的UTM坐标等信息
    });

  3. 进行视觉定位。

    通过设置AR会话状态(hwar.setARStatus)或者触发手动定位(hwar.requestVps)发送定位请求,定位成功结果通过回调函数返回。
    // 触发手动定位请求
    hwar.requestVps();
    
    // 设置定位成功回调函数
    hwar.registerGetNewVpsPose((dictPoseData, vpsOffset) => {    
        // 可计算与上次定位的差值、与终点的距离。当有3D内容时可重置世界坐标原点重新渲染内容
    });

  4. 获取导航路径。

    传入起始点与终点的UTM坐标请求导航(hwar.requestNavi),获取该段路程的路径点。
    // 请求导航路径
    hwar.requestNavi("xxx", 
        [xxx, xxx, xxx], 
        [xxx, xxx, xxx], 
        1
    ).then((res) => {
        // 获取导航路径点信息
    }).catch((err) => {
        // 获取失败
    })
    
    // 路径点结构:其中xyz是UTM坐标,渲染路径时需要转换成渲染坐标(TS语言)
    export interface INaviPoint {
        linkID: number;
        x: number;
        y: number;
        z: number;
        floor: string;
        building: string;
        status: number;
    }

  5. 获取相机矩阵和视频流图像,完成空间位置追踪与渲染。

    通过回调函数“hwar.registerRefreshCameraMat”获取相机矩阵和视频流图像。当3定位成功后输出相机矩阵,包含当前虚拟相机的位姿信息。视频流图像可通过Three.js、LayaAir等WebGL渲染引擎渲染成背景画面。

    • 您可以根据相机矩阵、视频流图像及路径点,自定义渲染导航路径、虚拟数字内容。
    • 自定义渲染导航路径时,建议您分段处理路径,及时移除失效路径点。渲染的每帧仅计算当前相机的位置和距离相机最近的点,且仅渲染当前路段。
    // 设置接收相机矩阵的回调函数
    hwar.registerRefreshCameraMat((cameraMat, imgData) => {
        if (cameraMat) {
            //VPS定位成功,输出相机矩阵
            console.log(`相机矩阵:${cameraMat}`);
        }
        // 图像预览流默认宽:高=480:640,不同尺寸屏幕请自行适配
        console.log(`接收到视频流图像:${imgData}`);
    });
    
    //Three.js r144版本 相机渲染代码示例(TS语言)
    //图像作为3D场景的背景,渲染器的设置如下:
    this.renderer = new THREE.WebGLRenderer({ alpha: true, preserveDrawingBuffer: true, antialias: true });
    this.renderer.autoClearColor = true;
    this.renderer.sortObjects = false;
    this.renderer.setPixelRatio(window.devicePixelRatio);
    this.renderer.setSize(window.innerWidth, window.innerHeight);
    this.renderer.localClippingEnabled = true;
    this.renderer.autoClear = false;
    this.renderer.debug.checkShaderErrors = false;
    document.body.appendChild(this.renderer.domElement);
    
    public updateARCameraMatrix(cameraMat: THREE.Matrix4, imgData: ImageData): void {
        if (cameraMat) {
            this.camera.matrix.fromArray(cameraMat.toArray());
            this.camera.updateMatrixWorld(true);
        }
        if (imgData) {
            let buffer: Uint8Array = new Uint8Array(imgData.data.buffer);
            let tex: DataTexture = new DataTexture(buffer, 
                imgData.width, 
                imgData.height, 
                THREE.RGBAFormat
            );
            tex.needsUpdate = true;
            tex.matrixAutoUpdate = false;
            tex.magFilter = THREE.LinearFilter;
            tex.flipY = true;
            tex.encoding = THREE.sRGBEncoding;
            this.scene.background = tex;
        }
    }
    
    //LayaAir 2.12版本 相机渲染代码示例(TS语言)
    //图像作为舞台的背景,将video: Laya.Sprite添加到舞台,添加3D场景,并将场景相机设置如下:
    Laya.stage.addChild(this.video);
    this.mainScene.mouseThrough = false;
    this.mainCamera = this.mainScene.getChildByName("Main Camera") as Laya.Camera;
    this.mainCamera.enableHDR = false;
    this.mainCamera.clearColor = new Laya.Vector4(0, 0, 0, 255);
    this.mainCamera.clearFlag = Laya.CameraClearFlags.DepthOnly;
    this.mainCamera.fieldOfView = 66;
    this.mainCamera.depthTextureMode = Laya.DepthTextureMode.None;
    Laya.stage.addChild(this.mainScene);
    
    public updateARCameraMatrix(cameraMat: { elements: Float32Array, isMatrix4: boolean }, imgData: ImageData): void {
        if (cameraMat) {
            let mat: Laya.Matrix4x4 = new Laya.Matrix4x4();
            mat.elements = cameraMat.elements;
            this.mainCamera.transform.worldMatrix = mat;
        }
        if (imgData) {
             if (this.stageHeight !== Laya.stage.height) {
                 // 请自行对渲染尺寸(宽:高=480:640)做屏幕适配
                 this.onResize();
             }
             if (this.videoTexture && this.videoTexture.bitmap) {
                 this.videoTexture.disposeBitmap();
                 this.videoTexture2D.destroy();
                 this.videoTexture = null;
                 this.videoTexture2D = null;
              }
              let buffer: Uint8Array = new Uint8Array(imgData.data.buffer);
              this.videoTexture2D = new Laya.Texture2D(imgData.width, imgData.height);
              this.videoTexture2D.setPixels(buffer);
              this.videoTexture = Laya.Texture.create(this.videoTexture2D, 0, 0, imgData.width, imgData.height);
              this.video.texture = this.videoTexture;
        }
    }

分享:

    相关文档

    相关产品