added teapot rendering

Fri, 13 Dec 2019 15:55:56 +0200

author
Teemu Piippo <teemu@hecknology.net>
date
Fri, 13 Dec 2019 15:55:56 +0200
changeset 17
a5111f4e6412
parent 16
aeb5f203b3eb
child 18
918b6c0f8b5b

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}}};
--- a/src/vertex.h	Fri Nov 08 19:05:07 2019 +0200
+++ b/src/vertex.h	Fri Dec 13 15:55:56 2019 +0200
@@ -23,7 +23,7 @@
 
 struct Vertex
 {
-	using ValueType = float;
+	using ValueType = double;
 	ValueType x;
 	ValueType y;
 	ValueType z;

mercurial