一、概念介绍
1.产生原理
OpenGL本身没有摄像机(Camera)的概念,但我们可以通过把场景中的所有物体往相反方向移动的方式来模拟出摄像机,产生一种我们在移动的感觉,而不是场景在移动。
2.制作摄像机
1️⃣摄像机位置
正z轴是从屏幕指向你的,如果我们希望摄像机向后移动,我们就沿着z轴的正方向移动。
var camera_pos = [0,0,3]
2️⃣摄像机方向
var camera_front = [0,0,-1]
3️⃣右轴
我们需要的另一个向量是一个右向量(Right Vector),它代表摄像机空间的x轴的正方向。为获取右向量我们需要先使用一个小技巧:先定义一个上向量(Up Vector)。接下来把上向量和第二步得到的方向向量进行叉乘。两个向量叉乘的结果会同时垂直于两向量,因此我们会得到指向x轴正方向的那个向量。
var camera_up = [0,1,0]
4️⃣上轴
现在我们已经有了x轴向量和z轴向量,获取一个指向摄像机的正y轴向量就相对简单了:我们把右向量和方向向量进行叉乘
3.LookAt
可以用这个矩阵乘以任何向量来将其变换到那个坐标空间,这正是LookAt矩阵所做的。
把这个LookAt矩阵作为观察矩阵可以很高效地把所有世界坐标变换到刚刚定义的观察空间。LookAt矩阵就像它的名字表达的那样:它会创建一个看着(Look at)给定目标的观察矩阵。
我们要做的只是定义一个摄像机位置,一个目标位置和一个表示世界空间中的上向量的向量(我们计算右向量使用的那个上向量)
function matrixAdd(_a,_b){
var c = []
for(var index in _a){
c[index] = _a[index]+_b[index]
}
return c
}
var view = mat4.create()
mat4.lookAt(view, camera_pos,matrixAdd(camera_pos,camera_front),camera_up);
方向是当前的位置加上我们刚刚定义的方向向量。这样能保证无论我们怎么移动,摄像机都会注视着目标方向。
让我们摆弄一下这些向量,在按下某些按钮时更新cameraPos向量:
function matrixMulti(_a,_b){
var c = []
for(var index in _a){
c[index] = _a[index]*_b
}
return c
}
window.onload=function () {
window.onkeydown=function (e) {
var speed = 0.5
if(e.key=='w'){
camera_pos = matrixAdd(camera_pos,matrixMulti(camera_front,speed))
}else if(e.key=='s'){
camera_pos = matrixAdd(camera_pos,matrixMulti(camera_front,-speed))
}else if(e.key=='a'){
var camera_left = []
vec3.cross(camera_left,camera_front,camera_up)
vec3.normalize(camera_left,camera_left)
camera_pos = matrixAdd(camera_pos,matrixMulti(camera_left,-speed))
}