图解opengl 3D 图形绘制实例
http://blog.csdn.net/bcbobo21cn/article/details/44200205
opengl環境配置
http://blog.csdn.net/bcbobo21cn/article/details/51044614#t4
以下的demo工程
http://pan.baidu.com/s/1pLgmScj
一 3D旋轉物體
碼碼:
//在窗口和全屏模式下切換,按ESC退出。#include <Windows.h> //Windows的頭文件 #include <gl/glut.h> //包含OpenGL實用庫HGLRC hRC=NULL; //窗口著色描述表句柄 HDC hDC=NULL;//OpenGL渲染描述表句柄 HWND hWnd=NULL; //保存窗口句柄 HINSTANCE hInstance; //保存程序實例bool keys[256];//保存鍵盤按鍵的數組 bool active=TRUE;//窗口的活動標志,缺省為TRUE bool fullscreen=TRUE; //全屏標志缺省,缺省設定成全屏模式GLfloat rtri;//用于三角形的角度 GLfloat rquad;//用于四邊形的角度LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);//WndProc的定義//重置OpenGL窗口大小 GLvoid ResizeGLScene(GLsizei width,GLsizei height) { if (height == 0) //防止被零除 { height =1;//將height設為1 }glViewport(0,0,width,height);//重置當前的視口 glMatrixMode(GL_PROJECTION);//旋轉投影矩陣 glLoadIdentity();//重置投影矩陣//設置視口的大小 gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);glMatrixMode(GL_MODELVIEW);//選擇模型觀察矩陣 glLoadIdentity();//重置模型觀察矩陣 }int InitGL(GLvoid)//對OpenGL進行設置 { glShadeModel(GL_SMOOTH);//啟用陰影平滑 glClearColor(0.0f,0.0f,0.0f,0.0f);//黑色背景 glClearDepth(1.0f);//設置深度緩存 glEnable(GL_DEPTH_TEST);//啟用深度測試 glDepthFunc(GL_LEQUAL);//所作深度測試的類型 glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);//告訴系統對透視進行修正return TRUE; }//進行繪制 int DrawGLScene(GLvoid) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清除屏幕和深度緩存 glLoadIdentity();//重置當前的模型觀察矩陣 glTranslatef(-1.5f,0.0f,-6.0f);//左移1.5單位,并移入屏幕6.0glRotatef(rtri,0.0f,1.0f,0.0f);//繞Y軸旋轉金字塔 glBegin(GL_TRIANGLES); //繪制金字塔各面glColor3f(1.0f,0.0f,0.0f);//設置當前色為紅色 glVertex3f(0.0f,1.0f,0.0f);//上頂點(前側面) glColor3f(0.0f,1.0f,0.0f);//設置當前色為綠色 glVertex3f(-1.0f,-1.0f,1.0f);//左下(前側面) glColor3f(0.0f,0.0f,1.0f);//設置當前色為藍色 glVertex3f(1.0f,-1.0f,1.0f);//右下(前側面)glColor3f(1.0f,0.0f,0.0f);//設置當前色為紅色 glVertex3f(0.0f,1.0f,0.0f);//上頂點(右側面) glColor3f(0.0f,1.0f,0.0f);//設置當前色為綠色 glVertex3f(1.0f,-1.0f,1.0f);//左下(右側面) glColor3f(0.0f,0.0f,1.0f);//設置當前色為藍色 glVertex3f(1.0f,-1.0f,-1.0f);//右下(右側面)glColor3f(1.0f,0.0f,0.0f);//設置當前色為紅色 glVertex3f(0.0f,1.0f,0.0f);//上頂點(后側面) glColor3f(0.0f,1.0f,0.0f);//設置當前色為綠色 glVertex3f(1.0f,-1.0f,-1.0f);//左下(后側面) glColor3f(0.0f,0.0f,1.0f);//設置當前色為藍色 glVertex3f(-1.0f,-1.0f,-1.0f);//右下(后側面)glColor3f(1.0f,0.0f,0.0f);//設置當前色為紅色 glVertex3f(0.0f,1.0f,0.0f);//上頂點(左側面) glColor3f(0.0f,1.0f,0.0f);//設置當前色為綠色 glVertex3f(-1.0f,-1.0f,-1.0f);//左下(左側面) glColor3f(0.0f,0.0f,1.0f);//設置當前色為藍色 glVertex3f(-1.0f,-1.0f,1.0f);//右下(左側面)glEnd();//三角形繪制結束glLoadIdentity();//重置模型觀察矩陣 glTranslatef(1.5f,0.0f,-7.0f);//先右移再移入屏幕 glRotatef(rquad,1.0f,1.0f,1.0f);//繞XYZ軸旋轉立方體glBegin(GL_QUADS); //繪制正方形 glColor3f(0.0f,1.0f,0.0f);//將當前色設置為綠色 //頂面 glVertex3f(1.0f,1.0f,-1.0f);//右上 glVertex3f(-1.0f,1.0f,-1.0f);//左上 glVertex3f(-1.0f,1.0f,1.0f);//左下 glVertex3f(1.0f,1.0f,1.0f);//右下//橙色 glColor3f(1.0f,0.5f,0.0f);//底面 glVertex3f(1.0f,-1.0f,-1.0f);//右上 glVertex3f(-1.0f,-1.0f,-1.0f);//左上 glVertex3f(-1.0f,-1.0f,1.0f);//左下 glVertex3f(1.0f,-1.0f,1.0f);//右下//紅色 glColor3f(1.0f,0.0f,0.0f); //前面 glVertex3f(1.0f,1.0f,1.0f);//右上 glVertex3f(-1.0f,1.0f,1.0f);//左上 glVertex3f(-1.0f,-1.0f,1.0f);//左下 glVertex3f(1.0f,-1.0f,1.0f);//右下//黃色 glColor3f(1.0f,1.0f,0.0f); //后面 glVertex3f(1.0f,1.0f,-1.0f);//右上 glVertex3f(-1.0f,1.0f,-1.0f);//左上 glVertex3f(-1.0f,-1.0f,-1.0f);//左下 glVertex3f(1.0f,-1.0f,-1.0f);//右下//藍色 glColor3f(0.0f,0.0f,1.0f); //左面 glVertex3f(-1.0f,1.0f,1.0f);//右上 glVertex3f(-1.0f,1.0f,-1.0f);//左上 glVertex3f(-1.0f,-1.0f,-1.0f);//左下 glVertex3f(-1.0f,-1.0f,1.0f);//右下//紫羅蘭色 glColor3f(1.0f,0.0f,1.0f); //右面 glVertex3f(1.0f,1.0f,1.0f);//右上 glVertex3f(1.0f,1.0f,-1.0f);//左上 glVertex3f(1.0f,-1.0f,-1.0f);//左下 glVertex3f(1.0f,-1.0f,1.0f);//右下glEnd();//<控制旋轉速度> rtri +=0.02f; //增加三角形的旋轉變量 rquad -=0.015f; //減少四邊形的旋轉變量return TRUE; }GLvoid KillGLWindow(GLvoid)//正常銷毀窗口 { if(fullscreen)//是否處于全屏模式 { ChangeDisplaySettings(NULL,0); //是的話,切換回桌面 ShowCursor(TRUE);//顯示鼠標指針 }if(hRC)//是否擁有OpenGL渲染描述表 { if(!wglMakeCurrent(NULL,NULL)) //能否是否DC和RC描述表 { MessageBox(NULL,"釋放DC或RC失敗。","關閉錯誤",MB_OK | MB_ICONINFORMATION ); }if(!wglDeleteContext(hRC)) //能否刪除RC { MessageBox(NULL,"釋放RC失敗。","關閉錯誤",MB_OK | MB_ICONINFORMATION ); }hRC = NULL; }if(hDC && !ReleaseDC(hWnd,hDC)) //能否釋放DC { MessageBox(NULL,"釋放DC失敗。","關閉錯誤",MB_OK | MB_ICONINFORMATION ); hDC = NULL; }if(hWnd && !DestroyWindow(hWnd)) //能否銷毀窗口 { MessageBox(NULL,"釋放窗口句柄失敗。","關閉錯誤",MB_OK | MB_ICONINFORMATION ); hWnd = NULL; }if(!UnregisterClass("OpenGL",hInstance)) //能否注銷窗口類 { MessageBox(NULL,"不能注銷窗口類。","關閉錯誤",MB_OK | MB_ICONINFORMATION ); hInstance = NULL; } }BOOL CreateGLWindow(char * title,int width,int height,int bits,bool fullscreenflag) { GLuint PixelFormat;//保存查找匹配的結果 WNDCLASS wc;//窗口類結構 DWORD dwExStyle; //擴展窗口風格 DWORD dwStyle;//窗口風格 RECT WindowRect;//取得矩形的左上角和右下角的坐標值 WindowRect.left=(long)0;//將Left設為0 WindowRect.right=(long)width;//將Right設為要求的寬度 WindowRect.top=(long)0; WindowRect.bottom=(long)height;fullscreen = fullscreenflag;//設置全局全屏標志hInstance = GetModuleHandle(NULL);//取得窗口的實例 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;//移動時重畫,并為窗口取得DC wc.lpfnWndProc = WndProc;//WndProc處理消息 wc.cbClsExtra = 0;//無額外窗口數據Specifies the number of extra bytes to allocate following the window-class structure. wc.cbWndExtra = 0; //無額外窗口數據Specifies the number of extra bytes to allocate following the window instance. wc.hInstance = hInstance;//設置實例 wc.hIcon = LoadIcon(NULL,IDI_WINLOGO);//裝入缺省圖標 wc.hCursor = LoadCursor(NULL,IDC_ARROW);//裝入鼠標指針 wc.hbrBackground = NULL; //GL不需要背景 wc.lpszMenuName = NULL ; //不需要菜單 wc.lpszClassName = "OpenGL"; //設定類名字if(!RegisterClass(&wc)) //嘗試注冊窗口類 { MessageBox(NULL,"注冊窗口失敗","錯誤",MB_OK | MB_ICONEXCLAMATION); return FALSE; }if(fullscreen) { DEVMODE dmScreenSettings; //設備模式 memset(&dmScreenSettings,0,sizeof(dmScreenSettings));//確保內存清空為零 dmScreenSettings.dmSize=sizeof(dmScreenSettings);//Devmode結構的大小 dmScreenSettings.dmPelsWidth = width;//所選屏幕寬度 dmScreenSettings.dmPelsHeight = height;//所選屏幕高度 dmScreenSettings.dmBitsPerPel = bits; //每像素所選的色彩濃度 dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;//嘗試設置顯示模式并返回結果。注:CDS_FULLSCREEN移去了狀態條。 if(ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) { //若模式失敗,提供兩個選項:退出或在窗口內運行。 if(MessageBox(NULL,"全屏模式在當前顯卡上設置失敗!\n使用窗口模式?", "提示",MB_YESNO | MB_ICONEXCLAMATION) == IDYES) { fullscreen = FALSE;//選擇窗口模式 } else { //彈出一個對話框,告訴用戶程序結束 MessageBox(NULL,"程序將被關閉","錯誤",MB_OK | MB_ICONSTOP); return FALSE; } } }if(fullscreen) { dwExStyle = WS_EX_APPWINDOW; //擴展窗體風格 dwStyle = WS_POPUP; //窗體風格 ShowCursor(FALSE); //隱藏鼠標指針 } else { dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;//擴展窗體風格 dwStyle = WS_OVERLAPPEDWINDOW; //窗體風格 }AdjustWindowRectEx(&WindowRect,dwStyle,FALSE,dwExStyle);//調整窗口達到真正要求的大小//窗體自適應各種分辨率以居中方式顯示 LONG nX, nY;nX = (::GetSystemMetrics(SM_CXSCREEN) - width) / 2; nY = (::GetSystemMetrics(SM_CYSCREEN) - height) / 2;if(!(hWnd = CreateWindowEx(dwExStyle, //擴展窗體風格 "OpenGL", //類名字 title, //窗口標題 WS_CLIPSIBLINGS | WS_CLIPCHILDREN| //必須的窗體風格屬性 dwStyle, //選擇的窗體屬性 nX,nY, //窗口位置 WindowRect.right - WindowRect.left, //計算調整好的窗口寬度 WindowRect.bottom - WindowRect.top, //計算調整好的窗體高度 NULL, //無父窗口 NULL, //無菜單 hInstance, //實例 NULL))) //不向WM_CREATE傳遞任何東西 { KillGLWindow();//重置顯示區 MessageBox(NULL,"不能創建一個窗口設備描述表","錯誤",MB_OK | MB_ICONEXCLAMATION); return FALSE; }static PIXELFORMATDESCRIPTOR pfd = //pdf告訴窗口希望的東西,即窗口使用的像素格式 { sizeof(PIXELFORMATDESCRIPTOR), //上述格式描述符的大小 1, //版本號 PFD_DRAW_TO_WINDOW | //格式支持窗口 PFD_SUPPORT_OPENGL | //格式支持OpenGL PFD_DOUBLEBUFFER, //支持雙緩沖 PFD_TYPE_RGBA, //申請RGBA格式 bits, //選定色彩深度 0,0,0,0,0,0, //忽略的色彩位 0, //無Alpha緩存 0, //忽略Shift Bit 0, //無累加緩存 0,0,0,0, //忽略聚集位 16, //16位Z-緩存(深度緩存) 0, //無蒙板緩存 0, //無輔助緩存 PFD_MAIN_PLANE, //主繪圖層 0, //Reserved 0,0,0 //忽略層遮罩 };if(!(hDC = GetDC(hWnd))) //是否取得設備描述表 { KillGLWindow();//重置顯示區 MessageBox(NULL,"不能創建一種相匹配的像素格式","錯誤",MB_OK | MB_ICONEXCLAMATION); return FALSE; }if(!(PixelFormat = ChoosePixelFormat(hDC,&pfd))) //Windows是否找到相應的像素格式 { KillGLWindow();//重置顯示區 MessageBox(NULL,"不能設置像素格式","錯誤",MB_OK | MB_ICONEXCLAMATION); return FALSE; }if(!SetPixelFormat(hDC,PixelFormat,&pfd)) //是否能夠設置像素格式 { KillGLWindow();//重置顯示區 MessageBox(NULL,"不能設置像素格式","錯誤",MB_OK | MB_ICONEXCLAMATION); return FALSE; }if (!(hRC = wglCreateContext(hDC))) //能否取得著色描述表 { KillGLWindow();//重置顯示區 MessageBox(NULL,"不能創建OpenGL渲染描述表","錯誤",MB_OK | MB_ICONEXCLAMATION); return FALSE; }if(!wglMakeCurrent(hDC,hRC)) //嘗試激活著色描述表 { KillGLWindow(); MessageBox(NULL,"不能激活當前的OpenGL渲染描述表","錯誤",MB_OK | MB_ICONEXCLAMATION); return FALSE; }ShowWindow(hWnd,SW_SHOW);//顯示窗口 SetForegroundWindow(hWnd);//提供優先級別 SetFocus(hWnd);//設置鍵盤的焦點至此窗口 ResizeGLScene(width,height);//設置透視GL屏幕if (!InitGL()) //初始化新建的GL窗口 { KillGLWindow(); MessageBox(NULL,"Initialization","ERROR",MB_OK | MB_ICONEXCLAMATION); return FALSE; }return TRUE; }//處理所有的窗口消息 LRESULT CALLBACK WndProc(HWND hWnd,//窗口的句柄 UINT uMsg,//窗口的消息 WPARAM wParam,//附加的消息內容 LPARAM lParam) //附加的消息內容 { switch(uMsg) //檢查檢查Windows消息 { case WM_ACTIVATE: //監視窗口激活消息 { if(!HIWORD(wParam)) //檢查最小化狀態 { active = TRUE; //程序處于激活狀態 } else { active = FALSE;//程序不再激活 }return 0;//返回消息循環 }case WM_SYSCOMMAND: //系統中斷命令 { switch(wParam) //檢查系統調用 { case SC_SCREENSAVE: //屏保運行 case SC_MONITORPOWER: //顯示器進入節電模式 return 0; //阻止發生 } break; //退出 } case WM_CLOSE: //收到Close消息 { PostQuitMessage(0);//發出退出消息 return 0; } case WM_KEYDOWN: //有鍵按下 { keys[wParam] = TRUE; return 0; } case WM_KEYUP: //有鍵放開 { keys[wParam] = FALSE; return 0; } case WM_SIZE: //調整OpenGL窗口大小 { ResizeGLScene(LOWORD(lParam),HIWORD(lParam));//LOWORD=width,HIWORD=height return 0; } }//向DefWindowProc傳遞所有未處理的消息 return DefWindowProc(hWnd,uMsg,wParam,lParam); }//Windows程序的入口,調用窗口創建例程,處理窗口消息,并監視人機交互。 int WINAPI WinMain(HINSTANCE hInstance,//當前窗口實例HINSTANCE hPrevInstance, //前一個窗口實例LPSTR lpCmdLine, //命令行參數int nCmdShow) //窗口顯示狀態 { MSG msg;//Windows消息結構 BOOL done=FALSE;//用來退出循環的BOOL變量 //提示用戶選擇運行模式 if (MessageBox(NULL,"你想在全屏模式下運行么?","設置全屏模式",MB_YESNO | MB_ICONQUESTION) == IDNO) { fullscreen = FALSE; //設置為窗口模式 }//創建OpenGL窗口 if(!CreateGLWindow("OpenGL 3D 旋轉物體",640,480,16,fullscreen)) { return 0; //失敗退出 }while(!done) { if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) //是否有消息在等待 { if(msg.message == WM_QUIT) //收到退出消息 { done = TRUE; } else //處理窗口消息 { TranslateMessage(&msg); //翻譯消息 DispatchMessage(&msg); //發送消息 } } else //如果沒有消息 { //繪制場景。監視ESC鍵和來自DrawGLScene()的退出消息 if(active) { if(keys[VK_ESCAPE]) { done = TRUE; } else //沒有退出,刷新屏幕 { DrawGLScene();//繪制場景 SwapBuffers(hDC);//交換緩存(雙緩存) } } if(keys[VK_F1]) { keys[VK_F1]=FALSE; KillGLWindow(); fullscreen = !fullscreen;//切換全屏/窗口模式 //重建OpenGL窗口 if(!CreateGLWindow("3D旋轉實例",640,480,16,fullscreen)) { return 0; } } } }//關閉程序 KillGLWindow(); //銷毀窗口 return (msg.wParam); //退出程序 }
效果:
代碼比較長;用notepad++折疊起來看下函數;
二 3D機器人
代碼: #include <gl/glut.h> #include <stdlib.h> #include <stdio.h>#define SOLID 1 #define WIRE 2int moveX,moveY; int spinX = 0; int spinY = 0; int des = 0;void init() {//定義光源的顏色和位置GLfloat ambient[] = { 0.5, 0.8, 0.1, 0.1 }; GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat position[] = { -80.0, 50.0, 25.0, 1.0 }; //選擇光照模型GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 }; GLfloat local_view[] = { 0.0 }; glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_SMOOTH); //設置環境光glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); //設置漫射光glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); //設置光源位置glLightfv(GL_LIGHT0, GL_POSITION, position); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view); //啟動光照glEnable(GL_LIGHTING); //啟用光源glEnable(GL_LIGHT0); }//畫球 void drawBall(double R, double x, double y,double z, int MODE) {glPushMatrix();glTranslated(x,y,z);if (MODE == SOLID) {glutSolidSphere(R,20,20);} else if (MODE ==WIRE) {glutWireSphere(R,20,20);}glPopMatrix(); }//畫半球 void drawHalfBall(double R, double x, double y,double z, int MODE) {glPushMatrix();glTranslated(x,y,z);GLdouble eqn[4]={0.0, 1.0, 0.0, 0.0};glClipPlane(GL_CLIP_PLANE0,eqn);glEnable(GL_CLIP_PLANE0);if (MODE == SOLID) {glutSolidSphere(R,20,20);} else if (MODE ==WIRE) {glutWireSphere(R,20,20);}glDisable(GL_CLIP_PLANE0);glPopMatrix(); }//畫長方體 void drawSkewed(double l, double w, double h, double x, double y, double z, int MODE) {glPushMatrix();glScaled(l, w, h);glTranslated(x, y, z);if (MODE == SOLID) {glutSolidCube(1);} else if (MODE ==WIRE) {glutWireCube(1);}glPopMatrix(); }void display(void) {//清除緩沖區顏色glClear(GL_COLOR_BUFFER_BIT);//定義白色glColor3f(1.0, 1.0, 1.0); //圓點放坐標中心glLoadIdentity(); //從哪個地方看gluLookAt(-2.0, -1.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glPushMatrix();glRotated(spinX, 0, 1, 0);glRotated(spinY, 1, 0, 0);glTranslated(0, 0, des);//頭drawBall(2, 0, 1, 0, SOLID);//身體drawSkewed(5, 4.4, 4, 0, -0.75, 0, SOLID);//肩膀drawHalfBall(1, 3.5, -2.1, 0, SOLID);drawHalfBall(1, -3.5, -2.1, 0, SOLID);//胳膊drawSkewed(1, 3, 1, 3.5, -1.3, 0, SOLID);drawSkewed(1, 3, 1, -3.5, -1.3, 0, SOLID);//手drawBall(1, 3.5, -6.4, 0, SOLID);drawBall(1, -3.5, -6.4, 0, SOLID);//腿drawSkewed(1.2, 3, 2, 1, -2.4, 0, SOLID);drawSkewed(1.2, 3, 2, -1, -2.4, 0, SOLID);//腳drawSkewed(1.5, 1, 3, 0.9, -9.2, 0, SOLID);drawSkewed(1.5, 1, 3, -0.9, -9.2, 0, SOLID);glPopMatrix();glutSwapBuffers(); } //鼠標點擊事件 void mouseClick(int btn, int state, int x, int y) {moveX = x;moveY = y;GLfloat ambient[] = { (float)rand() / RAND_MAX, (float)rand() / RAND_MAX, (float)rand() / RAND_MAX, 0.1 }; //設置環境光glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); //啟用光源glEnable(GL_LIGHT0); }//鍵盤事件 void keyPressed(unsigned char key, int x, int y) {switch (key) {case 'a':spinX -= 2;break;case 'd':spinX += 2; break;case 'w':des += 2;break;case 's':des -= 2;break;}glutPostRedisplay(); } // 鼠標移動事件 void mouseMove(int x, int y) {int dx = x - moveX;int dy = y - moveY;printf("dx;%dx,dy:%dy\n",dx,dy);spinX += dx;spinY += dy;glutPostRedisplay();moveX = x;moveY = y; }void reshape(int w, int h) {//定義視口大小glViewport(0, 0, (GLsizei) w, (GLsizei) h); //投影顯示glMatrixMode(GL_PROJECTION);//坐標原點在屏幕中心glLoadIdentity();//操作模型視景gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);glMatrixMode(GL_MODELVIEW); }int main(int argc, char** argv) {//初始化glutInit(&argc, argv);//設置顯示模式glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);//初始化窗口大小glutInitWindowSize(500, 500); //定義左上角窗口位置glutInitWindowPosition(100, 100);//創建窗口glutCreateWindow(argv[0]);//初始化init();//顯示函數glutDisplayFunc(display);//窗口大小改變時的響應glutReshapeFunc(reshape);//鼠標點擊事件,鼠標點擊或者松開時調用glutMouseFunc(mouseClick);//鼠標移動事件,鼠標按下并移動時調用glutMotionFunc(mouseMove);//鍵盤事件glutKeyboardFunc(keyPressed);//循環glutMainLoop();return 0; }效果;
折疊其代碼來看下函數;
三 繪制立方體
代碼: #include <gl/glut.h> //引用相關包void display(void) {glClear(GL_COLOR_BUFFER_BIT); //清空顏色緩沖區glColor3f(0,1,1); //重置顏色glLoadIdentity(); //清空矩陣glTranslatef(0,0,-5); //將場景中的物體沿z軸負方向移動5個單位長glRotatef(40,0,1,0);//gluLookAt(0,0,5,0,0,0,0,2,0); //視點變換glScalef(1,2,1); //模型變換glutWireCube(1.2); //繪制實心立方體和線框立方體glFlush(); //刷新窗口以顯示當前繪制圖形 } void init(void) {glClearColor(0,0,0,0);glShadeModel(GL_FLAT); //選擇平面明暗模式或光滑明暗模式 }void reshape(int w,int h) {glViewport(0,0,(GLsizei)w,(GLsizei)h); //設置機口glMatrixMode(GL_PROJECTION); //指定哪一個矩陣是當前矩陣glLoadIdentity();gluPerspective(60,1,1.5,20); //創建透視投影矩陣(fovy,aspect,zNear,zFar);//glFrustum(-1,1,-1,1,1.5,20.0); //用透視矩陣乘以當前矩陣(left,Right,bottom,top,near,far);glMatrixMode(GL_MODELVIEW); } int main(int argc, char *argv[]) {glutInit(&argc, argv); //固定格式glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //緩存模式glutInitWindowSize(400, 400); //顯示框的大小glutInitWindowPosition(400,400); //確定顯示框左上角的位置glutCreateWindow("繪制立方體");init();glutDisplayFunc(display);glutReshapeFunc(reshape);glutMainLoop(); //進人GLUT事件處理循環return 0; }效果:
上述分別是
glutWireCube(1.2);
glutWireCube(2.0);
的效果;
四 繪制立方體二
代碼:
#include<windows.h> #include<math.h>#ifdef __APPLE__ #include <GLUT/glut.h> #else #include <GL/glut.h> #endif#include <stdlib.h>void init(void) {glClearColor(0.75,0.75,0.75,0.0);glMatrixMode(GL_MODELVIEW);//設置當前矩陣模式為視圖模型矩陣glLoadIdentity(); //設置視點的位置,視線的方向和相機的向上方向gluLookAt(0,0,0, 0,0,-1, 0,1,0); //該設置為默認設置glScalef(0.3,1.0,0.5); //產生比例變換,分別設置物體在x,y,z方向上縮放因子,根據需要自己可以設置glRotatef(45,1.0,1.0,1.0);//產生旋轉變換,讓物體繞(1,1,1)軸旋轉45度glMatrixMode(GL_PROJECTION);//設置當前矩陣模式為投影矩陣glFrustum(-4,4,-4,4,0,20);設置場景投影時的可視范圍 }//float points[8][3] = {{0,0,0},{0,0.5,0},{0.5,0,0},{0.5,0.5,0},{0,0,0.5},{0,0.5,0.5},{0.5,0,0.5},{0.5,0.5,0.5}};float points[8][3] = {{0,0,0},{0,0.75,0},{0.75,0,0},{0.75,0.75,0},{0,0,0.75},{0,0.75,0.75},{0.75,0,0.75},{0.75,0.75,0.75}};float colors[6][3] = {{0.25,0,0},{0.25,0.25,0.25},{0,0,0.25},{0.5,0.25,0},{0,0.25,0.25},{0.25,0,0.25}};void vertexArray(void) {glClear(GL_COLOR_BUFFER_BIT); // glColor 3f(1.0,1.0,0.0);//glPolygonMode(GL_FRONT, GL_LINE);// 設置多邊形的顯示模式為面填充模式,該設置也是默認設置glFrontFace(GL_CCW); //設置前面的面的模式為逆時針模式, 該設置也是默認設置//glShadeModel(GL_SHADE_MODEL);// 默認就是此參數,可忽略,為了明確說明特意指定void quad(GLint n1,GLint n2,GLint n3,GLint n4,GLint index);quad(6,2,3,7,1);quad(5,1,0,4,2);quad(7,3,1,5,3);quad(4,0,2,6,4);quad(2,0,1,3,5);quad(7,5,4,6,6); glFlush(); }void quad(GLint n1,GLint n2,GLint n3,GLint n4,GLint index) {glColor3f(0.0,1.0,0.0);glEnable(GL_POLYGON_OFFSET_FILL);glPolygonOffset(1.0,1.0);glDisable(GL_POLYGON_OFFSET_FILL);glColor3f(colors[index][0],colors[index][1],colors[index][2]);//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//glPolygonMode(GL_FRONT, GL_LINE);glPolygonMode(GL_BACK, GL_LINE);//glColor3f(1.0,1.0,0);glBegin(GL_QUADS);glVertex3fv(points[n1]);glVertex3fv(points[n2]);glVertex3fv(points[n3]);glVertex3fv(points[n4]);glEnd(); }int main (int argc, char** argv) {glutInit (&argc, argv); // Initialize GLUT.glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); // Set display mode.glutInitWindowPosition (50, 100); // Set top-left display-window position.glutInitWindowSize (600, 500); // Set display-window width and height.glutCreateWindow ("An Example OpenGL Program"); // Create display window.init(); // Execute initialization procedure.glutDisplayFunc (vertexArray); // Send graphics to display window.glutMainLoop ( );// Send graphics to display window. // Display everything and wait.return 0; }效果:
五 任意兩點間畫圓柱體
#include <gl/glut.h> #include <cstdio> #include <cstdlib> #include <cmath> void init(void); void reshape(int w,int h); void display(void); void RenderBone(float x0, float y0, float z0, float x1, float y1, float z1 ); int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize (500, 500); glutInitWindowPosition (100, 100); glutCreateWindow("Sphere"); init (); glutReshapeFunc(reshape); glutDisplayFunc(display); glutMainLoop(); return 0; } void init (void) { glClearColor (0.6, 0.6, 0.6, 0.0); glClearDepth(1); glShadeModel(GL_SMOOTH); GLfloat _ambient[]={1.0,1.0,1.0,1.0}; //GLfloat _ambient[]={2.0,2.0,2.0,2.0}; GLfloat _diffuse[]={1.0,1.0,0.0,1.0}; GLfloat _specular[]={1.0,1.0,1.0,1.0}; GLfloat _position[]={300,300,300,0}; glLightfv(GL_LIGHT0,GL_AMBIENT,_ambient); glLightfv(GL_LIGHT0,GL_DIFFUSE,_diffuse); glLightfv(GL_LIGHT0,GL_SPECULAR,_specular); glLightfv(GL_LIGHT0,GL_POSITION,_position); glEnable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); } void reshape(int w, int h) { glViewport (0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, 500, 0.0, 500, -500, 500); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void display(void) { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glPushMatrix(); { //RenderBone(100, 100, 100, 200, 300, 500); RenderBone(200, 200, 200, 300, 400, 600); } glPopMatrix(); glFlush(); glutPostRedisplay(); } void RenderBone(float x0, float y0, float z0, float x1, float y1, float z1 ) { GLdouble dir_x = x1 - x0; GLdouble dir_y = y1 - y0; GLdouble dir_z = z1 - z0; GLdouble bone_length = sqrt( dir_x*dir_x + dir_y*dir_y + dir_z*dir_z ); static GLUquadricObj * quad_obj = NULL; if ( quad_obj == NULL ) quad_obj = gluNewQuadric(); gluQuadricDrawStyle( quad_obj, GLU_FILL ); gluQuadricNormals( quad_obj, GLU_SMOOTH ); glPushMatrix(); // 平移到起始點 glTranslated( x0, y0, z0 ); // 計算長度 double length; length = sqrt( dir_x*dir_x + dir_y*dir_y + dir_z*dir_z ); if ( length < 0.0001 ) { dir_x = 0.0; dir_y = 0.0; dir_z = 1.0; length = 1.0; } dir_x /= length; dir_y /= length; dir_z /= length; GLdouble up_x, up_y, up_z; up_x = 0.0; up_y = 1.0; up_z = 0.0; double side_x, side_y, side_z; side_x = up_y * dir_z - up_z * dir_y; side_y = up_z * dir_x - up_x * dir_z; side_z = up_x * dir_y - up_y * dir_x; length = sqrt( side_x*side_x + side_y*side_y + side_z*side_z ); if ( length < 0.0001 ) { side_x = 1.0; side_y = 0.0; side_z = 0.0; length = 1.0; } side_x /= length; side_y /= length; side_z /= length; up_x = dir_y * side_z - dir_z * side_y; up_y = dir_z * side_x - dir_x * side_z; up_z = dir_x * side_y - dir_y * side_x; // 計算變換矩陣 GLdouble m[16] = { side_x, side_y, side_z, 0.0, up_x, up_y, up_z, 0.0, dir_x, dir_y, dir_z, 0.0, 0.0, 0.0, 0.0, 1.0 }; glMultMatrixd( m ); // 圓柱體參數 GLdouble radius= 25; // 半徑 GLdouble slices = 8.0; // 段數 GLdouble stack = 3.0; // 遞歸次數 gluCylinder( quad_obj, radius, radius, bone_length, slices, stack ); glPopMatrix(); } 效果:
修改此句以改變半徑;
GLdouble radius= 25; ? ? ? ?// 半徑
六 球體
#include <windows.h> #include <gl/GL.h> #include <gl/glu.h> #include <gl/glut.h> #include <cstdlib> const GLfloat lightPosition[] = {10.0,10.0,10.0,0.0}; const GLfloat whiteLight[] = {0.8,0.8,0.8,1.0}; GLfloat matSpecular [] = {0.3,0.3,0.3,1.0}; GLfloat matShininess [] = {20.0}; GLfloat matEmission [] = {0.3,0.3,0.3,1.0}; GLfloat spin = 0; void init() { glClearColor(0.3,0.3,0.3,1.0); glClearDepth(1.0); glShadeModel(GL_SMOOTH); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glLightfv(GL_LIGHT0,GL_POSITION,lightPosition); glLightfv(GL_LIGHT0,GL_DIFFUSE,whiteLight); glLightfv(GL_LIGHT0,GL_SPECULAR,whiteLight); } void display() { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity();; glOrtho(-10.0,10.0,-10.0,10.0,-10.0,10.0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glRotatef(spin,0.0,1.0,0.0); glMaterialfv(GL_FRONT,GL_SPECULAR,matSpecular); glMaterialfv(GL_FRONT,GL_SHININESS,matShininess); glMaterialfv(GL_FRONT,GL_EMISSION,matEmission); //glutSolidSphere(6.0,16,16); glutSolidSphere(3.0,16,16); glPopMatrix(); glFlush(); } void reshape(int w,int h) { glViewport(0.0,0.0,(GLsizei) w,(GLsizei) h); } void keyboardFunc(unsigned char key,int x,int y) { switch(key) { case 'a': spin +=30; break; case 'd': spin -=30; break; } if(spin<360) spin +=360; else if(spin>=360) spin -=360; glutPostRedisplay(); } void mouseFunc(int button,int state,int x,int y) { if(state==GLUT_DOWN){ switch (button) { case GLUT_LEFT_BUTTON: matEmission[0]+=1.0; if(matEmission[0]>1.0) matEmission[0]-=1.1; break; case GLUT_MIDDLE_BUTTON: matEmission[1]+=1.0; if(matEmission[1]>1.0) matEmission[1]-=1.1; break; case GLUT_RIGHT_BUTTON: matEmission[2]+=1.0; if(matEmission[2]>1.0) matEmission[2]-=1.1; break; } glutPostRedisplay(); } } int main(int argc,char *argv[]) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_SINGLE|GLUT_RGBA|GLUT_DEPTH); glutInitWindowSize(450,450); glutInitWindowPosition(150,150); glutCreateWindow("rotate sphere"); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboardFunc); glutMouseFunc(mouseFunc); init(); glutMainLoop(); return EXIT_SUCCESS; } 效果:
上述分別是
? ? //glutSolidSphere(6.0,16,16); ?
glutSolidSphere(3.0,16,16);?
的效果;
七 球體,圓圈,茶壺......
#include <gl/glut.h> #include <math.h> #include <stdio.h> //圓周率宏 #define GL_PI 3.1415f //獲取屏幕的寬度 GLint SCREEN_WIDTH=0; GLint SCREEN_HEIGHT=0; //設置程序的窗口大小 GLint windowWidth=400; GLint windowHeight=300; //繞x軸旋轉角度 GLfloat xRotAngle=0.0f; //繞y軸旋轉角度 GLfloat yRotAngle=0.0f; //受支持的點大小范圍 GLfloat sizes[2]; //受支持的點大小增量 GLfloat step; enum MODELS{ SPHERE=0, CONE, CUBE, TORUS, DODECAHEDRON, TEAPOT, OCTAHEDRON, TETRAHEDRON, ICOSAHEDRON }; GLint iModel=SPHERE; GLboolean bWire=GL_TRUE; //菜單回調函數 void processMenu(int value){ switch(value){ case 1: iModel=SPHERE; break; case 2: iModel=CONE; break; case 3: iModel=CUBE; break; case 4: iModel=TORUS; break; case 5: iModel=DODECAHEDRON; break; case 6: iModel=TEAPOT; break; case 7: iModel=OCTAHEDRON; break; case 8: iModel=TETRAHEDRON; break; case 9: iModel=ICOSAHEDRON; break; case 10: bWire=GL_TRUE; break; case 11: bWire=GL_FALSE; break; default: break; } //重新繪制 glutPostRedisplay(); } //顯示回調函數 void renderScreen(void){ //將窗口顏色清理為黑色 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); //將模板緩沖區值全部清理為1 glClearStencil(1); //使能模板緩沖區 glEnable(GL_STENCIL_TEST); //把整個窗口清理為當前清理顏色:黑色。清除深度緩沖區、模板緩沖區 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); //將當前Matrix狀態入棧 glPushMatrix(); //坐標系繞x軸旋轉xRotAngle glRotatef(xRotAngle,1.0f,0.0f,0.0f); //坐標系繞y軸旋轉yRotAngle glRotatef(yRotAngle,0.0f,1.0f,0.0f); //進行平滑處理 glEnable(GL_POINT_SMOOTH); glHint(GL_POINT_SMOOTH,GL_NICEST); glEnable(GL_LINE_SMOOTH); glHint(GL_LINE_SMOOTH,GL_NICEST); glEnable(GL_POLYGON_SMOOTH); glHint(GL_POLYGON_SMOOTH,GL_NICEST); //白色繪制坐標系 glColor3f(1.0f,1.0f,1.0f); glBegin(GL_LINES); glVertex3f(-9.0f,0.0f,0.0f); glVertex3f(9.0f,0.0f,0.0f); glVertex3f(0.0f,-9.0f,0.0f); glVertex3f(0.0f,9.0f,0.0f); glVertex3f(0.0f,0.0f,-9.0f); glVertex3f(0.0f,0.0f,9.0f); glEnd(); glPushMatrix(); glTranslatef(9.0f,0.0f,0.0f); glRotatef(90.0f,0.0f,1.0f,0.0f); glutSolidCone(0.3,0.6,10,10); glPopMatrix(); glPushMatrix(); glTranslatef(0.0f,9.0f,0.0f); glRotatef(-90.0f,1.0f,0.0f,0.0f); glutSolidCone(0.3,0.6,10,10); glPopMatrix(); glPushMatrix(); glTranslatef(0.0f,0.0f,9.0f); glRotatef(90.0f,0.0f,0.0f,1.0f); glutSolidCone(0.3,0.6,10,10); glPopMatrix(); //設置繪畫顏色為金色 glColor3f(0.0f,1.0f,0.0f); switch(iModel){ //球 case SPHERE: if(bWire){ glutWireSphere(8.0f,20,20); } else{ glutSolidSphere(8.0f,20,20); } break; //錐體 case CONE: if(bWire){ glutWireCone(4.0f,8.0f,20,20); } else{ glutSolidCone(4.0f,8.0f,20,20); } break; //立體 case CUBE: if(bWire){ glutWireCube(8.0f); } else{ glutSolidCube(8.0f); } break; //甜圈 case TORUS: if(bWire){ glutWireTorus(3.0f,6.0f,20,20); } else{ glutSolidTorus(3.0f,6.0f,20,20); } break; //十六面體,默認半徑1.0 case DODECAHEDRON: glScalef(6.0f,6.0f,6.0f);//x,y,z軸均放大6倍 if(bWire){ glutWireDodecahedron(); } else{ glutSolidDodecahedron(); } break; //茶壺 case TEAPOT: if(bWire){ glutWireTeapot(8.0f); } else{ glutSolidTeapot(8.0f); } break; //八面體,默認半徑1.0 case OCTAHEDRON: glScalef(6.0f,6.0f,6.0f);//x,y,z軸均放大6倍 if(bWire){ glutWireOctahedron(); } else{ glutSolidOctahedron(); } break; //四面體,默認半徑1.0 case TETRAHEDRON: glScalef(6.0f,6.0f,6.0f);//x,y,z軸均放大6倍 if(bWire){ glutWireTetrahedron(); } else{ glutSolidTetrahedron(); } break; //二十面體,默認半徑1.0 case ICOSAHEDRON: glScalef(6.0f,6.0f,6.0f);//x,y,z軸均放大6倍 if(bWire){ glutWireIcosahedron(); } else{ glutSolidIcosahedron(); } break; default: break; } //恢復壓入棧的Matrix glPopMatrix(); //交換兩個緩沖區的指針 glutSwapBuffers(); } //設置Redering State void setupRederingState(void){ //設置清理顏色為黑色 glClearColor(0.0f,0.0,0.0,1.0f); //設置繪畫顏色為綠色 glColor3f(1.0f,1.0f,0.0f); //使能深度測試 glEnable(GL_DEPTH_TEST); //獲取受支持的點大小范圍 glGetFloatv(GL_POINT_SIZE_RANGE,sizes); //獲取受支持的點大小增量 glGetFloatv(GL_POINT_SIZE_GRANULARITY,&step); printf("point size range:%f-%f\n",sizes[0],sizes[1]); printf("point step:%f\n",step); } //窗口大小變化回調函數 void changSize(GLint w,GLint h){ //橫寬比率 GLfloat ratio; //設置坐標系為x(-100.0f,100.0f)、y(-100.0f,100.0f)、z(-100.0f,100.0f) GLfloat coordinatesize=10.0f; //窗口寬高為零直接返回 if((w==0)||(h==0)) return; //設置視口和窗口大小一致 glViewport(0,0,w,h); //對投影矩陣應用隨后的矩陣操作 glMatrixMode(GL_PROJECTION); //重置當前指定的矩陣為單位矩陣 glLoadIdentity(); ratio=(GLfloat)w/(GLfloat)h; //正交投影 if(w<h) glOrtho(-coordinatesize,coordinatesize,-coordinatesize/ratio,coordinatesize/ratio,-coordinatesize,coordinatesize); else glOrtho(-coordinatesize*ratio,coordinatesize*ratio,-coordinatesize,coordinatesize,-coordinatesize,coordinatesize); //對模型視圖矩陣堆棧應用隨后的矩陣操作 glMatrixMode(GL_MODELVIEW); //重置當前指定的矩陣為單位矩陣 glLoadIdentity(); } //按鍵輸入處理回調函數 void specialKey(int key,int x,int y){ if(key==GLUT_KEY_UP){ xRotAngle-=5.0f; } else if(key==GLUT_KEY_DOWN){ xRotAngle+=5.0f; } else if(key==GLUT_KEY_LEFT){ yRotAngle-=5.0f; } else if(key==GLUT_KEY_RIGHT){ yRotAngle+=5.0f; } //重新繪制 glutPostRedisplay(); } int main(int argc, char* argv[]) { int nModelMenu; int nWireMenu; int nMainMenu; //初始化glut glutInit(&argc,argv); //使用雙緩沖區、深度緩沖區、模板緩沖區 glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL); //獲取系統的寬像素 SCREEN_WIDTH=glutGet(GLUT_SCREEN_WIDTH); //獲取系統的高像素 SCREEN_HEIGHT=glutGet(GLUT_SCREEN_HEIGHT); //創建窗口,窗口名字為OpenGL Glut Demo glutCreateWindow("OpenGL Glut Demo"); //設置窗口大小 glutReshapeWindow(windowWidth,windowHeight); //窗口居中顯示 glutPositionWindow((SCREEN_WIDTH-windowWidth)/2,(SCREEN_HEIGHT-windowHeight)/2); //創建二級菜單 nModelMenu=glutCreateMenu(processMenu); glutAddMenuEntry("Sphere",1); glutAddMenuEntry("Cone",2); glutAddMenuEntry("Cube",3); glutAddMenuEntry("Torus",4); glutAddMenuEntry("Dodecahedron",5); glutAddMenuEntry("Teapot",6); glutAddMenuEntry("Octahedron",7); glutAddMenuEntry("Tetrahedron",8); glutAddMenuEntry("Icosahedron",9); nWireMenu=glutCreateMenu(processMenu); glutAddMenuEntry("Wire",10); glutAddMenuEntry("Solid",11); nMainMenu=glutCreateMenu(processMenu); glutAddSubMenu("Model",nModelMenu); glutAddSubMenu("WireOrSolid",nWireMenu); //將菜單榜定到鼠標右鍵上 glutAttachMenu(GLUT_RIGHT_BUTTON); //窗口大小變化時的處理函數 glutReshapeFunc(changSize); //設置顯示回調函數 glutDisplayFunc(renderScreen); //設置按鍵輸入處理回調函數 glutSpecialFunc(specialKey); //設置全局渲染參數 setupRederingState(); glutMainLoop(); return 0; } 右鍵選擇mode查看不同3d圖形;光標鍵調整角度;球體;
調整角度;
甜圈;
這只就是著名的雪山飛壺;
折疊起代碼來看下函數;
Glut下提供了一些現成的繪制立體的API,如glutWireSphere繪制球,glutWireCone繪制椎體,glutWireCube繪制立體,glutWireTorus繪制甜圈,glutWireTeapot繪制茶壺,glutWireOctahedron繪制八面體。
Glut提供的多面體API默認半徑是1.0f的,使用glScalef對其進行放大。
八 opengl資源鏈接
http://blog.csdn.net/one_in_one/article/category/960777
http://blog.csdn.net/yearafteryear/article/category/1442065
http://blog.csdn.net/Augusdi/article/category/685679
http://cuiqingcai.com/category/technique/cc
總結
以上是生活随笔為你收集整理的图解opengl 3D 图形绘制实例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图解VC++工具栏和状态栏编程实例
- 下一篇: 图解opengl曲线和曲面绘制