Wed, 22 Sep 2021 13:28:53 +0300
Document model.h
/* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 - 2020 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 <http://www.gnu.org/licenses/>. */ #include "main.h" #include "model.h" #include "gl/common.h" #include "invert.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<Axis> 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. */ glm::mat4 math::flipmatrix(const Axis dimension) { glm::mat4 result = glm::mat4(); const int k = static_cast<int>(dimension); result[k][k] = -1; 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<Vertex> 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<LDSubfileReference*>(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<LDCircularPrimitive*>(obj); if (primitive->isFlat()) primitive->setTransformationMatrix(primitive->transformationMatrix() * ::flipmatrix(Y)); else primitive->setInverted(not primitive->isInverted()); } } #endif /* * Inverts the winding of a polygon. */ void gl::invert(gl::Polygon& polygon) { switch (polygon.numPolygonVertices()) { case 2: case 3: // 0 1 => 1 0 // 0 1 2 => 1 0 2 std::swap(polygon.vertices[0], polygon.vertices[1]); break; case 4: // 0 1 2 3 => 0 3 2 1 std::swap(polygon.vertices[1], polygon.vertices[3]); break; } }