#include #include // C++ importer interface #include // Post processing flags #include // Output data structure #include #include #include #include #include #define VERTEX_SIZE 3 #define UV_SIZE 2 #define VERTEX_POSITION_INDEX 0 #define VERTEX_UV_INDEX 1 #define VERTEX_NORMAL_INDEX 2 namespace td { namespace ModelLoader { static std::unique_ptr ProcessMesh(aiMesh* mesh, const aiScene* scene, const aiMatrix4x4& transform) { std::vector positions; std::vector textureCoords; std::vector normals; std::vector indicies; aiFace* faces = mesh->mFaces; std::size_t faceNumber = mesh->mNumFaces; for (std::size_t j = 0; j < faceNumber; j++) { std::size_t offset = indicies.size(); std::size_t numIndices = faces[j].mNumIndices; indicies.resize(indicies.size() + numIndices); std::memcpy(indicies.data() + offset, faces[j].mIndices, numIndices * sizeof(unsigned int)); } std::size_t vertNumber = mesh->mNumVertices; aiVector3D* vertecies = mesh->mVertices; for (std::size_t j = 0; j < vertNumber; j++) { aiVector3D vertex = transform * vertecies[j]; positions.push_back(vertex.x); positions.push_back(vertex.y); positions.push_back(vertex.z); } if (mesh->HasNormals()) { aiVector3D* vertexNormals = mesh->mNormals; for (std::size_t j = 0; j < vertNumber; j++) { aiVector3D normal = transform * vertexNormals[j]; normals.push_back(normal.x); normals.push_back(normal.y); normals.push_back(normal.z); } } aiVector3D** vertexTexture = mesh->mTextureCoords; for (std::size_t j = 0; j < vertNumber; j++) { textureCoords.push_back(vertexTexture[0][j].x); textureCoords.push_back(vertexTexture[0][j].y); } GL::VertexBuffer positionVBO(positions, VERTEX_SIZE); positionVBO.AddVertexAttribPointer(VERTEX_POSITION_INDEX, VERTEX_SIZE, 0); GL::VertexBuffer textureVBO(textureCoords, UV_SIZE); textureVBO.AddVertexAttribPointer(VERTEX_UV_INDEX, UV_SIZE, 0); GL::VertexBuffer normalVBO(normals, VERTEX_SIZE); normalVBO.AddVertexAttribPointer(VERTEX_NORMAL_INDEX, VERTEX_SIZE, 0); auto Vao = std::make_unique(GL::ElementBuffer{indicies}); Vao->Bind(); Vao->BindVertexBuffer(std::move(positionVBO)); Vao->BindVertexBuffer(std::move(textureVBO)); Vao->BindVertexBuffer(std::move(normalVBO)); Vao->Unbind(); return Vao; } static void ProcessNode( aiNode* node, const aiScene* scene, std::vector>& meshes, const aiMatrix4x4& transform) { // recursive for (unsigned int i = 0; i < node->mNumChildren; i++) { ProcessNode(node->mChildren[i], scene, meshes, transform * node->mTransformation); } for (unsigned int i = 0; i < node->mNumMeshes; i++) { aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; meshes.push_back(ProcessMesh(mesh, scene, transform * node->mTransformation)); } } Model LoadModel(const std::string& fileName) { // DataBuffer fileData = utils::AssetsManager::GetAsset(fileName); sp::DataBuffer fileData; fileData.ReadFile(fileName); Assimp::Importer importer; const aiScene* scene = importer.ReadFile(fileName, aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_OptimizeGraph | aiProcess_OptimizeMeshes | aiProcess_GlobalScale); if (!scene) { std::cerr << "[ModelLoader] Failed to load model !\n"; return {}; } // utils::LOGD(utils::Format("[ModelLoader]\tModel nodes : %i", scene->mRootNode->mNumMeshes)); Model model; ProcessNode(scene->mRootNode, scene, model.m_Vaos, {}); std::cout << "Loaded " << model.m_Vaos.size() << " vaos !\n"; return model; } } // namespace ModelLoader } // namespace td