From 859935f3b5e92d5afb013d1565565061de22c1b4 Mon Sep 17 00:00:00 2001 From: Astazium <113135541+Astazium@users.noreply.github.com> Date: Wed, 5 Aug 2026 23:06:16 +0300 Subject: [PATCH] ObjParser and small libvecn refactor --- src/coders/obj.cpp | 122 +++++++++++++---------- src/logic/scripting/lua/libs/libvecn.cpp | 61 ++++-------- 2 files changed, 90 insertions(+), 93 deletions(-) diff --git a/src/coders/obj.cpp b/src/coders/obj.cpp index d7ff244aa..6da92a66c 100644 --- a/src/coders/obj.cpp +++ b/src/coders/obj.cpp @@ -10,53 +10,69 @@ class ObjParser : BasicParser { std::vector uvs {{0, 0}}; std::vector normals {{0, 1, 0}}; - // TODO: refactor - void parseFace(Mesh& mesh) { - std::vector vertices; - while (hasNext()) { - auto c = peekInLine(); - if (c == '\n') { - break; - } else if (hasNext()) { - uint indices[3] {}; - uint i = 0; - do { - char next = peekInLine(); - if (is_digit(next)) { - indices[i] = parseSimpleInt(10); - if (hasNext() && peekInLine() == '/') { - pos++; - } - } else if (next == '/') { - pos++; - } else { - break; - } - } while (hasNext() && peekInLine() != '\n' && ++i < 3); + Vertex parseFaceVertex() { + auto parseIndex = [&]() -> uint { + if (!hasNext() || !is_digit(peekInLine())) { + return 0; + } + return parseSimpleInt(10); + }; - vertices.push_back(Vertex { - coords[indices[0]], uvs[indices[1]], normals[indices[2]]}); + uint coord = parseIndex(); + uint uv = 0; + uint normal = 0; + + if (hasNext() && peekInLine() == '/') { + pos++; + + uv = parseIndex(); + + if (hasNext() && peekInLine() == '/') { + pos++; + normal = parseIndex(); } } - if (hasNext() && peekInLine() != '\n') { - skipLine(); - } + + return Vertex { + coords[coord], + uvs[uv], + normals[normal] + }; + } + + void triangulate(const std::vector& vertices, std::vector& output) { if (vertices.size() >= 3) { for (size_t j = 0; j < vertices.size() - 2; j++) { - mesh.vertices.push_back(vertices[0]); + output.push_back(vertices[0]); for (size_t i = 1; i < 3; i++) { - mesh.vertices.push_back(vertices[i + j]); + output.push_back(vertices[i + j]); } } } } -public: - ObjParser(const std::string_view file, const std::string_view src) - : BasicParser(file, src) { + + void parseFace(Mesh& mesh) { + std::vector vertices; + while (hasNext() && peekInLine() != '\n') { + vertices.push_back(parseFaceVertex()); + } + triangulate(vertices, mesh.vertices); } - std::unique_ptr parse() { - // first iteration - collecting vertex data + glm::vec3 parseVec3() { + float x = parseNumber().asNumber(); + float y = parseNumber().asNumber(); + float z = parseNumber().asNumber(); + return glm::vec3 {x, y, z}; + } + + glm::vec2 parseVec2() { + float x = parseNumber().asNumber(); + float y = parseNumber().asNumber(); + return glm::vec2 {x, y}; + } + + void collectVertexData() { while (hasNext()) { if (peek() == '#') { skipLine(); @@ -64,27 +80,18 @@ public: } auto cmd = parseName(); if (cmd == "v") { - float x = parseNumber().asNumber(); - float y = parseNumber().asNumber(); - float z = parseNumber().asNumber(); - coords.emplace_back(x, y, z); + coords.emplace_back(parseVec3()); } else if (cmd == "vt") { - float u = parseNumber().asNumber(); - float v = parseNumber().asNumber(); - uvs.emplace_back(u, v); + uvs.emplace_back(parseVec2()); } else if (cmd == "vn") { - float x = parseNumber().asNumber(); - float y = parseNumber().asNumber(); - float z = parseNumber().asNumber(); - normals.emplace_back(x, y, z); + normals.emplace_back(parseVec3()); } else { skipLine(); } } - // second iteration - building meshes - reset(); + } - auto model = std::make_unique(); + void buildMeshes(Model& model) { std::string texture; while (hasNext()) { if (peek() != '#' && parseName() == "usemtl") { @@ -95,7 +102,7 @@ public: skipLine(); } do { - Mesh* mesh = &model->addMesh(texture); + Mesh* mesh = &model.addMesh(texture); while (hasNext()) { if (peek() == '#') { skipLine(); @@ -105,7 +112,7 @@ public: if (cmd == "usemtl") { skipWhitespace(); texture = readUntilEOL(); - mesh = &model->addMesh(texture); + mesh = &model.addMesh(texture); break; } else if (cmd == "f") { parseFace(*mesh); @@ -113,6 +120,19 @@ public: skipLine(); } } while (hasNext()); + } +public: + ObjParser(const std::string_view file, const std::string_view src) + : BasicParser(file, src) { + } + + std::unique_ptr parse() { + // first iteration - collecting vertex data + collectVertexData(); + // second iteration - building meshes + reset(); + auto model = std::make_unique(); + buildMeshes(*model); model->clean(); return model; } diff --git a/src/logic/scripting/lua/libs/libvecn.cpp b/src/logic/scripting/lua/libs/libvecn.cpp index e0a5ac3dd..47ce1ca70 100644 --- a/src/logic/scripting/lua/libs/libvecn.cpp +++ b/src/logic/scripting/lua/libs/libvecn.cpp @@ -211,59 +211,36 @@ static int l_tostring(lua::State* L) { return lua::pushstring(L, ss.str()); } +#define VECLIB_BASE(dimension) \ +{"add", lua::wrap>}, \ +{"sub", lua::wrap>}, \ +{"mul", lua::wrap>}, \ +{"div", lua::wrap>}, \ +{"distance", lua::wrap>}, \ +{"normalize", lua::wrap>}, \ +{"length", lua::wrap>}, \ +{"tostring", lua::wrap>}, \ +{"abs", lua::wrap>}, \ +{"round", lua::wrap>}, \ +{"inverse", lua::wrap>}, \ +{"pow", lua::wrap>}, \ +{"dot", lua::wrap>}, \ +{"mix", lua::wrap>}, + const luaL_Reg vec2lib[] = { - {"add", lua::wrap>}, - {"sub", lua::wrap>}, - {"mul", lua::wrap>}, - {"div", lua::wrap>}, - {"distance", lua::wrap>}, - {"normalize", lua::wrap>}, - {"length", lua::wrap>}, - {"tostring", lua::wrap>}, - {"abs", lua::wrap>}, - {"round", lua::wrap>}, - {"inverse", lua::wrap>}, - {"pow", lua::wrap>}, - {"dot", lua::wrap>}, + VECLIB_BASE(2) {"angle", lua::wrap}, - {"mix", lua::wrap>}, {"rotate", lua::wrap}, {nullptr, nullptr} }; const luaL_Reg vec3lib[] = { - {"add", lua::wrap>}, - {"sub", lua::wrap>}, - {"mul", lua::wrap>}, - {"div", lua::wrap>}, - {"distance", lua::wrap>}, - {"normalize", lua::wrap>}, - {"length", lua::wrap>}, - {"tostring", lua::wrap>}, - {"abs", lua::wrap>}, - {"round", lua::wrap>}, - {"inverse", lua::wrap>}, - {"pow", lua::wrap>}, - {"dot", lua::wrap>}, + VECLIB_BASE(3) {"spherical_rand", lua::wrap}, - {"mix", lua::wrap>}, {nullptr, nullptr} }; const luaL_Reg vec4lib[] = { - {"add", lua::wrap>}, - {"sub", lua::wrap>}, - {"mul", lua::wrap>}, - {"div", lua::wrap>}, - {"distance", lua::wrap>}, - {"normalize", lua::wrap>}, - {"length", lua::wrap>}, - {"tostring", lua::wrap>}, - {"abs", lua::wrap>}, - {"round", lua::wrap>}, - {"inverse", lua::wrap>}, - {"pow", lua::wrap>}, - {"dot", lua::wrap>}, - {"mix", lua::wrap>}, + VECLIB_BASE(4) {nullptr, nullptr} };