Sun, 03 Jul 2022 15:59:22 +0300
Fix polygonize not finding the normal properly
#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; } } constexpr bool n_xor(bool a) { return a; } template<typename... Args> constexpr bool n_xor(bool a, Args&&... rest) { return a xor n_xor(rest...); } template<typename Fn, typename Fn2> static void inlineSubfileReference( const PolygonCache::vector_type& polygons, const Colored<SubfileReference>& ref, Fn&& add, Fn2&& reserve) { const bool needInverting = 0 ^ (glm::determinant(ref.transformation) < 0) ^ (ref.inverted); reserve(polygons.size()); for (const PolygonElement& cacheElement : polygons) { PolygonElement polygon = transformed(cacheElement, ref.transformation); if (needInverting) { gl::invert(polygon); } if (polygon.color == MAIN_COLOR) { polygon.color = ref.color; } add(polygon); } } Model* findDependency(const SubfileReference& ref, GetPolygonsContext* context) { return context->documents->findDependencyByName(context->modelId, ref.name); } 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* const dependency = findDependency(ref, context); if (PolygonCache* cache = (dependency != nullptr) ? findPolygonCacheForModel(dependency, context->documents) : nullptr ) { recacheIfNeeded(cache, dependency, context->documents); inlineSubfileReference(cache->polygons, ref, add, reserve); } }, [&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; } }