Added a new function `blinn_phong_specular_exponent_to_roughness` in `BSDF.h` to convert a specular exponent to roughness. Added a `textures` member to the `shading_context_t` structure in `Material.h` for passing texture information during shading. Added a new member `textures` in the `light_shading_context_t` structure in `Light.h` to hold texture information. Added inline functions in `Texture.h` for handling texture entities, including `invalid_texture_entity`, `is_texture_entity_valid`, and `get_texture`. Changed the texture-related members in `simple_lit_properties_t` in `SimpleLit.h` from pointers to `texture_entity_t` to better manage texture entities. Changed the `sample_material_bsdf` and `sample_material_bsdf_pdf` functions in `Material.h` to accept a `shading_context_t` instead of individual parameters. Changed the `mesh_load` function in `Mesh.c` to use the new roughness calculation and texture entity handling. Changed the `path_trace` function in `PathTracing.c` to use the new structure and functions for handling materials and textures. Refactored the `sample_material_bsdf` and `sample_material_bsdf_pdf` functions in `Material.c` to utilize the new `shading_context_t` structure. Updated the `material_collection_init` function in `Material.h` to reflect changes in the material sampling functions. Updated the `evaluate_bsdf_directional` and `evaluate_bsdf_const_sky` functions to use the new shading context structure. Adjusted the `simple_lit_data_default` function in `SimpleLit.c` to work with the new texture handling approach. Added texture entity handling in `Texture.c` for managing invalid texture entities.
152 lines
4.9 KiB
C
152 lines
4.9 KiB
C
#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;
|
|
}
|