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;
};
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
{
vertex_t vertex;
@ -55,33 +77,33 @@ namespace blt::gfx
struct triangle_t
{
std::int32_t v1, v2, v3;
std::int32_t v[3];
};
class obj_loader;
class obj_object_t
struct object_data
{
friend obj_loader;
private:
// TODO: shared VBO?
std::string object_name;
std::vector<constructed_vertex_t> vertices_;
std::vector<std::int32_t> indices_;
std::vector<triangle_t> indices;
};
obj_object_t(std::string_view name, std::vector<constructed_vertex_t> vertices, std::vector<std::int32_t> indices):
object_name(name), vertices_(std::move(vertices)), indices_(std::move(indices))
class obj_objects_t
{
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>& vertices()
inline const std::vector<constructed_vertex_t>& vertex_data()
{
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<normal_t> normals;
// maps between vertex indices -> face (constructed vertex)
//HASHMAP<std::int32_t, constructed_vertex_t> vertex_data;
// maps between face (constructed vertex) -> vertex indices
HASHMAP<face_t, std::int32_t, face_hash, face_eq> vertex_map;
std::vector<constructed_vertex_t> vertex_data;
struct object_data
{
std::string object_name;
std::vector<std::int32_t> indices;
};
object_data current_object;
std::vector<object_data> data;
private:
bool handle_vertex_and_normals(float x, float y, float z, char type);
void parse_extra_line(char_tokenizer& tokenizer);
void parse_face(char_tokenizer& tokenizer);
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;
}
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;
return objects;
obj_loader loader;
return loader.parseFile(file);
}
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));
for (const auto& line : lines)
@ -147,10 +145,16 @@ namespace blt::gfx
break;
case 'o':
{
if (!current_object.indices.empty())
data.push_back(current_object);
current_object = {};
current_object.object_name = token.read_fully();
break;
}
}
}
data.push_back(current_object);
return {std::move(vertex_data), std::move(data)};
}
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()), ' ');
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!!");
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)
{
BLT_WARN("Currently unable to process non-triangulated meshes!");