• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Razakhel / RaZ / 17194133734

24 Aug 2025 07:41PM UTC coverage: 74.168% (-0.03%) from 74.197%
17194133734

push

github

Razakhel
[Render/Overlay] Added validity checks to overlay widgets' constructors

- These produce warnings with GCC as they can be noexcept, but they should instead throw exceptions when inputs can be invalid

45 of 65 new or added lines in 4 files covered. (69.23%)

8338 of 11242 relevant lines covered (74.17%)

1758.09 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.22
/src/RaZ/Data/Mesh.cpp
1
#include "RaZ/Data/Mesh.hpp"
2
#include "RaZ/Math/Constants.hpp"
3
#include "RaZ/Utils/Threading.hpp"
4

5
#include "tracy/Tracy.hpp"
6

7
#include <unordered_map>
8

9
namespace Raz {
10

11
Mesh::Mesh(const Plane& plane, float width, float depth) {
4✔
12
  ZoneScopedN("Mesh::Mesh(Plane)");
13

14
  const float height = plane.computeCentroid().y();
4✔
15

16
  // TODO: creating a Mesh from a Plane doesn't take the normal into account for the vertices' position
17
  const Vec3f firstPos(-width, height, depth);
4✔
18
  const Vec3f secondPos(width, height, depth);
4✔
19
  const Vec3f thirdPos(width, height, -depth);
4✔
20
  const Vec3f fourthPos(-width, height, -depth);
4✔
21

22
  Vertex firstCorner {};
4✔
23
  firstCorner.position  = firstPos;
4✔
24
  firstCorner.normal    = plane.getNormal();
4✔
25
  firstCorner.texcoords = Vec2f(0.f, 0.f);
4✔
26

27
  Vertex secondCorner {};
4✔
28
  secondCorner.position  = secondPos;
4✔
29
  secondCorner.normal    = plane.getNormal();
4✔
30
  secondCorner.texcoords = Vec2f(1.f, 0.f);
4✔
31

32
  Vertex thirdCorner {};
4✔
33
  thirdCorner.position  = thirdPos;
4✔
34
  thirdCorner.normal    = plane.getNormal();
4✔
35
  thirdCorner.texcoords = Vec2f(1.f, 1.f);
4✔
36

37
  Vertex fourthCorner {};
4✔
38
  fourthCorner.position  = fourthPos;
4✔
39
  fourthCorner.normal    = plane.getNormal();
4✔
40
  fourthCorner.texcoords = Vec2f(0.f, 1.f);
4✔
41

42
  Submesh& submesh = m_submeshes.emplace_back();
4✔
43

44
  submesh.getVertices() = { firstCorner, secondCorner, thirdCorner, fourthCorner };
4✔
45
  submesh.getTriangleIndices() = {
4✔
46
    0, 1, 2,
47
    0, 2, 3
48
  };
4✔
49

50
  computeTangents();
4✔
51
}
4✔
52

53
Mesh::Mesh(const Sphere& sphere, uint32_t subdivCount, SphereMeshType type) {
8✔
54
  ZoneScopedN("Mesh::Mesh(Sphere)");
55

56
  if (subdivCount < 1)
8✔
57
    throw std::invalid_argument("[Mesh] Cannot create a sphere mesh with no subdivision");
2✔
58

59
  switch (type) {
6✔
60
    case SphereMeshType::UV:
5✔
61
      createUvSphere(sphere, subdivCount, subdivCount);
5✔
62
      break;
5✔
63

64
    case SphereMeshType::ICO:
1✔
65
      createIcosphere(sphere, subdivCount);
1✔
66
      break;
1✔
67

NEW
68
    default:
×
NEW
69
      throw std::invalid_argument("[Mesh] Invalid sphere mesh type");
×
70
  }
71

72
  computeTangents();
6✔
73
}
12✔
74

75
Mesh::Mesh(const Triangle& triangle, const Vec2f& firstTexcoords, const Vec2f& secondTexcoords, const Vec2f& thirdTexcoords) {
3✔
76
  ZoneScopedN("Mesh::Mesh(Triangle)");
77

78
  const Vec3f& firstPos  = triangle.getFirstPos();
3✔
79
  const Vec3f& secondPos = triangle.getSecondPos();
3✔
80
  const Vec3f& thirdPos  = triangle.getThirdPos();
3✔
81
  const Vec3f normal     = triangle.computeNormal();
3✔
82

83
  Vertex firstVert {};
3✔
84
  firstVert.position  = firstPos;
3✔
85
  firstVert.texcoords = firstTexcoords;
3✔
86
  firstVert.normal    = normal;
3✔
87

88
  Vertex secondVert {};
3✔
89
  secondVert.position  = secondPos;
3✔
90
  secondVert.texcoords = secondTexcoords;
3✔
91
  secondVert.normal    = normal;
3✔
92

93
  Vertex thirdVert {};
3✔
94
  thirdVert.position  = thirdPos;
3✔
95
  thirdVert.texcoords = thirdTexcoords;
3✔
96
  thirdVert.normal    = normal;
3✔
97

98
  Submesh& submesh = m_submeshes.emplace_back();
3✔
99

100
  submesh.getVertices() = { firstVert, secondVert, thirdVert };
3✔
101
  submesh.getTriangleIndices() = { 0, 1, 2 };
3✔
102

103
  computeTangents();
3✔
104
}
3✔
105

106
Mesh::Mesh(const Quad& quad) {
2✔
107
  ZoneScopedN("Mesh::Mesh(Quad)");
108

109
  const Vec3f& leftTopPos     = quad.getLeftTopPos();
2✔
110
  const Vec3f& rightTopPos    = quad.getRightTopPos();
2✔
111
  const Vec3f& rightBottomPos = quad.getRightBottomPos();
2✔
112
  const Vec3f& leftBottomPos  = quad.getLeftBottomPos();
2✔
113

114
  Vertex leftTop {};
2✔
115
  leftTop.position  = leftTopPos;
2✔
116
  leftTop.texcoords = Vec2f(0.f, 1.f);
2✔
117

118
  Vertex rightTop {};
2✔
119
  rightTop.position  = rightTopPos;
2✔
120
  rightTop.texcoords = Vec2f(1.f, 1.f);
2✔
121

122
  Vertex rightBottom {};
2✔
123
  rightBottom.position  = rightBottomPos;
2✔
124
  rightBottom.texcoords = Vec2f(1.f, 0.f);
2✔
125

126
  Vertex leftBottom {};
2✔
127
  leftBottom.position  = leftBottomPos;
2✔
128
  leftBottom.texcoords = Vec2f(0.f, 0.f);
2✔
129

130
  // Computing normals
131
  leftTop.normal     = (leftTopPos - rightTopPos).cross(leftBottomPos - leftTopPos).normalize();
2✔
132
  rightTop.normal    = (rightTopPos - rightBottomPos).cross(leftTopPos - rightTopPos).normalize();
2✔
133
  rightBottom.normal = (rightBottomPos - leftBottomPos).cross(rightTopPos - rightBottomPos).normalize();
2✔
134
  leftBottom.normal  = (leftBottomPos - leftTopPos).cross(rightBottomPos - leftBottomPos).normalize();
2✔
135

136
  Submesh& submesh = m_submeshes.emplace_back();
2✔
137

138
  submesh.getVertices() = { leftTop, leftBottom, rightBottom, rightTop };
2✔
139
  submesh.getTriangleIndices() = {
2✔
140
    0, 1, 2,
141
    0, 2, 3
142
  };
2✔
143

144
  computeTangents();
2✔
145
}
2✔
146

147
Mesh::Mesh(const AABB& box) {
3✔
148
  ZoneScopedN("Mesh::Mesh(AABB)");
149

150
  const auto [minX, minY, minZ] = box.getMinPosition().getData();
3✔
151
  const auto [maxX, maxY, maxZ] = box.getMaxPosition().getData();
3✔
152

153
  const Vec3f rightTopBack(maxX, maxY, minZ);
3✔
154
  const Vec3f rightTopFront(maxX, maxY, maxZ);
3✔
155
  const Vec3f rightBottomBack(maxX, minY, minZ);
3✔
156
  const Vec3f rightBottomFront(maxX, minY, maxZ);
3✔
157
  const Vec3f leftTopBack(minX, maxY, minZ);
3✔
158
  const Vec3f leftTopFront(minX, maxY, maxZ);
3✔
159
  const Vec3f leftBottomBack(minX, minY, minZ);
3✔
160
  const Vec3f leftBottomFront(minX, minY, maxZ);
3✔
161

162
  Submesh& submesh = m_submeshes.emplace_back();
3✔
163

164
  std::vector<Vertex>& vertices = submesh.getVertices();
3✔
165
  vertices.reserve(24);
3✔
166

167
  // Right face
168
  vertices.emplace_back(Vertex{ rightBottomFront, Vec2f(0.f, 0.f), Axis::Right, Axis::Forward });
3✔
169
  vertices.emplace_back(Vertex{ rightBottomBack, Vec2f(1.f, 0.f), Axis::Right, Axis::Forward });
3✔
170
  vertices.emplace_back(Vertex{ rightTopFront, Vec2f(0.f, 1.f), Axis::Right, Axis::Forward });
3✔
171
  vertices.emplace_back(Vertex{ rightTopBack, Vec2f(1.f, 1.f), Axis::Right, Axis::Forward });
3✔
172

173
  // Left face
174
  vertices.emplace_back(Vertex{ leftBottomBack, Vec2f(0.f, 0.f), Axis::Left, Axis::Backward });
3✔
175
  vertices.emplace_back(Vertex{ leftBottomFront, Vec2f(1.f, 0.f), Axis::Left, Axis::Backward });
3✔
176
  vertices.emplace_back(Vertex{ leftTopBack, Vec2f(0.f, 1.f), Axis::Left, Axis::Backward });
3✔
177
  vertices.emplace_back(Vertex{ leftTopFront, Vec2f(1.f, 1.f), Axis::Left, Axis::Backward });
3✔
178

179
  // Top face
180
  vertices.emplace_back(Vertex{ leftTopFront, Vec2f(0.f, 0.f), Axis::Up, Axis::Right });
3✔
181
  vertices.emplace_back(Vertex{ rightTopFront, Vec2f(1.f, 0.f), Axis::Up, Axis::Right });
3✔
182
  vertices.emplace_back(Vertex{ leftTopBack, Vec2f(0.f, 1.f), Axis::Up, Axis::Right });
3✔
183
  vertices.emplace_back(Vertex{ rightTopBack, Vec2f(1.f, 1.f), Axis::Up, Axis::Right });
3✔
184

185
  // Bottom face
186
  vertices.emplace_back(Vertex{ leftBottomBack, Vec2f(0.f, 0.f), Axis::Down, Axis::Right });
3✔
187
  vertices.emplace_back(Vertex{ rightBottomBack, Vec2f(1.f, 0.f), Axis::Down, Axis::Right });
3✔
188
  vertices.emplace_back(Vertex{ leftBottomFront, Vec2f(0.f, 1.f), Axis::Down, Axis::Right });
3✔
189
  vertices.emplace_back(Vertex{ rightBottomFront, Vec2f(1.f, 1.f), Axis::Down, Axis::Right });
3✔
190

191
  // Front face
192
  vertices.emplace_back(Vertex{ leftBottomFront, Vec2f(0.f, 0.f), Axis::Backward, Axis::Right });
3✔
193
  vertices.emplace_back(Vertex{ rightBottomFront, Vec2f(1.f, 0.f), Axis::Backward, Axis::Right });
3✔
194
  vertices.emplace_back(Vertex{ leftTopFront, Vec2f(0.f, 1.f), Axis::Backward, Axis::Right });
3✔
195
  vertices.emplace_back(Vertex{ rightTopFront, Vec2f(1.f, 1.f), Axis::Backward, Axis::Right });
3✔
196

197
  // Back face
198
  vertices.emplace_back(Vertex{ rightBottomBack, Vec2f(0.f, 0.f), Axis::Forward, Axis::Left });
3✔
199
  vertices.emplace_back(Vertex{ leftBottomBack, Vec2f(1.f, 0.f), Axis::Forward, Axis::Left });
3✔
200
  vertices.emplace_back(Vertex{ rightTopBack, Vec2f(0.f, 1.f), Axis::Forward, Axis::Left });
3✔
201
  vertices.emplace_back(Vertex{ leftTopBack, Vec2f(1.f, 1.f), Axis::Forward, Axis::Left });
3✔
202

203
  submesh.getTriangleIndices() = {
3✔
204
     0,  1,  2,  1,  3,  2, // Right face
205
     4,  5,  6,  5,  7,  6, // Left face
206
     8,  9, 10,  9, 11, 10, // Top face
207
    12, 13, 14, 13, 15, 14, // Bottom face
208
    16, 17, 18, 17, 19, 18, // Front face
209
    20, 21, 22, 21, 23, 22  // Back face
210
  };
3✔
211
}
3✔
212

213
std::size_t Mesh::recoverVertexCount() const {
33✔
214
  std::size_t vertexCount = 0;
33✔
215

216
  for (const Submesh& submesh : m_submeshes)
72✔
217
    vertexCount += submesh.getVertexCount();
39✔
218

219
  return vertexCount;
33✔
220
}
221

222
std::size_t Mesh::recoverTriangleCount() const {
46✔
223
  std::size_t indexCount = 0;
46✔
224

225
  for (const Submesh& submesh : m_submeshes)
97✔
226
    indexCount += submesh.getTriangleIndexCount();
51✔
227

228
  return indexCount / 3;
46✔
229
}
230

231
const AABB& Mesh::computeBoundingBox() {
10✔
232
  ZoneScopedN("Mesh::computeBoundingBox");
233

234
  Vec3f minPos(std::numeric_limits<float>::max());
10✔
235
  Vec3f maxPos(std::numeric_limits<float>::lowest());
10✔
236

237
  for (Submesh& submesh : m_submeshes) {
20✔
238
    const AABB& boundingBox = submesh.computeBoundingBox();
10✔
239

240
    minPos.x() = std::min(minPos.x(), boundingBox.getMinPosition().x());
10✔
241
    minPos.y() = std::min(minPos.y(), boundingBox.getMinPosition().y());
10✔
242
    minPos.z() = std::min(minPos.z(), boundingBox.getMinPosition().z());
10✔
243

244
    maxPos.x() = std::max(maxPos.x(), boundingBox.getMaxPosition().x());
10✔
245
    maxPos.y() = std::max(maxPos.y(), boundingBox.getMaxPosition().y());
10✔
246
    maxPos.z() = std::max(maxPos.z(), boundingBox.getMaxPosition().z());
10✔
247
  }
248

249
  m_boundingBox = AABB(minPos, maxPos);
10✔
250
  return m_boundingBox;
10✔
251
}
252

253
void Mesh::computeTangents() {
28✔
254
  ZoneScopedN("Mesh::computeTangents");
255

256
  if (m_submeshes.empty())
28✔
257
    return;
1✔
258

259
  Threading::parallelize(m_submeshes, [] (const auto& range) noexcept {
27✔
260
    for (Submesh& submesh : range)
60✔
261
      submesh.computeTangents();
30✔
262
  });
30✔
263
}
264

265
void Mesh::createUvSphere(const Sphere& sphere, uint32_t widthCount, uint32_t heightCount) {
5✔
266
  // Algorithm based on the standard/UV sphere presented here: http://www.songho.ca/opengl/gl_sphere.html#sphere
267

268
  ZoneScopedN("Mesh::createUvSphere");
269

270
  Submesh& submesh = m_submeshes.emplace_back();
5✔
271

272
  std::vector<Vertex>& vertices = submesh.getVertices();
5✔
273
  vertices.reserve((heightCount + 1) * (widthCount + 1));
5✔
274

275
  const float widthStep  = 2 * Pi<float> / static_cast<float>(widthCount);
5✔
276
  const float heightStep = Pi<float> / static_cast<float>(heightCount);
5✔
277
  const Vec3f center     = sphere.getCenter();
5✔
278

279
  for (unsigned int heightIndex = 0; heightIndex <= heightCount; ++heightIndex) {
123✔
280
    const float heightAngle = Pi<float> / 2 - static_cast<float>(heightIndex) * heightStep;
118✔
281

282
    const float xz = sphere.getRadius() * std::cos(heightAngle);
118✔
283
    const float y  = sphere.getRadius() * std::sin(heightAngle);
118✔
284

285
    for (unsigned int widthIndex = 0; widthIndex <= widthCount; ++widthIndex) {
10,452✔
286
      const float widthAngle = static_cast<float>(widthIndex) * widthStep;
10,334✔
287

288
      const float x = xz * std::cos(widthAngle);
10,334✔
289
      const float z = xz * std::sin(widthAngle);
10,334✔
290

291
      Vertex vert;
10,334✔
292
      vert.position  = Vec3f(x + center.x(), y + center.y(), z + center.z());
10,334✔
293
      vert.texcoords = Vec2f(static_cast<float>(widthIndex) / static_cast<float>(widthCount),
20,668✔
294
                             static_cast<float>(heightIndex) / static_cast<float>(heightCount));
10,334✔
295
      vert.normal    = Vec3f(x, y, z).normalize(); // Dividing by the inverse radius does not give a perfectly unit vector; normalizing directly
10,334✔
296

297
      vertices.emplace_back(vert);
10,334✔
298
    }
299
  }
300

301
  std::vector<unsigned int>& indices = submesh.getTriangleIndices();
5✔
302
  indices.reserve(widthCount * 6 + (heightCount - 2) * widthCount * 6);
5✔
303

304
  // Upper circle
305
  for (unsigned int widthIndex = 0; widthIndex < widthCount; ++widthIndex) {
118✔
306
    const unsigned int widthStride = widthCount + widthIndex;
113✔
307

308
    indices.push_back(widthStride + 1);
113✔
309
    indices.push_back(widthIndex + 1);
113✔
310
    indices.push_back(widthStride + 2);
113✔
311
  }
312

313
  for (unsigned int heightIndex = 1; heightIndex < heightCount - 1; ++heightIndex) {
111✔
314
    unsigned int curHeightStride  = heightIndex * (widthCount + 1);
106✔
315
    unsigned int nextHeightStride = curHeightStride + widthCount + 1;
106✔
316

317
    for (unsigned int widthIndex = 0; widthIndex < widthCount; ++widthIndex, ++curHeightStride, ++nextHeightStride) {
9,986✔
318
      indices.push_back(nextHeightStride);
9,880✔
319
      indices.push_back(curHeightStride);
9,880✔
320
      indices.push_back(curHeightStride + 1);
9,880✔
321

322
      indices.push_back(nextHeightStride);
9,880✔
323
      indices.push_back(curHeightStride + 1);
9,880✔
324
      indices.push_back(nextHeightStride + 1);
9,880✔
325
    }
326
  }
327

328
  // Lower circle
329
  {
330
    unsigned int curHeightStride  = (heightCount - 1) * (widthCount + 1);
5✔
331
    unsigned int nextHeightStride = curHeightStride + widthCount + 1;
5✔
332

333
    for (unsigned int widthIndex = 0; widthIndex < widthCount; ++widthIndex, ++curHeightStride, ++nextHeightStride) {
118✔
334
      indices.push_back(nextHeightStride);
113✔
335
      indices.push_back(curHeightStride);
113✔
336
      indices.push_back(curHeightStride + 1);
113✔
337
    }
338
  }
339
}
5✔
340

341
void Mesh::createIcosphere(const Sphere& sphere, uint32_t /* subdivCount */) {
1✔
342
  // Algorithm based on the icosphere presented here:
343
  // - http://www.songho.ca/opengl/gl_sphere.html#icosphere
344
  // - https://gist.github.com/warmwaffles/402b9c04318d6ee6dfa4
345

346
  ZoneScopedN("Mesh::createIcosphere");
347

348
  const float radius       = sphere.getRadius();
1✔
349
  const float goldenRadius = radius * GoldenRatio<float>;
1✔
350

351
  Submesh& submesh = m_submeshes.emplace_back();
1✔
352

353
  std::vector<Vertex>& vertices = submesh.getVertices();
1✔
354
  vertices.resize(12);
1✔
355

356
  constexpr float invFactor = 1.f / (Pi<float> * 2);
1✔
357

358
  vertices[0].normal    = Vec3f(-radius, goldenRadius, 0.f).normalize();
1✔
359
  vertices[0].position  = vertices[0].normal * radius;
1✔
360
  vertices[0].texcoords = Vec2f(std::atan2(vertices[0].normal[0], vertices[0].normal[2]) * invFactor + 0.5f, vertices[0].normal[1] * 0.5f + 0.5f);
1✔
361

362
  vertices[1].normal    = Vec3f(radius, goldenRadius, 0.f).normalize();
1✔
363
  vertices[1].position  = vertices[1].normal * radius;
1✔
364
  vertices[1].texcoords = Vec2f(std::atan2(vertices[1].normal[0], vertices[1].normal[2]) * invFactor + 0.5f, vertices[1].normal[1] * 0.5f + 0.5f);
1✔
365

366
  vertices[2].normal    = Vec3f(-radius, -goldenRadius, 0.f).normalize();
1✔
367
  vertices[2].position  = vertices[2].normal * radius;
1✔
368
  vertices[2].texcoords = Vec2f(std::atan2(vertices[2].normal[0], vertices[2].normal[2]) * invFactor + 0.5f, vertices[2].normal[1] * 0.5f + 0.5f);
1✔
369

370
  vertices[3].normal    = Vec3f(radius, -goldenRadius, 0.f).normalize();
1✔
371
  vertices[3].position  = vertices[3].normal * radius;
1✔
372
  vertices[3].texcoords = Vec2f(std::atan2(vertices[3].normal[0], vertices[3].normal[2]) * invFactor + 0.5f, vertices[3].normal[1] * 0.5f + 0.5f);
1✔
373

374
  vertices[4].normal    = Vec3f(0.f, -radius, goldenRadius).normalize();
1✔
375
  vertices[4].position  = vertices[4].normal * radius;
1✔
376
  vertices[4].texcoords = Vec2f(std::atan2(vertices[4].normal[0], vertices[4].normal[2]) * invFactor + 0.5f, vertices[4].normal[1] * 0.5f + 0.5f);
1✔
377

378
  vertices[5].normal    = Vec3f(0.f, radius, goldenRadius).normalize();
1✔
379
  vertices[5].position  = vertices[5].normal * radius;
1✔
380
  vertices[5].texcoords = Vec2f(std::atan2(vertices[5].normal[0], vertices[5].normal[2]) * invFactor + 0.5f, vertices[5].normal[1] * 0.5f + 0.5f);
1✔
381

382
  vertices[6].normal    = Vec3f(0.f, -radius, -goldenRadius).normalize();
1✔
383
  vertices[6].position  = vertices[6].normal * radius;
1✔
384
  vertices[6].texcoords = Vec2f(std::atan2(vertices[6].normal[0], vertices[6].normal[2]) * invFactor + 0.5f, vertices[6].normal[1] * 0.5f + 0.5f);
1✔
385

386
  vertices[7].normal    = Vec3f(0.f, radius, -goldenRadius).normalize();
1✔
387
  vertices[7].position  = vertices[7].normal * radius;
1✔
388
  vertices[7].texcoords = Vec2f(std::atan2(vertices[7].normal[0], vertices[7].normal[2]) * invFactor + 0.5f, vertices[7].normal[1] * 0.5f + 0.5f);
1✔
389

390
  vertices[8].normal    = Vec3f(goldenRadius, 0.f, -radius).normalize();
1✔
391
  vertices[8].position  = vertices[8].normal * radius;
1✔
392
  vertices[8].texcoords = Vec2f(std::atan2(vertices[8].normal[0], vertices[8].normal[2]) * invFactor + 0.5f, vertices[8].normal[1] * 0.5f + 0.5f);
1✔
393

394
  vertices[9].normal    = Vec3f(goldenRadius, 0.f, radius).normalize();
1✔
395
  vertices[9].position  = vertices[9].normal * radius;
1✔
396
  vertices[9].texcoords = Vec2f(std::atan2(vertices[9].normal[0], vertices[9].normal[2]) * invFactor + 0.5f, vertices[9].normal[1] * 0.5f + 0.5f);
1✔
397

398
  vertices[10].normal    = Vec3f(-goldenRadius, 0.f, -radius).normalize();
1✔
399
  vertices[10].position  = vertices[10].normal * radius;
1✔
400
  vertices[10].texcoords = Vec2f(std::atan2(vertices[10].normal[0], vertices[10].normal[2]) * invFactor + 0.5f, vertices[10].normal[1] * 0.5f + 0.5f);
1✔
401

402
  vertices[11].normal    = Vec3f(-goldenRadius, 0.f, radius).normalize();
1✔
403
  vertices[11].position  = vertices[11].normal * radius;
1✔
404
  vertices[11].texcoords = Vec2f(std::atan2(vertices[11].normal[0], vertices[11].normal[2]) * invFactor + 0.5f, vertices[11].normal[1] * 0.5f + 0.5f);
1✔
405

406
  // Applying a translation on each vertex by the sphere's center
407
  for (Vertex& vertex : vertices)
13✔
408
    vertex.position += sphere.getCenter();
12✔
409

410
  submesh.getTriangleIndices() = {
1✔
411
     5,  0, 11,
412
     1,  0,  5,
413
     7,  0,  1,
414
    10,  0,  7,
415
    11,  0, 10,
416
     9,  1,  5,
417
     4,  5, 11,
418
     2, 11, 10,
419
     6, 10,  7,
420
     8,  7,  1,
421
     4,  3,  9,
422
     2,  3,  4,
423
     6,  3,  2,
424
     8,  3,  6,
425
     9,  3,  8,
426
     5,  4,  9,
427
    11,  2,  4,
428
    10,  6,  2,
429
     7,  8,  6,
430
     1,  9,  8
431
  };
1✔
432

433
  // Applying subdivisions
434

435
  // TODO: subdivisions are clearly broken for the moment, must be investigated
436

437
//  std::unordered_map<Vertex, std::size_t> verticesIndices;
438
//  verticesIndices.emplace(vertices[0], 0);
439
//  verticesIndices.emplace(vertices[1], 1);
440
//  verticesIndices.emplace(vertices[2], 2);
441
//  verticesIndices.emplace(vertices[3], 3);
442
//  verticesIndices.emplace(vertices[4], 4);
443
//  verticesIndices.emplace(vertices[5], 5);
444
//  verticesIndices.emplace(vertices[6], 6);
445
//  verticesIndices.emplace(vertices[7], 7);
446
//  verticesIndices.emplace(vertices[8], 8);
447
//  verticesIndices.emplace(vertices[9], 9);
448
//  verticesIndices.emplace(vertices[10], 10);
449
//  verticesIndices.emplace(vertices[11], 11);
450
//
451
//  for (uint32_t subdivIndex = 0; subdivIndex < subdivCount; ++subdivIndex) {
452
//    std::vector<Vertex> newVertices;
453
//    newVertices.reserve(vertices.size() * 2);
454
//
455
//    std::vector<unsigned int> newIndices;
456
//    newIndices.reserve(indices.size() * 9);
457
//
458
//    const std::size_t indexCount = indices.size();
459
//
460
//    for (std::size_t triangleIndex = 0; triangleIndex < indexCount; triangleIndex += 3) {
461
//      // Recovering the original vertices
462
//      //       3
463
//      //      / \
464
//      //     /   \
465
//      //    /     \
466
//      //   /       \
467
//      //  /         \
468
//      // 1-----------2
469
//
470
//      const Vertex& firstVert  = vertices[indices[triangleIndex]];
471
//      const Vertex& secondVert = vertices[indices[triangleIndex + 1]];
472
//      const Vertex& thirdVert  = vertices[indices[triangleIndex + 2]];
473
//
474
//      newVertices.emplace_back(firstVert);
475
//      newVertices.emplace_back(secondVert);
476
//      newVertices.emplace_back(thirdVert);
477
//
478
//      // Computing the edge vertices to form another triangle
479
//      //       x
480
//      //      / \
481
//      //     /   \
482
//      //    3-----2
483
//      //   / \   / \
484
//      //  /   \ /   \
485
//      // x-----1-----x
486
//
487
//      Vertex& firstEdgeVert   = newVertices.emplace_back();
488
//      firstEdgeVert.position  = (firstVert.position + secondVert.position) * 0.5f;
489
//      firstEdgeVert.texcoords = (firstVert.texcoords + secondVert.texcoords) * 0.5f;
490
//      firstEdgeVert.normal    = (firstVert.normal + secondVert.normal).normalize();
491
//
492
//      Vertex& secondEdgeVert   = newVertices.emplace_back();
493
//      secondEdgeVert.position  = (secondVert.position + thirdVert.position) * 0.5f;
494
//      secondEdgeVert.texcoords = (secondVert.texcoords + thirdVert.texcoords) * 0.5f;
495
//      secondEdgeVert.normal    = (secondVert.normal + thirdVert.normal).normalize();
496
//
497
//      Vertex& thirdEdgeVert   = newVertices.emplace_back();
498
//      thirdEdgeVert.position  = (thirdVert.position + firstVert.position) * 0.5f;
499
//      thirdEdgeVert.texcoords = (thirdVert.texcoords + firstVert.texcoords) * 0.5f;
500
//      thirdEdgeVert.normal    = (thirdVert.normal + firstVert.normal).normalize();
501
//
502
//      // Adding indices to create the 4 resulting triangles
503
//      //       x
504
//      //      / \
505
//      //     / 4 \
506
//      //    x-----x
507
//      //   / \ 1 / \
508
//      //  / 2 \ / 3 \
509
//      // x-----x-----x
510
//
511
//      const std::size_t firstEdgeVertIndex = newVertices.size() - 3;
512
//      const std::size_t secondEdgeVertIndex = newVertices.size() - 2;
513
//      const std::size_t thirdEdgeVertIndex = newVertices.size() - 1;
514
//
515
//      verticesIndices.emplace(firstEdgeVert, firstEdgeVertIndex);
516
//      verticesIndices.emplace(secondEdgeVert, secondEdgeVertIndex);
517
//      verticesIndices.emplace(thirdEdgeVert, thirdEdgeVertIndex);
518
//
519
//      newIndices.emplace_back(firstEdgeVertIndex);
520
//      newIndices.emplace_back(secondEdgeVertIndex);
521
//      newIndices.emplace_back(thirdEdgeVertIndex);
522
//
523
//      newIndices.emplace_back(verticesIndices.find(firstVert)->second);
524
//      newIndices.emplace_back(firstEdgeVertIndex);
525
//      newIndices.emplace_back(thirdEdgeVertIndex);
526
//
527
//      newIndices.emplace_back(firstEdgeVertIndex);
528
//      newIndices.emplace_back(verticesIndices.find(secondVert)->second);
529
//      newIndices.emplace_back(secondEdgeVertIndex);
530
//
531
//      newIndices.emplace_back(thirdEdgeVertIndex);
532
//      newIndices.emplace_back(secondEdgeVertIndex);
533
//      newIndices.emplace_back(verticesIndices.find(thirdVert)->second);
534
//    }
535
//
536
//    vertices = std::move(newVertices);
537
//    indices  = std::move(newIndices);
538
//  }
539
}
1✔
540

541
} // namespace Raz
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc