使用C語言實現二維,三維繪圖算法(1)-透視投影
---- 引言----
每次使用OpenGL或DirectX寫三維程序的時候, 都有一種隔靴搔癢的感覺, 對於內部的三維算法的實現不甚了解. 其實想想, Win32中既然存在畫線畫點函數, 利用計算機圖形學的知識, 我們用可以用純C調用Win32實現三維繪圖, 完全不用借助OpenGL和DirectX, 這有重復造輪子的嫌疑, 但是自己動手實現一遍, 畢竟也是有意義的.
[效果演示]
線框效果, 隱藏面采用虛線
顏色填充后效果
[透視投影理論]
分析:假定投影中心在Z軸上(z=-d處),投影面在xoy面上,與z軸垂直,d為投影面與=投影中心的距離。現求空間一點p(x, y, z)的透視投影p'(x', y', z')點的坐標。
根據相似三角形對應邊成比例關系有:
寫成矩陣形式如下:
透視縮小效應:物體的透視投影的大小與物體到投影中心的Z方向距離成反比。
特點:透視投影的深度感更強,更加具有真實感,但透視投影不能夠准確反映物體的大小和形狀。
(1)透視投影的大小與物體到投影中心的距離有關。
(2)一組平行線若平行於投影平面時,它們的透視投影仍然保持平行。
(3)只有當物體表面平行於投影平面時,該表面上的角度在透視投影中才能被保持。
滅點:透視投影中不平行於投影面的平行線的投影會匯聚到一個點,這個點稱為滅點(Vanishing Point)。
坐標軸方向的平行線在投影面上形成的滅點稱作主滅點。 透視投影可以按照主滅點的個數分類:
(1)一點透視有一個主滅點,即投影面與一個坐標軸正交,與另外兩個坐標軸平行。
(2)二點透視有兩個主滅點,即投影面與兩個坐標軸相交,與另一個坐標軸平行。
(2)三點透視有三個主滅點,即投影面與三個坐標軸都相交。
[編程實現要點]
計算三維投影點的函數
void Calc3DPoint(void) { x = (-1)*x; xa = cr1*x - sr1*z; za = sr1*x + cr1*z; x = cr2*xa + sr2*y; ya = cr2*y - sr2*xa; z = cr3*za - sr3*ya; y = sr3*za + cr3*ya; x=x+mx; y=y+my; z=z+mz; sx = d*x/z; sy = d*y/z; return; }
逐個畫出各個側面, 並進行消隱形探測
...
surface1: x1=B1[6][0]; y01=B1[6][1]; z1=B1[6][2]; x2=B1[5][0]; y2=B1[5][1]; z2=B1[5][2]; x3=B1[4][0]; y3=B1[4][1]; z3=B1[4][2]; VisibilityTest(); if(sp>0) goto surface2; sx1=B2[6][0]; sy1=B2[6][1]; sx2=B2[5][0]; sy2=B2[5][1]; sx3=B2[4][0]; sy3=B2[4][1]; sx4=B2[7][0]; sy4=B2[7][1]; sx5=B3[1][0]; sy5=B3[1][1]; DrawPoly(); surface2: x1=B1[3][0]; y01=B1[3][1]; z1=B1[3][2]; x2=B1[2][0]; y2=B1[2][1]; z2=B1[2][2]; x3=B1[5][0]; y3=B1[5][1]; z3=B1[5][2]; VisibilityTest(); if(sp>0) goto surface3; sx1=B2[3][0]; sy1=B2[3][1]; sx2=B2[2][0]; sy2=B2[2][1]; sx3=B2[5][0]; sy3=B2[5][1]; sx4=B2[6][0]; sy4=B2[6][1]; sx5=B3[2][0]; sy5=B3[2][1]; DrawPoly();
...