# HG changeset patch # User Teemu Piippo # Date 1627467771 -10800 # Node ID 8c9fff6992415a67a46a62a8b4a9e37f72078da0 # Parent 24275a4064f47eef9721fa825ec06b152e50fb30 rework rendering of vertices diff -r 24275a4064f4 -r 8c9fff699241 src/gl/partrenderer.cpp --- 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, diff -r 24275a4064f4 -r 8c9fff699241 src/gl/partrenderer.h --- 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; diff -r 24275a4064f4 -r 8c9fff699241 src/gl/vertexprogram.cpp --- 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&) + 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(); diff -r 24275a4064f4 -r 8c9fff699241 src/maths.h --- 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 linePlaneIntersection(); } -inline unsigned int qHash(const glm::vec3& key) +template +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)); } diff -r 24275a4064f4 -r 8c9fff699241 src/ui/canvas.cpp --- 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); diff -r 24275a4064f4 -r 8c9fff699241 src/vertexmap.cpp --- 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 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([&](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(), 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))); } } diff -r 24275a4064f4 -r 8c9fff699241 src/vertexmap.h --- 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&)>; + struct VertexInfo + { + glm::vec3 point; + std::set objects; + bool transformSet = false; + glm::mat4 transform; + }; + using ApplyFunction = std::function; VertexMap(const Model *model); Q_SLOT void build(); void apply(ApplyFunction fn) const; @@ -21,7 +28,7 @@ const Model* const model; QSet vertexHashes; std::vector vertices; - std::map> map; + std::map map; }; #endif // VERTEXMAP_H