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数值微分线段算法
方法论
- 起始点 ( x 1 , y 1 ) (x_1,y_1) (x1,y1),终点 ( x n , y n ) (x_n,y_n) (xn,yn)
- Δ x = ∣ x n − x 1 ∣ , Δ y = ∣ y n − y 1 ∣ \Delta x=|x_n-x_1|,\Delta y=|y_n-y_1| Δx=∣xn−x1∣,Δy=∣yn−y1∣
- 比较 Δ x \Delta x Δx和 Δ y \Delta y Δy的步长
- steps= Δ x \Delta x Δx和 Δ y \Delta y Δy的较大者
- 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直线算法
方法论
- 输入起始点 ( x 1 , y 1 ) (x_1,y_1) (x1,y1),终点 ( x n , y n ) (x_n,y_n) (xn,yn)
- d x = x n − x 1 , d y = y n − y 1 dx=x_n-x_1, dy=y_n-y_1 dx=xn−x1,dy=yn−y1
- 计算 2 d x 2dx 2dx和 2 d y 2dy 2dy
- 计算 P 0 = 2 d y − d x P_0=2dy-dx P0=2dy−dx
- 循环
如果 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+2dy−2dx
如果 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
中点划线法
方法论
- 输入起始点 ( x 1 , y 1 ) (x_1,y_1) (x1,y1),终点 ( x n , y n ) (x_n,y_n) (xn,yn)
- Δ x = ∣ x n − x 1 ∣ , Δ y = ∣ y n − y 1 ∣ \Delta x=|x_n-x_1|,\Delta y=|y_n-y_1| Δx=∣xn−x1∣,Δy=∣yn−y1∣
- 计算 m = Δ x Δ y m=\frac{\Delta x}{\Delta y} m=ΔyΔx 和 b = y 1 − m x 1 b=y_1-mx_1 b=y1−mx1
- 计算 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.5−mx1−b
- 循环
如果 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+=1−m