0x00

实验二:(2学时)
一、实验目的:
利用鼠标、键盘,菜单等方式对图元进行交互操作
二、实验内容:
1、用鼠标拖动画直线,线段终点始终跟随鼠标移动;
2、使用菜单界面修改直线的颜色;
3、利用键盘控制直线在屏幕上移动;
三、实现效果及步骤(或流程)
四、创新设计和实现方法

0x01

  • 直接上代码,具体可参考书本

    P459 鼠标函数、P462 键盘函数、P471 菜单功能

#include "stdafx.h"
#include <GL/glut.h>
GLsizei winWidth = 400, winHeight = 300;
class scrPt {
public:
	GLint x, y;
};
scrPt endPt1, endPt2; //起点以及终点
GLfloat r=0.0, g=0.0, b=0.0; //颜色代码
bool flag;
int ptCtr = 0;
void init(void)
{
	glClearColor(1.0, 1.0, 1.0, 0.0);//背景设置为白色
	glMatrixMode(GL_PROJECTION);
	gluOrtho2D(0.0, 400.0, 0.0, 300.0);
}
void displayfcn(void){
}
void winReshapeFcn(GLint newWidth, GLint newHeight) { //窗体大小变化时刷新
	glClear(GL_COLOR_BUFFER_BIT);
	glViewport(0, 0, newWidth, newHeight);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, GLdouble(newWidth), 0.0, GLdouble(newHeight));
	winWidth = newWidth;
	winHeight = newHeight;
	glFlush();
}
void lineSegment(scrPt endPt1, scrPt endPt2) //画线函数
{
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(r, g, b); 
	glBegin(GL_LINES);
	glVertex2i(endPt1.x, endPt1.y);
	glVertex2i(endPt2.x, endPt2.y);
	glEnd();
	glFlush();
}
void mainMenu(GLint selectOptional) { //改变颜色菜单
	switch (selectOptional)
	{
	case 1: 
		r = 255;
		g = b = 0;
		lineSegment(endPt1, endPt2);
		break;
	case 2: 
		g = 255;
		r = b = 0;
		lineSegment(endPt1, endPt2);
		break;
	case 3: 
		b = 255;
		r = g = 0;
		lineSegment(endPt1, endPt2);
		break;
	}
}
void ployline1(GLint button, GLint action, GLint xMouse, GLint yMouse) { //确定起始终点坐标
		
		if (button == GLUT_LEFT_BUTTON && action == GLUT_DOWN) {
			if (ptCtr == 0) {
				r = g = b = 0.0;
				endPt1.x = xMouse;
				endPt1.y = winHeight - yMouse;
				ptCtr = 1;
			}
			else if (ptCtr == 1) {
				lineSegment(endPt1, endPt2);
				ptCtr = 0;
			}
		}
}
void ployline2(GLint xMouse, GLint yMouse) { //持续获取鼠标位置
	if (ptCtr == 1) {
		endPt2.x = xMouse;
		endPt2.y = winHeight - yMouse;
		lineSegment(endPt1, endPt2);
	}
}
void keyBoardeve(GLint specialKey, GLint xMouse, GLint yMouse) { //键盘控制
	switch (specialKey)
	{
	case GLUT_KEY_UP:
		flag = endPt1.y > endPt2.y ? true : false;
		if (flag && endPt2.y>=winHeight) {
			endPt2.y = 0-(endPt1.y - endPt2.y);
			endPt1.y = 0;
			lineSegment(endPt1, endPt2);
		}
		else if (!flag && endPt1.y >= winHeight) {
			endPt1.y = 0-(endPt2.y - endPt1.y);
			endPt2.y = 0;
			lineSegment(endPt1, endPt2);
		}
		else {
			endPt1.y += 10;
			endPt2.y += 10;
			lineSegment(endPt1, endPt2);
		}
		break;
	case GLUT_KEY_DOWN:
		flag = endPt1.y > endPt2.y ? true : false;
		if (flag && endPt1.y <= 0) {
			endPt1.y = winHeight + (endPt1.y - endPt2.y);
			endPt2.y = winHeight;
			lineSegment(endPt1, endPt2);
		}
		else if (!flag && endPt2.y <=0) {
			endPt2.y = winHeight + (endPt2.y - endPt1.y);
			endPt1.y = winHeight;
			lineSegment(endPt1, endPt2);
		}
		else {
			endPt1.y -= 10;
			endPt2.y -= 10;
			lineSegment(endPt1, endPt2);
		}
		break;
	case GLUT_KEY_LEFT:
		flag = endPt1.x < endPt2.x ? true : false;
		if (flag && endPt2.x <= 0) {
			endPt2.x = winWidth + (endPt2.x - endPt1.x);
			endPt1.x = winWidth;
			lineSegment(endPt1, endPt2);
		}
		else if (!flag && endPt1.x <= 0) {
			endPt1.x = winWidth + (endPt1.x - endPt2.x);
			endPt2.x = winWidth;
			lineSegment(endPt1, endPt2);
		}
		else {
			endPt1.x -= 10;
			endPt2.x -= 10;
			lineSegment(endPt1, endPt2);
		}
		break;
	case GLUT_KEY_RIGHT:
		flag = endPt1.x < endPt2.x ? true : false;
		if (flag && endPt1.x >= winWidth) {
			endPt1.x = 0 - (endPt2.x - endPt1.x);
			endPt2.x = 0;
			lineSegment(endPt1, endPt2);
		}
		else if (!flag && endPt2.x >= winWidth) {
			endPt2.x = 0 - (endPt1.x - endPt2.x);
			endPt1.x = 0;
			lineSegment(endPt1, endPt2);
		}
		else {
			endPt1.x += 10;
			endPt2.x += 10;
			lineSegment(endPt1, endPt2);
		}
		break;
	default:
		break;
	}
}
void main(int argc, char** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
	glutInitWindowPosition(50, 100);
	glutInitWindowSize(winWidth, winHeight);
	glutCreateWindow("An Example OpenGL Program");
	init();
	glutDisplayFunc(displayfcn);
	glutReshapeFunc(winReshapeFcn);
	glutPassiveMotionFunc(ployline2);
	glutMouseFunc(ployline1);
	glutSpecialFunc(keyBoardeve);
	glutCreateMenu(mainMenu);
		glutAddMenuEntry("red", 1);
		glutAddMenuEntry("green", 2);
		glutAddMenuEntry("blue", 3);
	glutAttachMenu(GLUT_RIGHT_BUTTON); //右键启动菜单
	glutMainLoop();
}
  • 最终效果

两点确定直线,右键唤出菜单

颜色变换

0x02

封面出处:http://simpledesktops.com/browse/desktops/2019/jan/19/lion/