Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 1 addition & 23 deletions asset/json/scene_simple.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,6 @@
"name": "SceneSimple",
"default_texture_name": "albedo",
"materials": [
{
"name": "SceneSimpleMaterial",
"program_name": "SceneSimpleProgram",
"texture_names": [
"apple_texture"
],
"inner_names": [
"Color"
]
},
{
"name": "CubeMapMaterial",
"program_name": "CubeMapProgram",
Expand Down Expand Up @@ -99,17 +89,6 @@
"negative_z": "asset/cubemap/positive_z.png"
}
},
{
"name": "apple_texture",
"cubemap": "false",
"pixel_element_size": {
"value": "BYTE"
},
"pixel_structure": {
"value": "RGB"
},
"file_name": "asset/apple/color.jpg"
},
{
"name": "albedo",
"cubemap": "false",
Expand Down Expand Up @@ -203,8 +182,7 @@
{
"name": "AppleMesh",
"parent": "mesh_holder",
"file_name": "apple.obj",
"material_name": "SceneSimpleMaterial",
"obj_file": "asset/model/apple.obj",
"render_time_enum": "SCENE_RENDER_TIME"
}
],
Expand Down
9 changes: 9 additions & 0 deletions include/frame/file/file_system.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
#pragma once

#include <filesystem>
#include <vector>

namespace frame::file
{

/**
* @brief Find the path to a file, this will avoid build directory.
* @param file: Basic search pattern for your file "asset/json/test.json".
* @return Full path to the file.
*/
std::filesystem::path FindFile(
std::filesystem::path file,
const std::vector<std::filesystem::path>& paths);
/**
* @brief Find the path to a file, this will avoid build directory.
* @param file: Basic search pattern for your file "asset/json/test.json".
Expand Down
53 changes: 53 additions & 0 deletions include/frame/file/mtl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#pragma once

#include <filesystem>
#include <map>
#include <string>
#include <vector>

#include <glm/glm.hpp>

#include "frame/logger.h"

namespace frame::file
{

// Structure to hold the material properties from the MTL file.
struct MtlMaterial
{
std::string name;
std::string ambient_str;
glm::vec4 ambient_vec4;
std::string diffuse_str;
glm::vec4 diffuse_vec4;
std::string displacement_str;
std::string emmissive_str;
std::string metallic_str;
float metallic_val;
std::string normal_str;
std::string roughness_str;
float roughness_val;
std::string sheen_str;
float sheen_val;
};

// Mtl class to parse and store material information from a .mtl file.
class Mtl
{
public:
// Constructor that takes the path to the .mtl file and a list of search
// paths for textures.
Mtl(const std::filesystem::path& path,
const std::vector<std::filesystem::path>& search_paths = {});
// Get a material by name.
const MtlMaterial& GetMaterial(const std::string& name) const;
// Get all materials.
const std::vector<MtlMaterial>& GetMaterials() const;

private:
std::vector<MtlMaterial> materials_;
std::map<std::string, std::size_t> material_name_map_;
Logger& logger_ = Logger::GetInstance();
};

} // End namespace frame::file.
2 changes: 2 additions & 0 deletions src/frame/file/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ add_library(FrameFile
STATIC
${CMAKE_CURRENT_SOURCE_DIR}/../../../include/frame/file/file_system.h
${CMAKE_CURRENT_SOURCE_DIR}/../../../include/frame/file/image_stb.h
${CMAKE_CURRENT_SOURCE_DIR}/../../../include/frame/file/mtl.h
file_system.cpp
image.cpp
image.h
mtl.cpp
obj.cpp
obj.h
ply.cpp
Expand Down
15 changes: 15 additions & 0 deletions src/frame/file/file_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,21 @@ std::filesystem::path FindDirectory(std::filesystem::path file)
});
}

std::filesystem::path FindFile(
std::filesystem::path file,
const std::vector<std::filesystem::path>& paths)
{
for (const auto& path : paths)
{
auto full_path = path / file;
if (std::filesystem::is_regular_file(full_path))
{
return full_path;
}
}
return FindFile(file);
}

std::filesystem::path FindFile(std::filesystem::path file)
{
return FindElement(file, [](const std::filesystem::path& p) {
Expand Down
140 changes: 140 additions & 0 deletions src/frame/file/mtl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#include "frame/file/mtl.h"

#include <fstream>
#include <sstream>

#include <glm/glm.hpp>

#include "frame/file/file_system.h"

namespace frame::file
{

Mtl::Mtl(const std::filesystem::path& path,
const std::vector<std::filesystem::path>& search_paths)
{
std::ifstream file(path);
if (!file.is_open())
{
throw std::runtime_error(
std::format("Could not open file: {}", path.string()));
}

std::string line;
MtlMaterial* current_material = nullptr;

while (std::getline(file, line))
{
std::istringstream iss(line);
std::string keyword;
iss >> keyword;

if (keyword == "newmtl")
{
std::string name;
iss >> name;
materials_.emplace_back();
current_material = &materials_.back();
current_material->name = name;
material_name_map_[name] = materials_.size() - 1;
}
else if (current_material)
{
if (keyword == "map_Ka")
{
std::string texture_path;
iss >> texture_path;
current_material->ambient_str =
FindFile(texture_path, search_paths).string();
}
else if (keyword == "Ka")
{
iss >> current_material->ambient_vec4.r >>
current_material->ambient_vec4.g >>
current_material->ambient_vec4.b;
}
else if (keyword == "map_Kd")
{
std::string texture_path;
iss >> texture_path;
current_material->diffuse_str =
FindFile(texture_path, search_paths).string();
}
else if (keyword == "Kd")
{
iss >> current_material->diffuse_vec4.r >>
current_material->diffuse_vec4.g >>
current_material->diffuse_vec4.b;
}
else if (keyword == "map_disp" || keyword == "disp")
{
std::string texture_path;
iss >> texture_path;
current_material->displacement_str =
FindFile(texture_path, search_paths).string();
}
else if (keyword == "map_Ke" || keyword == "Ke")
{
std::string texture_path;
iss >> texture_path;
current_material->emmissive_str =
FindFile(texture_path, search_paths).string();
}
else if (keyword == "map_Pm" || keyword == "Pm")
{
std::string texture_path;
iss >> texture_path;
current_material->metallic_str =
FindFile(texture_path, search_paths).string();
}
else if (keyword == "refl")
{
// Not supported yet.
}
else if (keyword == "norm")
{
std::string texture_path;
iss >> texture_path;
current_material->normal_str =
FindFile(texture_path, search_paths).string();
}
else if (keyword == "map_Pr" || keyword == "Pr")
{
std::string texture_path;
iss >> texture_path;
current_material->roughness_str =
FindFile(texture_path, search_paths).string();
}
else if (keyword == "map_Ps" || keyword == "Ps")
{
std::string texture_path;
iss >> texture_path;
current_material->sheen_str =
FindFile(texture_path, search_paths).string();
}
else if (keyword == "d")
{
// alpha
iss >> current_material->diffuse_vec4.a;
current_material->ambient_vec4.a =
current_material->diffuse_vec4.a;
}
}
}
}

const MtlMaterial& Mtl::GetMaterial(const std::string& name) const
{
if (material_name_map_.count(name))
{
return materials_[material_name_map_.at(name)];
}
throw std::runtime_error(std::format("Material not found: {}", name));
}

const std::vector<MtlMaterial>& Mtl::GetMaterials() const
{
return materials_;
}

} // End namespace frame::file.
62 changes: 32 additions & 30 deletions src/frame/file/obj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,46 @@
#include <numeric>
#define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cc
#include <format>
#include <sstream>
#include <tiny_obj_loader.h>

#include "frame/file/file_system.h"

namespace frame::file
{

Obj::Obj(std::filesystem::path file_name)
Obj::Obj(
const std::filesystem::path& file_name,
const std::vector<std::filesystem::path>& search_paths)
{
// First thing first, find the material file.
std::ifstream obj_file(file_name);
if (!obj_file.is_open())
{
throw std::runtime_error(
std::format("Could not open file: {}", file_name.string()));
}
std::string line;
std::string mtl_file_name;
while (std::getline(obj_file, line))
{
std::istringstream iss(line);
std::string keyword;
iss >> keyword;
if (keyword == "mtllib")
{
iss >> mtl_file_name;
break;
}
}

if (!mtl_file_name.empty())
{
auto mtl_path = FindFile(mtl_file_name, search_paths);
Mtl mtl(mtl_path, search_paths);
materials_ = mtl.GetMaterials();
}

#ifdef TINY_OBJ_LOADER_V2
tinyobj::ObjReaderConfig reader_config;
const auto pair = SplitFileDirectory(file_name);
Expand All @@ -38,7 +69,6 @@ Obj::Obj(std::filesystem::path file_name)

auto& attrib = reader.GetAttrib();
auto& shapes = reader.GetShapes();
auto& materials = reader.GetMaterials();
#else
tinyobj::attrib_t attrib;
std::vector<tinyobj::shape_t> shapes;
Expand Down Expand Up @@ -153,34 +183,6 @@ Obj::Obj(std::filesystem::path file_name)
meshes_.push_back(mesh);
}
}

for (const auto& material : materials)
{
ObjMaterial obj_material{};
obj_material.name = material.name;
obj_material.ambient_str = material.ambient_texname;
obj_material.ambient_vec4 = glm::vec4(
material.ambient[0],
material.ambient[1],
material.ambient[2],
material.dissolve);
obj_material.diffuse_str = material.diffuse_texname;
obj_material.diffuse_vec4 = glm::vec4(
material.diffuse[0],
material.diffuse[1],
material.diffuse[2],
material.dissolve);
obj_material.displacement_str = material.displacement_texname;
obj_material.emmissive_str = material.emissive_texname;
obj_material.metallic_str = material.metallic_texname;
obj_material.metallic_val = material.metallic;
obj_material.normal_str = material.normal_texname;
obj_material.roughness_str = material.roughness_texname;
obj_material.roughness_val = material.roughness;
obj_material.sheen_str = material.sheen_texname;
obj_material.sheen_val = material.sheen;
materials_.emplace_back(obj_material);
}
}

Obj::~Obj() = default;
Expand Down
Loading
Loading