Tue, 28 Jun 2022 17:35:56 +0300
Fix picking and rendering of selected colors
#pragma once #include <glm/gtc/matrix_transform.hpp> #include "src/basics.h" #include "src/model.h" #include "src/ldrawalgorithm.h" template<typename Fn> void rasterize(const CircularPrimitive& circ, Fn&& fn) { std::vector<ModelElement> result; const auto xform = [&circ](const glm::vec2& p, float y){ return glm::vec3{circ.transformation * glm::vec4{p.x, y, p.y, 1}}; }; const glm::vec3 primitiveOrigin = xform({0, 0}, 0); const bool invertedMatrix = (glm::determinant(circ.transformation) < 0) != circ.inverted; switch(circ.type) { case CircularPrimitive::Circle: ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&] (const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){ fn(edge(xform(p1, 0), xform(p2, 0))); }); break; case CircularPrimitive::Disc: ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&] (const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){ fn(triangle(primitiveOrigin, xform(p1, 0), xform(p2, 0))); }); break; case CircularPrimitive::Cylinder: ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&] (const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){ Colored<Quadrilateral> quad = quadrilateral(xform(p1, 1), xform(p2, 1), xform(p2, 0), xform(p1, 0)); if (invertedMatrix) { std::swap(quad.p2, quad.p4); } fn(quad); }); break; case CircularPrimitive::CylinderOpen: rasterize(CircularPrimitive{ .type = CircularPrimitive::Cylinder, .fraction = circ.fraction, .transformation = circ.transformation, }, fn); rasterize(CircularPrimitive{ .type = CircularPrimitive::Circle, .fraction = circ.fraction, .transformation = circ.transformation, }, fn); rasterize(CircularPrimitive{ .type = CircularPrimitive::Circle, .fraction = circ.fraction, .transformation = glm::translate(circ.transformation, {0, 1, 0}), }, fn); break; case CircularPrimitive::CylinderClosed: rasterize(CircularPrimitive{ .type = CircularPrimitive::CylinderOpen, .fraction = circ.fraction, .transformation = circ.transformation, }, fn); rasterize(CircularPrimitive{ .type = CircularPrimitive::Disc, .fraction = circ.fraction, .transformation = circ.transformation, }, fn); break; case CircularPrimitive::DiscNegative: { unsigned int i = 0; ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&] (const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){ constexpr glm::vec2 corners[4] = { {+1, +1}, {-1, +1}, {-1, -1}, {+1, -1}, }; const glm::vec2& corner = corners[i * 4 / circ.fraction.divisions]; fn(triangle(xform(p2, 0), xform(p1, 0), xform(corner, 0))); ++i; }); } break; case CircularPrimitive::Chord: for (unsigned int i = 1; i < circ.fraction.segments; ++i) { const glm::vec2& p1 = ldraw::rimpoint(circ.fraction.divisions, i); const glm::vec2& p2 = ldraw::rimpoint(circ.fraction.divisions, i + 1); fn(triangle(xform(p2, 0), xform(p1, 0), xform({1, 0}, 0))); } break; } }