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);
149 for(unsigned int i=0; i<amesh->mNumVertices; ++i) {
151 if(amesh->HasPositions()) {
152 Vec3 vertex = Vec3(amesh->mVertices[i].x, amesh->mVertices[i].y,
153 amesh->mVertices[i].z);
155 mesh->vertices.push_back(vertex);
158 fprintf(stderr, "Mesh has no geometry!\n");
164 if(amesh->HasNormals()) {
165 Vec3 normal = Vec3(amesh->mNormals[i].x, amesh->mNormals[i].y,
166 amesh->mNormals[i].z);
167 mesh->normals.push_back(normal);
170 fprintf(stderr, "Mesh has no normals!\n");
175 /* texture coordinates */
176 if(amesh->mTextureCoords[0]) {
177 Vec2 tex_coord = Vec2(amesh->mTextureCoords[0][i].x, amesh->mTextureCoords[0][i].y);
178 mesh->tex_coords.push_back(tex_coord);
181 mesh->tex_coords.push_back(Vec2(0, 0));
185 // if(amesh->mTangents) {
186 // mesh->which_mask |= MESH_TANGENT;
187 // Vec3 tangent = Vec3(amesh->mTangents[i].x, amesh->mTangents[i].y,
188 // amesh->mTangents[i].z);
189 // mesh->tangents.push_back(tangent);
192 // mesh->tangents.push_back(Vec3(1, 0, 0));
195 /* indices (called faces in assimp) */
196 if(amesh->HasFaces()) {
197 for(unsigned int i=0; i<amesh->mNumFaces; ++i) {
198 mesh->indices.push_back(amesh->mFaces[i].mIndices[0]);
199 mesh->indices.push_back(amesh->mFaces[i].mIndices[1]);
200 mesh->indices.push_back(amesh->mFaces[i].mIndices[2]);
204 fprintf(stderr, "No faces found.\n");
206 mesh->mat_idx = amesh->mMaterialIndex;
210 static Material *load_material(const aiScene *ascene, Scene *scene, unsigned int index)
212 aiMaterial *amat = ascene->mMaterials[index];
214 fprintf(stderr, "Failed to load material no: %d.\n", index);
218 Material *mat = new Material;
223 amat->Get(AI_MATKEY_NAME, name);
224 mat->name = std::string(name.data);
227 aiGetMaterialColor(amat, AI_MATKEY_COLOR_DIFFUSE, &color);
228 mat->diffuse = Vec3(color.r, color.g, color.b);
230 aiGetMaterialColor(amat, AI_MATKEY_COLOR_SPECULAR, &color);
232 aiGetMaterialFloat(amat, AI_MATKEY_SHININESS_STRENGTH, &spstr);
233 mat->specular = spstr * Vec3(color.r, color.g, color.b);
235 aiGetMaterialFloat(amat, AI_MATKEY_SHININESS, &mat->shininess);
238 if(aiGetMaterialString(amat, AI_MATKEY_TEXTURE_DIFFUSE(0), &tex_name) == aiReturn_SUCCESS) {
239 /* different scene objects might use the same texture, we shouldn't store it twice*/
240 //mat->dtex = scene->find_texture(tex_name.data);
243 mat->dtex = new TextureVK;
246 mat->dtex = new TextureGL;
248 if(!mat->dtex->load(tex_name.data)) {
249 fprintf(stderr, "Failed to load texture data: %s.\n", tex_name.data);
253 scene->textures.push_back(mat->dtex);