src/invert.cpp

Wed, 22 Sep 2021 13:28:53 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Wed, 22 Sep 2021 13:28:53 +0300
changeset 138
5d6a4ad46cc7
parent 33
4c41bfe2ec6e
child 183
97b591813c8b
permissions
-rw-r--r--

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

mercurial