admin 管理员组文章数量: 1087678
WebGL实践篇(七)三维相机及视图矩阵
一般来说,物体的位置是固定不动的,而我们的日常做法是将移动相机到合适的位置去拍摄这个物体(总不能把风景吸星大法过来,对它说自己过来站好拍照)。但是,在咱们这个三维空间里是有视锥体的范围,你随便移动相机那就可能要重新调节视锥体的参数,这样反而会更麻烦。因此一般来说在三维空间当中,相机应该是相对不变的。根据相机的位置再去对物体做一系列的变换。
1.相机矩阵:
var radius = 200;var cameraMatrix = m4.yRotation(cameraAngleRadians);cameraMatrix = m4.translate(cameraMatrix, 0, 0, radius * 1.5);
这个矩阵计算出来的相机的位置是图中这样的,相机看向原点,在半径为radius * 1.5的圆上移动
2.视图矩阵
通过视图矩阵,我们可以移动视角观察到每一个“F”,那么如何计算视图矩阵呢?它是利用相机矩阵的逆变换来进行计算的。这个计算就是相当于吸星大法,让物体移动到相机面前(保持相机的不变性)。
在利用相机矩阵计算完视图矩阵之后,再与投影矩阵相结合:
//计算视图矩阵var viewMatrix = m4.inverse(cameraMatrix);//计算视图投影矩阵var viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix);
我们要绘制五个围成一圈丢手绢的“F",需要将每个F乘以视图矩阵之后再做旋转跟平移,做旋转跟平移主要是为了让它们能围城小圈圈。视图矩阵将控制物体的移动距离(即距相机的远近)
for (var i = 0; i < numFs; i++) {var angle = i * Math.PI * 2 / numFs;var x = Math.cos(angle) * radius;var y = Math.sin(angle) * radius;var matrix = m4.translate(viewProjectionMatrix, x, 0, y);webgl.uniformMatrix4fv(matrixUniformLocation, false, matrix);webgl.drawArrays(webgl.TRIANGLES, 0, 16 * 6);}
OK,让我们看看结果吧。
为啥子我的F倒了!这不是我想要的结果!让我们来继续修正修正(具体为什么还是得去扒扒原理哈,大概就是三维的Y的正方向向上,之前的二维Y的正方向是向下的)我们要对F做个以X为旋转轴的旋转操作,把它们正过来。
接下来的操作需要在setGeometry()这个函数里面进行操作:
var matrix = m4.xRotation(Math.PI);matrix = m4.translate(matrix, -50, -75, -115);for (var i = 0; i < positions.length; i += 3) {var vector = m4.vectorMultiply([positions[i + 0], positions[i + 1], positions[i + 2], 1], matrix);positions[i + 0] = vector[0];positions[i + 1] = vector[1];positions[i + 2] = vector[2];}gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW)
结果如下:
3.相机矩阵的优化
这个优化相当于实在做一个视线跟随吧(锁定目标)。
(1)定义相机的位置和朝向
假设相机的位置为cameraPosition,物体的位置(即目标位置)为target,相机的朝向zAxis就是cameraPosition - target(注意相机注视的是Z的负方向),然后进行单位化。
(2)确定物体的姿态
我们知道正上方的单位矢量是(0,1,0),其与zAxis的叉乘则能得到xAxis,再根据zAxis与xAxis的叉乘我们则能得到yAxis
(3)得到最终的矩阵(xAxis,yAxis,zAxis,cameraPosition)
(4)lookAt的视图矩阵
lookAt: function (cameraPosition, target, up) {var zAxis = normalize(subtractVectors(cameraPosition, target));var xAxis = normalize(cross(up, zAxis));var yAxis = normalize(cross(zAxis, xAxis));return [xAxis[0], xAxis[1], xAxis[2], 0,yAxis[0], yAxis[1], yAxis[2], 0,zAxis[0], zAxis[1], zAxis[2], 0,cameraPosition[0], cameraPosition[1], cameraPosition[2], 1]},
(5)优化之后的矩阵参数设置
//计算第一个f的位置var fPosition = [radius, 0, 0];var cameraMatrix = m4.yRotation(cameraAngleRadians);cameraMatrix = m4.translate(cameraMatrix, 0, 0, radius * 1.5);var cameraPosition = [cameraMatrix[12], cameraMatrix[13], cameraMatrix[14]];var up = [0, 1, 0];var cameraMatrixLook = m4.lookAt(cameraPosition, fPosition, up);var viewMatrix = m4.inverse(cameraMatrixLook);var viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix);
(6)优化后的结果与上边的那个有点不同,这个移动滑块之后就有那种追踪单个“F”的效果了。
4.lookAt的用处
比如小时候玩的那种坦克游戏,坦克上面的那个瞄准的就可以用lookAt来做,你会发现通过上下左右的方向键能改变它的朝向从而瞄准你的目标。
然后lookAt也有一些外部库封装函数,可以根据参数直接调用使用,以及一些矩阵可能看起来长得有些不一样,但其实内部原理是一样的,具体可以看看这两篇博文(也是我现找的hhh),选择自己能理解的方式去理解就好啦。
(26条消息) WebGL之旅(九)视图矩阵_丿寒风的博客-CSDN博客(里面包括了模型矩阵、投影矩阵以及视图矩阵):
webgl笔记-1.模型视图矩阵和投影矩阵 - 一叶斋主人 - 博客园 (cnblogs).html
本文标签: WebGL实践篇(七)三维相机及视图矩阵
版权声明:本文标题:WebGL实践篇(七)三维相机及视图矩阵 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/p/1700372195a418317.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论