OpenGL利用鼠标、键盘分别实现那些绘图软件中的橡皮筋技术

橡皮筋技术:

如果大家用绘图软件画过直线,你就会发现选中那些直线、椭圆、矩形画图工具后,在画布上单击拖动就能画出我们所需尺寸的对应图形,十分方便,这就是所谓的橡皮筋技术。

实现橡皮筋技术的关键函数:

当然是鼠标响应函数了,OpenGL提供了以下几种响应鼠标事件的函数:

  1. 鼠标按下或者松开的响应函数:glutMouseFunc(MousePlot);
    参数MousePlot是对应的回调函数,可以随便取名字,但是参数一定是下面四个:
    void MousePlot(GLint button,GLint action,GLint xMouse,GLint yMouse)
    每个参数可取的值:
    (1)你按的是鼠标的哪个键(左中右)
    button:GLUT_LEFT_BUTTONGLUT_RIGHT_BUTTONGLUT_MIDDLE_BUTTON
    (2)对应事件(鼠标按下还是松开)
    action:GLUT_DOWN / GLUT_UP
    (3)鼠标的位置
    xMouse到窗口左侧的距离 yMouse到窗口顶部的距离,这里要注意这个yMouse,因为OpenGL的窗口是以左下角为坐标原点绘制图形的,所以yMouse是鼠标到底部的距离, 所以我们处理鼠标的y坐标时应该是用窗口高度减去yMouse来表示鼠标到顶部的距离。

  2. 按下鼠标移动鼠标时的响应函数glutMotionFunc(MouseMove);
    其参数仍是回调函数void MouseMove(GLint xMouse,GLint yMouse)

  3. 未按下鼠标移动鼠标时的响应函数glutPassiveMotionFunc(PassiveMouseMove);
    其参数仍是回调函数void PassiveMouseMove(GLint xMouse,GLint yMouse)

首先我们用鼠标来实现:

实现效果:
在这里插入图片描述
下面代码实现的功能有:
(1)单击一点松开鼠标再移动鼠标可以任意控制直线方向,再单击可以画一条直线
(2)右键清屏
屏幕上没有画或者画了都可以单击鼠标左键重新选第一个点

#include <GL\freeglut.h>

int iPointNum=0;//已确定点的数目
int x1=0,y1=0,x2=0,y2=0;//确定的点的坐标
int Width=400,Height=300;

//用户初始化函数
void myinit(void)
{
    //your initialization code
	glClearColor(1.0f,1.0f,1.0f,1.0f);
}

//窗口大小变化时的回调函数
void myReshape(int w, int h)
{
	Width=w;
	Height=h;
	//设定视区
    glViewport(0, 0, w, h);

	//设定透视方式
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
	gluOrtho2D(0.0,Width,0.0,Height);
}

//每桢OpenGL都会调用这个函数,用户应该把显示代码放在这个函数中
void display(void)
{
	//设置清除屏幕的颜色,并清除屏幕 
    glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1.0f,0.0f,0.0f);
	if(iPointNum>=1){
		glBegin(GL_LINES);
			glVertex2i(x1,y1);
			glVertex2i(x2,y2);
		glEnd();
	}
	//交换前后缓冲区
	glutSwapBuffers();
}
//按下鼠标的响应函数
void MousePlot(GLint button,GLint action,GLint xMouse,GLint yMouse)
{
	if(button==GLUT_LEFT_BUTTON && action==GLUT_DOWN){
		if(iPointNum==0||iPointNum==2){//屏幕上没有画或者画了都可以单击鼠标左键重新选第一个点
			iPointNum=1;//确定直线段的第一个端点
			x1=xMouse;
			y1=Height-yMouse;
		}else{//确定直线段的第二个端点
			iPointNum=2;
			x2=xMouse;
			y2=Height-yMouse;
			glutPostRedisplay();//指定窗口重新绘制
		}
	}
	if(button==GLUT_RIGHT_BUTTON && action==GLUT_DOWN){//右击可以清屏
		iPointNum=0;
		glutPostRedisplay();
	}
}
//没按鼠标时移动鼠标的回调函数,实现橡皮筋技术的地方
void PassiveMouseMove(GLint xMouse,GLint yMouse)
{
	if(iPointNum==1){
		x2=xMouse;
		y2=Height-yMouse;
		glutPostRedisplay();
	}
}
//主函数
int main(int argc, char* argv[])
{
	glutInit(&argc, argv);

	//初始化OPENGL显示方式
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA);
	//设定OPENGL窗口位置和大小
	glutInitWindowSize (400, 300); 
	glutInitWindowPosition (100, 100);
	//打开窗口
	glutCreateWindow ("橡皮筋技术");
	//调用初始化函数
    myinit();
	//开始OPENGL的循环
	glutDisplayFunc(display);
	//设定窗口大小变化的回调函数
	glutReshapeFunc(myReshape);
	//鼠标响应函数
	glutMouseFunc(MousePlot);
	//移动鼠标响应函数
	glutPassiveMotionFunc(PassiveMouseMove);
	 
	glutMainLoop();

	return 0;
}

用键盘控制:

我把代替鼠标的部分注释掉了,换成了键盘控制的部分,现在按下松开鼠标就由P键控制了。但是移动鼠标还是用的鼠标事件函数。

#include <GL\freeglut.h>

int iPointNum=0;//已确定点的数目
int x1=0,y1=0,x2=0,y2=0;//确定的点的坐标
int Width=400,Height=300;

//用户初始化函数
void myinit(void)
{
    //your initialization code
	glClearColor(1.0f,1.0f,1.0f,1.0f);
}

//窗口大小变化时的回调函数
void myReshape(int w, int h)
{
	Width=w;
	Height=h;
	//设定视区
    glViewport(0, 0, w, h);

	//设定透视方式
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
	gluOrtho2D(0.0,Width,0.0,Height);
}

//每桢OpenGL都会调用这个函数,用户应该把显示代码放在这个函数中
void display(void)
{
	//设置清除屏幕的颜色,并清除屏幕 
    glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1.0f,0.0f,0.0f);
	if(iPointNum>=1){
		glBegin(GL_LINES);
			glVertex2i(x1,y1);
			glVertex2i(x2,y2);
		glEnd();
	}
	//交换前后缓冲区
	glutSwapBuffers();
}
//用键盘的输入代替按下鼠标
void processNormalKeys(unsigned char key,int x,int y)
{
	switch(key){
		case 'p':
			if(iPointNum==0||iPointNum==2){//屏幕上没有画或者画了都可以单击鼠标左键重新选第一个点
				iPointNum=1;//确定直线段的第一个端点
				x1=x;
				y1=Height-y;
			}else{//确定直线段的第二个端点
				iPointNum=2;
				x2=x;
				y2=Height-y;
				glutPostRedisplay();//指定窗口重新绘制
			}
			break;
		default:break;
	}
}
/*//按下鼠标的响应函数
void MousePlot(GLint button,GLint action,GLint xMouse,GLint yMouse)
{
	if(button==GLUT_LEFT_BUTTON && action==GLUT_DOWN){
		if(iPointNum==0||iPointNum==2){//屏幕上没有画或者画了都可以单击鼠标左键重新选第一个点
			iPointNum=1;//确定直线段的第一个端点
			x1=xMouse;
			y1=Height-yMouse;
		}else{//确定直线段的第二个端点
			iPointNum=2;
			x2=xMouse;
			y2=Height-yMouse;
			glutPostRedisplay();//指定窗口重新绘制
		}
	}
	if(button==GLUT_RIGHT_BUTTON && action==GLUT_DOWN){//右击可以清屏
		iPointNum=0;
		glutPostRedisplay();
	}
}*/
//没按鼠标时移动鼠标的回调函数,实现橡皮筋技术的地方
void PassiveMouseMove(GLint xMouse,GLint yMouse)
{
	if(iPointNum==1){
		x2=xMouse;
		y2=Height-yMouse;
		glutPostRedisplay();
	}
}
//主函数
int main(int argc, char* argv[])
{
	glutInit(&argc, argv);

	//初始化OPENGL显示方式
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA);
	//设定OPENGL窗口位置和大小
	glutInitWindowSize (400, 300); 
	glutInitWindowPosition (100, 100);
	//打开窗口
	glutCreateWindow ("橡皮筋技术");
	//调用初始化函数
    myinit();
	//开始OPENGL的循环
	glutDisplayFunc(display);
	//设定窗口大小变化的回调函数
	glutReshapeFunc(myReshape);
	//鼠标响应函数
	//glutMouseFunc(MousePlot);
	//用键盘实现橡皮筋技术
	glutKeyboardFunc(processNormalKeys);
	//移动鼠标响应函数
	glutPassiveMotionFunc(PassiveMouseMove);
	 
	glutMainLoop();

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值