rework rendering of vertices

Wed, 28 Jul 2021 13:22:51 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Wed, 28 Jul 2021 13:22:51 +0300
changeset 120
8c9fff699241
parent 119
24275a4064f4
child 121
000781318c36

rework rendering of vertices

src/gl/partrenderer.cpp file | annotate | diff | comparison | revisions
src/gl/partrenderer.h file | annotate | diff | comparison | revisions
src/gl/vertexprogram.cpp file | annotate | diff | comparison | revisions
src/maths.h file | annotate | diff | comparison | revisions
src/ui/canvas.cpp file | annotate | diff | comparison | revisions
src/vertexmap.cpp file | annotate | diff | comparison | revisions
src/vertexmap.h file | annotate | diff | comparison | revisions
--- a/src/gl/partrenderer.cpp	Wed Jul 28 08:23:09 2021 +0300
+++ b/src/gl/partrenderer.cpp	Wed Jul 28 13:22:51 2021 +0300
@@ -26,6 +26,9 @@
 #include "partrenderer.h"
 #include "model.h"
 
+static constexpr double MIN_ZOOM = -3.0;
+static constexpr double MAX_ZOOM = 3.0;
+
 PartRenderer::PartRenderer(
 	Model* model,
 	DocumentManager* documents,
--- a/src/gl/partrenderer.h	Wed Jul 28 08:23:09 2021 +0300
+++ b/src/gl/partrenderer.h	Wed Jul 28 13:22:51 2021 +0300
@@ -59,8 +59,6 @@
 	void updateModelMatrix();
 	void setupBackgroundColor();
 	Q_SLOT void build();
-	static constexpr double MIN_ZOOM = 0.0;
-	static constexpr double MAX_ZOOM = 3.0;
 	double zoom = 1.0;
 	bool initialized = false;
 	bool needBuild = true;
--- a/src/gl/vertexprogram.cpp	Wed Jul 28 08:23:09 2021 +0300
+++ b/src/gl/vertexprogram.cpp	Wed Jul 28 13:22:51 2021 +0300
@@ -102,15 +102,15 @@
 
 void VertexProgram::build(const Document *document)
 {
-	constexpr float size = 1;
 	constexpr glm::vec3 color = {0.0, 1.0, 1.0};
 	this->data.clear();
-	document->applyToVertices([&](const glm::vec3& vertex, const std::set<ldraw::id_t>&)
+	document->applyToVertices([&](const glm::vec3&, const VertexMap::VertexInfo& info)
 	{
 		reserveMore(this->data, ::countof(::markerGeometry));
 		for (const glm::vec3& point : ::markerGeometry)
 		{
-			this->data.push_back({vertex + point * size, color});
+			const glm::vec3 transformed = info.transform * glm::vec4{point, 1};
+			this->data.push_back({transformed, color});
 		}
 	});
 	this->buffer.bind();
--- a/src/maths.h	Wed Jul 28 08:23:09 2021 +0300
+++ b/src/maths.h	Wed Jul 28 13:22:51 2021 +0300
@@ -94,7 +94,8 @@
 	std::optional<glm::vec3> linePlaneIntersection();
 }
 
-inline unsigned int qHash(const glm::vec3& key)
+template<typename T, glm::qualifier Q>
+inline unsigned int qHash(const glm::vec<3, T, Q>& key)
 {
 	return qHash(key.x) ^ utility::rotl10(qHash(key.y)) ^ utility::rotl20(qHash(key.z));
 }
--- a/src/ui/canvas.cpp	Wed Jul 28 08:23:09 2021 +0300
+++ b/src/ui/canvas.cpp	Wed Jul 28 13:22:51 2021 +0300
@@ -163,7 +163,7 @@
 		}
 		// Render vertices
 		{
-			glLineWidth(2);
+			glLineWidth(1.5);
 			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 			glEnable(GL_LINE_SMOOTH);
 			glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
--- a/src/vertexmap.cpp	Wed Jul 28 08:23:09 2021 +0300
+++ b/src/vertexmap.cpp	Wed Jul 28 13:22:51 2021 +0300
@@ -1,6 +1,15 @@
 #include "vertexmap.h"
 #include "linetypes/polygonobject.h"
 
+unsigned int hashVertex(const glm::vec3& vec)
+{
+	return qHash(glm::ivec3{
+		int(vec.x * 10000),
+		int(vec.y * 10000),
+		int(vec.z * 10000),
+	});
+}
+
 VertexMap::VertexMap(const Model *model) :
 	model{model}
 {
@@ -25,6 +34,22 @@
 	this->build();
 }
 
+struct Edge
+{
+	const glm::vec3& a;
+	const glm::vec3& b;
+};
+
+inline void edges(const ldraw::Object* object, std::function<void(Edge&&)> fn)
+{
+	for (int i = 0; i < object->numPoints() - 1; i += 1)
+	{
+		const glm::vec3 p1 = object->getPoint(i);
+		const glm::vec3 p2 = object->getPoint((i + 1) % object->numPoints());
+		fn(Edge{p1, p2});
+	}
+}
+
 void VertexMap::build()
 {
 	this->map.clear();
@@ -32,11 +57,31 @@
 	this->vertexHashes.clear();
 	this->model->apply<ldraw::Object>([&](const ldraw::Object* object)
 	{
+		glm::mat4 matrix;
+		if (object->numPoints() > 2)
+		{
+			const auto& p0 = object->getPoint(0);
+			const auto& p1 = object->getPoint(1);
+			const auto& p2 = object->getPoint(2);
+			const glm::vec3 a = glm::normalize(p1 - p0);
+			const glm::vec3 b = glm::normalize(p2 - p0);
+			const glm::vec3 c = glm::normalize(glm::cross(a, b));
+			const glm::vec3 d = glm::normalize(glm::cross(a, c));
+			matrix = glm::mat4{{a, 0}, {-c, 0}, {d, 0}, {}};
+		}
 		for (int i = 0; i < object->numPoints(); i += 1)
 		{
 			const glm::vec3& point = object->getPoint(i);
-			const unsigned int hash = qHash(point);
-			this->map[hash].insert(object->id);
+			const unsigned int hash = hashVertex(point);
+			VertexInfo& info = this->map[hash];
+			info.point = point;
+			info.objects.insert(object->id);
+			if (object->numPoints() > 2 and not info.transformSet)
+			{
+				info.transform = matrix;
+				info.transform[3] = {point, 1};
+				info.transformSet = true;
+			}
 			if (not this->vertexHashes.contains(hash))
 			{
 				this->vertexHashes.insert(hash);
@@ -44,6 +89,29 @@
 			}
 		}
 	});
+	for (auto& pair : this->map)
+	{
+		auto& info = pair.second;
+		// If there's no transformation calculated yet, make up a simple one that at least
+		// contains translation.
+		if (not info.transformSet)
+		{
+			info.transform = glm::translate(glm::identity<glm::mat4>(), info.point);
+			info.transformSet = true;
+		}
+		float scale = 1.0f;
+		for (const ldraw::id_t objectId : info.objects)
+		{
+			edges(model->get(objectId), [&](Edge&& edge)
+			{
+				if (hashVertex(edge.a) == pair.first or hashVertex(edge.b) == pair.first)
+				{
+					scale = std::min(scale, glm::length(edge.b - edge.a) / 3);
+				}
+			});
+		}
+		info.transform = glm::scale(info.transform, glm::vec3{scale, scale, scale});
+	}
 	Q_EMIT this->verticesChanged();
 }
 
@@ -56,6 +124,6 @@
 	for (unsigned int i = 0; i < this->vertices.size(); i += 1)
 	{
 		const glm::vec3& point = this->vertices[i];
-		fn(point, this->map.at(qHash(point)));
+		fn(point, this->map.at(hashVertex(point)));
 	}
 }
--- a/src/vertexmap.h	Wed Jul 28 08:23:09 2021 +0300
+++ b/src/vertexmap.h	Wed Jul 28 13:22:51 2021 +0300
@@ -11,7 +11,14 @@
 {
 	Q_OBJECT
 public:
-	using ApplyFunction = std::function<void(const glm::vec3&, const std::set<ldraw::id_t>&)>;
+	struct VertexInfo
+	{
+		glm::vec3 point;
+		std::set<ldraw::id_t> objects;
+		bool transformSet = false;
+		glm::mat4 transform;
+	};
+	using ApplyFunction = std::function<void(const glm::vec3&, const VertexInfo&)>;
 	VertexMap(const Model *model);
 	Q_SLOT void build();
 	void apply(ApplyFunction fn) const;
@@ -21,7 +28,7 @@
 	const Model* const model;
 	QSet<unsigned int> vertexHashes;
 	std::vector<glm::vec3> vertices;
-	std::map<unsigned int, std::set<ldraw::id_t>> map;
+	std::map<unsigned int, VertexInfo> map;
 };
 
 #endif // VERTEXMAP_H

mercurial