src/polygoncache.cpp

Sun, 26 Jun 2022 20:54:09 +0300

author
Teemu Piippo <teemu.s.piippo@gmail.com>
date
Sun, 26 Jun 2022 20:54:09 +0300
changeset 262
dc33f8a707c4
parent 250
2837b549e616
child 264
76a025db4948
permissions
-rw-r--r--

Add action to make a model unofficial (modifies the !LDRAW_ORG line)

#include "polygoncache.h"
#include "documentmanager.h"
#include "invert.h"
#include "circularprimitive.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;
	}
}

static std::vector<WithId<PolygonElement>> getPolygonsAt(
	const Model* model,
	GetPolygonsContext* context)
{
	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);
				}
				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);
	}
	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)
{
	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