31 #ifdef E3D_FEATURE_ASSIMP
32 # include <assimp/Importer.hpp>
33 # include <assimp/scene.h>
35 # include <assimp/postprocess.h>
36 # include <assimp/material.h>
40 #include "eng3d/model.hpp"
41 #include "eng3d/shader.hpp"
42 #include "eng3d/material.hpp"
43 #include "eng3d/texture.hpp"
44 #include "eng3d/shader.hpp"
45 #include "eng3d/state.hpp"
46 #include "eng3d/utils.hpp"
47 #include "eng3d/log.hpp"
74 #ifdef E3D_FEATURE_ASSIMP
75 static inline std::shared_ptr<Eng3D::Texture> get_material_texture(
const aiMaterial& material, aiTextureType type) {
77 for(
size_t i = 0; i < material.GetTextureCount(type); i++) {
79 material.GetTexture(type, i, &str);
81 auto path = std::string(
"gfx/") + str.C_Str();
82 return s.tex_man.load(s.package_man.get_unique(path));
84 return s.tex_man.get_white();
87 Eng3D::SimpleModel Eng3D::Model::process_simple_model(aiMesh& mesh,
const aiScene& scene) {
90 simple_model.buffer.resize(mesh.mNumVertices);
92 for(
size_t i = 0; i < mesh.mNumVertices; i++)
93 max_vert = glm::vec3(glm::max(max_vert.x, mesh.mVertices[i].x), glm::max(max_vert.y, mesh.mVertices[i].y), glm::max(max_vert.z, mesh.mVertices[i].z));
95 max_vert = glm::vec3(max_vert.x, glm::max(max_vert.y, max_vert.x), glm::max(max_vert.z, max_vert.x));
96 max_vert = glm::vec3(glm::max(max_vert.x, max_vert.y), max_vert.y, glm::max(max_vert.z, max_vert.y));
97 max_vert = glm::vec3(glm::max(max_vert.x, max_vert.z), glm::max(max_vert.y, max_vert.z), max_vert.z);
99 for(
size_t i = 0; i < mesh.mNumVertices; i++) {
100 auto vertice = glm::vec3(mesh.mVertices[i].x, mesh.mVertices[i].y, mesh.mVertices[i].z) / max_vert;
101 auto texcoord = glm::vec2(0.f, 0.f);
102 if(mesh.mTextureCoords[0])
103 texcoord = glm::vec2(mesh.mTextureCoords[0][i].x, mesh.mTextureCoords[0][i].y);
107 for(
size_t i = 0; i < mesh.mNumFaces; i++) {
108 auto& face = mesh.mFaces[i];
109 simple_model.indices.reserve(simple_model.indices.size() + face.mNumIndices);
110 for(
size_t j = 0; j < face.mNumIndices; j++)
111 simple_model.indices.push_back(face.mIndices[j]);
114 auto& material = *scene.mMaterials[mesh.mMaterialIndex];
117 simple_model.material = s.material_man.load(material.GetName().C_Str());
118 simple_model.material->diffuse_map = get_material_texture(material, aiTextureType_DIFFUSE);
119 simple_model.material->specular_map = get_material_texture(material, aiTextureType_SPECULAR);
120 simple_model.material->ambient_map = get_material_texture(material, aiTextureType_AMBIENT);
121 simple_model.material->height_map = get_material_texture(material, aiTextureType_HEIGHT);
122 simple_model.material->occlussion_map = get_material_texture(material, aiTextureType_AMBIENT_OCCLUSION);
123 simple_model.material->normal_map = get_material_texture(material, aiTextureType_NORMALS);
127 if(AI_SUCCESS == aiGetMaterialColor(&material, AI_MATKEY_COLOR_DIFFUSE, &diffuse))
128 simple_model.material->diffuse_color = glm::vec4(diffuse.r, diffuse.g, diffuse.b, diffuse.a);
130 if(AI_SUCCESS == aiGetMaterialColor(&material, AI_MATKEY_COLOR_SPECULAR, &specular))
131 simple_model.material->specular_color = glm::vec4(specular.r, specular.g, specular.b, specular.a);
133 if(AI_SUCCESS == aiGetMaterialColor(&material, AI_MATKEY_COLOR_AMBIENT, &ambient))
134 simple_model.material->ambient_color = glm::vec4(ambient.r, ambient.g, ambient.b, ambient.a);
136 simple_model.upload();
140 void Eng3D::Model::process_node(aiNode& node,
const aiScene& scene) {
142 for(
size_t i = 0; i < node.mNumMeshes; i++) {
143 auto& mesh = *scene.mMeshes[node.mMeshes[i]];
144 this->simple_models.push_back(this->process_simple_model(mesh, scene));
147 for(
size_t i = 0; i < node.mNumChildren; i++)
148 this->process_node(*node.mChildren[i], scene);
156 auto it = models.find(path);
157 if(it != models.cend())
161 std::shared_ptr<Eng3D::Model> model;
163 #ifdef E3D_FEATURE_ASSIMP
165 Assimp::Importer importer;
166 const auto* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);
167 if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || scene->mRootNode ==
nullptr)
168 CXX_THROW(std::runtime_error, importer.GetErrorString());
170 model = std::make_shared<Eng3D::Model>();
171 #ifdef E3D_FEATURE_ASSIMP
172 model->process_node(*scene->mRootNode, *scene);
174 }
catch(std::runtime_error& e) {
176 model = std::make_shared<Eng3D::Model>();
178 models[path] = model;
183 return this->
load(asset.get() !=
nullptr ? asset->get_abs_path() :
"");
std::shared_ptr< Eng3D::Model > load(const std::string &path)
void set_texture(int value, const std::string &name, const Eng3D::Texture &texture) const
void set_uniform(const std::string &name, glm::mat4 uniform) const
static State & get_instance()
void debug(const std::string_view category, const std::string_view msg)
std::string translate_format(const std::string_view format, Args &&... args)
String formatter, with translation.
void load(GameState &gs, const std::string &savefile_path)
A simple object - use these to store "simple" objects that MAY repeat.
std::shared_ptr< Eng3D::Material > material
virtual void draw(const Eng3D::OpenGL::Program &shader, int instances=0) const
#define CXX_THROW(class,...)