The assimp, "makes your program sexier".
If you're anything like me, you have an appreciation for simple.void Model::loadModel(std::string path){ Assimp::Importer importer; const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs); // handle error...}
Done. Then to get your hands on the data...aiNode* node = scene->mRootNode;aiMesh* mesh = scene->mMeshes[node->mMeshes[/*multiple mesh index*/]];for(unsigned int i=0; imNumVertices; i++){ aiVector3D = mesh->mVertices aiVector3D = mesh->mNormals // if not null aiVector3d = mesh->mTextureCoords[0/*first uv set*/] // if not null}for(unsigned int i=0; imNumFaces; i++){ aiFace face = mesh->mFaces; for(unsigned int j=0; jDamn that's tight. Doesn't get any better. Love the assimp.
So we take a closer look with a 5k character model. After import, we're given a 30k character model. Hate the assimp. :)
LOL...yes, we know what you did. Vertex duplication to the extreme. Our little lovely, rewrites to a linear index array and dumps vertices per face making indexed array drawing pointless. Keep hold of the love though, because our program is sexier even though the compile time is now measured in eons. Well, that last part makes her a butt-a-face, so I'm sorry sweetie...you go straight to offline process.
Right, so we have our data...it's bloated but it's there.
Time for a justifiable early data optimization.// optimize out vertex duplicationmyMesh mesh; // holding extracted data from assimp std::vector vv; // vector std::vector vi; // vector indicesfor (unsigned int i = 0; i < mesh.indices.size(); i++){ bool foundVertex = false; for (unsigned int j = 0; j < vv.size(); j++) { // search list for matching vertex if (mesh.vertices[mesh.indices].texcoord.x == vv[j].texcoord.x && mesh.vertices[mesh.indices].texcoord.y == vv[j].texcoord.y) { if (mesh.vertices[mesh.indices].position.x == vv[j].position.x && mesh.vertices[mesh.indices].position.y == vv[j].position.y && mesh.vertices[mesh.indices].position.z == vv[j].position.z) { foundVertex = true; vi.push_back(j); break; } } } if (foundVertex == false) { // add new vertex to list sVertex vertex; vertex.position = mesh.vertices[mesh.indices].position; vertex.normal = mesh.vertices[mesh.indices].normal; vertex.texcoord = mesh.vertices[mesh.indices].texcoord; vv.push_back(vertex); vi.push_back(vv.size() - 1); }}
Then we write this out to a binary file.std::string outPath = "NameYourOwnFileFormat";int numVertices = vv.size();int numIndices = vi.size();std::ofstream outFile(outPath, std::ios::out | std::ios::binary);outFile.write((char*)&numVertices, sizeof(int));outFile.write((char*)&numIndices, sizeof(int));for (int i = 0; i < numVertices; i++){ outFile.write((char*)&vv, sizeof(sVertex));}for (int i = 0; i < numIndices; i++){ outFile.write((char*)&vi, sizeof(unsigned int));}outFile.close();
Did I say I like easy...Back on engine side, it's a simple straight read and direct buffer upload.
No muss, no fuss. On the test mesh, we removed ~70% of the duplicated vertices cutting our asset size to about one third of what we were given.
Pretty sweet for an afternoon's play.