Sun, 03 Jul 2022 12:20:26 +0300
Let's try to keep the amount of indents in check...
#include "src/circularprimitive.h" #include "src/documentmanager.h" #include "src/invert.h" #include "src/polygoncache.h" Model* resolve(const QString& name, const ModelId callingModelId, DocumentManager* documents) { return documents->findDependencyByName(callingModelId, name); } static PolygonElement transformed( PolygonElement element, const glm::mat4& transform) { visitPoints([&transform](glm::vec3& p) { p = transform * glm::vec4{p, 1}; }, element); return element; } PolygonCache* findPolygonCacheForModel(Model* model, DocumentManager* context) { std::optional<ModelId> modelId = context->findIdForModel(model); if (modelId.has_value()) { return context->getPolygonCacheForModel(modelId.value()); } else { return nullptr; } } template<typename Fn, typename Fn2> static void collectPolygons( const ModelElement& element, Winding& winding, GetPolygonsContext* context, Fn&& add, Fn2&& reserve) { std::visit<void>(overloaded{ [&](const Colored<LineSegment>& edge) { add({edge, edge.color}); }, [&](const Colored<Triangle>& triangle) { add({triangle, triangle.color}); }, [&](const Colored<Quadrilateral>& quad) { add({quad, quad.color}); }, [&](const Colored<ConditionalEdge>& cedge) { add({cedge, cedge.color}); }, [&add, context, &reserve](const Colored<SubfileReference>& ref) { Model* dependency = context->documents->findDependencyByName(context->modelId, ref.name); PolygonCache* cache = nullptr; if (dependency != nullptr) { cache = findPolygonCacheForModel(dependency, context->documents); } if (cache != nullptr) { const bool needInverting = glm::determinant(ref.transformation) < 0; recacheIfNeeded(cache, dependency, context->documents); reserve(cache->polygons.size()); for (const PolygonElement& cacheElement : cache->polygons) { PolygonElement polygon = transformed(cacheElement, ref.transformation); if (needInverting != ref.inverted) { gl::invert(polygon); } if (polygon.color == MAIN_COLOR) { polygon.color = ref.color; } add(polygon); } } }, [&add](const Colored<CircularPrimitive>& circ) { rasterize(circ, [&](const PlainPolygonElement& polygon, ColorIndex color){ if (color == MAIN_COLOR) { color = circ.color; } add(PolygonElement{polygon, color}); }); }, [&winding](const Comment& comment) { if (comment.text == QStringLiteral("BFC CERTIFY CW")) { winding = Clockwise; } else if (comment.text == QStringLiteral("BFC CERTIFY CCW")) { winding = Anticlockwise; } else if (comment.text == QStringLiteral("BFC NOCERTIFY")) { winding = NoWinding; } }, [](const ModelElement&) {} }, element); } static std::vector<WithId<PolygonElement>> inlinePolygons( const Model* model, GetPolygonsContext* context) { Winding winding = NoWinding; std::vector<WithId<PolygonElement>> result; for (std::size_t i = 0; i < model->size(); i += 1) { const ModelElement& element = (*model)[i]; const ElementId id = model->idAt(i); collectPolygons(element, winding, context, [&result, winding, id](const PolygonElement& poly){ result.push_back({poly, id}); if (winding == Winding::Clockwise) { gl::invert(result.back()); } }, [&result](std::size_t incomingsize){ reserveMore(result, incomingsize); }); } return result; } void recacheIfNeeded(PolygonCache *cache, Model *model, DocumentManager *documents) { if (cache->needRecache) { cache->polygons.clear(); const std::optional<ModelId> modelId = documents->findIdForModel(model); if (modelId.has_value()) { GetPolygonsContext context{modelId.value(), documents}; cache->polygons = inlinePolygons(model, &context); } cache->needRecache = false; } }