src/polygoncache.cpp

Mon, 06 Jun 2022 22:01:22 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Mon, 06 Jun 2022 22:01:22 +0300
changeset 200
ca23936b455b
parent 193
b4beff48bb7a
child 205
1a4342d80de7
permissions
-rw-r--r--

Giant refactor

#include "polygoncache.h"
#include "documentmanager.h"
#include "invert.h"

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.
 * @details Will build polygons if polygons are outdated.
 * @param documents Documents to use to resolve subfile references
 * @return vector of GL polygons
 */
const std::vector<gl::Polygon> &getCachedPolygons(
	PolygonCache *cache,
	Model *model,
	DocumentManager *documents)
{
	if (cache->needRecache)
	{
		cache->cachedPolygons.clear();
		const std::optional<ModelId> modelId = documents->findIdForModel(model);
		if (modelId.has_value())
		{
			GetPolygonsContext context{modelId.value(), documents};
			cache->cachedPolygons = getPolygonsAt(model, &context);
		}
		cache->needRecache = false;
	}
	return cache->cachedPolygons;
}

mercurial