当前位置: 首页 > article >正文

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

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);  // 菜单项”蓝色“和其ID
    glutAddMenuEntry("绿色", 2);// 菜单项”绿色“和其ID
    glutAddMenuEntry("粉红色", 3);// 菜单项”红色“和其ID
    glutAddMenuEntry("黑色", 4);// 菜单项”黑色“和其ID
    glutAddMenuEntry("黄色", 5);// 菜单项”黄色“和其ID
    glutAttachMenu(GLUT_RIGHT_BUTTON);  //绑定菜单和鼠标右键

    glutMouseFunc(MousePlot); // 指定鼠标相应函数
    glutMainLoop();//启动主循环,等待消息
    return 0;
}

http://www.kler.cn/a/581775.html

相关文章:

  • Linux rpcbind漏洞
  • Python----计算机视觉处理(Opencv:自适应二值化,取均值,加权求和(高斯定理))
  • GitHub 项目版本管理与 Release 发布流程记录
  • 学习文章:Spring Boot 中 Redis 配置与序列化管理
  • 软件工程概述
  • 消息队列MQ使用场景有哪些?
  • 逐梦DBA:基本的SELECT语句
  • C#运算符详解
  • GStreamer —— 2.15、Windows下Qt加载GStreamer库后运行 - “播放教程 1:Playbin 使用“(附:完整源码)
  • AI重构私域增长:从流量收割到终身价值运营的三阶跃迁
  • AutoMQ x OSS 的 Iceberg 数据入湖的最佳实践
  • 深度评测DeepSeek、ChatGPT O1和谷歌Gemini AI应用开发场景 - DeepSeek性能完胜!
  • 【实战ES】实战 Elasticsearch:快速上手与深度实践-7.3.1直接调用ES API的风险与替代方案
  • 如何使用 CSS 实现黑色遮罩效果
  • 深度学习基础:线性代数本质2——线性组合、张成的空间与基
  • Torch 模型 model => .onnx => .trt 及利用 TensorTR 在 C++ 下的模型部署教程
  • 技术速递|Visual Studio Code 2025年2月更新(v1.98)
  • IHAOAVOA:一种改进的混合aquila优化器和非洲秃鹫优化算法的全局优化问题,附完整MATLAB代码
  • 【prompt实战】知乎问题解答专家
  • 为什么使用 XML Schema?