fast-nuclear-sim/src/graphics/model.cpp

122 lines
2.7 KiB
C++

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include <iostream>
#include <vector>
#include "mesh.hpp"
#include "model.hpp"
#include "arrays.hpp"
#include "texture.hpp"
using namespace sim::graphics;
struct proc_state
{
unsigned int offset = 0;
std::string base;
std::vector<arrays::vertex> vertices;
std::vector<unsigned int> indices;
};
static unsigned int proc_texture(const proc_state& state, aiMaterial* mat, aiTextureType type)
{
if(mat->GetTextureCount(type) == 0)
{
return 0;
}
aiString str;
mat->GetTexture(type, 0, &str);
std::string filename(str.C_Str());
std::replace(filename.begin(), filename.end(), '\\', '/');
return texture::load(state.base + "/" + filename);
}
static void proc_mesh(proc_state& state, std::vector<mesh>& meshes, aiMesh* mesh, const aiScene* scene)
{
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
unsigned int texid = proc_texture(state, material, aiTextureType_DIFFUSE);
unsigned int offset = state.offset;
for(unsigned int i = 0; i < mesh->mNumVertices; i++)
{
arrays::vertex vertex;
vertex.texid = texid;
vertex.pos = {mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z};
if(mesh->HasNormals())
{
vertex.normal = {mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z};
}
if(mesh->mTextureCoords[0])
{
vertex.texpos = {mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y};
vertex.do_tex = 1;
}
state.vertices.push_back(vertex);
}
for(unsigned int i = 0; i < mesh->mNumFaces; i++)
{
aiFace face = mesh->mFaces[i];
for(unsigned int j = 0; j < face.mNumIndices; j++)
{
state.indices.push_back(face.mIndices[j] + offset);
}
}
state.offset += mesh->mNumVertices;
}
static void proc_node(proc_state& state, std::vector<mesh>& meshes, aiNode* node, const aiScene* scene)
{
for(size_t i = 0; i < node->mNumMeshes; i++)
{
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
proc_mesh(state, meshes, mesh, scene);
}
for(size_t i = 0; i < node->mNumChildren; i++)
{
proc_node(state, meshes, node->mChildren[i], scene);
}
}
void model::load(std::string base, std::string filename)
{
proc_state state {.base = base};
std::string path = base + "/" + filename;
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(path.c_str(), aiProcess_Triangulate | aiProcess_FlipUVs);
proc_node(state, meshes, scene->mRootNode, scene);
sim::graphics::mesh m;
m.set_vertices(&state.vertices[0], state.vertices.size(), GL_STATIC_DRAW);
m.set_indices(&state.indices[0], state.indices.size(), GL_STATIC_DRAW);
meshes.push_back(std::move(m));
}
void model::render() const
{
for(const mesh& m : meshes)
{
m.bind();
m.render();
}
}