moved GridProgram to Canvas

Thu, 27 Feb 2020 22:46:39 +0200

author
Teemu Piippo <teemu@hecknology.net>
date
Thu, 27 Feb 2020 22:46:39 +0200
changeset 61
4585d8d7a7ec
parent 60
0f221121849b
child 62
3e92760fe00a

moved GridProgram to Canvas

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/src/gl/partrenderer.cpp	Thu Feb 27 14:38:58 2020 +0200
+++ b/src/gl/partrenderer.cpp	Thu Feb 27 22:46:39 2020 +0200
@@ -34,8 +34,7 @@
 	model{model},
 	documents{documents},
 	colorTable{colorTable},
-	compiler{new gl::Compiler{this->colorTable, this}},
-	gridProgram{this}
+	compiler{new gl::Compiler{this->colorTable, this}}
 {
 	this->setMouseTracking(true);
 }
@@ -46,7 +45,11 @@
 
 static QVector3D vec3FromQColor(const QColor& color)
 {
-	return {(float)color.redF(), (float)color.greenF(), (float)color.blueF()};
+	return {
+		toFloat(color.redF()),
+		toFloat(color.greenF()),
+		toFloat(color.blueF()),
+	};
 }
 
 void PartRenderer::initializeGL()
@@ -56,8 +59,6 @@
 	{
 		abort();
 	}
-	this->gridProgram.emplace(this);
-	this->gridProgram->initialize();
 	this->compiler->initialize();
 	this->compiler->build(this->model, this->documents, this->renderPreferences);
 	this->initialized = true;
@@ -79,7 +80,7 @@
 		0.1f,
 		10000.f);
 	this->compiler->setUniformMatrix("projectionMatrix", this->projectionMatrix);
-	this->gridProgram->setProjectionMatrix(this->projectionMatrix);
+	emit projectionMatrixChanged();
 }
 
 static GLenum getGlTypeForArrayClass(const gl::ArrayClass vboClass)
@@ -173,10 +174,6 @@
 		this->renderAllArrays();
 		break;
 	}
-	glEnable(GL_BLEND);
-	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-	this->gridProgram->draw();
-	glDisable(GL_BLEND);
 	glDisable(GL_POLYGON_OFFSET_FILL);
 }
 
@@ -195,24 +192,19 @@
 	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);
-	this->gridProgram->setViewMatrix(this->viewMatrix);
+	emit this->viewMatrixChanged();
 }
 
 void PartRenderer::updateModelMatrix()
 {
-	const glm::mat4 modelMatrix = glm::mat4_cast(this->modelQuaternion);
+	this->modelMatrix = glm::mat4_cast(this->modelQuaternion);
 	this->compiler->setUniformMatrix("modelMatrix", modelMatrix);
-	this->gridProgram->setModelMatrix(modelMatrix);
+	emit this->modelMatrixChanged();
 	this->update();
 }
 
 void PartRenderer::setupBackgroundColor()
 {
-	if (this->gridProgram.has_value())
-	{
-		const bool isDark = luma(this->renderPreferences.backgroundColor) < 0.25;
-		this->gridProgram->setGridColor(isDark ? Qt::white : Qt::black);
-	}
 }
 
 void PartRenderer::renderVao(const gl::ArrayClass arrayClass)
@@ -255,7 +247,7 @@
 void PartRenderer::mouseMoveEvent(QMouseEvent* event)
 {
 	const bool left = event->buttons() & Qt::LeftButton;
-	const QPointF move = pointToPointF(event->pos()) - this->lastMousePosition;
+	const QPoint move = event->pos() - this->lastMousePosition;
 	if (left and not move.isNull())
 	{
 		// q_x is the rotation of the brick along the vertical y-axis, because turning the
@@ -269,7 +261,7 @@
 		this->modelQuaternion = q_x * q_y * this->modelQuaternion;
 		this->updateModelMatrix();
 	}
-	this->lastMousePosition = pointToPointF(event->pos());
+	this->lastMousePosition = event->pos();
 }
 
 void PartRenderer::wheelEvent(QWheelEvent* event)
@@ -281,11 +273,6 @@
 	this->update();
 }
 
-glm::vec3 PartRenderer::viewport(const glm::vec3& point)
-{
-	return viewport(point, this->width(), this->height());
-}
-
 /**
  * @brief Converts the specified on the screen into the 3D world. The point is unprojected twice into 3D and the
  * intersection of the resulting line with the specified plane is returned. If the intersection point lies behind
@@ -296,9 +283,9 @@
  */
 std::optional<glm::vec3> PartRenderer::screenToModelCoordinates(const QPoint& point, const geom::Plane& plane)
 {
-	auto p1 = this->unproject({point.x(), point.y(), 0});
-	auto p2 = this->unproject({point.x(), point.y(), 1});
-	geom::Line line = geom::lineFromPoints(p1, p2);
+	const glm::vec3 p1 = this->unproject({point.x(), point.y(), 0});
+	const glm::vec3 p2 = this->unproject({point.x(), point.y(), 1});
+	const geom::Line line = geom::lineFromPoints(p1, p2);
 	std::optional<glm::vec3> result;
 	result = geom::linePlaneIntersection(line, plane, 0.01f);
 	// If the point lies behind the camera, do not return a result.
@@ -376,14 +363,6 @@
 		this->compiler->build(this->model, this->documents, this->renderPreferences);
 		this->setupBackgroundColor();
 	}
+	emit this->renderPreferencesChanged();
 	this->update();
 }
-
-glm::vec3 PartRenderer::viewport(const glm::vec3& point, float width, float height)
-{
-	return {
-		width * 0.5 * (point.x + 1),
-		height * 0.5 * (-point.y + 1),
-		0
-	};
-}
--- a/src/gl/partrenderer.h	Thu Feb 27 14:38:58 2020 +0200
+++ b/src/gl/partrenderer.h	Thu Feb 27 22:46:39 2020 +0200
@@ -10,7 +10,6 @@
 #include "main.h"
 #include "gl/common.h"
 #include "gl/compiler.h"
-#include "gl/gridprogram.h"
 
 class PartRenderer : public QOpenGLWidget, protected QOpenGLFunctions
 {
@@ -23,8 +22,6 @@
 		QWidget* parent = nullptr);
 	~PartRenderer() override;
 	void setRenderPreferences(const gl::RenderPreferences& newPreferences);
-	static glm::vec3 viewport(const glm::vec3& point, float width, float height);
-	static glm::vec3 antiviewport(const glm::vec3& point, float width, float height);
 protected:
 	ldraw::Id pick(const QPoint& where);
 	void initializeGL() override;
@@ -32,7 +29,6 @@
 	void paintGL() override;
 	void mouseMoveEvent(QMouseEvent* event) override;
 	void wheelEvent(QWheelEvent* event) override;
-	glm::vec3 viewport(const glm::vec3& point);
 	Model* const model;
 	DocumentManager* const documents;
 	const ldraw::ColorTable& colorTable;
@@ -41,6 +37,18 @@
 	std::optional<glm::vec3> screenToModelCoordinates(const QPoint& point, const geom::Plane& plane);
 	QPointF modelToScreenCoordinates(const glm::vec3& point);
 	glm::vec3 unproject(const glm::vec3& win);
+	glm::mat4 projectionMatrix;
+	glm::mat4 viewMatrix;
+	glm::mat4 modelMatrix;
+	glm::vec4 viewportVector;
+	glm::quat modelQuaternion;
+	QPoint lastMousePosition;
+	gl::RenderPreferences renderPreferences;
+signals:
+	void projectionMatrixChanged();
+	void modelMatrixChanged();
+	void viewMatrixChanged();
+	void renderPreferencesChanged();
 private:
 	void setFragmentStyle(gl::FragmentStyle fragStyle);
 	void renderAllArrays();
@@ -48,13 +56,6 @@
 	void updateViewMatrix();
 	void updateModelMatrix();
 	void setupBackgroundColor();
-	QPointF lastMousePosition;
-	gl::RenderPreferences renderPreferences;
-	glm::mat4 projectionMatrix;
-	glm::mat4 viewMatrix;
-	glm::vec4 viewportVector;
-	glm::quat modelQuaternion;
-	std::optional<GridProgram> gridProgram;
 	static constexpr double MIN_ZOOM = 0.0;
 	static constexpr double MAX_ZOOM = 3.0;
 	double zoom = 1.0;
--- a/src/ui/canvas.cpp	Thu Feb 27 14:38:58 2020 +0200
+++ b/src/ui/canvas.cpp	Thu Feb 27 22:46:39 2020 +0200
@@ -7,7 +7,8 @@
 	DocumentManager* documents,
 	const ldraw::ColorTable& colorTable,
 	QWidget* parent) :
-	PartRenderer{model, documents, colorTable, parent}
+	PartRenderer{model, documents, colorTable, parent},
+	gridProgram{this}
 {
 	this->setMouseTracking(true);
 }
@@ -21,13 +22,20 @@
 	this->update();
 }
 
+QString vectorToString(const glm::vec3& vec)
+{
+	return "(%1, %2, %3)"_q
+		.arg(toDouble(vec.x))
+		.arg(toDouble(vec.y))
+		.arg(toDouble(vec.z));
+}
+
 void Canvas::mouseMoveEvent(QMouseEvent* event)
 {
 	const ldraw::Id id = this->pick(event->pos());
 	this->highlighted = id;
 	this->totalMouseMove += (event->pos() - this->lastMousePosition).manhattanLength();
-	this->lastMousePosition = event->pos();
-	this->worldPosition = this->screenToModelCoordinates(this->lastMousePosition, geom::XY);
+	this->worldPosition = this->screenToModelCoordinates(event->pos(), geom::XY);
 	if (this->worldPosition.has_value())
 	{
 		this->worldPosition = glm::round(*this->worldPosition);
@@ -35,9 +43,9 @@
 	if (this->worldPosition.has_value())
 	{
 		this->newStatusText("Position: (%1, %2, %3)"_q
-			.arg(this->worldPosition->x)
-			.arg(this->worldPosition->y)
-			.arg(this->worldPosition->z));
+			.arg(toDouble(this->worldPosition->x))
+			.arg(toDouble(this->worldPosition->y))
+			.arg(toDouble(this->worldPosition->z)));
 	}
 	else
 	{
@@ -72,15 +80,51 @@
 	PartRenderer::mouseReleaseEvent(event);
 }
 
+void Canvas::initializeGL()
+{
+	// We first create the grid program and connect everything and only then call the part renderer's initialization
+	// 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->gridProgram->setModelMatrix(this->modelMatrix);
+	});
+	connect(this, &PartRenderer::viewMatrixChanged, [&]()
+	{
+		this->gridProgram->setViewMatrix(this->viewMatrix);
+	});
+	connect(this, &PartRenderer::renderPreferencesChanged, [&]()
+	{
+		if (this->gridProgram.has_value())
+		{
+			const bool isDark = luma(this->renderPreferences.backgroundColor) < 0.25;
+			this->gridProgram->setGridColor(isDark ? Qt::white : Qt::black);
+		}
+	});
+	PartRenderer::initializeGL();
+}
+
 void Canvas::paintGL()
 {
 	PartRenderer::paintGL();
+	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};
 		painter.setRenderHint(QPainter::Antialiasing);
 		painter.setPen(Qt::black);
 		painter.setBrush(Qt::green);
-		painter.drawEllipse(this->modelToScreenCoordinates(*this->worldPosition), 10, 10);
+		const QPointF pos = this->modelToScreenCoordinates(*this->worldPosition);
+		painter.drawEllipse(pos, 5, 5);
+		painter.setPen(Qt::white);
+		painter.drawText(pos + QPointF{5, 5}, vectorToString(*this->worldPosition));
 	}
 }
--- a/src/ui/canvas.h	Thu Feb 27 14:38:58 2020 +0200
+++ b/src/ui/canvas.h	Thu Feb 27 22:46:39 2020 +0200
@@ -1,5 +1,6 @@
 #pragma once
 #include "gl/partrenderer.h"
+#include "gl/gridprogram.h"
 
 class Canvas : public PartRenderer
 {
@@ -16,12 +17,13 @@
 	void mouseMoveEvent(QMouseEvent* event) override;
 	void mousePressEvent(QMouseEvent* event) override;
 	void mouseReleaseEvent(QMouseEvent* event) override;
+	void initializeGL() override;
 	void paintGL() override;
 signals:
 	void newStatusText(const QString& newStatusText);
 	void selectionChanged(const QSet<ldraw::Id>& newSelection);
 private:
-	QPoint lastMousePosition;
+	std::optional<GridProgram> gridProgram;
 	std::optional<glm::vec3> worldPosition;
 	int totalMouseMove = 0;
 	QSet<ldraw::Id> selection;

mercurial