-
Notifications
You must be signed in to change notification settings - Fork 509
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
3D互动游戏实践 #21
Comments
我觉得应该跟着全景照片素材一起讲才更通俗易懂呀( ⊙ o ⊙ )!例如,那个车内的3d展示,看代码只有6张图片,应该相当于做了一个立方体,而我们就在立方体的正中间。是这样吧?。但却给文中的限制性欧拉角的配图给眩晕了下。。问题来了。我们的时间,空间,到底是圆的还是方的。。。? |
确实,文中并没有详细解说CSS3 立方体的构建,以及透视效果的原理说明。因为立方体仅是一个兼容性非常好的方案,WebGL采用的最真实的球体来构建的。但归根结底,他们形成虚拟现实的原理,都是基于限制性欧拉角所得出的 旋转正交矩阵的相乘 |
mark |
threejs明明是右手坐标系 |
@sapjax 多谢指明错误,three.js可以指定响应坐标系,这demo里确实使用的是右手坐标系 |
嗯,学到了 |
scale3d(sx, sy, sz)这个不是正交矩阵 |
为什么您的demo都无法在chrome device mode中进行测试呢? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
神奇的第三维度
很多技术同学都是游戏玩家,3D游戏无疑是画面最棒、投入感最真实、最让人投入的。
说起3D,前端工程师们应该都很熟悉,CSS3对3D支持非常好,除部分低端Android机器外,性能和效果都不错。今天来分享下如何基于HTML5陀螺仪,来实现3D虚拟现实效果。
移动端虚拟现实
虚拟现实大家肯定都了解。VR视觉增强的电影、游戏,市面上已经有很多了。
我们这里的VR,就是简单的用手机屏幕来当 虚拟摄像机,让你来“观察”四周,感觉仿佛置身于虚拟环境里。我们团队有两个互动应用
星辰大海:http://www.tmall.com/go/chn/common/tgp-startui.php (把活动取消的提示叉掉就行:) )
,
汽车内景: http://m.laiwang.com/market/laiwang/tmall-vr-car.php?carid=2
这是天猫互动在 “陀螺仪感应” 结合 “虚拟3D技术” 的一次尝试,事实证明在某些特定商品(比如汽车)上效果非常好。
如果你看完Demo很感兴趣,那接下来让我一步一步分解这里面涉及到的所有内容。
矩阵
计算机3D图形和矩阵密切相关,图形API接口也都直接使用矩阵,下面简单列举下矩阵一些简单概念
CSS3 transform
Transform2d/3d 封装了最基本的变换操作。每个变换都可以转化为矩阵。我们只说虚拟现实涉及的几个3D变换
rotateX()
rotateY()
rotateZ()
scale3d(sx, sy, sz)
以上都是正交矩阵,简单说就是坐标系原点不变。
translate3d 使坐标原点变换,因此使用"仿射矩阵"来描述
rotate3d(x, y, z, a) 这个比较特殊,描述的不是矩阵,而是"四元数"
详细信息可查看https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function
以汽车内景Demo为例,旋转+透视点距离,使用了rotate+translateZ,手指缩放使用了scale3d。
矩阵不满足乘法交互率
多个矩阵变换叠加起来,就是是矩阵相乘。一个很重要的概念:矩阵不满足乘法交互率!这就意味着变换顺序的不同,直接导致最终结果千差万别。
通俗的讲就是:每一次变换都是相对上一次变换来做的,参考的坐标系时刻都在变化,无论2D、3D里都一样;
所以:translateZ() rotateX() rotateY() 和 rotateY() rotateX() translateZ() 得出的结果完全相反。
下一步我们要做的就是:如何将手机陀螺仪的数据正确反映出来!
陀螺仪
欧拉角
说陀螺仪之前,一定要先说这个概念 欧拉角。 欧拉角广泛应用于 航空航天领域,当然还有我们最熟悉的 手机陀螺仪方位感应器 deviceorientaiton
欧拉角描述3D空间里的方位,陀螺仪监听接口返回 alpha、beta、gamma 就是标准欧拉角方位。(这是手机端,欧拉角官方名称是 heading,pitch、bank)
两个不同的旋转顺序:(heading:45,bank:90) 和(bank:90,pitch:45)在效果是一致的,一个刚体的方位,可以表示成欧拉角多种不同的旋转顺序。也因为欧拉角的不唯一性,会产生“万向锁”的问题。
限制性欧拉角
为了保证唯一性,就有了“限制性欧拉角”这个概念。任何一个方位的描述,是按 alpha, beta, gamma 顺序旋转来得出的方位角度的。可以看成三个旋转正交矩阵,顺序相乘得出变换后的坐标,看下面的动态图,来帮助理解
先绕蓝色Z轴旋转,得出alpha,然后绕绿色轴旋转,得出beta,最后绕红色轴旋转,得出gamma;
最后这张示意图一目了然:
限制性欧拉角有一些特性:
欧拉角可参考这本书:3D数学基础:图形与游戏开发 第十章
代码实现:
前面全是介绍概念,接下来才是正题。相信我,真正的代码远没有你想象中复杂。
现在我们已知了限制性欧拉角三个方位:alpha、beta、gamma,接下来的工作就是转换成矩阵,提供给你所使用的图像API。
我们使用 CSS3 rotate3d,来操作一个已建模的正立方体,关于如何使用DIV+ Perspective3d 来构建一个3D立方体,又是另外一个话题了,但其实也很简单。大家可以看上面汽车Demo的样式。相关内容会在下期“伪3D”专题中说明
alpha、beta、gamma 一一对应 rotateZ()、rotateX()、rotateY(),相对于我们的Z轴向上的世界坐标系而言。
所以欧拉角方位最终的矩阵变换公式是:
使用CSS3就意味着不用关心矩阵,除非你想用 matrix3d()。但矩阵相乘是顺序相关的,所以你必须关注每个变换的顺序。代码超简单就是这样.....
最终的效果应该是,你所看的立方体相对于环境,位置是不变的。
发现不对?呵呵,没错,因为陀螺仪返回的是手机相对于世界坐标系的方位。
相对屏幕坐标系的逆矩阵
何为虚拟现实,就是你在屏幕中看到的物体,相对于环境是不动的,只是你的摄像机角度变了而已。而图形API所做的变换,都是相对手机屏幕的。下面是一段比较绕的逻辑:
陀螺仪的矩阵变换最终是 ZXY 相乘。这是相对世界坐标系,你的手机屏幕按照这个矩阵变换到现在的方位,但是屏幕中的物体,被施加的矩阵变换是相对屏幕坐标系的,为了让它相对于世界坐标系保持不变。所以最终图形API所需要的矩阵变换,是ZXY相反的方向,也就是它的逆矩阵!
ZXY将顺序颠倒相乘,YXZ 就能得到相应的逆矩阵。所以!我们最终的代码应该是:
大功告成!
基于两轴的变换
Android同学可能发现上面的汽车Demo,只能用滑屏操作,因为大部分Android机器的陀螺仪非常不稳定+不精确,抱歉了!
手指滑动逻辑也很简单,因为只改变了两个轴的旋转,代码如下:
注意这里的变换顺序也是不能改的,不然直接影响到你的交互。然后给X轴角度做个+-90°的取值范围就能防止颠倒效果。
切换不同的图形API
如果你不使用CSS3,那这些矩阵计算都得自己代码实现。我们完全可以使用webGL来渲染整个立方体,除了图形API不同,webGL所需要的变换矩阵完全一致;
WebGL是不二的选择,而且可以构建更加复杂的球体来渲染全景,这时候素材就需要一张全景图片。不使用框架的话,会有点复杂,我们采用Three.js来构建我们的webGL版本
上代码:
http://g.alicdn.com/tmapp/vr-car/1.1.1/demo/webgl.html
陀螺仪的其他应用
总结
以上就是基于手机陀螺仪的虚拟现实原理。我数学功底不扎实,很多描述不是很详细,如果你还是不太理解,欢迎随时来讨论。
前端工程师作为一个产品中人机交互的第一道门槛,创造性的交互方式、富有画面感的效果,能起对产品起到很积极的作用。个人认为掌握前沿的图形显示技术,对产品体验、技能提升都有很大帮助的。
The text was updated successfully, but these errors were encountered: