Experiment 4—OpenGL mouse interactive drawing

1. Purpose of the experiment

1. Master the mouse button response function of OpenGL.
2. Master the mouse movement response function of OpenGL.
3. Further consolidate the basic primitive drawing foundation of OpenGL

2. Experimental content

1. Draw a sketch with the mouse - realize that wherever the mouse is clicked, the line will be drawn.
Ideas:
1) Register the mouse response and mouse movement sub-functions in the main program:

glutMouseFunc(mymouse);
glutMotionFunc(mymotion)

Place it after display registration and before mainloop.
2) Declare the mouse response and mouse movement sub-functions in the program header:

void myMouse(int button,int state,int x,int y); 
void myMotion(int x,int y);

3) Construct the mouse response sub-function:
//mouse button response event

void myMouse(int button, int state,int x,int y)
{
    
    
//鼠标左键按下——确定起始点
//鼠标左键松开——画最后一个顶点,画线结束
}

4) Construct the mouse movement sub-function:
//Get the coordinates of the mouse movement when the mouse moves

void myMotion(int x,int y)
{
    
    
/ /鼠标移动	线画到哪
}

5) Modify the display function Display():

#include "stdafx.h"
#include "Shiyan4.h"
#include <windows.h>
#include <gl/glut.h>
//画直线程序框架
int ww, hh;	//显示窗口宽和高
void Myinit(void);
void Reshape(int w, int h);
void Display(void);
int APIENTRY _tWinMain(HINSTANCE hlnstance, HINSTANCE hPrevInstance, LPTSTR	IpCmdLine,int	nCmdShow)
{
    
    
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(IpCmdLine);
char *argv[] = {
    
    "hello"," "}; 
int argc = 2; // argv中的字符串数	
glutInit(&argc, argv);
glutInitWindowSize(800, 600);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutCreateWindow("H鼠标画线小程序演示");
Myinit ();	//初始化GLUT库
//设置显示窗口大小
//设置显示模式(注意双缓存)
//创建显示窗口
glutDisplayFunc(Display);
glutReshapeFunc(Reshape);	//注册显示回调函数
//注册窗口改变回调函数	
glutMainLoop(); 
return 0;	//进入事件处理循环	
}
void Myinit(void)
{
    
    
	glClearColor(0.0,0.0,0.0,0.0);
	glLineWidth(3.0);
}
//渲染绘制子程序
void Display(void)
{
    
    
glClear (GL_COLOR_BUFFER_BIT) ; // 刷新颜色缓存区 glBegin(GL_LINES);
glVertex2f(0, 0);
glVertex2f(ww,hh);
glEnd();
glutSwapBuffers ();	//双缓存的刷新模式
}
void Reshape(int w, int h){
    
    
	glMatrixMode(GL_PROJECTION);	//投影矩阵模式
	glLoadIdentity();	//矩阵堆栈清空
	glViewport(0, 0, w, h);	//设置视区大小
	gluOrtho2D(0, w, 0, h);	//设置裁剪窗口大小
	ww=w;	
	hh=h;	
}

2. Draw a line with the mouse. Read the OpenGL mouse line drawing program, you can use the mouse to interactively draw several straight lines in the drawing window, first press the left mouse button to determine the starting point of the straight line, press the left mouse button and move at the same time, see the line drawing process, release the left mouse button When on, determine the end point of the straight line, and draw multiple straight lines repeatedly.
Ideas:
1) Write a program framework for drawing several static lines, and replace the coordinates with variables.
2) Register the mouse button response function and mouse movement response function in the main function.
3) Give the mouse button response event in the mouse button response subfunction.
4) Give the mouse movement response event in the mouse movement response subfunction.
5) Read and analyze the program, and keep the program.

#include <windows.h>
#include <stdio.h>
#include "stdafx.h"
#include "Shiyan4.h"
#include <gl/glut.h>
#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);
void drawines();
int APIENTRY wWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR    lpCmdLine,int       nCmdShow)
{
    
    
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);
	char* argv[] = {
    
     "hello "," " };
	int argc = 2;		//argv中的字符串数
	int sheight = glutGet(GLUT_SCREEN_WIDTH);
	int swidth = glutGet(GLUT_SCREEN_HEIGHT);
	glutInit(&argc, argv);							//初始化GLUT库
	glutInitWindowSize(800, 600);					//绘图窗口大小
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutCreateWindow("鼠标画线小程序演示");	//创建显示窗口
	Myinit();
	glutDisplayFunc(display);				//注册显示回调函数
	glutMouseFunc(myMouse);					//注册鼠标按钮回调函数
	glutMotionFunc(myMotion);				//注册鼠标移动回调函数
	glutReshapeFunc(Reshape);				//注册窗口改变回调函数
	glutMainLoop();							//表示开始运行程序,用于程序的结尾
	return 0;
}
void Myinit(void) {
    
    
	glClearColor(0.0, 0.0, 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;				//线段起点x坐标
		line[k][1] = hh - y;		//线段终点y坐标
	}
	//鼠标左键松开——画最后一个顶点,画线结束
	if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
    
    
		line[k][2] = x;				//线段起点x坐标
		line[k][3] = hh - y;		//线段终点y坐标
		k++;
		glutPostRedisplay();
	}
}
//鼠标移动时获得鼠标移动中的坐标
void myMotion(int x, int y)
{
    
    
	//get the line's motion point
	line[k][2] = x;				//动态终点的x坐标
	line[k][3] = hh - y;		//动态终点的y坐标
	glutPostRedisplay();
}

Experimental results:
insert image description here
3. The mouse draws a rectangle. Modify the mouse line drawing program. Requirements: be able to interactively draw several rectangles with the mouse in the drawing window. Press the left mouse button first to determine the starting point of the diagonal of the rectangle. Press the left mouse button and move at the same time to see the rectangle drawing process. Release the left button to determine another point on the diagonal of the rectangle, and multiple rectangles can be drawn repeatedly. as the picture shows.
Experimental results:
insert image description here
Code:

//鼠标绘制矩形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();
}

4. Thinking question: Draw a circle with the mouse. How to modify the code when the mouse draws a circle?
Experimental results:
insert image description here
Code:

#include "stdafx.h"
#include "ShiYan4-2.h"
//鼠标绘制矩形
#define GLUT_DISABLE_ATEXIT_HACK
#include <windows.h>
#include <gl/glut.h>
#include <math.h>
#define N 1000				//圆最大个数
#define PI  3.14159			//设置圆周率 
int n = 3600, R;			//多边形边数,外接圆半径 
float theta = 0.0;			//旋转初始角度值
int k = 0;		//圆数据存储数组,圆计数
int r[N][3];
int ww, hh;					//显示窗口的宽和高
struct GLintPoint {
    
    		//矩形结构
	int x, y;
};
GLintPoint corner[N][2];
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
		r[k][0] = (corner[k][0].x + corner[k][1].x) / 2;
		r[k][1] = (corner[k][0].y + corner[k][1].y) / 2;
		r[k][2] = sqrt(double((corner[k][0].x - corner[k][1].x)*(corner[k][0].x - corner[k][1].x) +(corner[k][0].y - corner[k][1].y) *(corner[k][0].y - corner[k][1].y))) / 2;
		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();
}
void Myinit(void) {
    
    
	glClearColor(0, 0, 0, 0);
	glLineWidth(3.0);
}
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 drawRound() {
    
    
	for (int i = 0; i <= k; i++) {
    
    
		glBegin(GL_LINE_LOOP);
		for (int j = 0; j < n; j++)
			glVertex2f((r[i][0] + r[i][2] * cos(j * 2 * PI / n)), (r[i][1] + r[i][2] * sin(j * 2 * PI / n)));  //顶点坐标 
		glEnd();
	}
}
void display(void) {
    
    
	glClear(GL_COLOR_BUFFER_BIT);
	drawRound();
	glutSwapBuffers();
}
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("鼠标绘制圆形");
	Myinit();
	glutDisplayFunc(display);
	glutMouseFunc(myMouse);
	glutMotionFunc(myMotion);
	glutReshapeFunc(Reshape);
	glutMainLoop();
	return 0;
}
3. Reference functions and codes

Refer to Chapter 5 of the textbook for basic primitive drawing functions, and Chapter 6 for mouse interaction functions.
1) Clipping window setting function:

gluOrtho2D(xwmin,xwmax,ywmin,ywmax);

2) Viewport setting function:

glViewport(startx,starty,viewport_width,viewport_height);

3) Code example of mouse drawing polyline:
//Start drawing polyline when the mouse button is pressed, and end when the mouse button is released

glutMotionFunc(mymotion);
void mymotion(int x,int y)
{
    
    .
if (first_time_called)
glBegin(GL_LINE_STRIP);
glVertex2f (sx* (GLfloat) x, sy* (GLfloat) (h-y));
}
//注意:鼠标按钮松开时产生glEndO

insert image description here

Guess you like

Origin blog.csdn.net/weixin_52030647/article/details/130727608