理解計算機3D圖形學中的座標系變換

轉載文章1:http://www.cnblogs.com/shanhaobo/articles/1065380.html

[3D基礎]理解計算機3D圖形學中的座標系變換

要談座標系變換,那麼座標系有哪些呢?依次有:物體座標系,世界座標系,相機座標系,投影座標系以及屏幕座標系.我要討論的就是這些座標系間的轉換。
     這些座標系不是憑空而來,他們都是爲了完成計算機3D圖形學最最最基本的目標而出現.
      計算機3D圖形學最最最基本的目標就是:將構建好的3D物體顯示在2D屏幕座標上.
      初看好像就是將最初的物體座標系轉換到屏幕座標系就可以了呀,爲什麼多出了世界座標系,相機座標系,投影座標 系。這是因爲:在一個大世界裏有多個物體,而每個物體都有自己的座標系,如何表述這些物體間相對的關係,這個多出了世界座標系;如果只需要看到這個世界其 中一部分,這裏就多出了相機座標系;至於投影座標系那是因爲直接將3D座標轉換爲屏幕座標是非常複雜的(因爲它們不僅維度不同,度量不同(屏幕座標一般都 是像素爲單位,3D空間中我們可以現實世界的米,釐米爲單位),XY的方向也不同,在2D空間時還要進行座標系變換),所以先將3D座標降維到2D座標, 然後2D座標轉換到屏幕座標。
理解3D圖形學的第一步:理解左手座標系與右手座標系
      爲什麼會有左手座標系與右手座標系之分?
      在3D空間(沒錯!就是3D)中,所有2D座標系是等價的(就是通過一系列的仿射變換,可以互相轉換)
      而3D座標系不是等價的,通過仿射變換,是無法將左手座標系轉換到右手座標系;也就是說,物體座標系用的就是左手座標系,世界座標系用的是右手 座標系,那麼物體可能就是不會是我們所希望的樣子了,可能是倒立的,也可能是背對着我們的,所以我們要區分左手座標系與右手座標系。也許在4D空間,左右 手座標系就可以互相變換了吧。
      進入正題吧:
     首先討論的是物體座標系->世界座標系 
      前面說了爲了描述多個物體間相對的關係,這裏引進了世界座標系,所以世界座標系是個參考座標系。
      這一步的目的將所有的物體的點都轉移到世界座標系,這裏主要涉及的是旋轉,縮放,平移等。
      不過我將詳細說明爲何及如何用矩陣來描述這些變換。
      例:如果有兩個座標系C與C`, C`是C繞Z軸旋轉θ得到的。下面是各座標軸的變換:
                 
注:此處Cz'的縱座標應爲1

     如果是C座標系的點P(x, y, z),而在C`的表示就是
      注:此處Z’軸座標應爲z,爲作者筆誤,且C‘是C繞Z軸順時針方向旋轉

     這時該如何建立矩陣呢? 答案就是區分你用的是行向量還是列向量.也許有人會問爲什麼不區分是左手座標系還是右手座標系呢?因爲C可以變換到C`,那麼他們一定是同在左手座標系或右手座標系,變換只能在可以互相轉換的座標系之間進行。
      如果你用的是行向量:由於行向量只能左乘矩陣(注意乘與乘以的區別)
      所以矩陣形式應該是這樣
      
     只有這樣,在左乘矩陣時才能得到上面P`的形式。
      
     如果你用的是列向量: 由於列向量只能右乘矩陣(注意乘與乘以的區別)
     所以矩陣形式應該是這樣
      
     只有這樣,在右乘矩陣時才能得到上面P`的形式。
    
     至於如何旋轉,縮放,平移我不在多說。
     …………………………………
     我們再討論世界座標系->相機座標系 
     引進相機的目的就是隻需看到世界的一部分,而哪些是可以在相機裏看到的,就需要進行篩選。將物體轉換到相機座標系,這樣相機座標系進行篩選時就會簡單很多。這裏的重點是構建相機座標系。
     物體座標系,世界座標系是美工在繪製時就定義好了的。而相機座標系是需要程序實時構建的。(當然這是通常情況下,如果你要建立一個世界,這個世界都是圍繞 你轉,要實時改變所有物體座標系,固定相機座標系(其實這時候相機座標系就是世界座標系),建立一個地心說的世界,我也沒辦法,你的思維也太不一樣了。)
     如何構建相機座標系呢?首先我們要明確目標:我們是要構建3D座標系(好像是廢話),三個座標軸要互相垂直(也好像是廢話).
      我們一般用UVN相機。例如:D3D的D3DXMatrixLookAtLH,D3DXMatrixLookAtRH,OGL的gluLookAt(右手座標系).
      如何建立呢UVN相機呢? 我們就要利用叉積這個工具了:兩個不平行,不重疊的向量的叉積可以得到與這兩個向量互相垂直的向量。
      如果有了相機的位置與目標的位置那麼我們可以確定一個Z軸(有人問爲什麼是Z軸,因爲物體的遠與近我們就習慣用Z值來表示的)。求Z軸時要注意 是左手座標系還是右手座標系,左右手座標系XY軸方向相同時,Z軸的方向相反。所以左手座標系是目標位置減去相機位置,而右手座標系則是相機位置減去目標 位置。記得normalize
     這是我們要得到X與Y軸了。如何求X,Y軸呢?
     一般方法是:
     1、選擇一個臨時Y軸,
     2、對臨時Y 與Z 軸進行叉積求得一個X軸
     3、X軸再與Z軸進行叉積,得到一個Y軸。
     有了XYZ就可以求出旋轉的相機矩陣了。
     如何選擇一個Y軸呢?大多數情況下是(0,1,0),但是如果是相機位置E與目標位置T垂直,即(E-T=(0,+/-1,0)時),這時就不能用(0,1,0)了, 因爲兩個平行向量的叉積是零向量,所以我們就要另選一個Y軸。
     但是我覺得我們可以改變方法。
      如果不能選Y軸,我們就選擇一個臨時X軸,這個臨時X軸就是(1,0,0)。
     然後再對臨時X軸與Z軸進行叉積求得一個Y軸。
     最後Y軸再與Z軸進行叉積,得到X軸。
      這樣可以得到XYZ軸。
      最後再根據行向量與列向量建立相機矩陣,再進行平移。

     相機座標系->投影座標系 .
     投影的目的就是:降維.
      兩種投影方式:正交投影與透視投影.
      在我們TEAM中易穎已經寫了,我就不多說了,大家去看他的文章。

     投影座標系->屏幕座標系
      這是最簡單的。2D座標變換。也不多說。

轉載文章2:http://www.xingousi.com/computer/computergraphics.htm

計算機圖形學透視投影變換原理及一點和兩點透視

一、平行互分法

吳英凡所寫的《透視作圖的新方法——交點法體系》,其中談到的平行互分法,還是有道理的。

其實簡單點說,就是透視圖上的兩條“原來空間中的平行線”(在畫面上透視投影爲相交於滅點),通過其中一條透視投影直線的端點畫另一條透視投影直線的平行線,必平行於畫面;這第三條線在畫面的透視投影的滅點必然在另一條透視投影線上。

二、透視投影變換學習總結

1、用多維數列表示低維空間座標,加深理解齊次座標表示法。

    齊次座標表示法可以方便地運算,同時形狀不變。[x,y,z,0]表示一個無窮的點。

   

2、透視投影變換公式可以看成兩個矩陣的乘積,其中一個做透視變換,另外一個作正投影

   保留的z'值的確切含義:指的是在完全作完透視投影變換之前,僅作透視投影之後的一條線.

   它的幾何意義見李建平《計算機圖形學原理教程》第44頁。

3、左手和右手座標系的座標轉換

   “視點座標系與一般的物體所在的世界座標系不同,它遵循左手法則,即左手大拇指指向Z正軸,與之垂直的四個手指指向X正軸,四指彎曲90度的方向是Y正軸。而世界座標系遵循右手法則的。”

4、視點座標系的透視變換公式很重要!!王飛著計算機圖形學書65頁

5、z'值的確切含義:指的是在完全作完透視投影變換之前,僅作透視投影之後的一條線

三、兩點透視的變換矩陣:

王飛編著《計算機圖形學基礎》的道理是:

從平面圖形的平移、旋轉、錯切開始推導,兩點透視的變換矩陣可以看成是:

物體本身有一個物體座標系——xw,yw,zw,視點作爲原點又構成一個視點座標系——xe,ye,ze,物體座標系z軸朝上,y軸朝向遠處;而視點座標系y軸朝上,z軸朝向遠處。

這樣,最終的二點透視狀態可以這樣取得,首先把物體的位置的物體座標系表示法轉化爲視點座標系的表示法(第一個矩陣),然後圍繞視點座標系的y軸旋轉(第二個矩陣),然後在x,y,z方向上平移(第三個矩陣),最後做透視變換(第四個矩陣),它的原文是把平移放在第二步,我在平移之前轉動,目的是保證了物體旋轉的軸在離它不遠的地方:

我使用的矩陣變換如下,原文是是把平移放在第二步:

[xw,yw,zw,1]*  * * *

最後所得結果是一個新的矩陣,

[xe ye ze 1]=[cos *xw-sin *yw+l   zw+m   2sin *xw+2cos *yw+2n-d   (sin *xw+cos*yw+n)/d]

把最後一項變成1,可得

=[(cos *xw-sin *yw+l)*d/(sin *xw+cos *yw+n   (zw+m)*d/(sin *xw+cos *yw+n)   (2sin*xw+2cos *yw+2n-d)*d/(sin *xw+cos *yw+n)    1 ]


即:

Xe= (cos *xw-sin *yw+l)*d/(sin *xw+cos *yw+n)

Ye=(zw+m)*d/(sin *xw+cos *yw+n)

Ze=(2sin *xw+2cos *yw+2*n-d)*d/(sin *xw+cos *yw+n)

實際上我的delphi程序裏面是這樣的:

xe:=trunc((cos(angle)*eee[ii][k].X-sin(angle)*eee[ii][k].Y+l)*d/(sin(angle)*eee[ii][k].X+cos(angle)*eee[ii][k].Y+n));

        ye:=trunc((hhh[ii][k]+m)*d/(sin(angle)*eee[ii][k].X+cos(angle)*eee[ii][k].Y+n)); //透視變換

        //ze可以考慮使用作爲消隱

Ze:=trunc((2*sin(angle)*xw+2*cos(angle)*yw+2*n-d)*d/(sin(angle)*xw+cos(angle)*yw+n));

四、通過變換過的兩點透視的結果xe,ye,zw和 *,反求原來的物體座標xw,yw

即:xe,ye,zw和 已知,求出xw,yw

根據:

Xe= (cos *xw-sin *yw+l)*d/(sin *xw+cos *yw+n)          (1)

Ye=(zw+m)*d/(sin *xw+cos *yw+n)                         (2)

Ze=(2sin *xw+2cos *yw+2n-d)*d/(sin *xw+cos *yw+n) (3)

(1)除以(2)得

Xe/Ye= (cos *xw-sin *yw+l)/ (zw+m)

(Xe*(zw+m))/Ye=cos *xw-sin *yw+l

(Xe*(zw+m))/(Ye* cos )=xw-tan *yw+l/cos

Xw=(Xe*(zw+m))/ (Ye* cos ) - (ye*l)/(Ye* cos )+( sin *yw*ye)/ (Ye* cos )

Xw=(Xe*(zw+m)+ sin *yw*ye- ye*l)/ (Ye* cos )            (4)

由(2)得

Ye*(sin *xw+cos *yw+n)= (zw+m)*d

Ye*(sin *xw)+ye* cos *yw+n*ye=(zw+m)*d

把(4)代入上式得

Ye* sin *( Xe* (zw+m)+ sin *yw*ye- ye*l)/ (Ye* cos ) +ye* cos *yw+n*ye=(zw+m)*d

約去ye,得

sin *( Xe* (zw+m)+ sin *yw*ye- ye*l)/ cos +ye* cos *yw+n*ye=(zw+m)*d

tan *( Xe* zw+xe*m+ sin *yw*ye- ye*l) +ye* cos *yw+n*ye=(zw+m)*d

tan * Xe* zw+xe*m * tan - ye*l* tan + sin * tan *yw *ye +ye* cos *yw+n*ye=(zw+m)*d

(sin * tan *ye +ye* cos )*yw+ tan * Xe* zw +xe*m * tan - ye*l* tan +n*ye=(zw+m)*d

最後得

Yw=[(zw+m)*d- tan * Xe* zw- xe*m * tan + ye*l* tan - n*ye]/ (sin * tan *ye +ye* cos ) (5)

而前面已經得到

Xw=(Xe*(zw+m)+ sin *yw*ye- ye*l)/ (Ye* cos )            (4)

實際上相當於opengl裏面的逆變換,從鼠標選中的屏幕位置來確定對應的三維空間中位置,opengl使用gluUnProject和gluUnProject4來計算。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章