Sun, 17 Jun 2018 13:53:33 +0300
replaced the Matrix class with QMatrix4x4
--- a/CMakeLists.txt Sun Jun 10 23:25:08 2018 +0300 +++ b/CMakeLists.txt Sun Jun 17 13:53:33 2018 +0300 @@ -50,7 +50,6 @@ src/librariesmodel.cpp src/main.cpp src/mainwindow.cpp - src/matrixinput.cpp src/model.cpp src/partdownloader.cpp src/partdownloadrequest.cpp @@ -95,7 +94,6 @@ src/toolsets/toolset.cpp src/toolsets/viewtoolset.cpp src/types/boundingbox.cpp - src/types/matrix.cpp src/types/vertex.cpp src/widgets/colorbutton.cpp src/widgets/doublespinbox.cpp @@ -125,7 +123,6 @@ src/librariesmodel.h src/main.h src/mainwindow.h - src/matrixinput.h src/model.h src/partdownloader.h src/partdownloadrequest.h @@ -178,7 +175,6 @@ src/toolsets/viewtoolset.h src/types/boundingbox.h src/types/library.h - src/types/matrix.h src/types/vertex.h src/widgets/colorbutton.h src/widgets/doublespinbox.h
--- a/src/algorithms/geometry.cpp Sun Jun 10 23:25:08 2018 +0300 +++ b/src/algorithms/geometry.cpp Sun Jun 17 13:53:33 2018 +0300 @@ -69,35 +69,10 @@ } -void rotateVertex(Vertex& vertex, const Vertex& rotationPoint, const Matrix& transformationMatrix) -{ - vertex -= rotationPoint.toVector(); - vertex.transform (transformationMatrix, {0, 0, 0}); - vertex += rotationPoint.toVector(); -} - - -void rotateObjects(int l, int m, int n, double angle, const QVector<LDObject*>& objects) +void rotateObjects(float l, float m, float n, double angle, const QVector<LDObject*>& objects) { - Vertex rotationPoint = getRotationPoint (objects); - double cosAngle = cos(angle); - double sinAngle = sin(angle); - - // ref: http://en.wikipedia.org/wiki/Transformation_matrix#Rotation_2 - Matrix transformationMatrix ( - { - (l * l * (1 - cosAngle)) + cosAngle, - (m * l * (1 - cosAngle)) - (n * sinAngle), - (n * l * (1 - cosAngle)) + (m * sinAngle), - - (l * m * (1 - cosAngle)) + (n * sinAngle), - (m * m * (1 - cosAngle)) + cosAngle, - (n * m * (1 - cosAngle)) - (l * sinAngle), - - (l * n * (1 - cosAngle)) - (m * sinAngle), - (m * n * (1 - cosAngle)) + (l * sinAngle), - (n * n * (1 - cosAngle)) + cosAngle - }); + QVector3D rotationPoint = getRotationPoint (objects).toVector(); + QQuaternion orientation = QQuaternion::fromAxisAndAngle({l, m, n}, angle); // Apply the above matrix to everything for (LDObject* obj : objects) @@ -107,21 +82,20 @@ for (int i = 0; i < obj->numVertices(); ++i) { Vertex v = obj->vertex (i); - rotateVertex(v, rotationPoint, transformationMatrix); + v += rotationPoint; + v.rotate(orientation); + v -= rotationPoint; obj->setVertex (i, v); } } else if (obj->hasMatrix()) { LDMatrixObject* mo = dynamic_cast<LDMatrixObject*> (obj); - - // Transform the position - Vertex v = mo->position(); - rotateVertex(v, rotationPoint, transformationMatrix); - mo->setPosition (v); - - // Transform the matrix - mo->setTransformationMatrix(transformationMatrix * mo->transformationMatrix()); + QMatrix4x4 matrix = mo->transformationMatrix(); + matrix.translate(rotationPoint); + matrix.rotate(orientation); + matrix.translate(-rotationPoint); + mo->setTransformationMatrix(matrix); } } } @@ -138,15 +112,8 @@ // Calculate center vertex for (LDObject* obj : objs) { - if (obj->hasMatrix()) - { - box << static_cast<LDMatrixObject*> (obj)->position(); - } - else - { - for (int i = 0; i < obj->numVertices(); ++i) - box << obj->vertex(i); - } + for (int i = 0; i < obj->numVertices(); ++i) + box << obj->vertex(i); } return box.center();
--- a/src/algorithms/geometry.h Sun Jun 10 23:25:08 2018 +0300 +++ b/src/algorithms/geometry.h Sun Jun 17 13:53:33 2018 +0300 @@ -31,6 +31,5 @@ QPointF pointOnLDrawCircumference(int segment, int divisions); QVector<QLineF> makeCircle(int segments, int divisions, double radius); qreal distanceFromPointToRectangle(const QPointF& point, const QRectF& rectangle); -void rotateObjects(int l, int m, int n, double angle, const QVector<LDObject*>& objects); +void rotateObjects(float l, float m, float n, double angle, const QVector<LDObject*>& objects); Vertex getRotationPoint(const QVector<LDObject*>& objs); -void rotateVertex(Vertex& vertex, const Vertex& rotationPoint, const Matrix& transformationMatrix);
--- a/src/algorithms/invert.cpp Sun Jun 10 23:25:08 2018 +0300 +++ b/src/algorithms/invert.cpp Sun Jun 17 13:53:33 2018 +0300 @@ -69,9 +69,9 @@ /* * Returns a matrix that causes a flip on the given dimension. */ -Matrix flipmatrix(Axis dimension) +QMatrix4x4 flipmatrix(Axis dimension) { - Matrix result = Matrix::identity; + QMatrix4x4 result; switch (dimension) {
--- a/src/algorithms/invert.h Sun Jun 10 23:25:08 2018 +0300 +++ b/src/algorithms/invert.h Sun Jun 17 13:53:33 2018 +0300 @@ -20,6 +20,6 @@ #include "../main.h" bool isflat(class Model* model, Axis* axis); -Matrix flipmatrix(Axis axis); +QMatrix4x4 flipmatrix(Axis dimension); void invert(LDObject* obj, class DocumentManager* context); void invertPolygon(LDPolygon& polygon);
--- a/src/dialogs/subfilereferenceeditor.cpp Sun Jun 10 23:25:08 2018 +0300 +++ b/src/dialogs/subfilereferenceeditor.cpp Sun Jun 17 13:53:33 2018 +0300 @@ -30,7 +30,6 @@ { this->ui.setupUi(this); this->ui.referenceName->setText(reference->referenceName()); - this->ui.matrixEditor->setPosition(reference->position()); this->ui.matrixEditor->setMatrix(reference->transformationMatrix()); this->color = reference->color(); ::setColorButton(this->ui.colorButton, this->color); @@ -67,7 +66,6 @@ this->reference->setReferenceName(this->ui.referenceName->text()); this->reference->setColor(this->color); this->reference->setTransformationMatrix(this->ui.matrixEditor->matrix()); - this->reference->setPosition(this->ui.matrixEditor->position()); QDialog::accept(); }
--- a/src/editmodes/circleMode.cpp Sun Jun 10 23:25:08 2018 +0300 +++ b/src/editmodes/circleMode.cpp Sun Jun 17 13:53:33 2018 +0300 @@ -93,7 +93,7 @@ int divisions = m_window->ringToolDivisions(); double dist0 = getCircleDrawDist(0); double dist1 = getCircleDrawDist(1); - Vertex displacement = m_drawedVerts.first(); + QVector3D translation = m_drawedVerts.first().toVector(); if (dist1 < dist0) qSwap(dist0, dist1); @@ -102,9 +102,10 @@ { // Special case: radii are the same, there's no area. Use a circle. // transform = shearMatrixForPlane(renderer()); - Matrix transform = Matrix::fromQMatrix(renderer()->currentCamera().transformationMatrix(1)); - transform *= Matrix::scaleMatrix(dist0); - model.emplace<LDCircularPrimitive>(PrimitiveModel::Circle, segments, divisions, transform, displacement); + QMatrix4x4 transform = renderer()->currentCamera().transformationMatrix(1); + transform.scale(dist0); + transform.translate(translation); + model.emplace<LDCircularPrimitive>(PrimitiveModel::Circle, segments, divisions, transform); finishDraw(model); return; } @@ -112,9 +113,10 @@ { // Special case #2: one radius is 0, so use a disc. //transform = shearMatrixForPlane(renderer()); - Matrix transform = Matrix::fromQMatrix(renderer()->currentCamera().transformationMatrix(1)); - transform *= Matrix::scaleMatrix(max(dist0, dist1)); - model.emplace<LDCircularPrimitive>(PrimitiveModel::Disc, segments, divisions, transform, displacement); + QMatrix4x4 transform = renderer()->currentCamera().transformationMatrix(1); + transform.scale(max(dist0, dist1)); + transform.translate(translation); + model.emplace<LDCircularPrimitive>(PrimitiveModel::Disc, segments, divisions, transform); finishDraw(model); return; } @@ -130,9 +132,10 @@ { primitiveModel.ringNumber = component.num; LDDocument* primitiveFile = primitives()->getPrimitive(primitiveModel); - Matrix matrix = Matrix::fromQMatrix(renderer()->currentCamera().transformationMatrix(component.scale)); + QMatrix4x4 matrix = renderer()->currentCamera().transformationMatrix(component.scale); + matrix.translate(translation); // matrix = shearMatrixForPlane(renderer()) * matrix; - model.emplace<LDSubfileReference>(primitiveFile->name(), matrix, m_drawedVerts.first()); + model.emplace<LDSubfileReference>(primitiveFile->name(), matrix); } } else
--- a/src/format.h Sun Jun 10 23:25:08 2018 +0300 +++ b/src/format.h Sun Jun 17 13:53:33 2018 +0300 @@ -22,7 +22,6 @@ #include <QModelIndex> #include "basics.h" #include "colors.h" -#include "types/matrix.h" #include "types/vertex.h" // Converts a given value into a string that can be retrieved with text(). @@ -39,7 +38,6 @@ StringFormatArg (float a) : m_text (QString::number (a)) {} StringFormatArg (double a) : m_text (QString::number (a)) {} StringFormatArg (const Vertex& a) : m_text (a.toString()) {} - StringFormatArg (const Matrix& a) : m_text (a.toString()) {} StringFormatArg (const char* a) : m_text (a) {} StringFormatArg (LDColor a) : m_text (a.indexString()) {}
--- a/src/linetypes/circularprimitive.cpp Sun Jun 10 23:25:08 2018 +0300 +++ b/src/linetypes/circularprimitive.cpp Sun Jun 17 13:53:33 2018 +0300 @@ -27,14 +27,11 @@ return format("%1%2-%3%4.dat", prefix, numerator, denominator, stem()); } -LDCircularPrimitive::LDCircularPrimitive( - PrimitiveModel::Type type, +LDCircularPrimitive::LDCircularPrimitive(PrimitiveModel::Type type, int segments, int divisions, - const Matrix& transformationMatrix, - const Vertex& position -) : - LDMatrixObject {transformationMatrix, position}, + const QMatrix4x4& matrix) : + LDMatrixObject {matrix}, m_type {type}, m_segments {segments}, m_divisions {divisions} {} @@ -46,7 +43,7 @@ QString LDCircularPrimitive::asText() const { - return LDSubfileReference(buildFilename(), transformationMatrix(), position()).asText(); + return LDSubfileReference(buildFilename(), transformationMatrix()).asText(); } void LDCircularPrimitive::getVertices(DocumentManager* /* context */, QSet<Vertex>& vertices) const @@ -60,7 +57,7 @@ for (double y_value : {0.0, 1.0}) { Vertex vertex {point2d.x(), y_value, point2d.y()}; - vertex.transform(transformationMatrix(), position()); + vertex.transform(transformationMatrix()); vertices.insert(vertex); } } @@ -86,7 +83,7 @@ for (int i = 0; i < object->numVertices(); i += 1) { Vertex vertex = object->vertex(i); - vertex.transform(transformationMatrix(), position()); + vertex.transform(transformationMatrix()); object->setVertex(i, vertex); } } @@ -106,7 +103,7 @@ for (int i = 0; i < object->numVertices(); i += 1) { Vertex vertex = object->vertex(i); - vertex.transform(transformationMatrix(), position()); + vertex.transform(transformationMatrix()); object->setVertex(i, vertex); } @@ -174,8 +171,9 @@ position().toString(true) ).simplified(); - for (int i = 0; i < 9; ++i) - result += format("%1%2", transformationMatrix().value(i), (i != 8) ? " " : ""); + for (int i = 0; i < 3; ++i) + for (int j = 0; j < 3; ++j) + result += format("%1%2", transformationMatrix()(i, j), (i != 2 or j != 2) ? " " : ""); result += ')'; return result;
--- a/src/linetypes/circularprimitive.h Sun Jun 10 23:25:08 2018 +0300 +++ b/src/linetypes/circularprimitive.h Sun Jun 17 13:53:33 2018 +0300 @@ -12,8 +12,7 @@ PrimitiveModel::Type type, int segments, int divisions, - const Matrix& transformationMatrix, - const Vertex& position + const QMatrix4x4& matrix ); LDObjectType type() const override;
--- a/src/linetypes/modelobject.cpp Sun Jun 10 23:25:08 2018 +0300 +++ b/src/linetypes/modelobject.cpp Sun Jun 17 13:53:33 2018 +0300 @@ -51,11 +51,25 @@ // QString LDSubfileReference::asText() const { - QString val = format ("1 %1 %2 ", color(), position()); - val += transformationMatrix().toString(); - val += ' '; - val += m_referenceName; - return val; + auto cellString = [&](int row, int column) { return QString::number(transformationMatrix()(row, column)); }; + + return QStringList { + "1", + color().indexString(), + cellString(0, 3), // x + cellString(1, 3), // y + cellString(2, 3), // z + cellString(0, 0), // matrix start + cellString(0, 1), // ... + cellString(0, 2), // ... + cellString(1, 0), // ... + cellString(1, 1), // ... + cellString(1, 2), // ... + cellString(2, 0), // ... + cellString(2, 1), // ... + cellString(2, 2), // matrix end + referenceName() + }.join(" "); } QString LDBezierCurve::asText() const @@ -112,39 +126,25 @@ // ============================================================================= // -static void TransformObject (LDObject* obj, Matrix transform, Vertex pos, LDColor parentcolor) +static void TransformObject (LDObject* object, const QMatrix4x4& matrix, LDColor parentcolor) { - switch (obj->type()) + if (object->hasMatrix()) { + LDMatrixObject* reference = static_cast<LDMatrixObject*>(object); + QMatrix4x4 newMatrix = matrix * reference->transformationMatrix(); + reference->setTransformationMatrix(newMatrix); + } + else { - case LDObjectType::EdgeLine: - case LDObjectType::ConditionalEdge: - case LDObjectType::Triangle: - case LDObjectType::Quadrilateral: - for (int i = 0; i < obj->numVertices(); ++i) + for (int i = 0; i < object->numVertices(); ++i) { - Vertex v = obj->vertex (i); - v.transform (transform, pos); - obj->setVertex (i, v); + Vertex vertex = object->vertex(i); + vertex.transform(matrix); + object->setVertex(i, vertex); } - break; - - case LDObjectType::SubfileReference: - { - LDSubfileReference* ref = static_cast<LDSubfileReference*> (obj); - Matrix newMatrix = transform * ref->transformationMatrix(); - Vertex newpos = ref->position(); - newpos.transform (transform, pos); - ref->setPosition (newpos); - ref->setTransformationMatrix (newMatrix); - } - break; - - default: - break; } - if (obj->color() == MainColor) - obj->setColor (parentcolor); + if (object->color() == MainColor) + object->setColor(parentcolor); } /* @@ -201,7 +201,7 @@ if (shouldInvert(parentWinding, context)) ::invert(object, context); - TransformObject(object, transformationMatrix(), position(), color()); + TransformObject(object, transformationMatrix(), color()); } model.merge(inlined); @@ -280,7 +280,7 @@ for (LDPolygon& entry : data) { for (int i = 0; i < entry.numVertices(); ++i) - entry.vertices[i].transform (transformationMatrix(), position()); + entry.vertices[i].transform(transformationMatrix()); if (shouldInvert(parentWinding, context)) ::invertPolygon(entry); @@ -303,12 +303,12 @@ // // Moves this object using the given vector // -void LDObject::move (const QVector3D vector) +void LDObject::move(const QVector3D& vector) { if (hasMatrix()) { LDMatrixObject* mo = static_cast<LDMatrixObject*> (this); - mo->setPosition (mo->position() + vector); + mo->translate(vector); } else { @@ -409,39 +409,32 @@ changeProperty(&m_coords[i], vert); } -LDMatrixObject::LDMatrixObject (const Matrix& transform, const Vertex& pos) : - m_position (pos), - m_transformationMatrix (transform) {} +LDMatrixObject::LDMatrixObject(const QMatrix4x4& matrix) : + m_transformationMatrix {matrix} {} -void LDMatrixObject::setCoordinate (const Axis axis, double value) +Vertex LDMatrixObject::position() const { - Vertex position = this->position(); - position.setCoordinate(axis, value); - this->setPosition(position); -} - -const Vertex& LDMatrixObject::position() const -{ - return m_position; + QVector4D column = m_transformationMatrix.column(3); + return {column.x(), column.y(), column.z()}; } // ============================================================================= // -void LDMatrixObject::setPosition (const Vertex& a) -{ - changeProperty(&m_position, a); -} - -// ============================================================================= -// -const Matrix& LDMatrixObject::transformationMatrix() const +const QMatrix4x4& LDMatrixObject::transformationMatrix() const { return m_transformationMatrix; } -void LDMatrixObject::setTransformationMatrix (const Matrix& val) +void LDMatrixObject::translate(const QVector3D& offset) { - changeProperty(&m_transformationMatrix, val); + QMatrix4x4 matrix = transformationMatrix(); + matrix.translate(offset); + setTransformationMatrix(matrix); +} + +void LDMatrixObject::setTransformationMatrix(const QMatrix4x4& newMatrix) +{ + changeProperty(&m_transformationMatrix, newMatrix); } LDError::LDError (QString contents, QString reason) : @@ -509,10 +502,9 @@ LDSubfileReference::LDSubfileReference( QString referenceName, - const Matrix& transformationMatrix, - const Vertex& position + const QMatrix4x4& matrix ) : - LDMatrixObject {transformationMatrix, position}, + LDMatrixObject {matrix}, m_referenceName {referenceName} {} // ============================================================================= @@ -574,8 +566,9 @@ { QString result = format ("%1 %2, (", referenceName(), position().toString(true)); - for (int i = 0; i < 9; ++i) - result += format("%1%2", transformationMatrix().value(i), (i != 8) ? " " : ""); + for (int i = 0; i < 3; ++i) + for (int j = 0; j < 3; ++j) + result += format("%1%2", transformationMatrix()(i, j), (i != 2 or j != 2) ? " " : ""); result += ')'; return result; @@ -606,7 +599,6 @@ void LDMatrixObject::serialize(Serializer& serializer) { LDObject::serialize(serializer); - serializer << m_position; serializer << m_transformationMatrix; }
--- a/src/linetypes/modelobject.h Sun Jun 10 23:25:08 2018 +0300 +++ b/src/linetypes/modelobject.h Sun Jun 17 13:53:33 2018 +0300 @@ -72,7 +72,7 @@ bool isHidden() const; virtual bool isRasterizable() const { return false; } // Can this object be rasterized? virtual bool isScemantic() const; // Does this object have meaning in the part model? - void move (const QVector3D vector); + void move (const QVector3D& vector); virtual int numVertices() const; virtual int numPolygonVertices() const; virtual QString objectListText() const; @@ -117,22 +117,20 @@ { public: LDMatrixObject() = default; - LDMatrixObject(const Matrix& transformationMatrix, const Vertex& pos); + LDMatrixObject(const QMatrix4x4& matrix); bool hasMatrix() const override { return true; } - const Vertex& position() const; - void setCoordinate (const Axis ax, double value); - void setPosition (const Vertex& a); - void setTransformationMatrix (const Matrix& value); - const Matrix& transformationMatrix() const; + Vertex position() const; + void setTransformationMatrix(const QMatrix4x4& newMatrix); + const QMatrix4x4& transformationMatrix() const; + void translate(const QVector3D& offset); void serialize(class Serializer& serializer) override; protected: bool shouldInvert(Winding winding, DocumentManager* context); private: - Vertex m_position; - Matrix m_transformationMatrix = Matrix::identity; + QMatrix4x4 m_transformationMatrix; }; /* @@ -171,7 +169,7 @@ static const LDObjectType SubclassType = LDObjectType::SubfileReference; LDSubfileReference() = default; - LDSubfileReference(QString referenceName, const Matrix& transformationMatrix, const Vertex& position); + LDSubfileReference(QString referenceName, const QMatrix4x4& matrix = {}); virtual LDObjectType type() const override {
--- a/src/matrixinput.cpp Sun Jun 10 23:25:08 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,118 +0,0 @@ -/* - * 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 <http://www.gnu.org/licenses/>. - */ - -#include <QGridLayout> -#include "matrixinput.h" - -MatrixInput::MatrixInput(QWidget *parent) : QWidget(parent) -{ - QGridLayout* layout = new QGridLayout {this}; - setLayout(layout); - - for (int i = 0; i < 3; ++i) - for (int j = 0; j < 3; ++j) - { - _spinboxes[i * 3 + j] = new QDoubleSpinBox {this}; - layout->addWidget(_spinboxes[i * 3 + j], i, j); - } -} - -int MatrixInput::decimals() const -{ - return _spinboxes[0]->decimals(); -} - -double MatrixInput::maximum() const -{ - return _spinboxes[0]->maximum(); -} - -double MatrixInput::minimum() const -{ - return _spinboxes[0]->minimum(); -} - -QString MatrixInput::prefix() const -{ - return _spinboxes[0]->prefix(); -} - -void MatrixInput::setDecimals(int precision) -{ - for (QDoubleSpinBox* spinbox : _spinboxes) - spinbox->setDecimals(precision); -} - -void MatrixInput::setMaximum(double maximum) -{ - for (QDoubleSpinBox* spinbox : _spinboxes) - spinbox->setMaximum(maximum); -} - -void MatrixInput::setMinimum(double minimum) -{ - for (QDoubleSpinBox* spinbox : _spinboxes) - spinbox->setMinimum(minimum); -} - -void MatrixInput::setPrefix(const QString& prefix) -{ - for (QDoubleSpinBox* spinbox : _spinboxes) - spinbox->setPrefix(prefix); -} - -void MatrixInput::setRange(double minimum, double maximum) -{ - for (QDoubleSpinBox* spinbox : _spinboxes) - spinbox->setRange(minimum, maximum); -} - -void MatrixInput::setSingleStep(double singleStep) -{ - for (QDoubleSpinBox* spinbox : _spinboxes) - spinbox->setSingleStep(singleStep); -} - -void MatrixInput::setSuffix(const QString& suffix) -{ - for (QDoubleSpinBox* spinbox : _spinboxes) - spinbox->setSuffix(suffix); -} - -QString MatrixInput::suffix() -{ - return _spinboxes[0]->suffix(); -} - -void MatrixInput::setValue(const Matrix& value) -{ - for (int i = 0; i < 3; ++i) - for (int j = 0; j < 3; ++j) - _spinboxes[i * 3 + j]->setValue(value(i, j)); -} - -Matrix MatrixInput::value() -{ - Matrix result; - - for (int i = 0; i < 3; ++i) - for (int j = 0; j < 3; ++j) - result(i, j) = _spinboxes[i * 3 + j]->value(); - - return result; -}
--- a/src/matrixinput.h Sun Jun 10 23:25:08 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * 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 <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include "main.h" -#include <QDoubleSpinBox> - -/* - * Models a 3×3 array of spinboxes for matrix input. - */ -class MatrixInput : public QWidget -{ - Q_OBJECT - -public: - explicit MatrixInput(QWidget *parent = 0); - int decimals() const; - double maximum() const; - double minimum() const; - QString prefix() const; - void setDecimals(int precision); - void setMaximum(double maximum); - void setMinimum(double minimum); - void setPrefix(const QString& prefix); - void setRange(double minimum, double maximum); - void setSingleStep(double singleStep); - void setSuffix(const QString& suffix); - QString suffix(); - void setValue(const Matrix& value); - Matrix value(); - -private: - QDoubleSpinBox* _spinboxes[9]; -};
--- a/src/parser.cpp Sun Jun 10 23:25:08 2018 +0300 +++ b/src/parser.cpp Sun Jun 17 13:53:33 2018 +0300 @@ -383,12 +383,14 @@ CheckTokenNumbers (tokens, 1, 13); Vertex displacement = parseVertex (tokens, 2); // 2 - 4 - Matrix transform; + QMatrix4x4 matrix; + matrix.translate(displacement.x, displacement.y, displacement.z); QString referenceName = tokens[14]; for (int i = 0; i < 9; ++i) - transform.value(i) = tokens[i + 5].toDouble(); // 5 - 13 + matrix(i / 3, i % 3) = tokens[i + 5].toDouble(); // 5 - 13 + matrix.optimize(); static const QRegExp circularPrimitiveRegexp {R"((?:(\d+)\\)?(\d+)-(\d+)(cyli|edge|disc|ndis)\.dat)"}; LDObject* obj; @@ -417,13 +419,12 @@ type, segments, resolution, - transform, - displacement + matrix ); } else { - obj = model.emplaceAt<LDSubfileReference>(position, referenceName, transform, displacement); + obj = model.emplaceAt<LDSubfileReference>(position, referenceName, matrix); } obj->setColor(LDColor {tokens[1].toInt(nullptr, 0)});
--- a/src/toolsets/algorithmtoolset.cpp Sun Jun 10 23:25:08 2018 +0300 +++ b/src/toolsets/algorithmtoolset.cpp Sun Jun 17 13:53:33 2018 +0300 @@ -161,17 +161,12 @@ if (mo) { - Vertex position = mo->position(); - Matrix matrix = mo->transformationMatrix(); + QMatrix4x4 matrix = mo->transformationMatrix(); - for (Axis axis : {X, Y, Z}) - position[axis] = roundToDecimals(position[axis], config::roundPositionPrecision()); - - for (int i : {0, 1, 2}) - for (int j : {0, 1, 2}) + for (int i : {0, 1, 2, 3}) + for (int j : {0, 1, 2, 3}) matrix(i, j) = roundToDecimals(matrix(i, j), config::roundMatrixPrecision()); - mo->setPosition(position); mo->setTransformationMatrix(matrix); num += 12; } @@ -266,12 +261,14 @@ fixVertex(point); object->setVertex(i, point); } - if (object->type() == LDObjectType::SubfileReference) + if (object->hasMatrix()) { - LDSubfileReference* reference = static_cast<LDSubfileReference*>(object); + LDMatrixObject* reference = static_cast<LDMatrixObject*>(object); Vertex point = reference->position(); fixVertex(point); - reference->setPosition(point); + QMatrix4x4 matrix = reference->transformationMatrix(); + matrix.setColumn(3, {(float) point.x, (float) point.y, (float) point.z, 1}); + reference->setTransformationMatrix(matrix); } } } @@ -607,7 +604,7 @@ currentDocument()->remove(object); // Add a reference to the new subfile to where the selection was - currentDocument()->emplaceAt<LDSubfileReference>(referencePosition, subfile->name(), Matrix::identity, Vertex {0, 0, 0}); + currentDocument()->emplaceAt<LDSubfileReference>(referencePosition, subfile->name()); // Refresh stuff m_window->updateDocumentList();
--- a/src/toolsets/movetoolset.cpp Sun Jun 10 23:25:08 2018 +0300 +++ b/src/toolsets/movetoolset.cpp Sun Jun 17 13:53:33 2018 +0300 @@ -116,7 +116,7 @@ double MoveToolset::getRotateActionAngle() { - return (pi * grid()->angleSnap()) / 180; + return grid()->angleSnap(); } void MoveToolset::rotateXPos()
--- a/src/types/matrix.cpp Sun Jun 10 23:25:08 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,265 +0,0 @@ -/* - * 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 <http://www.gnu.org/licenses/>. - */ - -#include "../basics.h" -#include "../format.h" -#include "matrix.h" - -const Matrix Matrix::identity {1, 0, 0, 0, 1, 0, 0, 0, 1}; - -/* - * Default-constructor for a matrix - */ -Matrix::Matrix() : - m_values{0} {} - -/* - * Constructs a matrix from a single fill value. - */ -Matrix::Matrix (double fillvalue) : - m_values {fillvalue} {} - -/* - * Constructs a matrix from an initializer list. - * Note: the initializer list must have exactly 9 values. - */ -Matrix::Matrix (const std::initializer_list<double>& values) -{ - int i = 0; - - for (double value : values) - { - if (i < 9) - m_values[i++] = value; - else - break; - } -} - -/* - * Returns a string representation of the matrix - */ -QString Matrix::toString() const -{ - QString val; - - for (int i = 0; i < 9; ++i) - { - if (i > 0) - val += ' '; - - val += QString::number (m_values[i]); - } - - return val; -} - -/* - * Fills the matrix with zeros - */ -void Matrix::zero() -{ - for (double& value : m_values) - value = 0; -} - -/* - * Performs matrix multiplication. - * Note: A*B is not equivalent to B*A! - */ -Matrix Matrix::multiply (const Matrix& other) const -{ - Matrix result; - - for (int i = 0; i < 3; ++i) - for (int j = 0; j < 3; ++j) - for (int k = 0; k < 3; ++k) - result(i, j) += (*this)(i, k) * other(k, j); - - return result; -} - -/* - * Returns the matrix's determinant - */ -double Matrix::determinant() const -{ - return (value (0) * value (4) * value (8)) + - (value (1) * value (5) * value (6)) + - (value (2) * value (3) * value (7)) - - (value (2) * value (4) * value (6)) - - (value (1) * value (3) * value (8)) - - (value (0) * value (5) * value (7)); -} - -/* - * Returns a value in matrix value (index math must be done manually) - */ -double& Matrix::value(int index) -{ - return m_values[index]; -} - -/* - * Returns a value in matrix value (index math must be done manually) - */ -const double& Matrix::value(int index) const -{ - return m_values[index]; -} - -/* - * Performs matrix multiplication - */ -Matrix Matrix::operator*(const Matrix &other) const -{ - return multiply(other); -} - -/* - * Returns a row of the matrix - */ -Matrix::RowView Matrix::operator[](int row) -{ - return RowView {*this, row}; -} - -/* - * Returns a row of the matrix - */ -Matrix::ConstRowView Matrix::operator[](int row) const -{ - return ConstRowView {*this, row}; -} - -/* - * Checks whether the two matrices are equal - */ -bool Matrix::operator==(const Matrix& other) const -{ - for (int i = 0; i < countof(m_values); ++i) - { - if (not qFuzzyCompare(m_values[i], other.m_values[i])) - return false; - } - return true; -} - -/** - * @brief Matrix::operator != - * @param other - * @return whether the two matrices are not equal - */ -bool Matrix::operator!=(const Matrix& other) const -{ - return not operator==(other); -} - -double& Matrix::operator()(int row, int column) -{ - return m_values[row * 3 + column]; -} - -const double& Matrix::operator()(int row, int column) const -{ - return m_values[row * 3 + column]; -} - -double* Matrix::begin() -{ - return m_values; -} - -const double* Matrix::begin() const -{ - return m_values; -} - -double* Matrix::end() -{ - return m_values + countof(m_values); -} - -const double* Matrix::end() const -{ - return m_values + countof(m_values); -} - -Matrix::RowView::RowView(Matrix &matrix, int row) : - _matrix {matrix}, - _row {row} {} - -double& Matrix::RowView::operator[](int column) -{ - return _matrix.value(_row * 3 + column); -} - -Matrix& Matrix::RowView::matrix() const -{ - return _matrix; -} - -int Matrix::RowView::row() -{ - return _row; -} - -Matrix::ConstRowView::ConstRowView(const Matrix &matrix, int row) : - _matrix {matrix}, - _row {row} {} - -const double& Matrix::ConstRowView::operator[](int column) -{ - return _matrix.value(_row * 3 + column); -} - -const Matrix& Matrix::ConstRowView::matrix() const -{ - return _matrix; -} - -int Matrix::ConstRowView::row() -{ - return _row; -} - -Matrix Matrix::fromQMatrix(const QMatrix4x4& matrix) -{ - Matrix result; - - for (int i = 0; i < 3; ++i) - for (int j = 0; j < 3; ++j) - result(i, j) = matrix(i, j); - - return result; -} - -Matrix Matrix::scaleMatrix(qreal scalar) -{ - return { - scalar, 0, 0, - 0, scalar, 0, - 0, 0, scalar - }; -} - -Matrix& Matrix::operator*=(const Matrix& other) -{ - *this = *this * other; - return *this; -}
--- a/src/types/matrix.h Sun Jun 10 23:25:08 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -/* - * 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 <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <QString> -#include <QMetaType> - -/* - * A mathematical 3 × 3 matrix - */ -class Matrix -{ -public: - class RowView; - class ConstRowView; - - Matrix(); - Matrix (const std::initializer_list<double>& values); - Matrix (double fillval); - - double* begin(); - const double* begin() const; - double determinant() const; - double* end(); - const double* end() const; - Matrix multiply(const Matrix& other) const; - QString toString() const; - double& value(int index); - const double& value(int index) const; - void zero(); - - bool operator==(const Matrix& other) const; - bool operator!=(const Matrix& other) const; - Matrix operator*(const Matrix& other) const; - RowView operator[](int row); - ConstRowView operator[](int row) const; - double& operator()(int row, int column); - const double& operator()(int row, int column) const; - Matrix& operator*=(const Matrix& other); - - static const Matrix identity; - static Matrix fromQMatrix(const QMatrix4x4& matrix); - static Matrix scaleMatrix(qreal scalar); - -private: - double m_values[9]; -}; - -Q_DECLARE_METATYPE(Matrix) - -/* - * A structure that provides a view into a row in a matrix. - * This is returned by operator[] so that the matrix can be accessed by A[i][j] - */ -class Matrix::RowView -{ -public: - RowView(Matrix &matrix, int row); - double& operator[](int column); - Matrix& matrix() const; - int row(); - -private: - Matrix& _matrix; - const int _row; -}; - -/* - * Const version of the above - */ -class Matrix::ConstRowView -{ -public: - ConstRowView(const Matrix &matrix, int row); - const double& operator[](int column); - const Matrix& matrix() const; - int row(); - -private: - const Matrix& _matrix; - const int _row; -};
--- a/src/types/vertex.cpp Sun Jun 10 23:25:08 2018 +0300 +++ b/src/types/vertex.cpp Sun Jun 17 13:53:33 2018 +0300 @@ -19,14 +19,28 @@ #include "vertex.h" #include "../format.h" -void Vertex::transform(const Matrix& matrix, const Vertex& pos) +template<typename MatrixType> +void transformVertex(Vertex& vertex, const MatrixType& matrix) { - double x2 = (matrix(0, 0) * x) + (matrix(0, 1) * y) + (matrix(0, 2) * z) + pos.x; - double y2 = (matrix(1, 0) * x) + (matrix(1, 1) * y) + (matrix(1, 2) * z) + pos.y; - double z2 = (matrix(2, 0) * x) + (matrix(2, 1) * y) + (matrix(2, 2) * z) + pos.z; - this->x = x2; - this->y = y2; - this->z = z2; + double newX = (matrix(0, 0) * vertex.x) + (matrix(0, 1) * vertex.y) + (matrix(0, 2) * vertex.z); + double newY = (matrix(1, 0) * vertex.x) + (matrix(1, 1) * vertex.y) + (matrix(1, 2) * vertex.z); + double newZ = (matrix(2, 0) * vertex.x) + (matrix(2, 1) * vertex.y) + (matrix(2, 2) * vertex.z); + vertex.x = newX; + vertex.y = newY; + vertex.z = newZ; +} + +void Vertex::transform(const QMatrix4x4& matrix) +{ + transformVertex(*this, matrix); + x += matrix(0, 3); + y += matrix(1, 3); + z += matrix(2, 3); +} + +void Vertex::rotate(const QQuaternion& orientation) +{ + *this = Vertex {0, 0, 0} + orientation.rotatedVector(toVector()); } void Vertex::apply(ApplyFunction func)
--- a/src/types/vertex.h Sun Jun 10 23:25:08 2018 +0300 +++ b/src/types/vertex.h Sun Jun 17 13:53:33 2018 +0300 @@ -32,7 +32,8 @@ void apply(ApplyConstFunction func) const; QString toString(bool mangled = false) const; QVector3D toVector() const; - void transform(const class Matrix& matrix, const Vertex& pos); + void transform(const QMatrix4x4& matrix); + void rotate(const QQuaternion& orientation); Vertex transformed(const GLRotationMatrix& matrix) const; void setCoordinate(Axis ax, qreal value);
--- a/src/widgets/matrixeditor.cpp Sun Jun 10 23:25:08 2018 +0300 +++ b/src/widgets/matrixeditor.cpp Sun Jun 17 13:53:33 2018 +0300 @@ -1,12 +1,11 @@ #include "matrixeditor.h" #include "ui_matrixeditor.h" -MatrixEditor::MatrixEditor(const Matrix& matrix, const Vertex& position, QWidget *parent) : +MatrixEditor::MatrixEditor(const QMatrix4x4& matrix, QWidget *parent) : QWidget {parent}, ui {*new Ui_MatrixEditor} { this->ui.setupUi(this); - this->setPosition(position); this->setMatrix(matrix); for (int i : {0, 1, 2}) @@ -32,7 +31,7 @@ } MatrixEditor::MatrixEditor(QWidget* parent) : - MatrixEditor {Matrix::identity, {0, 0, 0}, parent} {} + MatrixEditor {{}, parent} {} MatrixEditor::~MatrixEditor() { @@ -152,18 +151,9 @@ catch (const std::out_of_range&) {} } -Vertex MatrixEditor::position() const +QMatrix4x4 MatrixEditor::matrix() const { - return { - this->ui.positionX->value(), - this->ui.positionY->value(), - this->ui.positionZ->value() - }; -} - -Matrix MatrixEditor::matrix() const -{ - Matrix transformationMatrix; + QMatrix4x4 transformationMatrix; for (int i : {0, 1, 2}) for (int j : {0, 1, 2}) @@ -171,17 +161,11 @@ transformationMatrix(i, j) = this->matrixCell(i, j)->value(); } + transformationMatrix.translate(ui.positionX->value(), ui.positionY->value(), ui.positionZ->value()); return transformationMatrix; } -void MatrixEditor::setPosition(const Vertex& position) -{ - this->ui.positionX->setValue(position.x); - this->ui.positionY->setValue(position.y); - this->ui.positionZ->setValue(position.z); -} - -void MatrixEditor::setMatrix(const Matrix& matrix) +void MatrixEditor::setMatrix(const QMatrix4x4& matrix) { for (int i : {0, 1, 2}) for (int j : {0, 1, 2}) @@ -190,6 +174,10 @@ withSignalsBlocked(spinbox, [&](){ spinbox->setValue(matrix(i, j)); }); } + ui.positionX->setValue(matrix(0, 3)); + ui.positionY->setValue(matrix(1, 3)); + ui.positionZ->setValue(matrix(2, 3)); + // Fill in the initial scaling values for (int column : {0, 1, 2}) {
--- a/src/widgets/matrixeditor.h Sun Jun 10 23:25:08 2018 +0300 +++ b/src/widgets/matrixeditor.h Sun Jun 17 13:53:33 2018 +0300 @@ -10,18 +10,12 @@ Q_OBJECT public: - MatrixEditor( - const Matrix& matrix = Matrix::identity, - const Vertex& position = {0, 0, 0}, - QWidget* parent = nullptr - ); + MatrixEditor(const QMatrix4x4& matrix = {}, QWidget* parent = nullptr); MatrixEditor(QWidget* parent); ~MatrixEditor(); - Vertex position() const; - Matrix matrix() const; - void setPosition(const Vertex& position); - void setMatrix(const Matrix& matrix); + QMatrix4x4 matrix() const; + void setMatrix(const QMatrix4x4& matrix); private slots: void scalingChanged();