Oxygen Engine
Modern C++ 3D Engine using OpenGL
Loading...
Searching...
No Matches
platonic_solid.h
1#ifndef OE_SCENE_PRIMITIVE_PLATONIC_SOLID_H
2#define OE_SCENE_PRIMITIVE_PLATONIC_SOLID_H
3
4#include "../mesh.h"
5
7{
16 {
17 TETRAHEDRON, //< 4 Faces of equilateral triangles
18 OCTAHEDRON, //< 8 Faces of equilateral triangles
19 DODECAHEDRON, //< 12 Faces of equilateral triangles
20 ICOSAHEDRON //< 20 Faces of regular pentagons
21 };
22
26 template <typename VertexType = Vertex>
27 struct PlatonicSolid : public Mesh<VertexType>
28 {
37 PlatonicSolid(const PlatonicSolidType solid, const bool smooth_normals = false)
38 {
39 auto& vertices = Mesh<VertexType>::vertices;
40 auto& indices = Mesh<VertexType>::indices;
41 auto& primitives = Mesh<VertexType>::primitives;
42
43 switch (solid)
44 {
45 case PlatonicSolidType::TETRAHEDRON:
46 {
47 const float sqrt_2 = sqrt(2.0f);
48 const float sqrt_6 = sqrt(6.0f);
49
50 vertices =
51 {
52 {.position = glm::vec3(0.0f, 0.f, 1.0f), .tex_coords_0 = glm::vec2(0.f, 0.f)},
53 {.position = glm::vec3(-sqrt_2, sqrt_6, -1.0f) / 3.0f, .tex_coords_0 = glm::vec2(1.f, 0.f)},
54 {.position = glm::vec3(2.f*sqrt_2, 0.f, -1.0f) / 3.0f, .tex_coords_0 = glm::vec2(0.f, 1.f)},
55 {.position = glm::vec3(-sqrt_2, -sqrt_6, -1.0f) / 3.0f, .tex_coords_0 = glm::vec2(1.f, 1.f)},
56 };
57
58 indices = {{
59 2, 1, 0,
60 3, 2, 0,
61 1, 3, 0,
62 2, 3, 1
63 }};
64 }
65 break;
66
67 case PlatonicSolidType::OCTAHEDRON:
68 {
69 vertices =
70 {
71 {.position = glm::vec3(1.0f, .0f, .0f), .tex_coords_0 = glm::vec2(1.f, 0.f)},
72 {.position = glm::vec3(-1.0f, .0f, .0f), .tex_coords_0 = glm::vec2(1.f, 0.f)},
73 {.position = glm::vec3(.0f, 1.0f, .0f), .tex_coords_0 = glm::vec2(0.f, 0.f)},
74 {.position = glm::vec3(0.0f, -1.f, .0f), .tex_coords_0 = glm::vec2(1.f, 1.f)},
75 {.position = glm::vec3(0.0f, 0.f, 1.f), .tex_coords_0 = glm::vec2(0.f, 1.f)},
76 {.position = glm::vec3(0.0f, 0.f, -1.f), .tex_coords_0 = glm::vec2(0.f, 1.f)},
77 };
78
79 indices = {{
80 4, 0, 2,
81 5, 2, 0,
82 4, 2, 1,
83 5, 1, 2,
84 4, 1, 3,
85 5, 3, 1,
86 4, 3, 0,
87 5, 0, 3
88 }};
89 }
90 break;
91
92 case PlatonicSolidType::DODECAHEDRON:
93 {
94 const float sqrt_3 = sqrt(3.0f);
95 const float sqrt_5 = sqrt(5.0f);
96
97 const float a = 1.0f / sqrt_3;
98 const float b = sqrt((3.0f - sqrt_5)/6.0f);
99 const float c = sqrt((3.0f + sqrt_5)/6.0f);
100
101 vertices =
102 {
103 {.position = glm::vec3(a, a, a), .tex_coords_0 = glm::vec2(1.f, 0.f)},
104 {.position = glm::vec3(a, a, -a), .tex_coords_0 = glm::vec2(1.f, 0.f)},
105 {.position = glm::vec3(a, -a, a), .tex_coords_0 = glm::vec2(1.f, 0.f)},
106 {.position = glm::vec3(a, -a, -a), .tex_coords_0 = glm::vec2(1.f, 0.f)},
107 {.position = glm::vec3(-a, a, a), .tex_coords_0 = glm::vec2(1.f, 0.f)},
108
109 {.position = glm::vec3(-a, a, -a), .tex_coords_0 = glm::vec2(1.f, 0.f)},
110 {.position = glm::vec3(-a, -a, a), .tex_coords_0 = glm::vec2(1.f, 0.f)},
111 {.position = glm::vec3(-a, -a, -a), .tex_coords_0 = glm::vec2(1.f, 0.f)},
112 {.position = glm::vec3(b, c, 0.f), .tex_coords_0 = glm::vec2(1.f, 0.f)},
113 {.position = glm::vec3(-b, c, 0.f), .tex_coords_0 = glm::vec2(1.f, 0.f)},
114
115 {.position = glm::vec3(b, -c, 0.f), .tex_coords_0 = glm::vec2(1.f, 0.f)},
116 {.position = glm::vec3(-b, -c, 0.f), .tex_coords_0 = glm::vec2(1.f, 0.f)},
117 {.position = glm::vec3(c, 0.f, b), .tex_coords_0 = glm::vec2(1.f, 0.f)},
118 {.position = glm::vec3(c, 0.f, -b), .tex_coords_0 = glm::vec2(1.f, 0.f)},
119 {.position = glm::vec3(-c, 0.f, b), .tex_coords_0 = glm::vec2(1.f, 0.f)},
120
121 {.position = glm::vec3(-c, 0.f, -b), .tex_coords_0 = glm::vec2(1.f, 0.f)},
122 {.position = glm::vec3(0.f, b, c), .tex_coords_0 = glm::vec2(1.f, 0.f)},
123 {.position = glm::vec3(0.f, -b, c), .tex_coords_0 = glm::vec2(1.f, 0.f)},
124 {.position = glm::vec3(0.f, b, -c), .tex_coords_0 = glm::vec2(1.f, 0.f)},
125 {.position = glm::vec3(0.f, -b, -c), .tex_coords_0 = glm::vec2(1.f, 0.f)},
126 };
127
128 indices = {{
129 0, 8, 9,
130 0, 9, 4,
131 0, 4, 16,
132 0, 12, 13,
133 0, 13, 1,
134 0, 1, 8,
135 0, 16, 17,
136 0, 17, 2,
137 0, 2, 12,
138 8, 1, 18,
139 8, 18, 5,
140 8, 5, 9,
141 12, 2, 10,
142 12, 10, 3,
143 12, 3, 13,
144 16, 4, 14,
145 16, 14, 6,
146 16, 6, 17,
147 9, 5, 15,
148 9, 15, 14,
149 9, 14, 4,
150 6, 11, 10,
151 6, 10, 2,
152 6, 2, 17,
153 3, 19, 18,
154 3, 18, 1,
155 3, 1, 13,
156 7, 15, 5,
157 7, 5, 18,
158 7, 18, 19,
159 7, 11, 6,
160 7, 6, 14,
161 7, 14, 15,
162 7, 19, 3,
163 7, 3, 10,
164 7, 10, 11
165 }};
166
167 for (size_t i=0; i<vertices.size(); i++)
168 {
169 VertexType& vertex = vertices[i];
170 vertex.tex_coords_0 = glm::vec2(vertex.position.x, -vertex.position.y);
171 }
172 }
173 break;
174
175 case PlatonicSolidType::ICOSAHEDRON:
176 {
177 const float phi = (1.0f + sqrt(5.0f)) / 2.0f; // Golden ratio
178 const float s = sqrt(1 + phi * phi);
179
180 vertices =
181 {
182 {.position = glm::vec3(phi, 1.f, 0.f) / s, .tex_coords_0 = glm::vec2(1.f, 0.f)},
183 {.position = glm::vec3(-phi, 1.f, 0.f) / s, .tex_coords_0 = glm::vec2(0.f, 1.f)},
184 {.position = glm::vec3(phi, -1.f, 0.f) / s, .tex_coords_0 = glm::vec2(1.f, 1.f)},
185
186 {.position = glm::vec3(-phi, -1.f, 0.f) / s, .tex_coords_0 = glm::vec2(1.f, 1.f)},
187 {.position = glm::vec3(1.f, 0.f, phi) / s, .tex_coords_0 = glm::vec2(1.f, 0.f)},
188 {.position = glm::vec3(1.f, 0.f, -phi) / s, .tex_coords_0 = glm::vec2(0.f, 0.f)},
189
190 {.position = glm::vec3(-1.f, 0.f, phi) / s, .tex_coords_0 = glm::vec2(0.f, 0.f)},
191 {.position = glm::vec3(-1.f, 0.f, -phi) / s, .tex_coords_0 = glm::vec2(1.f, 1.f)},
192 {.position = glm::vec3(0.f, phi, 1.f) / s, .tex_coords_0 = glm::vec2(1.f, 0.f)},
193
194 {.position = glm::vec3(0.f, -phi, 1.f) / s, .tex_coords_0 = glm::vec2(1.f, 0.f)},
195 {.position = glm::vec3(0.f, phi, -1.f) / s, .tex_coords_0 = glm::vec2(0.f, 1.f)},
196 {.position = glm::vec3(0.f, -phi, -1.f) / s, .tex_coords_0 = glm::vec2(1.f, 0.f)},
197 };
198
199 indices = {{
200 0, 8, 4,
201 0, 5, 10,
202 2, 4, 9,
203 2, 11, 5,
204 1, 6, 8,
205 1, 10, 7,
206 3, 9, 6,
207 3, 7, 11,
208 0, 10, 8,
209 1, 8, 10,
210 2, 9, 11,
211 3, 11, 9,
212 4, 2, 0,
213 5, 0, 2,
214 6, 1, 3,
215 7, 3, 1,
216 8, 6, 4,
217 9, 4, 6,
218 10, 5, 7,
219 11, 7, 5
220 }};
221
222 for (size_t i=0; i<vertices.size(); i++)
223 {
224 VertexType& vertex = vertices[i];
225 vertex.tex_coords_0 = glm::vec2(vertex.position.x, -vertex.position.y);
226 }
227 }
228 break;
229 }
230
231
232 // Duplicate vertices to achieve flat rendering
233 if (!smooth_normals)
234 {
235 std::vector<VertexType> duplicated_vertices;
236 duplicated_vertices.reserve(indices.size());
237
238 for (auto i = 0u; i<indices.size(); ++i)
239 {
240 duplicated_vertices.push_back(vertices[indices[i]]);
241 }
242
243 vertices = duplicated_vertices;
244 indices.resize(0);
245 indices.reserve(vertices.size());
246
247 for (auto i = 0u; i<vertices.size(); ++i)
248 {
249 indices.push_back(i);
250 }
251 }
252
253 primitives = {{0, indices.size()}};
254
255 if constexpr (IsVertexWithTangents<Vertex>)
256 {
259 }
260 }
261 };
262}
263
264#endif
Definition vertex.h:39
Standard mesh primitives (Cube, Plane, Teapot, etc...)
Definition cube.h:7
PlatonicSolidType
Type of Platonic solid.
Definition platonic_solid.h:16
Definition mesh.h:61
constexpr void generateNormals()
Generate mesh normals from vertices positions.
Definition mesh.h:272
constexpr void generateTangents()
Compute Tangents using mikkTSpace.
Definition mesh.h:340
Primitive generating a Platonic solid.
Definition platonic_solid.h:28
PlatonicSolid(const PlatonicSolidType solid, const bool smooth_normals=false)
Generate a Platonic solid mesh.
Definition platonic_solid.h:37