第四課
     
  在上一課中我已經教你如何在三角形和四邊形中加入色彩. 在本課程中, 我將教你如何繞著軸來旋轉這些彩色的物件.

使用上一課的程式碼, 我們再加入 DrawGLScene 程序中. 我會在下面重新改寫整個程序, 所以你很容易的可以分辨出哪些是新加入的, 哪些是要被取代掉的.

我們將開始加入兩個變數來追蹤每個物件的旋轉. 我們在程式的最開頭加入這兩個變數. 你也會注意到有兩行新的程式碼在 BOOL keys[256] 之後. 這兩行就是用來設定浮點變數, 所以我們就可以很準確的旋轉物件了. 浮點數允許有小數點的值, 也就是指我們不會受限於只能使用 1, 2, 3 的度數, 而可以使用 1.1, 1.7, 2.3, 甚至是更精確的 1.015. 你將會發現浮點數是 OpenGL 程式設計的要素.
 
     
#include <windows.h>						// Header File For Windows
#include <gl\gl.h>						// Header File For The OpenGL32 Library
#include <gl\glu.h>						// Header File For The GLu32 Library
#include <gl\glaux.h>						// Header File For The GLaux Library

HDC	hDC=NULL;						// Private GDI Device Context
HGLRC	hRC=NULL;						// Permanent Rendering Context
HWND	hWnd=NULL;						// Holds Our Window Handle

bool	keys[256];						// Array Used For The Keyboard Routine
bool	active=TRUE;						// Window Active Flag
bool	fullscreen=TRUE;					// Fullscreen Flag Set To TRUE By Default

GLfloat	rtri;							// Angle For The Triangle ( NEW )
GLfloat	rquad;							// Angle For The Quad     ( NEW )
     
  現在我們需要修改 DrawGLScene() 程式碼. 我會重新改寫整個程序. 你應該很容易的可以分辨出來, 我對原本的程式碼做了什麼修改. 我將解釋為什麼這幾行要被修改, 以及哪些是新增加的. 下一段的程式碼, 則跟上一課完全一樣.  
     
int DrawGLScene(GLvoid)						// Here's Where We Do All The Drawing
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear The Screen And The Depth Buffer
	glLoadIdentity();					// Reset The View
	glTranslatef(-1.5f,0.0f,-6.0f);				// Move Into The Screen And Left
     
  接著這一行程式碼是新的. glRotatef(Angle,Xvector,Yvector,Zvector) 表示物件繞著一個軸旋轉. 你將會用到一堆這個命令. 角度是一些數值 (通常存放一個變數) 表示你要旋轉物件多少的值. Xvector, Yvector 和 Zvector 參數則一起表示哪一個向量的旋轉會發生. 如果你用數值 (1,0,0), 你所描述的就是一個面向 x 軸右邊一個單位的向量. 當數值為 (-1,0,0), 你所描述的就是一個沿著 x 軸一個單位的向量, 不過這時是面向左邊.

D. Michael Traub: 已經提供以上對於 Xvector, Yvector 和 Zvector 參數的說明.

為了能更容易瞭解 X, Y 和 Z 的旋轉, 我將會用例子來解釋.

X 軸 - 就好像是一個桌上型的圓鋸. 旋轉軸由左而右通過圓鋸刀刃的軸心 (就像是 OpenGL 中的 x 軸). 尖銳的鋸齒就繞著 x 軸 (就像是旋轉軸通過圓鋸的中心), 依照刀鋒的旋轉方向, 而表示出旋入或旋出的情況. 當我們在 OpenGL 中的 x 軸旋轉某個東西時就會是這樣子的.

Y 軸 - 想像你站在田野的中心, 有一個巨大的龍捲風朝你而來. 龍捲風的中心由天空到地面 (由上而下, 就像是 OpenGL 中的 y 軸). 龍捲風中的灰塵和殘骸就繞著 y 軸旋轉 (龍捲風的中心), 由左而右或由右至左的轉著. 當我們繞著 OpenGL 中的 y 軸旋轉就像這樣子.

Z 軸 - 你正注視著正前方的電扇, 電扇的中心點面向你或是遠離你 (就像是 OpenGL 中的 z 軸). 風扇的葉面繞著 z 軸旋轉 (電扇的中心) 順時針或是逆時針方向. 當我們繞著 OpenGL 中的 z 軸旋轉就像這樣子.

所以在下一行的程式碼中, 如果 rtri 等於 7, 我們就會在 Y 軸上轉 7 (由左而右). 你可以試著試驗這段碼. 把 0.0f 的改為 1.0f, 1.0f 改為 0.1f, 這樣就會同時旋轉 X 和 Y 軸.
 
     
	glRotatef(rtri,0.0f,1.0f,0.0f);				// Rotate The Triangle On The Y axis ( NEW )
     
  下一段程式碼並沒有改變. 它畫出一個色彩豐富的混色三角形. 三角形會被畫在畫面的左邊, 而且將會繞著 Y 軸由左向右的旋轉.  
     
	glBegin(GL_TRIANGLES);					// Start Drawing A Triangle
		glColor3f(1.0f,0.0f,0.0f);			// Set Top Point Of Triangle To Red
		glVertex3f( 0.0f, 1.0f, 0.0f);			// First Point Of The Triangle
		glColor3f(0.0f,1.0f,0.0f);			// Set Left Point Of Triangle To Green
		glVertex3f(-1.0f,-1.0f, 0.0f);			// Second Point Of The Triangle
		glColor3f(0.0f,0.0f,1.0f);			// Set Right Point Of Triangle To Blue
		glVertex3f( 1.0f,-1.0f, 0.0f);			// Third Point Of The Triangle
	glEnd();						// Done Drawing The Triangle
     
  你將會注意到下面的程式碼, 我們加入另一個 glLoadIdentity(). 這麼做是為了重新設定觀點. 如果我們沒有重新設定觀點; 如果我們在物件被旋轉後做一些轉換, 那你將會得到無法預期的結果. 因為軸被旋轉了, 它所指向的方向就不會是你所想要的. 因此如果我們移往 X 軸的左邊, 可能得到的結果反而是移往上面或下面, 這要看你如何旋轉每個軸. 試著移除 glLoadIdentity() 這一行就會明瞭我的意思了.

只要場景被重新設定, 此時在我們做移動時, X 就會是左右向, Y 是上下, Z 則是進出畫面. 你將會注意到我們只向右移動 1.5 而不是像上一課的移動 3.0. 因為當你重新設定畫面, 我們的焦點就會移回畫面的中心, 也就是指我們不是在左邊的 1.5 單位, 而被設回 0.0. 所以要移往原點右邊 1.5, 就不必先由左邊移 1.5 回到原點, 再向右移 1.5 (總共是 3.0), 而只要由中心點向右移動 1.5 個單位就好了.

在我們移往畫面右邊新的位置後, 我們就繞著 X 軸旋轉四方形. 這會讓正方形上下旋轉.
 
     
	glLoadIdentity();					// Reset The Current Modelview Matrix
	glTranslatef(1.5f,0.0f,-6.0f);				// Move Right 1.5 Units And Into The Screen 6.0
	glRotatef(rquad,1.0f,0.0f,0.0f);			// Rotate The Quad On The X axis ( NEW )
     
  這一段程式碼仍然是相同的. 它用個四邊形畫出藍色的正方形. 它會在畫面的右邊畫出經過旋轉後的正方形.  
     
	glColor3f(0.5f,0.5f,1.0f);				// Set The Color To A Nice Blue Shade
	glBegin(GL_QUADS);					// Start Drawing A Quad
		glVertex3f(-1.0f, 1.0f, 0.0f);			// Top Left Of The Quad
		glVertex3f( 1.0f, 1.0f, 0.0f);			// Top Right Of The Quad
		glVertex3f( 1.0f,-1.0f, 0.0f);			// Bottom Right Of The Quad
		glVertex3f(-1.0f,-1.0f, 0.0f);			// Bottom Left Of The Quad
	glEnd();						// Done Drawing The Quad
     
  下面這兩行是新的碼. 想想看 rtri 和 rquad 就像是儲存器. 在程式的最上面我們建了這些儲存器 (GLfloat rtri, 和 GLfloat rquad). 當我們建立儲存器時, 儲存器內什麼也沒有. 下列第一行在儲存器中增加 0.2. 所以每次在這段程式碼之後, 我們檢查 rtri 中的數值, 然後增加 0.2. rquad 則是遞減 0.15. 所以每次檢查 rquad, 它就會減少 0.15. 遞減的旋轉會讓物件旋轉的方向與遞增時相反.

試著改變下一行的 + 為 -, 來看看物件如何往反方向旋轉. 試著把值由 0.2 改為 1.0. 較大的值時, 物件會轉的比較快. 值較小時, 物件會轉的比較慢.
 
     
	rtri+=0.2f;						// Increase The Rotation Variable For The Triangle ( NEW )
	rquad-=0.15f;						// Decrease The Rotation Variable For The Quad     ( NEW )
	return TRUE;						// Keep Going
}
     
  最後改變切換視窗 / 全螢幕模式的程式碼, 如此一來視窗上面的標題就會正確顯示了.  
     
			if (keys[VK_F1])			// Is F1 Being Pressed?
			{
				keys[VK_F1]=FALSE;		// If So Make Key FALSE
				KillGLWindow();			// Kill Our Current Window
				fullscreen=!fullscreen;		// Toggle Fullscreen / Windowed Mode
				// Recreate Our OpenGL Window ( Modified )
				if (!CreateGLWindow("NeHe's Rotation Tutorial",640,480,16,fullscreen))
				{
					return 0;		// Quit If Window Was Not Created
				}
			}
     
  在這個課程中, 我已經試著很仔細的解釋了, 如何繞著軸旋轉物件. 玩玩看這個程式碼, 試著繞著 Z 軸, X & Y 軸旋轉物件, 甚至是三軸一起 :) 如果你有意見或是問題, 請寄電子郵件告訴我. 如果你認為我的註解不正確, 或者某些段落的程式可以再更好, 請讓我知道. 我想盡我最大努力作最好的 OpenGL 教學課程, 我很有興趣聽聽你們的反應.

Jeff Molofee (NeHe)

* 下載 Visual C++ 程式碼給本課程的.
* 下載 Visual Basic 程式碼給本課程的. ( Conversion by Ross Dawson )
* 下載 Delphi 程式碼給本課程的. ( Conversion by Peter De Jaegher )
* 下載 ASM 程式碼給本課程的. ( Conversion by Foolman )
* 下載 Visual Fortran 程式碼給本課程的. ( Conversion by Jean-Philippe Perois )
* 下載 Linux 程式碼給本課程的. ( Conversion by Richard Campbell )
* 下載 Irix 程式碼給本課程的. ( Conversion by Lakmal Gunasekara )
* 下載 Solaris 程式碼給本課程的. ( Conversion by Lakmal Gunasekara )
* 下載 Mac OS 程式碼給本課程的. ( Conversion by Anthony Parker )
* 下載 Power Basic 程式碼給本課程的. ( Conversion by Angus Law )
* 下載 BeOS 程式碼給本課程的. ( Conversion by Chris Herborth )
* 下載 Java 程式碼給本課程的. ( Conversion by Darren Hodges )
* 下載 MingW32 & Allegro 程式碼給本課程的. ( Conversion by Peter Puck )
* 下載 Borland C++ Builder 4.0 程式碼給本課程的. ( Conversion by Patrick Salmons )
* 下載 Python 程式碼給本課程的. ( Conversion by John )
 
     
 
Back To NeHe Productions!
回到 OpenGL 教學索引
中文版由 Macbear 翻譯