#include "Geometry/Mesh.h" #include "Common/String.h" #include "Material/SimpleLit.h" #include "assimp/cimport.h" #include "assimp/scene.h" #include "assimp/postprocess.h" static texture_entity_t load_material_texture(const struct aiMaterial* material, enum aiTextureType type, const char* filename, scene_t* scene) { struct aiString path; if (AI_SUCCESS == aiGetMaterialTexture(material, type, 0, &path, NULL, NULL, NULL, NULL, NULL, NULL)) { if (!is_absolute_path(path.data)) { char directory[1024]; get_path_directory(filename, directory, 1024); char image_path[1024]; memcpy(image_path, path.data, 1024); string_join(directory, image_path, path.data, 1024); } return texture_load(path.data, true, UINT_8, &scene->textures); } return invalid_texture_entity(); } mesh_entity_t mesh_load(const char* filename, scene_t* scene) { mesh_entity_t entity = {0}; const struct aiScene* mesh_scene = aiImportFile(filename, aiProcessPreset_TargetRealtime_Quality); if (mesh_scene == NULL) { perror(aiGetErrorString()); return entity; } entity.triangle_id = scene->triangles.count; entity.material_id = scene->materials.count; for (uint32_t i = 0; i < mesh_scene->mNumMaterials; i++) { const struct aiMaterial* src = mesh_scene->mMaterials[i]; struct aiColor4D base_color = {0.73f}; aiGetMaterialColor(src, AI_MATKEY_COLOR_DIFFUSE, &base_color); float roughness = 0.75f; aiGetMaterialFloat(src, AI_MATKEY_ROUGHNESS_FACTOR, &roughness); float metallic = 0.0f; aiGetMaterialFloat(src, AI_MATKEY_METALLIC_FACTOR, &metallic); texture_entity_t albedo_entity = load_material_texture(src, aiTextureType_DIFFUSE, filename, scene); texture_entity_t normal_entity = load_material_texture(src, aiTextureType_NORMALS, filename, scene); texture_entity_t roughness_entity = load_material_texture(src, aiTextureType_DIFFUSE_ROUGHNESS, filename, scene); texture_entity_t metallic_entity = load_material_texture(src, aiTextureType_METALNESS, filename, scene); simple_lit_properties_t prop = { .albedo = {base_color.r, base_color.g, base_color.b}, .roughness = roughness, .metallic = metallic, .albedo_texture = albedo_entity, .normal_texture = normal_entity, .roughness_texture = roughness_entity, .metallic_texture = metallic_entity, }; material_create_simple_lit_default(&prop, &scene->materials); entity.material_count++; } for (uint32_t i = 0; i < mesh_scene->mNumMeshes; i++) { const struct aiMesh* mesh = mesh_scene->mMeshes[i]; //TODO: Handle all primitive types, not just triangles if (mesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE) { continue; } bool has_uv = mesh->mTextureCoords[0] != NULL && mesh->mNumUVComponents[0] >= 2; for (uint32_t j = 0; j < mesh->mNumFaces; j++) { const struct aiFace* face = &mesh->mFaces[j]; if (face->mNumIndices != 3) { continue; } uint32_t index0 = face->mIndices[0]; uint32_t index1 = face->mIndices[1]; uint32_t index2 = face->mIndices[2]; vertex_t vertices[3] = {0}; for (uint32_t k = 0; k < 3; k++) { vertices[k].position = (vec3s){mesh->mVertices[face->mIndices[k]].x, mesh->mVertices[face->mIndices[k]].y, mesh->mVertices[face->mIndices[k]].z}; vertices[k].normal = (vec3s){mesh->mNormals[face->mIndices[k]].x, mesh->mNormals[face->mIndices[k]].y, mesh->mNormals[face->mIndices[k]].z}; vertices[k].tangent = (vec3s){mesh->mTangents[face->mIndices[k]].x, mesh->mTangents[face->mIndices[k]].y, mesh->mTangents[face->mIndices[k]].z}; if (has_uv) { vertices[k].uv = (vec2s){mesh->mTextureCoords[0][face->mIndices[k]].x, mesh->mTextureCoords[0][face->mIndices[k]].y}; } } triangle_create(vertices[0], vertices[1], vertices[2], entity.material_id + mesh->mMaterialIndex, &scene->triangles); entity.triangle_count++; } } aiReleaseImport(mesh_scene); return entity; }