src/polygoncache.cpp

changeset 305
d891da20abca
parent 264
76a025db4948
child 309
d862721d19a3
--- a/src/polygoncache.cpp	Tue Jun 28 22:18:11 2022 +0300
+++ b/src/polygoncache.cpp	Wed Jun 29 14:11:58 2022 +0300
@@ -29,101 +29,106 @@
 	}
 }
 
-static std::vector<WithId<PolygonElement>> getPolygonsAt(
+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 ModelId id = model->idAt(i);
-		std::visit<void>(overloaded{
-			[&](const Colored<LineSegment>& edge) {
-				result.push_back({{edge, edge.color}, id});
-			},
-			[&](const Colored<Triangle>& triangle) {
-				result.push_back({{triangle, triangle.color}, id});
-			},
-			[&](const Colored<Quadrilateral>& quad) {
-				result.push_back({{quad, quad.color}, id});
-			},
-			[&](const Colored<ConditionalEdge>& cedge) {
-				result.push_back({{cedge, cedge.color}, id});
-			},
-			[&result, &id, context](const Colored<SubfileReference>& ref) {
-				Model* dependency = context->documents->findDependencyByName(context->modelId, ref.name);
-				PolygonCache* cache = nullptr;
-				if (dependency != nullptr) {
-					cache = findPolygonCacheForModel(dependency, context->documents);
+		collectPolygons(element, winding, context,
+			[&result, winding, id](const PolygonElement& poly){
+				result.push_back({poly, id});
+				if (winding == Winding::Clockwise) {
+					gl::invert(result.back());
 				}
-				if (cache != nullptr) {
-					const bool needInverting = glm::determinant(ref.transformation) < 0;
-					const PolygonCache::vector_type* modelPolygons = getCachedPolygons(
-						cache,
-						dependency,
-						context->documents);
-					reserveMore(result, modelPolygons->size());
-					for (WithId<PolygonElement> polygon : *modelPolygons) {
-						polygon = {transformed(polygon, ref.transformation), polygon.id};
-						if (needInverting != ref.inverted) {
-							gl::invert(polygon);
-						}
-						if (polygon.color == MAIN_COLOR) {
-							polygon.color = ref.color;
-						}
-						polygon.id = id;
-						result.push_back(polygon);
-					}
-				}
-			},
-			[&result, id](const Colored<CircularPrimitive>& circ) {
-				rasterize(circ, [&](const ModelElement& element){
-					std::visit<void>(overloaded{
-						// TODO: :-(
-						[&](const Colored<LineSegment>& edge) {
-							result.push_back({{edge, edge.color}, id});
-						},
-						[&](const Colored<Triangle>& triangle) {
-							result.push_back({{triangle, triangle.color}, id});
-						},
-						[&](const Colored<Quadrilateral>& quad) {
-							result.push_back({{quad, quad.color}, id});
-						},
-						[&](const Colored<ConditionalEdge>& cedge) {
-							result.push_back({{cedge, cedge.color}, id});
-						},
-						[&](const auto&){},
-					}, element);
-				});
-			},
-			[](const ModelElement&) {}
-		}, element);
+			}, [&result](std::size_t incomingsize){
+				reserveMore(result, incomingsize);
+			});
 	}
 	return result;
 }
 
-/**
- * @brief Gets a list of GL polygons that are used to represent this model.
- * @details Will build polygons if polygons are outdated.
- * @param documents Documents to use to resolve subfile references
- * @return vector of GL polygons
- */
-const PolygonCache::vector_type* getCachedPolygons(
-	PolygonCache *cache,
-	Model *model,
-	DocumentManager *documents)
+void recacheIfNeeded(PolygonCache *cache, Model *model, DocumentManager *documents)
 {
 	if (cache->needRecache)
 	{
-		cache->cachedPolygons.clear();
+		cache->polygons.clear();
 		const std::optional<ModelId> modelId = documents->findIdForModel(model);
 		if (modelId.has_value())
 		{
 			GetPolygonsContext context{modelId.value(), documents};
-			cache->cachedPolygons = getPolygonsAt(model, &context);
+			cache->polygons = inlinePolygons(model, &context);
 		}
 		cache->needRecache = false;
 	}
-	return &cache->cachedPolygons;
 }

mercurial