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);
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 unsigned int ai_flags = aiProcessPreset_TargetRealtime_Quality;
56 const aiScene *scene = aiImportFile(fname, ai_flags);
58 fprintf(stderr, "Failed to import scene: %s\n", fname);
63 for(unsigned int i=0; i<scene->mNumMeshes; ++i) {
64 Mesh *mesh = load_mesh(scene, i);
66 fprintf(stderr, "Failed to load mesh no: %d.\n", i);
69 meshes.push_back(mesh);
73 for(unsigned int i=0; i<scene->mNumMaterials; ++i) {
74 Material *material = load_material(scene, this, i);
76 fprintf(stderr, "Failed to load material no: %d", i);
79 materials.push_back(material);
83 aiNode *node = scene->mRootNode;
84 Mat4 transform = Mat4::identity;
85 create_object(node, transform, this, scene);
89 static Mat4 aiMatrix2Mat(aiMatrix4x4 t)
91 return Mat4(t.a1, t.a2, t.a3, t.a4,
92 t.b1, t.b2, t.b3, t.b4,
93 t.c1, t.c2, t.c3, t.c4,
94 t.d1, t.d2, t.d3, t.d4);
97 static void create_object(aiNode *node, Mat4 parent_transform, Scene *scene, const aiScene *ascene)
100 The 99% of the scenes have 1 mesh per node => for simplicity we only check the 1st one.
101 Also: the 3D models we are going to use for this demo, have flat structure (no hierarchy)
102 but just in case we need to replace them later, we calculate the transform by assuming that we
103 have a node hierarchy. This => that each object's modelling transformation is the
104 product of its local transformation (mTransformation) with the acc parent nodes transformations
107 Mat4 modelling_transform = parent_transform * aiMatrix2Mat(node->mTransformation);
109 if(node->mNumMeshes > 0) {
110 Object *object = new Object;
112 // get the mesh index from node
113 int mesh_idx = node->mMeshes[0];
114 object->mesh = scene->meshes[mesh_idx];
116 // get the material index from the mesh that is assigned to this node
117 aiMesh *amesh = ascene->mMeshes[mesh_idx];
118 object->material = scene->materials[amesh->mMaterialIndex];
120 // set the object's transformation
121 object->transform = modelling_transform;
122 scene->objects.push_back(object);
125 for(unsigned int i=0; i<node->mNumChildren; ++i) {
126 create_object(node->mChildren[i], modelling_transform, scene, ascene);
130 static Mesh *load_mesh(const aiScene *scene, unsigned int index)
132 /* load mesh with index from scene using assimp */
133 aiMesh *amesh = scene->mMeshes[index];
135 fprintf(stderr, "Failed to load assimp mesh no: %d.\n", index);
147 mesh->name = std::string(amesh->mName.data);
148 mesh->which_mask = 0;
150 for(unsigned int i=0; i<amesh->mNumVertices; ++i) {
152 if(amesh->HasPositions()) {
153 mesh->which_mask |= MESH_VERTEX;
154 Vec3 vertex = Vec3(amesh->mVertices[i].x, amesh->mVertices[i].y,
155 amesh->mVertices[i].z);
157 mesh->vertices.push_back(vertex);
160 fprintf(stderr, "Mesh has no geometry!\n");
166 if(amesh->HasNormals()) {
167 mesh->which_mask |= MESH_NORMAL;
168 Vec3 normal = Vec3(amesh->mNormals[i].x, amesh->mNormals[i].y,
169 amesh->mNormals[i].z);
170 mesh->normals.push_back(normal);
173 fprintf(stderr, "Mesh has no normals!\n");
178 /* texture coordinates */
179 if(amesh->mTextureCoords[0]) {
180 mesh->which_mask |= MESH_TEXTURE;
181 Vec2 tex_coord = Vec2(amesh->mTextureCoords[0][i].x, amesh->mTextureCoords[0][i].y);
182 mesh->tex_coords.push_back(tex_coord);
185 mesh->tex_coords.push_back(Vec2(0, 0));
189 if(amesh->mTangents) {
190 mesh->which_mask |= MESH_TANGENT;
191 Vec3 tangent = Vec3(amesh->mTangents[i].x, amesh->mTangents[i].y,
192 amesh->mTangents[i].z);
193 mesh->tangents.push_back(tangent);
196 mesh->tangents.push_back(Vec3(1, 0, 0));
199 /* indices (called faces in assimp) */
200 if(amesh->HasFaces()) {
201 mesh->which_mask |= MESH_INDEX;
202 for(unsigned int i=0; i<amesh->mNumFaces; ++i) {
203 mesh->indices.push_back(amesh->mFaces[i].mIndices[0]);
204 mesh->indices.push_back(amesh->mFaces[i].mIndices[1]);
205 mesh->indices.push_back(amesh->mFaces[i].mIndices[2]);
209 fprintf(stderr, "No faces found.\n");
211 mesh->mat_idx = amesh->mMaterialIndex;
215 static Material *load_material(const aiScene *ascene, Scene *scene, unsigned int index)
217 aiMaterial *amat = ascene->mMaterials[index];
219 fprintf(stderr, "Failed to load material no: %d.\n", index);
223 Material *mat = new Material;
228 amat->Get(AI_MATKEY_NAME, name);
229 mat->name = std::string(name.data);
232 aiGetMaterialColor(amat, AI_MATKEY_COLOR_DIFFUSE, &color);
233 mat->diffuse = Vec3(color.r, color.g, color.b);
235 aiGetMaterialColor(amat, AI_MATKEY_COLOR_SPECULAR, &color);
237 aiGetMaterialFloat(amat, AI_MATKEY_SHININESS_STRENGTH, &spstr);
238 mat->specular = spstr * Vec3(color.r, color.g, color.b);
240 aiGetMaterialFloat(amat, AI_MATKEY_SHININESS, &mat->shininess);
243 if(aiGetMaterialString(amat, AI_MATKEY_TEXTURE_DIFFUSE(0), &tex_name) == aiReturn_SUCCESS) {
244 /* different scene objects might use the same texture, we shouldn't store it twice*/
245 //mat->dtex = scene->find_texture(tex_name.data);
248 mat->dtex = new TextureVK;
251 mat->dtex = new TextureGL;
253 if(!mat->dtex->load(tex_name.data)) {
254 fprintf(stderr, "Failed to load texture data: %s.\n", tex_name.data);
258 scene->textures.push_back(mat->dtex);