计算机图形学 实验四 OpenGL的鼠标交互绘制

一、 实验目的

  1. 掌握OpenGL的鼠标按钮响应函数。
  2. 掌握OpenGL的鼠标移动响应函数。
  3. 进一步巩固OpenGL的基本图元绘制基础。

二、 实验环境
Microsoft Virtual Studio 2017+Win10
三、 实验内容
①鼠标画草图

  1. 在主程序注册鼠标响应和鼠标移动子函数:
		glutMouseFunc(myMouse);
		glutMotionFunc(myMotion);

2)在程序头部声明鼠标响应和鼠标移动子函数:

 void myMouse(int button, int state, int x, int y); 
 void myMotion(int x, int y);
3)构建鼠标响应子函数:
//鼠标按钮响应事件
void myMouse(int button, int state, int x, int y)
{
	//鼠标左键按下——确定起始点
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
	{
		line[k][0] = x;
		line[k][1] = hh - y;
	}
	//鼠标左键松开——画最后一个顶点,画线结束
	if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
		line[k][2] = x;
		line[k][3] = hh - y;
		k++;
		glutPostRedisplay();
	}
}

4)构建鼠标响应子函数:

void myMotion(int x, int y)
{
	//get the lines’ motion point
	line[k][2] = x;
	line[k][3] = hh - y;
	glutPostRedisplay();
}

5)修改显示函数Display(),并添加画线函数drawlines()绘制子程序

void Display(void) {
	glClear(GL_COLOR_BUFFER_BIT);		//刷新颜色缓冲区
	drawlines();

	glutSwapBuffers();
}
//画线子程序
void drawlines() {
	for (int i = 0; i <= k; i++) {
		glBegin(GL_LINES);
		glVertex2f(line[i][0], line[i][1]);
		glVertex2f(line[i][2], line[i][3]);
		glEnd();
	}
}

6)添加坐标变量并设置变量初始化,定义Reshape()函数

#define N 1000				//线段最大条数
int line[N][4], k = 0;		//线段坐标存储数组, 线段计数
int ww, hh;					//显示窗口的宽和高
	
void Reshape(int w, int h)		//窗口改变时自动获取显示窗口的宽w和高h
{
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glViewport(0, 0, w, h);		//设置视区大小
	gluOrtho2D(0, w, 0, h);		//设置裁剪窗口大小
	ww = w;
	hh = h;
}

2、鼠标画线。编写OpenGL鼠标画线程序,并能够实现在绘制窗口用鼠标交互绘制若干直线,鼠标左键按下确定直线的起始点,鼠标按下同时画线过程保持移动,鼠标左键松开时确定直线重点,可重复画多条直线。
在这里插入图片描述

鼠标画线程序运行后,程序效果如上图所示。
3、鼠标绘制矩形。修改鼠标画线程序,要求:能够是现在绘制窗口用鼠标交互绘制若干举行,鼠标左键按下确定矩形对角线的起始点,鼠标左键按下可看到矩形的绘制过程,鼠标左键松开确定矩形对角线的另一点,可重复绘制多个矩形。
在这里插入图片描述
完整代码:

//鼠标画线例程line_draw.cpp
#include <GL/glut.h>
#include <iostream>
#define N 1000				//线段最大条数
int line[N][4], k = 0;		//线段坐标存储数组, 线段计数
int ww, hh;					//显示窗口的宽和高


void myMouse(int button, int state, int x, int y);
void myMotion(int x, int y);
void myinit(void);
void Reshape(int w,int h);
void display(void);
INT WINAPI wWinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPTSTR	lpCmdline,
	int		nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdline);

	char *argv[] = { (char *)"hello ",(char *)" " };
	int argc = 2;

	glutInit(&argc, argv);			//initialize glut  library
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowSize(800, 600);
	glutInitWindowPosition(0, 0);
	glutCreateWindow("Mouse draw line Showtime");
	myinit();
	glutDisplayFunc(display);
	
	glutMouseFunc(myMouse);
	glutMotionFunc(myMotion);
	glutReshapeFunc(Reshape);
	glutMainLoop();
	return 0;
}

void myinit(void) {
	glClearColor(0, 0, 0, 0);
	glLineWidth(3.0);
}

//画线子程序
void drawlines() {
	for (int i = 0; i <= k; i++) {
		glBegin(GL_LINES);
		glVertex2f(line[i][0], line[i][1]);
		glVertex2f(line[i][2], line[i][3]);
		glEnd();
	}
}

void display(void) {
	glClear(GL_COLOR_BUFFER_BIT);
	drawlines();

	glutSwapBuffers();
}

void Reshape(int w, int h)		//窗口改变时自动获取显示窗口的宽w和高h
{
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glViewport(0, 0, w, h);		//设置视区大小
	gluOrtho2D(0, w, 0, h);		//设置裁剪窗口大小
	ww = w;
	hh = h;
}

//鼠标按钮响应事件
void myMouse(int button, int state, int x, int y)
{
	//鼠标左键按下——确定起始点
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
	{
		line[k][0] = x;
		line[k][1] = hh - y;
	}
	//鼠标左键松开——画最后一个顶点,画线结束
	if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
		line[k][2] = x;
		line[k][3] = hh - y;
		k++;
		glutPostRedisplay();
	}
}

void myMotion(int x, int y)
{
	//get the line's motion point
	line[k][2] = x;
	line[k][3] = hh - y;
	glutPostRedisplay();
}
//鼠标绘制矩形rect_draw.cpp
#include <GL/glut.h>
#include <iostream>
#define N 1000				//矩形最大个数
int k = 0;					//矩形计数
int ww, hh;					//显示窗口的宽和高
//int corner[N][4];
struct GLintPoint {		//矩形结构
	int x, y;
};
GLintPoint corner[N][2];
/*矩形存储数组,第i个矩形坐标
x0 = corner[i][0].x
y0 = corner[i][0].y
x1 = corner[i][1].x
y1 = corner[i][1].y
*/
void myMouse(int button, int state, int x, int y);
void myMotion(int x, int y);
void myinit(void);
void Reshape(int w, int h);
void display(void);
void drawRects();
INT WINAPI wWinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPTSTR	lpCmdline,
	int		nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdline);

	char *argv[] = { (char *)"hello ",(char *)" " };
	int argc = 2;

	glutInit(&argc, argv);			//initialize glut  library
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowSize(800, 600);
	glutInitWindowPosition(0, 0);
	glutCreateWindow("Mouse draw Rectangle");
	myinit();
	glutDisplayFunc(display);

	glutMouseFunc(myMouse);
	glutMotionFunc(myMotion);
	glutReshapeFunc(Reshape);
	glutMainLoop();
	return 0;
}

void myinit(void) {
	glClearColor(0, 0, 0, 0);
	glLineWidth(3.0);
}

//矩阵绘制子程序
void drawRects() {
	for (int i = 0; i <= k; i++) {
		glBegin(GL_LINE_LOOP);
		glVertex2f(corner[i][0].x, corner[i][0].y);		//x0,y0
		glVertex2f(corner[i][0].x, corner[i][1].y);		//x0,y1
		glVertex2f(corner[i][1].x, corner[i][1].y);		//x1,y1
		glVertex2f(corner[i][1].x, corner[i][0].y);		//x1,y0	
		glEnd();
	}
}
//display()函数
void display(void) {
	glClear(GL_COLOR_BUFFER_BIT);
	drawRects();

	glutSwapBuffers();
}

void Reshape(int w, int h)		//窗口改变时自动获取显示窗口的宽w和高h
{
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glViewport(0, 0, w, h);		//设置视区大小
	gluOrtho2D(0, w, 0, h);		//设置裁剪窗口大小
	ww = w;
	hh = h;
}

//鼠标按钮响应事件
void myMouse(int button, int state, int x, int y)
{
	//鼠标左键按下——确定第一个矩形对角点
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
	{
		corner[k][0].x = x;		//x1
		corner[k][0].y = hh - y;	//y1
	}
	//鼠标左键松开——画下一个对角点,将矩形个数加1,画线结束
	if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
		corner[k][1].x = x;		//x2
		corner[k][1].y = hh - y;	//y2
		k++;
		glutPostRedisplay();
	}
}

void myMotion(int x, int y)
{
	//get the line's motion point
	corner[k][1].x = x;
	corner[k][1].y = hh - y;
	glutPostRedisplay();
}
  • 15
    点赞
  • 113
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值