WebGl 球面计算公式

2 篇文章 0 订阅

概要

以下所涉及到的数学模型包括:

  1. WebGl 的球体模型构建
  2. WebGl 场景交互时视角变换的方法
  3. WebGl 中 3D 空间的点在二维平面上的投影
  4. 360 度播放器的视频流的处理

以上是全景播放器以及 Slam 场景所涉及的主要内容,其中 WebGl 球体模型的构建是两个项目的基础;在鼠标拖拽时的视角变换主要涉及到 WebGl 中的矩阵变换;Slam 中 3D 空间的点在二维平面的投影涉及到的是 Slam 场景的交互,虽然在后期的交互处理中没有采用此方式处理,但这里所涉及 3D 空间的物体在二维平面的投影很有参考意义;最后一点视频流的处理并不涉及到数学知识,主要针对播放器实现视频流的播放做些介绍。

全景播放器 demo

Slam

1、WebGl 的球体模型构建

在 WebGl 的 3D 模型的构建是基于三角形的(也可以使用其他方式构建,但在复杂或者组成物体的点特别多是主要以三角形方式构建),所以如何构建一个 WebGl 球体模型这一问题就可以转化为如何用很多三角形拼成一个球体,这里我们先不考虑投影以及坐标的变换,先考虑怎么拼合这一问题。看下一下三幅图

sphere-triangles图一 sphere-latitude图二 sphere-longitude图三

其中图一就简单地展示了如何使用三角形拼凑成一个完整的球体的方法,之后就是如何实现该方法的具体实现了。

如果我们把一个球想象成类似于地球仪之类的物体,那他存在经度和维度,纵横交错的经度纬度线将一个球体的表面分割成了多个矩形(贴在球体表面的矩形),而一个矩形又可以由两个三角形拼凑起来,那么问题就简单多了,我们现在就是要计算出若干经线和若干纬线的相交的点的 3D 坐标了。那接下来我们就看看计算这些点需要哪些参量。看看下面这张图

sphere-coord图四

显然经纬度线的交点是在球面上的,就像图四的 M 点,那 M 点的 xyz 坐标是多少呢?

图五

显然很容易的可以得出这些坐标

x=rsinθcosφ

y=rsinθsinφ

z=rcosθ

由此,我们计算 xyz 需要的参量就是 R、θ、φ 了,回到图二和图三,θ、φ的值如何求得就显而易见了

θ = 180 * latitudeNum/latitudeTotalNum

φ = 360 * longitudeNum/longitudeTotalNum

以上这些基于数学的计算已经可以得出我们所需的空间点的坐标数据了,但是还不够,在 WebGl 中有两个着色器,顶点着色器和片元着色器,当我们知道了一个点的坐标时,我们可以使用顶点着色器绘制这个点,但是绘制成什么颜色呢?这就需要用到片元着色器了,我们要在片元着色器中存入点的颜色,那么颜色从何而来?在不同的场景中,我们使用不同的纹理图案(视频、图片),而作为二维的视频或者图片如何和 3D 空间中的点一一对应呢?

图六

在 WebGl 中其球体展开之后并不是像上图,而是一个矩形,其在做纹理贴片时会自动的扭曲以适应球体表面,但是原理是一样的,一张二维的图片上面横竖排列着若干相交的经纬度线,其每一个交点和空间上球体表面的经纬度交点一一对应,那么空间上点的颜色就可以一一确认了,WebGl 会在纹理贴图上做采样,采样获得的颜色将作为片元着色器的值进行渲染。

参考:

WebGl 绘制球体

WebGl 着色器介绍

WebGl 坐标系介绍

2、WebGl 场景交互时视角变换的方法

不论在全景播放器还是在 SLam 场景中,基于鼠标拖拽产生的视角变换的交互是最为基础的,在 WebGl 中观察物体时 3D 效果的体现是由投影来完成的(从这一角度来说 WebGl 中的 3D 空间只在假想中存在)

图七

图八

那么现在我们思考下观测过过程中 3D 变换的方式:

a、观察者(对应上图 Camera)不动,旋转被观察物体(对应上图的 Cup 和 立方体)

b、观察者围着物体移动,被观察物体静止不动

理论上说在适当的处理下,两种方式都可以实现对物体的360度观测,也即实现视角转变的效果,在我们的项目中我们选择的是方式b,接下来我们就要说说没有选择方式a的原因以及方式b的实现方式。

在这里就不得不说到 WebGl 里的三个矩阵了,

mMatrix(model matrix)——对应被观察物体的旋转平移;

vMatrix(view matrix)——对应观察者(camera)的观测位置;

pMatrix(perspective matrix)——对应观察者和被观测物体的投影关系; 在 WebGl 中通过改变这三个矩阵的值就可以实现空间中的点投影至二维平面,在我们看来也就实现了 3D 的效果;而方式a的实现是靠改变 mMatrix 来实现的,方式b的实现是靠改变 vMatrix 来实现的,那么这两种方式实现起来会有哪些不同呢?

简单地说,最大的不同就是mMatrix改变之后,世界坐标系的坐标轴也会跟着改变,这样一来变化你的前后顺序就很重要了,比如左后上和先上后左,就会有不一样的结果,就是因为两次改变的世界坐标系的轴改变之后后续变化的基准也产生了变化。

方式b实现起来比较简单地一点在于世界坐标系的坐标轴始终没有发生变化,改变的只是观察者的位置。既然如此就来考虑如何改变观察者的位置才会有比较好的体验。在我们拖拽的时候并不想要产生观测距离的突然变近或者突然变远,那么我们就需要将观察点和世界中心的距离维持一个恒定的值,回顾图四,当我们观察点围绕世界中心(0,0,0)旋转时,距离维持一定,那不就相当于观察点在一个距世界中心为 d 的球面上观测世界中心吗。当 d < R 时,相当于在球体模型内部观察球体内表面,当 d > R 时,相当于从球体模型外部观测球体外表面。因此每当鼠标拖拽事件发生时我们只需要改变 vMatrix 的值即可。

PS.在我们处理鼠标拖拽的时候也许会遇到一个问题,鼠标仅仅拖拽了一小段距离,视角怎么会出现大幅度的旋转?分享一个可能的情况。看下下面的代码以上代码存在问题吗?上述代码仅仅是截取的一小段可能会断章取义,说明下,触发条件是 mousemove;事实上,上述代码就会出现刚描述的情况,为什么?问题就出现在 ‘+=’ 上,逻辑上是不存在什么问题,但是在鼠标拖拽时候事件触发不止一次,连续的累加就不是想要的结果了,可以将 angleBeta log出来看看是否是想要的结果。那么消除这一问题的方式也很简单。只需要多维持一个变量就可以了。改变触发条件是 mouseup。

 

参考:

WebGl 3D Cameras

WebGl 3D 经典demo

WebGl perspective 与 lookAt 的关系

3. WebGl 中 3D 空间的点在二维平面上的投影

WebGl中 3D 坐标投影到二维平面上的这一过程实际上已经在设置mMatrix、vMatrix、pMatrix的过程中已经被悄悄地完成了,在实际 WebGl渲染中,我们是不必要做这些运算的。

那我们思考一下在我们打开百度街景或者谷歌街景(谷歌街景已经升级,现在没有小箭头)里面仿佛出现在场景中的箭头或者指示是如何实现的?在纹理贴图中不存在的箭头或者指示标志是如何出现在场景中并且仿佛悬浮在哪里呢?如果要达到这一目的,那么由空间中的点到二维平面的投影就要我们自己实现了。早一些街景地图的 api 中,这些指示是以svg的形式存在的,这样做的好处在于,每一个svg图形都以 dom 节点的形式存在于 html 文档结构中,方便我们选取以及绑定事件。

现在看下 WebGl 中一个 3D 的点是如何被投影到二维屏幕上的 webgl transform图九

webgl clip space图十

图九显示了一个完整的 3D 点投影到二维屏幕的流程,简述如下:

3D 顶点的坐标数据经平移旋转以及观察者移动后会在空间中的到相应的一个 3D 坐标(Xe,Ye,Ze);之后对世界坐标系进行整体的投影变换,由此得到一个裁剪空间(投影之外的部分在视野内是看不到的)也就是图十,所有在这个裁剪空间内的点对于视野而言都是可见的,在裁剪完成之后需要将这一坐标归一化(Xn,Yn,Zn),及将 xyz 的值都限制在 [-1,1] 的闭区间内,最后一步根据显示范围的宽高将归一化的 xy 方向的坐标进行变化渲染在显示区域(Xp,Yp,Zp),其中 z 方向所表示的深度信息在进行二维方向的投影时已不具有意义了。 各坐标间的关系如下:

Xn-Xp Xn--Xp

Yn-Yp Yn--Yp

Xn-Xc Yn-Yc

其中

n -> near distance;

r -> window right;

l -> window left;

t -> top;

b -> bottom;

关于上述关系的详细推到过程可以在参考内容中找到详细过程;

好的,到此我们已经可以将空间中的点在二维平面的投影点找到,那么接下来我们就可以根据相应点的坐标使用 svg 绘制出一些多边形,每当视角变换时这些 svg 绘制的多边形的顶点就会重新计算二维平面的投影位置,因而在交互是我们看到的 svg 指示就仿佛是存在于场景空间中一样。

参考:

OpenGL Projection Matrix

OpenGL viewport transformation matrix

OpenGl 矩阵变换

svg transform

SVG+JS path等值变化实现CSS3兴叹的图形动画

4. 360 度播放器的视频流的处理

全景播放器播放的视频流分为 HLS 视频流和 Media Source 视频流;在 Apple 平台上我们使用了 HLS 协议,之后在其他平台上会使用 Rtmp 协议。

参考:

构建简单的 MPEG-DASH 流媒体播放器

HTTP Live Streaming

PS.以上部分网站、图片请用代理打开

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值