src/linetypes/compoundobject.cpp

Wed, 25 May 2022 17:42:02 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Wed, 25 May 2022 17:42:02 +0300
changeset 193
b4beff48bb7a
parent 186
922662adb72a
permissions
-rw-r--r--

Simplify PolygonCache

#include "compoundobject.h"
#include "documentmanager.h"
#include "invert.h"
#include "polygoncache.h"

ldraw::CompoundObject::CompoundObject
(
	const glm::mat4& transformation,
	const Color color
) :
	ColoredObject{color},
	transformation{transformation}
{
}

QVariant ldraw::CompoundObject::getProperty(Property property) const
{
	switch (property)
	{
	case Property::Transformation:
		return QVariant::fromValue(this->transformation);
	case Property::IsInverted:
		return this->isInverted;
	default:
		return ColoredObject::getProperty(property);
	}
}

void ldraw::CompoundObject::setProperty(SetPropertyResult* result, const PropertyKeyValue& pair)
{
	LDRAW_OBJECT_HANDLE_SET_PROPERTY(Transformation, {this->transformation = value;});
	LDRAW_OBJECT_HANDLE_SET_PROPERTY(IsInverted, {this->isInverted = value;});
	ldraw::ColoredObject::setProperty(result, pair);
}

glm::vec3 ldraw::CompoundObject::position() const
{
	return this->transformation[3];
}

void ldraw::CompoundObject::invert(GetPolygonsContext *context)
{
	const std::optional<Axis> flatDimension = context ? this->flatDimension(context) : std::optional<Axis>{};
	if (flatDimension.has_value())
	{
		glm::mat4 matrix = glm::identity<glm::mat4>();
		matrix[*flatDimension][*flatDimension] = -1.0f;
		this->transformation *= matrix;
	}
	else
	{
		this->isInverted = not this->isInverted;
	}
}


QDataStream& ldraw::CompoundObject::serialize(QDataStream &stream) const
{
	return ColoredObject::serialize(stream) << this->transformation << this->isInverted;
}

QDataStream& ldraw::CompoundObject::deserialize(QDataStream &stream)
{
	return ColoredObject::deserialize(stream) >> this->transformation >> this->isInverted;
}

/**
 * @brief Finds out in which dimension the object is flat in. In that dimension all vertices have a value of 0.
 * If the object is not flat, this does not return a value.
 * @param model Model to find out flatness of
 * @param documents Where to look for subfiles
 * @returns dimension the model is flat in, if such dimension exists, no value otherwise.
 */
std::optional<Axis> ldraw::CompoundObject::flatDimension(GetPolygonsContext *context) const
{
	// The dimensions that this model is potentially flat in.
	QVector<Axis> dimensions = {X, Y, Z};
	std::vector<gl::Polygon> polygons;
	this->getPolygons(polygons, context);
	for (const gl::Polygon& polygon : polygons)
	{
		for (unsigned int i = 0; i < polygon.numPolygonVertices(); i += 1)
		{
			const glm::vec3& v_i = polygon.vertices[i];
			if (not qFuzzyCompare(v_i.x, 0.0f))
			{
				dimensions.removeOne(X);
			}
			if (not qFuzzyCompare(v_i.y, 0.0f))
			{
				dimensions.removeOne(Y);
			}
			if (not qFuzzyCompare(v_i.z, 0.0f))
			{
				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.
		return dimensions[0];
	}
	else
	{
		// The model is not flat.
		return {};
	}
}

QString ldraw::CompoundObject::transformToBareString() const
{
	return utility::format(
		"%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12",
		this->transformation[3][0],
		this->transformation[3][1],
		this->transformation[3][2],
		this->transformation[0][0],
		this->transformation[1][0],
		this->transformation[2][0],
		this->transformation[0][1],
		this->transformation[1][1],
		this->transformation[2][1],
		this->transformation[0][2],
		this->transformation[1][2],
		this->transformation[2][2]);
}

mercurial