计算机图形学:实验四 带纹理的OBJ文件读取和显示

一、程序功能设计

在程序中读取带纹理的obj文件,载入相应的纹理图片文件,将带纹理的模型显示在程序窗口中。实现带纹理的OBJ文件读取与显示功能,具体设计如下:

OBJ文件解析与数据存储

通过实现TriMesh类中的readObj函数,解析OBJ文件中的顶点、法线、UV纹理坐标等信息,将其存储在指定的数据结构中:

  1. vertex_positions:存储顶点几何坐标。
  2. vertex_normals:存储顶点法线,用于光照计算。
  3. vertex_textures:存储UV纹理坐标,用于纹理映射。
  4. faces:存储面片顶点的索引信息,用于定义几何形状。
  5. normal_index和texture_index:分别存储面片顶点对应的法线索引和纹理坐标索引。
    此外,由于OBJ文件不包含顶点颜色数据,本实验利用顶点法线的数值作为颜色数据进行渲染。

数据组织与存储逻辑完善
通过补全storeFacesPoints函数,进一步完善面片顶点的索引解析与数据存储过程:

  1. 遍历面片数据,按顶点、法线、UV坐标的索引组织顶点信息。
  2. 确保所有几何数据、法线数据和UV数据一一对应,以便后续渲染时正确应用纹理。

纹理加载与显示

在main.cpp文件中修改init函数,通过以下步骤实现带纹理模型的加载与显示:

  1. 加载纹理图片文件并绑定到模型的UV坐标上。
  2. 根据模型的顶点、法线、纹理坐标等数据渲染模型。
  3. 显示玩偶和桌子模型,通过调整它们的位置与比例,生成合理的场景布局。

 实现效果

实现了多模型、多纹理的加载和显示功能。程序窗口中,带有纹理的玩偶模型和桌子模型正确显示,纹理映射效果清晰且无失真。

二、程序代码实现

补全TriMesh.cpp中的storeFacesPoints函数

通过补全storeFacesPoints函数,根据读取的模型数据,将三角面片的顶点属性(包括顶点位置、法线、颜色、纹理等)整理成适合传递给GPU的数据格式,为后续的渲染做准备。

顶点数据解析与存储(根据三角面片的索引将属性数据组织到GPU需要的格式):遍历每个三角面片的数据,根据顶点的索引将顶点属性依次存入对应的容器(points、colors、normals、textures)。每个三角面片的顶点属性都要按照顶点索引依次写入。要注意的是:

  1. faces:存储三角形面片的顶点索引。
  2. color_index:存储面片顶点的颜色索引。
  3. normal_index:存储面片顶点法线的索引。
  4. texture_index:存储面片顶点纹理坐标的索引。

补全TriMesh.cpp中的generateDisk函数和generateCone函数

generateDisk 函数生成圆盘,生成一个圆盘的网格,包括底面和相应的三角面片。generateCone 函数生成圆锥,生成一个圆锥体的网格,包括底面和圆锥侧面。两个函数分别用来生成圆盘和圆锥体(同实验4.1),依赖于三角形扇形的方式来连接底面和顶部(尖端)的顶点,生成相应的三角面片。

  • generateDisk 函数
  1. 生成顶点:使用循环计算每个切片的边界点(顶点坐标 x, y, z),其中 z 始终为 0(在 xy 平面上),并根据该顶点的法向量(法向量始终为 (0, 0, 1))添加颜色(这里简化为与法向量相同的颜色)。在循环结束后,添加一个圆盘的中心点(顶点坐标为 (0, 0, 0))。
  2. 生成三角面片:使用三角形扇形的方式将每个切片连接起来,形成三角面片,通过 faces.push_back() 存储每个三角形的三个顶点索引。为每个顶点生成相应的纹理坐标,并存储索引。
  3. 法向量和颜色设置:通过 normal_index 和 color_index 将每个三角面片的顶点与法向量和颜色的索引关联起来。

  • generateCone 函数:
  1. 生成底部顶点:使用循环计算圆锥底部的每个顶点坐标(x, y, z),其中 z 始终为 0。根据每个顶点位置生成法向量(平面上每个顶点的法向量为 (x, y, 0) 的归一化向量),并生成颜色(与法向量相同)。
  2. 添加圆锥的顶点:圆锥顶端添加一个顶点,坐标为 (0, 0, height),法向量为 (0, 0, 1)。
  3. 生成圆锥侧面三角面片:每两个相邻的底面顶点和圆锥顶点连接,形成一个三角形。通过 faces.push_back() 将每个侧面三角形的三个顶点索引存储起来。对每个三角面片的三个顶点生成纹理坐标并存储。
  4. 法向量和颜色设置:通过 normal_index 和 color_index 将三角面片与法向量、颜色的索引关联起来。

最终,所有的顶点、法向量、颜色、纹理坐标和面片索引通过 storeFacesPoints() 存储起来,以便后续使用。

补全TriMesh.cpp中的readObj函数

readObj函数实现了从 .obj 文件中读取三维模型的顶点数据、法向量数据、纹理坐标数据和面片数据,并将这些数据存储在类的成员变量中,供后续的渲染或计算使用。需要补充的代码逻辑如下:

  • 解析每一行的数据:
  1. 顶点数据 ("v"):读取顶点坐标(x, y, z),将其存入 vertex_positions 向量中。
  2. 法向量数据 ("vn"):读取法向量坐标(x, y, z),将其存入 vertex_normals 向量中。
  3. 纹理坐标数据 ("vt"):读取纹理坐标(x, y),将其存入 vertex_textures 向量中。
  4. 面数据 ("f"):读取面数据,包含三个顶点的索引(顶点、纹理和法向量索引),这些索引会被转换为从0开始的索引,并存储在 faces、texture_index、normal_index 中。
  • 处理面数据:

每一行的面数据包含三个顶点,使用索引(如 a0, b0, c0)来表示这些顶点在对应的数组中的位置。索引是从1开始的,因此需要将其减去1来转换为从0开始的索引。

  • 顶点颜色和法向量同步:

在 vertex_colors 中存储的是法向量(即 vertex_normals),因为通常情况下法向量用作顶点的颜色。

补全main.cpp中的init函数

在init() 函数加载桌子和娃娃的三维模型,并根据指定的平移、旋转和缩放变换进行调整。将这些模型添加到绘制管线(painter)中,供渲染使用。

  • 加载并设置桌子模型
  1. 创建一个新的 TriMesh 对象 table,并读取桌子模型文件 table.obj。
  2. 通过 setNormalize(true) 方法确保模型数据被归一化。
  3. 使用 readObj("./assets/table.obj") 函数加载桌子的几何数据。
  4. 设置桌子的平移(setTranslation)、旋转(setRotation)、缩放(setScale)变换。

平移:glm::vec3(-0.7, 0.0, 0.0) 将桌子稍微平移。

旋转:glm::vec3(-90.0, 0.0, 0.0) 将桌子旋转 -90 度。

缩放:glm::vec3(2.0, 2.0, 2.0) 放大桌子的大小。

将桌子模型添加到 painter 中,通过 painter->addMesh 方法加载模型并指定纹理和着色器。

加载并设置娃娃模型

  1. 创建一个新的 TriMesh 对象 wawa,并读取娃娃模型文件 wawa.obj。
  2. 同样通过 setNormalize(true) 方法归一化模型数据,并使用 readObj("./assets/wawa.obj") 函数加载娃娃的几何数据。
  3. 设置娃娃的平移、旋转和缩放变换:

平移:glm::vec3(0.7, 0.0, 0.0) 将娃娃平移。

旋转:glm::vec3(-90.0, 0.0, 0.0) 旋转 -90 度。

缩放:glm::vec3(2.0, 2.0, 2.0) 放大娃娃的大小。

将娃娃模型添加到 painter 中,指定纹理和着色器。

三、程序运行结果

运行程序初始界面

进行水平方向左右旋转

进行竖直方向旋转

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# OpenCV机器视觉:红外体温检测

在一个骄阳似火的夏日,全球却被一场突如其来的疫情阴霾笼罩。阿强所在的小镇,平日里熙熙攘攘的街道变得冷冷清清,人们戴着口罩,行色匆匆,眼神中满是对病毒的恐惧。阿强作为镇上小有名气的科技达人,看着这一…

PAT甲级-1020 Tree Traversals

题目 题目大意 给出一棵树的后序遍历和中序遍历,要求输出该树的层序遍历。 思路 非常典型的树的构建与遍历问题。后序遍历和中序遍历可以得出一个树的结构,用递归锁定根节点,然后再遍历左右子树,我之前发过类似题目的博客&…

C语言进阶——3字符函数和字符串函数(2)

8 strsrt char * strstr ( const char *str1, const char * str2);查找子字符串 返回指向 str1 中第一次出现的 str2 的指针,如果 str2 不是 str1 的一部分,则返回 null 指针。匹配过程不包括终止 null 字符,但会在此处停止。 8.1 库函数s…

python学opencv|读取图像(四十二)使用cv2.add()函数实现多图像叠加

【1】引言 前序学习过程中,掌握了灰度图像和彩色图像的掩模操作: python学opencv|读取图像(九)用numpy创建黑白相间灰度图_numpy生成全黑图片-CSDN博客 python学opencv|读取图像(四十)掩模:三…

基于C语言的数组从入门到精通

简介:本篇文章主要介绍了一维数组,二维数组,字符数组的定义,数组的应用,数组的核心代码解析,适用于0基础的初学者. C语言数组 1.一维数组 1.1定义 1.1.1声明 语法:数据类型 数组名[数组大小];示例:int arr[5]; 1.1.2初始化 a.静态初始化 完全初始化:int arr[5] {1…

【kong gateway】5分钟快速上手kong gateway

kong gateway的请求响应示意图 安装 下载对应的docker 镜像 可以直接使用docker pull命令拉取,也可以从以下地址下载:kong gateway 3.9.0.0 docker 镜像 https://download.csdn.net/download/zhangshenglu1/90307400, postgres-13.tar http…

python 安装插件 requests 下载免费简历(自学7)

安装 requests 库: 他们三个 按一个就行 pip install requests 或者 pip3 install requests 或者 conda install requests 代码 每次只可以下载一页的 简历模板 需要手动修改 id ### import requests from lxml import etree import osif __name__ "__…

西门子【Library of General Functions (LGF) for SIMATIC S7-1200 / S7-1500】

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 通用函数库 (LGF) 扩展了 TIA Portal 中用于 PLC 编程的 STEP 7 指令(数学函数、时间、计数器 等)。该库可以不受限制地使用,并包含 FIFO 、搜索功能、矩阵计算、 astro 计…

最新最详细的配置Node.js环境教程

配置Node.js环境 一、前言 (一)为什么要配置Node.js?(二)NPM生态是什么(三)Node和NPM的区别 二、如何配置Node.js环境 第一步、安装环境第二步、安装步骤第三步、验证安装第四步、修改全局模块…

黑龙江锅包肉:酸甜香酥的东北经典

黑龙江锅包肉:酸甜香酥的东北经典 黑龙江锅包肉,作为东北菜的代表之一,尤其在黑龙江省哈尔滨市享有极高的声誉。这道美食不仅承载着丰富的历史文化内涵,更以其鲜明的地域特色,成为了黑龙江省乃至整个东北地区的标志性菜肴。 历史渊源 锅包肉的历史可以追溯到清朝光绪年间,其…

linux——网络基础

文章目录 目录 文章目录 踏入网络世界:探索 Linux 网络的无垠天地 一、网络发展 早期单机处理模式 网络发展的需求催生 网络发展后的优势对比 二、局域网or广域网 典型局域网架构 广域网连接多个局域网 二者关系 三、协议 语言层与汉语协议 通信设备层与电话机协议 …

挖掘机的市场现状和发展前景:全球增长潜力,重塑基础设施建设新篇章

引言:工程机械的心脏,挖掘机的崛起之路 在现代化建设的浪潮中,挖掘机作为工程机械领域的核心设备,正以其强大的作业能力和广泛的应用场景,成为推动全球基础设施建设不可或缺的力量。从高速公路到大型矿场,…

tkinter绘制组件(44)——浮出ui控件

tkinter绘制组件(44)——浮出ui控件 引言布局函数结构ui框架对齐方向绑定已有控件出现和隐藏逻辑出现和隐藏动画完整代码函数 效果测试代码最终效果 github项目pip下载 引言 TinUI的浮出ui控件(flyout)其实是一个之间创建在UI框架…

【Unity3D】《跳舞的线》游戏的方块单方向拉伸实现案例

通过网盘分享的文件:CubeMoveMusic.unitypackage 链接: https://pan.baidu.com/s/1Rq-HH4H9qzVNtpQ84WXyUA?pwda7xn 提取码: a7xn 运行游戏点击空格动态创建拉伸的方块,由Speed控制速度,新方向是随机上下左右生成。 using System.Collect…

新版IDEA创建数据库表

这是老版本的IDEA创建数据库表,下面可以自己勾选Not null(非空),Auto inc(自增长),Unique(唯一标识)和Primary key(主键) 这是新版的IDEA创建数据库表,Not null和Auto inc可以看得到,但Unique和Primary key…

jmeter中对接口进行循环请求后获取相应数据

1、工作中遇到一个场景就是对某个单一接口进行循环请求,并需要获取每次请求后返回的相应数据; 2、首先就在jmeter对接口相关组件进行配置,需要组件有:循环控制器、CSV数据文件设置、计数器、访问接口、HTTP信息头管理器、正则表达…

【含代码】逆向获取 webpack chunk 下的__webpack_require__ 函数,获悉所有的模块以及模块下的函数

背景 Webpack 打包后的代码是不会直接暴露 __webpack_require__ 函数,目的是为了避免污染全局变量同时也为了保护 webpack 的打包后的模块都隐藏在闭包函数里,达到数据的安全性。 而有时我们为了测试某个函数,想直接获取这个内置函数&#…

最新常见的图数据库对比,选型,架构,性能对比

图数据库排名 地址:https://db-engines.com/en/ranking/graphdbms 知识图谱查询语言 SPARQL、Cypher、Gremlin、PGQL 和 G-CORE 语法 / 语义 / 特性 SPARQL Cypher Gremlin PGQL G-CORE 图模式匹配查询 语法 CGP CGP CGP(无可选)1 CGP CGP 语义 子…

CentOS7使用源码安装PHP8教程整理

CentOS7使用源码安装PHP8教程整理 下载安装包解压下载的php tar源码包安装所需的一些依赖扩展库安装前的配置修改配置文件1、进入php8的安装包 配置环境变量开机自启启动服务创建软连接常见问题1、checking for icu-uc > 50.1 icu-io icu-i18n... no2、configure: error: Pa…

php-phar打包避坑指南2025

有很多php脚本工具都是打包成phar形式,使用起来就很方便,那么如何自己做一个呢?也找了很多文档,也遇到很多坑,这里就来总结一下 phar安装 现在直接装yum php-cli包就有phar文件,很方便 可通过phar help查看…