void load_model()

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);
	}
}