further fixes

This commit is contained in:
ZY4N
2024-12-22 21:52:05 +01:00
parent db8db8f9d7
commit b385b3b1c8
5 changed files with 214 additions and 115 deletions

View File

@@ -24,7 +24,6 @@ public:
void emplace_hint_dir( void emplace_hint_dir(
directory_iterator directory_it, directory_iterator directory_it,
const std::filesystem::path& directory,
index_type index, index_type index,
dynamic_pose_store::id_type id dynamic_pose_store::id_type id
); );
@@ -45,7 +44,6 @@ public:
index_type index index_type index
); );
protected:
directory_iterator emplace_dir( directory_iterator emplace_dir(
directory_iterator directory_it, directory_iterator directory_it,
const std::filesystem::path& directory const std::filesystem::path& directory

View File

@@ -115,6 +115,7 @@ std::error_code kitti_loader::load(
continue; continue;
} }
// TODO find out if the path splitting is consistent
const auto base_directory = parent_directory(file.substr(0, sep_index)); const auto base_directory = parent_directory(file.substr(0, sep_index));
if (not base_directory) [[unlikely]] if (not base_directory) [[unlikely]]
{ {
@@ -162,14 +163,12 @@ std::error_code kitti_loader::load(
{ {
const auto file_path = std::string_view{ file.path().c_str() }; const auto file_path = std::string_view{ file.path().c_str() };
const auto extension_begin = file_path.rfind('.'); if (not file_path.ends_with(".bin"))
if (extension_begin == std::string_view::npos or file_path.substr(extension_begin) != ".bin")
{ {
continue; continue;
} }
auto filename_begin = file_path.rfind(fs::path::preferred_separator, extension_begin); auto filename_begin = file_path.rfind(fs::path::preferred_separator);
filename_begin = filename_begin == std::string_view::npos ? 0 : filename_begin + 1; filename_begin = filename_begin == std::string_view::npos ? 0 : filename_begin + 1;
const auto filename_only = file_path.substr(filename_begin); const auto filename_only = file_path.substr(filename_begin);

View File

@@ -42,9 +42,9 @@ std::error_code kitti_pose_loader::load(
auto path_buffer = fs::path{}; auto path_buffer = fs::path{};
auto in = std::ifstream{}; // TODO disable exceptions (for other loaders as well) auto in = std::ifstream{}; // TODO disable exceptions (for other loaders as well)
auto pose_buffer = dynamic_pose_buffer{};
pose_buffer = glm::identity<glm::mat4>(); // Needed to initialize 4th row and col
buffer = glm::identity<glm::mat4>();
auto processed_filenames = ztu::string_list{}; auto processed_filenames = ztu::string_list{};
@@ -62,13 +62,12 @@ std::error_code kitti_pose_loader::load(
ztu::logger::error("Kitti pose file does not exist: %", path_buffer); ztu::logger::error("Kitti pose file does not exist: %", path_buffer);
return; return;
} }
processed_filenames.push_back(path_buffer.c_str()); processed_filenames.push_back(path_buffer.c_str());
}; };
for (const auto directory : paths.directories) { for (const auto directory : paths.directories) {
path_buffer.assign(directory.begin(), directory.end()); path_buffer.assign(directory.begin(), directory.end());
path_buffer /= "pose.txt"; path_buffer /= pose_filename;
preprocess_file(); preprocess_file();
} }
@@ -79,6 +78,16 @@ std::error_code kitti_pose_loader::load(
for (const auto filename : processed_filenames) for (const auto filename : processed_filenames)
{ {
// TODO if (not) removing the path separator creates issues.
const auto directory = filename.substr(0, filename.length() - pose_filename.length());
auto [ dir_it, dir_match ] = id_lookup.poses.find_directory(directory);
if (not dir_match) [[unlikely]]
{
dir_it = id_lookup.poses.emplace_dir(dir_it, directory);
}
in.open(filename.data()); // Safe because string list adds null terminator in.open(filename.data()); // Safe because string list adds null terminator
if (not in.is_open()) if (not in.is_open())
{ {
@@ -90,7 +99,7 @@ std::error_code kitti_pose_loader::load(
for (auto i = pose_prefetch_lookup::index_type{}; in.peek() != std::ifstream::traits_type::eof(); ++i) for (auto i = pose_prefetch_lookup::index_type{}; in.peek() != std::ifstream::traits_type::eof(); ++i)
{ {
if (const auto error = parse_pose(in, pose_buffer)) if (const auto error = parse_pose(in, buffer))
{ {
ztu::logger::error( ztu::logger::error(
"Error occurred while parsing kitti pose % in file %: [%] %", "Error occurred while parsing kitti pose % in file %: [%] %",
@@ -102,60 +111,8 @@ std::error_code kitti_pose_loader::load(
continue; continue;
} }
const auto id = store.poses.add(pose_buffer); const auto id = store.poses.add(buffer);
id_lookup.poses.emplace_hint_dir(dir_it, i, id);
// TODO if (not) removing the path separator creates issues.
const auto directory = filename.substr(0, filename.length() - pose_filename.length());
id_lookup.poses.emplace(directory, i, id);
}
in.close();
}
}
void kitti_pose_loader::load(
const ztu::string_list& directories,
dynamic_pose_store& store,
pose_prefetch_lookup& id_lookup
) {
auto filename_buffer = std::filesystem::path{};
auto in = std::ifstream{}; // TODO disable exceptions (for other loaders as well)
auto pose_buffer = dynamic_pose_buffer{};
pose_buffer = glm::identity<glm::mat4>();
for (const auto directory : directories)
{
filename_buffer = directory;
filename_buffer /= "pose.txt";
in.open(filename_buffer);
if (not in.is_open())
{
ztu::logger::error("Cannot open kitti pose file %", filename_buffer);
continue;
}
in >> std::skipws;
for (auto i = pose_prefetch_lookup::index_type{}; in.peek() != std::ifstream::traits_type::eof(); ++i)
{
if (const auto error = parse_pose(in, pose_buffer))
{
ztu::logger::error(
"Error occurred while parsing kitti pose % in file %: [%] %",
i,
filename_buffer,
error.category().name(),
error.message()
);
continue;
}
const auto id = store.add(pose_buffer);
id_lookup.emplace(directory, i, id);
} }
in.close(); in.close();

View File

@@ -61,9 +61,10 @@ inline std::error_code make_error_code(codes e) {
} // namespace mesh_loader_error } // namespace mesh_loader_error
using vertex_type = std::array<dynamic_mesh_data::index_type, 3>; using vertex_type = std::array<dynamic_mesh_buffer::index_type, 3>;
struct indexed_vertex_type { struct indexed_vertex_type
{
vertex_type vertex; vertex_type vertex;
ztu::u32 buffer_index; ztu::u32 buffer_index;
@@ -102,6 +103,121 @@ std::errc parse_numeric_vector(std::string_view param, std::array<T, Count>& val
return {}; return {};
}; };
void find_materials(
std::span<char> buffer,
std::ifstream& in,
ztu::string_list& material_filenames
) {
static constexpr auto keyword = std::string_view{ "\nmtllib " };
const auto buffer_view = std::string_view(buffer);
// Add linebreak to simplify line begin search
buffer.front() = '\n';
auto leftover = std::size_t{ 1 };
do
{
// Keep some old characters to continue matching interrupted sequence
std::copy(buffer.end() - leftover, buffer.end(), buffer.begin());
in.read(buffer.data() + leftover, buffer.size() - leftover);
const auto str = buffer_view.substr(0, leftover + in.gcount());
leftover = keyword.size();
auto pos = std::string_view::size_type{};
while ((pos = str.find(keyword, pos)) != std::string_view::npos)
{
const auto filename_begin = pos + keyword.size();
const auto filename_end = str.find('\n', filename_begin);
if (filename_end != std::string_view::npos)
{
const auto length = filename_end - filename_begin;
const auto material_filename = str.substr(filename_begin, length);
// TODO get base dir from param figure out how to avoid heap
if (material_filename.is_relative())
{
material_filename = directory / material_filename;
}
material_filenames.push_back(material_filename);
pos = filename_end;
}
else // string exceeds the buffer
{
if (pos == 0) [[unlikely]]
{
std::cout << "Ignoring string match, as it exceeds buffer size." << std::endl;
leftover = 0;
}
else
{
leftover = str.size() - pos;
}
break;
}
}
} while (not in.eof());
}
std::error_code obj_loader::prefetch(
const file_dir_list& paths,
prefetch_queue& queue
) {
namespace fs = std::filesystem;
using obj_loader_error::codes;
using obj_loader_error::make_error_code;
auto buffer = std::vector<char>(8 * 1024, '\0');
auto in = std::ifstream{};
const auto parse_file = [&](const char* filename)
{
in.open(filename);
if (not in.is_open()) {
ztu::logger::error("Could not open .obj file '%'", filename);
return;
}
find_materials(buffer, in, queue.mtl_queue.files);
in.close();
};
for (const auto file : paths.files)
{
// `file` is null-terminates by list.
parse_file(file.data());
}
for (const auto directory : paths.directories)
{
for (const auto& file : fs::directory_iterator{ directory }) {
const auto& file_path = std::string_view{ file.path().c_str() };
// TODO remove heap allocation
if (not file_path.ends_with(".obj"))
{
continue;
}
// Null terminated by fs::path.
parse_file(file_path.data());
}
}
return {};
}
std::error_code obj_loader::load_directory( std::error_code obj_loader::load_directory(
dynamic_data_loader_ctx& ctx, dynamic_data_loader_ctx& ctx,
dynamic_mesh_store& store, dynamic_mesh_store& store,
@@ -144,15 +260,67 @@ std::error_code obj_loader::load_directory(
return {}; return {};
} }
[[nodiscard]] static std::error_code load(
components::mesh_vertex::flags enabled_components,
dynamic_mesh_buffer& buffer,
const file_dir_list& paths,
prefetch_lookup& id_lookup,
dynamic_data_store& store,
bool pedantic = false
) {
auto in = std::ifstream{};
std::set<indexed_vertex_type> vertex_ids;
const auto parse_file = [&](const char* filename)
{
in.open(filename);
if (not in.is_open()) {
ztu::logger::error("Could not open .obj file '%'", filename);
return;
}
vertex_ids.clear();
in.close();
};
for (const auto file : paths.files)
{
// `file` is null-terminates by list.
parse_file(file.data());
}
for (const auto directory : paths.directories)
{
for (const auto& file : fs::directory_iterator{ directory }) {
const auto& file_path = std::string_view{ file.path().c_str() };
// TODO remove heap allocation
if (not file_path.ends_with(".obj"))
{
continue;
}
// Null terminated by fs::path.
parse_file(file_path.data());
}
}
}
// TODO refactor so there is a function like parse_normals etc. // TODO refactor so there is a function like parse_normals etc.
std::error_code obj_loader::load( std::error_code obj_loader::load(
dynamic_data_loader_ctx& ctx,
dynamic_mesh_store& store,
components::mesh_vertex::flags enabled_components, components::mesh_vertex::flags enabled_components,
const std::filesystem::path& filename, dynamic_mesh_buffer& buffer,
const bool pedantic const char* filename,
prefetch_lookup& id_lookup,
dynamic_data_store& store,
bool pedantic
) { ) {
using obj_loader_error::codes; using obj_loader_error::codes;
using obj_loader_error::make_error_code; using obj_loader_error::make_error_code;
@@ -173,33 +341,26 @@ std::error_code obj_loader::load(
// and only push unique combinations to the buffers. // and only push unique combinations to the buffers.
std::set<indexed_vertex_type> vertex_ids; std::set<indexed_vertex_type> vertex_ids;
auto mesh = dynamic_mesh_data{};
// Buffers // Buffers
auto position_buffer = mesh.positions(); // TODO find out if this is still relevant
auto normal_buffer = mesh.normals(); auto position_buffer = buffer.positions();
auto tex_coord_buffer = mesh.tex_coords(); auto normal_buffer = buffer.normals();
auto tex_coord_buffer = buffer.tex_coords();
std::unordered_map<std::string, ztu::u32> material_name_lookup; std::unordered_map<std::string, ztu::u32> material_name_lookup;
constexpr auto mtl_loader_id = *ctx.material_loader.find_loader_static("mtl");
mtl_loader& material_loader = ctx.material_loader.get_loader<mtl_loader_id>();
material_loader.clear_name_lookup();
std::string material_name; std::string material_name;
const auto push_mesh = [&](const bool clear_buffers = false) { const auto push_mesh = [&](const bool clear_buffers = false) {
if (not mesh.positions().empty()) if (not buffer.positions().empty())
{ {
// Copy buffers instead of moving to keep capacity for further parsing // Copy buffers instead of moving to keep capacity for further parsing
// and have the final buffers be shrunk to size. // and have the final buffers be shrunk to size.
if (not material_name.empty()) { if (not material_name.empty()) {
if (const auto id = material_loader.find_id(material_name)) if (const auto id = material_loader.find_id(material_name))
{ {
mesh.material_id() = *id; buffer.material_id() = *id;
} }
else else
{ {
@@ -214,24 +375,24 @@ std::error_code obj_loader::load(
ztu::logger::debug("Parsed % normals.", mesh.normals().size()); ztu::logger::debug("Parsed % normals.", mesh.normals().size());
ztu::logger::debug("Parsed % tex_coords.", mesh.tex_coords().size()); ztu::logger::debug("Parsed % tex_coords.", mesh.tex_coords().size());
if (not mesh.positions().empty()) if (not buffer.positions().empty())
{ {
mesh.components() |= components::mesh_vertex::flags::position; buffer.components() |= components::mesh_vertex::flags::position;
} }
if (not mesh.normals().empty()) if (not buffer.normals().empty())
{ {
mesh.components() |= components::mesh_vertex::flags::normal; buffer.components() |= components::mesh_vertex::flags::normal;
} }
if (not mesh.tex_coords().empty()) if (not buffer.tex_coords().empty())
{ {
mesh.components() |= components::mesh_vertex::flags::tex_coord; buffer.components() |= components::mesh_vertex::flags::tex_coord;
} }
ztu::logger::debug("Pushing obj mesh with % triangles.", mesh.triangles().size()); ztu::logger::debug("Pushing obj mesh with % triangles.", buffer.triangles().size());
store.add(std::move(mesh)); store.meshes.add(buffer);
} }
if (clear_buffers) if (clear_buffers)
@@ -241,7 +402,7 @@ std::error_code obj_loader::load(
tex_coord_buffer.clear(); tex_coord_buffer.clear();
} }
mesh = dynamic_mesh_data{}; buffer.clear();
vertex_ids.clear(); vertex_ids.clear();
material_name.clear(); material_name.clear();
@@ -251,7 +412,7 @@ std::error_code obj_loader::load(
auto indexed_vid = indexed_vertex_type{ auto indexed_vid = indexed_vertex_type{
.vertex = vertex, .vertex = vertex,
.buffer_index = static_cast<ztu::u32>(mesh.positions().size()) .buffer_index = static_cast<ztu::u32>(buffer.positions().size())
}; };
// Search through sorted lookup to check if index combination is unique // Search through sorted lookup to check if index combination is unique
@@ -263,17 +424,17 @@ std::error_code obj_loader::load(
if (position_index < position_buffer.size()) if (position_index < position_buffer.size())
{ {
mesh.positions().emplace_back(position_buffer[position_index]); buffer.positions().emplace_back(position_buffer[position_index]);
} }
if (normal_index < normal_buffer.size()) if (normal_index < normal_buffer.size())
{ {
mesh.normals().emplace_back(normal_buffer[normal_index]); buffer.normals().emplace_back(normal_buffer[normal_index]);
} }
if (tex_coord_index < tex_coord_buffer.size()) if (tex_coord_index < tex_coord_buffer.size())
{ {
mesh.tex_coords().emplace_back(tex_coord_buffer[tex_coord_index]); buffer.tex_coords().emplace_back(tex_coord_buffer[tex_coord_index]);
} }
} }
@@ -437,8 +598,6 @@ std::error_code obj_loader::load(
}) })
); );
material_loader.clear_name_lookup();
if (ec != codes::ok) if (ec != codes::ok)
{ {
return make_error_code(ec); return make_error_code(ec);

View File

@@ -70,19 +70,8 @@ void pose_prefetch_lookup::emplace(
directory_it = emplace_dir(directory_it, directory); directory_it = emplace_dir(directory_it, directory);
} }
const auto [ index_it, match ] = find_index( emplace_hint_dir(
directory_it, directory_it,
index
);
if (not match)
{
}
emplace_hint_dir_index(
directory_it,
index_it,
index, index,
id id
); );
@@ -91,13 +80,10 @@ void pose_prefetch_lookup::emplace(
void pose_prefetch_lookup::emplace_hint_dir( void pose_prefetch_lookup::emplace_hint_dir(
directory_iterator directory_it, directory_iterator directory_it,
const std::filesystem::path& directory,
const index_type index, const index_type index,
const dynamic_pose_store::id_type id const dynamic_pose_store::id_type id
) { ) {
directory_it = emplace_dir(directory_it, directory);
const auto [ index_it, match ] = find_index( const auto [ index_it, match ] = find_index(
directory_it, directory_it,
index index
@@ -105,7 +91,7 @@ void pose_prefetch_lookup::emplace_hint_dir(
if (match) [[unlikely]] if (match) [[unlikely]]
{ {
const auto dir_index = dir_it->second; const auto dir_index = directory_it.first->second;
const auto id_index = index_it - m_directory_indices.begin() - dir_index; const auto id_index = index_it - m_directory_indices.begin() - dir_index;
m_pose_ids[id_index] = match; // TODO I guess I should warn?!? m_pose_ids[id_index] = match; // TODO I guess I should warn?!?
} }