320 likes | 539 Views
Viewing. 靜宜大學資工系 蔡奇偉 副教授 2003-2005. 大綱. 簡介 端點座標的轉換. 簡介. 底下我們比較用 OpenGL 程式產生場景畫面和用相機拍照的過程:. 相機 OpenGL 1. 選定相機位置和拍攝的角度 viewing transformation 2. 安排場景中物件的位置 modeling transformation 3. 選擇鏡頭或調整縮放度 projection transformation 4. 決定沖印的尺吋 viewport transformation. 端點座標的轉換.
E N D
Viewing 靜宜大學資工系 蔡奇偉 副教授 2003-2005
大綱 • 簡介 • 端點座標的轉換
簡介 底下我們比較用 OpenGL 程式產生場景畫面和用相機拍照的過程: 相機 OpenGL 1. 選定相機位置和拍攝的角度 viewing transformation 2. 安排場景中物件的位置 modeling transformation 3. 選擇鏡頭或調整縮放度 projection transformation 4. 決定沖印的尺吋 viewport transformation
Model/View Transformation 由於相機和物件的座標變換是彼此相對的,譬如:物件固定不動而相機往左移 10 單位等同於相機不動而物件往右移 10 單位,所以 OpenGL 把兩者合併在一起,稱為 Model/View Transformation。 由於 OpenGL 使用矩陣堆疊,因此我們應該按照下列順序來安排程式碼: • 設定相機的位置、角度、與拍攝方向。 • 物件的座標變換,如平移、旋轉、或放大縮小。 • 建立物件模型(用物件座標系統) 經過這一道座標變換我們得到物件在相機座標系統下的座標,稱之為 eye coordinates。
Projection Transformation 若指定了剪裁面(clipping planes),OpenGL 先截除掉落在剪裁面以外的物件部分,然後再實施透視(perspective)投影或正交(orthogonal)投影的轉換。此外,落在視體( viewing volume)之外的物件部分也會自動地被截除。 經過這一道轉換所得的座標稱為 clip coordinates。
Perspective division 這一個階段把 clip coordinate 的齊次座標 (x, y, z, w) 改成三維座標 (x/w, y/w, z/w),稱之為 normalized device coordinates(正規化裝置座標)。
Viewport Transformation 所謂 viewport(視埠)是指視窗上的一塊矩形區域。透過 viewport transformation,normalized device coordinates 被轉換成視窗座標。 你可以設定 viewpot 的原點位置、寬度、和高度。調整寬和高之間的比例可以產生放大、縮小、壓扁、拉長的效果。
範例 /* * cube.c * This program demonstrates a single modeling transformation, * glScalef() and a single viewing transformation, gluLookAt(). * A wireframe cube is rendered. */ #include <GL/glut.h> void init(void) { glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel (GL_FLAT); }
void display(void) { glClear (GL_COLOR_BUFFER_BIT); glColor3f (1.0, 1.0, 1.0); glLoadIdentity (); /* clear the matrix */ /* viewing transformation */ gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); /* modeling transformation */ glScalef (1.0, 2.0, 1.0); /* model */ glutWireCube (1.0); glFlush (); } up 方向 注視點的座標 相機位置的座標
void reshape (int w, int h) { glViewport (0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode (GL_PROJECTION); glLoadIdentity (); /* perspective projection */ glFrustum (-1.0, 1.0, -1.0, 1.0, 1.5, 20.0); glMatrixMode (GL_MODELVIEW); }
int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (500, 500); glutInitWindowPosition (100, 100); glutCreateWindow (argv[0]); init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMainLoop(); return 0; }
OpenGL 相關的函式 • 矩陣類別 • 通用的矩陣函式 • glLoadIdentity ()、 • glLoadMatrix{fd} () • glMultMatrix{fd} () • glPushMatrix() • glPopMatrix() • 簡易的幾何變換函式 • glTranslate{fd} () • glRotate{fd} () • glScale{fd} () • gluLookAt() • 投影變換函式 • 透視投影:glFrustum() & gluPerspective() • 正交投影:glOrtho() • glViewport
矩陣類別 OpenGL 有三個矩陣堆疊,這些堆疊用來處理不同的操作模式。所以在操作矩陣之前,你必須使用 glMatrixMode() 函式來選取矩陣堆疊。 void glMatrixMode (Glenum mode) 參數 mode 可為下列的常數: GL_MODELVIEW: 矩陣操作應用在「模形和攝相」堆疊上。 GL_PROJECTION : 矩陣操作應用在「投影」堆疊上。 GL_TEXTURE : 矩陣操作應用在「紋理」堆疊上。
矩陣堆疊 矩陣堆疊最上面的矩陣稱為「目前矩陣(current matrix)」。 current matrix C top 目前矩陣是目前的幾何變換,會自動地應用在端點上,即端點 v變成 Cv。
清除目前矩陣 void glLoadIdentity (void) 把目前矩陣設成 44 的單位矩陣 I C top top
void glLoadMatrix{fd} (Type *m) 把目前矩陣設成參數 m所指定的 44 矩陣。通常m是 16 個元素的陣列:[m1, m2, …, m16],代表底下的 44 矩陣: M C top top
對 C/C++ 二維陣列 m[4][4] 而言,元素 m[i][j] 相當於上述矩陣的第 i行和第 j 列,這樣的儲存順序並不同於 OpenGL 矩陣的元素順序。因此,我們最好用一維陣列 m[16] 而不用二維陣列 m[4][4] 來儲存 OpenGL 矩陣,以避免混淆或錯誤。
void glMultMatrix{fd} (Type *m) 參數m是一個有 16 個元素的陣列代表 44 矩陣。若目前矩陣是 C和 m 代表矩陣 M,則此函式把目前矩陣改成矩陣的乘積 CM。 CM C top top
void glPushMatrix (void) 把矩陣堆疊最上層的矩陣往下推一層,並拷貝其值至新的最上層矩陣。這個函式通常用來儲存目前矩陣。 C top C C top
top C top C void glPopMatrix (void) 移除矩陣堆疊最上層的矩陣。這個函式通常用來恢復之前的目前矩陣。
glPushMatrix() 和 glPopMatrix() 通常用來把定義在物件座標系統下的物件,轉換至世界座標系統中。 在右邊的程式碼中,我們用 glPushMatrix() 來儲存目前矩陣之後,呼叫 OpenGL 的幾何轉換函式來設定物件在世界座標系統中的位置、方向,與大小。DrawObject() 函式則是在物件座標系統中繪製物件。最後,我們用glPopMatrix() 恢復原來的目前矩陣。 • glPushMatrix(); • glTranslated(…); • glRotated(…); • glScaled(…); • DrawObject(); • glPopMatrix();
void glTranslate{fd} (Type x, Type y, Type z) 把目前矩陣乘上平移矩陣 T(x, y, z)。 CT C top top
y (x,y,z) x z void glRotate{fd} (Type , Type x, Type y, Type z) 參數 是旋轉角度,參數 (x, y, z) 用來指定旋轉軸的方向,通常 (x, y, z) 是單位向量(即長度為 1)。 繞 x軸 度: glRotate{fd} (, 1.0, 0.0, 0.0) 繞 y軸 度: glRotate{fd} (, 0.0, 1.0, 0.0) 繞 z軸 度: glRotate{fd} (, 0.0, 0.0, 1.0)
void glScale{fd} (Type x, Type y, Type z) 參數x, y, 和 z 是在三個座標軸方向的放大或縮小的比例。此函式把目前矩陣乘上矩陣 S(x, y, z), CS C top top
void gluLookAT ( • /* 相機位置 */ • GLdouble eyex, GLdouble eyey, GLdouble eyez, • /* 注視點位置 */ • GLdouble cx, GLdouble cy, GLdouble cz, • /* 相機朝上的方向 */ • GLdouble upx, GLdouble upy, GLdouble upz, • )
void glFrustum ( • GLdouble left, GLdouble right, GLdouble bottom, • GLdouble top, GLdouble near, GLdouble far • ) 呈像面
void gluPerspective ( • GLdouble fovy, GLdouble aspect, • GLdouble near, GLdouble far • ) fovy: yz平面上的視角。
void glOrtho ( • GLdouble left, GLdouble right, GLdouble bottom, • GLdouble top, GLdouble near, GLdouble far • )
width height (x, y) • void glViewport ( • GLint x, GLint y, GLsizei width, GLsizei height • ) 視窗 (0, 0)