Web全景图的原理及实现

全景图的基本原理

全景图是一种广角图。通过全景播放器可以让观看者身临其境地进入到全景图所记录的场景中去。比如像是这个。这种看起来很高大上的效果其实背后的原理并不复杂。

通常标准的全景图是一张2:1的图像,其背后的实质就是等距圆柱投影。等距圆柱投影是一种将球体上的各个点投影到圆柱体的侧面上的一种投影方式,投影完之后再将它展开就是一张2:1的长方形的图像。比较常见的就是应用在地图上的投影。

Web全景图的原理及实现

而在对全景图进行展示之前就需要得到一张这样的图像,这种图像可以自己用普通相机拍摄再自己合成,也可以直接使用专门的全景相机进行拍摄。全景照片的拍摄在网上有比较多的教程,由于这不是摄影分享就不详细的去说了:P。

在得到了全景图之后,就是要怎么去展示的问题了。接下来就要说说全景展示的原理。全景展示其实是等距圆柱投影的逆过程,我们要做的就是将我们得到的全景图,贴图到一个球体上,熟悉webgl的,可以用它画一个球体,然后将全景图作为材质贴到这个球体上进行渲染。由于使用webgl来进行编程的话,需要自己进行比较多的3d运算,所以也可以选择使用api更加友好的3D库,如THREE.JS来编程。比如下面的这张全景图,在球面上进行贴图。

Web全景图的原理及实现
Web全景图的原理及实现

这时我们看到的还跟预想的全景不一样,那是因为我们在球的外面,当我们在球的里面时,看到的就是跟一开始的示例一样的效果了。像是下面的这个示意图这样。

Web全景图的原理及实现

用threejs进行编程的话,关键的代码如下:

//新建一个球体var geometry = new THREE.SphereGeometry( 500, 60, 40 );//沿x轴进行-1的scale,让球体的面朝内(因为我们将从球内进行观看)。geometry.scale( - 1, 1, 1 );//载入一张全景图生成threejs中可以使用的材质var material = new THREE.MeshBasicMaterial( {    map: new THREE.TextureLoader().load( 'panoPic.jpg' )} );//将几何体和材质进行结合。mesh = new THREE.Mesh( geometry, material );

兼容性

虽然使用webgl可以很容易的就生成一个全景的场景,但是在web里,兼容性似乎是个挥之不去的话题。主要是由于webgl不支持Android5.0以下的机器,所以,用webgl来实现将会将很多用户排除在外。所以只能寻求更好的解决方案。首先想到的就是css 3D transform 和 2D canvas画布。在threejs里支持在2D的canvas里进行绘制,本是一个比较好的方案,但是经过测试之后,发现2d画布来绘制3d的场景,性能上太吃力。所以,也被排除。剩下的就是css变换了。但是,要怎么用css来画一个一个球体呢?答案显然是不行的。虽然css不能绘制一个球体,但是css通过3D变换来绘制立方体还是简单一些的。那么用立方体可不可以实现一样的效果呢?

球体到立方体

根据全景图的原理,我们是把视角放在球的中心,通过从球心观看球面上正式场景在球面上的映像从而产生一种空间中全方位的视觉体验,同理,对于立方体,应该也可以使用相同的方式来实现。而我们要做,就是把球面上的像素点映射到立方体上。

Web全景图的原理及实现

说了基本的原理,接下来就是进行数学建模了。首先我们建立一个球坐标系,坐标系描述的变量分别为半径r,竖直方向上的夹角θ,水平方向上的夹角ø,对于球体,我们可以假定

r=10 < θ < π -π/4 < ø < 7π/4

这样我们就可以得到球面上的各个点在直角坐标系中的x,y,z

x= r sin θ cos øy= r sin θ sin øz= r cos θ

对于球面到立方体上的投影,我们需要的是角度θ和ø相同时,延长球的半径r直到和立方体的面相交,假设这个长度是R,由于我们设了半径r是1所以球面上的点为 (sin θ cos ø, sin θ sin ø, cos θ) 对应的立方体上的点是(Rsin θ cos ø, Rsin θ sin ø, Rcos θ)

如果我们要求x=1这个平面上的点,则

1=Rsin θ cos ø

则可以求出来

R= 1/(sin θ cos ø)

所以在x平面上映射的点就是

(1, tan ø, cot θ / cos ø)

在立方体另外的五个平面上的投影也可以类似地得出。通过上述方法转换一张全景图,可以得到以下结果。

Web全景图的原理及实现

离我们想要的效果还有一些差距,图中似乎多了一些黑色的线。导致这种现象的原因是,由于我们的处理是以像素为单位来进行处理的,通过遍历球面图上的每个像素然后投影到立方体上的面来实现。经过这种方式进行投射之后,立方体的面上就会有一些像素被重复设置,而一些地方的像素就会缺失,比如图中的黑色部分(由于底色的黑色的)。为了解决这个问题,我们可以通过逆向的方法来解决,也就是遍历立方体上面上的每个点,求得映射到球面上的位置,然后获取球面上最接近的位置的像素。
Web全景图的原理及实现
得到了立方体上需要的图之后,就可以用css 3D变换来实现全景图了。

展示更多信息

单单地进行全景观看可能还不能满足我们的需求,也许我们还需要展示更多的信息,而这些信息可能是跟全景中的内容相关的,比如给全景中的物品打标,给全景中的内容添加评论,像是下图这样
Web全景图的原理及实现
对于这个实现的关键在于,屏幕2D坐标和空间3D坐标之间的相互转换。第一步需要实现的是记录,当用户点击屏幕,要根据点击的位置来计算出和空间中的立方体相交的点并记下这个点的位置信息。一些3d库当中会有一些api来帮助完成这项工作。而在THREEJS中使用的是Raycaster,Raycaster可以生成一条直线,然后可以很方便地得到三维空间中,和这条直线相交的物体和点。由于THREEJS中是以绘制的中心作为原点,而鼠标的点击位置是以左上角为原点,所以需要进行一下转换。

//将鼠标点击事件中的位置信息,转换到位置中心  var mouse = new THREE.Vector2(    ( ev.clientX / _this.wrapper.width() ) * 2 - 1,    -( ev.clientY / _this.wrapper.height() ) * 2 + 1  )

然后就可以初始化一个Raycaster获得需要的内容了

//创建一个Raycaster实例  var raycaster = new THREE.Raycaster()//根据点击的位置,从镜头开始初始化一和镜头的屏幕垂直的直线  raycaster.setFromCamera(mouse, _this.camera)//获得和直线相交的物体  var intersects = raycaster.intersectObjects(_this.scene.children)

这样就在空间中记录下了一个目标位置。

有了三维中的位置之后,如果我们想要展示这个位置相关信息,比如打一个标签,就是需要将空间中的位置还原到屏幕的二维坐标上,然后用传统的css方法来进行展示就可以了。

//根据上一步中记录的位置生成一个向量var vector  = new THREE.Vector3(pos.x, pos.y, pos.z)//将这个向量映射到镜头的平面上vector.project(camera)//将位置信息还原成以左上角为原点的位置信息var screenPos = {  left: Math.round((   vector.x + 1 ) * wrapper.width() / 2),  top: Math.round(( -vector.y + 1 ) * wrapper.height() / 2)

本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请添加站长微信举报,一经查实,本站将立刻删除。

如若转载,请注明出处:http://www.ibjoo.com/298.html

(0)
上一篇 2020年5月5日 下午3:44
下一篇 2020年5月5日 下午3:46

相关推荐

  • krpano HTML5全景漫游

    目前有个插件叫krpano HTML5 Viewer可以实现全景展示,官网都是英文,而且网上资料也比较少些,需要看看官网实例、文档。 下载地址:http://www.krpano.com/ 引用一下别人的博客:http://my.oschina.net/u/591525/blog/158572 Krpano功能介绍Krpano viewer的主程序所使用的X…

    VR全景教程 2020年5月5日
    9700
  • 720度全景怎么制作?

      720度全景实际上就是360全景,就是上下2个360度,其实还是360全景的制作。  360度全景图的制作流程:  全景拍摄硬件:  单反相机 鱼眼镜头 全景云台 三脚架  鱼眼镜头的选择: 根据单反相机的型号来判断适合多少mm的鱼眼镜头。(硬件配置参数表)  拍摄的顺序: 前—右—后—左—上—下 例如: 我使用单反相机尼康D7000配上尼康10.5mm…

    VR全景教程 2020年5月5日
    11100
  • 使用three.js开发全景漫游 制作单张球形全景

    简介一般网页中使用的全景图为两种,一种是由六张正方形图片组成的,另一种就是一整张的宽高比为2比1的全景图片。前面,第一节的案例就是一个六张正方形。今天我就实现一整张的案例文件引入。 实现思路一张全景图都是这样的 这是一张three.js官方的全景图片。我们通过这张全景图实现全景查看。首先我们需要一个球体的网格 var geometry = new THREE…

    VR全景教程 2020年5月5日
    15700
  • 盘点丨最流行最好用的720vr全景接片/制作软件

    相信看过720°VR全景的朋友都会印象深刻,“吃鸡”既视感,720°无死角全方位展示,除了震撼,还有新奇感。而对于做过720°VR全景的朋友来说,想要做出视觉效果非常好,还是有难度的,因为除了摄影技术够硬,还要用到不少全景接片/制作软件。那么,最流行最好用的720°vr全景接片/制作软件有哪些?下面给大家做个简单盘点。 1、PTGui 首先要说的就是PTGu…

    2020年4月23日
    16600
  • 技术分享:全景视频技术的实现

    全景视频技术的实现      全景视频在VR领域是一个非常热门的领域,它是在720度或者360度全景的技术之上发展延伸而来。它将静态的全景图片转化为动态的视频图像,全景视频可以在拍摄角度左右上下360度的任意观看动态视频,让我们有一种真正意义上身临其境的感觉,而它将不受时间、空间和地域的限制。全景视…

    VR全景教程 2020年5月5日
    13000

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

工具推荐
公众号
公众号
分享本页
返回顶部
特别提示:欢迎收藏&使用市场工具导航,如您有任何建议或好用工具推荐,请留言告知我们。谢谢~