obj loader is complete
parent
7836c7f022
commit
e5e0b4120c
|
@ -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;
|
|
||||||
private:
|
|
||||||
// TODO: shared VBO?
|
|
||||||
std::string object_name;
|
std::string object_name;
|
||||||
std::vector<constructed_vertex_t> vertices_;
|
std::vector<triangle_t> indices;
|
||||||
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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!");
|
||||||
|
|
Loading…
Reference in New Issue