src/polygoncache.cpp

changeset 305
d891da20abca
parent 264
76a025db4948
child 309
d862721d19a3
equal deleted inserted replaced
304:5d280bceb713 305:d891da20abca
27 else { 27 else {
28 return nullptr; 28 return nullptr;
29 } 29 }
30 } 30 }
31 31
32 static std::vector<WithId<PolygonElement>> getPolygonsAt( 32 template<typename Fn, typename Fn2>
33 static void collectPolygons(
34 const ModelElement& element,
35 Winding& winding,
36 GetPolygonsContext* context,
37 Fn&& add,
38 Fn2&& reserve)
39 {
40 std::visit<void>(overloaded{
41 [&](const Colored<LineSegment>& edge) {
42 add({edge, edge.color});
43 },
44 [&](const Colored<Triangle>& triangle) {
45 add({triangle, triangle.color});
46 },
47 [&](const Colored<Quadrilateral>& quad) {
48 add({quad, quad.color});
49 },
50 [&](const Colored<ConditionalEdge>& cedge) {
51 add({cedge, cedge.color});
52 },
53 [&add, context, &reserve](const Colored<SubfileReference>& ref) {
54 Model* dependency = context->documents->findDependencyByName(context->modelId, ref.name);
55 PolygonCache* cache = nullptr;
56 if (dependency != nullptr) {
57 cache = findPolygonCacheForModel(dependency, context->documents);
58 }
59 if (cache != nullptr) {
60 const bool needInverting = glm::determinant(ref.transformation) < 0;
61 recacheIfNeeded(cache, dependency, context->documents);
62 reserve(cache->polygons.size());
63 for (const PolygonElement& cacheElement : cache->polygons) {
64 PolygonElement polygon = transformed(cacheElement, ref.transformation);
65 if (needInverting != ref.inverted) {
66 gl::invert(polygon);
67 }
68 if (polygon.color == MAIN_COLOR) {
69 polygon.color = ref.color;
70 }
71 add(polygon);
72 }
73 }
74 },
75 [&add](const Colored<CircularPrimitive>& circ) {
76 rasterize(circ, [&](const PlainPolygonElement& polygon, ColorIndex color){
77 if (color == MAIN_COLOR) {
78 color = circ.color;
79 }
80 add(PolygonElement{polygon, color});
81 });
82 },
83 [&winding](const Comment& comment) {
84 if (comment.text == QStringLiteral("BFC CERTIFY CW")) {
85 winding = Clockwise;
86 }
87 else if (comment.text == QStringLiteral("BFC CERTIFY CCW")) {
88 winding = Anticlockwise;
89 }
90 else if (comment.text == QStringLiteral("BFC NOCERTIFY")) {
91 winding = NoWinding;
92 }
93 },
94 [](const ModelElement&) {}
95 }, element);
96 }
97
98 static std::vector<WithId<PolygonElement>> inlinePolygons(
33 const Model* model, 99 const Model* model,
34 GetPolygonsContext* context) 100 GetPolygonsContext* context)
35 { 101 {
102 Winding winding = NoWinding;
36 std::vector<WithId<PolygonElement>> result; 103 std::vector<WithId<PolygonElement>> result;
37 for (std::size_t i = 0; i < model->size(); i += 1) 104 for (std::size_t i = 0; i < model->size(); i += 1)
38 { 105 {
39 const ModelElement& element = (*model)[i]; 106 const ModelElement& element = (*model)[i];
40 const ModelId id = model->idAt(i); 107 const ModelId id = model->idAt(i);
41 std::visit<void>(overloaded{ 108 collectPolygons(element, winding, context,
42 [&](const Colored<LineSegment>& edge) { 109 [&result, winding, id](const PolygonElement& poly){
43 result.push_back({{edge, edge.color}, id}); 110 result.push_back({poly, id});
44 }, 111 if (winding == Winding::Clockwise) {
45 [&](const Colored<Triangle>& triangle) { 112 gl::invert(result.back());
46 result.push_back({{triangle, triangle.color}, id});
47 },
48 [&](const Colored<Quadrilateral>& quad) {
49 result.push_back({{quad, quad.color}, id});
50 },
51 [&](const Colored<ConditionalEdge>& cedge) {
52 result.push_back({{cedge, cedge.color}, id});
53 },
54 [&result, &id, context](const Colored<SubfileReference>& ref) {
55 Model* dependency = context->documents->findDependencyByName(context->modelId, ref.name);
56 PolygonCache* cache = nullptr;
57 if (dependency != nullptr) {
58 cache = findPolygonCacheForModel(dependency, context->documents);
59 } 113 }
60 if (cache != nullptr) { 114 }, [&result](std::size_t incomingsize){
61 const bool needInverting = glm::determinant(ref.transformation) < 0; 115 reserveMore(result, incomingsize);
62 const PolygonCache::vector_type* modelPolygons = getCachedPolygons( 116 });
63 cache,
64 dependency,
65 context->documents);
66 reserveMore(result, modelPolygons->size());
67 for (WithId<PolygonElement> polygon : *modelPolygons) {
68 polygon = {transformed(polygon, ref.transformation), polygon.id};
69 if (needInverting != ref.inverted) {
70 gl::invert(polygon);
71 }
72 if (polygon.color == MAIN_COLOR) {
73 polygon.color = ref.color;
74 }
75 polygon.id = id;
76 result.push_back(polygon);
77 }
78 }
79 },
80 [&result, id](const Colored<CircularPrimitive>& circ) {
81 rasterize(circ, [&](const ModelElement& element){
82 std::visit<void>(overloaded{
83 // TODO: :-(
84 [&](const Colored<LineSegment>& edge) {
85 result.push_back({{edge, edge.color}, id});
86 },
87 [&](const Colored<Triangle>& triangle) {
88 result.push_back({{triangle, triangle.color}, id});
89 },
90 [&](const Colored<Quadrilateral>& quad) {
91 result.push_back({{quad, quad.color}, id});
92 },
93 [&](const Colored<ConditionalEdge>& cedge) {
94 result.push_back({{cedge, cedge.color}, id});
95 },
96 [&](const auto&){},
97 }, element);
98 });
99 },
100 [](const ModelElement&) {}
101 }, element);
102 } 117 }
103 return result; 118 return result;
104 } 119 }
105 120
106 /** 121 void recacheIfNeeded(PolygonCache *cache, Model *model, DocumentManager *documents)
107 * @brief Gets a list of GL polygons that are used to represent this model.
108 * @details Will build polygons if polygons are outdated.
109 * @param documents Documents to use to resolve subfile references
110 * @return vector of GL polygons
111 */
112 const PolygonCache::vector_type* getCachedPolygons(
113 PolygonCache *cache,
114 Model *model,
115 DocumentManager *documents)
116 { 122 {
117 if (cache->needRecache) 123 if (cache->needRecache)
118 { 124 {
119 cache->cachedPolygons.clear(); 125 cache->polygons.clear();
120 const std::optional<ModelId> modelId = documents->findIdForModel(model); 126 const std::optional<ModelId> modelId = documents->findIdForModel(model);
121 if (modelId.has_value()) 127 if (modelId.has_value())
122 { 128 {
123 GetPolygonsContext context{modelId.value(), documents}; 129 GetPolygonsContext context{modelId.value(), documents};
124 cache->cachedPolygons = getPolygonsAt(model, &context); 130 cache->polygons = inlinePolygons(model, &context);
125 } 131 }
126 cache->needRecache = false; 132 cache->needRecache = false;
127 } 133 }
128 return &cache->cachedPolygons;
129 } 134 }

mercurial