計算Perspective camera的頂點位置
前言
最近需要計算Perspective camera的頂點位置,發現不是很好算,想一下後記起之前在做Shadow map時有算過,為了防止忘記怎麼算,在此做個紀錄。內容
在計算之前先來說一下一般表達Perspective camera,用C++來表達的話如下struct PerspactiveCamera { float fov; float aspect; float near; float far; };
為了方便說明,所以為每個頂點編號,如下圖
Perspective camera的8個頂點 |
在計算頂點時必須考慮坐標系,圖中所採用左手坐標系,Z軸代表遠近,X軸為左右,Y軸為上下。頂點"0"、"1"、"2"與"3"所形成的板子稱為"近板",頂點"4"、"5"、"6"與"7"所形成的板子稱為"遠板"。
先來計算頂點的Z值,遠板的Z值等於"far",近板的Z值等於"near",沒什麼困難,那寬度呢?像是頂點"0"到頂點"1"的長度可以從高度得來,將"0"到頂點"2"的長度乘上"aspect"就可以得到寬度,所重點擺在如何計算高度,看圖中頂點"0"、"2"、"4"與"6"所圍成的板子,在參照下圖
計算遠板與近板的高度 |
在圖中的紅線代表近板的半高度,綠線則是遠板的半高度,近板的半高度=near*cot(fov/2),遠板的半高度=far*cot(fov/2),半高度值會剛好等於Y值,頂點"0"的Y值就是近板的半高度,頂點"2"的Y值是近板的半高度乘上負1,遠板的Y值依此類推。
總結的計算如下
struct Point { float x; float y; float z; }; struct PerspactiveCamera { float fov; float aspect; float near; float far; }; // PerspactiveCamera camera; //... // Point p0,p1,p2,p3,p4,p5,p6,p7; // float nearHalfHeight=camera.near*cot(camera.near/2.0f); float nearHalfWidth=nearHalfHeight*camera.aspect; float farHalfHeight=camera.far*cot(camera.near/2.0f); float farHalfWidth=farHalfHeight*camera.aspect; // p0.x = -nearHalfWidth; p0.y = nearHalfHeight; p0.z = near; // p1.x = nearHalfWidth; p1.y = nearHalfHeight; p1.z = near; // p2.x = -nearHalfWidth; p2.y = -nearHalfHeight; p2.z = near; // p3.x = nearHalfWidth; p3.y = -nearHalfHeight; p3.z = near; // p4.x = -farHalfWidth; p4.y = farHalfHeight; p4.z = far; // p5.x = farHalfWidth; p5.y = farHalfHeight; p5.z = far; // p6.x = -farHalfWidth; p6.y = -farHalfHeight; p6.z = far; // p7.x = farHalfWidth; p7.y = -farHalfHeight; p7.z = far;
cot()是三角函數的"Cotangent",標準C++並不提供,如果需要自己實作可以參考Stable Cotangent。
沒有留言:
張貼留言