【OpenGL】使用DDA演算法畫線
阿新 • • 發佈:2019-01-08
DDA(數字微分分析儀...好高大上的樣子)演算法其實就是利用直線方程來生成直線的演算法,給定起點(x0,y0)和終點(xEnd,yEnd),這條直線就唯一確定了,它的斜率是k=(yEnd-y0)/(xEnd-x0)。對於x方向我們取增量為1,那麼下一個x值,即xi+1=xi+1,這樣一來,y方向的增量就是斜率k,那麼yi+1=yi+k。利用這兩個加粗的方程,我們就可以遍歷這條直線,每到一個地方就把這裡的畫素點填充上顏色,一條直線就繪製好了,當然,具體的演算法實現有一些小細節,放到了註釋裡。
程式碼:
/*使用DDA演算法畫線*/ #include<iostream> using namespace std; #include<windows.h> #include<math.h> #include<gl/glut.h> void myDisplay(void);//用這個函式來呼叫lineDDA void setPixel(int x,int y);//教科書裡畫點的函式,在OpenGL中可以用glVertex來實現 int round(const float a); void ChangeSize(GLsizei w, GLsizei h); void lineDDA(int x0,int y0,int xEnd,int yEnd); void myDisplay(void){ //glClear(GL_COLOR_BUFFER_BIT);//好像沒這句話也可以啊。。初學好迷=。= lineDDA(50,50,200,200); } void setPixel(int x,int y){ //用OpenGL自己的函式實現書上的setPixel glPointSize(5.0f); glBegin(GL_POINTS); glVertex2i(x,y); glEnd(); glFlush(); } int round(const float a){ return int(a+0.5); } //視窗大小改變時呼叫的登記函式 void ChangeSize(GLsizei w, GLsizei h){ if(h==0) h=1; glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho(0.0f,250.0f,0.0f,250.0f*h/w,1.0,-1.0); else glOrtho(0.0f,250.0f*w/h,0.0f,250.0f,1.0,-1.0); } void lineDDA(int x0,int y0,int xEnd,int yEnd){ glPointSize(3.0f);//設定畫素點大小 int dx=xEnd-x0,dy=yEnd-y0,steps,k; float xIncrement,yIncrement,x=x0,y=y0; if(abs(dx)>abs(dy))//確定步長,誰大就取誰 steps=abs(dx); else steps=abs(dy); xIncrement=float(dx)/float(steps);//增量當中有一個會為1,另一個會為斜率k yIncrement=float(dy)/float(steps); setPixel(round(x),round(y));//由於每次都加了小於1的增量,所以需要取整 for(k=0;k<steps;k++){ /* glBegin(GL_POINTS); glVertex2i((int)x,(int)y); glEnd(); glFlush(); */ x+=xIncrement; y+=yIncrement; setPixel(round(x),round(y)); } } int main(int argc,char* argv[]){ glutInit(&argc,argv); glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE); glutInitWindowPosition(200,200); glutInitWindowSize(400,400); glutCreateWindow("Daily Practice"); glutDisplayFunc(&myDisplay); glutReshapeFunc(ChangeSize); glutMainLoop(); return 0; }
執行效果:
DDA簡單(好吧我是說在這種二維的情況下,今天老師提了一下三維的情形,感覺還是有點複雜的=。=),但是比較粗糙,取整的誤差會累積得越來越大,如果繪製的線比較長,畫素點比較多,偏離相對就比較大,第二是演算法整體耗時高,因為round和浮點運算比較耗時。