一、实验目的

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

二、实验内容

1.鼠标画草图——实现鼠标点到哪,线就画到哪。 思路: 1 )在主程序注册鼠标响应和鼠标移动子函数:

glutMouseFunc(mymouse);

glutMotionFunc(mymotion);

放在display注册之后和mainloop之前。 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)

{

//鼠标左键按下——确定起始点

//鼠标左键松开——画最后一个顶点,画线结束

}

4)构造鼠标移动子函数: //鼠标移动时获得鼠标移动中的坐标

void myMotion(int x,int y)

{

/ /鼠标移动 线画到哪

}

5 )修改显示函数Display():

#include "stdafx.h"

#include "Shiyan4.h"

#include

#include

//画直线程序框架

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.鼠标画线。阅读OpenGL鼠标画线程序,能够实现在绘制窗口用鼠标交互绘制若干条 直线,鼠标左键首先按下确定直线的起始点,鼠标左键按下同时移动,看到画线过程,鼠标 左键松开时确定直线的终点,可重复画多条直线。 思路: 1) 写出画静止若干条直线程序框架,坐标用变量替代。 2) 在主函数里注册鼠标按钮响应函数和鼠标移动响应函数。 3) 在鼠标按钮响应子函数里给岀鼠标按钮响应事件。 4) 在鼠标移动响应子函数里给出鼠标移动响应事件。 5) 读懂程序并分析程序,保留程序。

#include

#include

#include "stdafx.h"

#include "Shiyan4.h"

#include

#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();

}

实验结果: 3.鼠标绘制矩形。修改鼠标画线程序,要求:能够实现在绘制窗口用鼠标交互绘制若干 矩形,鼠标左键首先按下确定矩形对角线的起始点,鼠标左键按下同时移动时看到画矩形过 程,鼠标左键松开确定矩形对角线的另一点,可重复画多个矩形。如图所示。 实验结果: 代码:

//鼠标绘制矩形rect_draw.cpp

#include

#include

#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.思考题:鼠标画圆。鼠标画圆应如何修改代码? 实验结果: 代码:

#include "stdafx.h"

#include "ShiYan4-2.h"

//鼠标绘制矩形

#define GLUT_DISABLE_ATEXIT_HACK

#include

#include

#include

#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;

}

三、参考函数与代码

基本图元绘制函数参考教材第5章,鼠标交互函数参考第6章。 1)裁剪窗口设置函数:

gluOrtho2D(xwmin,xwmax,ywmin,ywmax);

2)视区设置函数:

glViewport(startx,starty,viewport_width,viewport_height);

3)鼠标绘制折线代码示例: //鼠标按下时开始画折线,鼠标按钮松开时结束

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

参考链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: