assimp批量转模型,[OpenGL] 使用Assimp导入模型(Qt)

2023-10-27

最近终于决定要在本身的demo中加入模型了!本次选择的是开源库Assimp,以前一直嫌麻烦没有去落实这件事,但实际上,assimp的配置意外的没有我想象中的那么麻烦。html

下载源码后,须要使用cmake进行编译,在上方选择源码位置,和build工程的位置,若是没有什么特殊的配置需求的话,直接按顺序依次点1,2,3的按钮便可。Configure的时候,可能会遇到一个dx的error,按照引用文章的提示,直接在http://www.microsoft.com/en-us/download/details.aspx?id=6812下载相关组件,安装中还可能遇到s1023的错误代码,此处可在命令行输入(卸载vs的一些组件):post

MsiExec.exe /passive /X{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}

MsiExec.exe /passive /X{1D8E6291-B0D5-35EC-8441-6616F567A0F7}

b4ecd855ec850e2e34126a4e480eb58c.png

这里特别须要注意的是,cmake的generator选择,须要和最终调用assimp的编译器匹配。好比,个人Qt版本为:5.11.2 MSVC2017 64bit。ui

42dcf000ebd69cd9d584f3eed0aaaa82.png

也就是我使用了vs的msvc做为c++的编译器,而且是2017版本,64位的。那么相应的,如cmake界面右下角红色框所标出的,generator选择Visual Studio 15 2017 Win64。spa

编译完成以后,打开对应工程,切到release模式,而后点编译。以后,能够在code/Release获得咱们所需的lib和dll(用不一样的编译器获得的名称会不太同样):.net

1655eacab770da330119ea0d45aa3949.png

以后,咱们在Qt的pro文件处,新建include文件夹,把源码中的include内容复制过去;新建lib文件夹,把assimpxxx.lib放到该文件夹下。最后,把assimpxxx.dll放到生成的exe所在的文件夹下。(若是设定了shadow build和构建目录,那么就在这一目录下)。命令行

最后,在.pro按以下写好lib和include的链接:code

INCLUDEPATH += include

LIBS += -L$$PWD/lib/ \

-lassimp-vc140-mt

配置完成后,能够开始导入代码的编写。Assimp仅仅是实现了导入相关的功能,这些导入的数据实际上要如何使用,是须要额外实现的。orm

因为个人材质是动态加载和替换的,因此此处只导入了顶点、法线和纹理坐标:

(5.15更新,以前的代码只能加载一个mesh,改进了一下,不过每一个mesh只支持一个贴图)

#ifndef GEOMETRYENGINE_H

#define GEOMETRYENGINE_H

#include

#include

#include

#include

#include

#include

#include

using namespace std;

struct VertexData

{

QVector3D position;

QVector3D tangent;

QVector3D normal;

QVector2D texcoord;

};

struct MeshBuffer

{

QOpenGLBuffer arrayBuf;

QOpenGLBuffer indexBuf;

int vertexNum;

int indiceNum;

MeshBuffer() : indexBuf(QOpenGLBuffer::IndexBuffer)

{

arrayBuf.create();

indexBuf.create();

}

~MeshBuffer()

{

arrayBuf.destroy();

indexBuf.destroy();

}

void Init(VertexData* vertex, int num)

{

vertexNum = num;

arrayBuf.bind();

arrayBuf.allocate(vertex, vertexNum * static_cast(sizeof(VertexData)));

}

void Init(GLushort* indice, int num)

{

indiceNum = num;

indexBuf.bind();

indexBuf.allocate(indice, indiceNum * static_cast(sizeof(GLushort)));

}

void bind()

{

arrayBuf.bind();

indexBuf.bind();

}

};

struct Mesh

{

string name;

MeshBuffer* buffer = nullptr;

QOpenGLTexture* albedo;

};

class Model

{

private:

vector vecMesh;

public:

void Push(Mesh* mesh)

{

vecMesh.emplace_back(mesh);

}

MeshBuffer* GetMeshBuffer(size_t idx) { return vecMesh[idx]->buffer;}

Mesh* GetMesh(size_t idx) { return vecMesh[idx];}

size_t Count() { return vecMesh.size();}

};

class GeometryEngine

{

public:

GeometryEngine();

virtual ~GeometryEngine();

bool loadObj(string path, Model*& pModel);

void drawObj(string path,QOpenGLShaderProgram* program,bool bTess = false);

void drawObj(MeshBuffer* meshBuffer, QOpenGLShaderProgram* program,bool bTess = false);

void CalTangent(VertexData& vertex0, VertexData& vertex1, VertexData& vertex2);

private:

void processNode(const string& path, aiNode *node, const aiScene *scene);

void processMesh(vector& vertices, vector& indices, QOpenGLTexture*& albedo, aiMesh *mesh, const aiScene *scen);

map mapModel;

};

#endif // GEOMETRYENGINE_H

#include "geometryengine.h"

#include "resourceinfo.h"

#include

#include

#include

GeometryEngine::GeometryEngine()

{

}

GeometryEngine::~GeometryEngine()

{

}

bool GeometryEngine::loadObj(string path, Model*& pModel)

{

if(mapModel.find(path) != mapModel.end())

{

return true;

}

Assimp::Importer import;

const aiScene *scene = import.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);

if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)

{

qDebug() << "ERROR::ASSIMP::" << import.GetErrorString() ;

return false;

}

string directory = path.substr(0, path.find_last_of('/'));

processNode(path, scene->mRootNode, scene);

pModel = &mapModel[path];

return true;

}

void GeometryEngine::drawObj(MeshBuffer* meshBuffer, QOpenGLShaderProgram* program,bool bTess)

{

meshBuffer->bind();

auto gl = QOpenGLContext::currentContext()->extraFunctions();

int offset = 0;

int vertexLocation = program->attributeLocation("a_position");

program->enableAttributeArray(vertexLocation);

program->setAttributeBuffer(vertexLocation, GL_FLOAT, offset, 3, sizeof(VertexData));

offset += sizeof(QVector3D);

int tangentLocation = program->attributeLocation("a_tangent");

program->enableAttributeArray(tangentLocation);

program->setAttributeBuffer(tangentLocation, GL_FLOAT, offset, 3, sizeof(VertexData));

offset += sizeof(QVector3D);

int normalLocation = program->attributeLocation("a_normal");

program->enableAttributeArray(normalLocation);

program->setAttributeBuffer(normalLocation, GL_FLOAT, offset, 3, sizeof(VertexData));

offset += sizeof(QVector3D);

int texcoordLocation = program->attributeLocation("a_texcoord");

program->enableAttributeArray(texcoordLocation);

program->setAttributeBuffer(texcoordLocation, GL_FLOAT, offset, 2, sizeof(VertexData));

if(bTess)

{

gl->glPatchParameteri(GL_PATCH_VERTICES, 3);

gl->glDrawElements(GL_PATCHES, meshBuffer->indiceNum, GL_UNSIGNED_SHORT, nullptr);

}

else

{

gl->glDrawElements(GL_TRIANGLES, meshBuffer->indiceNum, GL_UNSIGNED_SHORT, nullptr);

}

}

void GeometryEngine::drawObj(string path,QOpenGLShaderProgram* program,bool bTess)

{

Model* pModel;

if(mapModel.find(path) == mapModel.end())

{

if(!loadObj(path, pModel))

{

return;

}

}

auto vecMesh = mapModel[path];

for(size_t i = 0;i < vecMesh.Count();i++)

{

auto meshBuffer = vecMesh.GetMeshBuffer(i);

drawObj(meshBuffer,program, bTess);

}

}

void GeometryEngine::processMesh(vector& vertices, vector& indices, QOpenGLTexture*& albedo, aiMesh *mesh, const aiScene *scene)

{

for(unsigned int i = 0; i < mesh->mNumVertices; i++)

{

VertexData vertex;

if(mesh->mVertices)

{

vertex.position = QVector3D(mesh->mVertices[i].x,mesh->mVertices[i].y,mesh->mVertices[i].z);

}

if(mesh->mTextureCoords[0])

{

vertex.texcoord = QVector2D(mesh->mTextureCoords[0][i].x,mesh->mTextureCoords[0][i].y);

}

if(mesh->mNormals)

{

vertex.normal = QVector3D(mesh->mNormals[i].x,mesh->mNormals[i].y,mesh->mNormals[i].z);

vertex.normal.normalized();

}

if(mesh->mTangents)

{

vertex.tangent = QVector3D(mesh->mTangents[i].x,mesh->mTangents[i].y,mesh->mTangents[i].z);

}

vertices.push_back(vertex);

}

for(unsigned int i = 0; i < mesh->mNumFaces; i++)

{

aiFace face = mesh->mFaces[i];

for(unsigned int j = 0; j < face.mNumIndices; j++)

{

indices.push_back(static_cast(face.mIndices[j]));

}

}

aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex];

for(unsigned int i = 0; i < material->GetTextureCount(aiTextureType_DIFFUSE); i++)

{

aiString str;

material->GetTexture(aiTextureType_DIFFUSE, i, &str);

albedo = CResourceInfo::Inst()->CreateTexture(str.C_Str());

}

}

void GeometryEngine::processNode(const string& path, aiNode *node, const aiScene *scene)

{

// process all the node's meshes (if any)

for(unsigned int i = 0; i < node->mNumMeshes; i++)

{

vector vertices;

vector indices;

QOpenGLTexture* albedo = nullptr;

aiMesh *aimesh = scene->mMeshes[node->mMeshes[i]];

processMesh(vertices, indices, albedo, aimesh, scene);

MeshBuffer* meshBuffer = new MeshBuffer();

for(size_t i = 0;i < indices.size() / 3; i++)

{

CalTangent(vertices[indices[3 * i]],vertices[indices[3 * i + 1]],vertices[indices[3 * i + 2]]);

}

meshBuffer->Init(vertices.data(),static_cast(vertices.size()));

meshBuffer->Init(indices.data(),static_cast(indices.size()));

Mesh* mesh = new Mesh();

mesh->name = node->mName.C_Str();

mesh->buffer = meshBuffer;

mesh->albedo = albedo;

mapModel[path].Push(mesh);

}

// then do the same for each of its children

for(unsigned int i = 0; i < node->mNumChildren; i++)

{

processNode(path, node->mChildren[i], scene);

}

}

void GeometryEngine::CalTangent(VertexData& vertex0, VertexData& vertex1, VertexData& vertex2)

{

float u0 = vertex0.texcoord.x();

float v0 = vertex0.texcoord.y();

float u1 = vertex1.texcoord.x();

float v1 = vertex1.texcoord.y();

float u2 = vertex2.texcoord.x();

float v2 = vertex2.texcoord.y();

float t1 = u1 - u0;

float b1 = v1 - v0;

float t2 = u2 - u0;

float b2 = v2 - v0;

QVector3D e0 = vertex1.position - vertex0.position;

QVector3D e1 = vertex2.position - vertex0.position;

float k = t1 * b2 - b1 * t2;

QVector3D tangent;

tangent = k * QVector3D(b2 * e0.x() - b1 * e1.x(),b2 * e0.y() - b1 * e1.y(),b2 * e0.z() - b1 * e1.z());

QVector vertexArr = { &vertex0, &vertex1, &vertex2};

QVector adjoinPlane;

adjoinPlane.resize(vertexArr.size());

for(int i = 0;i < vertexArr.size();i++)

{

adjoinPlane[i]++;

float ratio = 1.0f / adjoinPlane[i];

vertexArr[i]->tangent = vertexArr[i]->tangent * (1 - ratio) + tangent * ratio;

vertexArr[i]->tangent.normalize();

}

}

接下来,咱们能够试着导入一个简单的模型。

在建模软件maya中,拖出一个简单的甜甜圈,并勾选使用三角面显示:

aba5746859f63fb16a714dabddaaaf71.png

给这个甜甜圈绑定一个uv,此处uv用了一个圆柱形投影,将其水平扫描设为360度,高度稍微调高一些。这里只是大体获得一个还算过得去的uv纹理。

e017c355a4b6303794a90abd7e3e358a.png

选中当前对象,而后在文件菜单选择导出当前选择,而后根据本身的需求导出:

c54c7b5cc9e866fbb80b6d4bdb840bb5.png

而后就能够把这个"甜甜圈”导入本身的项目中了:

67281625af36a1341f799d3f307d0a26.png

试着加一下材质,除了有一块由于瞎搞的uv致使不太对的地方,其它看起来都没什么问题了。

43bbb012041b30ecf2a076371b559363.png

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

assimp批量转模型,[OpenGL] 使用Assimp导入模型(Qt) 的相关文章

  • python 字典

    字典的特征 1 字典中数据必须是以键值对的形式出现的 2 键不能重复 而值可以 3 字典中的键是不能修改的 而值是可以修改的 可以为任何对象 因此键不能用变量 字典的书写范例 dictory 猫 cat 狗 dog 狼 holf print
  • jenkins pipeline之自动构建(gitlab webhook 和 Generic Webhook Trigger集成)

    需求 1 开发在哪个分支上提交代码 jenkins就自动发布相对应的分支 2 实现既能手动发布jenkins 也要实现自动webhook发布 约定 和开发约定分支对应的环境 比如 debug对应开发环境 develop对应测试环境 mast
  • 【Fastdfs】通过 docker 快速搭建集群 fastdfs 环境

    Fastdfs 通过 docker 快速搭建集群 fastdfs 环境 1 镜像构建 码云地址 https gitee com hbsky fastDFS 构建新的镜像 使用我的镜像也行 docker build t registry cn
  • dlink网络打印服务器如何修改ip地址,如何使用脚本更改网络打印机的IP地址?

    HI 大家好 现在的客户端全部基于WIN XP WIN7 都连接着一台HP 4650网络打印机 IP ADDRESS 10 201 0 1 但是最近打印机IP做了整体的调整 如何实现用脚本更改以前的IP呢 我试过以下的脚本 但是只有添加TC
  • keil5中Undefined symbol XXX 的解决方法

    keil5中Undefined symbol XXX 的解决方法 OBJ LED axf Error L6218E Undefined symbol SPI Cmd referred from spi o OBJ LED axf Error
  • 库存预占架构升级方案设计-交易库存中心

    背景介绍 伴随物流行业的迅猛发展 一体化供应链模式的落地 对系统吞吐 系统稳定发出巨大挑战 库存作为供应链的重中之重表现更为明显 近三年数据可以看出 接入商家同比增长37 64 货品种类同比增长53 66 货品数量同比增长46 43 仓库数
  • 人工智能发展情况调研

    人工智能发展情况调研Artificial intelligence development circumstance investigation北京师范大学继续教育学院 2000级计算机科学与技术 赵旭峰E mail zxf95 163 c
  • Excel中如何找出两列数据中相同的数据,并且进行同行显示

    使用VLOOKUP方法即可 VLOOKUP A2 Sheet1 B C 1 0 的含义是 在sheet1工作表的B C区域的首列中查找等于a2的值 找到后 返回该区域的同行的值 最后的参数0表示精确查找 比如 想要列2根据列1中的数据进行排
  • PG概述及OSD对PG状态的影响

    前言 随着分布式存储的广泛应用 目前对PG的关注越来越多 本文基于ONStor分布式存储系统简要介绍一下PG的状态变化 重点说明OSD对PG状态的影响 一 Ceph分布式存储概述 Ceph是一个统一的分布式存储系统 设计初衷是提供较好的性能
  • Gazebo中特异性里程计odom的发布

    需求 将里程计 odom改成以小车初始位置为原点 车体坐标轴为方向建立坐标系 用该坐标系下的位姿作为里程计数据的位姿 分析 odom是ros发布的相对固定的里程计信息 不能使用命令行工具直接修改里程计信息参考的初始位置 因此 从 odom坐
  • QT5 创建“打开文件”按钮

    在GUI界面设计中 有时需要 打开文件 按钮 以加载外部文件 则需要我们用QFileDialog的静态函数完成 QT5中几个文件相关函数如下 函数名 作用 getOpenFileName 加载用户选择文件的文件名 getSaveFileNa
  • Java函数、数组

    Java函数 数组 函数 函数 就是定义在类中的具有特定功能的一段独立小程序 格式 修饰符 返回值类型 函数名 参数类型 参数1 参数类型 参数2 执行语句 return 返回值 返回值类型 函数运行后的结果的数据类型 参数类型 是形式参数
  • 手撸代码-删除链表的倒数第n个节点

    描述 给定一个链表 删除链表的倒数第 nn 个节点并返回链表的头指针 例如 给出的链表为 1 2 3 4 5 n 2n 2 删除了链表的倒数第 n 个节点之后 链表变为1 2 3 5 备注 题目保证 nn 一定是有效的 请给出时间复杂度为
  • Centos下配置Harbor私有仓库

    Centos下配置Harbor私有仓库 Harbor是一个开源的企业级容器镜像仓库 可以帮助用户建立和管理自己的私有Docker镜像仓库 本文将介绍在Centos操作系统下如何配置和使用Harbor私有仓库 安装Docker 首先 我们需要
  • 服务器安装完系统老重启,服务器老是自动重启

    服务器老是自动重启 内容精选 换一换 该任务以 Windows Server 2008 R2 64位 操作系统为例 指导用户安装Windows操作系统 由于镜像文件不同 安装步骤稍有不同 请根据实际的安装界面提示进行操作 请根据实际情况完成
  • linux文件系统初始化过程(3)---加载initrd(上)

    一 目的 本文主要讲述linux3 10文件系统初始化过程的第二阶段 加载initrd initrd是一个临时文件系统 由bootload负责加载到内存中 里面包含了基本的可执行程序和驱动程序 在linux初始化的初级阶段 它提供了一个基本
  • 如何在Linux中设置静态IP和配置网络

    如何在Linux中设置静态IP和配置网络 文章目录 如何在Linux中设置静态IP和配置网络 1 使用ifconfig的一次性修改 1 修改静态ip 2 修改网关 2 修改配置文件的永久性修改 1 Ubuntu相关系统 2 CentOS相关
  • C#+Sql Server开发一个简易的学生管理系统

    效果图 目前是这样 如果想做成这样 加一个DataGridView进行显示即可 使用VS2017新建一个控制台应用程序 连接数据库 即可对数据库进行增删改查 更多的功能还没有写 不适合直接拿去做课设 不过基本架子都有了 更多复杂的功能写sq
  • Qt之回调函数:6 在QT中使用回调函数替代信号槽

    文章目录 一 前言 二 如何使用CALLBACK工作 程序及解释 小方块 主窗口 MainWindow ui 总结 在QT中使用回调函数替代信号槽 前面讲了一堆 就是为了实现看到的这篇文章中的例子 由于对回调不懂 前前后后翻阅参考了一大堆优

随机推荐