计算机图形学OpenGL学习实验一

  • 写在开头:

相关实验是学校开设课程的相关实验,本人所作较为粗浅,若有同校师弟浏览,望看懂借鉴而非照搬全抄。


  • 实验目的:

利用鼠标、键盘,菜单等方式对图元进行交互操作


  • 实验内容:

1、用鼠标拖动画直线,线段终点始终跟随鼠标移动;

2、使用菜单界面修改直线的颜色;

3、利用键盘控制直线在屏幕上移动;


  • 实现效果及步骤(或流程)

实现效果:

1.鼠标左键选取直线,通过键盘的方向键对直线进行移动

2.绘制折线,鼠标右键开始折线绘制,单击键盘Q键,结束本次绘制

3.鼠标中键弹出菜单按钮,选择颜色对直线进行修改

实现步骤:


  • 相关功能实现方法
  1. 绘制折线

相关代码在方法mousePlot、drawLines、quitLinePlot中

#include <GL/glut.h>
#include <vector>
#include <iostream>

void mouseMovePtPlot(GLint xMouse, GLint yMouse);
GLsizei winWidth = 400, winHeight = 300;
GLint point[2][2];
bool ptCtr = true;
bool lineCtr = false;
GLenum fillMode = GL_SMOOTH;  // Initial polygon fill: color interpolation.
float color[1][3] = {0.0,0.0,0.0};

int tag;//记录选取的点在数组中的位置

std::vector<GLint> points;//用于存储线段


void init(void) {
	glClearColor(1.0, 1.0, 1.0, 1.0);
	glClear(GL_COLOR_BUFFER_BIT);
	glMatrixMode(GL_PROJECTION);
	gluOrtho2D(0.0, 200.0, 0.0, 150.0);
}

void displayFcn() {

	glColor3f(0.0, 0.0, 0.0);
	glPointSize(3.0);

}

//绘制已保存的线段
void drawLines() {

	int length = points.size();
	glColor3fv(color[0]);
	glBegin(GL_LINES);
		for (GLint i = 0; i <length - 3 ; i+=2) {
			if (points[i + 2] == points[i] && points[i + 3] == points[i + 1]) {
				i += 2;//跳过下一个点
				std::cout << "断点(" << points[i] << "," << points[i + 1] << ") " << std::endl;
				continue;
			}
			glVertex2i(points[i], points[i+1]);
			glVertex2i(points[i+2], points[i + 3]);
		}
		glVertex2i(points[length - 2], points[length - 1]);
		glVertex2iv(point[1]);//该点是鼠标移动过程中的点,是一个暂时的点,鼠标右键抬起时才会保存

		glEnd();
}

void drawChangedLines() {
	glClear(GL_COLOR_BUFFER_BIT);
	int length = points.size();
	glColor3fv(color[0]);
	glBegin(GL_LINES);
	for (GLint i = 0; i < length - 3; i += 2) {
		if (points[i + 2] == points[i] && points[i + 3] == points[i + 1]) {
			i += 2;//跳过下一个点
			std::cout << "断点(" << points[i] << "," << points[i + 1] << ") " << std::endl;
			continue;
		}
		glVertex2i(points[i], points[i + 1]);
		glVertex2i(points[i + 2], points[i + 3]);
	}
	glEnd();
	glFlush();
}

void winReshapeFcn(GLint newWidth, GLint newHeight) {
	glViewport(0, 0, newWidth, newHeight);
	glLoadIdentity();
	gluOrtho2D(0.0, GLdouble(newWidth), 0.0, GLdouble(newHeight));

	winWidth = newWidth;
	winHeight = newHeight;
}


//退出折线绘制
void quitLinePlot(GLubyte curvePlotKey, GLint xMouse, GLint yMouse)
{
	GLint x = xMouse;
	GLint y = winHeight - yMouse;
	switch (curvePlotKey)
	{
	case 'q':
		ptCtr = true;
		points.push_back(point[1][0]);
		points.push_back(point[1][1]);
		break;
	default:
		break;
	}
	glFlush();
}


void mouseMoveLinePlot(GLint xMouse, GLint yMouse) {
	if (lineCtr) {
		glClear(GL_COLOR_BUFFER_BIT);
		point[1][0] = xMouse;
		point[1][1] = winHeight - yMouse;

		drawLines();
		//plotLine(point);

		glFlush();
	}
	
	

}

//鼠标事件回调函数
void mousePlot(GLint button, GLint action, GLint xMouse, GLint yMouse) {
	//获得起始点坐标
	if (button == GLUT_LEFT_BUTTON && action == GLUT_DOWN)
	{
		if (points.size() != 0) {
			GLint x = xMouse;
			GLint y = winHeight - yMouse;
			for (GLint i = 0; i < points.size() - 3; i += 2) {
				if (points[i + 2] == points[i] && points[i + 3] == points[i + 1]) {
					i += 2;//跳过下一个点
					std::cout << "断点(" << points[i] << "," << points[i + 1] << ") " << std::endl;
					continue;
				}
				GLint x1, y1, x2, y2;
				x1 = points[i];
				y1 = points[i + 1];
				x2 = points[i + 2];
				y2 = points[i + 3];
				int k = x2 * y - x1 * y - y2 * x + y1 * x - x2 * y1 + x1 * y2;
				if (k + 1000 > 0 && k - 1000 < 0) {
					tag = i;
				}
			}
		}
		
	}
	else if (button == GLUT_RIGHT_BUTTON && action == GLUT_DOWN) {
		lineCtr = true;
		if (ptCtr) {
			point[0][0] = xMouse;
			point[0][1] = winHeight - yMouse;
			glutMotionFunc(mouseMoveLinePlot);
			points.push_back(point[0][0]);
			points.push_back(point[0][1]);
			ptCtr = false;
		}else {
			point[1][0] = xMouse;
			point[1][1] = winHeight - yMouse;
			glutMotionFunc(mouseMoveLinePlot);
		}
	}
	else if (button == GLUT_RIGHT_BUTTON && action == GLUT_UP) {
		
		point[0][0] = point[1][0];
		point[0][1] = point[1][1];
		std::cout << "线段终点(" << point[0][0]<< "," << point[0][1] << ") " << std::endl;
		points.push_back(point[1][0]);
		points.push_back(point[1][1]);
		for (int i = 0; i < points.size() - 1; i+=2) {
			std::cout << "(" << points[i] << "," << points[i+1] << ") ";
		}
		std::cout << std::endl;
		lineCtr = false;
	}
}

//菜单事件回调函数
void colorOption(GLint selectedOption)
{
	switch (selectedOption) {
	case 1:  
		color[0][0] = 1.0;
		color[0][1] = color[0][2] = 0.0;
		break;
	case 2:  
		color[0][1] = 1.0;
		color[0][0] = color[0][2] = 0.0;
		break;
	case 3:
		color[0][2] = 1.0;
		color[0][0] = color[0][1] = 0.0;
		break;
	default:
		break;
	}
	drawChangedLines();
}

//特殊键位移动直线
void moveLine(GLint reductionKey, GLint xMouse, GLint yMouse)
{
	switch (reductionKey)
	{
	case GLUT_KEY_UP:
		points[tag + 1] += 20;
		points[tag + 3] += 20;
		drawChangedLines();
		break;
	case GLUT_KEY_DOWN:
		points[tag + 1] -= 20;
		points[tag + 3] -= 20;
		drawChangedLines();
		break;
	case GLUT_KEY_LEFT:
		points[tag] -= 20;
		points[tag + 2] -= 20;
		drawChangedLines();
		break;
	case GLUT_KEY_RIGHT:
		points[tag] += 20;
		points[tag + 2] += 20;
		drawChangedLines();
		break;
	default:
		break;
	}
}


void main(int argc, char ** argv) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(winWidth, winHeight);
	glutCreateWindow("CGLab2_CAIYIPEI");

	init();

	glutDisplayFunc(displayFcn);
	glutReshapeFunc(winReshapeFcn);
	glutMouseFunc(mousePlot);
	glutKeyboardFunc(quitLinePlot);
	glutCreateMenu(colorOption);              // Create pop-up menu.
		glutAddMenuEntry("RED", 1);
		glutAddMenuEntry("GREEN", 2);
		glutAddMenuEntry("BLUE", 3);

	glutSpecialFunc(moveLine);
	/*  Select a menu option using the right mouse button.  */
	glutAttachMenu(GLUT_MIDDLE_BUTTON);

	glutMainLoop();
}

 

 

发布了4 篇原创文章 · 获赞 15 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_37996608/article/details/103921802