src/linetypes/compoundobject.cpp

Wed, 25 May 2022 20:36:34 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Wed, 25 May 2022 20:36:34 +0300
changeset 199
6988973515d2
parent 186
922662adb72a
permissions
-rw-r--r--

Fix pick() picking from weird places on the screen with high DPI scaling

glReadPixels reads data from the frame buffer, which contains data after
high DPI scaling, so any reads to that need to take this scaling into account

#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