约定
如何定位相机
定位摄像机需要3个向量
- 相机位置 pos
- 观察位置 target
- 相机上向量 up

定义FPS相机
Position、Target、Up、Pitch、Yaw
因为不需要翻滚,所以这里没有定义Roll
如何移动相机
1
| vec3 Front=Target-Position;
|
相机前进和后退:
1 2
| Position += Front; Position -= Front;
|
相机左右移动:
1 2 3
| vec Right = cross(Front,v3c(0,1,0)); Position += Right; Position -= Right;
|
如何旋转相机

1 2 3 4 5 6
| front.y = sin(pitch); front.x = cos(pitch) * cos(yaw); front.z = cos(pitch) * sin(yaw); Front=normalize(front)
mat4 view = lookat(Position,Position+Front,Up);
|
推导LookAt
首先,明确两个matrix
- camera transform matrix将camera当做世界中的一个物体来看,用于定位相机位置和朝向;记为 Mtm
- view matrix,用于将world space转换到view space,记为 Mview
其中:
Mtm=MT * MR
相机作为世界中的一个物体,在确认位置和朝向时;操作的顺序是先旋转再平移;因为我们使用的列向量,所以上述记法MR在右侧。也就是说,从右到左进行计算。
下图(px,py,pz)表示相机位置,r1-r9表示3x3的旋转矩阵。

Mview=Mtm-1=MR-1 * MT-1=MRT * MT-1
因为旋转矩阵是正交矩阵,正交矩阵的逆等于其转置,因此
Mview=MRT * MT-1


下面我们计算right、up、forward三个向量。
1 2 3 4 5
| vec3 worldup=(0.f,1.f,0.f);
vec3 forward = normalize(pos-target); vec3 right = normalize(cross(worldup,forward)); vec3 up = normalize(cross(forward,right));
|
由上我们求得了3个正交基向量,代入上面的公式,可得到view matrix
1 2 3 4
| | right.x right.y right.z -dot(right,pos) | | up.x up.y up.z -dot(up,pos) | | forward.x forward.y forward.z -dot(forward,pos) | | 0 0 0 1 |
|
实现LookAtRH
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| mat4 LookAtRH(vec3 position,vec3 target,vec3 wolrdup) { vec3 forward = normalize(position-target); vec3 right = normalize(cross(nomalize(worldup),forward)); vec3 up = normalize(forward,right); mat4 view(1.0f); view[0][0] = right.x; view[1][0] = right.y; view[2][0] = right.z; view[3][0] = -dot(right, position); view[0][1] = up.x; view[1][1] = up.y; view[2][1] = up.z; view[3][1] = -dot(up, position); view[0][2] = forward.x; view[1][2] = forward.y; view[2][2] = forward.z; view[3][2] = -dot(forward, position); view[0][3] = 0; view[1][3] = 0; view[2][3] = 0; view[3][3] = 1;
return view; }
|