diff -r 918b6c0f8b5b -r ed9685f44ab3 src/invert.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/invert.cpp Sat Dec 14 22:36:06 2019 +0200
@@ -0,0 +1,159 @@
+/*
+ * LDForge: LDraw parts authoring CAD
+ * Copyright (C) 2013 - 2018 Teemu Piippo
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "main.h"
+#include "model.h"
+#include "matrix.h"
+#include "gl/common.h"
+
+#if 0
+/*
+ * Returns whether or not the document is flat.
+ * If it is flat, the result is stored in *axis.
+ */
+bool isflat(Model* model, Axis* flatDimension)
+{
+ // The dimensions that this model is potentially flat in.
+ QVector dimensions = {X, Y, Z};
+
+ // Iterate through everything in the subfile. If there is any vertex with a coordinate not at
+ // zero, the subfile is not flat in that dimension.
+ for (LDObject* subfileObject : model->objects())
+ {
+ for (int i = 0; i < subfileObject->numVertices(); ++i)
+ {
+ Vertex const& v_i = subfileObject->vertex(i);
+
+ if (not qFuzzyCompare(v_i.x, 0.0))
+ dimensions.removeOne(X);
+
+ if (not qFuzzyCompare(v_i.y, 0.0))
+ dimensions.removeOne(Y);
+
+ if (not qFuzzyCompare(v_i.z, 0.0))
+ dimensions.removeOne(Z);
+ }
+
+ // If there are no more dimensions left, we can exit the loop.
+ if (dimensions.isEmpty())
+ break;
+ }
+
+ if (dimensions.size() == 1)
+ {
+ // The model is flat in one dimension, return that.
+ // If the model is flat in two or three dimensions, it's not really a valid model.
+ *flatDimension = dimensions[0];
+ return true;
+ }
+ else
+ {
+ // The model is not flat.
+ return false;
+ }
+}
+#endif
+
+/*
+ * Returns a matrix that causes a flip on the given dimension.
+ */
+Matrix4x4 flipmatrix(Axis dimension)
+{
+ Matrix4x4 result = identity4x4;
+ switch (dimension)
+ {
+ case X:
+ result(0, 0) = -1;
+ break;
+ case Y:
+ result(1, 1) = -1;
+ break;
+ case Z:
+ result(2, 2) = -1;
+ break;
+ }
+ return result;
+}
+
+#if 0
+/*
+ * Inverts an LDObject so that its winding is changed.
+ */
+void invert(LDObject* obj, DocumentManager* context)
+{
+ if (obj->numPolygonVertices() > 0)
+ {
+ // Object is vertex based, so change the order of the vertices.
+ QVector vertices;
+ vertices.resize(obj->numPolygonVertices());
+
+ for (int i = 0; i < vertices.size(); i += 1)
+ vertices[vertices.size() - 1 - i] = obj->vertex(i);
+
+ for (int i = 0; i < vertices.size(); i += 1)
+ obj->setVertex(i, vertices[i]);
+ }
+ else if (obj->type() == LDObjectType::SubfileReference)
+ {
+ // Check whether subfile is flat. If it is, flip it on the axis on which it is flat.
+ Model model {context};
+ LDSubfileReference* reference = static_cast(obj);
+ reference->fileInfo(context)->inlineContents(model, true, false);
+ Axis flatDimension;
+
+ if (::isflat(&model, &flatDimension))
+ {
+ reference->setTransformationMatrix(
+ reference->transformationMatrix() * ::flipmatrix(flatDimension)
+ );
+ }
+ else
+ {
+ // Subfile is not flat. Resort to invertnext.
+ reference->setInverted(not reference->isInverted());
+ }
+ }
+ else if (obj->type() == LDObjectType::CircularPrimitive)
+ {
+ auto primitive = static_cast(obj);
+
+ if (primitive->isFlat())
+ primitive->setTransformationMatrix(primitive->transformationMatrix() * ::flipmatrix(Y));
+ else
+ primitive->setInverted(not primitive->isInverted());
+ }
+}
+#endif
+
+/*
+ * Inverts the winding of a polygon.
+ */
+void invertPolygon(gl::Polygon& polygon)
+{
+ switch (polygon.numPolygonVertices())
+ {
+ case 2:
+ case 3:
+ std::swap(polygon.vertices[0], polygon.vertices[1]);
+ break;
+
+ case 4:
+ std::swap(polygon.vertices[1], polygon.vertices[3]);
+ break;
+ }
+}