【OpenGL】使用DDA算法画线

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和浮点运算比较耗时。

对了,代码里的ChangeSize()函数是在网上找到的(还不懂OPenGL的显示机制),这里参考了:http://blog.csdn.net/u012866328/article/details/52601217,特此说明,谢谢这位博主!

展开阅读全文

没有更多推荐了,返回首页