园区模型与全景图联动开启第一人称巡游

全景图 实际上是一种广角图,它的原理是等距圆柱投影。说白了就是将一个球体上的全部的点,所有投影到一个圆柱体的侧面上去,圆柱侧面展开图上包含了球体上全部的像素点。
哪里能看到全景图? 这种新颖的展示方式现在已经被各行各业所应用。不只可以实现身临其境的效果,更能嵌入各类应用功能。
例如咱们熟知的百度地图、高德地图、谷歌地图的街景模式,旅游网站的虚拟旅行模块,看房软件的全景图浏览等。遇到找不到的建筑或者地方,打开街景模式+导航指引,能够完美解决路痴的痛苦。
watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=
全景图像素材的获取有两种方式:一是采用专门全景设备,如全景相机或者带有鱼眼镜头或者广角镜头的相机;二是利用普通相机拍摄局部图像,而后通过拼接造成全景图。
如今明白了全景图素材的获取方式,那么咱们要作的就是建立全景图,怎么办?能够利用 ThingJS 建立全景图,还能够实现全景图与数字孪生可视化园区模型联动、巡游功能,实现第一人称在数字孪生可视化场景中行走的效果。
watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=
点击地面上的图标,全景图播放器中的图片跟随数字孪生可视化场景中小人的运动路径改变。点击全景图播放器中的热点,数字孪生可视化场景中小人跟随热点切换运动。
watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=
1.加载全景图插件,设置全景图数据。
2.建立全景图播放器,设置初始视角。
function createPlayer() {
        THING.PanoManager.createPlayer(panoData, {
            fullscreen: false, // 是否全屏
            location: "right-center", // 悬浮框所在位置
            offsetX: 0, // 相对于location的X轴偏移
            offsetY: 0 // 相对于location的Y轴偏移
        }, {
            panoID: panoData.config.panos[0].panoID, // 初始打开的全景图
            h: 180, // 打开全景图的初始视角h
            v: 0 // 打开全景图的初始视角v
        }, null, function() {
            createTourButton();
            createPoints();
        });

        // 全景图播放器中全景图切换事件
        app.on(THING.PanoEvent.PanoChange, function(event) {
            var panoID = event.panoID; // 当前打开的全景图ID
            var panoObj = app.query("[panoID=" + panoID + "]")[0]; // 当前打开的全景图ID
            if (isPoint && panoObj) {
                var panos = app.query("[panoObj=1]");
                moveToNext(panoObj.position);
            }

            curPanoConfig = event.pano;

            if (!carModel) return;
            reComputePosition(curPanoConfig.position, carModel.position, carModel.angles);
        });
    }
3.数字孪生可视化园区模型与全景图联动,数字孪生可视化园区建立模型后全景图也会加载模型,移动模型全景图内的模型位置也对应改变。
function createModel() {
        // 建立Thing
        carModel = app.create({
            type: 'Thing',
            name: 'car',
            url: modelUrl, // 模型地址
            position: [-25, 0, 30],
            angles: [0, 90, 0], // 旋转
            complete: function(ev) {
                ev.object.style.renderOrder = 1;
                // 添加到全景图中
                var pano3DObjProperties =
                    THING.PanoManager.compute3DObjectProperties(panoData.config.panos[0].position.position, ev.object.position, ev.object.angles);
                THING.PanoManager.create3DObject("pano3DObj", modelUrl, false, pano3DObjProperties);
            }
        });
        carModel.draggable = true; // 设置模型可拖拽
        carModel.on('drag', function(ev) {
            if (!ev.picked) return;

            var pickPos = ev.pickedPosition; // 获取当前拾取坐标
            ev.object.position = pickPos; // 设置模型位置
            reComputePosition(curPanoConfig.position.position, ev.object.position, ev.object.angles);
        });
    }
4.根据全景图数据在场景中建立点和路径线,控制数字孪生可视化人物模型移动,开启、暂停巡游。
function createRoute() {
        var line = app.query("panoLine");
        if (line[0]) line[0].destroy();
        var line2 = app.create({
            type: 'RouteLine',
            name: "panoLine",
            points: points,
            image: 'https://www.thingjs.com/static/images/line01.png' // 线路中的纹理资源
        });
        // 启用 UV 动画
        line2.scrollUV = true;
        line2.style.renderOrder = 9;
    }

    /**
     * 建立人物模型
     */
    function createPersonModel() {
        peopleModel = app.create({
            type: 'Thing',
            url: 'https://model.3dmomoda.cn/models/0bcba8ca78734b64a3dae3eb699a913c/0/gltf/',
            position: [-10.4, 0, 27.9],
            complete: function() {
                peopleModel.playAnimation({ name: '_defaultAnim_', loop: true });
            }
        });
        peopleModel.rotateY(-90.0);
    }

    /**
     * 控制人物移动
     */
    function moveToNext(p) {
        peopleModel.playAnimation({ name: '跑步', loop: true });
        peopleModel.style.opacity = 1.0;
        peopleModel.style.outlineColor = "#FF0000";
        peopleModel.moveTo({
            "position": p,
            "time": 1500,
            "orientToPath": true,
            "lerp": false,
            "complete": function() {
                peopleModel.playAnimation({ name: '_defaultAnim_', loop: true });
            }
        });
    }

    /**
     * 计算全景图中模型位置
     */
    function reComputePosition(panoPosition, modelPosition, modelAngles) {
        console.log(panoPosition);
        console.log(modelPosition);
        var pano3DObjProperties = THING.PanoManager.compute3DObjectProperties(panoPosition, modelPosition, modelAngles);
        console.log(pano3DObjProperties);
        THING.PanoManager.set3DObjectProperties("pano3DObj", pano3DObjProperties);
    }
})
运行结果:
watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=
相关文章
相关标签/搜索