討論區快速選單
知識庫快速選單
掌握Salesforce雲端管理秘訣 討論區最近新進100則主題 網路投保旅行平安險
[ 回上頁 ] [ 討論區發言規則 ]
請問 四元數 的意義及電腦圖學中的應用
更改我的閱讀文章字型大小
作者 : cromayen2000(CROMAYEN2000) OpenGL卓越專家貼文超過500則人氣指數超過10000點
[ 貼文 646 | 人氣 22308 | 評價 2260 | 評價/貼文 3.5 | 送出評價 38 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/1/12 下午 08:40:40
大家晚安 ^^~:

     在維基中查到 四元數可以使用在三維物件的旋轉及方位 不過我還是看不懂他矩陣的意義
     請問有人清楚四元數的意義、運用及限制嗎?
作者 : ma_hty(白老鼠(Gary))討論區板主 OpenGL卓越專家DirectX優秀好手C++頂尖高手貼文超過2000則人氣指數超過70000點
[ 貼文 2189 | 人氣 89850 | 評價 10120 | 評價/貼文 4.62 | 送出評價 79 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人cromayen2000註記此篇回應為最佳解答 2007/1/13 上午 10:50:06
歷史就不說了, 關於 四元數, 你可以很容易在網上找到很多很嚇人的抽象數學定義, 但是, 對於編程式的我們, 那些就太不實用. 就讓我從應用層面簡述一下吧.

四元數 主要應用在運算 rotation matrix 之上, 使用它的 加 減 乘 和 插值 運數都已被定義.

要了解 四元數 對於 三維旋轉矩陣 的意義, 你要先了解 三維旋轉 的問題.

三維空間的旋轉, 你有 三個自由度 (degree of freedom), 要記錄三維空間的旋轉, 就算是沒啥數學概念的人, 也會想到使用三個 由 三條座標軸 量度出來的 角度 去記錄. 這種可說是最原始的 三維旋轉 代表方法, 也就是大家說的 Euler Angle.

以 Euler Angle 去代表旋轉, 當成是簡單的記錄是沒問題的, 但是, 使用 Euler Angle 去實作旋轉介面時, 就會發生某旋轉方向失效的情況, 這是因為三個獨立處理的旋轉角, 它們其中一使兩條座標軸重疊了. 這個情況, 我們都叫作 Gimbal Lock.

為了避免 Gimbal Lock 的出現, 人們就發展出 Axis Angle 的旋轉定義, 就是說, 旋轉 都是以 自轉軸 和 自轉角 去代表的, 使用 Axis Angle 去實作旋轉介面方法, 就是先訂出兩支 unit vector (v0, v1), 然後以 Axis Angle 找出它們的最少旋轉, 即
axis = normalize( v0, v1 )
angle = acosf( v0,v1)

如此, Gimbal Lock 的問題就解決了.

... ...




作者 : ma_hty(白老鼠(Gary))討論區板主 OpenGL卓越專家DirectX優秀好手C++頂尖高手貼文超過2000則人氣指數超過70000點
[ 貼文 2189 | 人氣 89850 | 評價 10120 | 評價/貼文 4.62 | 送出評價 79 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/1/13 上午 11:23:18
... 續上篇 ...

雖然 Axis Angle 定義, 可以解決 Gimbal Lock 的問題, 但是, 如果我們想要在兩個 Axis Angle 旋轉 之間 插值 去做出它們之間的平滑變化, 你並不可以作單純的線性插值, 你會需要一番額外的運算, 才可以達到 插值 的功能.

又說, 如果你親手做過 Axis Angle 功能的話, 你就會發現當中常用的運算, 都包含很多類同的程序, 把它們 歸納 優化 之後, 就差不多跟我們常用的 四元數 同一樣了.

你可以把 四元數 想像成 優化版 的 Axis Angle 定義. 但是, 我要強調一點, 實質的程序, 兩者沒多大差別的, 最大的分別, 大概就只是 四元數 的名號讓人看來遠不可及吧.
作者 : cromayen2000(CROMAYEN2000) OpenGL卓越專家貼文超過500則人氣指數超過10000點
[ 貼文 646 | 人氣 22308 | 評價 2260 | 評價/貼文 3.5 | 送出評價 38 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/1/13 下午 12:38:00

>歷史就不說了, 關於 四元數, 你可以很容易在網上找到很多很嚇人的抽象數學定義, 但是, 對於編程式的我們, 那些就太不實用. 就讓我從應用層面簡述一下吧.
四元數 主要應用在運算 rotation matrix 之上, 使用它的 加 減 乘 和 插值 運數都已被定義.
>要了解 四元數 對於 三維旋轉矩陣 的意義, 你要先了解 三維旋轉 的問題.
>

這個是指分別以 3 軸的旋轉角度(rx,ry,rz)的方式記錄 物體的姿態嗎?
我目前還是用這種 跟 fi thta 的表示法(汗~)
>三維空間的旋轉, 你有 三個自由度 (degree of freedom), 要記錄三維空間的旋轉, 就算是沒啥數學概念的人, 也會想到使用三個 由 三條座標軸 量度出來的 角度 去記錄. 這種可說是最原始的 三維旋轉 代表方法, 也就是大家說的 Euler Angle.

嗯嗯 這個我遇到過 在 (rx,ry,rz) 的表示法時 根據旋轉軸計算的先露順序 如果依照 rx ry rz 這時候要是 rx 旋轉 90 度 讓 y 軸 旋轉到 -z 軸上 這時候的 ry 就失效了
>以 Euler Angle 去代表旋轉, 當成是簡單的記錄是沒問題的, 但是, 使用 Euler Angle 去實作旋轉介面時, 就會發生某旋轉方向失效的情況, 這是因為三個獨立處理的旋轉角, 它們其中一使兩條座標軸重疊了. 這個情況, 我們都叫作 Gimbal Lock.
>

ㄜ 這兩個我平常是拿來算物件的旋轉的(orz~ 居然不知道自己已經在用了)
axis = normalize( v0, v1 )
angle = acosf( v0,v1)
>為了避免 Gimbal Lock 的出現, 人們就發展出 Axis Angle 的旋轉定義, 就是說, 旋轉 都是以 自轉軸 和 自轉角 去代表的, 使用 Axis Angle 去實作旋轉介面方法, 就是先訂出兩支 unit vector (v0, v1), 然後以 Axis Angle 找出它們的最少旋轉, 即
>axis = normalize( v0, v1 )
>angle = acosf( v0,v1)
>
>如此, Gimbal Lock 的問題就解決了.
>

原來這個也能用在物件的姿態(原本以為一個旋轉軸沒有辦法做到翻滾的情況(汗~))
所以我在世界座標 要表示依個姿態的時候就會變成 (這樣對嗎?)
一個點座標 表示物件的位置
一個軸向 代表旋轉軸
一個旋轉角 代表旋轉角度

下面有幾個問題 拜託白老鼠大哥幫我看依下 ^^"
1.之所以不紀錄 v0, v1 是因為 兩者夾角在 180 度時沒有辦法確定出旋轉軸(這樣對嗎?)
2.如果我希望對 讓物件的姿態 隨著 世界座標的 X 軸旋轉 5 度 那我就直接用 X軸的旋轉矩陣對旋轉軸進行乘法(這樣對嗎?)
3.進行姿態控制之前 必須需要先檢查要旋轉的旋轉軸 是否與現在的旋轉軸相同 相同的話 就直接累計在旋轉角度上(這樣對嗎?)
4.這個方法的前提是要已經知道旋轉後同一軸向的位置 有時候我只能得到 (rx,ry,rz) 時 我該怎麼把它變成旋轉軸呢?

謝謝 ^^~




 


作者 : ma_hty(白老鼠(Gary))討論區板主 OpenGL卓越專家DirectX優秀好手C++頂尖高手貼文超過2000則人氣指數超過70000點
[ 貼文 2189 | 人氣 89850 | 評價 10120 | 評價/貼文 4.62 | 送出評價 79 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/1/13 下午 04:56:24
>1.之所以不紀錄 v0, v1 是因為 兩者夾角在 180 度時沒有辦法確定出旋轉軸(這樣對嗎?)

沒什麼可不可以, 就算是使用 Euler Angle 也沒問題呀, 問題不是出在記錄上, 問題是在於 旋轉介面設計 和 插值 上.

>2.如果我希望對 讓物件的姿態 隨著 世界座標的 X 軸旋轉 5 度 那我就直接用 X軸的旋轉矩陣對旋轉軸進行乘法(這樣對嗎?)

我不太明白你說的 姿態 是什麼, 如果是 旋轉 的話, 你當然可以把 Axis Angle 旋轉 轉換成 旋轉矩陣, 轉成為 旋轉矩陣 就是一般的 affine transform, 當然可以相乘...

>3.進行姿態控制之前 必須需要先檢查要旋轉的旋轉軸 是否與現在的旋轉軸相同 相同的話 就直接累計在旋轉角度上(這樣對嗎?)

我不明白你說的 姿態控制 是什麼, 我假定是 為旋轉作插值 吧, 要為兩個 旋轉 作插值, 最直接不過的方法, 就是使用 四元數, 別自己去併奇怪的應用吧, 為旋轉作插值 已經有很仔細的程序, 你自己併出來的, 最好的結果, 也就是跟 四元數插值 一般了, 為什麼不重最開始使用 四元數 呢?!

>4.這個方法的前提是要已經知道旋轉後同一軸向的位置 有時候我只能得到 (rx,ry,rz) 時 我該怎麼把它變成旋轉軸呢?
>

Rotation Matrix, Euler Angle, Axis Angle 和 Quaternion, 對於旋轉, 都是全等的定義, 你是必然可以把它們互相轉換的 (如果你的數學程序沒錯誤的話...). 關於它們之間互相轉換的公式 和 使用 四元數 作插值的方法, 都可以在下列網址找到...

http://www.flipcode.com/documents/matrfaq.html


作者 : cromayen2000(CROMAYEN2000) OpenGL卓越專家貼文超過500則人氣指數超過10000點
[ 貼文 646 | 人氣 22308 | 評價 2260 | 評價/貼文 3.5 | 送出評價 38 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/1/13 下午 05:17:46
ㄜ 姿態指的是 我有個模型在自己的物件座標系統中轉換到世界座標系統(ModelingTransformations) 時的參數 簡單的說就是姿勢 ^^" (努力研究網頁中)... 好物阿~
作者 : cromayen2000(CROMAYEN2000) OpenGL卓越專家貼文超過500則人氣指數超過10000點
[ 貼文 646 | 人氣 22308 | 評價 2260 | 評價/貼文 3.5 | 送出評價 38 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/1/13 下午 05:32:20
拿 OpenGL 的程式來說明比較容易一點

原來我的物體姿勢是這樣紀錄的
CVector m_ObjCenter; ///< 物件的中心點
CVector m_ObjPosition; ///< 物件的位置
GLdouble m_ObjRotateAngle[3]; ///< 對三軸的旋轉量
GLdouble m_ObjScale[3]; ///< 對三軸的縮放量

ps. CVector 是自己寫的 向量物件 4 x 1 內容為 [x,y,z,1]

輸出物體之前 要先輸出物件在世界座標系統的樣子
glTranslated(m_ObjPosition.m_X,m_ObjPosition.m_Y,m_ObjPosition.m_Z);
glRotatef(m_ObjRotateAngle[2],0,0,1);
glRotatef(m_ObjRotateAngle[1],0,1,0);
glRotatef(m_ObjRotateAngle[0],1,0,0);
glScaled(m_ObjScale[0],m_ObjScale[1],m_ObjScale[2]);
glTranslated(-m_ObjCenter.m_X,-m_ObjCenter.m_Y,-m_ObjCenter.m_Z);

結果當然是很慘的會有 Gimbal Lock 的問題 orz~

作者 : cromayen2000(CROMAYEN2000) OpenGL卓越專家貼文超過500則人氣指數超過10000點
[ 貼文 646 | 人氣 22308 | 評價 2260 | 評價/貼文 3.5 | 送出評價 38 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/1/13 下午 05:44:02
如果改寫成
CVector m_ObjCenter; ///< 物件的中心點
CVector m_ObjPosition; ///< 物件的位置
CVector m_ObjRotateAxis; ///< 對物件的旋轉軸
GLdouble m_ObjRotateAngle; ///< 對旋轉的角度
GLdouble m_ObjScale[3]; ///< 對三軸的縮放量

glTranslated(m_ObjPosition.m_X,m_ObjPosition.m_Y,m_ObjPosition.m_Z);
glRotatef(m_ObjRotateAngle,m_ObjRotateAxis.m_X,m_ObjRotateAxis.m_Y,m_ObjRotateAxis.m_Z);
glScaled(m_ObjScale[0],m_ObjScale[1],m_ObjScale[2]);
glTranslated(-m_ObjCenter.m_X,-m_ObjCenter.m_Y,-m_ObjCenter.m_Z);

這樣會比較好嗎? 或者我直接使用依個 4x4 的矩陣來表示會比較好呢?

作者 : cromayen2000(CROMAYEN2000) OpenGL卓越專家貼文超過500則人氣指數超過10000點
[ 貼文 646 | 人氣 22308 | 評價 2260 | 評價/貼文 3.5 | 送出評價 38 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/1/13 下午 08:11:18
不好意思 我重新解釋剛剛的問題 ^^"

1.之所以不紀錄 v0, v1 是因為 兩者夾角在 180 度時沒有辦法確定出旋轉軸(這樣對嗎?)

因為我本來希望記錄 物件在世界座標上的軸向然後計算旋轉軸跟角度就可以了結果發現
當我把
v0 當作 物件座標的軸向 例如 X 軸
v1 當作 世界座標中的 X 軸
計算這兩個單位向量的法向量 當作旋轉軸 取 acos ( v0 dot v1 ) 當作旋轉角
但是發現這樣當兩個向量成 180 度時 沒有辦法算出法向量
所以必須要保留旋轉軸 而不保留世界座標中的同一軸向

現在想想直接保留 4x4 的矩陣 三個軸向 跟 位置都保留下來了 好像也行 ^^"
  | 1 0 0 tx | 前面的三個 Column 相當於座標的 X Y Z 軸
  | 0 1 0 ty |
  | 0 0 1 tz |
  | 0 0 0 1 |

直接把 Y 軸 當作旋轉軸
計算矩陣中的 X 軸 與 物件座標 X 軸的夾角當作旋轉角度 ( 這樣對嗎?)

2.如果我希望對 讓物件的姿態 隨著 世界座標的 X 軸旋轉 5 度 那我就直接用 X 軸的旋轉矩陣對旋轉軸進行乘法(這樣對嗎?)
這個就變成

// 自己寫的矩陣類別 預設值是單位矩陣
CMatrix Matrix; 跟 OpenGL 矩陣有點像 函數會對目前內容累積
Matrix.SetRotate( 5,1,0,0) <--- 目前的 矩陣乘上 旋轉的矩陣
m_ObjRotateAxis = Matrix * m_ObjRotateAxis;
......... 現在想想 如果是 4x4 的矩陣 好像也可以乘 不過要對 座標的部份作平移
那就變成了
CMatrix Matrix; // 單位矩陣
Matrix.SetTranslate(tx,ty,tz); // 等於 單位矩陣 * 平移矩陣
Matrix.SetRotate( 5,1,0,0) // 等於 單位矩陣 * 平移矩陣 * 旋轉矩陣
Matrix.SetTranslate(-tx,-ty,-tz); // 等於 單位矩陣 * 平移矩陣 * 旋轉矩陣 * 平移矩陣
這便成 先平移回原點 旋轉 在平移回來
m_ObjRotateAxis = Matrix * m_ObjRotateAxis;

3.進行姿態控制之前 必須需要先檢查要旋轉的旋轉軸 是否與現在的旋轉軸相同 相同的話 就直接累計在旋轉角度上(這樣對嗎?)

如果依個點在 X 軸上如(2,0,0) 如果我對 X 軸旋轉的話 這個點是不會動的
這樣的話 如果 指定的旋轉軸 等於 m_ObjRotateAxis 或是 -m_ObjRotateAxis
應該是修改 m_ObjRotateAngle (這樣對嗎?)

4.這個方法的前提是要已經知道旋轉後同一軸向的位置 有時候我只能得到 (rx,ry,rz) 時 我該怎麼把它變成旋轉軸呢?



作者 : ma_hty(白老鼠(Gary))討論區板主 OpenGL卓越專家DirectX優秀好手C++頂尖高手貼文超過2000則人氣指數超過70000點
[ 貼文 2189 | 人氣 89850 | 評價 10120 | 評價/貼文 4.62 | 送出評價 79 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/1/14 上午 09:26:33
這些問題我答過了.

還有, 建議你 直接使用 四元數 吧, 別再自己併奇怪的旋轉功能, 你再努力去併自己的奇怪旋轉功能, 也及不上 四元數 的, 前人把問題了解透徹之後, 提供了 四元數 這個答案, 為什麼你不去用?!

正確的方法 也許只有幾個, 但是 錯誤的方法, 是無窮無盡的, 別再想為什麼 錯, 沒意義的, 你應該想 如何做對 呀.
作者 : cromayen2000(CROMAYEN2000) OpenGL卓越專家貼文超過500則人氣指數超過10000點
[ 貼文 646 | 人氣 22308 | 評價 2260 | 評價/貼文 3.5 | 送出評價 38 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/1/14 上午 09:54:42
ㄜ 要怎麼弄才是對的?
作者 : ma_hty(白老鼠(Gary))討論區板主 OpenGL卓越專家DirectX優秀好手C++頂尖高手貼文超過2000則人氣指數超過70000點
[ 貼文 2189 | 人氣 89850 | 評價 10120 | 評價/貼文 4.62 | 送出評價 79 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/1/14 下午 05:04:03
直接使用 四元數
作者 : cromayen2000(CROMAYEN2000) OpenGL卓越專家貼文超過500則人氣指數超過10000點
[ 貼文 646 | 人氣 22308 | 評價 2260 | 評價/貼文 3.5 | 送出評價 38 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/1/14 下午 08:12:31
是這樣的意思嗎?

把物件姿勢的三軸還有座標 放進矩陣裡面像這樣 M

  X軸 Y軸 Z軸 位置
| 1 0 0 tx |
| 0 1 0 ty |
| 0 0 1 tz |
| 0 0 0 1 |

要旋轉的資料 變成四元素的旋轉矩陣 MT

然後兩個相乘 M = MT * M

 板主 : 徵求中
 > 影像處理與計算機圖學 - 討論區
 - 最近熱門問答精華集
 - 全部歷史問答精華集
 - 影像處理與計算機圖學 - 知識庫
  ■ 全站最新Post列表
  ■ 我的文章收藏
  ■ 我最愛的作者
  ■ 全站文章收藏排行榜
  ■ 全站最愛作者排行榜
  ■  月熱門主題
  ■  季熱門主題
  ■  熱門主題Top 20
  ■  本區Post排行榜
  ■  本區評價排行榜
  ■  全站專家名人榜
  ■  全站Post排行榜
  ■  全站評價排行榜
  ■  全站人氣排行榜
 請輸入關鍵字 
  開始搜尋
 
Top 10
評價排行
影像處理與計算機圖學
1 Linkin 780 
2 CrazyStar 400 
3 青衫 360 
4 白老鼠(Gary) 330 
5 悠悠深藍 220 
6 none 220 
7 shou 200 
8 ultra 200 
9 ghost 140 
10 ozzy 130 
影像處理與計算機圖學
  專家等級 評價  
  一代宗師 10000  
  曠世奇才 5000  
  頂尖高手 3000  
  卓越專家 1500  
  優秀好手 750  
Microsoft Internet Explorer 6.0. Screen 1024x768 pixel. High Color (16 bit).
2000-2019 程式設計俱樂部 http://www.programmer-club.com.tw/
0.0625