图形学中的画线算法之 "DDA"算法
DDA算法画直线,其理论依据:如 m 表示直线斜率, 那么有斜率 m = (y2 - y1) / (x2 - x1),
∴ m = Δy / Δx , 从而有对于沿直线给定的 x 任何增量Δx,计算出对应的y的增量 Δy = m • Δx ; 同理: Δx = Δy / m;
假设斜率 |m| <= 1;即 x 的长度大于 y的长度。现以 x 单位间距为增量,逐个计算 y 值, 有: yk+1 = yk + m;
同理,对于|m| > 1; 我们有: xK+1 = yK + 1 / m;
(注意: m为斜率,可正可负);
有了上面的数学依据,画线的流程应该很清楚了。假如有两个点(x1, y1)和 (x2, y2); 计算出 detaX 和detaY, 绝对值大的确定我们所要绘制的步数 steps。 依次增加 增量 m 来达到我们画线的目的,
代码如下:
1 // gltest.cpp : 定义控制台应用程序的入口点。 2 // 3 #include "StdAfx.h" 4 #include "stdio.h" 5 #include <iostream> 6 #pragma comment(lib,"glew32.lib") 7 #include <gl/glew.h> 8 #include <gl/glut.h> 9 10 using namespace std; 11 12 static void dda_draw_line(int x0, int y0, int x1, int y1); 13 void renderScene(void); 14 static int round(const float x); 15 static void drawPixel(int x, int y); 16 static void draw_init(void); 17 18 void renderScene(void) 19 { 20 glClearColor(1,1,1,1); 21 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 22 dda_draw_line(10, -80, 200, 150); 23 //drawPixel(100, 100); 24 } 25 26 static int round(const float x) 27 { 28 return (int)(x + 0.5); 29 } 30 31 static void drawPixel(int x, int y) 32 { 33 glBegin(GL_POINTS); 34 glVertex2i(x, y); 35 glEnd(); 36 } 37 38 static void draw_init(void) 39 { 40 glMatrixMode(GL_PROJECTION); 41 gluOrtho2D(-400, 400, -300, 300); 42 glPointSize(2.0f); 43 glColor3f(1,0,0); 44 } 45 46 static void dda_draw_line(int x0, int y0, int x1, int y1) 47 { 48 int dx = abs(x1 - x0); 49 int dy = abs(y1 - y0); 50 float steps; 51 float x = x0, y = y0; 52 float ad; 53 float xIncrement, yIncrement; 54 55 cout<< "dx: "<<dx << ", dy:" <<dy <<endl; 56 57 if(dx >= dy) 58 { 59 steps = dx; 60 } 61 else 62 { 63 steps = dy; 64 } 65 66 cout<<"step: " << steps <<endl; 67 68 xIncrement = dx / steps; 69 yIncrement = dy / steps; 70 71 cout<<"xIn: " << xIncrement << " , yIn: " << yIncrement <<endl; 72 73 drawPixel(round(x), round(y)); 74 for(int i = 0; i < steps; i++) 75 { 76 //cout<<"x: " <<x << ", y: " <<y<<endl; 77 x += xIncrement; 78 y += yIncrement; 79 drawPixel(round(x), round(y)); 80 } 81 glutSwapBuffers(); 82 83 } 84 85 int main(int argc, char* argv[]) 86 { 87 glutInitWindowSize(800, 600); 88 glutInitWindowPosition(500,200); 89 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); 90 glutInit(&argc, argv); 91 glutCreateWindow("hello opengl"); 92 93 draw_init(); 94 95 96 printf("opengl version; %s\n", glGetString(GL_VERSION)); 97 printf("glsl version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION)); 98 99 glutDisplayFunc(renderScene); 100 glutMainLoop(); 101 return 0; 102 103 }