简单读取obj并打印所有内容:
#include<iostream>
#include<string>
#include<vector>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
using namespace std;
bool processMaterial(aiMaterial* matPtr, const aiScene* sceneObjPtr, const aiTextureType textureType)
{
if(!matPtr || !sceneObjPtr)
{
return false;
}
if(matPtr->GetTextureCount(textureType) <= 0)
{
///获得该类型的材质个数
return true;
}
for(size_t i = 0; i < matPtr->GetTextureCount(textureType); ++i)
{
aiString textPath;
aiReturn retStatus = matPtr->GetTexture(textureType, i, &textPath);
if(retStatus != aiReturn_SUCCESS || textPath.length == 0)
{
std::cerr << "Warning, load texture type=" << textureType
<< "index= " << i << " failed with return value= "
<< retStatus << std::endl;
continue;
}
cout << "材质路径" << textPath.C_Str() << endl;
}
return true;
}
bool processMesh(const aiMesh* meshPtr, const aiScene* sceneObjPtr)
{
if(!meshPtr || !sceneObjPtr)
{
return false;
}
// 从Mesh得到顶点数据、法向量、纹理数据
cout << "===== Mesh: " << meshPtr->mName.C_Str() << "=====" << endl;
cout << "顶点个数\t" << meshPtr->mNumVertices << endl;
for(size_t i = 0; i<meshPtr->mNumVertices; ++i) //只输出5个说明情况
{
if(i > 2)
{
cout << "\t..." << endl;
break;
}
// 获取顶点位置
if(meshPtr->HasPositions())
{
cout << "顶点坐标(";
cout << meshPtr->mVertices[i].x << ',';
cout << meshPtr->mVertices[i].y << ',';
cout << meshPtr->mVertices[i].z << ")\t";
}
// 获取纹理数据 目前只处理0号纹理
if(meshPtr->HasTextureCoords(0))
{
cout << "纹理坐标(";
cout << meshPtr->mTextureCoords[0][i].x << ',';
cout << meshPtr->mTextureCoords[0][i].y << ")\t";
}
else
{
cout << "无纹理坐标\t";
}
// 获取法向量数据
if(meshPtr->HasNormals())
{
cout << "法向量(";
cout << meshPtr->mNormals[i].x << ',';
cout << meshPtr->mNormals[i].y << ',';
cout << meshPtr->mNormals[i].z << ")\t";;
}
else
{
cout << "无法向量\t";
}
cout << endl;
}
cout << endl;
// 获取索引数据
cout << "Face个数\t" << meshPtr->mNumFaces << endl;
for(size_t i = 0; i < meshPtr->mNumFaces; ++i)
{
if(i > 2)
{
cout << "\t..." << endl;
break;
}
aiFace face = meshPtr->mFaces[i];
if(face.mNumIndices != 3) //在导入时设置了aiProcess_Triangulate参数
{
//没有正常三角化,模型出错!
std::cerr << "Error:Model::processMesh, mesh not transformed to triangle mesh." << std::endl;
return false;
}
for(size_t j = 0; j < face.mNumIndices; ++j)
{
cout << face.mIndices[j] << '\t';
}
cout << endl;
}
cout << endl;
// 获取纹理数据
cout << "= Mesh的材质: " << meshPtr->mName.C_Str() << "=====" << endl;
if(meshPtr->mMaterialIndex >= 0)
{
aiMaterial* materialPtr = sceneObjPtr->mMaterials[meshPtr->mMaterialIndex];
// 获取diffuse类型
processMaterial(materialPtr, sceneObjPtr, aiTextureType_DIFFUSE);
// 获取specular类型
processMaterial(materialPtr, sceneObjPtr, aiTextureType_SPECULAR);
}
return true;
}
bool processNode(const aiNode* node, const aiScene* sceneObjPtr)
{
if(!node || !sceneObjPtr)
{
return false;
}
// 自身结点的信息
cout << "======= Node: " << node->mName.C_Str() << "=======" << endl;
cout << "该结点Mesh个数\t" << node->mNumMeshes << endl;
cout << "该结点的孩子个数(即该结点的aiNode的个数)" << node->mNumChildren << endl;
for(size_t i = 0; i<node->mNumMeshes; ++i)
{
if(i > 2)
{
cout << "\t..." << endl;
break;
}
unsigned int meshIndex = node->mMeshes[i]; ///node中存的是mesh的索引
const aiMesh* meshPtr = sceneObjPtr->mMeshes[meshIndex]; ///所有的mesh都存在aiScene中,所以要在其中获取
if(meshPtr) ///如果有该mesh
{
processMesh(meshPtr, sceneObjPtr); //处理该mesh
}
}
cout << endl;
// 孩子结点的信息
for(size_t i = 0; i < node->mNumChildren; ++i)
{
processNode(node->mChildren[i], sceneObjPtr);
}
return true;
}
/*!
* \brief: printNodeTree 打印aiNode的层级关系(先根遍历树)
*
* \param: node node结点
* \param: sceneObjPtr aiScene场景信息
* \param: level 层级,第一层为1
* \returns: void
* \author: wangqi
* \date: 2020/08/26 14:36
*
* TODO:
*
*/
void printNodeTree(const aiNode* node, const aiScene* sceneObjPtr, int level)
{
if(!node || !sceneObjPtr) ///遍历结束
{
return;
}
if (level == 1) ///表头
{
cout << "层数\tNode名称\t父亲\tMesh个数\t孩子结点的个数" << endl;
}
//节点信息
cout << level << '\t'; ///此节点的层级
cout << node->mName.C_Str() << '\t'; ///此节点的名字
std::string parent_name = node->mParent == nullptr ? "无" : node->mParent->mName.C_Str();
cout << parent_name << '\t'; ///父亲的名称
cout << node->mNumMeshes << '\t'; ///节点个数
cout << node->mNumChildren << endl; ///孩子个数
// 处理孩子结点
for(size_t i = 0; i < node->mNumChildren; ++i)
{
printNodeTree(node->mChildren[i], sceneObjPtr, level+1);
}
}
int main()
{
// 加载
string filePath = "D:/codes/Tools/GLAL/testdata/njnz/F316.obj";
Assimp::Importer importer;
const aiScene* sceneObjPtr = importer.ReadFile(filePath,
aiProcess_Triangulate | aiProcess_FlipUVs);
if(!sceneObjPtr
|| sceneObjPtr->mFlags == AI_SCENE_FLAGS_INCOMPLETE
|| !sceneObjPtr->mRootNode)
{
std::cerr << "Error:Model::loadModel, description: "
<< importer.GetErrorString() << std::endl;
return false;
}
cout << "========== aiScene表示一个场景 ==========" << endl;
cout << "场景名称(即文件名)\t" << sceneObjPtr->GetShortFilename(filePath.c_str()) << endl;
cout << "场景中Mesh的数量\t" << sceneObjPtr->mNumMeshes << endl;
cout << "场景中material的数量\t" << sceneObjPtr->mNumMaterials << endl;
cout << "场景中textures的数量\t" << sceneObjPtr->mNumTextures << endl;
///除了这些信息,场景中还有光照、摄像机等
cout << "此场景是否有灯光数据\t" << sceneObjPtr->HasLights() << endl;
cout << "此场景是否有摄像机\t" << sceneObjPtr->HasCameras() << endl;
cout << "此场景是否有动画\t" << sceneObjPtr->HasAnimations() << endl;
cout << endl << "========== aiNode其实表示一个Model,aiNode本身是树形结构(即Model与子Model=1:n的关系) ==========" << endl;
cout << "//以下打印aiNode之间的树形关系" << endl;
printNodeTree(sceneObjPtr->mRootNode, sceneObjPtr, 1); //输出aiNode的树形结构
cout << endl << "========== 递归遍历每个Node,并输出信息 ==========" << endl;
if(!processNode(sceneObjPtr->mRootNode, sceneObjPtr))
{
std::cerr << "Error:Model::loadModel, process node failed." << std::endl;
return false;
}
return 0;
}