全景图其实就是一张广角图,它的原理是等距圆柱投影。说白了,一个球体上的所有点都投影到一个圆柱体的侧面上,圆柱体侧面的展开图包含了球体上的所有像素点。哪里可以看全景?这种新颖的展示方式已被各行各业所应用。不仅可以达到身临其境的效果,还可以嵌入各种应用功能。比如我们熟悉的百度地图、高德地图、谷歌地图的街景模式、旅游网站的虚拟旅游模块、看房软件的全景浏览等。遇到找不到的建筑物或地方时,打开街景模式+导航引导,完美解决路痴之痛。获取全景影像素材的途径有两种:一种是使用专用的全景设备,如全景相机或带有鱼眼镜头或广角镜头的相机;另一种是用普通相机拍摄局部图像,然后通过拼接形成全景图。既然我们了解了如何获取全景素材,接下来要做的就是创建一张全景图,我们该怎么做呢?可以使用ThingJS制作全景图,还可以实现全景图与数字孪生可视化公园模型的联动和巡游功能,实现数字孪生可视化场景中第一人称行走的效果。点击地面上的图标,全景播放器中的画面会跟随数字孪生可视化场景中小人的移动路径。点击全景播放器中的热点,数字孪生可视化场景中的反派会跟随热点切换移动。1.加载全景插件,设置全景数据。2.创建全景播放器并设置初始视角。functioncreatePlayer(){THING.PanoManager.createPlayer(panoData,{fullscreen:false,//是否全屏location:"right-center",//浮框位置offsetX:0,//X-axisoffsetrelativetothelocationoffsetY:0//Y轴相对于location的偏移},{panoID:panoData.config.panos[0].panoID,//初始打开的全景h:180,//打开全景的初始视角hv:0//开启全景图的初始视角v},null,function(){createTourButton();createPoints();});//全景播放器中的全景切换事件app.on(THING.PanoEvent.PanoChange,function(event){varpanoID=event.panoID;//当前打开的全景IDvarpanoObj=app.query("[panoID="+panoID+"]")[0];//当前打开的全景IDif(isPoint&&panoObj){varpanos=app.query("[panoObj=1]");moveToNext(panoObj.position);}curPanoConfig=event.pano;如果(!carModel)返回;reComputePosition(curPanoConfig.position,carModel.position,carModel.angles);});}3。数字孪生可视化公园模型与全景图联动。数字孪生可视化公园模型创建完成后,全景图也会加载模型,移动模型全景图中的模型位置也相应变化。functioncreateModel(){//创建ThingcarModel=app.create({type:'Thing',name:'car',url:modelUrl,//模型地址position:[-25,0,30],angles:[0,90,0],//旋转完成:function(ev){ev.object.style.renderOrder=1;//添加到全景图varpano3DObjProperties=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;//设置模型DraggablecarModel.on('drag',function(ev){if(!ev.picked)return;varpickPos=ev.pickedPosition;//获取当前拾取坐标ev.object.position=pickPos;//设置模型位置reComputePosition(curPanoConfig.position.position,ev.object.position,ev.object.angles);});}4。根据全景数据在场景中创建点和路径线,控制数字孪生视觉人物模型的移动、开启、暂停巡游。functioncreateRoute(){varline=app.query("panoLine");如果(行[0])行[0].destroy();varline2=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;}/***创建人物模型*/functioncreatePersonModel(){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);}/***控制角色移动*/functionmoveToNext(p){peopleModel.playAnimation({name:'running',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});}});}/***计算模型在全景图中的位置*/functionreComputePosition(panoPosition,modelPosition,modelAngles){console.log(panoPosition);控制台日志(模型位置);varpano3DObjProperties=THING.PanoManager.compute3DObjectProperties(panoPosition,modelPosition,modelAngles);控制台日志(pano3DObjProperties);THING.PanoManager.set3DObjectProperties("pano3DObj",pano3DObjProperties);}})运行结果:
