129 lines
3.8 KiB
C++
129 lines
3.8 KiB
C++
#include <td/render/loader/FbxLoader.h>
|
|
|
|
#include <assimp/Importer.hpp> // C++ importer interface
|
|
#include <assimp/postprocess.h> // Post processing flags
|
|
#include <assimp/scene.h> // Output data structure
|
|
#include <iostream>
|
|
#include <memory>
|
|
#include <sp/common/DataBuffer.h>
|
|
#include <td/render/loader/GLLoader.h>
|
|
#include <vector>
|
|
|
|
#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<GL::VertexArray> ProcessMesh(aiMesh* mesh, const aiScene* scene, const aiMatrix4x4& transform) {
|
|
std::vector<float> positions;
|
|
std::vector<float> textureCoords;
|
|
std::vector<float> normals;
|
|
|
|
std::vector<unsigned int> 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::VertexArray>(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<std::unique_ptr<GL::VertexArray>>& 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
|