Added axes rendering

Fri, 06 Mar 2020 20:13:10 +0200

author
Teemu Piippo <teemu@hecknology.net>
date
Fri, 06 Mar 2020 20:13:10 +0200
changeset 70
f21b800b02a4
parent 69
a36913fc552a
child 71
198d25fe4e21

Added axes rendering

CMakeLists.txt file | annotate | diff | comparison | revisions
src/basics.h file | annotate | diff | comparison | revisions
src/gl/axesprogram.cpp file | annotate | diff | comparison | revisions
src/gl/axesprogram.h file | annotate | diff | comparison | revisions
src/gl/basicshaderprogram.cpp file | annotate | diff | comparison | revisions
src/gl/basicshaderprogram.h file | annotate | diff | comparison | revisions
src/gl/gridprogram.cpp file | annotate | diff | comparison | revisions
src/gl/gridprogram.h file | annotate | diff | comparison | revisions
src/gl/partrenderer.cpp file | annotate | diff | comparison | revisions
src/gl/partrenderer.h file | annotate | diff | comparison | revisions
src/ui/canvas.cpp file | annotate | diff | comparison | revisions
src/ui/canvas.h file | annotate | diff | comparison | revisions
--- a/CMakeLists.txt	Fri Mar 06 16:08:53 2020 +0200
+++ b/CMakeLists.txt	Fri Mar 06 20:13:10 2020 +0200
@@ -36,6 +36,7 @@
 	src/uiutilities.cpp
 	src/version.cpp
 	src/gl/axesprogram.cpp
+	src/gl/basicshaderprogram.cpp
 	src/gl/compiler.cpp
 	src/gl/gridprogram.cpp
 	src/gl/partrenderer.cpp
@@ -76,6 +77,7 @@
 	src/utility.h
 	src/version.h
 	src/gl/axesprogram.h
+	src/gl/basicshaderprogram.h
 	src/gl/common.h
 	src/gl/compiler.h
 	src/gl/gridprogram.h
--- a/src/basics.h	Fri Mar 06 16:08:53 2020 +0200
+++ b/src/basics.h	Fri Mar 06 20:13:10 2020 +0200
@@ -151,5 +151,9 @@
 	return {point.x(), point.y()};
 }
 
+constexpr float PIf = static_cast<float>(M_PI);
+constexpr double PI = M_PI;
+constexpr long double PIl = M_PIl;
+
 Q_DECLARE_METATYPE(glm::vec3)
 Q_DECLARE_METATYPE(glm::mat4)
--- a/src/gl/axesprogram.cpp	Fri Mar 06 16:08:53 2020 +0200
+++ b/src/gl/axesprogram.cpp	Fri Mar 06 20:13:10 2020 +0200
@@ -16,7 +16,7 @@
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "gridprogram.h"
+#include "axesprogram.h"
 
 // Based on https://stackoverflow.com/q/30842755
 const char vertexShaderSource[] = R"(
@@ -31,8 +31,8 @@
 
 void main()
 {
-	gl_Position = projection * view * model * vec4(in_position, 0.0, 1.0);
-	ex_uv = ex_color;
+	gl_Position = projection * view * model * vec4(in_position, 1.0);
+	ex_color = in_color;
 }
 )";
 
@@ -44,7 +44,7 @@
 
 void main(void)
 {
-	color = vec4(ex_color, 1)
+	color = vec4(ex_color, 1);
 }
 )";
 
@@ -67,102 +67,43 @@
 	AxesVertex{{0, 0, 10000}, {0, 0, 1}},
 };
 
-AxesProgram::AxesProgram(QObject* parent) :
-	QObject{parent},
-	buffer{QOpenGLBuffer::VertexBuffer},
-	vertexShader{QOpenGLShader::Vertex},
-	fragmentShader{QOpenGLShader::Fragment}
+const char* AxesProgram::vertexShaderSource() const
 {
+	return ::vertexShaderSource;
 }
 
-void AxesProgram::initialize()
+const char* AxesProgram::fragmentShaderSource() const
 {
-	if (not isInitialized)
-	{
-		this->initializeOpenGLFunctions();
-		this->isInitialized = true;
-		this->program.emplace(this);
-		gl::buildShaders(&*this->program, ::vertexShaderSource, ::fragmentShaderSource);
-		this->program->bind();
-		this->buffer.create();
-		this->buffer.bind();
-		this->buffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
-		this->buffer.allocate(data, countof(data) * sizeof data[0]);
-		this->vertexArrayObject.create();
-		this->vertexArrayObject.bind();
-		this->program->enableAttributeArray(0);
-		this->program->setAttributeBuffer(0, GL_FLOAT, 0, 2, 0);
-		this->program->setUniformVector("gridColor", this->gridColor);
-		this->vertexArrayObject.release();
-		this->buffer.release();
-		this->program->release();
-		this->checkForGLErrors();
-	}
+	return ::fragmentShaderSource;
 }
 
-void AxesProgram::setViewMatrix(const glm::mat4& newViewMatrix)
+const void* AxesProgram::vertexData() const
 {
-	this->setMatrix("view", newViewMatrix);
+	return ::data;
 }
 
-void AxesProgram::setProjectionMatrix(const glm::mat4& newProjectionMatrix)
+GLenum AxesProgram::drawMode() const
 {
-	this->setMatrix("projection", newProjectionMatrix);
-}
-
-void AxesProgram::setModelMatrix(const glm::mat4& newModelMatrix)
-{
-	this->setMatrix("model", newModelMatrix);
+	return GL_LINES;
 }
 
-void AxesProgram::setGridMatrix(const glm::mat4& newGridMatrix)
+int AxesProgram::vertexSize() const
 {
-	this->setMatrix("grid", newGridMatrix);
+	return sizeof data[0];
 }
 
-void AxesProgram::setMatrix(const char* name, const glm::mat4& matrix)
+int AxesProgram::vertexCount() const
 {
-	Q_ASSERT(this->isInitialized);
-	this->program->bind();
-	this->program->setUniformMatrix(name, matrix);
-	this->program->release();
-	this->checkForGLErrors();
+	return countof(data);
 }
 
-void GridProgram::setGridColor(const QColor& newGridColor)
-{
-	const glm::vec4 vec = gl::colorToVector4(newGridColor);
-	if (this->isInitialized)
-	{
-		this->program->bind();
-		this->program->setUniformVector("gridColor", vec);
-		this->program->release();
-		this->checkForGLErrors();
-	}
-	else
-	{
-		this->gridColor = vec;
-	}
-}
-
-void GridProgram::draw()
+void AxesProgram::setupVertexArrays()
 {
-	this->program->bind();
-	this->vertexArrayObject.bind();
-	glDrawArrays(GL_QUADS, 0, countof(data));
-	this->vertexArrayObject.release();
-	this->program->release();
-	this->checkForGLErrors();
+	for (int i : {0, 1})
+	{
+		this->program->enableAttributeArray(i);
+	}
+	const int stride = this->vertexSize();
+	this->program->setAttributeBuffer(0, GL_FLOAT, offsetof(AxesVertex, position), 3, stride);
+	this->program->setAttributeBuffer(1, GL_FLOAT, offsetof(AxesVertex, color), 3, stride);
 }
-
-void GridProgram::teardown()
-{
-	this->vertexArrayObject.destroy();
-	this->buffer.destroy();
-	this->program.reset();
-}
-
-void GridProgram::checkForGLErrors()
-{
-	gl::checkForGLErrors(qobject_cast<QWidget*>(this->parent()));
-}
--- a/src/gl/axesprogram.h	Fri Mar 06 16:08:53 2020 +0200
+++ b/src/gl/axesprogram.h	Fri Mar 06 20:13:10 2020 +0200
@@ -1,11 +1,18 @@
-#ifndef AXESPROGRAM_H
-#define AXESPROGRAM_H
+#pragma once
+#include "gl/common.h"
+#include "gl/basicshaderprogram.h"
 
-
-class AxesProgram
+class AxesProgram : public AbstractBasicShaderProgram
 {
+	Q_OBJECT
 public:
-	AxesProgram();
+	using AbstractBasicShaderProgram::AbstractBasicShaderProgram;
+protected:
+	const char* vertexShaderSource() const override;
+	const char* fragmentShaderSource() const override;
+	const void* vertexData() const override;
+	GLenum drawMode() const override;
+	int vertexSize() const override;
+	int vertexCount() const override;
+	void setupVertexArrays() override;
 };
-
-#endif // AXESPROGRAM_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gl/basicshaderprogram.cpp	Fri Mar 06 20:13:10 2020 +0200
@@ -0,0 +1,96 @@
+/*
+ *  LDForge: LDraw parts authoring CAD
+ *  Copyright (C) 2020 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 "basicshaderprogram.h"
+
+AbstractBasicShaderProgram::AbstractBasicShaderProgram(QObject* parent) :
+	QObject{parent},
+	buffer{QOpenGLBuffer::VertexBuffer},
+	vertexShader{QOpenGLShader::Vertex},
+	fragmentShader{QOpenGLShader::Fragment}
+{
+}
+
+void AbstractBasicShaderProgram::initialize()
+{
+	if (not isInitialized)
+	{
+		this->initializeOpenGLFunctions();
+		this->isInitialized = true;
+		this->program.emplace(this);
+		gl::buildShaders(&*this->program, this->vertexShaderSource(), this->fragmentShaderSource());
+		this->program->bind();
+		this->buffer.create();
+		this->buffer.bind();
+		this->buffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
+		this->buffer.allocate(this->vertexData(), this->vertexCount() * this->vertexSize());
+		this->vertexArrayObject.create();
+		this->vertexArrayObject.bind();
+		this->setupVertexArrays();
+		this->vertexArrayObject.release();
+		this->buffer.release();
+		this->program->release();
+		this->checkForGLErrors();
+	}
+}
+
+void AbstractBasicShaderProgram::setViewMatrix(const glm::mat4& newViewMatrix)
+{
+	this->setMatrix("view", newViewMatrix);
+}
+
+void AbstractBasicShaderProgram::setProjectionMatrix(const glm::mat4& newProjectionMatrix)
+{
+	this->setMatrix("projection", newProjectionMatrix);
+}
+
+void AbstractBasicShaderProgram::setModelMatrix(const glm::mat4& newModelMatrix)
+{
+	this->setMatrix("model", newModelMatrix);
+}
+
+void AbstractBasicShaderProgram::setMatrix(const char* name, const glm::mat4& matrix)
+{
+	Q_ASSERT(this->isInitialized);
+	this->program->bind();
+	this->program->setUniformMatrix(name, matrix);
+	this->program->release();
+	this->checkForGLErrors();
+}
+
+void AbstractBasicShaderProgram::draw()
+{
+	this->program->bind();
+	this->vertexArrayObject.bind();
+	glDrawArrays(this->drawMode(), 0, this->vertexCount());
+	this->vertexArrayObject.release();
+	this->program->release();
+	this->checkForGLErrors();
+}
+
+void AbstractBasicShaderProgram::teardown()
+{
+	this->vertexArrayObject.destroy();
+	this->buffer.destroy();
+	this->program.reset();
+}
+
+void AbstractBasicShaderProgram::checkForGLErrors()
+{
+	gl::checkForGLErrors(qobject_cast<QWidget*>(this->parent()));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gl/basicshaderprogram.h	Fri Mar 06 20:13:10 2020 +0200
@@ -0,0 +1,32 @@
+#pragma once
+#include "common.h"
+
+class AbstractBasicShaderProgram : public QObject, protected QOpenGLFunctions
+{
+	Q_OBJECT
+public:
+	AbstractBasicShaderProgram(QObject* parent = nullptr);
+	~AbstractBasicShaderProgram() = default;
+	void initialize();
+	Q_SLOT void setViewMatrix(const glm::mat4& newViewMatrix);
+	Q_SLOT void setProjectionMatrix(const glm::mat4& newProjectionMatrix);
+	Q_SLOT void setModelMatrix(const glm::mat4& newModelMatrix);
+	void draw();
+	void teardown();
+protected:
+	void setMatrix(const char* name, const glm::mat4& matrix);
+	void checkForGLErrors();
+	virtual const char* vertexShaderSource() const = 0;
+	virtual const char* fragmentShaderSource() const = 0;
+	virtual const void* vertexData() const = 0;
+	virtual int vertexSize() const = 0;
+	virtual int vertexCount() const = 0;
+	virtual void setupVertexArrays() = 0;
+	virtual GLenum drawMode() const = 0;
+	bool isInitialized = false;
+	QOpenGLBuffer buffer;
+	QOpenGLShader vertexShader;
+	QOpenGLShader fragmentShader;
+	std::optional<gl::ShaderProgram> program{std::nullopt};
+	QOpenGLVertexArrayObject vertexArrayObject;
+};
--- a/src/gl/gridprogram.cpp	Fri Mar 06 16:08:53 2020 +0200
+++ b/src/gl/gridprogram.cpp	Fri Mar 06 20:13:10 2020 +0200
@@ -64,68 +64,11 @@
 
 static const glm::vec2 data[] = {{-1, -1}, {-1, 1}, {1, 1}, {1, -1}};
 
-GridProgram::GridProgram(QObject* parent) :
-	QObject{parent},
-	buffer{QOpenGLBuffer::VertexBuffer},
-	vertexShader{QOpenGLShader::Vertex},
-	fragmentShader{QOpenGLShader::Fragment}
-{
-}
-
-void GridProgram::initialize()
-{
-	if (not isInitialized)
-	{
-		this->initializeOpenGLFunctions();
-		this->isInitialized = true;
-		this->program.emplace(this);
-		gl::buildShaders(&*this->program, ::vertexShaderSource, ::fragmentShaderSource);
-		this->program->bind();
-		this->buffer.create();
-		this->buffer.bind();
-		this->buffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
-		this->buffer.allocate(data, countof(data) * sizeof data[0]);
-		this->vertexArrayObject.create();
-		this->vertexArrayObject.bind();
-		this->program->enableAttributeArray(0);
-		this->program->setAttributeBuffer(0, GL_FLOAT, 0, 2, 0);
-		this->program->setUniformVector("gridColor", this->gridColor);
-		this->vertexArrayObject.release();
-		this->buffer.release();
-		this->program->release();
-		this->checkForGLErrors();
-	}
-}
-
-void GridProgram::setViewMatrix(const glm::mat4& newViewMatrix)
-{
-	this->setMatrix("view", newViewMatrix);
-}
-
-void GridProgram::setProjectionMatrix(const glm::mat4& newProjectionMatrix)
-{
-	this->setMatrix("projection", newProjectionMatrix);
-}
-
-void GridProgram::setModelMatrix(const glm::mat4& newModelMatrix)
-{
-	this->setMatrix("model", newModelMatrix);
-}
-
 void GridProgram::setGridMatrix(const glm::mat4& newGridMatrix)
 {
 	this->setMatrix("grid", newGridMatrix);
 }
 
-void GridProgram::setMatrix(const char* name, const glm::mat4& matrix)
-{
-	Q_ASSERT(this->isInitialized);
-	this->program->bind();
-	this->program->setUniformMatrix(name, matrix);
-	this->program->release();
-	this->checkForGLErrors();
-}
-
 void GridProgram::setGridColor(const QColor& newGridColor)
 {
 	const glm::vec4 vec = gl::colorToVector4(newGridColor);
@@ -142,24 +85,39 @@
 	}
 }
 
-void GridProgram::draw()
+const char* GridProgram::vertexShaderSource() const
+{
+	return ::vertexShaderSource;
+}
+
+const char* GridProgram::fragmentShaderSource() const
 {
-	this->program->bind();
-	this->vertexArrayObject.bind();
-	glDrawArrays(GL_QUADS, 0, countof(data));
-	this->vertexArrayObject.release();
-	this->program->release();
-	this->checkForGLErrors();
+	return ::fragmentShaderSource;
+}
+
+const void* GridProgram::vertexData() const
+{
+	return ::data;
 }
 
-void GridProgram::teardown()
+int GridProgram::vertexSize() const
 {
-	this->vertexArrayObject.destroy();
-	this->buffer.destroy();
-	this->program.reset();
+	return sizeof data[0];
+}
+
+int GridProgram::vertexCount() const
+{
+	return countof(data);
 }
 
-void GridProgram::checkForGLErrors()
+void GridProgram::setupVertexArrays()
 {
-	gl::checkForGLErrors(qobject_cast<QWidget*>(this->parent()));
+	this->program->enableAttributeArray(0);
+	this->program->setAttributeBuffer(0, GL_FLOAT, 0, 2, 0);
+	this->program->setUniformVector("gridColor", this->gridColor);
 }
+
+GLenum GridProgram::drawMode() const
+{
+	return GL_QUADS;
+}
--- a/src/gl/gridprogram.h	Fri Mar 06 16:08:53 2020 +0200
+++ b/src/gl/gridprogram.h	Fri Mar 06 20:13:10 2020 +0200
@@ -17,33 +17,24 @@
  */
 
 #pragma once
+#include "basicshaderprogram.h"
 #include "common.h"
 
-class GridProgram : public QObject, protected QOpenGLFunctions
+class GridProgram : public AbstractBasicShaderProgram
 {
 	Q_OBJECT
 public:
-	GridProgram(QObject* parent = nullptr);
-	GridProgram(const GridProgram&) = delete;
-	GridProgram(GridProgram&&) = delete;
-	~GridProgram() = default;
-	void initialize();
-	void setViewMatrix(const glm::mat4& newViewMatrix);
-	void setProjectionMatrix(const glm::mat4& newProjectionMatrix);
-	void setModelMatrix(const glm::mat4& newModelMatrix);
+	using AbstractBasicShaderProgram::AbstractBasicShaderProgram;
 	void setGridMatrix(const glm::mat4& newGridMatrix);
 	void setGridColor(const QColor& newGridColor);
-	void operator=(GridProgram) = delete;
-	void draw();
-	void teardown();
+protected:
+	const char* vertexShaderSource() const override;
+	const char* fragmentShaderSource() const override;
+	const void* vertexData() const override;
+	int vertexSize() const override;
+	int vertexCount() const override;
+	void setupVertexArrays() override;
+	GLenum drawMode() const override;
 private:
-	void setMatrix(const char* name, const glm::mat4& matrix);
-	void checkForGLErrors();
-	bool isInitialized = false;
-	QOpenGLBuffer buffer;
-	QOpenGLShader vertexShader;
-	QOpenGLShader fragmentShader;
-	std::optional<gl::ShaderProgram> program{std::nullopt};
 	glm::vec4 gridColor = {1.0f, 1.0f, 1.0f, 0.75f};
-	QOpenGLVertexArrayObject vertexArrayObject;
 };
--- a/src/gl/partrenderer.cpp	Fri Mar 06 16:08:53 2020 +0200
+++ b/src/gl/partrenderer.cpp	Fri Mar 06 20:13:10 2020 +0200
@@ -80,7 +80,7 @@
 		0.1f,
 		10000.f);
 	this->compiler->setUniformMatrix("projectionMatrix", this->projectionMatrix);
-	emit projectionMatrixChanged();
+	emit projectionMatrixChanged(this->projectionMatrix);
 }
 
 static GLenum getGlTypeForArrayClass(const gl::ArrayClass vboClass)
@@ -192,14 +192,14 @@
 	const double z  = 2 * std::exp(this->zoom) * (1 + this->compiler->modelDistance());
 	this->viewMatrix = glm::lookAt(glm::vec3{0, 0, z}, {0, 0, 0}, {0, -1, 0});
 	this->compiler->setUniformMatrix("viewMatrix", this->viewMatrix);
-	emit this->viewMatrixChanged();
+	emit this->viewMatrixChanged(this->viewMatrix);
 }
 
 void PartRenderer::updateModelMatrix()
 {
 	this->modelMatrix = glm::mat4_cast(this->modelQuaternion);
 	this->compiler->setUniformMatrix("modelMatrix", modelMatrix);
-	emit this->modelMatrixChanged();
+	emit this->modelMatrixChanged(this->modelMatrix);
 	this->update();
 }
 
--- a/src/gl/partrenderer.h	Fri Mar 06 16:08:53 2020 +0200
+++ b/src/gl/partrenderer.h	Fri Mar 06 20:13:10 2020 +0200
@@ -46,9 +46,9 @@
 	QPoint lastMousePosition;
 	gl::RenderPreferences renderPreferences;
 signals:
-	void projectionMatrixChanged();
-	void modelMatrixChanged();
-	void viewMatrixChanged();
+	void projectionMatrixChanged(const glm::mat4& newMatrix);
+	void modelMatrixChanged(const glm::mat4& newMatrix);
+	void viewMatrixChanged(const glm::mat4& newMatrix);
 	void renderPreferencesChanged();
 private:
 	void setFragmentStyle(gl::FragmentStyle fragStyle);
--- a/src/ui/canvas.cpp	Fri Mar 06 16:08:53 2020 +0200
+++ b/src/ui/canvas.cpp	Fri Mar 06 20:13:10 2020 +0200
@@ -7,8 +7,7 @@
 	DocumentManager* documents,
 	const ldraw::ColorTable& colorTable,
 	QWidget* parent) :
-	PartRenderer{model, documents, colorTable, parent},
-	gridProgram{this}
+	PartRenderer{model, documents, colorTable, parent}
 {
 	this->setMouseTracking(true);
 }
@@ -70,12 +69,12 @@
 		if (angle_x < angle_y)
 		{
 			this->newStatusText("rotate by X axis");
-			this->gridMatrix = glm::rotate(this->gridMatrix, float{M_PI} / 2, glm::vec3{1, 0, 0});
+			this->gridMatrix = glm::rotate(this->gridMatrix, PIf / 2, glm::vec3{1, 0, 0});
 		}
 		else
 		{
 			this->newStatusText("rotate by Y axis");
-			this->gridMatrix = glm::rotate(this->gridMatrix, float{M_PI} / 2, glm::vec3{0, 1, 0});
+			this->gridMatrix = glm::rotate(this->gridMatrix, PIf / 2, glm::vec3{0, 1, 0});
 		}
 		this->updateGridMatrix();
 		this->update();
@@ -119,18 +118,20 @@
 	// functions so that when initialization sets up, the signals also set up the matrices on our side.
 	this->gridProgram.emplace(this);
 	this->gridProgram->initialize();
-	connect(this, &PartRenderer::projectionMatrixChanged, [&]()
-	{
-		this->gridProgram->setProjectionMatrix(this->projectionMatrix);
-	});
-	connect(this, &PartRenderer::modelMatrixChanged, [&]()
+	this->axesProgram.emplace(this);
+	this->axesProgram->initialize();
+	for (AbstractBasicShaderProgram* program : {
+		static_cast<AbstractBasicShaderProgram*>(&*this->gridProgram),
+		static_cast<AbstractBasicShaderProgram*>(&*this->axesProgram),
+	})
 	{
-		this->gridProgram->setModelMatrix(this->modelMatrix);
-	});
-	connect(this, &PartRenderer::viewMatrixChanged, [&]()
-	{
-		this->gridProgram->setViewMatrix(this->viewMatrix);
-	});
+		connect(this, &PartRenderer::projectionMatrixChanged,
+			program, &AbstractBasicShaderProgram::setProjectionMatrix);
+		connect(this, &PartRenderer::modelMatrixChanged,
+			program, &AbstractBasicShaderProgram::setModelMatrix);
+		connect(this, &PartRenderer::viewMatrixChanged,
+			program, &AbstractBasicShaderProgram::setViewMatrix);
+	}
 	connect(this, &PartRenderer::renderPreferencesChanged, [&]()
 	{
 		if (this->gridProgram.has_value())
@@ -140,14 +141,7 @@
 		}
 	});
 	PartRenderer::initializeGL();
-	/*
-	this->gridMatrix = glm::mat4{
-		{-4, 0, 0, 0},
-		{0, 6.9266, -3.6955, 0},
-		{0, -16.7222, -1.5307, 0},
-		{0, -13.273, -9.255, 1},
-	};
-	*/
+	// Set up XZ grid matrix
 	this->gridMatrix = glm::mat4{
 		{1, 0, 0, 0},
 		{0, 0, 1, 0},
@@ -160,10 +154,21 @@
 void Canvas::paintGL()
 {
 	PartRenderer::paintGL();
-	glEnable(GL_BLEND);
-	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-	this->gridProgram->draw();
-	glDisable(GL_BLEND);
+	// Render axes
+	{
+		glLineWidth(5);
+		glEnable(GL_LINE_SMOOTH);
+		glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
+		this->axesProgram->draw();
+		glDisable(GL_LINE_SMOOTH);
+	}
+	// Render grid
+	{
+		glEnable(GL_BLEND);
+		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+		this->gridProgram->draw();
+		glDisable(GL_BLEND);
+	}
 	if (this->worldPosition.has_value())
 	{
 		QPainter painter{this};
@@ -175,22 +180,6 @@
 		painter.setPen(Qt::white);
 		painter.drawText(pos + QPointF{5, 5}, vectorToString(*this->worldPosition));
 	}
-	{
-		QPainter axisPainter{this};
-		axisPainter.setRenderHint(QPainter::Antialiasing);
-		axisPainter.setPen(Qt::red);
-		axisPainter.drawLine(
-			this->modelToScreenCoordinates({10, 0, 0}),
-			this->modelToScreenCoordinates({-10, 0, 0}));
-		axisPainter.setPen(Qt::green);
-		axisPainter.drawLine(
-			this->modelToScreenCoordinates({0, 10, 0}),
-			this->modelToScreenCoordinates({0, -10, 0}));
-		axisPainter.setPen(Qt::blue);
-		axisPainter.drawLine(
-			this->modelToScreenCoordinates({0, 0, 10}),
-			this->modelToScreenCoordinates({0, 0, -10}));
-	}
 }
 
 void Canvas::updateGridMatrix()
--- a/src/ui/canvas.h	Fri Mar 06 16:08:53 2020 +0200
+++ b/src/ui/canvas.h	Fri Mar 06 20:13:10 2020 +0200
@@ -1,6 +1,7 @@
 #pragma once
 #include "gl/partrenderer.h"
 #include "gl/gridprogram.h"
+#include "gl/axesprogram.h"
 
 class Canvas : public PartRenderer
 {
@@ -27,6 +28,7 @@
 	glm::vec3 cameraVector() const;
 	bool isGridPerpendicularToScreen(float threshold) const;
 	std::optional<GridProgram> gridProgram;
+	std::optional<AxesProgram> axesProgram;
 	std::optional<glm::vec3> worldPosition;
 	glm::mat4 gridMatrix;
 	geom::Plane gridPlane;

mercurial