| |
1 #pragma once |
| |
2 #include <glm/gtc/matrix_transform.hpp> |
| |
3 #include "basics.h" |
| |
4 #include "model.h" |
| |
5 #include "ldrawalgorithm.h" |
| |
6 |
| |
7 template<typename Fn> |
| |
8 void rasterize(const CircularPrimitive& circ, Fn&& fn) |
| |
9 { |
| |
10 std::vector<ModelElement> result; |
| |
11 const auto xform = [&circ](const glm::vec2& p, float y){ |
| |
12 return glm::vec3{circ.transformation * glm::vec4{p.x, y, p.y, 1}}; |
| |
13 }; |
| |
14 const glm::vec3 origin = xform({0, 0}, 0); |
| |
15 switch(circ.type) { |
| |
16 case CircularPrimitive::Circle: |
| |
17 ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&] |
| |
18 (const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){ |
| |
19 fn(edge(xform(p1, 0), xform(p2, 0))); |
| |
20 }); |
| |
21 break; |
| |
22 case CircularPrimitive::Disc: |
| |
23 ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&] |
| |
24 (const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){ |
| |
25 fn(triangle(origin, xform(p1, 0), xform(p2, 0))); |
| |
26 }); |
| |
27 break; |
| |
28 case CircularPrimitive::Cylinder: |
| |
29 ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&] |
| |
30 (const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){ |
| |
31 fn(quadrilateral(xform(p1, 1), xform(p2, 1), xform(p2, 0), xform(p1, 0))); |
| |
32 }); |
| |
33 break; |
| |
34 case CircularPrimitive::CylinderOpen: |
| |
35 rasterize(CircularPrimitive{ |
| |
36 .type = CircularPrimitive::Cylinder, |
| |
37 .fraction = circ.fraction, |
| |
38 .transformation = circ.transformation, |
| |
39 }, fn); |
| |
40 rasterize(CircularPrimitive{ |
| |
41 .type = CircularPrimitive::Circle, |
| |
42 .fraction = circ.fraction, |
| |
43 .transformation = circ.transformation, |
| |
44 }, fn); |
| |
45 rasterize(CircularPrimitive{ |
| |
46 .type = CircularPrimitive::Circle, |
| |
47 .fraction = circ.fraction, |
| |
48 .transformation = glm::translate(circ.transformation, {0, 1, 0}), |
| |
49 }, fn); |
| |
50 break; |
| |
51 case CircularPrimitive::CylinderClosed: |
| |
52 rasterize(CircularPrimitive{ |
| |
53 .type = CircularPrimitive::CylinderOpen, |
| |
54 .fraction = circ.fraction, |
| |
55 .transformation = circ.transformation, |
| |
56 }, fn); |
| |
57 rasterize(CircularPrimitive{ |
| |
58 .type = CircularPrimitive::Disc, |
| |
59 .fraction = circ.fraction, |
| |
60 .transformation = circ.transformation, |
| |
61 }, fn); |
| |
62 break; |
| |
63 case CircularPrimitive::DiscNegative: |
| |
64 { |
| |
65 unsigned int i = 0; |
| |
66 ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&] |
| |
67 (const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){ |
| |
68 constexpr glm::vec2 corners[4] = { |
| |
69 {+1, +1}, |
| |
70 {-1, +1}, |
| |
71 {-1, -1}, |
| |
72 {+1, -1}, |
| |
73 }; |
| |
74 const glm::vec2& corner = corners[i * 4 / circ.fraction.divisions]; |
| |
75 fn(triangle(xform(p2, 0), xform(p1, 0), xform(corner, 0))); |
| |
76 ++i; |
| |
77 }); |
| |
78 } |
| |
79 break; |
| |
80 case CircularPrimitive::Chord: |
| |
81 for (unsigned int i = 1; i < circ.fraction.segments; ++i) { |
| |
82 const glm::vec2& p1 = ldraw::rimpoint(circ.fraction.divisions, i); |
| |
83 const glm::vec2& p2 = ldraw::rimpoint(circ.fraction.divisions, i + 1); |
| |
84 fn(triangle(xform(p2, 0), xform(p1, 0), xform({1, 0}, 0))); |
| |
85 } |
| |
86 break; |
| |
87 } |
| |
88 } |