- 写在开头:
相关实验是学校开设课程的相关实验,本人所作较为粗浅,若有同校师弟浏览,望看懂借鉴而非照搬全抄。
- 实验目的:
利用鼠标、键盘,菜单等方式对图元进行交互操作
- 实验内容:
1、用鼠标拖动画直线,线段终点始终跟随鼠标移动;
2、使用菜单界面修改直线的颜色;
3、利用键盘控制直线在屏幕上移动;
- 实现效果及步骤(或流程)
实现效果:
1.鼠标左键选取直线,通过键盘的方向键对直线进行移动
2.绘制折线,鼠标右键开始折线绘制,单击键盘Q键,结束本次绘制
3.鼠标中键弹出菜单按钮,选择颜色对直线进行修改
实现步骤:
实验代码:
#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();
}