smk::Shape Class Reference

#include <Shape.hpp>

A collection of static function to build simple shape. More...

Description

A collection of static function to build simple shape.

Definition at line 20 of file Shape.hpp.

Static Public Member Functions

static Transformable FromVertexArray (VertexArray vertex_array)
 
static Transformable Line (const glm::vec2 &a, const glm::vec2 &b, float thickness)
 Return a line with a given thickness. More...
 
static Transformable Square ()
 Return the square [0,1]x[0,1]. More...
 
static Transformable Circle (float radius)
 Return a circle. More...
 
static Transformable Circle (float radius, int subdivisions)
 Return a circle. More...
 
static Transformable Path (const std::vector< glm::vec2 > &points, float thickness)
 Build a path of a given |thickness| along a sequence of connected lines. @params points The sequence of points the path is going through. @params thickness This width of the path. More...
 
static Transformable RoundedRectangle (float width, float height, float radius)
 Return a rounded centered rectangle. @params width The width of the rectangle. @params height The height of the rectangle. @params radius The radius of the four corners. More...
 
static Transformable3D Cube ()
 Return a centered 1x1x1 3D cube. More...
 
static Transformable3D IcoSphere (int iteration)
 A centered sphere. More...
 
static Transformable3D Plane ()
 Return a centered 1x1 square in a 3D space. More...
 
static std::vector< glm::vec2 > Bezier (const std::vector< glm::vec2 > &point, size_t subdivision)
 Return a bezier curve. More...
 

Member Function Documentation

◆ Bezier()

std::vector< glm::vec2 > smk::Shape::Bezier ( const std::vector< glm::vec2 > &  points,
size_t  subdivision 
)
static

Return a bezier curve.

See also
https://en.wikipedia.org/wiki/Bézier_curve
Parameters
pointsThe sequence of control points where the produced curve should pass by.
subdivisionThe number of points in the output.
Examples
bezier.cpp.

Definition at line 193 of file Shape.cpp.

194 {
195 std::vector<glm::vec2> path;
196 for (size_t index = 0; index < subdivision + 1; ++index) {
197 std::vector<glm::vec2> data = points;
198 float x = float(index) / float(subdivision);
199 while (data.size() >= 2) {
200 for (size_t i = 0; i < data.size() - 1; ++i) {
201 data[i] = glm::mix(data[i], data[i + 1], x);
202 }
203 data.resize(data.size() - 1);
204 }
205 path.push_back(data[0]);
206 }
207 return path;
208}

◆ Circle() [1/2]

Transformable smk::Shape::Circle ( float  radius)
static

Return a circle.

Parameters
radiusThe circle'radius.
Examples
framebuffer.cpp, and shape_2d.cpp.

Definition at line 61 of file Shape.cpp.

61 {
62 return Circle(radius, 16 + radius * 0.9); // NOLINT
63}
static Transformable Circle(float radius)
Return a circle.
Definition: Shape.cpp:61

◆ Circle() [2/2]

Transformable smk::Shape::Circle ( float  radius,
int  subdivisions 
)
static

Return a circle.

Parameters
radiusThe circle'radius.
subdivisionsThe number of triangles used for drawing the circle.

Definition at line 68 of file Shape.cpp.

68 {
69 std::vector<Vertex> v;
70 glm::vec2 p1 = glm::vec2(1.0f, 0.0f);
71 glm::vec2 t1 = glm::vec2(0.5F, 0.5F) + 0.5F * p1; // NOLINT
72 glm::vec2 zero(0.F, 0.F);
73 for (int i = 1; i <= subdivisions; ++i) {
74 float a = float(2.F * M_PI * i) / float(subdivisions); // NOLINT
75 glm::vec2 p2 = glm::vec2(std::cos(a), std::sin(a));
76 glm::vec2 t2 = glm::vec2(0.5F, 0.5F) + 0.5F * p2; // NOLINT
77
78 v.push_back({zero, zero});
79 v.push_back({radius * p1, t1});
80 v.push_back({radius * p2, t2});
81 p1 = p2;
82 t1 = t2;
83 }
84
85 return FromVertexArray(VertexArray(v));
86}

◆ Cube()

Transformable3D smk::Shape::Cube ( )
static

Return a centered 1x1x1 3D cube.

Examples
shape_3d.cpp.

Definition at line 89 of file Shape.cpp.

89 {
90 constexpr float m = -0.5F;
91 constexpr float z = +0.F;
92 constexpr float p = +0.5F;
93 constexpr float l = 0.F;
94 constexpr float r = 1.F;
95 auto vertex_array = smk::VertexArray({
96 {{m, m, p}, {z, z, p}, {l, l}}, {{p, m, p}, {z, z, p}, {r, l}},
97 {{p, p, p}, {z, z, p}, {r, r}}, {{m, m, p}, {z, z, p}, {l, l}},
98 {{p, p, p}, {z, z, p}, {r, r}}, {{m, p, p}, {z, z, p}, {l, r}},
99
100 {{m, m, m}, {z, z, m}, {l, l}}, {{p, p, m}, {z, z, m}, {r, r}},
101 {{p, m, m}, {z, z, m}, {r, l}}, {{m, m, m}, {z, z, m}, {l, l}},
102 {{m, p, m}, {z, z, m}, {l, r}}, {{p, p, m}, {z, z, m}, {r, r}},
103
104 {{m, p, m}, {z, p, z}, {l, l}}, {{m, p, p}, {z, p, z}, {r, l}},
105 {{p, p, p}, {z, p, z}, {r, r}}, {{m, p, m}, {z, p, z}, {l, l}},
106 {{p, p, p}, {z, p, z}, {r, r}}, {{p, p, m}, {z, p, z}, {l, r}},
107
108 {{m, m, m}, {z, m, z}, {l, l}}, {{p, m, p}, {z, m, z}, {r, r}},
109 {{m, m, p}, {z, m, z}, {r, l}}, {{m, m, m}, {z, m, z}, {l, l}},
110 {{p, m, m}, {z, m, z}, {l, r}}, {{p, m, p}, {z, m, z}, {r, r}},
111
112 {{p, m, m}, {p, z, z}, {l, l}}, {{p, p, m}, {p, z, z}, {r, l}},
113 {{p, p, p}, {p, z, z}, {r, r}}, {{p, m, m}, {p, z, z}, {l, l}},
114 {{p, p, p}, {p, z, z}, {r, r}}, {{p, m, p}, {p, z, z}, {l, r}},
115
116 {{m, m, m}, {m, z, z}, {l, l}}, {{m, p, p}, {m, z, z}, {r, r}},
117 {{m, p, m}, {m, z, z}, {r, l}}, {{m, m, m}, {m, z, z}, {l, l}},
118 {{m, m, p}, {m, z, z}, {l, r}}, {{m, p, p}, {m, z, z}, {r, r}},
119 });
120
121 Transformable3D transformable;
122 transformable.SetVertexArray(std::move(vertex_array));
123 return transformable;
124}
An array of smk::Vertex moved to the GPU memory. This represent a set of triangles to be drawn by the...
Definition: VertexArray.hpp:20

◆ FromVertexArray()

Transformable smk::Shape::FromVertexArray ( VertexArray  vertex_array)
static

Definition at line 15 of file Shape.cpp.

15 {
16 Transformable drawable;
17 drawable.SetVertexArray(std::move(vertex_array));
18 return drawable;
19}
void SetVertexArray(VertexArray vertex_array)
Set the object's shape.

◆ IcoSphere()

Transformable3D smk::Shape::IcoSphere ( int  iteration)
static

A centered sphere.

Parameters
iterationControl the number of triangle used to make the sphere. It will contain $ 8 \time 3^iteration$ triangles.
Examples
shape_3d.cpp.

Definition at line 130 of file Shape.cpp.

130 {
131 std::vector<glm::vec3> out = {
132 {+1.F, +0.F, +0.F}, {+0.F, +1.F, +0.F}, {+0.F, +0.F, +1.F},
133 {-1.F, +0.F, +0.F}, {+0.F, +0.F, -1.F}, {+0.F, -1.F, +0.F},
134 {+0.F, -1.F, +0.F}, {+1.F, +0.F, +0.F}, {+0.F, +0.F, +1.F},
135 {+0.F, +1.F, +0.F}, {+0.F, +0.F, -1.F}, {-1.F, +0.F, +0.F},
136 {-1.F, +0.F, +0.F}, {+0.F, -1.F, +0.F}, {+0.F, +0.F, +1.F},
137 {+1.F, +0.F, +0.F}, {+0.F, +0.F, -1.F}, {+0.F, +1.F, +0.F},
138 {+0.F, +1.F, +0.F}, {-1.F, +0.F, +0.F}, {+0.F, +0.F, +1.F},
139 {+0.F, -1.F, +0.F}, {+0.F, +0.F, -1.F}, {+1.F, +0.F, +0.F},
140 };
141
142 for (int i = 0; i < iteration; ++i) {
143 std::vector<glm::vec3> in;
144 std::swap(in, out);
145 for (unsigned int j = 0; j < in.size();) {
146 glm::vec3& a = in[j++];
147 glm::vec3& b = in[j++];
148 glm::vec3& c = in[j++];
149 glm::vec3 d = glm::normalize(a + b + c);
150 auto addition = {a, b, d, b, c, d, c, a, d};
151 out.insert(out.end(), addition.begin(), addition.end()); // NOLINT
152 }
153 }
154
155 std::vector<Vertex3D> vertex_array(out.size());
156 for (auto& it : out) {
157 vertex_array.push_back(
158 {it * 0.5F, it, {it.x * 0.5F + 0.5F, it.y * 0.5F + 0.5F}}); // NOLINT
159 }
160
161 Transformable3D transformable;
162 transformable.SetVertexArray(vertex_array);
163 return transformable;
164}

◆ Line()

Transformable smk::Shape::Line ( const glm::vec2 &  a,
const glm::vec2 &  b,
float  thickness 
)
static

Return a line with a given thickness.

Parameters
aThe first end.
bSecond end.
thicknessThis line thickness.
Examples
shape_2d.cpp.

Definition at line 25 of file Shape.cpp.

27 {
28 glm::vec2 dt = glm::normalize(glm::vec2(b.y - a.y, -b.x + a.x)) * thickness *
29 0.5F; // NOLINT
30
31 return FromVertexArray(VertexArray({
32 {a + dt, {0.F, 0.F}},
33 {b + dt, {1.F, 0.F}},
34 {b - dt, {1.F, 1.F}},
35 {a + dt, {0.F, 0.F}},
36 {b - dt, {1.F, 1.F}},
37 {a - dt, {0.F, 1.F}},
38 }));
39}

◆ Path()

smk::Transformable smk::Shape::Path ( const std::vector< glm::vec2 > &  points,
float  thickness 
)
static

Build a path of a given |thickness| along a sequence of connected lines. @params points The sequence of points the path is going through. @params thickness This width of the path.

Examples
bezier.cpp.

Definition at line 215 of file Shape.cpp.

216 {
217 using namespace glm;
218 std::vector<glm::vec3> planes_left;
219 std::vector<glm::vec3> planes_right;
220
221 thickness *= 0.5F; // NOLINT
222 // Compute planes shifted by +/- |thickness| around lines:
223 // points[i] -- points[i+1]
224
225 for (size_t i = 1; i < points.size(); ++i) {
226 glm::vec3 plane_left =
227 cross(vec3(points[i - 1], 1.F), vec3(points[i - 0], 1.F));
228 glm::vec3 plane_right = plane_left;
229 plane_left.z -= thickness * length(vec2(plane_left.x, plane_left.y));
230 plane_right.z += thickness * length(vec2(plane_right.x, plane_right.y));
231 planes_left.push_back(plane_left);
232 planes_right.push_back(plane_right);
233 }
234
235 // Compute the intersection of plane[i] and plane[i+1]. It gives us the the
236 // outline of the shape to be filled.
237 std::vector<glm::vec2> points_left;
238 std::vector<glm::vec2> points_right;
239
240 // Cap begin.
241 {
242 glm::vec2 direction = normalize(points[1] - points[0]);
243 glm::vec2 normal = {direction.y, -direction.x};
244 points_left.push_back(points[0] - normal * thickness);
245 points_right.push_back(points[0] + normal * thickness);
246 }
247
248 size_t i = 0;
249 for (size_t j = 1; j < points.size() - 1; ++j) {
250 glm::vec3 intersection_left = cross(planes_left[i], planes_left[j]);
251 glm::vec3 intersection_right = cross(planes_right[i], planes_right[j]);
252 const float epsilon = 0.01F;
253 if (intersection_left.z * intersection_right.z < epsilon) {
254 continue;
255 }
256 intersection_left /= intersection_left.z;
257 intersection_right /= intersection_right.z;
258 auto left = glm::vec2(intersection_left);
259 auto right = glm::vec2(intersection_right);
260 // NOLINTNEXTLINE
261 if (glm::distance(left, right) > 10.F * thickness) {
262 auto middle = glm::vec2(left + right) * 0.5F; // NOLINT
263 // NOLINTNEXTLINE
264 auto dir = glm::normalize(glm::vec2(right - left)) * 5.F * thickness;
265 left = glm::vec3(middle - dir, 1.F);
266 right = glm::vec3(middle + dir, 1.F);
267 }
268 points_left.push_back(left);
269 points_right.push_back(right);
270 i = j;
271 }
272
273 // Cap end.
274 {
275 glm::vec2 direction = normalize(points[points.size() - 2] - points.back());
276 glm::vec2 normal = {direction.y, -direction.x};
277 points_left.push_back(points.back() + normal * thickness);
278 points_right.push_back(points.back() - normal * thickness);
279 }
280
281 std::vector<smk::Vertex> v;
282
283 // Fill using rectangles.
284 // ...-A--C-... A = points_left[i]
285 // |\ | ... B = points_right[i]
286 // | \| ... C = points_left[i + 1]
287 // ...-B--D-... D = points_right[i + 1];
288 for (size_t i = 1; i < points_left.size(); ++i) {
289 glm::vec2& A = points_left[i - 1];
290 glm::vec2& B = points_right[i - 1];
291 glm::vec2& C = points_left[i];
292 glm::vec2& D = points_right[i];
293
294 v.push_back({A, {0.0, 0.0}});
295 v.push_back({B, {0.0, 0.0}});
296 v.push_back({D, {0.0, 0.0}});
297 v.push_back({A, {0.0, 0.0}});
298 v.push_back({D, {0.0, 0.0}});
299 v.push_back({C, {0.0, 0.0}});
300 }
301
302 return smk::Shape::FromVertexArray(smk::VertexArray(v));
303}

◆ Plane()

Transformable3D smk::Shape::Plane ( )
static

Return a centered 1x1 square in a 3D space.

Definition at line 167 of file Shape.cpp.

167 {
168 constexpr float m = -0.5F;
169 constexpr float z = +0.F;
170 constexpr float p = +0.5F;
171 constexpr float l = 0.F;
172 constexpr float r = 1.F;
173 auto vertex_array = smk::VertexArray({
174 {{m, m, z}, {z, z, p}, {l, l}},
175 {{p, m, z}, {z, z, p}, {r, l}},
176 {{p, p, z}, {z, z, p}, {r, r}},
177 {{m, m, z}, {z, z, p}, {l, l}},
178 {{p, p, z}, {z, z, p}, {r, r}},
179 {{m, p, z}, {z, z, p}, {l, r}},
180 });
181
182 Transformable3D transformable;
183 transformable.SetVertexArray(std::move(vertex_array));
184 return transformable;
185}

◆ RoundedRectangle()

smk::Transformable smk::Shape::RoundedRectangle ( float  width,
float  height,
float  radius 
)
static

Return a rounded centered rectangle. @params width The width of the rectangle. @params height The height of the rectangle. @params radius The radius of the four corners.

Examples
rounded_rectangle.cpp.

Definition at line 309 of file Shape.cpp.

311 {
312 radius = std::max(radius, 0.F);
313 radius = std::min(radius, width * 0.5F); // NOLINT
314 radius = std::min(radius, height * 0.5F); // NOLINT
315
316 width = width * 0.5F - radius; // NOLINT
317 height = height * 0.5F - radius; // NOLINT
318 std::vector<smk::Vertex> v;
319 smk::Vertex p0 = {{0.F, 0.F}, {0.F, 0.F}};
320 smk::Vertex p1 = {{width + radius, -height}, {0.F, 0.F}};
321 smk::Vertex p2 = {{width + radius, height}, {0.F, 0.F}};
322
323 v.push_back(p0);
324 v.push_back(p1);
325 v.push_back(p2);
326
327 const float angle_delta = 2.0 * M_PI / 40.f;
328
329 auto center = glm::vec2(width, radius);
330 // NOLINTNEXTLINE
331 for (float angle = 0.F; angle < 2.F * M_PI; angle += angle_delta) {
332 if (angle > 0.75 * 2.F * M_PI) { // NOLINT
333 center = glm::vec2(width, -height);
334 } else if (angle > 0.5 * 2.F * M_PI) { // NOLINT
335 center = glm::vec2(-width, -height);
336 } else if (angle > 0.25 * 2.F * M_PI) { // NOLINT
337 center = glm::vec2(-width, +height);
338 } else {
339 center = glm::vec2(+width, +height);
340 }
341
342 p1 = p2;
343 p2 = {center + radius * glm::vec2(std::cos(angle), std::sin(angle)), {0.F, 0.F}};
344
345 v.push_back(p0);
346 v.push_back(p1);
347 v.push_back(p2);
348 }
349
350 p1 = p2;
351 p2 = {{width + radius, -height}, {0.F, 0.F}};
352 v.push_back(p0);
353 v.push_back(p1);
354 v.push_back(p2);
355
356 return smk::Shape::FromVertexArray(smk::VertexArray(v));
357}
The vertex structure suitable for a 2D shader.
Definition: Vertex.hpp:13

◆ Square()

Transformable smk::Shape::Square ( )
static

Return the square [0,1]x[0,1].

Definition at line 42 of file Shape.cpp.

42 {
43 static VertexArray vertex_array;
44
45 if (!vertex_array.size()) {
46 vertex_array = VertexArray({
47 {{0.F, 0.F}, {0.F, 0.F}},
48 {{1.F, 0.F}, {1.F, 0.F}},
49 {{1.F, 1.F}, {1.F, 1.F}},
50 {{0.F, 0.F}, {0.F, 0.F}},
51 {{1.F, 1.F}, {1.F, 1.F}},
52 {{0.F, 1.F}, {0.F, 1.F}},
53 });
54 }
55
56 return FromVertexArray(vertex_array);
57}

The documentation for this class was generated from the following files: