轉自lyo的blog,原文地址:http://lyo.blogsome.com/2007/01/31/camera-in-jsr184/
1. Camera類
— Lyo Wu
寫完模擬器的M3G部分,早就想寫點總結,不寫怕要忘了。
那就從最簡單的Camera類開始。
Camera類封裝了3種投影變換:Generic、Parallel、Perspective。
1) Generic
public void setGeneric(Transform transform)
直接指定一個變換矩陣(Transform類其實就是一個矩陣的封裝),可以根據需求任意設定投影矩陣。
2) Parallel
public void setParallel(float fovy, float aspectRatio, float near, float far)
平行投影(正射投影,Orthographic Projection),忽略z軸作用,投影后的物體大小尺寸不變。M3G Specification中已經給出了對應的矩陣(NDC座標系):
| 2/w 0 0 0 |
| 0 2/h 0 0 |
| 0 0 -2/d -(near+far)/d |
| 0 0 0 1 |
其中,fovy - height of the view volume in camera coordinates。
h = height (= fovy)
w = aspectRatio * h
d = far - near
公式推導:
設(x, y, z, w)為視點座標,(x’, y’, z’, w’)為投影座標,(Px, Py, Pz, Pw)為NDC。
近平面距離為n,遠平面距離為f,視口寬為w,高為h。
x’ = x
y’ = y
映射到NDC ([-1, 1]),
Px = 2 * x’/ w = 2 * x / w
Py = 2 * y’ / h = 2 * y / h
由於z座標投影后不參與繪圖,用於可見度判斷,只要保證Pz與z呈線性關係,即Pz=a*z+b
將(-n,-1), (-f, 1) 代入得
a = -2 / (f - n)
b = -(n + f) / (f - n)
Pz = -2/ (f - n)*z - (n + f) / (f - n)
即等價於
| x | | 2/ w 0 0 0 |
| y | | 0 2 / h 0 0 |
| z | * | 0 0 -2/ (f – n) -( n + f) / (f - n) |
| 1 | | 0 0 0 1 |
3) Perspective
public void setPerspective(float fovy, float aspectRatio, float near, float far)
透視投影,即離視點近的物體大,離視點遠的物體小,符合人們心理習慣。
M3G Specification中已經給出了對應的矩陣(NDC座標系):
| 1/w 0 0 0 |
| 0 1/h 0 0 |
| 0 0 -(near+far)/d -2*near*far/d |
| 0 0 -1 0 |
其中,fovy - field of view in the vertical direction, in degrees。
h = tan ( fovy/2 )
w = aspectRatio * h
d = far - near
公式推導:
設(x, y, z, w)為視點座標,(x’, y’, z’, w’)為投影座標,(Px, Py, Pz, Pw)為NDC。
近平面距離為n,遠平面距離為f,近平面寬為W,高為H。
由相識三角形可以得到
x’ = -n * x / z
y’ = -n * y / z
映射到NDC ([-1, 1]),可得
Px = x’/ (W/2) = -2*n*x / z * W
Py = y’/ (H/2) = -2*n*y / z * H
由於x’, y’與1/ z有線性關係,只要保證Pz與1/z呈線性關係,即Pz=a/z+b
將(-n,-1), (-f, 1) 代入得
a = 2*n*f / f - n
b = f + n / f – n
Pz = 2*n*f / (f - n)*z + (f+n) / (f - n)
由於最後會除以w分量,所以可以把共同項寫入w分量:
-zPx = 2*n*x / W
-zPy = 2*n*y / H
-zPz = -2*n*f / (f – n) - (f+n) / (f - n) * z
w = -z
即等價於
| x | | 2*n / W 0 0 0 |
| y | | 0 2*n / H 0 0 |
| z | * | 0 0 - (f+n) / (f - n) -2*n*f / (f – n) |
| 1 | | 0 0 -1 0 |
引入視角fovy,即:
h = tan ( fovy/2 ) = (H/2) / n = H / 2*n
w = aspectRatio * h = W / 2*n
d = f - n
=============
不知道有沒有下文。。。。