# HG changeset patch # User Teemu Piippo # Date 1654770775 -10800 # Node ID 232e7634cc8a7d1050d6eb291ad8c5cfa8f6cd86 # Parent c93e4a1eaadb0efef31727df98613b045e722382 more refactoring, dosn't build yet diff -r c93e4a1eaadb -r 232e7634cc8a src/gl/common.h --- a/src/gl/common.h Thu Jun 09 11:51:42 2022 +0300 +++ b/src/gl/common.h Thu Jun 09 13:32:55 2022 +0300 @@ -31,7 +31,6 @@ namespace gl { - struct Polygon; class ShaderProgram; void buildShaders( @@ -67,121 +66,10 @@ } }; -struct gl::Polygon -{ - enum Type : qint8 - { - EdgeLine, - Triangle, - Quadrilateral, - ConditionalEdge - } type; - glm::vec3 vertices[4]; - ldraw::Color color; - ModelId id; - - /** - * @return amount of vertices used for geometry - */ - inline unsigned int numPolygonVertices() const - { - if (type == Type::ConditionalEdge) - return 2; - else - return numVertices(); - } - - /** - * @return amount of vertices - */ - inline unsigned int numVertices() const - { - switch (type) - { - case Type::EdgeLine: - return 2; - case Type::Triangle: - return 3; - case Type::ConditionalEdge: - case Type::Quadrilateral: - return 4; - } - return 0; - } -}; - -Q_DECLARE_METATYPE(gl::Polygon) extern QOpenGLFunctions glfunc; namespace gl { - constexpr Polygon::Type POLYGON_TYPES[] = - { - Polygon::Type::EdgeLine, - Polygon::Type::Triangle, - Polygon::Type::Quadrilateral, - Polygon::Type::ConditionalEdge - }; - - constexpr int NUM_POLYGON_TYPES = countof(POLYGON_TYPES); - - inline Polygon edgeLine(const Colored& seg, ModelId id) - { - return Polygon{ - .type = Polygon::EdgeLine, - .vertices = {seg.p1, seg.p2}, - .color = seg.color, - .id = id, - }; - } - - inline Polygon triangle(const Colored& tri, ModelId id) - { - return Polygon{ - .type = Polygon::Triangle, - .vertices = {tri.p1, tri.p2, tri.p3}, - .color = tri.color, - .id = id, - }; - } - - inline Polygon quadrilateral(const Colored& quad, ModelId id) - { - return Polygon{ - .type = Polygon::Quadrilateral, - .vertices = {quad.p1, quad.p2, quad.p3, quad.p4}, - .color = quad.color, - .id = id, - }; - } - - inline Polygon conditionalEdge(const Colored& cedge, ModelId id) - { - return Polygon{ - .type = Polygon::ConditionalEdge, - .vertices = {cedge.p1, cedge.p2, cedge.c1, cedge.c2}, - .color = cedge.color, - .id = id, - }; - } - - // Vbo names - enum class ArrayClass : std::uint8_t - { - Lines, - Triangles, - Quads, - ConditionalLines - }; - - constexpr ArrayClass ARRAY_CLASSES[] = { - ArrayClass::Lines, - ArrayClass::Triangles, - ArrayClass::Quads, - ArrayClass::ConditionalLines, - }; - constexpr int NUM_ARRAY_CLASSES = countof(ARRAY_CLASSES); - // Different ways to render the scene enum class RenderStyle { diff -r c93e4a1eaadb -r 232e7634cc8a src/gl/compiler.cpp --- a/src/gl/compiler.cpp Thu Jun 09 11:51:42 2022 +0300 +++ b/src/gl/compiler.cpp Thu Jun 09 13:32:55 2022 +0300 @@ -196,20 +196,14 @@ } } -static gl::ArrayClass classifyPolygon(const gl::Polygon& polygon) +static constexpr gl::ArrayClass classifyPolygon(const PolygonElement& element) { - switch (polygon.type) - { - case gl::Polygon::EdgeLine: - return gl::ArrayClass::Lines; - case gl::Polygon::Triangle: - return gl::ArrayClass::Triangles; - case gl::Polygon::Quadrilateral: - return gl::ArrayClass::Quads; - case gl::Polygon::ConditionalEdge: - return gl::ArrayClass::ConditionalLines; - } - return gl::ArrayClass::Lines; + return visitPolygon( + [](const LineSegment&) { return gl::ArrayClass::Lines; }, + [](const Triangle&) { return gl::ArrayClass::Triangles; }, + [](const Quadrilateral&) { return gl::ArrayClass::Quads; }, + [](const ConditionalEdge&) { return gl::ArrayClass::ConditionalLines; }, + element); } template @@ -221,7 +215,7 @@ PolygonCache* cache = context->getPolygonCacheForModel(modelId.value()); if (cache != nullptr) { - for (const gl::Polygon& polygon : getCachedPolygons(cache, model, context)) + for (const WithId& polygon : getCachedPolygons(cache, model, context)) { fn(polygon); } @@ -230,7 +224,7 @@ } static QColor getColorForPolygon( - const gl::Polygon& polygon, + const PolygonElement& polygon, const gl::RenderPreferences& preferences, const ColorTable& colorTable) { @@ -259,12 +253,11 @@ BoundingBox gl::boundingBoxForModel(Model* model, DocumentManager* context) { BoundingBox result = emptyBoundingBox; - iterateModelPolygons(model, context, [&](const gl::Polygon& polygon) + iterateModelPolygons(model, context, [&](const PolygonElement& polygon) { - for (unsigned int i = 0; i < polygon.numPolygonVertices(); i += 1) - { - addPointToBox(result, polygon.vertices[i]); - } + visitPoints( + [&result](const glm::vec3& p) { addPointToBox(result, p); }, + polygon); }); return result; } @@ -282,7 +275,7 @@ for (gl::ModelShaders::ShaderObject& shader : shaders->shaderObjects) { shader.cachedData.clear(); } - iterateModelPolygons(model, context, [&](const Polygon& polygon) + iterateModelPolygons(model, context, [&](const PolygonElement& polygon) { const int index = static_cast(classifyPolygon(polygon)); std::vector& vertexBuffer = shaders->shaderObjects[index].cachedData; diff -r c93e4a1eaadb -r 232e7634cc8a src/gl/compiler.h --- a/src/gl/compiler.h Thu Jun 09 11:51:42 2022 +0300 +++ b/src/gl/compiler.h Thu Jun 09 13:32:55 2022 +0300 @@ -32,6 +32,23 @@ namespace gl { + // VAO names + enum class ArrayClass : std::uint8_t + { + Lines, + Triangles, + Quads, + ConditionalLines + }; + + constexpr ArrayClass ARRAY_CLASSES[] = { + ArrayClass::Lines, + ArrayClass::Triangles, + ArrayClass::Quads, + ArrayClass::ConditionalLines, + }; + constexpr int NUM_ARRAY_CLASSES = countof(ARRAY_CLASSES); + struct ModelShaders { struct Vertex @@ -51,7 +68,7 @@ QOpenGLVertexArrayObject vertexArray; std::vector cachedData; std::size_t vertexCount; - } shaderObjects[gl::NUM_POLYGON_TYPES]; + } shaderObjects[gl::NUM_ARRAY_CLASSES]; }; void build( diff -r c93e4a1eaadb -r 232e7634cc8a src/invert.cpp --- a/src/invert.cpp Thu Jun 09 11:51:42 2022 +0300 +++ b/src/invert.cpp Thu Jun 09 13:32:55 2022 +0300 @@ -36,19 +36,16 @@ /* * Inverts the winding of a polygon. */ -void gl::invert(gl::Polygon& polygon) +void gl::invert(PolygonElement& polygon) { - switch (polygon.numPolygonVertices()) - { - case 2: - case 3: - // 0 1 => 1 0 - // 0 1 2 => 1 0 2 - std::swap(polygon.vertices[0], polygon.vertices[1]); - break; - case 4: - // 0 1 2 3 => 0 3 2 1 - std::swap(polygon.vertices[1], polygon.vertices[3]); - break; - } + visitPolygon( + [](LineSegment&) {}, + [](Triangle& tri) { + std::swap(tri.p1, tri.p2); + }, + [](Quadrilateral& quad) { + std::swap(quad.p1, quad.p3); + }, + [](ConditionalEdge&) {}, + polygon); } diff -r c93e4a1eaadb -r 232e7634cc8a src/invert.h --- a/src/invert.h Thu Jun 09 11:51:42 2022 +0300 +++ b/src/invert.h Thu Jun 09 13:32:55 2022 +0300 @@ -30,5 +30,5 @@ namespace gl { - void invert(gl::Polygon& polygon); + void invert(PolygonElement &polygon); } diff -r c93e4a1eaadb -r 232e7634cc8a src/model.h --- a/src/model.h Thu Jun 09 11:51:42 2022 +0300 +++ b/src/model.h Thu Jun 09 13:32:55 2022 +0300 @@ -47,6 +47,30 @@ struct Empty {}; +template +struct transfer_reference +{ + using type = std::remove_reference_t; +}; + +template +struct transfer_reference +{ + using type = std::remove_reference_t&; +}; + +template +struct transfer_reference +{ + using type = std::remove_reference_t&&; +}; + +template +using transfer_reference_t = typename transfer_reference::type; +static_assert(std::is_same_v, char>); +static_assert(std::is_same_v, char&>); +static_assert(std::is_same_v, char&&>); + using ModelElement = std::variant< Colored, Colored, @@ -57,6 +81,76 @@ Empty, ParseError>; +using PolygonElement = Colored>; + +template +struct remove_color { using type = T; }; + +template +struct remove_color> { using type = T; }; + +template +struct remove_color&> { using type = T&; }; + +template +struct remove_color&&> { using type = T&&; }; + +template +using remove_color_t = typename remove_color::type; + +template +constexpr remove_color_t extract_colored(T&& x) +{ + return static_cast>(x); +} + +template +constexpr auto visitPolygon( + std::function)> f1, + std::function)> f2, + std::function)> f3, + std::function)> f4, + T&& element) +{ + return std::visit(overloaded{f1, f2, f3, f4}, extract_colored(element)); +} + +template +constexpr void visitPoints(T&& element, Fn func) +{ + visitPolygon( + [&func](transfer_reference_t edge) + { + func(edge.p1); + func(edge.p2); + }, + [&func](transfer_reference_t& tri) + { + func(tri.p1); + func(tri.p2); + func(tri.p3); + }, + [&func](transfer_reference_t& quad) + { + func(quad.p1); + func(quad.p2); + func(quad.p3); + func(quad.p4); + }, + [&func](transfer_reference_t& cedge) + { + func(cedge.p1); + func(cedge.p2); + func(cedge.c1); + func(cedge.c2); + }, + element); +} + QString modelElementToString(const ModelElement& element); struct ModelId { diff -r c93e4a1eaadb -r 232e7634cc8a src/polygoncache.cpp --- a/src/polygoncache.cpp Thu Jun 09 11:51:42 2022 +0300 +++ b/src/polygoncache.cpp Thu Jun 09 13:32:55 2022 +0300 @@ -7,31 +7,37 @@ return documents->findDependencyByName(callingModelId, name); } -/** - * @brief Gets the GL polygons of the object at the specified position in the model - * @param index Index of object in the model - * @param polygons_out Vector to add polygons into - * @param context Context to use to resolve subfile references - */ -static std::vector getPolygonsAt(const Model* model, GetPolygonsContext* context) +static PolygonElement transformed( + PolygonElement element, + const glm::mat4& transform) { - std::vector result; + visitPoints(element, [&transform](glm::vec3& p) { + p = transform * glm::vec4{p, 1}; + }); + return element; +} + +static std::vector> getPolygonsAt( + const Model* model, + GetPolygonsContext* context) +{ + std::vector> result; for (int i = 0; i < model->size(); i += 1) { const ModelElement& element = (*model)[i]; const ModelId id = model->idAt(i); std::visit(overloaded{ [&](const Colored& edge) { - result.push_back(gl::edgeLine(edge, id)); + result.push_back({{edge, edge.color}, id}); }, [&](const Colored& triangle) { - result.push_back(gl::triangle(triangle, id)); + result.push_back({{triangle, triangle.color}, id}); }, [&](const Colored& quad) { - result.push_back(gl::quadrilateral(quad, id)); + result.push_back({{quad, quad.color}, id}); }, [&](const Colored& cedge) { - result.push_back(gl::conditionalEdge(cedge, id)); + result.push_back({{cedge, cedge.color}, id}); }, [&](const Colored& ref) { Model* dependency = context->documents->findDependencyByName(context->modelId, ref.name); @@ -45,24 +51,17 @@ } if (cache != nullptr) { const bool needInverting = glm::determinant(ref.transformation) < 0; - const std::vector& modelPolygons = getCachedPolygons( + const auto& modelPolygons = getCachedPolygons( cache, dependency, context->documents); result.reserve(result.size() + modelPolygons.size()); - for (gl::Polygon polygon : modelPolygons) - { - for (unsigned int i = 0; i < polygon.numPolygonVertices(); i += 1) - { - const glm::vec4 homogenousVertex {polygon.vertices[i], 1}; - polygon.vertices[i] = ref.transformation * homogenousVertex; - } - if (needInverting != ref.inverted) - { + for (WithId polygon : modelPolygons) { + polygon = {transformed(polygon, ref.transformation), polygon.id}; + if (needInverting != ref.inverted) { gl::invert(polygon); } - if (polygon.color == MAIN_COLOR) - { + if (polygon.color == MAIN_COLOR) { polygon.color = ref.color; } polygon.id = id; @@ -82,7 +81,7 @@ * @param documents Documents to use to resolve subfile references * @return vector of GL polygons */ -const std::vector &getCachedPolygons( +const std::vector> &getCachedPolygons( PolygonCache *cache, Model *model, DocumentManager *documents) diff -r c93e4a1eaadb -r 232e7634cc8a src/polygoncache.h --- a/src/polygoncache.h Thu Jun 09 11:51:42 2022 +0300 +++ b/src/polygoncache.h Thu Jun 09 13:32:55 2022 +0300 @@ -3,6 +3,12 @@ #include "model.h" #include "gl/common.h" +template +struct WithId : T +{ + ModelId id; +}; + struct GetPolygonsContext { ModelId modelId; @@ -11,11 +17,11 @@ struct PolygonCache { - std::vector cachedPolygons; + std::vector> cachedPolygons; bool needRecache = true; }; -const std::vector& getCachedPolygons( +const std::vector>& getCachedPolygons( PolygonCache* cache, Model* model, class DocumentManager* documents);