--- 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); -}