1.簡(jiǎn)介
本博客以.glb格式為例,加載glb格式的3d模型,網(wǎng)上找了一圈,基本上都是根據(jù)OpenGL官方示例,加載.obj格式的3d模型。
下面以.obj和.glb格式的3D模型簡(jiǎn)單介紹一下。
常見的.obj格式的3D模型如下所示:紋理都已經(jīng)被剝離出來了。所以在使用Assimp庫加載的時(shí)候,加載了指定的路徑即可。
但是.glb格式的3D模型如下所示,就只有一個(gè)glb文件,紋理嵌入到模型當(dāng)中,假如我們使用Assimp庫去加載的時(shí)候,能夠加載出模型,但是加載出來的效果全是黑的,加載不了紋理。
加載的效果如下圖所示,黑的一片。
原因分析:找不到紋理路徑。
2.解決方法
將紋理分離,保存到本地文件,加載本地紋理文件。
首先通過ReadFile,讀取本地文件,返回aiScene。
獲取紋理數(shù)量:scene->mNumTextures。
獲取當(dāng)前的紋理:aiTexture* texture = scene->mTextures[i]。
然后看一下aiTexture官網(wǎng)文檔介紹。
/** 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指向的內(nèi)存區(qū)域,以字節(jié)為單位。
mHeigth:紋理的像素高,像jpeg類型,該值為0。
pcData:紋理數(shù)據(jù),數(shù)據(jù)的rgba值保存到這個(gè)數(shù)據(jù)里面。
achFormatHint:圖片的格式,png或者jpg或者別的。
再進(jìn)去看一下aiTexel結(jié)構(gòu),結(jié)構(gòu)如下:包含r、g、b、a值,代表每一個(gè)像素的r、g、b、a值。
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;
?根據(jù)上面的條件,將圖片保存到本地。
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數(shù)據(jù)到緩沖區(qū)
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格式的紋理圖片剝離出來保存到了本地。?
最后加載對(duì)應(yīng)的紋理即可。
3.加載效果圖
文章來源:http://www.zghlxwxcb.cn/news/detail-805066.html
4.完整源碼
https://download.csdn.net/download/wzz953200463/88746271文章來源地址http://www.zghlxwxcb.cn/news/detail-805066.html
到了這里,關(guān)于OpenGL Assimp加載各類型模型(.obj、.fbx、.glb、.3ds)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!