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 mesh->update_vertex_data();
70 meshes.push_back(mesh);
74 for(unsigned int i=0; i<scene->mNumMaterials; ++i) {
75 Material *material = load_material(scene, this, i);
77 fprintf(stderr, "Failed to load material no: %d", i);
80 materials.push_back(material);
84 aiNode *node = scene->mRootNode;
85 Mat4 transform = Mat4::identity;
86 create_object(node, transform, this, scene);
90 static Mat4 aiMatrix2Mat(aiMatrix4x4 t)
92 return Mat4(t.a1, t.a2, t.a3, t.a4,
93 t.b1, t.b2, t.b3, t.b4,
94 t.c1, t.c2, t.c3, t.c4,
95 t.d1, t.d2, t.d3, t.d4);
98 static void create_object(aiNode *node, Mat4 parent_transform, Scene *scene, const aiScene *ascene)
101 The 99% of the scenes have 1 mesh per node => for simplicity we only check the 1st one.
102 Also: the 3D models we are going to use for this demo, have flat structure (no hierarchy)
103 but just in case we need to replace them later, we calculate the transform by assuming that we
104 have a node hierarchy. This => that each object's modelling transformation is the
105 product of its local transformation (mTransformation) with the acc parent nodes transformations
108 Mat4 modelling_transform = parent_transform * aiMatrix2Mat(node->mTransformation);
110 if(node->mNumMeshes > 0) {
111 Object *object = new Object;
113 // get the mesh index from node
114 int mesh_idx = node->mMeshes[0];
115 object->mesh = scene->meshes[mesh_idx];
117 // get the material index from the mesh that is assigned to this node
118 aiMesh *amesh = ascene->mMeshes[mesh_idx];
119 object->material = scene->materials[amesh->mMaterialIndex];
121 // set the object's transformation
122 object->transform = modelling_transform;
123 scene->objects.push_back(object);
126 for(unsigned int i=0; i<node->mNumChildren; ++i) {
127 create_object(node->mChildren[i], modelling_transform, scene, ascene);
131 static Mesh *load_mesh(const aiScene *scene, unsigned int index)
133 /* load mesh with index from scene using assimp */
134 aiMesh *amesh = scene->mMeshes[index];
136 fprintf(stderr, "Failed to load assimp mesh no: %d.\n", index);
148 mesh->name = std::string(amesh->mName.data);
150 for(unsigned int i=0; i<amesh->mNumVertices; ++i) {
152 if(amesh->HasPositions()) {
153 Vec3 vertex = Vec3(amesh->mVertices[i].x, amesh->mVertices[i].y,
154 amesh->mVertices[i].z);
156 mesh->vertices.push_back(vertex);
159 fprintf(stderr, "Mesh has no geometry!\n");
165 if(amesh->HasNormals()) {
166 Vec3 normal = Vec3(amesh->mNormals[i].x, amesh->mNormals[i].y,
167 amesh->mNormals[i].z);
168 mesh->normals.push_back(normal);
171 fprintf(stderr, "Mesh has no normals!\n");
176 /* texture coordinates */
177 if(amesh->mTextureCoords[0]) {
178 Vec2 tex_coord = Vec2(amesh->mTextureCoords[0][i].x, amesh->mTextureCoords[0][i].y);
179 mesh->tex_coords.push_back(tex_coord);
182 mesh->tex_coords.push_back(Vec2(0, 0));
186 // if(amesh->mTangents) {
187 // mesh->which_mask |= MESH_TANGENT;
188 // Vec3 tangent = Vec3(amesh->mTangents[i].x, amesh->mTangents[i].y,
189 // amesh->mTangents[i].z);
190 // mesh->tangents.push_back(tangent);
193 // mesh->tangents.push_back(Vec3(1, 0, 0));
196 /* indices (called faces in assimp) */
197 if(amesh->HasFaces()) {
198 for(unsigned int i=0; i<amesh->mNumFaces; ++i) {
199 mesh->indices.push_back(amesh->mFaces[i].mIndices[0]);
200 mesh->indices.push_back(amesh->mFaces[i].mIndices[1]);
201 mesh->indices.push_back(amesh->mFaces[i].mIndices[2]);
205 fprintf(stderr, "No faces found.\n");
207 mesh->mat_idx = amesh->mMaterialIndex;
211 static Material *load_material(const aiScene *ascene, Scene *scene, unsigned int index)
213 aiMaterial *amat = ascene->mMaterials[index];
215 fprintf(stderr, "Failed to load material no: %d.\n", index);
219 Material *mat = new Material;
224 amat->Get(AI_MATKEY_NAME, name);
225 mat->name = std::string(name.data);
228 aiGetMaterialColor(amat, AI_MATKEY_COLOR_DIFFUSE, &color);
229 mat->diffuse = Vec3(color.r, color.g, color.b);
231 aiGetMaterialColor(amat, AI_MATKEY_COLOR_SPECULAR, &color);
233 aiGetMaterialFloat(amat, AI_MATKEY_SHININESS_STRENGTH, &spstr);
234 mat->specular = spstr * Vec3(color.r, color.g, color.b);
236 aiGetMaterialFloat(amat, AI_MATKEY_SHININESS, &mat->shininess);
239 if(aiGetMaterialString(amat, AI_MATKEY_TEXTURE_DIFFUSE(0), &tex_name) == aiReturn_SUCCESS) {
240 /* different scene objects might use the same texture, we shouldn't store it twice*/
241 //mat->dtex = scene->find_texture(tex_name.data);
244 mat->dtex = new TextureVK;
247 mat->dtex = new TextureGL;
249 if(!mat->dtex->load(tex_name.data)) {
250 fprintf(stderr, "Failed to load texture data: %s.\n", tex_name.data);
254 scene->textures.push_back(mat->dtex);