计算机图形学【绘制立方体和正六边形】

news2025/1/13 23:25:40

工具介绍

OpenGL:一个跨语言的图形API,用于渲染2D和3D图形。它提供了绘制图形所需的底层功能。

GLUT:OpenGL的一个工具库,简化了窗口创建、输入处理和其他与图形环境相关的任务。

使用的函数

1. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

原理:此函数用于清除当前的颜色缓冲区和深度缓冲区。颜色缓冲区存储着每个像素的颜色信息,而深度缓冲区用于存储每个像素的深度值,以确保在3D场景中正确渲染物体的可见性。每次绘制新帧时,必须清除前一帧的数据,以避免旧内容影响新渲染的图像。清除颜色缓冲区确保背景色是统一的,而清除深度缓冲区允许重新计算物体的深度关系。

2. glLoadIdentity()

原理:此函数重置当前的模型观察矩阵为单位矩阵。模型观察矩阵用于转换物体的位置、旋转和缩放。在设置新的视图或模型转换之前,重置矩阵是必要的,以确保新的变换不会受到之前变换的影响。使用单位矩阵作为基础,可以确保后续的变换(如移动相机)是从一个已知的状态开始的。

3. gluLookAt(2.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0)

原理:此函数设置相机的位置、观察点和上方向。它通过创建视图矩阵来定义相机的视角。

① eye (相机位置):(2.0, 2.0, 2.0),表示相机位于三维空间中的位置。

② center (观察点):(0.0, 0.0, 0.0),表示相机注视的目标点。

③ up (上方向):(0.0, 0.0, 1.0),定义相机的上方向,通常用来确定视图的“上”方向。

4. glutSwapBuffers()

原理:在双缓冲模式下,glutSwapBuffers 函数用于交换前后缓冲区。前缓冲区显示当前渲染的内容,后缓冲区用于下一帧的绘制。通过交换缓冲区,可以避免画面闪烁和撕裂现象,提供更平滑的视觉效果。这使得用户在屏幕上看到的是完整的一帧,而不是正在绘制的部分。

5. glutMainLoop()

原理:此函数进入GLUT的事件处理循环,持续处理窗口事件和重绘请求。这是程序运行的核心循环,确保应用程序能够响应用户输入、窗口变化等事件。它使得OpenGL程序能够持续运行,并在需要时重绘场景。

实验过程

(0)打开 Visual Studio,在项目栏的 [管理Nuget程序包] 下载安装必要库:

(1)Drawing a Cube

源代码:cube.cpp

#include <GL/glut.h> // 包含OpenGL和GLUT库的头文件

// 定义正方体的顶点坐标(边长为0.7)
GLfloat vertices[][3] = {
    {0.0f, 0.0f, 0.0f}, {0.7f, 0.0f, 0.0f}, {0.7f, 0.7f, 0.0f}, {0.0f, 0.7f, 0.0f},
    {0.0f, 0.0f, 0.7f}, {0.7f, 0.0f, 0.7f}, {0.7f, 0.7f, 0.7f}, {0.0f, 0.7f, 0.7f}
};

// 定义正方体的边,每条边由两个顶点索引定义
int edges[][2] = {
    {0, 1}, {1, 2}, {2, 3}, {3, 0},
    {4, 5}, {5, 6}, {6, 7}, {7, 4},
    {0, 4}, {1, 5}, {2, 6}, {3, 7}
};

// 绘制坐标轴
void drawAxes() {
    glBegin(GL_LINES); // 开始绘制线段

    // X轴(红色)
    glColor3f(1.0, 0.0, 0.0); // 设置颜色为红色
    glVertex3f(0.0, 0.0, 0.0); // X轴起点,坐标为 (-2.0, 0.0, 0.0)
    glVertex3f(1.5, 0.0, 0.0);  // X轴终点,坐标为 (2.0, 0.0, 0.0)

    // Y轴(绿色)
    glColor3f(0.0, 1.0, 0.0); // 设置颜色为绿色
    glVertex3f(0.0, 0.0, 0.0); // Y轴起点,坐标为 (0.0, -2.0, 0.0)
    glVertex3f(0.0, 1.5, 0.0);  // Y轴终点,坐标为 (0.0, 2.0, 0.0)

    // Z轴(蓝色)
    glColor3f(0.0, 0.0, 1.0); // 设置颜色为蓝色
    glVertex3f(0.0, 0.0, 0.0); // Z轴起点,坐标为 (0.0, 0.0, -2.0)
    glVertex3f(0.0, 0.0, 1.5);  // Z轴终点,坐标为 (0.0, 0.0, 2.0)

    glEnd(); // 结束绘制线段

}

// 绘制正方体的函数
void drawCube() {
    glColor3f(0.0, 0.0, 0.0); // 设置颜色为黑色
    glBegin(GL_LINES); // 开始绘制线段

    for (int i = 0; i < 12; i++) {
        int v1 = edges[i][0]; // 边的第一个顶点
        int v2 = edges[i][1]; // 边的第二个顶点
        glVertex3fv(vertices[v1]); // 绘制第一个顶点
        glVertex3fv(vertices[v2]); // 绘制第二个顶点

    }

    glEnd(); // 结束绘制线段

}

// 显示回调函数,用于绘制场景
void display() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除颜色缓冲区和深度缓冲区
    glLoadIdentity(); // 重置当前的模型观察矩阵

    // 设置观察点和方向
    gluLookAt(2.0, 2.0, 2.0, // 相机位置(eye)
              0.0, 0.0, 0.0, // 观察点(center)
              0.0, 0.0, 1.0); // 上方向(up)

    drawAxes(); // 绘制坐标轴
    drawCube(); // 调用绘制正方体的函数

    glutSwapBuffers(); // 交换前后缓冲区
}

// 初始化函数,设置清除颜色和启用深度测试
void init() {
    glClearColor(1.0, 1.0, 1.0, 1.0); // 设置背景颜色为白色
    glEnable(GL_DEPTH_TEST); // 启用深度测试

    glMatrixMode(GL_PROJECTION); // 选择投影矩阵
    glLoadIdentity(); // 重置投影矩阵
    gluPerspective(45.0, 640.0 / 480.0, 0.1, 100.0); // 设置透视投影
    glMatrixMode(GL_MODELVIEW); // 切换回模型视图矩阵
}

int main(int argc, char** argv) {
    glutInit(&argc, argv); // 初始化GLUT库
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); // 设置显示模式
    glutInitWindowSize(640, 480); // 设置窗口大小
    glutCreateWindow("Cube"); // 创建窗口

    init(); // 调用初始化函数

    glutDisplayFunc(display); // 设置显示回调函数
    glutMainLoop(); // 进入GLUT事件处理循环

    return 0;
}

①源代码的实验结果:

改变参数,可以得到不同视角的投影:

②替换 drawCube() 函数中的绘制逻辑:

// 绘制正方体的函数
void drawCube() {
    glBegin(GL_QUADS); // 开始绘制四边形

    // 正面 (Z=0.0)
    glColor3f(0.5, 0.5, 0.5); // 设置颜色为灰色
    glVertex3fv(vertices[0]); // 底左
    glVertex3fv(vertices[1]); // 底右
    glVertex3fv(vertices[2]); // 顶右
    glVertex3fv(vertices[3]); // 顶左

    // 背面 (Z=0.7)
    glVertex3fv(vertices[4]); // 底左
    glVertex3fv(vertices[5]); // 底右
    glVertex3fv(vertices[6]); // 顶右
    glVertex3fv(vertices[7]); // 顶左

    // 左面 (X=0.0)
    glVertex3fv(vertices[0]); // 前底
    glVertex3fv(vertices[3]); // 前顶
    glVertex3fv(vertices[7]); // 后顶
    glVertex3fv(vertices[4]); // 后底

    // 右面 (X=0.7)
    glVertex3fv(vertices[1]); // 前底
    glVertex3fv(vertices[5]); // 前顶
    glVertex3fv(vertices[6]); // 后顶
    glVertex3fv(vertices[2]); // 后底

    // 上面 (Y=0.7)
    glVertex3fv(vertices[3]); // 左顶
    glVertex3fv(vertices[2]); // 右顶
    glVertex3fv(vertices[6]); // 后顶
    glVertex3fv(vertices[7]); // 后左顶

    // 下面 (Y=0.0)
    glVertex3fv(vertices[0]); // 左底
    glVertex3fv(vertices[1]); // 右底
    glVertex3fv(vertices[5]); // 后底
    glVertex3fv(vertices[4]); // 后左底

    glEnd(); // 结束绘制四边形
}

运行结果:

(2)Drawing a Hexagon

源代码:hexagon.cpp

#include <GL/glut.h>
#include <math.h>

// 窗口大小调整的回调函数
void reshape(int width, int height) {
    glViewport(0, 0, width, height); // 设置视口
    glMatrixMode(GL_PROJECTION); // 选择投影矩阵
    glLoadIdentity(); // 重置投影矩阵

    // 保持纵横比
    if (width <= height) {
        gluOrtho2D(-1.0, 1.0, -1.0 * (GLfloat)height / (GLfloat)width, 1.0 * (GLfloat)height / (GLfloat)width);
    }
    else {
        gluOrtho2D(-1.0 * (GLfloat)width / (GLfloat)height, 1.0 * (GLfloat)width / (GLfloat)height, -1.0, 1.0);
    }

    glMatrixMode(GL_MODELVIEW); // 切换回模型视图矩阵
}

// 绘制正六边形及其对角线的函数
void drawHexagon() {
    // 设置六边形的顶点
    GLfloat vertices[6][2];
    float sideLength = 0.5f; // 边长设置为0.3
    double M_PI = 3.14159265358979323846f;

    for (int i = 0; i < 6; i++) {
        float angle = 2.0f * M_PI * i / 6 + M_PI / 2; // 顶角在上
        vertices[i][0] = sideLength * cos(angle); // X坐标
        vertices[i][1] = sideLength * sin(angle); // Y坐标
    }

    // 绘制正六边形
    glBegin(GL_LINE_LOOP); // 开始绘制六边形的边
    for (int i = 0; i < 6; i++) {
        glVertex2fv(vertices[i]); // 添加顶点
    }
    glEnd(); // 结束绘制六边形

    // 绘制六边形的对角线
    glBegin(GL_LINES); // 开始绘制线段
    for (int i = 0; i < 6; i++) {
        for (int j = i + 2; j < 6; j++) { // 只绘制非相邻的顶点之间的线
            glVertex2fv(vertices[i]); // 第一端点
            glVertex2fv(vertices[j]); // 第二端点
        }
    }
    glEnd(); // 结束绘制对角线
}

// 显示回调函数
void display() {
    glClear(GL_COLOR_BUFFER_BIT); // 清除颜色缓冲区
    glLoadIdentity(); // 重置当前的模型观察矩阵

    drawHexagon(); // 绘制正六边形及其对角线
    glutSwapBuffers(); // 交换前后缓冲区
}

// 初始化函数
void init() {
    glClearColor(1.0, 1.0, 1.0, 1.0); // 设置背景颜色为白色
    glColor3f(0.0, 0.0, 0.0); // 设置绘制颜色为黑色
    glMatrixMode(GL_PROJECTION); // 选择投影矩阵
    glLoadIdentity(); // 重置投影矩阵
    gluOrtho2D(-1.0, 1.0, -1.0, 1.0); // 使用正交投影
    glMatrixMode(GL_MODELVIEW); // 切换回模型视图矩阵
}

// 主程序入口
int main(int argc, char** argv) {
    glutInit(&argc, argv); // 初始化GLUT库
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); // 设置显示模式
    glutInitWindowSize(640, 480); // 设置窗口大小
    glutCreateWindow("Hexagon"); // 创建窗口
    init(); // 调用初始化函数
    glutDisplayFunc(display); // 设置显示回调函数
    glutReshapeFunc(reshape); // 设置窗口大小调整回调函数
    glutMainLoop(); // 进入GLUT事件处理循环
    return 0;
}

注意:正六边形看起来扁平的原因通常与视口的纵横比(宽高比)有关。如果窗口的宽度和高度比例不一致,例如宽度比高度大,那么在正交投影下绘制的形状可能会在视觉上变得扁平。

调整:

a.保持窗口的纵横比:

在窗口调整大小时,保持宽高比一致,确保 OpenGL 的视口与窗口大小相匹配。

b.调整正交投影参数:

根据窗口的宽高比调整 gluOrtho2D 的参数,使得在不同的窗口尺寸下,六边形的显示不受影响。

运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2276198.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

有限元分析学习——Anasys Workbanch第一阶段笔记(10)桌子载荷案例分析_实际载荷与均布载荷的对比

目录 0 序言 1 桌子案例 2 模型简化 3 方案A 前处理 1&#xff09;分析类型选择 2&#xff09;材料加载 3&#xff09;约束、载荷及接触 4&#xff09;控制网格(网格大小需要根据结果不断调整) 初始计算结果 加密后计算结果 4 方案B、C 前处理 1&#xff09;分析…

Docker compose 使用 --force-recreate --no-recreate 控制重启容器时的行为【后续】

前情&#xff1a;上一篇实际是让AI工具帮我总结了一下讨论的内容&#xff0c;这里把讨论的过程贴出来&#xff0c;这个讨论是为解决实际问题 前文https://blog.csdn.net/wgdzg/article/details/145039446 问题说明&#xff1a; 我使用 docker compose 管理我的容器&#xff0…

Mysql--基础篇--多表查询(JOIN,笛卡尔积)

在MySQL中&#xff0c;多表查询&#xff08;也称为联表查询或JOIN操作&#xff09;是数据库操作中非常常见的需求。通过多表查询&#xff0c;你可以从多个表中获取相关数据&#xff0c;并根据一定的条件将它们组合在一起。MySQL支持多种类型的JOIN操作&#xff0c;每种JOIN都有…

postgresql|数据库|利用sqlparse和psycopg2库批量按顺序执行SQL语句(psyconpg2新优化版本)

一、 旧版批量执行SQL脚本的python文件缺点&#xff0c;优点&#xff0c;以及更新内容 书接上回&#xff0c;postgresql|数据库开发|python的psycopg2库按指定顺序批量执行SQL文件(可离线化部署)_python sql psycopg2-CSDN博客 这个python脚本写了很久了&#xff0c;最近开始…

5个不同类型的数据库安装

各种社区版本下载官方地址&#xff1a;MySQL :: MySQL Community Downloads 一、在线YUM仓库&#xff08;Linux&#xff09; 选择 MySQL Yum Repository 选择对应版本下载仓库安装包&#xff08;No thanks, just start my download.&#xff09; 下载方法1&#xff1a;下载到本…

shell基础使用及vim的常用快捷键

一、shell简介 参考博文1 参考博文2——shell语法及应用 参考博文3——vi的使用 在linux中有很多类型的shell&#xff0c;不同的shell具备不同的功能&#xff0c;shell还决定了脚本中函数的语法&#xff0c;Linux中默认的shell是 / b in/ b a s h &#xff0c;流行的shell…

Spring Data Elasticsearch简介

一、Spring Data Elasticsearch简介 1 SpringData ElasticSearch简介 Elasticsearch是一个实时的分布式搜索和分析引擎。它底层封装了Lucene框架,可以提供分布式多用户的全文搜索服务。 Spring Data ElasticSearch是SpringData技术对ElasticSearch原生API封装之后的产物,它通…

【巨实用】Git客户端基本操作

本文主要分享Git的一些基本常规操作&#xff0c;手把手教你如何配置~ ● 一个文件夹中初始化Git git init ● 为了方便以后提交代码需要对git进行配置&#xff08;第一次使用或者需求变更的时候&#xff09;&#xff0c;告诉git未来是谁在提交代码 git config --global user.na…

有收到腾讯委托律师事务所向AppStore投诉带有【水印相机】主标题名称App的开发者吗

近期&#xff0c;有多名开发者反馈&#xff0c;收到来自腾讯科技 (深圳) 有限公司委托北京的一家**诚律师事务所卞&#xff0c;写给AppStore的投诉邮件。 邮件内容主要说的是&#xff0c;腾讯注册了【水印相机】这四个字的商标&#xff0c;所以你们这些在AppStore上的app&…

导出文件,能够导出但是文件打不开

背景&#xff1a; 在项目开发中&#xff0c;对于列表的查询&#xff0c;而后会有导出功能&#xff0c;这里导出的是一个excell表格。实现了两种&#xff0c;1.导出的文件&#xff0c;命名是前端传输过去的&#xff1b;2.导出的文件&#xff0c;命名是根据后端返回的文件名获取的…

Redis 源码分析-内部数据结构 dict

Redis 源码分析-内部数据结构 dict 在上一篇 Redis 数据库源码分析 提到了 Redis 其实用了全局的 hash 表来存储所有的键值对&#xff0c;即下方图示的 dict&#xff0c;dict 中有两个数组&#xff0c;其中 ht[1] 只在 rehash 时候才真正用到&#xff0c;平时都是指向 null&am…

010:传统计算机视觉之大津算法初探

本文为合集收录&#xff0c;欢迎查看合集/专栏链接进行全部合集的系统学习。 合集完整版请参考这里。 上一节学习了利用 Canny 算法来完成一个图片的边缘检测&#xff0c;从而可以区分出图像的边缘。 本节再了解一个计算机视觉中更常见的应用&#xff0c;那就是把图片的前景和…

使用Cilium/eBPF实现大规模云原生网络和安全

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 目录 抽象 1 Trip.com 云基础设施 1.1 分层架构 1.2 更多细节 2 纤毛在 Trip.com 2.1 推出时间表 2.2 自定义 2.3 优化和调整 2.3.1 解耦安装 2.3.2 避免重试/重启风暴 2.3.3 稳定性优先 2…

怎么把word试题转成excel?

在教育行业、学校管理以及在线学习平台中&#xff0c;试题库的高效管理是一项核心任务。许多教育工作者和系统开发人员常常面临将 Word 中的试题批量导入 Excel 的需求。本文将详细介绍如何快速将试题从 Word 转换为 Excel&#xff0c;帮助您轻松解决繁琐的数据整理问题&#x…

css盒子水平垂直居中

目录 1采用flex弹性布局&#xff1a; 2子绝父相margin&#xff1a;负值&#xff1a; 3.子绝父相margin:auto&#xff1a; 4子绝父相transform&#xff1a; 5通过伪元素 6table布局 7grid弹性布局 文字 水平垂直居中链接&#xff1a;文字水平垂直居中-CSDN博客 以下为盒子…

Spring 项目 基于 Tomcat容器进行部署

文章目录 一、前置知识二、项目部署1. 将写好的 Spring 项目先打包成 war 包2. 查看项目工件&#xff08;Artifact&#xff09;是否存在3. 配置 Tomcat3.1 添加一个本地 Tomcat 容器3.2 将项目部署到 Tomcat 4. 运行项目 尽管市场上许多新项目都已经转向 Spring Boot&#xff0…

【Web安全】SQL 注入攻击技巧详解:UNION 注入(UNION SQL Injection)

【Web安全】SQL 注入攻击技巧详解&#xff1a;UNION 注入&#xff08;UNION SQL Injection&#xff09; 引言 UNION注入是一种利用SQL的UNION操作符进行注入攻击的技术。攻击者通过合并两个或多个SELECT语句的结果集&#xff0c;可以获取数据库中未授权的数据。这种注入技术要…

docker安装rabbit后访问报错最佳的几种解决方案

错误通常是由于RabbitMQ的安全配置导致的&#xff0c;RabbitMQ默认配置允许的用户仅能通过localhost访问。这通常出现在RabbitMQ的guest用户上&#xff0c;guest用户默认只能从localhost登录&#xff0c;而无法从其他IP地址进行远程访问。 解决方法&#xff1a; 1. **创建一个…

计科高可用服务器架构实训(防火墙、双机热备,VRRP、MSTP、DHCP、OSPF)

一、项目介绍 需求分析&#xff1a; &#xff08;1&#xff09;总部和分部要求网络拓扑简单&#xff0c;方便维护&#xff0c;网络有扩展和冗余性&#xff1b; &#xff08;2&#xff09;总部分财务部&#xff0c;人事部&#xff0c;工程部&#xff0c;技术部&#xff0c;提供…

spark汇总

目录 描述运行模式1. Windows模式代码示例 2. Local模式3. Standalone模式 RDD描述特性RDD创建代码示例&#xff08;并行化创建&#xff09;代码示例&#xff08;读取外部数据&#xff09;代码示例&#xff08;读取目录下的所有文件&#xff09; 算子DAGSparkSQLSparkStreaming…