diff --git a/include/blt/parse/obj_loader.h b/include/blt/parse/obj_loader.h index ad75b50..5d2c72d 100644 --- a/include/blt/parse/obj_loader.h +++ b/include/blt/parse/obj_loader.h @@ -31,6 +31,7 @@ namespace blt::gfx typedef blt::vec3f vertex_t; typedef blt::vec2f uv_t; typedef blt::vec3f normal_t; + typedef blt::vec3f color_t; class model_data { @@ -85,31 +86,55 @@ namespace blt::gfx std::int32_t v[4]; }; + struct material_t + { + std::string material_name; + color_t ambient; + color_t diffuse; + color_t specular; + float specular_exponent = 0.0f; + float transparency = 1.0f; + color_t transmission_filter_color{1, 1, 1}; + std::string texture_ambient; + std::string texture_diffuse; + std::string map_spec_color; + std::string map_spec_highlight; + std::string map_bump; + std::string map_displacement; + }; + struct object_data { - std::string object_name; + std::vector object_names; + std::string material; std::vector indices; }; - class obj_objects_t + class obj_model_t { private: std::vector vertex_data_; std::vector objects_; + HASHMAP materials_; public: - obj_objects_t(std::vector&& vertex_data, std::vector&& objects): - vertex_data_(vertex_data), objects_(objects) + obj_model_t(std::vector&& vertex_data, std::vector&& objects, HASHMAP&& mats): + vertex_data_(vertex_data), objects_(objects), materials_(mats) {} - inline const std::vector& vertex_data() + inline const auto& vertex_data() { return vertex_data_; }; - inline const std::vector& objects() + inline const auto& objects() { return objects_; }; + + inline const auto& materials() + { + return materials_; + } }; class char_tokenizer; @@ -126,6 +151,9 @@ namespace blt::gfx std::vector vertex_data; object_data current_object; std::vector data; + HASHMAP materials; + + size_t current_line = 0; private: bool handle_vertex_and_normals(float x, float y, float z, char type); @@ -136,10 +164,10 @@ namespace blt::gfx void handle_face_vertex(const std::vector& face_list, std::int32_t* arr); public: - obj_objects_t parseFile(std::string_view file); + obj_model_t parseFile(std::string_view file); }; - obj_objects_t quick_load(std::string_view file); + obj_model_t quick_load(std::string_view file); } diff --git a/src/blt/parse/obj_loader.cpp b/src/blt/parse/obj_loader.cpp index 11636f9..215dde3 100644 --- a/src/blt/parse/obj_loader.cpp +++ b/src/blt/parse/obj_loader.cpp @@ -15,14 +15,18 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#define BLT_DISABLE_TRACE +#define BLT_DISABLE_DEBUG + #include #include #include -#include #include #include #include "blt/std/assert.h" #include "blt/std/utility.h" +#include + namespace blt::gfx { @@ -86,6 +90,7 @@ namespace blt::gfx auto elements = blt::string::split(std::string(tokenizer.read_fully()), " "); BLT_ASSERT(elements.size() >= 2 && "Current line doesn't have enough arguments to process!"); float x = get(elements[0]), y = get(elements[1]); + BLT_DEBUG_STREAM << "Loaded value of (" << x << ", " << y << ")"; if (elements.size() < 3) { if (type == 't') @@ -95,9 +100,11 @@ namespace blt::gfx } else { float z = get(elements[2]); + BLT_DEBUG_STREAM << " with z: " << z; if (!handle_vertex_and_normals(x, y, z, type)) BLT_ERROR("Unable to parse line '%s' type '%c' not recognized", std::string(tokenizer.read_fully()).c_str(), type); } + BLT_DEBUG_STREAM << "\n"; } bool obj_loader::handle_vertex_and_normals(float x, float y, float z, char type) @@ -113,16 +120,18 @@ namespace blt::gfx return true; } - obj_objects_t quick_load(std::string_view file) + obj_model_t quick_load(std::string_view file) { return obj_loader().parseFile(file); } - obj_objects_t obj_loader::parseFile(std::string_view file) + obj_model_t obj_loader::parseFile(std::string_view file) { auto lines = blt::fs::getLinesFromFile(std::string(file)); - for (const auto& line : lines) + for (auto line_e : blt::enumerate(lines)) { + auto& line = line_e.second; + current_line = line_e.first; char_tokenizer token(line); if (!token.has_next() || token.read_fully().empty()) continue; @@ -138,29 +147,35 @@ 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(); + current_object.object_names.emplace_back(token.read_fully()); + BLT_TRACE("Setting object '%s'", std::string(current_object.object_name).c_str()); break; } case 'm': { - BLT_TRACE("Material '%s' needs to be loaded!", std::string(token.read_fully()).c_str()); + while (token.has_next() && token.advance() != ' ') + {} + BLT_WARN("Material '%s' needs to be loaded!", std::string(token.read_fully()).c_str()); break; } case 'u': { - BLT_TRACE("Using material '%s'", std::string(token.read_fully()).c_str()); + if (!current_object.indices.empty()) + data.push_back(current_object); + current_object = {}; + while (token.has_next() && token.advance() != ' ') + {} + current_object.material = token.read_fully(); + //BLT_WARN("Using material '%s'", std::string(token.read_fully()).c_str()); break; } case 's': - BLT_TRACE("Using shading: %s", std::string(token.read_fully()).c_str()); + //BLT_WARN("Using shading: %s", std::string(token.read_fully()).c_str()); break; } } data.push_back(current_object); - return {std::move(vertex_data), std::move(data)}; + return {std::move(vertex_data), std::move(data), std::move(materials)}; } void obj_loader::parse_face(char_tokenizer& tokenizer) @@ -187,7 +202,7 @@ namespace blt::gfx current_object.indices.push_back(t1); current_object.indices.push_back(t2); } else - BLT_WARN("Unsupported vertex count! %d", faces.size()); + BLT_WARN("Unsupported face vertex count of %d on line %d!", faces.size(), current_line); } void obj_loader::handle_face_vertex(const std::vector& face_list, int32_t* arr) @@ -197,21 +212,30 @@ namespace blt::gfx auto indices = blt::string::split(pair.second, '/'); BLT_ASSERT(indices.size() == 3 && "Must have vertex, uv, and normal indices!!"); - auto vi = get(indices[0]); - auto ui = get(indices[1]); - auto ni = get(indices[2]); + auto vi = get(indices[0]) - 1; + auto ui = get(indices[1]) - 1; + auto ni = get(indices[2]) - 1; + + BLT_DEBUG("Found vertex: %d, UV: %d, and normal: %d", vi, ui, ni); face_t face{vi, ui, ni}; auto loc = vertex_map.find(face); if (loc == vertex_map.end()) { + BLT_DEBUG("DID NOT FIND FACE!"); auto index = static_cast(vertex_data.size()); vertex_data.push_back({vertices[vi], uvs[ui], normals[ni]}); + BLT_DEBUG("Vertex: (%f, %f, %f), UV: (%f, %f), Normal: (%f, %f, %f)", vertices[vi].x(), vertices[vi].y(), vertices[vi].z(), + uvs[ui].x(), uvs[ui].y(), normals[ni].x(), normals[ni].y(), normals[ni].z()); vertex_map.insert({face, index}); arr[pair.first] = index; } else { + BLT_TRACE("Using cached data; %d; map size: %d", loc->second, vertex_data.size()); + const auto& d = vertex_data[loc->second]; + BLT_TRACE("Vertex: (%f, %f, %f), UV: (%f, %f), Normal: (%f, %f, %f)", d.vertex.x(), d.vertex.y(), d.vertex.z(), + d.uv.x(), d.uv.y(), d.normal.x(), d.normal.y(), d.normal.z()); arr[pair.first] = loc->second; } }