diff -r a9bf6bab5ea2 -r 8efa3a33172e src/circularprimitive.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/circularprimitive.h Mon Jun 20 02:04:51 2022 +0300 @@ -0,0 +1,88 @@ +#pragma once +#include +#include "basics.h" +#include "model.h" +#include "ldrawalgorithm.h" + +template +void rasterize(const CircularPrimitive& circ, Fn&& fn) +{ + std::vector 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 origin = xform({0, 0}, 0); + 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(origin, 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){ + fn(quadrilateral(xform(p1, 1), xform(p2, 1), xform(p2, 0), xform(p1, 0))); + }); + 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; + } +}