16 inline vertex create_vertex(
const glm::vec3& pos,
bool bUnitLengthPosNormal =
false)
22 if (bUnitLengthPosNormal)
24 normalPos.x = normalPos.x > 0.f ? 1.f : -1.f;
25 normalPos.y = normalPos.y > 0.f ? 1.f : -1.f;
26 normalPos.z = normalPos.z > 0.f ? 1.f : -1.f;
28 ret.normal = glm::normalize(normalPos);
33 inline geometry create_figure(
34 std::span<const glm::vec3> positions,
35 std::span<const index_type> _indices,
36 const glm::vec3& offset,
38 bool bUnitLengthPosNormal =
false)
45 for (
size_t i = 0; i < _indices.size(); i += 3)
47 const glm::vec3 pos0 = positions[_indices[i + 0]];
48 const glm::vec3 pos1 = positions[_indices[i + 1]];
49 const glm::vec3 pos2 = positions[_indices[i + 2]];
51 const glm::vec3 normal = glm::cross(pos2 - pos1, pos0 - pos1);
54 ret.geomVertices.emplace_back(pos0, normal, tangent);
55 ret.geomVertices.emplace_back(pos1, normal, tangent);
56 ret.geomVertices.emplace_back(pos2, normal, tangent);
58 ret.geomIndices.push_back(
static_cast<index_type
>(i + 0));
59 ret.geomIndices.push_back(
static_cast<index_type
>(i + 1));
60 ret.geomIndices.push_back(
static_cast<index_type
>(i + 2));
65 for (
const glm::vec3& pos : positions)
66 ret.geomVertices.emplace_back(create_vertex(pos, bUnitLengthPosNormal));
68 ret.geomIndices = indices(_indices.begin(), _indices.end());
74 inline std::array<glm::vec3, 12> create_icosahedron_positions(
float fRadius)
76 const float X = 0.525731112119133606f * fRadius;
77 const float Z = 0.850650808352039932f * fRadius;
100 bool bUnitLengthPosNormal)
102 const float fHalfSide1 = fSide1 / 2.f;
103 const float fHalfSide2 = fSide2 / 2.f;
104 const float fHalfSide3 = fSide3 / 2.f;
106 const std::array<glm::vec3, 8> parallelogramPositions = { { { -fHalfSide1, -fHalfSide2, -fHalfSide3 },
107 { fHalfSide1, -fHalfSide2, -fHalfSide3 },
108 { fHalfSide1, fHalfSide2, -fHalfSide3 },
109 { -fHalfSide1, fHalfSide2, -fHalfSide3 },
110 { -fHalfSide1, -fHalfSide2, fHalfSide3 },
111 { fHalfSide1, -fHalfSide2, fHalfSide3 },
112 { fHalfSide1, fHalfSide2, fHalfSide3 },
113 { -fHalfSide1, fHalfSide2, fHalfSide3 } } };
115 return details::create_figure(
116 parallelogramPositions,
117 shape_indices::parallelogram,
118 { fHalfSide1, fHalfSide2, fHalfSide3 },
120 bUnitLengthPosNormal);
128 constexpr
auto negativeZVector = glm::vec3(0.f, 0.f, -1.f);
129 return glm::normalize(glm::cross(negativeZVector, normal));
136 for (
size_t i = 0; i < triangles.size(); i += 3)
138 lines.push_back(triangles[i + 0]);
139 lines.push_back(triangles[i + 1]);
141 lines.push_back(triangles[i + 1]);
142 lines.push_back(triangles[i + 2]);
144 lines.push_back(triangles[i + 2]);
145 lines.push_back(triangles[i + 0]);
153 return details::create_parallelogram(fSide1, fSide2, fSide3, bFlatNormals,
true);
159 geom.eDrawMode = draw_mode::lines_list;
167 return details::create_parallelogram(fSide, fSide, fSide, bFlatNormals,
false);
173 geom.eDrawMode = draw_mode::lines_list;
181 return details::create_figure(
182 details::create_icosahedron_positions(fRadius),
183 shape_indices::icosahedron,
184 { fRadius, fRadius, fRadius },
191 geom.eDrawMode = draw_mode::lines_list;
199 const auto icosahedronPositions = details::create_icosahedron_positions(fRadius);
201 std::vector<glm::vec3> icospherePositions = std::vector(icosahedronPositions.cbegin(), icosahedronPositions.cend());
203 indices thisLevelIndices;
204 indices prevLevelIndices = indices(shape_indices::icosahedron.cbegin(), shape_indices::icosahedron.cend());
206 std::unordered_map<size_t, index_type> edgeMap;
208 for (
size_t i = 0; i < nDivides; ++i)
211 const size_t end = prevLevelIndices.size();
213 for (
size_t j = 0; j < end; j += 3)
215 std::array<index_type, 3> indicesOuter;
216 std::array<index_type, 3> indicesEdge;
218 for (
size_t k = 0; k < 3; ++k)
220 const index_type k1 = (k + 1) % 3;
221 index_type e0 = prevLevelIndices[j + k];
222 index_type e1 = prevLevelIndices[j + k1];
223 indicesOuter[k] = e0;
228 const size_t nEdgeKey = e0 | e1 << 16;
230 if (
auto it = edgeMap.find(nEdgeKey); it != edgeMap.end())
232 indicesEdge[k] = it->second;
236 indicesEdge[k] =
static_cast<index_type
>(icospherePositions.size());
237 edgeMap[nEdgeKey] = indicesEdge[k];
239 const auto& e0pos = icospherePositions[e0];
240 const auto& e1pos = icospherePositions[e1];
241 glm::vec3 newVertex { e0pos.x + e1pos.x, e0pos.y + e1pos.y, e0pos.z + e1pos.z };
243 const float fScale = fRadius / glm::length(newVertex);
246 icospherePositions.push_back(newVertex);
250 thisLevelIndices.push_back(indicesOuter[0]);
251 thisLevelIndices.push_back(indicesEdge[0]);
252 thisLevelIndices.push_back(indicesEdge[2]);
253 thisLevelIndices.push_back(indicesOuter[1]);
254 thisLevelIndices.push_back(indicesEdge[1]);
255 thisLevelIndices.push_back(indicesEdge[0]);
256 thisLevelIndices.push_back(indicesOuter[2]);
257 thisLevelIndices.push_back(indicesEdge[2]);
258 thisLevelIndices.push_back(indicesEdge[1]);
259 thisLevelIndices.push_back(indicesEdge[0]);
260 thisLevelIndices.push_back(indicesEdge[1]);
261 thisLevelIndices.push_back(indicesEdge[2]);
264 prevLevelIndices = std::move(thisLevelIndices);
267 return details::create_figure(icospherePositions, prevLevelIndices, { fRadius, fRadius, fRadius }, bFlatNormals);
273 geom.eDrawMode = draw_mode::lines_list;
281 const float fHalfWidth = fWidth / 2.f;
282 const float fHalfHeight = fHeight / 2.f;
284 return { { { details::create_vertex({ fHalfWidth, fHalfHeight, 0.f }),
285 details::create_vertex({ fHalfWidth, -fHalfHeight, 0.f }),
286 details::create_vertex({ -fHalfWidth, -fHalfHeight, 0.f }),
287 details::create_vertex({ -fHalfWidth, fHalfHeight, 0.f }) } },
288 std::vector(shape_indices::rect.cbegin(), shape_indices::rect.cend()),
289 { fHalfWidth, fHalfHeight, 0.f },
290 draw_mode::triangles_list };
295 const float fLinesWidth = fWidth - 1.f;
296 const float fLinesHeight = fHeight - 1.f;
298 const float fHalfWidth = fLinesWidth / 2.f;
299 const float fHalfHeight = fLinesHeight / 2.f;
302 return { { { details::create_vertex({ fHalfWidth, fHalfHeight, 0.f }),
303 details::create_vertex({ fHalfWidth, -fHalfHeight, 0.f }),
304 details::create_vertex({ -fHalfWidth, -fHalfHeight, 0.f }),
305 details::create_vertex({ -fHalfWidth, -fHalfHeight - 1.f, 0.f }),
306 details::create_vertex({ -fHalfWidth, fHalfHeight, 0.f }) } },
307 { 0, 1, 2, 3, 4, 0 },
308 { fHalfWidth + 1.f, fHalfHeight + 1.f, 0.f },
309 draw_mode::lines_strip };
324 const size_t nVertices = nSides + 2;
325 const float fSides =
static_cast<float>(nSides);
326 constexpr
float f2Pi = 2.0f * std::numbers::pi_v<float>;
333 ret.
geomVertices.emplace_back(details::create_vertex({ 0.f, 0.f, 0.f }));
335 for (
size_t i = 1; i < nVertices; ++i)
337 ret.
geomIndices.push_back(
static_cast<index_type
>(i));
339 details::create_vertex({ fHorRadius * std::cos(
static_cast<float>(i) * f2Pi / fSides),
340 fVertRadius * std::sin(
static_cast<float>(i) * f2Pi / fSides),
344 ret.
eDrawMode = draw_mode::triangles_fan;
345 ret.
offset = { fHorRadius, fVertRadius, 0.f };
geometry create_cube(float fSide, bool bFlatNormals=true)
Create cube geometry.
geometry create_circle_lines(float fRadius, size_t nSides)
Create circle geometry for lines drawing.
geometry create_ellipse(float fHorRadius, float fVertRadius, size_t nSides)
Create ellipse geometry.
geometry create_icosahedron(float fRadius, bool bFlatNormals=true)
Create icosahedron geometry.
geometry create_square_lines(float fSideLength)
Create square geometry for lines drawing.
geometry create_parallelogram_lines(float fSide1, float fSide2, float fSide3)
Create parallelogram geometry for lines drawing.
geometry create_icosphere_lines(float fRadius, size_t nDivides)
Create icosphere geometry for lines drawing.
geometry create_ellipse_lines(float fHorRadius, float fVertRadius, size_t nSides)
Create ellipse geometry for lines drawing.
glm::vec3 create_tangent(const glm::vec3 &normal)
Create tangent vector for a given normal.
geometry create_parallelogram(float fSide1, float fSide2, float fSide3, bool bFlatNormals=true)
Create parallelogram geometry.
geometry create_square(float fSideLength)
Create square geometry.
geometry create_cube_lines(float fSide)
Create cube geometry for lines drawing.
indices transform_triangle_indices_to_lines(indices_view triangles)
Transform triangle indices to line indices.
geometry create_icosahedron_lines(float fRadius)
Create icosahedron geometry for lines drawing.
geometry create_circle(float fRadius, size_t nSides)
Create circle geometry for lines drawing.
geometry create_icosphere(float fRadius, size_t nDivides, bool bFlatNormals=false)
Create icosphere geometry.
geometry create_rect(float fWidth, float fHeight)
Create rectangle geometry.
geometry create_rect_lines(float fWidth, float fHeight)
Create rectangle geometry for lines drawing.
indices geomIndices
indices array
vertices geomVertices
vertices array
glm::vec3 offset
offset of the center
draw_mode eDrawMode
draw mode