obj loader is complete

main
Brett 2024-01-09 14:31:21 -05:00
parent 7836c7f022
commit e5e0b4120c
2 changed files with 80 additions and 37 deletions

View File

@ -46,6 +46,28 @@ namespace blt::gfx
std::int32_t vertex, uv, normal; std::int32_t vertex, uv, normal;
}; };
static inline bool operator==(const face_t& f1, const face_t& f2)
{
return f1.vertex == f2.vertex && f1.uv == f2.uv && f1.normal == f2.normal;
}
struct face_hash
{
size_t operator()(const face_t& face) const
{
std::hash<std::int32_t> hasher;
return hasher(face.vertex) ^ hasher(face.uv) ^ hasher(face.normal);
}
};
struct face_eq
{
bool operator()(const face_t& f1, const face_t& f2) const
{
return f1 == f2;
}
};
struct constructed_vertex_t struct constructed_vertex_t
{ {
vertex_t vertex; vertex_t vertex;
@ -55,33 +77,33 @@ namespace blt::gfx
struct triangle_t struct triangle_t
{ {
std::int32_t v1, v2, v3; std::int32_t v[3];
}; };
class obj_loader; struct object_data
class obj_object_t
{ {
friend obj_loader; std::string object_name;
private: std::vector<triangle_t> indices;
// TODO: shared VBO? };
std::string object_name;
std::vector<constructed_vertex_t> vertices_;
std::vector<std::int32_t> indices_;
obj_object_t(std::string_view name, std::vector<constructed_vertex_t> vertices, std::vector<std::int32_t> indices): class obj_objects_t
object_name(name), vertices_(std::move(vertices)), indices_(std::move(indices)) {
private:
std::vector<constructed_vertex_t> vertex_data_;
std::vector<object_data> objects_;
public:
obj_objects_t(std::vector<constructed_vertex_t>&& vertex_data, std::vector<object_data>&& objects):
vertex_data_(vertex_data), objects_(objects)
{} {}
public: inline const std::vector<constructed_vertex_t>& vertex_data()
inline const std::vector<constructed_vertex_t>& vertices()
{ {
return vertices_; return vertex_data_;
}; };
inline const std::vector<std::int32_t>& indices() inline const std::vector<object_data>& objects()
{ {
return indices_; return objects_;
}; };
}; };
@ -94,24 +116,23 @@ namespace blt::gfx
std::vector<uv_t> uvs; std::vector<uv_t> uvs;
std::vector<normal_t> normals; std::vector<normal_t> normals;
// maps between vertex indices -> face (constructed vertex) // maps between face (constructed vertex) -> vertex indices
//HASHMAP<std::int32_t, constructed_vertex_t> vertex_data; HASHMAP<face_t, std::int32_t, face_hash, face_eq> vertex_map;
std::vector<constructed_vertex_t> vertex_data; std::vector<constructed_vertex_t> vertex_data;
struct object_data object_data current_object;
{
std::string object_name;
std::vector<std::int32_t> indices;
};
std::vector<object_data> data; std::vector<object_data> data;
private: private:
bool handle_vertex_and_normals(float x, float y, float z, char type); bool handle_vertex_and_normals(float x, float y, float z, char type);
void parse_extra_line(char_tokenizer& tokenizer); void parse_extra_line(char_tokenizer& tokenizer);
void parse_face(char_tokenizer& tokenizer); void parse_face(char_tokenizer& tokenizer);
public: public:
void parseFile(std::string_view file); obj_objects_t parseFile(std::string_view file);
}; };
std::vector<obj_object_t> quick_load(std::string_view file); obj_objects_t quick_load(std::string_view file);
} }

View File

@ -119,15 +119,13 @@ namespace blt::gfx
return true; return true;
} }
std::vector<obj_object_t> quick_load(std::string_view file) obj_objects_t quick_load(std::string_view file)
{ {
std::vector<obj_object_t> objects; obj_loader loader;
return loader.parseFile(file);
return objects;
} }
void obj_loader::parseFile(std::string_view file) obj_objects_t obj_loader::parseFile(std::string_view file)
{ {
auto lines = blt::fs::getLinesFromFile(std::string(file)); auto lines = blt::fs::getLinesFromFile(std::string(file));
for (const auto& line : lines) for (const auto& line : lines)
@ -147,10 +145,16 @@ namespace blt::gfx
break; break;
case 'o': case 'o':
{ {
if (!current_object.indices.empty())
data.push_back(current_object);
current_object = {};
current_object.object_name = token.read_fully();
break; break;
} }
} }
} }
data.push_back(current_object);
return {std::move(vertex_data), std::move(data)};
} }
void obj_loader::parse_face(char_tokenizer& tokenizer) void obj_loader::parse_face(char_tokenizer& tokenizer)
@ -158,13 +162,31 @@ namespace blt::gfx
auto vertexes = blt::string::split(std::string(tokenizer.read_fully()), ' '); auto vertexes = blt::string::split(std::string(tokenizer.read_fully()), ' ');
if (vertexes.size() == 3) if (vertexes.size() == 3)
{ {
for (const auto& v : vertexes) triangle_t triangle{};
for (const auto& pair : blt::enumerate(vertexes))
{ {
auto indices = blt::string::split(v, '/'); auto indices = blt::string::split(pair.second, '/');
BLT_ASSERT(indices.size() == 3 && "Must have vertex, uv, and normal indices!!"); BLT_ASSERT(indices.size() == 3 && "Must have vertex, uv, and normal indices!!");
vertex_data.push_back(
{vertices[get<std::int32_t>(indices[0])], uvs[get<std::int32_t>(indices[1])], normals[get<std::int32_t>(indices[2])]}); auto vi = get<std::int32_t>(indices[0]);
auto ui = get<std::int32_t>(indices[1]);
auto ni = get<std::int32_t>(indices[2]);
face_t face{vi, ui, ni};
auto loc = vertex_map.find(face);
if (loc == vertex_map.end())
{
auto index = static_cast<std::int32_t>(vertex_data.size());
vertex_data.push_back({vertices[vi], uvs[ui], normals[ni]});
vertex_map.insert({face, index});
triangle.v[pair.first] = index;
} else
{
triangle.v[pair.first] = loc->second;
}
} }
current_object.indices.push_back(triangle);
} else if (vertexes.size() == 4) } else if (vertexes.size() == 4)
{ {
BLT_WARN("Currently unable to process non-triangulated meshes!"); BLT_WARN("Currently unable to process non-triangulated meshes!");