一、 实验目的
- 掌握OpenGL的鼠标按钮响应函数。
- 掌握OpenGL的鼠标移动响应函数。
- 进一步巩固OpenGL的基本图元绘制基础。
二、 实验环境
Microsoft Virtual Studio 2017+Win10
三、 实验内容
①鼠标画草图
- 在主程序注册鼠标响应和鼠标移动子函数:
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();
}