计算机图形学【绘制立方体和正六边形】
工具介绍
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.3double 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 的参数,使得在不同的窗口尺寸下,六边形的显示不受影响。
运行结果:

相关文章:
计算机图形学【绘制立方体和正六边形】
工具介绍 OpenGL:一个跨语言的图形API,用于渲染2D和3D图形。它提供了绘制图形所需的底层功能。 GLUT:OpenGL的一个工具库,简化了窗口创建、输入处理和其他与图形环境相关的任务。 使用的函数 1. glClear(GL_COLOR_BUFFER_BIT |…...
基于django中医药数据可视化平台(源码+lw+部署文档+讲解),源码可白嫖!
摘要 时代在飞速进步,每个行业都在努力发展现在先进技术,通过这些先进的技术来提高自己的水平和优势,中医药管理平台当然不能排除在外。中医药数据可视化平台是在实际应用和软件工程的开发原理之上,运用Python语言、ECharts技术、…...
kafka消费堆积问题探索
背景 我们的商城项目用PHP写的,原本写日志方案用的是PHP的方案,但是,这个方案导致资源消耗一直降不下来,使用了20个CPU。后面考虑使用通过kafka的方案写日志,商城中把产生的日志丢到kafka中,在以go写的项目…...
Vue.js 使用插槽(Slots)优化组件结构
Vue.js 使用插槽(Slots)优化组件结构 今天我们聊聊 Vue.js 的一个超实用功能——插槽(Slots)。插槽是 Vue 组件开发中的神器,用好它,你可以让组件变得更灵活、更可复用,还能写出优雅的代码结构…...
Broker如何进行定时心跳发送和故障感知
1.前言 此文章是在儒猿课程中的学习笔记,感兴趣的想看原来的课程可以去咨询儒猿课堂《从0开始带你成为RocketMQ高手》,我本人觉得这个作者还是不错,都是从场景来进行分析,感觉还是挺适合我这种小白的。这块主要都是我自己的学习笔…...
网络安全设备主要有什么
网络安全设备指的肯定是硬件设备了,国内卖安全硬件的没几家,天融信,启明星辰,绿盟,深信服,就这四家卖的比较齐全吧,上它们官网看一下,就知道市面上主要的网络安全设备有哪些了。分类…...
Android Framework WMS全面概述和知识要点
一、概述 定义与作用 在 Android 系统中,WindowManagerService(WMS)就像是一个大管家,负责管理整个系统的窗口界面。它是 Android Framework 的核心组件之一,处于 system_server 进程内,在 Framework 层占…...
记一次某红蓝演练经历
在某天接到任务,对xxx进行一次红蓝演练,于是把自己渗透过程给记录下来,漏洞关键地方也会打码,希望各位大佬理解,菜鸡一枚,勿喷/(ㄒoㄒ)/~~ 概述 拿到目标域名第一件事就是信息收集,曾经一位大…...
一个运行在浏览器中的开源Web操作系统Puter本地部署与远程访问
文章目录 前言1.关于Puter2.本地部署Puter3.Puter简单使用4. 安装内网穿透5.配置puter公网地址6. 配置固定公网地址 💡 推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【点击跳转到网站…...
【零基础入门Go语言】struct 和 interface:Go语言是如何实现继承的?
提到面向对象编程中的继承,许多人脑海中可能会浮现出 Java、C 等语言中那一套熟悉的类继承体系。然而,Go 语言作为一门别具一格的编程语言,并没有遵循传统的继承模式。那么,在 Go 语言的世界里,它是怎样实现类似于继承…...
麦田物语学习笔记:实现拖拽物品交换数据和在地图上生成物品
基本流程 1.代码思路 (1)InventoryUI的PlayerSlots与PlayerBag里一一对应,所以想要实现交换数据实际上是,先拿到被拖拽的物体所对的Slot的序号和目标的Slot序号,然后将这两个序号对调一下 (2)物品交换的数据逻辑应该在InventoryManager里去调用,因为InventoryManager里管理了p…...
一些计算机零碎知识随写(25年1月)-1
我原以为世界上有技术的那批人不会那么闲,我错了,被脚本真实了。 今天正隔着画画呢,手机突然弹出几条安全告警通知。 急忙打开服务器,发现问题不简单,直接关服务器重装系统..... 首先,不要认为小网站&…...
Qt学习笔记第81到90讲
第81讲 串口调试助手实现自动发送 为这个名叫“定时发送”的QCheckBox编写槽函数。 想要做出定时发送的效果,必须引入QT框架下的毫秒级定时器QTimer,查阅手册了解详情。 在widget.h内添加新的私有成员变量: QTimer *timer; 在widget类的构造…...
Centos9 + Docker 安装 MySQL8.4.0 + 定时备份数据库到本地
Centos9 Docker 安装 MySQL8.4.0 定时备份数据库到本地 创建目录,创建配置文件启动容器命令定时备份MySQL执行脚本Linux每日定时任务命令文件内参数其他时间参数 AT一次性定时任务 创建目录,创建配置文件 $ mkdir -p /opt/mysql/conf$ vim /opt/mysql/…...
网络原理一>UDP协议详解
UDP和TCP都是应用层中的重要协议,如果做基础架构开发,会用得多一些。 这一篇我们先简单聊一下的UDP TCP格式呈现: 我们知道UDP是一种无连接,面向数据报,全双工,不可靠传输特性的网络协议。 基本格式如图…...
MySQL的小问题
编码问题 不管官方使用什么编码:latin1、gbk、utf8、utfmb4。统一使用utfmb4 MySQL中的utf8并不是utf-8,它省略了一个字节,只是用三个字节存储所有的符号,utfmb4才是utf-8 远程登录问题: MySQL官方默认没有启动远程…...
Mac——Docker desktop安装与使用教程
摘要 本文是一篇关于Mac系统下Docker Desktop安装与使用教程的博文。首先介绍连接WiFi网络,然后详细阐述了如何在Mac上安装Docker,包括下载地址以及不同芯片版本的选择。接着讲解了如何下载基础镜像和指定版本镜像,旨在帮助用户在Mac上高效使…...
FastApi Swagger 序列化问题
问题 错误现象: fastapi的 swagger 界面无法正常打开控制台报错:raise PydanticInvalidForJsonSchema(fCannot generate a JsonSchema for {error_info}) 详细报错: File "d:\Envs\miniconda3\envs\xdagent\lib\site-packages\pydan…...
《机器学习》——sklearn库中CountVectorizer方法(词频矩阵)
CountVectorizer方法介绍 CountVectorizer 是 scikit-learn 库中的一个工具,它主要用于将文本数据转换为词频矩阵,而不是传统意义上的词向量转换,但可以作为词向量转换的一种基础形式。用于将文本数据转换为词频矩阵,它是文本特征…...
UML系列之Rational Rose笔记三:活动图(泳道图)
一、新建活动图(泳道图) 依旧在用例视图里面,新建一个activity diagram;新建好之后,就可以绘制活动图了: 正常每个活动需要一个开始,点击黑点,然后在图中某个位置安放,接…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
python爬虫——气象数据爬取
一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用: 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests:发送 …...
