in roboschool/cpp-household/assets-mesh.cpp [79:165]
void load_model(const shared_ptr<ShapeDetailLevels>& result, const std::string& fn, btScalar scale, const btTransform& transform)
{
//fprintf(stderr, "Loading model '%s' (takes some time, should not happen when learning without rendering)\n", fn.c_str());
Assimp::Importer importer1;
std::string ext = fn.substr(fn.size()-3, 3);
aiMatrix4x4 root_trans;
importer1.SetPropertyInteger(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION, 1);
importer1.SetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, root_trans); // setting identity matrix helps to load .dae, resulting model turned on the side without it
const aiScene* scene1 = importer1.ReadFile(fn,
aiProcess_JoinIdenticalVertices | aiProcess_GenNormals | aiProcess_ImproveCacheLocality | aiProcess_PreTransformVertices | aiProcess_Triangulate
);
if (!scene1) throw std::runtime_error("cannot load '" + fn + "': " + std::string(importer1.GetErrorString()) );
if (scene1->mNumMeshes==0 && scene1->mMaterials==0) throw std::runtime_error("cannot load '" + fn + "': model empty");
Assimp::Importer importer2;
importer2.SetPropertyInteger(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION, 1);
importer2.SetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, root_trans);
const aiScene* scene2 = importer2.ReadFile(fn, aiProcess_JoinIdenticalVertices | aiProcess_PreTransformVertices);
assert(scene2->mNumMaterials==scene1->mNumMaterials);
assert(scene2->mNumMeshes==scene1->mNumMeshes);
std::vector<shared_ptr<Material>> materials;
if (!result->materials || ext=="dae") // Texture names tend to repeat in .dae, for example "Material_001", cannot be made common for the whole robot
result->materials.reset(new MaterialNamespace);
for (int c=0; c<(int)scene1->mNumMaterials; c++) {
const aiMaterial* aim = scene1->mMaterials[c];
aiString name;
aim->Get(AI_MATKEY_NAME, name);
shared_ptr<Material> m;
auto find = result->materials->name2mtl.find(name.C_Str());
if (find!=result->materials->name2mtl.end()) {
m = find->second;
} else {
m.reset(new Material(name.C_Str()));
aiString aipath;
if (aim->GetTexture(aiTextureType_DIFFUSE, 0, &aipath, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS) {
QFileInfo finfo(QString::fromUtf8(fn.c_str()));
QString path = finfo.absolutePath();
path += "/";
path += QString::fromUtf8(aipath.data);
m->diffuse_texture_image_fn = path.toUtf8().constData();
}
aiColor4D diffuse;
if (aiGetMaterialColor(aim, AI_MATKEY_COLOR_DIFFUSE, &diffuse) == AI_SUCCESS) {
m->diffuse_color =
(uint32_t(255*diffuse[0]) << 16) |
(uint32_t(255*diffuse[1]) << 8) |
(uint32_t(255*diffuse[2]) << 0);
}
result->materials->name2mtl[m->name] = m;
}
materials.push_back(m);
}
for (int c=0; c<(int)scene1->mNumMeshes; c++) {
const aiMesh* aimesh1 = scene1->mMeshes[c];
const aiMesh* aimesh2 = scene2->mMeshes[c];
shared_ptr<Shape> mesh(new Shape);
mesh->origin = transform;
for (int v=0; v<(int)aimesh2->mNumVertices; v++) {
mesh->raw_vertexes.push_back(aimesh2->mVertices[v][0]*scale);
mesh->raw_vertexes.push_back(aimesh2->mVertices[v][1]*scale);
mesh->raw_vertexes.push_back(aimesh2->mVertices[v][2]*scale);
}
mesh->material = materials[aimesh1->mMaterialIndex];
for (int f=0; f<(int)aimesh1->mNumFaces; f++) {
const aiFace& face = aimesh1->mFaces[f];
if (face.mNumIndices==3) {
mesh_push_vertex(mesh, aimesh1, face.mIndices[0], scale);
mesh_push_vertex(mesh, aimesh1, face.mIndices[1], scale);
mesh_push_vertex(mesh, aimesh1, face.mIndices[2], scale);
mesh_push_line(mesh, aimesh1, face.mIndices[0], face.mIndices[1], scale);
mesh_push_line(mesh, aimesh1, face.mIndices[1], face.mIndices[2], scale);
mesh_push_line(mesh, aimesh1, face.mIndices[2], face.mIndices[0], scale);
} else {
fprintf(stderr, "%s mesh face with %i verts\n", fn.c_str(), face.mNumIndices);
}
}
if (mesh->v.size())
result->detail_levels[DETAIL_BEST].push_back(mesh);
//printf("%s mesh %i\n%5i raw vertexes, %5i vertexes in triangles, %5i vertexes in quads\n",
// fn.c_str(), c, (int)mesh->raw_vertexes.size()/3, (int)mesh->v.size()/3, (int)mesh->v.size()/3);
}
}