src/polygoncache.cpp

changeset 200
ca23936b455b
parent 193
b4beff48bb7a
child 205
1a4342d80de7
--- a/src/polygoncache.cpp	Wed May 25 20:36:34 2022 +0300
+++ b/src/polygoncache.cpp	Mon Jun 06 22:01:22 2022 +0300
@@ -1,11 +1,80 @@
 #include "polygoncache.h"
 #include "documentmanager.h"
+#include "invert.h"
 
-static void getObjectPolygons(
-	Model* model,
-	const int index,
-	std::vector<gl::Polygon>& polygons_out,
-	ldraw::GetPolygonsContext* context);
+Model* resolve(const QString& name, const ModelId callingModelId, DocumentManager* documents)
+{
+	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<gl::Polygon> getPolygonsAt(const Model* model, GetPolygonsContext* context)
+{
+	std::vector<gl::Polygon> result;
+	for (int 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(gl::edgeLine(edge, id));
+			},
+			[&](const Colored<Triangle>& triangle) {
+				result.push_back(gl::triangle(triangle, id));
+			},
+			[&](const Colored<Quadrilateral>& quad) {
+				result.push_back(gl::quadrilateral(quad, id));
+			},
+			[&](const Colored<ConditionalEdge>& cedge) {
+				result.push_back(gl::conditionalEdge(cedge, id));
+			},
+			[&](const Colored<SubfileReference>& ref) {
+				Model* dependency = context->documents->findDependencyByName(context->modelId, ref.name);
+				PolygonCache* cache = nullptr;
+				if (dependency != nullptr)
+				{
+					const auto dependencyModelId = context->documents->findIdForModel(dependency);
+					if (dependencyModelId.has_value()) {
+						cache = context->documents->getPolygonCacheForModel(dependencyModelId.value());
+					}
+				}
+				if (cache != nullptr) {
+					const bool needInverting = glm::determinant(ref.transformation) < 0;
+					const std::vector<gl::Polygon>& 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)
+						{
+							gl::invert(polygon);
+						}
+						if (polygon.color == ldraw::MAIN_COLOR)
+						{
+							polygon.color = ref.color;
+						}
+						polygon.id = id;
+						result.push_back(polygon);
+					}
+				}
+			},
+			[](const ModelElement&) {}
+		}, element);
+	}
+	return result;
+}
 
 /**
  * @brief Gets a list of GL polygons that are used to represent this model.
@@ -24,29 +93,10 @@
 		const std::optional<ModelId> modelId = documents->findIdForModel(model);
 		if (modelId.has_value())
 		{
-			ldraw::GetPolygonsContext context{modelId.value(), documents};
-			for (int i = 0; i < model->size(); i += 1)
-			{
-				getObjectPolygons(model, i, cache->cachedPolygons, &context);
-			}
+			GetPolygonsContext context{modelId.value(), documents};
+			cache->cachedPolygons = getPolygonsAt(model, &context);
 		}
 		cache->needRecache = false;
 	}
 	return cache->cachedPolygons;
 }
-
-/**
- * @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 void getObjectPolygons(
-	Model* model,
-	const int index,
-	std::vector<gl::Polygon>& polygons_out,
-	ldraw::GetPolygonsContext* context)
-{
-	const ldraw::Object* object = (*model)[unsigned_cast(index)];
-	object->getPolygons(polygons_out, context);
-}

mercurial