OpenGL Assimp加载各类型模型(.obj、.fbx、.glb、.3ds)

1.简介

本博客以.glb格式为例,加载glb格式的3d模型,网上找了一圈,基本上都是根据OpenGL官方示例,加载.obj格式的3d模型。

下面以.obj和.glb格式的3D模型简单介绍一下。

常见的.obj格式的3D模型如下所示:纹理都已经被剥离出来了。所以在使用Assimp库加载的时候,加载了指定的路径即可。

但是.glb格式的3D模型如下所示,就只有一个glb文件,纹理嵌入到模型当中, 假如我们使用Assimp库去加载的时候,能够加载出模型,但是加载出来的效果全是黑的,加载不了纹理。

加载的效果如下图所示,黑的一片。

原因分析:找不到纹理路径。

2.解决方法

将纹理分离,保存到本地文件,加载本地纹理文件。

首先通过ReadFile,读取本地文件,返回aiScene。

获取纹理数量:scene->mNumTextures。

获取当前的纹理:aiTexture* texture = scene->mTexturesi。

然后看一下aiTexture官网文档介绍。

cpp 复制代码
    /** Width of the texture, in pixels
     *
     * If mHeight is zero the texture is compressed in a format
     * like JPEG. In this case mWidth specifies the size of the
     * memory area pcData is pointing to, in bytes.
     */
    unsigned int mWidth;

    /** Height of the texture, in pixels
     *
     * If this value is zero, pcData points to an compressed texture
     * in any format (e.g. JPEG).
     */
    unsigned int mHeight;

    /** Data of the texture.
     *
     * Points to an array of mWidth * mHeight aiTexel's.
     * The format of the texture data is always ARGB8888 to
     * make the implementation for user of the library as easy
     * as possible. If mHeight = 0 this is a pointer to a memory
     * buffer of size mWidth containing the compressed texture
     * data. Good luck, have fun!
     */
     C_STRUCT aiTexel* pcData;

     char achFormatHint[ HINTMAXTEXTURELEN ]

mWidth:纹理的像素宽,如果高度为0,mWidth指定pcData指向的内存区域,以字节为单位。

mHeigth:纹理的像素高,像jpeg类型,该值为0。

pcData:纹理数据,数据的rgba值保存到这个数据里面。

achFormatHint:图片的格式,png或者jpg或者别的。

再进去看一下aiTexel结构,结构如下:包含r、g、b、a值,代表每一个像素的r、g、b、a值。

cpp 复制代码
struct aiTexel {
    unsigned char b,g,r,a;

#ifdef __cplusplus
    //! Comparison operator
    bool operator== (const aiTexel& other) const
    {
        return b == other.b && r == other.r &&
               g == other.g && a == other.a;
    }

    //! Inverse comparison operator
    bool operator!= (const aiTexel& other) const
    {
        return b != other.b || r != other.r ||
               g != other.g || a != other.a;
    }

    //! Conversion to a floating-point 4d color
    operator aiColor4D() const
    {
        return aiColor4D(r/255.f,g/255.f,b/255.f,a/255.f);
    }
#endif // __cplusplus

} PACK_STRUCT;

根据上面的条件,将图片保存到本地。

cpp 复制代码
   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;
    }
    
    directory = path.substr(0, path.find_last_of('/'));

    for (int i = 0; i < scene->mNumTextures; i++)
    {
        aiTexture* texture = scene->mTextures[i];

        char fileName[100];
        sprintf(fileName, "%s/%s.%s", modelDirectory.c_str(), texture->mFilename.C_Str(), texture->achFormatHint);

        QFile file(fileName);
        if (file.exists())
        {
            m_mapPath.insert(i, QString(fileName));
            continue;
        }

        if (!file.open(QIODevice::WriteOnly))
            break;

        unsigned char* buffer = new unsigned char[texture->mWidth * 4];
        memset(buffer, 0, texture->mWidth * 4);
        for (int x = 0; x < texture->mWidth; ++x)
        {
            //拷贝RGBA数据到缓冲区
            int index = x * 4;

            buffer[index] = texture->pcData[x].b; // Blue
            buffer[index + 1] = texture->pcData[x].g; // Green
            buffer[index + 2] = texture->pcData[x].r;         // Red
            buffer[index + 3] = texture->pcData[x].a; // Alpha

        }

        file.write((char*)buffer, texture->mWidth * 4);
        file.close();
        m_mapPath.insert(i, QString(fileName));
        delete[]buffer;
    }

如下图所示,将glb格式的纹理图片剥离出来保存到了本地。

最后加载对应的纹理即可。

3.加载效果图

4.完整源码

https://download.csdn.net/download/wzz953200463/88746271

相关推荐
扶尔魔ocy9 分钟前
【qt openGL入门笔记】windows编译MinGW版本的osgearth(2.10.1)
qt·opengl·osg
河图洛水1 小时前
UniDex-VLA:用人类第一视角视频,训出能跨 8 种灵巧手的 3D VLA
3d·大模型·具身智能·vla·ego
云飞云共享云桌面3 小时前
苏州半导体工厂研发部门多个SolidWorks 如何共享服务器来进行研发设计
运维·服务器·3d·自动化·制造
坚定信念,勇往无前3 小时前
3d建模整个流程-完整工作流总结(Maya + Marmoset Toolbag 八猴 + Substance Painter + Unity URP)
3d
FansAI_art4 小时前
3D潮玩手办的材质还原与多角色同屏防崩坏
3d·材质
Solange__4 小时前
AI模型编辑器、Blender和3D Agent怎么选?按5类修改任务比较局部编辑、拓扑与自动化
人工智能·3d·自然语言处理·编辑器·音视频·blender·游戏策划
小王C语言4 小时前
Qt常用控件:按钮类控件,普通按键、单选、复选
开发语言·qt
杀生丸学AI5 小时前
【世界模型】AEON:统一视频与 3D 世界模型
3d·三维重建·空间智能·动态重建·大场景重建·流式重建·前馈式重建
初阳78514 小时前
【基于Qt5仿音乐播放器(六)】——细节打磨与总结
qt·1024程序员节
GlobalInfo15 小时前
全球包装检测用3D轮廓传感器市场调研:2026年规模预计达1.87亿美元,食品医药与电商物流需求推动增长
大数据·人工智能·3d