#include "Geometry/Mesh.h" #include "ALgorithm/BSDF.h" #include "Common/String.h" #include "Material/SimpleLit.h" #include "assimp/cimport.h" #include "assimp/scene.h" #include "assimp/postprocess.h" 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; aiGetMaterialColor(src, AI_MATKEY_COLOR_DIFFUSE, &base_color); float roughness = 0.5f; aiGetMaterialFloat(src, AI_MATKEY_SHININESS, &roughness); roughness = blinn_phong_specular_exponent_to_roughness(roughness); texture_entity_t albedo_entity = invalid_texture_entity(); if (aiGetMaterialTextureCount(src, aiTextureType_DIFFUSE) > 0) { struct aiString path; if (AI_SUCCESS == aiGetMaterialTexture(src, aiTextureType_DIFFUSE, 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); } texture_entity_t entity = texture_load(path.data, true, &scene->textures); if (entity.id != INVALID_TEXTURE_ID) { albedo_entity = entity; } } } simple_lit_properties_t prop = { .albedo = {base_color.r, base_color.g, base_color.b}, .roughness = roughness, .metallic = 0.0f, .albedo_texture = albedo_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 index1 = face->mIndices[0]; uint32_t index2 = face->mIndices[1]; uint32_t index3 = face->mIndices[2]; vec3s point1 = { mesh->mVertices[index1].x, mesh->mVertices[index1].y, mesh->mVertices[index1].z }; vec3s point2 = { mesh->mVertices[index2].x, mesh->mVertices[index2].y, mesh->mVertices[index2].z }; vec3s point3 = { mesh->mVertices[index3].x, mesh->mVertices[index3].y, mesh->mVertices[index3].z }; vec2s uv1 = {0.0f, 0.0f}; vec2s uv2 = {0.0f, 0.0f}; vec2s uv3 = {0.0f, 0.0f}; if (has_uv) { struct aiVector3D const* tc = mesh->mTextureCoords[0]; uv1.x = tc[index1].x; uv1.y = tc[index1].y; uv2.x = tc[index2].x; uv2.y = tc[index2].y; uv3.x = tc[index3].x; uv3.y = tc[index3].y; } vec3s normal1 = { mesh->mNormals[index1].x, mesh->mNormals[index1].y, mesh->mNormals[index1].z }; vec3s normal2 = { mesh->mNormals[index2].x, mesh->mNormals[index2].y, mesh->mNormals[index2].z }; vec3s normal3 = { mesh->mNormals[index3].x, mesh->mNormals[index3].y, mesh->mNormals[index3].z }; vertex_t vertex1 = {.position = point1, .normal = normal1, .uv = uv1}; vertex_t vertex2 = {.position = point2, .normal = normal2, .uv = uv2}; vertex_t vertex3 = {.position = point3, .normal = normal3, .uv = uv3}; triangle_create(vertex1, vertex2, vertex3, entity.material_id + mesh->mMaterialIndex, &scene->triangles); entity.triangle_count++; } } aiReleaseImport(mesh_scene); return entity; }