先上結(jié)論:
Unity 使用的是左手坐標(biāo)系,threejs和WEBGL是右手坐標(biāo)系
一近哟、概念
關(guān)于左右手坐標(biāo)系的概念,可以參考馮樂樂 unity shader入門精要
第4章 學(xué)習(xí)Shader所需的數(shù)學(xué)基礎(chǔ)(上)(坐標(biāo)系鲫寄、點(diǎn)和矢量)
1.左手坐標(biāo)系和右手坐標(biāo)系
為什么在三維笛卡兒坐標(biāo)系中要區(qū)分左手坐標(biāo)系和右手坐標(biāo)系吉执,而二維中就沒有這些煩人的事情呢?
這是因?yàn)榈乩矗诙S笛卡兒坐標(biāo)系中戳玫, x 軸和y 軸的指向雖然可能不同,就如我們在圖4.4中看到的一樣靠抑。但我們總可以通過一些旋轉(zhuǎn)操作來使它們的坐標(biāo)軸指向相同量九。以圖4.4 中OpenGL和DirectX 使用的坐標(biāo)系為例,為了把右側(cè)的坐標(biāo)軸指向轉(zhuǎn)換到左側(cè)那樣的指向颂碧,我們可以首先對右側(cè)的坐標(biāo)系順時(shí)針旋轉(zhuǎn)180荠列。此時(shí)它的y 軸指向上,而x 軸指向左载城。然后肌似,我們再把整個(gè)紙面水平翻轉(zhuǎn)一下,就可以把x 軸翻轉(zhuǎn)到指向右了诉瓦,此時(shí)左右兩側(cè)的坐標(biāo)軸指向就完全相同了川队。從這種意義上來說,所有的二維笛卡兒坐標(biāo)系都是等價(jià)的睬澡。
但對于三維笛卡兒坐標(biāo)系固额,靠這種旋轉(zhuǎn)有時(shí)并不能使兩個(gè)不同朝向的坐標(biāo)系重合。例如煞聪,在圖4.6 中斗躏,+z 軸的方向指向紙面的內(nèi)部,如果有另一個(gè)三維笛卡兒坐標(biāo)系昔脯,它的+z 軸指向紙面外部啄糙, x 軸和y 軸保持不變,那么我們可以通過旋轉(zhuǎn)把這兩個(gè)坐標(biāo)軸重合在一起嗎云稚?答案是否定的隧饼。
我們總可以讓其中兩個(gè)坐標(biāo)軸的指向重合,但第三個(gè)坐標(biāo)軸的指向總是相反的静陈。
也就是說燕雁, 三維笛卡兒坐標(biāo)系并不都是等價(jià)的。因此,就出現(xiàn)了兩種不同的三維坐標(biāo)系: 左手坐標(biāo)系和右手坐標(biāo)系贵白。如果兩個(gè)坐標(biāo)系具有相同的旋向性( handedness )率拒,那么我們就可以通過旋轉(zhuǎn)的方法來讓它們的坐標(biāo)軸指向重合崩泡。但是禁荒,如果它們具有不同的旋向性〈例如坐標(biāo)系A(chǔ) 屬于左手坐標(biāo)系,而坐標(biāo)系B 屬于右手坐標(biāo)系〉角撞,那么就無法達(dá)到重合的目的呛伴。
那么,為什么叫左手坐標(biāo)系和右手坐標(biāo)系呢谒所?和手有什么關(guān)系热康?這是因?yàn)椋覀兛梢岳梦覀兊碾p手來判斷一個(gè)坐標(biāo)系的旋向性劣领。請讀者舉起你的左手姐军,用食指和大拇指擺出一個(gè)“L”的手勢,并且讓你的食指指向上尖淘,大拇指指向右∞刃浚現(xiàn)在,伸出你的中指村生,不出意外的話它應(yīng)該指向你的前方(如果你一定要展示自己骨驚奇的話我也沒有辦法〉惊暴。恭喜你, 你己經(jīng)得到了一個(gè)左手坐標(biāo)系了趁桃!你的大拇指辽话、食指和中指分別對應(yīng)了+x 、+y 和+z 軸的方向卫病,如圖4.7 所示油啤。
正如我們之前所說,左手坐標(biāo)系和右手坐標(biāo)系之間無法通過旋轉(zhuǎn)來同時(shí)使它們的3 個(gè)坐標(biāo)軸指向重合蟀苛,如果你不信益咬,你現(xiàn)在可以拿自己的雙手來試驗(yàn)一下。
另外一個(gè)確定是左手還是右手坐標(biāo)系的方法是屹逛,判斷前向( forward ) 的方向础废。請讀者坐直,向右伸直你的右手罕模,此時(shí)右手方向就是x 軸的正向评腺,而你的頭頂向上的方向就是y 軸的正向。這時(shí)淑掌,如果你的正前方的方向是z 軸的正向蒿讥,那么你本身所在的坐標(biāo)系就是一個(gè)左手坐標(biāo)系: 如果你的正前方的方向?qū)?yīng)的是z 軸的負(fù)向,那么這就是一個(gè)右手坐標(biāo)系。
除了坐標(biāo)軸朝向不同之外芋绸,左手坐標(biāo)系和右手坐標(biāo)系對于正向旋轉(zhuǎn)的定義也不同媒殉,即在初高中物理中學(xué)到的左手法則(left-hand rule ) 和右手法則(right-hand rule )。
2.正旋轉(zhuǎn)
假設(shè)現(xiàn)在空間中有一條直線摔敛,還有一個(gè)點(diǎn)廷蓉,找們希望把這個(gè)點(diǎn)以該直線為旋轉(zhuǎn)軸旋轉(zhuǎn)某個(gè)角度,比如旋轉(zhuǎn)30度马昙。讀者可以拿一支筆當(dāng)成這個(gè)旋轉(zhuǎn)軸桃犬,再拿自己的手當(dāng)成這個(gè)需要旋轉(zhuǎn)的點(diǎn),可以發(fā)現(xiàn)行楞,我們有兩個(gè)旋轉(zhuǎn)方向可以選擇攒暇。那么,我們應(yīng)該往哪個(gè)方向旋轉(zhuǎn)呢子房?
這意味著形用,我們需要在坐標(biāo)系中定義一個(gè)旋轉(zhuǎn)的正方向。在左手坐標(biāo)系中证杭,這個(gè)旋轉(zhuǎn)正方向是由左手法則定義的田度,而在右手坐標(biāo)系中則是由右手法則定義的。
在左手坐標(biāo)系中躯砰,我們可以這樣來應(yīng)用左手法則:還是舉起你的左手每币,握拳,伸出大拇指讓它指向旋轉(zhuǎn)軸的正方向琢歇,那么旋轉(zhuǎn)的正方向就是剩下4 個(gè)手指的彎曲方向兰怠。在右手坐標(biāo)系中,使用右手法則對旋轉(zhuǎn)正方向的判斷類似李茫,如圖4.9 所示揭保。
從圖4.9 中可以看出,在左手坐標(biāo)系中魄宏,旋轉(zhuǎn)正方向是順時(shí)針的秸侣,而在右手坐標(biāo)系中,旋轉(zhuǎn)正方向是逆時(shí)針的宠互。
3.左右手坐標(biāo)系之間的轉(zhuǎn)換
左右手坐標(biāo)系之間是可以進(jìn)行互相轉(zhuǎn)換的味榛。最簡單的方法就是把其中一個(gè)軸反轉(zhuǎn),并保持其他兩個(gè)軸不變予跌。
對于開發(fā)者來說搏色,使用左手坐標(biāo)系還是右手坐標(biāo)系都是可以的,它們之間并沒有優(yōu)劣之分券册。無論使用哪種坐標(biāo)系频轿,絕大多數(shù)情況下并不會影響底層的數(shù)學(xué)運(yùn)算垂涯,而只是在映射到視覺上時(shí)會有差別(見練習(xí)題2 )。
這是因?yàn)楹叫希粋€(gè)點(diǎn)或者旋轉(zhuǎn)在空間內(nèi)來說是絕對的耕赘。一些較真兒的讀者可能會看不慣“絕對”這個(gè)詞: “你怎么能忽略相對論呢?這世上一切都是相對的膳殷!”這些讀者請容我解釋操骡。這里所說的絕對是說, 在我們所關(guān)心的最廣闊的空間中秽之,這些值是絕對的当娱。例如我說吃既,把你的書從桌子的左邊移到右邊,你不會對這個(gè)過程產(chǎn)生什么疑問鹦倚, 此時(shí)我們關(guān)心的整個(gè)空間就是桌子這個(gè)空間河质,而在這個(gè)空間中,書的運(yùn)動(dòng)是絕對的震叙。但是掀鹅,在數(shù)學(xué)的世界中,我們需要使用一種數(shù)學(xué)模型來精確地描述它們媒楼,這個(gè)模型就是坐標(biāo)系乐尊。一旦有了坐標(biāo)系,每個(gè)點(diǎn)的位置就不再是絕對的划址,而是相對于這個(gè)坐標(biāo)系來說的扔嵌。這種相對關(guān)系導(dǎo)致,即便從數(shù)學(xué)表示上來說兩種表示方式完全一樣夺颤,但從視覺上來說是不一樣的痢缎。
我們可以在奶牛農(nóng)場的例子中體會左手坐標(biāo)系和右手坐標(biāo)系的分別。我們假設(shè)世澜,妞妞想要到一個(gè)新的地方独旷,因?yàn)槟抢锏牟莺苊牢丁fゆぶ赖竭_(dá)這個(gè)目標(biāo)點(diǎn)的“絕對路徑”是怎樣的寥裂,如圖4.10 所示嵌洼。
我們可以分別在一個(gè)左手坐標(biāo)系和右手坐標(biāo)系中描述這樣一次運(yùn)動(dòng), 即使用數(shù)學(xué)表達(dá)式來描述它封恰。我們會發(fā)現(xiàn)麻养,在不同的坐標(biāo)系中描述這樣同一次運(yùn)動(dòng)是不一樣的,如圖4.11 所示俭驮。
在左手坐標(biāo)系中回溺, 3 個(gè)坐標(biāo)軸的朝向如圖4.11 左圖所示春贸。妞妞首先向x 軸正方向平移1個(gè)單位,然后再向z 軸負(fù)方向移動(dòng)4 個(gè)單位遗遵,最后朝旋轉(zhuǎn)的正方向旋轉(zhuǎn)60萍恕。。而在右手坐標(biāo)系中车要,+z軸的方向和左手坐標(biāo)系中剛好相反允粤,因此妞妞首先向x 軸正方向平移1個(gè)單位(與左手坐標(biāo)系中的移動(dòng)一致),然后再向z 軸正方向移動(dòng)4 個(gè)單位( 與左手坐標(biāo)系中的移動(dòng)相反) 翼岁,最后朝旋轉(zhuǎn)的負(fù)方向旋轉(zhuǎn)60类垫。(與左手坐標(biāo)系中的旋轉(zhuǎn)相反)。
可以看出琅坡,為了達(dá)到同樣的視覺效果(這里指把妞妞移動(dòng)到視覺上的同一個(gè)位置)悉患,左右手坐標(biāo)系在z 軸上的移動(dòng)以及旋轉(zhuǎn)方向是不同的。如果使用相同的數(shù)學(xué)運(yùn)算(指均向z 軸某方向移動(dòng)或均朝旋轉(zhuǎn)正方向旋轉(zhuǎn)等〉榆俺,那么得到的視覺效果就是不一樣的售躁。因此,如果我們需要從左手坐標(biāo)系遷移到右手坐標(biāo)系茴晋,并且保持視覺上的不變陪捷,就需要進(jìn)行一些轉(zhuǎn)換。讀者可以參見本章最后的擴(kuò)展閱讀部分诺擅。
4.左右手坐標(biāo)系與叉積
這個(gè)結(jié)果是怎么得到的呢市袖?來,先舉起你的右手烁涌。在右手坐標(biāo)系中苍碟, a×b 的方向?qū)⑹褂糜沂址▌t來判斷。我們先想象把手心放在了a 和b 的尾部交點(diǎn)處烹玉,然后張開你的手掌讓手掌方向和a 的方向重合驰怎,再彎曲你的四指讓它們向b 的方向靠攏,最后伸出你的大拇指二打! 大拇指指向的方向就是右手坐標(biāo)系中a x b 的方向了县忌。如果你實(shí)在不明白怎么擺放和扭動(dòng)你的手,那么就看圖4.28 好了.
同理继效,我們可以使用左手法則來判斷左手坐標(biāo)系中ax b 的方向症杏。趕緊舉起你的左手試試吧(你可能會發(fā)現(xiàn)這個(gè)姿勢比較扭曲∪鹦牛〉厉颤!
需要注意的是,雖然看起來左右手坐標(biāo)系的選擇會影響叉積的結(jié)果凡简,但這僅僅是“看起來”而己逼友。從叉積的數(shù)學(xué)表達(dá)式可以發(fā)現(xiàn)精肃,使用左手坐標(biāo)系還是右手坐標(biāo)系不會對計(jì)算結(jié)果產(chǎn)生任何影響,它影響的只是數(shù)字在三維空間中的視覺化表現(xiàn)而己帜乞。當(dāng)從右手坐標(biāo)系轉(zhuǎn)換為左手坐標(biāo)系時(shí)司抱,所有點(diǎn)和矢量的表達(dá)和計(jì)算方式都會保持不變,只是當(dāng)呈現(xiàn)到屏幕上時(shí)黎烈, 我們可能會發(fā)現(xiàn)习柠, “咦,怎么圖像反過來了照棋! ”资溃。當(dāng)我們想要兩個(gè)坐標(biāo)系達(dá)到同樣的視覺效果時(shí),可能就需要改變一些數(shù)學(xué)運(yùn)算公式烈炭, 這不在本書的范疇內(nèi)溶锭。有興趣的讀者可以參考本章的擴(kuò)展閱讀部分。
那么梳庆,叉積到底有什么用呢暖途?最常見的一個(gè)應(yīng)用就是計(jì)算垂直于一個(gè)平面、三角形的矢量膏执。另外,還可以用于判斷三角面片的朝向露久。
二更米、Unity 使用的坐標(biāo)系
1.模型空間和世界空間
對于一個(gè)需要可視化虛擬的三維世界的應(yīng)用(如Unity )來說,它的設(shè)計(jì)者就要進(jìn)行一個(gè)選擇毫痕。對于模型空間和世界空間(在4.6 節(jié)中會具體講解這兩個(gè)空間是什么) , Unity 使用的是左手坐標(biāo)系(注:threejs是右手坐標(biāo)系)征峦。這可以從Scene 視圖的坐標(biāo)軸顯示看出來,如圖4.12 所示消请。這意味著栏笆,在模型空間中,一個(gè)物體的右側(cè)( right)臊泰、上側(cè)( up )和前側(cè)( forward )分別對應(yīng)了x 軸蛉加、y 軸和z 軸的正方向。
2.觀察空間
但對于觀察空間來說缸逃, Unity 使用的是右手坐標(biāo)系针饥。觀察空間,通俗來講就是以攝像機(jī)為原點(diǎn)的坐標(biāo)系需频。在這個(gè)坐標(biāo)系中丁眼,攝像機(jī)的前向是z 軸的負(fù)方向,這與在模型空間和世界空間中的定義相反昭殉。也就是說苞七, z 軸坐標(biāo)的減少意味著場景深度的增加藐守,如圖4.13 所示。