计算机图形学交互式技术实验(鼠标、拾取操作和菜单)——绘制可用鼠标进行修改颜色的五角星和矩形

news/2025/3/13 15:30:58/

1、实验目的:

熟练OpenGL中的鼠标响应函数的使用方法、拾取操作实现和创建菜单的实现。

2、实验要求:

(1)绘制两个及以上图元(在此我绘制了一个五角星和两个矩形)

(2)创建窗体菜单用于改图元的颜色(菜单内写入若干可供选择的颜色)

(3)鼠标左键用于拾取特定的图元(如五角星,矩形等)

(4)选定图元后,通过鼠标右键弹出颜色菜单来改图元的颜色

如下图所示:

3、实验步骤

(1)需要引入两个程序库

#include <gl/glut.h>  // 引入GLUT 程序库
#include <stdio.h>   // 为打印选择元素的提示

(2)确定窗口大小

GLsizei winWidth = 800, winHeight = 540;    // 窗口的宽度和高度

(3)为每个图元赋予对应的RGB变量

GLfloat red1 = 1.0, green1 = 1.0, blue1 = 1.0; // 第一个图元(五角星)的RGB混合颜色成分
GLfloat red2 = 1.0, green2 = 1.0, blue2 = 1.0; // 第二个图元(矩形)的RGB混合颜色成分
GLfloat red3 = 1.0, green3 = 1.0, blue3 = 1.0; // 第三个图元(矩形)的RGB混合颜色成分

(4)使用一个变量来保存目前指定的图元,如选定第一个图元时,flag=1;选定第二个图元时,flag=2;选定第三个图元时,flag=3等,根据当前图元可更改对应图元RGB的值

const GLint pickSize = 32;//拾取缓冲区的大小
GLuint flag = 0;   // 一个变量为了指定目前的图元-是五角星还是矩形等

(5)构造方法体

void initial()
{glClearColor(255, 0, 0, 0); // 设置窗口背景颜色为红色}void mainMenu(GLint colorOption)   // 接收菜单项的ID, 并执行相应的任务
{if (flag == 1) {  // 通过菜单选择第一个图元(五角星)switch (colorOption)  //判断菜单项的ID{case  1:red1 = 0.98, green1 = 0.625, blue1 = 0.12; // 改第一个图元(五角星)的颜色为南瓜橙break;case  2:red1 = 0.0, green1 = 1.0, blue1 = 0.0;// 改第一个图元(五角星)的颜色为绿色break;case  3:red1 = 0.98, green1 = 0.04, blue1 = 0.70;// 改第一个图元(五角星)的颜色为粉红色break;case  4:red1 = 0.0, green1 = 0.0, blue1 = 0.0;// 改第一个图元(五角星)的颜色为黑色break;case  5:red1 = 1.0, green1 = 1.0, blue1 = 0.0;// 改第一个图元(五角星)的颜色为黄色break;default:break;}glutPostRedisplay();}if (flag == 2) {  // 通过菜单选择第二个图元(矩形)switch (colorOption)  //判断菜单项的ID{case  1:red2 = 0.98, green2 = 0.625, blue2 = 0.12; // 改第二个图元(矩形)的颜色为南瓜橙break;case  2:red2 = 0.0, green2 = 1.0, blue2 = 0.0;// 改第二个图元(矩形)的颜色为绿色break;case  3:red2 = 0.98, green2 = 0.04, blue2 = 0.70;// 改第二个图元(矩形)的颜色为粉红色break;case  4:red2 = 0.0, green2 = 0.0, blue2 = 0.0;// 改第二个图元(矩形)的颜色为黑色break;case  5:red2 = 1.0, green2 = 1.0, blue2 = 0.0;// 改第二个图元(矩形)的颜色为黄色break;default:break;}glutPostRedisplay();}if (flag == 3) {  // 通过菜单选择第三个图元(矩形)switch (colorOption)  //判断菜单项的ID{case  1:red3 = 0.98, green3 = 0.625, blue3 = 0.12; // 改第三个图元(矩形)的颜色为南瓜橙break;case  2:red3 = 0.0, green3 = 1.0, blue3 = 0.0;// 改第三个图元(矩形)的颜色为绿色break;case  3:red3 = 0.98, green3 = 0.04, blue3 = 0.70;// 改第三个图元(矩形)的颜色为粉红色break;case  4:red3 = 0.0, green3 = 0.0, blue3 = 0.0;// 改第三个图元(矩形)的颜色为黑色break;case  5:red3 = 1.0, green3 = 1.0, blue3 = 0.0;// 改第三个图元(矩形)的颜色为黄色break;default:break;}glutPostRedisplay();}
}void winReshapeFcn(GLint newWidth, GLint newHeight)
{glViewport(0, 0, newWidth, newHeight);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(0.0, GLdouble(newWidth), 0.0, GLdouble(newHeight));winWidth = newWidth;winHeight = newHeight;
}void Draw(GLenum mode) {if (mode == GL_SELECT)glPushName(1);//将名字1压入堆栈glColor3f(red1, green1, blue1);glBegin(GL_TRIANGLES);glVertex2i(200, 300);glVertex2i(590, 300);glVertex2i(400, 180);glEnd();glColor3f(red1, green1, blue1);glBegin(GL_TRIANGLES);glVertex2i(200, 300);glVertex2i(510, 100);glVertex2i(450, 300);glEnd();glColor3f(red1, green1, blue1);glBegin(GL_TRIANGLES);glVertex2i(270, 100);glVertex2i(400, 420);glVertex2i(470, 215);glEnd();if (mode == GL_SELECT)glPushName(2);//将名字2压入堆栈glColor3f(red2, green2, blue2);glRectf(50, 50, 750, 80);if (mode == GL_SELECT)glPushName(3);//将名字3压入堆栈glColor3f(red3, green3, blue3);glRectf(50, 450, 750, 480);}
void display(void)
{glClear(GL_COLOR_BUFFER_BIT);Draw(GL_RENDER);//用渲染模式绘制图形glFlush();
}void ProcessPicks(GLint nPicks, GLuint pickBuffer[]) {   // 在控制台里显示鼠标选择的图元GLint i; GLuint name, * ptr;ptr = pickBuffer;printf("\n");for (i = 0; i < nPicks; i++) {name = *ptr;//选中图元在堆栈中的位置ptr += 3;//跳过名字和深度信息ptr += name - 1;//根据位置信息获得选中的图元名字if (*ptr == 1) {printf("你选择的图元是五角星\n");flag = 1; //选择的图元是五角星}if (*ptr == 2) {printf("你选择的图元是矩形\n");flag = 2; //选择的图元是矩形}if (*ptr == 3) {printf("你选择的图元是矩形\n");flag = 3; //选择的图元是矩形}ptr++;}printf("\n");
}
void MousePlot(GLint button, GLint action, GLint xMouse, GLint yMouse) { // 指定鼠标相应函数GLuint pickBuffer[pickSize];GLint nPicks, vp[4];if (button == GLUT_LEFT_BUTTON && action == GLUT_DOWN) {glSelectBuffer(pickSize, pickBuffer);//设置选择缓冲区glRenderMode(GL_SELECT);//激活选择模式glInitNames();//初始化名字堆栈glMatrixMode(GL_PROJECTION);glPushMatrix();//将当前的投影矩阵复制一个并压入堆栈glLoadIdentity();glGetIntegerv(GL_VIEWPORT, vp);//获得当前窗口显示区域的参数//定义一个10×10的选择区域gluPickMatrix(GLdouble(xMouse), GLdouble(vp[3] - yMouse), 10.0, 10.0, vp);gluOrtho2D(0.0, winWidth, 0.0, winHeight);Draw(GL_SELECT);//用选择模式绘制图形//恢复投影变换glMatrixMode(GL_PROJECTION);glPopMatrix();//将投影矩阵堆栈中的栈顶元素删除glFlush();//获得选择集并输出nPicks = glRenderMode(GL_RENDER);ProcessPicks(nPicks, pickBuffer);//输出选择结果glutPostRedisplay();}
}

(6)main方法需要声明的函数:initial、glutReshapeFunc、glutDisplayFunc、glutCreateMenu、glutMouseFunc等

int  main(int argc, char* argv[])
{glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowPosition(300, 200);glutInitWindowSize(winWidth, winHeight);glutCreateWindow("交互式技术");initial();glutReshapeFunc(winReshapeFcn); //指定窗口的大小glutDisplayFunc(display);     // 绘制窗口内的内容glutCreateMenu(mainMenu);//主菜单项glutAddMenuEntry("南瓜橙", 1);  // 菜单项”蓝色“和其IDglutAddMenuEntry("绿色", 2);// 菜单项”绿色“和其IDglutAddMenuEntry("粉红色", 3);// 菜单项”红色“和其IDglutAddMenuEntry("黑色", 4);// 菜单项”黑色“和其IDglutAddMenuEntry("黄色", 5);// 菜单项”黄色“和其IDglutAttachMenu(GLUT_RIGHT_BUTTON);  //绑定菜单和鼠标右键glutMouseFunc(MousePlot); // 指定鼠标相应函数glutMainLoop();//启动主循环,等待消息return 0;
}

http://www.ppmy.cn/news/1578817.html

相关文章

基于SpringBoot+Vue的校园跑腿原生小程序

系列文章目录 1.基于SSM的洗衣房管理系统原生微信小程序LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统LW参考示例 3.基于SpringBootVue的企业人事管理系统LW参考示例 4.基于SSM的高校实验室管理系统LW参考示例 5.基于SpringBoot的二手数码回收系统原生微信小程序LW参考示…

LLM最新的模型微调技术有哪些

LLM 最新的模型微调技术有哪些 目录 LLM 最新的模型微调技术有哪些1. QLoRA(Quantized Low-Rank Adaptation)2. P-Tuning v23. LoRA++(增强版 LoRA)4. AdaLoRA(Adaptive LoRA)5. BitFit(仅微调偏置)1. QLoRA(Quantized Low-Rank Adaptation) 原理:QLoRA 结合了低秩自…

FFmpeg入门:最简单的音视频播放器(Plus优化版)

FFmpeg入门&#xff1a;最简单的音视频播放器&#xff08;Plus优化版&#xff09; 今天我们继续学习FFmpeg的入门&#xff0c;咱们主要是从上一期的音频播放器的基础上进行了部分优化。没有看过上期讲解的朋友可以去回顾一下&#xff0c;链接放下面了。 FFmpeg入门&#xff1a…

uniapp+微信小程序+最简单局部下拉刷新实现

直接上代码 <scroll-view style"height: 27vh;" :scroll-top"scrollTop" scroll-y"true"scrolltolower"onScrollToLower1" lower-threshold"50"refresher-enabled"true" refresherrefresh"onRefresherR…

案例1_1:Proteus点亮8个蓝色LED灯

文章目录 文章介绍1、原理图2、新建项目文件和.c文件3、代码3.1 源码3.2 生成16进制.hex文件3.3 重建代码3.4 在代码路径中找到.hex文件 4、在原理图中加载代码5、效果图 文章介绍 用Proteus仿真图实现点亮8个led蓝色小灯 1、原理图 2、新建项目文件和.c文件 在STC89C52Study…

为什么需要进行软件测试需求分析?专业第三方软件测评中心分享

一、什么是软件测试需求分析?   软件测试需求就是了解软件测试要测试什么项目&#xff0c;只有明确了测试需求&#xff0c;才能确定如何进行测试工作、测试时间、测试人员、测试环境、测试工具等等&#xff0c;这些都是测试计划设计的基本要素&#xff0c;因此测试需求则是测…

华为HCIE认证用处大吗?

新盟教育 专注华为认证培训十余年 为你提供认证一线资讯&#xff01; 在ICT行业的认证体系中&#xff0c;华为HCIE认证一直备受关注。那么&#xff0c;华为HCIE认证用处大吗&#xff1f;今天咱们就来深入探讨一下&#xff0c;以数据通信方向为例&#xff0c;看看它到底能带来什…

C语言 第四章 数组(2)

目录 一维数组的遍历练习 实例&#xff08;为数组遍历赋值&#xff09; 实例1 &#xff08;查询数组是否包含指定元素) 代码功能概述 实例2&#xff08;比较数组的元素求最大最小值&#xff09; 代码功能概述 实例3&#xff08;数组复制&#xff09; 代码功能概述 实例…