3 #include "src/basics.h" |
3 #include "src/basics.h" |
4 #include "src/model.h" |
4 #include "src/model.h" |
5 #include "src/ldrawalgorithm.h" |
5 #include "src/ldrawalgorithm.h" |
6 |
6 |
7 template<typename Fn> |
7 template<typename Fn> |
8 void rasterize(const CircularPrimitive& circ, Fn&& fn) |
8 void circular_element_to_polygons(const circular_primitive& circ, Fn&& fn) |
9 { |
9 { |
10 std::vector<ModelElement> result; |
10 std::vector<ModelElement> result; |
11 const auto xform = [&circ](const glm::vec2& p, float y){ |
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}}; |
12 return glm::vec3{circ.transformation * glm::vec4{p.x, y, p.y, 1}}; |
13 }; |
13 }; |
14 const glm::vec3 primitiveOrigin = xform({0, 0}, 0); |
14 const glm::vec3 primitiveOrigin = xform({0, 0}, 0); |
15 const bool invertedMatrix = (glm::determinant(circ.transformation) < 0) != circ.inverted; |
15 const bool invertedMatrix = (glm::determinant(circ.transformation) < 0) != circ.inverted; |
16 switch(circ.type) { |
16 switch(circ.type) { |
17 case CircularPrimitive::Circle: |
17 case circular_primitive_type_e::circle: |
18 ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&] |
18 ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&] |
19 (const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){ |
19 (const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){ |
20 fn(LineSegment{xform(p1, 0), xform(p2, 0)}, EDGE_COLOR); |
20 fn(LineSegment{xform(p1, 0), xform(p2, 0)}, EDGE_COLOR); |
21 }); |
21 }); |
22 break; |
22 break; |
23 case CircularPrimitive::Disc: |
23 case circular_primitive_type_e::disc: |
24 ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&] |
24 ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&] |
25 (const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){ |
25 (const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){ |
26 fn(Triangle{primitiveOrigin, xform(p1, 0), xform(p2, 0)}, MAIN_COLOR); |
26 fn(Triangle{primitiveOrigin, xform(p1, 0), xform(p2, 0)}, MAIN_COLOR); |
27 }); |
27 }); |
28 break; |
28 break; |
29 case CircularPrimitive::Cylinder: |
29 case circular_primitive_type_e::cylinder: |
30 ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&] |
30 ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&] |
31 (const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){ |
31 (const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){ |
32 Quadrilateral quad{xform(p1, 1), xform(p2, 1), xform(p2, 0), xform(p1, 0)}; |
32 Quadrilateral quad{xform(p1, 1), xform(p2, 1), xform(p2, 0), xform(p1, 0)}; |
33 if (invertedMatrix) { |
33 if (invertedMatrix) { |
34 std::swap(quad.p2, quad.p4); |
34 std::swap(quad.p2, quad.p4); |
35 } |
35 } |
36 fn(quad, MAIN_COLOR); |
36 fn(quad, MAIN_COLOR); |
37 }); |
37 }); |
38 break; |
38 break; |
39 case CircularPrimitive::CylinderOpen: |
39 case circular_primitive_type_e::cylinder_open: |
40 rasterize(CircularPrimitive{ |
40 circular_element_to_polygons(circular_primitive{ |
41 .type = CircularPrimitive::Cylinder, |
41 .type = circular_primitive_type_e::cylinder, |
42 .fraction = circ.fraction, |
42 .fraction = circ.fraction, |
43 .transformation = circ.transformation, |
43 .transformation = circ.transformation, |
44 }, fn); |
44 }, fn); |
45 rasterize(CircularPrimitive{ |
45 circular_element_to_polygons(circular_primitive{ |
46 .type = CircularPrimitive::Circle, |
46 .type = circular_primitive_type_e::circle, |
47 .fraction = circ.fraction, |
47 .fraction = circ.fraction, |
48 .transformation = circ.transformation, |
48 .transformation = circ.transformation, |
49 }, fn); |
49 }, fn); |
50 rasterize(CircularPrimitive{ |
50 circular_element_to_polygons(circular_primitive{ |
51 .type = CircularPrimitive::Circle, |
51 .type = circular_primitive_type_e::circle, |
52 .fraction = circ.fraction, |
52 .fraction = circ.fraction, |
53 .transformation = glm::translate(circ.transformation, {0, 1, 0}), |
53 .transformation = glm::translate(circ.transformation, {0, 1, 0}), |
54 }, fn); |
54 }, fn); |
55 break; |
55 break; |
56 case CircularPrimitive::CylinderClosed: |
56 case circular_primitive_type_e::cylinder_closed: |
57 rasterize(CircularPrimitive{ |
57 circular_element_to_polygons(circular_primitive{ |
58 .type = CircularPrimitive::CylinderOpen, |
58 .type = circular_primitive_type_e::cylinder_open, |
59 .fraction = circ.fraction, |
59 .fraction = circ.fraction, |
60 .transformation = circ.transformation, |
60 .transformation = circ.transformation, |
61 }, fn); |
61 }, fn); |
62 rasterize(CircularPrimitive{ |
62 circular_element_to_polygons(circular_primitive{ |
63 .type = CircularPrimitive::Disc, |
63 .type = circular_primitive_type_e::disc, |
64 .fraction = circ.fraction, |
64 .fraction = circ.fraction, |
65 .transformation = circ.transformation, |
65 .transformation = circ.transformation, |
66 }, fn); |
66 }, fn); |
67 break; |
67 break; |
68 case CircularPrimitive::DiscNegative: |
68 case circular_primitive_type_e::disc_negative: |
69 { |
69 { |
70 unsigned int i = 0; |
70 unsigned int i = 0; |
71 ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&] |
71 ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&] |
72 (const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){ |
72 (const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){ |
73 constexpr glm::vec2 corners[4] = { |
73 constexpr glm::vec2 corners[4] = { |