因爲可能要做太陽系,所以通過此程序先了解一下,順便學習以下知識。沒有列出來的,代碼裏如果有註釋的話,也要看一下。
學習要點
理解glMatrixMode()設置的幾種變換。
瞭解gluPerspective()和gluLookAt()的參數,清楚他們該如何使用的。理解OpenGL下的三維座標的展示,觀察一個物體的角度。
理解深度緩衝區。
瞭解怎麼用glutSolidSphere()畫一個圓。
關於旋轉和平移的用法,glRotatef(),glTranslatef()。
相關學習資料
要點簡單解析
其實就是註釋裏寫的,解釋的比較簡單,主要是函數參數解釋,詳細解釋和深入理解還得看其他的文章。
投影變換
glMatrixMode(GL_PROJECTION);
gluPerspective(75, 1, 1, 2000);
在投影變換下才能設置。透視投影空間, 近大遠小的那種感覺。
參數:
眼睛睜開的角度,實際窗口的縱橫比,眼睛距離近處的距離,遠處的裁面(即後面兩個參數表示眼睛能看的多遠)。
函數設置投視角設爲75度, 在y軸方向上以角度爲單位的視野, 度數越大離的越遠看的越小。
模型變換
在模型變換下可以對矩陣進行變換,移動旋轉縮放等。
glMatrixMode(GL_MODELVIEW);
gluLookAt(0, -200, 200, 0, 0, 0, 0, 0, 1)
參數:每三個參數表示一個座標
eye眼睛在世界座標系的位置,center眼睛看的那個點的座標,up觀察者本身的方向,比如正立還是倒立異或某一個角度在看。
函數表示在(0, -200, -200)的位置正着向(0, 0, 0)點看去。
深度緩衝區
opengl默認是沒有開啓深度檢測的,也就是說, 後繪製的物體覆蓋先繪製的物體。
當開啓更新深度緩衝區的功能,也就是,如果通過比較後,深度值發生變化了,會進行更新深度緩衝區的操作。啓動後,OpenGL就可以跟蹤在Z軸上的像素,這樣,它只會再那個像素前方沒有東西時,纔會繪製這個像素。
#include<Windows.h>
#include<GL\glut.h>
//太陽、地球和月亮
//假設每個月都是30天
//一年12個月,共是360天
static int day = 200; // day的變化:從0到359
void myDisplay(void)
{
/*用來開啓更新深度緩衝區的功能,也就是,如果通過比較後深度值發生變化了,
會進行更新深度緩衝區的操作。啓動它,OpenGL就可以跟蹤再Z軸上的像素,
這樣,它只會再那個像素前方沒有東西時,纔會繪畫這個像素。*/
glEnable(GL_DEPTH_TEST);
/*opengl默認是沒有開啓深度檢測的,也就是說,
後繪製的物體覆蓋先繪製的物體(顏色緩衝區中,先繪製的物體 被 後繪製的物體 覆蓋)。*/
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION); //投影變換
glLoadIdentity(); //調用單位矩陣
//投視角設爲75度, 在y軸方向上以角度爲單位的視野, 度數越大離的越遠看的越小
//參數 眼睛睜開的角度 實際窗口的縱橫比 眼睛距離近處的距離 遠處的裁面(即眼睛能看的多遠)
gluPerspective(75, 1, 1, 2000); //透視投影空間, 近大遠小
glMatrixMode(GL_MODELVIEW); //模型變換
glLoadIdentity();
//eye眼睛在世界座標系的位置,
//center眼睛看的那個點的座標,
//up觀察者本身的方向,比如正立還是倒立異或某一個角度在看
gluLookAt(0, -200, 200, 0, 0, 0, 0, 0, 1);
//繪製紅色的“太陽”
glColor3f(1.0f, 0.0f, 0.0f);
glutSolidSphere(69.6, 100, 100);
//繪製藍色的“地球”
glColor3f(0.0f, 0.0f, 1.0f);
glRotatef(day / 360.0*360.0, 0.0f, 0.0f, -1.0f);
//相對當前所在屏幕位置移動
glTranslatef(150, 0.0f, 0.0f);
glutSolidSphere(15.945, 100, 100);
//繪製黃色的“月亮”
glColor3f(1.0f, 1.0f, 0.0f);
glRotatef(day / 30.0*360.0 - day / 360.0*360.0, 0.0f, 0.0f, -1.0f);
glRotatef(day / 30.0*360.0, 0.0f, 0.0f, -1.0f);
glTranslatef(38, 0.0f, 0.0f);
glutSolidSphere(4.345, 100, 100);
//glFlush(); //這句加不加好像都行,因爲用的是雙緩衝區
glutSwapBuffers();
}
void myIdle(void)
{
Sleep(50);
++day;
if (day >= 360)
day = 0;
myDisplay();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitWindowPosition(200, 100);
glutInitWindowSize(600, 600);
glutCreateWindow("平移旋轉");
glutDisplayFunc(&myDisplay);
//如果不存在其他尚未完成的,就執行這個函數(當沒有窗口事件到達時,就執行這個回調函數
glutIdleFunc(&myIdle);
glutMainLoop();
return 0;
}