From 1e19d706fc5f5e3490d4ce204a6c5ca56c6614f8 Mon Sep 17 00:00:00 2001 From: vimene Date: Tue, 31 Dec 2024 08:38:30 +0100 Subject: fixed parse_object by implementing custom parsers std::setlocale also change the parsing of floats with std::stof. It is also more future proof to use a parser specific to Wavefront .obj files. --- src/engine.cpp | 21 ++++++----- src/fb/chfb.cpp | 2 +- src/fb/chfb.h | 2 +- src/obj_parser.cpp | 100 ++++++++++++++++++++++++++++++++++++++++++----------- 4 files changed, 94 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/engine.cpp b/src/engine.cpp index c484b0d..9b2f673 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -79,14 +79,16 @@ static void scene_main(Renderer& renderer, const Matrix4& final_tra Scene scene{ {{{0.f, 0.f, rad * dist}, {1.f, 0.f, 0.f, 0.f}, {1.f, 1.f, 1.f}}}, { - // { - // Mesh::plane(), - // { - // Vector3(0.f, 0.f, 0.f), - // {1.f, 0.f, 0.f, 0.f}, - // Vector3(rad, rad, rad), - // } - // }, +#if 0 + { + Mesh::plane(), + { + Vector3(0.f, 0.f, 0.f), + {1.f, 0.f, 0.f, 0.f}, + Vector3(rad, rad, rad), + } + }, +#else { engine::parse_object("../assets/suzanne.obj"), { @@ -95,6 +97,7 @@ static void scene_main(Renderer& renderer, const Matrix4& final_tra Vector3(rad, rad, rad), } }, +#endif } }; float mul_angle = 0.f; @@ -133,7 +136,7 @@ static void scene_main(Renderer& renderer, const Matrix4& final_tra static int main_term() { // init - setlocale(LC_ALL, ""); + std::setlocale(LC_ALL, ""); initscr(); cbreak(); noecho(); diff --git a/src/fb/chfb.cpp b/src/fb/chfb.cpp index cfd7635..98c9f23 100644 --- a/src/fb/chfb.cpp +++ b/src/fb/chfb.cpp @@ -21,7 +21,7 @@ void CharacterFrameBuffer::clear() { std::fill(chars_vector.begin(), chars_vector.end(), ' '); } -void CharacterFrameBuffer::draw_point(int x, int y, const Vector3& loc, const VertexData& vd, const engine::math::Vector3& normal) { +void CharacterFrameBuffer::draw_point(int x, int y, const Vector3& loc, const VertexData& vd, const Vector3& normal) { (void) x; (void) y; (void) loc; diff --git a/src/fb/chfb.h b/src/fb/chfb.h index 7c786fc..a866fef 100644 --- a/src/fb/chfb.h +++ b/src/fb/chfb.h @@ -14,7 +14,7 @@ class CharacterFrameBuffer { CharacterFrameBuffer(unsigned int w, unsigned int h); void resize(unsigned int w, unsigned int h); void clear(); - void draw_point(int x, int y, const engine::math::Vector3& loc, const engine::o3d::VertexData& vd, const engine::math::Vector3& normal); + void draw_point(int x, int y, const Vector3& loc, const VertexData& vd, const Vector3& normal); constexpr unsigned int width() const & { return w; diff --git a/src/obj_parser.cpp b/src/obj_parser.cpp index 7791678..ad71935 100644 --- a/src/obj_parser.cpp +++ b/src/obj_parser.cpp @@ -27,6 +27,66 @@ std::vector split(const std::string& s, char sep) { return res; } +float parse_float(const std::string& s) { + std::string::size_type ind = 0; + bool positive = true; + while (ind < s.length() && (s[ind] == '+' || s[ind] == '-')) + if (s[ind++] == '-') + positive = !positive; + + // improve error checking + if (ind == s.length()) + return 0.f; + + int n = 0; + while (ind < s.length() && s[ind] >= '0' && s[ind] <= '9') + n = n * 10 + static_cast(s[ind++]) - static_cast('0'); + + if (ind == s.length()) + return (positive ? 1.f : -1.f) * static_cast(n); + + // improve error checking + if (s[ind] != '.') + return 0.f; + + ind++; + + float decimal_part = 0.f; + float decimal_fac = .1f; + while (ind < s.length() && s[ind] >= '0' && s[ind] <= '9') { + decimal_part += decimal_fac * static_cast(static_cast(s[ind++]) - static_cast('0')); + decimal_fac *= .1f; + } + + // improve error checking + if (ind != s.length()) + return 0.f; + + return (positive ? 1.f : -1.f) * (static_cast(n) + decimal_part); +} + +float parse_int(const std::string& s) { + std::string::size_type ind = 0; + bool positive = true; + while (ind < s.length() && (s[ind] == '+' || s[ind] == '-')) + if (s[ind++] == '-') + positive = !positive; + + // improve error checking + if (ind == s.length()) + return 0.f; + + int n = 0; + while (ind < s.length() && s[ind] >= '0' && s[ind] <= '9') + n = n * 10 + static_cast(s[ind++]) - static_cast('0'); + + // improve error checking + if (ind != s.length()) + return 0.f; + + return (positive ? 1.f : -1.f) * n; +} + } o3d::Mesh parse_object(const std::string& obj_path) { @@ -38,40 +98,40 @@ o3d::Mesh parse_object(const std::string& obj_path) { if (line.length() == 0 || line[0] == '#') continue; if (line.rfind("o ", 0) == 0) { - std::cout << "Object: " << line.substr(2) << std::endl; + // std::cout << "Object: " << line.substr(2) << std::endl; } else if (line.rfind("v ", 0) == 0) { auto s_coords = split(line.substr(2), ' '); - math::Vector3 v{std::stof(s_coords[0]), std::stof(s_coords[1]), std::stof(s_coords[2])}; - std::cout << "Vertex x: " << v.x << " y: " << v.y << " z: " << v.z << std::endl; + math::Vector4 v{parse_float(s_coords[0]), parse_float(s_coords[1]), parse_float(s_coords[2]), 1.f}; + // std::cout << "Vertex x: " << v.x << " y: " << v.y << " z: " << v.z << std::endl; mesh.vertices.push_back(v); } else if (line.rfind("vn ", 0) == 0) { auto s_coords = split(line.substr(3), ' '); - math::Vector3 vn{std::stof(s_coords[0]), std::stof(s_coords[1]), std::stof(s_coords[2])}; - std::cout << "Vertex normal x: " << vn.x << " y: " << vn.y << " z: " << vn.z << std::endl; + math::Vector3 vn{parse_float(s_coords[0]), parse_float(s_coords[1]), parse_float(s_coords[2])}; + // std::cout << "Vertex normal x: " << vn.x << " y: " << vn.y << " z: " << vn.z << std::endl; mesh.normals.push_back(vn); } else if (line.rfind("s ", 0) == 0) { - auto smooth = false; - auto s_smooth = line.substr(2); - if (s_smooth == "0" || s_smooth == "off") { - smooth = false; - } else if (s_smooth == "1" || s_smooth == "on") { - smooth = true; - } - std::cout << "Smooth: " << std::boolalpha << smooth << std::endl; + // auto smooth = false; + // auto s_smooth = line.substr(2); + // if (s_smooth == "0" || s_smooth == "off") { + // smooth = false; + // } else if (s_smooth == "1" || s_smooth == "on") { + // smooth = true; + // } + // std::cout << "Smooth: " << std::boolalpha << smooth << std::endl; } else if (line.rfind("f ", 0) == 0) { std::array, 3> indices; auto line_split = split(line.substr(2), ' '); for (int i = 0; i < 3; i++) { auto indices_s_group = split(line_split[i], '/'); - indices[i][0] = std::stoi(indices_s_group[0]) - 1; - indices[i][1] = std::stoi(indices_s_group[2]) - 1; + indices[i][0] = parse_int(indices_s_group[0]) - 1; + indices[i][1] = parse_int(indices_s_group[2]) - 1; indices[i][2] = 0; } - std::cout << "Face:" - << " 1: vertex: " << indices[0][0] << " normal: " << indices[0][1] - << " 2: vertex: " << indices[1][0] << " normal: " << indices[1][1] - << " 3: vertex: " << indices[2][0] << " normal: " << indices[2][1] - << std::endl; + // std::cout << "Face:" + // << " 1: vertex: " << indices[0][0] << " normal: " << indices[0][1] + // << " 2: vertex: " << indices[1][0] << " normal: " << indices[1][1] + // << " 3: vertex: " << indices[2][0] << " normal: " << indices[2][1] + // << std::endl; mesh.indices.push_back(indices); } } -- cgit v1.2.3