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>
20 static Mesh *load_mesh(const aiScene *scene, unsigned int index);
21 static Material *load_material(const aiScene *ascene, Scene *scene, unsigned int index, const char *tex_fname);
23 static Mat4 aiMatrix2Mat(aiMatrix4x4 t);
24 static void create_object(aiNode *node, Mat4 transform, Scene *scene, const aiScene *ascene);
30 for(size_t i=0; i<meshes.size(); i++)
34 for(size_t i=0; i<materials.size(); i++)
38 for(size_t i=0; i<textures.size(); i++)
42 for(size_t i=0; i<objects.size(); i++)
47 bool Scene::load(const char *fname)
50 /* TODO !!!!!!!!!!!!!!!! flipuvs might need to be removed + fix the cow */
51 unsigned int ai_flags = aiProcessPreset_TargetRealtime_Quality | aiProcess_FlipUVs;
52 const aiScene *scene = aiImportFile(fname, ai_flags);
54 fprintf(stderr, "Failed to import scene: %s\n", fname);
59 for(unsigned int i=0; i<scene->mNumMeshes; i++) {
60 Mesh *mesh = load_mesh(scene, i);
62 fprintf(stderr, "Failed to load mesh no: %d.\n", i);
65 mesh->update_vertex_data();
66 meshes.push_back(mesh);
70 char *tex_path = new char[strlen(fname) + 1];
71 strcpy(tex_path, fname);
72 char *last_slash = strrchr(tex_path, '/');
81 for(unsigned int i=0; i<scene->mNumMaterials; i++) {
82 Material *material = load_material(scene, this, i, tex_path);
84 fprintf(stderr, "Failed to load material no: %d", i);
87 materials.push_back(material);
91 aiNode *node = scene->mRootNode;
92 Mat4 transform = Mat4::identity;
93 create_object(node, transform, this, scene);
97 static Mat4 aiMatrix2Mat(aiMatrix4x4 t)
99 return Mat4(t.a1, t.a2, t.a3, t.a4,
100 t.b1, t.b2, t.b3, t.b4,
101 t.c1, t.c2, t.c3, t.c4,
102 t.d1, t.d2, t.d3, t.d4);
105 static void create_object(aiNode *node, Mat4 parent_transform, Scene *scene, const aiScene *ascene)
108 The 99% of the scenes have 1 mesh per node => for simplicity we only check the 1st one.
109 Also: the 3D models we are going to use for this demo, have flat structure (no hierarchy)
110 but just in case we need to replace them later, we calculate the transform by assuming that we
111 have a node hierarchy. This => that each object's modelling transformation is the
112 product of its local transformation (mTransformation) with the acc parent nodes transformations
115 Mat4 modelling_transform = parent_transform * aiMatrix2Mat(node->mTransformation);
117 if(node->mNumMeshes > 0) {
118 Object *object = new Object;
120 // get the mesh index from node
121 int mesh_idx = node->mMeshes[0];
122 object->mesh = scene->meshes[mesh_idx];
124 // get the material index from the mesh that is assigned to this node
125 aiMesh *amesh = ascene->mMeshes[mesh_idx];
126 object->material = scene->materials[amesh->mMaterialIndex];
128 // set the object's transformation
129 object->transform = modelling_transform;
130 scene->objects.push_back(object);
133 for(unsigned int i=0; i<node->mNumChildren; i++) {
134 create_object(node->mChildren[i], modelling_transform, scene, ascene);
138 static Mesh *load_mesh(const aiScene *scene, unsigned int index)
140 /* load mesh with index from scene using assimp */
141 aiMesh *amesh = scene->mMeshes[index];
143 fprintf(stderr, "Failed to load assimp mesh no: %d.\n", index);
147 Mesh *mesh = gfx_create_mesh();
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 printf("mesh has no texture coordinates.\n");
183 mesh->tex_coords.push_back(Vec2(0, 0));
187 // if(amesh->mTangents) {
188 // mesh->which_mask |= MESH_TANGENT;
189 // Vec3 tangent = Vec3(amesh->mTangents[i].x, amesh->mTangents[i].y,
190 // amesh->mTangents[i].z);
191 // mesh->tangents.push_back(tangent);
194 // mesh->tangents.push_back(Vec3(1, 0, 0));
197 /* indices (called faces in assimp) */
198 if(amesh->HasFaces()) {
199 for(unsigned int i=0; i<amesh->mNumFaces; i++) {
200 mesh->indices.push_back(amesh->mFaces[i].mIndices[0]);
201 mesh->indices.push_back(amesh->mFaces[i].mIndices[1]);
202 mesh->indices.push_back(amesh->mFaces[i].mIndices[2]);
206 fprintf(stderr, "No faces found.\n");
211 static Material *load_material(const aiScene *ascene, Scene *scene, unsigned int index, const char *tex_path)
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);
235 mat->specular = Vec3(color.r, color.g, color.b);
237 aiGetMaterialFloat(amat, AI_MATKEY_SHININESS, &mat->shininess);
238 mat->shininess /= 128.0;
240 printf("shininess: %f\n", mat->shininess);
242 if(aiGetMaterialString(amat, AI_MATKEY_TEXTURE_DIFFUSE(0), &tex_name) == aiReturn_SUCCESS) {
243 /* different scene objects might use the same texture, we shouldn't store it twice*/
245 std::string tex_fname = tex_path ? std::string(tex_path) + "/" + tex_name.data : tex_name.data;
247 mat->dtex = scene->find_texture(tex_fname.c_str());
249 mat->dtex = gfx_create_texture();
251 if(!mat->dtex->load(tex_fname.c_str())) {
252 fprintf(stderr, "Failed to load texture data: %s.\n", tex_fname.c_str());
257 mat->dtex->name = std::string(tex_fname.c_str());
259 printf("Successfully loaded texture: %s\n", tex_fname.c_str());
260 scene->textures.push_back(mat->dtex);
267 Mesh *Scene::find_mesh(const char *name)
269 for(size_t i=0; i<meshes.size(); i++) {
270 if(meshes[i]->name == name) {
274 fprintf(stderr, "Mesh %s not found.\n", name);
278 Material *Scene::find_material(const char *name)
280 for(size_t i=0; i<materials.size(); i++) {
281 if(materials[i]->name == name) {
285 fprintf(stderr, "Material %s not found.\n", name);
289 Texture *Scene::find_texture(const char *name)
291 for(size_t i=0; i<textures.size(); i++) {
292 if(textures[i]->name == name) {