obj loader is complete
parent
7836c7f022
commit
e5e0b4120c
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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!");
|
||||
|
|
Loading…
Reference in New Issue