2013年11月24日 星期日

[openGL] 3D中 glTranslate()、glRotate() 和 glScale() 的實作

[一] glTranslate()


1.    拿來移動物體
2.    原理:

dx, dy, dz 是各個方向的移動距離
| x' |      | 1  0  0  dx |      | x |
| y' |      | 0  1  0  dy |      | y |
| z' |  =  | 0  0  1  dz |   ˙  | z |
| 1 |       | 0  0  0  1  |      | 1 |

[二] glRotate()


1.    物體繞某個軸線旋轉
2.    原理:

a是旋轉角度

[繞 y 軸旋轉]
| x' |      | 1     0          0        0 |      | x |
| y' |      | 0  cos(a)  -sing(a)  0 |      | y |
| z' |  =  | 0  sin(a)    cos(a)   0 |   ˙  | z |
| 1 |       | 0    0          0        1 |      | 1 |


[繞 x 軸旋轉]
| x' |      | cos(a)   0   sin(a)    0 |      | x |
| y' |      |     0       1     0        0 |      | y |
| z' |  =  | -sin(a)   0  cos(a)    0 |   ˙  | z |
| 1 |       |    0       0     0        1 |      | 1 |

3.    如果有要繞 x 軸轉也有要繞 y 軸轉,那就把兩個 matrix 乘起來就好

[三] glScale()

1.    放大縮小物體
2.    原理:

sx, sy, sz 是各個方向的放大縮小大小
| x' |      | sx  0  0  0 |      | x |
| y' |      | 0  sy  0  0 |      | y |
| z' |  =  | 0  0  sz  0 |   ˙  | z |
| 1 |       | 0  0  0  1  |      | 1 |

[四] 困難


因為在 rotate 之後,單位向量會跑掉,所以此時就須要做 glLoadIdentity(),不然在 translate的話,移動的方向也會不如預期,這也是為什麼人家說你要先移動之後再旋轉,因為先旋轉之後再移動,單位向量跑掉,之後的移動方向也會錯誤,此時,你可能會說,那我先旋轉 -> loadIdentity() -> 移動,這樣不就好了嗎? 錯,因為旋轉完之後 load identity,會把最初的資訊讀進 matrix,這樣就變回沒有旋轉的樣子了,所以每次都要先移動之後再做旋轉,這樣才會正確,如此一來就可以很清楚保留 matrix 資訊的功用到底是什麼了。

最後,因為這是我自己讀現代寫的 function ,所以只是拿來記錄情況,方便我用來回憶這些動作的原理。


(p.s) 這一部分比較需要會線性代數,其實不過就只是把新的 model matrix算出來,再重新跟 modelview 和 projection 乘在一起就好

沒有留言:

張貼留言