Bootstrap

OpenGL编程学习笔记——交互与直线算法

交互

键盘交互(glutKeyboardFunc)

例子:实现小方块的移动

代码

#include <GL/glut.h>

int xd = 0, yd = 0;

void myDisplay()
{
	int p1[] = { 10 + xd,10 + yd };
	int p2[] = { 20 + xd,10 + yd };
	int p3[] = { 20 + xd,0 + yd };
	int p4[] = { 10 + xd,0 + yd };
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(0.8, 0.5, 0.6);
	glPointSize(5);
	//glBegin(GL_POINTS);
	//glBegin(GL_LINES);
	//glBegin(GL_LINE_STRIP);
	//glBegin(GL_LINE_LOOP);
	//glBegin(GL_POLYGON);//多边形
	//glBegin(GL_TRIANGLES);//三角形
	glBegin(GL_QUADS);//四边形
	glVertex2iv(p1);
	glVertex2iv(p2);
	glVertex2iv(p3);
	glVertex2iv(p4);
	glEnd();
	glFlush();
}

void myKeyBorad(unsigned char key, int x, int y) 
{
	switch (key) 
	{
	case 'w': yd++; break;
	case 's': yd--; break;
	case 'a': xd--; break;
	case 'd': xd++; break;
	}
	glutPostRedisplay();
}

void init()
{
	glClearColor(1.0, 1.0, 1.0, 0.0);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(-20, 30, -20, 30);
}

int main(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(300, 100);
	glutInitWindowSize(600, 500);
	glutCreateWindow("key interaction");

	init();
	glutDisplayFunc(myDisplay);
	glutKeyboardFunc(myKeyBorad);//键盘交互
	glutMainLoop();
	return 0;
}

鼠标交互(glutMouseFunc)

例子:实现小方块的移动

代码

#include <GL/glut.h>

GLint w = 600, h = 500;

GLint xd = 0, yd = 0;

void myDisplay()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(0.87, 0.56, 0.4);
	glPointSize(2);
	//glBegin(GL_POINTS);
	//glBegin(GL_LINES);
	//glBegin(GL_LINE_STRIP);
	//glBegin(GL_LINE_LOOP);
	//glBegin(GL_TRIANGLES);//三角形
	//glBegin(GL_QUADS);//四边形
	glBegin(GL_POLYGON);//多边形
	glVertex2i(10 + xd, 10 + yd);
	glVertex2i(10 + xd,100 + yd);
	glVertex2i(100 + xd,100 + yd);
	glVertex2i(100 + xd,10 + yd);
	glEnd();
	glFlush();
}

void mouseMotion(GLint button, GLint state, GLint x, GLint y)
{
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)//当鼠标左键按下去的时候
	{
		xd = x;//改变全局变量xd,改变矩形的位置
		yd = h - y;//注意这里是h-y
		glutPostRedisplay();
	}
}

void myKeyBorad(unsigned char key, int x, int y)
{
	switch (key)
	{
	case 'w': yd++; break;
	case 's': yd--; break;
	case 'a': xd--; break;
	case 'd': xd++; break;
	}
	glutPostRedisplay();
}

void init()
{
	glClearColor(1.0, 1.0, 1.0, 0.0);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0, w, 0, h);
}

int main(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(300, 100);
	glutInitWindowSize(w, h);
	glutCreateWindow("Mouse Motion");

	init();
	glutDisplayFunc(myDisplay);
	//glutKeyboardFunc(myKeyBorad);
	glutMouseFunc(mouseMotion);
	glutMainLoop();
	return 0;
}

直线算法

DDA数值微分线段算法

方法论

  1. 起始点 ( x 1 , y 1 ) (x_1,y_1) (x1,y1),终点 ( x n , y n ) (x_n,y_n) (xn,yn)
  2. Δ x = ∣ x n − x 1 ∣ , Δ y = ∣ y n − y 1 ∣ \Delta x=|x_n-x_1|,\Delta y=|y_n-y_1| Δx=xnx1,Δy=yny1
  3. 比较 Δ x \Delta x Δx Δ y \Delta y Δy的步长
  4. steps= Δ x \Delta x Δx Δ y \Delta y Δy的较大者
  5. s t e p X = Δ x s t e p s , s t e p Y = Δ y s t e p s stepX=\frac{\Delta x}{steps},stepY=\frac{\Delta y}{steps} stepX=stepsΔx,stepY=stepsΔy

代码

#include <GL/glut.h>
#include<math.h>

GLint w = 600, h = 500;
GLint xd = 0, yd = 0;

void myDDA(GLfloat x1,GLfloat y1,GLfloat xn,GLfloat yn)
{
	float dx = fabs(xn - x1);//注意这里需要绝对值
	float dy = fabs(yn - y1);//注意这里abs会报错
	float steps;
	if (dx > dy)
		steps = dx;
	else
		steps = dy;
	float stepX = dx / steps;
	float stepY = dy / steps;
	glBegin(GL_POINTS);
	for (int i=0; i < (int)steps; i++) {
		glVertex2f(x1, y1);
		x1 += stepX;
		y1 += stepY;
	}
}

void myDisplay()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(0.87, 0.56, 0.4);
	glPointSize(1);
	myDDA(1.5, 3.8, 189.8, 267.5);//调用myDDA
	glEnd();
	glFlush();
}

void init()
{
	glClearColor(1.0, 1.0, 1.0, 0.0);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(-10, w, 0, h);
}

int main(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(300, 100);
	glutInitWindowSize(w, h);
	glutCreateWindow("DDA application");

	init();
	glutDisplayFunc(myDisplay);
	glutMainLoop();
	return 0;
}

效果

在这里插入图片描述

Bresenham直线算法

方法论

  1. 输入起始点 ( x 1 , y 1 ) (x_1,y_1) (x1,y1),终点 ( x n , y n ) (x_n,y_n) (xn,yn)
  2. d x = x n − x 1 , d y = y n − y 1 dx=x_n-x_1, dy=y_n-y_1 dx=xnx1,dy=yny1
  3. 计算 2 d x 2dx 2dx 2 d y 2dy 2dy
  4. 计算 P 0 = 2 d y − d x P_0=2dy-dx P0=2dydx
  5. 循环
    如果 P k > 0 P_k\gt0 Pk>0,选上面点 ( x k + 1 , y k + 1 ) , P k + 1 = P k + 2 d y − 2 d x (x_k+1,y_k+1),P_{k+1}=P_k+2dy-2dx (xk+1,yk+1),Pk+1=Pk+2dy2dx
    如果 P k < 0 P_k\lt0 Pk<0,选下面点 ( x k + 1 , y k ) , P k + 1 = P k + 2 d y (x_k+1,y_k),P_{k+1}=P_k+2dy (xk+1,yk),Pk+1=Pk+2dy

中点划线法

方法论

  1. 输入起始点 ( x 1 , y 1 ) (x_1,y_1) (x1,y1),终点 ( x n , y n ) (x_n,y_n) (xn,yn)
  2. Δ x = ∣ x n − x 1 ∣ , Δ y = ∣ y n − y 1 ∣ \Delta x=|x_n-x_1|,\Delta y=|y_n-y_1| Δx=xnx1,Δy=yny1
  3. 计算 m = Δ x Δ y m=\frac{\Delta x}{\Delta y} m=ΔyΔx b = y 1 − m x 1 b=y_1-mx_1 b=y1mx1
  4. 计算 d = F ( x 1 , y 1 + 0.5 ) = y 1 + 0.5 − m x 1 − b d=F(x_1,y_1+0.5)=y_1+0.5-mx_1-b d=F(x1,y1+0.5)=y1+0.5mx1b
  5. 循环
    如果 d > 0 d\gt0 d>0 x + + , ( x , y ) , d + = − m x++,(x,y),d+=-m x++,(x,y),d+=m
    如果 d < 0 d\lt0 d<0 x + + , y + + , ( x , y ) , d + = 1 − m x++,y++,(x,y),d+=1-m x++,y++,(x,y),d+=1m
;