Fri, 13 Dec 2019 15:55:56 +0200
added teapot rendering
CMakeLists.txt | file | annotate | diff | comparison | revisions | |
locale/fi.ts | file | annotate | diff | comparison | revisions | |
src/basics.h | file | annotate | diff | comparison | revisions | |
src/document.ui | file | annotate | diff | comparison | revisions | |
src/documentmanager.cpp | file | annotate | diff | comparison | revisions | |
src/gl/partrenderer.cpp | file | annotate | diff | comparison | revisions | |
src/gl/partrenderer.h | file | annotate | diff | comparison | revisions | |
src/linetypes/object.cpp | file | annotate | diff | comparison | revisions | |
src/linetypes/object.h | file | annotate | diff | comparison | revisions | |
src/main.cpp | file | annotate | diff | comparison | revisions | |
src/matrix.h | file | annotate | diff | comparison | revisions | |
src/vertex.h | file | annotate | diff | comparison | revisions |
--- a/CMakeLists.txt Fri Nov 08 19:05:07 2019 +0200 +++ b/CMakeLists.txt Fri Dec 13 15:55:56 2019 +0200 @@ -10,14 +10,17 @@ find_package(Qt5OpenGL REQUIRED) find_package(Qt5Network REQUIRED) find_package(Qt5LinguistTools REQUIRED) +find_package(GLUT REQUIRED) set (CMAKE_AUTOMOC ON) find_package(OpenGL REQUIRED) include_directories(${QT_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR}) +include_directories(${GLUT_INCLUDE_DIR}) set (LDFORGE_SOURCES src/document.cpp src/documentmanager.cpp src/libraries.cpp + src/invert.cpp src/main.cpp src/mainwindow.cpp src/matrix.cpp @@ -27,6 +30,8 @@ src/uiutilities.cpp src/version.cpp src/vertex.cpp + src/gl/compiler.cpp + src/gl/partrenderer.cpp src/linetypes/comment.cpp src/linetypes/conditionaledge.cpp src/linetypes/edge.cpp @@ -39,12 +44,14 @@ src/settingseditor/keyboardshortcutseditor.cpp src/settingseditor/librarieseditor.cpp src/settingseditor/settingseditor.cpp + src/types/boundingbox.cpp ) set (LDFORGE_HEADERS src/basics.h src/colors.h src/document.h src/documentmanager.h + src/invert.h src/libraries.h src/main.h src/mainwindow.h @@ -52,10 +59,14 @@ src/model.h src/modeleditcontext.h src/parser.h + src/ring.h src/uiutilities.h src/utility.h src/version.h src/vertex.h + src/gl/common.h + src/gl/compiler.h + src/gl/partrenderer.h src/linetypes/comment.h src/linetypes/conditionaledge.h src/linetypes/edge.h @@ -68,6 +79,7 @@ src/settingseditor/keyboardshortcutseditor.h src/settingseditor/librarieseditor.h src/settingseditor/settingseditor.h + src/types/boundingbox.h ) set (LDFORGE_FORMS src/document.ui @@ -127,6 +139,7 @@ set_source_files_properties(${LDFORGE_RESOURCES} PROPERTIES HEADER_FILE_ONLY TRUE) set_target_properties(ldforge PROPERTIES AUTOMOC 1) target_link_libraries(ldforge Qt5::Widgets Qt5::Network Qt5::OpenGL ${OPENGL_LIBRARIES}) +target_link_libraries(ldforge ${GLUT_LIBRARIES}) cotire(ldforge) # Collect the current hg revision into hginfo.h
--- a/locale/fi.ts Fri Nov 08 19:05:07 2019 +0200 +++ b/locale/fi.ts Fri Dec 13 15:55:56 2019 +0200 @@ -205,7 +205,7 @@ </message> <message> <location filename="../src/settingseditor/settingseditor.ui" line="38"/> - <location filename="../src/settingseditor/settingseditor.cpp" line="49"/> + <location filename="../src/settingseditor/settingseditor.cpp" line="54"/> <source>System language</source> <translation type="unfinished"></translation> </message>
--- a/src/basics.h Fri Nov 08 19:05:07 2019 +0200 +++ b/src/basics.h Fri Dec 13 15:55:56 2019 +0200 @@ -66,4 +66,5 @@ return one; } +constexpr double infinity = std::numeric_limits<double>::infinity(); static constexpr long double pi = M_PIl;
--- a/src/document.ui Fri Nov 08 19:05:07 2019 +0200 +++ b/src/document.ui Fri Dec 13 15:55:56 2019 +0200 @@ -19,12 +19,19 @@ <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <widget class="QOpenGLWidget" name="viewport"/> + <widget class="PartRenderer" name="viewport"/> <widget class="QListView" name="listView"/> </widget> </item> </layout> </widget> + <customwidgets> + <customwidget> + <class>PartRenderer</class> + <extends>QOpenGLWidget</extends> + <header>gl/partrenderer.h</header> + </customwidget> + </customwidgets> <resources/> <connections/> </ui>
--- a/src/documentmanager.cpp Fri Nov 08 19:05:07 2019 +0200 +++ b/src/documentmanager.cpp Fri Dec 13 15:55:56 2019 +0200 @@ -55,7 +55,7 @@ const QString baseName = path.fileName(); const QString dirName = QFileInfo{path.dir().path()}.fileName(); QString result; - if (utility::contains(paths, dirName)) + if (std::find(std::begin(paths), std::end(paths), dirName) != std::end(paths)) { result = dirName + "\\" + baseName; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gl/partrenderer.cpp Fri Dec 13 15:55:56 2019 +0200 @@ -0,0 +1,118 @@ +#include <QMouseEvent> +#include <GL/glut.h> // teapot +#include "partrenderer.h" + +PartRenderer::PartRenderer(QWidget* parent) : + QOpenGLWidget{parent} +{ + this->setMouseTracking(true); +} + +void PartRenderer::initializeGL() +{ + this->initializeOpenGLFunctions(); + if (this->glGetError() != GL_NO_ERROR) + { + abort(); + } + this->initializeLighting(); + this->initialized = true; + this->rotation = QQuaternion::fromAxisAndAngle({1, 0, 0}, 30); + this->rotation *= QQuaternion::fromAxisAndAngle({0, 1, 0}, 330); +} + +// https://stackoverflow.com/a/12943456 +static void perspectiveGL(GLdouble fovY, GLdouble aspect, GLdouble zNear, GLdouble zFar) +{ + //fH = tan( (fovY / 2) / 180 * pi ) * zNear; + const GLdouble fH = std::tan(fovY / 360 * pi) * zNear; + const GLdouble fW = fH * aspect; + glFrustum(-fW, fW, -fH, fH, zNear, zFar); +} + +/* + * Pads a 3×3 matrix into a 4×4 one by adding cells from the identity matrix. + */ +static QMatrix4x4 padMatrix(const QMatrix3x3& stub) +{ + return { + stub(0, 0), stub(0, 1), stub(0, 2), 0, + stub(1, 0), stub(1, 1), stub(1, 2), 0, + stub(2, 0), stub(2, 1), stub(2, 2), 0, + 0, 0, 0, 1 + }; +} + + +void PartRenderer::initializeLighting() +{ + GLfloat materialShininess[] = {5.0}; + GLfloat lightPosition[] = {1.0, 1.0, 1.0, 0.0}; + GLfloat ambientLightingLevel[] = {0.5, 0.5, 0.5, 1.0}; + glShadeModel(GL_SMOOTH); + glMaterialfv(GL_FRONT, GL_SHININESS, materialShininess); + glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLightingLevel); + glLightfv(GL_LIGHT0, GL_DIFFUSE, ambientLightingLevel); + glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_COLOR_MATERIAL); + glEnable(GL_DEPTH_TEST); +} + +void PartRenderer::resizeGL(int width, int height) +{ + constexpr GLfloat near = 1.0f; + constexpr GLfloat far = 1.0e+05f; + glViewport (0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + ::perspectiveGL(45.0f, static_cast<double>(width) / static_cast<double>(height), near, far); + glMatrixMode(GL_MODELVIEW); +} + +// https://www.codemiles.com/c-opengl-examples/drawing-teapot-using-opengl-t9010.html?mobile=on +void PartRenderer::paintGL() +{ + glMatrixMode(GL_MODELVIEW); + // clear the drawing buffer. + glClear(GL_COLOR_BUFFER_BIT); + // clear the identity matrix. + glLoadIdentity(); + // traslate the draw by z = -4.0 + // Note this when you decrease z like -8.0 the drawing will looks far , or smaller. + glTranslatef(0.0,0.0,-4.5); + // Red color used to draw. + glColor3f(0.8, 0.2, 0.1); + glMultMatrixf(padMatrix(this->rotation.toRotationMatrix()).constData()); + glutSolidTeapot(1.0); + glFlush(); +} + +static QPointF pointToPointF(const QPoint& point) +{ + return {static_cast<qreal>(point.x()), static_cast<qreal>(point.y())}; +} + +/* +static QPoint pointFToPoint(const QPointF& point) +{ + return {static_cast<int>(std::round(point.x())), static_cast<int>(std::round(point.y()))}; +} +*/ + +void PartRenderer::mouseMoveEvent(QMouseEvent* event) +{ + const bool left = event->buttons() & Qt::LeftButton; + const QPointF move = pointToPointF(event->pos()) - this->lastMousePosition; + if (left and not move.isNull()) + { + const QQuaternion versor = QQuaternion::fromAxisAndAngle( + QVector3D{static_cast<float>(move.y()), static_cast<float>(move.x()), 0.0f}, + 0.6 * std::hypot(move.x(), move.y()) + ); + this->rotation = versor * this->rotation; + this->update(); + } + this->lastMousePosition = pointToPointF(event->pos()); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gl/partrenderer.h Fri Dec 13 15:55:56 2019 +0200 @@ -0,0 +1,21 @@ +#pragma once +#include <QOpenGLWidget> +#include <QOpenGLFunctions> +#include <QQuaternion> +#include "main.h" + +class PartRenderer : public QOpenGLWidget, protected QOpenGLFunctions +{ +public: + PartRenderer(QWidget* parent = nullptr); +protected: + void initializeGL() override; + void resizeGL(int width, int height) override; + void paintGL() override; + void mouseMoveEvent(QMouseEvent* event) override; +private: + QPointF lastMousePosition; + bool initialized = false; + QQuaternion rotation; + void initializeLighting(); +};
--- a/src/linetypes/object.cpp Fri Nov 08 19:05:07 2019 +0200 +++ b/src/linetypes/object.cpp Fri Dec 13 15:55:56 2019 +0200 @@ -2,15 +2,6 @@ #include <QFont> #include "object.h" -/* -static Uuid &getUuidForNewObject() -{ - static Uuid running_uuid {0, 0}; - incrementUuid(running_uuid); - return running_uuid; -} -*/ - static unsigned int getIdForNewObject() { static unsigned int id = 0;
--- a/src/linetypes/object.h Fri Nov 08 19:05:07 2019 +0200 +++ b/src/linetypes/object.h Fri Dec 13 15:55:56 2019 +0200 @@ -8,6 +8,7 @@ namespace linetypes { + struct Id { unsigned int value; }; enum class Property; class Object; class ColoredObject; @@ -46,7 +47,7 @@ Object(); Object(const Object&) = delete; virtual ~Object(); - const unsigned int id; + const Id id; //virtual void toString(QTextStream &out) = 0; virtual bool hasColor() const; virtual QVariant getProperty(Property id) const; @@ -75,8 +76,3 @@ { QString textRepresentation() const override; }; - -namespace linetypes -{ - using Id = std::decay_t<decltype(Object::id)>; -}
--- a/src/main.cpp Fri Nov 08 19:05:07 2019 +0200 +++ b/src/main.cpp Fri Dec 13 15:55:56 2019 +0200 @@ -1,11 +1,15 @@ #include <QApplication> #include <QDir> +#include <QtDebug> +#include <GL/glut.h> #include "main.h" #include "mainwindow.h" #include "version.h" +#include "matrix.h" int main(int argc, char *argv[]) { + ::glutInit(&argc, argv); QCoreApplication::setApplicationName(::appName); QCoreApplication::setOrganizationName("hecknology.net"); QCoreApplication::setOrganizationDomain("hecknology.net");
--- a/src/matrix.h Fri Nov 08 19:05:07 2019 +0200 +++ b/src/matrix.h Fri Dec 13 15:55:56 2019 +0200 @@ -1,10 +1,30 @@ #pragma once #include <QGenericMatrix> +#include <type_traits> + +template<int Rows, int Columns, typename T = double> +struct MatrixIterator; + +template<int Rows, int Columns> +struct MatrixIndex +{ + int row; + int column; +}; template<int Rows, int Columns, typename T = double> struct Matrix { + using Iterator = MatrixIterator<Rows, Columns, T>; T values[Rows][Columns]; + Iterator begin() + { + return {*this, {0, 0}}; + } + Iterator end() + { + return {*this, {Rows, 0}}; + } T& operator()(int row, int column) { return this->values[row][column]; @@ -13,9 +33,78 @@ { return this->values[row][column]; } + T& operator[](const MatrixIndex<Rows, Columns>& index) + { + return (*this)(index.row, index.column); + } + T operator[](const MatrixIndex<Rows, Columns>& index) const + { + return (*this)(index.row, index.column); + } }; template<int Rows, int Columns, typename T> +struct MatrixIterator +{ + struct Value + { + const MatrixIndex<Rows, Columns> index; + decltype(std::declval<Matrix<Rows, Columns, T>>()(0, 0)) value; + }; + Matrix<Rows, Columns, T>& matrix; + MatrixIndex<Rows, Columns> index; +}; + +template<int Rows, int Columns> +auto& operator++(MatrixIndex<Rows, Columns>& index) +{ + index.column += 1; + if (index.column >= Columns) + { + index.row += 1; + index.column -= Columns; + } + return index; +} + +template<int Rows, int Columns> +bool operator==( + const MatrixIndex<Rows, Columns>& one, + const MatrixIndex<Rows, Columns>& other) +{ + return one.row == other.row and one.column == other.column; +} +template<int Rows, int Columns, typename T> +auto& operator++(MatrixIterator<Rows, Columns, T>& iterator) +{ + ++iterator.index; + return iterator; +} + +template<int Rows, int Columns, typename T> +bool operator==( + const MatrixIterator<Rows, Columns, T>& one, + const MatrixIterator<Rows, Columns, T>& other) +{ + return &one.matrix == &other.matrix and one.index == other.index; +} + +template<int Rows, int Columns, typename T> +bool operator!=( + const MatrixIterator<Rows, Columns, T>& one, + const MatrixIterator<Rows, Columns, T>& other) +{ + return not (one == other); +} + +template<int Rows, int Columns, typename T> +auto operator*(MatrixIterator<Rows, Columns, T>& iterator) + -> typename MatrixIterator<Rows, Columns, T>::Value +{ + return {iterator.index, iterator.matrix[iterator.index]}; +} + +template<int Rows, int Columns, typename T> QGenericMatrix<Rows, Columns, T> matrixToQGenericMatrix(const Matrix<Rows, Columns, T>& matrix) { return {matrix.values}; @@ -25,12 +114,9 @@ Matrix<Rows, Columns, T> matrixFromQGenericMatrix(const QGenericMatrix<Rows, Columns, T&> matrix) { Matrix<Rows, Columns, T> result; - for (int row = 0; row < Rows; row += 1) + for (auto& cell : result) { - for (int column = 0; column < Columns; column += 1) - { - result(row, column) = matrix(row, column); - } + matrix(cell.index.row, cell.index.column) = result[cell.index]; } return result; } @@ -43,14 +129,22 @@ template<int Rows, int Columns, typename T> QDataStream& operator<<(QDataStream& stream, const Matrix<Rows, Columns, T>& matrix) { - return stream << matrixToQGenericMatrix(matrix); + for (auto& cell : matrix) + { + stream << cell.value; + } + return stream; } template<int Rows, int Columns, typename T> QDataStream& operator>>(QDataStream& stream, Matrix<Rows, Columns, T>& matrix) { - QGenericMatrix<Rows, Columns, T> qmatrix; - stream >> qmatrix; - matrix = matrixFromQGenericMatrix(matrix); + for (auto& cell : matrix) + { + stream >> cell.value; + } return stream; } + +static constexpr Matrix3x3 identity3x3 {{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}}; +static constexpr Matrix4x4 identity4x4 {{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}};