3 #include <assimp/cimport.h>
4 #include <assimp/material.h>
5 #include <assimp/mesh.h>
6 #include <assimp/postprocess.h>
7 #include <assimp/scene.h>
11 #include <gmath/gmath.h>
18 #include "opengl/mesh-gl.h"
19 #include "vulkan/mesh-vk.h"
21 #include "opengl/texture-gl.h"
22 #include "vulkan/texture-vk.h"
24 extern bool use_vulkan;
25 static Mesh *load_mesh(const aiScene *scene, unsigned int index);
26 static Material *load_material(const aiScene *ascene, Scene *scene, unsigned int index, const char *tex_fname);
28 static Mat4 aiMatrix2Mat(aiMatrix4x4 t);
29 static void create_object(aiNode *node, Mat4 transform, Scene *scene, const aiScene *ascene);
35 for(size_t i=0; i<meshes.size(); i++)
39 for(size_t i=0; i<materials.size(); i++)
43 for(size_t i=0; i<textures.size(); i++)
47 for(size_t i=0; i<objects.size(); i++)
52 bool Scene::load(const char *fname)
55 /* TODO !!!!!!!!!!!!!!!! flipuvs might need to be removed + fix the cow */
56 unsigned int ai_flags = aiProcessPreset_TargetRealtime_Quality | aiProcess_FlipUVs;
57 const aiScene *scene = aiImportFile(fname, ai_flags);
59 fprintf(stderr, "Failed to import scene: %s\n", fname);
64 for(unsigned int i=0; i<scene->mNumMeshes; i++) {
65 Mesh *mesh = load_mesh(scene, i);
67 fprintf(stderr, "Failed to load mesh no: %d.\n", i);
70 mesh->update_vertex_data();
71 meshes.push_back(mesh);
75 char *tex_path = new char[strlen(fname) + 1];
76 strcpy(tex_path, fname);
77 char *last_slash = strrchr(tex_path, '/');
86 for(unsigned int i=0; i<scene->mNumMaterials; i++) {
87 Material *material = load_material(scene, this, i, tex_path);
89 fprintf(stderr, "Failed to load material no: %d", i);
92 materials.push_back(material);
96 aiNode *node = scene->mRootNode;
97 Mat4 transform = Mat4::identity;
98 create_object(node, transform, this, scene);
102 static Mat4 aiMatrix2Mat(aiMatrix4x4 t)
104 return Mat4(t.a1, t.a2, t.a3, t.a4,
105 t.b1, t.b2, t.b3, t.b4,
106 t.c1, t.c2, t.c3, t.c4,
107 t.d1, t.d2, t.d3, t.d4);
110 static void create_object(aiNode *node, Mat4 parent_transform, Scene *scene, const aiScene *ascene)
113 The 99% of the scenes have 1 mesh per node => for simplicity we only check the 1st one.
114 Also: the 3D models we are going to use for this demo, have flat structure (no hierarchy)
115 but just in case we need to replace them later, we calculate the transform by assuming that we
116 have a node hierarchy. This => that each object's modelling transformation is the
117 product of its local transformation (mTransformation) with the acc parent nodes transformations
120 Mat4 modelling_transform = parent_transform * aiMatrix2Mat(node->mTransformation);
122 if(node->mNumMeshes > 0) {
123 Object *object = new Object;
125 // get the mesh index from node
126 int mesh_idx = node->mMeshes[0];
127 object->mesh = scene->meshes[mesh_idx];
129 // get the material index from the mesh that is assigned to this node
130 aiMesh *amesh = ascene->mMeshes[mesh_idx];
131 object->material = scene->materials[amesh->mMaterialIndex];
133 // set the object's transformation
134 object->transform = modelling_transform;
135 scene->objects.push_back(object);
138 for(unsigned int i=0; i<node->mNumChildren; i++) {
139 create_object(node->mChildren[i], modelling_transform, scene, ascene);
143 static Mesh *load_mesh(const aiScene *scene, unsigned int index)
145 /* load mesh with index from scene using assimp */
146 aiMesh *amesh = scene->mMeshes[index];
148 fprintf(stderr, "Failed to load assimp mesh no: %d.\n", index);
160 mesh->name = std::string(amesh->mName.data);
162 for(unsigned int i=0; i<amesh->mNumVertices; i++) {
164 if(amesh->HasPositions()) {
165 Vec3 vertex = Vec3(amesh->mVertices[i].x, amesh->mVertices[i].y,
166 amesh->mVertices[i].z);
168 mesh->vertices.push_back(vertex);
171 fprintf(stderr, "Mesh has no geometry!\n");
177 if(amesh->HasNormals()) {
178 Vec3 normal = Vec3(amesh->mNormals[i].x, amesh->mNormals[i].y,
179 amesh->mNormals[i].z);
180 mesh->normals.push_back(normal);
183 fprintf(stderr, "Mesh has no normals!\n");
188 /* texture coordinates */
189 if(amesh->mTextureCoords[0]) {
190 Vec2 tex_coord = Vec2(amesh->mTextureCoords[0][i].x, amesh->mTextureCoords[0][i].y);
191 mesh->tex_coords.push_back(tex_coord);
194 printf("mesh has no texture coordinates.\n");
195 mesh->tex_coords.push_back(Vec2(0, 0));
199 // if(amesh->mTangents) {
200 // mesh->which_mask |= MESH_TANGENT;
201 // Vec3 tangent = Vec3(amesh->mTangents[i].x, amesh->mTangents[i].y,
202 // amesh->mTangents[i].z);
203 // mesh->tangents.push_back(tangent);
206 // mesh->tangents.push_back(Vec3(1, 0, 0));
209 /* indices (called faces in assimp) */
210 if(amesh->HasFaces()) {
211 for(unsigned int i=0; i<amesh->mNumFaces; i++) {
212 mesh->indices.push_back(amesh->mFaces[i].mIndices[0]);
213 mesh->indices.push_back(amesh->mFaces[i].mIndices[1]);
214 mesh->indices.push_back(amesh->mFaces[i].mIndices[2]);
218 fprintf(stderr, "No faces found.\n");
220 mesh->mat_idx = amesh->mMaterialIndex;
224 static Material *load_material(const aiScene *ascene, Scene *scene, unsigned int index, const char *tex_path)
226 aiMaterial *amat = ascene->mMaterials[index];
228 fprintf(stderr, "Failed to load material no: %d.\n", index);
232 Material *mat = new Material;
237 amat->Get(AI_MATKEY_NAME, name);
238 mat->name = std::string(name.data);
241 aiGetMaterialColor(amat, AI_MATKEY_COLOR_DIFFUSE, &color);
242 mat->diffuse = Vec3(color.r, color.g, color.b);
244 aiGetMaterialColor(amat, AI_MATKEY_COLOR_SPECULAR, &color);
246 // aiGetMaterialFloat(amat, AI_MATKEY_SHININESS_STRENGTH, &spstr);
247 // mat->specular = spstr * Vec3(color.r, color.g, color.b);
248 mat->specular = Vec3(color.r, color.g, color.b);
250 aiGetMaterialFloat(amat, AI_MATKEY_SHININESS, &mat->shininess);
251 mat->shininess /= 128.0;
253 printf("shininess: %f\n", mat->shininess);
255 if(aiGetMaterialString(amat, AI_MATKEY_TEXTURE_DIFFUSE(0), &tex_name) == aiReturn_SUCCESS) {
256 /* different scene objects might use the same texture, we shouldn't store it twice*/
258 std::string tex_fname = tex_path ? std::string(tex_path) + "/" + tex_name.data : tex_name.data;
260 mat->dtex = scene->find_texture(tex_fname.c_str());
262 printf("!mat->dtex\n");
264 mat->dtex = new TextureVK;
267 mat->dtex = new TextureGL;
269 if(!mat->dtex->load(tex_fname.c_str())) {
270 fprintf(stderr, "Failed to load texture data: %s.\n", tex_fname.c_str());
275 mat->dtex->name = std::string(tex_fname.c_str());
277 printf("Successfully loaded texture: %s\n", tex_fname.c_str());
278 scene->textures.push_back(mat->dtex);
285 Mesh *Scene::find_mesh(const char *name)
287 for(size_t i=0; i<meshes.size(); i++) {
288 if(meshes[i]->name == name) {
292 fprintf(stderr, "Mesh %s not found.\n", name);
296 Material *Scene::find_material(const char *name)
298 for(size_t i=0; i<materials.size(); i++) {
299 if(materials[i]->name == name) {
303 fprintf(stderr, "Material %s not found.\n", name);
307 Texture *Scene::find_texture(const char *name) {
308 for(size_t i=0; i<textures.size(); i++) {
309 if(textures[i]->name == name) {
313 fprintf(stderr, "Texture %s not found.\n", name);