OpenGL進階演示樣例1——動態畫線(虛線、實線、顏色、速度等)


        用OpenGL動態繪制線段。事實上非常easy,但到如今為止。網上可參考資料並不多。

於是親自己主動手寫一個函數,方便動態繪制線段。代碼例如以下:


#include<GL/glut.h>						//OpenGL有用工具包
#include <Windows.h>

/*所遇問題:
1、系統API函數Sleep()不聽話,睡眠時快時慢(可能跟我計算機當前執行程序有關吧)
解決方式:重寫Sleep()函數。實質為空循環。

僅用於Debug下。Release會將其優化 2、動態畫直線,朝某些方向畫線時出現塊狀 解決方式:認認真真把直線方程推導一遍。斜率存在或不存在分別討論,將數學思想轉換為編程思想 */ void init(void) { glClearColor(0.0,0.0,0.0,0.0); //指定清除顏色(黑色),即背景顏色 glShadeModel(GL_FLAT); //設置着色模式。採用恆定着色 } void Sleep(int ms) //覆蓋系統API函數 { for(int i=0;i<ms*ms*ms*10;i++) //數值大小依據實際情況調試 { ; } } //特別注意:1、斜率不存在。2、直線斜率一定要保持一致,將直線兩點式方程轉化為斜率式方程y=kx+c //k=(y2-y1)/(x2-x1); //c=(x2*y1-x1*y2)/(x2-x1); void DrawDynamicLine(GLfloat x1, GLfloat y1, //起點坐標 GLfloat x2, GLfloat y2, //終點坐標 GLfloat red,GLfloat green,GLfloat blue, //線段顏色 int speed, //繪制速度。0-100,值越大速度越大 int type //虛線類型。16位2進制表示。1為實點,0為虛點。0xFFFF為實線 ) { glEnable(GL_LINE_STIPPLE); //點畫線模式 glColor3f(red,green,blue); //設置線段繪制顏色 glLineStipple(1,type); //dashed(虛線),type為16位2進制數。0表示實點,1表示虛點 if (x1!=x2) //假設斜率存在 { GLfloat k=(y2-y1)/(x2-x1); //直線斜率 y=kx+c GLfloat c=(x2*y1-x1*y2)/(x2-x1); //直線常數 //假定以A為原點建立二維坐標系,則下邊4個if分別相應於:第一象限,第二象限,第三象限,第四象限 if (x1<x2&&y1<=y2) //從A(x1,y1)到B(x2,y2)畫線。B點在A點的右上方 { for (int i=0;i<=x2-x1;i++) //注意循環條件 { glBegin(GL_LINES); glVertex2f(x1,y1); glVertex2f(x1+i,k*(x1+i)+c); glEnd(); Sleep(100-speed); glFlush(); //立馬開始處理保存在緩沖區中的OpenGL函數調用 } } else if (x1>x2&&y1<=y2) //從A(x1,y1)到B(x2,y2)畫線,B點在A點的左下方 { for (int i=0;i>=x2-x1;i--) //特別注意循環條件。既要避免死循環又要避免少循環 { glBegin(GL_LINES); glVertex2f(x1,y1); glVertex2f(x1+i,k*(x1+i)+c); glEnd(); Sleep(100-speed); glFlush(); //立馬開始處理保存在緩沖區中的OpenGL函數調用 } } else if (x1>x2&&y1>=y2) //從A(x1,y1)到B(x2,y2)畫線,B點在A點的左上方 { for (int i=0;i>=x2-x1;i--) //特別注意循環條件,既要避免死循環又要避免少循環 { glBegin(GL_LINES); glVertex2f(x1,y1); glVertex2f(x1+i,k*(x1+i)+c); glEnd(); Sleep(100-speed); glFlush(); //立馬開始處理保存在緩沖區中的OpenGL函數調用 } } else if (x1<x2&&y1>=y2) //從A(x1,y1)到B(x2,y2)畫線,B點在A點的左上方 { for (int i=0;i<=x2-x1;i++) //特別注意循環條件,既要避免死循環又要避免少循環 { glBegin(GL_LINES); glVertex2f(x1,y1); glVertex2f(x1+i,k*(x1+i)+c); glEnd(); Sleep(100-speed); glFlush(); //立馬開始處理保存在緩沖區中的OpenGL函數調用 } } } else { if (y1<y2) //沿y軸正方向畫線 { for (int i=0;i<=y2-y1;i++) //特別注意循環條件,既要避免死循環又要避免少循環 { glBegin(GL_LINES); glVertex2f(x1,y1); glVertex2f(x1,y1+i); glEnd(); Sleep(100-speed); glFlush(); //立馬開始處理保存在緩沖區中的OpenGL函數調用 } } else //沿y軸負方向畫線 { for (int i=0;i>=y2-y1;i--) //特別注意循環條件,既要避免死循環又要避免少循環 { glBegin(GL_LINES); glVertex2f(x1,y1); glVertex2f(x1,y1+i); glEnd(); Sleep(100-speed); glFlush(); //立馬開始處理保存在緩沖區中的OpenGL函數調用 } } } } void display(void) { glClear(GL_COLOR_BUFFER_BIT); //清除全部的像素 //正方形ABCD DrawDynamicLine(100,500,500,500,1,1,0,60,0xFFFF); //AB DrawDynamicLine(500,500,500,100,1,0,1,70,0xFFFF); //BC DrawDynamicLine(500,100,100,100,1,1,1,80,0xFFFF); //CD DrawDynamicLine(100,100,100,500,0,1,1,90,0xFFFF); //DA //沿順時針方向測試動態畫線:第一象限,第四象限。第三象限,第二象限 DrawDynamicLine(300,300,300,500,1,0,0,90,0xFFFF); //1 DrawDynamicLine(300,300,400,500,1,0,0,90,0x00FF); DrawDynamicLine(300,300,500,500,1,0,0,90,0xFFFF); DrawDynamicLine(300,300,500,400,1,0,0,90,0x00FF); DrawDynamicLine(300,300,500,300,1,0,0,90,0xFFFF); DrawDynamicLine(300,300,500,300,1,0,0,90,0xFFFF); //2 DrawDynamicLine(300,300,500,200,1,0,0,90,0x00FF); DrawDynamicLine(300,300,500,100,1,0,0,90,0xFFFF); DrawDynamicLine(300,300,400,200,1,0,0,90,0x00FF); DrawDynamicLine(300,300,400,100,1,0,0,90,0x00FF); DrawDynamicLine(300,300,300,100,1,0,0,90,0xFFFF); //3 DrawDynamicLine(300,300,200,100,1,0,0,90,0x00FF); DrawDynamicLine(300,300,100,100,1,0,0,90,0xFFFF); DrawDynamicLine(300,300,100,200,1,0,0,90,0x00FF); DrawDynamicLine(300,300,100,300,1,0,0,90,0xFFFF); DrawDynamicLine(300,300,100,300,1,0,0,90,0xFFFF); //4 DrawDynamicLine(300,300,100,400,1,0,0,90,0x00FF); DrawDynamicLine(300,300,100,500,1,0,0,90,0xFFFF); DrawDynamicLine(300,300,200,500,1,0,0,90,0x00FF); DrawDynamicLine(300,300,300,500,1,0,0,90,0xFFFF); } void reshape(int w,int h) { glViewport(0,0,(GLsizei)w,(GLsizei)h); //為了選擇一個更小的畫圖區域,在窗體中定義一個像素矩形。將圖像映射到這個矩形中 glMatrixMode(GL_PROJECTION); //指定哪一個矩陣是當前矩陣(GL_PROJECTION,對投影矩陣應用隨后的矩陣操作) glLoadIdentity(); //將當前的用戶坐標系的原點移到了屏幕中心:相似於一個復位操作 gluOrtho2D(0.0,(GLdouble)w,0.0,(GLdouble)h); //將當前的可視空間設置為正投影空間,這個函數描寫敘述了一個平行修剪空間,意味着離觀察者較遠的對象看上去不會變小 } int main(int argc,char** argv) //注意參數 { glutInit(&argc,argv); //初始化GLUT並處理命令行參數 glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); //指定模式:單緩存OR雙緩存;RGBA模式OR顏色索引模式 glutInitWindowSize(600,600); //指定窗體大小(像素) glutInitWindowPosition(300,50); //指定窗體左上角在屏幕上的位置 glutCreateWindow(argv[0]); //使用OpenGL場景創建一個窗體,參數為窗體名稱 init(); //調用初始化函數 glutDisplayFunc(display); //注冊用於顯示圖形的回調函數。每當GLUT覺得須要重繪窗體時。都會執行該函數。故應將重繪場景所需調用的函數都放到顯示回調函數中。 glutReshapeFunc(reshape); //重繪回調函數 glutMainLoop(); //進入主循環並處理事件。此時創建的全部窗體都會顯示出來。被渲染到這些窗體中的內容也將顯示出來,程序開始處理事件,注冊的顯示回調函數被觸發 return 0; //ANSI C要求函數main()返回一個int值 }


效果例如以下:



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM